diff options
Diffstat (limited to 'source/blender/editors/armature/poseobject.c')
-rw-r--r-- | source/blender/editors/armature/poseobject.c | 240 |
1 files changed, 226 insertions, 14 deletions
diff --git a/source/blender/editors/armature/poseobject.c b/source/blender/editors/armature/poseobject.c index 8176aa5893b..20165a67879 100644 --- a/source/blender/editors/armature/poseobject.c +++ b/source/blender/editors/armature/poseobject.c @@ -64,6 +64,7 @@ #include "RNA_access.h" #include "RNA_define.h" +#include "RNA_enum_types.h" #include "WM_api.h" #include "WM_types.h" @@ -1002,6 +1003,14 @@ static int pose_paste_exec (bContext *C, wmOperator *op) return OPERATOR_CANCELLED; } + /* if selOnly option is enabled, if user hasn't selected any bones, + * just go back to default behaviour to be more in line with other pose tools + */ + if (selOnly) { + if (CTX_DATA_COUNT(C, selected_pose_bones) == 0) + selOnly = 0; + } + /* Safely merge all of the channels in the buffer pose into any existing pose */ for (chan= g_posebuf->chanbase.first; chan; chan=chan->next) { if (chan->flag & POSE_KEY) { @@ -1098,21 +1107,19 @@ static int pose_paste_exec (bContext *C, wmOperator *op) } } - /* ID properties - * - only free the existing properties if the channel we're copying from has them - * NOTE: this means that if the pose depends on some pchan property, the pose may not be ok, - * but this is better than loosing all the setting you've painstakingly added... - */ + /* ID properties */ if (chan->prop) { - /* free the old properties since we want to replace them now */ if (pchan->prop) { - IDP_FreeProperty(pchan->prop); - MEM_freeN(pchan->prop); - pchan->prop= NULL; + /* if we have existing properties on a bone, just copy over the values of + * matching properties (i.e. ones which will have some impact) on to the + * target instead of just blinding replacing all [ + */ + IDP_SyncGroupValues(pchan->prop, chan->prop); + } + else { + /* no existing properties, so assume that we want copies too? */ + pchan->prop= IDP_CopyProperty(chan->prop); } - - /* now copy over the new copy of the properties */ - pchan->prop= IDP_CopyProperty(chan->prop); } /* keyframing tagging */ @@ -1169,7 +1176,7 @@ void POSE_OT_paste (wmOperatorType *ot) /* properties */ RNA_def_boolean(ot->srna, "flipped", 0, "Flipped on X-Axis", "Paste the stored pose flipped on to current pose"); - RNA_def_boolean(ot->srna, "selected_mask", 0, "On Selected Only", "Only paste the stored pose on to selected bones in the current pose"); + RNA_def_boolean(ot->srna, "selected_mask", 1, "On Selected Only", "Only paste the stored pose on to selected bones in the current pose"); } /* ********************************************** */ @@ -1425,6 +1432,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; @@ -1625,6 +1797,46 @@ void POSE_OT_autoside_names (wmOperatorType *ot) /* ********************************************** */ +static int pose_bone_rotmode_exec (bContext *C, wmOperator *op) +{ + Object *ob = CTX_data_active_object(C); + int mode = RNA_enum_get(op->ptr, "type"); + + /* set rotation mode of selected bones */ + CTX_DATA_BEGIN(C, bPoseChannel *, pchan, selected_pose_bones) + { + pchan->rotmode = mode; + } + CTX_DATA_END; + + /* notifiers and updates */ + DAG_id_tag_update((ID *)ob, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, ob); + + return OPERATOR_FINISHED; +} + +void POSE_OT_rotation_mode_set (wmOperatorType *ot) +{ + /* identifiers */ + ot->name= "Set Rotation Mode"; + ot->idname= "POSE_OT_rotation_mode_set"; + ot->description= "Set the rotation representation used by selected bones"; + + /* callbacks */ + ot->invoke= WM_menu_invoke; + ot->exec= pose_bone_rotmode_exec; + ot->poll= ED_operator_posemode; + + /* flags */ + ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; + + /* properties */ + ot->prop= RNA_def_enum(ot->srna, "type", posebone_rotmode_items, 0, "Rotation Mode", ""); +} + +/* ********************************************** */ + /* Show all armature layers */ static int pose_armature_layers_showall_poll (bContext *C) { @@ -1711,7 +1923,7 @@ static int pose_armature_layers_exec (bContext *C, wmOperator *op) PointerRNA ptr; int layers[32]; /* hardcoded for now - we can only have 32 armature layers, so this should be fine... */ - if(ob==NULL || ob->data==NULL) { + if (ELEM(NULL, ob, ob->data)) { return OPERATOR_CANCELLED; } |