c6ef76c570c1bb3755113c72878f50c4042eaf92
[blender-staging.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 "DNA_armature_types.h"
33 #include "DNA_object_types.h"
34 #include "DNA_scene_types.h"
35
36 #include "BLI_blenlib.h"
37 #include "BLI_math.h"
38
39 #include "BKE_context.h"
40 #include "BKE_deform.h"
41 #include "BKE_report.h"
42
43 #include "BIF_gl.h"
44
45 #include "RNA_access.h"
46 #include "RNA_define.h"
47
48 #include "WM_api.h"
49 #include "WM_types.h"
50
51 #include "ED_armature.h"
52 #include "ED_screen.h"
53 #include "ED_view3d.h"
54
55 #include "armature_intern.h"
56
57 /* utility macros fro storing a temp int in the bone (selection flag) */
58 #define EBONE_PREV_FLAG_GET(ebone) ((void)0, (GET_INT_FROM_POINTER((ebone)->temp)))
59 #define EBONE_PREV_FLAG_SET(ebone, val) ((ebone)->temp = SET_INT_IN_POINTER(val))
60
61 /* **************** PoseMode & EditMode Selection Buffer Queries *************************** */
62
63 /* only for opengl selection indices */
64 Bone *get_indexed_bone(Object *ob, int index)
65 {
66         bPoseChannel *pchan;
67         if (ob->pose == NULL) return NULL;
68         index >>= 16;     // bone selection codes use left 2 bytes
69         
70         pchan = BLI_findlink(&ob->pose->chanbase, index);
71         return pchan ? pchan->bone : NULL;
72 }
73
74 /* See if there are any selected bones in this buffer */
75 /* only bones from base are checked on */
76 void *get_bone_from_selectbuffer(Scene *scene, Base *base, unsigned int *buffer, short hits, short findunsel, bool do_nearest)
77 {
78         Object *obedit = scene->obedit; // XXX get from context
79         Bone *bone;
80         EditBone *ebone;
81         void *firstunSel = NULL, *firstSel = NULL, *data;
82         unsigned int hitresult;
83         short i;
84         bool takeNext = false;
85         int minsel = 0xffffffff, minunsel = 0xffffffff;
86         
87         for (i = 0; i < hits; i++) {
88                 hitresult = buffer[3 + (i * 4)];
89                 
90                 if (!(hitresult & BONESEL_NOSEL)) {
91                         if (hitresult & BONESEL_ANY) {  /* to avoid including objects in selection */
92                                 bool sel;
93                                 
94                                 hitresult &= ~(BONESEL_ANY);
95                                 /* Determine what the current bone is */
96                                 if (obedit == NULL || base->object != obedit) {
97                                         /* no singular posemode, so check for correct object */
98                                         if (base->selcol == (hitresult & 0xFFFF)) {
99                                                 bone = get_indexed_bone(base->object, hitresult);
100                                                 
101                                                 if (findunsel)
102                                                         sel = (bone->flag & BONE_SELECTED);
103                                                 else
104                                                         sel = !(bone->flag & BONE_SELECTED);
105                                                 
106                                                 data = bone;                                            
107                                         }
108                                         else {
109                                                 data = NULL;
110                                                 sel = 0;
111                                         }
112                                 }
113                                 else {
114                                         bArmature *arm = obedit->data;
115                                         
116                                         ebone = BLI_findlink(arm->edbo, hitresult);
117                                         if (findunsel)
118                                                 sel = (ebone->flag & BONE_SELECTED);
119                                         else
120                                                 sel = !(ebone->flag & BONE_SELECTED);
121                                         
122                                         data = ebone;
123                                 }
124                                 
125                                 if (data) {
126                                         if (sel) {
127                                                 if (do_nearest) {
128                                                         if (minsel > buffer[4 * i + 1]) {
129                                                                 firstSel = data;
130                                                                 minsel = buffer[4 * i + 1];
131                                                         }
132                                                 }
133                                                 else {
134                                                         if (!firstSel) firstSel = data;
135                                                         takeNext = 1;
136                                                 }
137                                         }
138                                         else {
139                                                 if (do_nearest) {
140                                                         if (minunsel > buffer[4 * i + 1]) {
141                                                                 firstunSel = data;
142                                                                 minunsel = buffer[4 * i + 1];
143                                                         }
144                                                 }
145                                                 else {
146                                                         if (!firstunSel) firstunSel = data;
147                                                         if (takeNext) return data;
148                                                 }
149                                         }
150                                 }
151                         }
152                 }
153         }
154         
155         if (firstunSel)
156                 return firstunSel;
157         else 
158                 return firstSel;
159 }
160
161 /* used by posemode as well editmode */
162 /* only checks scene->basact! */
163 /* x and y are mouse coords (area space) */
164 void *get_nearest_bone(bContext *C, short findunsel, int x, int y)
165 {
166         ViewContext vc;
167         rcti rect;
168         unsigned int buffer[MAXPICKBUF];
169         short hits;
170         
171         view3d_set_viewcontext(C, &vc);
172         
173         // rect.xmin = ... mouseco!
174         rect.xmin = rect.xmax = x;
175         rect.ymin = rect.ymax = y;
176         
177         glInitNames();
178         hits = view3d_opengl_select(&vc, buffer, MAXPICKBUF, &rect, true);
179
180         if (hits > 0)
181                 return get_bone_from_selectbuffer(vc.scene, vc.scene->basact, buffer, hits, findunsel, true);
182         
183         return NULL;
184 }
185
186 /* **************** EditMode stuff ********************** */
187
188 /* called in space.c */
189 /* previously "selectconnected_armature" */
190 static int armature_select_linked_invoke(bContext *C, wmOperator *op, const wmEvent *event)
191 {
192         bArmature *arm;
193         EditBone *bone, *curBone, *next;
194         const bool extend = RNA_boolean_get(op->ptr, "extend");
195         Object *obedit = CTX_data_edit_object(C);
196         arm = obedit->data;
197
198         view3d_operator_needs_opengl(C);
199
200         if (extend)
201                 bone = get_nearest_bone(C, 0, event->mval[0], event->mval[1]);
202         else
203                 bone = get_nearest_bone(C, 1, event->mval[0], event->mval[1]);
204
205         if (!bone)
206                 return OPERATOR_CANCELLED;
207
208         /* Select parents */
209         for (curBone = bone; curBone; curBone = next) {
210                 if ((curBone->flag & BONE_UNSELECTABLE) == 0) {
211                         if (extend) {
212                                 curBone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
213                         }
214                         else {
215                                 curBone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
216                         }
217                 }
218                 
219                 if (curBone->flag & BONE_CONNECTED)
220                         next = curBone->parent;
221                 else
222                         next = NULL;
223         }
224
225         /* Select children */
226         while (bone) {
227                 for (curBone = arm->edbo->first; curBone; curBone = next) {
228                         next = curBone->next;
229                         if ((curBone->parent == bone) && (curBone->flag & BONE_UNSELECTABLE) == 0) {
230                                 if (curBone->flag & BONE_CONNECTED) {
231                                         if (extend)
232                                                 curBone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
233                                         else
234                                                 curBone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
235                                         bone = curBone;
236                                         break;
237                                 }
238                                 else {
239                                         bone = NULL;
240                                         break;
241                                 }
242                         }
243                 }
244                 if (!curBone)
245                         bone = NULL;
246         }
247         
248         ED_armature_sync_selection(arm->edbo);
249         
250         WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
251         
252         return OPERATOR_FINISHED;
253 }
254
255 static int armature_select_linked_poll(bContext *C)
256 {
257         return (ED_operator_view3d_active(C) && ED_operator_editarmature(C) );
258 }
259
260 void ARMATURE_OT_select_linked(wmOperatorType *ot)
261 {
262         /* identifiers */
263         ot->name = "Select Connected";
264         ot->idname = "ARMATURE_OT_select_linked";
265         ot->description = "Select bones related to selected ones by parent/child relationships";
266         
267         /* api callbacks */
268         /* leave 'exec' unset */
269         ot->invoke = armature_select_linked_invoke;
270         ot->poll = armature_select_linked_poll;
271         
272         /* flags */
273         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
274         
275         /* properties */
276         RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend selection instead of deselecting everything first");
277 }
278
279 /* does bones and points */
280 /* note that BONE ROOT only gets drawn for root bones (or without IK) */
281 static EditBone *get_nearest_editbonepoint(ViewContext *vc, const int mval[2],
282                                            ListBase *edbo, int findunsel, int *selmask)
283 {
284         bArmature *arm = (bArmature *)vc->obedit->data;
285         EditBone *ebone_next_act = arm->act_edbone;
286
287         EditBone *ebone;
288         rcti rect;
289         unsigned int buffer[MAXPICKBUF];
290         unsigned int hitresult, besthitresult = BONESEL_NOSEL;
291         int i, mindep = 4;
292         short hits;
293
294         glInitNames();
295         
296         /* find the bone after the current active bone, so as to bump up its chances in selection.
297          * this way overlapping bones will cycle selection state as with objects. */
298         if (ebone_next_act &&
299             EBONE_VISIBLE(arm, ebone_next_act) &&
300             ebone_next_act->flag & (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL))
301         {
302                 ebone_next_act = ebone_next_act->next ? ebone_next_act->next : arm->edbo->first;
303         }
304         else {
305                 ebone_next_act = NULL;
306         }
307
308         rect.xmin = mval[0] - 5;
309         rect.xmax = mval[0] + 5;
310         rect.ymin = mval[1] - 5;
311         rect.ymax = mval[1] + 5;
312
313         hits = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect, true);
314         if (hits == 0) {
315                 rect.xmin = mval[0] - 12;
316                 rect.xmax = mval[0] + 12;
317                 rect.ymin = mval[1] - 12;
318                 rect.ymax = mval[1] + 12;
319                 hits = view3d_opengl_select(vc, buffer, MAXPICKBUF, &rect, true);
320         }
321         /* See if there are any selected bones in this group */
322         if (hits > 0) {
323                 
324                 if (hits == 1) {
325                         if (!(buffer[3] & BONESEL_NOSEL))
326                                 besthitresult = buffer[3];
327                 }
328                 else {
329                         for (i = 0; i < hits; i++) {
330                                 hitresult = buffer[3 + (i * 4)];
331                                 if (!(hitresult & BONESEL_NOSEL)) {
332                                         int dep;
333                                         
334                                         ebone = BLI_findlink(edbo, hitresult & ~BONESEL_ANY);
335                                         
336                                         /* clicks on bone points get advantage */
337                                         if (hitresult & (BONESEL_ROOT | BONESEL_TIP)) {
338                                                 /* but also the unselected one */
339                                                 if (findunsel) {
340                                                         if ( (hitresult & BONESEL_ROOT) && (ebone->flag & BONE_ROOTSEL) == 0)
341                                                                 dep = 1;
342                                                         else if ( (hitresult & BONESEL_TIP) && (ebone->flag & BONE_TIPSEL) == 0)
343                                                                 dep = 1;
344                                                         else 
345                                                                 dep = 2;
346                                                 }
347                                                 else {
348                                                         dep = 2;
349                                                 }
350                                         }
351                                         else {
352                                                 /* bone found */
353                                                 if (findunsel) {
354                                                         if ((ebone->flag & BONE_SELECTED) == 0)
355                                                                 dep = 2;
356                                                         else
357                                                                 dep = 3;
358                                                 }
359                                                 else {
360                                                         dep = 3;
361                                                 }
362                                         }
363
364                                         if (ebone == ebone_next_act) {
365                                                 dep -= 1;
366                                         }
367
368                                         if (dep < mindep) {
369                                                 mindep = dep;
370                                                 besthitresult = hitresult;
371                                         }
372                                 }
373                         }
374                 }
375                 
376                 if (!(besthitresult & BONESEL_NOSEL)) {
377                         
378                         ebone = BLI_findlink(edbo, besthitresult & ~BONESEL_ANY);
379                         
380                         *selmask = 0;
381                         if (besthitresult & BONESEL_ROOT)
382                                 *selmask |= BONE_ROOTSEL;
383                         if (besthitresult & BONESEL_TIP)
384                                 *selmask |= BONE_TIPSEL;
385                         if (besthitresult & BONESEL_BONE)
386                                 *selmask |= BONE_SELECTED;
387                         return ebone;
388                 }
389         }
390         *selmask = 0;
391         return NULL;
392 }
393
394
395
396 /* toggle==0: deselect
397  * toggle==1: swap (based on test)
398  * toggle==2: swap (no test), CURRENTLY UNUSED
399  */
400 void ED_armature_deselect_all(Object *obedit, int toggle)
401 {
402         bArmature *arm = obedit->data;
403         EditBone    *eBone;
404         int sel = 1;
405         
406         if (toggle == 1) {
407                 /* Determine if there are any selected bones
408                  * and therefore whether we are selecting or deselecting */
409                 for (eBone = arm->edbo->first; eBone; eBone = eBone->next) {
410                         //                      if (arm->layer & eBone->layer) {
411                         if (eBone->flag & (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL)) {
412                                 sel = 0;
413                                 break;
414                         }
415                         //                      }
416                 }
417         }
418         else {
419                 sel = toggle;
420         }
421
422         /*      Set the flags */
423         for (eBone = arm->edbo->first; eBone; eBone = eBone->next) {
424                 if (sel == 2) {
425                         /* invert selection of bone */
426                         if (EBONE_VISIBLE(arm, eBone)) {
427                                 eBone->flag ^= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
428                                 if (arm->act_edbone == eBone)
429                                         arm->act_edbone = NULL;
430                         }
431                 }
432                 else if (sel == 1) {
433                         /* select bone */
434                         if (EBONE_VISIBLE(arm, eBone)) {
435                                 eBone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
436                                 if (eBone->parent)
437                                         eBone->parent->flag |= (BONE_TIPSEL);
438                         }
439                 }
440                 else {
441                         /* deselect bone */
442                         eBone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
443                         if (arm->act_edbone == eBone)
444                                 arm->act_edbone = NULL;
445                 }
446         }
447         
448         ED_armature_sync_selection(arm->edbo);
449 }
450
451 void ED_armature_deselect_all_visible(Object *obedit)
452 {
453         bArmature *arm = obedit->data;
454         EditBone    *ebone;
455
456         for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
457                 /* first and foremost, bone must be visible and selected */
458                 if (EBONE_VISIBLE(arm, ebone)) {
459                         ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
460                 }
461         }
462
463         ED_armature_sync_selection(arm->edbo);
464 }
465
466 /* accounts for connected parents */
467 static int ebone_select_flag(EditBone *ebone)
468 {
469         if (ebone->parent && (ebone->flag & BONE_CONNECTED)) {
470                 return ((ebone->parent->flag & BONE_TIPSEL) ? BONE_ROOTSEL : 0) | (ebone->flag & (BONE_SELECTED | BONE_TIPSEL));
471         }
472         else {
473                 return ebone->flag & (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL);
474         }
475 }
476
477 /* context: editmode armature in view3d */
478 bool mouse_armature(bContext *C, const int mval[2], bool extend, bool deselect, bool toggle)
479 {
480         Object *obedit = CTX_data_edit_object(C);
481         bArmature *arm = obedit->data;
482         ViewContext vc;
483         EditBone *nearBone = NULL;
484         int selmask;
485
486         view3d_set_viewcontext(C, &vc);
487         
488         BIF_sk_selectStroke(C, mval, extend);
489         
490         nearBone = get_nearest_editbonepoint(&vc, mval, arm->edbo, 1, &selmask);
491         if (nearBone) {
492
493                 if (!extend && !deselect && !toggle)
494                         ED_armature_deselect_all(obedit, 0);
495                 
496                 /* by definition the non-root connected bones have no root point drawn,
497                  * so a root selection needs to be delivered to the parent tip */
498                 
499                 if (selmask & BONE_SELECTED) {
500                         if (nearBone->parent && (nearBone->flag & BONE_CONNECTED)) {
501                                 /* click in a chain */
502                                 if (extend) {
503                                         /* select this bone */
504                                         nearBone->flag |= BONE_TIPSEL;
505                                         nearBone->parent->flag |= BONE_TIPSEL;
506                                 }
507                                 else if (deselect) {
508                                         /* deselect this bone */
509                                         nearBone->flag &= ~(BONE_TIPSEL | BONE_SELECTED);
510                                         /* only deselect parent tip if it is not selected */
511                                         if (!(nearBone->parent->flag & BONE_SELECTED))
512                                                 nearBone->parent->flag &= ~BONE_TIPSEL;
513                                 }
514                                 else if (toggle) {
515                                         /* hold shift inverts this bone's selection */
516                                         if (nearBone->flag & BONE_SELECTED) {
517                                                 /* deselect this bone */
518                                                 nearBone->flag &= ~(BONE_TIPSEL | BONE_SELECTED);
519                                                 /* only deselect parent tip if it is not selected */
520                                                 if (!(nearBone->parent->flag & BONE_SELECTED))
521                                                         nearBone->parent->flag &= ~BONE_TIPSEL;
522                                         }
523                                         else {
524                                                 /* select this bone */
525                                                 nearBone->flag |= BONE_TIPSEL;
526                                                 nearBone->parent->flag |= BONE_TIPSEL;
527                                         }
528                                 }
529                                 else {
530                                         /* select this bone */
531                                         nearBone->flag |= BONE_TIPSEL;
532                                         nearBone->parent->flag |= BONE_TIPSEL;
533                                 }
534                         }
535                         else {
536                                 if (extend) {
537                                         nearBone->flag |= (BONE_TIPSEL | BONE_ROOTSEL);
538                                 }
539                                 else if (deselect) {
540                                         nearBone->flag &= ~(BONE_TIPSEL | BONE_ROOTSEL);
541                                 }
542                                 else if (toggle) {
543                                         /* hold shift inverts this bone's selection */
544                                         if (nearBone->flag & BONE_SELECTED)
545                                                 nearBone->flag &= ~(BONE_TIPSEL | BONE_ROOTSEL);
546                                         else
547                                                 nearBone->flag |= (BONE_TIPSEL | BONE_ROOTSEL);
548                                 }
549                                 else
550                                         nearBone->flag |= (BONE_TIPSEL | BONE_ROOTSEL);
551                         }
552                 }
553                 else {
554                         if (extend)
555                                 nearBone->flag |= selmask;
556                         else if (deselect)
557                                 nearBone->flag &= ~selmask;
558                         else if (toggle && (nearBone->flag & selmask))
559                                 nearBone->flag &= ~selmask;
560                         else
561                                 nearBone->flag |= selmask;
562                 }
563                 
564                 ED_armature_sync_selection(arm->edbo);
565                 
566                 if (nearBone) {
567                         /* then now check for active status */
568                         if (ebone_select_flag(nearBone)) {
569                                 arm->act_edbone = nearBone;
570                         }
571                 }
572                 
573                 WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, vc.obedit);
574                 return true;
575         }
576
577         return false;
578 }
579
580
581 /* ****************  Selections  ******************/
582
583 static int armature_de_select_all_exec(bContext *C, wmOperator *op)
584 {
585         int action = RNA_enum_get(op->ptr, "action");
586
587         if (action == SEL_TOGGLE) {
588                 /* Determine if there are any selected bones
589                  * And therefore whether we are selecting or deselecting */
590                 action = SEL_SELECT;
591                 CTX_DATA_BEGIN(C, EditBone *, ebone, visible_bones)
592                 {
593                         if (ebone->flag & (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL)) {
594                                 action = SEL_DESELECT;
595                                 break;
596                         }
597                 }
598                 CTX_DATA_END;
599         }
600         
601         /*      Set the flags */
602         CTX_DATA_BEGIN(C, EditBone *, ebone, visible_bones)
603         {
604                 /* ignore bone if selection can't change */
605                 switch (action) {
606                         case SEL_SELECT:
607                                 if ((ebone->flag & BONE_UNSELECTABLE) == 0) {
608                                         ebone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
609                                         if (ebone->parent) {
610                                                 ebone->parent->flag |= (BONE_TIPSEL);
611                                         }
612                                 }
613                                 break;
614                         case SEL_DESELECT:
615                                 ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
616                                 break;
617                         case SEL_INVERT:
618                                 if (ebone->flag & BONE_SELECTED) {
619                                         ebone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
620                                 }
621                                 else {
622                                         if ((ebone->flag & BONE_UNSELECTABLE) == 0) {
623                                                 ebone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
624                                                 if (ebone->parent) {
625                                                         ebone->parent->flag |= (BONE_TIPSEL);
626                                                 }
627                                         }
628                                 }
629                                 break;
630                 }
631         }
632         CTX_DATA_END;
633
634         WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, NULL);
635         
636         return OPERATOR_FINISHED;
637 }
638
639 void ARMATURE_OT_select_all(wmOperatorType *ot)
640 {
641         /* identifiers */
642         ot->name = "(De)select All";
643         ot->idname = "ARMATURE_OT_select_all";
644         ot->description = "Toggle selection status of all bones";
645         
646         /* api callbacks */
647         ot->exec = armature_de_select_all_exec;
648         ot->poll = ED_operator_editarmature;
649         
650         /* flags */
651         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
652         
653         WM_operator_properties_select_all(ot);
654 }
655
656 /**************** Select more/less **************/
657
658 static void armature_select_more(bArmature *arm, EditBone *ebone)
659 {
660         if ((EBONE_PREV_FLAG_GET(ebone) & (BONE_ROOTSEL | BONE_TIPSEL)) != 0) {
661                 if (EBONE_SELECTABLE(arm, ebone)) {
662                         ED_armature_ebone_select_set(ebone, true);
663                 }
664         }
665
666         if (ebone->parent && (ebone->flag & BONE_CONNECTED)) {
667                 /* to parent */
668                 if ((EBONE_PREV_FLAG_GET(ebone) & BONE_ROOTSEL) != 0) {
669                         if (EBONE_SELECTABLE(arm, ebone->parent)) {
670                                 ED_armature_ebone_selectflag_enable(ebone->parent, (BONE_SELECTED | BONE_ROOTSEL | BONE_TIPSEL));
671                         }
672                 }
673
674                 /* from parent (difference from select less) */
675                 if ((EBONE_PREV_FLAG_GET(ebone->parent) & BONE_TIPSEL) != 0) {
676                         if (EBONE_SELECTABLE(arm, ebone)) {
677                                 ED_armature_ebone_selectflag_enable(ebone, (BONE_SELECTED | BONE_ROOTSEL));
678                         }
679                 }
680         }
681 }
682
683 static void armature_select_less(bArmature *UNUSED(arm), EditBone *ebone)
684 {
685         if ((EBONE_PREV_FLAG_GET(ebone) & (BONE_ROOTSEL | BONE_TIPSEL)) != (BONE_ROOTSEL | BONE_TIPSEL)) {
686                 ED_armature_ebone_select_set(ebone, false);
687         }
688
689         if (ebone->parent && (ebone->flag & BONE_CONNECTED)) {
690                 /* to parent */
691                 if ((EBONE_PREV_FLAG_GET(ebone) & BONE_SELECTED) == 0) {
692                         ED_armature_ebone_selectflag_disable(ebone->parent, (BONE_SELECTED | BONE_TIPSEL));
693                 }
694
695                 /* from parent (difference from select more) */
696                 if ((EBONE_PREV_FLAG_GET(ebone->parent) & BONE_SELECTED) == 0) {
697                         ED_armature_ebone_selectflag_disable(ebone, (BONE_SELECTED | BONE_ROOTSEL));
698                 }
699         }
700 }
701
702 static void armature_select_more_less(Object *ob, bool more)
703 {
704         bArmature *arm = (bArmature *)ob->data;
705         EditBone *ebone;
706
707         /* XXX, eventually we shouldn't need this - campbell */
708         ED_armature_sync_selection(arm->edbo);
709
710         /* count bones & store selection state */
711         for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
712                 EBONE_PREV_FLAG_SET(ebone, ED_armature_ebone_selectflag_get(ebone));
713         }
714
715         /* do selection */
716         for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
717                 if (EBONE_VISIBLE(arm, ebone)) {
718                         if (more) {
719                                 armature_select_more(arm, ebone);
720                         }
721                         else {
722                                 armature_select_less(arm, ebone);
723                         }
724                 }
725         }
726
727         for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
728                 if (EBONE_VISIBLE(arm, ebone)) {
729                         if (more == false) {
730                                 if (ebone->flag & BONE_SELECTED) {
731                                         ED_armature_ebone_select_set(ebone, true);
732                                 }
733                         }
734                 }
735                 ebone->temp = NULL;
736         }
737
738         ED_armature_sync_selection(arm->edbo);
739 }
740
741 static int armature_de_select_more_exec(bContext *C, wmOperator *UNUSED(op))
742 {
743         Object *obedit = CTX_data_edit_object(C);
744         armature_select_more_less(obedit, true);
745         WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
746
747         return OPERATOR_FINISHED;
748 }
749
750 void ARMATURE_OT_select_more(wmOperatorType *ot)
751 {
752         /* identifiers */
753         ot->name = "Select More";
754         ot->idname = "ARMATURE_OT_select_more";
755         ot->description = "Select those bones connected to the initial selection";
756
757         /* api callbacks */
758         ot->exec = armature_de_select_more_exec;
759         ot->poll = ED_operator_editarmature;
760
761         /* flags */
762         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
763 }
764
765 static int armature_de_select_less_exec(bContext *C, wmOperator *UNUSED(op))
766 {
767         Object *obedit = CTX_data_edit_object(C);
768         armature_select_more_less(obedit, false);
769         WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
770
771         return OPERATOR_FINISHED;
772 }
773
774 void ARMATURE_OT_select_less(wmOperatorType *ot)
775 {
776         /* identifiers */
777         ot->name = "Select Less";
778         ot->idname = "ARMATURE_OT_select_less";
779         ot->description = "Deselect those bones at the boundary of each selection region";
780
781         /* api callbacks */
782         ot->exec = armature_de_select_less_exec;
783         ot->poll = ED_operator_editarmature;
784
785         /* flags */
786         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
787 }
788
789 enum {
790         SIMEDBONE_LENGTH = 1,
791         SIMEDBONE_DIRECTION,
792         SIMEDBONE_PREFIX,
793         SIMEDBONE_SUFFIX,
794         SIMEDBONE_LAYER
795 };
796
797 static EnumPropertyItem prop_similar_types[] = {
798         {SIMEDBONE_LENGTH, "LENGTH", 0, "Length", ""},
799         {SIMEDBONE_DIRECTION, "DIRECTION", 0, "Direction (Y axis)", ""},
800         {SIMEDBONE_PREFIX, "PREFIX", 0, "Prefix", ""},
801         {SIMEDBONE_SUFFIX, "SUFFIX", 0, "Suffix", ""},
802         {SIMEDBONE_LAYER, "LAYER", 0, "Layer", ""},
803         {0, NULL, 0, NULL, NULL}
804 };
805
806
807 static void select_similar_length(bArmature *arm, EditBone *ebone_act, const float thresh)
808 {
809         EditBone *ebone;
810
811         /* thresh is always relative to current length */
812         const float len_min = ebone_act->length / (1.0f + thresh);
813         const float len_max = ebone_act->length * (1.0f + thresh);
814
815         for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
816                 if (EBONE_SELECTABLE(arm, ebone)) {
817                         if ((ebone->length >= len_min) &&
818                             (ebone->length <= len_max))
819                         {
820                                 ED_armature_ebone_select_set(ebone, true);
821                         }
822                 }
823         }
824 }
825
826 static void select_similar_direction(bArmature *arm, EditBone *ebone_act, const float thresh)
827 {
828         EditBone *ebone;
829         float dir_act[3];
830         sub_v3_v3v3(dir_act, ebone_act->head, ebone_act->tail);
831
832         for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
833                 if (EBONE_SELECTABLE(arm, ebone)) {
834                         float dir[3];
835                         sub_v3_v3v3(dir, ebone->head, ebone->tail);
836
837                         if (angle_v3v3(dir_act, dir) / (float)M_PI < thresh) {
838                                 ED_armature_ebone_select_set(ebone, true);
839                         }
840                 }
841         }
842 }
843
844 static void select_similar_layer(bArmature *arm, EditBone *ebone_act)
845 {
846         EditBone *ebone;
847
848         for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
849                 if (EBONE_SELECTABLE(arm, ebone)) {
850                         if (ebone->layer & ebone_act->layer) {
851                                 ED_armature_ebone_select_set(ebone, true);
852                         }
853                 }
854         }
855 }
856
857 static void select_similar_prefix(bArmature *arm, EditBone *ebone_act)
858 {
859         EditBone *ebone;
860
861         char body_tmp[MAX_VGROUP_NAME];
862         char prefix_act[MAX_VGROUP_NAME];
863
864         BKE_deform_split_prefix(ebone_act->name, prefix_act, body_tmp);
865
866         if (prefix_act[0] == '\0')
867                 return;
868
869         /* Find matches */
870         for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
871                 if (EBONE_SELECTABLE(arm, ebone)) {
872                         char prefix_other[MAX_VGROUP_NAME];
873                         BKE_deform_split_prefix(ebone->name, prefix_other, body_tmp);
874                         if (STREQ(prefix_act, prefix_other)) {
875                                 ED_armature_ebone_select_set(ebone, true);
876                         }
877                 }
878         }
879 }
880
881 static void select_similar_suffix(bArmature *arm, EditBone *ebone_act)
882 {
883         EditBone *ebone;
884
885         char body_tmp[MAX_VGROUP_NAME];
886         char suffix_act[MAX_VGROUP_NAME];
887
888         BKE_deform_split_suffix(ebone_act->name, body_tmp, suffix_act);
889
890         if (suffix_act[0] == '\0')
891                 return;
892
893         /* Find matches */
894         for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
895                 if (EBONE_SELECTABLE(arm, ebone)) {
896                         char suffix_other[MAX_VGROUP_NAME];
897                         BKE_deform_split_suffix(ebone->name, body_tmp, suffix_other);
898                         if (STREQ(suffix_act, suffix_other)) {
899                                 ED_armature_ebone_select_set(ebone, true);
900                         }
901                 }
902         }
903 }
904
905 static int armature_select_similar_exec(bContext *C, wmOperator *op)
906 {
907         Object *obedit = CTX_data_edit_object(C);
908         bArmature *arm = obedit->data;
909         EditBone *ebone_act = CTX_data_active_bone(C);
910
911         /* Get props */
912         int type = RNA_enum_get(op->ptr, "type");
913         float thresh = RNA_float_get(op->ptr, "threshold");
914
915         /* Check for active bone */
916         if (ebone_act == NULL) {
917                 BKE_report(op->reports, RPT_ERROR, "Operation requires an active bone");
918                 return OPERATOR_CANCELLED;
919         }
920
921         switch (type) {
922                 case SIMEDBONE_LENGTH:
923                         select_similar_length(arm, ebone_act, thresh);
924                         break;
925                 case SIMEDBONE_DIRECTION:
926                         select_similar_direction(arm, ebone_act, thresh);
927                         break;
928                 case SIMEDBONE_PREFIX:
929                         select_similar_prefix(arm, ebone_act);
930                         break;
931                 case SIMEDBONE_SUFFIX:
932                         select_similar_suffix(arm, ebone_act);
933                         break;
934                 case SIMEDBONE_LAYER:
935                         select_similar_layer(arm, ebone_act);
936                         break;
937         }
938
939         WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
940
941         return OPERATOR_FINISHED;
942 }
943
944 void ARMATURE_OT_select_similar(wmOperatorType *ot)
945 {
946         /* identifiers */
947         ot->name = "Select Similar";
948         ot->idname = "ARMATURE_OT_select_similar";
949
950         /* callback functions */
951         ot->invoke = WM_menu_invoke;
952         ot->exec = armature_select_similar_exec;
953         ot->poll = ED_operator_editarmature;
954         ot->description = "Select similar bones by property types";
955
956         /* flags */
957         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
958
959         /* properties */
960         ot->prop = RNA_def_enum(ot->srna, "type", prop_similar_types, 0, "Type", "");
961         RNA_def_float(ot->srna, "threshold", 0.1f, 0.0f, 1.0f, "Threshold", "", 0.0f, 1.0f);
962 }
963
964 /* ********************* select hierarchy operator ************** */
965
966 /* Get the first available child of an editbone */
967 static EditBone *editbone_get_child(bArmature *arm, EditBone *pabone, short use_visibility)
968 {
969         EditBone *curbone, *chbone = NULL;
970         
971         for (curbone = arm->edbo->first; curbone; curbone = curbone->next) {
972                 if (curbone->parent == pabone) {
973                         if (use_visibility) {
974                                 if ((arm->layer & curbone->layer) && !(pabone->flag & BONE_HIDDEN_A)) {
975                                         chbone = curbone;
976                                 }
977                         }
978                         else
979                                 chbone = curbone;
980                 }
981         }
982         
983         return chbone;
984 }
985
986 static int armature_select_hierarchy_exec(bContext *C, wmOperator *op)
987 {
988         Object *obedit = CTX_data_edit_object(C);
989         Object *ob;
990         bArmature *arm;
991         EditBone *curbone, *pabone, *chbone;
992         int direction = RNA_enum_get(op->ptr, "direction");
993         const bool add_to_sel = RNA_boolean_get(op->ptr, "extend");
994         
995         ob = obedit;
996         arm = (bArmature *)ob->data;
997         
998         for (curbone = arm->edbo->first; curbone; curbone = curbone->next) {
999                 /* only work on bone if it is visible and its selection can change */
1000                 if (EBONE_SELECTABLE(arm, curbone)) {
1001                         if (curbone == arm->act_edbone) {
1002                                 if (direction == BONE_SELECT_PARENT) {
1003                                         if (curbone->parent == NULL) continue;
1004                                         else pabone = curbone->parent;
1005                                         
1006                                         if (EBONE_VISIBLE(arm, pabone)) {
1007                                                 pabone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
1008                                                 arm->act_edbone = pabone;
1009                                                 if (pabone->parent) pabone->parent->flag |= BONE_TIPSEL;
1010                                                 
1011                                                 if (!add_to_sel) curbone->flag &= ~(BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
1012                                                 break;
1013                                         }
1014                                         
1015                                 }
1016                                 else { // BONE_SELECT_CHILD
1017                                         chbone = editbone_get_child(arm, curbone, 1);
1018                                         if (chbone == NULL) continue;
1019                                         
1020                                         if (EBONE_SELECTABLE(arm, chbone)) {
1021                                                 chbone->flag |= (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL);
1022                                                 arm->act_edbone = chbone;
1023                                                 
1024                                                 if (!add_to_sel) {
1025                                                         curbone->flag &= ~(BONE_SELECTED | BONE_ROOTSEL);
1026                                                         if (curbone->parent) curbone->parent->flag &= ~BONE_TIPSEL;
1027                                                 }
1028                                                 break;
1029                                         }
1030                                 }
1031                         }
1032                 }
1033         }
1034         
1035         ED_armature_sync_selection(arm->edbo);
1036         
1037         WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
1038         
1039         return OPERATOR_FINISHED;
1040 }
1041
1042 void ARMATURE_OT_select_hierarchy(wmOperatorType *ot)
1043 {
1044         static EnumPropertyItem direction_items[] = {
1045                 {BONE_SELECT_PARENT, "PARENT", 0, "Select Parent", ""},
1046                 {BONE_SELECT_CHILD, "CHILD", 0, "Select Child", ""},
1047                 {0, NULL, 0, NULL, NULL}
1048         };
1049         
1050         /* identifiers */
1051         ot->name = "Select Hierarchy";
1052         ot->idname = "ARMATURE_OT_select_hierarchy";
1053         ot->description = "Select immediate parent/children of selected bones";
1054         
1055         /* api callbacks */
1056         ot->exec = armature_select_hierarchy_exec;
1057         ot->poll = ED_operator_editarmature;
1058         
1059         /* flags */
1060         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1061
1062         /* props */
1063         RNA_def_enum(ot->srna, "direction", direction_items,
1064                      BONE_SELECT_PARENT, "Direction", "");
1065         RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
1066 }
1067
1068 /****************** Mirror Select ****************/
1069
1070 /**
1071  * \note clone of #pose_select_mirror_exec keep in sync
1072  */
1073 static int armature_select_mirror_exec(bContext *C, wmOperator *op)
1074 {
1075         Object *obedit = CTX_data_edit_object(C);
1076         bArmature *arm = obedit->data;
1077         EditBone *ebone, *ebone_mirror_act = NULL;
1078         const bool active_only = RNA_boolean_get(op->ptr, "only_active");
1079         const bool extend = RNA_boolean_get(op->ptr, "extend");
1080
1081         for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
1082                 const int flag = ED_armature_ebone_selectflag_get(ebone);
1083                 EBONE_PREV_FLAG_SET(ebone, flag);
1084         }
1085
1086         for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
1087                 if (EBONE_SELECTABLE(arm, ebone)) {
1088                         EditBone *ebone_mirror;
1089                         int flag_new = extend ? EBONE_PREV_FLAG_GET(ebone) : 0;
1090
1091                         if ((ebone_mirror = ED_armature_bone_get_mirrored(arm->edbo, ebone)) &&
1092                             (EBONE_VISIBLE(arm, ebone_mirror)))
1093                         {
1094                                 const int flag_mirror = EBONE_PREV_FLAG_GET(ebone_mirror);
1095                                 flag_new |= flag_mirror;
1096
1097                                 if (ebone == arm->act_edbone) {
1098                                         ebone_mirror_act = ebone_mirror;
1099                                 }
1100
1101                                 /* skip all but the active or its mirror */
1102                                 if (active_only && !ELEM(arm->act_edbone, ebone, ebone_mirror)) {
1103                                         continue;
1104                                 }
1105                         }
1106
1107                         ED_armature_ebone_selectflag_set(ebone, flag_new);
1108                 }
1109         }
1110
1111         if (ebone_mirror_act) {
1112                 arm->act_edbone = ebone_mirror_act;
1113         }
1114
1115         ED_armature_sync_selection(arm->edbo);
1116
1117         WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
1118
1119         return OPERATOR_FINISHED;
1120 }
1121
1122 void ARMATURE_OT_select_mirror(wmOperatorType *ot)
1123 {
1124         /* identifiers */
1125         ot->name = "Flip Active/Selected Bone";
1126         ot->idname = "ARMATURE_OT_select_mirror";
1127         ot->description = "Mirror the bone selection";
1128
1129         /* api callbacks */
1130         ot->exec = armature_select_mirror_exec;
1131         ot->poll = ED_operator_editarmature;
1132
1133         /* flags */
1134         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1135
1136         /* properties */
1137         RNA_def_boolean(ot->srna, "only_active", false, "Active Only", "Only operate on the active bone");
1138         RNA_def_boolean(ot->srna, "extend", false, "Extend", "Extend the selection");
1139 }
1140
1141
1142 /****************** Select Path ****************/
1143
1144 static bool armature_shortest_path_select(bArmature *arm, EditBone *ebone_parent, EditBone *ebone_child,
1145                                           bool use_parent, bool is_test)
1146 {
1147         do {
1148
1149                 if (!use_parent && (ebone_child == ebone_parent))
1150                         break;
1151
1152                 if (is_test) {
1153                         if (!EBONE_SELECTABLE(arm, ebone_child)) {
1154                                 return false;
1155                         }
1156                 }
1157                 else {
1158                         ED_armature_ebone_selectflag_set(ebone_child, (BONE_SELECTED | BONE_TIPSEL | BONE_ROOTSEL));
1159                 }
1160
1161                 if (ebone_child == ebone_parent)
1162                         break;
1163
1164                 ebone_child = ebone_child->parent;
1165         } while (true);
1166
1167         return true;
1168 }
1169
1170 static int armature_shortest_path_pick_invoke(bContext *C, wmOperator *op, const wmEvent *event)
1171 {
1172         Object *obedit = CTX_data_edit_object(C);
1173         bArmature *arm = obedit->data;
1174         EditBone *ebone_src, *ebone_dst;
1175         EditBone *ebone_isect_parent = NULL;
1176         EditBone *ebone_isect_child[2];
1177         bool changed;
1178
1179         view3d_operator_needs_opengl(C);
1180
1181         ebone_src = arm->act_edbone;
1182         ebone_dst = get_nearest_bone(C, 0, event->mval[0], event->mval[1]);
1183
1184         /* fallback to object selection */
1185         if (ELEM(NULL, ebone_src, ebone_dst) || (ebone_src == ebone_dst)) {
1186                 return OPERATOR_PASS_THROUGH;
1187         }
1188
1189         ebone_isect_child[0] = ebone_src;
1190         ebone_isect_child[1] = ebone_dst;
1191
1192
1193         /* ensure 'ebone_src' is the parent of 'ebone_dst', or set 'ebone_isect_parent' */
1194         if (ED_armature_ebone_is_child_recursive(ebone_src, ebone_dst)) {
1195                 /* pass */
1196         }
1197         else if (ED_armature_ebone_is_child_recursive(ebone_dst, ebone_src)) {
1198                 SWAP(EditBone *, ebone_src, ebone_dst);
1199         }
1200         else if ((ebone_isect_parent = ED_armature_bone_find_shared_parent(ebone_isect_child, 2))) {
1201                 /* pass */
1202         }
1203         else {
1204                 /* disconnected bones */
1205                 return OPERATOR_CANCELLED;
1206         }
1207
1208
1209         if (ebone_isect_parent) {
1210                 if (armature_shortest_path_select(arm, ebone_isect_parent, ebone_src, false, true) &&
1211                     armature_shortest_path_select(arm, ebone_isect_parent, ebone_dst, false, true))
1212                 {
1213                         armature_shortest_path_select(arm, ebone_isect_parent, ebone_src, false, false);
1214                         armature_shortest_path_select(arm, ebone_isect_parent, ebone_dst, false, false);
1215                         changed = true;
1216                 }
1217                 else {
1218                         /* unselectable */
1219                         changed = false;
1220                 }
1221         }
1222         else {
1223                 if (armature_shortest_path_select(arm, ebone_src, ebone_dst, true, true)) {
1224                         armature_shortest_path_select(arm, ebone_src, ebone_dst, true, false);
1225                         changed = true;
1226                 }
1227                 else {
1228                         /* unselectable */
1229                         changed = false;
1230                 }
1231         }
1232
1233         if (changed) {
1234                 arm->act_edbone = ebone_dst;
1235                 ED_armature_sync_selection(arm->edbo);
1236                 WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
1237
1238                 return OPERATOR_FINISHED;
1239         }
1240         else {
1241                 BKE_report(op->reports, RPT_WARNING, "Unselectable bone in chain");
1242                 return OPERATOR_CANCELLED;
1243         }
1244 }
1245
1246 void ARMATURE_OT_shortest_path_pick(wmOperatorType *ot)
1247 {
1248         /* identifiers */
1249         ot->name = "Pick Shortest Path";
1250         ot->idname = "ARMATURE_OT_shortest_path_pick";
1251         ot->description = "Select shortest path between two bones";
1252
1253         /* api callbacks */
1254         ot->invoke = armature_shortest_path_pick_invoke;
1255         ot->poll = ED_operator_editarmature;
1256
1257         /* flags */
1258         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1259 }