Changeset View
Changeset View
Standalone View
Standalone View
source/blender/editors/transform/transform_convert_armature.c
| Show All 39 Lines | |||||
| #include "ED_armature.h" | #include "ED_armature.h" | ||||
| #include "DEG_depsgraph.h" | #include "DEG_depsgraph.h" | ||||
| #include "DEG_depsgraph_query.h" | #include "DEG_depsgraph_query.h" | ||||
| #include "transform.h" | #include "transform.h" | ||||
| #include "transform_convert.h" | #include "transform_convert.h" | ||||
| #include "transform_data.h" | |||||
| typedef struct BoneInitData { | typedef struct BoneInitData { | ||||
| struct EditBone *bone; | struct EditBone *bone; | ||||
| float tail[3]; | float tail[3]; | ||||
| float rad_head; | float rad_head; | ||||
| float rad_tail; | float rad_tail; | ||||
| float roll; | float roll; | ||||
| float head[3]; | float head[3]; | ||||
| Show All 29 Lines | |||||
| static void update_deg_with_temporary_ik(Main *bmain, Object *ob) | static void update_deg_with_temporary_ik(Main *bmain, Object *ob) | ||||
| { | { | ||||
| BIK_clear_data(ob->pose); | BIK_clear_data(ob->pose); | ||||
| /* TODO(sergey): Consider doing partial update only. */ | /* TODO(sergey): Consider doing partial update only. */ | ||||
| DEG_relations_tag_update(bmain); | DEG_relations_tag_update(bmain); | ||||
| } | } | ||||
| static void add_pose_transdata( | static void add_pose_transdata( | ||||
| TransInfo *t, bPoseChannel *pchan, Object *ob, TransDataContainer *tc, TransData *td) | TransInfo *t, bPoseChannel *pchan, Object *ob, TransDataContainer *tc, const int tdi) | ||||
| { | { | ||||
| const TransData *td = tc->data; | |||||
| Bone *bone = pchan->bone; | Bone *bone = pchan->bone; | ||||
| float pmat[3][3], omat[3][3]; | float pmat[3][3], omat[3][3]; | ||||
| float cmat[3][3], tmat[3][3]; | float cmat[3][3], tmat[3][3]; | ||||
| float vec[3]; | float vec[3]; | ||||
| copy_v3_v3(vec, pchan->pose_mat[3]); | copy_v3_v3(vec, pchan->pose_mat[3]); | ||||
| copy_v3_v3(td->center, vec); | copy_v3_v3(td->center[tdi], vec); | ||||
| td->ob = ob; | td->object[tdi].ob = ob; | ||||
| td->flag = TD_SELECTED; | td->basic[tdi].flag = TD_SELECTED; | ||||
| if (bone->flag & BONE_HINGE_CHILD_TRANSFORM) { | if (bone->flag & BONE_HINGE_CHILD_TRANSFORM) { | ||||
| td->flag |= TD_NOCENTER; | td->basic[tdi].flag |= TD_NOCENTER; | ||||
| } | } | ||||
| if (bone->flag & BONE_TRANSFORM_CHILD) { | if (bone->flag & BONE_TRANSFORM_CHILD) { | ||||
| td->flag |= TD_NOCENTER; | td->basic[tdi].flag |= TD_NOCENTER; | ||||
| td->flag |= TD_NO_LOC; | td->basic[tdi].flag |= TD_NO_LOC; | ||||
| } | } | ||||
| td->extra = pchan; | td->basic[tdi].extra = pchan; | ||||
| td->protectflag = pchan->protectflag; | td->object[tdi].protectflag = pchan->protectflag; | ||||
| td->loc = pchan->loc; | td->basic[tdi].loc = pchan->loc; | ||||
| copy_v3_v3(td->iloc, pchan->loc); | copy_v3_v3(td->basic[tdi].iloc, pchan->loc); | ||||
| td->ext->size = pchan->size; | td->ext[tdi].size = pchan->size; | ||||
| copy_v3_v3(td->ext->isize, pchan->size); | copy_v3_v3(td->ext[tdi].isize, pchan->size); | ||||
| if (pchan->rotmode > 0) { | if (pchan->rotmode > 0) { | ||||
| td->ext->rot = pchan->eul; | td->ext[tdi].rot = pchan->eul; | ||||
| td->ext->rotAxis = NULL; | td->ext[tdi].rotAxis = NULL; | ||||
| td->ext->rotAngle = NULL; | td->ext[tdi].rotAngle = NULL; | ||||
| td->ext->quat = NULL; | td->ext[tdi].quat = NULL; | ||||
| copy_v3_v3(td->ext->irot, pchan->eul); | copy_v3_v3(td->ext[tdi].irot, pchan->eul); | ||||
| } | } | ||||
| else if (pchan->rotmode == ROT_MODE_AXISANGLE) { | else if (pchan->rotmode == ROT_MODE_AXISANGLE) { | ||||
| td->ext->rot = NULL; | td->ext[tdi].rot = NULL; | ||||
| td->ext->rotAxis = pchan->rotAxis; | td->ext[tdi].rotAxis = pchan->rotAxis; | ||||
| td->ext->rotAngle = &pchan->rotAngle; | td->ext[tdi].rotAngle = &pchan->rotAngle; | ||||
| td->ext->quat = NULL; | td->ext[tdi].quat = NULL; | ||||
| td->ext->irotAngle = pchan->rotAngle; | td->ext[tdi].irotAngle = pchan->rotAngle; | ||||
| copy_v3_v3(td->ext->irotAxis, pchan->rotAxis); | copy_v3_v3(td->ext[tdi].irotAxis, pchan->rotAxis); | ||||
| } | } | ||||
| else { | else { | ||||
| td->ext->rot = NULL; | td->ext[tdi].rot = NULL; | ||||
| td->ext->rotAxis = NULL; | td->ext[tdi].rotAxis = NULL; | ||||
| td->ext->rotAngle = NULL; | td->ext[tdi].rotAngle = NULL; | ||||
| td->ext->quat = pchan->quat; | td->ext[tdi].quat = pchan->quat; | ||||
| copy_qt_qt(td->ext->iquat, pchan->quat); | copy_qt_qt(td->ext[tdi].iquat, pchan->quat); | ||||
| } | } | ||||
| td->ext->rotOrder = pchan->rotmode; | td->ext[tdi].rotOrder = pchan->rotmode; | ||||
| /* proper way to get parent transform + own transform + constraints transform */ | /* proper way to get parent transform + own transform + constraints transform */ | ||||
| copy_m3_m4(omat, ob->obmat); | copy_m3_m4(omat, ob->obmat); | ||||
| /* New code, using "generic" BKE_bone_parent_transform_calc_from_pchan(). */ | /* New code, using "generic" BKE_bone_parent_transform_calc_from_pchan(). */ | ||||
| { | { | ||||
| BoneParentTransform bpt; | BoneParentTransform bpt; | ||||
| float rpmat[3][3]; | float rpmat[3][3]; | ||||
| BKE_bone_parent_transform_calc_from_pchan(pchan, &bpt); | BKE_bone_parent_transform_calc_from_pchan(pchan, &bpt); | ||||
| if (t->mode == TFM_TRANSLATION) { | if (t->mode == TFM_TRANSLATION) { | ||||
| copy_m3_m4(pmat, bpt.loc_mat); | copy_m3_m4(pmat, bpt.loc_mat); | ||||
| } | } | ||||
| else { | else { | ||||
| copy_m3_m4(pmat, bpt.rotscale_mat); | copy_m3_m4(pmat, bpt.rotscale_mat); | ||||
| } | } | ||||
| /* Grrr! Exceptional case: When translating pose bones that are either Hinge or NoLocal, | /* Grrr! Exceptional case: When translating pose bones that are either Hinge or NoLocal, | ||||
| * and want align snapping, we just need both loc_mat and rotscale_mat. | * and want align snapping, we just need both loc_mat and rotscale_mat. | ||||
| * So simply always store rotscale mat in td->ext, and always use it to apply rotations... | * So simply always store rotscale mat in td->ext_p[tdi].ext, and always use it to apply | ||||
| * Ugly to need such hacks! :/ */ | * rotations... Ugly to need such hacks! :/ */ | ||||
| copy_m3_m4(rpmat, bpt.rotscale_mat); | copy_m3_m4(rpmat, bpt.rotscale_mat); | ||||
| if (constraints_list_needinv(t, &pchan->constraints)) { | if (constraints_list_needinv(t, &pchan->constraints)) { | ||||
| copy_m3_m4(tmat, pchan->constinv); | copy_m3_m4(tmat, pchan->constinv); | ||||
| invert_m3_m3(cmat, tmat); | invert_m3_m3(cmat, tmat); | ||||
| mul_m3_series(td->mtx, cmat, omat, pmat); | mul_m3_series(td->space[tdi].mtx, cmat, omat, pmat); | ||||
| mul_m3_series(td->ext->r_mtx, cmat, omat, rpmat); | mul_m3_series(td->ext[tdi].r_mtx, cmat, omat, rpmat); | ||||
| } | } | ||||
| else { | else { | ||||
| mul_m3_series(td->mtx, omat, pmat); | mul_m3_series(td->space[tdi].mtx, omat, pmat); | ||||
| mul_m3_series(td->ext->r_mtx, omat, rpmat); | mul_m3_series(td->ext[tdi].r_mtx, omat, rpmat); | ||||
| } | } | ||||
| invert_m3_m3(td->ext->r_smtx, td->ext->r_mtx); | invert_m3_m3(td->ext[tdi].r_smtx, td->ext[tdi].r_mtx); | ||||
| } | } | ||||
| pseudoinverse_m3_m3(td->smtx, td->mtx, PSEUDOINVERSE_EPSILON); | pseudoinverse_m3_m3(td->space[tdi].smtx, td->space[tdi].mtx, PSEUDOINVERSE_EPSILON); | ||||
| /* exceptional case: rotate the pose bone which also applies transformation | /* exceptional case: rotate the pose bone which also applies transformation | ||||
| * when a parentless bone has BONE_NO_LOCAL_LOCATION [] */ | * when a parentless bone has BONE_NO_LOCAL_LOCATION [] */ | ||||
| if (!ELEM(t->mode, TFM_TRANSLATION, TFM_RESIZE) && | if (!ELEM(t->mode, TFM_TRANSLATION, TFM_RESIZE) && | ||||
| (pchan->bone->flag & BONE_NO_LOCAL_LOCATION)) { | (pchan->bone->flag & BONE_NO_LOCAL_LOCATION)) { | ||||
| if (pchan->parent) { | if (pchan->parent) { | ||||
| /* same as td->smtx but without pchan->bone->bone_mat */ | /* same as td->space[tdi].smtx but without pchan->bone->bone_mat */ | ||||
| td->flag |= TD_PBONE_LOCAL_MTX_C; | td->basic[tdi].flag |= TD_PBONE_LOCAL_MTX_C; | ||||
| mul_m3_m3m3(td->ext->l_smtx, pchan->bone->bone_mat, td->smtx); | mul_m3_m3m3(td->ext[tdi].l_smtx, pchan->bone->bone_mat, td->space[tdi].smtx); | ||||
| } | } | ||||
| else { | else { | ||||
| td->flag |= TD_PBONE_LOCAL_MTX_P; | td->basic[tdi].flag |= TD_PBONE_LOCAL_MTX_P; | ||||
| } | } | ||||
| } | } | ||||
| /* for axismat we use bone's own transform */ | /* for axismat we use bone's own transform */ | ||||
| copy_m3_m4(pmat, pchan->pose_mat); | copy_m3_m4(pmat, pchan->pose_mat); | ||||
| mul_m3_m3m3(td->axismtx, omat, pmat); | mul_m3_m3m3(td->space[tdi].axismtx, omat, pmat); | ||||
| normalize_m3(td->axismtx); | normalize_m3(td->space[tdi].axismtx); | ||||
| if (ELEM(t->mode, TFM_BONESIZE, TFM_BONE_ENVELOPE_DIST)) { | if (ELEM(t->mode, TFM_BONESIZE, TFM_BONE_ENVELOPE_DIST)) { | ||||
| bArmature *arm = tc->poseobj->data; | bArmature *arm = tc->poseobj->data; | ||||
| if ((t->mode == TFM_BONE_ENVELOPE_DIST) || (arm->drawtype == ARM_ENVELOPE)) { | if ((t->mode == TFM_BONE_ENVELOPE_DIST) || (arm->drawtype == ARM_ENVELOPE)) { | ||||
| td->loc = NULL; | td->basic[tdi].loc = NULL; | ||||
| td->val = &bone->dist; | td->special[tdi].val = &bone->dist; | ||||
| td->ival = bone->dist; | td->special[tdi].ival = bone->dist; | ||||
| } | } | ||||
| else { | else { | ||||
| // abusive storage of scale in the loc pointer :) | // abusive storage of scale in the loc pointer :) | ||||
| td->loc = &bone->xwidth; | td->basic[tdi].loc = &bone->xwidth; | ||||
| copy_v3_v3(td->iloc, td->loc); | copy_v3_v3(td->basic[tdi].iloc, td->basic[tdi].loc); | ||||
| td->val = NULL; | td->special[tdi].val = NULL; | ||||
| } | } | ||||
| } | } | ||||
| /* in this case we can do target-less IK grabbing */ | /* in this case we can do target-less IK grabbing */ | ||||
| if (t->mode == TFM_TRANSLATION) { | if (t->mode == TFM_TRANSLATION) { | ||||
| bKinematicConstraint *data = has_targetless_ik(pchan); | bKinematicConstraint *data = has_targetless_ik(pchan); | ||||
| if (data) { | if (data) { | ||||
| if (data->flag & CONSTRAINT_IK_TIP) { | if (data->flag & CONSTRAINT_IK_TIP) { | ||||
| copy_v3_v3(data->grabtarget, pchan->pose_tail); | copy_v3_v3(data->grabtarget, pchan->pose_tail); | ||||
| } | } | ||||
| else { | else { | ||||
| copy_v3_v3(data->grabtarget, pchan->pose_head); | copy_v3_v3(data->grabtarget, pchan->pose_head); | ||||
| } | } | ||||
| td->loc = data->grabtarget; | td->basic[tdi].loc = data->grabtarget; | ||||
| copy_v3_v3(td->iloc, td->loc); | copy_v3_v3(td->basic[tdi].iloc, td->basic[tdi].loc); | ||||
| data->flag |= CONSTRAINT_IK_AUTO; | data->flag |= CONSTRAINT_IK_AUTO; | ||||
| /* Add a temporary auto IK constraint here, as we will only temporarily active this | /* Add a temporary auto IK constraint here, as we will only temporarily active this | ||||
| * targetless bone during transform. (Targetless IK constraints are treated as if they are | * targetless bone during transform. (Targetless IK constraints are treated as if they are | ||||
| * disabled unless they are transformed). */ | * disabled unless they are transformed). */ | ||||
| add_temporary_ik_constraint(pchan, data); | add_temporary_ik_constraint(pchan, data); | ||||
| Main *bmain = CTX_data_main(t->context); | Main *bmain = CTX_data_main(t->context); | ||||
| update_deg_with_temporary_ik(bmain, ob); | update_deg_with_temporary_ik(bmain, ob); | ||||
| /* only object matrix correction */ | /* only object matrix correction */ | ||||
| copy_m3_m3(td->mtx, omat); | copy_m3_m3(td->space[tdi].mtx, omat); | ||||
| pseudoinverse_m3_m3(td->smtx, td->mtx, PSEUDOINVERSE_EPSILON); | pseudoinverse_m3_m3(td->space[tdi].smtx, td->space[tdi].mtx, PSEUDOINVERSE_EPSILON); | ||||
| } | } | ||||
| } | } | ||||
| /* store reference to first constraint */ | /* store reference to first constraint */ | ||||
| td->con = pchan->constraints.first; | td->object[tdi].con = pchan->constraints.first; | ||||
| } | } | ||||
| /* -------------------------------------------------------------------- */ | /* -------------------------------------------------------------------- */ | ||||
| /** \name Pose Auto-IK | /** \name Pose Auto-IK | ||||
| * \{ */ | * \{ */ | ||||
| bKinematicConstraint *has_targetless_ik(bPoseChannel *pchan) | bKinematicConstraint *has_targetless_ik(bPoseChannel *pchan) | ||||
| { | { | ||||
| ▲ Show 20 Lines • Show All 302 Lines • ▼ Show 20 Lines | void pose_transform_mirror_update(TransInfo *t, TransDataContainer *tc, Object *ob) | ||||
| bPose *pose = ob->pose; | bPose *pose = ob->pose; | ||||
| PoseInitData_Mirror *pid = NULL; | PoseInitData_Mirror *pid = NULL; | ||||
| if ((t->mode != TFM_BONESIZE) && (pose->flag & POSE_MIRROR_RELATIVE)) { | if ((t->mode != TFM_BONESIZE) && (pose->flag & POSE_MIRROR_RELATIVE)) { | ||||
| pid = tc->custom.type.data; | pid = tc->custom.type.data; | ||||
| } | } | ||||
| TransData *td = tc->data; | TransData *td = tc->data; | ||||
| for (int i = tc->data_len; i--; td++) { | for (int tdi = 0; tdi < tc->data_len; tdi++) { | ||||
| bPoseChannel *pchan_orig = td->extra; | bPoseChannel *pchan_orig = td->basic[tdi].extra; | ||||
| BLI_assert(pchan_orig->bone->flag & BONE_TRANSFORM); | BLI_assert(pchan_orig->bone->flag & BONE_TRANSFORM); | ||||
| /* No layer check, correct mirror is more important. */ | /* No layer check, correct mirror is more important. */ | ||||
| bPoseChannel *pchan = BKE_pose_channel_get_mirrored(pose, pchan_orig->name); | bPoseChannel *pchan = BKE_pose_channel_get_mirrored(pose, pchan_orig->name); | ||||
| if (pchan == NULL) { | if (pchan == NULL) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| /* Also do bbone scaling. */ | /* Also do bbone scaling. */ | ||||
| Show All 19 Lines | for (int tdi = 0; tdi < tc->data_len; tdi++) { | ||||
| pchan->bone->flag |= BONE_TRANSFORM_MIRROR; | pchan->bone->flag |= BONE_TRANSFORM_MIRROR; | ||||
| /* In this case we can do target-less IK grabbing. */ | /* In this case we can do target-less IK grabbing. */ | ||||
| if (t->mode == TFM_TRANSLATION) { | if (t->mode == TFM_TRANSLATION) { | ||||
| bKinematicConstraint *data = has_targetless_ik(pchan); | bKinematicConstraint *data = has_targetless_ik(pchan); | ||||
| if (data == NULL) { | if (data == NULL) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| mul_v3_m4v3(data->grabtarget, flip_mtx, td->loc); | mul_v3_m4v3(data->grabtarget, flip_mtx, td->basic[tdi].loc); | ||||
| if (pid) { | if (pid) { | ||||
| /* TODO(germano): Realitve Mirror support */ | /* TODO(germano): Realitve Mirror support */ | ||||
| } | } | ||||
| data->flag |= CONSTRAINT_IK_AUTO; | data->flag |= CONSTRAINT_IK_AUTO; | ||||
| /* Add a temporary auto IK constraint here, as we will only temporarily active this | /* Add a temporary auto IK constraint here, as we will only temporarily active this | ||||
| * target-less bone during transform. (Target-less IK constraints are treated as if they are | * target-less bone during transform. (Target-less IK constraints are treated as if they are | ||||
| * disabled unless they are transformed) */ | * disabled unless they are transformed) */ | ||||
| add_temporary_ik_constraint(pchan, data); | add_temporary_ik_constraint(pchan, data); | ||||
| ▲ Show 20 Lines • Show All 91 Lines • ▼ Show 20 Lines | FOREACH_TRANS_DATA_CONTAINER (t, tc) { | ||||
| } | } | ||||
| } | } | ||||
| FOREACH_TRANS_DATA_CONTAINER (t, tc) { | FOREACH_TRANS_DATA_CONTAINER (t, tc) { | ||||
| if (tc->data_len == 0) { | if (tc->data_len == 0) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| Object *ob = tc->poseobj; | Object *ob = tc->poseobj; | ||||
| TransData *td; | |||||
| TransDataExtension *tdx; | TransDataExtension *tdx; | ||||
| int i; | int tdi; | ||||
| PoseInitData_Mirror *pid = tc->custom.type.data; | PoseInitData_Mirror *pid = tc->custom.type.data; | ||||
| int pid_index = 0; | int pid_index = 0; | ||||
| bPose *pose = ob->pose; | bPose *pose = ob->pose; | ||||
| if (pose == NULL) { | if (pose == NULL) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| const bool mirror = ((pose->flag & POSE_MIRROR_EDIT) != 0); | const bool mirror = ((pose->flag & POSE_MIRROR_EDIT) != 0); | ||||
| const bool is_mirror_relative = ((pose->flag & POSE_MIRROR_RELATIVE) != 0); | const bool is_mirror_relative = ((pose->flag & POSE_MIRROR_RELATIVE) != 0); | ||||
| tc->poseobj = ob; /* we also allow non-active objects to be transformed, in weightpaint */ | tc->poseobj = ob; /* we also allow non-active objects to be transformed, in weightpaint */ | ||||
| /* init trans data */ | /* init trans data */ | ||||
| td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransPoseBone"); | TransData *td = tc->data = transform_data_alloc(tc->data_len, TD_ALL_COMP); | ||||
| tdx = tc->data_ext = MEM_callocN(tc->data_len * sizeof(TransDataExtension), | tdx = &td->ext[0]; | ||||
| "TransPoseBoneExt"); | |||||
| for (i = 0; i < tc->data_len; i++, td++, tdx++) { | |||||
| td->ext = tdx; | |||||
| td->val = NULL; | |||||
| } | |||||
| if (mirror) { | if (mirror) { | ||||
| LISTBASE_FOREACH (bPoseChannel *, pchan, &pose->chanbase) { | LISTBASE_FOREACH (bPoseChannel *, pchan, &pose->chanbase) { | ||||
| if (pchan->bone->flag & BONE_TRANSFORM) { | if (pchan->bone->flag & BONE_TRANSFORM) { | ||||
| bPoseChannel *pchan_mirror = BKE_pose_channel_get_mirrored(ob->pose, pchan->name); | bPoseChannel *pchan_mirror = BKE_pose_channel_get_mirrored(ob->pose, pchan->name); | ||||
| if (pchan_mirror) { | if (pchan_mirror) { | ||||
| pchan_mirror->bone->flag |= BONE_TRANSFORM_MIRROR; | pchan_mirror->bone->flag |= BONE_TRANSFORM_MIRROR; | ||||
| pose_mirror_info_init(&pid[pid_index], pchan_mirror, pchan, is_mirror_relative); | pose_mirror_info_init(&pid[pid_index], pchan_mirror, pchan, is_mirror_relative); | ||||
| pid_index++; | pid_index++; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| /* do we need to add temporal IK chains? */ | /* do we need to add temporal IK chains? */ | ||||
| if ((pose->flag & POSE_AUTO_IK) && t->mode == TFM_TRANSLATION) { | if ((pose->flag & POSE_AUTO_IK) && t->mode == TFM_TRANSLATION) { | ||||
| if (pose_grab_with_ik(bmain, ob)) { | if (pose_grab_with_ik(bmain, ob)) { | ||||
| t->flag |= T_AUTOIK; | t->flag |= T_AUTOIK; | ||||
| has_translate_rotate[0] = true; | has_translate_rotate[0] = true; | ||||
| } | } | ||||
| } | } | ||||
| /* use pose channels to fill trans data */ | /* use pose channels to fill trans data */ | ||||
| td = tc->data; | tdi = 0; | ||||
| LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) { | LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) { | ||||
| if (pchan->bone->flag & BONE_TRANSFORM) { | if (pchan->bone->flag & BONE_TRANSFORM) { | ||||
| add_pose_transdata(t, pchan, ob, tc, td); | add_pose_transdata(t, pchan, ob, tc, tdi); | ||||
| td++; | tdi++; | ||||
| } | } | ||||
| } | } | ||||
| if (td != (tc->data + tc->data_len)) { | if (tdi != tc->data_len) { | ||||
| BKE_report(t->reports, RPT_DEBUG, "Bone selection count error"); | BKE_report(t->reports, RPT_DEBUG, "Bone selection count error"); | ||||
| } | } | ||||
| } | } | ||||
| /* initialize initial auto=ik chainlen's? */ | /* initialize initial auto=ik chainlen's? */ | ||||
| if (t->flag & T_AUTOIK) { | if (t->flag & T_AUTOIK) { | ||||
| transform_autoik_update(t, 0); | transform_autoik_update(t, 0); | ||||
| } | } | ||||
| ▲ Show 20 Lines • Show All 127 Lines • ▼ Show 20 Lines | void createTransArmatureVerts(TransInfo *t) | ||||
| FOREACH_TRANS_DATA_CONTAINER (t, tc) { | FOREACH_TRANS_DATA_CONTAINER (t, tc) { | ||||
| if (!tc->data_len) { | if (!tc->data_len) { | ||||
| continue; | continue; | ||||
| } | } | ||||
| EditBone *ebo, *eboflip; | EditBone *ebo, *eboflip; | ||||
| bArmature *arm = tc->obedit->data; | bArmature *arm = tc->obedit->data; | ||||
| ListBase *edbo = arm->edbo; | ListBase *edbo = arm->edbo; | ||||
| TransData *td, *td_old; | |||||
| float mtx[3][3], smtx[3][3], bonemat[3][3]; | float mtx[3][3], smtx[3][3], bonemat[3][3]; | ||||
| bool mirror = ((arm->flag & ARM_MIRROR_EDIT) != 0); | bool mirror = ((arm->flag & ARM_MIRROR_EDIT) != 0); | ||||
| BoneInitData *bid = tc->custom.type.data; | BoneInitData *bid = tc->custom.type.data; | ||||
| copy_m3_m4(mtx, tc->obedit->obmat); | copy_m3_m4(mtx, tc->obedit->obmat); | ||||
| pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON); | pseudoinverse_m3_m3(smtx, mtx, PSEUDOINVERSE_EPSILON); | ||||
| td = tc->data = MEM_callocN(tc->data_len * sizeof(TransData), "TransEditBone"); | TransData *td = tc->data = transform_data_alloc(tc->data_len, TD_BASIC_COMP); | ||||
| int tdi = 0; | |||||
| int i = 0; | int i = 0; | ||||
| int tdi_old; | |||||
| for (ebo = edbo->first; ebo; ebo = ebo->next) { | for (ebo = edbo->first; ebo; ebo = ebo->next) { | ||||
| td_old = td; | tdi_old = tdi; | ||||
| ebo->oldlength = | ebo->oldlength = | ||||
| ebo->length; // length==0.0 on extrude, used for scaling radius of bone points | ebo->length; // length==0.0 on extrude, used for scaling radius of bone points | ||||
| if (EBONE_VISIBLE(arm, ebo) && !(ebo->flag & BONE_EDITMODE_LOCKED)) { | if (EBONE_VISIBLE(arm, ebo) && !(ebo->flag & BONE_EDITMODE_LOCKED)) { | ||||
| if (t->mode == TFM_BONE_ENVELOPE) { | if (t->mode == TFM_BONE_ENVELOPE) { | ||||
| if (ebo->flag & BONE_ROOTSEL) { | if (ebo->flag & BONE_ROOTSEL) { | ||||
| td->val = &ebo->rad_head; | td->special[tdi].val = &ebo->rad_head; | ||||
| td->ival = *td->val; | td->special[tdi].ival = *td->special[tdi].val; | ||||
| copy_v3_v3(td->center, ebo->head); | copy_v3_v3(td->center[tdi], ebo->head); | ||||
| td->flag = TD_SELECTED; | td->basic[tdi].flag = TD_SELECTED; | ||||
| copy_m3_m3(td->smtx, smtx); | copy_m3_m3(td->space[tdi].smtx, smtx); | ||||
| copy_m3_m3(td->mtx, mtx); | copy_m3_m3(td->space[tdi].mtx, mtx); | ||||
| td->loc = NULL; | td->basic[tdi].loc = NULL; | ||||
| td->ext = NULL; | td->object[tdi].ob = tc->obedit; | ||||
| td->ob = tc->obedit; | |||||
| td++; | tdi++; | ||||
| } | } | ||||
| if (ebo->flag & BONE_TIPSEL) { | if (ebo->flag & BONE_TIPSEL) { | ||||
| td->val = &ebo->rad_tail; | td->special[tdi].val = &ebo->rad_tail; | ||||
| td->ival = *td->val; | td->special[tdi].ival = *td->special[tdi].val; | ||||
| copy_v3_v3(td->center, ebo->tail); | copy_v3_v3(td->center[tdi], ebo->tail); | ||||
| td->flag = TD_SELECTED; | td->basic[tdi].flag = TD_SELECTED; | ||||
| copy_m3_m3(td->smtx, smtx); | copy_m3_m3(td->space[tdi].smtx, smtx); | ||||
| copy_m3_m3(td->mtx, mtx); | copy_m3_m3(td->space[tdi].mtx, mtx); | ||||
| td->loc = NULL; | td->basic[tdi].loc = NULL; | ||||
| td->ext = NULL; | td->object[tdi].ob = tc->obedit; | ||||
| td->ob = tc->obedit; | |||||
| td++; | tdi++; | ||||
| } | } | ||||
| } | } | ||||
| else if (ELEM(t->mode, TFM_BONESIZE, TFM_BONE_ENVELOPE_DIST)) { | else if (ELEM(t->mode, TFM_BONESIZE, TFM_BONE_ENVELOPE_DIST)) { | ||||
| if (ebo->flag & BONE_SELECTED) { | if (ebo->flag & BONE_SELECTED) { | ||||
| if ((t->mode == TFM_BONE_ENVELOPE_DIST) || (arm->drawtype == ARM_ENVELOPE)) { | if ((t->mode == TFM_BONE_ENVELOPE_DIST) || (arm->drawtype == ARM_ENVELOPE)) { | ||||
| td->loc = NULL; | td->basic[tdi].loc = NULL; | ||||
| td->val = &ebo->dist; | td->special[tdi].val = &ebo->dist; | ||||
| td->ival = ebo->dist; | td->special[tdi].ival = ebo->dist; | ||||
| } | } | ||||
| else { | else { | ||||
| // abusive storage of scale in the loc pointer :) | // abusive storage of scale in the loc pointer :) | ||||
| td->loc = &ebo->xwidth; | td->basic[tdi].loc = &ebo->xwidth; | ||||
| copy_v3_v3(td->iloc, td->loc); | copy_v3_v3(td->basic[tdi].iloc, td->basic[tdi].loc); | ||||
| td->val = NULL; | td->special[tdi].val = NULL; | ||||
| } | } | ||||
| copy_v3_v3(td->center, ebo->head); | copy_v3_v3(td->center[tdi], ebo->head); | ||||
| td->flag = TD_SELECTED; | td->basic[tdi].flag = TD_SELECTED; | ||||
| /* use local bone matrix */ | /* use local bone matrix */ | ||||
| ED_armature_ebone_to_mat3(ebo, bonemat); | ED_armature_ebone_to_mat3(ebo, bonemat); | ||||
| mul_m3_m3m3(td->mtx, mtx, bonemat); | mul_m3_m3m3(td->space[tdi].mtx, mtx, bonemat); | ||||
| invert_m3_m3(td->smtx, td->mtx); | invert_m3_m3(td->space[tdi].smtx, td->space[tdi].mtx); | ||||
| copy_m3_m3(td->axismtx, td->mtx); | copy_m3_m3(td->space[tdi].axismtx, td->space[tdi].mtx); | ||||
| normalize_m3(td->axismtx); | normalize_m3(td->space[tdi].axismtx); | ||||
| td->ext = NULL; | td->object[tdi].ob = tc->obedit; | ||||
| td->ob = tc->obedit; | |||||
| td++; | tdi++; | ||||
| } | } | ||||
| } | } | ||||
| else if (t->mode == TFM_BONE_ROLL) { | else if (t->mode == TFM_BONE_ROLL) { | ||||
| if (ebo->flag & BONE_SELECTED) { | if (ebo->flag & BONE_SELECTED) { | ||||
| td->loc = NULL; | td->basic[tdi].loc = NULL; | ||||
| td->val = &(ebo->roll); | td->special[tdi].val = &(ebo->roll); | ||||
| td->ival = ebo->roll; | td->special[tdi].ival = ebo->roll; | ||||
| copy_v3_v3(td->center, ebo->head); | copy_v3_v3(td->center[tdi], ebo->head); | ||||
| td->flag = TD_SELECTED; | td->basic[tdi].flag = TD_SELECTED; | ||||
| td->ext = NULL; | td->object[tdi].ob = tc->obedit; | ||||
| td->ob = tc->obedit; | |||||
| td++; | tdi++; | ||||
| } | } | ||||
| } | } | ||||
| else { | else { | ||||
| if (ebo->flag & BONE_TIPSEL) { | if (ebo->flag & BONE_TIPSEL) { | ||||
| copy_v3_v3(td->iloc, ebo->tail); | copy_v3_v3(td->basic[tdi].iloc, ebo->tail); | ||||
| /* Don't allow single selected tips to have a modified center, | /* Don't allow single selected tips to have a modified center, | ||||
| * causes problem with snapping (see T45974). | * causes problem with snapping (see T45974). | ||||
| * However, in rotation mode, we want to keep that 'rotate bone around root with | * However, in rotation mode, we want to keep that 'rotate bone around root with | ||||
| * only its tip selected' behavior (see T46325). */ | * only its tip selected' behavior (see T46325). */ | ||||
| if ((t->around == V3D_AROUND_LOCAL_ORIGINS) && | if ((t->around == V3D_AROUND_LOCAL_ORIGINS) && | ||||
| ((t->mode == TFM_ROTATION) || (ebo->flag & BONE_ROOTSEL))) { | ((t->mode == TFM_ROTATION) || (ebo->flag & BONE_ROOTSEL))) { | ||||
| copy_v3_v3(td->center, ebo->head); | copy_v3_v3(td->center[tdi], ebo->head); | ||||
| } | } | ||||
| else { | else { | ||||
| copy_v3_v3(td->center, td->iloc); | copy_v3_v3(td->center[tdi], td->basic[tdi].iloc); | ||||
| } | } | ||||
| td->loc = ebo->tail; | td->basic[tdi].loc = ebo->tail; | ||||
| td->flag = TD_SELECTED; | td->basic[tdi].flag = TD_SELECTED; | ||||
| if (ebo->flag & BONE_EDITMODE_LOCKED) { | if (ebo->flag & BONE_EDITMODE_LOCKED) { | ||||
| td->protectflag = OB_LOCK_LOC | OB_LOCK_ROT | OB_LOCK_SCALE; | td->object[tdi].protectflag = OB_LOCK_LOC | OB_LOCK_ROT | OB_LOCK_SCALE; | ||||
| } | } | ||||
| copy_m3_m3(td->smtx, smtx); | copy_m3_m3(td->space[tdi].smtx, smtx); | ||||
| copy_m3_m3(td->mtx, mtx); | copy_m3_m3(td->space[tdi].mtx, mtx); | ||||
| ED_armature_ebone_to_mat3(ebo, td->axismtx); | ED_armature_ebone_to_mat3(ebo, td->space[tdi].axismtx); | ||||
| if ((ebo->flag & BONE_ROOTSEL) == 0) { | if ((ebo->flag & BONE_ROOTSEL) == 0) { | ||||
| td->extra = ebo; | td->basic[tdi].extra = ebo; | ||||
| td->ival = ebo->roll; | td->special[tdi].ival = ebo->roll; | ||||
| } | } | ||||
| td->ext = NULL; | td->special[tdi].val = NULL; | ||||
| td->val = NULL; | td->object[tdi].ob = tc->obedit; | ||||
| td->ob = tc->obedit; | |||||
| td++; | tdi++; | ||||
| } | } | ||||
| if (ebo->flag & BONE_ROOTSEL) { | if (ebo->flag & BONE_ROOTSEL) { | ||||
| copy_v3_v3(td->iloc, ebo->head); | copy_v3_v3(td->basic[tdi].iloc, ebo->head); | ||||
| copy_v3_v3(td->center, td->iloc); | copy_v3_v3(td->center[tdi], td->basic[tdi].iloc); | ||||
| td->loc = ebo->head; | td->basic[tdi].loc = ebo->head; | ||||
| td->flag = TD_SELECTED; | td->basic[tdi].flag = TD_SELECTED; | ||||
| if (ebo->flag & BONE_EDITMODE_LOCKED) { | if (ebo->flag & BONE_EDITMODE_LOCKED) { | ||||
| td->protectflag = OB_LOCK_LOC | OB_LOCK_ROT | OB_LOCK_SCALE; | td->object[tdi].protectflag = OB_LOCK_LOC | OB_LOCK_ROT | OB_LOCK_SCALE; | ||||
| } | } | ||||
| copy_m3_m3(td->smtx, smtx); | copy_m3_m3(td->space[tdi].smtx, smtx); | ||||
| copy_m3_m3(td->mtx, mtx); | copy_m3_m3(td->space[tdi].mtx, mtx); | ||||
| ED_armature_ebone_to_mat3(ebo, td->axismtx); | ED_armature_ebone_to_mat3(ebo, td->space[tdi].axismtx); | ||||
| td->extra = ebo; /* to fix roll */ | td->basic[tdi].extra = ebo; /* to fix roll */ | ||||
| td->ival = ebo->roll; | td->special[tdi].ival = ebo->roll; | ||||
| td->ext = NULL; | td->special[tdi].val = NULL; | ||||
| td->val = NULL; | td->object[tdi].ob = tc->obedit; | ||||
| td->ob = tc->obedit; | |||||
| td++; | tdi++; | ||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| if (mirror && (td_old != td)) { | if (mirror && (tdi_old != tdi)) { | ||||
| eboflip = ED_armature_ebone_get_mirrored(arm->edbo, ebo); | eboflip = ED_armature_ebone_get_mirrored(arm->edbo, ebo); | ||||
| if (eboflip) { | if (eboflip) { | ||||
| bid[i].bone = eboflip; | bid[i].bone = eboflip; | ||||
| bid[i].dist = eboflip->dist; | bid[i].dist = eboflip->dist; | ||||
| bid[i].rad_head = eboflip->rad_head; | bid[i].rad_head = eboflip->rad_head; | ||||
| bid[i].rad_tail = eboflip->rad_tail; | bid[i].rad_tail = eboflip->rad_tail; | ||||
| bid[i].roll = eboflip->roll; | bid[i].roll = eboflip->roll; | ||||
| bid[i].xwidth = eboflip->xwidth; | bid[i].xwidth = eboflip->xwidth; | ||||
| Show All 17 Lines | |||||