Patch [#23682] Add sort+move to bone group list in panel

Thanks  Torsten Rupp (rupp)   for the patch!

This patch adds the abilities to sort the bone group list in the
properties panel and to move bone groups up/down in the list (similar
like for vertex groups)
This commit is contained in:
Joshua Leung 2011-07-07 04:31:53 +00:00
parent 0eacdc94ba
commit cff7c61ddb
4 changed files with 190 additions and 2 deletions

@ -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)

@ -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);

@ -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);

@ -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;