From 186e50441f66aedd17b440f0d9d8ae88e0f59314 Mon Sep 17 00:00:00 2001 From: cgtinker Date: Thu, 30 Mar 2023 22:36:48 +0200 Subject: [PATCH 1/4] init refactor --- .../blender/editors/armature/armature_add.c | 172 ++++++++++-------- 1 file changed, 101 insertions(+), 71 deletions(-) diff --git a/source/blender/editors/armature/armature_add.c b/source/blender/editors/armature/armature_add.c index 806da5ee286..b7c518e343b 100644 --- a/source/blender/editors/armature/armature_add.c +++ b/source/blender/editors/armature/armature_add.c @@ -327,6 +327,7 @@ void postEditBoneDuplicate(struct ListBase *editbones, Object *ob) if (!ebone_dst) { ebone_dst = ED_armature_ebone_get_mirrored(editbones, ebone_src); } + if (ebone_dst) { BLI_ghash_insert(name_map, ebone_src->name, ebone_dst->name); } @@ -334,22 +335,28 @@ void postEditBoneDuplicate(struct ListBase *editbones, Object *ob) LISTBASE_FOREACH (EditBone *, ebone_src, editbones) { EditBone *ebone_dst = ebone_src->temp.ebone; - if (ebone_dst) { - bPoseChannel *pchan_src = BKE_pose_channel_find_name(ob->pose, ebone_src->name); - if (pchan_src) { - bPoseChannel *pchan_dst = BKE_pose_channel_find_name(ob->pose, ebone_dst->name); - if (pchan_dst) { - if (pchan_src->custom_tx) { - pchan_dst->custom_tx = pchan_duplicate_map(ob->pose, name_map, pchan_src->custom_tx); - } - if (pchan_src->bbone_prev) { - pchan_dst->bbone_prev = pchan_duplicate_map(ob->pose, name_map, pchan_src->bbone_prev); - } - if (pchan_src->bbone_next) { - pchan_dst->bbone_next = pchan_duplicate_map(ob->pose, name_map, pchan_src->bbone_next); - } - } - } + if (!ebone_dst) { + continue; + } + + bPoseChannel *pchan_src = BKE_pose_channel_find_name(ob->pose, ebone_src->name); + if (!pchan_src) { + continue; + } + + bPoseChannel *pchan_dst = BKE_pose_channel_find_name(ob->pose, ebone_dst->name); + if (!pchan_dst) { + continue; + } + + if (pchan_src->custom_tx) { + pchan_dst->custom_tx = pchan_duplicate_map(ob->pose, name_map, pchan_src->custom_tx); + } + if (pchan_src->bbone_prev) { + pchan_dst->bbone_prev = pchan_duplicate_map(ob->pose, name_map, pchan_src->bbone_prev); + } + if (pchan_src->bbone_next) { + pchan_dst->bbone_next = pchan_duplicate_map(ob->pose, name_map, pchan_src->bbone_next); } } @@ -1089,6 +1096,71 @@ static EditBone *get_symmetrized_bone(bArmature *arm, EditBone *bone) return (mirror != NULL) ? mirror : bone; } +static void ED_armature_set_symmetrizable_ebone_selection(bArmature *arm, int axis, int direction) +{ + /* Deselects ebones depending on input axis and direction. + * A symmetrizable selection contains selected ebones of the input direction + * and unique selected bones with an unique flippable name.*/ + EditBone *ebone_iter; + + for (ebone_iter = arm->edbo->first; ebone_iter; ebone_iter = ebone_iter->next) { + if (!(EBONE_VISIBLE(arm, ebone_iter) && (ebone_iter->flag & BONE_SELECTED))) { + /* ignore selected bones which are invisble */ + continue; + } + + char name_flip[MAXBONENAME]; + + if (ebone_iter == NULL) { + continue; + } + + BLI_string_flip_side_name(name_flip, ebone_iter->name, false, sizeof(name_flip)); + + if (STREQ(name_flip, ebone_iter->name)) { + /* if the name matches, we don't have the potential to be mirrored, just skip */ + ebone_iter->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); + continue; + } + + EditBone *ebone = ED_armature_ebone_find_name(arm->edbo, name_flip); + + if (!ebone) { + continue; + } + + if ((ebone->flag & BONE_SELECTED) == 0) { + /* ebone is only once selected per side */ + continue; + } + + /* complicated - choose which direction to copy */ + float axis_delta; + + axis_delta = ebone->head[axis] - ebone_iter->head[axis]; + if (axis_delta == 0.0f) { + axis_delta = ebone->tail[axis] - ebone_iter->tail[axis]; + + if (axis_delta == 0.0f) { + /* Both mirrored bones exist and point to each other and overlap exactly. + * in this case there's no well defined solution, so de-select both and skip. + */ + ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); + ebone_iter->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); + continue; + } + } + + // deselect depending on direction + if (((axis_delta < 0.0f) ? -1 : 1) == direction) { + ebone_iter->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); + } + else { + ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); + } + } +} + /** * near duplicate of #armature_duplicate_selected_exec, * except for parenting part (keep in sync) @@ -1109,69 +1181,26 @@ static int armature_symmetrize_exec(bContext *C, wmOperator *op) Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data( scene, view_layer, CTX_wm_view3d(C), &objects_len); for (uint ob_index = 0; ob_index < objects_len; ob_index++) { - Object *obedit = objects[ob_index]; - bArmature *arm = obedit->data; - EditBone *ebone_iter; /* The beginning of the duplicated mirrored bones in the edbo list */ EditBone *ebone_first_dupe = NULL; + Object *obedit = objects[ob_index]; + bArmature *arm = obedit->data; + ED_armature_edit_sync_selection(arm->edbo); /* XXX why is this needed? */ preEditBoneDuplicate(arm->edbo); /* Select mirrored bones */ + ED_armature_set_symmetrizable_ebone_selection(arm, axis, direction); for (ebone_iter = arm->edbo->first; ebone_iter; ebone_iter = ebone_iter->next) { if (EBONE_VISIBLE(arm, ebone_iter) && (ebone_iter->flag & BONE_SELECTED)) { - char name_flip[MAXBONENAME]; - - BLI_string_flip_side_name(name_flip, ebone_iter->name, false, sizeof(name_flip)); - - if (STREQ(name_flip, ebone_iter->name)) { - /* if the name matches, we don't have the potential to be mirrored, just skip */ - ebone_iter->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); - } - else { - EditBone *ebone = ED_armature_ebone_find_name(arm->edbo, name_flip); - - if (ebone) { - if ((ebone->flag & BONE_SELECTED) == 0) { - /* simple case, we're selected, the other bone isn't! */ - ebone_iter->temp.ebone = ebone; - } - else { - /* complicated - choose which direction to copy */ - float axis_delta; - - axis_delta = ebone->head[axis] - ebone_iter->head[axis]; - if (axis_delta == 0.0f) { - axis_delta = ebone->tail[axis] - ebone_iter->tail[axis]; - } - - if (axis_delta == 0.0f) { - /* Both mirrored bones exist and point to each other and overlap exactly. - * - * in this case there's no well defined solution, so de-select both and skip. - */ - ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); - ebone_iter->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); - } - else { - EditBone *ebone_src, *ebone_dst; - if (((axis_delta < 0.0f) ? -1 : 1) == direction) { - ebone_src = ebone; - ebone_dst = ebone_iter; - } - else { - ebone_src = ebone_iter; - ebone_dst = ebone; - } - - ebone_src->temp.ebone = ebone_dst; - ebone_dst->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); - } - } - } + EditBone *ebone; + /* Set temp pointer to mirrored ebones */ + ebone = ED_armature_ebone_get_mirrored(arm->edbo, ebone_iter); + if (ebone) { + ebone_iter->temp.ebone = ebone; } } } @@ -1194,11 +1223,12 @@ static int armature_symmetrize_exec(bContext *C, wmOperator *op) ebone_iter->temp.ebone->inherit_scale_mode = ebone_iter->inherit_scale_mode; continue; } + char name_flip[MAXBONENAME]; BLI_string_flip_side_name(name_flip, ebone_iter->name, false, sizeof(name_flip)); - /* bones must have a side-suffix */ + /* mirrored bones must have a side-suffix */ if (!STREQ(name_flip, ebone_iter->name)) { EditBone *ebone; @@ -1241,8 +1271,8 @@ static int armature_symmetrize_exec(bContext *C, wmOperator *op) */ if (ebone->head[axis] != 0.0f) { - /* The mirrored bone doesn't start on the mirror axis, so assume that this one should - * not be connected to the old parent */ + /* The mirrored bone doesn't start on the mirror axis, so assume that this one + * should not be connected to the old parent */ ebone->flag &= ~BONE_CONNECTED; } } -- 2.30.2 From 11723861762efe4e53223dc84d945739ae490f0e Mon Sep 17 00:00:00 2001 From: cgtinker Date: Fri, 7 Apr 2023 17:13:55 +0200 Subject: [PATCH 2/4] rm duplicate refactor logic --- .../blender/editors/armature/armature_add.c | 136 ++++++++---------- 1 file changed, 63 insertions(+), 73 deletions(-) diff --git a/source/blender/editors/armature/armature_add.c b/source/blender/editors/armature/armature_add.c index b7c518e343b..4643bdfe1ff 100644 --- a/source/blender/editors/armature/armature_add.c +++ b/source/blender/editors/armature/armature_add.c @@ -1096,71 +1096,6 @@ static EditBone *get_symmetrized_bone(bArmature *arm, EditBone *bone) return (mirror != NULL) ? mirror : bone; } -static void ED_armature_set_symmetrizable_ebone_selection(bArmature *arm, int axis, int direction) -{ - /* Deselects ebones depending on input axis and direction. - * A symmetrizable selection contains selected ebones of the input direction - * and unique selected bones with an unique flippable name.*/ - EditBone *ebone_iter; - - for (ebone_iter = arm->edbo->first; ebone_iter; ebone_iter = ebone_iter->next) { - if (!(EBONE_VISIBLE(arm, ebone_iter) && (ebone_iter->flag & BONE_SELECTED))) { - /* ignore selected bones which are invisble */ - continue; - } - - char name_flip[MAXBONENAME]; - - if (ebone_iter == NULL) { - continue; - } - - BLI_string_flip_side_name(name_flip, ebone_iter->name, false, sizeof(name_flip)); - - if (STREQ(name_flip, ebone_iter->name)) { - /* if the name matches, we don't have the potential to be mirrored, just skip */ - ebone_iter->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); - continue; - } - - EditBone *ebone = ED_armature_ebone_find_name(arm->edbo, name_flip); - - if (!ebone) { - continue; - } - - if ((ebone->flag & BONE_SELECTED) == 0) { - /* ebone is only once selected per side */ - continue; - } - - /* complicated - choose which direction to copy */ - float axis_delta; - - axis_delta = ebone->head[axis] - ebone_iter->head[axis]; - if (axis_delta == 0.0f) { - axis_delta = ebone->tail[axis] - ebone_iter->tail[axis]; - - if (axis_delta == 0.0f) { - /* Both mirrored bones exist and point to each other and overlap exactly. - * in this case there's no well defined solution, so de-select both and skip. - */ - ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); - ebone_iter->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); - continue; - } - } - - // deselect depending on direction - if (((axis_delta < 0.0f) ? -1 : 1) == direction) { - ebone_iter->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); - } - else { - ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); - } - } -} - /** * near duplicate of #armature_duplicate_selected_exec, * except for parenting part (keep in sync) @@ -1192,16 +1127,71 @@ static int armature_symmetrize_exec(bContext *C, wmOperator *op) preEditBoneDuplicate(arm->edbo); - /* Select mirrored bones */ - ED_armature_set_symmetrizable_ebone_selection(arm, axis, direction); + /* Deselect ebones depending on input axis and direction. + * A symmetrizable selection contains selected ebones of the input direction + * and unique selected bones with an unique flippable name. + * + * Storing temp ptrs to mirrored unselected ebones. */ for (ebone_iter = arm->edbo->first; ebone_iter; ebone_iter = ebone_iter->next) { - if (EBONE_VISIBLE(arm, ebone_iter) && (ebone_iter->flag & BONE_SELECTED)) { - EditBone *ebone; - /* Set temp pointer to mirrored ebones */ - ebone = ED_armature_ebone_get_mirrored(arm->edbo, ebone_iter); - if (ebone) { - ebone_iter->temp.ebone = ebone; + if (!(EBONE_VISIBLE(arm, ebone_iter) && (ebone_iter->flag & BONE_SELECTED))) { + /* Skipping invisible selected bones. */ + continue; + } + + char name_flip[MAXBONENAME]; + if (ebone_iter == NULL) { + continue; + } + + BLI_string_flip_side_name(name_flip, ebone_iter->name, false, sizeof(name_flip)); + + if (STREQ(name_flip, ebone_iter->name)) { + /* Skipping ebones without flippable as they don't have the potential to be mirrored. */ + ebone_iter->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); + continue; + } + + EditBone *ebone = ED_armature_ebone_find_name(arm->edbo, name_flip); + + if (!ebone) { + /* The ebone_iter is unique and mirrorable. */ + continue; + } + + if (ebone->flag & BONE_SELECTED) { + /* The mirrored ebone and the ebone_iter are selected. + * Deselect based on the input direction and axis. */ + float axis_delta; + + axis_delta = ebone->head[axis] - ebone_iter->head[axis]; + if (axis_delta == 0.0f) { + /* The ebone heads are overlapping. */ + axis_delta = ebone->tail[axis] - ebone_iter->tail[axis]; + + if (axis_delta == 0.0f) { + /* Both mirrored bones point to each other and overlap exactly. + * In this case there's no well defined solution, so de-select both and skip. */ + ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); + ebone_iter->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); + continue; + } } + + /* Deselect depending on direction. */ + if (((axis_delta < 0.0f) ? -1 : 1) == direction) { + /* Don't store temp ptr if the iter_bone gets deselected. + * In this case, the ebone.temp should point to the ebone_iter. */ + ebone_iter->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); + continue; + } + + ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); + } + + /* Set temp pointer to mirrored ebones */ + ebone = ED_armature_ebone_get_mirrored(arm->edbo, ebone_iter); + if (ebone) { + ebone_iter->temp.ebone = ebone; } } -- 2.30.2 From b551a6f770939952354124cfa68126c2bf6c6f71 Mon Sep 17 00:00:00 2001 From: cgtinker Date: Fri, 7 Apr 2023 17:24:02 +0200 Subject: [PATCH 3/4] rm duplicate ebone search --- source/blender/editors/armature/armature_add.c | 1 - 1 file changed, 1 deletion(-) diff --git a/source/blender/editors/armature/armature_add.c b/source/blender/editors/armature/armature_add.c index 4643bdfe1ff..34da2bbd1b2 100644 --- a/source/blender/editors/armature/armature_add.c +++ b/source/blender/editors/armature/armature_add.c @@ -1189,7 +1189,6 @@ static int armature_symmetrize_exec(bContext *C, wmOperator *op) } /* Set temp pointer to mirrored ebones */ - ebone = ED_armature_ebone_get_mirrored(arm->edbo, ebone_iter); if (ebone) { ebone_iter->temp.ebone = ebone; } -- 2.30.2 From 4cd6bf07d069d039f5d6b351ce1142fa74879dfd Mon Sep 17 00:00:00 2001 From: cgtinker Date: Wed, 19 Apr 2023 17:25:06 +0200 Subject: [PATCH 4/4] removed unnecessary if --- source/blender/editors/armature/armature_add.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/source/blender/editors/armature/armature_add.c b/source/blender/editors/armature/armature_add.c index 34da2bbd1b2..202c4c745c4 100644 --- a/source/blender/editors/armature/armature_add.c +++ b/source/blender/editors/armature/armature_add.c @@ -1189,9 +1189,7 @@ static int armature_symmetrize_exec(bContext *C, wmOperator *op) } /* Set temp pointer to mirrored ebones */ - if (ebone) { - ebone_iter->temp.ebone = ebone; - } + ebone_iter->temp.ebone = ebone; } /* Find the selected bones and duplicate them as needed, with mirrored name. */ -- 2.30.2