Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/transform/transform_snap.c
| Show First 20 Lines • Show All 66 Lines • ▼ Show 20 Lines | |||||
| #include "DEG_depsgraph.h" | #include "DEG_depsgraph.h" | ||||
| #include "UI_resources.h" | #include "UI_resources.h" | ||||
| #include "UI_view2d.h" | #include "UI_view2d.h" | ||||
| #include "MEM_guardedalloc.h" | #include "MEM_guardedalloc.h" | ||||
| #include "transform.h" | #include "transform.h" | ||||
| #include "transform_data.h" | |||||
| #include "transform_snap.h" | #include "transform_snap.h" | ||||
| /* this should be passed as an arg for use in snap functions */ | /* this should be passed as an arg for use in snap functions */ | ||||
| #undef BASACT | #undef BASACT | ||||
| /* use half of flt-max so we can scale up without an exception */ | /* use half of flt-max so we can scale up without an exception */ | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| ▲ Show 20 Lines • Show All 206 Lines • ▼ Show 20 Lines | |||||
| #endif | #endif | ||||
| if (event->type == MOUSEMOVE) { | if (event->type == MOUSEMOVE) { | ||||
| status |= updateSelectedSnapPoint(t); | status |= updateSelectedSnapPoint(t); | ||||
| } | } | ||||
| return status; | return status; | ||||
| } | } | ||||
| /** | |||||
| * Rotate an element, low level code, ignore protected channels. | |||||
| * (use for objects or pose-bones) | |||||
| * Similar to #ElementRotation. | |||||
| */ | |||||
| static void transform_data_ext_rotate(TransDataExtension *ext, | |||||
| float tdi_mtx[3][3], | |||||
| float tdi_smtx[3][3], | |||||
| float mat[3][3], | |||||
| bool use_drot) | |||||
| { | |||||
| float totmat[3][3]; | |||||
| float smat[3][3]; | |||||
| float fmat[3][3]; | |||||
| float obmat[3][3]; | |||||
| float dmat[3][3]; /* delta rotation */ | |||||
| float dmat_inv[3][3]; | |||||
| mul_m3_m3m3(totmat, mat, tdi_mtx); | |||||
| mul_m3_m3m3(smat, tdi_smtx, mat); | |||||
| /* logic from BKE_object_rot_to_mat3 */ | |||||
| if (use_drot) { | |||||
| if (ext->rotOrder > 0) { | |||||
| eulO_to_mat3(dmat, ext->drot, ext->rotOrder); | |||||
| } | |||||
| else if (ext->rotOrder == ROT_MODE_AXISANGLE) { | |||||
| #if 0 | |||||
| axis_angle_to_mat3(dmat, ext->drotAxis, ext->drotAngle); | |||||
| #else | |||||
| unit_m3(dmat); | |||||
| #endif | |||||
| } | |||||
| else { | |||||
| float tquat[4]; | |||||
| normalize_qt_qt(tquat, ext->dquat); | |||||
| quat_to_mat3(dmat, tquat); | |||||
| } | |||||
| invert_m3_m3(dmat_inv, dmat); | |||||
| } | |||||
| if (ext->rotOrder == ROT_MODE_QUAT) { | |||||
| float quat[4]; | |||||
| /* calculate the total rotatation */ | |||||
| quat_to_mat3(obmat, ext->iquat); | |||||
| if (use_drot) { | |||||
| mul_m3_m3m3(obmat, dmat, obmat); | |||||
| } | |||||
| /* mat = transform, obmat = object rotation */ | |||||
| mul_m3_m3m3(fmat, smat, obmat); | |||||
| if (use_drot) { | |||||
| mul_m3_m3m3(fmat, dmat_inv, fmat); | |||||
| } | |||||
| mat3_to_quat(quat, fmat); | |||||
| /* apply */ | |||||
| copy_qt_qt(ext->quat, quat); | |||||
| } | |||||
| else if (ext->rotOrder == ROT_MODE_AXISANGLE) { | |||||
| float axis[3], angle; | |||||
| /* calculate the total rotatation */ | |||||
| axis_angle_to_mat3(obmat, ext->irotAxis, ext->irotAngle); | |||||
| if (use_drot) { | |||||
| mul_m3_m3m3(obmat, dmat, obmat); | |||||
| } | |||||
| /* mat = transform, obmat = object rotation */ | |||||
| mul_m3_m3m3(fmat, smat, obmat); | |||||
| if (use_drot) { | |||||
| mul_m3_m3m3(fmat, dmat_inv, fmat); | |||||
| } | |||||
| mat3_to_axis_angle(axis, &angle, fmat); | |||||
| /* apply */ | |||||
| copy_v3_v3(ext->rotAxis, axis); | |||||
| *ext->rotAngle = angle; | |||||
| } | |||||
| else { | |||||
| float eul[3]; | |||||
| /* calculate the total rotatation */ | |||||
| eulO_to_mat3(obmat, ext->irot, ext->rotOrder); | |||||
| if (use_drot) { | |||||
| mul_m3_m3m3(obmat, dmat, obmat); | |||||
| } | |||||
| /* mat = transform, obmat = object rotation */ | |||||
| mul_m3_m3m3(fmat, smat, obmat); | |||||
| if (use_drot) { | |||||
| mul_m3_m3m3(fmat, dmat_inv, fmat); | |||||
| } | |||||
| mat3_to_compatible_eulO(eul, ext->rot, ext->rotOrder, fmat); | |||||
| /* apply */ | |||||
| copy_v3_v3(ext->rot, eul); | |||||
| } | |||||
| } | |||||
| void applyProject(TransInfo *t) | void applyProject(TransInfo *t) | ||||
| { | { | ||||
| /* XXX FLICKER IN OBJECT MODE */ | /* XXX FLICKER IN OBJECT MODE */ | ||||
| if ((t->tsnap.project) && activeSnap(t) && (t->flag & T_NO_PROJECT) == 0) { | if ((t->tsnap.project) && activeSnap(t) && (t->flag & T_NO_PROJECT) == 0) { | ||||
| float tvec[3]; | float tvec[3]; | ||||
| int i; | |||||
| FOREACH_TRANS_DATA_CONTAINER (t, tc) { | FOREACH_TRANS_DATA_CONTAINER (t, tc) { | ||||
| TransData *td = tc->data; | TransData *td = tc->data; | ||||
| for (i = 0; i < tc->data_len; i++, td++) { | for (int tdi = 0; tdi < tc->data_len; tdi++) { | ||||
| float iloc[3], loc[3], no[3]; | float iloc[3], loc[3], no[3]; | ||||
| float mval_fl[2]; | float mval_fl[2]; | ||||
| if (td->flag & TD_SKIP) { | if (td->basic[tdi].flag & TD_SKIP) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| if ((t->flag & T_PROP_EDIT) && (td->factor == 0.0f)) { | if ((t->flag & T_PROP_EDIT) && (td->prop[tdi].factor == 0.0f)) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| copy_v3_v3(iloc, td->loc); | float(*tdi_smtx)[3] = td->space[tdi].smtx; | ||||
| float *tdi_loc = td->basic[tdi].loc; | |||||
| copy_v3_v3(iloc, tdi_loc); | |||||
| if (tc->use_local_mat) { | if (tc->use_local_mat) { | ||||
| mul_m4_v3(tc->mat, iloc); | mul_m4_v3(tc->mat, iloc); | ||||
| } | } | ||||
| else if (t->flag & T_OBJECT) { | else if (t->flag & T_OBJECT) { | ||||
| BKE_object_eval_transform_all(t->depsgraph, t->scene, td->ob); | Object *ob = td->object[tdi].ob; | ||||
| copy_v3_v3(iloc, td->ob->obmat[3]); | BKE_object_eval_transform_all(t->depsgraph, t->scene, ob); | ||||
| copy_v3_v3(iloc, ob->obmat[3]); | |||||
| } | } | ||||
| if (ED_view3d_project_float_global(t->region, iloc, mval_fl, V3D_PROJ_TEST_NOP) == | if (ED_view3d_project_float_global(t->region, iloc, mval_fl, V3D_PROJ_TEST_NOP) == | ||||
| V3D_PROJ_RET_OK) { | V3D_PROJ_RET_OK) { | ||||
| if (ED_transform_snap_object_project_view3d( | if (ED_transform_snap_object_project_view3d( | ||||
| t->tsnap.object_context, | t->tsnap.object_context, | ||||
| t->depsgraph, | t->depsgraph, | ||||
| SCE_SNAP_MODE_FACE, | SCE_SNAP_MODE_FACE, | ||||
| Show All 12 Lines | |||||
| #if 0 | #if 0 | ||||
| if (tc->use_local_mat) { | if (tc->use_local_mat) { | ||||
| mul_m4_v3(tc->imat, loc); | mul_m4_v3(tc->imat, loc); | ||||
| } | } | ||||
| #endif | #endif | ||||
| sub_v3_v3v3(tvec, loc, iloc); | sub_v3_v3v3(tvec, loc, iloc); | ||||
| mul_m3_v3(td->smtx, tvec); | mul_m3_v3(tdi_smtx, tvec); | ||||
| add_v3_v3(td->loc, tvec); | add_v3_v3(tdi_loc, tvec); | ||||
| if (t->tsnap.align && (t->flag & T_OBJECT)) { | if (t->tsnap.align && (t->flag & T_OBJECT)) { | ||||
| /* handle alignment as well */ | /* handle alignment as well */ | ||||
| const float *original_normal; | const float *original_normal; | ||||
| float mat[3][3]; | float mat[3][3]; | ||||
| /* In pose mode, we want to align normals with Y axis of bones... */ | /* In pose mode, we want to align normals with Y axis of bones... */ | ||||
| original_normal = td->axismtx[2]; | BLI_assert(td->ext); | ||||
| TransDataExtension *ext = &td->ext[tdi]; | |||||
| float(*tdi_mtx)[3] = td->space[tdi].mtx; | |||||
| float(*tdi_axismtx)[3] = td->space[tdi].axismtx; | |||||
| original_normal = tdi_axismtx[2]; | |||||
| rotation_between_vecs_to_mat3(mat, original_normal, no); | rotation_between_vecs_to_mat3(mat, original_normal, no); | ||||
| transform_data_ext_rotate(td, mat, true); | transform_data_ext_rotate(ext, tdi_mtx, tdi_smtx, mat, true); | ||||
| /* TODO support constraints for rotation too? see ElementRotation */ | /* TODO support constraints for rotation too? see ElementRotation */ | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| // XXX constraintTransLim(t, td); | // XXX constraintTransLim(t, td); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| void applyGridAbsolute(TransInfo *t) | void applyGridAbsolute(TransInfo *t) | ||||
| { | { | ||||
| float grid_size = 0.0f; | float grid_size = 0.0f; | ||||
| GearsType grid_action; | GearsType grid_action; | ||||
| int i; | |||||
| if (!(activeSnap(t) && (t->tsnap.mode & (SCE_SNAP_MODE_INCREMENT | SCE_SNAP_MODE_GRID)))) { | if (!(activeSnap(t) && (t->tsnap.mode & (SCE_SNAP_MODE_INCREMENT | SCE_SNAP_MODE_GRID)))) { | ||||
| return; | return; | ||||
| } | } | ||||
| grid_action = BIG_GEARS; | grid_action = BIG_GEARS; | ||||
| if (t->modifiers & MOD_PRECISION) { | if (t->modifiers & MOD_PRECISION) { | ||||
| grid_action = SMALL_GEARS; | grid_action = SMALL_GEARS; | ||||
| Show All 11 Lines | case SMALL_GEARS: | ||||
| break; | break; | ||||
| } | } | ||||
| /* early exit on unusable grid size */ | /* early exit on unusable grid size */ | ||||
| if (grid_size == 0.0f) { | if (grid_size == 0.0f) { | ||||
| return; | return; | ||||
| } | } | ||||
| FOREACH_TRANS_DATA_CONTAINER (t, tc) { | FOREACH_TRANS_DATA_CONTAINER (t, tc) { | ||||
| TransData *td; | TransData *td = tc->data; | ||||
| for (int tdi = 0; tdi < tc->data_len; tdi++) { | |||||
| for (i = 0, td = tc->data; i < tc->data_len; i++, td++) { | |||||
| float iloc[3], loc[3], tvec[3]; | float iloc[3], loc[3], tvec[3]; | ||||
| if (td->flag & TD_SKIP) { | if (td->basic[tdi].flag & TD_SKIP) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| if ((t->flag & T_PROP_EDIT) && (td->factor == 0.0f)) { | if ((t->flag & T_PROP_EDIT) && (td->prop[tdi].factor == 0.0f)) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| copy_v3_v3(iloc, td->loc); | float(*tdi_smtx)[3] = td->space[tdi].smtx; | ||||
| float *tdi_loc = td->basic[tdi].loc; | |||||
| copy_v3_v3(iloc, tdi_loc); | |||||
| if (tc->use_local_mat) { | if (tc->use_local_mat) { | ||||
| mul_m4_v3(tc->mat, iloc); | mul_m4_v3(tc->mat, iloc); | ||||
| } | } | ||||
| else if (t->flag & T_OBJECT) { | else if (t->flag & T_OBJECT) { | ||||
| BKE_object_eval_transform_all(t->depsgraph, t->scene, td->ob); | Object *ob = td->object[tdi].ob; | ||||
| copy_v3_v3(iloc, td->ob->obmat[3]); | BKE_object_eval_transform_all(t->depsgraph, t->scene, ob); | ||||
| copy_v3_v3(iloc, ob->obmat[3]); | |||||
| } | } | ||||
| mul_v3_v3fl(loc, iloc, 1.0f / grid_size); | mul_v3_v3fl(loc, iloc, 1.0f / grid_size); | ||||
| loc[0] = roundf(loc[0]); | loc[0] = roundf(loc[0]); | ||||
| loc[1] = roundf(loc[1]); | loc[1] = roundf(loc[1]); | ||||
| loc[2] = roundf(loc[2]); | loc[2] = roundf(loc[2]); | ||||
| mul_v3_fl(loc, grid_size); | mul_v3_fl(loc, grid_size); | ||||
| sub_v3_v3v3(tvec, loc, iloc); | sub_v3_v3v3(tvec, loc, iloc); | ||||
| mul_m3_v3(td->smtx, tvec); | mul_m3_v3(tdi_smtx, tvec); | ||||
| add_v3_v3(td->loc, tvec); | add_v3_v3(tdi_loc, tvec); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| void applySnapping(TransInfo *t, float *vec) | void applySnapping(TransInfo *t, float *vec) | ||||
| { | { | ||||
| /* Each Trans Data already makes the snap to face */ | /* Each Trans Data already makes the snap to face */ | ||||
| if (doForceIncrementSnap(t) || (t->tsnap.project && t->tsnap.mode == SCE_SNAP_MODE_FACE)) { | if (doForceIncrementSnap(t) || (t->tsnap.project && t->tsnap.mode == SCE_SNAP_MODE_FACE)) { | ||||
| ▲ Show 20 Lines • Show All 480 Lines • ▼ Show 20 Lines | static float RotationBetween(TransInfo *t, const float p1[3], const float p2[3]) | ||||
| sub_v3_v3v3(start, p1, t->center_global); | sub_v3_v3v3(start, p1, t->center_global); | ||||
| sub_v3_v3v3(end, p2, t->center_global); | sub_v3_v3v3(end, p2, t->center_global); | ||||
| // Angle around a constraint axis (error prone, will need debug) | // Angle around a constraint axis (error prone, will need debug) | ||||
| if (t->con.applyRot != NULL && (t->con.mode & CON_APPLY)) { | if (t->con.applyRot != NULL && (t->con.mode & CON_APPLY)) { | ||||
| float axis[3], tmp[3]; | float axis[3], tmp[3]; | ||||
| t->con.applyRot(t, NULL, NULL, axis, NULL); | t->con.applyRot(t, NULL, 0, axis, NULL); | ||||
| project_v3_v3v3(tmp, end, axis); | project_v3_v3v3(tmp, end, axis); | ||||
| sub_v3_v3v3(end, end, tmp); | sub_v3_v3v3(end, end, tmp); | ||||
| project_v3_v3v3(tmp, start, axis); | project_v3_v3v3(tmp, start, axis); | ||||
| sub_v3_v3v3(start, start, tmp); | sub_v3_v3v3(start, start, tmp); | ||||
| normalize_v3(end); | normalize_v3(end); | ||||
| ▲ Show 20 Lines • Show All 146 Lines • ▼ Show 20 Lines | |||||
| } | } | ||||
| /** \} */ | /** \} */ | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /** \name Target | /** \name Target | ||||
| * \{ */ | * \{ */ | ||||
| static void TargetSnapOffset(TransInfo *t, TransData *td) | static void TargetSnapOffset(TransInfo *t, bNode *node) | ||||
| { | { | ||||
| if (t->spacetype == SPACE_NODE && td != NULL) { | if (t->spacetype == SPACE_NODE && node != NULL) { | ||||
| bNode *node = td->extra; | |||||
| char border = t->tsnap.snapNodeBorder; | char border = t->tsnap.snapNodeBorder; | ||||
| float width = BLI_rctf_size_x(&node->totr); | float width = BLI_rctf_size_x(&node->totr); | ||||
| float height = BLI_rctf_size_y(&node->totr); | float height = BLI_rctf_size_y(&node->totr); | ||||
| #ifdef USE_NODE_CENTER | #ifdef USE_NODE_CENTER | ||||
| if (border & NODE_LEFT) { | if (border & NODE_LEFT) { | ||||
| t->tsnap.snapTarget[0] -= 0.5f * width; | t->tsnap.snapTarget[0] -= 0.5f * width; | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 59 Lines • ▼ Show 20 Lines | if ((t->tsnap.status & TARGET_INIT) == 0) { | ||||
| int i_accum = 0; | int i_accum = 0; | ||||
| t->tsnap.snapTarget[0] = 0; | t->tsnap.snapTarget[0] = 0; | ||||
| t->tsnap.snapTarget[1] = 0; | t->tsnap.snapTarget[1] = 0; | ||||
| t->tsnap.snapTarget[2] = 0; | t->tsnap.snapTarget[2] = 0; | ||||
| FOREACH_TRANS_DATA_CONTAINER (t, tc) { | FOREACH_TRANS_DATA_CONTAINER (t, tc) { | ||||
| TransData *td = tc->data; | TransData *td = tc->data; | ||||
| int i; | int tdi; | ||||
| float v[3]; | float v[3]; | ||||
| zero_v3(v); | zero_v3(v); | ||||
| for (i = 0; i < tc->data_len && td->flag & TD_SELECTED; i++, td++) { | for (tdi = 0; tdi < tc->data_len && (td->basic[tdi].flag & TD_SELECTED); tdi++) { | ||||
| add_v3_v3(v, td->center); | add_v3_v3(v, td->center[tdi]); | ||||
| } | } | ||||
| if (i == 0) { | if (tdi == 0) { | ||||
| /* Is this possible? */ | /* Is this possible? */ | ||||
| continue; | continue; | ||||
| } | } | ||||
| mul_v3_fl(v, 1.0 / i); | mul_v3_fl(v, 1.0 / tdi); | ||||
| if (tc->use_local_mat) { | if (tc->use_local_mat) { | ||||
| mul_m4_v3(tc->mat, v); | mul_m4_v3(tc->mat, v); | ||||
| } | } | ||||
| add_v3_v3(t->tsnap.snapTarget, v); | add_v3_v3(t->tsnap.snapTarget, v); | ||||
| i_accum++; | i_accum++; | ||||
| } | } | ||||
| mul_v3_fl(t->tsnap.snapTarget, 1.0 / i_accum); | mul_v3_fl(t->tsnap.snapTarget, 1.0 / i_accum); | ||||
| TargetSnapOffset(t, NULL); | TargetSnapOffset(t, NULL); | ||||
| t->tsnap.status |= TARGET_INIT; | t->tsnap.status |= TARGET_INIT; | ||||
| } | } | ||||
| } | } | ||||
| static void TargetSnapClosest(TransInfo *t) | static void TargetSnapClosest(TransInfo *t) | ||||
| { | { | ||||
| // Only valid if a snap point has been selected | // Only valid if a snap point has been selected | ||||
| if (t->tsnap.status & POINT_INIT) { | if (t->tsnap.status & POINT_INIT) { | ||||
| float dist_closest = 0.0f; | float dist_closest = 0.0f; | ||||
| TransData *closest = NULL; | TransData *td_closest = NULL; | ||||
| int tdi_closest = -1; | |||||
| /* Object mode */ | /* Object mode */ | ||||
| if (t->flag & T_OBJECT) { | if (t->flag & T_OBJECT) { | ||||
| int i; | |||||
| FOREACH_TRANS_DATA_CONTAINER (t, tc) { | FOREACH_TRANS_DATA_CONTAINER (t, tc) { | ||||
| TransData *td = tc->data; | TransData *td = tc->data; | ||||
| for (td = tc->data, i = 0; i < tc->data_len && td->flag & TD_SELECTED; i++, td++) { | for (int tdi = 0; tdi < tc->data_len && (td->basic[tdi].flag & TD_SELECTED); tdi++) { | ||||
| const BoundBox *bb = NULL; | const BoundBox *bb = NULL; | ||||
| if ((t->options & CTX_OBMODE_XFORM_OBDATA) == 0) { | if ((t->options & CTX_OBMODE_XFORM_OBDATA) == 0) { | ||||
| bb = BKE_object_boundbox_get(td->ob); | bb = BKE_object_boundbox_get(td->object[tdi].ob); | ||||
| } | } | ||||
| /* use boundbox if possible */ | /* use boundbox if possible */ | ||||
| if (bb) { | if (bb) { | ||||
| int j; | int j; | ||||
| for (j = 0; j < 8; j++) { | for (j = 0; j < 8; j++) { | ||||
| BLI_assert(td->ext); | |||||
| TransDataExtension *ext = &td->ext[tdi]; | |||||
| float loc[3]; | float loc[3]; | ||||
| float dist; | float dist; | ||||
| copy_v3_v3(loc, bb->vec[j]); | copy_v3_v3(loc, bb->vec[j]); | ||||
| mul_m4_v3(td->ext->obmat, loc); | mul_m4_v3(ext->obmat, loc); | ||||
| dist = t->tsnap.distance(t, loc, t->tsnap.snapPoint); | dist = t->tsnap.distance(t, loc, t->tsnap.snapPoint); | ||||
| if ((dist != TRANSFORM_DIST_INVALID) && | if ((dist != TRANSFORM_DIST_INVALID) && | ||||
| (closest == NULL || fabsf(dist) < fabsf(dist_closest))) { | (td_closest == NULL || fabsf(dist) < fabsf(dist_closest))) { | ||||
| copy_v3_v3(t->tsnap.snapTarget, loc); | copy_v3_v3(t->tsnap.snapTarget, loc); | ||||
| closest = td; | td_closest = td; | ||||
| tdi_closest = tdi; | |||||
| dist_closest = dist; | dist_closest = dist; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* use element center otherwise */ | /* use element center otherwise */ | ||||
| else { | else { | ||||
| float loc[3]; | float loc[3]; | ||||
| float dist; | float dist; | ||||
| copy_v3_v3(loc, td->center); | copy_v3_v3(loc, td->center[tdi]); | ||||
| dist = t->tsnap.distance(t, loc, t->tsnap.snapPoint); | dist = t->tsnap.distance(t, loc, t->tsnap.snapPoint); | ||||
| if ((dist != TRANSFORM_DIST_INVALID) && | if ((dist != TRANSFORM_DIST_INVALID) && | ||||
| (closest == NULL || fabsf(dist) < fabsf(dist_closest))) { | (tdi_closest == -1 || fabsf(dist) < fabsf(dist_closest))) { | ||||
| copy_v3_v3(t->tsnap.snapTarget, loc); | copy_v3_v3(t->tsnap.snapTarget, loc); | ||||
| closest = td; | td_closest = td; | ||||
| tdi_closest = tdi; | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| FOREACH_TRANS_DATA_CONTAINER (t, tc) { | FOREACH_TRANS_DATA_CONTAINER (t, tc) { | ||||
| TransData *td = tc->data; | TransData *td = tc->data; | ||||
| int i; | int elem_len = tc->data_len; | ||||
| for (i = 0; i < tc->data_len && td->flag & TD_SELECTED; i++, td++) { | for (int tdi = 0; tdi < elem_len && (td->basic[tdi].flag & TD_SELECTED); tdi++) { | ||||
| float loc[3]; | float loc[3]; | ||||
| float dist; | float dist; | ||||
| copy_v3_v3(loc, td->center); | copy_v3_v3(loc, td->center[tdi]); | ||||
| if (tc->use_local_mat) { | if (tc->use_local_mat) { | ||||
| mul_m4_v3(tc->mat, loc); | mul_m4_v3(tc->mat, loc); | ||||
| } | } | ||||
| dist = t->tsnap.distance(t, loc, t->tsnap.snapPoint); | dist = t->tsnap.distance(t, loc, t->tsnap.snapPoint); | ||||
| if ((dist != TRANSFORM_DIST_INVALID) && | if ((dist != TRANSFORM_DIST_INVALID) && | ||||
| (closest == NULL || fabsf(dist) < fabsf(dist_closest))) { | (tdi_closest == -1 || fabsf(dist) < fabsf(dist_closest))) { | ||||
| copy_v3_v3(t->tsnap.snapTarget, loc); | copy_v3_v3(t->tsnap.snapTarget, loc); | ||||
| closest = td; | td_closest = td; | ||||
| tdi_closest = tdi; | |||||
| dist_closest = dist; | dist_closest = dist; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| TargetSnapOffset(t, closest); | if (tdi_closest != -1) { | ||||
| bNode *node = td_closest->basic[tdi_closest].extra; | |||||
| TargetSnapOffset(t, node); | |||||
| } | |||||
| t->tsnap.status |= TARGET_INIT; | t->tsnap.status |= TARGET_INIT; | ||||
| } | } | ||||
| } | } | ||||
| /** \} */ | /** \} */ | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| ▲ Show 20 Lines • Show All 440 Lines • Show Last 20 Lines | |||||