Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--release/scripts/startup/bl_ui/properties_data_bone.py6
-rw-r--r--release/scripts/startup/bl_ui/space_view3d.py2
-rw-r--r--source/blender/blenkernel/BKE_armature.h1
-rw-r--r--source/blender/blenkernel/intern/armature.c104
-rw-r--r--source/blender/blenlib/BLI_math_matrix.h6
-rw-r--r--source/blender/blenlib/intern/math_matrix.c126
-rw-r--r--source/blender/blenloader/intern/versioning_280.c19
-rw-r--r--source/blender/editors/armature/armature_edit.c6
-rw-r--r--source/blender/editors/armature/armature_utils.c2
-rw-r--r--source/blender/editors/armature/pose_transform.c32
-rw-r--r--source/blender/editors/include/ED_armature.h1
-rw-r--r--source/blender/makesdna/DNA_armature_types.h19
-rw-r--r--source/blender/makesrna/intern/rna_armature.c76
-rw-r--r--source/blender/makesrna/intern/rna_armature_api.c5
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) {