Merge branch 'master' into blender2.8
[blender.git] / source / blender / editors / armature / armature_select.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
19  * All rights reserved.
20  *
21  * Contributor(s): Blender Foundation, 2002-2009 full recode.
22  *
23  * ***** END GPL LICENSE BLOCK *****
24  *
25  * API's and Operators for selecting armature bones in EditMode
26  */
27
28 /** \file blender/editors/armature/armature_select.c
29  *  \ingroup edarmature
30  */
31
32 #include "MEM_guardedalloc.h"
33
34 #include "DNA_armature_types.h"
35 #include "DNA_object_types.h"
36 #include "DNA_scene_types.h"
37
38 #include "BLI_blenlib.h"
39 #include "BLI_math.h"
40 #include "BLI_string_utils.h"
41
42 #include "BKE_context.h"
43 #include "BKE_action.h"
44 #include "BKE_object.h"
45 #include "BKE_report.h"
46 #include "BKE_layer.h"
47
48 #include "BIF_gl.h"
49
50 #include "RNA_access.h"
51 #include "RNA_define.h"
52
53 #include "WM_api.h"
54 #include "WM_types.h"
55
56 #include "ED_armature.h"
57 #include "ED_screen.h"
58 #include "ED_view3d.h"
59
60 #include "DEG_depsgraph.h"
61
62 #include "armature_intern.h"
63
64 /* utility macros for storing a temp int in the bone (selection flag) */
65 #define EBONE_PREV_FLAG_GET(ebone) ((void)0, (ebone)->temp.i)
66 #define EBONE_PREV_FLAG_SET(ebone, val) ((ebone)->temp.i = val)
67
68 /* **************** PoseMode & EditMode Selection Buffer Queries *************************** */
69
70 Base *ED_armature_base_and_ebone_from_select_buffer(
71         Base **bases, uint bases_len, int hit, EditBone **r_ebone)
72 {
73         const uint hit_object = hit & 0xFFFF;
74         Base *base = NULL;
75         EditBone *ebone = NULL;
76         /* TODO(campbell): optimize, eg: sort & binary search. */
77         for (uint base_index = 0; base_index < bases_len; base_index++) {
78                 if (bases[base_index]->object->select_color == hit_object) {
79                         base = bases[base_index];
80                         break;
81                 }
82         }
83         if (base != NULL) {
84                 const uint hit_bone = (hit & ~BONESEL_ANY) >> 16;
85                 bArmature *arm = base->object->data;
86                 ebone = BLI_findlink(arm->edbo, hit_bone);
87         }
88         *r_ebone = ebone;
89         return base;
90 }
91
92 Object *ED_armature_object_and_ebone_from_select_buffer(
93         Object **objects, uint objects_len, int hit, EditBone **r_ebone)
94 {
95         const uint hit_object = hit & 0xFFFF;
96         Object *ob = NULL;
97         EditBone *ebone = NULL;
98         /* TODO(campbell): optimize, eg: sort & binary search. */
99         for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
100                 if (objects[ob_index]->select_color == hit_object) {
101                         ob = objects[ob_index];
102                         break;
103                 }
104         }
105         if (ob != NULL) {
106                 const uint hit_bone = (hit & ~BONESEL_ANY) >> 16;
107                 bArmature *arm = ob->data;
108                 ebone = BLI_findlink(arm->edbo, hit_bone);
109         }
110         *r_ebone = ebone;
111         return ob;
112 }
113
114 Base *ED_armature_base_and_bone_from_select_buffer(
115         Base **bases, uint bases_len, int hit, Bone **r_bone)
116 {
117         const uint hit_object = hit & 0xFFFF;
118         Base *base = NULL;
119         Bone *bone = NULL;
120         /* TODO(campbell): optimize, eg: sort & binary search. */
121         for (uint base_index = 0; base_index < bases_len; base_index++) {
122                 if (bases[base_index]->object->select_color == hit_object) {
123                         base = bases[base_index];
124                         break;
125                 }
126         }
127         if (base != NULL) {
128                 if (base->object->pose != NULL) {
129                         const uint hit_bone = (hit & ~BONESEL_ANY) >> 16;
130                         bPoseChannel *pchan = BLI_findlink(&base->object->pose->chanbase, hit_bone);;
131                         bone = pchan ? pchan->bone : NULL;
132                 }
133         }
134         *r_bone = bone;
135         return base;
136 }
137
138 /* See if there are any selected bones in this buffer */
139 /* only bones from base are checked on */
140 void *get_bone_from_selectbuffer(
141         Base **bases, uint bases_len, bool is_editmode, const unsigned int *buffer, short hits,
142         bool findunsel, bool do_nearest, Base **r_base)
143 {
144         Bone *bone;
145         EditBone *ebone;
146         void *firstunSel = NULL, *firstSel = NULL, *data;
147         Base *firstunSel_base = NULL, *firstSel_base = NULL;
148         unsigned int hitresult;
149         short i;
150         bool takeNext = false;
151         int minsel = 0xffffffff, minunsel = 0xffffffff;
152
153         for (i = 0; i < hits; i++) {
154                 hitresult = buffer[3 + (i * 4)];
155
156                 if (!(hitresult & BONESEL_NOSEL)) {
157                         if (hitresult & BONESEL_ANY) {  /* to avoid including objects in selection */
158                                 Base *base = NULL;
159                                 bool sel;
160
161                                 hitresult &= ~(BONESEL_ANY);
162                                 /* Determine what the current bone is */
163                                 if (is_editmode == false) {
164                                         base = ED_armature_base_and_bone_from_select_buffer(bases, bases_len, hitresult, &bone);
165                                         if (bone != NULL) {
166                                                 if (findunsel)
167                                                         sel = (bone->flag & BONE_SELECTED);
168                                                 else
169                                                         sel = !(bone->flag & BONE_SELECTED);
170
171                                                 data = bone;
172                                         }
173                                         else {
174                                                 data = NULL;
175                                                 sel = 0;
176                                         }
177                                 }
178                                 else {
179                                         base = ED_armature_base_and_ebone_from_select_buffer(bases, bases_len, hitresult, &ebone);
180                                         if (findunsel)
181                                                 sel = (ebone->flag & BONE_SELECTED);
182                                         else
183                                                 sel = !(ebone->flag & BONE_SELECTED);
184
185                                         data = ebone;
186                                 }
187
188                                 if (data) {
189                                         if (sel) {
190                                                 if (do_nearest) {
191                                                         if (minsel > buffer[4 * i + 1]) {
192                                                                 firstSel = data;
193                                                                 firstSel_base = base;
194                                                                 minsel = buffer[4 * i + 1];
195                                                         }
196                                                 }
197                                                 else {
198                                                         if (!firstSel) {
199                                                                 firstSel = data;
200                                                                 firstSel_base = base;
201                                                         }
202                                                         takeNext = 1;
203                                                 }
204                                         }
205                                         else {
206                                                 if (do_nearest) {
207                                                         if (minunsel > buffer[4 * i + 1]) {
208                                                                 firstunSel = data;
209                                                                 firstunSel_base = base;
210                                                                 minunsel = buffer[4 * i + 1];
211                                                         }
212                                                 }
213                                                 else {
214                                                         if (!firstunSel) {
215                                                                 firstunSel = data;
216                                                                 firstunSel_base = base;
217                                                         }
218                                                         if (takeNext) {
219                                                                 *r_base = base;
220                                                                 return data;
221                                                         }
222                                                 }
223                                         }
224                                 }
225                         }
226                 }
227         }
228
229         if (firstunSel) {
230                 *r_base = firstunSel_base;
231                 return firstunSel;
232         }
233         else {
234                 *r_base = firstSel_base;
235                 return firstSel;
236         }
237 }
238
239 /* used by posemode as well editmode */
240 /* only checks scene->basact! */
241 /* x and y are mouse coords (area space) */
242 void *get_nearest_bone(
243         bContext *C, const int xy[2], bool findunsel,
244         Base **r_base)
245 {
246         ViewContext vc;
247         rcti rect;
248         unsigned int buffer[MAXPICKBUF];
249         short hits;
250
251         ED_view3d_viewcontext_init(C, &vc);
252
253         // rect.xmin = ... mouseco!
254         rect.xmin = rect.xmax = xy[0];
255         rect.ymin = rect.ymax = xy[1];
256
257         hits = view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect, VIEW3D_SELECT_PICK_NEAREST);
258
259         *r_base = NULL;
260
261         if (hits > 0) {
262                 uint bases_len = 0;
263                 Base **bases;
264
265                 if (vc.obedit != NULL) {
266                         bases = BKE_view_layer_array_from_bases_in_mode(
267                                 vc.view_layer, &bases_len, {
268                                     .object_mode = OB_MODE_EDIT});
269                 }
270                 else {
271                         bases = BKE_object_pose_base_array_get(vc.view_layer, &bases_len);
272                 }
273
274                 void *bone = get_bone_from_selectbuffer(
275                         bases, bases_len, vc.obedit != NULL, buffer, hits, findunsel, true, r_base);
276
277                 MEM_freeN(bases);
278                 return bone;
279         }
280         return NULL;
281 }
282
283 /* **************** EditMode stuff ********************** */
284
285 /* called in space.c */
286 /* previously "selectconnected_armature" */
287 static int armature_select_linked_invoke(bContext *C, wmOperator *op, const wmEvent *event)
288 {
289         bArmature *arm;
290         EditBone *bone, *curBone, *next;
291         const bool extend = RNA_boolean_get(op->ptr, "extend");
292
293         view3d_operator_needs_opengl(C);
294
295         Base *base = NULL;
296         bone = get_nearest_bone(C, event->mval, !extend, &base);
297
298         if (!bone)
299                 return OPERATOR_CANCELLED;
300
301         arm = base->object->data;
302
303         /* Select parents */
304         for (curBone = bone; curBone; curBone = next) {
305                 if ((curBone->flag & BONE_UNSELECTABLE) == 0) {
306                         if (extend) {
307                                 curBone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
308                         }
309                         else {
310                                 curBone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
311                         }
312                 }
313
314                 if (curBone->flag & BONE_CONNECTED)
315                         next = curBone->parent;
316                 else
317                         next = NULL;
318         }
319
320         /* Select children */
321         while (bone) {
322                 for (curBone = arm->edbo->first; curBone; curBone = next) {
323                         next = curBone->next;
324                         if ((curBone->parent == bone) && (curBone->flag & BONE_UNSELECTABLE) == 0) {
325                                 if (curBone->flag & BONE_CONNECTED) {
326                                         if (extend)
327                                                 curBone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
328                                         else
329                                                 curBone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
330                                         bone = curBone;
331                                         break;
332                                 }
333                                 else {
334                                         bone = NULL;
335                                         break;
336                                 }
337                         }
338                 }
339                 if (!curBone)
340                         bone = NULL;
341         }
342
343         ED_armature_edit_sync_selection(arm->edbo);
344
345         WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, base->object);
346
347         return OPERATOR_FINISHED;
348 }
349
350 static int armature_select_linked_poll(bContext *C)
351 {
352         return (ED_operator_view3d_active(C) && ED_operator_editarmature(C));
353 }
354
355 void ARMATURE_OT_select_linked(wmOperatorType *ot)
356 {
357         /* identifiers */
358         ot->name = "Select Connected";
359         ot->idname = "ARMATURE_OT_select_linked";
360         ot->description = "Select bones related to selected ones by parent/child relationships";
361
362         /* api callbacks */
363         /* leave 'exec' unset */
364         ot->invoke = armature_select_linked_invoke;
365         ot->poll = armature_select_linked_poll;
366
367         /* flags */
368         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
369
370         /* properties */
371         RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend selection instead of deselecting everything first");
372 }
373
374 /* utility function for get_nearest_editbonepoint */
375 static int selectbuffer_ret_hits_12(unsigned int *UNUSED(buffer), const int hits12)
376 {
377         return hits12;
378 }
379
380 static int selectbuffer_ret_hits_5(unsigned int *buffer, const int hits12, const int hits5)
381 {
382         const int offs = 4 * hits12;
383         memcpy(buffer, buffer + offs, 4 * hits5 * sizeof(unsigned int));
384         return hits5;
385 }
386
387 /* does bones and points */
388 /* note that BONE ROOT only gets drawn for root bones (or without IK) */
389 static EditBone *get_nearest_editbonepoint(
390         ViewContext *vc,
391         bool findunsel, bool use_cycle,
392         Base **r_base, int *r_selmask)
393 {
394         uint buffer[MAXPICKBUF];
395         struct {
396                 uint hitresult;
397                 Base *base;
398                 EditBone *ebone;
399         } best = {
400                 .hitresult = BONESEL_NOSEL,
401                 .base = NULL,
402                 .ebone = NULL,
403         };
404
405         /* find the bone after the current active bone, so as to bump up its chances in selection.
406          * this way overlapping bones will cycle selection state as with objects. */
407         EditBone *ebone_next_act = ((bArmature *)vc->obedit->data)->act_edbone;
408         {
409                 bArmature *arm = (bArmature *)vc->obedit->data;
410                 if (ebone_next_act &&
411                     EBONE_VISIBLE(arm, ebone_next_act) &&
412                     ebone_next_act->flag & (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL))
413                 {
414                         ebone_next_act = ebone_next_act->next ? ebone_next_act->next : arm->edbo->first;
415                 }
416                 else {
417                         ebone_next_act = NULL;
418                 }
419         }
420
421         bool do_nearest = false;
422
423         /* define if we use solid nearest select or not */
424         if (use_cycle) {
425                 static int last_mval[2] = {-100, -100};
426
427                 if (vc->v3d->drawtype > OB_WIRE) {
428                         do_nearest = true;
429                         if (len_manhattan_v2v2_int(vc->mval, last_mval) < 3) {
430                                 do_nearest = false;
431                         }
432                 }
433                 copy_v2_v2_int(last_mval, vc->mval);
434         }
435         else {
436                 if (vc->v3d->drawtype > OB_WIRE) {
437                         do_nearest = true;
438                 }
439         }
440
441         /* matching logic from 'mixed_bones_object_selectbuffer' */
442         int hits = 0;
443
444         /* we _must_ end cache before return, use 'goto cache_end' */
445         view3d_opengl_select_cache_begin();
446
447         {
448                 const int select_mode = (do_nearest ? VIEW3D_SELECT_PICK_NEAREST : VIEW3D_SELECT_PICK_ALL);
449                 rcti rect;
450                 BLI_rcti_init_pt_radius(&rect, vc->mval, 12);
451                 const int hits12 = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect, select_mode);
452                 if (hits12 == 1) {
453                         hits = selectbuffer_ret_hits_12(buffer, hits12);
454                         goto cache_end;
455                 }
456                 else if (hits12 > 0) {
457                         int offs;
458
459                         offs = 4 * hits12;
460                         BLI_rcti_init_pt_radius(&rect, vc->mval, 5);
461                         const int hits5 = view3d_opengl_select(vc, buffer + offs, MAXPICKBUF - offs, &rect, select_mode);
462
463                         if (hits5 == 1) {
464                                 hits = selectbuffer_ret_hits_5(buffer, hits12, hits5);
465                                 goto cache_end;
466                         }
467
468                         if      (hits5 > 0) { hits = selectbuffer_ret_hits_5(buffer,  hits12, hits5); goto cache_end; }
469                         else                { hits = selectbuffer_ret_hits_12(buffer, hits12); goto cache_end; }
470                 }
471         }
472
473 cache_end:
474         view3d_opengl_select_cache_end();
475
476         uint bases_len;
477         Base **bases = BKE_view_layer_array_from_bases_in_edit_mode_unique_data(vc->view_layer, &bases_len);
478
479         /* See if there are any selected bones in this group */
480         if (hits > 0) {
481                 if (hits == 1) {
482                         if (!(buffer[3] & BONESEL_NOSEL)) {
483                                 best.hitresult = buffer[3];
484                                 best.base = ED_armature_base_and_ebone_from_select_buffer(
485                                         bases, bases_len, best.hitresult, &best.ebone);
486                         }
487                 }
488                 else {
489                         int dep_min = 5;
490                         for (int i = 0; i < hits; i++) {
491                                 const uint hitresult = buffer[3 + (i * 4)];
492                                 if (!(hitresult & BONESEL_NOSEL)) {
493                                         Base *base = NULL;
494                                         EditBone *ebone;
495                                         base = ED_armature_base_and_ebone_from_select_buffer(bases, bases_len, hitresult, &ebone);
496                                         /* If this fails, selection code is setting the selection ID's incorrectly. */
497                                         BLI_assert(base && ebone);
498
499                                         int dep;
500                                         /* clicks on bone points get advantage */
501                                         if (hitresult & (BONESEL_ROOT | BONESEL_TIP)) {
502                                                 /* but also the unselected one */
503                                                 if (findunsel) {
504                                                         if ( (hitresult & BONESEL_ROOT) && (ebone->flag & BONE_ROOTSEL) == 0)
505                                                                 dep = 1;
506                                                         else if ( (hitresult & BONESEL_TIP) && (ebone->flag & BONE_TIPSEL) == 0)
507                                                                 dep = 1;
508                                                         else
509                                                                 dep = 2;
510                                                 }
511                                                 else {
512                                                         dep = 1;
513                                                 }
514                                         }
515                                         else {
516                                                 /* bone found */
517                                                 if (findunsel) {
518                                                         if ((ebone->flag & BONE_SELECTED) == 0)
519                                                                 dep = 3;
520                                                         else
521                                                                 dep = 4;
522                                                 }
523                                                 else {
524                                                         dep = 3;
525                                                 }
526                                         }
527
528                                         if (ebone == ebone_next_act) {
529                                                 dep -= 1;
530                                         }
531
532                                         if (dep < dep_min) {
533                                                 dep_min = dep;
534                                                 best.hitresult = hitresult;
535                                                 best.base = base;
536                                                 best.ebone = ebone;
537                                         }
538                                 }
539                         }
540                 }
541
542                 if (!(best.hitresult & BONESEL_NOSEL)) {
543                         *r_base = best.base;
544
545                         *r_selmask = 0;
546                         if (best.hitresult & BONESEL_ROOT) {
547                                 *r_selmask |= BONE_ROOTSEL;
548                         }
549                         if (best.hitresult & BONESEL_TIP) {
550                                 *r_selmask |= BONE_TIPSEL;
551                         }
552                         if (best.hitresult & BONESEL_BONE) {
553                                 *r_selmask |= BONE_SELECTED;
554                         }
555                         MEM_freeN(bases);
556                         return best.ebone;
557                 }
558         }
559         *r_selmask = 0;
560         *r_base = NULL;
561         MEM_freeN(bases);
562         return NULL;
563 }
564
565 void ED_armature_edit_deselect_all(Object *obedit)
566 {
567         bArmature *arm = obedit->data;
568         EditBone *ebone;
569
570         for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
571                 ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
572         }
573 }
574
575 void ED_armature_edit_deselect_all_visible(Object *obedit)
576 {
577         bArmature *arm = obedit->data;
578         EditBone    *ebone;
579
580         for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
581                 /* first and foremost, bone must be visible and selected */
582                 if (EBONE_VISIBLE(arm, ebone)) {
583                         ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
584                 }
585         }
586
587         ED_armature_edit_sync_selection(arm->edbo);
588 }
589
590
591 void ED_armature_edit_deselect_all_multi(struct Object **objects, uint objects_len)
592 {
593         for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
594                 Object *obedit = objects[ob_index];
595                 ED_armature_edit_deselect_all(obedit);
596         }
597 }
598
599 void ED_armature_edit_deselect_all_visible_multi(struct Object **objects, uint objects_len)
600 {
601         for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
602                 Object *obedit = objects[ob_index];
603                 ED_armature_edit_deselect_all_visible(obedit);
604         }
605 }
606
607 /* accounts for connected parents */
608 static int ebone_select_flag(EditBone *ebone)
609 {
610         if (ebone->parent && (ebone->flag & BONE_CONNECTED)) {
611                 return ((ebone->parent->flag & BONE_TIPSEL) ? BONE_ROOTSEL : 0) | (ebone->flag & (BONE_SELECTED | BONE_TIPSEL));
612         }
613         else {
614                 return ebone->flag & (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL);
615         }
616 }
617
618 /* context: editmode armature in view3d */
619 bool ED_armature_edit_select_pick(bContext *C, const int mval[2], bool extend, bool deselect, bool toggle)
620 {
621         ViewContext vc;
622         EditBone *nearBone = NULL;
623         int selmask;
624         Base *basact = NULL;
625
626         ED_view3d_viewcontext_init(C, &vc);
627         vc.mval[0] = mval[0];
628         vc.mval[1] = mval[1];
629
630         nearBone = get_nearest_editbonepoint(&vc, true, true, &basact, &selmask);
631         if (nearBone) {
632                 ED_view3d_viewcontext_init_object(&vc, basact->object);
633                 bArmature *arm = vc.obedit->data;
634
635                 if (!extend && !deselect && !toggle) {
636                         uint objects_len = 0;
637                         Object **objects = BKE_view_layer_array_from_objects_in_edit_mode_unique_data(vc.view_layer, &objects_len);
638                         ED_armature_edit_deselect_all_multi(objects, objects_len);
639                         MEM_freeN(objects);
640                 }
641
642                 /* by definition the non-root connected bones have no root point drawn,
643                  * so a root selection needs to be delivered to the parent tip */
644
645                 if (selmask & BONE_SELECTED) {
646                         if (nearBone->parent && (nearBone->flag & BONE_CONNECTED)) {
647                                 /* click in a chain */
648                                 if (extend) {
649                                         /* select this bone */
650                                         nearBone->flag |= BONE_TIPSEL;
651                                         nearBone->parent->flag |= BONE_TIPSEL;
652                                 }
653                                 else if (deselect) {
654                                         /* deselect this bone */
655                                         nearBone->flag &= ~(BONE_TIPSEL | BONE_SELECTED);
656                                         /* only deselect parent tip if it is not selected */
657                                         if (!(nearBone->parent->flag & BONE_SELECTED))
658                                                 nearBone->parent->flag &= ~BONE_TIPSEL;
659                                 }
660                                 else if (toggle) {
661                                         /* hold shift inverts this bone's selection */
662                                         if (nearBone->flag & BONE_SELECTED) {
663                                                 /* deselect this bone */
664                                                 nearBone->flag &= ~(BONE_TIPSEL | BONE_SELECTED);
665                                                 /* only deselect parent tip if it is not selected */
666                                                 if (!(nearBone->parent->flag & BONE_SELECTED))
667                                                         nearBone->parent->flag &= ~BONE_TIPSEL;
668                                         }
669                                         else {
670                                                 /* select this bone */
671                                                 nearBone->flag |= BONE_TIPSEL;
672                                                 nearBone->parent->flag |= BONE_TIPSEL;
673                                         }
674                                 }
675                                 else {
676                                         /* select this bone */
677                                         nearBone->flag |= BONE_TIPSEL;
678                                         nearBone->parent->flag |= BONE_TIPSEL;
679                                 }
680                         }
681                         else {
682                                 if (extend) {
683                                         nearBone->flag |= (BONE_TIPSEL | BONE_ROOTSEL);
684                                 }
685                                 else if (deselect) {
686                                         nearBone->flag &= ~(BONE_TIPSEL | BONE_ROOTSEL);
687                                 }
688                                 else if (toggle) {
689                                         /* hold shift inverts this bone's selection */
690                                         if (nearBone->flag & BONE_SELECTED)
691                                                 nearBone->flag &= ~(BONE_TIPSEL | BONE_ROOTSEL);
692                                         else
693                                                 nearBone->flag |= (BONE_TIPSEL | BONE_ROOTSEL);
694                                 }
695                                 else
696                                         nearBone->flag |= (BONE_TIPSEL | BONE_ROOTSEL);
697                         }
698                 }
699                 else {
700                         if (extend)
701                                 nearBone->flag |= selmask;
702                         else if (deselect)
703                                 nearBone->flag &= ~selmask;
704                         else if (toggle && (nearBone->flag & selmask))
705                                 nearBone->flag &= ~selmask;
706                         else
707                                 nearBone->flag |= selmask;
708                 }
709
710                 ED_armature_edit_sync_selection(arm->edbo);
711
712                 if (nearBone) {
713                         /* then now check for active status */
714                         if (ebone_select_flag(nearBone)) {
715                                 arm->act_edbone = nearBone;
716                         }
717
718                         if (vc.view_layer->basact != basact) {
719                                 vc.view_layer->basact = basact;
720                                 WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, vc.scene);
721                         }
722                 }
723
724                 WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, basact->object);
725                 return true;
726         }
727
728         return false;
729 }
730
731
732 /* ****************  Selections  ******************/
733
734 static int armature_de_select_all_exec(bContext *C, wmOperator *op)
735 {
736         int action = RNA_enum_get(op->ptr, "action");
737
738         if (action == SEL_TOGGLE) {
739                 /* Determine if there are any selected bones
740                  * And therefore whether we are selecting or deselecting */
741                 action = SEL_SELECT;
742                 CTX_DATA_BEGIN(C, EditBone *, ebone, visible_bones)
743                 {
744                         if (ebone->flag & (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL)) {
745                                 action = SEL_DESELECT;
746                                 break;
747                         }
748                 }
749                 CTX_DATA_END;
750         }
751
752         /*      Set the flags */
753         CTX_DATA_BEGIN(C, EditBone *, ebone, visible_bones)
754         {
755                 /* ignore bone if selection can't change */
756                 switch (action) {
757                         case SEL_SELECT:
758                                 if ((ebone->flag & BONE_UNSELECTABLE) == 0) {
759                                         ebone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
760                                         if (ebone->parent) {
761                                                 ebone->parent->flag |= (BONE_TIPSEL);
762                                         }
763                                 }
764                                 break;
765                         case SEL_DESELECT:
766                                 ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
767                                 break;
768                         case SEL_INVERT:
769                                 if (ebone->flag & BONE_SELECTED) {
770                                         ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
771                                 }
772                                 else {
773                                         if ((ebone->flag & BONE_UNSELECTABLE) == 0) {
774                                                 ebone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
775                                                 if (ebone->parent) {
776                                                         ebone->parent->flag |= (BONE_TIPSEL);
777                                                 }
778                                         }
779                                 }
780                                 break;
781                 }
782         }
783         CTX_DATA_END;
784
785         WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, NULL);
786
787         return OPERATOR_FINISHED;
788 }
789
790 void ARMATURE_OT_select_all(wmOperatorType *ot)
791 {
792         /* identifiers */
793         ot->name = "(De)select All";
794         ot->idname = "ARMATURE_OT_select_all";
795         ot->description = "Toggle selection status of all bones";
796
797         /* api callbacks */
798         ot->exec = armature_de_select_all_exec;
799         ot->poll = ED_operator_editarmature;
800
801         /* flags */
802         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
803
804         WM_operator_properties_select_all(ot);
805 }
806
807 /**************** Select more/less **************/
808
809 static void armature_select_more(bArmature *arm, EditBone *ebone)
810 {
811         if ((EBONE_PREV_FLAG_GET(ebone) & (BONE_ROOTSEL | BONE_TIPSEL)) != 0) {
812                 if (EBONE_SELECTABLE(arm, ebone)) {
813                         ED_armature_ebone_select_set(ebone, true);
814                 }
815         }
816
817         if (ebone->parent && (ebone->flag & BONE_CONNECTED)) {
818                 /* to parent */
819                 if ((EBONE_PREV_FLAG_GET(ebone) & BONE_ROOTSEL) != 0) {
820                         if (EBONE_SELECTABLE(arm, ebone->parent)) {
821                                 ED_armature_ebone_selectflag_enable(ebone->parent, (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL));
822                         }
823                 }
824
825                 /* from parent (difference from select less) */
826                 if ((EBONE_PREV_FLAG_GET(ebone->parent) & BONE_TIPSEL) != 0) {
827                         if (EBONE_SELECTABLE(arm, ebone)) {
828                                 ED_armature_ebone_selectflag_enable(ebone, (BONE_SELECTED | BONE_ROOTSEL));
829                         }
830                 }
831         }
832 }
833
834 static void armature_select_less(bArmature *UNUSED(arm), EditBone *ebone)
835 {
836         if ((EBONE_PREV_FLAG_GET(ebone) & (BONE_ROOTSEL | BONE_TIPSEL)) != (BONE_ROOTSEL | BONE_TIPSEL)) {
837                 ED_armature_ebone_select_set(ebone, false);
838         }
839
840         if (ebone->parent && (ebone->flag & BONE_CONNECTED)) {
841                 /* to parent */
842                 if ((EBONE_PREV_FLAG_GET(ebone) & BONE_SELECTED) == 0) {
843                         ED_armature_ebone_selectflag_disable(ebone->parent, (BONE_SELECTED | BONE_TIPSEL));
844                 }
845
846                 /* from parent (difference from select more) */
847                 if ((EBONE_PREV_FLAG_GET(ebone->parent) & BONE_SELECTED) == 0) {
848                         ED_armature_ebone_selectflag_disable(ebone, (BONE_SELECTED | BONE_ROOTSEL));
849                 }
850         }
851 }
852
853 static void armature_select_more_less(Object *ob, bool more)
854 {
855         bArmature *arm = (bArmature *)ob->data;
856         EditBone *ebone;
857
858         /* XXX, eventually we shouldn't need this - campbell */
859         ED_armature_edit_sync_selection(arm->edbo);
860
861         /* count bones & store selection state */
862         for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
863                 EBONE_PREV_FLAG_SET(ebone, ED_armature_ebone_selectflag_get(ebone));
864         }
865
866         /* do selection */
867         for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
868                 if (EBONE_VISIBLE(arm, ebone)) {
869                         if (more) {
870                                 armature_select_more(arm, ebone);
871                         }
872                         else {
873                                 armature_select_less(arm, ebone);
874                         }
875                 }
876         }
877
878         for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
879                 if (EBONE_VISIBLE(arm, ebone)) {
880                         if (more == false) {
881                                 if (ebone->flag & BONE_SELECTED) {
882                                         ED_armature_ebone_select_set(ebone, true);
883                                 }
884                         }
885                 }
886                 ebone->temp.p = NULL;
887         }
888
889         ED_armature_edit_sync_selection(arm->edbo);
890 }
891
892 static int armature_de_select_more_exec(bContext *C, wmOperator *UNUSED(op))
893 {
894         Object *obedit = CTX_data_edit_object(C);
895         armature_select_more_less(obedit, true);
896         WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
897
898         return OPERATOR_FINISHED;
899 }
900
901 void ARMATURE_OT_select_more(wmOperatorType *ot)
902 {
903         /* identifiers */
904         ot->name = "Select More";
905         ot->idname = "ARMATURE_OT_select_more";
906         ot->description = "Select those bones connected to the initial selection";
907
908         /* api callbacks */
909         ot->exec = armature_de_select_more_exec;
910         ot->poll = ED_operator_editarmature;
911
912         /* flags */
913         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
914 }
915
916 static int armature_de_select_less_exec(bContext *C, wmOperator *UNUSED(op))
917 {
918         Object *obedit = CTX_data_edit_object(C);
919         armature_select_more_less(obedit, false);
920         WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
921
922         return OPERATOR_FINISHED;
923 }
924
925 void ARMATURE_OT_select_less(wmOperatorType *ot)
926 {
927         /* identifiers */
928         ot->name = "Select Less";
929         ot->idname = "ARMATURE_OT_select_less";
930         ot->description = "Deselect those bones at the boundary of each selection region";
931
932         /* api callbacks */
933         ot->exec = armature_de_select_less_exec;
934         ot->poll = ED_operator_editarmature;
935
936         /* flags */
937         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
938 }
939
940 enum {
941         SIMEDBONE_CHILDREN = 1,
942         SIMEDBONE_CHILDREN_IMMEDIATE,
943         SIMEDBONE_SIBLINGS,
944         SIMEDBONE_LENGTH,
945         SIMEDBONE_DIRECTION,
946         SIMEDBONE_PREFIX,
947         SIMEDBONE_SUFFIX,
948         SIMEDBONE_LAYER,
949         SIMEDBONE_GROUP,
950         SIMEDBONE_SHAPE,
951 };
952
953 static const EnumPropertyItem prop_similar_types[] = {
954         {SIMEDBONE_CHILDREN, "CHILDREN", 0, "Children", ""},
955         {SIMEDBONE_CHILDREN_IMMEDIATE, "CHILDREN_IMMEDIATE", 0, "Immediate children", ""},
956         {SIMEDBONE_SIBLINGS, "SIBLINGS", 0, "Siblings", ""},
957         {SIMEDBONE_LENGTH, "LENGTH", 0, "Length", ""},
958         {SIMEDBONE_DIRECTION, "DIRECTION", 0, "Direction (Y axis)", ""},
959         {SIMEDBONE_PREFIX, "PREFIX", 0, "Prefix", ""},
960         {SIMEDBONE_SUFFIX, "SUFFIX", 0, "Suffix", ""},
961         {SIMEDBONE_LAYER, "LAYER", 0, "Layer", ""},
962         {SIMEDBONE_GROUP, "GROUP", 0, "Group", ""},
963         {SIMEDBONE_SHAPE, "SHAPE", 0, "Shape", ""},
964         {0, NULL, 0, NULL, NULL}
965 };
966
967
968 static void select_similar_length(bArmature *arm, EditBone *ebone_act, const float thresh)
969 {
970         EditBone *ebone;
971
972         /* thresh is always relative to current length */
973         const float len_min = ebone_act->length / (1.0f + thresh);
974         const float len_max = ebone_act->length * (1.0f + thresh);
975
976         for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
977                 if (EBONE_SELECTABLE(arm, ebone)) {
978                         if ((ebone->length >= len_min) &&
979                             (ebone->length <= len_max))
980                         {
981                                 ED_armature_ebone_select_set(ebone, true);
982                         }
983                 }
984         }
985 }
986
987 static void select_similar_direction(bArmature *arm, EditBone *ebone_act, const float thresh)
988 {
989         EditBone *ebone;
990         float dir_act[3];
991         sub_v3_v3v3(dir_act, ebone_act->head, ebone_act->tail);
992
993         for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
994                 if (EBONE_SELECTABLE(arm, ebone)) {
995                         float dir[3];
996                         sub_v3_v3v3(dir, ebone->head, ebone->tail);
997
998                         if (angle_v3v3(dir_act, dir) / (float)M_PI < thresh) {
999                                 ED_armature_ebone_select_set(ebone, true);
1000                         }
1001                 }
1002         }
1003 }
1004
1005 static void select_similar_layer(bArmature *arm, EditBone *ebone_act)
1006 {
1007         EditBone *ebone;
1008
1009         for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
1010                 if (EBONE_SELECTABLE(arm, ebone)) {
1011                         if (ebone->layer & ebone_act->layer) {
1012                                 ED_armature_ebone_select_set(ebone, true);
1013                         }
1014                 }
1015         }
1016 }
1017
1018 static void select_similar_prefix(bArmature *arm, EditBone *ebone_act)
1019 {
1020         EditBone *ebone;
1021
1022         char body_tmp[MAXBONENAME];
1023         char prefix_act[MAXBONENAME];
1024
1025         BLI_string_split_prefix(ebone_act->name, prefix_act, body_tmp, sizeof(ebone_act->name));
1026
1027         if (prefix_act[0] == '\0')
1028                 return;
1029
1030         /* Find matches */
1031         for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
1032                 if (EBONE_SELECTABLE(arm, ebone)) {
1033                         char prefix_other[MAXBONENAME];
1034                         BLI_string_split_prefix(ebone->name, prefix_other, body_tmp, sizeof(ebone->name));
1035                         if (STREQ(prefix_act, prefix_other)) {
1036                                 ED_armature_ebone_select_set(ebone, true);
1037                         }
1038                 }
1039         }
1040 }
1041
1042 static void select_similar_suffix(bArmature *arm, EditBone *ebone_act)
1043 {
1044         EditBone *ebone;
1045
1046         char body_tmp[MAXBONENAME];
1047         char suffix_act[MAXBONENAME];
1048
1049         BLI_string_split_suffix(ebone_act->name, body_tmp, suffix_act, sizeof(ebone_act->name));
1050
1051         if (suffix_act[0] == '\0')
1052                 return;
1053
1054         /* Find matches */
1055         for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
1056                 if (EBONE_SELECTABLE(arm, ebone)) {
1057                         char suffix_other[MAXBONENAME];
1058                         BLI_string_split_suffix(ebone->name, body_tmp, suffix_other, sizeof(ebone->name));
1059                         if (STREQ(suffix_act, suffix_other)) {
1060                                 ED_armature_ebone_select_set(ebone, true);
1061                         }
1062                 }
1063         }
1064 }
1065
1066 /** Use for matching any pose channel data. */
1067 static void select_similar_data_pchan(
1068         bArmature *arm, Object *obj, EditBone *ebone_active,
1069         const size_t bytes_size, const int offset)
1070 {
1071         const bPoseChannel *pchan_active = BKE_pose_channel_find_name(obj->pose, ebone_active->name);
1072         const char *data_active = (const char *)POINTER_OFFSET(pchan_active, offset);
1073         for (EditBone *ebone = arm->edbo->first; ebone; ebone = ebone->next) {
1074                 if (EBONE_SELECTABLE(arm, ebone)) {
1075                         const bPoseChannel *pchan = BKE_pose_channel_find_name(obj->pose, ebone->name);
1076                         if (pchan) {
1077                                 const char *data_test = (const char *)POINTER_OFFSET(pchan, offset);
1078                                 if (memcmp(data_active, data_test, bytes_size) == 0) {
1079                                         ED_armature_ebone_select_set(ebone, true);
1080                                 }
1081                         }
1082                 }
1083         }
1084 }
1085
1086 static void is_ancestor(EditBone *bone, EditBone *ancestor)
1087 {
1088         if (bone->temp.ebone == ancestor || bone->temp.ebone == NULL)
1089                 return;
1090
1091         if (bone->temp.ebone->temp.ebone != NULL && bone->temp.ebone->temp.ebone != ancestor)
1092                 is_ancestor(bone->temp.ebone, ancestor);
1093
1094         bone->temp.ebone = bone->temp.ebone->temp.ebone;
1095 }
1096
1097 static void select_similar_children(bArmature *arm, EditBone *ebone_act)
1098 {
1099         EditBone *ebone_iter;
1100
1101         for (ebone_iter = arm->edbo->first; ebone_iter; ebone_iter = ebone_iter->next) {
1102                 ebone_iter->temp.ebone = ebone_iter->parent;
1103         }
1104
1105         for (ebone_iter = arm->edbo->first; ebone_iter; ebone_iter = ebone_iter->next) {
1106                 is_ancestor(ebone_iter, ebone_act);
1107
1108                 if (ebone_iter->temp.ebone == ebone_act && EBONE_SELECTABLE(arm, ebone_iter))
1109                         ED_armature_ebone_select_set(ebone_iter, true);
1110         }
1111 }
1112
1113 static void select_similar_children_immediate(bArmature *arm, EditBone *ebone_act)
1114 {
1115         EditBone *ebone_iter;
1116         for (ebone_iter = arm->edbo->first; ebone_iter; ebone_iter = ebone_iter->next) {
1117                 if (ebone_iter->parent == ebone_act && EBONE_SELECTABLE(arm, ebone_iter)) {
1118                         ED_armature_ebone_select_set(ebone_iter, true);
1119                 }
1120         }
1121 }
1122
1123 static void select_similar_siblings(bArmature *arm, EditBone *ebone_act)
1124 {
1125         EditBone *ebone_iter;
1126
1127         if (ebone_act->parent == NULL)
1128                 return;
1129
1130         for (ebone_iter = arm->edbo->first; ebone_iter; ebone_iter = ebone_iter->next) {
1131                 if (ebone_iter->parent == ebone_act->parent && EBONE_SELECTABLE(arm, ebone_iter)) {
1132                         ED_armature_ebone_select_set(ebone_iter, true);
1133                 }
1134         }
1135 }
1136
1137 static int armature_select_similar_exec(bContext *C, wmOperator *op)
1138 {
1139         Object *obedit = CTX_data_edit_object(C);
1140         bArmature *arm = obedit->data;
1141         EditBone *ebone_act = CTX_data_active_bone(C);
1142
1143         /* Get props */
1144         int type = RNA_enum_get(op->ptr, "type");
1145         float thresh = RNA_float_get(op->ptr, "threshold");
1146
1147         /* Check for active bone */
1148         if (ebone_act == NULL) {
1149                 BKE_report(op->reports, RPT_ERROR, "Operation requires an active bone");
1150                 return OPERATOR_CANCELLED;
1151         }
1152
1153 #define STRUCT_SIZE_AND_OFFSET(_struct, _member) \
1154         sizeof(((_struct *)NULL)->_member), offsetof(_struct, _member)
1155
1156         switch (type) {
1157                 case SIMEDBONE_CHILDREN:
1158                         select_similar_children(arm, ebone_act);
1159                         break;
1160                 case SIMEDBONE_CHILDREN_IMMEDIATE:
1161                         select_similar_children_immediate(arm, ebone_act);
1162                         break;
1163                 case SIMEDBONE_SIBLINGS:
1164                         select_similar_siblings(arm, ebone_act);
1165                         break;
1166                 case SIMEDBONE_LENGTH:
1167                         select_similar_length(arm, ebone_act, thresh);
1168                         break;
1169                 case SIMEDBONE_DIRECTION:
1170                         select_similar_direction(arm, ebone_act, thresh);
1171                         break;
1172                 case SIMEDBONE_PREFIX:
1173                         select_similar_prefix(arm, ebone_act);
1174                         break;
1175                 case SIMEDBONE_SUFFIX:
1176                         select_similar_suffix(arm, ebone_act);
1177                         break;
1178                 case SIMEDBONE_LAYER:
1179                         select_similar_layer(arm, ebone_act);
1180                         break;
1181                 case SIMEDBONE_GROUP:
1182                         select_similar_data_pchan(
1183                                 arm, obedit, ebone_act,
1184                                 STRUCT_SIZE_AND_OFFSET(bPoseChannel, agrp_index));
1185                         break;
1186                 case SIMEDBONE_SHAPE:
1187                         select_similar_data_pchan(
1188                                 arm, obedit, ebone_act,
1189                                 STRUCT_SIZE_AND_OFFSET(bPoseChannel, custom));
1190                         break;
1191         }
1192
1193 #undef STRUCT_SIZE_AND_OFFSET
1194
1195         WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
1196
1197         return OPERATOR_FINISHED;
1198 }
1199
1200 void ARMATURE_OT_select_similar(wmOperatorType *ot)
1201 {
1202         /* identifiers */
1203         ot->name = "Select Similar";
1204         ot->idname = "ARMATURE_OT_select_similar";
1205
1206         /* callback functions */
1207         ot->invoke = WM_menu_invoke;
1208         ot->exec = armature_select_similar_exec;
1209         ot->poll = ED_operator_editarmature;
1210         ot->description = "Select similar bones by property types";
1211
1212         /* flags */
1213         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1214
1215         /* properties */
1216         ot->prop = RNA_def_enum(ot->srna, "type", prop_similar_types, SIMEDBONE_LENGTH, "Type", "");
1217         RNA_def_float(ot->srna, "threshold", 0.1f, 0.0f, 1.0f, "Threshold", "", 0.0f, 1.0f);
1218 }
1219
1220 /* ********************* select hierarchy operator ************** */
1221
1222 static int armature_select_hierarchy_exec(bContext *C, wmOperator *op)
1223 {
1224         Object *obedit = CTX_data_edit_object(C);
1225         Object *ob;
1226         bArmature *arm;
1227         EditBone *ebone_active;
1228         int direction = RNA_enum_get(op->ptr, "direction");
1229         const bool add_to_sel = RNA_boolean_get(op->ptr, "extend");
1230         bool changed = false;
1231
1232         ob = obedit;
1233         arm = (bArmature *)ob->data;
1234
1235         ebone_active = arm->act_edbone;
1236         if (ebone_active == NULL) {
1237                 return OPERATOR_CANCELLED;
1238         }
1239
1240         if (direction == BONE_SELECT_PARENT) {
1241                 if (ebone_active->parent) {
1242                         EditBone *ebone_parent;
1243
1244                         ebone_parent = ebone_active->parent;
1245
1246                         if (EBONE_SELECTABLE(arm, ebone_parent)) {
1247                                 arm->act_edbone = ebone_parent;
1248
1249                                 if (!add_to_sel) {
1250                                         ED_armature_ebone_select_set(ebone_active, false);
1251                                 }
1252                                 ED_armature_ebone_select_set(ebone_parent, true);
1253
1254                                 changed = true;
1255                         }
1256                 }
1257
1258         }
1259         else {  /* BONE_SELECT_CHILD */
1260                 EditBone *ebone_iter, *ebone_child = NULL;
1261                 int pass;
1262
1263                 /* first pass, only connected bones (the logical direct child) */
1264                 for (pass = 0; pass < 2 && (ebone_child == NULL); pass++) {
1265                         for (ebone_iter = arm->edbo->first; ebone_iter; ebone_iter = ebone_iter->next) {
1266                                 /* possible we have multiple children, some invisible */
1267                                 if (EBONE_SELECTABLE(arm, ebone_iter)) {
1268                                         if (ebone_iter->parent == ebone_active) {
1269                                                 if ((pass == 1) || (ebone_iter->flag & BONE_CONNECTED)) {
1270                                                         ebone_child = ebone_iter;
1271                                                         break;
1272                                                 }
1273                                         }
1274                                 }
1275                         }
1276                 }
1277
1278                 if (ebone_child) {
1279                         arm->act_edbone = ebone_child;
1280
1281                         if (!add_to_sel) {
1282                                 ED_armature_ebone_select_set(ebone_active, false);
1283                         }
1284                         ED_armature_ebone_select_set(ebone_child, true);
1285
1286                         changed = true;
1287                 }
1288         }
1289
1290         if (changed == false) {
1291                 return OPERATOR_CANCELLED;
1292         }
1293
1294         ED_armature_edit_sync_selection(arm->edbo);
1295
1296         WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
1297
1298         return OPERATOR_FINISHED;
1299 }
1300
1301 void ARMATURE_OT_select_hierarchy(wmOperatorType *ot)
1302 {
1303         static const EnumPropertyItem direction_items[] = {
1304                 {BONE_SELECT_PARENT, "PARENT", 0, "Select Parent", ""},
1305                 {BONE_SELECT_CHILD, "CHILD", 0, "Select Child", ""},
1306                 {0, NULL, 0, NULL, NULL}
1307         };
1308
1309         /* identifiers */
1310         ot->name = "Select Hierarchy";
1311         ot->idname = "ARMATURE_OT_select_hierarchy";
1312         ot->description = "Select immediate parent/children of selected bones";
1313
1314         /* api callbacks */
1315         ot->exec = armature_select_hierarchy_exec;
1316         ot->poll = ED_operator_editarmature;
1317
1318         /* flags */
1319         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1320
1321         /* props */
1322         RNA_def_enum(ot->srna, "direction", direction_items,
1323                      BONE_SELECT_PARENT, "Direction", "");
1324         RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
1325 }
1326
1327 /****************** Mirror Select ****************/
1328
1329 /**
1330  * \note clone of #pose_select_mirror_exec keep in sync
1331  */
1332 static int armature_select_mirror_exec(bContext *C, wmOperator *op)
1333 {
1334         Object *obedit = CTX_data_edit_object(C);
1335         bArmature *arm = obedit->data;
1336         EditBone *ebone, *ebone_mirror_act = NULL;
1337         const bool active_only = RNA_boolean_get(op->ptr, "only_active");
1338         const bool extend = RNA_boolean_get(op->ptr, "extend");
1339
1340         for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
1341                 const int flag = ED_armature_ebone_selectflag_get(ebone);
1342                 EBONE_PREV_FLAG_SET(ebone, flag);
1343         }
1344
1345         for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
1346                 if (EBONE_SELECTABLE(arm, ebone)) {
1347                         EditBone *ebone_mirror;
1348                         int flag_new = extend ? EBONE_PREV_FLAG_GET(ebone) : 0;
1349
1350                         if ((ebone_mirror = ED_armature_ebone_get_mirrored(arm->edbo, ebone)) &&
1351                             (EBONE_VISIBLE(arm, ebone_mirror)))
1352                         {
1353                                 const int flag_mirror = EBONE_PREV_FLAG_GET(ebone_mirror);
1354                                 flag_new |= flag_mirror;
1355
1356                                 if (ebone == arm->act_edbone) {
1357                                         ebone_mirror_act = ebone_mirror;
1358                                 }
1359
1360                                 /* skip all but the active or its mirror */
1361                                 if (active_only && !ELEM(arm->act_edbone, ebone, ebone_mirror)) {
1362                                         continue;
1363                                 }
1364                         }
1365
1366                         ED_armature_ebone_selectflag_set(ebone, flag_new);
1367                 }
1368         }
1369
1370         if (ebone_mirror_act) {
1371                 arm->act_edbone = ebone_mirror_act;
1372         }
1373
1374         ED_armature_edit_sync_selection(arm->edbo);
1375
1376         WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
1377
1378         return OPERATOR_FINISHED;
1379 }
1380
1381 void ARMATURE_OT_select_mirror(wmOperatorType *ot)
1382 {
1383         /* identifiers */
1384         ot->name = "Flip Active/Selected Bone";
1385         ot->idname = "ARMATURE_OT_select_mirror";
1386         ot->description = "Mirror the bone selection";
1387
1388         /* api callbacks */
1389         ot->exec = armature_select_mirror_exec;
1390         ot->poll = ED_operator_editarmature;
1391
1392         /* flags */
1393         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1394
1395         /* properties */
1396         RNA_def_boolean(ot->srna, "only_active", false, "Active Only", "Only operate on the active bone");
1397         RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
1398 }
1399
1400
1401 /****************** Select Path ****************/
1402
1403 static bool armature_shortest_path_select(bArmature *arm, EditBone *ebone_parent, EditBone *ebone_child,
1404                                           bool use_parent, bool is_test)
1405 {
1406         do {
1407
1408                 if (!use_parent && (ebone_child == ebone_parent))
1409                         break;
1410
1411                 if (is_test) {
1412                         if (!EBONE_SELECTABLE(arm, ebone_child)) {
1413                                 return false;
1414                         }
1415                 }
1416                 else {
1417                         ED_armature_ebone_selectflag_set(ebone_child, (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL));
1418                 }
1419
1420                 if (ebone_child == ebone_parent)
1421                         break;
1422
1423                 ebone_child = ebone_child->parent;
1424         } while (true);
1425
1426         return true;
1427 }
1428
1429 static int armature_shortest_path_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
1430 {
1431         Object *obedit = CTX_data_edit_object(C);
1432         bArmature *arm = obedit->data;
1433         EditBone *ebone_src, *ebone_dst;
1434         EditBone *ebone_isect_parent = NULL;
1435         EditBone *ebone_isect_child[2];
1436         bool changed;
1437         Base *base_dst = NULL;
1438
1439         view3d_operator_needs_opengl(C);
1440
1441         ebone_src = arm->act_edbone;
1442         ebone_dst = get_nearest_bone(C, event->mval, false, &base_dst);
1443
1444         /* fallback to object selection */
1445         if (ELEM(NULL, ebone_src, ebone_dst) || (ebone_src == ebone_dst)) {
1446                 return OPERATOR_PASS_THROUGH;
1447         }
1448
1449         if (base_dst && base_dst->object != obedit) {
1450                 /* Disconnected, ignore. */
1451                 return OPERATOR_CANCELLED;
1452         }
1453
1454         ebone_isect_child[0] = ebone_src;
1455         ebone_isect_child[1] = ebone_dst;
1456
1457
1458         /* ensure 'ebone_src' is the parent of 'ebone_dst', or set 'ebone_isect_parent' */
1459         if (ED_armature_ebone_is_child_recursive(ebone_src, ebone_dst)) {
1460                 /* pass */
1461         }
1462         else if (ED_armature_ebone_is_child_recursive(ebone_dst, ebone_src)) {
1463                 SWAP(EditBone *, ebone_src, ebone_dst);
1464         }
1465         else if ((ebone_isect_parent = ED_armature_ebone_find_shared_parent(ebone_isect_child, 2))) {
1466                 /* pass */
1467         }
1468         else {
1469                 /* disconnected bones */
1470                 return OPERATOR_CANCELLED;
1471         }
1472
1473
1474         if (ebone_isect_parent) {
1475                 if (armature_shortest_path_select(arm, ebone_isect_parent, ebone_src, false, true) &&
1476                     armature_shortest_path_select(arm, ebone_isect_parent, ebone_dst, false, true))
1477                 {
1478                         armature_shortest_path_select(arm, ebone_isect_parent, ebone_src, false, false);
1479                         armature_shortest_path_select(arm, ebone_isect_parent, ebone_dst, false, false);
1480                         changed = true;
1481                 }
1482                 else {
1483                         /* unselectable */
1484                         changed = false;
1485                 }
1486         }
1487         else {
1488                 if (armature_shortest_path_select(arm, ebone_src, ebone_dst, true, true)) {
1489                         armature_shortest_path_select(arm, ebone_src, ebone_dst, true, false);
1490                         changed = true;
1491                 }
1492                 else {
1493                         /* unselectable */
1494                         changed = false;
1495                 }
1496         }
1497
1498         if (changed) {
1499                 arm->act_edbone = ebone_dst;
1500                 ED_armature_edit_sync_selection(arm->edbo);
1501                 WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
1502
1503                 return OPERATOR_FINISHED;
1504         }
1505         else {
1506                 BKE_report(op->reports, RPT_WARNING, "Unselectable bone in chain");
1507                 return OPERATOR_CANCELLED;
1508         }
1509 }
1510
1511 void ARMATURE_OT_shortest_path_pick(wmOperatorType *ot)
1512 {
1513         /* identifiers */
1514         ot->name = "Pick Shortest Path";
1515         ot->idname = "ARMATURE_OT_shortest_path_pick";
1516         ot->description = "Select shortest path between two bones";
1517
1518         /* api callbacks */
1519         ot->invoke = armature_shortest_path_pick_invoke;
1520         ot->poll = ED_operator_editarmature;
1521
1522         /* flags */
1523         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1524 }