diff options
author | Alexander Gavrilov <angavrilov@gmail.com> | 2018-10-05 20:00:32 +0300 |
---|---|---|
committer | Alexander Gavrilov <angavrilov@gmail.com> | 2018-10-05 20:19:58 +0300 |
commit | 25bd9feadb36053bdef938b52f77caf0a34016ad (patch) | |
tree | 02bcc662aa524ad8c544dab14f18329d0ff61727 /source/blender | |
parent | 6723e173a52769602846ed485f6f3341077eaa02 (diff) |
Add a new B-Bone Custom Handle type that uses the handle bone direction.
Both original handle types are based on location, and Absolute uses it
in a weird way: the Start handle uses the head, while End uses the tail.
This makes controlling the shape of the B-Bone via control bone rotation
really non-intuitive, especially if trying to add a single control for
the tangent in the middle of a B-Bone chain.
To remedy this, add a new custom handle type that uses the orientation
of the control bone, while completely ignoring location. It is even
possible to control both ends of one B-Bone with the same handle bone,
resulting in an S shape.
Reviewers: brecht
Differential Revision: https://developer.blender.org/D3769
Diffstat (limited to 'source/blender')
-rw-r--r-- | source/blender/blenkernel/intern/armature.c | 25 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_armature.c | 11 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_armature_types.h | 1 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_armature.c | 1 |
4 files changed, 36 insertions, 2 deletions
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index 91661f0a4e3..198cc526865 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -468,6 +468,7 @@ void b_bone_spline_setup(bPoseChannel *pchan, int rest, Mat4 result_array[MAX_BB Bone *bone = pchan->bone; BBoneSplineParameters param; float imat[4][4], posemat[4][4]; + float delta[3]; memset(¶m, 0, sizeof(param)); @@ -518,11 +519,21 @@ void b_bone_spline_setup(bPoseChannel *pchan, int rest, Mat4 result_array[MAX_BB done = true; } else { - float delta[3]; sub_v3_v3v3(delta, prev->pose_head, prev->bone->arm_head); sub_v3_v3v3(h1, pchan->pose_head, delta); } } + else if (bone->bbone_prev_type == BBONE_HANDLE_TANGENT) { + /* Use bone direction by offsetting so that its tail meets current bone's head */ + if (rest) { + sub_v3_v3v3(delta, prev->bone->arm_tail, prev->bone->arm_head); + sub_v3_v3v3(h1, bone->arm_head, delta); + } + else { + sub_v3_v3v3(delta, prev->pose_tail, prev->pose_head); + sub_v3_v3v3(h1, pchan->pose_head, delta); + } + } else { /* Apply special handling for smoothly joining B-Bone chains */ param.prev_bbone = (prev->bone->segments > 1); @@ -556,11 +567,21 @@ void b_bone_spline_setup(bPoseChannel *pchan, int rest, Mat4 result_array[MAX_BB done = true; } else { - float delta[3]; sub_v3_v3v3(delta, next->pose_head, next->bone->arm_head); add_v3_v3v3(h2, pchan->pose_tail, delta); } } + else if (bone->bbone_next_type == BBONE_HANDLE_TANGENT) { + /* Use bone direction by offsetting so that its head meets current bone's tail */ + if (rest) { + sub_v3_v3v3(delta, next->bone->arm_tail, next->bone->arm_head); + add_v3_v3v3(h2, bone->arm_tail, delta); + } + else { + sub_v3_v3v3(delta, next->pose_tail, next->pose_head); + add_v3_v3v3(h2, pchan->pose_tail, delta); + } + } else { /* Apply special handling for smoothly joining B-Bone chains */ param.next_bbone = (next->bone->segments > 1); diff --git a/source/blender/draw/intern/draw_armature.c b/source/blender/draw/intern/draw_armature.c index a73bddf880f..5f8a2d00188 100644 --- a/source/blender/draw/intern/draw_armature.c +++ b/source/blender/draw/intern/draw_armature.c @@ -940,6 +940,7 @@ static void ebone_spline_preview(EditBone *ebone, float result_array[MAX_BBONE_S BBoneSplineParameters param; EditBone *prev, *next; float imat[4][4], bonemat[4][4]; + float tmp[3]; memset(¶m, 0, sizeof(param)); @@ -979,6 +980,11 @@ static void ebone_spline_preview(EditBone *ebone, float result_array[MAX_BBONE_S if (ebone->bbone_prev_type == BBONE_HANDLE_RELATIVE) { zero_v3(param.prev_h); } + else if (ebone->bbone_prev_type == BBONE_HANDLE_TANGENT) { + sub_v3_v3v3(tmp, prev->tail, prev->head); + sub_v3_v3v3(tmp, ebone->head, tmp); + mul_v3_m4v3(param.prev_h, imat, tmp); + } else { param.prev_bbone = (prev->segments > 1); @@ -997,6 +1003,11 @@ static void ebone_spline_preview(EditBone *ebone, float result_array[MAX_BBONE_S if (ebone->bbone_next_type == BBONE_HANDLE_RELATIVE) { copy_v3_fl3(param.next_h, 0.0f, param.length, 0.0); } + else if (ebone->bbone_next_type == BBONE_HANDLE_TANGENT) { + sub_v3_v3v3(tmp, next->tail, next->head); + add_v3_v3v3(tmp, ebone->tail, tmp); + mul_v3_m4v3(param.next_h, imat, tmp); + } else { param.next_bbone = (next->segments > 1); diff --git a/source/blender/makesdna/DNA_armature_types.h b/source/blender/makesdna/DNA_armature_types.h index 141ad7c3ce0..3e68ddcb96b 100644 --- a/source/blender/makesdna/DNA_armature_types.h +++ b/source/blender/makesdna/DNA_armature_types.h @@ -221,6 +221,7 @@ typedef enum eBone_BBoneHandleType { BBONE_HANDLE_AUTO = 0, /* Default mode based on parents & children. */ BBONE_HANDLE_ABSOLUTE, /* Custom handle in absolute position mode. */ BBONE_HANDLE_RELATIVE, /* Custom handle in relative position mode. */ + BBONE_HANDLE_TANGENT, /* Custom handle in tangent mode (use direction, not location). */ } eBone_BBoneHandleType; #define MAXBONENAME 64 diff --git a/source/blender/makesrna/intern/rna_armature.c b/source/blender/makesrna/intern/rna_armature.c index 4fd42a97568..2a83d7350bb 100644 --- a/source/blender/makesrna/intern/rna_armature.c +++ b/source/blender/makesrna/intern/rna_armature.c @@ -655,6 +655,7 @@ static void rna_def_bone_common(StructRNA *srna, int editbone) {BBONE_HANDLE_AUTO, "AUTO", 0, "Automatic", "Use connected parent and children to compute the handle"}, {BBONE_HANDLE_ABSOLUTE, "ABSOLUTE", 0, "Absolute", "Use the position of the specified bone to compute the handle"}, {BBONE_HANDLE_RELATIVE, "RELATIVE", 0, "Relative", "Use the offset of the specified bone from rest pose to compute the handle"}, + {BBONE_HANDLE_TANGENT, "TANGENT", 0, "Tangent", "Use the orientation of the specified bone to compute the handle, ignoring the location"}, {0, NULL, 0, NULL, NULL} }; |