Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/transform/transform_convert.c
| Show All 27 Lines | |||||
| #include "DNA_mask_types.h" | #include "DNA_mask_types.h" | ||||
| #include "DNA_space_types.h" | #include "DNA_space_types.h" | ||||
| #include "MEM_guardedalloc.h" | #include "MEM_guardedalloc.h" | ||||
| #include "BLI_kdtree.h" | #include "BLI_kdtree.h" | ||||
| #include "BLI_listbase.h" | #include "BLI_listbase.h" | ||||
| #include "BLI_math.h" | #include "BLI_math.h" | ||||
| #include "BLI_sort.h" | |||||
| #include "BLI_string.h" | #include "BLI_string.h" | ||||
| #include "BKE_animsys.h" | #include "BKE_animsys.h" | ||||
| #include "BKE_armature.h" | #include "BKE_armature.h" | ||||
| #include "BKE_context.h" | #include "BKE_context.h" | ||||
| #include "BKE_editmesh.h" | #include "BKE_editmesh.h" | ||||
| #include "BKE_fcurve.h" | #include "BKE_fcurve.h" | ||||
| #include "BKE_global.h" | #include "BKE_global.h" | ||||
| Show All 32 Lines | |||||
| #include "RNA_access.h" | #include "RNA_access.h" | ||||
| #include "DEG_depsgraph.h" | #include "DEG_depsgraph.h" | ||||
| #include "DEG_depsgraph_build.h" | #include "DEG_depsgraph_build.h" | ||||
| #include "transform.h" | #include "transform.h" | ||||
| #include "transform_convert.h" | #include "transform_convert.h" | ||||
| #include "transform_data.h" | |||||
| #include "transform_mode.h" | #include "transform_mode.h" | ||||
| bool transform_mode_use_local_origins(const TransInfo *t) | bool transform_mode_use_local_origins(const TransInfo *t) | ||||
| { | { | ||||
| return ELEM(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL); | return ELEM(t->mode, TFM_ROTATION, TFM_RESIZE, TFM_TRACKBALL); | ||||
| } | } | ||||
| /** | /** | ||||
| Show All 13 Lines | else if (t->data_len_all == 3) { | ||||
| if (t->obedit_type == OB_CURVE) { | if (t->obedit_type == OB_CURVE) { | ||||
| /* Special case check for curve, if we have a single curve bezier triple selected | /* Special case check for curve, if we have a single curve bezier triple selected | ||||
| * treat */ | * treat */ | ||||
| FOREACH_TRANS_DATA_CONTAINER (t, tc) { | FOREACH_TRANS_DATA_CONTAINER (t, tc) { | ||||
| if (!tc->data_len) { | if (!tc->data_len) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| if (tc->data_len == 3) { | if (tc->data_len == 3) { | ||||
| const TransData *td = tc->data; | const TransDataBasic *td_basic = tc->data->basic; | ||||
| if ((td[0].flag | td[1].flag | td[2].flag) & TD_BEZTRIPLE) { | if ((td_basic[0].flag | td_basic[1].flag | td_basic[2].flag) & TD_BEZTRIPLE) { | ||||
| if ((td[0].loc == td[1].loc) && (td[1].loc == td[2].loc)) { | if ((td_basic[0].loc == td_basic[1].loc) && (td_basic[1].loc == td_basic[2].loc)) { | ||||
| is_data_single = true; | is_data_single = true; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| if (is_data_single) { | if (is_data_single) { | ||||
| t->around = V3D_AROUND_LOCAL_ORIGINS; | t->around = V3D_AROUND_LOCAL_ORIGINS; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /** \name Proportional Editing | /** \name Proportional Editing | ||||
| * \{ */ | * \{ */ | ||||
| static int trans_data_compare_dist(const void *a, const void *b) | static int trans_data_compare_dist(const void *a, const void *b, void *ctx) | ||||
| { | { | ||||
| const TransData *td_a = (const TransData *)a; | const TransDataProportional *prop = ctx; | ||||
| const TransData *td_b = (const TransData *)b; | const int index_a = *(int *)a; | ||||
| const int index_b = *(int *)b; | |||||
| const float dista = prop[index_a].dist; | |||||
| const float distb = prop[index_b].dist; | |||||
| if (td_a->dist < td_b->dist) { | if (dista < distb) { | ||||
| return -1; | return -1; | ||||
| } | } | ||||
| else if (td_a->dist > td_b->dist) { | else if (dista > distb) { | ||||
| return 1; | return 1; | ||||
| } | } | ||||
| else { | else { | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| } | } | ||||
| static int trans_data_compare_rdist(const void *a, const void *b) | static int trans_data_compare_rdist(const void *a, const void *b, void *ctx) | ||||
| { | { | ||||
| const TransData *td_a = (const TransData *)a; | const TransDataProportional *prop = ctx; | ||||
| const TransData *td_b = (const TransData *)b; | const int index_a = *(int *)a; | ||||
| const int index_b = *(int *)b; | |||||
| const float rdista = prop[index_a].rdist; | |||||
| const float rdistb = prop[index_b].rdist; | |||||
| if (td_a->rdist < td_b->rdist) { | if (rdista < rdistb) { | ||||
| return -1; | return -1; | ||||
| } | } | ||||
| else if (td_a->rdist > td_b->rdist) { | else if (rdista > rdistb) { | ||||
| return 1; | return 1; | ||||
| } | } | ||||
| else { | else { | ||||
| return 0; | return 0; | ||||
| } | } | ||||
| } | } | ||||
| static void sort_trans_data_dist_container(const TransInfo *t, TransDataContainer *tc) | static void sort_trans_data_dist_container(const TransInfo *t, TransDataContainer *tc) | ||||
| { | { | ||||
| TransData *start = tc->data; | TransData *td = tc->data; | ||||
| int tdi_start = 0; | |||||
| int i; | int i; | ||||
| for (i = 0; i < tc->data_len && start->flag & TD_SELECTED; i++) { | for (i = 0; i < tc->data_len; i++, tdi_start++) { | ||||
| start++; | if (td->basic[tdi_start].flag & TD_SELECTED) { | ||||
| break; | |||||
| } | |||||
| } | } | ||||
| if (i < tc->data_len) { | if (i < tc->data_len) { | ||||
| int len = td->elem_len - i; | |||||
| int *indexes = MEM_mallocN(len * sizeof(*indexes), __func__); | |||||
| for (i = 0; i < len; i++) { | |||||
| indexes[i] = i; | |||||
| } | |||||
| if (t->flag & T_PROP_CONNECTED) { | if (t->flag & T_PROP_CONNECTED) { | ||||
| qsort(start, tc->data_len - i, sizeof(TransData), trans_data_compare_dist); | BLI_qsort_r(indexes, len, sizeof(*indexes), trans_data_compare_dist, td->prop); | ||||
| } | } | ||||
| else { | else { | ||||
| qsort(start, tc->data_len - i, sizeof(TransData), trans_data_compare_rdist); | BLI_qsort_r(indexes, len, sizeof(*indexes), trans_data_compare_rdist, td->prop); | ||||
| } | } | ||||
| transform_data_reorder(td, indexes); | |||||
| MEM_freeN(indexes); | |||||
| } | } | ||||
| } | } | ||||
| void sort_trans_data_dist(TransInfo *t) | void sort_trans_data_dist(TransInfo *t) | ||||
| { | { | ||||
| FOREACH_TRANS_DATA_CONTAINER (t, tc) { | FOREACH_TRANS_DATA_CONTAINER (t, tc) { | ||||
| sort_trans_data_dist_container(t, tc); | sort_trans_data_dist_container(t, tc); | ||||
| } | } | ||||
| } | } | ||||
| /** | /** | ||||
| * Make #TD_SELECTED first in the array. | * Make #TD_SELECTED first in the array. | ||||
| */ | */ | ||||
| static void sort_trans_data_selected_first_container(TransDataContainer *tc) | static void sort_trans_data_selected_first_container(TransDataContainer *tc) | ||||
| { | { | ||||
| TransData *sel, *unsel; | const TransData *td = tc->data; | ||||
| TransData temp; | TransDataIter tdi_sel, tdi_unsel; | ||||
| unsel = tc->data; | int unsel = 0; | ||||
| sel = tc->data; | int sel = tc->data_len - 1; | ||||
| sel += tc->data_len - 1; | |||||
| while (sel > unsel) { | while (sel > unsel) { | ||||
| while (unsel->flag & TD_SELECTED) { | while (td->basic[unsel].flag & TD_SELECTED) { | ||||
| unsel++; | unsel++; | ||||
| if (unsel == sel) { | if (unsel == sel) { | ||||
| return; | return; | ||||
| } | } | ||||
| } | } | ||||
| while (!(sel->flag & TD_SELECTED)) { | while (!(td->basic[sel].flag & TD_SELECTED)) { | ||||
| sel--; | sel--; | ||||
| if (unsel == sel) { | if (unsel == sel) { | ||||
| return; | return; | ||||
| } | } | ||||
| } | } | ||||
| temp = *unsel; | transform_data_elem_read_all(td, unsel, &tdi_unsel); | ||||
| *unsel = *sel; | transform_data_elem_read_all(td, sel, &tdi_sel); | ||||
| *sel = temp; | transform_data_elem_update_all(td, unsel, &tdi_sel); | ||||
| transform_data_elem_update_all(td, sel, &tdi_unsel); | |||||
| sel--; | sel--; | ||||
| unsel++; | unsel++; | ||||
| } | } | ||||
| } | } | ||||
| static void sort_trans_data_selected_first(TransInfo *t) | static void sort_trans_data_selected_first(TransInfo *t) | ||||
| { | { | ||||
| FOREACH_TRANS_DATA_CONTAINER (t, tc) { | FOREACH_TRANS_DATA_CONTAINER (t, tc) { | ||||
| sort_trans_data_selected_first_container(tc); | sort_trans_data_selected_first_container(tc); | ||||
| } | } | ||||
| } | } | ||||
| /** | /** | ||||
| * Distance calculated from not-selected vertex to nearest selected vertex. | * Distance calculated from not-selected vertex to nearest selected vertex. | ||||
| */ | */ | ||||
| static void set_prop_dist(TransInfo *t, const bool with_dist) | static void set_prop_dist(TransInfo *t, const bool with_dist) | ||||
| { | { | ||||
| int a; | |||||
| float _proj_vec[3]; | float _proj_vec[3]; | ||||
| const float *proj_vec = NULL; | const float *proj_vec = NULL; | ||||
| /* support for face-islands */ | /* support for face-islands */ | ||||
| const bool use_island = transdata_check_local_islands(t, t->around); | const bool use_island = transdata_check_local_islands(t, t->around); | ||||
| if (t->flag & T_PROP_PROJECTED) { | if (t->flag & T_PROP_PROJECTED) { | ||||
| if (t->spacetype == SPACE_VIEW3D && t->region && t->region->regiontype == RGN_TYPE_WINDOW) { | if (t->spacetype == SPACE_VIEW3D && t->region && t->region->regiontype == RGN_TYPE_WINDOW) { | ||||
| RegionView3D *rv3d = t->region->regiondata; | RegionView3D *rv3d = t->region->regiondata; | ||||
| normalize_v3_v3(_proj_vec, rv3d->viewinv[2]); | normalize_v3_v3(_proj_vec, rv3d->viewinv[2]); | ||||
| proj_vec = _proj_vec; | proj_vec = _proj_vec; | ||||
| } | } | ||||
| } | } | ||||
| /* Count number of selected. */ | /* Count number of selected. */ | ||||
| int td_table_len = 0; | int td_table_len = 0; | ||||
| FOREACH_TRANS_DATA_CONTAINER (t, tc) { | FOREACH_TRANS_DATA_CONTAINER (t, tc) { | ||||
| TransData *td = tc->data; | TransData *td = tc->data; | ||||
| for (a = 0; a < tc->data_len; a++, td++) { | for (int tdi = 0; tdi < tc->data_len; tdi++) { | ||||
| if (td->flag & TD_SELECTED) { | if (td->basic[tdi].flag & TD_SELECTED) { | ||||
| td_table_len++; | td_table_len++; | ||||
| } | } | ||||
| else { | else { | ||||
| /* By definition transform-data has selected items in beginning. */ | /* By definition transform-data has selected items in beginning. */ | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* Pointers to selected's #TransData. | /* Pointers to selected's #TransData. | ||||
| * Used to find #TransData from the index returned by #BLI_kdtree_find_nearest. */ | * Used to find #TransData from the index returned by #BLI_kdtree_find_nearest. */ | ||||
| TransData **td_table = MEM_mallocN(sizeof(*td_table) * td_table_len, __func__); | int *td_table = MEM_mallocN(sizeof(*td_table) * td_table_len, __func__); | ||||
| /* Create and fill kd-tree of selected's positions - in global or proj_vec space. */ | /* Create and fill kd-tree of selected's positions - in global or proj_vec space. */ | ||||
| KDTree_3d *td_tree = BLI_kdtree_3d_new(td_table_len); | KDTree_3d *td_tree = BLI_kdtree_3d_new(td_table_len); | ||||
| int td_table_index = 0; | int td_table_index = 0; | ||||
| FOREACH_TRANS_DATA_CONTAINER (t, tc) { | FOREACH_TRANS_DATA_CONTAINER (t, tc) { | ||||
| TransData *td = tc->data; | TransData *td = tc->data; | ||||
| for (a = 0; a < tc->data_len; a++, td++) { | for (int tdi = 0; tdi < tc->data_len; tdi++) { | ||||
| if (td->flag & TD_SELECTED) { | if (td->basic[tdi].flag & TD_SELECTED) { | ||||
| /* Initialize, it was mallocced. */ | /* Initialize, it was mallocced. */ | ||||
| float vec[3]; | float vec[3]; | ||||
| td->rdist = 0.0f; | td->prop[tdi].rdist = 0.0f; | ||||
| if (use_island) { | if (use_island) { | ||||
| if (tc->use_local_mat) { | if (tc->use_local_mat) { | ||||
| mul_v3_m4v3(vec, tc->mat, td->iloc); | mul_v3_m4v3(vec, tc->mat, td->basic[tdi].iloc); | ||||
| } | } | ||||
| else { | else { | ||||
| mul_v3_m3v3(vec, td->mtx, td->iloc); | mul_v3_m3v3(vec, td->space[tdi].mtx, td->basic[tdi].iloc); | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| if (tc->use_local_mat) { | if (tc->use_local_mat) { | ||||
| mul_v3_m4v3(vec, tc->mat, td->center); | mul_v3_m4v3(vec, tc->mat, td->center[tdi]); | ||||
| } | } | ||||
| else { | else { | ||||
| mul_v3_m3v3(vec, td->mtx, td->center); | mul_v3_m3v3(vec, td->space[tdi].mtx, td->center[tdi]); | ||||
| } | } | ||||
| } | } | ||||
| if (proj_vec) { | if (proj_vec) { | ||||
| float vec_p[3]; | float vec_p[3]; | ||||
| project_v3_v3v3(vec_p, vec, proj_vec); | project_v3_v3v3(vec_p, vec, proj_vec); | ||||
| sub_v3_v3(vec, vec_p); | sub_v3_v3(vec, vec_p); | ||||
| } | } | ||||
| BLI_kdtree_3d_insert(td_tree, td_table_index, vec); | BLI_kdtree_3d_insert(td_tree, td_table_index, vec); | ||||
| td_table[td_table_index++] = td; | td_table[td_table_index++] = tdi; | ||||
| } | } | ||||
| else { | else { | ||||
| /* By definition transform-data has selected items in beginning. */ | /* By definition transform-data has selected items in beginning. */ | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| BLI_assert(td_table_index == td_table_len); | BLI_assert(td_table_index == td_table_len); | ||||
| BLI_kdtree_3d_balance(td_tree); | BLI_kdtree_3d_balance(td_tree); | ||||
| /* For each non-selected vertex, find distance to the nearest selected vertex. */ | /* For each non-selected vertex, find distance to the nearest selected vertex. */ | ||||
| FOREACH_TRANS_DATA_CONTAINER (t, tc) { | FOREACH_TRANS_DATA_CONTAINER (t, tc) { | ||||
| TransData *td = tc->data; | TransData *td = tc->data; | ||||
| for (a = 0; a < tc->data_len; a++, td++) { | for (int tdi = 0; tdi < tc->data_len; tdi++) { | ||||
| if ((td->flag & TD_SELECTED) == 0) { | if ((td->basic[tdi].flag & TD_SELECTED) == 0) { | ||||
| float vec[3]; | float vec[3]; | ||||
| if (use_island) { | if (use_island) { | ||||
| if (tc->use_local_mat) { | if (tc->use_local_mat) { | ||||
| mul_v3_m4v3(vec, tc->mat, td->iloc); | mul_v3_m4v3(vec, tc->mat, td->basic[tdi].iloc); | ||||
| } | } | ||||
| else { | else { | ||||
| mul_v3_m3v3(vec, td->mtx, td->iloc); | mul_v3_m3v3(vec, td->space[tdi].mtx, td->basic[tdi].iloc); | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| if (tc->use_local_mat) { | if (tc->use_local_mat) { | ||||
| mul_v3_m4v3(vec, tc->mat, td->center); | mul_v3_m4v3(vec, tc->mat, td->center[tdi]); | ||||
| } | } | ||||
| else { | else { | ||||
| mul_v3_m3v3(vec, td->mtx, td->center); | mul_v3_m3v3(vec, td->space[tdi].mtx, td->center[tdi]); | ||||
| } | } | ||||
| } | } | ||||
| if (proj_vec) { | if (proj_vec) { | ||||
| float vec_p[3]; | float vec_p[3]; | ||||
| project_v3_v3v3(vec_p, vec, proj_vec); | project_v3_v3v3(vec_p, vec, proj_vec); | ||||
| sub_v3_v3(vec, vec_p); | sub_v3_v3(vec, vec_p); | ||||
| } | } | ||||
| KDTreeNearest_3d nearest; | KDTreeNearest_3d nearest; | ||||
| const int td_index = BLI_kdtree_3d_find_nearest(td_tree, vec, &nearest); | const int td_index = BLI_kdtree_3d_find_nearest(td_tree, vec, &nearest); | ||||
| td->rdist = -1.0f; | td->prop[tdi].rdist = -1.0f; | ||||
| if (td_index != -1) { | if (td_index != -1) { | ||||
| td->rdist = nearest.dist; | td->prop[tdi].rdist = nearest.dist; | ||||
| if (use_island) { | if (use_island) { | ||||
| copy_v3_v3(td->center, td_table[td_index]->center); | copy_v3_v3(td->center[tdi], td->center[td_table[td_index]]); | ||||
| copy_m3_m3(td->axismtx, td_table[td_index]->axismtx); | copy_m3_m3(td->space[tdi].axismtx, td->space[td_table[td_index]].axismtx); | ||||
| } | } | ||||
| } | } | ||||
| if (with_dist) { | if (with_dist) { | ||||
| td->dist = td->rdist; | td->prop[tdi].dist = td->prop[tdi].rdist; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| BLI_kdtree_3d_free(td_tree); | BLI_kdtree_3d_free(td_tree); | ||||
| MEM_freeN(td_table); | MEM_freeN(td_table); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 312 Lines • ▼ Show 20 Lines | |||||
| } | } | ||||
| /** \} */ | /** \} */ | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /** \name Curve Surface | /** \name Curve Surface | ||||
| * \{ */ | * \{ */ | ||||
| void calc_distanceCurveVerts(TransData *head, TransData *tail) | void calc_distanceCurveVerts(const TransData *td, int head, int tail) | ||||
| { | { | ||||
| TransData *td, *td_near = NULL; | int tdi, tdi_near = 0; | ||||
| for (td = head; td <= tail; td++) { | for (tdi = head; tdi <= tail; tdi++) { | ||||
| if (td->flag & TD_SELECTED) { | if (td->basic[tdi].flag & TD_SELECTED) { | ||||
| td_near = td; | tdi_near = tdi; | ||||
| td->dist = 0.0f; | td->prop[tdi].dist = 0.0f; | ||||
| } | } | ||||
| else if (td_near) { | else if (tdi_near) { | ||||
| float dist; | float dist; | ||||
| float vec[3]; | float vec[3]; | ||||
| sub_v3_v3v3(vec, td_near->center, td->center); | sub_v3_v3v3(vec, td->center[tdi_near], td->center[tdi]); | ||||
| mul_m3_v3(head->mtx, vec); | mul_m3_v3(td->space[head].mtx, vec); | ||||
| dist = len_v3(vec); | dist = len_v3(vec); | ||||
| if (dist < (td - 1)->dist) { | float dist_prev = td->prop[tdi - 1].dist; | ||||
| td->dist = (td - 1)->dist; | if (dist < dist_prev) { | ||||
| td->prop[tdi].dist = dist_prev; | |||||
| } | } | ||||
| else { | else { | ||||
| td->dist = dist; | td->prop[tdi].dist = dist; | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| td->dist = FLT_MAX; | td->prop[tdi].dist = FLT_MAX; | ||||
| td->flag |= TD_NOTCONNECTED; | td->basic[tdi].flag |= TD_NOTCONNECTED; | ||||
| } | } | ||||
| } | } | ||||
| td_near = NULL; | |||||
| for (td = tail; td >= head; td--) { | tdi_near = 0; | ||||
| if (td->flag & TD_SELECTED) { | for (tdi = tail; tdi >= head; tdi--) { | ||||
| td_near = td; | if (td->basic[tdi].flag & TD_SELECTED) { | ||||
| td->dist = 0.0f; | tdi_near = tdi; | ||||
| td->prop[tdi].dist = 0.0f; | |||||
| } | } | ||||
| else if (td_near) { | else if (tdi_near) { | ||||
| float dist; | float dist; | ||||
| float vec[3]; | float vec[3]; | ||||
| float dist_curr = td->prop[tdi].dist; | |||||
| int tdi_next = tdi; | |||||
| tdi++; | |||||
| float dist_next = td->prop[tdi_next].dist; | |||||
| sub_v3_v3v3(vec, td_near->center, td->center); | sub_v3_v3v3(vec, td->center[tdi_near], td->center[tdi]); | ||||
| mul_m3_v3(head->mtx, vec); | mul_m3_v3(td->space[head].mtx, vec); | ||||
| dist = len_v3(vec); | dist = len_v3(vec); | ||||
| if (td->flag & TD_NOTCONNECTED || dist < td->dist || (td + 1)->dist < td->dist) { | if ((td->basic[tdi].flag & TD_NOTCONNECTED) || dist < dist_curr || dist_next < dist_curr) { | ||||
| td->flag &= ~TD_NOTCONNECTED; | td->basic[tdi].flag &= ~TD_NOTCONNECTED; | ||||
| if (dist < (td + 1)->dist) { | if (dist < dist_next) { | ||||
| td->dist = (td + 1)->dist; | td->prop[tdi].dist = dist_next; | ||||
| } | } | ||||
| else { | else { | ||||
| td->dist = dist; | td->prop[tdi].dist = dist; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* Utility function for getting the handle data from bezier's */ | /* Utility function for getting the handle data from bezier's */ | ||||
| TransDataCurveHandleFlags *initTransDataCurveHandles(TransData *td, struct BezTriple *bezt) | TransDataCurveHandleFlags *initTransDataCurveHandles(const TransData *td, | ||||
| const int tdi, | |||||
| struct BezTriple *bezt) | |||||
| { | { | ||||
| TransDataCurveHandleFlags *hdata; | TransDataCurveHandleFlags *hdata; | ||||
| td->flag |= TD_BEZTRIPLE; | td->basic[tdi].flag |= TD_BEZTRIPLE; | ||||
| hdata = td->hdata = MEM_mallocN(sizeof(TransDataCurveHandleFlags), "CuHandle Data"); | td->curve[tdi].hdata = hdata = MEM_mallocN(sizeof(TransDataCurveHandleFlags), "CuHandle Data"); | ||||
| hdata->ih1 = bezt->h1; | hdata->ih1 = bezt->h1; | ||||
| hdata->h1 = &bezt->h1; | hdata->h1 = &bezt->h1; | ||||
| hdata->ih2 = bezt->h2; /* in case the second is not selected */ | hdata->ih2 = bezt->h2; /* in case the second is not selected */ | ||||
| hdata->h2 = &bezt->h2; | hdata->h2 = &bezt->h2; | ||||
| return hdata; | return hdata; | ||||
| } | } | ||||
| /** \} */ | /** \} */ | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /** \name UV Coordinates | /** \name UV Coordinates | ||||
| * \{ */ | * \{ */ | ||||
| bool clipUVTransform(TransInfo *t, float vec[2], const bool resize) | bool clipUVTransform(TransInfo *t, float vec[2], const bool resize) | ||||
| { | { | ||||
| bool clipx = true, clipy = true; | bool clipx = true, clipy = true; | ||||
| float min[2], max[2]; | float min[2], max[2]; | ||||
| min[0] = min[1] = 0.0f; | min[0] = min[1] = 0.0f; | ||||
| max[0] = t->aspect[0]; | max[0] = t->aspect[0]; | ||||
| max[1] = t->aspect[1]; | max[1] = t->aspect[1]; | ||||
| FOREACH_TRANS_DATA_CONTAINER (t, tc) { | FOREACH_TRANS_DATA_CONTAINER (t, tc) { | ||||
| TransData *td = tc->data; | |||||
| TransData *td; | for (int tdi = 0; tdi < tc->data_len; tdi++) { | ||||
| int a; | minmax_v2v2_v2(min, max, td->basic[tdi].loc); | ||||
| for (a = 0, td = tc->data; a < tc->data_len; a++, td++) { | |||||
| minmax_v2v2_v2(min, max, td->loc); | |||||
| } | } | ||||
| } | } | ||||
| if (resize) { | if (resize) { | ||||
| if (min[0] < 0.0f && t->center_global[0] > 0.0f && t->center_global[0] < t->aspect[0] * 0.5f) { | if (min[0] < 0.0f && t->center_global[0] > 0.0f && t->center_global[0] < t->aspect[0] * 0.5f) { | ||||
| vec[0] *= t->center_global[0] / (t->center_global[0] - min[0]); | vec[0] *= t->center_global[0] / (t->center_global[0] - min[0]); | ||||
| } | } | ||||
| else if (max[0] > t->aspect[0] && t->center_global[0] < t->aspect[0]) { | else if (max[0] > t->aspect[0] && t->center_global[0] < t->aspect[0]) { | ||||
| Show All 37 Lines | bool clipUVTransform(TransInfo *t, float vec[2], const bool resize) | ||||
| return (clipx || clipy); | return (clipx || clipy); | ||||
| } | } | ||||
| void clipUVData(TransInfo *t) | void clipUVData(TransInfo *t) | ||||
| { | { | ||||
| FOREACH_TRANS_DATA_CONTAINER (t, tc) { | FOREACH_TRANS_DATA_CONTAINER (t, tc) { | ||||
| TransData *td = tc->data; | TransData *td = tc->data; | ||||
| for (int a = 0; a < tc->data_len; a++, td++) { | for (int tdi = 0; tdi < tc->data_len; tdi++) { | ||||
| if ((td->flag & TD_SKIP) || (!td->loc)) { | if (td->basic[tdi].flag & TD_SKIP) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| td->loc[0] = min_ff(max_ff(0.0f, td->loc[0]), t->aspect[0]); | if (td->basic[tdi].loc == NULL) { | ||||
| td->loc[1] = min_ff(max_ff(0.0f, td->loc[1]), t->aspect[1]); | continue; | ||||
| } | |||||
| td->basic[tdi].loc[0] = min_ff(max_ff(0.0f, td->basic[tdi].loc[0]), t->aspect[0]); | |||||
| td->basic[tdi].loc[1] = min_ff(max_ff(0.0f, td->basic[tdi].loc[1]), t->aspect[1]); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /** \} */ | /** \} */ | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /** \name Animation Editors (General) | /** \name Animation Editors (General) | ||||
| ▲ Show 20 Lines • Show All 396 Lines • ▼ Show 20 Lines | |||||
| } | } | ||||
| /* This function firstly adjusts the pointers that the transdata has to each BezTriple */ | /* This function firstly adjusts the pointers that the transdata has to each BezTriple */ | ||||
| static void beztmap_to_data(TransInfo *t, FCurve *fcu, BeztMap *bezms, int totvert) | static void beztmap_to_data(TransInfo *t, FCurve *fcu, BeztMap *bezms, int totvert) | ||||
| { | { | ||||
| BezTriple *bezts = fcu->bezt; | BezTriple *bezts = fcu->bezt; | ||||
| BeztMap *bezm; | BeztMap *bezm; | ||||
| TransData2D *td2d; | TransData2D *td2d; | ||||
| TransData *td; | |||||
| int i, j; | int i, j; | ||||
| char *adjusted; | char *adjusted; | ||||
| TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t); | TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t); | ||||
| /* dynamically allocate an array of chars to mark whether an TransData's | /* dynamically allocate an array of chars to mark whether an TransData's | ||||
| * pointers have been fixed already, so that we don't override ones that are | * pointers have been fixed already, so that we don't override ones that are | ||||
| * already done | * already done | ||||
| */ | */ | ||||
| adjusted = MEM_callocN(tc->data_len, "beztmap_adjusted_map"); | adjusted = MEM_callocN(tc->data_len, "beztmap_adjusted_map"); | ||||
| /* for each beztmap item, find if it is used anywhere */ | /* for each beztmap item, find if it is used anywhere */ | ||||
| bezm = bezms; | bezm = bezms; | ||||
| for (i = 0; i < totvert; i++, bezm++) { | for (i = 0; i < totvert; i++, bezm++) { | ||||
| /* loop through transdata, testing if we have a hit | /* loop through transdata, testing if we have a hit | ||||
| * for the handles (vec[0]/vec[2]), we must also check if they need to be swapped... | * for the handles (vec[0]/vec[2]), we must also check if they need to be swapped... | ||||
| */ | */ | ||||
| td2d = tc->data_2d; | td2d = tc->data_2d; | ||||
| td = tc->data; | for (j = 0; j < tc->data_len; j++, td2d++) { | ||||
| for (j = 0; j < tc->data_len; j++, td2d++, td++) { | |||||
| /* skip item if already marked */ | /* skip item if already marked */ | ||||
| if (adjusted[j] != 0) { | if (adjusted[j] != 0) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| /* update all transdata pointers, no need to check for selections etc, | /* update all transdata pointers, no need to check for selections etc, | ||||
| * since only points that are really needed were created as transdata | * since only points that are really needed were created as transdata | ||||
| */ | */ | ||||
| Show All 25 Lines | for (j = 0; j < tc->data_len; j++, td2d++) { | ||||
| if (td2d->h2) { | if (td2d->h2) { | ||||
| td2d->h2 = (bezts + bezm->newIndex)->vec[2]; | td2d->h2 = (bezts + bezm->newIndex)->vec[2]; | ||||
| } | } | ||||
| adjusted[j] = 1; | adjusted[j] = 1; | ||||
| } | } | ||||
| /* the handle type pointer has to be updated too */ | /* the handle type pointer has to be updated too */ | ||||
| if (adjusted[j] && td->flag & TD_BEZTRIPLE && td->hdata) { | struct TransDataCurveHandleFlags *hdata; | ||||
| hdata = tc->data->curve[j].hdata; | |||||
| if (hdata && adjusted[j] && (tc->data->basic[j].flag & TD_BEZTRIPLE)) { | |||||
| if (bezm->swapHs == 1) { | if (bezm->swapHs == 1) { | ||||
| td->hdata->h1 = &(bezts + bezm->newIndex)->h2; | hdata->h1 = &(bezts + bezm->newIndex)->h2; | ||||
| td->hdata->h2 = &(bezts + bezm->newIndex)->h1; | hdata->h2 = &(bezts + bezm->newIndex)->h1; | ||||
| } | } | ||||
| else { | else { | ||||
| td->hdata->h1 = &(bezts + bezm->newIndex)->h1; | hdata->h1 = &(bezts + bezm->newIndex)->h1; | ||||
| td->hdata->h2 = &(bezts + bezm->newIndex)->h2; | hdata->h2 = &(bezts + bezm->newIndex)->h2; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* free temp memory used for 'adjusted' array */ | /* free temp memory used for 'adjusted' array */ | ||||
| MEM_freeN(adjusted); | MEM_freeN(adjusted); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 1,047 Lines • ▼ Show 20 Lines | #endif | ||||
| } | } | ||||
| else if (t->flag & T_CURSOR) { | else if (t->flag & T_CURSOR) { | ||||
| /* do nothing */ | /* do nothing */ | ||||
| } | } | ||||
| else { /* Objects */ | else { /* Objects */ | ||||
| BLI_assert(t->flag & (T_OBJECT | T_TEXTURE)); | BLI_assert(t->flag & (T_OBJECT | T_TEXTURE)); | ||||
| TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t); | TransDataContainer *tc = TRANS_DATA_CONTAINER_FIRST_SINGLE(t); | ||||
| TransData *td = tc->data; | |||||
| bool motionpath_update = false; | bool motionpath_update = false; | ||||
| for (int i = 0; i < tc->data_len; i++) { | for (int i = 0; i < tc->data_len; i++) { | ||||
| TransData *td = tc->data + i; | const int tdi = i; | ||||
| ListBase pidlist; | ListBase pidlist; | ||||
| PTCacheID *pid; | PTCacheID *pid; | ||||
| ob = td->ob; | ob = td->object[tdi].ob; | ||||
| if (td->flag & TD_SKIP) { | if (td->basic[tdi].flag & TD_SKIP) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| /* flag object caches as outdated */ | /* flag object caches as outdated */ | ||||
| BKE_ptcache_ids_from_object(&pidlist, ob, t->scene, MAX_DUPLI_RECUR); | BKE_ptcache_ids_from_object(&pidlist, ob, t->scene, MAX_DUPLI_RECUR); | ||||
| for (pid = pidlist.first; pid; pid = pid->next) { | for (pid = pidlist.first; pid; pid = pid->next) { | ||||
| if (pid->type != PTCACHE_TYPE_PARTICLES) { | if (pid->type != PTCACHE_TYPE_PARTICLES) { | ||||
| /* particles don't need reset on geometry change */ | /* particles don't need reset on geometry change */ | ||||
| Show All 19 Lines | for (int i = 0; i < tc->data_len; i++) { | ||||
| } | } | ||||
| motionpath_update |= motionpath_need_update_object(t->scene, ob); | motionpath_update |= motionpath_need_update_object(t->scene, ob); | ||||
| /* restore rigid body transform */ | /* restore rigid body transform */ | ||||
| if (ob->rigidbody_object && canceled) { | if (ob->rigidbody_object && canceled) { | ||||
| float ctime = BKE_scene_frame_get(t->scene); | float ctime = BKE_scene_frame_get(t->scene); | ||||
| if (BKE_rigidbody_check_sim_running(t->scene->rigidbody_world, ctime)) { | if (BKE_rigidbody_check_sim_running(t->scene->rigidbody_world, ctime)) { | ||||
| BKE_rigidbody_aftertrans_update(ob, | TransDataExtension *ext = &td->ext[tdi]; | ||||
| td->ext->oloc, | BKE_rigidbody_aftertrans_update( | ||||
| td->ext->orot, | ob, ext->oloc, ext->orot, ext->oquat, ext->orotAxis, ext->orotAngle); | ||||
| td->ext->oquat, | |||||
| td->ext->orotAxis, | |||||
| td->ext->orotAngle); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| if (motionpath_update) { | if (motionpath_update) { | ||||
| /* Update motion paths once for all transformed objects. */ | /* Update motion paths once for all transformed objects. */ | ||||
| const eObjectPathCalcRange range = canceled ? OBJECT_PATH_CALC_RANGE_CURRENT_FRAME : | const eObjectPathCalcRange range = canceled ? OBJECT_PATH_CALC_RANGE_CURRENT_FRAME : | ||||
| OBJECT_PATH_CALC_RANGE_CHANGED; | OBJECT_PATH_CALC_RANGE_CHANGED; | ||||
| ▲ Show 20 Lines • Show All 86 Lines • ▼ Show 20 Lines | else if (t->options & CTX_TEXTURE) { | ||||
| t->flag |= T_TEXTURE; | t->flag |= T_TEXTURE; | ||||
| createTransTexspace(t); | createTransTexspace(t); | ||||
| countAndCleanTransDataContainer(t); | countAndCleanTransDataContainer(t); | ||||
| } | } | ||||
| else if (t->options & CTX_EDGE) { | else if (t->options & CTX_EDGE) { | ||||
| /* Multi object editing. */ | /* Multi object editing. */ | ||||
| initTransDataContainers_FromObjectData(t, ob, NULL, 0); | initTransDataContainers_FromObjectData(t, ob, NULL, 0); | ||||
| #if DEBUG | |||||
| FOREACH_TRANS_DATA_CONTAINER (t, tc) { | FOREACH_TRANS_DATA_CONTAINER (t, tc) { | ||||
| tc->data_ext = NULL; | BLI_assert(!tc->data || !tc->data->ext); | ||||
| } | } | ||||
| #endif | |||||
| t->flag |= T_EDIT; | t->flag |= T_EDIT; | ||||
| createTransEdge(t); | createTransEdge(t); | ||||
| countAndCleanTransDataContainer(t); | countAndCleanTransDataContainer(t); | ||||
| if (t->data_len_all && t->flag & T_PROP_EDIT) { | if (t->data_len_all && t->flag & T_PROP_EDIT) { | ||||
| sort_trans_data_selected_first(t); | sort_trans_data_selected_first(t); | ||||
| set_prop_dist(t, 1); | set_prop_dist(t, 1); | ||||
| ▲ Show 20 Lines • Show All 136 Lines • ▼ Show 20 Lines | else if (t->spacetype == SPACE_CLIP) { | ||||
| else { | else { | ||||
| has_transform_context = false; | has_transform_context = false; | ||||
| } | } | ||||
| } | } | ||||
| else if (t->obedit_type != -1) { | else if (t->obedit_type != -1) { | ||||
| /* Multi object editing. */ | /* Multi object editing. */ | ||||
| initTransDataContainers_FromObjectData(t, ob, NULL, 0); | initTransDataContainers_FromObjectData(t, ob, NULL, 0); | ||||
| #if DEBUG | |||||
| FOREACH_TRANS_DATA_CONTAINER (t, tc) { | FOREACH_TRANS_DATA_CONTAINER (t, tc) { | ||||
| tc->data_ext = NULL; | BLI_assert(!tc->data || !tc->data->ext); | ||||
| } | } | ||||
| #endif | |||||
| if (t->obedit_type == OB_MESH) { | if (t->obedit_type == OB_MESH) { | ||||
| createTransEditVerts(t); | createTransEditVerts(t); | ||||
| } | } | ||||
| else if (ELEM(t->obedit_type, OB_CURVE, OB_SURF)) { | else if (ELEM(t->obedit_type, OB_CURVE, OB_SURF)) { | ||||
| createTransCurveVerts(t); | createTransCurveVerts(t); | ||||
| } | } | ||||
| else if (t->obedit_type == OB_LATTICE) { | else if (t->obedit_type == OB_LATTICE) { | ||||
| createTransLatticeVerts(t); | createTransLatticeVerts(t); | ||||
| ▲ Show 20 Lines • Show All 167 Lines • Show Last 20 Lines | |||||