diff options
author | Sebastian Parborg <darkdefende@gmail.com> | 2019-05-06 10:47:45 +0300 |
---|---|---|
committer | Sebastian Parborg <darkdefende@gmail.com> | 2019-05-06 10:47:45 +0300 |
commit | 09181540b5aa889df6aa24bea4ce9a4823e0c18d (patch) | |
tree | 9d4daaf5f0f41883d64b8e6f21bca49e7cfcea84 /source/blender/editors/transform/transform_generics.c | |
parent | f999c40d77f32594e3fdd5800758e70aa9a314f3 (diff) |
Implement mirroring in pose mode (absolute and relative)
Added working X-mirroring in pose mode with an optional relative mirror
mode.
Reviewed By: Campbell Barton
Differential Revision: http://developer.blender.org/D4765
Diffstat (limited to 'source/blender/editors/transform/transform_generics.c')
-rw-r--r-- | source/blender/editors/transform/transform_generics.c | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/source/blender/editors/transform/transform_generics.c b/source/blender/editors/transform/transform_generics.c index a840c04ab5a..05bb9785112 100644 --- a/source/blender/editors/transform/transform_generics.c +++ b/source/blender/editors/transform/transform_generics.c @@ -781,6 +781,45 @@ static void recalcData_spaceclip(TransInfo *t) } } +/** + * if pose bone (partial) selected, copy data. + * context; posemode armature, with mirror editing enabled. + * + * \param pid: Optional, apply relative transform when set. + */ +static void pose_transform_mirror_update(Object *ob, PoseInitData_Mirror *pid) +{ + float flip_mtx[4][4]; + unit_m4(flip_mtx); + flip_mtx[0][0] = -1; + + for (bPoseChannel *pchan_orig = ob->pose->chanbase.first; pchan_orig; + pchan_orig = pchan_orig->next) { + /* no layer check, correct mirror is more important */ + if (pchan_orig->bone->flag & BONE_TRANSFORM) { + bPoseChannel *pchan = BKE_pose_channel_get_mirrored(ob->pose, pchan_orig->name); + + if (pchan) { + /* we assume X-axis flipping for now */ + pchan->curve_in_x = pchan_orig->curve_in_x * -1; + pchan->curve_out_x = pchan_orig->curve_out_x * -1; + pchan->roll1 = pchan_orig->roll1 * -1; // XXX? + pchan->roll2 = pchan_orig->roll2 * -1; // XXX? + + float pchan_mtx_final[4][4]; + BKE_pchan_to_mat4(pchan_orig, pchan_mtx_final); + mul_m4_m4m4(pchan_mtx_final, pchan_mtx_final, flip_mtx); + mul_m4_m4m4(pchan_mtx_final, flip_mtx, pchan_mtx_final); + if (pid) { + mul_m4_m4m4(pchan_mtx_final, pid->offset_mtx, pchan_mtx_final); + pid++; + } + BKE_pchan_apply_mat4(pchan, pchan_mtx_final, false); + } + } + } +} + /* helper for recalcData() - for object transforms, typically in the 3D view */ static void recalcData_objects(TransInfo *t) { @@ -992,6 +1031,19 @@ static void recalcData_objects(TransInfo *t) Object *ob = tc->poseobj; bArmature *arm = ob->data; + if (arm->flag & ARM_MIRROR_EDIT) { + if (t->state != TRANS_CANCEL) { + PoseInitData_Mirror *pid = NULL; + if (arm->flag & ARM_MIRROR_RELATIVE) { + pid = tc->custom.type.data; + } + pose_transform_mirror_update(ob, pid); + } + else { + restoreMirrorPoseBones(tc); + } + } + /* if animtimer is running, and the object already has animation data, * check if the auto-record feature means that we should record 'samples' * (i.e. un-editable animation values) |