[Bf-blender-cvs] [702bc5ba26] master: Fix T50393: Flip names working just on one side when both are selected.

Bastien Montagne noreply at git.blender.org
Mon Jan 16 20:49:25 CET 2017


Commit: 702bc5ba26d5ff2a4da9e92cabb2fa34ed3f2312
Author: Bastien Montagne
Date:   Mon Jan 16 14:03:31 2017 +0100
Branches: master
https://developer.blender.org/rB702bc5ba26d5ff2a4da9e92cabb2fa34ed3f2312

Fix T50393: Flip names working just on one side when both are selected.

Just store bones that could not get renamed to desired flipped name on the
first try into a temp list, and try to rename them a second time.

This is rather simple solution, will induce 'over numbering' in case you
flip a bone to another unselected bone's name (since number will be
incremented in both rename attempts), but think this is acceptable minor
glitch, for a corner case situation that does not have any good
resolution anyway.

Also, set `strip_numbers` option of `BKE_deform_flip_side_name` to
false, otherwise chains of bones with same names would get their numbers
completely messed up after name flipping.

Based on work by @dfelinto in D2456 (https://developer.blender.org/D2456), thanks.

===================================================================

M	source/blender/editors/armature/armature_naming.c
M	source/blender/editors/armature/pose_edit.c
M	source/blender/editors/include/ED_armature.h

===================================================================

diff --git a/source/blender/editors/armature/armature_naming.c b/source/blender/editors/armature/armature_naming.c
index 56dbdb3a63..4cffd99ce1 100644
--- a/source/blender/editors/armature/armature_naming.c
+++ b/source/blender/editors/armature/armature_naming.c
@@ -37,6 +37,7 @@
 
 #include "BLI_blenlib.h"
 #include "BLI_ghash.h"
+#include "BLI_utildefines.h"
 
 #include "BLT_translation.h"
 
@@ -297,6 +298,55 @@ void ED_armature_bone_rename(bArmature *arm, const char *oldnamep, const char *n
 	}
 }
 
+typedef struct BoneFlipNameData {
+	struct BoneFlipNameData *next, *prev;
+	char *name;
+	char name_flip[MAXBONENAME];
+} BoneFlipNameData;
+
+/**
+ * Renames (by flipping) all selected bones at once.
+ *
+ * This way if we are flipping related bones (e.g., Bone.L, Bone.R) at the same time
+ * all the bones are safely renamed, without conflicting with each other.
+ *
+ * \param arm Armature the bones belong to
+ * \param bones ListBase of BoneConflict elems, populated via ED_armature_bones_flip_names_add
+ */
+void ED_armature_bones_flip_names(bArmature *arm, ListBase *bones_names)
+{
+	ListBase bones_names_conflicts = {NULL};
+	BoneFlipNameData *bfn;
+
+	/* First pass: generate flip names, and blindly rename.
+	 * If rename did not yield expected result, store both bone's name and expected flipped one into temp list
+	 * for second pass. */
+	for (LinkData *link = bones_names->first; link; link = link->next) {
+		char name_flip[MAXBONENAME];
+		char *name = link->data;
+
+		/* Do not strip numbers, otherwise we'll end up with completely mismatched names in cases like
+		 * Bone.R, Bone.R.001, Bone.R.002, etc. */
+		BKE_deform_flip_side_name(name_flip, name, false);
+
+		ED_armature_bone_rename(arm, name, name_flip);
+
+		if (!STREQ(name, name_flip)) {
+			bfn = alloca(sizeof(BoneFlipNameData));
+			bfn->name = name;
+			BLI_strncpy(bfn->name_flip, name_flip, sizeof(bfn->name_flip));
+			BLI_addtail(&bones_names_conflicts, bfn);
+		}
+	}
+
+	/* Second pass to handle the bones that have naming conflicts with other bones.
+	 * Note that if the other bone was not selected, its name was not flipped, so conflict remains and that second
+	 * rename simply generates a new numbered alternative name. */
+	for (bfn = bones_names_conflicts.first; bfn; bfn = bfn->next) {
+		ED_armature_bone_rename(arm, bfn->name, bfn->name_flip);
+	}
+}
+
 /* ************************************************** */
 /* Bone Renaming - EditMode */
 
@@ -304,20 +354,24 @@ static int armature_flip_names_exec(bContext *C, wmOperator *UNUSED(op))
 {
 	Object *ob = CTX_data_edit_object(C);
 	bArmature *arm;
-	
+
 	/* paranoia checks */
-	if (ELEM(NULL, ob, ob->pose)) 
+	if (ELEM(NULL, ob, ob->pose))
 		return OPERATOR_CANCELLED;
+
 	arm = ob->data;
-	
-	/* loop through selected bones, auto-naming them */
+
+	ListBase bones_names= {NULL};
+
 	CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones)
 	{
-		char name_flip[MAXBONENAME];
-		BKE_deform_flip_side_name(name_flip, ebone->name, true);
-		ED_armature_bone_rename(arm, ebone->name, name_flip);
+		BLI_addtail(&bones_names, BLI_genericNodeN(ebone->name));
 	}
 	CTX_DATA_END;
+
+	ED_armature_bones_flip_names(arm, &bones_names);
+
+	BLI_freelistN(&bones_names);
 	
 	/* since we renamed stuff... */
 	DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
diff --git a/source/blender/editors/armature/pose_edit.c b/source/blender/editors/armature/pose_edit.c
index 322476dcca..86b7271bff 100644
--- a/source/blender/editors/armature/pose_edit.c
+++ b/source/blender/editors/armature/pose_edit.c
@@ -593,20 +593,24 @@ static int pose_flip_names_exec(bContext *C, wmOperator *UNUSED(op))
 {
 	Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
 	bArmature *arm;
-	
+
 	/* paranoia checks */
 	if (ELEM(NULL, ob, ob->pose)) 
 		return OPERATOR_CANCELLED;
+
 	arm = ob->data;
-	
-	/* loop through selected bones, auto-naming them */
+
+	ListBase bones_names = {NULL};
+
 	CTX_DATA_BEGIN (C, bPoseChannel *, pchan, selected_pose_bones)
 	{
-		char name_flip[MAXBONENAME];
-		BKE_deform_flip_side_name(name_flip, pchan->name, true);
-		ED_armature_bone_rename(arm, pchan->name, name_flip);
+		BLI_addtail(&bones_names, BLI_genericNodeN(pchan->name));
 	}
 	CTX_DATA_END;
+
+	ED_armature_bones_flip_names(arm, &bones_names);
+
+	BLI_freelistN(&bones_names);
 	
 	/* since we renamed stuff... */
 	DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
diff --git a/source/blender/editors/include/ED_armature.h b/source/blender/editors/include/ED_armature.h
index 904132b887..7ad61671b1 100644
--- a/source/blender/editors/include/ED_armature.h
+++ b/source/blender/editors/include/ED_armature.h
@@ -171,6 +171,7 @@ void create_vgroups_from_armature(struct ReportList *reports, struct Scene *scen
 /* if bone is already in list, pass it as param to ignore it */
 void unique_editbone_name(struct ListBase *ebones, char *name, EditBone *bone);
 void ED_armature_bone_rename(struct bArmature *arm, const char *oldnamep, const char *newnamep);
+void ED_armature_bones_flip_names(struct bArmature *arm, struct ListBase *bones_names);
 
 void undo_push_armature(struct bContext *C, const char *name);




More information about the Bf-blender-cvs mailing list