fdc58f6e2536cbb94eda45747ba01419e36e661d
[blender.git] / source / blender / editors / armature / pose_select.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * Contributor(s): Blender Foundation, 2002-2009 full recode.
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  */
25
26 /** \file blender/editors/armature/pose_select.c
27  *  \ingroup edarmature
28  */
29
30 #include <string.h>
31
32 #include "DNA_anim_types.h"
33 #include "DNA_armature_types.h"
34 #include "DNA_constraint_types.h"
35 #include "DNA_object_types.h"
36 #include "DNA_scene_types.h"
37
38 #include "MEM_guardedalloc.h"
39
40 #include "BLI_blenlib.h"
41
42 #include "BKE_action.h"
43 #include "BKE_armature.h"
44 #include "BKE_constraint.h"
45 #include "BKE_context.h"
46 #include "BKE_depsgraph.h"
47 #include "BKE_object.h"
48 #include "BKE_report.h"
49
50 #include "RNA_access.h"
51 #include "RNA_define.h"
52
53 #include "WM_api.h"
54 #include "WM_types.h"
55
56 #include "ED_armature.h"
57 #include "ED_keyframing.h"
58 #include "ED_mesh.h"
59 #include "ED_object.h"
60 #include "ED_screen.h"
61 #include "ED_view3d.h"
62
63 #include "armature_intern.h"
64
65 /* utility macros for storing a temp int in the bone (selection flag) */
66 #define PBONE_PREV_FLAG_GET(pchan) ((void)0, (GET_INT_FROM_POINTER((pchan)->temp)))
67 #define PBONE_PREV_FLAG_SET(pchan, val) ((pchan)->temp = SET_INT_IN_POINTER(val))
68
69
70 /* ***************** Pose Select Utilities ********************* */
71
72 /* Note: SEL_TOGGLE is assumed to have already been handled! */
73 static void pose_do_bone_select(bPoseChannel *pchan, const int select_mode)
74 {
75         /* select pchan only if selectable, but deselect works always */
76         switch (select_mode) {
77                 case SEL_SELECT:
78                         if (!(pchan->bone->flag & BONE_UNSELECTABLE))
79                                 pchan->bone->flag |= BONE_SELECTED;
80                         break;
81                 case SEL_DESELECT:
82                         pchan->bone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
83                         break;
84                 case SEL_INVERT:
85                         if (pchan->bone->flag & BONE_SELECTED) {
86                                 pchan->bone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
87                         }
88                         else if (!(pchan->bone->flag & BONE_UNSELECTABLE)) {
89                                 pchan->bone->flag |= BONE_SELECTED;
90                         }
91                         break;
92         }
93 }
94
95 /* Utility method for changing the selection status of a bone */
96 void ED_pose_bone_select(Object *ob, bPoseChannel *pchan, bool select)
97 {
98         bArmature *arm;
99
100         /* sanity checks */
101         // XXX: actually, we can probably still get away with no object - at most we have no updates
102         if (ELEM(NULL, ob, ob->pose, pchan, pchan->bone))
103                 return;
104         
105         arm = ob->data;
106         
107         /* can only change selection state if bone can be modified */
108         if (PBONE_SELECTABLE(arm, pchan->bone)) {
109                 /* change selection state - activate too if selected */
110                 if (select) {
111                         pchan->bone->flag |= BONE_SELECTED;
112                         arm->act_bone = pchan->bone;
113                 }
114                 else {
115                         pchan->bone->flag &= ~BONE_SELECTED;
116                         arm->act_bone = NULL;
117                 }
118                 
119                 // TODO: select and activate corresponding vgroup?
120                 
121                 /* tag necessary depsgraph updates 
122                  * (see rna_Bone_select_update() in rna_armature.c for details)
123                  */
124                 if (arm->flag & ARM_HAS_VIZ_DEPS) {
125                         DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
126                 }
127                 
128                 /* send necessary notifiers */
129                 WM_main_add_notifier(NC_GEOM | ND_DATA, ob);
130         }
131 }
132
133 /* called from editview.c, for mode-less pose selection */
134 /* assumes scene obact and basact is still on old situation */
135 bool ED_do_pose_selectbuffer(
136         Scene *scene, SceneLayer *sl, Base *base, const unsigned int *buffer, short hits,
137         bool extend, bool deselect, bool toggle, bool do_nearest)
138 {
139         Object *ob = base->object;
140         Bone *nearBone;
141         
142         if (!ob || !ob->pose) return 0;
143
144         nearBone = get_bone_from_selectbuffer(scene, base, buffer, hits, 1, do_nearest);
145         
146         /* if the bone cannot be affected, don't do anything */
147         if ((nearBone) && !(nearBone->flag & BONE_UNSELECTABLE)) {
148                 Object *ob_act = OBACT_NEW;
149                 bArmature *arm = ob->data;
150                 
151                 /* since we do unified select, we don't shift+select a bone if the
152                  * armature object was not active yet.
153                  * note, special exception for armature mode so we can do multi-select
154                  * we could check for multi-select explicitly but think its fine to
155                  * always give predictable behavior in weight paint mode - campbell */
156                 if ((ob_act == NULL) || ((ob_act != ob) && (ob_act->mode & OB_MODE_WEIGHT_PAINT) == 0)) {
157                         /* when we are entering into posemode via toggle-select,
158                          * frop another active object - always select the bone. */
159                         if (!extend && !deselect && toggle) {
160                                 /* re-select below */
161                                 nearBone->flag &= ~BONE_SELECTED;
162                         }
163                 }
164
165                 if (!extend && !deselect && !toggle) {
166                         ED_pose_de_selectall(ob, SEL_DESELECT, true);
167                         nearBone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
168                         arm->act_bone = nearBone;
169                 }
170                 else {
171                         if (extend) {
172                                 nearBone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
173                                 arm->act_bone = nearBone;
174                         }
175                         else if (deselect) {
176                                 nearBone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
177                         }
178                         else if (toggle) {
179                                 if (nearBone->flag & BONE_SELECTED) {
180                                         /* if not active, we make it active */
181                                         if (nearBone != arm->act_bone) {
182                                                 arm->act_bone = nearBone;
183                                         }
184                                         else {
185                                                 nearBone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
186                                         }
187                                 }
188                                 else {
189                                         nearBone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
190                                         arm->act_bone = nearBone;
191                                 }
192                         }
193                 }
194                 
195                 if (ob_act) {
196                         /* in weightpaint we select the associated vertex group too */
197                         if (ob_act->mode & OB_MODE_WEIGHT_PAINT) {
198                                 if (nearBone == arm->act_bone) {
199                                         ED_vgroup_select_by_name(ob_act, nearBone->name);
200                                         DAG_id_tag_update(&ob_act->id, OB_RECALC_DATA);
201                                 }
202                         }
203                         /* if there are some dependencies for visualizing armature state 
204                          * (e.g. Mask Modifier in 'Armature' mode), force update 
205                          */
206                         else if (arm->flag & ARM_HAS_VIZ_DEPS) {
207                                 /* NOTE: ob not ob_act here is intentional - it's the source of the 
208                                  *       bones being selected  [T37247]
209                                  */
210                                 DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
211                         }
212                 }
213         }
214         
215         return nearBone != NULL;
216 }
217
218 /* 'select_mode' is usual SEL_SELECT/SEL_DESELECT/SEL_TOGGLE/SEL_INVERT.
219  * When true, 'ignore_visibility' makes this func also affect invisible bones (hidden or on hidden layers). */
220 void ED_pose_de_selectall(Object *ob, int select_mode, const bool ignore_visibility)
221 {
222         bArmature *arm = ob->data;
223         bPoseChannel *pchan;
224         
225         /* we call this from outliner too */
226         if (ob->pose == NULL) {
227                 return;
228         }
229         
230         /*      Determine if we're selecting or deselecting     */
231         if (select_mode == SEL_TOGGLE) {
232                 select_mode = SEL_SELECT;
233                 for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
234                         if (ignore_visibility || PBONE_VISIBLE(arm, pchan->bone)) {
235                                 if (pchan->bone->flag & BONE_SELECTED) {
236                                         select_mode = SEL_DESELECT;
237                                         break;
238                                 }
239                         }
240                 }
241         }
242         
243         /* Set the flags accordingly */
244         for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
245                 /* ignore the pchan if it isn't visible or if its selection cannot be changed */
246                 if (ignore_visibility || PBONE_VISIBLE(arm, pchan->bone)) {
247                         pose_do_bone_select(pchan, select_mode);
248                 }
249         }
250 }
251
252 /* ***************** Selections ********************** */
253
254 static void selectconnected_posebonechildren(Object *ob, Bone *bone, int extend)
255 {
256         Bone *curBone;
257         
258         /* stop when unconnected child is encountered, or when unselectable bone is encountered */
259         if (!(bone->flag & BONE_CONNECTED) || (bone->flag & BONE_UNSELECTABLE))
260                 return;
261         
262         /* XXX old cruft! use notifiers instead */
263         //select_actionchannel_by_name (ob->action, bone->name, !(shift));
264         
265         if (extend)
266                 bone->flag &= ~BONE_SELECTED;
267         else
268                 bone->flag |= BONE_SELECTED;
269         
270         for (curBone = bone->childbase.first; curBone; curBone = curBone->next)
271                 selectconnected_posebonechildren(ob, curBone, extend);
272 }
273
274 /* within active object context */
275 /* previously known as "selectconnected_posearmature" */
276 static int pose_select_connected_invoke(bContext *C, wmOperator *op, const wmEvent *event)
277 {
278         Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
279         bArmature *arm = (bArmature *)ob->data;
280         Bone *bone, *curBone, *next = NULL;
281         const bool extend = RNA_boolean_get(op->ptr, "extend");
282
283         view3d_operator_needs_opengl(C);
284
285         bone = get_nearest_bone(C, event->mval, !extend);
286
287         if (!bone)
288                 return OPERATOR_CANCELLED;
289         
290         /* Select parents */
291         for (curBone = bone; curBone; curBone = next) {
292                 /* ignore bone if cannot be selected */
293                 if ((curBone->flag & BONE_UNSELECTABLE) == 0) {
294                         if (extend)
295                                 curBone->flag &= ~BONE_SELECTED;
296                         else
297                                 curBone->flag |= BONE_SELECTED;
298                         
299                         if (curBone->flag & BONE_CONNECTED)
300                                 next = curBone->parent;
301                         else
302                                 next = NULL;
303                 }
304                 else
305                         next = NULL;
306         }
307         
308         /* Select children */
309         for (curBone = bone->childbase.first; curBone; curBone = next)
310                 selectconnected_posebonechildren(ob, curBone, extend);
311         
312         /* updates */
313         WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
314         
315         if (arm->flag & ARM_HAS_VIZ_DEPS) {
316                 /* mask modifier ('armature' mode), etc. */
317                 DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
318         }
319
320         return OPERATOR_FINISHED;
321 }
322
323 static int pose_select_linked_poll(bContext *C)
324 {
325         return (ED_operator_view3d_active(C) && ED_operator_posemode(C));
326 }
327
328 void POSE_OT_select_linked(wmOperatorType *ot)
329 {
330         /* identifiers */
331         ot->name = "Select Connected";
332         ot->idname = "POSE_OT_select_linked";
333         ot->description = "Select bones related to selected ones by parent/child relationships";
334         
335         /* api callbacks */
336         /* leave 'exec' unset */
337         ot->invoke = pose_select_connected_invoke;
338         ot->poll = pose_select_linked_poll;
339         
340         /* flags */
341         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
342         
343         /* props */
344         RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend selection instead of deselecting everything first");
345 }
346
347 /* -------------------------------------- */
348
349 static int pose_de_select_all_exec(bContext *C, wmOperator *op)
350 {
351         int action = RNA_enum_get(op->ptr, "action");
352         
353         Scene *scene = CTX_data_scene(C);
354         Object *ob = ED_object_context(C);
355         bArmature *arm = ob->data;
356         int multipaint = scene->toolsettings->multipaint;
357
358         if (action == SEL_TOGGLE) {
359                 action = CTX_DATA_COUNT(C, selected_pose_bones) ? SEL_DESELECT : SEL_SELECT;
360         }
361         
362         /*      Set the flags */
363         CTX_DATA_BEGIN(C, bPoseChannel *, pchan, visible_pose_bones)
364         {
365                 pose_do_bone_select(pchan, action);
366         }
367         CTX_DATA_END;
368
369         WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, NULL);
370         
371         /* weightpaint or mask modifiers need depsgraph updates */
372         if (multipaint || (arm->flag & ARM_HAS_VIZ_DEPS)) {
373                 DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
374         }
375
376         return OPERATOR_FINISHED;
377 }
378
379 void POSE_OT_select_all(wmOperatorType *ot)
380 {
381         /* identifiers */
382         ot->name = "(De)select All";
383         ot->idname = "POSE_OT_select_all";
384         ot->description = "Toggle selection status of all bones";
385         
386         /* api callbacks */
387         ot->exec = pose_de_select_all_exec;
388         ot->poll = ED_operator_posemode;
389         
390         /* flags */
391         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
392         
393         WM_operator_properties_select_all(ot);
394 }
395
396 /* -------------------------------------- */
397
398 static int pose_select_parent_exec(bContext *C, wmOperator *UNUSED(op))
399 {
400         Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
401         bArmature *arm = (bArmature *)ob->data;
402         bPoseChannel *pchan, *parent;
403
404         /* Determine if there is an active bone */
405         pchan = CTX_data_active_pose_bone(C);
406         if (pchan) {
407                 parent = pchan->parent;
408                 if ((parent) && !(parent->bone->flag & (BONE_HIDDEN_P | BONE_UNSELECTABLE))) {
409                         parent->bone->flag |= BONE_SELECTED;
410                         arm->act_bone = parent->bone;
411                 }
412                 else {
413                         return OPERATOR_CANCELLED;
414                 }
415         }
416         else {
417                 return OPERATOR_CANCELLED;
418         }
419         
420         /* updates */
421         WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
422         
423         if (arm->flag & ARM_HAS_VIZ_DEPS) {
424                 /* mask modifier ('armature' mode), etc. */
425                 DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
426         }
427         
428         return OPERATOR_FINISHED;
429 }
430
431 void POSE_OT_select_parent(wmOperatorType *ot)
432 {
433         /* identifiers */
434         ot->name = "Select Parent Bone";
435         ot->idname = "POSE_OT_select_parent";
436         ot->description = "Select bones that are parents of the currently selected bones";
437
438         /* api callbacks */
439         ot->exec = pose_select_parent_exec;
440         ot->poll = ED_operator_posemode;
441
442         /* flags */
443         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
444 }
445
446 /* -------------------------------------- */
447
448 static int pose_select_constraint_target_exec(bContext *C, wmOperator *UNUSED(op))
449 {
450         Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
451         bArmature *arm = (bArmature *)ob->data;
452         bConstraint *con;
453         int found = 0;
454         
455         CTX_DATA_BEGIN (C, bPoseChannel *, pchan, visible_pose_bones)
456         {
457                 if (pchan->bone->flag & BONE_SELECTED) {
458                         for (con = pchan->constraints.first; con; con = con->next) {
459                                 const bConstraintTypeInfo *cti = BKE_constraint_typeinfo_get(con);
460                                 ListBase targets = {NULL, NULL};
461                                 bConstraintTarget *ct;
462                                 
463                                 if (cti && cti->get_constraint_targets) {
464                                         cti->get_constraint_targets(con, &targets);
465                                         
466                                         for (ct = targets.first; ct; ct = ct->next) {
467                                                 if ((ct->tar == ob) && (ct->subtarget[0])) {
468                                                         bPoseChannel *pchanc = BKE_pose_channel_find_name(ob->pose, ct->subtarget);
469                                                         if ((pchanc) && !(pchanc->bone->flag & BONE_UNSELECTABLE)) {
470                                                                 pchanc->bone->flag |= BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL;
471                                                                 found = 1;
472                                                         }
473                                                 }
474                                         }
475                                         
476                                         if (cti->flush_constraint_targets)
477                                                 cti->flush_constraint_targets(con, &targets, 1);
478                                 }
479                         }
480                 }
481         }
482         CTX_DATA_END;
483         
484         if (!found)
485                 return OPERATOR_CANCELLED;
486         
487         /* updates */
488         WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
489         
490         if (arm->flag & ARM_HAS_VIZ_DEPS) {
491                 /* mask modifier ('armature' mode), etc. */
492                 DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
493         }
494         
495         return OPERATOR_FINISHED;
496 }
497
498 void POSE_OT_select_constraint_target(wmOperatorType *ot)
499 {
500         /* identifiers */
501         ot->name = "Select Constraint Target";
502         ot->idname = "POSE_OT_select_constraint_target";
503         ot->description = "Select bones used as targets for the currently selected bones";
504         
505         /* api callbacks */
506         ot->exec = pose_select_constraint_target_exec;
507         ot->poll = ED_operator_posemode;
508         
509         /* flags */
510         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
511 }
512
513 /* -------------------------------------- */
514
515 static int pose_select_hierarchy_exec(bContext *C, wmOperator *op)
516 {
517         Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
518         bArmature *arm = ob->data;
519         bPoseChannel *pchan_act;
520         int direction = RNA_enum_get(op->ptr, "direction");
521         const bool add_to_sel = RNA_boolean_get(op->ptr, "extend");
522         bool changed = false;
523         
524         pchan_act = BKE_pose_channel_active(ob);
525         if (pchan_act == NULL) {
526                 return OPERATOR_CANCELLED;
527         }
528
529         if (direction == BONE_SELECT_PARENT) {
530                 if (pchan_act->parent) {
531                         Bone *bone_parent;
532                         bone_parent = pchan_act->parent->bone;
533
534                         if (PBONE_SELECTABLE(arm, bone_parent)) {
535                                 if (!add_to_sel) {
536                                         pchan_act->bone->flag &= ~BONE_SELECTED;
537                                 }
538                                 bone_parent->flag |= BONE_SELECTED;
539                                 arm->act_bone = bone_parent;
540
541                                 changed = true;
542                         }
543                 }
544         }
545         else { /* direction == BONE_SELECT_CHILD */
546                 bPoseChannel *pchan_iter;
547                 Bone *bone_child = NULL;
548                 int pass;
549
550                 /* first pass, only connected bones (the logical direct child) */
551                 for (pass = 0; pass < 2 && (bone_child == NULL); pass++) {
552                         for (pchan_iter = ob->pose->chanbase.first; pchan_iter; pchan_iter = pchan_iter->next) {
553                                 /* possible we have multiple children, some invisible */
554                                 if (PBONE_SELECTABLE(arm, pchan_iter->bone)) {
555                                         if (pchan_iter->parent == pchan_act) {
556                                                 if ((pass == 1) || (pchan_iter->bone->flag & BONE_CONNECTED)) {
557                                                         bone_child = pchan_iter->bone;
558                                                         break;
559                                                 }
560                                         }
561                                 }
562                         }
563                 }
564
565                 if (bone_child) {
566                         arm->act_bone = bone_child;
567
568                         if (!add_to_sel) {
569                                 pchan_act->bone->flag &= ~BONE_SELECTED;
570                         }
571                         bone_child->flag |= BONE_SELECTED;
572
573                         changed = true;
574                 }
575         }
576
577         if (changed == false) {
578                 return OPERATOR_CANCELLED;
579         }
580         
581         /* updates */
582         WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
583         
584         if (arm->flag & ARM_HAS_VIZ_DEPS) {
585                 /* mask modifier ('armature' mode), etc. */
586                 DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
587         }
588         
589         return OPERATOR_FINISHED;
590 }
591
592 void POSE_OT_select_hierarchy(wmOperatorType *ot)
593 {
594         static EnumPropertyItem direction_items[] = {
595                 {BONE_SELECT_PARENT, "PARENT", 0, "Select Parent", ""},
596                 {BONE_SELECT_CHILD, "CHILD", 0, "Select Child", ""},
597                 {0, NULL, 0, NULL, NULL}
598         };
599         
600         /* identifiers */
601         ot->name = "Select Hierarchy";
602         ot->idname = "POSE_OT_select_hierarchy";
603         ot->description = "Select immediate parent/children of selected bones";
604         
605         /* api callbacks */
606         ot->exec = pose_select_hierarchy_exec;
607         ot->poll = ED_operator_posemode;
608         
609         /* flags */
610         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
611         
612         /* props */
613         ot->prop = RNA_def_enum(ot->srna, "direction", direction_items, BONE_SELECT_PARENT, "Direction", "");
614         RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
615 }
616
617 /* -------------------------------------- */
618
619 /* modes for select same */
620 typedef enum ePose_SelectSame_Mode {
621         POSE_SEL_SAME_LAYER      = 0,
622         POSE_SEL_SAME_GROUP      = 1,
623         POSE_SEL_SAME_KEYINGSET  = 2,
624 } ePose_SelectSame_Mode;
625
626 static bool pose_select_same_group(bContext *C, Object *ob, bool extend)
627 {
628         bArmature *arm = (ob) ? ob->data : NULL;
629         bPose *pose = (ob) ? ob->pose : NULL;
630         char *group_flags;
631         int numGroups = 0;
632         bool changed = false, tagged = false;
633         
634         /* sanity checks */
635         if (ELEM(NULL, ob, pose, arm))
636                 return 0;
637                 
638         /* count the number of groups */
639         numGroups = BLI_listbase_count(&pose->agroups);
640         if (numGroups == 0)
641                 return 0;
642                 
643         /* alloc a small array to keep track of the groups to use 
644          *  - each cell stores on/off state for whether group should be used
645          *      - size is (numGroups + 1), since (index = 0) is used for no-group
646          */
647         group_flags = MEM_callocN(numGroups + 1, "pose_select_same_group");
648         
649         CTX_DATA_BEGIN (C, bPoseChannel *, pchan, visible_pose_bones)
650         {
651                 /* keep track of group as group to use later? */
652                 if (pchan->bone->flag & BONE_SELECTED) {
653                         group_flags[pchan->agrp_index] = 1;
654                         tagged = true;
655                 }
656                 
657                 /* deselect all bones before selecting new ones? */
658                 if ((extend == false) && (pchan->bone->flag & BONE_UNSELECTABLE) == 0)
659                         pchan->bone->flag &= ~BONE_SELECTED;
660         }
661         CTX_DATA_END;
662         
663         /* small optimization: only loop through bones a second time if there are any groups tagged */
664         if (tagged) {
665                 /* only if group matches (and is not selected or current bone) */
666                 CTX_DATA_BEGIN (C, bPoseChannel *, pchan, visible_pose_bones)
667                 {
668                         if ((pchan->bone->flag & BONE_UNSELECTABLE) == 0) {
669                                 /* check if the group used by this bone is counted */
670                                 if (group_flags[pchan->agrp_index]) {
671                                         pchan->bone->flag |= BONE_SELECTED;
672                                         changed = true;
673                                 }
674                         }
675                 }
676                 CTX_DATA_END;
677         }
678         
679         /* free temp info */
680         MEM_freeN(group_flags);
681         
682         return changed;
683 }
684
685 static bool pose_select_same_layer(bContext *C, Object *ob, bool extend)
686 {
687         bPose *pose = (ob) ? ob->pose : NULL;
688         bArmature *arm = (ob) ? ob->data : NULL;
689         bool changed = false;
690         int layers = 0;
691         
692         if (ELEM(NULL, ob, pose, arm))
693                 return 0;
694         
695         /* figure out what bones are selected */
696         CTX_DATA_BEGIN (C, bPoseChannel *, pchan, visible_pose_bones)
697         {
698                 /* keep track of layers to use later? */
699                 if (pchan->bone->flag & BONE_SELECTED)
700                         layers |= pchan->bone->layer;
701                         
702                 /* deselect all bones before selecting new ones? */
703                 if ((extend == false) && (pchan->bone->flag & BONE_UNSELECTABLE) == 0)
704                         pchan->bone->flag &= ~BONE_SELECTED;
705         }
706         CTX_DATA_END;
707         if (layers == 0) 
708                 return 0;
709                 
710         /* select bones that are on same layers as layers flag */
711         CTX_DATA_BEGIN (C, bPoseChannel *, pchan, visible_pose_bones)
712         {
713                 /* if bone is on a suitable layer, and the bone can have its selection changed, select it */
714                 if ((layers & pchan->bone->layer) && (pchan->bone->flag & BONE_UNSELECTABLE) == 0) {
715                         pchan->bone->flag |= BONE_SELECTED;
716                         changed = true;
717                 }
718         }
719         CTX_DATA_END;
720         
721         return changed;
722 }
723
724 static bool pose_select_same_keyingset(bContext *C, ReportList *reports, Object *ob, bool extend)
725 {
726         KeyingSet *ks = ANIM_scene_get_active_keyingset(CTX_data_scene(C));
727         KS_Path *ksp;
728         
729         bArmature *arm = (ob) ? ob->data : NULL;
730         bPose *pose = (ob) ? ob->pose : NULL;
731         bool changed = false;
732         
733         /* sanity checks: validate Keying Set and object */
734         if (ks == NULL) {
735                 BKE_report(reports, RPT_ERROR, "No active Keying Set to use");
736                 return false;
737         }
738         else if (ANIM_validate_keyingset(C, NULL, ks) != 0) {
739                 if (ks->paths.first == NULL) {
740                         if ((ks->flag & KEYINGSET_ABSOLUTE) == 0) {
741                                 BKE_report(reports, RPT_ERROR, 
742                                            "Use another Keying Set, as the active one depends on the currently "
743                                            "selected items or cannot find any targets due to unsuitable context");
744                         }
745                         else {
746                                 BKE_report(reports, RPT_ERROR, "Keying Set does not contain any paths");
747                         }
748                 }
749                 return false;
750         }
751                 
752         if (ELEM(NULL, ob, pose, arm))
753                 return false;
754                 
755         /* if not extending selection, deselect all selected first */
756         if (extend == false) {
757                 CTX_DATA_BEGIN (C, bPoseChannel *, pchan, visible_pose_bones)
758                 {
759                         if ((pchan->bone->flag & BONE_UNSELECTABLE) == 0)
760                                 pchan->bone->flag &= ~BONE_SELECTED;
761                 }
762                 CTX_DATA_END;
763         }
764                 
765         /* iterate over elements in the Keying Set, setting selection depending on whether 
766          * that bone is visible or not...
767          */
768         for (ksp = ks->paths.first; ksp; ksp = ksp->next) {
769                 /* only items related to this object will be relevant */
770                 if ((ksp->id == &ob->id) && (ksp->rna_path != NULL)) {
771                         if (strstr(ksp->rna_path, "bones")) {
772                                 char *boneName = BLI_str_quoted_substrN(ksp->rna_path, "bones[");
773                                 
774                                 if (boneName) {
775                                         bPoseChannel *pchan = BKE_pose_channel_find_name(pose, boneName);
776                                         
777                                         if (pchan) {
778                                                 /* select if bone is visible and can be affected */
779                                                 if (PBONE_SELECTABLE(arm, pchan->bone)) {
780                                                         pchan->bone->flag |= BONE_SELECTED;
781                                                         changed = true;
782                                                 }
783                                         }
784                                         
785                                         /* free temp memory */
786                                         MEM_freeN(boneName);
787                                 }
788                         }
789                 }
790         }
791         
792         return changed;
793 }
794
795 static int pose_select_grouped_exec(bContext *C, wmOperator *op)
796 {
797         Object *ob = BKE_object_pose_armature_get(CTX_data_active_object(C));
798         bArmature *arm = (bArmature *)ob->data;
799         const ePose_SelectSame_Mode type = RNA_enum_get(op->ptr, "type");
800         const bool extend = RNA_boolean_get(op->ptr, "extend");
801         bool changed = false;
802         
803         /* sanity check */
804         if (ob->pose == NULL)
805                 return OPERATOR_CANCELLED;
806                 
807         /* selection types */
808         switch (type) {
809                 case POSE_SEL_SAME_LAYER: /* layer */
810                         changed = pose_select_same_layer(C, ob, extend);
811                         break;
812                 
813                 case POSE_SEL_SAME_GROUP: /* group */
814                         changed = pose_select_same_group(C, ob, extend);
815                         break;
816                         
817                 case POSE_SEL_SAME_KEYINGSET: /* Keying Set */
818                         changed = pose_select_same_keyingset(C, op->reports, ob, extend);
819                         break;
820                 
821                 default:
822                         printf("pose_select_grouped() - Unknown selection type %u\n", type);
823                         break;
824         }
825         
826         /* notifiers for updates */
827         WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
828         
829         if (arm->flag & ARM_HAS_VIZ_DEPS) {
830                 /* mask modifier ('armature' mode), etc. */
831                 DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
832         }
833         
834         /* report done status */
835         if (changed)
836                 return OPERATOR_FINISHED;
837         else
838                 return OPERATOR_CANCELLED;
839 }
840
841 void POSE_OT_select_grouped(wmOperatorType *ot)
842 {
843         static EnumPropertyItem prop_select_grouped_types[] = {
844                 {POSE_SEL_SAME_LAYER, "LAYER", 0, "Layer", "Shared layers"},
845                 {POSE_SEL_SAME_GROUP, "GROUP", 0, "Group", "Shared group"},
846                 {POSE_SEL_SAME_KEYINGSET, "KEYINGSET", 0, "Keying Set", "All bones affected by active Keying Set"},
847                 {0, NULL, 0, NULL, NULL}
848         };
849
850         /* identifiers */
851         ot->name = "Select Grouped";
852         ot->description = "Select all visible bones grouped by similar properties";
853         ot->idname = "POSE_OT_select_grouped";
854         
855         /* api callbacks */
856         ot->invoke = WM_menu_invoke;
857         ot->exec = pose_select_grouped_exec;
858         ot->poll = ED_operator_posemode;
859         
860         /* flags */
861         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
862         
863         /* properties */
864         RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend selection instead of deselecting everything first");
865         ot->prop = RNA_def_enum(ot->srna, "type", prop_select_grouped_types, 0, "Type", "");
866 }
867
868 /* -------------------------------------- */
869
870 /**
871  * \note clone of #armature_select_mirror_exec keep in sync
872  */
873 static int pose_select_mirror_exec(bContext *C, wmOperator *op)
874 {
875         Object *ob_act = CTX_data_active_object(C);
876         Object *ob = BKE_object_pose_armature_get(ob_act);
877         bArmature *arm;
878         bPoseChannel *pchan, *pchan_mirror_act = NULL;
879         const bool active_only = RNA_boolean_get(op->ptr, "only_active");
880         const bool extend = RNA_boolean_get(op->ptr, "extend");
881
882         if ((ob && (ob->mode & OB_MODE_POSE)) == 0) {
883                 return OPERATOR_CANCELLED;
884         }
885
886         arm = ob->data;
887
888         for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
889                 const int flag = (pchan->bone->flag & BONE_SELECTED);
890                 PBONE_PREV_FLAG_SET(pchan, flag);
891         }
892
893         for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
894                 if (PBONE_SELECTABLE(arm, pchan->bone)) {
895                         bPoseChannel *pchan_mirror;
896                         int flag_new = extend ? PBONE_PREV_FLAG_GET(pchan) : 0;
897
898                         if ((pchan_mirror = BKE_pose_channel_get_mirrored(ob->pose, pchan->name)) &&
899                             (PBONE_VISIBLE(arm, pchan_mirror->bone)))
900                         {
901                                 const int flag_mirror = PBONE_PREV_FLAG_GET(pchan_mirror);
902                                 flag_new |= flag_mirror;
903
904                                 if (pchan->bone == arm->act_bone) {
905                                         pchan_mirror_act = pchan_mirror;
906                                 }
907
908                                 /* skip all but the active or its mirror */
909                                 if (active_only && !ELEM(arm->act_bone, pchan->bone, pchan_mirror->bone)) {
910                                         continue;
911                                 }
912                         }
913
914                         pchan->bone->flag = (pchan->bone->flag & ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL)) | flag_new;
915                 }
916         }
917
918         if (pchan_mirror_act) {
919                 arm->act_bone = pchan_mirror_act->bone;
920
921                 /* in weightpaint we select the associated vertex group too */
922                 if (ob_act->mode & OB_MODE_WEIGHT_PAINT) {
923                         ED_vgroup_select_by_name(ob_act, pchan_mirror_act->name);
924                         DAG_id_tag_update(&ob_act->id, OB_RECALC_DATA);
925                 }
926         }
927
928         WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
929
930         return OPERATOR_FINISHED;
931 }
932
933 void POSE_OT_select_mirror(wmOperatorType *ot)
934 {
935         /* identifiers */
936         ot->name = "Flip Active/Selected Bone";
937         ot->idname = "POSE_OT_select_mirror";
938         ot->description = "Mirror the bone selection";
939         
940         /* api callbacks */
941         ot->exec = pose_select_mirror_exec;
942         ot->poll = ED_operator_posemode;
943         
944         /* flags */
945         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
946
947         /* properties */
948         RNA_def_boolean(ot->srna, "only_active", false, "Active Only", "Only operate on the active bone");
949         RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
950 }
951