forked from bartvdbraak/blender
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.
This commit is contained in:
parent
41499247db
commit
5844560ec2
@ -419,6 +419,9 @@ class VIEW3D_MT_select_pose(bpy.types.Menu):
|
|||||||
props.extend = True
|
props.extend = True
|
||||||
props.direction = 'CHILD'
|
props.direction = 'CHILD'
|
||||||
|
|
||||||
|
layout.separator()
|
||||||
|
|
||||||
|
layout.operator_menu_enum("pose.select_grouped", "type", text="Grouped")
|
||||||
layout.operator("object.select_pattern", text="Select Pattern...")
|
layout.operator("object.select_pattern", text="Select Pattern...")
|
||||||
|
|
||||||
|
|
||||||
@ -988,6 +991,8 @@ class VIEW3D_MT_pose(bpy.types.Menu):
|
|||||||
|
|
||||||
layout.operator("pose.flip_names")
|
layout.operator("pose.flip_names")
|
||||||
|
|
||||||
|
layout.operator("pose.quaternions_flip")
|
||||||
|
|
||||||
layout.separator()
|
layout.separator()
|
||||||
|
|
||||||
layout.operator_context = 'INVOKE_AREA'
|
layout.operator_context = 'INVOKE_AREA'
|
||||||
|
@ -817,6 +817,7 @@ static float dtar_get_prop_val (ChannelDriver *driver, DriverTarget *dtar)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* degrees to radians (since curves are stored in degrees, but drivers need radians) */
|
||||||
if (RNA_SUBTYPE_UNIT(RNA_property_subtype(prop)) == PROP_UNIT_ROTATION) {
|
if (RNA_SUBTYPE_UNIT(RNA_property_subtype(prop)) == PROP_UNIT_ROTATION) {
|
||||||
value *= 180.0/M_PI;
|
value *= 180.0/M_PI;
|
||||||
}
|
}
|
||||||
|
@ -86,6 +86,7 @@ void POSE_OT_select_parent(struct wmOperatorType *ot);
|
|||||||
void POSE_OT_select_hierarchy(struct wmOperatorType *ot);
|
void POSE_OT_select_hierarchy(struct wmOperatorType *ot);
|
||||||
void POSE_OT_select_linked(struct wmOperatorType *ot);
|
void POSE_OT_select_linked(struct wmOperatorType *ot);
|
||||||
void POSE_OT_select_constraint_target(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_add(struct wmOperatorType *ot);
|
||||||
void POSE_OT_group_remove(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_autoside_names(struct wmOperatorType *ot);
|
||||||
void POSE_OT_flip_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_flags_set(struct wmOperatorType *ot);
|
||||||
|
|
||||||
void POSE_OT_armature_layers(struct wmOperatorType *ot);
|
void POSE_OT_armature_layers(struct wmOperatorType *ot);
|
||||||
|
@ -127,6 +127,7 @@ void ED_operatortypes_armature(void)
|
|||||||
WM_operatortype_append(POSE_OT_select_hierarchy);
|
WM_operatortype_append(POSE_OT_select_hierarchy);
|
||||||
WM_operatortype_append(POSE_OT_select_linked);
|
WM_operatortype_append(POSE_OT_select_linked);
|
||||||
WM_operatortype_append(POSE_OT_select_constraint_target);
|
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_add);
|
||||||
WM_operatortype_append(POSE_OT_group_remove);
|
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_autoside_names);
|
||||||
WM_operatortype_append(POSE_OT_flip_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_flags_set);
|
||||||
|
|
||||||
WM_operatortype_append(POSE_OT_armature_layers);
|
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_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_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_copy", CKEY, KM_PRESS, KM_CTRL, 0);
|
||||||
WM_keymap_add_item(keymap, "POSE_OT_paste", VKEY, 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);
|
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);
|
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_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_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);
|
WM_keymap_add_item(keymap, "POSE_OT_constraints_clear", CKEY, KM_PRESS, KM_CTRL|KM_ALT, 0);
|
||||||
|
@ -93,8 +93,6 @@
|
|||||||
static int pupmenu() {return 0;}
|
static int pupmenu() {return 0;}
|
||||||
static void error() {};
|
static void error() {};
|
||||||
static void BIF_undo_push() {}
|
static void BIF_undo_push() {}
|
||||||
static void countall() {}
|
|
||||||
static void autokeyframe_pose_cb_func() {}
|
|
||||||
/* ************* XXX *************** */
|
/* ************* XXX *************** */
|
||||||
|
|
||||||
/* This function is used to indicate that a bone is selected and needs keyframes inserted */
|
/* 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;
|
return OPERATOR_CANCELLED;
|
||||||
|
|
||||||
WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, ob);
|
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;
|
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
|
||||||
|
|
||||||
/* props */
|
/* props */
|
||||||
RNA_def_enum(ot->srna, "direction", direction_items,
|
ot->prop= RNA_def_enum(ot->srna, "direction", direction_items, BONE_SELECT_PARENT, "Direction", "");
|
||||||
BONE_SELECT_PARENT, "Direction", "");
|
|
||||||
RNA_def_boolean(ot->srna, "extend", 0, "Add to Selection", "");
|
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)
|
void pose_copy_menu(Scene *scene)
|
||||||
{
|
{
|
||||||
@ -1205,14 +1362,14 @@ static int pose_group_unassign_exec (bContext *C, wmOperator *op)
|
|||||||
pose= ob->pose;
|
pose= ob->pose;
|
||||||
arm= ob->data;
|
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...
|
// NOTE: unfortunately, we cannot use the context-iterators here, since they might not be defined...
|
||||||
// CTX_DATA_BEGIN(C, bPoseChannel*, pchan, selected_pose_bones)
|
// CTX_DATA_BEGIN(C, bPoseChannel*, pchan, selected_pose_bones)
|
||||||
for (pchan= pose->chanbase.first; pchan; pchan= pchan->next) {
|
for (pchan= pose->chanbase.first; pchan; pchan= pchan->next) {
|
||||||
/* ensure that PoseChannel is on visible layer and is not hidden in PoseMode */
|
/* ensure that PoseChannel is on visible layer and is not hidden in PoseMode */
|
||||||
// NOTE: sync this view3d_context() in space_view3d.c
|
// 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) && (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) {
|
if (pchan->agrp_index) {
|
||||||
pchan->agrp_index= 0;
|
pchan->agrp_index= 0;
|
||||||
done= 1;
|
done= 1;
|
||||||
@ -1246,95 +1403,6 @@ void POSE_OT_group_unassign (wmOperatorType *ot)
|
|||||||
ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
|
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)
|
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 */
|
static int pose_flip_quats_exec (bContext *C, wmOperator *op)
|
||||||
void pose_flipquats(Scene *scene)
|
|
||||||
{
|
{
|
||||||
Object *ob = OBACT;
|
Scene *scene= CTX_data_scene(C);
|
||||||
bArmature *arm= ob->data;
|
Object *ob= CTX_data_active_object(C);
|
||||||
bPoseChannel *pchan;
|
|
||||||
|
|
||||||
if(ob->pose==NULL)
|
bCommonKeySrc cks;
|
||||||
return;
|
ListBase dsources = {&cks, &cks};
|
||||||
|
|
||||||
/* find sel bones */
|
/* init common-key-source for use by KeyingSets */
|
||||||
for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
|
memset(&cks, 0, sizeof(bCommonKeySrc));
|
||||||
if(pchan->bone && (pchan->bone->flag & BONE_SELECTED) && (pchan->bone->layer & arm->layer)) {
|
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 */
|
/* quaternions have 720 degree range */
|
||||||
pchan->quat[0]= -pchan->quat[0];
|
pchan->quat[0]= -pchan->quat[0];
|
||||||
pchan->quat[1]= -pchan->quat[1];
|
pchan->quat[1]= -pchan->quat[1];
|
||||||
pchan->quat[2]= -pchan->quat[2];
|
pchan->quat[2]= -pchan->quat[2];
|
||||||
pchan->quat[3]= -pchan->quat[3];
|
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;
|
||||||
|
|
||||||
|
/* 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* do autokey */
|
void POSE_OT_quaternions_flip (wmOperatorType *ot)
|
||||||
autokeyframe_pose_cb_func(ob, TFM_ROTATION, 0);
|
{
|
||||||
|
/* 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 */
|
/* context: active channel */
|
||||||
void pose_special_editmenu(Scene *scene)
|
void pose_special_editmenu(Scene *scene)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user