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:
authorBastien Montagne <bastien@blender.org>2020-11-25 13:20:12 +0300
committerBastien Montagne <bastien@blender.org>2020-11-27 18:18:59 +0300
commitfbdf1af3555027696df5b687c7fe8d345e4c39e9 (patch)
tree722f9d0146507cc372a0a1edc9d5002a9ab8b7dd /source/blender/blenkernel/intern/armature.c
parente4e7dfc1d8c0486530e5cabd2e448bf79b2fdb0b (diff)
Fix T82758: Convert Proxy to Override: Local constraints aren't saved.
Ensure consistent order of pose bones. Now it should always match the one from bones in armature obdata (as exposed by e.g. RNA, i.e. children-first). Previously when some pose bones would need to be added or removed from a pose due to changes in the bone armature, or if bones in armature were re-ordered, the bones order in pose would not match anymore the one from armature, and could even become different between e.g. a proxy and its linked source. This was not really nice, but not a big issue before either. But with diffing process of override, consistent order of items between reference linked collection and local override one is crucial. Reviewed By: #animation_rigging, sybren Maniphest Tasks: T82758 Differential Revision: https://developer.blender.org/D9646
Diffstat (limited to 'source/blender/blenkernel/intern/armature.c')
-rw-r--r--source/blender/blenkernel/intern/armature.c32
1 files changed, 29 insertions, 3 deletions
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index b5d3a04acb8..92146082557 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -2440,17 +2440,42 @@ static void pose_proxy_sync(Object *ob, Object *from, int layer_protected)
}
}
-static int rebuild_pose_bone(bPose *pose, Bone *bone, bPoseChannel *parchan, int counter)
+/**
+ * \param r_last_visited_bone_p the last bone handled by the last call to this function.
+ */
+static int rebuild_pose_bone(
+ bPose *pose, Bone *bone, bPoseChannel *parchan, int counter, Bone **r_last_visited_bone_p)
{
bPoseChannel *pchan = BKE_pose_channel_verify(pose, bone->name); /* verify checks and/or adds */
pchan->bone = bone;
pchan->parent = parchan;
+ /* We ensure the current pchan is immediately after the one we just generated/updated in the
+ * previous call to `rebuild_pose_bone`.
+ *
+ * It may be either the parent, the previous sibling, or the last
+ * (grand-(grand-(...)))-child (as processed by the recursive, depth-first nature of this
+ * function) of the previous sibling.
+ *
+ * Note: In most cases there is nothing to do here, but pose list may get out of order when some
+ * bones are added, removed or moved in the armature data. */
+ bPoseChannel *pchan_prev = pchan->prev;
+ const Bone *last_visited_bone = *r_last_visited_bone_p;
+ if ((pchan_prev == NULL && last_visited_bone != NULL) ||
+ (pchan_prev != NULL && pchan_prev->bone != last_visited_bone)) {
+ pchan_prev = last_visited_bone != NULL ?
+ BKE_pose_channel_find_name(pose, last_visited_bone->name) :
+ NULL;
+ BLI_remlink(&pose->chanbase, pchan);
+ BLI_insertlinkafter(&pose->chanbase, pchan_prev, pchan);
+ }
+
+ *r_last_visited_bone_p = pchan->bone;
counter++;
for (bone = bone->childbase.first; bone; bone = bone->next) {
- counter = rebuild_pose_bone(pose, bone, pchan, counter);
+ counter = rebuild_pose_bone(pose, bone, pchan, counter, r_last_visited_bone_p);
/* for quick detecting of next bone in chain, only b-bone uses it now */
if (bone->flag & BONE_CONNECTED) {
pchan->child = BKE_pose_channel_find_name(pose, bone->name);
@@ -2520,8 +2545,9 @@ void BKE_pose_rebuild(Main *bmain, Object *ob, bArmature *arm, const bool do_id_
BKE_pose_clear_pointers(pose);
/* first step, check if all channels are there */
+ Bone *prev_bone = NULL;
for (bone = arm->bonebase.first; bone; bone = bone->next) {
- counter = rebuild_pose_bone(pose, bone, NULL, counter);
+ counter = rebuild_pose_bone(pose, bone, NULL, counter, &prev_bone);
}
/* and a check for garbage */