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