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