diff options
-rw-r--r-- | release/scripts/startup/bl_ui/properties_data_armature.py | 23 | ||||
-rw-r--r-- | source/blender/editors/armature/armature_intern.h | 2 | ||||
-rw-r--r-- | source/blender/editors/armature/armature_ops.c | 2 | ||||
-rw-r--r-- | source/blender/editors/armature/poseobject.c | 165 |
4 files changed, 190 insertions, 2 deletions
diff --git a/release/scripts/startup/bl_ui/properties_data_armature.py b/release/scripts/startup/bl_ui/properties_data_armature.py index 9477dc866ab..217cd59f0de 100644 --- a/release/scripts/startup/bl_ui/properties_data_armature.py +++ b/release/scripts/startup/bl_ui/properties_data_armature.py @@ -96,6 +96,16 @@ class DATA_PT_display(ArmatureButtonsPanel, bpy.types.Panel): col.prop(arm, "use_deform_delay", text="Delay Refresh") +class DATA_PT_bone_group_specials(bpy.types.Menu): + bl_label = "Bone Group Specials" + COMPAT_ENGINES = {'BLENDER_RENDER', 'BLENDER_GAME'} + + def draw(self, context): + layout = self.layout + + layout.operator("pose.group_sort", icon='SORTALPHA') + + class DATA_PT_bone_groups(ArmatureButtonsPanel, bpy.types.Panel): bl_label = "Bone Groups" @@ -108,16 +118,25 @@ class DATA_PT_bone_groups(ArmatureButtonsPanel, bpy.types.Panel): ob = context.object pose = ob.pose + group = pose.bone_groups.active row = layout.row() - row.template_list(pose, "bone_groups", pose.bone_groups, "active_index", rows=2) + + rows = 2 + if group: + rows = 5 + row.template_list(pose, "bone_groups", pose.bone_groups, "active_index", rows=rows) col = row.column(align=True) col.active = (ob.proxy is None) col.operator("pose.group_add", icon='ZOOMIN', text="") col.operator("pose.group_remove", icon='ZOOMOUT', text="") + col.menu("DATA_PT_bone_group_specials", icon='DOWNARROW_HLT', text="") + if group: + col.separator() + col.operator("pose.group_move", icon='TRIA_UP', text="").direction = 'UP' + col.operator("pose.group_move", icon='TRIA_DOWN', text="").direction = 'DOWN' - group = pose.bone_groups.active if group: col = layout.column() col.active = (ob.proxy is None) diff --git a/source/blender/editors/armature/armature_intern.h b/source/blender/editors/armature/armature_intern.h index 85da7a212c9..f583ba0c903 100644 --- a/source/blender/editors/armature/armature_intern.h +++ b/source/blender/editors/armature/armature_intern.h @@ -110,6 +110,8 @@ void POSE_OT_select_flip_active(struct wmOperatorType *ot); void POSE_OT_group_add(struct wmOperatorType *ot); void POSE_OT_group_remove(struct wmOperatorType *ot); +void POSE_OT_group_move(struct wmOperatorType *ot); +void POSE_OT_group_sort(struct wmOperatorType *ot); void POSE_OT_group_assign(struct wmOperatorType *ot); void POSE_OT_group_unassign(struct wmOperatorType *ot); void POSE_OT_group_select(struct wmOperatorType *ot); diff --git a/source/blender/editors/armature/armature_ops.c b/source/blender/editors/armature/armature_ops.c index 16b748737ca..33748ebd0bb 100644 --- a/source/blender/editors/armature/armature_ops.c +++ b/source/blender/editors/armature/armature_ops.c @@ -126,6 +126,8 @@ void ED_operatortypes_armature(void) WM_operatortype_append(POSE_OT_group_add); WM_operatortype_append(POSE_OT_group_remove); + WM_operatortype_append(POSE_OT_group_move); + WM_operatortype_append(POSE_OT_group_sort); WM_operatortype_append(POSE_OT_group_assign); WM_operatortype_append(POSE_OT_group_unassign); WM_operatortype_append(POSE_OT_group_select); diff --git a/source/blender/editors/armature/poseobject.c b/source/blender/editors/armature/poseobject.c index fa5fecbd9d0..cfd3f54c5b9 100644 --- a/source/blender/editors/armature/poseobject.c +++ b/source/blender/editors/armature/poseobject.c @@ -1433,6 +1433,171 @@ void POSE_OT_group_unassign (wmOperatorType *ot) ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; } +static int group_move_exec(bContext *C, wmOperator *op) +{ + Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data; + bPose *pose= (ob) ? ob->pose : NULL; + bPoseChannel *pchan; + bActionGroup *grp; + int dir= RNA_enum_get(op->ptr, "direction"); + int grpIndexA, grpIndexB; + + if (ELEM(NULL, ob, pose)) + return OPERATOR_CANCELLED; + if (pose->active_group <= 0) + return OPERATOR_CANCELLED; + + /* get group to move */ + grp= BLI_findlink(&pose->agroups, pose->active_group-1); + if (grp == NULL) + return OPERATOR_CANCELLED; + + /* move bone group */ + grpIndexA = pose->active_group; + if (dir == 1) { /* up */ + void *prev = grp->prev; + + if (prev == NULL) + return OPERATOR_FINISHED; + + BLI_remlink(&pose->agroups, grp); + BLI_insertlinkbefore(&pose->agroups, prev, grp); + + grpIndexB = grpIndexA - 1; + pose->active_group--; + } + else { /* down */ + void *next = grp->next; + + if (next == NULL) + return OPERATOR_FINISHED; + + BLI_remlink(&pose->agroups, grp); + BLI_insertlinkafter(&pose->agroups, next, grp); + + grpIndexB = grpIndexA + 1; + pose->active_group++; + } + + /* fix changed bone group indices in bones (swap grpIndexA with grpIndexB) */ + for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { + if (pchan->agrp_index == grpIndexB) + pchan->agrp_index= grpIndexA; + else if (pchan->agrp_index == grpIndexA) + pchan->agrp_index= grpIndexB; + } + + /* notifiers for updates */ + WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob); + + return OPERATOR_FINISHED; +} + +void POSE_OT_group_move(wmOperatorType *ot) +{ + static EnumPropertyItem group_slot_move[] = { + {1, "UP", 0, "Up", ""}, + {-1, "DOWN", 0, "Down", ""}, + {0, NULL, 0, NULL, NULL} + }; + + /* identifiers */ + ot->name= "Move Bone Group"; + ot->idname= "POSE_OT_group_move"; + ot->description= "Change position of active Bone Group in list of Bone Groups"; + + /* api callbacks */ + ot->exec= group_move_exec; + ot->poll= ED_operator_posemode; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + RNA_def_enum(ot->srna, "direction", group_slot_move, 0, "Direction", "Direction to move, UP or DOWN"); +} + +/* bone group sort element */ +typedef struct tSortActionGroup { + bActionGroup *agrp; + int index; +} tSortActionGroup; + +/* compare bone groups by name */ +static int compare_agroup(const void *sgrp_a_ptr, const void *sgrp_b_ptr) +{ + tSortActionGroup *sgrp_a= (tSortActionGroup *)sgrp_a_ptr; + tSortActionGroup *sgrp_b= (tSortActionGroup *)sgrp_b_ptr; + + return strcmp(sgrp_a->agrp->name, sgrp_b->agrp->name); +} + +static int group_sort_exec(bContext *C, wmOperator *op) +{ + Object *ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data; + bPose *pose= (ob) ? ob->pose : NULL; + bPoseChannel *pchan; + tSortActionGroup *agrp_array; + bActionGroup *agrp; + int agrp_count; + int i; + + if (ELEM(NULL, ob, pose)) + return OPERATOR_CANCELLED; + if (pose->active_group <= 0) + return OPERATOR_CANCELLED; + + /* create temporary array with bone groups and indices */ + agrp_count = BLI_countlist(&pose->agroups); + agrp_array = MEM_mallocN(sizeof(tSortActionGroup) * agrp_count, "sort bone groups"); + for (agrp= pose->agroups.first, i= 0; agrp; agrp= agrp->next, i++) { + BLI_assert(i < agrp_count); + agrp_array[i].agrp = agrp; + agrp_array[i].index = i+1; + } + + /* sort bone groups by name */ + qsort(agrp_array, agrp_count, sizeof(tSortActionGroup), compare_agroup); + + /* create sorted bone group list from sorted array */ + pose->agroups.first= pose->agroups.last= NULL; + for (i= 0; i < agrp_count; i++) { + BLI_addtail(&pose->agroups, agrp_array[i].agrp); + } + + /* fix changed bone group indizes in bones */ + for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) { + for (i= 0; i < agrp_count; i++) { + if (pchan->agrp_index == agrp_array[i].index) { + pchan->agrp_index= i+1; + break; + } + } + } + + /* free temp resources */ + MEM_freeN(agrp_array); + + /* notifiers for updates */ + WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob); + + return OPERATOR_FINISHED; +} + +void POSE_OT_group_sort(wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Sort Bone Groups"; + ot->idname= "POSE_OT_group_sort"; + ot->description= "Sort Bone Groups by their names in ascending order"; + + /* api callbacks */ + ot->exec= group_sort_exec; + ot->poll= ED_operator_posemode; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; +} + static void pose_group_select(bContext *C, Object *ob, int select) { bPose *pose= ob->pose; |