Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/transform/transform_mode.c
| Show All 40 Lines | |||||
| #include "ED_screen.h" | #include "ED_screen.h" | ||||
| #include "UI_interface.h" | #include "UI_interface.h" | ||||
| #include "BLT_translation.h" | #include "BLT_translation.h" | ||||
| #include "transform.h" | #include "transform.h" | ||||
| #include "transform_data.h" | |||||
| #include "transform_snap.h" | #include "transform_snap.h" | ||||
| /* Own include. */ | /* Own include. */ | ||||
| #include "transform_mode.h" | #include "transform_mode.h" | ||||
| bool transdata_check_local_center(TransInfo *t, short around) | bool transdata_check_local_center(TransInfo *t, short around) | ||||
| { | { | ||||
| return ((around == V3D_AROUND_LOCAL_ORIGINS) && | return ((around == V3D_AROUND_LOCAL_ORIGINS) && | ||||
| ▲ Show 20 Lines • Show All 169 Lines • ▼ Show 20 Lines | |||||
| } | } | ||||
| /** \} */ | /** \} */ | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /** \name Transform Limits | /** \name Transform Limits | ||||
| * \{ */ | * \{ */ | ||||
| void constraintTransLim(TransInfo *t, TransData *td) | void constraintTransLim(TransInfo *t, const TransData *td, const int tdi) | ||||
| { | { | ||||
| if (td->con) { | if (td->object[tdi].con) { | ||||
| const bConstraintTypeInfo *ctiLoc = BKE_constraint_typeinfo_from_type( | const bConstraintTypeInfo *ctiLoc = BKE_constraint_typeinfo_from_type( | ||||
| CONSTRAINT_TYPE_LOCLIMIT); | CONSTRAINT_TYPE_LOCLIMIT); | ||||
| const bConstraintTypeInfo *ctiDist = BKE_constraint_typeinfo_from_type( | const bConstraintTypeInfo *ctiDist = BKE_constraint_typeinfo_from_type( | ||||
| CONSTRAINT_TYPE_DISTLIMIT); | CONSTRAINT_TYPE_DISTLIMIT); | ||||
| bConstraintOb cob = {NULL}; | bConstraintOb cob = {NULL}; | ||||
| bConstraint *con; | bConstraint *con; | ||||
| float ctime = (float)(t->scene->r.cfra); | float ctime = (float)(t->scene->r.cfra); | ||||
| /* Make a temporary bConstraintOb for using these limit constraints | /* Make a temporary bConstraintOb for using these limit constraints | ||||
| * - they only care that cob->matrix is correctly set ;-) | * - they only care that cob->matrix is correctly set ;-) | ||||
| * - current space should be local | * - current space should be local | ||||
| */ | */ | ||||
| unit_m4(cob.matrix); | unit_m4(cob.matrix); | ||||
| copy_v3_v3(cob.matrix[3], td->loc); | copy_v3_v3(cob.matrix[3], td->basic[tdi].loc); | ||||
| /* Evaluate valid constraints */ | /* Evaluate valid constraints */ | ||||
| for (con = td->con; con; con = con->next) { | for (con = td->object[tdi].con; con; con = con->next) { | ||||
| const bConstraintTypeInfo *cti = NULL; | const bConstraintTypeInfo *cti = NULL; | ||||
| ListBase targets = {NULL, NULL}; | ListBase targets = {NULL, NULL}; | ||||
| /* only consider constraint if enabled */ | /* only consider constraint if enabled */ | ||||
| if (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF)) { | if (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF)) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| if (con->enforce == 0.0f) { | if (con->enforce == 0.0f) { | ||||
| Show All 16 Lines | for (con = td->object[tdi].con; con; con = con->next) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| cti = ctiDist; | cti = ctiDist; | ||||
| } | } | ||||
| if (cti) { | if (cti) { | ||||
| /* do space conversions */ | /* do space conversions */ | ||||
| if (con->ownspace == CONSTRAINT_SPACE_WORLD) { | if (con->ownspace == CONSTRAINT_SPACE_WORLD) { | ||||
| /* just multiply by td->mtx (this should be ok) */ | /* just multiply by td->space[tdi].mtx (this should be ok) */ | ||||
| mul_m4_m3m4(cob.matrix, td->mtx, cob.matrix); | mul_m4_m3m4(cob.matrix, td->space[tdi].mtx, cob.matrix); | ||||
| } | } | ||||
| else if (con->ownspace != CONSTRAINT_SPACE_LOCAL) { | else if (con->ownspace != CONSTRAINT_SPACE_LOCAL) { | ||||
| /* skip... incompatible spacetype */ | /* skip... incompatible spacetype */ | ||||
| continue; | continue; | ||||
| } | } | ||||
| /* get constraint targets if needed */ | /* get constraint targets if needed */ | ||||
| BKE_constraint_targets_for_solving_get(t->depsgraph, con, &cob, &targets, ctime); | BKE_constraint_targets_for_solving_get(t->depsgraph, con, &cob, &targets, ctime); | ||||
| /* do constraint */ | /* do constraint */ | ||||
| cti->evaluate_constraint(con, &cob, &targets); | cti->evaluate_constraint(con, &cob, &targets); | ||||
| /* convert spaces again */ | /* convert spaces again */ | ||||
| if (con->ownspace == CONSTRAINT_SPACE_WORLD) { | if (con->ownspace == CONSTRAINT_SPACE_WORLD) { | ||||
| /* just multiply by td->smtx (this should be ok) */ | /* just multiply by td->space[tdi].smtx (this should be ok) */ | ||||
| mul_m4_m3m4(cob.matrix, td->smtx, cob.matrix); | mul_m4_m3m4(cob.matrix, td->space[tdi].smtx, cob.matrix); | ||||
| } | } | ||||
| /* free targets list */ | /* free targets list */ | ||||
| BLI_freelistN(&targets); | BLI_freelistN(&targets); | ||||
| } | } | ||||
| } | } | ||||
| /* copy results from cob->matrix */ | /* copy results from cob->matrix */ | ||||
| copy_v3_v3(td->loc, cob.matrix[3]); | copy_v3_v3(td->basic[tdi].loc, cob.matrix[3]); | ||||
| } | } | ||||
| } | } | ||||
| static void constraintob_from_transdata(bConstraintOb *cob, TransData *td) | static void constraintob_from_transdata(bConstraintOb *cob, const TransData *td, const int tdi) | ||||
| { | { | ||||
| /* Make a temporary bConstraintOb for use by limit constraints | /* Make a temporary bConstraintOb for use by limit constraints | ||||
| * - they only care that cob->matrix is correctly set ;-) | * - they only care that cob->matrix is correctly set ;-) | ||||
| * - current space should be local | * - current space should be local | ||||
| */ | */ | ||||
| memset(cob, 0, sizeof(bConstraintOb)); | memset(cob, 0, sizeof(bConstraintOb)); | ||||
| if (td->ext) { | if (td->ext) { | ||||
| if (td->ext->rotOrder == ROT_MODE_QUAT) { | if (td->ext[tdi].rotOrder == ROT_MODE_QUAT) { | ||||
| /* quats */ | /* quats */ | ||||
| /* objects and bones do normalization first too, otherwise | /* objects and bones do normalization first too, otherwise | ||||
| * we don't necessarily end up with a rotation matrix, and | * we don't necessarily end up with a rotation matrix, and | ||||
| * then conversion back to quat gives a different result */ | * then conversion back to quat gives a different result */ | ||||
| float quat[4]; | float quat[4]; | ||||
| normalize_qt_qt(quat, td->ext->quat); | normalize_qt_qt(quat, td->ext[tdi].quat); | ||||
| quat_to_mat4(cob->matrix, quat); | quat_to_mat4(cob->matrix, quat); | ||||
| } | } | ||||
| else if (td->ext->rotOrder == ROT_MODE_AXISANGLE) { | else if (td->ext[tdi].rotOrder == ROT_MODE_AXISANGLE) { | ||||
| /* axis angle */ | /* axis angle */ | ||||
| axis_angle_to_mat4(cob->matrix, td->ext->rotAxis, *td->ext->rotAngle); | axis_angle_to_mat4(cob->matrix, td->ext[tdi].rotAxis, *td->ext[tdi].rotAngle); | ||||
| } | } | ||||
| else { | else { | ||||
| /* eulers */ | /* eulers */ | ||||
| eulO_to_mat4(cob->matrix, td->ext->rot, td->ext->rotOrder); | eulO_to_mat4(cob->matrix, td->ext[tdi].rot, td->ext[tdi].rotOrder); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| static void constraintRotLim(TransInfo *UNUSED(t), TransData *td) | static void constraintRotLim(TransInfo *UNUSED(t), const TransData *td, const int tdi) | ||||
| { | { | ||||
| if (td->con) { | if (td->object[tdi].con) { | ||||
| const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_from_type(CONSTRAINT_TYPE_ROTLIMIT); | const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_from_type(CONSTRAINT_TYPE_ROTLIMIT); | ||||
| bConstraintOb cob; | bConstraintOb cob; | ||||
| bConstraint *con; | bConstraint *con; | ||||
| bool do_limit = false; | bool do_limit = false; | ||||
| /* Evaluate valid constraints */ | /* Evaluate valid constraints */ | ||||
| for (con = td->con; con; con = con->next) { | for (con = td->object[tdi].con; con; con = con->next) { | ||||
| /* only consider constraint if enabled */ | /* only consider constraint if enabled */ | ||||
| if (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF)) { | if (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF)) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| if (con->enforce == 0.0f) { | if (con->enforce == 0.0f) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| /* we're only interested in Limit-Rotation constraints */ | /* we're only interested in Limit-Rotation constraints */ | ||||
| if (con->type == CONSTRAINT_TYPE_ROTLIMIT) { | if (con->type == CONSTRAINT_TYPE_ROTLIMIT) { | ||||
| bRotLimitConstraint *data = (bRotLimitConstraint *)con->data; | bRotLimitConstraint *data = (bRotLimitConstraint *)con->data; | ||||
| /* only use it if it's tagged for this purpose */ | /* only use it if it's tagged for this purpose */ | ||||
| if ((data->flag2 & LIMIT_TRANSFORM) == 0) { | if ((data->flag2 & LIMIT_TRANSFORM) == 0) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| /* skip incompatible spacetypes */ | /* skip incompatible spacetypes */ | ||||
| if (!ELEM(con->ownspace, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL)) { | if (!ELEM(con->ownspace, CONSTRAINT_SPACE_WORLD, CONSTRAINT_SPACE_LOCAL)) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| /* only do conversion if necessary, to preserve quats and eulers */ | /* only do conversion if necessary, to preserve quats and eulers */ | ||||
| if (do_limit == false) { | if (do_limit == false) { | ||||
| constraintob_from_transdata(&cob, td); | constraintob_from_transdata(&cob, td, tdi); | ||||
| do_limit = true; | do_limit = true; | ||||
| } | } | ||||
| /* do space conversions */ | /* do space conversions */ | ||||
| if (con->ownspace == CONSTRAINT_SPACE_WORLD) { | if (con->ownspace == CONSTRAINT_SPACE_WORLD) { | ||||
| /* just multiply by td->mtx (this should be ok) */ | /* just multiply by td->space[tdi].mtx (this should be ok) */ | ||||
| mul_m4_m3m4(cob.matrix, td->mtx, cob.matrix); | mul_m4_m3m4(cob.matrix, td->space[tdi].mtx, cob.matrix); | ||||
| } | } | ||||
| /* do constraint */ | /* do constraint */ | ||||
| cti->evaluate_constraint(con, &cob, NULL); | cti->evaluate_constraint(con, &cob, NULL); | ||||
| /* convert spaces again */ | /* convert spaces again */ | ||||
| if (con->ownspace == CONSTRAINT_SPACE_WORLD) { | if (con->ownspace == CONSTRAINT_SPACE_WORLD) { | ||||
| /* just multiply by td->smtx (this should be ok) */ | /* just multiply by td->space[tdi].smtx (this should be ok) */ | ||||
| mul_m4_m3m4(cob.matrix, td->smtx, cob.matrix); | mul_m4_m3m4(cob.matrix, td->space[tdi].smtx, cob.matrix); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| if (do_limit) { | if (do_limit) { | ||||
| /* copy results from cob->matrix */ | /* copy results from cob->matrix */ | ||||
| if (td->ext->rotOrder == ROT_MODE_QUAT) { | if (td->ext[tdi].rotOrder == ROT_MODE_QUAT) { | ||||
| /* quats */ | /* quats */ | ||||
| mat4_to_quat(td->ext->quat, cob.matrix); | mat4_to_quat(td->ext[tdi].quat, cob.matrix); | ||||
| } | } | ||||
| else if (td->ext->rotOrder == ROT_MODE_AXISANGLE) { | else if (td->ext[tdi].rotOrder == ROT_MODE_AXISANGLE) { | ||||
| /* axis angle */ | /* axis angle */ | ||||
| mat4_to_axis_angle(td->ext->rotAxis, td->ext->rotAngle, cob.matrix); | mat4_to_axis_angle(td->ext[tdi].rotAxis, td->ext[tdi].rotAngle, cob.matrix); | ||||
| } | } | ||||
| else { | else { | ||||
| /* eulers */ | /* eulers */ | ||||
| mat4_to_eulO(td->ext->rot, td->ext->rotOrder, cob.matrix); | mat4_to_eulO(td->ext[tdi].rot, td->ext[tdi].rotOrder, cob.matrix); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| static void constraintSizeLim(TransInfo *t, TransData *td) | static void constraintSizeLim(TransInfo *t, const TransData *td, const int tdi) | ||||
| { | { | ||||
| if (td->con && td->ext) { | if (td->object && td->ext && td->object[tdi].con) { | ||||
| const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_from_type(CONSTRAINT_TYPE_SIZELIMIT); | const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_from_type(CONSTRAINT_TYPE_SIZELIMIT); | ||||
| bConstraintOb cob = {NULL}; | bConstraintOb cob = {NULL}; | ||||
| bConstraint *con; | bConstraint *con; | ||||
| float size_sign[3], size_abs[3]; | float size_sign[3], size_abs[3]; | ||||
| int i; | int i; | ||||
| /* Make a temporary bConstraintOb for using these limit constraints | /* Make a temporary bConstraintOb for using these limit constraints | ||||
| * - they only care that cob->matrix is correctly set ;-) | * - they only care that cob->matrix is correctly set ;-) | ||||
| * - current space should be local | * - current space should be local | ||||
| */ | */ | ||||
| if ((td->flag & TD_SINGLESIZE) && !(t->con.mode & CON_APPLY)) { | if ((td->basic[tdi].flag & TD_SINGLESIZE) && !(t->con.mode & CON_APPLY)) { | ||||
| /* scale val and reset size */ | /* scale val and reset size */ | ||||
| return; // TODO: fix this case | return; // TODO: fix this case | ||||
| } | } | ||||
| else { | else { | ||||
| /* Reset val if SINGLESIZE but using a constraint */ | /* Reset val if SINGLESIZE but using a constraint */ | ||||
| if (td->flag & TD_SINGLESIZE) { | if (td->basic[tdi].flag & TD_SINGLESIZE) { | ||||
| return; | return; | ||||
| } | } | ||||
| /* separate out sign to apply back later */ | /* separate out sign to apply back later */ | ||||
| for (i = 0; i < 3; i++) { | for (i = 0; i < 3; i++) { | ||||
| size_sign[i] = signf(td->ext->size[i]); | size_sign[i] = signf(td->ext[tdi].size[i]); | ||||
| size_abs[i] = fabsf(td->ext->size[i]); | size_abs[i] = fabsf(td->ext[tdi].size[i]); | ||||
| } | } | ||||
| size_to_mat4(cob.matrix, size_abs); | size_to_mat4(cob.matrix, size_abs); | ||||
| } | } | ||||
| /* Evaluate valid constraints */ | /* Evaluate valid constraints */ | ||||
| for (con = td->con; con; con = con->next) { | for (con = td->object[tdi].con; con; con = con->next) { | ||||
| /* only consider constraint if enabled */ | /* only consider constraint if enabled */ | ||||
| if (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF)) { | if (con->flag & (CONSTRAINT_DISABLE | CONSTRAINT_OFF)) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| if (con->enforce == 0.0f) { | if (con->enforce == 0.0f) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| /* we're only interested in Limit-Scale constraints */ | /* we're only interested in Limit-Scale constraints */ | ||||
| if (con->type == CONSTRAINT_TYPE_SIZELIMIT) { | if (con->type == CONSTRAINT_TYPE_SIZELIMIT) { | ||||
| bSizeLimitConstraint *data = con->data; | bSizeLimitConstraint *data = con->data; | ||||
| /* only use it if it's tagged for this purpose */ | /* only use it if it's tagged for this purpose */ | ||||
| if ((data->flag2 & LIMIT_TRANSFORM) == 0) { | if ((data->flag2 & LIMIT_TRANSFORM) == 0) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| /* do space conversions */ | /* do space conversions */ | ||||
| if (con->ownspace == CONSTRAINT_SPACE_WORLD) { | if (con->ownspace == CONSTRAINT_SPACE_WORLD) { | ||||
| /* just multiply by td->mtx (this should be ok) */ | /* just multiply by td->space[tdi].mtx (this should be ok) */ | ||||
| mul_m4_m3m4(cob.matrix, td->mtx, cob.matrix); | mul_m4_m3m4(cob.matrix, td->space[tdi].mtx, cob.matrix); | ||||
| } | } | ||||
| else if (con->ownspace != CONSTRAINT_SPACE_LOCAL) { | else if (con->ownspace != CONSTRAINT_SPACE_LOCAL) { | ||||
| /* skip... incompatible spacetype */ | /* skip... incompatible spacetype */ | ||||
| continue; | continue; | ||||
| } | } | ||||
| /* do constraint */ | /* do constraint */ | ||||
| cti->evaluate_constraint(con, &cob, NULL); | cti->evaluate_constraint(con, &cob, NULL); | ||||
| /* convert spaces again */ | /* convert spaces again */ | ||||
| if (con->ownspace == CONSTRAINT_SPACE_WORLD) { | if (con->ownspace == CONSTRAINT_SPACE_WORLD) { | ||||
| /* just multiply by td->smtx (this should be ok) */ | /* just multiply by td->space[tdi].smtx (this should be ok) */ | ||||
| mul_m4_m3m4(cob.matrix, td->smtx, cob.matrix); | mul_m4_m3m4(cob.matrix, td->space[tdi].smtx, cob.matrix); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* copy results from cob->matrix */ | /* copy results from cob->matrix */ | ||||
| if ((td->flag & TD_SINGLESIZE) && !(t->con.mode & CON_APPLY)) { | if ((td->basic[tdi].flag & TD_SINGLESIZE) && !(t->con.mode & CON_APPLY)) { | ||||
| /* scale val and reset size */ | /* scale val and reset size */ | ||||
| return; // TODO: fix this case | return; // TODO: fix this case | ||||
| } | } | ||||
| else { | else { | ||||
| /* Reset val if SINGLESIZE but using a constraint */ | /* Reset val if SINGLESIZE but using a constraint */ | ||||
| if (td->flag & TD_SINGLESIZE) { | if (td->basic[tdi].flag & TD_SINGLESIZE) { | ||||
| return; | return; | ||||
| } | } | ||||
| /* extrace scale from matrix and apply back sign */ | /* extrace scale from matrix and apply back sign */ | ||||
| mat4_to_size(td->ext->size, cob.matrix); | mat4_to_size(td->ext[tdi].size, cob.matrix); | ||||
| mul_v3_v3(td->ext->size, size_sign); | mul_v3_v3(td->ext[tdi].size, size_sign); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /* Transform (Rotation Utils) */ | /* Transform (Rotation Utils) */ | ||||
| /** \name Transform Rotation Utils | /** \name Transform Rotation Utils | ||||
| Show All 26 Lines | void headerRotation(TransInfo *t, char str[UI_MAX_DRAW_STR], float final) | ||||
| } | } | ||||
| } | } | ||||
| void postInputRotation(TransInfo *t, float values[3]) | void postInputRotation(TransInfo *t, float values[3]) | ||||
| { | { | ||||
| float axis_final[3]; | float axis_final[3]; | ||||
| copy_v3_v3(axis_final, t->spacemtx[t->orient_axis]); | copy_v3_v3(axis_final, t->spacemtx[t->orient_axis]); | ||||
| if ((t->con.mode & CON_APPLY) && t->con.applyRot) { | if ((t->con.mode & CON_APPLY) && t->con.applyRot) { | ||||
| t->con.applyRot(t, NULL, NULL, axis_final, values); | t->con.applyRot(t, NULL, 0, axis_final, values); | ||||
| } | } | ||||
| } | } | ||||
| /** | /** | ||||
| * Applies values of rotation to `td->loc` and `td->ext->quat` | * Applies values of rotation to `td->basic[tdi].loc` and `td->ext[tdi].quat` | ||||
| * based on a rotation matrix (mat) and a pivot (center). | * based on a rotation matrix (mat) and a pivot (center). | ||||
| * | * | ||||
| * Protected axis and other transform settings are taken into account. | * Protected axis and other transform settings are taken into account. | ||||
| */ | */ | ||||
| void ElementRotation_ex(TransInfo *t, | void ElementRotation_ex(TransInfo *t, | ||||
| TransDataContainer *tc, | TransDataContainer *tc, | ||||
| TransData *td, | const int tdi, | ||||
| const float mat[3][3], | const float mat[3][3], | ||||
| const float *center) | const float *center) | ||||
| { | { | ||||
| const TransData *td = tc->data; | |||||
| float vec[3], totmat[3][3], smat[3][3]; | float vec[3], totmat[3][3], smat[3][3]; | ||||
| float eul[3], fmat[3][3], quat[4]; | float eul[3], fmat[3][3], quat[4]; | ||||
| if (t->flag & T_POINTS) { | if (t->flag & T_POINTS) { | ||||
| mul_m3_m3m3(totmat, mat, td->mtx); | mul_m3_m3m3(totmat, mat, td->space[tdi].mtx); | ||||
| mul_m3_m3m3(smat, td->smtx, totmat); | mul_m3_m3m3(smat, td->space[tdi].smtx, totmat); | ||||
| /* apply gpencil falloff */ | /* apply gpencil falloff */ | ||||
| if (t->options & CTX_GPENCIL_STROKES) { | if (t->options & CTX_GPENCIL_STROKES) { | ||||
| bGPDstroke *gps = (bGPDstroke *)td->extra; | bGPDstroke *gps = (bGPDstroke *)td->basic[tdi].extra; | ||||
| float sx = smat[0][0]; | float sx = smat[0][0]; | ||||
| float sy = smat[1][1]; | float sy = smat[1][1]; | ||||
| float sz = smat[2][2]; | float sz = smat[2][2]; | ||||
| mul_m3_fl(smat, gps->runtime.multi_frame_falloff); | mul_m3_fl(smat, gps->runtime.multi_frame_falloff); | ||||
| /* fix scale */ | /* fix scale */ | ||||
| smat[0][0] = sx; | smat[0][0] = sx; | ||||
| smat[1][1] = sy; | smat[1][1] = sy; | ||||
| smat[2][2] = sz; | smat[2][2] = sz; | ||||
| } | } | ||||
| sub_v3_v3v3(vec, td->iloc, center); | sub_v3_v3v3(vec, td->basic[tdi].iloc, center); | ||||
| mul_m3_v3(smat, vec); | mul_m3_v3(smat, vec); | ||||
| add_v3_v3v3(td->loc, vec, center); | add_v3_v3v3(td->basic[tdi].loc, vec, center); | ||||
| sub_v3_v3v3(vec, td->loc, td->iloc); | sub_v3_v3v3(vec, td->basic[tdi].loc, td->basic[tdi].iloc); | ||||
| protectedTransBits(td->protectflag, vec); | protectedTransBits(td->object[tdi].protectflag, vec); | ||||
| add_v3_v3v3(td->loc, td->iloc, vec); | add_v3_v3v3(td->basic[tdi].loc, td->basic[tdi].iloc, vec); | ||||
| if (td->flag & TD_USEQUAT) { | if (td->basic[tdi].flag & TD_USEQUAT) { | ||||
| mul_m3_series(fmat, td->smtx, mat, td->mtx); | mul_m3_series(fmat, td->space[tdi].smtx, mat, td->space[tdi].mtx); | ||||
| mat3_to_quat(quat, fmat); // Actual transform | mat3_to_quat(quat, fmat); // Actual transform | ||||
| if (td->ext->quat) { | if (td->ext[tdi].quat) { | ||||
| mul_qt_qtqt(td->ext->quat, quat, td->ext->iquat); | mul_qt_qtqt(td->ext[tdi].quat, quat, td->ext[tdi].iquat); | ||||
| /* is there a reason not to have this here? -jahka */ | /* is there a reason not to have this here? -jahka */ | ||||
| protectedQuaternionBits(td->protectflag, td->ext->quat, td->ext->iquat); | protectedQuaternionBits( | ||||
| td->object[tdi].protectflag, td->ext[tdi].quat, td->ext[tdi].iquat); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /** | /** | ||||
| * HACK WARNING | * HACK WARNING | ||||
| * | * | ||||
| * This is some VERY ugly special case to deal with pose mode. | * This is some VERY ugly special case to deal with pose mode. | ||||
| * | * | ||||
| * The problem is that mtx and smtx include each bone orientation. | * The problem is that mtx and smtx include each bone orientation. | ||||
| * | * | ||||
| * That is needed to rotate each bone properly, HOWEVER, to calculate | * That is needed to rotate each bone properly, HOWEVER, to calculate | ||||
| * the translation component, we only need the actual armature object's | * the translation component, we only need the actual armature object's | ||||
| * matrix (and inverse). That is not all though. Once the proper translation | * matrix (and inverse). That is not all though. Once the proper translation | ||||
| * has been computed, it has to be converted back into the bone's space. | * has been computed, it has to be converted back into the bone's space. | ||||
| */ | */ | ||||
| else if (t->flag & T_POSE) { | else if (t->flag & T_POSE) { | ||||
| // Extract and invert armature object matrix | // Extract and invert armature object matrix | ||||
| if ((td->flag & TD_NO_LOC) == 0) { | if ((td->basic[tdi].flag & TD_NO_LOC) == 0) { | ||||
| sub_v3_v3v3(vec, td->center, center); | sub_v3_v3v3(vec, td->center[tdi], center); | ||||
| mul_m3_v3(tc->mat3, vec); // To Global space | mul_m3_v3(tc->mat3, vec); // To Global space | ||||
| mul_m3_v3(mat, vec); // Applying rotation | mul_m3_v3(mat, vec); // Applying rotation | ||||
| mul_m3_v3(tc->imat3, vec); // To Local space | mul_m3_v3(tc->imat3, vec); // To Local space | ||||
| add_v3_v3(vec, center); | add_v3_v3(vec, center); | ||||
| /* vec now is the location where the object has to be */ | /* vec now is the location where the object has to be */ | ||||
| sub_v3_v3v3(vec, vec, td->center); // Translation needed from the initial location | sub_v3_v3v3(vec, vec, td->center[tdi]); // Translation needed from the initial location | ||||
| /* special exception, see TD_PBONE_LOCAL_MTX definition comments */ | /* special exception, see TD_PBONE_LOCAL_MTX definition comments */ | ||||
| if (td->flag & TD_PBONE_LOCAL_MTX_P) { | if (td->basic[tdi].flag & TD_PBONE_LOCAL_MTX_P) { | ||||
| /* do nothing */ | /* do nothing */ | ||||
| } | } | ||||
| else if (td->flag & TD_PBONE_LOCAL_MTX_C) { | else if (td->basic[tdi].flag & TD_PBONE_LOCAL_MTX_C) { | ||||
| mul_m3_v3(tc->mat3, vec); // To Global space | mul_m3_v3(tc->mat3, vec); // To Global space | ||||
| mul_m3_v3(td->ext->l_smtx, vec); // To Pose space (Local Location) | mul_m3_v3(td->ext[tdi].l_smtx, vec); // To Pose space (Local Location) | ||||
| } | } | ||||
| else { | else { | ||||
| mul_m3_v3(tc->mat3, vec); // To Global space | mul_m3_v3(tc->mat3, vec); // To Global space | ||||
| mul_m3_v3(td->smtx, vec); // To Pose space | mul_m3_v3(td->space[tdi].smtx, vec); // To Pose space | ||||
| } | } | ||||
| protectedTransBits(td->protectflag, vec); | protectedTransBits(td->object[tdi].protectflag, vec); | ||||
| add_v3_v3v3(td->loc, td->iloc, vec); | add_v3_v3v3(td->basic[tdi].loc, td->basic[tdi].iloc, vec); | ||||
| constraintTransLim(t, td); | constraintTransLim(t, td, tdi); | ||||
| } | } | ||||
| /* rotation */ | /* rotation */ | ||||
| /* MORE HACK: as in some cases the matrix to apply location and rot/scale is not the same, | /* MORE HACK: as in some cases the matrix to apply location and rot/scale is not the same, | ||||
| * and ElementRotation() might be called in Translation context (with align snapping), | * and ElementRotation() might be called in Translation context (with align snapping), | ||||
| * we need to be sure to actually use the *rotation* matrix here... | * we need to be sure to actually use the *rotation* matrix here... | ||||
| * So no other way than storing it in some dedicated members of td->ext! */ | * So no other way than storing it in some dedicated members of td->ext_p[tdi].ext! */ | ||||
| if ((t->flag & T_V3D_ALIGN) == 0) { /* align mode doesn't rotate objects itself */ | if ((t->flag & T_V3D_ALIGN) == 0) { /* align mode doesn't rotate objects itself */ | ||||
| /* euler or quaternion/axis-angle? */ | /* euler or quaternion/axis-angle? */ | ||||
| if (td->ext->rotOrder == ROT_MODE_QUAT) { | if (td->ext[tdi].rotOrder == ROT_MODE_QUAT) { | ||||
| mul_m3_series(fmat, td->ext->r_smtx, mat, td->ext->r_mtx); | mul_m3_series(fmat, td->ext[tdi].r_smtx, mat, td->ext[tdi].r_mtx); | ||||
| mat3_to_quat(quat, fmat); /* Actual transform */ | mat3_to_quat(quat, fmat); /* Actual transform */ | ||||
| mul_qt_qtqt(td->ext->quat, quat, td->ext->iquat); | mul_qt_qtqt(td->ext[tdi].quat, quat, td->ext[tdi].iquat); | ||||
| /* this function works on end result */ | /* this function works on end result */ | ||||
| protectedQuaternionBits(td->protectflag, td->ext->quat, td->ext->iquat); | protectedQuaternionBits( | ||||
| td->object[tdi].protectflag, td->ext[tdi].quat, td->ext[tdi].iquat); | |||||
| } | } | ||||
| else if (td->ext->rotOrder == ROT_MODE_AXISANGLE) { | else if (td->ext[tdi].rotOrder == ROT_MODE_AXISANGLE) { | ||||
| /* calculate effect based on quats */ | /* calculate effect based on quats */ | ||||
| float iquat[4], tquat[4]; | float iquat[4], tquat[4]; | ||||
| axis_angle_to_quat(iquat, td->ext->irotAxis, td->ext->irotAngle); | axis_angle_to_quat(iquat, td->ext[tdi].irotAxis, td->ext[tdi].irotAngle); | ||||
| mul_m3_series(fmat, td->ext->r_smtx, mat, td->ext->r_mtx); | mul_m3_series(fmat, td->ext[tdi].r_smtx, mat, td->ext[tdi].r_mtx); | ||||
| mat3_to_quat(quat, fmat); /* Actual transform */ | mat3_to_quat(quat, fmat); /* Actual transform */ | ||||
| mul_qt_qtqt(tquat, quat, iquat); | mul_qt_qtqt(tquat, quat, iquat); | ||||
| quat_to_axis_angle(td->ext->rotAxis, td->ext->rotAngle, tquat); | quat_to_axis_angle(td->ext[tdi].rotAxis, td->ext[tdi].rotAngle, tquat); | ||||
| /* this function works on end result */ | /* this function works on end result */ | ||||
| protectedAxisAngleBits(td->protectflag, | protectedAxisAngleBits(td->object[tdi].protectflag, | ||||
| td->ext->rotAxis, | td->ext[tdi].rotAxis, | ||||
| td->ext->rotAngle, | td->ext[tdi].rotAngle, | ||||
| td->ext->irotAxis, | td->ext[tdi].irotAxis, | ||||
| td->ext->irotAngle); | td->ext[tdi].irotAngle); | ||||
| } | } | ||||
| else { | else { | ||||
| float eulmat[3][3]; | float eulmat[3][3]; | ||||
| mul_m3_m3m3(totmat, mat, td->ext->r_mtx); | mul_m3_m3m3(totmat, mat, td->ext[tdi].r_mtx); | ||||
| mul_m3_m3m3(smat, td->ext->r_smtx, totmat); | mul_m3_m3m3(smat, td->ext[tdi].r_smtx, totmat); | ||||
| /* calculate the total rotatation in eulers */ | /* calculate the total rotatation in eulers */ | ||||
| copy_v3_v3(eul, td->ext->irot); | copy_v3_v3(eul, td->ext[tdi].irot); | ||||
| eulO_to_mat3(eulmat, eul, td->ext->rotOrder); | eulO_to_mat3(eulmat, eul, td->ext[tdi].rotOrder); | ||||
| /* mat = transform, obmat = bone rotation */ | /* mat = transform, obmat = bone rotation */ | ||||
| mul_m3_m3m3(fmat, smat, eulmat); | mul_m3_m3m3(fmat, smat, eulmat); | ||||
| mat3_to_compatible_eulO(eul, td->ext->rot, td->ext->rotOrder, fmat); | mat3_to_compatible_eulO(eul, td->ext[tdi].rot, td->ext[tdi].rotOrder, fmat); | ||||
| /* and apply (to end result only) */ | /* and apply (to end result only) */ | ||||
| protectedRotateBits(td->protectflag, eul, td->ext->irot); | protectedRotateBits(td->object[tdi].protectflag, eul, td->ext[tdi].irot); | ||||
| copy_v3_v3(td->ext->rot, eul); | copy_v3_v3(td->ext[tdi].rot, eul); | ||||
| } | } | ||||
| constraintRotLim(t, td); | constraintRotLim(t, td, tdi); | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| if ((td->flag & TD_NO_LOC) == 0) { | if ((td->basic[tdi].flag & TD_NO_LOC) == 0) { | ||||
| /* translation */ | /* translation */ | ||||
| sub_v3_v3v3(vec, td->center, center); | sub_v3_v3v3(vec, td->center[tdi], center); | ||||
| mul_m3_v3(mat, vec); | mul_m3_v3(mat, vec); | ||||
| add_v3_v3(vec, center); | add_v3_v3(vec, center); | ||||
| /* vec now is the location where the object has to be */ | /* vec now is the location where the object has to be */ | ||||
| sub_v3_v3(vec, td->center); | sub_v3_v3(vec, td->center[tdi]); | ||||
| mul_m3_v3(td->smtx, vec); | mul_m3_v3(td->space[tdi].smtx, vec); | ||||
| protectedTransBits(td->protectflag, vec); | protectedTransBits(td->object[tdi].protectflag, vec); | ||||
| add_v3_v3v3(td->loc, td->iloc, vec); | add_v3_v3v3(td->basic[tdi].loc, td->basic[tdi].iloc, vec); | ||||
| } | } | ||||
| constraintTransLim(t, td); | constraintTransLim(t, td, tdi); | ||||
| /* rotation */ | /* rotation */ | ||||
| if ((t->flag & T_V3D_ALIGN) == 0) { // align mode doesn't rotate objects itself | if ((t->flag & T_V3D_ALIGN) == 0) { // align mode doesn't rotate objects itself | ||||
| /* euler or quaternion? */ | /* euler or quaternion? */ | ||||
| if ((td->ext->rotOrder == ROT_MODE_QUAT) || (td->flag & TD_USEQUAT)) { | if ((td->ext[tdi].rotOrder == ROT_MODE_QUAT) || (td->basic[tdi].flag & TD_USEQUAT)) { | ||||
| /* can be called for texture space translate for example, then opt out */ | /* can be called for texture space translate for example, then opt out */ | ||||
| if (td->ext->quat) { | if (td->ext[tdi].quat) { | ||||
| mul_m3_series(fmat, td->smtx, mat, td->mtx); | mul_m3_series(fmat, td->space[tdi].smtx, mat, td->space[tdi].mtx); | ||||
| mat3_to_quat(quat, fmat); // Actual transform | mat3_to_quat(quat, fmat); // Actual transform | ||||
| mul_qt_qtqt(td->ext->quat, quat, td->ext->iquat); | mul_qt_qtqt(td->ext[tdi].quat, quat, td->ext[tdi].iquat); | ||||
| /* this function works on end result */ | /* this function works on end result */ | ||||
| protectedQuaternionBits(td->protectflag, td->ext->quat, td->ext->iquat); | protectedQuaternionBits( | ||||
| td->object[tdi].protectflag, td->ext[tdi].quat, td->ext[tdi].iquat); | |||||
| } | } | ||||
| } | } | ||||
| else if (td->ext->rotOrder == ROT_MODE_AXISANGLE) { | else if (td->ext[tdi].rotOrder == ROT_MODE_AXISANGLE) { | ||||
| /* calculate effect based on quats */ | /* calculate effect based on quats */ | ||||
| float iquat[4], tquat[4]; | float iquat[4], tquat[4]; | ||||
| axis_angle_to_quat(iquat, td->ext->irotAxis, td->ext->irotAngle); | axis_angle_to_quat(iquat, td->ext[tdi].irotAxis, td->ext[tdi].irotAngle); | ||||
| mul_m3_series(fmat, td->smtx, mat, td->mtx); | mul_m3_series(fmat, td->space[tdi].smtx, mat, td->space[tdi].mtx); | ||||
| mat3_to_quat(quat, fmat); // Actual transform | mat3_to_quat(quat, fmat); // Actual transform | ||||
| mul_qt_qtqt(tquat, quat, iquat); | mul_qt_qtqt(tquat, quat, iquat); | ||||
| quat_to_axis_angle(td->ext->rotAxis, td->ext->rotAngle, tquat); | quat_to_axis_angle(td->ext[tdi].rotAxis, td->ext[tdi].rotAngle, tquat); | ||||
| /* this function works on end result */ | /* this function works on end result */ | ||||
| protectedAxisAngleBits(td->protectflag, | protectedAxisAngleBits(td->object[tdi].protectflag, | ||||
| td->ext->rotAxis, | td->ext[tdi].rotAxis, | ||||
| td->ext->rotAngle, | td->ext[tdi].rotAngle, | ||||
| td->ext->irotAxis, | td->ext[tdi].irotAxis, | ||||
| td->ext->irotAngle); | td->ext[tdi].irotAngle); | ||||
| } | } | ||||
| else { | else { | ||||
| float obmat[3][3]; | float obmat[3][3]; | ||||
| mul_m3_m3m3(totmat, mat, td->mtx); | mul_m3_m3m3(totmat, mat, td->space[tdi].mtx); | ||||
| mul_m3_m3m3(smat, td->smtx, totmat); | mul_m3_m3m3(smat, td->space[tdi].smtx, totmat); | ||||
| /* calculate the total rotatation in eulers */ | /* calculate the total rotatation in eulers */ | ||||
| add_v3_v3v3(eul, td->ext->irot, td->ext->drot); /* correct for delta rot */ | add_v3_v3v3(eul, td->ext[tdi].irot, td->ext[tdi].drot); /* correct for delta rot */ | ||||
| eulO_to_mat3(obmat, eul, td->ext->rotOrder); | eulO_to_mat3(obmat, eul, td->ext[tdi].rotOrder); | ||||
| /* mat = transform, obmat = object rotation */ | /* mat = transform, obmat = object rotation */ | ||||
| mul_m3_m3m3(fmat, smat, obmat); | mul_m3_m3m3(fmat, smat, obmat); | ||||
| mat3_to_compatible_eulO(eul, td->ext->rot, td->ext->rotOrder, fmat); | mat3_to_compatible_eulO(eul, td->ext[tdi].rot, td->ext[tdi].rotOrder, fmat); | ||||
| /* correct back for delta rot */ | /* correct back for delta rot */ | ||||
| sub_v3_v3v3(eul, eul, td->ext->drot); | sub_v3_v3v3(eul, eul, td->ext[tdi].drot); | ||||
| /* and apply */ | /* and apply */ | ||||
| protectedRotateBits(td->protectflag, eul, td->ext->irot); | protectedRotateBits(td->object[tdi].protectflag, eul, td->ext[tdi].irot); | ||||
| copy_v3_v3(td->ext->rot, eul); | copy_v3_v3(td->ext[tdi].rot, eul); | ||||
| } | } | ||||
| constraintRotLim(t, td); | constraintRotLim(t, td, tdi); | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| void ElementRotation( | void ElementRotation( | ||||
| TransInfo *t, TransDataContainer *tc, TransData *td, float mat[3][3], const short around) | TransInfo *t, TransDataContainer *tc, const int tdi, float mat[3][3], const short around) | ||||
| { | { | ||||
| const TransData *td = tc->data; | |||||
| const float *center; | const float *center; | ||||
| /* local constraint shouldn't alter center */ | /* local constraint shouldn't alter center */ | ||||
| if (transdata_check_local_center(t, around)) { | if (transdata_check_local_center(t, around)) { | ||||
| center = td->center; | center = td->center[tdi]; | ||||
| } | } | ||||
| else { | else { | ||||
| center = tc->center_local; | center = tc->center_local; | ||||
| } | } | ||||
| ElementRotation_ex(t, tc, td, mat, center); | ElementRotation_ex(t, tc, tdi, mat, center); | ||||
| } | } | ||||
| /** \} */ | /** \} */ | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /* Transform (Resize Utils) */ | /* Transform (Resize Utils) */ | ||||
| /** \name Transform Resize Utils | /** \name Transform Resize Utils | ||||
| * \{ */ | * \{ */ | ||||
| ▲ Show 20 Lines • Show All 87 Lines • ▼ Show 20 Lines | static void TransMat3ToSize(float mat[3][3], float smat[3][3], float size[3]) | ||||
| if (dot_v3v3(rmat[1], smat[1]) < 0.0f) { | if (dot_v3v3(rmat[1], smat[1]) < 0.0f) { | ||||
| size[1] = -size[1]; | size[1] = -size[1]; | ||||
| } | } | ||||
| if (dot_v3v3(rmat[2], smat[2]) < 0.0f) { | if (dot_v3v3(rmat[2], smat[2]) < 0.0f) { | ||||
| size[2] = -size[2]; | size[2] = -size[2]; | ||||
| } | } | ||||
| } | } | ||||
| void ElementResize(TransInfo *t, TransDataContainer *tc, TransData *td, float mat[3][3]) | void ElementResize(TransInfo *t, TransDataContainer *tc, const int tdi, float mat[3][3]) | ||||
| { | { | ||||
| const TransData *td = tc->data; | |||||
| float tmat[3][3], smat[3][3], center[3]; | float tmat[3][3], smat[3][3], center[3]; | ||||
| float vec[3]; | float vec[3]; | ||||
| if (t->flag & T_EDIT) { | if (t->flag & T_EDIT) { | ||||
| mul_m3_m3m3(smat, mat, td->mtx); | mul_m3_m3m3(smat, mat, td->space[tdi].mtx); | ||||
| mul_m3_m3m3(tmat, td->smtx, smat); | mul_m3_m3m3(tmat, td->space[tdi].smtx, smat); | ||||
| } | } | ||||
| else { | else { | ||||
| copy_m3_m3(tmat, mat); | copy_m3_m3(tmat, mat); | ||||
| } | } | ||||
| if (t->con.applySize) { | if (t->con.applySize) { | ||||
| t->con.applySize(t, tc, td, tmat); | t->con.applySize(t, tc, tdi, tmat); | ||||
| } | } | ||||
| /* local constraint shouldn't alter center */ | /* local constraint shouldn't alter center */ | ||||
| if (transdata_check_local_center(t, t->around)) { | if (transdata_check_local_center(t, t->around)) { | ||||
| copy_v3_v3(center, td->center); | copy_v3_v3(center, td->center[tdi]); | ||||
| } | } | ||||
| else if (t->options & CTX_MOVIECLIP) { | else if (t->options & CTX_MOVIECLIP) { | ||||
| if (td->flag & TD_INDIVIDUAL_SCALE) { | if (td->basic[tdi].flag & TD_INDIVIDUAL_SCALE) { | ||||
| copy_v3_v3(center, td->center); | copy_v3_v3(center, td->center[tdi]); | ||||
| } | } | ||||
| else { | else { | ||||
| copy_v3_v3(center, tc->center_local); | copy_v3_v3(center, tc->center_local); | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| copy_v3_v3(center, tc->center_local); | copy_v3_v3(center, tc->center_local); | ||||
| } | } | ||||
| /* Size checked needed since the 3D cursor only uses rotation fields. */ | /* Size checked needed since the 3D cursor only uses rotation fields. */ | ||||
| if (td->ext && td->ext->size) { | if (td->ext && td->ext[tdi].size) { | ||||
| float fsize[3]; | float fsize[3]; | ||||
| if ((t->options & CTX_SCULPT) || t->flag & (T_OBJECT | T_TEXTURE | T_POSE)) { | if ((t->options & CTX_SCULPT) || t->flag & (T_OBJECT | T_TEXTURE | T_POSE)) { | ||||
| float obsizemat[3][3]; | float obsizemat[3][3]; | ||||
| /* Reorient the size mat to fit the oriented object. */ | /* Reorient the size mat to fit the oriented object. */ | ||||
| mul_m3_m3m3(obsizemat, tmat, td->axismtx); | mul_m3_m3m3(obsizemat, tmat, td->space[tdi].axismtx); | ||||
| /* print_m3("obsizemat", obsizemat); */ | /* print_m3("obsizemat", obsizemat); */ | ||||
| TransMat3ToSize(obsizemat, td->axismtx, fsize); | TransMat3ToSize(obsizemat, td->space[tdi].axismtx, fsize); | ||||
| /* print_v3("fsize", fsize); */ | /* print_v3("fsize", fsize); */ | ||||
| } | } | ||||
| else { | else { | ||||
| mat3_to_size(fsize, tmat); | mat3_to_size(fsize, tmat); | ||||
| } | } | ||||
| protectedSizeBits(td->protectflag, fsize); | protectedSizeBits(td->object[tdi].protectflag, fsize); | ||||
| if ((t->flag & T_V3D_ALIGN) == 0) { /* align mode doesn't resize objects itself */ | if ((t->flag & T_V3D_ALIGN) == 0) { /* align mode doesn't resize objects itself */ | ||||
| if ((td->flag & TD_SINGLESIZE) && !(t->con.mode & CON_APPLY)) { | if ((td->basic[tdi].flag & TD_SINGLESIZE) && !(t->con.mode & CON_APPLY)) { | ||||
| /* scale val and reset size */ | /* scale val and reset size */ | ||||
| *td->val = td->ival * (1 + (fsize[0] - 1) * td->factor); | *td->special[tdi].val = td->special[tdi].ival * | ||||
| (1 + (fsize[0] - 1) * td->prop[tdi].factor); | |||||
| td->ext->size[0] = td->ext->isize[0]; | td->ext[tdi].size[0] = td->ext[tdi].isize[0]; | ||||
| td->ext->size[1] = td->ext->isize[1]; | td->ext[tdi].size[1] = td->ext[tdi].isize[1]; | ||||
| td->ext->size[2] = td->ext->isize[2]; | td->ext[tdi].size[2] = td->ext[tdi].isize[2]; | ||||
| } | } | ||||
| else { | else { | ||||
| /* Reset val if SINGLESIZE but using a constraint */ | /* Reset val if SINGLESIZE but using a constraint */ | ||||
| if (td->flag & TD_SINGLESIZE) { | if (td->basic[tdi].flag & TD_SINGLESIZE) { | ||||
| *td->val = td->ival; | *td->special[tdi].val = td->special[tdi].ival; | ||||
| } | } | ||||
| td->ext->size[0] = td->ext->isize[0] * (1 + (fsize[0] - 1) * td->factor); | td->ext[tdi].size[0] = td->ext[tdi].isize[0] * (1 + (fsize[0] - 1) * td->prop[tdi].factor); | ||||
| td->ext->size[1] = td->ext->isize[1] * (1 + (fsize[1] - 1) * td->factor); | td->ext[tdi].size[1] = td->ext[tdi].isize[1] * (1 + (fsize[1] - 1) * td->prop[tdi].factor); | ||||
| td->ext->size[2] = td->ext->isize[2] * (1 + (fsize[2] - 1) * td->factor); | td->ext[tdi].size[2] = td->ext[tdi].isize[2] * (1 + (fsize[2] - 1) * td->prop[tdi].factor); | ||||
| } | } | ||||
| } | } | ||||
| constraintSizeLim(t, td); | constraintSizeLim(t, td, tdi); | ||||
| } | } | ||||
| /* For individual element center, Editmode need to use iloc */ | /* For individual element center, Editmode need to use iloc */ | ||||
| if (t->flag & T_POINTS) { | if (t->flag & T_POINTS) { | ||||
| sub_v3_v3v3(vec, td->iloc, center); | sub_v3_v3v3(vec, td->basic[tdi].iloc, center); | ||||
| } | } | ||||
| else { | else { | ||||
| sub_v3_v3v3(vec, td->center, center); | sub_v3_v3v3(vec, td->center[tdi], center); | ||||
| } | } | ||||
| mul_m3_v3(tmat, vec); | mul_m3_v3(tmat, vec); | ||||
| add_v3_v3(vec, center); | add_v3_v3(vec, center); | ||||
| if (t->flag & T_POINTS) { | if (t->flag & T_POINTS) { | ||||
| sub_v3_v3(vec, td->iloc); | sub_v3_v3(vec, td->basic[tdi].iloc); | ||||
| } | } | ||||
| else { | else { | ||||
| sub_v3_v3(vec, td->center); | sub_v3_v3(vec, td->center[tdi]); | ||||
| } | } | ||||
| /* grease pencil falloff */ | /* grease pencil falloff */ | ||||
| if (t->options & CTX_GPENCIL_STROKES) { | if (t->options & CTX_GPENCIL_STROKES) { | ||||
| bGPDstroke *gps = (bGPDstroke *)td->extra; | bGPDstroke *gps = (bGPDstroke *)td->basic[tdi].extra; | ||||
| mul_v3_fl(vec, td->factor * gps->runtime.multi_frame_falloff); | mul_v3_fl(vec, td->prop[tdi].factor * gps->runtime.multi_frame_falloff); | ||||
| /* scale stroke thickness */ | /* scale stroke thickness */ | ||||
| if (td->val) { | if (td->special[tdi].val) { | ||||
| snapGridIncrement(t, t->values_final); | snapGridIncrement(t, t->values_final); | ||||
| applyNumInput(&t->num, t->values_final); | applyNumInput(&t->num, t->values_final); | ||||
| float ratio = t->values_final[0]; | float ratio = t->values_final[0]; | ||||
| *td->val = td->ival * ratio * gps->runtime.multi_frame_falloff; | *td->special[tdi].val = td->special[tdi].ival * ratio * gps->runtime.multi_frame_falloff; | ||||
| CLAMP_MIN(*td->val, 0.001f); | CLAMP_MIN(*td->special[tdi].val, 0.001f); | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| mul_v3_fl(vec, td->factor); | mul_v3_fl(vec, td->prop[tdi].factor); | ||||
| } | } | ||||
| if (t->flag & (T_OBJECT | T_POSE)) { | if (t->flag & (T_OBJECT | T_POSE)) { | ||||
| mul_m3_v3(td->smtx, vec); | mul_m3_v3(td->space[tdi].smtx, vec); | ||||
| } | } | ||||
| protectedTransBits(td->protectflag, vec); | protectedTransBits(td->object[tdi].protectflag, vec); | ||||
| if (td->loc) { | if (td->basic[tdi].loc) { | ||||
| add_v3_v3v3(td->loc, td->iloc, vec); | add_v3_v3v3(td->basic[tdi].loc, td->basic[tdi].iloc, vec); | ||||
| } | } | ||||
| constraintTransLim(t, td); | constraintTransLim(t, td, tdi); | ||||
| } | } | ||||
| /** \} */ | /** \} */ | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /* Transform (Frame Utils) */ | /* Transform (Frame Utils) */ | ||||
| /** \name Transform Frame Utils | /** \name Transform Frame Utils | ||||
| * \{ */ | * \{ */ | ||||
| ▲ Show 20 Lines • Show All 44 Lines • ▼ Show 20 Lines | short getAnimEdit_SnapMode(TransInfo *t) | ||||
| } | } | ||||
| return autosnap; | return autosnap; | ||||
| } | } | ||||
| /* This function is used by Animation Editor specific transform functions to do | /* This function is used by Animation Editor specific transform functions to do | ||||
| * the Snap Keyframe to Nearest Frame/Marker | * the Snap Keyframe to Nearest Frame/Marker | ||||
| */ | */ | ||||
| void doAnimEdit_SnapFrame( | void doAnimEdit_SnapFrame(TransInfo *t, | ||||
| TransInfo *t, TransData *td, TransData2D *td2d, AnimData *adt, short autosnap) | const TransData *td, | ||||
| const int tdi, | |||||
| TransData2D *td2d, | |||||
| AnimData *adt, | |||||
| short autosnap) | |||||
| { | { | ||||
| if (autosnap != SACTSNAP_OFF) { | if (autosnap != SACTSNAP_OFF) { | ||||
| float val; | float val; | ||||
| /* convert frame to nla-action time (if needed) */ | /* convert frame to nla-action time (if needed) */ | ||||
| if (adt && (t->spacetype != SPACE_SEQ)) { | if (adt && (t->spacetype != SPACE_SEQ)) { | ||||
| val = BKE_nla_tweakedit_remap(adt, *(td->val), NLATIME_CONVERT_MAP); | val = BKE_nla_tweakedit_remap(adt, *(td->special[tdi].val), NLATIME_CONVERT_MAP); | ||||
| } | } | ||||
| else { | else { | ||||
| val = *(td->val); | val = *(td->special[tdi].val); | ||||
| } | } | ||||
| snapFrameTransform(t, autosnap, true, val, &val); | snapFrameTransform(t, autosnap, true, val, &val); | ||||
| /* convert frame out of nla-action time */ | /* convert frame out of nla-action time */ | ||||
| if (adt && (t->spacetype != SPACE_SEQ)) { | if (adt && (t->spacetype != SPACE_SEQ)) { | ||||
| *(td->val) = BKE_nla_tweakedit_remap(adt, val, NLATIME_CONVERT_UNMAP); | *(td->special[tdi].val) = BKE_nla_tweakedit_remap(adt, val, NLATIME_CONVERT_UNMAP); | ||||
| } | } | ||||
| else { | else { | ||||
| *(td->val) = val; | *(td->special[tdi].val) = val; | ||||
| } | } | ||||
| } | } | ||||
| /* If the handles are to be moved too | /* If the handles are to be moved too | ||||
| * (as side-effect of keyframes moving, to keep the general effect) | * (as side-effect of keyframes moving, to keep the general effect) | ||||
| * offset them by the same amount so that the general angles are maintained | * offset them by the same amount so that the general angles are maintained | ||||
| * (i.e. won't change while handles are free-to-roam and keyframes are snap-locked). | * (i.e. won't change while handles are free-to-roam and keyframes are snap-locked). | ||||
| */ | */ | ||||
| if ((td->flag & TD_MOVEHANDLE1) && td2d->h1) { | if ((td->basic[tdi].flag & TD_MOVEHANDLE1) && td2d->h1) { | ||||
| td2d->h1[0] = td2d->ih1[0] + *td->val - td->ival; | td2d->h1[0] = td2d->ih1[0] + *td->special[tdi].val - td->special[tdi].ival; | ||||
| } | } | ||||
| if ((td->flag & TD_MOVEHANDLE2) && td2d->h2) { | if ((td->basic[tdi].flag & TD_MOVEHANDLE2) && td2d->h2) { | ||||
| td2d->h2[0] = td2d->ih2[0] + *td->val - td->ival; | td2d->h2[0] = td2d->ih2[0] + *td->special[tdi].val - td->special[tdi].ival; | ||||
| } | } | ||||
| } | } | ||||
| /** \} */ | /** \} */ | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /** \name Transform Mode Initialization | /** \name Transform Mode Initialization | ||||
| * \{ */ | * \{ */ | ||||
| ▲ Show 20 Lines • Show All 100 Lines • ▼ Show 20 Lines | case TFM_TIME_DUPLICATE: | ||||
| if (ELEM(t->spacetype, SPACE_GRAPH, SPACE_NLA)) { | if (ELEM(t->spacetype, SPACE_GRAPH, SPACE_NLA)) { | ||||
| initTranslation(t); | initTranslation(t); | ||||
| } | } | ||||
| else { | else { | ||||
| initTimeTranslate(t); | initTimeTranslate(t); | ||||
| } | } | ||||
| break; | break; | ||||
| case TFM_TIME_EXTEND: | case TFM_TIME_EXTEND: | ||||
| /* now that transdata has been made, do like for TFM_TIME_TRANSLATE (for most Animation | /* now that TransDataIter has been made, do like for TFM_TIME_TRANSLATE (for most Animation | ||||
| * Editors because they have only 1D transforms for time values) or TFM_TRANSLATION | * Editors because they have only 1D transforms for time values) or TFM_TRANSLATION | ||||
| * (for Graph/NLA Editors only since they uses 'standard' transforms to get 2D movement) | * (for Graph/NLA Editors only since they uses 'standard' transforms to get 2D movement) | ||||
| * depending on which editor this was called from | * depending on which editor this was called from | ||||
| */ | */ | ||||
| if (ELEM(t->spacetype, SPACE_GRAPH, SPACE_NLA)) { | if (ELEM(t->spacetype, SPACE_GRAPH, SPACE_NLA)) { | ||||
| initTranslation(t); | initTranslation(t); | ||||
| } | } | ||||
| else { | else { | ||||
| Show All 32 Lines | |||||