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