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