code cleanup: use const events for modal and invoke operators.
[blender.git] / source / blender / editors / armature / armature_relations.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  * Operators for relations between bones and for transferring bones between armature objects
26  */
27
28 /** \file blender/editors/armature/armature_relations.c
29  *  \ingroup edarmature
30  */
31
32 #include "DNA_armature_types.h"
33 #include "DNA_constraint_types.h"
34 #include "DNA_object_types.h"
35 #include "DNA_scene_types.h"
36
37 #include "BLI_blenlib.h"
38 #include "BLI_math.h"
39
40 #include "BLF_translation.h"
41
42 #include "BKE_action.h"
43 #include "BKE_armature.h"
44 #include "BKE_constraint.h"
45 #include "BKE_context.h"
46 #include "BKE_depsgraph.h"
47 #include "BKE_global.h"
48 #include "BKE_main.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_object.h"
59 #include "ED_screen.h"
60
61 #include "UI_interface.h"
62 #include "UI_resources.h"
63
64 #include "armature_intern.h"
65
66 /* *************************************** Join *************************************** */
67 /* NOTE: no operator define here as this is exported to the Object-level operator */
68
69 /* Helper function for armature joining - link fixing */
70 static void joined_armature_fix_links(Object *tarArm, Object *srcArm, bPoseChannel *pchan, EditBone *curbone)
71 {
72         Object *ob;
73         bPose *pose;
74         bPoseChannel *pchant;
75         bConstraint *con;
76         
77         /* let's go through all objects in database */
78         for (ob = G.main->object.first; ob; ob = ob->id.next) {
79                 /* do some object-type specific things */
80                 if (ob->type == OB_ARMATURE) {
81                         pose = ob->pose;
82                         for (pchant = pose->chanbase.first; pchant; pchant = pchant->next) {
83                                 for (con = pchant->constraints.first; con; con = con->next) {
84                                         bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
85                                         ListBase targets = {NULL, NULL};
86                                         bConstraintTarget *ct;
87                                         
88                                         /* constraint targets */
89                                         if (cti && cti->get_constraint_targets) {
90                                                 cti->get_constraint_targets(con, &targets);
91                                                 
92                                                 for (ct = targets.first; ct; ct = ct->next) {
93                                                         if (ct->tar == srcArm) {
94                                                                 if (ct->subtarget[0] == '\0') {
95                                                                         ct->tar = tarArm;
96                                                                 }
97                                                                 else if (strcmp(ct->subtarget, pchan->name) == 0) {
98                                                                         ct->tar = tarArm;
99                                                                         BLI_strncpy(ct->subtarget, curbone->name, sizeof(ct->subtarget));
100                                                                 }
101                                                         }
102                                                 }
103                                                 
104                                                 if (cti->flush_constraint_targets)
105                                                         cti->flush_constraint_targets(con, &targets, 0);
106                                         }
107                                         
108                                         /* action constraint? */
109                                         if (con->type == CONSTRAINT_TYPE_ACTION) {
110                                                 bActionConstraint *data = con->data; // XXX old animation system
111                                                 bAction *act;
112                                                 bActionChannel *achan;
113                                                 
114                                                 if (data->act) {
115                                                         act = data->act;
116                                                         
117                                                         for (achan = act->chanbase.first; achan; achan = achan->next) {
118                                                                 if (strcmp(achan->name, pchan->name) == 0)
119                                                                         BLI_strncpy(achan->name, curbone->name, sizeof(achan->name));
120                                                         }
121                                                 }
122                                         }
123                                         
124                                 }
125                         }
126                 }
127                         
128                 /* fix object-level constraints */
129                 if (ob != srcArm) {
130                         for (con = ob->constraints.first; con; con = con->next) {
131                                 bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
132                                 ListBase targets = {NULL, NULL};
133                                 bConstraintTarget *ct;
134                                 
135                                 /* constraint targets */
136                                 if (cti && cti->get_constraint_targets) {
137                                         cti->get_constraint_targets(con, &targets);
138                                         
139                                         for (ct = targets.first; ct; ct = ct->next) {
140                                                 if (ct->tar == srcArm) {
141                                                         if (ct->subtarget[0] == '\0') {
142                                                                 ct->tar = tarArm;
143                                                         }
144                                                         else if (strcmp(ct->subtarget, pchan->name) == 0) {
145                                                                 ct->tar = tarArm;
146                                                                 BLI_strncpy(ct->subtarget, curbone->name, sizeof(ct->subtarget));
147                                                         }
148                                                 }
149                                         }
150                                         
151                                         if (cti->flush_constraint_targets)
152                                                 cti->flush_constraint_targets(con, &targets, 0);
153                                 }
154                         }
155                 }
156                 
157                 /* See if an object is parented to this armature */
158                 if (ob->parent && (ob->parent == srcArm)) {
159                         /* Is object parented to a bone of this src armature? */
160                         if (ob->partype == PARBONE) {
161                                 /* bone name in object */
162                                 if (!strcmp(ob->parsubstr, pchan->name))
163                                         BLI_strncpy(ob->parsubstr, curbone->name, sizeof(ob->parsubstr));
164                         }
165                         
166                         /* make tar armature be new parent */
167                         ob->parent = tarArm;
168                 }
169         }
170 }
171
172 /* join armature exec is exported for use in object->join objects operator... */
173 int join_armature_exec(bContext *C, wmOperator *UNUSED(op))
174 {
175         Main *bmain = CTX_data_main(C);
176         Scene *scene = CTX_data_scene(C);
177         Object  *ob = CTX_data_active_object(C);
178         bArmature *arm = (ob) ? ob->data : NULL;
179         bPose *pose, *opose;
180         bPoseChannel *pchan, *pchann;
181         EditBone *curbone;
182         float mat[4][4], oimat[4][4];
183         
184         /*      Ensure we're not in editmode and that the active object is an armature*/
185         if (!ob || ob->type != OB_ARMATURE)
186                 return OPERATOR_CANCELLED;
187         if (!arm || arm->edbo)
188                 return OPERATOR_CANCELLED;
189         
190         /* Get editbones of active armature to add editbones to */
191         ED_armature_to_edit(ob);
192         
193         /* get pose of active object and move it out of posemode */
194         pose = ob->pose;
195         ob->mode &= ~OB_MODE_POSE;
196
197         CTX_DATA_BEGIN(C, Base *, base, selected_editable_bases)
198         {
199                 if ((base->object->type == OB_ARMATURE) && (base->object != ob)) {
200                         bArmature *curarm = base->object->data;
201                         
202                         /* Make a list of editbones in current armature */
203                         ED_armature_to_edit(base->object);
204                         
205                         /* Get Pose of current armature */
206                         opose = base->object->pose;
207                         base->object->mode &= ~OB_MODE_POSE;
208                         //BASACT->flag &= ~OB_MODE_POSE;
209                         
210                         /* Find the difference matrix */
211                         invert_m4_m4(oimat, ob->obmat);
212                         mult_m4_m4m4(mat, oimat, base->object->obmat);
213                         
214                         /* Copy bones and posechannels from the object to the edit armature */
215                         for (pchan = opose->chanbase.first; pchan; pchan = pchann) {
216                                 pchann = pchan->next;
217                                 curbone = editbone_name_exists(curarm->edbo, pchan->name);
218                                 
219                                 /* Get new name */
220                                 unique_editbone_name(arm->edbo, curbone->name, NULL);
221                                 
222                                 /* Transform the bone */
223                                 {
224                                         float premat[4][4];
225                                         float postmat[4][4];
226                                         float difmat[4][4];
227                                         float imat[4][4];
228                                         float temp[3][3];
229                                         float delta[3];
230                                         
231                                         /* Get the premat */
232                                         sub_v3_v3v3(delta, curbone->tail, curbone->head);
233                                         vec_roll_to_mat3(delta, curbone->roll, temp);
234                                         
235                                         unit_m4(premat); /* Mat4MulMat34 only sets 3x3 part */
236                                         mul_m4_m3m4(premat, temp, mat);
237                                         
238                                         mul_m4_v3(mat, curbone->head);
239                                         mul_m4_v3(mat, curbone->tail);
240                                         
241                                         /* Get the postmat */
242                                         sub_v3_v3v3(delta, curbone->tail, curbone->head);
243                                         vec_roll_to_mat3(delta, curbone->roll, temp);
244                                         copy_m4_m3(postmat, temp);
245                                         
246                                         /* Find the roll */
247                                         invert_m4_m4(imat, premat);
248                                         mult_m4_m4m4(difmat, imat, postmat);
249                                         
250                                         curbone->roll -= (float)atan2(difmat[2][0], difmat[2][2]);
251                                 }
252                                 
253                                 /* Fix Constraints and Other Links to this Bone and Armature */
254                                 joined_armature_fix_links(ob, base->object, pchan, curbone);
255                                 
256                                 /* Rename pchan */
257                                 BLI_strncpy(pchan->name, curbone->name, sizeof(pchan->name));
258                                 
259                                 /* Jump Ship! */
260                                 BLI_remlink(curarm->edbo, curbone);
261                                 BLI_addtail(arm->edbo, curbone);
262                                 
263                                 BLI_remlink(&opose->chanbase, pchan);
264                                 BLI_addtail(&pose->chanbase, pchan);
265                                 BKE_pose_channels_hash_free(opose);
266                                 BKE_pose_channels_hash_free(pose);
267                         }
268                         
269                         ED_base_object_free_and_unlink(bmain, scene, base);
270                 }
271         }
272         CTX_DATA_END;
273         
274         DAG_relations_tag_update(bmain);  /* because we removed object(s) */
275
276         ED_armature_from_edit(ob);
277         ED_armature_edit_free(ob);
278
279         WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
280         
281         return OPERATOR_FINISHED;
282 }
283
284 /* *********************************** Separate *********************************************** */
285
286 /* Helper function for armature separating - link fixing */
287 static void separated_armature_fix_links(Object *origArm, Object *newArm)
288 {
289         Object *ob;
290         bPoseChannel *pchan;
291         bConstraint *con;
292         ListBase *opchans, *npchans;
293         
294         /* get reference to list of bones in original and new armatures  */
295         opchans = &origArm->pose->chanbase;
296         npchans = &newArm->pose->chanbase;
297         
298         /* let's go through all objects in database */
299         for (ob = G.main->object.first; ob; ob = ob->id.next) {
300                 /* do some object-type specific things */
301                 if (ob->type == OB_ARMATURE) {
302                         for (pchan = ob->pose->chanbase.first; pchan; pchan = pchan->next) {
303                                 for (con = pchan->constraints.first; con; con = con->next) {
304                                         bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
305                                         ListBase targets = {NULL, NULL};
306                                         bConstraintTarget *ct;
307                                         
308                                         /* constraint targets */
309                                         if (cti && cti->get_constraint_targets) {
310                                                 cti->get_constraint_targets(con, &targets);
311                                                 
312                                                 for (ct = targets.first; ct; ct = ct->next) {
313                                                         /* any targets which point to original armature are redirected to the new one only if:
314                                                          *      - the target isn't origArm/newArm itself
315                                                          *      - the target is one that can be found in newArm/origArm
316                                                          */
317                                                         if (ct->subtarget[0] != 0) {
318                                                                 if (ct->tar == origArm) {
319                                                                         if (BLI_findstring(npchans, ct->subtarget, offsetof(bPoseChannel, name))) {
320                                                                                 ct->tar = newArm;
321                                                                         }
322                                                                 }
323                                                                 else if (ct->tar == newArm) {
324                                                                         if (BLI_findstring(opchans, ct->subtarget, offsetof(bPoseChannel, name))) {
325                                                                                 ct->tar = origArm;
326                                                                         }
327                                                                 }
328                                                         }
329                                                 }
330
331                                                 if (cti->flush_constraint_targets) {
332                                                         cti->flush_constraint_targets(con, &targets, 0);
333                                                 }
334                                         }
335                                 }
336                         }
337                 }
338                         
339                 /* fix object-level constraints */
340                 if (ob != origArm) {
341                         for (con = ob->constraints.first; con; con = con->next) {
342                                 bConstraintTypeInfo *cti = BKE_constraint_get_typeinfo(con);
343                                 ListBase targets = {NULL, NULL};
344                                 bConstraintTarget *ct;
345                                 
346                                 /* constraint targets */
347                                 if (cti && cti->get_constraint_targets) {
348                                         cti->get_constraint_targets(con, &targets);
349                                         
350                                         for (ct = targets.first; ct; ct = ct->next) {
351                                                 /* any targets which point to original armature are redirected to the new one only if:
352                                                  *      - the target isn't origArm/newArm itself
353                                                  *      - the target is one that can be found in newArm/origArm
354                                                  */
355                                                 if (ct->subtarget[0] != '\0') {
356                                                         if (ct->tar == origArm) {
357                                                                 if (BLI_findstring(npchans, ct->subtarget, offsetof(bPoseChannel, name))) {
358                                                                         ct->tar = newArm;
359                                                                 }
360                                                         }
361                                                         else if (ct->tar == newArm) {
362                                                                 if (BLI_findstring(opchans, ct->subtarget, offsetof(bPoseChannel, name))) {
363                                                                         ct->tar = origArm;
364                                                                 }
365                                                         }
366                                                 }
367                                         }
368                                         
369                                         if (cti->flush_constraint_targets) {
370                                                 cti->flush_constraint_targets(con, &targets, 0);
371                                         }
372                                 }
373                         }
374                 }
375                 
376                 /* See if an object is parented to this armature */
377                 if (ob->parent && (ob->parent == origArm)) {
378                         /* Is object parented to a bone of this src armature? */
379                         if ((ob->partype == PARBONE) && (ob->parsubstr[0] != '\0')) {
380                                 if (BLI_findstring(npchans, ob->parsubstr, offsetof(bPoseChannel, name))) {
381                                         ob->parent = newArm;
382                                 }
383                         }
384                 }
385         }
386 }
387
388 /* Helper function for armature separating - remove certain bones from the given armature 
389  *      sel: remove selected bones from the armature, otherwise the unselected bones are removed
390  *  (ob is not in editmode)
391  */
392 static void separate_armature_bones(Object *ob, short sel) 
393 {
394         bArmature *arm = (bArmature *)ob->data;
395         bPoseChannel *pchan, *pchann;
396         EditBone *curbone;
397         
398         /* make local set of editbones to manipulate here */
399         ED_armature_to_edit(ob);
400         
401         /* go through pose-channels, checking if a bone should be removed */
402         for (pchan = ob->pose->chanbase.first; pchan; pchan = pchann) {
403                 pchann = pchan->next;
404                 curbone = editbone_name_exists(arm->edbo, pchan->name);
405                 
406                 /* check if bone needs to be removed */
407                 if ( (sel && (curbone->flag & BONE_SELECTED)) ||
408                      (!sel && !(curbone->flag & BONE_SELECTED)) )
409                 {
410                         EditBone *ebo;
411                         bPoseChannel *pchn;
412                         
413                         /* clear the bone->parent var of any bone that had this as its parent  */
414                         for (ebo = arm->edbo->first; ebo; ebo = ebo->next) {
415                                 if (ebo->parent == curbone) {
416                                         ebo->parent = NULL;
417                                         ebo->temp = NULL; /* this is needed to prevent random crashes with in ED_armature_from_edit */
418                                         ebo->flag &= ~BONE_CONNECTED;
419                                 }
420                         }
421                         
422                         /* clear the pchan->parent var of any pchan that had this as its parent */
423                         for (pchn = ob->pose->chanbase.first; pchn; pchn = pchn->next) {
424                                 if (pchn->parent == pchan)
425                                         pchn->parent = NULL;
426                         }
427                         
428                         /* free any of the extra-data this pchan might have */
429                         BKE_pose_channel_free(pchan);
430                         BKE_pose_channels_hash_free(ob->pose);
431                         
432                         /* get rid of unneeded bone */
433                         bone_free(arm, curbone);
434                         BLI_freelinkN(&ob->pose->chanbase, pchan);
435                 }
436         }
437         
438         /* exit editmode (recalculates pchans too) */
439         ED_armature_from_edit(ob);
440         ED_armature_edit_free(ob);
441 }
442
443 /* separate selected bones into their armature */
444 static int separate_armature_exec(bContext *C, wmOperator *UNUSED(op))
445 {
446         Main *bmain = CTX_data_main(C);
447         Scene *scene = CTX_data_scene(C);
448         Object *obedit = CTX_data_edit_object(C);
449         Object *oldob, *newob;
450         Base *oldbase, *newbase;
451         
452         /* sanity checks */
453         if (obedit == NULL)
454                 return OPERATOR_CANCELLED;
455         
456         /* set wait cursor in case this takes a while */
457         WM_cursor_wait(1);
458         
459         /* we are going to do this as follows (unlike every other instance of separate):
460          *      1. exit editmode +posemode for active armature/base. Take note of what this is.
461          *      2. duplicate base - BASACT is the new one now
462          *      3. for each of the two armatures, enter editmode -> remove appropriate bones -> exit editmode + recalc
463          *      4. fix constraint links
464          *      5. make original armature active and enter editmode
465          */
466
467         /* 1) only edit-base selected */
468         /* TODO: use context iterators for this? */
469         CTX_DATA_BEGIN(C, Base *, base, visible_bases)
470         {
471                 if (base->object == obedit) base->flag |= 1;
472                 else base->flag &= ~1;
473         }
474         CTX_DATA_END;
475         
476         /* 1) store starting settings and exit editmode */
477         oldob = obedit;
478         oldbase = BASACT;
479         oldob->mode &= ~OB_MODE_POSE;
480         //oldbase->flag &= ~OB_POSEMODE;
481         
482         ED_armature_from_edit(obedit);
483         ED_armature_edit_free(obedit);
484         
485         /* 2) duplicate base */
486         newbase = ED_object_add_duplicate(bmain, scene, oldbase, USER_DUP_ARM); /* only duplicate linked armature */
487         DAG_relations_tag_update(bmain);
488
489         newob = newbase->object;
490         newbase->flag &= ~SELECT;
491         
492         
493         /* 3) remove bones that shouldn't still be around on both armatures */
494         separate_armature_bones(oldob, 1);
495         separate_armature_bones(newob, 0);
496         
497         
498         /* 4) fix links before depsgraph flushes */ // err... or after?
499         separated_armature_fix_links(oldob, newob);
500         
501         DAG_id_tag_update(&oldob->id, OB_RECALC_DATA);  /* this is the original one */
502         DAG_id_tag_update(&newob->id, OB_RECALC_DATA);  /* this is the separated one */
503         
504         
505         /* 5) restore original conditions */
506         obedit = oldob;
507         
508         ED_armature_to_edit(obedit);
509         
510         /* note, notifier might evolve */
511         WM_event_add_notifier(C, NC_OBJECT | ND_POSE, obedit);
512         
513         /* recalc/redraw + cleanup */
514         WM_cursor_wait(0);
515         
516         return OPERATOR_FINISHED;
517 }
518
519 void ARMATURE_OT_separate(wmOperatorType *ot)
520 {
521         /* identifiers */
522         ot->name = "Separate Bones";
523         ot->idname = "ARMATURE_OT_separate";
524         ot->description = "Isolate selected bones into a separate armature";
525         
526         /* callbacks */
527         ot->invoke = WM_operator_confirm;
528         ot->exec = separate_armature_exec;
529         ot->poll = ED_operator_editarmature;
530         
531         /* flags */
532         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
533 }
534
535 /* ******************************************** Parenting ************************************************* */
536
537 /* armature parenting options */
538 #define ARM_PAR_CONNECT 1
539 #define ARM_PAR_OFFSET  2
540
541
542 /* check for null, before calling! */
543 static void bone_connect_to_existing_parent(EditBone *bone)
544 {
545         bone->flag |= BONE_CONNECTED;
546         copy_v3_v3(bone->head, bone->parent->tail);
547         bone->rad_head = bone->parent->rad_tail;
548 }
549
550 static void bone_connect_to_new_parent(ListBase *edbo, EditBone *selbone, EditBone *actbone, short mode)
551 {
552         EditBone *ebone;
553         float offset[3];
554         
555         if ((selbone->parent) && (selbone->flag & BONE_CONNECTED))
556                 selbone->parent->flag &= ~(BONE_TIPSEL);
557         
558         /* make actbone the parent of selbone */
559         selbone->parent = actbone;
560         
561         /* in actbone tree we cannot have a loop */
562         for (ebone = actbone->parent; ebone; ebone = ebone->parent) {
563                 if (ebone->parent == selbone) {
564                         ebone->parent = NULL;
565                         ebone->flag &= ~BONE_CONNECTED;
566                 }
567         }
568         
569         if (mode == ARM_PAR_CONNECT) {
570                 /* Connected: Child bones will be moved to the parent tip */
571                 selbone->flag |= BONE_CONNECTED;
572                 sub_v3_v3v3(offset, actbone->tail, selbone->head);
573                 
574                 copy_v3_v3(selbone->head, actbone->tail);
575                 selbone->rad_head = actbone->rad_tail;
576                 
577                 add_v3_v3(selbone->tail, offset);
578                 
579                 /* offset for all its children */
580                 for (ebone = edbo->first; ebone; ebone = ebone->next) {
581                         EditBone *par;
582                         
583                         for (par = ebone->parent; par; par = par->parent) {
584                                 if (par == selbone) {
585                                         add_v3_v3(ebone->head, offset);
586                                         add_v3_v3(ebone->tail, offset);
587                                         break;
588                                 }
589                         }
590                 }
591         }
592         else {
593                 /* Offset: Child bones will retain their distance from the parent tip */
594                 selbone->flag &= ~BONE_CONNECTED;
595         }
596 }
597
598
599 static EnumPropertyItem prop_editarm_make_parent_types[] = {
600         {ARM_PAR_CONNECT, "CONNECTED", 0, "Connected", ""},
601         {ARM_PAR_OFFSET, "OFFSET", 0, "Keep Offset", ""},
602         {0, NULL, 0, NULL, NULL}
603 };
604
605 static int armature_parent_set_exec(bContext *C, wmOperator *op) 
606 {
607         Object *ob = CTX_data_edit_object(C);
608         bArmature *arm = (bArmature *)ob->data;
609         EditBone *actbone = CTX_data_active_bone(C);
610         EditBone *actmirb = NULL;
611         short val = RNA_enum_get(op->ptr, "type");
612         
613         /* there must be an active bone */
614         if (actbone == NULL) {
615                 BKE_report(op->reports, RPT_ERROR, "Operation requires an active bone");
616                 return OPERATOR_CANCELLED;
617         }
618         else if (arm->flag & ARM_MIRROR_EDIT) {
619                 /* For X-Axis Mirror Editing option, we may need a mirror copy of actbone
620                  * - if there's a mirrored copy of selbone, try to find a mirrored copy of actbone 
621                  *   (i.e.  selbone="child.L" and actbone="parent.L", find "child.R" and "parent.R").
622                  * This is useful for arm-chains, for example parenting lower arm to upper arm
623                  * - if there's no mirrored copy of actbone (i.e. actbone = "parent.C" or "parent")
624                  *   then just use actbone. Useful when doing upper arm to spine.
625                  */
626                 actmirb = ED_armature_bone_get_mirrored(arm->edbo, actbone);
627                 if (actmirb == NULL) 
628                         actmirb = actbone;
629         }
630         
631         /* if there is only 1 selected bone, we assume that that is the active bone, 
632          * since a user will need to have clicked on a bone (thus selecting it) to make it active
633          */
634         if (CTX_DATA_COUNT(C, selected_editable_bones) <= 1) {
635                 /* When only the active bone is selected, and it has a parent,
636                  * connect it to the parent, as that is the only possible outcome. 
637                  */
638                 if (actbone->parent) {
639                         bone_connect_to_existing_parent(actbone);
640                         
641                         if ((arm->flag & ARM_MIRROR_EDIT) && (actmirb->parent))
642                                 bone_connect_to_existing_parent(actmirb);
643                 }
644         }
645         else {
646                 /* Parent 'selected' bones to the active one
647                  * - the context iterator contains both selected bones and their mirrored copies,
648                  *   so we assume that unselected bones are mirrored copies of some selected bone
649                  * - since the active one (and/or its mirror) will also be selected, we also need 
650                  *  to check that we are not trying to operate on them, since such an operation
651                  *      would cause errors
652                  */
653                 
654                 /* parent selected bones to the active one */
655                 CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones)
656                 {
657                         if (ELEM(ebone, actbone, actmirb) == 0) {
658                                 if (ebone->flag & BONE_SELECTED) 
659                                         bone_connect_to_new_parent(arm->edbo, ebone, actbone, val);
660                                 else
661                                         bone_connect_to_new_parent(arm->edbo, ebone, actmirb, val);
662                         }
663                 }
664                 CTX_DATA_END;
665         }
666         
667
668         /* note, notifier might evolve */
669         WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
670         
671         return OPERATOR_FINISHED;
672 }
673
674 static int armature_parent_set_invoke(bContext *C, wmOperator *UNUSED(op), const wmEvent *UNUSED(event))
675 {
676         EditBone *actbone = CTX_data_active_bone(C);
677         uiPopupMenu *pup = uiPupMenuBegin(C, CTX_IFACE_(BLF_I18NCONTEXT_OPERATOR_DEFAULT, "Make Parent"), ICON_NONE);
678         uiLayout *layout = uiPupMenuLayout(pup);
679         int allchildbones = 0;
680         
681         CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones)
682         {
683                 if (ebone != actbone) {
684                         if (ebone->parent != actbone) allchildbones = 1;
685                 }
686         }
687         CTX_DATA_END;
688
689         uiItemEnumO(layout, "ARMATURE_OT_parent_set", NULL, 0, "type", ARM_PAR_CONNECT);
690         
691         /* ob becomes parent, make the associated menus */
692         if (allchildbones)
693                 uiItemEnumO(layout, "ARMATURE_OT_parent_set", NULL, 0, "type", ARM_PAR_OFFSET);
694                 
695         uiPupMenuEnd(C, pup);
696         
697         return OPERATOR_CANCELLED;
698 }
699
700 void ARMATURE_OT_parent_set(wmOperatorType *ot)
701 {
702         /* identifiers */
703         ot->name = "Make Parent";
704         ot->idname = "ARMATURE_OT_parent_set";
705         ot->description = "Set the active bone as the parent of the selected bones";
706         
707         /* api callbacks */
708         ot->invoke = armature_parent_set_invoke;
709         ot->exec = armature_parent_set_exec;
710         ot->poll = ED_operator_editarmature;
711         
712         /* flags */
713         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
714         
715         RNA_def_enum(ot->srna, "type", prop_editarm_make_parent_types, 0, "ParentType", "Type of parenting");
716 }
717
718
719
720 static EnumPropertyItem prop_editarm_clear_parent_types[] = {
721         {1, "CLEAR", 0, "Clear Parent", ""},
722         {2, "DISCONNECT", 0, "Disconnect Bone", ""},
723         {0, NULL, 0, NULL, NULL}
724 };
725
726 static void editbone_clear_parent(EditBone *ebone, int mode)
727 {
728         if (ebone->parent) {
729                 /* for nice selection */
730                 ebone->parent->flag &= ~(BONE_TIPSEL);
731         }
732         
733         if (mode == 1) ebone->parent = NULL;
734         ebone->flag &= ~BONE_CONNECTED;
735 }
736
737 static int armature_parent_clear_exec(bContext *C, wmOperator *op) 
738 {
739         Object *ob = CTX_data_edit_object(C);
740         bArmature *arm = (bArmature *)ob->data;
741         int val = RNA_enum_get(op->ptr, "type");
742                 
743         CTX_DATA_BEGIN(C, EditBone *, ebone, selected_editable_bones)
744         {
745                 editbone_clear_parent(ebone, val);
746         }
747         CTX_DATA_END;
748         
749         ED_armature_sync_selection(arm->edbo);
750
751         /* note, notifier might evolve */
752         WM_event_add_notifier(C, NC_OBJECT | ND_BONE_SELECT, ob);
753         
754         return OPERATOR_FINISHED;
755 }
756
757 void ARMATURE_OT_parent_clear(wmOperatorType *ot)
758 {
759         /* identifiers */
760         ot->name = "Clear Parent";
761         ot->idname = "ARMATURE_OT_parent_clear";
762         ot->description = "Remove the parent-child relationship between selected bones and their parents";
763         
764         /* api callbacks */
765         ot->invoke = WM_menu_invoke;
766         ot->exec = armature_parent_clear_exec;
767         ot->poll = ED_operator_editarmature;
768         
769         /* flags */
770         ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
771         
772         ot->prop = RNA_def_enum(ot->srna, "type", prop_editarm_clear_parent_types, 0, "ClearType", "What way to clear parenting");
773 }
774