Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/editors/armature/poseobject.c')
-rw-r--r--source/blender/editors/armature/poseobject.c240
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;
}