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:
authorJoshua Leung <aligorith@gmail.com>2010-01-25 13:16:36 +0300
committerJoshua Leung <aligorith@gmail.com>2010-01-25 13:16:36 +0300
commit5844560ec2384f2e1208fdd6c2298df048c18461 (patch)
tree3cbed127da797922ab6dbe8d5da45dfd6c2afb1d /source/blender/editors/armature
parent41499247dbe947fdb18fe8def48f1c6b2a11bfd6 (diff)
Restored missing PoseMode Operators:
* Select Grouped Selects bones in the same layer or same group as the selected ones. Optimised the code for the select same groups too. * Flip Quats Flips quaternion values so that the rotation progresses over a different path while maintaining the same endpoint orientations.
Diffstat (limited to 'source/blender/editors/armature')
-rw-r--r--source/blender/editors/armature/armature_intern.h3
-rw-r--r--source/blender/editors/armature/armature_ops.c6
-rw-r--r--source/blender/editors/armature/poseobject.c334
3 files changed, 235 insertions, 108 deletions
diff --git a/source/blender/editors/armature/armature_intern.h b/source/blender/editors/armature/armature_intern.h
index c65d4637dcf..5a1f8f35d62 100644
--- a/source/blender/editors/armature/armature_intern.h
+++ b/source/blender/editors/armature/armature_intern.h
@@ -86,6 +86,7 @@ void POSE_OT_select_parent(struct wmOperatorType *ot);
void POSE_OT_select_hierarchy(struct wmOperatorType *ot);
void POSE_OT_select_linked(struct wmOperatorType *ot);
void POSE_OT_select_constraint_target(struct wmOperatorType *ot);
+void POSE_OT_select_grouped(struct wmOperatorType *ot);
void POSE_OT_group_add(struct wmOperatorType *ot);
void POSE_OT_group_remove(struct wmOperatorType *ot);
@@ -99,6 +100,8 @@ void POSE_OT_paths_clear(struct wmOperatorType *ot);
void POSE_OT_autoside_names(struct wmOperatorType *ot);
void POSE_OT_flip_names(struct wmOperatorType *ot);
+void POSE_OT_quaternions_flip(struct wmOperatorType *ot);
+
void POSE_OT_flags_set(struct wmOperatorType *ot);
void POSE_OT_armature_layers(struct wmOperatorType *ot);
diff --git a/source/blender/editors/armature/armature_ops.c b/source/blender/editors/armature/armature_ops.c
index a3c35413680..5f90f6eb745 100644
--- a/source/blender/editors/armature/armature_ops.c
+++ b/source/blender/editors/armature/armature_ops.c
@@ -127,6 +127,7 @@ void ED_operatortypes_armature(void)
WM_operatortype_append(POSE_OT_select_hierarchy);
WM_operatortype_append(POSE_OT_select_linked);
WM_operatortype_append(POSE_OT_select_constraint_target);
+ WM_operatortype_append(POSE_OT_select_grouped);
WM_operatortype_append(POSE_OT_group_add);
WM_operatortype_append(POSE_OT_group_remove);
@@ -139,6 +140,8 @@ void ED_operatortypes_armature(void)
WM_operatortype_append(POSE_OT_autoside_names);
WM_operatortype_append(POSE_OT_flip_names);
+ WM_operatortype_append(POSE_OT_quaternions_flip);
+
WM_operatortype_append(POSE_OT_flags_set);
WM_operatortype_append(POSE_OT_armature_layers);
@@ -290,6 +293,8 @@ void ED_keymap_armature(wmKeyConfig *keyconf)
WM_keymap_add_item(keymap, "POSE_OT_loc_clear", GKEY, KM_PRESS, KM_ALT, 0);
WM_keymap_add_item(keymap, "POSE_OT_scale_clear", SKEY, KM_PRESS, KM_ALT, 0);
+ WM_keymap_add_item(keymap, "POSE_OT_quaternions_flip", FKEY, KM_PRESS, KM_ALT, 0);
+
WM_keymap_add_item(keymap, "POSE_OT_copy", CKEY, KM_PRESS, KM_CTRL, 0);
WM_keymap_add_item(keymap, "POSE_OT_paste", VKEY, KM_PRESS, KM_CTRL, 0);
kmi= WM_keymap_add_item(keymap, "POSE_OT_paste", VKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0);
@@ -313,6 +318,7 @@ void ED_keymap_armature(wmKeyConfig *keyconf)
RNA_boolean_set(kmi->ptr, "extend", 1);
WM_keymap_add_item(keymap, "POSE_OT_select_linked", LKEY, KM_PRESS, 0, 0);
+ WM_keymap_add_item(keymap, "POSE_OT_select_grouped", GKEY, KM_PRESS, KM_SHIFT, 0);
WM_keymap_add_item(keymap, "POSE_OT_constraint_add_with_targets", CKEY, KM_PRESS, KM_CTRL|KM_SHIFT, 0);
WM_keymap_add_item(keymap, "POSE_OT_constraints_clear", CKEY, KM_PRESS, KM_CTRL|KM_ALT, 0);
diff --git a/source/blender/editors/armature/poseobject.c b/source/blender/editors/armature/poseobject.c
index 03e25bb67b8..7799c6e6e89 100644
--- a/source/blender/editors/armature/poseobject.c
+++ b/source/blender/editors/armature/poseobject.c
@@ -93,8 +93,6 @@
static int pupmenu() {return 0;}
static void error() {};
static void BIF_undo_push() {}
-static void countall() {}
-static void autokeyframe_pose_cb_func() {}
/* ************* XXX *************** */
/* This function is used to indicate that a bone is selected and needs keyframes inserted */
@@ -488,7 +486,7 @@ static int pose_select_hierarchy_exec(bContext *C, wmOperator *op)
}
}
- if(!found)
+ if (found == 0)
return OPERATOR_CANCELLED;
WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, ob);
@@ -516,12 +514,171 @@ void POSE_OT_select_hierarchy(wmOperatorType *ot)
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
/* props */
- RNA_def_enum(ot->srna, "direction", direction_items,
- BONE_SELECT_PARENT, "Direction", "");
+ ot->prop= RNA_def_enum(ot->srna, "direction", direction_items, BONE_SELECT_PARENT, "Direction", "");
RNA_def_boolean(ot->srna, "extend", 0, "Add to Selection", "");
}
+/* ******************* select grouped operator ************* */
+
+static short pose_select_same_group (Object *ob, short extend)
+{
+ bPose *pose= (ob)? ob->pose : NULL;
+ bArmature *arm= (ob)? ob->data : NULL;
+ bPoseChannel *pchan;
+ char *group_flags;
+ int numGroups = 0;
+ short changed=0, tagged=0;
+
+ /* sanity checks */
+ if (ELEM3(NULL, ob, pose, arm))
+ return 0;
+
+ /* count the number of groups */
+ numGroups= BLI_countlist(&pose->agroups);
+ if (numGroups == 0)
+ return 0;
+
+ /* alloc a small array to keep track of the groups to use
+ * - each cell stores on/off state for whether group should be used
+ * - size is numGroups + 1, since index=0 is used for no-group
+ */
+ group_flags= MEM_callocN(numGroups+1, "pose_select_same_group");
+
+ for (pchan= pose->chanbase.first; pchan; pchan= pchan->next) {
+ if (arm->layer & pchan->bone->layer) {
+ /* keep track of group as group to use later? */
+ if ((pchan->bone->flag & BONE_SELECTED) || (pchan->bone == arm->act_bone)) {
+ group_flags[pchan->agrp_index] = 1;
+ tagged= 1;
+ }
+
+ /* deselect all bones before selecting new ones? */
+ if ((extend == 0) && (pchan->bone->flag & BONE_UNSELECTABLE)==0)
+ pchan->bone->flag &= ~BONE_SELECTED;
+ }
+ }
+
+ /* small optimisation: only loop through bones a second time if there are any groups tagged */
+ if (tagged) {
+ /* only if group matches (and is not selected or current bone) */
+ for (pchan= pose->chanbase.first; pchan; pchan= pchan->next) {
+ if ((arm->layer & pchan->bone->layer) && (pchan->bone->flag & BONE_UNSELECTABLE)==0) {
+ /* check if the group used by this bone is counted */
+ if (group_flags[pchan->agrp_index]) {
+ pchan->bone->flag |= BONE_SELECTED;
+ changed= 1;
+ }
+ }
+ }
+ }
+
+ /* free temp info */
+ MEM_freeN(group_flags);
+
+ return changed;
+}
+
+static short pose_select_same_layer (Object *ob, short extend)
+{
+ bPose *pose= (ob)? ob->pose : NULL;
+ bArmature *arm= (ob)? ob->data : NULL;
+ bPoseChannel *pchan;
+ short changed= 0;
+ int layers= 0;
+
+ if (ELEM3(NULL, ob, pose, arm))
+ return 0;
+
+ /* figure out what bones are selected */
+ for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+ if (arm->layer & pchan->bone->layer) {
+ /* keep track of layers to use later? */
+ if ((pchan->bone->flag & BONE_SELECTED) || (pchan->bone == arm->act_bone))
+ layers |= pchan->bone->layer;
+
+ /* deselect all bones before selecting new ones? */
+ if ((extend == 0) && (pchan->bone->flag & BONE_UNSELECTABLE)==0)
+ pchan->bone->flag &= ~BONE_SELECTED;
+ }
+ }
+ if (layers == 0)
+ return 0;
+
+ /* select bones that are on same layers as layers flag */
+ for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
+ if (arm->layer & pchan->bone->layer) {
+ /* if bone is on a suitable layer, and the bone can have its selection changed, select it */
+ if ((layers & pchan->bone->layer) && (pchan->bone->flag & BONE_UNSELECTABLE)==0) {
+ pchan->bone->flag |= BONE_SELECTED;
+ changed= 1;
+ }
+ }
+ }
+
+ return changed;
+}
+
+
+static int pose_select_grouped_exec (bContext *C, wmOperator *op)
+{
+ Object *ob= CTX_data_active_object(C);
+ short extend= RNA_boolean_get(op->ptr, "extend");
+ short changed = 0;
+
+ /* sanity check */
+ if (ELEM(NULL, ob, ob->pose))
+ return OPERATOR_CANCELLED;
+
+ /* selection types
+ * NOTE: for the order of these, see the enum in POSE_OT_select_grouped()
+ */
+ switch (RNA_enum_get(op->ptr, "type")) {
+ case 1: /* group */
+ changed= pose_select_same_group(ob, extend);
+ break;
+ default: /* layer */
+ changed= pose_select_same_layer(ob, extend);
+ break;
+ }
+
+ /* notifiers for updates */
+ WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob);
+
+ /* report done status */
+ if (changed)
+ return OPERATOR_FINISHED;
+ else
+ return OPERATOR_CANCELLED;
+}
+
+void POSE_OT_select_grouped (wmOperatorType *ot)
+{
+ static EnumPropertyItem prop_select_grouped_types[] = {
+ {0, "LAYER", 0, "Layer", "Shared layers"},
+ {1, "GROUP", 0, "Group", "Shared group"},
+ {0, NULL, 0, NULL, NULL}
+ };
+
+ /* identifiers */
+ ot->name= "Select Grouped";
+ ot->description = "Select all visible bones grouped by various properties.";
+ ot->idname= "POSE_OT_select_grouped";
+
+ /* api callbacks */
+ ot->invoke= WM_menu_invoke;
+ ot->exec= pose_select_grouped_exec;
+ ot->poll= ED_operator_posemode;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+
+ /* properties */
+ RNA_def_boolean(ot->srna, "extend", FALSE, "Extend", "Extend selection instead of deselecting everything first.");
+ ot->prop= RNA_def_enum(ot->srna, "type", prop_select_grouped_types, 0, "Type", "");
+}
+
+/* ********************************************** */
void pose_copy_menu(Scene *scene)
{
@@ -1205,14 +1362,14 @@ static int pose_group_unassign_exec (bContext *C, wmOperator *op)
pose= ob->pose;
arm= ob->data;
- /* add selected bones to ungroup then */
+ /* find selected bones to remove from all bone groups */
// NOTE: unfortunately, we cannot use the context-iterators here, since they might not be defined...
// CTX_DATA_BEGIN(C, bPoseChannel*, pchan, selected_pose_bones)
for (pchan= pose->chanbase.first; pchan; pchan= pchan->next) {
/* ensure that PoseChannel is on visible layer and is not hidden in PoseMode */
// NOTE: sync this view3d_context() in space_view3d.c
if ((pchan->bone) && (arm->layer & pchan->bone->layer) && !(pchan->bone->flag & BONE_HIDDEN_P)) {
- if (pchan->bone->flag & BONE_SELECTED || pchan->bone == arm->act_bone) {
+ if ((pchan->bone->flag & BONE_SELECTED) || (pchan->bone == arm->act_bone)) {
if (pchan->agrp_index) {
pchan->agrp_index= 0;
done= 1;
@@ -1246,95 +1403,6 @@ void POSE_OT_group_unassign (wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
}
-static short pose_select_same_group (Object *ob)
-{
- bPose *pose= (ob)? ob->pose : NULL;
- bArmature *arm= (ob)? ob->data : NULL;
- bPoseChannel *pchan, *chan;
- short changed= 0;
-
- if (ELEM3(NULL, ob, pose, arm))
- return 0;
-
- /* loop in loop... bad and slow! */
- for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
- if (arm->layer & pchan->bone->layer) {
- if (pchan->bone->flag & BONE_SELECTED || pchan->bone == arm->act_bone) {
-
- /* only if group matches (and is not selected or current bone) */
- for (chan= ob->pose->chanbase.first; chan; chan= chan->next) {
- if (arm->layer & chan->bone->layer) {
- if (pchan->agrp_index == chan->agrp_index) {
- chan->bone->flag |= BONE_SELECTED;
- changed= 1;
- }
- }
- }
-
- }
- }
- }
-
- return changed;
-}
-
-static short pose_select_same_layer (Object *ob)
-{
- bPose *pose= (ob)? ob->pose : NULL;
- bArmature *arm= (ob)? ob->data : NULL;
- bPoseChannel *pchan;
- int layers= 0, changed= 0;
-
- if (ELEM3(NULL, ob, pose, arm))
- return 0;
-
- /* figure out what bones are selected */
- for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
- if (arm->layer & pchan->bone->layer) {
- if (pchan->bone->flag & BONE_SELECTED || pchan->bone == arm->act_bone) {
- layers |= pchan->bone->layer;
- }
- }
- }
- if (layers == 0)
- return 0;
-
- /* select bones that are on same layers as layers flag */
- for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
- if (arm->layer & pchan->bone->layer) {
- if (layers & pchan->bone->layer) {
- pchan->bone->flag |= BONE_SELECTED;
- changed= 1;
- }
- }
- }
-
- return changed;
-}
-
-void pose_select_grouped (Scene *scene, short nr)
-{
- short changed = 0;
-
- if (nr == 1) changed= pose_select_same_group(OBACT);
- else if (nr == 2) changed= pose_select_same_layer(OBACT);
-
- if (changed) {
- countall();
- BIF_undo_push("Select Grouped");
- }
-}
-
-/* Shift-G in 3D-View while in PoseMode */
-void pose_select_grouped_menu (Scene *scene)
-{
- short nr;
-
- /* here we go */
- nr= pupmenu("Select Grouped%t|In Same Group%x1|In Same Layer%x2");
- pose_select_grouped(scene, nr);
-}
-
/* ********************************************** */
static int pose_flip_names_exec (bContext *C, wmOperator *op)
@@ -1714,31 +1782,81 @@ void ARMATURE_OT_bone_layers (wmOperatorType *ot)
/* ********************************************** */
-/* for use in insertkey, ensure rotation goes other way around */
-void pose_flipquats(Scene *scene)
+static int pose_flip_quats_exec (bContext *C, wmOperator *op)
{
- Object *ob = OBACT;
- bArmature *arm= ob->data;
- bPoseChannel *pchan;
+ Scene *scene= CTX_data_scene(C);
+ Object *ob= CTX_data_active_object(C);
- if(ob->pose==NULL)
- return;
+ bCommonKeySrc cks;
+ ListBase dsources = {&cks, &cks};
- /* find sel bones */
- for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
- if(pchan->bone && (pchan->bone->flag & BONE_SELECTED) && (pchan->bone->layer & arm->layer)) {
+ /* init common-key-source for use by KeyingSets */
+ memset(&cks, 0, sizeof(bCommonKeySrc));
+ cks.id= &ob->id;
+
+ /* loop through all selected pchans, flipping and keying (as needed) */
+ CTX_DATA_BEGIN(C, bPoseChannel*, pchan, selected_pose_bones)
+ {
+ /* only if bone is using quaternion rotation */
+ if (pchan->rotmode == ROT_MODE_QUAT) {
/* quaternions have 720 degree range */
pchan->quat[0]= -pchan->quat[0];
pchan->quat[1]= -pchan->quat[1];
pchan->quat[2]= -pchan->quat[2];
pchan->quat[3]= -pchan->quat[3];
+
+ /* perform auto-keying
+ * NOTE: paths don't need recalculation here, since the orientations shouldn't have changed
+ */
+ if (autokeyframe_cfra_can_key(scene, &ob->id)) {
+ /* Set keys on pose
+ * - KeyingSet to use depends on rotation mode
+ * (but that's handled by the templates code)
+ */
+ KeyingSet *ks= ANIM_builtin_keyingset_get_named(NULL, "Rotation");
+
+ /* init cks for this PoseChannel, then use the relative KeyingSets to keyframe it */
+ cks.pchan= pchan;
+
+ modify_keyframes(scene, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
+
+ /* clear any unkeyed tags */
+ if (pchan->bone)
+ pchan->bone->flag &= ~BONE_UNKEYED;
+ }
+ else {
+ /* add unkeyed tags */
+ if (pchan->bone)
+ pchan->bone->flag |= BONE_UNKEYED;
+ }
}
}
+ CTX_DATA_END;
- /* do autokey */
- autokeyframe_pose_cb_func(ob, TFM_ROTATION, 0);
+ /* notifiers and updates */
+ DAG_id_flush_update(&ob->id, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, ob);
+
+ return OPERATOR_FINISHED;
}
+void POSE_OT_quaternions_flip (wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name = "Flip Quats";
+ ot->idname= "POSE_OT_quaternions_flip";
+ ot->description= "Flip quaternion values to achieve desired rotations, while maintaining the same orientations.";
+
+ /* callbacks */
+ ot->exec= pose_flip_quats_exec;
+ ot->poll= ED_operator_posemode;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/* ********************************************** */
+
/* context: active channel */
void pose_special_editmenu(Scene *scene)
{