0c493672d9e64876f7ab210c6511c2b6e764bf06
[blender.git] / source / blender / editors / armature / armature_select.c
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
21 /** \file
22  * \ingroup edarmature
23  */
24
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_string_utils.h"
34
35 #include "BKE_context.h"
36 #include "BKE_action.h"
37 #include "BKE_object.h"
38 #include "BKE_report.h"
39 #include "BKE_layer.h"
40
41 #include "RNA_access.h"
42 #include "RNA_define.h"
43
44 #include "WM_api.h"
45 #include "WM_types.h"
46
47 #include "ED_armature.h"
48 #include "ED_object.h"
49 #include "ED_screen.h"
50 #include "ED_select_utils.h"
51 #include "ED_view3d.h"
52
53 #include "DEG_depsgraph.h"
54
55 #include "armature_intern.h"
56
57 /* utility macros for storing a temp int in the bone (selection flag) */
58 #define EBONE_PREV_FLAG_GET(ebone) ((void)0, (ebone)->temp.i)
59 #define EBONE_PREV_FLAG_SET(ebone, val) ((ebone)->temp.i = val)
60
61 /* **************** PoseMode & EditMode Selection Buffer Queries *************************** */
62
63 Base *ED_armature_base_and_ebone_from_select_buffer(Base **bases,
64                                                     uint bases_len,
65                                                     int hit,
66                                                     EditBone **r_ebone)
67 {
68   const uint hit_object = hit & 0xFFFF;
69   Base *base = NULL;
70   EditBone *ebone = NULL;
71   /* TODO(campbell): optimize, eg: sort & binary search. */
72   for (uint base_index = 0; base_index < bases_len; base_index++) {
73     if (bases[base_index]->object->select_id == hit_object) {
74       base = bases[base_index];
75       break;
76     }
77   }
78   if (base != NULL) {
79     const uint hit_bone = (hit & ~BONESEL_ANY) >> 16;
80     bArmature *arm = base->object->data;
81     ebone = BLI_findlink(arm->edbo, hit_bone);
82   }
83   *r_ebone = ebone;
84   return base;
85 }
86
87 Object *ED_armature_object_and_ebone_from_select_buffer(Object **objects,
88                                                         uint objects_len,
89                                                         int hit,
90                                                         EditBone **r_ebone)
91 {
92   const uint hit_object = hit & 0xFFFF;
93   Object *ob = NULL;
94   EditBone *ebone = NULL;
95   /* TODO(campbell): optimize, eg: sort & binary search. */
96   for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
97     if (objects[ob_index]->select_id == hit_object) {
98       ob = objects[ob_index];
99       break;
100     }
101   }
102   if (ob != NULL) {
103     const uint hit_bone = (hit & ~BONESEL_ANY) >> 16;
104     bArmature *arm = ob->data;
105     ebone = BLI_findlink(arm->edbo, hit_bone);
106   }
107   *r_ebone = ebone;
108   return ob;
109 }
110
111 Base *ED_armature_base_and_bone_from_select_buffer(Base **bases,
112                                                    uint bases_len,
113                                                    int hit,
114                                                    Bone **r_bone)
115 {
116   const uint hit_object = hit & 0xFFFF;
117   Base *base = NULL;
118   Bone *bone = NULL;
119   /* TODO(campbell): optimize, eg: sort & binary search. */
120   for (uint base_index = 0; base_index < bases_len; base_index++) {
121     if (bases[base_index]->object->select_id == hit_object) {
122       base = bases[base_index];
123       break;
124     }
125   }
126   if (base != NULL) {
127     if (base->object->pose != NULL) {
128       const uint hit_bone = (hit & ~BONESEL_ANY) >> 16;
129       bPoseChannel *pchan = BLI_findlink(&base->object->pose->chanbase, hit_bone);
130       bone = pchan ? pchan->bone : NULL;
131     }
132   }
133   *r_bone = bone;
134   return base;
135 }
136
137 /* See if there are any selected bones in this buffer */
138 /* only bones from base are checked on */
139 void *get_bone_from_selectbuffer(Base **bases,
140                                  uint bases_len,
141                                  bool is_editmode,
142                                  const unsigned int *buffer,
143                                  short hits,
144                                  bool findunsel,
145                                  bool do_nearest,
146                                  Base **r_base)
147 {
148   Bone *bone;
149   EditBone *ebone;
150   void *firstunSel = NULL, *firstSel = NULL, *data;
151   Base *firstunSel_base = NULL, *firstSel_base = NULL;
152   unsigned int hitresult;
153   short i;
154   bool takeNext = false;
155   int minsel = 0xffffffff, minunsel = 0xffffffff;
156
157   for (i = 0; i < hits; i++) {
158     hitresult = buffer[3 + (i * 4)];
159
160     if (!(hitresult & BONESEL_NOSEL)) {
161       if (hitresult & BONESEL_ANY) { /* to avoid including objects in selection */
162         Base *base = NULL;
163         bool sel;
164
165         hitresult &= ~(BONESEL_ANY);
166         /* Determine what the current bone is */
167         if (is_editmode == false) {
168           base = ED_armature_base_and_bone_from_select_buffer(bases, bases_len, hitresult, &bone);
169           if (bone != NULL) {
170             if (findunsel)
171               sel = (bone->flag & BONE_SELECTED);
172             else
173               sel = !(bone->flag & BONE_SELECTED);
174
175             data = bone;
176           }
177           else {
178             data = NULL;
179             sel = 0;
180           }
181         }
182         else {
183           base = ED_armature_base_and_ebone_from_select_buffer(
184               bases, bases_len, hitresult, &ebone);
185           if (findunsel)
186             sel = (ebone->flag & BONE_SELECTED);
187           else
188             sel = !(ebone->flag & BONE_SELECTED);
189
190           data = ebone;
191         }
192
193         if (data) {
194           if (sel) {
195             if (do_nearest) {
196               if (minsel > buffer[4 * i + 1]) {
197                 firstSel = data;
198                 firstSel_base = base;
199                 minsel = buffer[4 * i + 1];
200               }
201             }
202             else {
203               if (!firstSel) {
204                 firstSel = data;
205                 firstSel_base = base;
206               }
207               takeNext = 1;
208             }
209           }
210           else {
211             if (do_nearest) {
212               if (minunsel > buffer[4 * i + 1]) {
213                 firstunSel = data;
214                 firstunSel_base = base;
215                 minunsel = buffer[4 * i + 1];
216               }
217             }
218             else {
219               if (!firstunSel) {
220                 firstunSel = data;
221                 firstunSel_base = base;
222               }
223               if (takeNext) {
224                 *r_base = base;
225                 return data;
226               }
227             }
228           }
229         }
230       }
231     }
232   }
233
234   if (firstunSel) {
235     *r_base = firstunSel_base;
236     return firstunSel;
237   }
238   else {
239     *r_base = firstSel_base;
240     return firstSel;
241   }
242 }
243
244 /* used by posemode as well editmode */
245 /* only checks scene->basact! */
246 /* x and y are mouse coords (area space) */
247 void *get_nearest_bone(bContext *C, const int xy[2], bool findunsel, Base **r_base)
248 {
249   ViewContext vc;
250   rcti rect;
251   unsigned int buffer[MAXPICKBUF];
252   short hits;
253
254   ED_view3d_viewcontext_init(C, &vc);
255
256   // rect.xmin = ... mouseco!
257   rect.xmin = rect.xmax = xy[0];
258   rect.ymin = rect.ymax = xy[1];
259
260   hits = view3d_opengl_select(
261       &vc, buffer, MAXPICKBUF, &rect, VIEW3D_SELECT_PICK_NEAREST, VIEW3D_SELECT_FILTER_NOP);
262
263   *r_base = NULL;
264
265   if (hits > 0) {
266     uint bases_len = 0;
267     Base **bases;
268
269     if (vc.obedit != NULL) {
270       bases = BKE_view_layer_array_from_bases_in_mode(vc.view_layer,
271                                                       vc.v3d,
272                                                       &bases_len,
273                                                       {
274                                                           .object_mode = OB_MODE_EDIT,
275                                                       });
276     }
277     else {
278       bases = BKE_object_pose_base_array_get(vc.view_layer, vc.v3d, &bases_len);
279     }
280
281     void *bone = get_bone_from_selectbuffer(
282         bases, bases_len, vc.obedit != NULL, buffer, hits, findunsel, true, r_base);
283
284     MEM_freeN(bases);
285     return bone;
286   }
287   return NULL;
288 }
289
290 /* **************** EditMode stuff ********************** */
291
292 static int armature_select_linked_invoke(bContext *C, wmOperator *op, const wmEvent *event)
293 {
294   bArmature *arm;
295   EditBone *bone, *curBone, *next;
296   const bool sel = !RNA_boolean_get(op->ptr, "deselect");
297
298   view3d_operator_needs_opengl(C);
299
300   Base *base = NULL;
301   bone = get_nearest_bone(C, event->mval, true, &base);
302
303   if (!bone)
304     return OPERATOR_CANCELLED;
305
306   arm = base->object->data;
307
308   /* Select parents */
309   for (curBone = bone; curBone; curBone = next) {
310     if ((curBone->flag & BONE_UNSELECTABLE) == 0) {
311       if (sel) {
312         curBone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
313       }
314       else {
315         curBone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
316       }
317     }
318
319     if (curBone->flag & BONE_CONNECTED)
320       next = curBone->parent;
321     else
322       next = NULL;
323   }
324
325   /* Select children */
326   while (bone) {
327     for (curBone = arm->edbo->first; curBone; curBone = next) {
328       next = curBone->next;
329       if ((curBone->parent == bone) && (curBone->flag & BONE_UNSELECTABLE) == 0) {
330         if (curBone->flag & BONE_CONNECTED) {
331           if (sel) {
332             curBone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
333           }
334           else {
335             curBone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
336           }
337           bone = curBone;
338           break;
339         }
340         else {
341           bone = NULL;
342           break;
343         }
344       }
345     }
346     if (!curBone)
347       bone = NULL;
348   }
349
350   ED_armature_edit_sync_selection(arm->edbo);
351
352   WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, base->object);
353
354   return OPERATOR_FINISHED;
355 }
356
357 static bool armature_select_linked_poll(bContext *C)
358 {
359   return (ED_operator_view3d_active(C) && ED_operator_editarmature(C));
360 }
361
362 void ARMATURE_OT_select_linked(wmOperatorType *ot)
363 {
364   /* identifiers */
365   ot->name = "Select Connected";
366   ot->idname = "ARMATURE_OT_select_linked";
367   ot->description = "Select bones related to selected ones by parent/child relationships";
368
369   /* api callbacks */
370   /* leave 'exec' unset */
371   ot->invoke = armature_select_linked_invoke;
372   ot->poll = armature_select_linked_poll;
373
374   /* flags */
375   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
376
377   RNA_def_boolean(ot->srna, "deselect", 0, "Deselect", "");
378 }
379
380 /* utility function for get_nearest_editbonepoint */
381 static int selectbuffer_ret_hits_12(unsigned int *UNUSED(buffer), const int hits12)
382 {
383   return hits12;
384 }
385
386 static int selectbuffer_ret_hits_5(unsigned int *buffer, const int hits12, const int hits5)
387 {
388   const int offs = 4 * hits12;
389   memcpy(buffer, buffer + offs, 4 * hits5 * sizeof(unsigned int));
390   return hits5;
391 }
392
393 /* does bones and points */
394 /* note that BONE ROOT only gets drawn for root bones (or without IK) */
395 static EditBone *get_nearest_editbonepoint(
396     ViewContext *vc, bool findunsel, bool use_cycle, Base **r_base, int *r_selmask)
397 {
398   uint buffer[MAXPICKBUF];
399   struct {
400     uint hitresult;
401     Base *base;
402     EditBone *ebone;
403   } best = {
404       .hitresult = BONESEL_NOSEL,
405       .base = NULL,
406       .ebone = NULL,
407   };
408
409   /* find the bone after the current active bone, so as to bump up its chances in selection.
410    * this way overlapping bones will cycle selection state as with objects. */
411   EditBone *ebone_next_act = ((bArmature *)vc->obedit->data)->act_edbone;
412   {
413     bArmature *arm = (bArmature *)vc->obedit->data;
414     if (ebone_next_act && EBONE_VISIBLE(arm, ebone_next_act) &&
415         ebone_next_act->flag & (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL)) {
416       ebone_next_act = ebone_next_act->next ? ebone_next_act->next : arm->edbo->first;
417     }
418     else {
419       ebone_next_act = NULL;
420     }
421   }
422
423   bool do_nearest = false;
424
425   /* define if we use solid nearest select or not */
426   if (use_cycle) {
427     static int last_mval[2] = {-100, -100};
428
429     if (!XRAY_ACTIVE(vc->v3d)) {
430       do_nearest = true;
431       if (len_manhattan_v2v2_int(vc->mval, last_mval) <= WM_EVENT_CURSOR_MOTION_THRESHOLD) {
432         do_nearest = false;
433       }
434     }
435     copy_v2_v2_int(last_mval, vc->mval);
436   }
437   else {
438     if (!XRAY_ACTIVE(vc->v3d)) {
439       do_nearest = true;
440     }
441   }
442
443   /* matching logic from 'mixed_bones_object_selectbuffer' */
444   int hits = 0;
445
446   /* we _must_ end cache before return, use 'goto cache_end' */
447   view3d_opengl_select_cache_begin();
448
449   {
450     const int select_mode = (do_nearest ? VIEW3D_SELECT_PICK_NEAREST : VIEW3D_SELECT_PICK_ALL);
451     const eV3DSelectObjectFilter select_filter = VIEW3D_SELECT_FILTER_NOP;
452
453     rcti rect;
454     BLI_rcti_init_pt_radius(&rect, vc->mval, 12);
455     const int hits12 = view3d_opengl_select(
456         vc, buffer, MAXPICKBUF, &rect, select_mode, select_filter);
457     if (hits12 == 1) {
458       hits = selectbuffer_ret_hits_12(buffer, hits12);
459       goto cache_end;
460     }
461     else if (hits12 > 0) {
462       int offs;
463
464       offs = 4 * hits12;
465       BLI_rcti_init_pt_radius(&rect, vc->mval, 5);
466       const int hits5 = view3d_opengl_select(
467           vc, buffer + offs, MAXPICKBUF - offs, &rect, select_mode, select_filter);
468
469       if (hits5 == 1) {
470         hits = selectbuffer_ret_hits_5(buffer, hits12, hits5);
471         goto cache_end;
472       }
473
474       if (hits5 > 0) {
475         hits = selectbuffer_ret_hits_5(buffer, hits12, hits5);
476         goto cache_end;
477       }
478       else {
479         hits = selectbuffer_ret_hits_12(buffer, hits12);
480         goto cache_end;
481       }
482     }
483   }
484
485 cache_end:
486   view3d_opengl_select_cache_end();
487
488   uint bases_len;
489   Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data(
490       vc->view_layer, vc->v3d, &bases_len);
491
492   /* See if there are any selected bones in this group */
493   if (hits > 0) {
494     if (hits == 1) {
495       if (!(buffer[3] & BONESEL_NOSEL)) {
496         best.hitresult = buffer[3];
497         best.base = ED_armature_base_and_ebone_from_select_buffer(
498             bases, bases_len, best.hitresult, &best.ebone);
499       }
500     }
501     else {
502       int dep_min = 5;
503       for (int i = 0; i < hits; i++) {
504         const uint hitresult = buffer[3 + (i * 4)];
505         if (!(hitresult & BONESEL_NOSEL)) {
506           Base *base = NULL;
507           EditBone *ebone;
508           base = ED_armature_base_and_ebone_from_select_buffer(
509               bases, bases_len, hitresult, &ebone);
510           /* If this fails, selection code is setting the selection ID's incorrectly. */
511           BLI_assert(base && ebone);
512
513           int dep;
514           /* clicks on bone points get advantage */
515           if (hitresult & (BONESEL_ROOT | BONESEL_TIP)) {
516             /* but also the unselected one */
517             if (findunsel) {
518               if ((hitresult & BONESEL_ROOT) && (ebone->flag & BONE_ROOTSEL) == 0)
519                 dep = 1;
520               else if ((hitresult & BONESEL_TIP) && (ebone->flag & BONE_TIPSEL) == 0)
521                 dep = 1;
522               else
523                 dep = 2;
524             }
525             else {
526               dep = 1;
527             }
528           }
529           else {
530             /* bone found */
531             if (findunsel) {
532               if ((ebone->flag & BONE_SELECTED) == 0)
533                 dep = 3;
534               else
535                 dep = 4;
536             }
537             else {
538               dep = 3;
539             }
540           }
541
542           if (ebone == ebone_next_act) {
543             dep -= 1;
544           }
545
546           if (dep < dep_min) {
547             dep_min = dep;
548             best.hitresult = hitresult;
549             best.base = base;
550             best.ebone = ebone;
551           }
552         }
553       }
554     }
555
556     if (!(best.hitresult & BONESEL_NOSEL)) {
557       *r_base = best.base;
558
559       *r_selmask = 0;
560       if (best.hitresult & BONESEL_ROOT) {
561         *r_selmask |= BONE_ROOTSEL;
562       }
563       if (best.hitresult & BONESEL_TIP) {
564         *r_selmask |= BONE_TIPSEL;
565       }
566       if (best.hitresult & BONESEL_BONE) {
567         *r_selmask |= BONE_SELECTED;
568       }
569       MEM_freeN(bases);
570       return best.ebone;
571     }
572   }
573   *r_selmask = 0;
574   *r_base = NULL;
575   MEM_freeN(bases);
576   return NULL;
577 }
578
579 bool ED_armature_edit_deselect_all(Object *obedit)
580 {
581   bArmature *arm = obedit->data;
582   bool changed = false;
583   for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
584     if (ebone->flag & (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL)) {
585       ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
586       changed = true;
587     }
588   }
589   return changed;
590 }
591
592 bool ED_armature_edit_deselect_all_visible(Object *obedit)
593 {
594   bArmature *arm = obedit->data;
595   bool changed = false;
596   for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
597     /* first and foremost, bone must be visible and selected */
598     if (EBONE_VISIBLE(arm, ebone)) {
599       if (ebone->flag & (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL)) {
600         ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
601         changed = true;
602       }
603     }
604   }
605
606   if (changed) {
607     ED_armature_edit_sync_selection(arm->edbo);
608   }
609   return changed;
610 }
611
612 bool ED_armature_edit_deselect_all_multi_ex(struct Base **bases, uint bases_len)
613 {
614   bool changed_multi = false;
615   for (uint base_index = 0; base_index < bases_len; base_index++) {
616     Object *obedit = bases[base_index]->object;
617     changed_multi |= ED_armature_edit_deselect_all(obedit);
618   }
619   return changed_multi;
620 }
621
622 bool ED_armature_edit_deselect_all_visible_multi_ex(struct Base **bases, uint bases_len)
623 {
624   bool changed_multi = false;
625   for (uint base_index = 0; base_index < bases_len; base_index++) {
626     Object *obedit = bases[base_index]->object;
627     changed_multi |= ED_armature_edit_deselect_all_visible(obedit);
628   }
629   return changed_multi;
630 }
631
632 bool ED_armature_edit_deselect_all_visible_multi(bContext *C)
633 {
634   ViewContext vc;
635   ED_view3d_viewcontext_init(C, &vc);
636   uint bases_len = 0;
637   Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data(
638       vc.view_layer, vc.v3d, &bases_len);
639   bool changed_multi = ED_armature_edit_deselect_all_multi_ex(bases, bases_len);
640   MEM_freeN(bases);
641   return changed_multi;
642 }
643
644 /* accounts for connected parents */
645 static int ebone_select_flag(EditBone *ebone)
646 {
647   if (ebone->parent && (ebone->flag & BONE_CONNECTED)) {
648     return ((ebone->parent->flag & BONE_TIPSEL) ? BONE_ROOTSEL : 0) |
649            (ebone->flag & (BONE_SELECTED | BONE_TIPSEL));
650   }
651   else {
652     return ebone->flag & (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL);
653   }
654 }
655
656 /* context: editmode armature in view3d */
657 bool ED_armature_edit_select_pick(
658     bContext *C, const int mval[2], bool extend, bool deselect, bool toggle)
659 {
660   ViewContext vc;
661   EditBone *nearBone = NULL;
662   int selmask;
663   Base *basact = NULL;
664
665   ED_view3d_viewcontext_init(C, &vc);
666   vc.mval[0] = mval[0];
667   vc.mval[1] = mval[1];
668
669   nearBone = get_nearest_editbonepoint(&vc, true, true, &basact, &selmask);
670   if (nearBone) {
671     ED_view3d_viewcontext_init_object(&vc, basact->object);
672     bArmature *arm = vc.obedit->data;
673
674     if (!EBONE_SELECTABLE(arm, nearBone)) {
675       return false;
676     }
677
678     if (!extend && !deselect && !toggle) {
679       uint bases_len = 0;
680       Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data(
681           vc.view_layer, vc.v3d, &bases_len);
682       ED_armature_edit_deselect_all_multi_ex(bases, bases_len);
683       MEM_freeN(bases);
684     }
685
686     /* by definition the non-root connected bones have no root point drawn,
687      * so a root selection needs to be delivered to the parent tip */
688
689     if (selmask & BONE_SELECTED) {
690       if (nearBone->parent && (nearBone->flag & BONE_CONNECTED)) {
691         /* click in a chain */
692         if (extend) {
693           /* select this bone */
694           nearBone->flag |= BONE_TIPSEL;
695           nearBone->parent->flag |= BONE_TIPSEL;
696         }
697         else if (deselect) {
698           /* deselect this bone */
699           nearBone->flag &= ~(BONE_TIPSEL | BONE_SELECTED);
700           /* only deselect parent tip if it is not selected */
701           if (!(nearBone->parent->flag & BONE_SELECTED))
702             nearBone->parent->flag &= ~BONE_TIPSEL;
703         }
704         else if (toggle) {
705           /* hold shift inverts this bone's selection */
706           if (nearBone->flag & BONE_SELECTED) {
707             /* deselect this bone */
708             nearBone->flag &= ~(BONE_TIPSEL | BONE_SELECTED);
709             /* only deselect parent tip if it is not selected */
710             if (!(nearBone->parent->flag & BONE_SELECTED))
711               nearBone->parent->flag &= ~BONE_TIPSEL;
712           }
713           else {
714             /* select this bone */
715             nearBone->flag |= BONE_TIPSEL;
716             nearBone->parent->flag |= BONE_TIPSEL;
717           }
718         }
719         else {
720           /* select this bone */
721           nearBone->flag |= BONE_TIPSEL;
722           nearBone->parent->flag |= BONE_TIPSEL;
723         }
724       }
725       else {
726         if (extend) {
727           nearBone->flag |= (BONE_TIPSEL | BONE_ROOTSEL);
728         }
729         else if (deselect) {
730           nearBone->flag &= ~(BONE_TIPSEL | BONE_ROOTSEL);
731         }
732         else if (toggle) {
733           /* hold shift inverts this bone's selection */
734           if (nearBone->flag & BONE_SELECTED)
735             nearBone->flag &= ~(BONE_TIPSEL | BONE_ROOTSEL);
736           else
737             nearBone->flag |= (BONE_TIPSEL | BONE_ROOTSEL);
738         }
739         else
740           nearBone->flag |= (BONE_TIPSEL | BONE_ROOTSEL);
741       }
742     }
743     else {
744       if (extend)
745         nearBone->flag |= selmask;
746       else if (deselect)
747         nearBone->flag &= ~selmask;
748       else if (toggle && (nearBone->flag & selmask))
749         nearBone->flag &= ~selmask;
750       else
751         nearBone->flag |= selmask;
752     }
753
754     ED_armature_edit_sync_selection(arm->edbo);
755
756     /* then now check for active status */
757     if (ebone_select_flag(nearBone)) {
758       arm->act_edbone = nearBone;
759     }
760
761     if (vc.view_layer->basact != basact) {
762       ED_object_base_activate(C, basact);
763     }
764
765     WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, basact->object);
766     return true;
767   }
768
769   return false;
770 }
771
772 /* -------------------------------------------------------------------- */
773 /** \name Select Op From Tagged
774  *
775  * Implements #ED_armature_edit_select_op_from_tagged
776  * \{ */
777
778 static bool armature_edit_select_op_apply(bArmature *arm,
779                                           EditBone *ebone,
780                                           const eSelectOp sel_op,
781                                           int is_ignore_flag,
782                                           int is_inside_flag)
783 {
784   BLI_assert(!(is_ignore_flag & ~(BONESEL_ROOT | BONESEL_TIP)));
785   BLI_assert(!(is_inside_flag & ~(BONESEL_ROOT | BONESEL_TIP | BONESEL_BONE)));
786   BLI_assert(EBONE_VISIBLE(arm, ebone));
787   bool changed = false;
788   bool is_point_done = false;
789   int points_proj_tot = 0;
790   BLI_assert(ebone->flag == ebone->temp.i);
791   const int ebone_flag_prev = ebone->flag;
792
793   if ((is_ignore_flag & BONE_ROOTSEL) == 0) {
794     points_proj_tot++;
795     const bool is_select = ebone->flag & BONE_ROOTSEL;
796     const bool is_inside = is_inside_flag & BONESEL_ROOT;
797     const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
798     if (sel_op_result != -1) {
799       if (sel_op_result == 0 || EBONE_SELECTABLE(arm, ebone)) {
800         SET_FLAG_FROM_TEST(ebone->flag, sel_op_result, BONE_ROOTSEL);
801       }
802     }
803     is_point_done |= is_inside;
804   }
805
806   if ((is_ignore_flag & BONE_TIPSEL) == 0) {
807     points_proj_tot++;
808     const bool is_select = ebone->flag & BONE_TIPSEL;
809     const bool is_inside = is_inside_flag & BONESEL_TIP;
810     const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
811     if (sel_op_result != -1) {
812       if (sel_op_result == 0 || EBONE_SELECTABLE(arm, ebone)) {
813         SET_FLAG_FROM_TEST(ebone->flag, sel_op_result, BONE_TIPSEL);
814       }
815     }
816     is_point_done |= is_inside;
817   }
818
819   /* if one of points selected, we skip the bone itself */
820   if ((is_point_done == false) && (points_proj_tot == 2)) {
821     const bool is_select = ebone->flag & BONE_SELECTED;
822     {
823       const bool is_inside = is_inside_flag & BONESEL_BONE;
824       const int sel_op_result = ED_select_op_action_deselected(sel_op, is_select, is_inside);
825       if (sel_op_result != -1) {
826         if (sel_op_result == 0 || EBONE_SELECTABLE(arm, ebone)) {
827           SET_FLAG_FROM_TEST(
828               ebone->flag, sel_op_result, BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL);
829         }
830       }
831     }
832
833     changed = true;
834   }
835   changed |= is_point_done;
836
837   if (ebone_flag_prev != ebone->flag) {
838     ebone->temp.i = ebone->flag;
839     ebone->flag = ebone_flag_prev;
840     ebone->flag = ebone_flag_prev | BONE_DONE;
841     changed = true;
842   }
843
844   return changed;
845 }
846
847 /**
848  * Perform a selection operation on elements which have been 'touched', use for lasso & border select
849  * but can be used elsewhere too.
850  *
851  * Tagging is done via #EditBone.temp.i using: #BONESEL_ROOT, #BONESEL_TIP, #BONESEL_BONE
852  * And optionally ignoring end-points using the #BONESEL_ROOT, #BONESEL_TIP right shifted 16 bits.
853  * (used when the values are clipped outside the view).
854  *
855  * \param sel_op: #eSelectOp type.
856  *
857  * \note Visibility checks must be done by the caller.
858  */
859 bool ED_armature_edit_select_op_from_tagged(bArmature *arm, const int sel_op)
860 {
861   bool changed = false;
862
863   /* Initialize flags. */
864   {
865     for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
866
867       /* Flush the parent flag to this bone
868        * so we don't need to check the parent when adjusting the selection. */
869       if ((ebone->flag & BONE_CONNECTED) && ebone->parent) {
870         if (ebone->parent->flag & BONE_TIPSEL) {
871           ebone->flag |= BONE_ROOTSEL;
872         }
873         else {
874           ebone->flag &= ~BONE_ROOTSEL;
875         }
876
877         /* Flush the 'temp.i' flag. */
878         if (ebone->parent->temp.i & BONESEL_TIP) {
879           ebone->temp.i |= BONESEL_ROOT;
880         }
881       }
882       ebone->flag &= ~BONE_DONE;
883     }
884   }
885
886   /* Apply selection from bone selection flags. */
887   for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
888     if (ebone->temp.i != 0) {
889       int is_ignore_flag = ((ebone->temp.i << 16) & (BONESEL_ROOT | BONESEL_TIP));
890       int is_inside_flag = (ebone->temp.i & (BONESEL_ROOT | BONESEL_TIP | BONESEL_BONE));
891
892       /* Use as previous bone flag from now on. */
893       ebone->temp.i = ebone->flag;
894
895       /* When there is a partial selection without both endpoints, only select an endpoint. */
896       if ((is_inside_flag & BONESEL_BONE) && (is_inside_flag & (BONESEL_ROOT | BONESEL_TIP)) &&
897           ((is_inside_flag & (BONESEL_ROOT | BONESEL_TIP)) != (BONESEL_ROOT | BONESEL_TIP))) {
898         is_inside_flag &= ~BONESEL_BONE;
899       }
900
901       changed |= armature_edit_select_op_apply(arm, ebone, sel_op, is_ignore_flag, is_inside_flag);
902     }
903   }
904
905   if (changed) {
906     /* Cleanup flags. */
907     for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
908       if (ebone->flag & BONE_DONE) {
909         SWAP(int, ebone->temp.i, ebone->flag);
910         ebone->flag |= BONE_DONE;
911         if ((ebone->flag & BONE_CONNECTED) && ebone->parent) {
912           if ((ebone->parent->flag & BONE_DONE) == 0) {
913             /* Checked below. */
914             ebone->parent->temp.i = ebone->parent->flag;
915           }
916         }
917       }
918     }
919
920     for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
921       if (ebone->flag & BONE_DONE) {
922         if ((ebone->flag & BONE_CONNECTED) && ebone->parent) {
923           bool is_parent_tip_changed = (ebone->parent->flag & BONE_TIPSEL) !=
924                                        (ebone->parent->temp.i & BONE_TIPSEL);
925           if ((ebone->temp.i & BONE_ROOTSEL) == 0) {
926             if ((ebone->flag & BONE_ROOTSEL) != 0) {
927               ebone->parent->flag |= BONE_TIPSEL;
928             }
929           }
930           else {
931             if ((ebone->flag & BONE_ROOTSEL) == 0) {
932               ebone->parent->flag &= ~BONE_TIPSEL;
933             }
934           }
935
936           if (is_parent_tip_changed == false) {
937             /* Keep tip selected if the parent remains selected. */
938             if (ebone->parent->flag & BONE_SELECTED) {
939               ebone->parent->flag |= BONE_TIPSEL;
940             }
941           }
942         }
943         ebone->flag &= ~BONE_DONE;
944       }
945     }
946
947     ED_armature_edit_sync_selection(arm->edbo);
948     ED_armature_edit_validate_active(arm);
949   }
950
951   return changed;
952 }
953
954 /** \} */
955
956 /* ****************  Selections  ******************/
957
958 static int armature_de_select_all_exec(bContext *C, wmOperator *op)
959 {
960   int action = RNA_enum_get(op->ptr, "action");
961
962   if (action == SEL_TOGGLE) {
963     /* Determine if there are any selected bones
964      * And therefore whether we are selecting or deselecting */
965     action = SEL_SELECT;
966     CTX_DATA_BEGIN (C, EditBone *, ebone, visible_bones) {
967       if (ebone->flag & (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL)) {
968         action = SEL_DESELECT;
969         break;
970       }
971     }
972     CTX_DATA_END;
973   }
974
975   /*  Set the flags */
976   CTX_DATA_BEGIN (C, EditBone *, ebone, visible_bones) {
977     /* ignore bone if selection can't change */
978     switch (action) {
979       case SEL_SELECT:
980         if ((ebone->flag & BONE_UNSELECTABLE) == 0) {
981           ebone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
982           if (ebone->parent) {
983             ebone->parent->flag |= (BONE_TIPSEL);
984           }
985         }
986         break;
987       case SEL_DESELECT:
988         ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
989         break;
990       case SEL_INVERT:
991         if (ebone->flag & BONE_SELECTED) {
992           ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
993         }
994         else {
995           if ((ebone->flag & BONE_UNSELECTABLE) == 0) {
996             ebone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
997             if (ebone->parent) {
998               ebone->parent->flag |= (BONE_TIPSEL);
999             }
1000           }
1001         }
1002         break;
1003     }
1004   }
1005   CTX_DATA_END;
1006
1007   WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, NULL);
1008
1009   return OPERATOR_FINISHED;
1010 }
1011
1012 void ARMATURE_OT_select_all(wmOperatorType *ot)
1013 {
1014   /* identifiers */
1015   ot->name = "(De)select All";
1016   ot->idname = "ARMATURE_OT_select_all";
1017   ot->description = "Toggle selection status of all bones";
1018
1019   /* api callbacks */
1020   ot->exec = armature_de_select_all_exec;
1021   ot->poll = ED_operator_editarmature;
1022
1023   /* flags */
1024   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1025
1026   WM_operator_properties_select_all(ot);
1027 }
1028
1029 /**************** Select more/less **************/
1030
1031 static void armature_select_more(bArmature *arm, EditBone *ebone)
1032 {
1033   if ((EBONE_PREV_FLAG_GET(ebone) & (BONE_ROOTSEL | BONE_TIPSEL)) != 0) {
1034     if (EBONE_SELECTABLE(arm, ebone)) {
1035       ED_armature_ebone_select_set(ebone, true);
1036     }
1037   }
1038
1039   if (ebone->parent && (ebone->flag & BONE_CONNECTED)) {
1040     /* to parent */
1041     if ((EBONE_PREV_FLAG_GET(ebone) & BONE_ROOTSEL) != 0) {
1042       if (EBONE_SELECTABLE(arm, ebone->parent)) {
1043         ED_armature_ebone_selectflag_enable(ebone->parent,
1044                                             (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL));
1045       }
1046     }
1047
1048     /* from parent (difference from select less) */
1049     if ((EBONE_PREV_FLAG_GET(ebone->parent) & BONE_TIPSEL) != 0) {
1050       if (EBONE_SELECTABLE(arm, ebone)) {
1051         ED_armature_ebone_selectflag_enable(ebone, (BONE_SELECTED | BONE_ROOTSEL));
1052       }
1053     }
1054   }
1055 }
1056
1057 static void armature_select_less(bArmature *UNUSED(arm), EditBone *ebone)
1058 {
1059   if ((EBONE_PREV_FLAG_GET(ebone) & (BONE_ROOTSEL | BONE_TIPSEL)) !=
1060       (BONE_ROOTSEL | BONE_TIPSEL)) {
1061     ED_armature_ebone_select_set(ebone, false);
1062   }
1063
1064   if (ebone->parent && (ebone->flag & BONE_CONNECTED)) {
1065     /* to parent */
1066     if ((EBONE_PREV_FLAG_GET(ebone) & BONE_SELECTED) == 0) {
1067       ED_armature_ebone_selectflag_disable(ebone->parent, (BONE_SELECTED | BONE_TIPSEL));
1068     }
1069
1070     /* from parent (difference from select more) */
1071     if ((EBONE_PREV_FLAG_GET(ebone->parent) & BONE_SELECTED) == 0) {
1072       ED_armature_ebone_selectflag_disable(ebone, (BONE_SELECTED | BONE_ROOTSEL));
1073     }
1074   }
1075 }
1076
1077 static void armature_select_more_less(Object *ob, bool more)
1078 {
1079   bArmature *arm = (bArmature *)ob->data;
1080   EditBone *ebone;
1081
1082   /* XXX, eventually we shouldn't need this - campbell */
1083   ED_armature_edit_sync_selection(arm->edbo);
1084
1085   /* count bones & store selection state */
1086   for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
1087     EBONE_PREV_FLAG_SET(ebone, ED_armature_ebone_selectflag_get(ebone));
1088   }
1089
1090   /* do selection */
1091   for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
1092     if (EBONE_VISIBLE(arm, ebone)) {
1093       if (more) {
1094         armature_select_more(arm, ebone);
1095       }
1096       else {
1097         armature_select_less(arm, ebone);
1098       }
1099     }
1100   }
1101
1102   for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
1103     if (EBONE_VISIBLE(arm, ebone)) {
1104       if (more == false) {
1105         if (ebone->flag & BONE_SELECTED) {
1106           ED_armature_ebone_select_set(ebone, true);
1107         }
1108       }
1109     }
1110     ebone->temp.p = NULL;
1111   }
1112
1113   ED_armature_edit_sync_selection(arm->edbo);
1114 }
1115
1116 static int armature_de_select_more_exec(bContext *C, wmOperator *UNUSED(op))
1117 {
1118   ViewLayer *view_layer = CTX_data_view_layer(C);
1119   uint objects_len = 0;
1120   Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
1121       view_layer, CTX_wm_view3d(C), &objects_len);
1122   for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
1123     Object *ob = objects[ob_index];
1124     armature_select_more_less(ob, true);
1125     WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
1126   }
1127   MEM_freeN(objects);
1128   return OPERATOR_FINISHED;
1129 }
1130
1131 void ARMATURE_OT_select_more(wmOperatorType *ot)
1132 {
1133   /* identifiers */
1134   ot->name = "Select More";
1135   ot->idname = "ARMATURE_OT_select_more";
1136   ot->description = "Select those bones connected to the initial selection";
1137
1138   /* api callbacks */
1139   ot->exec = armature_de_select_more_exec;
1140   ot->poll = ED_operator_editarmature;
1141
1142   /* flags */
1143   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1144 }
1145
1146 static int armature_de_select_less_exec(bContext *C, wmOperator *UNUSED(op))
1147 {
1148   ViewLayer *view_layer = CTX_data_view_layer(C);
1149   uint objects_len = 0;
1150   Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
1151       view_layer, CTX_wm_view3d(C), &objects_len);
1152   for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
1153     Object *ob = objects[ob_index];
1154     armature_select_more_less(ob, false);
1155     WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
1156   }
1157   MEM_freeN(objects);
1158   return OPERATOR_FINISHED;
1159 }
1160
1161 void ARMATURE_OT_select_less(wmOperatorType *ot)
1162 {
1163   /* identifiers */
1164   ot->name = "Select Less";
1165   ot->idname = "ARMATURE_OT_select_less";
1166   ot->description = "Deselect those bones at the boundary of each selection region";
1167
1168   /* api callbacks */
1169   ot->exec = armature_de_select_less_exec;
1170   ot->poll = ED_operator_editarmature;
1171
1172   /* flags */
1173   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1174 }
1175
1176 enum {
1177   SIMEDBONE_CHILDREN = 1,
1178   SIMEDBONE_CHILDREN_IMMEDIATE,
1179   SIMEDBONE_SIBLINGS,
1180   SIMEDBONE_LENGTH,
1181   SIMEDBONE_DIRECTION,
1182   SIMEDBONE_PREFIX,
1183   SIMEDBONE_SUFFIX,
1184   SIMEDBONE_LAYER,
1185   SIMEDBONE_GROUP,
1186   SIMEDBONE_SHAPE,
1187 };
1188
1189 static const EnumPropertyItem prop_similar_types[] = {
1190     {SIMEDBONE_CHILDREN, "CHILDREN", 0, "Children", ""},
1191     {SIMEDBONE_CHILDREN_IMMEDIATE, "CHILDREN_IMMEDIATE", 0, "Immediate children", ""},
1192     {SIMEDBONE_SIBLINGS, "SIBLINGS", 0, "Siblings", ""},
1193     {SIMEDBONE_LENGTH, "LENGTH", 0, "Length", ""},
1194     {SIMEDBONE_DIRECTION, "DIRECTION", 0, "Direction (Y axis)", ""},
1195     {SIMEDBONE_PREFIX, "PREFIX", 0, "Prefix", ""},
1196     {SIMEDBONE_SUFFIX, "SUFFIX", 0, "Suffix", ""},
1197     {SIMEDBONE_LAYER, "LAYER", 0, "Layer", ""},
1198     {SIMEDBONE_GROUP, "GROUP", 0, "Group", ""},
1199     {SIMEDBONE_SHAPE, "SHAPE", 0, "Shape", ""},
1200     {0, NULL, 0, NULL, NULL},
1201 };
1202
1203 static float bone_length_squared_worldspace_get(Object *ob, EditBone *ebone)
1204 {
1205   float v1[3], v2[3];
1206   mul_v3_mat3_m4v3(v1, ob->obmat, ebone->head);
1207   mul_v3_mat3_m4v3(v2, ob->obmat, ebone->tail);
1208   return len_squared_v3v3(v1, v2);
1209 }
1210
1211 static void select_similar_length(bContext *C, const float thresh)
1212 {
1213   ViewLayer *view_layer = CTX_data_view_layer(C);
1214   Object *ob_act = CTX_data_edit_object(C);
1215   EditBone *ebone_act = CTX_data_active_bone(C);
1216
1217   /* Thresh is always relative to current length. */
1218   const float len = bone_length_squared_worldspace_get(ob_act, ebone_act);
1219   const float len_min = len / (1.0f + (thresh - FLT_EPSILON));
1220   const float len_max = len * (1.0f + (thresh + FLT_EPSILON));
1221
1222   uint objects_len = 0;
1223   Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
1224       view_layer, CTX_wm_view3d(C), &objects_len);
1225   for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
1226     Object *ob = objects[ob_index];
1227     bArmature *arm = ob->data;
1228     bool changed = false;
1229
1230     for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
1231       if (EBONE_SELECTABLE(arm, ebone)) {
1232         const float len_iter = bone_length_squared_worldspace_get(ob, ebone);
1233         if ((len_iter > len_min) && (len_iter < len_max)) {
1234           ED_armature_ebone_select_set(ebone, true);
1235           changed = true;
1236         }
1237       }
1238     }
1239
1240     if (changed) {
1241       WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
1242     }
1243   }
1244   MEM_freeN(objects);
1245 }
1246
1247 static void bone_direction_worldspace_get(Object *ob, EditBone *ebone, float *r_dir)
1248 {
1249   float v1[3], v2[3];
1250   copy_v3_v3(v1, ebone->head);
1251   copy_v3_v3(v2, ebone->tail);
1252
1253   mul_m4_v3(ob->obmat, v1);
1254   mul_m4_v3(ob->obmat, v2);
1255
1256   sub_v3_v3v3(r_dir, v1, v2);
1257   normalize_v3(r_dir);
1258 }
1259
1260 static void select_similar_direction(bContext *C, const float thresh)
1261 {
1262   ViewLayer *view_layer = CTX_data_view_layer(C);
1263   Object *ob_act = CTX_data_edit_object(C);
1264   EditBone *ebone_act = CTX_data_active_bone(C);
1265
1266   float dir_act[3];
1267   bone_direction_worldspace_get(ob_act, ebone_act, dir_act);
1268
1269   uint objects_len = 0;
1270   Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
1271       view_layer, CTX_wm_view3d(C), &objects_len);
1272   for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
1273     Object *ob = objects[ob_index];
1274     bArmature *arm = ob->data;
1275     bool changed = false;
1276
1277     for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
1278       if (EBONE_SELECTABLE(arm, ebone)) {
1279         float dir[3];
1280         bone_direction_worldspace_get(ob, ebone, dir);
1281
1282         if (angle_v3v3(dir_act, dir) / (float)M_PI < (thresh + FLT_EPSILON)) {
1283           ED_armature_ebone_select_set(ebone, true);
1284           changed = true;
1285         }
1286       }
1287     }
1288
1289     if (changed) {
1290       WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
1291     }
1292   }
1293   MEM_freeN(objects);
1294 }
1295
1296 static void select_similar_layer(bContext *C)
1297 {
1298   ViewLayer *view_layer = CTX_data_view_layer(C);
1299   EditBone *ebone_act = CTX_data_active_bone(C);
1300
1301   uint objects_len = 0;
1302   Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
1303       view_layer, CTX_wm_view3d(C), &objects_len);
1304   for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
1305     Object *ob = objects[ob_index];
1306     bArmature *arm = ob->data;
1307     bool changed = false;
1308
1309     for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
1310       if (EBONE_SELECTABLE(arm, ebone)) {
1311         if (ebone->layer & ebone_act->layer) {
1312           ED_armature_ebone_select_set(ebone, true);
1313           changed = true;
1314         }
1315       }
1316     }
1317
1318     if (changed) {
1319       WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
1320     }
1321   }
1322   MEM_freeN(objects);
1323 }
1324
1325 static void select_similar_prefix(bContext *C)
1326 {
1327   ViewLayer *view_layer = CTX_data_view_layer(C);
1328   EditBone *ebone_act = CTX_data_active_bone(C);
1329
1330   char body_tmp[MAXBONENAME];
1331   char prefix_act[MAXBONENAME];
1332
1333   BLI_string_split_prefix(ebone_act->name, prefix_act, body_tmp, sizeof(ebone_act->name));
1334
1335   if (prefix_act[0] == '\0') {
1336     return;
1337   }
1338
1339   uint objects_len = 0;
1340   Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
1341       view_layer, CTX_wm_view3d(C), &objects_len);
1342   for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
1343     Object *ob = objects[ob_index];
1344     bArmature *arm = ob->data;
1345     bool changed = false;
1346
1347     /* Find matches */
1348     for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
1349       if (EBONE_SELECTABLE(arm, ebone)) {
1350         char prefix_other[MAXBONENAME];
1351         BLI_string_split_prefix(ebone->name, prefix_other, body_tmp, sizeof(ebone->name));
1352         if (STREQ(prefix_act, prefix_other)) {
1353           ED_armature_ebone_select_set(ebone, true);
1354           changed = true;
1355         }
1356       }
1357     }
1358
1359     if (changed) {
1360       WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
1361     }
1362   }
1363   MEM_freeN(objects);
1364 }
1365
1366 static void select_similar_suffix(bContext *C)
1367 {
1368   ViewLayer *view_layer = CTX_data_view_layer(C);
1369   EditBone *ebone_act = CTX_data_active_bone(C);
1370
1371   char body_tmp[MAXBONENAME];
1372   char suffix_act[MAXBONENAME];
1373
1374   BLI_string_split_suffix(ebone_act->name, body_tmp, suffix_act, sizeof(ebone_act->name));
1375
1376   if (suffix_act[0] == '\0')
1377     return;
1378
1379   uint objects_len = 0;
1380   Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
1381       view_layer, CTX_wm_view3d(C), &objects_len);
1382   for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
1383     Object *ob = objects[ob_index];
1384     bArmature *arm = ob->data;
1385     bool changed = false;
1386
1387     /* Find matches */
1388     for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
1389       if (EBONE_SELECTABLE(arm, ebone)) {
1390         char suffix_other[MAXBONENAME];
1391         BLI_string_split_suffix(ebone->name, body_tmp, suffix_other, sizeof(ebone->name));
1392         if (STREQ(suffix_act, suffix_other)) {
1393           ED_armature_ebone_select_set(ebone, true);
1394           changed = true;
1395         }
1396       }
1397     }
1398
1399     if (changed) {
1400       WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
1401     }
1402   }
1403   MEM_freeN(objects);
1404 }
1405
1406 /** Use for matching any pose channel data. */
1407 static void select_similar_data_pchan(bContext *C, const size_t bytes_size, const int offset)
1408 {
1409   Object *obedit = CTX_data_edit_object(C);
1410   bArmature *arm = obedit->data;
1411   EditBone *ebone_act = CTX_data_active_bone(C);
1412
1413   const bPoseChannel *pchan_active = BKE_pose_channel_find_name(obedit->pose, ebone_act->name);
1414   const char *data_active = (const char *)POINTER_OFFSET(pchan_active, offset);
1415   for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
1416     if (EBONE_SELECTABLE(arm, ebone)) {
1417       const bPoseChannel *pchan = BKE_pose_channel_find_name(obedit->pose, ebone->name);
1418       if (pchan) {
1419         const char *data_test = (const char *)POINTER_OFFSET(pchan, offset);
1420         if (memcmp(data_active, data_test, bytes_size) == 0) {
1421           ED_armature_ebone_select_set(ebone, true);
1422         }
1423       }
1424     }
1425   }
1426
1427   WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
1428 }
1429
1430 static void is_ancestor(EditBone *bone, EditBone *ancestor)
1431 {
1432   if (bone->temp.ebone == ancestor || bone->temp.ebone == NULL)
1433     return;
1434
1435   if (bone->temp.ebone->temp.ebone != NULL && bone->temp.ebone->temp.ebone != ancestor)
1436     is_ancestor(bone->temp.ebone, ancestor);
1437
1438   bone->temp.ebone = bone->temp.ebone->temp.ebone;
1439 }
1440
1441 static void select_similar_children(bContext *C)
1442 {
1443   Object *obedit = CTX_data_edit_object(C);
1444   bArmature *arm = obedit->data;
1445   EditBone *ebone_act = CTX_data_active_bone(C);
1446
1447   for (EditBone *ebone_iter = arm->edbo->first; ebone_iter; ebone_iter = ebone_iter->next) {
1448     ebone_iter->temp.ebone = ebone_iter->parent;
1449   }
1450
1451   for (EditBone *ebone_iter = arm->edbo->first; ebone_iter; ebone_iter = ebone_iter->next) {
1452     is_ancestor(ebone_iter, ebone_act);
1453
1454     if (ebone_iter->temp.ebone == ebone_act && EBONE_SELECTABLE(arm, ebone_iter))
1455       ED_armature_ebone_select_set(ebone_iter, true);
1456   }
1457
1458   WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
1459 }
1460
1461 static void select_similar_children_immediate(bContext *C)
1462 {
1463   Object *obedit = CTX_data_edit_object(C);
1464   bArmature *arm = obedit->data;
1465   EditBone *ebone_act = CTX_data_active_bone(C);
1466
1467   for (EditBone *ebone_iter = arm->edbo->first; ebone_iter; ebone_iter = ebone_iter->next) {
1468     if (ebone_iter->parent == ebone_act && EBONE_SELECTABLE(arm, ebone_iter)) {
1469       ED_armature_ebone_select_set(ebone_iter, true);
1470     }
1471   }
1472
1473   WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
1474 }
1475
1476 static void select_similar_siblings(bContext *C)
1477 {
1478   Object *obedit = CTX_data_edit_object(C);
1479   bArmature *arm = obedit->data;
1480   EditBone *ebone_act = CTX_data_active_bone(C);
1481
1482   if (ebone_act->parent == NULL) {
1483     return;
1484   }
1485
1486   for (EditBone *ebone_iter = arm->edbo->first; ebone_iter; ebone_iter = ebone_iter->next) {
1487     if (ebone_iter->parent == ebone_act->parent && EBONE_SELECTABLE(arm, ebone_iter)) {
1488       ED_armature_ebone_select_set(ebone_iter, true);
1489     }
1490   }
1491
1492   WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
1493 }
1494
1495 static int armature_select_similar_exec(bContext *C, wmOperator *op)
1496 {
1497   /* Get props */
1498   int type = RNA_enum_get(op->ptr, "type");
1499   float thresh = RNA_float_get(op->ptr, "threshold");
1500
1501   /* Check for active bone */
1502   if (CTX_data_active_bone(C) == NULL) {
1503     BKE_report(op->reports, RPT_ERROR, "Operation requires an active bone");
1504     return OPERATOR_CANCELLED;
1505   }
1506
1507 #define STRUCT_SIZE_AND_OFFSET(_struct, _member) \
1508   sizeof(((_struct *)NULL)->_member), offsetof(_struct, _member)
1509
1510   switch (type) {
1511     case SIMEDBONE_CHILDREN:
1512       select_similar_children(C);
1513       break;
1514     case SIMEDBONE_CHILDREN_IMMEDIATE:
1515       select_similar_children_immediate(C);
1516       break;
1517     case SIMEDBONE_SIBLINGS:
1518       select_similar_siblings(C);
1519       break;
1520     case SIMEDBONE_LENGTH:
1521       select_similar_length(C, thresh);
1522       break;
1523     case SIMEDBONE_DIRECTION:
1524       select_similar_direction(C, thresh);
1525       break;
1526     case SIMEDBONE_PREFIX:
1527       select_similar_prefix(C);
1528       break;
1529     case SIMEDBONE_SUFFIX:
1530       select_similar_suffix(C);
1531       break;
1532     case SIMEDBONE_LAYER:
1533       select_similar_layer(C);
1534       break;
1535     case SIMEDBONE_GROUP:
1536       select_similar_data_pchan(C, STRUCT_SIZE_AND_OFFSET(bPoseChannel, agrp_index));
1537       break;
1538     case SIMEDBONE_SHAPE:
1539       select_similar_data_pchan(C, STRUCT_SIZE_AND_OFFSET(bPoseChannel, custom));
1540       break;
1541   }
1542
1543 #undef STRUCT_SIZE_AND_OFFSET
1544
1545   return OPERATOR_FINISHED;
1546 }
1547
1548 void ARMATURE_OT_select_similar(wmOperatorType *ot)
1549 {
1550   /* identifiers */
1551   ot->name = "Select Similar";
1552   ot->idname = "ARMATURE_OT_select_similar";
1553
1554   /* callback functions */
1555   ot->invoke = WM_menu_invoke;
1556   ot->exec = armature_select_similar_exec;
1557   ot->poll = ED_operator_editarmature;
1558   ot->description = "Select similar bones by property types";
1559
1560   /* flags */
1561   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1562
1563   /* properties */
1564   ot->prop = RNA_def_enum(ot->srna, "type", prop_similar_types, SIMEDBONE_LENGTH, "Type", "");
1565   RNA_def_float(ot->srna, "threshold", 0.1f, 0.0f, 1.0f, "Threshold", "", 0.0f, 1.0f);
1566 }
1567
1568 /* ********************* select hierarchy operator ************** */
1569
1570 /* No need to convert to multi-objects. Just like we keep the non-active bones
1571  * selected we then keep the non-active objects untouched (selected/unselected). */
1572 static int armature_select_hierarchy_exec(bContext *C, wmOperator *op)
1573 {
1574   Object *ob = CTX_data_edit_object(C);
1575   EditBone *ebone_active;
1576   int direction = RNA_enum_get(op->ptr, "direction");
1577   const bool add_to_sel = RNA_boolean_get(op->ptr, "extend");
1578   bool changed = false;
1579   bArmature *arm = (bArmature *)ob->data;
1580
1581   ebone_active = arm->act_edbone;
1582   if (ebone_active == NULL) {
1583     return OPERATOR_CANCELLED;
1584   }
1585
1586   if (direction == BONE_SELECT_PARENT) {
1587     if (ebone_active->parent) {
1588       EditBone *ebone_parent;
1589
1590       ebone_parent = ebone_active->parent;
1591
1592       if (EBONE_SELECTABLE(arm, ebone_parent)) {
1593         arm->act_edbone = ebone_parent;
1594
1595         if (!add_to_sel) {
1596           ED_armature_ebone_select_set(ebone_active, false);
1597         }
1598         ED_armature_ebone_select_set(ebone_parent, true);
1599
1600         changed = true;
1601       }
1602     }
1603   }
1604   else { /* BONE_SELECT_CHILD */
1605     EditBone *ebone_iter, *ebone_child = NULL;
1606     int pass;
1607
1608     /* first pass, only connected bones (the logical direct child) */
1609     for (pass = 0; pass < 2 && (ebone_child == NULL); pass++) {
1610       for (ebone_iter = arm->edbo->first; ebone_iter; ebone_iter = ebone_iter->next) {
1611         /* possible we have multiple children, some invisible */
1612         if (EBONE_SELECTABLE(arm, ebone_iter)) {
1613           if (ebone_iter->parent == ebone_active) {
1614             if ((pass == 1) || (ebone_iter->flag & BONE_CONNECTED)) {
1615               ebone_child = ebone_iter;
1616               break;
1617             }
1618           }
1619         }
1620       }
1621     }
1622
1623     if (ebone_child) {
1624       arm->act_edbone = ebone_child;
1625
1626       if (!add_to_sel) {
1627         ED_armature_ebone_select_set(ebone_active, false);
1628       }
1629       ED_armature_ebone_select_set(ebone_child, true);
1630
1631       changed = true;
1632     }
1633   }
1634
1635   if (changed == false) {
1636     return OPERATOR_CANCELLED;
1637   }
1638
1639   ED_armature_edit_sync_selection(arm->edbo);
1640
1641   WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
1642
1643   return OPERATOR_FINISHED;
1644 }
1645
1646 void ARMATURE_OT_select_hierarchy(wmOperatorType *ot)
1647 {
1648   static const EnumPropertyItem direction_items[] = {
1649       {BONE_SELECT_PARENT, "PARENT", 0, "Select Parent", ""},
1650       {BONE_SELECT_CHILD, "CHILD", 0, "Select Child", ""},
1651       {0, NULL, 0, NULL, NULL},
1652   };
1653
1654   /* identifiers */
1655   ot->name = "Select Hierarchy";
1656   ot->idname = "ARMATURE_OT_select_hierarchy";
1657   ot->description = "Select immediate parent/children of selected bones";
1658
1659   /* api callbacks */
1660   ot->exec = armature_select_hierarchy_exec;
1661   ot->poll = ED_operator_editarmature;
1662
1663   /* flags */
1664   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1665
1666   /* props */
1667   RNA_def_enum(ot->srna, "direction", direction_items, BONE_SELECT_PARENT, "Direction", "");
1668   RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
1669 }
1670
1671 /****************** Mirror Select ****************/
1672
1673 /**
1674  * \note clone of #pose_select_mirror_exec keep in sync
1675  */
1676 static int armature_select_mirror_exec(bContext *C, wmOperator *op)
1677 {
1678   ViewLayer *view_layer = CTX_data_view_layer(C);
1679   const bool active_only = RNA_boolean_get(op->ptr, "only_active");
1680   const bool extend = RNA_boolean_get(op->ptr, "extend");
1681
1682   uint objects_len = 0;
1683   Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(
1684       view_layer, CTX_wm_view3d(C), &objects_len);
1685   for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
1686     Object *ob = objects[ob_index];
1687     bArmature *arm = ob->data;
1688
1689     EditBone *ebone, *ebone_mirror_act = NULL;
1690
1691     for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
1692       const int flag = ED_armature_ebone_selectflag_get(ebone);
1693       EBONE_PREV_FLAG_SET(ebone, flag);
1694     }
1695
1696     for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
1697       if (EBONE_SELECTABLE(arm, ebone)) {
1698         EditBone *ebone_mirror;
1699         int flag_new = extend ? EBONE_PREV_FLAG_GET(ebone) : 0;
1700
1701         if ((ebone_mirror = ED_armature_ebone_get_mirrored(arm->edbo, ebone)) &&
1702             (EBONE_VISIBLE(arm, ebone_mirror))) {
1703           const int flag_mirror = EBONE_PREV_FLAG_GET(ebone_mirror);
1704           flag_new |= flag_mirror;
1705
1706           if (ebone == arm->act_edbone) {
1707             ebone_mirror_act = ebone_mirror;
1708           }
1709
1710           /* skip all but the active or its mirror */
1711           if (active_only && !ELEM(arm->act_edbone, ebone, ebone_mirror)) {
1712             continue;
1713           }
1714         }
1715
1716         ED_armature_ebone_selectflag_set(ebone, flag_new);
1717       }
1718     }
1719
1720     if (ebone_mirror_act) {
1721       arm->act_edbone = ebone_mirror_act;
1722     }
1723
1724     ED_armature_edit_sync_selection(arm->edbo);
1725
1726     WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
1727   }
1728   MEM_freeN(objects);
1729
1730   return OPERATOR_FINISHED;
1731 }
1732
1733 void ARMATURE_OT_select_mirror(wmOperatorType *ot)
1734 {
1735   /* identifiers */
1736   ot->name = "Flip Active/Selected Bone";
1737   ot->idname = "ARMATURE_OT_select_mirror";
1738   ot->description = "Mirror the bone selection";
1739
1740   /* api callbacks */
1741   ot->exec = armature_select_mirror_exec;
1742   ot->poll = ED_operator_editarmature;
1743
1744   /* flags */
1745   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1746
1747   /* properties */
1748   RNA_def_boolean(
1749       ot->srna, "only_active", false, "Active Only", "Only operate on the active bone");
1750   RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
1751 }
1752
1753 /****************** Select Path ****************/
1754
1755 static bool armature_shortest_path_select(
1756     bArmature *arm, EditBone *ebone_parent, EditBone *ebone_child, bool use_parent, bool is_test)
1757 {
1758   do {
1759
1760     if (!use_parent && (ebone_child == ebone_parent))
1761       break;
1762
1763     if (is_test) {
1764       if (!EBONE_SELECTABLE(arm, ebone_child)) {
1765         return false;
1766       }
1767     }
1768     else {
1769       ED_armature_ebone_selectflag_set(ebone_child, (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL));
1770     }
1771
1772     if (ebone_child == ebone_parent)
1773       break;
1774
1775     ebone_child = ebone_child->parent;
1776   } while (true);
1777
1778   return true;
1779 }
1780
1781 static int armature_shortest_path_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
1782 {
1783   Object *obedit = CTX_data_edit_object(C);
1784   bArmature *arm = obedit->data;
1785   EditBone *ebone_src, *ebone_dst;
1786   EditBone *ebone_isect_parent = NULL;
1787   EditBone *ebone_isect_child[2];
1788   bool changed;
1789   Base *base_dst = NULL;
1790
1791   view3d_operator_needs_opengl(C);
1792
1793   ebone_src = arm->act_edbone;
1794   ebone_dst = get_nearest_bone(C, event->mval, false, &base_dst);
1795
1796   /* fallback to object selection */
1797   if (ELEM(NULL, ebone_src, ebone_dst) || (ebone_src == ebone_dst)) {
1798     return OPERATOR_PASS_THROUGH;
1799   }
1800
1801   if (base_dst && base_dst->object != obedit) {
1802     /* Disconnected, ignore. */
1803     return OPERATOR_CANCELLED;
1804   }
1805
1806   ebone_isect_child[0] = ebone_src;
1807   ebone_isect_child[1] = ebone_dst;
1808
1809   /* ensure 'ebone_src' is the parent of 'ebone_dst', or set 'ebone_isect_parent' */
1810   if (ED_armature_ebone_is_child_recursive(ebone_src, ebone_dst)) {
1811     /* pass */
1812   }
1813   else if (ED_armature_ebone_is_child_recursive(ebone_dst, ebone_src)) {
1814     SWAP(EditBone *, ebone_src, ebone_dst);
1815   }
1816   else if ((ebone_isect_parent = ED_armature_ebone_find_shared_parent(ebone_isect_child, 2))) {
1817     /* pass */
1818   }
1819   else {
1820     /* disconnected bones */
1821     return OPERATOR_CANCELLED;
1822   }
1823
1824   if (ebone_isect_parent) {
1825     if (armature_shortest_path_select(arm, ebone_isect_parent, ebone_src, false, true) &&
1826         armature_shortest_path_select(arm, ebone_isect_parent, ebone_dst, false, true)) {
1827       armature_shortest_path_select(arm, ebone_isect_parent, ebone_src, false, false);
1828       armature_shortest_path_select(arm, ebone_isect_parent, ebone_dst, false, false);
1829       changed = true;
1830     }
1831     else {
1832       /* unselectable */
1833       changed = false;
1834     }
1835   }
1836   else {
1837     if (armature_shortest_path_select(arm, ebone_src, ebone_dst, true, true)) {
1838       armature_shortest_path_select(arm, ebone_src, ebone_dst, true, false);
1839       changed = true;
1840     }
1841     else {
1842       /* unselectable */
1843       changed = false;
1844     }
1845   }
1846
1847   if (changed) {
1848     arm->act_edbone = ebone_dst;
1849     ED_armature_edit_sync_selection(arm->edbo);
1850     WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
1851
1852     return OPERATOR_FINISHED;
1853   }
1854   else {
1855     BKE_report(op->reports, RPT_WARNING, "Unselectable bone in chain");
1856     return OPERATOR_CANCELLED;
1857   }
1858 }
1859
1860 void ARMATURE_OT_shortest_path_pick(wmOperatorType *ot)
1861 {
1862   /* identifiers */
1863   ot->name = "Pick Shortest Path";
1864   ot->idname = "ARMATURE_OT_shortest_path_pick";
1865   ot->description = "Select shortest path between two bones";
1866
1867   /* api callbacks */
1868   ot->invoke = armature_shortest_path_pick_invoke;
1869   ot->poll = ED_operator_editarmature;
1870
1871   /* flags */
1872   ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1873 }