680218551db50def0a2ff8807e08ef7f2a27d8e7
[blender.git] / source / blender / editors / armature / poseobject.c
1 /*
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. 
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * Contributor(s): Ton Roosendaal, Blender Foundation '05, full recode.
24  *                               Joshua Leung
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  * support for animation modes - Reevan McKay
28  */
29
30 /** \file blender/editors/armature/poseobject.c
31  *  \ingroup edarmature
32  */
33
34
35 #include <stdlib.h>
36 #include <stddef.h>
37 #include <string.h>
38
39 #include "MEM_guardedalloc.h"
40
41 #include "BLI_math.h"
42 #include "BLI_blenlib.h"
43 #include "BLI_dynstr.h"
44 #include "BLI_utildefines.h"
45
46 #include "BLF_api.h"
47
48 #include "DNA_anim_types.h"
49 #include "DNA_armature_types.h"
50 #include "DNA_constraint_types.h"
51 #include "DNA_scene_types.h"
52 #include "DNA_object_types.h"
53
54 #include "BKE_anim.h"
55 #include "BKE_idprop.h"
56 #include "BKE_action.h"
57 #include "BKE_armature.h"
58 #include "BKE_context.h"
59 #include "BKE_constraint.h"
60 #include "BKE_deform.h"
61 #include "BKE_depsgraph.h"
62 #include "BKE_fcurve.h"
63 #include "BKE_modifier.h"
64 #include "BKE_report.h"
65
66
67 #include "RNA_access.h"
68 #include "RNA_define.h"
69
70 #include "WM_api.h"
71 #include "WM_types.h"
72
73 #include "ED_armature.h"
74 #include "ED_keyframing.h"
75 #include "ED_mesh.h"
76 #include "ED_screen.h"
77
78 #include "UI_interface.h"
79 #include "UI_resources.h"
80
81 #include "armature_intern.h"
82
83 static int object_pose_context(Object *ob)
84 {
85         if(     (ob) && 
86                 (ob->type == OB_ARMATURE) &&
87                 (ob->pose) &&
88                 (ob->mode & OB_MODE_POSE)
89         ) {
90                 return 1;
91         }
92         else {
93                 return 0;
94         }
95 }
96
97 Object *ED_object_pose_armature(Object *ob)
98 {
99         if(ob==NULL)
100                 return NULL;
101         
102         if(object_pose_context(ob))
103                 return ob;
104
105         ob= modifiers_isDeformedByArmature(ob);
106
107         if(object_pose_context(ob))
108                 return ob;
109
110         return NULL;
111 }
112
113
114 /* This function is used to indicate that a bone is selected and needs keyframes inserted */
115 static void set_pose_keys (Object *ob)
116 {
117         bArmature *arm= ob->data;
118         bPoseChannel *chan;
119
120         if (ob->pose){
121                 for (chan=ob->pose->chanbase.first; chan; chan=chan->next){
122                         Bone *bone= chan->bone;
123                         if ((bone) && (bone->flag & BONE_SELECTED) && (arm->layer & bone->layer))
124                                 chan->flag |= POSE_KEY; 
125                         else
126                                 chan->flag &= ~POSE_KEY;
127                 }
128         }
129 }
130
131 /* This function is used to process the necessary updates for */
132 void ED_armature_enter_posemode(bContext *C, Base *base)
133 {
134         ReportList *reports= CTX_wm_reports(C);
135         Object *ob= base->object;
136         
137         if (ob->id.lib) {
138                 BKE_report(reports, RPT_WARNING, "Can't pose libdata");
139                 return;
140         }
141         
142         switch (ob->type) {
143                 case OB_ARMATURE:
144                         ob->restore_mode = ob->mode;
145                         ob->mode |= OB_MODE_POSE;
146                         
147                         WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_MODE_POSE, NULL);
148                         
149                         break;
150                 default:
151                         return;
152         }
153         
154         // XXX: disabled as this would otherwise cause a nasty loop...
155         //ED_object_toggle_modes(C, ob->mode);
156 }
157
158 void ED_armature_exit_posemode(bContext *C, Base *base)
159 {
160         if(base) {
161                 Object *ob= base->object;
162                 
163                 ob->restore_mode = ob->mode;
164                 ob->mode &= ~OB_MODE_POSE;
165                 
166                 WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_MODE_OBJECT, NULL);
167         }       
168 }
169
170 /* if a selected or active bone is protected, throw error (oonly if warn==1) and return 1 */
171 /* only_selected==1 : the active bone is allowed to be protected */
172 #if 0 /* UNUSED 2.5 */
173 static short pose_has_protected_selected(Object *ob, short warn)
174 {
175         /* check protection */
176         if (ob->proxy) {
177                 bPoseChannel *pchan;
178                 bArmature *arm= ob->data;
179
180                 for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
181                         if (pchan->bone && (pchan->bone->layer & arm->layer)) {
182                                 if (pchan->bone->layer & arm->layer_protected) {
183                                         if (pchan->bone->flag & BONE_SELECTED)
184                                            break;
185                                 }
186                         }
187                 }
188                 if (pchan) {
189                         if (warn) error("Cannot change Proxy protected bones");
190                         return 1;
191                 }
192         }
193         return 0;
194 }
195 #endif
196
197 /* only for real IK, not for auto-IK */
198 static int pose_channel_in_IK_chain(Object *ob, bPoseChannel *pchan, int level)
199 {
200         bConstraint *con;
201         Bone *bone;
202         
203         /* No need to check if constraint is active (has influence),
204          * since all constraints with CONSTRAINT_IK_AUTO are active */
205         for(con= pchan->constraints.first; con; con= con->next) {
206                 if(con->type==CONSTRAINT_TYPE_KINEMATIC) {
207                         bKinematicConstraint *data= con->data;
208                         if(data->rootbone == 0 || data->rootbone > level) {
209                                 if((data->flag & CONSTRAINT_IK_AUTO)==0)
210                                         return 1;
211                         }
212                 }
213         }
214         for(bone= pchan->bone->childbase.first; bone; bone= bone->next) {
215                 pchan= get_pose_channel(ob->pose, bone->name);
216                 if(pchan && pose_channel_in_IK_chain(ob, pchan, level + 1))
217                         return 1;
218         }
219         return 0;
220 }
221
222 int ED_pose_channel_in_IK_chain(Object *ob, bPoseChannel *pchan)
223 {
224         return pose_channel_in_IK_chain(ob, pchan, 0);
225 }
226
227 /* ********************************************** */
228 /* Motion Paths */
229
230 /* For the object with pose/action: update paths for those that have got them
231  * This should selectively update paths that exist...
232  *
233  * To be called from various tools that do incremental updates 
234  */
235 void ED_pose_recalculate_paths(Scene *scene, Object *ob)
236 {
237         ListBase targets = {NULL, NULL};
238         
239         /* set flag to force recalc, then grab the relevant bones to target */
240         ob->pose->avs.recalc |= ANIMVIZ_RECALC_PATHS;
241         animviz_get_object_motionpaths(ob, &targets);
242         
243         /* recalculate paths, then free */
244         animviz_calc_motionpaths(scene, &targets);
245         BLI_freelistN(&targets);
246 }
247
248 /* For the object with pose/action: create path curves for selected bones 
249  * This recalculates the WHOLE path within the pchan->pathsf and pchan->pathef range
250  */
251 static int pose_calculate_paths_exec (bContext *C, wmOperator *UNUSED(op))
252 {
253         ScrArea *sa= CTX_wm_area(C);
254         Scene *scene= CTX_data_scene(C);
255         Object *ob;
256         
257         /* since this call may also be used from the buttons window, we need to check for where to get the object */
258         if (sa->spacetype == SPACE_BUTS) 
259                 ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
260         else
261                 ob= ED_object_pose_armature(CTX_data_active_object(C));
262                 
263         if (ELEM(NULL, ob, ob->pose))
264                 return OPERATOR_CANCELLED;
265         
266         /* set up path data for bones being calculated */
267         CTX_DATA_BEGIN(C, bPoseChannel*, pchan, selected_pose_bones) 
268         {
269                 /* verify makes sure that the selected bone has a bone with the appropriate settings */
270                 animviz_verify_motionpaths(scene, ob, pchan);
271         }
272         CTX_DATA_END;
273         
274         /* calculate the bones that now have motionpaths... */
275         // TODO: only make for the selected bones?
276         ED_pose_recalculate_paths(scene, ob);
277         
278         /* notifiers for updates */
279         WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob);
280         
281         return OPERATOR_FINISHED; 
282 }
283
284 void POSE_OT_paths_calculate (wmOperatorType *ot)
285 {
286         /* identifiers */
287         ot->name= "Calculate Bone Paths";
288         ot->idname= "POSE_OT_paths_calculate";
289         ot->description= "Calculate paths for the selected bones";
290         
291         /* api callbacks */
292         ot->exec= pose_calculate_paths_exec;
293         ot->poll= ED_operator_posemode;
294         
295         /* flags */
296         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
297 }
298
299 /* --------- */
300
301 /* for the object with pose/action: clear path curves for selected bones only */
302 static void ED_pose_clear_paths(Object *ob)
303 {
304         bPoseChannel *pchan;
305         short skipped = 0;
306         
307         if ELEM(NULL, ob, ob->pose)
308                 return;
309         
310         /* free the motionpath blocks, but also take note of whether we skipped some... */
311         for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
312                 if (pchan->mpath) {
313                         if ((pchan->bone) && (pchan->bone->flag & BONE_SELECTED)) {
314                                 animviz_free_motionpath(pchan->mpath);
315                                 pchan->mpath= NULL;
316                         }
317                         else 
318                                 skipped = 1;
319                 }
320         }
321         
322         /* if we didn't skip any, we shouldn't have any paths left */
323         if (skipped == 0)
324                 ob->pose->avs.path_bakeflag &= ~MOTIONPATH_BAKE_HAS_PATHS;
325 }
326
327 /* operator callback for this */
328 static int pose_clear_paths_exec (bContext *C, wmOperator *UNUSED(op))
329 {
330         ScrArea *sa= CTX_wm_area(C);
331         Object *ob;
332         
333         /* since this call may also be used from the buttons window, we need to check for where to get the object */
334         if (sa->spacetype == SPACE_BUTS) 
335                 ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
336         else
337                 ob= ED_object_pose_armature(CTX_data_active_object(C));
338                 
339         /* only continue if there's an object */
340         if ELEM(NULL, ob, ob->pose)
341                 return OPERATOR_CANCELLED;
342         
343         /* use the backend function for this */
344         ED_pose_clear_paths(ob);
345         
346         /* notifiers for updates */
347         WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob);
348         
349         return OPERATOR_FINISHED; 
350 }
351
352 void POSE_OT_paths_clear (wmOperatorType *ot)
353 {
354         /* identifiers */
355         ot->name= "Clear Bone Paths";
356         ot->idname= "POSE_OT_paths_clear";
357         ot->description= "Clear path caches for selected bones";
358         
359         /* api callbacks */
360         ot->exec= pose_clear_paths_exec;
361         ot->poll= ED_operator_posemode;
362         
363         /* flags */
364         ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
365 }
366
367 /* ******************* Select Constraint Target Operator ************* */
368
369 static int pose_select_constraint_target_exec(bContext *C, wmOperator *UNUSED(op))
370 {
371         Object *ob= ED_object_pose_armature(CTX_data_active_object(C));
372         bConstraint *con;
373         int found= 0;
374         
375         CTX_DATA_BEGIN(C, bPoseChannel *, pchan, visible_pose_bones) 
376         {
377                 if (pchan->bone->flag & BONE_SELECTED) {
378                         for (con= pchan->constraints.first; con; con= con->next) {
379                                 bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
380                                 ListBase targets = {NULL, NULL};
381                                 bConstraintTarget *ct;
382                                 
383                                 if (cti && cti->get_constraint_targets) {
384                                         cti->get_constraint_targets(con, &targets);
385                                         
386                                         for (ct= targets.first; ct; ct= ct->next) {
387                                                 if ((ct->tar == ob) && (ct->subtarget[0])) {
388                                                         bPoseChannel *pchanc= get_pose_channel(ob->pose, ct->subtarget);
389                                                         if((pchanc) && !(pchanc->bone->flag & BONE_UNSELECTABLE)) {
390                                                                 pchanc->bone->flag |= BONE_SELECTED|BONE_TIPSEL|BONE_ROOTSEL;
391                                                                 found= 1;
392                                                         }
393                                                 }
394                                         }
395                                         
396                                         if (cti->flush_constraint_targets)
397                                                 cti->flush_constraint_targets(con, &targets, 1);
398                                 }
399                         }
400                 }
401         }
402         CTX_DATA_END;
403
404         if (!found)
405                 return OPERATOR_CANCELLED;
406
407         WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, ob);
408
409         return OPERATOR_FINISHED;
410 }
411
412 void POSE_OT_select_constraint_target(wmOperatorType *ot)
413 {
414         /* identifiers */
415         ot->name= "Select Constraint Target";
416         ot->idname= "POSE_OT_select_constraint_target";
417         ot->description= "Select bones used as targets for the currently selected bones";
418         
419         /* api callbacks */
420         ot->exec= pose_select_constraint_target_exec;
421         ot->poll= ED_operator_posemode;
422         
423         /* flags */
424         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
425 }
426
427 /* ******************* select hierarchy operator ************* */
428
429 static int pose_select_hierarchy_exec(bContext *C, wmOperator *op)
430 {
431         Object *ob= ED_object_pose_armature(CTX_data_active_object(C));
432         bArmature *arm= ob->data;
433         Bone *curbone, *pabone, *chbone;
434         int direction = RNA_enum_get(op->ptr, "direction");
435         int add_to_sel = RNA_boolean_get(op->ptr, "extend");
436         int found= 0;
437         
438         CTX_DATA_BEGIN(C, bPoseChannel *, pchan, visible_pose_bones) 
439         {
440                 curbone= pchan->bone;
441                 
442                 if ((curbone->flag & BONE_UNSELECTABLE)==0) {
443                         if (curbone == arm->act_bone) {
444                                 if (direction == BONE_SELECT_PARENT) {
445                                         if (pchan->parent == NULL) continue;
446                                         else pabone= pchan->parent->bone;
447                                         
448                                         if (PBONE_VISIBLE(arm, pabone)) {
449                                                 if (!add_to_sel) curbone->flag &= ~BONE_SELECTED;
450                                                 pabone->flag |= BONE_SELECTED;
451                                                 arm->act_bone= pabone;
452                                                 
453                                                 found= 1;
454                                                 break;
455                                         }
456                                 } 
457                                 else { /* direction == BONE_SELECT_CHILD */
458                                         if (pchan->child == NULL) continue;
459                                         else chbone = pchan->child->bone;
460                                         
461                                         if (PBONE_VISIBLE(arm, chbone)) {
462                                                 if (!add_to_sel) curbone->flag &= ~BONE_SELECTED;
463                                                 chbone->flag |= BONE_SELECTED;
464                                                 arm->act_bone= chbone;
465                                                 
466                                                 found= 1;
467                                                 break;
468                                         }
469                                 }
470                         }
471                 }
472         }
473         CTX_DATA_END;
474
475         if (found == 0)
476                 return OPERATOR_CANCELLED;
477
478         WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, ob);
479
480         return OPERATOR_FINISHED;
481 }
482
483 void POSE_OT_select_hierarchy(wmOperatorType *ot)
484 {
485         static EnumPropertyItem direction_items[]= {
486                 {BONE_SELECT_PARENT, "PARENT", 0, "Select Parent", ""},
487                 {BONE_SELECT_CHILD, "CHILD", 0, "Select Child", ""},
488                 {0, NULL, 0, NULL, NULL}
489         };
490         
491         /* identifiers */
492         ot->name= _("Select Hierarchy");
493         ot->idname= "POSE_OT_select_hierarchy";
494         ot->description= _("Select immediate parent/children of selected bones");
495         
496         /* api callbacks */
497         ot->exec= pose_select_hierarchy_exec;
498         ot->poll= ED_operator_posemode;
499         
500         /* flags */
501         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
502         
503         /* props */
504         ot->prop= RNA_def_enum(ot->srna, "direction", direction_items, BONE_SELECT_PARENT, "Direction", "");
505         RNA_def_boolean(ot->srna, "extend", 0, _("Add to Selection"), "");
506         
507 }
508
509 /* ******************* select grouped operator ************* */
510
511 static short pose_select_same_group (bContext *C, Object *ob, short extend)
512 {
513         bArmature *arm= (ob)? ob->data : NULL;
514         bPose *pose= (ob)? ob->pose : NULL;
515         char *group_flags;
516         int numGroups = 0;
517         short changed=0, tagged=0;
518         
519         /* sanity checks */
520         if (ELEM3(NULL, ob, pose, arm))
521                 return 0;
522                 
523         /* count the number of groups */
524         numGroups= BLI_countlist(&pose->agroups);
525         if (numGroups == 0)
526                 return 0;
527                 
528         /* alloc a small array to keep track of the groups to use 
529          *      - each cell stores on/off state for whether group should be used
530          *      - size is numGroups + 1, since index=0 is used for no-group
531          */
532         group_flags= MEM_callocN(numGroups+1, "pose_select_same_group");
533         
534         CTX_DATA_BEGIN(C, bPoseChannel *, pchan, visible_pose_bones) 
535         {
536                 /* keep track of group as group to use later? */
537                 if (pchan->bone->flag & BONE_SELECTED) {
538                         group_flags[pchan->agrp_index] = 1;
539                         tagged= 1;
540                 }
541                 
542                 /* deselect all bones before selecting new ones? */
543                 if ((extend == 0) && (pchan->bone->flag & BONE_UNSELECTABLE)==0)
544                         pchan->bone->flag &= ~BONE_SELECTED;
545         }
546         CTX_DATA_END;
547         
548         /* small optimisation: only loop through bones a second time if there are any groups tagged */
549         if (tagged) {
550                 /* only if group matches (and is not selected or current bone) */
551                 CTX_DATA_BEGIN(C, bPoseChannel *, pchan, visible_pose_bones) 
552                 {
553                         if ((pchan->bone->flag & BONE_UNSELECTABLE)==0) {
554                                 /* check if the group used by this bone is counted */
555                                 if (group_flags[pchan->agrp_index]) {
556                                         pchan->bone->flag |= BONE_SELECTED;
557                                         changed= 1;
558                                 }
559                         }
560                 }
561                 CTX_DATA_END;
562         }
563         
564         /* free temp info */
565         MEM_freeN(group_flags);
566         
567         return changed;
568 }
569
570 static short pose_select_same_layer (bContext *C, Object *ob, short extend)
571 {
572         bPose *pose= (ob)? ob->pose : NULL;
573         bArmature *arm= (ob)? ob->data : NULL;
574         short changed= 0;
575         int layers= 0;
576         
577         if (ELEM3(NULL, ob, pose, arm))
578                 return 0;
579         
580         /* figure out what bones are selected */
581         CTX_DATA_BEGIN(C, bPoseChannel *, pchan, visible_pose_bones) 
582         {
583                 /* keep track of layers to use later? */
584                 if (pchan->bone->flag & BONE_SELECTED)
585                         layers |= pchan->bone->layer;
586                         
587                 /* deselect all bones before selecting new ones? */
588                 if ((extend == 0) && (pchan->bone->flag & BONE_UNSELECTABLE)==0)
589                         pchan->bone->flag &= ~BONE_SELECTED;
590         }
591         CTX_DATA_END;
592         if (layers == 0) 
593                 return 0;
594                 
595         /* select bones that are on same layers as layers flag */
596         CTX_DATA_BEGIN(C, bPoseChannel *, pchan, visible_pose_bones) 
597         {
598                 /* if bone is on a suitable layer, and the bone can have its selection changed, select it */
599                 if ((layers & pchan->bone->layer) && (pchan->bone->flag & BONE_UNSELECTABLE)==0) {
600                         pchan->bone->flag |= BONE_SELECTED;
601                         changed= 1;
602                 }
603         }
604         CTX_DATA_END;
605         
606         return changed;
607 }
608
609
610 static int pose_select_grouped_exec (bContext *C, wmOperator *op)
611 {
612         Object *ob= ED_object_pose_armature(CTX_data_active_object(C));
613         short extend= RNA_boolean_get(op->ptr, "extend");
614         short changed = 0;
615         
616         /* sanity check */
617         if (ELEM(NULL, ob, ob->pose))
618                 return OPERATOR_CANCELLED;
619                 
620         /* selection types 
621          * NOTE: for the order of these, see the enum in POSE_OT_select_grouped()
622          */
623         switch (RNA_enum_get(op->ptr, "type")) {
624                 case 1: /* group */
625                         changed= pose_select_same_group(C, ob, extend);
626                         break;
627                 default: /* layer */
628                         changed= pose_select_same_layer(C, ob, extend);
629                         break;
630         }
631         
632         /* notifiers for updates */
633         WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob);
634         
635         /* report done status */
636         if (changed)
637                 return OPERATOR_FINISHED;
638         else
639                 return OPERATOR_CANCELLED;
640 }
641
642 void POSE_OT_select_grouped (wmOperatorType *ot)
643 {
644         static EnumPropertyItem prop_select_grouped_types[] = {
645                 {0, "LAYER", 0, "Layer", "Shared layers"},
646                 {1, "GROUP", 0, "Group", "Shared group"},
647                 {0, NULL, 0, NULL, NULL}
648         };
649
650         /* identifiers */
651         ot->name= _("Select Grouped");
652         ot->description = _("Select all visible bones grouped by similar properties");
653         ot->idname= "POSE_OT_select_grouped";
654         
655         /* api callbacks */
656         ot->invoke= WM_menu_invoke;
657         ot->exec= pose_select_grouped_exec;
658         ot->poll= ED_operator_posemode;
659         
660         /* flags */
661         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
662         
663         /* properties */
664         RNA_def_boolean(ot->srna, "extend", FALSE, _("Extend"), _("Extend selection instead of deselecting everything first."));
665         ot->prop= RNA_def_enum(ot->srna, "type", prop_select_grouped_types, 0, "Type", "");
666 }
667
668
669 /* ********************************************** */
670
671 /* context active object, or weightpainted object with armature in posemode */
672 static int pose_bone_flip_active_exec (bContext *C, wmOperator *UNUSED(op))
673 {
674         Object *ob_act= CTX_data_active_object(C);
675         Object *ob= ED_object_pose_armature(ob_act);
676
677         if(ob && (ob->mode & OB_MODE_POSE)) {
678                 bArmature *arm= ob->data;
679
680                 if(arm->act_bone) {
681                         bPoseChannel *pchanf;
682                         char name[MAXBONENAME];
683                         flip_side_name(name, arm->act_bone->name, TRUE);
684
685                         pchanf= get_pose_channel(ob->pose, name);
686                         if(pchanf && pchanf->bone != arm->act_bone) {
687                                 arm->act_bone->flag &= ~BONE_SELECTED;
688                                 pchanf->bone->flag |= BONE_SELECTED;
689
690                                 arm->act_bone= pchanf->bone;
691
692                                 /* in weightpaint we select the associated vertex group too */
693                                 if(ob_act->mode & OB_MODE_WEIGHT_PAINT) {
694                                         ED_vgroup_select_by_name(ob_act, name);
695                                         DAG_id_tag_update(&ob_act->id, OB_RECALC_DATA);
696                                 }
697
698                                 WM_event_add_notifier(C, NC_OBJECT|ND_BONE_SELECT, ob);
699
700                                 return OPERATOR_FINISHED;
701                         }
702                 }
703         }
704
705         return OPERATOR_CANCELLED;
706 }
707
708 void POSE_OT_select_flip_active(wmOperatorType *ot)
709 {
710         /* identifiers */
711         ot->name= "Flip Selected Active Bone";
712         ot->idname= "POSE_OT_select_flip_active";
713         ot->description= "Activate the bone with a flipped name.";
714         
715         /* api callbacks */
716         ot->exec= pose_bone_flip_active_exec;
717         ot->poll= ED_operator_posemode;
718         
719         /* flags */
720         ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
721 }
722
723
724 /* ********************************************** */
725 #if 0 /* UNUSED 2.5 */
726 static void pose_copy_menu(Scene *scene)
727 {
728         Object *obedit= scene->obedit; // XXX context
729         Object *ob= OBACT;
730         bArmature *arm;
731         bPoseChannel *pchan, *pchanact;
732         short nr=0;
733         int i=0;
734         
735         /* paranoia checks */
736         if (ELEM(NULL, ob, ob->pose)) return;
737         if ((ob==obedit) || (ob->mode & OB_MODE_POSE)==0) return;
738         
739         pchan= get_active_posechannel(ob);
740         
741         if (pchan==NULL) return;
742         pchanact= pchan;
743         arm= ob->data;
744
745         /* if proxy-protected bones selected, some things (such as locks + displays) shouldn't be changable, 
746          * but for constraints (just add local constraints)
747          */
748         if (pose_has_protected_selected(ob, 0)) {
749                 i= BLI_countlist(&(pchanact->constraints)); /* if there are 24 or less, allow for the user to select constraints */
750                 if (i < 25)
751                         nr= pupmenu("Copy Pose Attributes %t|Local Location%x1|Local Rotation%x2|Local Size%x3|%l|Visual Location %x9|Visual Rotation%x10|Visual Size%x11|%l|Constraints (All)%x4|Constraints...%x5");
752                 else
753                         nr= pupmenu("Copy Pose Attributes %t|Local Location%x1|Local Rotation%x2|Local Size%x3|%l|Visual Location %x9|Visual Rotation%x10|Visual Size%x11|%l|Constraints (All)%x4");
754         }
755         else {
756                 i= BLI_countlist(&(pchanact->constraints)); /* if there are 24 or less, allow for the user to select constraints */
757                 if (i < 25)
758                         nr= pupmenu("Copy Pose Attributes %t|Local Location%x1|Local Rotation%x2|Local Size%x3|%l|Visual Location %x9|Visual Rotation%x10|Visual Size%x11|%l|Constraints (All)%x4|Constraints...%x5|%l|Transform Locks%x6|IK Limits%x7|Bone Shape%x8");
759                 else
760                         nr= pupmenu("Copy Pose Attributes %t|Local Location%x1|Local Rotation%x2|Local Size%x3|%l|Visual Location %x9|Visual Rotation%x10|Visual Size%x11|%l|Constraints (All)%x4|%l|Transform Locks%x6|IK Limits%x7|Bone Shape%x8");
761         }
762         
763         if (nr <= 0) 
764                 return;
765         
766         if (nr != 5)  {
767                 for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
768                         if ( (arm->layer & pchan->bone->layer) &&
769                                  (pchan->bone->flag & BONE_SELECTED) &&
770                                  (pchan != pchanact) ) 
771                         {
772                                 switch (nr) {
773                                         case 1: /* Local Location */
774                                                 VECCOPY(pchan->loc, pchanact->loc);
775                                                 break;
776                                         case 2: /* Local Rotation */
777                                                 QUATCOPY(pchan->quat, pchanact->quat);
778                                                 VECCOPY(pchan->eul, pchanact->eul);
779                                                 break;
780                                         case 3: /* Local Size */
781                                                 VECCOPY(pchan->size, pchanact->size);
782                                                 break;
783                                         case 4: /* All Constraints */
784                                         {
785                                                 ListBase tmp_constraints = {NULL, NULL};
786                                                 
787                                                 /* copy constraints to tmpbase and apply 'local' tags before 
788                                                  * appending to list of constraints for this channel
789                                                  */
790                                                 copy_constraints(&tmp_constraints, &pchanact->constraints, TRUE);
791                                                 if ((ob->proxy) && (pchan->bone->layer & arm->layer_protected)) {
792                                                         bConstraint *con;
793                                                         
794                                                         /* add proxy-local tags */
795                                                         for (con= tmp_constraints.first; con; con= con->next)
796                                                                 con->flag |= CONSTRAINT_PROXY_LOCAL;
797                                                 }
798                                                 BLI_movelisttolist(&pchan->constraints, &tmp_constraints);
799                                                 
800                                                 /* update flags (need to add here, not just copy) */
801                                                 pchan->constflag |= pchanact->constflag;
802                                                 
803                                                 if (ob->pose)
804                                                         ob->pose->flag |= POSE_RECALC;
805                                         }
806                                                 break;
807                                         case 6: /* Transform Locks */
808                                                 pchan->protectflag = pchanact->protectflag;
809                                                 break;
810                                         case 7: /* IK (DOF) settings */
811                                         {
812                                                 pchan->ikflag = pchanact->ikflag;
813                                                 VECCOPY(pchan->limitmin, pchanact->limitmin);
814                                                 VECCOPY(pchan->limitmax, pchanact->limitmax);
815                                                 VECCOPY(pchan->stiffness, pchanact->stiffness);
816                                                 pchan->ikstretch= pchanact->ikstretch;
817                                                 pchan->ikrotweight= pchanact->ikrotweight;
818                                                 pchan->iklinweight= pchanact->iklinweight;
819                                         }
820                                                 break;
821                                         case 8: /* Custom Bone Shape */
822                                                 pchan->custom = pchanact->custom;
823                                                 break;
824                                         case 9: /* Visual Location */
825                                                 armature_loc_pose_to_bone(pchan, pchanact->pose_mat[3], pchan->loc);
826                                                 break;
827                                         case 10: /* Visual Rotation */
828                                         {
829                                                 float delta_mat[4][4];
830                                                 
831                                                 armature_mat_pose_to_bone(pchan, pchanact->pose_mat, delta_mat);
832                                                 
833                                                 if (pchan->rotmode == ROT_MODE_AXISANGLE) {
834                                                         float tmp_quat[4];
835                                                         
836                                                         /* need to convert to quat first (in temp var)... */
837                                                         mat4_to_quat( tmp_quat,delta_mat);
838                                                         quat_to_axis_angle( pchan->rotAxis, &pchan->rotAngle,tmp_quat);
839                                                 }
840                                                 else if (pchan->rotmode == ROT_MODE_QUAT)
841                                                         mat4_to_quat( pchan->quat,delta_mat);
842                                                 else
843                                                         mat4_to_eulO( pchan->eul, pchan->rotmode,delta_mat);
844                                         }
845                                                 break;
846                                         case 11: /* Visual Size */
847                                         {
848                                                 float delta_mat[4][4], size[4];
849                                                 
850                                                 armature_mat_pose_to_bone(pchan, pchanact->pose_mat, delta_mat);
851                                                 mat4_to_size( size,delta_mat);
852                                                 VECCOPY(pchan->size, size);
853                                         }
854                                 }
855                         }
856                 }
857         } 
858         else { /* constraints, optional (note: max we can have is 24 constraints) */
859                 bConstraint *con, *con_back;
860                 int const_toggle[24]= {0}; /* XXX, initialize as 0 to quiet errors */
861                 ListBase const_copy = {NULL, NULL};
862                 
863                 BLI_duplicatelist(&const_copy, &(pchanact->constraints));
864                 
865                 /* build the puplist of constraints */
866                 for (con = pchanact->constraints.first, i=0; con; con=con->next, i++){
867                         const_toggle[i]= 1;
868 //                      add_numbut(i, TOG|INT, con->name, 0, 0, &(const_toggle[i]), "");
869                 }
870                 
871 //              if (!do_clever_numbuts("Select Constraints", i, REDRAW)) {
872 //                      BLI_freelistN(&const_copy);
873 //                      return;
874 //              }
875                 
876                 /* now build a new listbase from the options selected */
877                 for (i=0, con=const_copy.first; con; i++) {
878                         /* if not selected, free/remove it from the list */
879                         if (!const_toggle[i]) {
880                                 con_back= con->next;
881                                 BLI_freelinkN(&const_copy, con);
882                                 con= con_back;
883                         } 
884                         else
885                                 con= con->next;
886                 }
887                 
888                 /* Copy the temo listbase to the selected posebones */
889                 for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
890                         if ( (arm->layer & pchan->bone->layer) &&
891                                  (pchan->bone->flag & BONE_SELECTED) &&
892                                  (pchan!=pchanact) ) 
893                         {
894                                 ListBase tmp_constraints = {NULL, NULL};
895                                 
896                                 /* copy constraints to tmpbase and apply 'local' tags before 
897                                  * appending to list of constraints for this channel
898                                  */
899                                 copy_constraints(&tmp_constraints, &const_copy, TRUE);
900                                 if ((ob->proxy) && (pchan->bone->layer & arm->layer_protected)) {                                       
901                                         /* add proxy-local tags */
902                                         for (con= tmp_constraints.first; con; con= con->next)
903                                                 con->flag |= CONSTRAINT_PROXY_LOCAL;
904                                 }
905                                 BLI_movelisttolist(&pchan->constraints, &tmp_constraints);
906                                 
907                                 /* update flags (need to add here, not just copy) */
908                                 pchan->constflag |= pchanact->constflag;
909                         }
910                 }
911                 BLI_freelistN(&const_copy);
912                 update_pose_constraint_flags(ob->pose); /* we could work out the flags but its simpler to do this */
913                 
914                 if (ob->pose)
915                         ob->pose->flag |= POSE_RECALC;
916         }
917         
918         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);     // and all its relations
919         
920         BIF_undo_push("Copy Pose Attributes");
921         
922 }
923 #endif
924
925 /* ******************** copy/paste pose ********************** */
926
927 /* Global copy/paste buffer for pose - cleared on start/end session + before every copy operation */
928 static bPose *g_posebuf = NULL;
929
930 void free_posebuf(void) 
931 {
932         if (g_posebuf) {
933                 bPoseChannel *pchan;
934                 
935                 for (pchan= g_posebuf->chanbase.first; pchan; pchan= pchan->next) {
936                         if(pchan->prop) {
937                                 IDP_FreeProperty(pchan->prop);
938                                 MEM_freeN(pchan->prop);
939                         }
940                 }
941                 
942                 /* was copied without constraints */
943                 BLI_freelistN(&g_posebuf->chanbase);
944                 MEM_freeN(g_posebuf);
945         }
946         
947         g_posebuf=NULL;
948 }
949
950 /* ---- */
951
952 static int pose_copy_exec (bContext *C, wmOperator *op)
953 {
954         Object *ob= ED_object_pose_armature(CTX_data_active_object(C));
955         
956         /* sanity checking */
957         if ELEM(NULL, ob, ob->pose) {
958                 BKE_report(op->reports, RPT_ERROR, "No Pose to Copy");
959                 return OPERATOR_CANCELLED;
960         }
961
962         /* free existing pose buffer */
963         free_posebuf();
964         
965         /* sets chan->flag to POSE_KEY if bone selected, then copy those bones to the buffer */
966         set_pose_keys(ob);  
967         copy_pose(&g_posebuf, ob->pose, 0);
968         
969         
970         return OPERATOR_FINISHED;
971 }
972
973 void POSE_OT_copy (wmOperatorType *ot) 
974 {
975         /* identifiers */
976         ot->name= "Copy Pose";
977         ot->idname= "POSE_OT_copy";
978         ot->description= "Copies the current pose of the selected bones to copy/paste buffer";
979         
980         /* api callbacks */
981         ot->exec= pose_copy_exec;
982         ot->poll= ED_operator_posemode;
983         
984         /* flag */
985         ot->flag= OPTYPE_REGISTER;
986 }
987
988 /* ---- */
989
990 static int pose_paste_exec (bContext *C, wmOperator *op)
991 {
992         Scene *scene= CTX_data_scene(C);
993         Object *ob= ED_object_pose_armature(CTX_data_active_object(C));
994         bPoseChannel *chan, *pchan;
995         int flip= RNA_boolean_get(op->ptr, "flipped");
996         int selOnly= RNA_boolean_get(op->ptr, "selected_mask");
997         
998         /* sanity checks */
999         if ELEM(NULL, ob, ob->pose)
1000                 return OPERATOR_CANCELLED;
1001
1002         if (g_posebuf == NULL) {
1003                 BKE_report(op->reports, RPT_ERROR, "Copy buffer is empty");
1004                 return OPERATOR_CANCELLED;
1005         }
1006         
1007         /* Safely merge all of the channels in the buffer pose into any existing pose */
1008         for (chan= g_posebuf->chanbase.first; chan; chan=chan->next) {
1009                 if (chan->flag & POSE_KEY) {
1010                         char name[32];
1011                         short paste_ok;
1012                         
1013                         /* get the name - if flipping, we must flip this first */
1014                         if (flip)
1015                                 flip_side_name(name, chan->name, 0);            /* 0 = don't strip off number extensions */
1016                         else
1017                                 BLI_strncpy(name, chan->name, sizeof(name));
1018                         
1019                         /* only copy when:
1020                          *      1) channel exists - poses are not meant to add random channels to anymore
1021                          *      2) if selection-masking is on, channel is selected - only selected bones get pasted on, allowing making both sides symmetrical
1022                          */
1023                         pchan= get_pose_channel(ob->pose, name);
1024                         
1025                         if (selOnly)
1026                                 paste_ok= ((pchan) && (pchan->bone->flag & BONE_SELECTED));
1027                         else
1028                                 paste_ok= ((pchan != NULL));
1029                         
1030                         /* continue? */
1031                         if (paste_ok) {
1032                                 /* only loc rot size 
1033                                  *      - only copies transform info for the pose 
1034                                  */
1035                                 VECCOPY(pchan->loc, chan->loc);
1036                                 VECCOPY(pchan->size, chan->size);
1037                                 pchan->flag= chan->flag;
1038                                 
1039                                 /* check if rotation modes are compatible (i.e. do they need any conversions) */
1040                                 if (pchan->rotmode == chan->rotmode) {
1041                                         /* copy the type of rotation in use */
1042                                         if (pchan->rotmode > 0) {
1043                                                 VECCOPY(pchan->eul, chan->eul);
1044                                         }
1045                                         else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
1046                                                 VECCOPY(pchan->rotAxis, chan->rotAxis);
1047                                                 pchan->rotAngle = chan->rotAngle;
1048                                         }
1049                                         else {
1050                                                 QUATCOPY(pchan->quat, chan->quat);
1051                                         }
1052                                 }
1053                                 else if (pchan->rotmode > 0) {
1054                                         /* quat/axis-angle to euler */
1055                                         if (chan->rotmode == ROT_MODE_AXISANGLE)
1056                                                 axis_angle_to_eulO( pchan->eul, pchan->rotmode,chan->rotAxis, chan->rotAngle);
1057                                         else
1058                                                 quat_to_eulO( pchan->eul, pchan->rotmode,chan->quat);
1059                                 }
1060                                 else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
1061                                         /* quat/euler to axis angle */
1062                                         if (chan->rotmode > 0)
1063                                                 eulO_to_axis_angle(pchan->rotAxis, &pchan->rotAngle, chan->eul, chan->rotmode);
1064                                         else    
1065                                                 quat_to_axis_angle(pchan->rotAxis, &pchan->rotAngle, chan->quat);
1066                                 }
1067                                 else {
1068                                         /* euler/axis-angle to quat */
1069                                         if (chan->rotmode > 0)
1070                                                 eulO_to_quat(pchan->quat, chan->eul, chan->rotmode);
1071                                         else
1072                                                 axis_angle_to_quat(pchan->quat, chan->rotAxis, pchan->rotAngle);
1073                                 }
1074                                 
1075                                 /* paste flipped pose? */
1076                                 if (flip) {
1077                                         pchan->loc[0]*= -1;
1078                                         
1079                                         /* has to be done as eulers... */
1080                                         if (pchan->rotmode > 0) {
1081                                                 pchan->eul[1] *= -1;
1082                                                 pchan->eul[2] *= -1;
1083                                         }
1084                                         else if (pchan->rotmode == ROT_MODE_AXISANGLE) {
1085                                                 float eul[3];
1086                                                 
1087                                                 axis_angle_to_eulO(eul, EULER_ORDER_DEFAULT, pchan->rotAxis, pchan->rotAngle);
1088                                                 eul[1]*= -1;
1089                                                 eul[2]*= -1;
1090                                                 eulO_to_axis_angle(pchan->rotAxis, &pchan->rotAngle, eul, EULER_ORDER_DEFAULT);
1091                                         }
1092                                         else {
1093                                                 float eul[3];
1094                                                 
1095                                                 normalize_qt(pchan->quat);
1096                                                 quat_to_eul(eul, pchan->quat);
1097                                                 eul[1]*= -1;
1098                                                 eul[2]*= -1;
1099                                                 eul_to_quat(pchan->quat, eul);
1100                                         }
1101                                 }
1102                                 
1103                                 /* ID properties 
1104                                  *      - only free the existing properties if the channel we're copying from has them
1105                                  *        NOTE: this means that if the pose depends on some pchan property, the pose may not be ok,
1106                                  *                  but this is better than loosing all the setting you've painstakingly added...
1107                                  */
1108                                 if (chan->prop) {
1109                                         /* free the old properties since we want to replace them now */
1110                                         if (pchan->prop) {
1111                                                 IDP_FreeProperty(pchan->prop);
1112                                                 MEM_freeN(pchan->prop);
1113                                                 pchan->prop= NULL;
1114                                         }
1115                                         
1116                                         /* now copy over the new copy of the properties */
1117                                         pchan->prop= IDP_CopyProperty(chan->prop);      
1118                                 }
1119                                 
1120                                 /* keyframing tagging */
1121                                 if (autokeyframe_cfra_can_key(scene, &ob->id)) {
1122                                         ListBase dsources = {NULL, NULL};
1123                                         
1124                                         /* get KeyingSet to use */
1125                                         KeyingSet *ks = ANIM_get_keyingset_for_autokeying(scene, "LocRotScale");
1126                                         
1127                                         /* now insert the keyframe(s) using the Keying Set
1128                                          *      1) add datasource override for the PoseChannel
1129                                          *      2) insert keyframes
1130                                          *      3) free the extra info 
1131                                          */
1132                                         ANIM_relative_keyingset_add_source(&dsources, &ob->id, &RNA_PoseBone, pchan); 
1133                                         ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
1134                                         BLI_freelistN(&dsources);
1135                                         
1136                                         /* clear any unkeyed tags */
1137                                         if (chan->bone)
1138                                                 chan->bone->flag &= ~BONE_UNKEYED;
1139                                 }
1140                                 else {
1141                                         /* add unkeyed tags */
1142                                         if (chan->bone)
1143                                                 chan->bone->flag |= BONE_UNKEYED;
1144                                 }
1145                         }
1146                 }
1147         }
1148         
1149         /* Update event for pose and deformation children */
1150         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1151                 
1152         /* notifiers for updates */
1153         WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob);
1154
1155         return OPERATOR_FINISHED;
1156 }
1157
1158 void POSE_OT_paste (wmOperatorType *ot)
1159 {
1160         /* identifiers */
1161         ot->name= _("Paste Pose");
1162         ot->idname= "POSE_OT_paste";
1163         ot->description= _("Pastes the stored pose on to the current pose");
1164         
1165         /* api callbacks */
1166         ot->exec= pose_paste_exec;
1167         ot->poll= ED_operator_posemode;
1168         
1169         /* flag */
1170         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1171         
1172         /* properties */
1173         RNA_def_boolean(ot->srna, "flipped", 0, _("Flipped on X-Axis"), _("Paste the stored pose flipped on to current pose"));
1174         RNA_def_boolean(ot->srna, "selected_mask", 0, _("On Selected Only"), _("Only paste the stored pose on to selected bones in the current pose"));
1175 }
1176
1177 /* ********************************************** */
1178
1179
1180 static int pose_group_add_exec (bContext *C, wmOperator *UNUSED(op))
1181 {
1182         ScrArea *sa= CTX_wm_area(C);
1183         Object *ob;
1184         
1185         /* since this call may also be used from the buttons window, we need to check for where to get the object */
1186         if (sa->spacetype == SPACE_BUTS) 
1187                 ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1188         else
1189                 ob= ED_object_pose_armature(CTX_data_active_object(C));
1190                 
1191         /* only continue if there's an object */
1192         if (ob == NULL)
1193                 return OPERATOR_CANCELLED;
1194         
1195         /* for now, just call the API function for this */
1196         pose_add_group(ob);
1197         
1198         /* notifiers for updates */
1199         WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob);
1200         
1201         return OPERATOR_FINISHED;
1202 }
1203
1204 void POSE_OT_group_add (wmOperatorType *ot)
1205 {
1206         /* identifiers */
1207         ot->name= "Add Bone Group";
1208         ot->idname= "POSE_OT_group_add";
1209         ot->description= "Add a new bone group";
1210         
1211         /* api callbacks */
1212         ot->exec= pose_group_add_exec;
1213         ot->poll= ED_operator_posemode;
1214         
1215         /* flags */
1216         ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
1217 }
1218
1219
1220 static int pose_group_remove_exec (bContext *C, wmOperator *UNUSED(op))
1221 {
1222         ScrArea *sa= CTX_wm_area(C);
1223         Object *ob;
1224         
1225         /* since this call may also be used from the buttons window, we need to check for where to get the object */
1226         if (sa->spacetype == SPACE_BUTS) 
1227                 ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1228         else
1229                 ob= ED_object_pose_armature(CTX_data_active_object(C));
1230         
1231         /* only continue if there's an object */
1232         if (ob == NULL)
1233                 return OPERATOR_CANCELLED;
1234         
1235         /* for now, just call the API function for this */
1236         pose_remove_group(ob);
1237         
1238         /* notifiers for updates */
1239         WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob);
1240         
1241         return OPERATOR_FINISHED;
1242 }
1243
1244 void POSE_OT_group_remove (wmOperatorType *ot)
1245 {
1246         /* identifiers */
1247         ot->name= "Remove Bone Group";
1248         ot->idname= "POSE_OT_group_remove";
1249         ot->description= "Removes the active bone group";
1250         
1251         /* api callbacks */
1252         ot->exec= pose_group_remove_exec;
1253         ot->poll= ED_operator_posemode;
1254         
1255         /* flags */
1256         ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
1257 }
1258
1259 /* ------------ */
1260
1261 /* invoke callback which presents a list of bone-groups for the user to choose from */
1262 static int pose_groups_menu_invoke (bContext *C, wmOperator *op, wmEvent *UNUSED(evt))
1263 {
1264         ScrArea *sa= CTX_wm_area(C);
1265         Object *ob;
1266         bPose *pose;
1267         
1268         uiPopupMenu *pup;
1269         uiLayout *layout;
1270         bActionGroup *grp;
1271         int i;
1272         
1273         /* since this call may also be used from the buttons window, we need to check for where to get the object */
1274         if (sa->spacetype == SPACE_BUTS) 
1275                 ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1276         else
1277                 ob= ED_object_pose_armature(CTX_data_active_object(C));
1278         
1279         /* only continue if there's an object, and a pose there too */
1280         if (ELEM(NULL, ob, ob->pose)) 
1281                 return OPERATOR_CANCELLED;
1282         pose= ob->pose;
1283         
1284         /* if there's no active group (or active is invalid), create a new menu to find it */
1285         if (pose->active_group <= 0) {
1286                 /* create a new menu, and start populating it with group names */
1287                 pup= uiPupMenuBegin(C, op->type->name, ICON_NONE);
1288                 layout= uiPupMenuLayout(pup);
1289                 
1290                 /* special entry - allow to create new group, then use that 
1291                  *      (not to be used for removing though)
1292                  */
1293                 if (strstr(op->idname, "assign")) {
1294                         uiItemIntO(layout, "New Group", ICON_NONE, op->idname, "type", 0);
1295                         uiItemS(layout);
1296                 }
1297                 
1298                 /* add entries for each group */
1299                 for (grp= pose->agroups.first, i=1; grp; grp=grp->next, i++)
1300                         uiItemIntO(layout, grp->name, ICON_NONE, op->idname, "type", i);
1301                         
1302                 /* finish building the menu, and process it (should result in calling self again) */
1303                 uiPupMenuEnd(C, pup);
1304                 
1305                 return OPERATOR_CANCELLED;
1306         }
1307         else {
1308                 /* just use the active group index, and call the exec callback for the calling operator */
1309                 RNA_int_set(op->ptr, "type", pose->active_group);
1310                 return op->type->exec(C, op);
1311         }
1312 }
1313
1314 /* Assign selected pchans to the bone group that the user selects */
1315 static int pose_group_assign_exec (bContext *C, wmOperator *op)
1316 {
1317         ScrArea *sa= CTX_wm_area(C);
1318         Object *ob;
1319         bPose *pose;
1320         short done= 0;
1321         
1322         /* since this call may also be used from the buttons window, we need to check for where to get the object */
1323         if (sa->spacetype == SPACE_BUTS) 
1324                 ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1325         else
1326                 ob= ED_object_pose_armature(CTX_data_active_object(C));
1327         
1328         /* only continue if there's an object, and a pose there too */
1329         if (ELEM(NULL, ob, ob->pose))
1330                 return OPERATOR_CANCELLED;
1331
1332         pose= ob->pose;
1333         
1334         /* set the active group number to the one from operator props 
1335          *      - if 0 after this, make a new group...
1336          */
1337         pose->active_group= RNA_int_get(op->ptr, "type");
1338         if (pose->active_group == 0)
1339                 pose_add_group(ob);
1340         
1341         /* add selected bones to group then */
1342         CTX_DATA_BEGIN(C, bPoseChannel*, pchan, selected_pose_bones)
1343         {
1344                 pchan->agrp_index= pose->active_group;
1345                 done= 1;
1346         }
1347         CTX_DATA_END;
1348
1349         /* notifiers for updates */
1350         WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob);
1351         
1352         /* report done status */
1353         if (done)
1354                 return OPERATOR_FINISHED;
1355         else
1356                 return OPERATOR_CANCELLED;
1357 }
1358
1359 void POSE_OT_group_assign (wmOperatorType *ot)
1360 {
1361         /* identifiers */
1362         ot->name= "Add Selected to Bone Group";
1363         ot->idname= "POSE_OT_group_assign";
1364         ot->description= "Add selected bones to the chosen bone group";
1365         
1366         /* api callbacks */
1367         ot->invoke= pose_groups_menu_invoke;
1368         ot->exec= pose_group_assign_exec;
1369         ot->poll= ED_operator_posemode;
1370         
1371         /* flags */
1372         ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
1373         
1374         /* properties */
1375         RNA_def_int(ot->srna, "type", 0, 0, 10, _("Bone Group Index"), "", 0, INT_MAX);
1376 }
1377
1378
1379 static int pose_group_unassign_exec (bContext *C, wmOperator *UNUSED(op))
1380 {
1381         ScrArea *sa= CTX_wm_area(C);
1382         Object *ob;
1383         short done= 0;
1384         
1385         /* since this call may also be used from the buttons window, we need to check for where to get the object */
1386         if (sa->spacetype == SPACE_BUTS) 
1387                 ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1388         else
1389                 ob= ED_object_pose_armature(CTX_data_active_object(C));
1390         
1391         /* only continue if there's an object, and a pose there too */
1392         if (ELEM(NULL, ob, ob->pose))
1393                 return OPERATOR_CANCELLED;
1394         
1395         /* find selected bones to remove from all bone groups */
1396         CTX_DATA_BEGIN(C, bPoseChannel*, pchan, selected_pose_bones)
1397         {
1398                 if (pchan->agrp_index) {
1399                         pchan->agrp_index= 0;
1400                         done= 1;
1401                 }
1402         }
1403         CTX_DATA_END;
1404         
1405         /* notifiers for updates */
1406         WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob);
1407         
1408         /* report done status */
1409         if (done)
1410                 return OPERATOR_FINISHED;
1411         else
1412                 return OPERATOR_CANCELLED;
1413 }
1414
1415 void POSE_OT_group_unassign (wmOperatorType *ot)
1416 {
1417         /* identifiers */
1418         ot->name= "Remove Selected from Bone Groups";
1419         ot->idname= "POSE_OT_group_unassign";
1420         ot->description= "Remove selected bones from all bone groups";
1421         
1422         /* api callbacks */
1423         ot->exec= pose_group_unassign_exec;
1424         ot->poll= ED_operator_posemode;
1425         
1426         /* flags */
1427         ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
1428 }
1429
1430 static void pose_group_select(bContext *C, Object *ob, int select)
1431 {
1432         bPose *pose= ob->pose;
1433         
1434         CTX_DATA_BEGIN(C, bPoseChannel*, pchan, visible_pose_bones)
1435         {
1436                 if ((pchan->bone->flag & BONE_UNSELECTABLE)==0) {
1437                         if (select) {
1438                                 if (pchan->agrp_index == pose->active_group) 
1439                                         pchan->bone->flag |= BONE_SELECTED;
1440                         }
1441                         else {
1442                                 if (pchan->agrp_index == pose->active_group) 
1443                                         pchan->bone->flag &= ~BONE_SELECTED;
1444                         }
1445                 }
1446         }
1447         CTX_DATA_END;
1448 }
1449
1450 static int pose_group_select_exec (bContext *C, wmOperator *UNUSED(op))
1451 {
1452         ScrArea *sa= CTX_wm_area(C);
1453         Object *ob;
1454         
1455         /* since this call may also be used from the buttons window, we need to check for where to get the object */
1456         if (sa->spacetype == SPACE_BUTS) 
1457                 ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1458         else
1459                 ob= ED_object_pose_armature(CTX_data_active_object(C));
1460         
1461         /* only continue if there's an object, and a pose there too */
1462         if (ELEM(NULL, ob, ob->pose))
1463                 return OPERATOR_CANCELLED;
1464         
1465         pose_group_select(C, ob, 1);
1466         
1467         /* notifiers for updates */
1468         WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob);
1469         
1470         return OPERATOR_FINISHED;
1471 }
1472
1473 void POSE_OT_group_select (wmOperatorType *ot)
1474 {
1475         /* identifiers */
1476         ot->name= "Select Bones of Bone Group";
1477         ot->idname= "POSE_OT_group_select";
1478         ot->description= "Select bones in active Bone Group";
1479         
1480         /* api callbacks */
1481         ot->exec= pose_group_select_exec;
1482         ot->poll= ED_operator_posemode;
1483         
1484         /* flags */
1485         ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
1486 }
1487
1488 static int pose_group_deselect_exec (bContext *C, wmOperator *UNUSED(op))
1489 {
1490         ScrArea *sa= CTX_wm_area(C);
1491         Object *ob;
1492         
1493         /* since this call may also be used from the buttons window, we need to check for where to get the object */
1494         if (sa->spacetype == SPACE_BUTS) 
1495                 ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1496         else
1497                 ob= ED_object_pose_armature(CTX_data_active_object(C));
1498         
1499         /* only continue if there's an object, and a pose there too */
1500         if (ELEM(NULL, ob, ob->pose))
1501                 return OPERATOR_CANCELLED;
1502         
1503         pose_group_select(C, ob, 0);
1504         
1505         /* notifiers for updates */
1506         WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob);
1507         
1508         return OPERATOR_FINISHED;
1509 }
1510
1511 void POSE_OT_group_deselect (wmOperatorType *ot)
1512 {
1513         /* identifiers */
1514         ot->name= "Deselect Bone Group";
1515         ot->idname= "POSE_OT_group_deselect";
1516         ot->description= "Deselect bones of active Bone Group";
1517         
1518         /* api callbacks */
1519         ot->exec= pose_group_deselect_exec;
1520         ot->poll= ED_operator_posemode;
1521         
1522         /* flags */
1523         ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
1524 }
1525
1526 /* ********************************************** */
1527
1528 static int pose_flip_names_exec (bContext *C, wmOperator *UNUSED(op))
1529 {
1530         Object *ob= ED_object_pose_armature(CTX_data_active_object(C));
1531         bArmature *arm;
1532         
1533         /* paranoia checks */
1534         if (ELEM(NULL, ob, ob->pose)) 
1535                 return OPERATOR_CANCELLED;
1536         arm= ob->data;
1537         
1538         /* loop through selected bones, auto-naming them */
1539         CTX_DATA_BEGIN(C, bPoseChannel*, pchan, selected_pose_bones)
1540         {
1541                 char newname[32];
1542                 flip_side_name(newname, pchan->name, TRUE);
1543                 ED_armature_bone_rename(arm, pchan->name, newname);
1544         }
1545         CTX_DATA_END;
1546         
1547         /* since we renamed stuff... */
1548         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1549
1550         /* note, notifier might evolve */
1551         WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob);
1552         
1553         return OPERATOR_FINISHED;
1554 }
1555
1556 void POSE_OT_flip_names (wmOperatorType *ot)
1557 {
1558         /* identifiers */
1559         ot->name= "Flip Names";
1560         ot->idname= "POSE_OT_flip_names";
1561         ot->description= "Flips (and corrects) the axis suffixes of the the names of selected bones";
1562         
1563         /* api callbacks */
1564         ot->exec= pose_flip_names_exec;
1565         ot->poll= ED_operator_posemode;
1566         
1567         /* flags */
1568         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1569 }
1570
1571 /* ------------------ */
1572
1573 static int pose_autoside_names_exec (bContext *C, wmOperator *op)
1574 {
1575         Object *ob= ED_object_pose_armature(CTX_data_active_object(C));
1576         bArmature *arm;
1577         char newname[32];
1578         short axis= RNA_enum_get(op->ptr, "axis");
1579         
1580         /* paranoia checks */
1581         if (ELEM(NULL, ob, ob->pose)) 
1582                 return OPERATOR_CANCELLED;
1583         arm= ob->data;
1584         
1585         /* loop through selected bones, auto-naming them */
1586         CTX_DATA_BEGIN(C, bPoseChannel*, pchan, selected_pose_bones)
1587         {
1588                 BLI_strncpy(newname, pchan->name, sizeof(newname));
1589                 if(bone_autoside_name(newname, 1, axis, pchan->bone->head[axis], pchan->bone->tail[axis]))
1590                         ED_armature_bone_rename(arm, pchan->name, newname);
1591         }
1592         CTX_DATA_END;
1593         
1594         /* since we renamed stuff... */
1595         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1596
1597         /* note, notifier might evolve */
1598         WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob);
1599         
1600         return OPERATOR_FINISHED;
1601 }
1602
1603 void POSE_OT_autoside_names (wmOperatorType *ot)
1604 {
1605         static EnumPropertyItem axis_items[]= {
1606                 {0, "XAXIS", 0, "X-Axis", "Left/Right"},
1607                 {1, "YAXIS", 0, "Y-Axis", "Front/Back"},
1608                 {2, "ZAXIS", 0, "Z-Axis", "Top/Bottom"},
1609                 {0, NULL, 0, NULL, NULL}};
1610         
1611         /* identifiers */
1612         ot->name= "AutoName by Axis";
1613         ot->idname= "POSE_OT_autoside_names";
1614         ot->description= "Automatically renames the selected bones according to which side of the target axis they fall on";
1615         
1616         /* api callbacks */
1617         ot->invoke= WM_menu_invoke;
1618         ot->exec= pose_autoside_names_exec;
1619         ot->poll= ED_operator_posemode;
1620         
1621         /* flags */
1622         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1623         
1624         /* settings */
1625         ot->prop= RNA_def_enum(ot->srna, "axis", axis_items, 0, "Axis", "Axis tag names with.");
1626 }
1627
1628 /* ********************************************** */
1629
1630 /* Show all armature layers */
1631 static int pose_armature_layers_showall_poll (bContext *C)
1632 {
1633         /* this single operator can be used in posemode OR editmode for armatures */
1634         return ED_operator_posemode(C) || ED_operator_editarmature(C);
1635 }
1636
1637 static int pose_armature_layers_showall_exec (bContext *C, wmOperator *op)
1638 {
1639         Object *ob= ED_object_pose_armature(CTX_data_active_object(C));
1640         bArmature *arm = (ob)? ob->data : NULL;
1641         PointerRNA ptr;
1642         int maxLayers = (RNA_boolean_get(op->ptr, "all"))? 32 : 16;
1643         int layers[32] = {0}; /* hardcoded for now - we can only have 32 armature layers, so this should be fine... */
1644         int i;
1645         
1646         /* sanity checking */
1647         if (arm == NULL)
1648                 return OPERATOR_CANCELLED;
1649         
1650         /* use RNA to set the layers
1651          *      although it would be faster to just set directly using bitflags, we still
1652          *      need to setup a RNA pointer so that we get the "update" callbacks for free...
1653          */
1654         RNA_id_pointer_create(&arm->id, &ptr);
1655         
1656         for (i = 0; i < maxLayers; i++)
1657                 layers[i] = 1;
1658         
1659         RNA_boolean_set_array(&ptr, "layers", layers);
1660         
1661         /* note, notifier might evolve */
1662         WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob);
1663         
1664         /* done */
1665         return OPERATOR_FINISHED;
1666 }
1667
1668 void ARMATURE_OT_layers_show_all (wmOperatorType *ot)
1669 {
1670         /* identifiers */
1671         ot->name= "Show All Layers";
1672         ot->idname= "ARMATURE_OT_layers_show_all";
1673         ot->description= "Make all armature layers visible";
1674         
1675         /* callbacks */
1676         ot->exec= pose_armature_layers_showall_exec;
1677         ot->poll= pose_armature_layers_showall_poll;
1678         
1679         /* flags */
1680         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1681         
1682         /* properties */
1683         ot->prop = RNA_def_boolean(ot->srna, "all", 1, _("All Layers"), _("Enable all layers or just the first 16 (top row)"));
1684 }
1685
1686 /* ------------------- */
1687
1688 /* Present a popup to get the layers that should be used */
1689 static int pose_armature_layers_invoke (bContext *C, wmOperator *op, wmEvent *evt)
1690 {
1691         Object *ob= ED_object_pose_armature(CTX_data_active_object(C));
1692         bArmature *arm= (ob)? ob->data : NULL;
1693         PointerRNA ptr;
1694         int layers[32]; /* hardcoded for now - we can only have 32 armature layers, so this should be fine... */
1695         
1696         /* sanity checking */
1697         if (arm == NULL)
1698                 return OPERATOR_CANCELLED;
1699                 
1700         /* get RNA pointer to armature data to use that to retrieve the layers as ints to init the operator */
1701         RNA_id_pointer_create((ID *)arm, &ptr);
1702         RNA_boolean_get_array(&ptr, "layers", layers);
1703         RNA_boolean_set_array(op->ptr, "layers", layers);
1704         
1705         /* part to sync with other similar operators... */
1706         return WM_operator_props_popup(C, op, evt);
1707 }
1708
1709 /* Set the visible layers for the active armature (edit and pose modes) */
1710 static int pose_armature_layers_exec (bContext *C, wmOperator *op)
1711 {
1712         Object *ob= ED_object_pose_armature(CTX_data_active_object(C));
1713         PointerRNA ptr;
1714         int layers[32]; /* hardcoded for now - we can only have 32 armature layers, so this should be fine... */
1715
1716         if(ob==NULL || ob->data==NULL) {
1717                 return OPERATOR_CANCELLED;
1718         }
1719
1720         /* get the values set in the operator properties */
1721         RNA_boolean_get_array(op->ptr, "layers", layers);
1722
1723         /* get pointer for armature, and write data there... */
1724         RNA_id_pointer_create((ID *)ob->data, &ptr);
1725         RNA_boolean_set_array(&ptr, "layers", layers);
1726
1727         /* note, notifier might evolve */
1728         WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob);
1729
1730         return OPERATOR_FINISHED;
1731 }
1732
1733
1734 void POSE_OT_armature_layers (wmOperatorType *ot)
1735 {
1736         /* identifiers */
1737         ot->name= "Change Armature Layers";
1738         ot->idname= "POSE_OT_armature_layers";
1739         ot->description= "Change the visible armature layers";
1740         
1741         /* callbacks */
1742         ot->invoke= pose_armature_layers_invoke;
1743         ot->exec= pose_armature_layers_exec;
1744         ot->poll= ED_operator_posemode;
1745         
1746         /* flags */
1747         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1748         
1749         /* properties */
1750         RNA_def_boolean_layer_member(ot->srna, "layers", 32, NULL, "Layer", "Armature layers to make visible");
1751 }
1752
1753 void ARMATURE_OT_armature_layers (wmOperatorType *ot)
1754 {
1755         /* identifiers */
1756         ot->name= "Change Armature Layers";
1757         ot->idname= "ARMATURE_OT_armature_layers";
1758         ot->description= "Change the visible armature layers";
1759         
1760         /* callbacks */
1761         ot->invoke= pose_armature_layers_invoke;
1762         ot->exec= pose_armature_layers_exec;
1763         ot->poll= ED_operator_editarmature;
1764         
1765         /* flags */
1766         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1767         
1768         /* properties */
1769         RNA_def_boolean_layer_member(ot->srna, "layers", 32, NULL, "Layer", "Armature layers to make visible");
1770 }
1771
1772 /* ------------------- */
1773
1774 /* Present a popup to get the layers that should be used */
1775 static int pose_bone_layers_invoke (bContext *C, wmOperator *op, wmEvent *evt)
1776 {
1777         int layers[32]= {0}; /* hardcoded for now - we can only have 32 armature layers, so this should be fine... */
1778         
1779         /* get layers that are active already */        
1780         CTX_DATA_BEGIN(C, bPoseChannel *, pchan, selected_pose_bones) 
1781         {
1782                 short bit;
1783                 
1784                 /* loop over the bits for this pchan's layers, adding layers where they're needed */
1785                 for (bit= 0; bit < 32; bit++) {
1786                         if (pchan->bone->layer & (1<<bit))
1787                                 layers[bit]= 1;
1788                 }
1789         }
1790         CTX_DATA_END;
1791         
1792         /* copy layers to operator */
1793         RNA_boolean_set_array(op->ptr, "layers", layers);
1794         
1795                 /* part to sync with other similar operators... */
1796         return WM_operator_props_popup(C, op, evt);
1797 }
1798
1799 /* Set the visible layers for the active armature (edit and pose modes) */
1800 static int pose_bone_layers_exec (bContext *C, wmOperator *op)
1801 {
1802         Object *ob= ED_object_pose_armature(CTX_data_active_object(C));
1803         PointerRNA ptr;
1804         int layers[32]; /* hardcoded for now - we can only have 32 armature layers, so this should be fine... */
1805
1806         if(ob==NULL || ob->data==NULL) {
1807                 return OPERATOR_CANCELLED;
1808         }
1809
1810         /* get the values set in the operator properties */
1811         RNA_boolean_get_array(op->ptr, "layers", layers);
1812
1813         /* set layers of pchans based on the values set in the operator props */
1814         CTX_DATA_BEGIN(C, bPoseChannel *, pchan, selected_pose_bones)
1815         {
1816                 /* get pointer for pchan, and write flags this way */
1817                 RNA_pointer_create((ID *)ob->data, &RNA_Bone, pchan->bone, &ptr);
1818                 RNA_boolean_set_array(&ptr, "layers", layers);
1819         }
1820         CTX_DATA_END;
1821
1822         /* note, notifier might evolve */
1823         WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob);
1824
1825         return OPERATOR_FINISHED;
1826 }
1827
1828 void POSE_OT_bone_layers (wmOperatorType *ot)
1829 {
1830         /* identifiers */
1831         ot->name= "Change Bone Layers";
1832         ot->idname= "POSE_OT_bone_layers";
1833         ot->description= "Change the layers that the selected bones belong to";
1834         
1835         /* callbacks */
1836         ot->invoke= pose_bone_layers_invoke;
1837         ot->exec= pose_bone_layers_exec;
1838         ot->poll= ED_operator_posemode;
1839         
1840         /* flags */
1841         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1842         
1843         /* properties */
1844         RNA_def_boolean_layer_member(ot->srna, "layers", 32, NULL, "Layer", "Armature layers that bone belongs to");
1845 }
1846
1847 /* ------------------- */
1848
1849 /* Present a popup to get the layers that should be used */
1850 static int armature_bone_layers_invoke (bContext *C, wmOperator *op, wmEvent *evt)
1851 {
1852         int layers[32]= {0}; /* hardcoded for now - we can only have 32 armature layers, so this should be fine... */
1853         
1854         /* get layers that are active already */
1855         CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones) 
1856         {
1857                 short bit;
1858                 
1859                 /* loop over the bits for this pchan's layers, adding layers where they're needed */
1860                 for (bit= 0; bit < 32; bit++) {
1861                         if (ebone->layer & (1<<bit))
1862                                 layers[bit]= 1;
1863                 }
1864         }
1865         CTX_DATA_END;
1866         
1867         /* copy layers to operator */
1868         RNA_boolean_set_array(op->ptr, "layers", layers);
1869         
1870                 /* part to sync with other similar operators... */
1871         return WM_operator_props_popup(C, op, evt);
1872 }
1873
1874 /* Set the visible layers for the active armature (edit and pose modes) */
1875 static int armature_bone_layers_exec (bContext *C, wmOperator *op)
1876 {
1877         Object *ob= CTX_data_edit_object(C);
1878         bArmature *arm= (ob)? ob->data : NULL;
1879         PointerRNA ptr;
1880         int layers[32]; /* hardcoded for now - we can only have 32 armature layers, so this should be fine... */
1881         
1882         /* get the values set in the operator properties */
1883         RNA_boolean_get_array(op->ptr, "layers", layers);
1884         
1885         /* set layers of pchans based on the values set in the operator props */
1886         CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones) 
1887         {
1888                 /* get pointer for pchan, and write flags this way */
1889                 RNA_pointer_create((ID *)arm, &RNA_EditBone, ebone, &ptr);
1890                 RNA_boolean_set_array(&ptr, "layers", layers);
1891         }
1892         CTX_DATA_END;
1893         
1894         /* note, notifier might evolve */
1895         WM_event_add_notifier(C, NC_OBJECT|ND_POSE, ob);
1896         
1897         return OPERATOR_FINISHED;
1898 }
1899
1900 void ARMATURE_OT_bone_layers (wmOperatorType *ot)
1901 {
1902         /* identifiers */
1903         ot->name= "Change Bone Layers";
1904         ot->idname= "ARMATURE_OT_bone_layers";
1905         ot->description= "Change the layers that the selected bones belong to";
1906         
1907         /* callbacks */
1908         ot->invoke= armature_bone_layers_invoke;
1909         ot->exec= armature_bone_layers_exec;
1910         ot->poll= ED_operator_editarmature;
1911         
1912         /* flags */
1913         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1914         
1915         /* properties */
1916         RNA_def_boolean_layer_member(ot->srna, "layers", 32, NULL, "Layer", "Armature layers that bone belongs to");
1917 }
1918
1919 /* ********************************************** */
1920
1921 static int pose_flip_quats_exec (bContext *C, wmOperator *UNUSED(op))
1922 {
1923         Scene *scene= CTX_data_scene(C);
1924         Object *ob= ED_object_pose_armature(CTX_data_active_object(C));
1925         KeyingSet *ks = ANIM_builtin_keyingset_get_named(NULL, "LocRotScale");
1926         
1927         /* loop through all selected pchans, flipping and keying (as needed) */
1928         CTX_DATA_BEGIN(C, bPoseChannel*, pchan, selected_pose_bones)
1929         {
1930                 /* only if bone is using quaternion rotation */
1931                 if (pchan->rotmode == ROT_MODE_QUAT) {
1932                         /* quaternions have 720 degree range */
1933                         negate_v4(pchan->quat);
1934
1935                         /* tagging */
1936                         if (autokeyframe_cfra_can_key(scene, &ob->id)) {
1937                                 ListBase dsources = {NULL, NULL};
1938                                 
1939                                 /* now insert the keyframe(s) using the Keying Set
1940                                  *      1) add datasource override for the PoseChannel
1941                                  *      2) insert keyframes
1942                                  *      3) free the extra info 
1943                                  */
1944                                 ANIM_relative_keyingset_add_source(&dsources, &ob->id, &RNA_PoseBone, pchan); 
1945                                 ANIM_apply_keyingset(C, &dsources, NULL, ks, MODIFYKEY_MODE_INSERT, (float)CFRA);
1946                                 BLI_freelistN(&dsources);
1947                                 
1948                                 /* clear any unkeyed tags */
1949                                 if (pchan->bone)
1950                                         pchan->bone->flag &= ~BONE_UNKEYED;
1951                         }
1952                         else {
1953                                 /* add unkeyed tags */
1954                                 if (pchan->bone)
1955                                         pchan->bone->flag |= BONE_UNKEYED;
1956                         }
1957                 }
1958         }
1959         CTX_DATA_END;
1960         
1961         /* notifiers and updates */
1962         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
1963         WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, ob);
1964         
1965         return OPERATOR_FINISHED;
1966 }
1967
1968 void POSE_OT_quaternions_flip (wmOperatorType *ot)
1969 {
1970         /* identifiers */
1971         ot->name = "Flip Quats";
1972         ot->idname= "POSE_OT_quaternions_flip";
1973         ot->description= "Flip quaternion values to achieve desired rotations, while maintaining the same orientations";
1974         
1975         /* callbacks */
1976         ot->exec= pose_flip_quats_exec;
1977         ot->poll= ED_operator_posemode;
1978         
1979         /* flags */
1980         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1981 }
1982
1983 /* ********************************************** */
1984
1985 /* context: active channel */
1986 #if 0
1987 void pose_special_editmenu(Scene *scene)
1988 {
1989         Object *obedit= scene->obedit; // XXX context
1990         Object *ob= OBACT;
1991         short nr;
1992         
1993         /* paranoia checks */
1994         if(!ob && !ob->pose) return;
1995         if(ob==obedit || (ob->mode & OB_MODE_POSE)==0) return;
1996         
1997         nr= pupmenu("Specials%t|Select Constraint Target%x1|Flip Left-Right Names%x2|Calculate Paths%x3|Clear Paths%x4|Clear User Transform %x5|Relax Pose %x6|%l|AutoName Left-Right%x7|AutoName Front-Back%x8|AutoName Top-Bottom%x9");
1998         if(nr==1) {
1999                 pose_select_constraint_target(scene);
2000         }
2001         else if(nr==2) {
2002                 pose_flip_names();
2003         }
2004         else if(nr==3) {
2005                 pose_calculate_path(C, ob);
2006         }
2007         else if(nr==4) {
2008                 pose_clear_paths(ob);
2009         }
2010         else if(nr==5) {
2011                 pose_clear_user_transforms(ob);
2012         }
2013         else if(nr==6) {
2014                 pose_relax();
2015         }
2016         else if(ELEM3(nr, 7, 8, 9)) {
2017                 pose_autoside_names(nr-7);
2018         }
2019 }
2020
2021
2022 /* Restore selected pose-bones to 'action'-defined pose */
2023 static void pose_clear_user_transforms(Object *ob)
2024 {
2025         bArmature *arm= ob->data;
2026         bPoseChannel *pchan;
2027         
2028         if (ob->pose == NULL)
2029                 return;
2030         
2031         /* if the object has an action, restore pose to the pose defined by the action by clearing pose on selected bones */
2032         if (ob->action) {
2033                 /* find selected bones */
2034                 for (pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
2035                         if (pchan->bone && (pchan->bone->flag & BONE_SELECTED) && (pchan->bone->layer & arm->layer)) {
2036                                 /* just clear the BONE_UNKEYED flag, allowing this bone to get overwritten by actions again */
2037                                 pchan->bone->flag &= ~BONE_UNKEYED;
2038                         }
2039                 }
2040                 
2041                 /* clear pose locking flag 
2042                  *      - this will only clear the user-defined pose in the selected bones, where BONE_UNKEYED has been cleared
2043                  */
2044                 ob->pose->flag |= POSE_DO_UNLOCK;
2045         }
2046         else {
2047                 /* no action, so restore entire pose to rest pose (cannot restore only selected bones) */
2048                 rest_pose(ob->pose);
2049         }
2050         
2051         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
2052         BIF_undo_push("Clear User Transform");
2053 }
2054
2055 #endif