From daae72e17b9f9375c6e33e0c3036784bdf35ed18 Mon Sep 17 00:00:00 2001 From: Campbell Barton Date: Sun, 29 Apr 2012 18:23:33 +0000 Subject: patch [#30834] Quick Hack: Select similar for bones in edit mode from Felix Schlitter (dalai) made some changes to select length measurement. --- source/blender/blenkernel/BKE_deform.h | 1 + source/blender/blenkernel/intern/deform.c | 8 +- source/blender/editors/armature/armature_intern.h | 1 + source/blender/editors/armature/armature_ops.c | 3 + source/blender/editors/armature/editarmature.c | 157 ++++++++++++++++++++++ 5 files changed, 166 insertions(+), 4 deletions(-) diff --git a/source/blender/blenkernel/BKE_deform.h b/source/blender/blenkernel/BKE_deform.h index 17275b6ea7d..d3d66967ebb 100644 --- a/source/blender/blenkernel/BKE_deform.h +++ b/source/blender/blenkernel/BKE_deform.h @@ -71,6 +71,7 @@ void defvert_normalize_lock(struct MDeformVert *dvert, const int def_nr_lock); /* utility function, note that 32 chars is the maximum string length since its only * used with defgroups currently */ +int BKE_deform_is_char_sep(const char c); void flip_side_name(char name[64], const char from_name[64], int strip_number); #endif diff --git a/source/blender/blenkernel/intern/deform.c b/source/blender/blenkernel/intern/deform.c index 3e0c947ff4a..a14456845b9 100644 --- a/source/blender/blenkernel/intern/deform.c +++ b/source/blender/blenkernel/intern/deform.c @@ -437,7 +437,7 @@ void defgroup_unique_name(bDeformGroup *dg, Object *ob) BLI_uniquename_cb(defgroup_unique_check, &data, "Group", '.', dg->name, sizeof(dg->name)); } -BLI_INLINE int is_char_sep(const char c) +int BKE_deform_is_char_sep(const char c) { return ELEM4(c, '.', ' ', '-', '_'); } @@ -466,7 +466,7 @@ void flip_side_name(char name[MAX_VGROUP_NAME], const char from_name[MAX_VGROUP_ /* We first check the case with a .### extension, let's find the last period */ if (isdigit(name[len - 1])) { index = strrchr(name, '.'); // last occurrence - if (index && isdigit(index[1]) ) { // doesnt handle case bone.1abc2 correct..., whatever! + if (index && isdigit(index[1])) { // doesnt handle case bone.1abc2 correct..., whatever! if (strip_number == 0) { BLI_strncpy(number, index, sizeof(number)); } @@ -478,7 +478,7 @@ void flip_side_name(char name[MAX_VGROUP_NAME], const char from_name[MAX_VGROUP_ BLI_strncpy(prefix, name, sizeof(prefix)); /* first case; separator . - _ with extensions r R l L */ - if (is_char_sep(name[len - 2]) ) { + if (BKE_deform_is_char_sep(name[len - 2])) { switch (name[len - 1]) { case 'l': prefix[len - 1] = 0; @@ -499,7 +499,7 @@ void flip_side_name(char name[MAX_VGROUP_NAME], const char from_name[MAX_VGROUP_ } } /* case; beginning with r R l L , with separator after it */ - else if (is_char_sep(name[1]) ) { + else if (BKE_deform_is_char_sep(name[1])) { switch (name[0]) { case 'l': strcpy(replace, "r"); diff --git a/source/blender/editors/armature/armature_intern.h b/source/blender/editors/armature/armature_intern.h index 13239f87e65..72d261ec187 100644 --- a/source/blender/editors/armature/armature_intern.h +++ b/source/blender/editors/armature/armature_intern.h @@ -63,6 +63,7 @@ void ARMATURE_OT_select_all(struct wmOperatorType *ot); void ARMATURE_OT_select_inverse(struct wmOperatorType *ot); void ARMATURE_OT_select_hierarchy(struct wmOperatorType *ot); void ARMATURE_OT_select_linked(struct wmOperatorType *ot); +void ARMATURE_OT_select_similar(struct wmOperatorType *ot); void ARMATURE_OT_delete(struct wmOperatorType *ot); void ARMATURE_OT_duplicate(struct wmOperatorType *ot); diff --git a/source/blender/editors/armature/armature_ops.c b/source/blender/editors/armature/armature_ops.c index 21b97188522..aeecbc1fd28 100644 --- a/source/blender/editors/armature/armature_ops.c +++ b/source/blender/editors/armature/armature_ops.c @@ -69,6 +69,7 @@ void ED_operatortypes_armature(void) WM_operatortype_append(ARMATURE_OT_select_inverse); WM_operatortype_append(ARMATURE_OT_select_hierarchy); WM_operatortype_append(ARMATURE_OT_select_linked); + WM_operatortype_append(ARMATURE_OT_select_similar); WM_operatortype_append(ARMATURE_OT_delete); WM_operatortype_append(ARMATURE_OT_duplicate); @@ -261,6 +262,8 @@ void ED_keymap_armature(wmKeyConfig *keyconf) RNA_enum_set(kmi->ptr, "direction", BONE_SELECT_CHILD); RNA_boolean_set(kmi->ptr, "extend", TRUE); + WM_keymap_add_item(keymap, "ARMATURE_OT_select_similar", GKEY, KM_PRESS, KM_SHIFT, 0); + WM_keymap_add_item(keymap, "ARMATURE_OT_select_linked", LKEY, KM_PRESS, 0, 0); WM_keymap_add_item(keymap, "ARMATURE_OT_delete", XKEY, KM_PRESS, 0, 0); diff --git a/source/blender/editors/armature/editarmature.c b/source/blender/editors/armature/editarmature.c index 4184f15c159..c188a936d5d 100644 --- a/source/blender/editors/armature/editarmature.c +++ b/source/blender/editors/armature/editarmature.c @@ -4027,6 +4027,163 @@ void ARMATURE_OT_select_all(wmOperatorType *ot) WM_operator_properties_select_all(ot); } +enum { + SIMEDBONE_LENGTH = 1, + SIMEDBONE_PREFIX, + SIMEDBONE_SUFFIX, + SIMEDBONE_LAYER +}; + +static EnumPropertyItem prop_similar_types[] = { + {SIMEDBONE_LENGTH, "LENGTH", 0, "Length", ""}, + {SIMEDBONE_PREFIX, "PREFIX", 0, "Prefix", ""}, + {SIMEDBONE_SUFFIX, "SUFFIX", 0, "Suffix", ""}, + {SIMEDBONE_LAYER, "LAYER", 0, "Layer", ""}, + {0, NULL, 0, NULL, NULL} +}; + +/* could be used in more places */ +static void ED_armature_edit_bone_select(EditBone *ebone) +{ + BLI_assert((ebone->flag & BONE_UNSELECTABLE) == 0); + ebone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL); + + if ((ebone->flag & BONE_CONNECTED) && (ebone->parent != NULL)) { + ebone->parent->flag |= BONE_TIPSEL; + } +} + +static void select_similar_length(bArmature *arm, EditBone *actBone, const float thresh) +{ + EditBone *ebone; + + /* thresh is always relative to current length */ + const float len_min = actBone->length / (1.0f + thresh); + const float len_max = actBone->length * (1.0f + thresh); + + for (ebone = arm->edbo->first; ebone; ebone = ebone->next) { + if (EBONE_VISIBLE(arm, ebone) && (ebone->flag & BONE_UNSELECTABLE) == 0) { + if ((ebone->length >= len_min) && + (ebone->length <= len_max)) + { + ED_armature_edit_bone_select(ebone); + } + } + } +} + +static void select_similar_layer(bArmature *arm, EditBone *actBone) +{ + EditBone *ebone; + + for (ebone = arm->edbo->first; ebone; ebone = ebone->next) { + if (EBONE_VISIBLE(arm, ebone) && (ebone->flag & BONE_UNSELECTABLE) == 0) { + if (ebone->layer & actBone->layer) { + ED_armature_edit_bone_select(ebone); + } + } + } +} + +static void find_pre_or_suffix(char *outCompare, const char *name, int mode) +{ + int len = BLI_strnlen(name, MAX_VGROUP_NAME); + + if (len < 3) + return; + + if (mode == SIMEDBONE_SUFFIX) { + if (BKE_deform_is_char_sep(name[len - 2])) { + BLI_strncpy(outCompare, &name[len - 1], sizeof(outCompare)); + } + } + else if (mode == SIMEDBONE_PREFIX) { + if (BKE_deform_is_char_sep(name[1])) { + BLI_strncpy(outCompare, &name[0], sizeof(outCompare)); + } + } +} + +static void select_similar_name(bArmature *arm, EditBone *actBone, int mode) +{ + EditBone *ebone; + + char *name = actBone->name; + char compare[MAX_VGROUP_NAME] = ""; + find_pre_or_suffix(compare, name, mode); + + if (compare[0] == '\0') + return; + + /* Find matches */ + for (ebone = arm->edbo->first; ebone; ebone = ebone->next) { + if (EBONE_VISIBLE(arm, ebone) && (ebone->flag & BONE_UNSELECTABLE) == 0) { + char tCompare[MAX_VGROUP_NAME] = ""; + find_pre_or_suffix(tCompare, ebone->name, mode); + if (!strcmp(tCompare, compare)) { + ED_armature_edit_bone_select(ebone); + } + } + } + +} + +static int armature_select_similar_exec(bContext *C, wmOperator *op) +{ + Object *obedit = CTX_data_edit_object(C); + bArmature *arm = obedit->data; + EditBone *actBone = CTX_data_active_bone(C); + + /* Get props */ + int type = RNA_enum_get(op->ptr, "type"); + float thresh = RNA_float_get(op->ptr, "threshold"); + + /* Check for active bone */ + if (actBone == NULL) { + BKE_report(op->reports, RPT_ERROR, "Operation requires an Active Bone"); + return OPERATOR_CANCELLED; + } + + switch (type) { + case SIMEDBONE_LENGTH: + select_similar_length(arm, actBone, thresh); + break; + case SIMEDBONE_PREFIX: + select_similar_name(arm, actBone, SIMEDBONE_PREFIX); + break; + case SIMEDBONE_SUFFIX: + select_similar_name(arm, actBone, SIMEDBONE_SUFFIX); + break; + case SIMEDBONE_LAYER: + select_similar_layer(arm, actBone); + break; + } + + WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit); + + return OPERATOR_FINISHED; +} + +void ARMATURE_OT_select_similar(wmOperatorType *ot) { + + /* identifiers */ + ot->name = "Select Similar"; + ot->idname = "ARMATURE_OT_select_similar"; + + /* callback functions */ + ot->invoke = WM_menu_invoke; + ot->exec = armature_select_similar_exec; + ot->poll = ED_operator_editarmature; + ot->description = "Select similar bones by property types"; + + /* flags */ + ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO; + + /* properties */ + ot->prop = RNA_def_enum(ot->srna, "type", prop_similar_types, 0, "Type", ""); + RNA_def_float(ot->srna, "threshold", 0.1f, 0.0f, 1.0f, "Threshold", "", 0.0f, 1.0f); +} + /* ********************* select hierarchy operator ************** */ static int armature_select_hierarchy_exec(bContext *C, wmOperator *op) -- cgit v1.2.3