diff options
-rw-r--r-- | release/scripts/startup/bl_ui/properties_data_bone.py | 6 | ||||
-rw-r--r-- | release/scripts/startup/bl_ui/space_view3d.py | 2 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_armature.h | 1 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/armature.c | 104 | ||||
-rw-r--r-- | source/blender/blenlib/BLI_math_matrix.h | 6 | ||||
-rw-r--r-- | source/blender/blenlib/intern/math_matrix.c | 126 | ||||
-rw-r--r-- | source/blender/blenloader/intern/versioning_280.c | 19 | ||||
-rw-r--r-- | source/blender/editors/armature/armature_edit.c | 6 | ||||
-rw-r--r-- | source/blender/editors/armature/armature_utils.c | 2 | ||||
-rw-r--r-- | source/blender/editors/armature/pose_transform.c | 32 | ||||
-rw-r--r-- | source/blender/editors/include/ED_armature.h | 1 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_armature_types.h | 19 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_armature.c | 76 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_armature_api.c | 5 |
14 files changed, 364 insertions, 41 deletions
diff --git a/release/scripts/startup/bl_ui/properties_data_bone.py b/release/scripts/startup/bl_ui/properties_data_bone.py index 8b691ddcc2a..c50b9414667 100644 --- a/release/scripts/startup/bl_ui/properties_data_bone.py +++ b/release/scripts/startup/bl_ui/properties_data_bone.py @@ -232,11 +232,13 @@ class BONE_PT_relations(BoneButtonsPanel, Panel): sub = col.column() sub.active = (bone.parent is not None) sub.prop(bone, "use_connect") - sub.prop(bone, "use_inherit_rotation") - sub.prop(bone, "use_inherit_scale") sub = col.column() sub.active = (not bone.parent or not bone.use_connect) sub.prop(bone, "use_local_location") + sub = col.column() + sub.active = (bone.parent is not None) + sub.prop(bone, "use_inherit_rotation") + sub.prop(bone, "inherit_scale") class BONE_PT_display(BoneButtonsPanel, Panel): diff --git a/release/scripts/startup/bl_ui/space_view3d.py b/release/scripts/startup/bl_ui/space_view3d.py index 501cda1d67a..fdf683c16ea 100644 --- a/release/scripts/startup/bl_ui/space_view3d.py +++ b/release/scripts/startup/bl_ui/space_view3d.py @@ -3193,7 +3193,7 @@ class BoneOptions: "use_deform", "use_envelope_multiply", "use_inherit_rotation", - "use_inherit_scale", + "inherit_scale", ] if context.mode == 'EDIT_ARMATURE': diff --git a/source/blender/blenkernel/BKE_armature.h b/source/blender/blenkernel/BKE_armature.h index 3beae7a1f9d..b255500272a 100644 --- a/source/blender/blenkernel/BKE_armature.h +++ b/source/blender/blenkernel/BKE_armature.h @@ -182,6 +182,7 @@ void BKE_bone_parent_transform_apply(const struct BoneParentTransform *bpt, void BKE_bone_parent_transform_calc_from_pchan(const struct bPoseChannel *pchan, struct BoneParentTransform *r_bpt); void BKE_bone_parent_transform_calc_from_matrices(int bone_flag, + int inherit_scale_mode, const float offs_bone[4][4], const float parent_arm_mat[4][4], const float parent_pose_mat[4][4], diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c index 168422a4454..c31d1a77404 100644 --- a/source/blender/blenkernel/intern/armature.c +++ b/source/blender/blenkernel/intern/armature.c @@ -1867,11 +1867,16 @@ void BKE_bone_parent_transform_calc_from_pchan(const bPoseChannel *pchan, /* yoffs(b-1) + root(b) + bonemat(b). */ BKE_bone_offset_matrix_get(bone, offs_bone); - BKE_bone_parent_transform_calc_from_matrices( - bone->flag, offs_bone, parbone->arm_mat, parchan->pose_mat, r_bpt); + BKE_bone_parent_transform_calc_from_matrices(bone->flag, + bone->inherit_scale_mode, + offs_bone, + parbone->arm_mat, + parchan->pose_mat, + r_bpt); } else { - BKE_bone_parent_transform_calc_from_matrices(bone->flag, bone->arm_mat, NULL, NULL, r_bpt); + BKE_bone_parent_transform_calc_from_matrices( + bone->flag, bone->inherit_scale_mode, bone->arm_mat, NULL, NULL, r_bpt); } } @@ -1882,39 +1887,90 @@ void BKE_bone_parent_transform_calc_from_pchan(const bPoseChannel *pchan, * parent_arm_mat, parent_pose_mat: arm_mat and pose_mat of parent, or NULL * r_bpt: OUTPUT parent transform */ void BKE_bone_parent_transform_calc_from_matrices(int bone_flag, + int inherit_scale_mode, const float offs_bone[4][4], const float parent_arm_mat[4][4], const float parent_pose_mat[4][4], BoneParentTransform *r_bpt) { if (parent_pose_mat) { + const bool use_rotation = (bone_flag & BONE_HINGE) == 0; + const bool full_transform = use_rotation && inherit_scale_mode == BONE_INHERIT_SCALE_FULL; + /* Compose the rotscale matrix for this bone. */ - if ((bone_flag & BONE_HINGE) && (bone_flag & BONE_NO_SCALE)) { - /* Parent rest rotation and scale. */ - mul_m4_m4m4(r_bpt->rotscale_mat, parent_arm_mat, offs_bone); + if (full_transform) { + /* Parent pose rotation and scale. */ + mul_m4_m4m4(r_bpt->rotscale_mat, parent_pose_mat, offs_bone); } - else if (bone_flag & BONE_HINGE) { - /* Parent rest rotation and pose scale. */ + else { float tmat[4][4], tscale[3]; - /* Extract the scale of the parent pose matrix. */ - mat4_to_size(tscale, parent_pose_mat); - size_to_mat4(tmat, tscale); + /* If using parent pose rotation: */ + if (use_rotation) { + copy_m4_m4(tmat, parent_pose_mat); + + /* Normalize the matrix when needed. */ + switch (inherit_scale_mode) { + case BONE_INHERIT_SCALE_FULL: + case BONE_INHERIT_SCALE_FIX_SHEAR: + /* Keep scale and shear. */ + break; + + case BONE_INHERIT_SCALE_NONE: + case BONE_INHERIT_SCALE_AVERAGE: + /* Remove scale and shear from parent. */ + orthogonalize_m4_stable(tmat, 1, true); + break; + + case BONE_INHERIT_SCALE_NONE_LEGACY: + /* Remove only scale - bad legacy way. */ + normalize_m4(tmat); + break; + + default: + BLI_assert(false); + } + } + /* If removing parent pose rotation: */ + else { + copy_m4_m4(tmat, parent_arm_mat); + + /* Copy the parent scale when needed. */ + switch (inherit_scale_mode) { + case BONE_INHERIT_SCALE_FULL: + /* Ignore effects of shear. */ + mat4_to_size(tscale, parent_pose_mat); + rescale_m4(tmat, tscale); + break; + + case BONE_INHERIT_SCALE_FIX_SHEAR: + /* Take the effects of parent shear into account to get exact volume. */ + mat4_to_size_fix_shear(tscale, parent_pose_mat); + rescale_m4(tmat, tscale); + break; + + case BONE_INHERIT_SCALE_NONE: + case BONE_INHERIT_SCALE_AVERAGE: + case BONE_INHERIT_SCALE_NONE_LEGACY: + /* Keep unscaled. */ + break; + + default: + BLI_assert(false); + } + } - /* Applies the parent pose scale to the rest matrix. */ - mul_m4_m4m4(tmat, tmat, parent_arm_mat); + /* Apply the average parent scale when needed. */ + if (inherit_scale_mode == BONE_INHERIT_SCALE_AVERAGE) { + mul_mat3_m4_fl(tmat, cbrtf(fabsf(mat4_to_volume_scale(parent_pose_mat)))); + } mul_m4_m4m4(r_bpt->rotscale_mat, tmat, offs_bone); - } - else if (bone_flag & BONE_NO_SCALE) { - /* Parent pose rotation and rest scale (i.e. no scaling). */ - float tmat[4][4]; - copy_m4_m4(tmat, parent_pose_mat); - normalize_m4(tmat); - mul_m4_m4m4(r_bpt->rotscale_mat, tmat, offs_bone); - } - else { - mul_m4_m4m4(r_bpt->rotscale_mat, parent_pose_mat, offs_bone); + + /* Remove remaining shear when needed, preserving volume. */ + if (inherit_scale_mode == BONE_INHERIT_SCALE_FIX_SHEAR) { + orthogonalize_m4_stable(r_bpt->rotscale_mat, 1, false); + } } /* Compose the loc matrix for this bone. */ @@ -1938,7 +1994,7 @@ void BKE_bone_parent_transform_calc_from_matrices(int bone_flag, mul_m4_m4m4(r_bpt->loc_mat, bone_loc, tmat4); } /* Those flags do not affect position, use plain parent transform space! */ - else if (bone_flag & (BONE_HINGE | BONE_NO_SCALE)) { + else if (!full_transform) { mul_m4_m4m4(r_bpt->loc_mat, parent_pose_mat, offs_bone); } /* Else (i.e. default, usual case), diff --git a/source/blender/blenlib/BLI_math_matrix.h b/source/blender/blenlib/BLI_math_matrix.h index f5d87667b73..00c301a01bc 100644 --- a/source/blender/blenlib/BLI_math_matrix.h +++ b/source/blender/blenlib/BLI_math_matrix.h @@ -252,6 +252,9 @@ void normalize_m4_m4(float R[4][4], const float A[4][4]) ATTR_NONNULL(); void orthogonalize_m3(float R[3][3], int axis); void orthogonalize_m4(float R[4][4], int axis); +void orthogonalize_m3_stable(float R[3][3], int axis, bool normalize); +void orthogonalize_m4_stable(float R[4][4], int axis, bool normalize); + bool is_orthogonal_m3(const float mat[3][3]); bool is_orthogonal_m4(const float mat[4][4]); bool is_orthonormal_m3(const float mat[3][3]); @@ -303,8 +306,11 @@ void size_to_mat4(float R[4][4], const float size[3]); void mat3_to_size(float r[3], const float M[3][3]); void mat4_to_size(float r[3], const float M[4][4]); +void mat4_to_size_fix_shear(float r[3], const float M[4][4]); + void translate_m4(float mat[4][4], float tx, float ty, float tz); void rotate_m4(float mat[4][4], const char axis, const float angle); +void rescale_m4(float mat[4][4], float scale[3]); void transform_pivot_set_m4(float mat[4][4], const float pivot[3]); void mat3_to_rot_size(float rot[3][3], float size[3], const float mat3[3][3]); diff --git a/source/blender/blenlib/intern/math_matrix.c b/source/blender/blenlib/intern/math_matrix.c index 2568d42566c..7c1b44978e2 100644 --- a/source/blender/blenlib/intern/math_matrix.c +++ b/source/blender/blenlib/intern/math_matrix.c @@ -1516,6 +1516,111 @@ void orthogonalize_m4(float mat[4][4], int axis) mul_v3_fl(mat[2], size[2]); } +/** Make an orthonormal basis around v1 in a way that is stable and symmetric. */ +static void orthogonalize_stable(float v1[3], float v2[3], float v3[3], bool normalize) +{ + /* Make secondary axis vectors orthogonal to the primary via + * plane projection, which preserves the determinant. */ + float len_sq_v1 = len_squared_v3(v1); + + if (len_sq_v1 > 0.0f) { + madd_v3_v3fl(v2, v1, -dot_v3v3(v2, v1) / len_sq_v1); + madd_v3_v3fl(v3, v1, -dot_v3v3(v3, v1) / len_sq_v1); + + if (normalize) { + mul_v3_fl(v1, 1.0f / sqrtf(len_sq_v1)); + } + } + + /* Make secondary axis vectors orthogonal relative to each other. */ + float norm_v2[3], norm_v3[3], tmp[3]; + float length_v2 = normalize_v3_v3(norm_v2, v2); + float length_v3 = normalize_v3_v3(norm_v3, v3); + float cos_angle = dot_v3v3(norm_v2, norm_v3); + float abs_cos_angle = fabsf(cos_angle); + + /* Apply correction if the shear angle is significant, and not degenerate. */ + if (abs_cos_angle > 1e-4f && abs_cos_angle < 1.0f - FLT_EPSILON) { + /* Adjust v2 by half of the necessary angle correction. + * Thus the angle change is the same for both axis directions. */ + float angle = acosf(cos_angle); + float target_angle = angle + ((float)M_PI_2 - angle) / 2; + + madd_v3_v3fl(norm_v2, norm_v3, -cos_angle); + mul_v3_fl(norm_v2, sinf(target_angle) / len_v3(norm_v2)); + madd_v3_v3fl(norm_v2, norm_v3, cosf(target_angle)); + + /* Make v3 orthogonal. */ + cross_v3_v3v3(tmp, norm_v2, norm_v3); + cross_v3_v3v3(norm_v3, tmp, norm_v2); + normalize_v3(norm_v3); + + /* Re-apply scale, preserving area and proportion. */ + if (!normalize) { + float scale_fac = sqrtf(sinf(angle)); + mul_v3_v3fl(v2, norm_v2, length_v2 * scale_fac); + mul_v3_v3fl(v3, norm_v3, length_v3 * scale_fac); + } + } + + if (normalize) { + copy_v3_v3(v2, norm_v2); + copy_v3_v3(v3, norm_v3); + } +} + +/** + * Make an orthonormal matrix around the selected axis of the given matrix, + * in a way that is symmetric and stable to variations in the input, and + * preserving the value of the determinant, i.e. the overall volume change. + * + * \param axis: Axis to build the orthonormal basis around. + * \param normalize: Normalize the matrix instead of preserving volume. + */ +void orthogonalize_m3_stable(float R[3][3], int axis, bool normalize) +{ + switch (axis) { + case 0: + orthogonalize_stable(R[0], R[1], R[2], normalize); + break; + case 1: + orthogonalize_stable(R[1], R[0], R[2], normalize); + break; + case 2: + orthogonalize_stable(R[2], R[0], R[1], normalize); + break; + default: + BLI_assert(0); + break; + } +} + +/** + * Make an orthonormal matrix around the selected axis of the given matrix, + * in a way that is symmetric and stable to variations in the input, and + * preserving the value of the determinant, i.e. the overall volume change. + * + * \param axis: Axis to build the orthonormal basis around. + * \param normalize: Normalize the matrix instead of preserving volume. + */ +void orthogonalize_m4_stable(float R[4][4], int axis, bool normalize) +{ + switch (axis) { + case 0: + orthogonalize_stable(R[0], R[1], R[2], normalize); + break; + case 1: + orthogonalize_stable(R[1], R[0], R[2], normalize); + break; + case 2: + orthogonalize_stable(R[2], R[0], R[1], normalize); + break; + default: + BLI_assert(0); + break; + } +} + bool is_orthogonal_m3(const float m[3][3]) { int i, j; @@ -1851,6 +1956,19 @@ void mat4_to_size(float size[3], const float mat[4][4]) size[2] = len_v3(mat[2]); } +/** Extract scale factors from the matrix, with correction to ensure + * exact volume in case of a sheared matrix. */ +void mat4_to_size_fix_shear(float size[3], const float mat[4][4]) +{ + mat4_to_size(size, mat); + + float volume = size[0] * size[1] * size[2]; + + if (volume != 0.0f) { + mul_v3_fl(size, cbrtf(fabsf(mat4_to_volume_scale(mat) / volume))); + } +} + /** * This computes the overall volume scale factor of a transformation matrix. * For an orthogonal matrix, it is the product of all three scale values. @@ -2045,6 +2163,14 @@ void rotate_m4(float mat[4][4], const char axis, const float angle) } } +/** Scale a matrix in-place. */ +void rescale_m4(float mat[4][4], float scale[3]) +{ + mul_v3_fl(mat[0], scale[0]); + mul_v3_fl(mat[1], scale[1]); + mul_v3_fl(mat[2], scale[2]); +} + /** * Scale or rotate around a pivot point, * a convenience function to avoid having to do inline. diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c index 454f1921586..45276181102 100644 --- a/source/blender/blenloader/intern/versioning_280.c +++ b/source/blender/blenloader/intern/versioning_280.c @@ -637,6 +637,18 @@ static void do_version_bones_split_bbone_scale(ListBase *lb) } } +static void do_version_bones_inherit_scale(ListBase *lb) +{ + for (Bone *bone = lb->first; bone; bone = bone->next) { + if (bone->flag & BONE_NO_SCALE) { + bone->inherit_scale_mode = BONE_INHERIT_SCALE_NONE_LEGACY; + bone->flag &= ~BONE_NO_SCALE; + } + + do_version_bones_inherit_scale(&bone->childbase); + } +} + static bool replace_bbone_scale_rnapath(char **p_old_path) { char *old_path = *p_old_path; @@ -3756,5 +3768,12 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain) } } } + + /* Convert the BONE_NO_SCALE flag to inherit_scale_mode enum. */ + if (!DNA_struct_elem_find(fd->filesdna, "Bone", "char", "inherit_scale_mode")) { + LISTBASE_FOREACH (bArmature *, arm, &bmain->armatures) { + do_version_bones_inherit_scale(&arm->bonebase); + } + } } } diff --git a/source/blender/editors/armature/armature_edit.c b/source/blender/editors/armature/armature_edit.c index c4c10549da3..64857dd1874 100644 --- a/source/blender/editors/armature/armature_edit.c +++ b/source/blender/editors/armature/armature_edit.c @@ -908,8 +908,10 @@ static void bones_merge( newbone->parent = start->parent; /* TODO, copy more things to the new bone */ - newbone->flag = start->flag & (BONE_HINGE | BONE_NO_DEFORM | BONE_NO_SCALE | - BONE_NO_CYCLICOFFSET | BONE_NO_LOCAL_LOCATION | BONE_DONE); + newbone->flag = start->flag & (BONE_HINGE | BONE_NO_DEFORM | BONE_NO_CYCLICOFFSET | + BONE_NO_LOCAL_LOCATION | BONE_DONE); + + newbone->inherit_scale_mode = start->inherit_scale_mode; /* Step 2a: reparent any side chains which may be parented to any bone in the chain * of bones to merge - potentially several tips for side chains leading to some tree exist. diff --git a/source/blender/editors/armature/armature_utils.c b/source/blender/editors/armature/armature_utils.c index cd299906b4c..2b18fc15f63 100644 --- a/source/blender/editors/armature/armature_utils.c +++ b/source/blender/editors/armature/armature_utils.c @@ -491,6 +491,7 @@ static EditBone *make_boneList_rec(ListBase *edbo, eBone->parent = parent; BLI_strncpy(eBone->name, curBone->name, sizeof(eBone->name)); eBone->flag = curBone->flag; + eBone->inherit_scale_mode = curBone->inherit_scale_mode; /* fix selection flags */ if (eBone->flag & BONE_SELECTED) { @@ -719,6 +720,7 @@ void ED_armature_from_edit(Main *bmain, bArmature *arm) newBone->arm_roll = eBone->roll; newBone->flag = eBone->flag; + newBone->inherit_scale_mode = eBone->inherit_scale_mode; if (eBone == arm->act_edbone) { /* don't change active selection, this messes up separate which uses diff --git a/source/blender/editors/armature/pose_transform.c b/source/blender/editors/armature/pose_transform.c index 854fb237929..52a3f7711c4 100644 --- a/source/blender/editors/armature/pose_transform.c +++ b/source/blender/editors/armature/pose_transform.c @@ -241,13 +241,21 @@ static void applyarmature_process_selected_rec(bArmature *arm, /* Parent effects on the bone transform that have to be removed. */ BKE_bone_offset_matrix_get(bone, offs_bone); - BKE_bone_parent_transform_calc_from_matrices( - bone->flag, offs_bone, bone->parent->arm_mat, pchan_eval->parent->pose_mat, &old_bpt); + BKE_bone_parent_transform_calc_from_matrices(bone->flag, + bone->inherit_scale_mode, + offs_bone, + bone->parent->arm_mat, + pchan_eval->parent->pose_mat, + &old_bpt); /* Applied parent effects that have to be kept, if any. */ float(*new_parent_pose)[4] = pstate ? pstate->new_rest_mat : bone->parent->arm_mat; - BKE_bone_parent_transform_calc_from_matrices( - bone->flag, offs_bone, bone->parent->arm_mat, new_parent_pose, &new_bpt); + BKE_bone_parent_transform_calc_from_matrices(bone->flag, + bone->inherit_scale_mode, + offs_bone, + bone->parent->arm_mat, + new_parent_pose, + &new_bpt); BKE_bone_parent_transform_invert(&old_bpt); BKE_bone_parent_transform_combine(&new_bpt, &old_bpt, &invparent); @@ -283,8 +291,12 @@ static void applyarmature_process_selected_rec(bArmature *arm, /* Include applied parent effects. */ BKE_bone_offset_matrix_get(bone, offs_bone); - BKE_bone_parent_transform_calc_from_matrices( - bone->flag, offs_bone, pstate->bone->arm_mat, pstate->new_rest_mat, &bpt); + BKE_bone_parent_transform_calc_from_matrices(bone->flag, + bone->inherit_scale_mode, + offs_bone, + pstate->bone->arm_mat, + pstate->new_rest_mat, + &bpt); unit_m4(new_pstate.new_rest_mat); BKE_bone_parent_transform_apply(&bpt, new_pstate.new_rest_mat, new_pstate.new_rest_mat); @@ -306,8 +318,12 @@ static void applyarmature_process_selected_rec(bArmature *arm, /* Compute the channel coordinate space matrices for the new rest state. */ invert_m4_m4(inv_parent_arm, pstate->new_arm_mat); mul_m4_m4m4(offs_bone, inv_parent_arm, new_pstate.new_arm_mat); - BKE_bone_parent_transform_calc_from_matrices( - bone->flag, offs_bone, pstate->new_arm_mat, pstate->new_arm_mat, &bpt); + BKE_bone_parent_transform_calc_from_matrices(bone->flag, + bone->inherit_scale_mode, + offs_bone, + pstate->new_arm_mat, + pstate->new_arm_mat, + &bpt); /* Re-apply the location to keep the final effect. */ invert_m4(bpt.loc_mat); diff --git a/source/blender/editors/include/ED_armature.h b/source/blender/editors/include/ED_armature.h index 48d0a5fe8be..173ba65fc47 100644 --- a/source/blender/editors/include/ED_armature.h +++ b/source/blender/editors/include/ED_armature.h @@ -73,6 +73,7 @@ typedef struct EditBone { * animation are automatically relative to the bones' rest positions*/ int flag; int layer; + char inherit_scale_mode; /* Envelope distance & weight */ float dist, weight; diff --git a/source/blender/makesdna/DNA_armature_types.h b/source/blender/makesdna/DNA_armature_types.h index 088fd96a5ae..68241df3f93 100644 --- a/source/blender/makesdna/DNA_armature_types.h +++ b/source/blender/makesdna/DNA_armature_types.h @@ -60,6 +60,9 @@ typedef struct Bone { int flag; + char inherit_scale_mode; + char _pad[7]; + float arm_head[3]; /** head/tail in Armature Space (rest pos). */ float arm_tail[3]; @@ -229,8 +232,10 @@ typedef enum eBone_Flag { BONE_UNKEYED = (1 << 13), /** set to prevent hinge child bones from influencing the transform center */ BONE_HINGE_CHILD_TRANSFORM = (1 << 14), +#ifdef DNA_DEPRECATED /** No parent scale */ BONE_NO_SCALE = (1 << 15), +#endif /** hidden bone when drawing PoseChannels (for ghost drawing) */ BONE_HIDDEN_PG = (1 << 16), /** bone should be drawn as OB_WIRE, regardless of draw-types of view+armature */ @@ -254,6 +259,20 @@ typedef enum eBone_Flag { } eBone_Flag; +/* bone->inherit_scale_mode */ +typedef enum eBone_InheritScaleMode { + /* Inherit all scale and shear. */ + BONE_INHERIT_SCALE_FULL = 0, + /* Inherit scale, but remove final shear. */ + BONE_INHERIT_SCALE_FIX_SHEAR, + /* Inherit average scale. */ + BONE_INHERIT_SCALE_AVERAGE, + /* Inherit no scale or shear. */ + BONE_INHERIT_SCALE_NONE, + /* Inherit effects of shear on parent (same as old disabled Inherit Scale). */ + BONE_INHERIT_SCALE_NONE_LEGACY, +} eBone_InheritScaleMode; + /* bone->bbone_prev_type, bbone_next_type */ typedef enum eBone_BBoneHandleType { BBONE_HANDLE_AUTO = 0, /* Default mode based on parents & children. */ diff --git a/source/blender/makesrna/intern/rna_armature.c b/source/blender/makesrna/intern/rna_armature.c index 7949db9055f..cfcc37adf6c 100644 --- a/source/blender/makesrna/intern/rna_armature.c +++ b/source/blender/makesrna/intern/rna_armature.c @@ -303,6 +303,40 @@ static void rna_Bone_layer_set(PointerRNA *ptr, const bool *values) BKE_armature_refresh_layer_used(arm); } +/* TODO: remove the deprecation stubs. */ +static bool rna_use_inherit_scale_get(char inherit_scale_mode) +{ + return inherit_scale_mode <= BONE_INHERIT_SCALE_FIX_SHEAR; +} + +static void rna_use_inherit_scale_set(char *inherit_scale_mode, bool value) +{ + bool cur_value = (*inherit_scale_mode <= BONE_INHERIT_SCALE_FIX_SHEAR); + if (value != cur_value) { + *inherit_scale_mode = (value ? BONE_INHERIT_SCALE_FULL : BONE_INHERIT_SCALE_NONE); + } +} + +static bool rna_EditBone_use_inherit_scale_get(PointerRNA *ptr) +{ + return rna_use_inherit_scale_get(((EditBone *)ptr->data)->inherit_scale_mode); +} + +static void rna_EditBone_use_inherit_scale_set(PointerRNA *ptr, bool value) +{ + rna_use_inherit_scale_set(&((EditBone *)ptr->data)->inherit_scale_mode, value); +} + +static bool rna_Bone_use_inherit_scale_get(PointerRNA *ptr) +{ + return rna_use_inherit_scale_get(((Bone *)ptr->data)->inherit_scale_mode); +} + +static void rna_Bone_use_inherit_scale_set(PointerRNA *ptr, bool value) +{ + rna_use_inherit_scale_set(&((Bone *)ptr->data)->inherit_scale_mode, value); +} + static void rna_Armature_layer_set(PointerRNA *ptr, const bool *values) { bArmature *arm = (bArmature *)ptr->data; @@ -773,6 +807,28 @@ static void rna_def_bone_common(StructRNA *srna, int editbone) {0, NULL, 0, NULL, NULL}, }; + static const EnumPropertyItem prop_inherit_scale_mode[] = { + {BONE_INHERIT_SCALE_FULL, "FULL", 0, "Full", "Inherit all effects of parent scaling"}, + {BONE_INHERIT_SCALE_FIX_SHEAR, + "FIX_SHEAR", + 0, + "Fix Shear", + "Inherit scaling, but remove shearing of the child in the rest orientation"}, + {BONE_INHERIT_SCALE_AVERAGE, + "AVERAGE", + 0, + "Average", + "Inherit uniform scaling representing the overall change in the volume of the parent"}, + {BONE_INHERIT_SCALE_NONE, "NONE", 0, "None", "Completely ignore parent scaling"}, + {BONE_INHERIT_SCALE_NONE_LEGACY, + "NONE_LEGACY", + 0, + "None (Legacy)", + "Ignore parent scaling without compensating for parent shear. " + "Replicates the effect of disabling the original Inherit Scale checkbox"}, + {0, NULL, 0, NULL, NULL}, + }; + PropertyRNA *prop; /* strings */ @@ -832,9 +888,25 @@ static void rna_def_bone_common(StructRNA *srna, int editbone) RNA_def_property_ui_text(prop, "Deform", "Enable Bone to deform geometry"); RNA_def_property_update(prop, 0, "rna_Armature_update_data"); + prop = RNA_def_property(srna, "inherit_scale", PROP_ENUM, PROP_NONE); + RNA_def_property_ui_text( + prop, "Inherit Scale", "Specifies how the bone inherits scaling from the parent bone"); + RNA_def_property_enum_sdna(prop, NULL, "inherit_scale_mode"); + RNA_def_property_enum_items(prop, prop_inherit_scale_mode); + RNA_def_property_update(prop, 0, "rna_Armature_update_data"); + + /* TODO: remove the compatibility stub. */ prop = RNA_def_property(srna, "use_inherit_scale", PROP_BOOLEAN, PROP_NONE); - RNA_def_property_ui_text(prop, "Inherit Scale", "Bone inherits scaling from parent bone"); - RNA_def_property_boolean_negative_sdna(prop, NULL, "flag", BONE_NO_SCALE); + RNA_def_property_ui_text( + prop, "Inherit Scale", "DEPRECATED: Bone inherits scaling from parent bone"); + if (editbone) { + RNA_def_property_boolean_funcs( + prop, "rna_EditBone_use_inherit_scale_get", "rna_EditBone_use_inherit_scale_set"); + } + else { + RNA_def_property_boolean_funcs( + prop, "rna_Bone_use_inherit_scale_get", "rna_Bone_use_inherit_scale_set"); + } RNA_def_property_update(prop, 0, "rna_Armature_update_data"); prop = RNA_def_property(srna, "use_local_location", PROP_BOOLEAN, PROP_NONE); diff --git a/source/blender/makesrna/intern/rna_armature_api.c b/source/blender/makesrna/intern/rna_armature_api.c index f3bdef75c9c..2b60dbde39f 100644 --- a/source/blender/makesrna/intern/rna_armature_api.c +++ b/source/blender/makesrna/intern/rna_armature_api.c @@ -71,14 +71,15 @@ static void rna_Bone_convert_local_to_pose(Bone *bone, if (is_zero_m4(parent_pose_mat) || is_zero_m4(parent_arm_mat)) { /* No parent case. */ - BKE_bone_parent_transform_calc_from_matrices(bone->flag, bone_arm_mat, NULL, NULL, &bpt); + BKE_bone_parent_transform_calc_from_matrices( + bone->flag, bone->inherit_scale_mode, bone_arm_mat, NULL, NULL, &bpt); } else { invert_m4_m4(offs_bone, parent_arm_mat); mul_m4_m4m4(offs_bone, offs_bone, bone_arm_mat); BKE_bone_parent_transform_calc_from_matrices( - bone->flag, offs_bone, parent_arm_mat, parent_pose_mat, &bpt); + bone->flag, bone->inherit_scale_mode, offs_bone, parent_arm_mat, parent_pose_mat, &bpt); } if (invert) { |