Blender  V2.93
armature_select.c
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
17  * All rights reserved.
18  * API's and Operators for selecting armature bones in EditMode
19  */
20 
25 #include "MEM_guardedalloc.h"
26 
27 #include "DNA_armature_types.h"
28 #include "DNA_object_types.h"
29 #include "DNA_scene_types.h"
30 
31 #include "BLI_blenlib.h"
32 #include "BLI_math.h"
33 #include "BLI_rect.h"
34 #include "BLI_string_utils.h"
35 
36 #include "BKE_action.h"
37 #include "BKE_armature.h"
38 #include "BKE_context.h"
39 #include "BKE_layer.h"
40 #include "BKE_object.h"
41 #include "BKE_report.h"
42 
43 #include "RNA_access.h"
44 #include "RNA_define.h"
45 
46 #include "WM_api.h"
47 #include "WM_types.h"
48 
49 #include "ED_armature.h"
50 #include "ED_object.h"
51 #include "ED_outliner.h"
52 #include "ED_screen.h"
53 #include "ED_select_utils.h"
54 #include "ED_view3d.h"
55 
56 #include "DEG_depsgraph.h"
57 
58 #include "armature_intern.h"
59 
60 /* utility macros for storing a temp int in the bone (selection flag) */
61 #define EBONE_PREV_FLAG_GET(ebone) ((void)0, (ebone)->temp.i)
62 #define EBONE_PREV_FLAG_SET(ebone, val) ((ebone)->temp.i = val)
63 
64 /* -------------------------------------------------------------------- */
69  uint bases_len,
70  int hit,
71  EditBone **r_ebone)
72 {
73  const uint hit_object = hit & 0xFFFF;
74  Base *base = NULL;
75  EditBone *ebone = NULL;
76  /* TODO(campbell): optimize, eg: sort & binary search. */
77  for (uint base_index = 0; base_index < bases_len; base_index++) {
78  if (bases[base_index]->object->runtime.select_id == hit_object) {
79  base = bases[base_index];
80  break;
81  }
82  }
83  if (base != NULL) {
84  const uint hit_bone = (hit & ~BONESEL_ANY) >> 16;
85  bArmature *arm = base->object->data;
86  ebone = BLI_findlink(arm->edbo, hit_bone);
87  }
88  *r_ebone = ebone;
89  return base;
90 }
91 
93  uint objects_len,
94  int hit,
95  EditBone **r_ebone)
96 {
97  const uint hit_object = hit & 0xFFFF;
98  Object *ob = NULL;
99  EditBone *ebone = NULL;
100  /* TODO(campbell): optimize, eg: sort & binary search. */
101  for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
102  if (objects[ob_index]->runtime.select_id == hit_object) {
103  ob = objects[ob_index];
104  break;
105  }
106  }
107  if (ob != NULL) {
108  const uint hit_bone = (hit & ~BONESEL_ANY) >> 16;
109  bArmature *arm = ob->data;
110  ebone = BLI_findlink(arm->edbo, hit_bone);
111  }
112  *r_ebone = ebone;
113  return ob;
114 }
115 
117  uint bases_len,
118  int hit,
119  bPoseChannel **r_pchan)
120 {
121  const uint hit_object = hit & 0xFFFF;
122  Base *base = NULL;
123  bPoseChannel *pchan = NULL;
124  /* TODO(campbell): optimize, eg: sort & binary search. */
125  for (uint base_index = 0; base_index < bases_len; base_index++) {
126  if (bases[base_index]->object->runtime.select_id == hit_object) {
127  base = bases[base_index];
128  break;
129  }
130  }
131  if (base != NULL) {
132  if (base->object->pose != NULL) {
133  const uint hit_bone = (hit & ~BONESEL_ANY) >> 16;
134  /* pchan may be NULL. */
135  pchan = BLI_findlink(&base->object->pose->chanbase, hit_bone);
136  }
137  }
138  *r_pchan = pchan;
139  return base;
140 }
141 
142 /* For callers that don't need the pose channel. */
144  uint bases_len,
145  int hit,
146  Bone **r_bone)
147 {
148  bPoseChannel *pchan = NULL;
149  Base *base = ED_armature_base_and_pchan_from_select_buffer(bases, bases_len, hit, &pchan);
150  *r_bone = pchan ? pchan->bone : NULL;
151  return base;
152 }
153 
156 /* -------------------------------------------------------------------- */
165 /* See if there are any selected bones in this buffer */
166 /* only bones from base are checked on */
167 static void *ed_armature_pick_bone_from_selectbuffer_impl(const bool is_editmode,
168  Base **bases,
169  uint bases_len,
170  const uint *buffer,
171  short hits,
172  bool findunsel,
173  bool do_nearest,
174  Base **r_base)
175 {
176  bPoseChannel *pchan;
177  EditBone *ebone;
178  void *firstunSel = NULL, *firstSel = NULL, *data;
179  Base *firstunSel_base = NULL, *firstSel_base = NULL;
180  uint hitresult;
181  bool takeNext = false;
182  int minsel = 0xffffffff, minunsel = 0xffffffff;
183 
184  for (short i = 0; i < hits; i++) {
185  hitresult = buffer[3 + (i * 4)];
186 
187  if (hitresult & BONESEL_ANY) { /* to avoid including objects in selection */
188  Base *base = NULL;
189  bool sel;
190 
191  hitresult &= ~BONESEL_ANY;
192  /* Determine what the current bone is */
193  if (is_editmode == false) {
194  base = ED_armature_base_and_pchan_from_select_buffer(bases, bases_len, hitresult, &pchan);
195  if (pchan != NULL) {
196  if (findunsel) {
197  sel = (pchan->bone->flag & BONE_SELECTED);
198  }
199  else {
200  sel = !(pchan->bone->flag & BONE_SELECTED);
201  }
202 
203  data = pchan;
204  }
205  else {
206  data = NULL;
207  sel = 0;
208  }
209  }
210  else {
211  base = ED_armature_base_and_ebone_from_select_buffer(bases, bases_len, hitresult, &ebone);
212  if (findunsel) {
213  sel = (ebone->flag & BONE_SELECTED);
214  }
215  else {
216  sel = !(ebone->flag & BONE_SELECTED);
217  }
218 
219  data = ebone;
220  }
221 
222  if (data) {
223  if (sel) {
224  if (do_nearest) {
225  if (minsel > buffer[4 * i + 1]) {
226  firstSel = data;
227  firstSel_base = base;
228  minsel = buffer[4 * i + 1];
229  }
230  }
231  else {
232  if (!firstSel) {
233  firstSel = data;
234  firstSel_base = base;
235  }
236  takeNext = 1;
237  }
238  }
239  else {
240  if (do_nearest) {
241  if (minunsel > buffer[4 * i + 1]) {
242  firstunSel = data;
243  firstunSel_base = base;
244  minunsel = buffer[4 * i + 1];
245  }
246  }
247  else {
248  if (!firstunSel) {
249  firstunSel = data;
250  firstunSel_base = base;
251  }
252  if (takeNext) {
253  *r_base = base;
254  return data;
255  }
256  }
257  }
258  }
259  }
260  }
261 
262  if (firstunSel) {
263  *r_base = firstunSel_base;
264  return firstunSel;
265  }
266  *r_base = firstSel_base;
267  return firstSel;
268 }
269 
271  uint bases_len,
272  const uint *buffer,
273  short hits,
274  bool findunsel,
275  bool do_nearest,
276  Base **r_base)
277 {
278  const bool is_editmode = true;
280  is_editmode, bases, bases_len, buffer, hits, findunsel, do_nearest, r_base);
281 }
282 
284  uint bases_len,
285  const uint *buffer,
286  short hits,
287  bool findunsel,
288  bool do_nearest,
289  Base **r_base)
290 {
291  const bool is_editmode = false;
293  is_editmode, bases, bases_len, buffer, hits, findunsel, do_nearest, r_base);
294 }
295 
297  uint bases_len,
298  const uint *buffer,
299  short hits,
300  bool findunsel,
301  bool do_nearest,
302  Base **r_base)
303 {
305  bases, bases_len, buffer, hits, findunsel, do_nearest, r_base);
306  return pchan ? pchan->bone : NULL;
307 }
308 
311 /* -------------------------------------------------------------------- */
326  const bool is_editmode, bContext *C, const int xy[2], bool findunsel, Base **r_base)
327 {
329  ViewContext vc;
330  rcti rect;
332  short hits;
333 
335  BLI_assert((vc.obedit != NULL) == is_editmode);
336 
337  BLI_rcti_init_pt_radius(&rect, xy, 0);
338 
339  /* Don't use hits with this ID, (armature drawing uses this). */
340  const int select_id_ignore = -1;
341 
343  buffer,
344  MAXPICKBUF,
345  &rect,
348  select_id_ignore);
349 
350  *r_base = NULL;
351 
352  if (hits > 0) {
353  uint bases_len = 0;
354  Base **bases;
355 
356  if (vc.obedit != NULL) {
358  vc.v3d,
359  &bases_len,
360  {
361  .object_mode = OB_MODE_EDIT,
362  });
363  }
364  else {
365  bases = BKE_object_pose_base_array_get(vc.view_layer, vc.v3d, &bases_len);
366  }
367 
369  is_editmode, bases, bases_len, buffer, hits, findunsel, true, r_base);
370 
371  MEM_freeN(bases);
372 
373  return bone;
374  }
375  return NULL;
376 }
377 
378 EditBone *ED_armature_pick_ebone(bContext *C, const int xy[2], bool findunsel, Base **r_base)
379 {
380  const bool is_editmode = true;
381  return ed_armature_pick_bone_impl(is_editmode, C, xy, findunsel, r_base);
382 }
383 
384 bPoseChannel *ED_armature_pick_pchan(bContext *C, const int xy[2], bool findunsel, Base **r_base)
385 {
386  const bool is_editmode = false;
387  return ed_armature_pick_bone_impl(is_editmode, C, xy, findunsel, r_base);
388 }
389 
390 Bone *ED_armature_pick_bone(bContext *C, const int xy[2], bool findunsel, Base **r_base)
391 {
392  bPoseChannel *pchan = ED_armature_pick_pchan(C, xy, findunsel, r_base);
393  return pchan ? pchan->bone : NULL;
394 }
395 
398 /* -------------------------------------------------------------------- */
411 static bool armature_select_linked_impl(Object *ob, const bool select, const bool all_forks)
412 {
413  bool changed = false;
414  bArmature *arm = ob->data;
415 
416  /* Implementation note, this flood-fills selected bones with the 'TOUCH' flag,
417  * even though this is a loop-within a loop, walking up the parent chain only touches new bones.
418  * Bones that have been touched are skipped, so the complexity is OK. */
419 
420  enum {
421  /* Bone has been walked over, its LINK value can be read. */
422  TOUCH = (1 << 0),
423  /* When TOUCH has been set, this flag can be checked to see if the bone is connected. */
424  LINK = (1 << 1),
425  };
426 
427 #define CHECK_PARENT(ebone) \
428  (((ebone)->flag & BONE_CONNECTED) && \
429  ((ebone)->parent ? EBONE_SELECTABLE(arm, (ebone)->parent) : false))
430 
431  LISTBASE_FOREACH (EditBone *, ebone, arm->edbo) {
432  ebone->temp.i = 0;
433  }
434 
435  /* Select parents. */
436  LISTBASE_FOREACH (EditBone *, ebone_iter, arm->edbo) {
437  if (ebone_iter->temp.i & TOUCH) {
438  continue;
439  }
440  if ((ebone_iter->flag & BONE_DONE) == 0) {
441  continue;
442  }
443 
444  ebone_iter->temp.i |= TOUCH | LINK;
445 
446  /* We have an un-touched link. */
447  for (EditBone *ebone = ebone_iter; ebone; ebone = CHECK_PARENT(ebone) ? ebone->parent : NULL) {
449  changed = true;
450 
451  if (all_forks) {
452  ebone->temp.i |= (TOUCH | LINK);
453  }
454  else {
455  ebone->temp.i |= TOUCH;
456  }
457  /* Don't walk onto links (messes up 'all_forks' logic). */
458  if (ebone->parent && ebone->parent->temp.i & LINK) {
459  break;
460  }
461  }
462  }
463 
464  /* Select children. */
465  LISTBASE_FOREACH (EditBone *, ebone_iter, arm->edbo) {
466  /* No need to 'touch' this bone as it won't be walked over when scanning up the chain. */
467  if (!CHECK_PARENT(ebone_iter)) {
468  continue;
469  }
470  if (ebone_iter->temp.i & TOUCH) {
471  continue;
472  }
473 
474  /* First check if we're marked. */
475  EditBone *ebone_touched_parent = NULL;
476  for (EditBone *ebone = ebone_iter; ebone; ebone = CHECK_PARENT(ebone) ? ebone->parent : NULL) {
477  if (ebone->temp.i & TOUCH) {
478  ebone_touched_parent = ebone;
479  break;
480  }
481  ebone->temp.i |= TOUCH;
482  }
483 
484  if ((ebone_touched_parent != NULL) && (ebone_touched_parent->temp.i & LINK)) {
485  for (EditBone *ebone = ebone_iter; ebone != ebone_touched_parent; ebone = ebone->parent) {
486  if ((ebone->temp.i & LINK) == 0) {
487  ebone->temp.i |= LINK;
489  changed = true;
490  }
491  }
492  }
493  }
494 
495 #undef CHECK_PARENT
496 
497  if (changed) {
501  }
502 
503  return changed;
504 }
505 
508 /* -------------------------------------------------------------------- */
513 {
514  const bool all_forks = RNA_boolean_get(op->ptr, "all_forks");
515 
516  bool changed_multi = false;
517  ViewLayer *view_layer = CTX_data_view_layer(C);
518  uint objects_len = 0;
520  view_layer, CTX_wm_view3d(C), &objects_len);
521  for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
522  Object *ob = objects[ob_index];
523  bArmature *arm = ob->data;
524 
525  bool found = false;
526  LISTBASE_FOREACH (EditBone *, ebone, arm->edbo) {
527  if (EBONE_VISIBLE(arm, ebone) &&
528  (ebone->flag & (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL))) {
529  ebone->flag |= BONE_DONE;
530  found = true;
531  }
532  else {
533  ebone->flag &= ~BONE_DONE;
534  }
535  }
536 
537  if (found) {
538  if (armature_select_linked_impl(ob, true, all_forks)) {
539  changed_multi = true;
540  }
541  }
542  }
543  MEM_freeN(objects);
544 
545  if (changed_multi) {
547  }
548  return OPERATOR_FINISHED;
549 }
550 
552 {
553  /* identifiers */
554  ot->name = "Select Linked All";
555  ot->idname = "ARMATURE_OT_select_linked";
556  ot->description = "Select all bones linked by parent/child connections to the current selection";
557 
558  /* api callbacks */
561 
562  /* flags */
564 
565  /* Leave disabled by default as this matches pose mode. */
566  RNA_def_boolean(ot->srna, "all_forks", 0, "All Forks", "Follow forks in the parents chain");
567 }
568 
571 /* -------------------------------------------------------------------- */
576 {
577  const bool select = !RNA_boolean_get(op->ptr, "deselect");
578  const bool all_forks = RNA_boolean_get(op->ptr, "all_forks");
579 
582 
583  Base *base = NULL;
584  EditBone *ebone_active = ED_armature_pick_ebone(C, event->mval, true, &base);
585 
586  if (ebone_active == NULL) {
587  return OPERATOR_CANCELLED;
588  }
589 
590  bArmature *arm = base->object->data;
591  if (!EBONE_SELECTABLE(arm, ebone_active)) {
592  return OPERATOR_CANCELLED;
593  }
594 
595  /* Initialize flags. */
596  LISTBASE_FOREACH (EditBone *, ebone, arm->edbo) {
597  ebone->flag &= ~BONE_DONE;
598  }
599  ebone_active->flag |= BONE_DONE;
600 
601  if (armature_select_linked_impl(base->object, select, all_forks)) {
603  }
604 
605  return OPERATOR_FINISHED;
606 }
607 
609 {
611 }
612 
614 {
615  /* identifiers */
616  ot->name = "Select Linked";
617  ot->idname = "ARMATURE_OT_select_linked_pick";
618  ot->description = "(De)select bones linked by parent/child connections under the mouse cursor";
619 
620  /* api callbacks */
621  /* leave 'exec' unset */
624 
625  /* flags */
627 
628  RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "");
629  /* Leave disabled by default as this matches pose mode. */
630  RNA_def_boolean(ot->srna, "all_forks", 0, "All Forks", "Follow forks in the parents chain");
631 }
632 
635 /* -------------------------------------------------------------------- */
639 /* utility function for get_nearest_editbonepoint */
640 static int selectbuffer_ret_hits_12(uint *UNUSED(buffer), const int hits12)
641 {
642  return hits12;
643 }
644 
645 static int selectbuffer_ret_hits_5(uint *buffer, const int hits12, const int hits5)
646 {
647  const int ofs = 4 * hits12;
648  memcpy(buffer, buffer + ofs, 4 * hits5 * sizeof(uint));
649  return hits5;
650 }
651 
652 /* does bones and points */
653 /* note that BONE ROOT only gets drawn for root bones (or without IK) */
655  ViewContext *vc, bool findunsel, bool use_cycle, Base **r_base, int *r_selmask)
656 {
658  struct {
659  uint hitresult;
660  Base *base;
661  EditBone *ebone;
662  } *result = NULL,
663 
664  result_cycle = {.hitresult = -1, .base = NULL, .ebone = NULL},
665  result_bias = {.hitresult = -1, .base = NULL, .ebone = NULL};
666 
667  /* find the bone after the current active bone, so as to bump up its chances in selection.
668  * this way overlapping bones will cycle selection state as with objects. */
669  Object *obedit_orig = vc->obedit;
670  EditBone *ebone_active_orig = ((bArmature *)obedit_orig->data)->act_edbone;
671  if (ebone_active_orig == NULL) {
672  use_cycle = false;
673  }
674 
675  if (use_cycle) {
676  static int last_mval[2] = {-100, -100};
677  if ((len_manhattan_v2v2_int(vc->mval, last_mval) <= WM_EVENT_CURSOR_MOTION_THRESHOLD) == 0) {
678  use_cycle = false;
679  }
680  copy_v2_v2_int(last_mval, vc->mval);
681  }
682 
683  const bool do_nearest = !(XRAY_ACTIVE(vc->v3d) || use_cycle);
684 
685  /* matching logic from 'mixed_bones_object_selectbuffer' */
686  int hits = 0;
687  /* Don't use hits with this ID, (armature drawing uses this). */
688  const int select_id_ignore = -1;
689 
690  /* we _must_ end cache before return, use 'goto cache_end' */
692 
693  {
694  const int select_mode = (do_nearest ? VIEW3D_SELECT_PICK_NEAREST : VIEW3D_SELECT_PICK_ALL);
695  const eV3DSelectObjectFilter select_filter = VIEW3D_SELECT_FILTER_NOP;
696 
697  rcti rect;
698  BLI_rcti_init_pt_radius(&rect, vc->mval, 12);
699  const int hits12 = view3d_opengl_select_with_id_filter(
700  vc, buffer, MAXPICKBUF, &rect, select_mode, select_filter, select_id_ignore);
701 
702  if (hits12 == 1) {
703  hits = selectbuffer_ret_hits_12(buffer, hits12);
704  goto cache_end;
705  }
706  else if (hits12 > 0) {
707  int ofs;
708 
709  ofs = 4 * hits12;
710  BLI_rcti_init_pt_radius(&rect, vc->mval, 5);
711  const int hits5 = view3d_opengl_select_with_id_filter(
712  vc, buffer + ofs, MAXPICKBUF - ofs, &rect, select_mode, select_filter, select_id_ignore);
713 
714  if (hits5 == 1) {
715  hits = selectbuffer_ret_hits_5(buffer, hits12, hits5);
716  goto cache_end;
717  }
718 
719  if (hits5 > 0) {
720  hits = selectbuffer_ret_hits_5(buffer, hits12, hits5);
721  goto cache_end;
722  }
723  else {
724  hits = selectbuffer_ret_hits_12(buffer, hits12);
725  goto cache_end;
726  }
727  }
728  }
729 
730 cache_end:
732 
733  uint bases_len;
735  vc->view_layer, vc->v3d, &bases_len);
736 
737  /* See if there are any selected bones in this group */
738  if (hits > 0) {
739  if (hits == 1) {
740  result_bias.hitresult = buffer[3];
742  bases, bases_len, result_bias.hitresult, &result_bias.ebone);
743  }
744  else {
745  int bias_max = INT_MIN;
746 
747  /* Track Cycle Variables
748  * - Offset is always set to the active bone.
749  * - The object & bone indices subtracted by the 'offset.as_u32' value.
750  * Unsigned subtraction wrapping means we always select the next bone in the cycle.
751  */
752  struct {
753  union {
754  uint32_t as_u32;
755  struct {
756 #ifdef __BIG_ENDIAN__
757  uint16_t ob;
758  uint16_t bone;
759 #else
760  uint16_t bone;
761  uint16_t ob;
762 #endif
763  };
764  } offset, test, best;
765  } cycle_order;
766 
767  if (use_cycle) {
768  bArmature *arm = obedit_orig->data;
769  int ob_index = obedit_orig->runtime.select_id & 0xFFFF;
770  int bone_index = BLI_findindex(arm->edbo, ebone_active_orig);
771  /* Offset from the current active bone, so we cycle onto the next. */
772  cycle_order.offset.ob = ob_index;
773  cycle_order.offset.bone = bone_index;
774  /* The value of the active bone (with offset subtracted, a signal to always overwrite). */
775  cycle_order.best.as_u32 = 0;
776  }
777 
778  for (int i = 0; i < hits; i++) {
779  const uint hitresult = buffer[3 + (i * 4)];
780 
781  Base *base = NULL;
782  EditBone *ebone;
783  base = ED_armature_base_and_ebone_from_select_buffer(bases, bases_len, hitresult, &ebone);
784  /* If this fails, selection code is setting the selection ID's incorrectly. */
785  BLI_assert(base && ebone);
786 
787  /* Prioritized selection. */
788  {
789  int bias;
790  /* clicks on bone points get advantage */
791  if (hitresult & (BONESEL_ROOT | BONESEL_TIP)) {
792  /* but also the unselected one */
793  if (findunsel) {
794  if ((hitresult & BONESEL_ROOT) && (ebone->flag & BONE_ROOTSEL) == 0) {
795  bias = 4;
796  }
797  else if ((hitresult & BONESEL_TIP) && (ebone->flag & BONE_TIPSEL) == 0) {
798  bias = 4;
799  }
800  else {
801  bias = 3;
802  }
803  }
804  else {
805  bias = 4;
806  }
807  }
808  else {
809  /* bone found */
810  if (findunsel) {
811  if ((ebone->flag & BONE_SELECTED) == 0) {
812  bias = 2;
813  }
814  else {
815  bias = 1;
816  }
817  }
818  else {
819  bias = 2;
820  }
821  }
822 
823  if (bias > bias_max) {
824  bias_max = bias;
825 
826  result_bias.hitresult = hitresult;
827  result_bias.base = base;
828  result_bias.ebone = ebone;
829  }
830  }
831 
832  /* Cycle selected items (objects & bones). */
833  if (use_cycle) {
834  cycle_order.test.ob = hitresult & 0xFFFF;
835  cycle_order.test.bone = (hitresult & ~BONESEL_ANY) >> 16;
836  if (ebone == ebone_active_orig) {
837  BLI_assert(cycle_order.test.ob == cycle_order.offset.ob);
838  BLI_assert(cycle_order.test.bone == cycle_order.offset.bone);
839  }
840  /* Subtraction as a single value is needed to support cycling through bones
841  * from multiple objects. So once the last bone is selected,
842  * the bits for the bone index wrap into the object,
843  * causing the next object to be stepped onto. */
844  cycle_order.test.as_u32 -= cycle_order.offset.as_u32;
845 
846  /* Even though this logic avoids stepping onto the active bone,
847  * always set the 'best' value for the first time.
848  * Otherwise ensure the value is the smallest it can be,
849  * relative to the active bone, as long as it's not the active bone. */
850  if ((cycle_order.best.as_u32 == 0) ||
851  (cycle_order.test.as_u32 && (cycle_order.test.as_u32 < cycle_order.best.as_u32))) {
852  cycle_order.best = cycle_order.test;
853  result_cycle.hitresult = hitresult;
854  result_cycle.base = base;
855  result_cycle.ebone = ebone;
856  }
857  }
858  }
859  }
860 
861  result = (use_cycle && result_cycle.ebone) ? &result_cycle : &result_bias;
862 
863  if (result->hitresult != -1) {
864  *r_base = result->base;
865 
866  *r_selmask = 0;
867  if (result->hitresult & BONESEL_ROOT) {
868  *r_selmask |= BONE_ROOTSEL;
869  }
870  if (result->hitresult & BONESEL_TIP) {
871  *r_selmask |= BONE_TIPSEL;
872  }
873  if (result->hitresult & BONESEL_BONE) {
874  *r_selmask |= BONE_SELECTED;
875  }
876  MEM_freeN(bases);
877  return result->ebone;
878  }
879  }
880  *r_selmask = 0;
881  *r_base = NULL;
882  MEM_freeN(bases);
883  return NULL;
884 }
885 
888 /* -------------------------------------------------------------------- */
893 {
894  bArmature *arm = obedit->data;
895  bool changed = false;
896  LISTBASE_FOREACH (EditBone *, ebone, arm->edbo) {
897  if (ebone->flag & (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL)) {
898  ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
899  changed = true;
900  }
901  }
902  return changed;
903 }
904 
906 {
907  bArmature *arm = obedit->data;
908  bool changed = false;
909  LISTBASE_FOREACH (EditBone *, ebone, arm->edbo) {
910  /* first and foremost, bone must be visible and selected */
911  if (EBONE_VISIBLE(arm, ebone)) {
912  if (ebone->flag & (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL)) {
913  ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
914  changed = true;
915  }
916  }
917  }
918 
919  if (changed) {
921  }
922  return changed;
923 }
924 
925 bool ED_armature_edit_deselect_all_multi_ex(struct Base **bases, uint bases_len)
926 {
927  bool changed_multi = false;
928  for (uint base_index = 0; base_index < bases_len; base_index++) {
929  Object *obedit = bases[base_index]->object;
930  changed_multi |= ED_armature_edit_deselect_all(obedit);
931  }
932  return changed_multi;
933 }
934 
936 {
937  bool changed_multi = false;
938  for (uint base_index = 0; base_index < bases_len; base_index++) {
939  Object *obedit = bases[base_index]->object;
940  changed_multi |= ED_armature_edit_deselect_all_visible(obedit);
941  }
942  return changed_multi;
943 }
944 
946 {
948  ViewContext vc;
950  uint bases_len = 0;
952  vc.view_layer, vc.v3d, &bases_len);
953  bool changed_multi = ED_armature_edit_deselect_all_multi_ex(bases, bases_len);
954  MEM_freeN(bases);
955  return changed_multi;
956 }
957 
960 /* -------------------------------------------------------------------- */
965  Base *basact,
966  EditBone *ebone,
967  const int selmask,
968  const bool extend,
969  const bool deselect,
970  const bool toggle)
971 {
972  if (!ebone) {
973  return false;
974  }
975 
976  ViewLayer *view_layer = CTX_data_view_layer(C);
977  View3D *v3d = CTX_wm_view3d(C);
978 
980  bArmature *arm = basact->object->data;
981 
982  if (!EBONE_SELECTABLE(arm, ebone)) {
983  return false;
984  }
985 
986  if (!extend && !deselect && !toggle) {
987  uint bases_len = 0;
989  view_layer, v3d, &bases_len);
990  ED_armature_edit_deselect_all_multi_ex(bases, bases_len);
991  MEM_freeN(bases);
992  }
993 
994  /* By definition the non-root connected bones have no root point drawn,
995  * so a root selection needs to be delivered to the parent tip. */
996 
997  if (selmask & BONE_SELECTED) {
998  if (ebone->parent && (ebone->flag & BONE_CONNECTED)) {
999  /* Bone is in a chain. */
1000  if (extend) {
1001  /* Select this bone. */
1002  ebone->flag |= BONE_TIPSEL;
1003  ebone->parent->flag |= BONE_TIPSEL;
1004  }
1005  else if (deselect) {
1006  /* Deselect this bone. */
1007  ebone->flag &= ~(BONE_TIPSEL | BONE_SELECTED);
1008  /* Only deselect parent tip if it is not selected. */
1009  if (!(ebone->parent->flag & BONE_SELECTED)) {
1010  ebone->parent->flag &= ~BONE_TIPSEL;
1011  }
1012  }
1013  else if (toggle) {
1014  /* Toggle inverts this bone's selection. */
1015  if (ebone->flag & BONE_SELECTED) {
1016  /* Deselect this bone. */
1017  ebone->flag &= ~(BONE_TIPSEL | BONE_SELECTED);
1018  /* Only deselect parent tip if it is not selected. */
1019  if (!(ebone->parent->flag & BONE_SELECTED)) {
1020  ebone->parent->flag &= ~BONE_TIPSEL;
1021  }
1022  }
1023  else {
1024  /* Select this bone. */
1025  ebone->flag |= BONE_TIPSEL;
1026  ebone->parent->flag |= BONE_TIPSEL;
1027  }
1028  }
1029  else {
1030  /* Select this bone. */
1031  ebone->flag |= BONE_TIPSEL;
1032  ebone->parent->flag |= BONE_TIPSEL;
1033  }
1034  }
1035  else {
1036  if (extend) {
1037  ebone->flag |= (BONE_TIPSEL | BONE_ROOTSEL);
1038  }
1039  else if (deselect) {
1040  ebone->flag &= ~(BONE_TIPSEL | BONE_ROOTSEL);
1041  }
1042  else if (toggle) {
1043  /* Toggle inverts this bone's selection. */
1044  if (ebone->flag & BONE_SELECTED) {
1045  ebone->flag &= ~(BONE_TIPSEL | BONE_ROOTSEL);
1046  }
1047  else {
1048  ebone->flag |= (BONE_TIPSEL | BONE_ROOTSEL);
1049  }
1050  }
1051  else {
1052  ebone->flag |= (BONE_TIPSEL | BONE_ROOTSEL);
1053  }
1054  }
1055  }
1056  else {
1057  if (extend) {
1058  ebone->flag |= selmask;
1059  }
1060  else if (deselect) {
1061  ebone->flag &= ~selmask;
1062  }
1063  else if (toggle && (ebone->flag & selmask)) {
1064  ebone->flag &= ~selmask;
1065  }
1066  else {
1067  ebone->flag |= selmask;
1068  }
1069  }
1070 
1072 
1073  /* Then now check for active status. */
1074  if (ED_armature_ebone_selectflag_get(ebone)) {
1075  arm->act_edbone = ebone;
1076  }
1077 
1078  if (view_layer->basact != basact) {
1079  ED_object_base_activate(C, basact);
1080  }
1081 
1084  return true;
1085 }
1086 
1087 /* context: editmode armature in view3d */
1089  bContext *C, const int mval[2], bool extend, bool deselect, bool toggle)
1090 {
1092  ViewContext vc;
1093  EditBone *nearBone = NULL;
1094  int selmask;
1095  Base *basact = NULL;
1096 
1098  vc.mval[0] = mval[0];
1099  vc.mval[1] = mval[1];
1100 
1101  nearBone = get_nearest_editbonepoint(&vc, true, true, &basact, &selmask);
1102  return ED_armature_edit_select_pick_bone(C, basact, nearBone, selmask, extend, deselect, toggle);
1103 }
1104 
1107 /* -------------------------------------------------------------------- */
1114  EditBone *ebone,
1115  const eSelectOp sel_op,
1116  int is_ignore_flag,
1117  int is_inside_flag)
1118 {
1119  BLI_assert(!(is_ignore_flag & ~(BONESEL_ROOT | BONESEL_TIP)));
1120  BLI_assert(!(is_inside_flag & ~(BONESEL_ROOT | BONESEL_TIP | BONESEL_BONE)));
1121  BLI_assert(EBONE_VISIBLE(arm, ebone));
1122  bool changed = false;
1123  bool is_point_done = false;
1124  int points_proj_tot = 0;
1125  BLI_assert(ebone->flag == ebone->temp.i);
1126  const int ebone_flag_prev = ebone->flag;
1127 
1128  if ((is_ignore_flag & BONE_ROOTSEL) == 0) {
1129  points_proj_tot++;
1130  const bool is_select = ebone->flag & BONE_ROOTSEL;
1131  const bool is_inside = is_inside_flag & BONESEL_ROOT;
1132  const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
1133  if (sel_op_result != -1) {
1134  if (sel_op_result == 0 || EBONE_SELECTABLE(arm, ebone)) {
1135  SET_FLAG_FROM_TEST(ebone->flag, sel_op_result, BONE_ROOTSEL);
1136  }
1137  }
1138  is_point_done |= is_inside;
1139  }
1140 
1141  if ((is_ignore_flag & BONE_TIPSEL) == 0) {
1142  points_proj_tot++;
1143  const bool is_select = ebone->flag & BONE_TIPSEL;
1144  const bool is_inside = is_inside_flag & BONESEL_TIP;
1145  const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
1146  if (sel_op_result != -1) {
1147  if (sel_op_result == 0 || EBONE_SELECTABLE(arm, ebone)) {
1148  SET_FLAG_FROM_TEST(ebone->flag, sel_op_result, BONE_TIPSEL);
1149  }
1150  }
1151  is_point_done |= is_inside;
1152  }
1153 
1154  /* if one of points selected, we skip the bone itself */
1155  if ((is_point_done == false) && (points_proj_tot == 2)) {
1156  const bool is_select = ebone->flag & BONE_SELECTED;
1157  {
1158  const bool is_inside = is_inside_flag & BONESEL_BONE;
1159  const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
1160  if (sel_op_result != -1) {
1161  if (sel_op_result == 0 || EBONE_SELECTABLE(arm, ebone)) {
1163  ebone->flag, sel_op_result, BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL);
1164  }
1165  }
1166  }
1167 
1168  changed = true;
1169  }
1170  changed |= is_point_done;
1171 
1172  if (ebone_flag_prev != ebone->flag) {
1173  ebone->temp.i = ebone->flag;
1174  ebone->flag = ebone_flag_prev;
1175  ebone->flag = ebone_flag_prev | BONE_DONE;
1176  changed = true;
1177  }
1178 
1179  return changed;
1180 }
1181 
1195 {
1196  bool changed = false;
1197 
1198  /* Initialize flags. */
1199  {
1200  LISTBASE_FOREACH (EditBone *, ebone, arm->edbo) {
1201 
1202  /* Flush the parent flag to this bone
1203  * so we don't need to check the parent when adjusting the selection. */
1204  if ((ebone->flag & BONE_CONNECTED) && ebone->parent) {
1205  if (ebone->parent->flag & BONE_TIPSEL) {
1206  ebone->flag |= BONE_ROOTSEL;
1207  }
1208  else {
1209  ebone->flag &= ~BONE_ROOTSEL;
1210  }
1211 
1212  /* Flush the 'temp.i' flag. */
1213  if (ebone->parent->temp.i & BONESEL_TIP) {
1214  ebone->temp.i |= BONESEL_ROOT;
1215  }
1216  }
1217  ebone->flag &= ~BONE_DONE;
1218  }
1219  }
1220 
1221  /* Apply selection from bone selection flags. */
1222  LISTBASE_FOREACH (EditBone *, ebone, arm->edbo) {
1223  if (ebone->temp.i != 0) {
1224  int is_ignore_flag = ((ebone->temp.i << 16) & (BONESEL_ROOT | BONESEL_TIP));
1225  int is_inside_flag = (ebone->temp.i & (BONESEL_ROOT | BONESEL_TIP | BONESEL_BONE));
1226 
1227  /* Use as previous bone flag from now on. */
1228  ebone->temp.i = ebone->flag;
1229 
1230  /* When there is a partial selection without both endpoints, only select an endpoint. */
1231  if ((is_inside_flag & BONESEL_BONE) &&
1232  ELEM(is_inside_flag & (BONESEL_ROOT | BONESEL_TIP), BONESEL_ROOT, BONESEL_TIP)) {
1233  is_inside_flag &= ~BONESEL_BONE;
1234  }
1235 
1236  changed |= armature_edit_select_op_apply(arm, ebone, sel_op, is_ignore_flag, is_inside_flag);
1237  }
1238  }
1239 
1240  if (changed) {
1241  /* Cleanup flags. */
1242  LISTBASE_FOREACH (EditBone *, ebone, arm->edbo) {
1243  if (ebone->flag & BONE_DONE) {
1244  SWAP(int, ebone->temp.i, ebone->flag);
1245  ebone->flag |= BONE_DONE;
1246  if ((ebone->flag & BONE_CONNECTED) && ebone->parent) {
1247  if ((ebone->parent->flag & BONE_DONE) == 0) {
1248  /* Checked below. */
1249  ebone->parent->temp.i = ebone->parent->flag;
1250  }
1251  }
1252  }
1253  }
1254 
1255  LISTBASE_FOREACH (EditBone *, ebone, arm->edbo) {
1256  if (ebone->flag & BONE_DONE) {
1257  if ((ebone->flag & BONE_CONNECTED) && ebone->parent) {
1258  bool is_parent_tip_changed = (ebone->parent->flag & BONE_TIPSEL) !=
1259  (ebone->parent->temp.i & BONE_TIPSEL);
1260  if ((ebone->temp.i & BONE_ROOTSEL) == 0) {
1261  if ((ebone->flag & BONE_ROOTSEL) != 0) {
1262  ebone->parent->flag |= BONE_TIPSEL;
1263  }
1264  }
1265  else {
1266  if ((ebone->flag & BONE_ROOTSEL) == 0) {
1267  ebone->parent->flag &= ~BONE_TIPSEL;
1268  }
1269  }
1270 
1271  if (is_parent_tip_changed == false) {
1272  /* Keep tip selected if the parent remains selected. */
1273  if (ebone->parent->flag & BONE_SELECTED) {
1274  ebone->parent->flag |= BONE_TIPSEL;
1275  }
1276  }
1277  }
1278  ebone->flag &= ~BONE_DONE;
1279  }
1280  }
1281 
1284  }
1285 
1286  return changed;
1287 }
1288 
1291 /* -------------------------------------------------------------------- */
1296 {
1297  int action = RNA_enum_get(op->ptr, "action");
1298 
1299  if (action == SEL_TOGGLE) {
1300  /* Determine if there are any selected bones
1301  * And therefore whether we are selecting or deselecting */
1302  action = SEL_SELECT;
1303  CTX_DATA_BEGIN (C, EditBone *, ebone, visible_bones) {
1304  if (ebone->flag & (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL)) {
1305  action = SEL_DESELECT;
1306  break;
1307  }
1308  }
1309  CTX_DATA_END;
1310  }
1311 
1312  /* Set the flags. */
1313  CTX_DATA_BEGIN (C, EditBone *, ebone, visible_bones) {
1314  /* ignore bone if selection can't change */
1315  switch (action) {
1316  case SEL_SELECT:
1317  if ((ebone->flag & BONE_UNSELECTABLE) == 0) {
1318  ebone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
1319  if (ebone->parent) {
1320  ebone->parent->flag |= BONE_TIPSEL;
1321  }
1322  }
1323  break;
1324  case SEL_DESELECT:
1325  ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
1326  break;
1327  case SEL_INVERT:
1328  if (ebone->flag & BONE_SELECTED) {
1329  ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
1330  }
1331  else {
1332  if ((ebone->flag & BONE_UNSELECTABLE) == 0) {
1333  ebone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
1334  if (ebone->parent) {
1335  ebone->parent->flag |= BONE_TIPSEL;
1336  }
1337  }
1338  }
1339  break;
1340  }
1341  }
1342  CTX_DATA_END;
1343 
1345 
1347 
1348  /* Tagging only one object to refresh drawing. */
1349  Object *obedit = CTX_data_edit_object(C);
1351 
1352  return OPERATOR_FINISHED;
1353 }
1354 
1356 {
1357  /* identifiers */
1358  ot->name = "(De)select All";
1359  ot->idname = "ARMATURE_OT_select_all";
1360  ot->description = "Toggle selection status of all bones";
1361 
1362  /* api callbacks */
1365 
1366  /* flags */
1368 
1370 }
1371 
1374 /* -------------------------------------------------------------------- */
1378 static void armature_select_more(bArmature *arm, EditBone *ebone)
1379 {
1380  if ((EBONE_PREV_FLAG_GET(ebone) & (BONE_ROOTSEL | BONE_TIPSEL)) != 0) {
1381  if (EBONE_SELECTABLE(arm, ebone)) {
1382  ED_armature_ebone_select_set(ebone, true);
1383  }
1384  }
1385 
1386  if (ebone->parent && (ebone->flag & BONE_CONNECTED)) {
1387  /* to parent */
1388  if ((EBONE_PREV_FLAG_GET(ebone) & BONE_ROOTSEL) != 0) {
1389  if (EBONE_SELECTABLE(arm, ebone->parent)) {
1392  }
1393  }
1394 
1395  /* from parent (difference from select less) */
1396  if ((EBONE_PREV_FLAG_GET(ebone->parent) & BONE_TIPSEL) != 0) {
1397  if (EBONE_SELECTABLE(arm, ebone)) {
1399  }
1400  }
1401  }
1402 }
1403 
1404 static void armature_select_less(bArmature *UNUSED(arm), EditBone *ebone)
1405 {
1406  if ((EBONE_PREV_FLAG_GET(ebone) & (BONE_ROOTSEL | BONE_TIPSEL)) !=
1407  (BONE_ROOTSEL | BONE_TIPSEL)) {
1408  ED_armature_ebone_select_set(ebone, false);
1409  }
1410 
1411  if (ebone->parent && (ebone->flag & BONE_CONNECTED)) {
1412  /* to parent */
1413  if ((EBONE_PREV_FLAG_GET(ebone) & BONE_SELECTED) == 0) {
1415  }
1416 
1417  /* from parent (difference from select more) */
1418  if ((EBONE_PREV_FLAG_GET(ebone->parent) & BONE_SELECTED) == 0) {
1420  }
1421  }
1422 }
1423 
1424 static void armature_select_more_less(Object *ob, bool more)
1425 {
1426  bArmature *arm = (bArmature *)ob->data;
1427  EditBone *ebone;
1428 
1429  /* XXX, eventually we shouldn't need this - campbell */
1431 
1432  /* count bones & store selection state */
1433  for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
1435  }
1436 
1437  /* do selection */
1438  for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
1439  if (EBONE_VISIBLE(arm, ebone)) {
1440  if (more) {
1441  armature_select_more(arm, ebone);
1442  }
1443  else {
1444  armature_select_less(arm, ebone);
1445  }
1446  }
1447  }
1448 
1449  for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
1450  if (EBONE_VISIBLE(arm, ebone)) {
1451  if (more == false) {
1452  if (ebone->flag & BONE_SELECTED) {
1453  ED_armature_ebone_select_set(ebone, true);
1454  }
1455  }
1456  }
1457  ebone->temp.p = NULL;
1458  }
1459 
1461 }
1462 
1465 /* -------------------------------------------------------------------- */
1470 {
1471  ViewLayer *view_layer = CTX_data_view_layer(C);
1472  uint objects_len = 0;
1474  view_layer, CTX_wm_view3d(C), &objects_len);
1475  for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
1476  Object *ob = objects[ob_index];
1477  armature_select_more_less(ob, true);
1480  }
1481  MEM_freeN(objects);
1482 
1484  return OPERATOR_FINISHED;
1485 }
1486 
1488 {
1489  /* identifiers */
1490  ot->name = "Select More";
1491  ot->idname = "ARMATURE_OT_select_more";
1492  ot->description = "Select those bones connected to the initial selection";
1493 
1494  /* api callbacks */
1497 
1498  /* flags */
1500 }
1501 
1504 /* -------------------------------------------------------------------- */
1509 {
1510  ViewLayer *view_layer = CTX_data_view_layer(C);
1511  uint objects_len = 0;
1513  view_layer, CTX_wm_view3d(C), &objects_len);
1514  for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
1515  Object *ob = objects[ob_index];
1516  armature_select_more_less(ob, false);
1519  }
1520  MEM_freeN(objects);
1521 
1523  return OPERATOR_FINISHED;
1524 }
1525 
1527 {
1528  /* identifiers */
1529  ot->name = "Select Less";
1530  ot->idname = "ARMATURE_OT_select_less";
1531  ot->description = "Deselect those bones at the boundary of each selection region";
1532 
1533  /* api callbacks */
1536 
1537  /* flags */
1539 }
1540 
1543 /* -------------------------------------------------------------------- */
1547 enum {
1558 };
1559 
1561  {SIMEDBONE_CHILDREN, "CHILDREN", 0, "Children", ""},
1562  {SIMEDBONE_CHILDREN_IMMEDIATE, "CHILDREN_IMMEDIATE", 0, "Immediate Children", ""},
1563  {SIMEDBONE_SIBLINGS, "SIBLINGS", 0, "Siblings", ""},
1564  {SIMEDBONE_LENGTH, "LENGTH", 0, "Length", ""},
1565  {SIMEDBONE_DIRECTION, "DIRECTION", 0, "Direction (Y Axis)", ""},
1566  {SIMEDBONE_PREFIX, "PREFIX", 0, "Prefix", ""},
1567  {SIMEDBONE_SUFFIX, "SUFFIX", 0, "Suffix", ""},
1568  {SIMEDBONE_LAYER, "LAYER", 0, "Layer", ""},
1569  {SIMEDBONE_GROUP, "GROUP", 0, "Group", ""},
1570  {SIMEDBONE_SHAPE, "SHAPE", 0, "Shape", ""},
1571  {0, NULL, 0, NULL, NULL},
1572 };
1573 
1575 {
1576  float v1[3], v2[3];
1577  mul_v3_mat3_m4v3(v1, ob->obmat, ebone->head);
1578  mul_v3_mat3_m4v3(v2, ob->obmat, ebone->tail);
1579  return len_squared_v3v3(v1, v2);
1580 }
1581 
1582 static void select_similar_length(bContext *C, const float thresh)
1583 {
1584  ViewLayer *view_layer = CTX_data_view_layer(C);
1585  Object *ob_act = CTX_data_edit_object(C);
1586  EditBone *ebone_act = CTX_data_active_bone(C);
1587 
1588  /* Thresh is always relative to current length. */
1589  const float len = bone_length_squared_worldspace_get(ob_act, ebone_act);
1590  const float len_min = len / (1.0f + (thresh - FLT_EPSILON));
1591  const float len_max = len * (1.0f + (thresh + FLT_EPSILON));
1592 
1593  uint objects_len = 0;
1595  view_layer, CTX_wm_view3d(C), &objects_len);
1596  for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
1597  Object *ob = objects[ob_index];
1598  bArmature *arm = ob->data;
1599  bool changed = false;
1600 
1601  LISTBASE_FOREACH (EditBone *, ebone, arm->edbo) {
1602  if (EBONE_SELECTABLE(arm, ebone)) {
1603  const float len_iter = bone_length_squared_worldspace_get(ob, ebone);
1604  if ((len_iter > len_min) && (len_iter < len_max)) {
1605  ED_armature_ebone_select_set(ebone, true);
1606  changed = true;
1607  }
1608  }
1609  }
1610 
1611  if (changed) {
1614  }
1615  }
1616  MEM_freeN(objects);
1617 }
1618 
1619 static void bone_direction_worldspace_get(Object *ob, EditBone *ebone, float *r_dir)
1620 {
1621  float v1[3], v2[3];
1622  copy_v3_v3(v1, ebone->head);
1623  copy_v3_v3(v2, ebone->tail);
1624 
1625  mul_m4_v3(ob->obmat, v1);
1626  mul_m4_v3(ob->obmat, v2);
1627 
1628  sub_v3_v3v3(r_dir, v1, v2);
1629  normalize_v3(r_dir);
1630 }
1631 
1632 static void select_similar_direction(bContext *C, const float thresh)
1633 {
1634  ViewLayer *view_layer = CTX_data_view_layer(C);
1635  Object *ob_act = CTX_data_edit_object(C);
1636  EditBone *ebone_act = CTX_data_active_bone(C);
1637 
1638  float dir_act[3];
1639  bone_direction_worldspace_get(ob_act, ebone_act, dir_act);
1640 
1641  uint objects_len = 0;
1643  view_layer, CTX_wm_view3d(C), &objects_len);
1644  for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
1645  Object *ob = objects[ob_index];
1646  bArmature *arm = ob->data;
1647  bool changed = false;
1648 
1649  LISTBASE_FOREACH (EditBone *, ebone, arm->edbo) {
1650  if (EBONE_SELECTABLE(arm, ebone)) {
1651  float dir[3];
1652  bone_direction_worldspace_get(ob, ebone, dir);
1653 
1654  if (angle_v3v3(dir_act, dir) / (float)M_PI < (thresh + FLT_EPSILON)) {
1655  ED_armature_ebone_select_set(ebone, true);
1656  changed = true;
1657  }
1658  }
1659  }
1660 
1661  if (changed) {
1665  }
1666  }
1667  MEM_freeN(objects);
1668 }
1669 
1671 {
1672  ViewLayer *view_layer = CTX_data_view_layer(C);
1673  EditBone *ebone_act = CTX_data_active_bone(C);
1674 
1675  uint objects_len = 0;
1677  view_layer, CTX_wm_view3d(C), &objects_len);
1678  for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
1679  Object *ob = objects[ob_index];
1680  bArmature *arm = ob->data;
1681  bool changed = false;
1682 
1683  LISTBASE_FOREACH (EditBone *, ebone, arm->edbo) {
1684  if (EBONE_SELECTABLE(arm, ebone)) {
1685  if (ebone->layer & ebone_act->layer) {
1686  ED_armature_ebone_select_set(ebone, true);
1687  changed = true;
1688  }
1689  }
1690  }
1691 
1692  if (changed) {
1695  }
1696  }
1697  MEM_freeN(objects);
1698 }
1699 
1701 {
1702  ViewLayer *view_layer = CTX_data_view_layer(C);
1703  EditBone *ebone_act = CTX_data_active_bone(C);
1704 
1705  char body_tmp[MAXBONENAME];
1706  char prefix_act[MAXBONENAME];
1707 
1708  BLI_string_split_prefix(ebone_act->name, prefix_act, body_tmp, sizeof(ebone_act->name));
1709 
1710  if (prefix_act[0] == '\0') {
1711  return;
1712  }
1713 
1714  uint objects_len = 0;
1716  view_layer, CTX_wm_view3d(C), &objects_len);
1717  for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
1718  Object *ob = objects[ob_index];
1719  bArmature *arm = ob->data;
1720  bool changed = false;
1721 
1722  /* Find matches */
1723  LISTBASE_FOREACH (EditBone *, ebone, arm->edbo) {
1724  if (EBONE_SELECTABLE(arm, ebone)) {
1725  char prefix_other[MAXBONENAME];
1726  BLI_string_split_prefix(ebone->name, prefix_other, body_tmp, sizeof(ebone->name));
1727  if (STREQ(prefix_act, prefix_other)) {
1728  ED_armature_ebone_select_set(ebone, true);
1729  changed = true;
1730  }
1731  }
1732  }
1733 
1734  if (changed) {
1737  }
1738  }
1739  MEM_freeN(objects);
1740 }
1741 
1743 {
1744  ViewLayer *view_layer = CTX_data_view_layer(C);
1745  EditBone *ebone_act = CTX_data_active_bone(C);
1746 
1747  char body_tmp[MAXBONENAME];
1748  char suffix_act[MAXBONENAME];
1749 
1750  BLI_string_split_suffix(ebone_act->name, body_tmp, suffix_act, sizeof(ebone_act->name));
1751 
1752  if (suffix_act[0] == '\0') {
1753  return;
1754  }
1755 
1756  uint objects_len = 0;
1758  view_layer, CTX_wm_view3d(C), &objects_len);
1759  for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
1760  Object *ob = objects[ob_index];
1761  bArmature *arm = ob->data;
1762  bool changed = false;
1763 
1764  /* Find matches */
1765  LISTBASE_FOREACH (EditBone *, ebone, arm->edbo) {
1766  if (EBONE_SELECTABLE(arm, ebone)) {
1767  char suffix_other[MAXBONENAME];
1768  BLI_string_split_suffix(ebone->name, body_tmp, suffix_other, sizeof(ebone->name));
1769  if (STREQ(suffix_act, suffix_other)) {
1770  ED_armature_ebone_select_set(ebone, true);
1771  changed = true;
1772  }
1773  }
1774  }
1775 
1776  if (changed) {
1779  }
1780  }
1781  MEM_freeN(objects);
1782 }
1783 
1785 static void select_similar_data_pchan(bContext *C, const size_t bytes_size, const int offset)
1786 {
1787  Object *obedit = CTX_data_edit_object(C);
1788  bArmature *arm = obedit->data;
1789  EditBone *ebone_act = CTX_data_active_bone(C);
1790 
1791  const bPoseChannel *pchan_active = BKE_pose_channel_find_name(obedit->pose, ebone_act->name);
1792 
1793  /* This will mostly happen for corner cases where the user tried to access this
1794  * before having any valid pose data for the armature. */
1795  if (pchan_active == NULL) {
1796  return;
1797  }
1798 
1799  const char *data_active = (const char *)POINTER_OFFSET(pchan_active, offset);
1800  LISTBASE_FOREACH (EditBone *, ebone, arm->edbo) {
1801  if (EBONE_SELECTABLE(arm, ebone)) {
1802  const bPoseChannel *pchan = BKE_pose_channel_find_name(obedit->pose, ebone->name);
1803  if (pchan) {
1804  const char *data_test = (const char *)POINTER_OFFSET(pchan, offset);
1805  if (memcmp(data_active, data_test, bytes_size) == 0) {
1806  ED_armature_ebone_select_set(ebone, true);
1807  }
1808  }
1809  }
1810  }
1811 
1814 }
1815 
1816 static void is_ancestor(EditBone *bone, EditBone *ancestor)
1817 {
1818  if (ELEM(bone->temp.ebone, ancestor, NULL)) {
1819  return;
1820  }
1821 
1822  if (!ELEM(bone->temp.ebone->temp.ebone, NULL, ancestor)) {
1823  is_ancestor(bone->temp.ebone, ancestor);
1824  }
1825 
1826  bone->temp.ebone = bone->temp.ebone->temp.ebone;
1827 }
1828 
1830 {
1831  Object *obedit = CTX_data_edit_object(C);
1832  bArmature *arm = obedit->data;
1833  EditBone *ebone_act = CTX_data_active_bone(C);
1834 
1835  LISTBASE_FOREACH (EditBone *, ebone_iter, arm->edbo) {
1836  ebone_iter->temp.ebone = ebone_iter->parent;
1837  }
1838 
1839  LISTBASE_FOREACH (EditBone *, ebone_iter, arm->edbo) {
1840  is_ancestor(ebone_iter, ebone_act);
1841 
1842  if (ebone_iter->temp.ebone == ebone_act && EBONE_SELECTABLE(arm, ebone_iter)) {
1843  ED_armature_ebone_select_set(ebone_iter, true);
1844  }
1845  }
1846 
1849 }
1850 
1852 {
1853  Object *obedit = CTX_data_edit_object(C);
1854  bArmature *arm = obedit->data;
1855  EditBone *ebone_act = CTX_data_active_bone(C);
1856 
1857  LISTBASE_FOREACH (EditBone *, ebone_iter, arm->edbo) {
1858  if (ebone_iter->parent == ebone_act && EBONE_SELECTABLE(arm, ebone_iter)) {
1859  ED_armature_ebone_select_set(ebone_iter, true);
1860  }
1861  }
1862 
1865 }
1866 
1868 {
1869  Object *obedit = CTX_data_edit_object(C);
1870  bArmature *arm = obedit->data;
1871  EditBone *ebone_act = CTX_data_active_bone(C);
1872 
1873  if (ebone_act->parent == NULL) {
1874  return;
1875  }
1876 
1877  LISTBASE_FOREACH (EditBone *, ebone_iter, arm->edbo) {
1878  if (ebone_iter->parent == ebone_act->parent && EBONE_SELECTABLE(arm, ebone_iter)) {
1879  ED_armature_ebone_select_set(ebone_iter, true);
1880  }
1881  }
1882 
1885 }
1886 
1888 {
1889  /* Get props */
1890  int type = RNA_enum_get(op->ptr, "type");
1891  float thresh = RNA_float_get(op->ptr, "threshold");
1892 
1893  /* Check for active bone */
1894  if (CTX_data_active_bone(C) == NULL) {
1895  BKE_report(op->reports, RPT_ERROR, "Operation requires an active bone");
1896  return OPERATOR_CANCELLED;
1897  }
1898 
1899 #define STRUCT_SIZE_AND_OFFSET(_struct, _member) \
1900  sizeof(((_struct *)NULL)->_member), offsetof(_struct, _member)
1901 
1902  switch (type) {
1903  case SIMEDBONE_CHILDREN:
1905  break;
1908  break;
1909  case SIMEDBONE_SIBLINGS:
1911  break;
1912  case SIMEDBONE_LENGTH:
1913  select_similar_length(C, thresh);
1914  break;
1915  case SIMEDBONE_DIRECTION:
1916  select_similar_direction(C, thresh);
1917  break;
1918  case SIMEDBONE_PREFIX:
1920  break;
1921  case SIMEDBONE_SUFFIX:
1923  break;
1924  case SIMEDBONE_LAYER:
1926  break;
1927  case SIMEDBONE_GROUP:
1929  break;
1930  case SIMEDBONE_SHAPE:
1932  break;
1933  }
1934 
1935 #undef STRUCT_SIZE_AND_OFFSET
1936 
1938 
1939  return OPERATOR_FINISHED;
1940 }
1941 
1943 {
1944  /* identifiers */
1945  ot->name = "Select Similar";
1946  ot->idname = "ARMATURE_OT_select_similar";
1947 
1948  /* callback functions */
1952  ot->description = "Select similar bones by property types";
1953 
1954  /* flags */
1956 
1957  /* properties */
1958  ot->prop = RNA_def_enum(ot->srna, "type", prop_similar_types, SIMEDBONE_LENGTH, "Type", "");
1959  RNA_def_float(ot->srna, "threshold", 0.1f, 0.0f, 1.0f, "Threshold", "", 0.0f, 1.0f);
1960 }
1961 
1964 /* -------------------------------------------------------------------- */
1968 /* No need to convert to multi-objects. Just like we keep the non-active bones
1969  * selected we then keep the non-active objects untouched (selected/unselected). */
1971 {
1972  Object *ob = CTX_data_edit_object(C);
1973  EditBone *ebone_active;
1974  int direction = RNA_enum_get(op->ptr, "direction");
1975  const bool add_to_sel = RNA_boolean_get(op->ptr, "extend");
1976  bool changed = false;
1977  bArmature *arm = (bArmature *)ob->data;
1978 
1979  ebone_active = arm->act_edbone;
1980  if (ebone_active == NULL) {
1981  return OPERATOR_CANCELLED;
1982  }
1983 
1984  if (direction == BONE_SELECT_PARENT) {
1985  if (ebone_active->parent) {
1986  EditBone *ebone_parent;
1987 
1988  ebone_parent = ebone_active->parent;
1989 
1990  if (EBONE_SELECTABLE(arm, ebone_parent)) {
1991  arm->act_edbone = ebone_parent;
1992 
1993  if (!add_to_sel) {
1994  ED_armature_ebone_select_set(ebone_active, false);
1995  }
1996  ED_armature_ebone_select_set(ebone_parent, true);
1997 
1998  changed = true;
1999  }
2000  }
2001  }
2002  else { /* BONE_SELECT_CHILD */
2003  EditBone *ebone_iter, *ebone_child = NULL;
2004  int pass;
2005 
2006  /* first pass, only connected bones (the logical direct child) */
2007  for (pass = 0; pass < 2 && (ebone_child == NULL); pass++) {
2008  for (ebone_iter = arm->edbo->first; ebone_iter; ebone_iter = ebone_iter->next) {
2009  /* possible we have multiple children, some invisible */
2010  if (EBONE_SELECTABLE(arm, ebone_iter)) {
2011  if (ebone_iter->parent == ebone_active) {
2012  if ((pass == 1) || (ebone_iter->flag & BONE_CONNECTED)) {
2013  ebone_child = ebone_iter;
2014  break;
2015  }
2016  }
2017  }
2018  }
2019  }
2020 
2021  if (ebone_child) {
2022  arm->act_edbone = ebone_child;
2023 
2024  if (!add_to_sel) {
2025  ED_armature_ebone_select_set(ebone_active, false);
2026  }
2027  ED_armature_ebone_select_set(ebone_child, true);
2028 
2029  changed = true;
2030  }
2031  }
2032 
2033  if (changed == false) {
2034  return OPERATOR_CANCELLED;
2035  }
2036 
2038 
2040 
2043 
2044  return OPERATOR_FINISHED;
2045 }
2046 
2048 {
2049  static const EnumPropertyItem direction_items[] = {
2050  {BONE_SELECT_PARENT, "PARENT", 0, "Select Parent", ""},
2051  {BONE_SELECT_CHILD, "CHILD", 0, "Select Child", ""},
2052  {0, NULL, 0, NULL, NULL},
2053  };
2054 
2055  /* identifiers */
2056  ot->name = "Select Hierarchy";
2057  ot->idname = "ARMATURE_OT_select_hierarchy";
2058  ot->description = "Select immediate parent/children of selected bones";
2059 
2060  /* api callbacks */
2063 
2064  /* flags */
2066 
2067  /* props */
2068  RNA_def_enum(ot->srna, "direction", direction_items, BONE_SELECT_PARENT, "Direction", "");
2069  RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
2070 }
2071 
2074 /* -------------------------------------------------------------------- */
2082 {
2083  ViewLayer *view_layer = CTX_data_view_layer(C);
2084  const bool active_only = RNA_boolean_get(op->ptr, "only_active");
2085  const bool extend = RNA_boolean_get(op->ptr, "extend");
2086 
2087  uint objects_len = 0;
2089  view_layer, CTX_wm_view3d(C), &objects_len);
2090  for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
2091  Object *ob = objects[ob_index];
2092  bArmature *arm = ob->data;
2093 
2094  EditBone *ebone, *ebone_mirror_act = NULL;
2095 
2096  for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
2097  const int flag = ED_armature_ebone_selectflag_get(ebone);
2098  EBONE_PREV_FLAG_SET(ebone, flag);
2099  }
2100 
2101  for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
2102  if (EBONE_SELECTABLE(arm, ebone)) {
2103  EditBone *ebone_mirror;
2104  int flag_new = extend ? EBONE_PREV_FLAG_GET(ebone) : 0;
2105 
2106  if ((ebone_mirror = ED_armature_ebone_get_mirrored(arm->edbo, ebone)) &&
2107  (EBONE_VISIBLE(arm, ebone_mirror))) {
2108  const int flag_mirror = EBONE_PREV_FLAG_GET(ebone_mirror);
2109  flag_new |= flag_mirror;
2110 
2111  if (ebone == arm->act_edbone) {
2112  ebone_mirror_act = ebone_mirror;
2113  }
2114 
2115  /* skip all but the active or its mirror */
2116  if (active_only && !ELEM(arm->act_edbone, ebone, ebone_mirror)) {
2117  continue;
2118  }
2119  }
2120 
2121  ED_armature_ebone_selectflag_set(ebone, flag_new);
2122  }
2123  }
2124 
2125  if (ebone_mirror_act) {
2126  arm->act_edbone = ebone_mirror_act;
2127  }
2128 
2130 
2132 
2135  }
2136  MEM_freeN(objects);
2137 
2138  return OPERATOR_FINISHED;
2139 }
2140 
2142 {
2143  /* identifiers */
2144  ot->name = "Select Mirror";
2145  ot->idname = "ARMATURE_OT_select_mirror";
2146  ot->description = "Mirror the bone selection";
2147 
2148  /* api callbacks */
2151 
2152  /* flags */
2154 
2155  /* properties */
2157  ot->srna, "only_active", false, "Active Only", "Only operate on the active bone");
2158  RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
2159 }
2160 
2163 /* -------------------------------------------------------------------- */
2168  bArmature *arm, EditBone *ebone_parent, EditBone *ebone_child, bool use_parent, bool is_test)
2169 {
2170  do {
2171 
2172  if (!use_parent && (ebone_child == ebone_parent)) {
2173  break;
2174  }
2175 
2176  if (is_test) {
2177  if (!EBONE_SELECTABLE(arm, ebone_child)) {
2178  return false;
2179  }
2180  }
2181  else {
2183  }
2184 
2185  if (ebone_child == ebone_parent) {
2186  break;
2187  }
2188 
2189  ebone_child = ebone_child->parent;
2190  } while (true);
2191 
2192  return true;
2193 }
2194 
2196 {
2197  Object *obedit = CTX_data_edit_object(C);
2198  bArmature *arm = obedit->data;
2199  EditBone *ebone_src, *ebone_dst;
2200  EditBone *ebone_isect_parent = NULL;
2201  EditBone *ebone_isect_child[2];
2202  bool changed;
2203  Base *base_dst = NULL;
2204 
2207 
2208  ebone_src = arm->act_edbone;
2209  ebone_dst = ED_armature_pick_ebone(C, event->mval, false, &base_dst);
2210 
2211  /* fallback to object selection */
2212  if (ELEM(NULL, ebone_src, ebone_dst) || (ebone_src == ebone_dst)) {
2213  return OPERATOR_PASS_THROUGH;
2214  }
2215 
2216  if (base_dst && base_dst->object != obedit) {
2217  /* Disconnected, ignore. */
2218  return OPERATOR_CANCELLED;
2219  }
2220 
2221  ebone_isect_child[0] = ebone_src;
2222  ebone_isect_child[1] = ebone_dst;
2223 
2224  /* ensure 'ebone_src' is the parent of 'ebone_dst', or set 'ebone_isect_parent' */
2225  if (ED_armature_ebone_is_child_recursive(ebone_src, ebone_dst)) {
2226  /* pass */
2227  }
2228  else if (ED_armature_ebone_is_child_recursive(ebone_dst, ebone_src)) {
2229  SWAP(EditBone *, ebone_src, ebone_dst);
2230  }
2231  else if ((ebone_isect_parent = ED_armature_ebone_find_shared_parent(ebone_isect_child, 2))) {
2232  /* pass */
2233  }
2234  else {
2235  /* disconnected bones */
2236  return OPERATOR_CANCELLED;
2237  }
2238 
2239  if (ebone_isect_parent) {
2240  if (armature_shortest_path_select(arm, ebone_isect_parent, ebone_src, false, true) &&
2241  armature_shortest_path_select(arm, ebone_isect_parent, ebone_dst, false, true)) {
2242  armature_shortest_path_select(arm, ebone_isect_parent, ebone_src, false, false);
2243  armature_shortest_path_select(arm, ebone_isect_parent, ebone_dst, false, false);
2244  changed = true;
2245  }
2246  else {
2247  /* unselectable */
2248  changed = false;
2249  }
2250  }
2251  else {
2252  if (armature_shortest_path_select(arm, ebone_src, ebone_dst, true, true)) {
2253  armature_shortest_path_select(arm, ebone_src, ebone_dst, true, false);
2254  changed = true;
2255  }
2256  else {
2257  /* unselectable */
2258  changed = false;
2259  }
2260  }
2261 
2262  if (changed) {
2263  arm->act_edbone = ebone_dst;
2268 
2269  return OPERATOR_FINISHED;
2270  }
2271 
2272  BKE_report(op->reports, RPT_WARNING, "Unselectable bone in chain");
2273  return OPERATOR_CANCELLED;
2274 }
2275 
2277 {
2278  /* identifiers */
2279  ot->name = "Pick Shortest Path";
2280  ot->idname = "ARMATURE_OT_shortest_path_pick";
2281  ot->description = "Select shortest path between two bones";
2282 
2283  /* api callbacks */
2286 
2287  /* flags */
2289 }
2290 
Blender kernel action and pose functionality.
struct bPoseChannel * BKE_pose_channel_find_name(const struct bPose *pose, const char *name)
struct Object * CTX_data_edit_object(const bContext *C)
Definition: context.c:1296
#define CTX_DATA_BEGIN(C, Type, instance, member)
Definition: BKE_context.h:252
struct ViewLayer * CTX_data_view_layer(const bContext *C)
Definition: context.c:1044
struct Depsgraph * CTX_data_ensure_evaluated_depsgraph(const bContext *C)
Definition: context.c:1424
struct View3D * CTX_wm_view3d(const bContext *C)
Definition: context.c:760
struct EditBone * CTX_data_active_bone(const bContext *C)
Definition: context.c:1321
struct Main * CTX_data_main(const bContext *C)
Definition: context.c:1018
#define CTX_DATA_END
Definition: BKE_context.h:260
#define BKE_view_layer_array_from_objects_in_edit_mode_unique_data(view_layer, v3d, r_len)
Definition: BKE_layer.h:426
#define BKE_view_layer_array_from_bases_in_edit_mode_unique_data(view_layer, v3d, r_len)
Definition: BKE_layer.h:430
#define BKE_view_layer_array_from_bases_in_mode(view_layer, v3d, r_len,...)
Definition: BKE_layer.h:411
General operations, lookup, etc. for blender objects.
struct Base ** BKE_object_pose_base_array_get(struct ViewLayer *view_layer, struct View3D *v3d, unsigned int *r_bases_len)
Definition: object.c:2604
void BKE_object_update_select_id(struct Main *bmain)
Definition: object.c:5654
bool BKE_object_is_in_editmode(const struct Object *ob)
void BKE_report(ReportList *reports, ReportType type, const char *message)
Definition: report.c:104
#define BLI_assert(a)
Definition: BLI_assert.h:58
#define LISTBASE_FOREACH(type, var, list)
Definition: BLI_listbase.h:172
int BLI_findindex(const struct ListBase *listbase, const void *vlink) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void * BLI_findlink(const struct ListBase *listbase, int number) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
#define M_PI
Definition: BLI_math_base.h:38
void mul_m4_v3(const float M[4][4], float r[3])
Definition: math_matrix.c:732
void mul_v3_mat3_m4v3(float r[3], const float M[4][4], const float v[3])
Definition: math_matrix.c:804
float angle_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
Definition: math_vector.c:443
MINLINE float normalize_v3(float r[3])
MINLINE float len_squared_v3v3(const float a[3], const float b[3]) ATTR_WARN_UNUSED_RESULT
MINLINE void sub_v3_v3v3(float r[3], const float a[3], const float b[3])
MINLINE void copy_v2_v2_int(int r[2], const int a[2])
MINLINE void copy_v3_v3(float r[3], const float a[3])
MINLINE int len_manhattan_v2v2_int(const int a[2], const int b[2]) ATTR_WARN_UNUSED_RESULT
void BLI_rcti_init_pt_radius(struct rcti *rect, const int xy[2], int size)
Definition: rct.c:508
void BLI_string_split_prefix(const char *string, char *r_pre, char *r_body, const size_t str_len)
Definition: string_utils.c:130
void BLI_string_split_suffix(const char *string, char *r_body, char *r_suf, const size_t str_len)
Definition: string_utils.c:109
unsigned int uint
Definition: BLI_sys_types.h:83
#define SWAP(type, a, b)
#define UNUSED(x)
#define SET_FLAG_FROM_TEST(value, test, flag)
#define ELEM(...)
#define POINTER_OFFSET(v, ofs)
#define STREQ(a, b)
struct Depsgraph Depsgraph
Definition: DEG_depsgraph.h:51
void DEG_id_tag_update(struct ID *id, int flag)
@ ID_RECALC_COPY_ON_WRITE
Definition: DNA_ID.h:654
@ ID_RECALC_SELECT
Definition: DNA_ID.h:638
#define MAXBONENAME
@ BONE_ROOTSEL
@ BONE_SELECTED
@ BONE_UNSELECTABLE
@ BONE_DONE
@ BONE_TIPSEL
@ BONE_CONNECTED
Object is a sort of wrapper for general info.
@ OPERATOR_CANCELLED
@ OPERATOR_FINISHED
@ OPERATOR_PASS_THROUGH
#define BONESEL_ANY
Definition: ED_armature.h:53
#define EBONE_VISIBLE(arm, ebone)
Definition: ED_armature.h:56
#define BONESEL_ROOT
Definition: ED_armature.h:50
#define BONE_SELECT_CHILD
Definition: ED_armature.h:70
#define BONESEL_TIP
Definition: ED_armature.h:51
#define BONE_SELECT_PARENT
Definition: ED_armature.h:69
#define BONESEL_BONE
Definition: ED_armature.h:52
#define EBONE_SELECTABLE(arm, ebone)
Definition: ED_armature.h:61
void ED_object_base_activate(struct bContext *C, struct Base *base)
void ED_outliner_select_sync_from_edit_bone_tag(struct bContext *C)
Definition: outliner_sync.c:62
bool ED_operator_editarmature(struct bContext *C)
Definition: screen_ops.c:437
bool ED_operator_view3d_active(struct bContext *C)
Definition: screen_ops.c:230
@ SEL_SELECT
@ SEL_INVERT
@ SEL_DESELECT
@ SEL_TOGGLE
int ED_select_op_action_deselected(const eSelectOp sel_op, const bool is_select, const bool is_inside)
Definition: select_utils.c:53
eSelectOp
void view3d_opengl_select_cache_end(void)
Definition: view3d_view.c:897
void ED_view3d_viewcontext_init(struct bContext *C, struct ViewContext *vc, struct Depsgraph *depsgraph)
#define MAXPICKBUF
Definition: ED_view3d.h:511
#define XRAY_ACTIVE(v3d)
Definition: ED_view3d.h:711
void view3d_opengl_select_cache_begin(void)
Definition: view3d_view.c:892
@ VIEW3D_SELECT_PICK_ALL
Definition: ED_view3d.h:517
@ VIEW3D_SELECT_PICK_NEAREST
Definition: ED_view3d.h:519
void view3d_operator_needs_opengl(const struct bContext *C)
eV3DSelectObjectFilter
Definition: ED_view3d.h:522
@ VIEW3D_SELECT_FILTER_NOP
Definition: ED_view3d.h:524
int view3d_opengl_select_with_id_filter(struct ViewContext *vc, unsigned int *buffer, unsigned int bufsize, const struct rcti *input, eV3DSelectMode select_mode, eV3DSelectObjectFilter select_filter, uint select_id)
_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
_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 const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble v1
Read Guarded memory(de)allocation.
#define C
Definition: RandGen.cpp:39
@ OPTYPE_UNDO
Definition: WM_types.h:155
@ OPTYPE_REGISTER
Definition: WM_types.h:153
#define ND_DATA
Definition: WM_types.h:408
#define NA_EDITED
Definition: WM_types.h:462
#define WM_EVENT_CURSOR_MOTION_THRESHOLD
Definition: WM_types.h:648
#define NC_GPENCIL
Definition: WM_types.h:300
#define ND_BONE_SELECT
Definition: WM_types.h:361
#define NC_OBJECT
Definition: WM_types.h:280
#define CHECK_PARENT(ebone)
void ARMATURE_OT_select_similar(wmOperatorType *ot)
static void armature_select_less(bArmature *UNUSED(arm), EditBone *ebone)
void ARMATURE_OT_select_all(wmOperatorType *ot)
void ARMATURE_OT_select_hierarchy(wmOperatorType *ot)
static int selectbuffer_ret_hits_12(uint *UNUSED(buffer), const int hits12)
bool ED_armature_edit_deselect_all_visible(Object *obedit)
static int armature_select_similar_exec(bContext *C, wmOperator *op)
#define EBONE_PREV_FLAG_GET(ebone)
static bool armature_select_linked_pick_poll(bContext *C)
Base * ED_armature_base_and_ebone_from_select_buffer(Base **bases, uint bases_len, int hit, EditBone **r_ebone)
static bool armature_edit_select_op_apply(bArmature *arm, EditBone *ebone, const eSelectOp sel_op, int is_ignore_flag, int is_inside_flag)
static void select_similar_length(bContext *C, const float thresh)
static EditBone * get_nearest_editbonepoint(ViewContext *vc, bool findunsel, bool use_cycle, Base **r_base, int *r_selmask)
void ARMATURE_OT_select_mirror(wmOperatorType *ot)
EditBone * ED_armature_pick_ebone_from_selectbuffer(Base **bases, uint bases_len, const uint *buffer, short hits, bool findunsel, bool do_nearest, Base **r_base)
static int armature_de_select_all_exec(bContext *C, wmOperator *op)
static const EnumPropertyItem prop_similar_types[]
Bone * ED_armature_pick_bone(bContext *C, const int xy[2], bool findunsel, Base **r_base)
static void select_similar_suffix(bContext *C)
static void bone_direction_worldspace_get(Object *ob, EditBone *ebone, float *r_dir)
Bone * ED_armature_pick_bone_from_selectbuffer(Base **bases, uint bases_len, const uint *buffer, short hits, bool findunsel, bool do_nearest, Base **r_base)
bPoseChannel * ED_armature_pick_pchan(bContext *C, const int xy[2], bool findunsel, Base **r_base)
bool ED_armature_edit_deselect_all(Object *obedit)
static bool armature_select_linked_impl(Object *ob, const bool select, const bool all_forks)
EditBone * ED_armature_pick_ebone(bContext *C, const int xy[2], bool findunsel, Base **r_base)
void ARMATURE_OT_select_less(wmOperatorType *ot)
static int armature_select_mirror_exec(bContext *C, wmOperator *op)
Base * ED_armature_base_and_pchan_from_select_buffer(Base **bases, uint bases_len, int hit, bPoseChannel **r_pchan)
static void select_similar_prefix(bContext *C)
bPoseChannel * ED_armature_pick_pchan_from_selectbuffer(Base **bases, uint bases_len, const uint *buffer, short hits, bool findunsel, bool do_nearest, Base **r_base)
Base * ED_armature_base_and_bone_from_select_buffer(Base **bases, uint bases_len, int hit, Bone **r_bone)
bool ED_armature_edit_deselect_all_multi_ex(struct Base **bases, uint bases_len)
static void is_ancestor(EditBone *bone, EditBone *ancestor)
static int armature_shortest_path_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
static void select_similar_siblings(bContext *C)
bool ED_armature_edit_deselect_all_visible_multi(bContext *C)
static void select_similar_children_immediate(bContext *C)
@ SIMEDBONE_CHILDREN
@ SIMEDBONE_SUFFIX
@ SIMEDBONE_PREFIX
@ SIMEDBONE_DIRECTION
@ SIMEDBONE_LENGTH
@ SIMEDBONE_SIBLINGS
@ SIMEDBONE_SHAPE
@ SIMEDBONE_CHILDREN_IMMEDIATE
@ SIMEDBONE_GROUP
@ SIMEDBONE_LAYER
static int armature_select_linked_exec(bContext *C, wmOperator *op)
static void select_similar_children(bContext *C)
static float bone_length_squared_worldspace_get(Object *ob, EditBone *ebone)
static void armature_select_more_less(Object *ob, bool more)
#define EBONE_PREV_FLAG_SET(ebone, val)
#define STRUCT_SIZE_AND_OFFSET(_struct, _member)
static int selectbuffer_ret_hits_5(uint *buffer, const int hits12, const int hits5)
static void * ed_armature_pick_bone_impl(const bool is_editmode, bContext *C, const int xy[2], bool findunsel, Base **r_base)
static int armature_select_hierarchy_exec(bContext *C, wmOperator *op)
static void select_similar_data_pchan(bContext *C, const size_t bytes_size, const int offset)
Object * ED_armature_object_and_ebone_from_select_buffer(Object **objects, uint objects_len, int hit, EditBone **r_ebone)
void ARMATURE_OT_select_linked(wmOperatorType *ot)
static void select_similar_layer(bContext *C)
static bool armature_shortest_path_select(bArmature *arm, EditBone *ebone_parent, EditBone *ebone_child, bool use_parent, bool is_test)
static void armature_select_more(bArmature *arm, EditBone *ebone)
bool ED_armature_edit_select_op_from_tagged(bArmature *arm, const int sel_op)
bool ED_armature_edit_select_pick(bContext *C, const int mval[2], bool extend, bool deselect, bool toggle)
static int armature_select_linked_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
bool ED_armature_edit_select_pick_bone(bContext *C, Base *basact, EditBone *ebone, const int selmask, const bool extend, const bool deselect, const bool toggle)
static void select_similar_direction(bContext *C, const float thresh)
void ARMATURE_OT_select_linked_pick(wmOperatorType *ot)
static int armature_de_select_less_exec(bContext *C, wmOperator *UNUSED(op))
static void * ed_armature_pick_bone_from_selectbuffer_impl(const bool is_editmode, Base **bases, uint bases_len, const uint *buffer, short hits, bool findunsel, bool do_nearest, Base **r_base)
static int armature_de_select_more_exec(bContext *C, wmOperator *UNUSED(op))
void ARMATURE_OT_select_more(wmOperatorType *ot)
bool ED_armature_edit_deselect_all_visible_multi_ex(struct Base **bases, uint bases_len)
void ARMATURE_OT_shortest_path_pick(wmOperatorType *ot)
bool ED_armature_ebone_is_child_recursive(EditBone *ebone_parent, EditBone *ebone_child)
void ED_armature_ebone_selectflag_disable(EditBone *ebone, int flag)
void ED_armature_edit_sync_selection(ListBase *edbo)
int ED_armature_ebone_selectflag_get(const EditBone *ebone)
void ED_armature_ebone_selectflag_set(EditBone *ebone, int flag)
void ED_armature_ebone_select_set(EditBone *ebone, bool select)
EditBone * ED_armature_ebone_find_shared_parent(EditBone *ebone_child[], const uint ebone_child_tot)
void ED_armature_edit_validate_active(struct bArmature *arm)
void ED_armature_ebone_selectflag_enable(EditBone *ebone, int flag)
EditBone * ED_armature_ebone_get_mirrored(const ListBase *edbo, EditBone *ebo)
ATTR_WARN_UNUSED_RESULT const BMVert * v2
const Depsgraph * depsgraph
static bool is_inside(int x, int y, int cols, int rows)
Definition: filesel.c:663
__kernel void ccl_constant KernelData ccl_global void ccl_global char ccl_global int ccl_global char ccl_global unsigned int ccl_global float * buffer
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:41
float RNA_float_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6355
bool RNA_boolean_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6261
int RNA_enum_get(PointerRNA *ptr, const char *name)
Definition: rna_access.c:6402
PropertyRNA * RNA_def_float(StructOrFunctionRNA *cont_, const char *identifier, float default_value, float hardmin, float hardmax, const char *ui_name, const char *ui_description, float softmin, float softmax)
Definition: rna_define.c:3825
PropertyRNA * RNA_def_boolean(StructOrFunctionRNA *cont_, const char *identifier, bool default_value, const char *ui_name, const char *ui_description)
Definition: rna_define.c:3481
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:3771
unsigned short uint16_t
Definition: stdint.h:82
unsigned int uint32_t
Definition: stdint.h:83
struct Object * object
char name[64]
Definition: BKE_armature.h:57
struct EditBone * next
Definition: BKE_armature.h:49
float tail[3]
Definition: BKE_armature.h:66
struct EditBone * ebone
Definition: BKE_armature.h:112
struct Bone * bone
Definition: BKE_armature.h:113
struct EditBone * parent
Definition: BKE_armature.h:55
union EditBone::@2 temp
float head[3]
Definition: BKE_armature.h:65
void * first
Definition: DNA_listBase.h:47
struct bPose * pose
Object_Runtime runtime
float obmat[4][4]
void * data
int mval[2]
Definition: ED_view3d.h:85
struct ViewLayer * view_layer
Definition: ED_view3d.h:77
struct Object * obedit
Definition: ED_view3d.h:79
struct View3D * v3d
Definition: ED_view3d.h:81
struct Base * basact
struct EditBone * act_edbone
ListBase * edbo
struct Bone * bone
ListBase chanbase
int mval[2]
Definition: WM_types.h:583
int(* invoke)(struct bContext *, struct wmOperator *, const struct wmEvent *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:752
const char * name
Definition: WM_types.h:721
const char * idname
Definition: WM_types.h:723
bool(* poll)(struct bContext *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:776
struct StructRNA * srna
Definition: WM_types.h:802
const char * description
Definition: WM_types.h:726
int(* exec)(struct bContext *, struct wmOperator *) ATTR_WARN_UNUSED_RESULT
Definition: WM_types.h:736
PropertyRNA * prop
Definition: WM_types.h:814
struct ReportList * reports
struct PointerRNA * ptr
__forceinline const avxb select(const avxb &m, const avxb &t, const avxb &f)
Definition: util_avxb.h:167
uint len
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:3156
void WM_operator_properties_select_all(wmOperatorType *ot)
int WM_menu_invoke(bContext *C, wmOperator *op, const wmEvent *UNUSED(event))
Definition: wm_operators.c:982