Fix #137398: Transforming editbones can propagate wrong envelope radii

When tweaking envelope radii of (connected) envelope bones, we dont
always make sure that corresponding head and tail radii are in sync.
Using the `Bone Size` tool should take care of this (and it works to
some extend) but tweaking the radii through the sidepanel UI or the
Properties Editor (through RNA), then corresponding heads and tails
radii get out of sync.

Once we are in such unfortunate situation, then code in the transform
system's `recalcData_edit_armature` fails with wrong assumptions, it
propagates radii from children to parents which are unexpected / not in
use.

So one thing to do would be to add this syncing of radii to
`rna_Armature_editbone_transform_update`.
This alone would solve the "problem" in new files.

For existing files that are already out of sync we  add versioning that
corrects this on file load

Pull Request: https://projects.blender.org/blender/blender/pulls/137599
This commit is contained in:
Philipp Oeser
2025-04-30 09:18:34 +02:00
committed by Philipp Oeser
parent cf319d108d
commit 17d8650d2d
3 changed files with 21 additions and 1 deletions

View File

@@ -27,7 +27,7 @@
/* Blender file format version. */
#define BLENDER_FILE_VERSION BLENDER_VERSION
#define BLENDER_FILE_SUBVERSION 56
#define BLENDER_FILE_SUBVERSION 57
/* Minimum Blender version that supports reading file written with the current
* version. Older Blender versions will test this and cancel loading the file, showing a warning to

View File

@@ -9953,6 +9953,24 @@ void blo_do_versions_400(FileData *fd, Library * /*lib*/, Main *bmain)
version_convert_sculpt_planar_brushes(bmain);
}
/* Enforce that bone envelope radii match for parent and connected children. */
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 405, 57)) {
LISTBASE_FOREACH (bArmature *, arm, &bmain->armatures) {
blender::animrig::ANIM_armature_foreach_bone(&arm->bonebase, [](Bone *bone) {
if (bone->parent && (bone->flag & BONE_CONNECTED)) {
bone->rad_head = bone->parent->rad_tail;
}
});
if (arm->edbo) {
LISTBASE_FOREACH (EditBone *, ebone, arm->edbo) {
if (ebone->parent && (ebone->flag & BONE_CONNECTED)) {
ebone->rad_head = ebone->parent->rad_tail;
}
}
}
}
}
/* Always run this versioning (keep at the bottom of the function). Meshes are written with the
* legacy format which always needs to be converted to the new format on file load. To be moved
* to a subversion check in 5.0. */

View File

@@ -1035,12 +1035,14 @@ static void rna_Armature_editbone_transform_update(Main *bmain, Scene *scene, Po
/* update our parent */
if (ebone->parent && ebone->flag & BONE_CONNECTED) {
copy_v3_v3(ebone->parent->tail, ebone->head);
ebone->parent->rad_tail = ebone->rad_head;
}
/* update our children if necessary */
for (child = static_cast<EditBone *>(arm->edbo->first); child; child = child->next) {
if (child->parent == ebone && (child->flag & BONE_CONNECTED)) {
copy_v3_v3(child->head, ebone->tail);
child->rad_head = ebone->rad_tail;
}
}