Code cleanup: use bool
[blender.git] / source / blender / editors / armature / armature_edit.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  * Armature EditMode tools - transforms, chain based editing, and other settings
26  */
27
28 /** \file blender/editors/armature/armature_edit.c
29  *  \ingroup edarmature
30  */
31
32 #include <assert.h> 
33
34 #include "DNA_armature_types.h"
35 #include "DNA_constraint_types.h"
36 #include "DNA_object_types.h"
37 #include "DNA_scene_types.h"
38
39 #include "MEM_guardedalloc.h"
40
41 #include "BLI_blenlib.h"
42 #include "BLI_math.h"
43
44 #include "BKE_action.h"
45 #include "BKE_armature.h"
46 #include "BKE_constraint.h"
47 #include "BKE_context.h"
48 #include "BKE_global.h"
49 #include "BKE_report.h"
50
51 #include "RNA_access.h"
52 #include "RNA_define.h"
53
54 #include "WM_api.h"
55 #include "WM_types.h"
56
57 #include "ED_armature.h"
58 #include "ED_screen.h"
59 #include "ED_view3d.h"
60
61 #include "armature_intern.h"
62
63 /* ************************** Object Tools Exports ******************************* */
64 /* NOTE: these functions are exported to the Object module to be called from the tools there */
65
66 void ED_armature_apply_transform(Object *ob, float mat[4][4])
67 {
68         bArmature *arm = ob->data;
69
70         /* Put the armature into editmode */
71         ED_armature_to_edit(arm);
72
73         /* Transform the bones*/
74         ED_armature_transform_bones(arm, mat);
75
76         /* Turn the list into an armature */
77         ED_armature_from_edit(arm);
78         ED_armature_edit_free(arm);
79 }
80
81 void ED_armature_transform_bones(struct bArmature *arm, float mat[4][4])
82 {
83         EditBone *ebone;
84         float scale = mat4_to_scale(mat);   /* store the scale of the matrix here to use on envelopes */
85         float mat3[3][3];
86
87         copy_m3_m4(mat3, mat);
88         normalize_m3(mat3);
89         /* Do the rotations */
90         for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
91                 float tmat[3][3];
92                 
93                 /* find the current bone's roll matrix */
94                 ED_armature_ebone_to_mat3(ebone, tmat);
95                 
96                 /* transform the roll matrix */
97                 mul_m3_m3m3(tmat, mat3, tmat);
98                 
99                 /* transform the bone */
100                 mul_m4_v3(mat, ebone->head);
101                 mul_m4_v3(mat, ebone->tail);
102
103                 /* apply the transfiormed roll back */
104                 mat3_to_vec_roll(tmat, NULL, &ebone->roll);
105                 
106                 ebone->rad_head *= scale;
107                 ebone->rad_tail *= scale;
108                 ebone->dist     *= scale;
109                 
110                 /* we could be smarter and scale by the matrix along the x & z axis */
111                 ebone->xwidth   *= scale;
112                 ebone->zwidth   *= scale;
113         }
114 }
115
116 void ED_armature_transform(struct bArmature *arm, float mat[4][4])
117 {
118         if (arm->edbo) {
119                 ED_armature_transform_bones(arm, mat);
120         }
121         else {
122                 /* Put the armature into editmode */
123                 ED_armature_to_edit(arm);
124
125                 /* Transform the bones */
126                 ED_armature_transform_bones(arm, mat);
127
128                 /* Go back to object mode*/
129                 ED_armature_from_edit(arm);
130                 ED_armature_edit_free(arm);
131         }
132 }
133
134 /* exported for use in editors/object/ */
135 /* 0 == do center, 1 == center new, 2 == center cursor */
136 void ED_armature_origin_set(Scene *scene, Object *ob, float cursor[3], int centermode, int around)
137 {
138         Object *obedit = scene->obedit; // XXX get from context
139         EditBone *ebone;
140         bArmature *arm = ob->data;
141         float cent[3];
142
143         /* Put the armature into editmode */
144         if (ob != obedit) {
145                 ED_armature_to_edit(arm);
146                 obedit = NULL; /* we cant use this so behave as if there is no obedit */
147         }
148
149         /* Find the centerpoint */
150         if (centermode == 2) {
151                 copy_v3_v3(cent, cursor);
152                 invert_m4_m4(ob->imat, ob->obmat);
153                 mul_m4_v3(ob->imat, cent);
154         }
155         else {
156                 if (around == V3D_CENTROID) {
157                         int total = 0;
158                         zero_v3(cent);
159                         for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
160                                 total += 2;
161                                 add_v3_v3(cent, ebone->head);
162                                 add_v3_v3(cent, ebone->tail);
163                         }
164                         if (total) {
165                                 mul_v3_fl(cent, 1.0f / (float)total);
166                         }
167                 }
168                 else {
169                         float min[3], max[3];
170                         INIT_MINMAX(min, max);
171                         for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
172                                 minmax_v3v3_v3(min, max, ebone->head);
173                                 minmax_v3v3_v3(min, max, ebone->tail);
174                         }
175                         mid_v3_v3v3(cent, min, max);
176                 }
177         }
178         
179         /* Do the adjustments */
180         for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
181                 sub_v3_v3(ebone->head, cent);
182                 sub_v3_v3(ebone->tail, cent);
183         }
184         
185         /* Turn the list into an armature */
186         if (obedit == NULL) {
187                 ED_armature_from_edit(arm);
188                 ED_armature_edit_free(arm);
189         }
190
191         /* Adjust object location for new centerpoint */
192         if (centermode && obedit == NULL) {
193                 mul_mat3_m4_v3(ob->obmat, cent); /* ommit translation part */
194                 add_v3_v3(ob->loc, cent);
195         }
196 }
197
198 /* ********************************* Roll ******************************* */
199
200 /* adjust bone roll to align Z axis with vector
201  * vec is in local space and is normalized
202  */
203 float ED_rollBoneToVector(EditBone *bone, const float align_axis[3], const bool axis_only)
204 {
205         float mat[3][3], nor[3];
206
207         sub_v3_v3v3(nor, bone->tail, bone->head);
208         vec_roll_to_mat3(nor, 0.0f, mat);
209         
210         /* check the bone isn't aligned with the axis */
211         if (!is_zero_v3(align_axis) && angle_v3v3(align_axis, mat[2]) > FLT_EPSILON) {
212                 float vec[3], align_axis_proj[3], roll;
213                 
214                 /* project the new_up_axis along the normal */
215                 project_v3_v3v3(vec, align_axis, nor);
216                 sub_v3_v3v3(align_axis_proj, align_axis, vec);
217                 
218                 if (axis_only) {
219                         if (angle_v3v3(align_axis_proj, mat[2]) > (float)(M_PI / 2.0)) {
220                                 negate_v3(align_axis_proj);
221                         }
222                 }
223                 
224                 roll = angle_v3v3(align_axis_proj, mat[2]);
225                 
226                 cross_v3_v3v3(vec, mat[2], align_axis_proj);
227                 
228                 if (dot_v3v3(vec, nor) < 0) {
229                         roll = -roll;
230                 }
231                 
232                 return roll;
233         }
234
235         return 0.0f;
236 }
237
238
239 typedef enum eCalcRollTypes {
240         CALC_ROLL_X          = 0,
241         CALC_ROLL_Y          = 1,
242         CALC_ROLL_Z          = 2,
243         
244         CALC_ROLL_TAN_X      = 3,
245         CALC_ROLL_TAN_Z      = 4,
246
247         CALC_ROLL_ACTIVE     = 5,
248         CALC_ROLL_VIEW       = 6,
249         CALC_ROLL_CURSOR     = 7,
250 } eCalcRollTypes;
251
252 static EnumPropertyItem prop_calc_roll_types[] = {
253         {CALC_ROLL_TAN_X, "X", 0, "Local X Tangent", ""},
254         {CALC_ROLL_TAN_Z, "Z", 0, "Local Z Tangent", ""},
255
256         {CALC_ROLL_X, "X", 0, "Global X Axis", ""},
257         {CALC_ROLL_Y, "Y", 0, "Global Y Axis", ""},
258         {CALC_ROLL_Z, "Z", 0, "Global Z Axis", ""},
259
260         {CALC_ROLL_ACTIVE, "ACTIVE", 0, "Active Bone", ""},
261         {CALC_ROLL_VIEW, "VIEW", 0, "View Axis", ""},
262         {CALC_ROLL_CURSOR, "CURSOR", 0, "Cursor", ""},
263         {0, NULL, 0, NULL, NULL}
264 };
265
266
267 static int armature_calc_roll_exec(bContext *C, wmOperator *op) 
268 {
269         Object *ob = CTX_data_edit_object(C);
270         const short type = RNA_enum_get(op->ptr, "type");
271         const short axis_only = RNA_boolean_get(op->ptr, "axis_only");
272         const short axis_flip = RNA_boolean_get(op->ptr, "axis_flip");
273
274         float imat[3][3];
275
276         bArmature *arm = ob->data;
277         EditBone *ebone;
278
279         copy_m3_m4(imat, ob->obmat);
280         invert_m3(imat);
281
282         if (type == CALC_ROLL_CURSOR) { /* Cursor */
283                 Scene *scene = CTX_data_scene(C);
284                 View3D *v3d = CTX_wm_view3d(C); /* can be NULL */
285                 float cursor_local[3];
286                 const float   *cursor = ED_view3d_cursor3d_get(scene, v3d);
287                 
288                 
289                 copy_v3_v3(cursor_local, cursor);
290                 mul_m3_v3(imat, cursor_local);
291                 
292                 /* cursor */
293                 for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
294                         if (EBONE_VISIBLE(arm, ebone) && EBONE_EDITABLE(ebone)) {
295                                 float cursor_rel[3];
296                                 sub_v3_v3v3(cursor_rel, cursor_local, ebone->head);
297                                 if (axis_flip) negate_v3(cursor_rel);
298                                 ebone->roll = ED_rollBoneToVector(ebone, cursor_rel, axis_only);
299                         }
300                 }
301         }
302         else if (ELEM(type, CALC_ROLL_TAN_X, CALC_ROLL_TAN_Z)) {
303                 for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
304                         if (ebone->parent) {
305                                 bool is_edit        = (EBONE_VISIBLE(arm, ebone)         && EBONE_EDITABLE(ebone));
306                                 bool is_edit_parent = (EBONE_VISIBLE(arm, ebone->parent) && EBONE_EDITABLE(ebone->parent));
307
308                                 if (is_edit || is_edit_parent) {
309                                         EditBone *ebone_other = ebone->parent;
310                                         float dir_a[3];
311                                         float dir_b[3];
312                                         float vec[3];
313                                         bool is_vec_zero;
314
315                                         sub_v3_v3v3(dir_a, ebone->tail, ebone->head);
316                                         normalize_v3(dir_a);
317
318                                         /* find the first bone in the chane with a different direction */
319                                         do {
320                                                 sub_v3_v3v3(dir_b, ebone_other->head, ebone_other->tail);
321                                                 normalize_v3(dir_b);
322
323                                                 if (type == CALC_ROLL_TAN_Z) {
324                                                         cross_v3_v3v3(vec, dir_a, dir_b);
325                                                 }
326                                                 else {
327                                                         add_v3_v3v3(vec, dir_a, dir_b);
328                                                 }
329                                         } while ((is_vec_zero = (normalize_v3(vec) < 0.00001f)) &&
330                                                  (ebone_other = ebone_other->parent));
331
332                                         if (!is_vec_zero) {
333                                                 if (axis_flip) negate_v3(vec);
334
335                                                 if (is_edit) {
336                                                         ebone->roll = ED_rollBoneToVector(ebone, vec, axis_only);
337                                                 }
338
339                                                 /* parentless bones use cross product with child */
340                                                 if (is_edit_parent) {
341                                                         if (ebone->parent->parent == NULL) {
342                                                                 ebone->parent->roll = ED_rollBoneToVector(ebone->parent, vec, axis_only);
343                                                         }
344                                                 }
345                                         }
346                                 }
347                         }
348                 }
349         }
350         else {
351                 float vec[3] = {0.0f, 0.0f, 0.0f};
352                 if (type == CALC_ROLL_VIEW) { /* View */
353                         RegionView3D *rv3d = CTX_wm_region_view3d(C);
354                         if (rv3d == NULL) {
355                                 BKE_report(op->reports, RPT_ERROR, "No region view3d available");
356                                 return OPERATOR_CANCELLED;
357                         }
358                         
359                         copy_v3_v3(vec, rv3d->viewinv[2]);
360                         mul_m3_v3(imat, vec);
361                 }
362                 else if (type == CALC_ROLL_ACTIVE) {
363                         float mat[3][3];
364                         ebone = (EditBone *)arm->act_edbone;
365                         if (ebone == NULL) {
366                                 BKE_report(op->reports, RPT_ERROR, "No active bone set");
367                                 return OPERATOR_CANCELLED;
368                         }
369                         
370                         ED_armature_ebone_to_mat3(ebone, mat);
371                         copy_v3_v3(vec, mat[2]);
372                 }
373                 else { /* Axis */
374                         assert(type >= 0 && type <= 5);
375                         if (type < 3) vec[type] = 1.0f;
376                         else vec[type - 2] = -1.0f;
377                         mul_m3_v3(imat, vec);
378                 }
379                 
380                 if (axis_flip) negate_v3(vec);
381                 
382                 for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
383                         if (EBONE_VISIBLE(arm, ebone) && EBONE_EDITABLE(ebone)) {
384                                 /* roll func is a callback which assumes that all is well */
385                                 ebone->roll = ED_rollBoneToVector(ebone, vec, axis_only);
386                         }
387                 }
388         }
389         
390         if (arm->flag & ARM_MIRROR_EDIT) {
391                 for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
392                         if ((EBONE_VISIBLE(arm, ebone) && EBONE_EDITABLE(ebone)) == 0) {
393                                 EditBone *ebone_mirr = ED_armature_bone_get_mirrored(arm->edbo, ebone);
394                                 if (ebone_mirr && (EBONE_VISIBLE(arm, ebone_mirr) && EBONE_EDITABLE(ebone_mirr))) {
395                                         ebone->roll = -ebone_mirr->roll;
396                                 }
397                         }
398                 }
399         }
400         
401         /* note, notifier might evolve */
402         WM_event_add_notifier(C, NC_OBJECT | ND_POSE, ob);
403         
404         return OPERATOR_FINISHED;
405 }
406
407 void ARMATURE_OT_calculate_roll(wmOperatorType *ot)
408 {
409         /* identifiers */
410         ot->name = "Recalculate Roll";
411         ot->idname = "ARMATURE_OT_calculate_roll";
412         ot->description = "Automatically fix alignment of select bones' axes";
413         
414         /* api callbacks */
415         ot->invoke = WM_menu_invoke;
416         ot->exec = armature_calc_roll_exec;
417         ot->poll = ED_operator_editarmature;
418         
419         /* flags */
420         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
421
422         /* properties */
423         ot->prop = RNA_def_enum(ot->srna, "type", prop_calc_roll_types, CALC_ROLL_TAN_X, "Type", "");
424         RNA_def_boolean(ot->srna, "axis_flip", 0, "Flip Axis", "Negate the alignment axis");
425         RNA_def_boolean(ot->srna, "axis_only", 0, "Shortest Rotation", "Ignore the axis direction, use the shortest rotation to align");
426 }
427
428 /* ******************************** Chain-Based Tools ********************************* */
429
430 /* temporary data-structure for merge/fill bones */
431 typedef struct EditBonePoint {
432         struct EditBonePoint *next, *prev;
433         
434         EditBone *head_owner;       /* EditBone which uses this point as a 'head' point */
435         EditBone *tail_owner;       /* EditBone which uses this point as a 'tail' point */
436         
437         float vec[3];               /* the actual location of the point in local/EditMode space */
438 } EditBonePoint;
439
440 /* find chain-tips (i.e. bones without children) */
441 static void chains_find_tips(ListBase *edbo, ListBase *list)
442 {
443         EditBone *curBone, *ebo;
444         LinkData *ld;
445         
446         /* note: this is potentially very slow ... there's got to be a better way */
447         for (curBone = edbo->first; curBone; curBone = curBone->next) {
448                 short stop = 0;
449                 
450                 /* is this bone contained within any existing chain? (skip if so) */
451                 for (ld = list->first; ld; ld = ld->next) {
452                         for (ebo = ld->data; ebo; ebo = ebo->parent) {
453                                 if (ebo == curBone) {
454                                         stop = 1;
455                                         break;
456                                 }
457                         }
458                         
459                         if (stop) break;
460                 }
461                 /* skip current bone if it is part of an existing chain */
462                 if (stop) continue;
463                 
464                 /* is any existing chain part of the chain formed by this bone? */
465                 stop = 0;
466                 for (ebo = curBone->parent; ebo; ebo = ebo->parent) {
467                         for (ld = list->first; ld; ld = ld->next) {
468                                 if (ld->data == ebo) {
469                                         ld->data = curBone;
470                                         stop = 1;
471                                         break;
472                                 }
473                         }
474                         
475                         if (stop) break;
476                 }
477                 /* current bone has already been added to a chain? */
478                 if (stop) continue;
479                 
480                 /* add current bone to a new chain */
481                 ld = MEM_callocN(sizeof(LinkData), "BoneChain");
482                 ld->data = curBone;
483                 BLI_addtail(list, ld);
484         }
485 }
486
487 /* --------------------- */
488
489 static void fill_add_joint(EditBone *ebo, short eb_tail, ListBase *points)
490 {
491         EditBonePoint *ebp;
492         float vec[3];
493         short found = 0;
494         
495         if (eb_tail) {
496                 copy_v3_v3(vec, ebo->tail);
497         }
498         else {
499                 copy_v3_v3(vec, ebo->head);
500         }
501         
502         for (ebp = points->first; ebp; ebp = ebp->next) {
503                 if (equals_v3v3(ebp->vec, vec)) {
504                         if (eb_tail) {
505                                 if ((ebp->head_owner) && (ebp->head_owner->parent == ebo)) {
506                                         /* so this bone's tail owner is this bone */
507                                         ebp->tail_owner = ebo;
508                                         found = 1;
509                                         break;
510                                 }
511                         }
512                         else {
513                                 if ((ebp->tail_owner) && (ebo->parent == ebp->tail_owner)) {
514                                         /* so this bone's head owner is this bone */
515                                         ebp->head_owner = ebo;
516                                         found = 1;
517                                         break;
518                                 }
519                         }
520                 }
521         }
522         
523         /* allocate a new point if no existing point was related */
524         if (found == 0) {
525                 ebp = MEM_callocN(sizeof(EditBonePoint), "EditBonePoint");
526                 
527                 if (eb_tail) {
528                         copy_v3_v3(ebp->vec, ebo->tail);
529                         ebp->tail_owner = ebo;
530                 }
531                 else {
532                         copy_v3_v3(ebp->vec, ebo->head);
533                         ebp->head_owner = ebo;
534                 }
535                 
536                 BLI_addtail(points, ebp);
537         }
538 }
539
540 /* bone adding between selected joints */
541 static int armature_fill_bones_exec(bContext *C, wmOperator *op)
542 {
543         Object *obedit = CTX_data_edit_object(C);
544         bArmature *arm = (obedit) ? obedit->data : NULL;
545         Scene *scene = CTX_data_scene(C);
546         View3D *v3d = CTX_wm_view3d(C);
547         ListBase points = {NULL, NULL};
548         int count;
549
550         /* sanity checks */
551         if (ELEM(NULL, obedit, arm))
552                 return OPERATOR_CANCELLED;
553
554         /* loop over all bones, and only consider if visible */
555         CTX_DATA_BEGIN(C, EditBone *, ebone, visible_bones)
556         {
557                 if (!(ebone->flag & BONE_CONNECTED) && (ebone->flag & BONE_ROOTSEL))
558                         fill_add_joint(ebone, 0, &points);
559                 if (ebone->flag & BONE_TIPSEL) 
560                         fill_add_joint(ebone, 1, &points);
561         }
562         CTX_DATA_END;
563         
564         /* the number of joints determines how we fill:
565          *  1) between joint and cursor (joint=head, cursor=tail)
566          *  2) between the two joints (order is dependent on active-bone/hierarchy)
567          *  3+) error (a smarter method involving finding chains needs to be worked out
568          */
569         count = BLI_countlist(&points);
570         
571         if (count == 0) {
572                 BKE_report(op->reports, RPT_ERROR, "No joints selected");
573                 return OPERATOR_CANCELLED;
574         }
575         else if (count == 1) {
576                 EditBonePoint *ebp;
577                 float curs[3];
578                 
579                 /* Get Points - selected joint */
580                 ebp = (EditBonePoint *)points.first;
581                 
582                 /* Get points - cursor (tail) */
583                 invert_m4_m4(obedit->imat, obedit->obmat);
584                 mul_v3_m4v3(curs, obedit->imat, ED_view3d_cursor3d_get(scene, v3d));
585                 
586                 /* Create a bone */
587                 /* newbone = */ add_points_bone(obedit, ebp->vec, curs);
588         }
589         else if (count == 2) {
590                 EditBonePoint *ebp, *ebp2;
591                 float head[3], tail[3];
592                 short headtail = 0;
593                 
594                 /* check that the points don't belong to the same bone */
595                 ebp = (EditBonePoint *)points.first;
596                 ebp2 = ebp->next;
597                 
598                 if ((ebp->head_owner == ebp2->tail_owner) && (ebp->head_owner != NULL)) {
599                         BKE_report(op->reports, RPT_ERROR, "Same bone selected...");
600                         BLI_freelistN(&points);
601                         return OPERATOR_CANCELLED;
602                 }
603                 if ((ebp->tail_owner == ebp2->head_owner) && (ebp->tail_owner != NULL)) {
604                         BKE_report(op->reports, RPT_ERROR, "Same bone selected...");
605                         BLI_freelistN(&points);
606                         return OPERATOR_CANCELLED;
607                 }
608                 
609                 /* find which one should be the 'head' */
610                 if ((ebp->head_owner && ebp2->head_owner) || (ebp->tail_owner && ebp2->tail_owner)) {
611                         /* rule: whichever one is closer to 3d-cursor */
612                         float curs[3];
613                         float vecA[3], vecB[3];
614                         float distA, distB;
615                         
616                         /* get cursor location */
617                         invert_m4_m4(obedit->imat, obedit->obmat);
618                         mul_v3_m4v3(curs, obedit->imat, ED_view3d_cursor3d_get(scene, v3d));
619                         
620                         /* get distances */
621                         sub_v3_v3v3(vecA, ebp->vec, curs);
622                         sub_v3_v3v3(vecB, ebp2->vec, curs);
623                         distA = len_v3(vecA);
624                         distB = len_v3(vecB);
625                         
626                         /* compare distances - closer one therefore acts as direction for bone to go */
627                         headtail = (distA < distB) ? 2 : 1;
628                 }
629                 else if (ebp->head_owner) {
630                         headtail = 1;
631                 }
632                 else if (ebp2->head_owner) {
633                         headtail = 2;
634                 }
635                 
636                 /* assign head/tail combinations */
637                 if (headtail == 2) {
638                         copy_v3_v3(head, ebp->vec);
639                         copy_v3_v3(tail, ebp2->vec);
640                 }
641                 else if (headtail == 1) {
642                         copy_v3_v3(head, ebp2->vec);
643                         copy_v3_v3(tail, ebp->vec);
644                 }
645                 
646                 /* add new bone and parent it to the appropriate end */
647                 if (headtail) {
648                         EditBone *newbone = add_points_bone(obedit, head, tail);
649                         
650                         /* do parenting (will need to set connected flag too) */
651                         if (headtail == 2) {
652                                 /* ebp tail or head - tail gets priority */
653                                 if (ebp->tail_owner)
654                                         newbone->parent = ebp->tail_owner;
655                                 else
656                                         newbone->parent = ebp->head_owner;
657                         }
658                         else {
659                                 /* ebp2 tail or head - tail gets priority */
660                                 if (ebp2->tail_owner)
661                                         newbone->parent = ebp2->tail_owner;
662                                 else
663                                         newbone->parent = ebp2->head_owner;
664                         }
665
666                         /* don't set for bone connecting two head points of bones */
667                         if (ebp->tail_owner || ebp2->tail_owner) {
668                                 newbone->flag |= BONE_CONNECTED;
669                         }
670                 }
671         }
672         else {
673                 /* FIXME.. figure out a method for multiple bones */
674                 BKE_reportf(op->reports, RPT_ERROR, "Too many points selected: %d", count);
675                 BLI_freelistN(&points);
676                 return OPERATOR_CANCELLED;
677         }
678         
679         /* updates */
680         WM_event_add_notifier(C, NC_OBJECT | ND_POSE, obedit);
681         
682         /* free points */
683         BLI_freelistN(&points);
684         
685         return OPERATOR_FINISHED;
686 }
687
688 void ARMATURE_OT_fill(wmOperatorType *ot)
689 {
690         /* identifiers */
691         ot->name = "Fill Between Joints";
692         ot->idname = "ARMATURE_OT_fill";
693         ot->description = "Add bone between selected joint(s) and/or 3D-Cursor";
694         
695         /* callbacks */
696         ot->exec = armature_fill_bones_exec;
697         ot->poll = ED_operator_editarmature;
698         
699         /* flags */
700         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
701 }
702
703 /* --------------------- */
704
705 /* this function merges between two bones, removes them and those in-between, 
706  * and adjusts the parent relationships for those in-between
707  */
708 static void bones_merge(Object *obedit, EditBone *start, EditBone *end, EditBone *endchild, ListBase *chains)
709 {
710         bArmature *arm = obedit->data;
711         EditBone *ebo, *ebone, *newbone;
712         LinkData *chain;
713         float head[3], tail[3];
714         
715         /* check if same bone */
716         if (start == end) {
717                 if (G.debug & G_DEBUG) {
718                         printf("Error: same bone!\n");
719                         printf("\tstart = %s, end = %s\n", start->name, end->name);
720                 }
721         }
722         
723         /* step 1: add a new bone
724          *      - head = head/tail of start (default head)
725          *      - tail = head/tail of end (default tail)
726          *      - parent = parent of start
727          */
728         if ((start->flag & BONE_TIPSEL) && (start->flag & BONE_SELECTED) == 0) {
729                 copy_v3_v3(head, start->tail);
730         }
731         else {
732                 copy_v3_v3(head, start->head);
733         }
734         if ((end->flag & BONE_ROOTSEL) && (end->flag & BONE_SELECTED) == 0) {
735                 copy_v3_v3(tail, end->head);
736         }
737         else {
738                 copy_v3_v3(tail, end->tail);
739         }
740         newbone = add_points_bone(obedit, head, tail);
741         newbone->parent = start->parent;
742
743         /* TODO, copy more things to the new bone */
744         newbone->flag = start->flag & (BONE_HINGE | BONE_NO_DEFORM | BONE_NO_SCALE |
745                                        BONE_NO_CYCLICOFFSET | BONE_NO_LOCAL_LOCATION | BONE_DONE);
746         
747         /* step 2a: reparent any side chains which may be parented to any bone in the chain of bones to merge 
748          *      - potentially several tips for side chains leading to some tree exist...
749          */
750         for (chain = chains->first; chain; chain = chain->next) {
751                 /* traverse down chain until we hit the bottom or if we run into the tip of the chain of bones we're 
752                  * merging (need to stop in this case to avoid corrupting this chain too!) 
753                  */
754                 for (ebone = chain->data; (ebone) && (ebone != end); ebone = ebone->parent) {
755                         short found = 0;
756                         
757                         /* check if this bone is parented to one in the merging chain
758                          * ! WATCHIT: must only go check until end of checking chain
759                          */
760                         for (ebo = end; (ebo) && (ebo != start->parent); ebo = ebo->parent) {
761                                 /* side-chain found? --> remap parent to new bone, then we're done with this chain :) */
762                                 if (ebone->parent == ebo) {
763                                         ebone->parent = newbone;
764                                         found = 1;
765                                         break;
766                                 }
767                         }
768                         
769                         /* carry on to the next tip now  */
770                         if (found) 
771                                 break;
772                 }
773         }
774         
775         /* step 2b: parent child of end to newbone (child from this chain) */
776         if (endchild)
777                 endchild->parent = newbone;
778         
779         /* step 3: delete all bones between and including start and end */
780         for (ebo = end; ebo; ebo = ebone) {
781                 ebone = (ebo == start) ? (NULL) : (ebo->parent);
782                 bone_free(arm, ebo);
783         }
784         
785         newbone->flag |= (BONE_ROOTSEL | BONE_TIPSEL | BONE_SELECTED);
786         ED_armature_sync_selection(arm->edbo);
787 }
788
789
790 static int armature_merge_exec(bContext *C, wmOperator *op)
791 {
792         Object *obedit = CTX_data_edit_object(C);
793         bArmature *arm = (obedit) ? obedit->data : NULL;
794         short type = RNA_enum_get(op->ptr, "type");
795         
796         /* sanity checks */
797         if (ELEM(NULL, obedit, arm))
798                 return OPERATOR_CANCELLED;
799         
800         /* for now, there's only really one type of merging that's performed... */
801         if (type == 1) {
802                 /* go down chains, merging bones */
803                 ListBase chains = {NULL, NULL};
804                 LinkData *chain, *nchain;
805                 EditBone *ebo;
806                 
807                 armature_tag_select_mirrored(arm);
808                 
809                 /* get chains (ends on chains) */
810                 chains_find_tips(arm->edbo, &chains);
811                 if (BLI_listbase_is_empty(&chains)) return OPERATOR_CANCELLED;
812                 
813                 /* each 'chain' is the last bone in the chain (with no children) */
814                 for (chain = chains.first; chain; chain = nchain) {
815                         EditBone *bstart = NULL, *bend = NULL;
816                         EditBone *bchild = NULL, *child = NULL;
817                         
818                         /* temporarily remove chain from list of chains */
819                         nchain = chain->next;
820                         BLI_remlink(&chains, chain);
821                         
822                         /* only consider bones that are visible and selected */
823                         for (ebo = chain->data; ebo; child = ebo, ebo = ebo->parent) {
824                                 /* check if visible + selected */
825                                 if (EBONE_VISIBLE(arm, ebo) &&
826                                     ((ebo->flag & BONE_CONNECTED) || (ebo->parent == NULL)) &&
827                                     (ebo->flag & BONE_SELECTED) )
828                                 {
829                                         /* set either end or start (end gets priority, unless it is already set) */
830                                         if (bend == NULL) {
831                                                 bend = ebo;
832                                                 bchild = child;
833                                         }
834                                         else 
835                                                 bstart = ebo;
836                                 }
837                                 else {
838                                         /* chain is broken... merge any continous segments then clear */
839                                         if (bstart && bend)
840                                                 bones_merge(obedit, bstart, bend, bchild, &chains);
841                                         
842                                         bstart = NULL;
843                                         bend = NULL;
844                                         bchild = NULL;
845                                 }
846                         }
847                         
848                         /* merge from bstart to bend if something not merged */
849                         if (bstart && bend)
850                                 bones_merge(obedit, bstart, bend, bchild, &chains);
851                         
852                         /* put back link */
853                         BLI_insertlinkbefore(&chains, nchain, chain);
854                 }
855                 
856                 armature_tag_unselect(arm);
857                 
858                 BLI_freelistN(&chains);
859         }
860         
861         /* updates */
862         ED_armature_sync_selection(arm->edbo);
863         WM_event_add_notifier(C, NC_OBJECT | ND_POSE, obedit);
864         
865         return OPERATOR_FINISHED;
866 }
867
868 void ARMATURE_OT_merge(wmOperatorType *ot)
869 {
870         static EnumPropertyItem merge_types[] = {
871                 {1, "WITHIN_CHAIN", 0, "Within Chains", ""},
872                 {0, NULL, 0, NULL, NULL}
873         };
874
875         /* identifiers */
876         ot->name = "Merge Bones";
877         ot->idname = "ARMATURE_OT_merge";
878         ot->description = "Merge continuous chains of selected bones";
879         
880         /* callbacks */
881         ot->invoke = WM_menu_invoke;
882         ot->exec = armature_merge_exec;
883         ot->poll = ED_operator_editarmature;
884         
885         /* flags */
886         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
887         
888         /* properties */
889         ot->prop = RNA_def_enum(ot->srna, "type", merge_types, 0, "Type", "");
890 }
891
892 /* --------------------- */
893
894 /* Switch Direction operator:
895  * Currently, this does not use context loops, as context loops do not make it
896  * easy to retrieve any hierarchical/chain relationships which are necessary for
897  * this to be done easily.
898  */
899  
900 /* helper to clear BONE_TRANSFORM flags */
901 static void armature_clear_swap_done_flags(bArmature *arm)
902 {
903         EditBone *ebone;
904         
905         for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
906                 ebone->flag &= ~BONE_TRANSFORM;
907         }
908 }
909
910 static int armature_switch_direction_exec(bContext *C, wmOperator *UNUSED(op)) 
911 {
912         Object *ob = CTX_data_edit_object(C);
913         bArmature *arm = (bArmature *)ob->data;
914         ListBase chains = {NULL, NULL};
915         LinkData *chain;
916         
917         /* get chains of bones (ends on chains) */
918         chains_find_tips(arm->edbo, &chains);
919         if (BLI_listbase_is_empty(&chains)) return OPERATOR_CANCELLED;
920         
921         /* ensure that mirror bones will also be operated on */
922         armature_tag_select_mirrored(arm);
923         
924         /* clear BONE_TRANSFORM flags 
925          * - used to prevent duplicate/canceling operations from occurring [#34123]
926          * - BONE_DONE cannot be used here as that's already used for mirroring
927          */
928         armature_clear_swap_done_flags(arm);
929         
930         /* loop over chains, only considering selected and visible bones */
931         for (chain = chains.first; chain; chain = chain->next) {
932                 EditBone *ebo, *child = NULL, *parent = NULL;
933                 
934                 /* loop over bones in chain */
935                 for (ebo = chain->data; ebo; ebo = parent) {
936                         /* parent is this bone's original parent
937                          *      - we store this, as the next bone that is checked is this one
938                          *        but the value of ebo->parent may change here...
939                          */
940                         parent = ebo->parent;
941                         
942                         /* skip bone if already handled... [#34123] */
943                         if ((ebo->flag & BONE_TRANSFORM) == 0) {
944                                 /* only if selected and editable */
945                                 if (EBONE_VISIBLE(arm, ebo) && EBONE_EDITABLE(ebo)) {
946                                         /* swap head and tail coordinates */
947                                         SWAP(float, ebo->head[0], ebo->tail[0]);
948                                         SWAP(float, ebo->head[1], ebo->tail[1]);
949                                         SWAP(float, ebo->head[2], ebo->tail[2]);
950                                         
951                                         /* do parent swapping:
952                                          *      - use 'child' as new parent
953                                          *      - connected flag is only set if points are coincidental
954                                          */
955                                         ebo->parent = child;
956                                         if ((child) && equals_v3v3(ebo->head, child->tail))
957                                                 ebo->flag |= BONE_CONNECTED;
958                                         else
959                                                 ebo->flag &= ~BONE_CONNECTED;
960                                         
961                                         /* get next bones 
962                                          *      - child will become the new parent of next bone
963                                          */
964                                         child = ebo;
965                                 }
966                                 else {
967                                         /* not swapping this bone, however, if its 'parent' got swapped, unparent us from it 
968                                          * as it will be facing in opposite direction
969                                          */
970                                         if ((parent) && (EBONE_VISIBLE(arm, parent) && EBONE_EDITABLE(parent))) {
971                                                 ebo->parent = NULL;
972                                                 ebo->flag &= ~BONE_CONNECTED;
973                                         }
974                                         
975                                         /* get next bones
976                                          *      - child will become new parent of next bone (not swapping occurred, 
977                                          *        so set to NULL to prevent infinite-loop)
978                                          */
979                                         child = NULL;
980                                 }
981                                 
982                                 /* tag as done (to prevent double-swaps) */
983                                 ebo->flag |= BONE_TRANSFORM;
984                         }
985                 }
986         }
987         
988         /* free chains */
989         BLI_freelistN(&chains);
990         
991         /* clear temp flags */
992         armature_clear_swap_done_flags(arm);
993         armature_tag_unselect(arm);
994         
995         /* note, notifier might evolve */
996         WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
997         
998         return OPERATOR_FINISHED;
999 }
1000
1001 void ARMATURE_OT_switch_direction(wmOperatorType *ot)
1002 {
1003         /* identifiers */
1004         ot->name = "Switch Direction";
1005         ot->idname = "ARMATURE_OT_switch_direction";
1006         ot->description = "Change the direction that a chain of bones points in (head <-> tail swap)";
1007         
1008         /* api callbacks */
1009         ot->exec = armature_switch_direction_exec;
1010         ot->poll = ED_operator_editarmature;
1011         
1012         /* flags */
1013         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1014 }
1015
1016 /* ********************************* Align ******************************* */
1017
1018 /* helper to fix a ebone position if its parent has moved due to alignment*/
1019 static void fix_connected_bone(EditBone *ebone)
1020 {
1021         float diff[3];
1022         
1023         if (!(ebone->parent) || !(ebone->flag & BONE_CONNECTED) || equals_v3v3(ebone->parent->tail, ebone->head))
1024                 return;
1025         
1026         /* if the parent has moved we translate child's head and tail accordingly */
1027         sub_v3_v3v3(diff, ebone->parent->tail, ebone->head);
1028         add_v3_v3(ebone->head, diff);
1029         add_v3_v3(ebone->tail, diff);
1030 }
1031
1032 /* helper to recursively find chains of connected bones starting at ebone and fix their position */
1033 static void fix_editbone_connected_children(ListBase *edbo, EditBone *ebone)
1034 {
1035         EditBone *selbone;
1036         
1037         for (selbone = edbo->first; selbone; selbone = selbone->next) {
1038                 if ((selbone->parent) && (selbone->parent == ebone) && (selbone->flag & BONE_CONNECTED)) {
1039                         fix_connected_bone(selbone);
1040                         fix_editbone_connected_children(edbo, selbone);
1041                 }
1042         }
1043 }                       
1044
1045 static void bone_align_to_bone(ListBase *edbo, EditBone *selbone, EditBone *actbone)
1046 {
1047         float selboneaxis[3], actboneaxis[3], length;
1048
1049         sub_v3_v3v3(actboneaxis, actbone->tail, actbone->head);
1050         normalize_v3(actboneaxis);
1051
1052         sub_v3_v3v3(selboneaxis, selbone->tail, selbone->head);
1053         length =  len_v3(selboneaxis);
1054
1055         mul_v3_fl(actboneaxis, length);
1056         add_v3_v3v3(selbone->tail, selbone->head, actboneaxis);
1057         selbone->roll = actbone->roll;
1058         
1059         /* if the bone being aligned has connected descendants they must be moved
1060          * according to their parent new position, otherwise they would be left
1061          * in an inconsistent state: connected but away from the parent*/
1062         fix_editbone_connected_children(edbo, selbone);
1063 }
1064
1065 static int armature_align_bones_exec(bContext *C, wmOperator *op) 
1066 {
1067         Object *ob = CTX_data_edit_object(C);
1068         bArmature *arm = (bArmature *)ob->data;
1069         EditBone *actbone = CTX_data_active_bone(C);
1070         EditBone *actmirb = NULL;
1071         int num_selected_bones;
1072         
1073         /* there must be an active bone */
1074         if (actbone == NULL) {
1075                 BKE_report(op->reports, RPT_ERROR, "Operation requires an active bone");
1076                 return OPERATOR_CANCELLED;
1077         }
1078         else if (arm->flag & ARM_MIRROR_EDIT) {
1079                 /* For X-Axis Mirror Editing option, we may need a mirror copy of actbone
1080                  * - if there's a mirrored copy of selbone, try to find a mirrored copy of actbone 
1081                  *   (i.e.  selbone="child.L" and actbone="parent.L", find "child.R" and "parent.R").
1082                  *   This is useful for arm-chains, for example parenting lower arm to upper arm
1083                  * - if there's no mirrored copy of actbone (i.e. actbone = "parent.C" or "parent")
1084                  *   then just use actbone. Useful when doing upper arm to spine.
1085                  */
1086                 actmirb = ED_armature_bone_get_mirrored(arm->edbo, actbone);
1087                 if (actmirb == NULL) 
1088                         actmirb = actbone;
1089         }
1090         
1091         /* if there is only 1 selected bone, we assume that that is the active bone, 
1092          * since a user will need to have clicked on a bone (thus selecting it) to make it active
1093          */
1094         num_selected_bones = CTX_DATA_COUNT(C, selected_editable_bones);
1095         if (num_selected_bones <= 1) {
1096                 /* When only the active bone is selected, and it has a parent,
1097                  * align it to the parent, as that is the only possible outcome. 
1098                  */
1099                 if (actbone->parent) {
1100                         bone_align_to_bone(arm->edbo, actbone, actbone->parent);
1101                         
1102                         if ((arm->flag & ARM_MIRROR_EDIT) && (actmirb->parent))
1103                                 bone_align_to_bone(arm->edbo, actmirb, actmirb->parent);
1104
1105                         BKE_reportf(op->reports, RPT_INFO, "Aligned bone '%s' to parent", actbone->name);
1106                 }
1107         }
1108         else {
1109                 /* Align 'selected' bones to the active one
1110                  * - the context iterator contains both selected bones and their mirrored copies,
1111                  *   so we assume that unselected bones are mirrored copies of some selected bone
1112                  * - since the active one (and/or its mirror) will also be selected, we also need 
1113                  *   to check that we are not trying to operate on them, since such an operation
1114                  *   would cause errors
1115                  */
1116                 
1117                 /* align selected bones to the active one */
1118                 CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones)
1119                 {
1120                         if (ELEM(ebone, actbone, actmirb) == 0) {
1121                                 if (ebone->flag & BONE_SELECTED)
1122                                         bone_align_to_bone(arm->edbo, ebone, actbone);
1123                                 else
1124                                         bone_align_to_bone(arm->edbo, ebone, actmirb);
1125                         }
1126                 }
1127                 CTX_DATA_END;
1128
1129                 BKE_reportf(op->reports, RPT_INFO, "%d bones aligned to bone '%s'", num_selected_bones, actbone->name);
1130         }
1131
1132         /* note, notifier might evolve */
1133         WM_event_add_notifier(C, NC_OBJECT | ND_TRANSFORM, ob);
1134         
1135         return OPERATOR_FINISHED;
1136 }
1137
1138 void ARMATURE_OT_align(wmOperatorType *ot)
1139 {
1140         /* identifiers */
1141         ot->name = "Align Bones";
1142         ot->idname = "ARMATURE_OT_align";
1143         ot->description = "Align selected bones to the active bone (or to their parent)";
1144         
1145         /* api callbacks */
1146         ot->exec = armature_align_bones_exec;
1147         ot->poll = ED_operator_editarmature;
1148         
1149         /* flags */
1150         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1151 }
1152
1153 /* ********************************* Split ******************************* */
1154
1155 static int armature_split_exec(bContext *C, wmOperator *UNUSED(op))
1156 {
1157         Object *ob = CTX_data_edit_object(C);
1158         bArmature *arm = (bArmature *)ob->data;
1159         EditBone *bone;
1160
1161         for (bone = arm->edbo->first; bone; bone = bone->next) {
1162                 if (bone->parent && (bone->flag & BONE_SELECTED) != (bone->parent->flag & BONE_SELECTED)) {
1163                         bone->parent = NULL;
1164                         bone->flag &= ~BONE_CONNECTED;
1165                 }
1166         }
1167         for (bone = arm->edbo->first; bone; bone = bone->next) {
1168                 ED_armature_ebone_select_set(bone, (bone->flag & BONE_SELECTED) != 0);
1169         }
1170
1171         WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
1172
1173         return OPERATOR_FINISHED;
1174 }
1175
1176 void ARMATURE_OT_split(wmOperatorType *ot)
1177 {
1178         /* identifiers */
1179         ot->name = "Split";
1180         ot->idname = "ARMATURE_OT_split";
1181         ot->description = "Split off selected bones from connected unselected bones";
1182
1183         /* api callbacks */
1184         ot->exec = armature_split_exec;
1185         ot->poll = ED_operator_editarmature;
1186
1187         /* flags */
1188         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1189 }
1190
1191 /* ********************************* Delete ******************************* */
1192
1193 /* previously delete_armature */
1194 /* only editmode! */
1195 static int armature_delete_selected_exec(bContext *C, wmOperator *UNUSED(op))
1196 {
1197         bArmature *arm;
1198         EditBone *curBone, *ebone_next;
1199         bConstraint *con;
1200         Object *obedit = CTX_data_edit_object(C); // XXX get from context
1201         bool changed = false;
1202         arm = obedit->data;
1203
1204         /* cancel if nothing selected */
1205         if (CTX_DATA_COUNT(C, selected_bones) == 0)
1206                 return OPERATOR_CANCELLED;
1207         
1208         armature_select_mirrored(arm);
1209         
1210         /*  First erase any associated pose channel */
1211         if (obedit->pose) {
1212                 bPoseChannel *pchan, *pchan_next;
1213                 for (pchan = obedit->pose->chanbase.first; pchan; pchan = pchan_next) {
1214                         pchan_next = pchan->next;
1215                         curBone = ED_armature_bone_find_name(arm->edbo, pchan->name);
1216                         
1217                         if (curBone && (curBone->flag & BONE_SELECTED) && (arm->layer & curBone->layer)) {
1218                                 BKE_pose_channel_free(pchan);
1219                                 BKE_pose_channels_hash_free(obedit->pose);
1220                                 BLI_freelinkN(&obedit->pose->chanbase, pchan);
1221                         }
1222                         else {
1223                                 for (con = pchan->constraints.first; con; con = con->next) {
1224                                         bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
1225                                         ListBase targets = {NULL, NULL};
1226                                         bConstraintTarget *ct;
1227                                         
1228                                         if (cti && cti->get_constraint_targets) {
1229                                                 cti->get_constraint_targets(con, &targets);
1230                                                 
1231                                                 for (ct = targets.first; ct; ct = ct->next) {
1232                                                         if (ct->tar == obedit) {
1233                                                                 if (ct->subtarget[0]) {
1234                                                                         curBone = ED_armature_bone_find_name(arm->edbo, ct->subtarget);
1235                                                                         if (curBone && (curBone->flag & BONE_SELECTED) && (arm->layer & curBone->layer)) {
1236                                                                                 con->flag |= CONSTRAINT_DISABLE;
1237                                                                                 ct->subtarget[0] = 0;
1238                                                                         }
1239                                                                 }
1240                                                         }
1241                                                 }
1242                                                 
1243                                                 if (cti->flush_constraint_targets)
1244                                                         cti->flush_constraint_targets(con, &targets, 0);
1245                                         }
1246                                 }
1247                         }
1248                 }
1249         }
1250         
1251         
1252         for (curBone = arm->edbo->first; curBone; curBone = ebone_next) {
1253                 ebone_next = curBone->next;
1254                 if (arm->layer & curBone->layer) {
1255                         if (curBone->flag & BONE_SELECTED) {
1256                                 if (curBone == arm->act_edbone) arm->act_edbone = NULL;
1257                                 ED_armature_edit_bone_remove(arm, curBone);
1258                                 changed = true;
1259                         }
1260                 }
1261         }
1262         
1263         if (!changed)
1264                 return OPERATOR_CANCELLED;
1265         
1266         ED_armature_sync_selection(arm->edbo);
1267
1268         WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
1269
1270         return OPERATOR_FINISHED;
1271 }
1272
1273 void ARMATURE_OT_delete(wmOperatorType *ot)
1274 {
1275         /* identifiers */
1276         ot->name = "Delete Selected Bone(s)";
1277         ot->idname = "ARMATURE_OT_delete";
1278         ot->description = "Remove selected bones from the armature";
1279         
1280         /* api callbacks */
1281         ot->invoke = WM_operator_confirm;
1282         ot->exec = armature_delete_selected_exec;
1283         ot->poll = ED_operator_editarmature;
1284         
1285         /* flags */
1286         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1287 }
1288
1289 /* ********************************* Show/Hide ******************************* */
1290
1291 static int armature_hide_exec(bContext *C, wmOperator *op)
1292 {
1293         Object *obedit = CTX_data_edit_object(C);
1294         bArmature *arm = obedit->data;
1295         EditBone *ebone;
1296         const int invert = RNA_boolean_get(op->ptr, "unselected") ? BONE_SELECTED : 0;
1297
1298         /* cancel if nothing selected */
1299         if (CTX_DATA_COUNT(C, selected_bones) == 0)
1300                 return OPERATOR_CANCELLED;
1301
1302         for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
1303                 if (EBONE_VISIBLE(arm, ebone)) {
1304                         if ((ebone->flag & BONE_SELECTED) != invert) {
1305                                 ebone->flag &= ~(BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL);
1306                                 ebone->flag |= BONE_HIDDEN_A;
1307                         }
1308                 }
1309         }
1310         ED_armature_validate_active(arm);
1311         ED_armature_sync_selection(arm->edbo);
1312
1313         WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
1314
1315         return OPERATOR_FINISHED;
1316 }
1317
1318 void ARMATURE_OT_hide(wmOperatorType *ot)
1319 {
1320         /* identifiers */
1321         ot->name = "Hide Selected Bones";
1322         ot->idname = "ARMATURE_OT_hide";
1323         ot->description = "Tag selected bones to not be visible in Edit Mode";
1324         
1325         /* api callbacks */
1326         ot->exec = armature_hide_exec;
1327         ot->poll = ED_operator_editarmature;
1328         
1329         /* flags */
1330         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1331
1332         /* props */
1333         RNA_def_boolean(ot->srna, "unselected", 0, "Unselected", "Hide unselected rather than selected");
1334 }
1335
1336 static int armature_reveal_exec(bContext *C, wmOperator *UNUSED(op))
1337 {
1338         Object *obedit = CTX_data_edit_object(C);
1339         bArmature *arm = obedit->data;
1340         EditBone *ebone;
1341         
1342         for (ebone = arm->edbo->first; ebone; ebone = ebone->next) {
1343                 if (arm->layer & ebone->layer) {
1344                         if (ebone->flag & BONE_HIDDEN_A) {
1345                                 ebone->flag |= (BONE_TIPSEL | BONE_SELECTED | BONE_ROOTSEL);
1346                                 ebone->flag &= ~BONE_HIDDEN_A;
1347                         }
1348                 }
1349         }
1350         ED_armature_validate_active(arm);
1351         ED_armature_sync_selection(arm->edbo);
1352
1353         WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, obedit);
1354
1355         return OPERATOR_FINISHED;
1356 }
1357
1358 void ARMATURE_OT_reveal(wmOperatorType *ot)
1359 {
1360         /* identifiers */
1361         ot->name = "Reveal Bones";
1362         ot->idname = "ARMATURE_OT_reveal";
1363         ot->description = "Unhide all bones that have been tagged to be hidden in Edit Mode";
1364         
1365         /* api callbacks */
1366         ot->exec = armature_reveal_exec;
1367         ot->poll = ED_operator_editarmature;
1368         
1369         /* flags */
1370         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
1371
1372 }