Blender  V3.3
pose_select.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2001-2002 NaN Holding BV. All rights reserved. */
3 
8 #include <string.h>
9 
10 #include "DNA_anim_types.h"
11 #include "DNA_armature_types.h"
12 #include "DNA_constraint_types.h"
14 #include "DNA_object_types.h"
15 #include "DNA_scene_types.h"
16 
17 #include "MEM_guardedalloc.h"
18 
19 #include "BLI_blenlib.h"
20 
21 #include "BKE_action.h"
22 #include "BKE_armature.h"
23 #include "BKE_constraint.h"
24 #include "BKE_context.h"
25 #include "BKE_gpencil_modifier.h"
26 #include "BKE_layer.h"
27 #include "BKE_modifier.h"
28 #include "BKE_object.h"
29 #include "BKE_report.h"
30 
31 #include "DEG_depsgraph.h"
32 
33 #include "RNA_access.h"
34 #include "RNA_define.h"
35 
36 #include "WM_api.h"
37 #include "WM_types.h"
38 
39 #include "ED_armature.h"
40 #include "ED_keyframing.h"
41 #include "ED_mesh.h"
42 #include "ED_object.h"
43 #include "ED_outliner.h"
44 #include "ED_screen.h"
45 #include "ED_select_utils.h"
46 #include "ED_view3d.h"
47 
48 #include "armature_intern.h"
49 
50 /* utility macros for storing a temp int in the bone (selection flag) */
51 #define PBONE_PREV_FLAG_GET(pchan) ((void)0, (POINTER_AS_INT((pchan)->temp)))
52 #define PBONE_PREV_FLAG_SET(pchan, val) ((pchan)->temp = POINTER_FROM_INT(val))
53 
54 /* ***************** Pose Select Utilities ********************* */
55 
56 /* NOTE: SEL_TOGGLE is assumed to have already been handled! */
57 static void pose_do_bone_select(bPoseChannel *pchan, const int select_mode)
58 {
59  /* select pchan only if selectable, but deselect works always */
60  switch (select_mode) {
61  case SEL_SELECT:
62  if (!(pchan->bone->flag & BONE_UNSELECTABLE)) {
63  pchan->bone->flag |= BONE_SELECTED;
64  }
65  break;
66  case SEL_DESELECT:
68  break;
69  case SEL_INVERT:
70  if (pchan->bone->flag & BONE_SELECTED) {
72  }
73  else if (!(pchan->bone->flag & BONE_UNSELECTABLE)) {
74  pchan->bone->flag |= BONE_SELECTED;
75  }
76  break;
77  }
78 }
79 
81 {
82  BLI_assert(ob->type == OB_ARMATURE);
83  bArmature *arm = ob->data;
86 
87  if (arm->flag & ARM_HAS_VIZ_DEPS) {
88  /* mask modifier ('armature' mode), etc. */
90  }
91 
93 }
94 
96 {
97  bArmature *arm;
98 
99  /* sanity checks */
100  /* XXX: actually, we can probably still get away with no object - at most we have no updates */
101  if (ELEM(NULL, ob, ob->pose, pchan, pchan->bone)) {
102  return;
103  }
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? */
121  }
122 }
123 
125  View3D *v3d,
126  Object *ob,
127  Bone *bone,
128  const struct SelectPick_Params *params)
129 {
130  bool found = false;
131  bool changed = false;
132 
133  if (ob || ob->pose) {
134  if (bone && ((bone->flag & BONE_UNSELECTABLE) == 0)) {
135  found = true;
136  }
137  }
138 
139  if (params->sel_op == SEL_OP_SET) {
140  if ((found && params->select_passthrough) && (bone->flag & BONE_SELECTED)) {
141  found = false;
142  }
143  else if (found || params->deselect_all) {
144  /* Deselect everything. */
145  /* Don't use 'BKE_object_pose_base_array_get_unique'
146  * because we may be selecting from object mode. */
147  FOREACH_VISIBLE_BASE_BEGIN (view_layer, v3d, base_iter) {
148  Object *ob_iter = base_iter->object;
149  if ((ob_iter->type == OB_ARMATURE) && (ob_iter->mode & OB_MODE_POSE)) {
150  if (ED_pose_deselect_all(ob_iter, SEL_DESELECT, true)) {
152  }
153  }
154  }
156  changed = true;
157  }
158  }
159 
160  if (found) {
161  Object *ob_act = OBACT(view_layer);
162  BLI_assert(OBEDIT_FROM_VIEW_LAYER(view_layer) == NULL);
163 
164  /* If the bone cannot be affected, don't do anything. */
165  bArmature *arm = ob->data;
166 
167  /* Since we do unified select, we don't shift+select a bone if the
168  * armature object was not active yet.
169  * NOTE(campbell): special exception for armature mode so we can do multi-select
170  * we could check for multi-select explicitly but think its fine to
171  * always give predictable behavior in weight paint mode. */
172  if ((ob_act == NULL) || ((ob_act != ob) && (ob_act->mode & OB_MODE_ALL_WEIGHT_PAINT) == 0)) {
173  /* When we are entering into posemode via toggle-select,
174  * from another active object - always select the bone. */
175  if (params->sel_op == SEL_OP_SET) {
176  /* Re-select the bone again later in this function. */
177  bone->flag &= ~BONE_SELECTED;
178  }
179  }
180 
181  switch (params->sel_op) {
182  case SEL_OP_ADD: {
184  arm->act_bone = bone;
185  break;
186  }
187  case SEL_OP_SUB: {
188  bone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
189  break;
190  }
191  case SEL_OP_XOR: {
192  if (bone->flag & BONE_SELECTED) {
193  /* If not active, we make it active. */
194  if (bone != arm->act_bone) {
195  arm->act_bone = bone;
196  }
197  else {
198  bone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
199  }
200  }
201  else {
203  arm->act_bone = bone;
204  }
205  break;
206  }
207  case SEL_OP_SET: {
209  arm->act_bone = bone;
210  break;
211  }
212  case SEL_OP_AND: {
213  BLI_assert_unreachable(); /* Doesn't make sense for picking. */
214  break;
215  }
216  }
217 
218  if (ob_act) {
219  /* In weightpaint we select the associated vertex group too. */
220  if (ob_act->mode & OB_MODE_ALL_WEIGHT_PAINT) {
221  if (bone == arm->act_bone) {
222  ED_vgroup_select_by_name(ob_act, bone->name);
224  }
225  }
226  /* If there are some dependencies for visualizing armature state
227  * (e.g. Mask Modifier in 'Armature' mode), force update.
228  */
229  else if (arm->flag & ARM_HAS_VIZ_DEPS) {
230  /* NOTE: ob not ob_act here is intentional - it's the source of the
231  * bones being selected [T37247]
232  */
234  }
235 
236  /* Tag armature for copy-on-write update (since act_bone is in armature not object). */
238  }
239 
240  changed = true;
241  }
242 
243  return changed || found;
244 }
245 
247  View3D *v3d,
248  Base *base,
249  const struct GPUSelectResult *buffer,
250  const short hits,
251  const struct SelectPick_Params *params,
252  bool do_nearest)
253 {
254  Object *ob = base->object;
255  Bone *nearBone;
256 
257  if (!ob || !ob->pose) {
258  return 0;
259  }
260 
261  /* Callers happen to already get the active base */
262  Base *base_dummy = NULL;
264  &base, 1, buffer, hits, 1, do_nearest, &base_dummy);
265 
266  return ED_armature_pose_select_pick_bone(view_layer, v3d, ob, nearBone, params);
267 }
268 
270 {
271  BLI_assert(base_select && (base_select->object->type == OB_ARMATURE));
272  Object *ob_active = OBACT(view_layer);
273  BLI_assert(ob_active && (ob_active->mode & OB_MODE_ALL_WEIGHT_PAINT));
274 
275  if (ob_active->type == OB_GPENCIL) {
276  GpencilVirtualModifierData virtualModifierData;
278  &virtualModifierData);
279  for (; md; md = md->next) {
280  if (md->type == eGpencilModifierType_Armature) {
282  Object *ob_arm = agmd->object;
283  if (ob_arm != NULL) {
284  Base *base_arm = BKE_view_layer_base_find(view_layer, ob_arm);
285  if ((base_arm != NULL) && (base_arm != base_select) &&
286  (base_arm->flag & BASE_SELECTED)) {
288  }
289  }
290  }
291  }
292  }
293  else {
294  VirtualModifierData virtualModifierData;
295  ModifierData *md = BKE_modifiers_get_virtual_modifierlist(ob_active, &virtualModifierData);
296  for (; md; md = md->next) {
297  if (md->type == eModifierType_Armature) {
299  Object *ob_arm = amd->object;
300  if (ob_arm != NULL) {
301  Base *base_arm = BKE_view_layer_base_find(view_layer, ob_arm);
302  if ((base_arm != NULL) && (base_arm != base_select) &&
303  (base_arm->flag & BASE_SELECTED)) {
305  }
306  }
307  }
308  }
309  }
310  if ((base_select->flag & BASE_SELECTED) == 0) {
311  ED_object_base_select(base_select, BA_SELECT);
312  }
313 }
314 
315 bool ED_pose_deselect_all(Object *ob, int select_mode, const bool ignore_visibility)
316 {
317  bArmature *arm = ob->data;
318  bPoseChannel *pchan;
319 
320  /* we call this from outliner too */
321  if (ob->pose == NULL) {
322  return false;
323  }
324 
325  /* Determine if we're selecting or deselecting */
326  if (select_mode == SEL_TOGGLE) {
327  select_mode = SEL_SELECT;
328  for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
329  if (ignore_visibility || PBONE_VISIBLE(arm, pchan->bone)) {
330  if (pchan->bone->flag & BONE_SELECTED) {
331  select_mode = SEL_DESELECT;
332  break;
333  }
334  }
335  }
336  }
337 
338  /* Set the flags accordingly */
339  bool changed = false;
340  for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
341  /* ignore the pchan if it isn't visible or if its selection cannot be changed */
342  if (ignore_visibility || PBONE_VISIBLE(arm, pchan->bone)) {
343  int flag_prev = pchan->bone->flag;
344  pose_do_bone_select(pchan, select_mode);
345  changed = (changed || flag_prev != pchan->bone->flag);
346  }
347  }
348  return changed;
349 }
350 
351 static bool ed_pose_is_any_selected(Object *ob, bool ignore_visibility)
352 {
353  bArmature *arm = ob->data;
354  LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
355  if (ignore_visibility || PBONE_VISIBLE(arm, pchan->bone)) {
356  if (pchan->bone->flag & BONE_SELECTED) {
357  return true;
358  }
359  }
360  }
361  return false;
362 }
363 
364 static bool ed_pose_is_any_selected_multi(Base **bases, uint bases_len, bool ignore_visibility)
365 {
366  for (uint base_index = 0; base_index < bases_len; base_index++) {
367  Object *ob_iter = bases[base_index]->object;
368  if (ed_pose_is_any_selected(ob_iter, ignore_visibility)) {
369  return true;
370  }
371  }
372  return false;
373 }
374 
376  uint bases_len,
377  int select_mode,
378  const bool ignore_visibility)
379 {
380  if (select_mode == SEL_TOGGLE) {
381  select_mode = ed_pose_is_any_selected_multi(bases, bases_len, ignore_visibility) ?
382  SEL_DESELECT :
383  SEL_SELECT;
384  }
385 
386  bool changed_multi = false;
387  for (uint base_index = 0; base_index < bases_len; base_index++) {
388  Object *ob_iter = bases[base_index]->object;
389  if (ED_pose_deselect_all(ob_iter, select_mode, ignore_visibility)) {
391  changed_multi = true;
392  }
393  }
394  return changed_multi;
395 }
396 
397 bool ED_pose_deselect_all_multi(bContext *C, int select_mode, const bool ignore_visibility)
398 {
400  ViewContext vc;
402  uint bases_len = 0;
403 
404  Base **bases = BKE_object_pose_base_array_get_unique(vc.view_layer, vc.v3d, &bases_len);
405  bool changed_multi = ED_pose_deselect_all_multi_ex(
406  bases, bases_len, select_mode, ignore_visibility);
407  MEM_freeN(bases);
408  return changed_multi;
409 }
410 
411 /* ***************** Selections ********************** */
412 
413 static void selectconnected_posebonechildren(Object *ob, Bone *bone, int extend)
414 {
415  Bone *curBone;
416 
417  /* stop when unconnected child is encountered, or when unselectable bone is encountered */
418  if (!(bone->flag & BONE_CONNECTED) || (bone->flag & BONE_UNSELECTABLE)) {
419  return;
420  }
421 
422  if (extend) {
423  bone->flag &= ~BONE_SELECTED;
424  }
425  else {
426  bone->flag |= BONE_SELECTED;
427  }
428 
429  for (curBone = bone->childbase.first; curBone; curBone = curBone->next) {
430  selectconnected_posebonechildren(ob, curBone, extend);
431  }
432 }
433 
434 /* within active object context */
435 /* previously known as "selectconnected_posearmature" */
437 {
438  Bone *bone, *curBone, *next = NULL;
439  const bool extend = RNA_boolean_get(op->ptr, "extend");
440 
442 
443  Base *base = NULL;
444  bone = ED_armature_pick_bone(C, event->mval, !extend, &base);
445 
446  if (!bone) {
447  return OPERATOR_CANCELLED;
448  }
449 
450  /* Select parents */
451  for (curBone = bone; curBone; curBone = next) {
452  /* ignore bone if cannot be selected */
453  if ((curBone->flag & BONE_UNSELECTABLE) == 0) {
454  if (extend) {
455  curBone->flag &= ~BONE_SELECTED;
456  }
457  else {
458  curBone->flag |= BONE_SELECTED;
459  }
460 
461  if (curBone->flag & BONE_CONNECTED) {
462  next = curBone->parent;
463  }
464  else {
465  next = NULL;
466  }
467  }
468  else {
469  next = NULL;
470  }
471  }
472 
473  /* Select children */
474  for (curBone = bone->childbase.first; curBone; curBone = curBone->next) {
475  selectconnected_posebonechildren(base->object, curBone, extend);
476  }
477 
479 
481 
482  return OPERATOR_FINISHED;
483 }
484 
486 {
488 }
489 
491 {
492  PropertyRNA *prop;
493 
494  /* identifiers */
495  ot->name = "Select Connected";
496  ot->idname = "POSE_OT_select_linked_pick";
497  ot->description = "Select bones linked by parent/child connections under the mouse cursor";
498 
499  /* callbacks */
500  /* leave 'exec' unset */
503 
504  /* flags */
506 
507  /* props */
508  prop = RNA_def_boolean(ot->srna,
509  "extend",
510  false,
511  "Extend",
512  "Extend selection instead of deselecting everything first");
514 }
515 
517 {
518  Bone *curBone, *next = NULL;
519 
520  CTX_DATA_BEGIN_WITH_ID (C, bPoseChannel *, pchan, visible_pose_bones, Object *, ob) {
521  if ((pchan->bone->flag & BONE_SELECTED) == 0) {
522  continue;
523  }
524 
525  bArmature *arm = ob->data;
526 
527  /* Select parents */
528  for (curBone = pchan->bone; curBone; curBone = next) {
529  if (PBONE_SELECTABLE(arm, curBone)) {
530  curBone->flag |= BONE_SELECTED;
531 
532  if (curBone->flag & BONE_CONNECTED) {
533  next = curBone->parent;
534  }
535  else {
536  next = NULL;
537  }
538  }
539  else {
540  next = NULL;
541  }
542  }
543 
544  /* Select children */
545  for (curBone = pchan->bone->childbase.first; curBone; curBone = curBone->next) {
546  selectconnected_posebonechildren(ob, curBone, false);
547  }
549  }
550  CTX_DATA_END;
551 
553 
554  return OPERATOR_FINISHED;
555 }
556 
558 {
559  /* identifiers */
560  ot->name = "Select Connected";
561  ot->idname = "POSE_OT_select_linked";
562  ot->description = "Select all bones linked by parent/child connections to the current selection";
563 
564  /* callbacks */
567 
568  /* flags */
570 }
571 
572 /* -------------------------------------- */
573 
575 {
576  int action = RNA_enum_get(op->ptr, "action");
577 
579  int multipaint = scene->toolsettings->multipaint;
580 
581  if (action == SEL_TOGGLE) {
582  action = CTX_DATA_COUNT(C, selected_pose_bones) ? SEL_DESELECT : SEL_SELECT;
583  }
584 
585  Object *ob_prev = NULL;
586 
587  /* Set the flags. */
588  CTX_DATA_BEGIN_WITH_ID (C, bPoseChannel *, pchan, visible_pose_bones, Object *, ob) {
589  bArmature *arm = ob->data;
590  pose_do_bone_select(pchan, action);
591 
592  if (ob_prev != ob) {
593  /* weightpaint or mask modifiers need depsgraph updates */
594  if (multipaint || (arm->flag & ARM_HAS_VIZ_DEPS)) {
596  }
597  /* need to tag armature for cow updates, or else selection doesn't update */
599  ob_prev = ob;
600  }
601  }
602  CTX_DATA_END;
603 
605 
607 
608  return OPERATOR_FINISHED;
609 }
610 
612 {
613  /* identifiers */
614  ot->name = "(De)select All";
615  ot->idname = "POSE_OT_select_all";
616  ot->description = "Toggle selection status of all bones";
617 
618  /* api callbacks */
621 
622  /* flags */
624 
626 }
627 
628 /* -------------------------------------- */
629 
631 {
633  bArmature *arm = (bArmature *)ob->data;
634  bPoseChannel *pchan, *parent;
635 
636  /* Determine if there is an active bone */
637  pchan = CTX_data_active_pose_bone(C);
638  if (pchan) {
639  parent = pchan->parent;
640  if ((parent) && !(parent->bone->flag & (BONE_HIDDEN_P | BONE_UNSELECTABLE))) {
641  parent->bone->flag |= BONE_SELECTED;
642  arm->act_bone = parent->bone;
643  }
644  else {
645  return OPERATOR_CANCELLED;
646  }
647  }
648  else {
649  return OPERATOR_CANCELLED;
650  }
651 
653 
655  return OPERATOR_FINISHED;
656 }
657 
659 {
660  /* identifiers */
661  ot->name = "Select Parent Bone";
662  ot->idname = "POSE_OT_select_parent";
663  ot->description = "Select bones that are parents of the currently selected bones";
664 
665  /* api callbacks */
668 
669  /* flags */
671 }
672 
673 /* -------------------------------------- */
674 
676 {
677  bConstraint *con;
678  int found = 0;
679 
680  CTX_DATA_BEGIN (C, bPoseChannel *, pchan, visible_pose_bones) {
681  if (pchan->bone->flag & BONE_SELECTED) {
682  for (con = pchan->constraints.first; con; con = con->next) {
683  ListBase targets = {NULL, NULL};
684  bConstraintTarget *ct;
685 
686  if (BKE_constraint_targets_get(con, &targets)) {
687  for (ct = targets.first; ct; ct = ct->next) {
688  Object *ob = ct->tar;
689 
690  /* Any armature that is also in pose mode should be selected. */
691  if ((ct->subtarget[0] != '\0') && (ob != NULL) && (ob->type == OB_ARMATURE) &&
692  (ob->mode == OB_MODE_POSE)) {
694  if ((pchanc) && !(pchanc->bone->flag & BONE_UNSELECTABLE)) {
697  found = 1;
698  }
699  }
700  }
701 
702  BKE_constraint_targets_flush(con, &targets, 1);
703  }
704  }
705  }
706  }
707  CTX_DATA_END;
708 
709  if (!found) {
710  return OPERATOR_CANCELLED;
711  }
712 
714 
715  return OPERATOR_FINISHED;
716 }
717 
719 {
720  /* identifiers */
721  ot->name = "Select Constraint Target";
722  ot->idname = "POSE_OT_select_constraint_target";
723  ot->description = "Select bones used as targets for the currently selected bones";
724 
725  /* api callbacks */
728 
729  /* flags */
731 }
732 
733 /* -------------------------------------- */
734 
735 /* No need to convert to multi-objects. Just like we keep the non-active bones
736  * selected we then keep the non-active objects untouched (selected/unselected). */
738 {
740  bArmature *arm = ob->data;
741  bPoseChannel *pchan_act;
742  int direction = RNA_enum_get(op->ptr, "direction");
743  const bool add_to_sel = RNA_boolean_get(op->ptr, "extend");
744  bool changed = false;
745 
747  if (pchan_act == NULL) {
748  return OPERATOR_CANCELLED;
749  }
750 
751  if (direction == BONE_SELECT_PARENT) {
752  if (pchan_act->parent) {
753  Bone *bone_parent;
754  bone_parent = pchan_act->parent->bone;
755 
756  if (PBONE_SELECTABLE(arm, bone_parent)) {
757  if (!add_to_sel) {
758  pchan_act->bone->flag &= ~BONE_SELECTED;
759  }
760  bone_parent->flag |= BONE_SELECTED;
761  arm->act_bone = bone_parent;
762 
763  changed = true;
764  }
765  }
766  }
767  else { /* direction == BONE_SELECT_CHILD */
768  bPoseChannel *pchan_iter;
769  Bone *bone_child = NULL;
770  int pass;
771 
772  /* first pass, only connected bones (the logical direct child) */
773  for (pass = 0; pass < 2 && (bone_child == NULL); pass++) {
774  for (pchan_iter = ob->pose->chanbase.first; pchan_iter; pchan_iter = pchan_iter->next) {
775  /* possible we have multiple children, some invisible */
776  if (PBONE_SELECTABLE(arm, pchan_iter->bone)) {
777  if (pchan_iter->parent == pchan_act) {
778  if ((pass == 1) || (pchan_iter->bone->flag & BONE_CONNECTED)) {
779  bone_child = pchan_iter->bone;
780  break;
781  }
782  }
783  }
784  }
785  }
786 
787  if (bone_child) {
788  arm->act_bone = bone_child;
789 
790  if (!add_to_sel) {
791  pchan_act->bone->flag &= ~BONE_SELECTED;
792  }
793  bone_child->flag |= BONE_SELECTED;
794 
795  changed = true;
796  }
797  }
798 
799  if (changed == false) {
800  return OPERATOR_CANCELLED;
801  }
802 
804 
806 
807  return OPERATOR_FINISHED;
808 }
809 
811 {
812  static const EnumPropertyItem direction_items[] = {
813  {BONE_SELECT_PARENT, "PARENT", 0, "Select Parent", ""},
814  {BONE_SELECT_CHILD, "CHILD", 0, "Select Child", ""},
815  {0, NULL, 0, NULL, NULL},
816  };
817 
818  /* identifiers */
819  ot->name = "Select Hierarchy";
820  ot->idname = "POSE_OT_select_hierarchy";
821  ot->description = "Select immediate parent/children of selected bones";
822 
823  /* api callbacks */
826 
827  /* flags */
829 
830  /* props */
831  ot->prop = RNA_def_enum(
832  ot->srna, "direction", direction_items, BONE_SELECT_PARENT, "Direction", "");
833  RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
834 }
835 
836 /* -------------------------------------- */
837 
838 /* modes for select same */
839 typedef enum ePose_SelectSame_Mode {
844 
845 static bool pose_select_same_group(bContext *C, bool extend)
846 {
847  ViewLayer *view_layer = CTX_data_view_layer(C);
848  bool *group_flags_array;
849  bool *group_flags = NULL;
850  int groups_len = 0;
851  bool changed = false, tagged = false;
852  Object *ob_prev = NULL;
853  uint ob_index;
854 
855  uint objects_len = 0;
856  Object **objects = BKE_object_pose_array_get_unique(view_layer, CTX_wm_view3d(C), &objects_len);
857 
858  for (ob_index = 0; ob_index < objects_len; ob_index++) {
859  Object *ob = BKE_object_pose_armature_get(objects[ob_index]);
860  bArmature *arm = (ob) ? ob->data : NULL;
861  bPose *pose = (ob) ? ob->pose : NULL;
862 
863  /* Sanity checks. */
864  if (ELEM(NULL, ob, pose, arm)) {
865  continue;
866  }
867 
868  ob->id.tag &= ~LIB_TAG_DOIT;
869  groups_len = MAX2(groups_len, BLI_listbase_count(&pose->agroups));
870  }
871 
872  /* Nothing to do here. */
873  if (groups_len == 0) {
874  MEM_freeN(objects);
875  return false;
876  }
877 
878  /* alloc a small array to keep track of the groups to use
879  * - each cell stores on/off state for whether group should be used
880  * - size is (groups_len + 1), since (index = 0) is used for no-group
881  */
882  groups_len++;
883  group_flags_array = MEM_callocN(objects_len * groups_len * sizeof(bool),
884  "pose_select_same_group");
885 
886  group_flags = NULL;
887  ob_index = -1;
888  ob_prev = NULL;
889  CTX_DATA_BEGIN_WITH_ID (C, bPoseChannel *, pchan, visible_pose_bones, Object *, ob) {
890  if (ob != ob_prev) {
891  ob_index++;
892  group_flags = group_flags_array + (ob_index * groups_len);
893  ob_prev = ob;
894  }
895 
896  /* keep track of group as group to use later? */
897  if (pchan->bone->flag & BONE_SELECTED) {
898  group_flags[pchan->agrp_index] = true;
899  tagged = true;
900  }
901 
902  /* deselect all bones before selecting new ones? */
903  if ((extend == false) && (pchan->bone->flag & BONE_UNSELECTABLE) == 0) {
904  pchan->bone->flag &= ~BONE_SELECTED;
905  }
906  }
907  CTX_DATA_END;
908 
909  /* small optimization: only loop through bones a second time if there are any groups tagged */
910  if (tagged) {
911  group_flags = NULL;
912  ob_index = -1;
913  ob_prev = NULL;
914  /* only if group matches (and is not selected or current bone) */
915  CTX_DATA_BEGIN_WITH_ID (C, bPoseChannel *, pchan, visible_pose_bones, Object *, ob) {
916  if (ob != ob_prev) {
917  ob_index++;
918  group_flags = group_flags_array + (ob_index * groups_len);
919  ob_prev = ob;
920  }
921 
922  if ((pchan->bone->flag & BONE_UNSELECTABLE) == 0) {
923  /* check if the group used by this bone is counted */
924  if (group_flags[pchan->agrp_index]) {
925  pchan->bone->flag |= BONE_SELECTED;
926  ob->id.tag |= LIB_TAG_DOIT;
927  }
928  }
929  }
930  CTX_DATA_END;
931  }
932 
933  for (ob_index = 0; ob_index < objects_len; ob_index++) {
934  Object *ob = objects[ob_index];
935  if (ob->id.tag & LIB_TAG_DOIT) {
937  changed = true;
938  }
939  }
940 
941  /* Cleanup. */
942  MEM_freeN(group_flags_array);
943  MEM_freeN(objects);
944 
945  return changed;
946 }
947 
948 static bool pose_select_same_layer(bContext *C, bool extend)
949 {
950  ViewLayer *view_layer = CTX_data_view_layer(C);
951  int *layers_array, *layers = NULL;
952  Object *ob_prev = NULL;
953  uint ob_index;
954  bool changed = false;
955 
956  uint objects_len = 0;
957  Object **objects = BKE_object_pose_array_get_unique(view_layer, CTX_wm_view3d(C), &objects_len);
958 
959  for (ob_index = 0; ob_index < objects_len; ob_index++) {
960  Object *ob = objects[ob_index];
961  ob->id.tag &= ~LIB_TAG_DOIT;
962  }
963 
964  layers_array = MEM_callocN(objects_len * sizeof(*layers_array), "pose_select_same_layer");
965 
966  /* Figure out what bones are selected. */
967  layers = NULL;
968  ob_prev = NULL;
969  ob_index = -1;
970  CTX_DATA_BEGIN_WITH_ID (C, bPoseChannel *, pchan, visible_pose_bones, Object *, ob) {
971  if (ob != ob_prev) {
972  layers = &layers_array[++ob_index];
973  ob_prev = ob;
974  }
975 
976  /* Keep track of layers to use later? */
977  if (pchan->bone->flag & BONE_SELECTED) {
978  *layers |= pchan->bone->layer;
979  }
980 
981  /* Deselect all bones before selecting new ones? */
982  if ((extend == false) && (pchan->bone->flag & BONE_UNSELECTABLE) == 0) {
983  pchan->bone->flag &= ~BONE_SELECTED;
984  }
985  }
986  CTX_DATA_END;
987 
988  bool any_layer = false;
989  for (ob_index = 0; ob_index < objects_len; ob_index++) {
990  if (layers_array[ob_index]) {
991  any_layer = true;
992  break;
993  }
994  }
995 
996  if (!any_layer) {
997  goto cleanup;
998  }
999 
1000  /* Select bones that are on same layers as layers flag. */
1001  ob_prev = NULL;
1002  ob_index = -1;
1003  CTX_DATA_BEGIN_WITH_ID (C, bPoseChannel *, pchan, visible_pose_bones, Object *, ob) {
1004  if (ob != ob_prev) {
1005  layers = &layers_array[++ob_index];
1006  ob_prev = ob;
1007  }
1008 
1009  /* if bone is on a suitable layer, and the bone can have its selection changed, select it */
1010  if ((*layers & pchan->bone->layer) && (pchan->bone->flag & BONE_UNSELECTABLE) == 0) {
1011  pchan->bone->flag |= BONE_SELECTED;
1012  ob->id.tag |= LIB_TAG_DOIT;
1013  }
1014  }
1015  CTX_DATA_END;
1016 
1017  for (ob_index = 0; ob_index < objects_len; ob_index++) {
1018  Object *ob = objects[ob_index];
1019  if (ob->id.tag & LIB_TAG_DOIT) {
1021  changed = true;
1022  }
1023  }
1024 
1025 cleanup:
1026  /* Cleanup. */
1027  MEM_freeN(layers_array);
1028  MEM_freeN(objects);
1029 
1030  return changed;
1031 }
1032 
1033 static bool pose_select_same_keyingset(bContext *C, ReportList *reports, bool extend)
1034 {
1035  ViewLayer *view_layer = CTX_data_view_layer(C);
1036  bool changed_multi = false;
1038  KS_Path *ksp;
1039 
1040  /* sanity checks: validate Keying Set and object */
1041  if (ks == NULL) {
1042  BKE_report(reports, RPT_ERROR, "No active Keying Set to use");
1043  return false;
1044  }
1045  if (ANIM_validate_keyingset(C, NULL, ks) != 0) {
1046  if (ks->paths.first == NULL) {
1047  if ((ks->flag & KEYINGSET_ABSOLUTE) == 0) {
1048  BKE_report(reports,
1049  RPT_ERROR,
1050  "Use another Keying Set, as the active one depends on the currently "
1051  "selected items or cannot find any targets due to unsuitable context");
1052  }
1053  else {
1054  BKE_report(reports, RPT_ERROR, "Keying Set does not contain any paths");
1055  }
1056  }
1057  return false;
1058  }
1059 
1060  /* if not extending selection, deselect all selected first */
1061  if (extend == false) {
1062  CTX_DATA_BEGIN (C, bPoseChannel *, pchan, visible_pose_bones) {
1063  if ((pchan->bone->flag & BONE_UNSELECTABLE) == 0) {
1064  pchan->bone->flag &= ~BONE_SELECTED;
1065  }
1066  }
1067  CTX_DATA_END;
1068  }
1069 
1070  uint objects_len = 0;
1071  Object **objects = BKE_object_pose_array_get_unique(view_layer, CTX_wm_view3d(C), &objects_len);
1072 
1073  for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
1074  Object *ob = BKE_object_pose_armature_get(objects[ob_index]);
1075  bArmature *arm = (ob) ? ob->data : NULL;
1076  bPose *pose = (ob) ? ob->pose : NULL;
1077  bool changed = false;
1078 
1079  /* Sanity checks. */
1080  if (ELEM(NULL, ob, pose, arm)) {
1081  continue;
1082  }
1083 
1084  /* iterate over elements in the Keying Set, setting selection depending on whether
1085  * that bone is visible or not...
1086  */
1087  for (ksp = ks->paths.first; ksp; ksp = ksp->next) {
1088  /* only items related to this object will be relevant */
1089  if ((ksp->id == &ob->id) && (ksp->rna_path != NULL)) {
1090  bPoseChannel *pchan = NULL;
1091  char boneName[sizeof(pchan->name)];
1092  if (!BLI_str_quoted_substr(ksp->rna_path, "bones[", boneName, sizeof(boneName))) {
1093  continue;
1094  }
1095  pchan = BKE_pose_channel_find_name(pose, boneName);
1096 
1097  if (pchan) {
1098  /* select if bone is visible and can be affected */
1099  if (PBONE_SELECTABLE(arm, pchan->bone)) {
1100  pchan->bone->flag |= BONE_SELECTED;
1101  changed = true;
1102  }
1103  }
1104  }
1105  }
1106 
1107  if (changed || !extend) {
1109  changed_multi = true;
1110  }
1111  }
1112  MEM_freeN(objects);
1113 
1114  return changed_multi;
1115 }
1116 
1118 {
1120  const ePose_SelectSame_Mode type = RNA_enum_get(op->ptr, "type");
1121  const bool extend = RNA_boolean_get(op->ptr, "extend");
1122  bool changed = false;
1123 
1124  /* sanity check */
1125  if (ob->pose == NULL) {
1126  return OPERATOR_CANCELLED;
1127  }
1128 
1129  /* selection types */
1130  switch (type) {
1131  case POSE_SEL_SAME_LAYER: /* layer */
1132  changed = pose_select_same_layer(C, extend);
1133  break;
1134 
1135  case POSE_SEL_SAME_GROUP: /* group */
1136  changed = pose_select_same_group(C, extend);
1137  break;
1138 
1139  case POSE_SEL_SAME_KEYINGSET: /* Keying Set */
1140  changed = pose_select_same_keyingset(C, op->reports, extend);
1141  break;
1142 
1143  default:
1144  printf("pose_select_grouped() - Unknown selection type %u\n", type);
1145  break;
1146  }
1147 
1148  /* report done status */
1149  if (changed) {
1151 
1152  return OPERATOR_FINISHED;
1153  }
1154  return OPERATOR_CANCELLED;
1155 }
1156 
1158 {
1159  static const EnumPropertyItem prop_select_grouped_types[] = {
1160  {POSE_SEL_SAME_LAYER, "LAYER", 0, "Layer", "Shared layers"},
1161  {POSE_SEL_SAME_GROUP, "GROUP", 0, "Group", "Shared group"},
1163  "KEYINGSET",
1164  0,
1165  "Keying Set",
1166  "All bones affected by active Keying Set"},
1167  {0, NULL, 0, NULL, NULL},
1168  };
1169 
1170  /* identifiers */
1171  ot->name = "Select Grouped";
1172  ot->description = "Select all visible bones grouped by similar properties";
1173  ot->idname = "POSE_OT_select_grouped";
1174 
1175  /* api callbacks */
1179 
1180  /* flags */
1182 
1183  /* properties */
1185  "extend",
1186  false,
1187  "Extend",
1188  "Extend selection instead of deselecting everything first");
1189  ot->prop = RNA_def_enum(ot->srna, "type", prop_select_grouped_types, 0, "Type", "");
1190 }
1191 
1192 /* -------------------------------------- */
1193 
1198 {
1199  ViewLayer *view_layer = CTX_data_view_layer(C);
1200  Object *ob_active = CTX_data_active_object(C);
1201 
1202  const bool is_weight_paint = (ob_active->mode & OB_MODE_WEIGHT_PAINT) != 0;
1203  const bool active_only = RNA_boolean_get(op->ptr, "only_active");
1204  const bool extend = RNA_boolean_get(op->ptr, "extend");
1205 
1206  uint objects_len = 0;
1207  Object **objects = BKE_object_pose_array_get_unique(view_layer, CTX_wm_view3d(C), &objects_len);
1208 
1209  for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
1210  Object *ob = objects[ob_index];
1211  bArmature *arm = ob->data;
1212  bPoseChannel *pchan, *pchan_mirror_act = NULL;
1213 
1214  for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
1215  const int flag = (pchan->bone->flag & BONE_SELECTED);
1216  PBONE_PREV_FLAG_SET(pchan, flag);
1217  }
1218 
1219  for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
1220  if (PBONE_SELECTABLE(arm, pchan->bone)) {
1221  bPoseChannel *pchan_mirror;
1222  int flag_new = extend ? PBONE_PREV_FLAG_GET(pchan) : 0;
1223 
1224  if ((pchan_mirror = BKE_pose_channel_get_mirrored(ob->pose, pchan->name)) &&
1225  (PBONE_VISIBLE(arm, pchan_mirror->bone))) {
1226  const int flag_mirror = PBONE_PREV_FLAG_GET(pchan_mirror);
1227  flag_new |= flag_mirror;
1228 
1229  if (pchan->bone == arm->act_bone) {
1230  pchan_mirror_act = pchan_mirror;
1231  }
1232 
1233  /* Skip all but the active or its mirror. */
1234  if (active_only && !ELEM(arm->act_bone, pchan->bone, pchan_mirror->bone)) {
1235  continue;
1236  }
1237  }
1238 
1239  pchan->bone->flag = (pchan->bone->flag & ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL)) |
1240  flag_new;
1241  }
1242  }
1243 
1244  if (pchan_mirror_act) {
1245  arm->act_bone = pchan_mirror_act->bone;
1246 
1247  /* In weightpaint we select the associated vertex group too. */
1248  if (is_weight_paint) {
1249  ED_vgroup_select_by_name(ob_active, pchan_mirror_act->name);
1250  DEG_id_tag_update(&ob_active->id, ID_RECALC_GEOMETRY);
1251  }
1252  }
1253 
1255 
1256  /* Need to tag armature for cow updates, or else selection doesn't update. */
1258  }
1259  MEM_freeN(objects);
1260 
1262 
1263  return OPERATOR_FINISHED;
1264 }
1265 
1267 {
1268  /* identifiers */
1269  ot->name = "Select Mirror";
1270  ot->idname = "POSE_OT_select_mirror";
1271  ot->description = "Mirror the bone selection";
1272 
1273  /* api callbacks */
1276 
1277  /* flags */
1279 
1280  /* properties */
1282  ot->srna, "only_active", false, "Active Only", "Only operate on the active bone");
1283  RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
1284 }
Blender kernel action and pose functionality.
struct bPoseChannel * BKE_pose_channel_find_name(const struct bPose *pose, const char *name)
struct bPoseChannel * BKE_pose_channel_active_if_layer_visible(struct Object *ob)
Definition: action.c:720
struct bPoseChannel * BKE_pose_channel_get_mirrored(const struct bPose *pose, const char *name)
#define PBONE_VISIBLE(arm, bone)
Definition: BKE_armature.h:549
#define PBONE_SELECTABLE(arm, bone)
Definition: BKE_armature.h:554
void BKE_constraint_targets_flush(struct bConstraint *con, struct ListBase *targets, bool no_copy)
Definition: constraint.c:6186
int BKE_constraint_targets_get(struct bConstraint *con, struct ListBase *r_targets)
Definition: constraint.c:6157
#define CTX_DATA_BEGIN_WITH_ID(C, Type, instance, member, Type_id, instance_id)
Definition: BKE_context.h:284
struct Scene * CTX_data_scene(const bContext *C)
Definition: context.c:1090
#define CTX_DATA_BEGIN(C, Type, instance, member)
Definition: BKE_context.h:269
struct ViewLayer * CTX_data_view_layer(const bContext *C)
Definition: context.c:1100
struct Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
Definition: context.c:1528
struct Object * CTX_data_active_object(const bContext *C)
Definition: context.c:1353
struct View3D * CTX_wm_view3d(const bContext *C)
Definition: context.c:784
#define CTX_DATA_COUNT(C, member)
Definition: BKE_context.h:290
#define CTX_DATA_END
Definition: BKE_context.h:278
struct bPoseChannel * CTX_data_active_pose_bone(const bContext *C)
Definition: context.c:1425
struct GpencilModifierData * BKE_gpencil_modifiers_get_virtual_modifierlist(const struct Object *ob, struct GpencilVirtualModifierData *data)
#define FOREACH_VISIBLE_BASE_END
Definition: BKE_layer.h:418
#define FOREACH_VISIBLE_BASE_BEGIN(_view_layer, _v3d, _instance)
Definition: BKE_layer.h:406
struct Base * BKE_view_layer_base_find(struct ViewLayer *view_layer, struct Object *ob)
Definition: layer.c:379
struct ModifierData * BKE_modifiers_get_virtual_modifierlist(const struct Object *ob, struct VirtualModifierData *data)
General operations, lookup, etc. for blender objects.
struct Object * BKE_object_pose_armature_get(struct Object *ob)
Definition: object.cc:2511
struct Object ** BKE_object_pose_array_get_unique(struct ViewLayer *view_layer, struct View3D *v3d, unsigned int *r_objects_len)
Definition: object.cc:2594
struct Base ** BKE_object_pose_base_array_get_unique(struct ViewLayer *view_layer, struct View3D *v3d, unsigned int *r_bases_len)
Definition: object.cc:2641
void BKE_report(ReportList *reports, eReportType type, const char *message)
Definition: report.c:83
#define BLI_assert_unreachable()
Definition: BLI_assert.h:93
#define BLI_assert(a)
Definition: BLI_assert.h:46
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:336
int BLI_listbase_count(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
bool bool BLI_str_quoted_substr(const char *__restrict str, const char *__restrict prefix, char *result, size_t result_maxlen)
Definition: string.c:424
unsigned int uint
Definition: BLI_sys_types.h:67
#define UNUSED(x)
#define MAX2(a, b)
#define ELEM(...)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:35
void DEG_id_tag_update(struct ID *id, int flag)
@ ID_RECALC_COPY_ON_WRITE
Definition: DNA_ID.h:834
@ ID_RECALC_SELECT
Definition: DNA_ID.h:818
@ ID_RECALC_GEOMETRY
Definition: DNA_ID.h:791
@ LIB_TAG_DOIT
Definition: DNA_ID.h:707
@ KEYINGSET_ABSOLUTE
@ BONE_ROOTSEL
@ BONE_SELECTED
@ BONE_UNSELECTABLE
@ BONE_HIDDEN_P
@ BONE_TIPSEL
@ BONE_CONNECTED
@ ARM_HAS_VIZ_DEPS
@ eGpencilModifierType_Armature
@ BASE_SELECTED
@ eModifierType_Armature
#define OB_MODE_ALL_WEIGHT_PAINT
@ OB_MODE_WEIGHT_PAINT
@ OB_MODE_POSE
Object is a sort of wrapper for general info.
@ OB_ARMATURE
@ OB_GPENCIL
#define OBEDIT_FROM_VIEW_LAYER(view_layer)
#define OBACT(_view_layer)
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
#define BONE_SELECT_CHILD
Definition: ED_armature.h:62
#define BONE_SELECT_PARENT
Definition: ED_armature.h:61
void ED_vgroup_select_by_name(struct Object *ob, const char *name)
void ED_object_base_select(struct Base *base, eObjectSelect_Mode mode)
Definition: object_select.c:76
@ BA_DESELECT
Definition: ED_object.h:154
@ BA_SELECT
Definition: ED_object.h:155
void ED_outliner_select_sync_from_pose_bone_tag(struct bContext *C)
bool ED_operator_posemode(struct bContext *C)
Definition: screen_ops.c:530
bool ED_operator_view3d_active(struct bContext *C)
Definition: screen_ops.c:225
@ SEL_SELECT
@ SEL_INVERT
@ SEL_DESELECT
@ SEL_TOGGLE
@ SEL_OP_ADD
@ SEL_OP_SUB
@ SEL_OP_SET
@ SEL_OP_AND
@ SEL_OP_XOR
void ED_view3d_viewcontext_init(struct bContext *C, struct ViewContext *vc, struct Depsgraph *depsgraph)
void view3d_operator_needs_opengl(const struct bContext *C)
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
Read Guarded memory(de)allocation.
@ PROP_SKIP_SAVE
Definition: RNA_types.h:218
#define C
Definition: RandGen.cpp:25
@ OPTYPE_UNDO
Definition: WM_types.h:148
@ OPTYPE_REGISTER
Definition: WM_types.h:146
#define NC_GEOM
Definition: WM_types.h:343
#define ND_DATA
Definition: WM_types.h:456
#define ND_BONE_SELECT
Definition: WM_types.h:409
#define NC_OBJECT
Definition: WM_types.h:329
struct Bone * ED_armature_pick_bone(struct bContext *C, const int xy[2], bool findunsel, struct Base **r_base)
struct Bone * ED_armature_pick_bone_from_selectbuffer(struct Base **bases, uint bases_len, const struct GPUSelectResult *buffer, short hits, bool findunsel, bool do_nearest, struct Base **r_base)
__forceinline const avxb select(const avxb &m, const avxb &t, const avxb &f)
Definition: avxb.h:154
Scene scene
const Depsgraph * depsgraph
uiWidgetBaseParameters params[MAX_WIDGET_BASE_BATCH]
ccl_global float * buffer
eModifyKey_Returns ANIM_validate_keyingset(bContext *C, ListBase *dsources, KeyingSet *ks)
Definition: keyingsets.c:954
KeyingSet * ANIM_scene_get_active_keyingset(const Scene *scene)
Definition: keyingsets.c:647
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
void *(* MEM_callocN)(size_t len, const char *str)
Definition: mallocn.c:31
static ulong * next
static const EnumPropertyItem prop_select_grouped_types[]
void POSE_OT_select_parent(wmOperatorType *ot)
Definition: pose_select.c:658
static bool pose_select_same_group(bContext *C, bool extend)
Definition: pose_select.c:845
bool ED_pose_deselect_all_multi_ex(Base **bases, uint bases_len, int select_mode, const bool ignore_visibility)
Definition: pose_select.c:375
#define PBONE_PREV_FLAG_SET(pchan, val)
Definition: pose_select.c:52
static bool ed_pose_is_any_selected_multi(Base **bases, uint bases_len, bool ignore_visibility)
Definition: pose_select.c:364
static int pose_select_hierarchy_exec(bContext *C, wmOperator *op)
Definition: pose_select.c:737
static int pose_select_linked_exec(bContext *C, wmOperator *UNUSED(op))
Definition: pose_select.c:516
bool ED_armature_pose_select_pick_bone(ViewLayer *view_layer, View3D *v3d, Object *ob, Bone *bone, const struct SelectPick_Params *params)
Definition: pose_select.c:124
static int pose_select_constraint_target_exec(bContext *C, wmOperator *UNUSED(op))
Definition: pose_select.c:675
void POSE_OT_select_hierarchy(wmOperatorType *ot)
Definition: pose_select.c:810
void POSE_OT_select_grouped(wmOperatorType *ot)
Definition: pose_select.c:1157
void POSE_OT_select_linked_pick(wmOperatorType *ot)
Definition: pose_select.c:490
static void pose_do_bone_select(bPoseChannel *pchan, const int select_mode)
Definition: pose_select.c:57
static bool pose_select_same_layer(bContext *C, bool extend)
Definition: pose_select.c:948
void ED_pose_bone_select_tag_update(Object *ob)
Definition: pose_select.c:80
bool ED_pose_deselect_all(Object *ob, int select_mode, const bool ignore_visibility)
Definition: pose_select.c:315
static int pose_select_connected_invoke(bContext *C, wmOperator *op, const wmEvent *event)
Definition: pose_select.c:436
void POSE_OT_select_mirror(wmOperatorType *ot)
Definition: pose_select.c:1266
static bool ed_pose_is_any_selected(Object *ob, bool ignore_visibility)
Definition: pose_select.c:351
bool ED_pose_deselect_all_multi(bContext *C, int select_mode, const bool ignore_visibility)
Definition: pose_select.c:397
static int pose_select_mirror_exec(bContext *C, wmOperator *op)
Definition: pose_select.c:1197
void POSE_OT_select_all(wmOperatorType *ot)
Definition: pose_select.c:611
void POSE_OT_select_constraint_target(wmOperatorType *ot)
Definition: pose_select.c:718
static bool pose_select_linked_pick_poll(bContext *C)
Definition: pose_select.c:485
ePose_SelectSame_Mode
Definition: pose_select.c:839
@ POSE_SEL_SAME_GROUP
Definition: pose_select.c:841
@ POSE_SEL_SAME_LAYER
Definition: pose_select.c:840
@ POSE_SEL_SAME_KEYINGSET
Definition: pose_select.c:842
static int pose_de_select_all_exec(bContext *C, wmOperator *op)
Definition: pose_select.c:574
bool ED_armature_pose_select_pick_with_buffer(ViewLayer *view_layer, View3D *v3d, Base *base, const struct GPUSelectResult *buffer, const short hits, const struct SelectPick_Params *params, bool do_nearest)
Definition: pose_select.c:246
static int pose_select_parent_exec(bContext *C, wmOperator *UNUSED(op))
Definition: pose_select.c:630
void ED_armature_pose_select_in_wpaint_mode(ViewLayer *view_layer, Base *base_select)
Definition: pose_select.c:269
static bool pose_select_same_keyingset(bContext *C, ReportList *reports, bool extend)
Definition: pose_select.c:1033
void POSE_OT_select_linked(wmOperatorType *ot)
Definition: pose_select.c:557
#define PBONE_PREV_FLAG_GET(pchan)
Definition: pose_select.c:51
static void selectconnected_posebonechildren(Object *ob, Bone *bone, int extend)
Definition: pose_select.c:413
void ED_pose_bone_select(Object *ob, bPoseChannel *pchan, bool select)
Definition: pose_select.c:95
static int pose_select_grouped_exec(bContext *C, wmOperator *op)
Definition: pose_select.c:1117
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:4863
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:5004
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, bool default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3493
void RNA_def_property_flag(PropertyRNA *prop, PropertyFlag flag)
Definition: rna_define.c:1490
PropertyRNA * RNA_def_enum(StructOrFunctionRNA *cont_, const char *identifier, const EnumPropertyItem *items, int default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3783
short flag
struct Object * object
struct Bone * parent
char name[64]
struct Bone * next
ListBase childbase
struct GpencilModifierData * next
int tag
Definition: DNA_ID.h:387
struct KS_Path * next
char * rna_path
ListBase paths
void * first
Definition: DNA_listBase.h:31
struct ModifierData * next
struct bPose * pose
void * data
struct ToolSettings * toolsettings
struct ViewLayer * view_layer
Definition: ED_view3d.h:66
struct View3D * v3d
Definition: ED_view3d.h:70
struct bConstraintTarget * next
struct bConstraint * next
struct Bone * bone
struct bPoseChannel * parent
struct bPoseChannel * next
ListBase chanbase
int mval[2]
Definition: WM_types.h:684
int(* invoke)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:919
const char * name
Definition: WM_types.h:888
const char * idname
Definition: WM_types.h:890
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:943
struct StructRNA * srna
Definition: WM_types.h:969
const char * description
Definition: WM_types.h:893
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:903
PropertyRNA * prop
Definition: WM_types.h:981
struct ReportList * reports
struct PointerRNA * ptr
void WM_main_add_notifier(unsigned int type, void *reference)
void WM_event_add_notifier(const bContext *C, uint type, void *reference)
wmOperatorType * ot
Definition: wm_files.c:3479
void WM_operator_properties_select_all(wmOperatorType *ot)
int WM_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))