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.
This commit is contained in:
parent
92fbcbb4bf
commit
702bc5ba26
Notes:
blender-bot
2023-02-14 08:45:12 +01:00
Referenced by issue #54189, Armature "flip names" is not removing .001 suffix Referenced by issue #54074, Armature flip names Referenced by issue #51543, Bone flip names don't remove suffix Referenced by issue #50393, Flip names working just on one side
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in New Issue