Index: blenkernel/BKE_deform.h =================================================================== --- blenkernel/BKE_deform.h (revision 45421) +++ blenkernel/BKE_deform.h (working copy) @@ -71,6 +71,7 @@ /* utility function, note that 32 chars is the maximum string length since its only * used with defgroups currently */ +int is_char_sep(const char c); void flip_side_name(char name[64], const char from_name[64], int strip_number); #endif Index: blenkernel/intern/deform.c =================================================================== --- blenkernel/intern/deform.c (revision 45421) +++ blenkernel/intern/deform.c (working copy) @@ -437,7 +437,7 @@ BLI_uniquename_cb(defgroup_unique_check, &data, "Group", '.', dg->name, sizeof(dg->name)); } -BLI_INLINE int is_char_sep(const char c) +int is_char_sep(const char c) { return ELEM4(c, '.', ' ', '-', '_'); } Index: editors/armature/armature_intern.h =================================================================== --- editors/armature/armature_intern.h (revision 45421) +++ editors/armature/armature_intern.h (working copy) @@ -63,6 +63,7 @@ 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); Index: editors/armature/armature_ops.c =================================================================== --- editors/armature/armature_ops.c (revision 45421) +++ editors/armature/armature_ops.c (working copy) @@ -68,7 +68,8 @@ WM_operatortype_append(ARMATURE_OT_select_all); 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_linked); + WM_operatortype_append(ARMATURE_OT_select_similar); WM_operatortype_append(ARMATURE_OT_delete); WM_operatortype_append(ARMATURE_OT_duplicate); @@ -261,6 +262,8 @@ RNA_enum_set(kmi->ptr, "direction", BONE_SELECT_CHILD); RNA_boolean_set(kmi->ptr, "extend", TRUE); + kmi = 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); Index: editors/armature/editarmature.c =================================================================== --- editors/armature/editarmature.c (revision 45421) +++ editors/armature/editarmature.c (working copy) @@ -4031,6 +4031,145 @@ 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} +}; + +static void select_similar_length(bArmature *arm, EditBone *actBone, float thresh) +{ + EditBone *eBone; + + for (eBone = arm->edbo->first; eBone; eBone = eBone->next) + { + if (eBone->length > (actBone->length - thresh) && eBone->length < (actBone->length + thresh)) + eBone->flag |= SELECT; + } +} + +static void select_similar_layer(bArmature *arm, EditBone *actBone) +{ + EditBone *eBone; + + for (eBone = arm->edbo->first; eBone; eBone = eBone->next) + { + if (eBone->layer & actBone->layer) + eBone->flag |= SELECT; + } +} + +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 (is_char_sep(name[len - 2]) ) { + BLI_strncpy(outCompare, &name[len - 1], sizeof(outCompare)); + } + } + else if (mode == SIMEDBONE_PREFIX) + { + if (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) + { + char tCompare[MAX_VGROUP_NAME] = ""; + find_pre_or_suffix(tCompare, eBone->name, mode); + if (!strcmp(tCompare, compare)) + eBone->flag |= SELECT; + } + +} + +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)