2.5/Posemode:
[blender-staging.git] / source / blender / editors / object / editconstraint.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): Joshua Leung, Blender Foundation
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30 #include <stdio.h>
31 #include <string.h>
32
33 #include "MEM_guardedalloc.h"
34
35 #include "BLI_blenlib.h"
36 #include "BLI_arithb.h"
37 #include "BLI_dynstr.h"
38
39 #include "DNA_action_types.h"
40 #include "DNA_armature_types.h"
41 #include "DNA_constraint_types.h"
42 #include "DNA_curve_types.h"
43 #include "DNA_object_types.h"
44 #include "DNA_scene_types.h"
45 #include "DNA_screen_types.h"
46 #include "DNA_text_types.h"
47 #include "DNA_view3d_types.h"
48
49 #include "BKE_action.h"
50 #include "BKE_armature.h"
51 #include "BKE_constraint.h"
52 #include "BKE_context.h"
53 #include "BKE_depsgraph.h"
54 #include "BKE_global.h"
55 #include "BKE_main.h"
56 #include "BKE_object.h"
57 #include "BKE_report.h"
58 #include "BKE_utildefines.h"
59
60 #ifndef DISABLE_PYTHON
61 #include "BPY_extern.h"
62 #endif
63
64 #include "WM_api.h"
65 #include "WM_types.h"
66
67 #include "RNA_access.h"
68 #include "RNA_define.h"
69 #include "RNA_enum_types.h"
70 #include "RNA_types.h"
71
72 #include "ED_object.h"
73 #include "ED_screen.h"
74
75 #include "UI_interface.h"
76
77 #include "object_intern.h"
78
79 /* XXX */
80 static int pupmenu() {return 0;}
81
82 /* -------------- Get Active Constraint Data ---------------------- */
83
84 /* if object in posemode, active bone constraints, else object constraints */
85 ListBase *get_active_constraints (Object *ob)
86 {
87         if (ob == NULL)
88                 return NULL;
89
90         if (ob->mode & OB_MODE_POSE) {
91                 bPoseChannel *pchan;
92                 
93                 pchan = get_active_posechannel(ob);
94                 if (pchan)
95                         return &pchan->constraints;
96         }
97         else 
98                 return &ob->constraints;
99
100         return NULL;
101 }
102
103 /* single constraint */
104 bConstraint *get_active_constraint (Object *ob)
105 {
106         ListBase *lb= get_active_constraints(ob);
107
108         if (lb) {
109                 bConstraint *con;
110                 
111                 for (con= lb->first; con; con=con->next) {
112                         if (con->flag & CONSTRAINT_ACTIVE)
113                                 return con;
114                 }
115         }
116         
117         return NULL;
118 }
119 /* -------------- Constraint Management (Add New, Remove, Rename) -------------------- */
120 /* ------------- PyConstraints ------------------ */
121
122 /* this callback sets the text-file to be used for selected menu item */
123 void validate_pyconstraint_cb (void *arg1, void *arg2)
124 {
125         bPythonConstraint *data = arg1;
126         Text *text= NULL;
127         int index = *((int *)arg2);
128         int i;
129         
130         /* exception for no script */
131         if (index) {
132                 /* innovative use of a for...loop to search */
133                 for (text=G.main->text.first, i=1; text && index!=i; i++, text=text->id.next);
134         }
135         data->text = text;
136 }
137
138 #ifndef DISABLE_PYTHON
139 /* this returns a string for the list of usable pyconstraint script names */
140 char *buildmenu_pyconstraints (Text *con_text, int *pyconindex)
141 {
142         DynStr *pupds= BLI_dynstr_new();
143         Text *text;
144         char *str;
145         char buf[64];
146         int i;
147         
148         /* add title first */
149         sprintf(buf, "Scripts: %%t|[None]%%x0|");
150         BLI_dynstr_append(pupds, buf);
151         
152         /* init active-index first */
153         if (con_text == NULL)
154                 *pyconindex= 0;
155         
156         /* loop through markers, adding them */
157         for (text=G.main->text.first, i=1; text; i++, text=text->id.next) {
158                 /* this is important to ensure that right script is shown as active */
159                 if (text == con_text) *pyconindex = i;
160                 
161                 /* only include valid pyconstraint scripts */
162                 if (BPY_is_pyconstraint(text)) {
163                         BLI_dynstr_append(pupds, text->id.name+2);
164                         
165                         sprintf(buf, "%%x%d", i);
166                         BLI_dynstr_append(pupds, buf);
167                         
168                         if (text->id.next)
169                                 BLI_dynstr_append(pupds, "|");
170                 }
171         }
172         
173         /* convert to normal MEM_malloc'd string */
174         str= BLI_dynstr_get_cstring(pupds);
175         BLI_dynstr_free(pupds);
176         
177         return str;
178 }
179 #endif /* DISABLE_PYTHON */
180
181 /* this callback gets called when the 'refresh' button of a pyconstraint gets pressed */
182 void update_pyconstraint_cb (void *arg1, void *arg2)
183 {
184         Object *owner= (Object *)arg1;
185         bConstraint *con= (bConstraint *)arg2;
186 #ifndef DISABLE_PYTHON
187         if (owner && con)
188                 BPY_pyconstraint_update(owner, con);
189 #endif
190 }
191
192 /* Creates a new constraint, initialises its data, and returns it */
193 bConstraint *add_new_constraint (short type)
194 {
195         bConstraint *con;
196         bConstraintTypeInfo *cti;
197
198         con = MEM_callocN(sizeof(bConstraint), "Constraint");
199         
200         /* Set up a generic constraint datablock */
201         con->type = type;
202         con->flag |= CONSTRAINT_EXPAND;
203         con->enforce = 1.0f;
204         
205         /* Load the data for it */
206         cti = constraint_get_typeinfo(con);
207         if (cti) {
208                 con->data = MEM_callocN(cti->size, cti->structName);
209                 
210                 /* only constraints that change any settings need this */
211                 if (cti->new_data)
212                         cti->new_data(con->data);
213                         
214                 /* set the name based on the type of constraint */
215                 strcpy(con->name, cti->name); 
216         }
217         else
218                 strcpy(con->name, "Const");
219         
220         return con;
221 }
222
223 /* Adds the given constraint to the Object-level set of constraints for the given Object */
224 void add_constraint_to_object (bConstraint *con, Object *ob)
225 {
226         ListBase *list;
227         list = &ob->constraints;
228         
229         if (list) {
230                 unique_constraint_name(con, list);
231                 BLI_addtail(list, con);
232                 
233                 if (proxylocked_constraints_owner(ob, NULL))
234                         con->flag |= CONSTRAINT_PROXY_LOCAL;
235                 
236                 con->flag |= CONSTRAINT_ACTIVE;
237                 for (con= con->prev; con; con= con->prev)
238                         con->flag &= ~CONSTRAINT_ACTIVE;
239         }
240 }
241
242 /* helper function for add_constriant - sets the last target for the active constraint */
243 static void set_constraint_nth_target (bConstraint *con, Object *target, char subtarget[], int index)
244 {
245         bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
246         ListBase targets = {NULL, NULL};
247         bConstraintTarget *ct;
248         int num_targets, i;
249         
250         if (cti && cti->get_constraint_targets) {
251                 cti->get_constraint_targets(con, &targets);
252                 num_targets= BLI_countlist(&targets);
253                 
254                 if (index < 0) {
255                         if (abs(index) < num_targets)
256                                 index= num_targets - abs(index);
257                         else
258                                 index= num_targets - 1;
259                 }
260                 else if (index >= num_targets) {
261                         index= num_targets - 1;
262                 }
263                 
264                 for (ct=targets.first, i=0; ct; ct= ct->next, i++) {
265                         if (i == index) {
266                                 ct->tar= target;
267                                 strcpy(ct->subtarget, subtarget);
268                                 break;
269                         }
270                 }
271                 
272                 if (cti->flush_constraint_targets)
273                         cti->flush_constraint_targets(con, &targets, 0);
274         }
275 }
276
277 /* ------------- Constraint Sanity Testing ------------------- */
278
279 /* checks validity of object pointers, and NULLs,
280  * if Bone doesnt exist it sets the CONSTRAINT_DISABLE flag 
281  */
282 static void test_constraints (Object *owner, const char substring[])
283 {
284         bConstraint *curcon;
285         ListBase *conlist= NULL;
286         int type;
287         
288         if (owner==NULL) return;
289         
290         /* Check parents */
291         if (strlen(substring)) {
292                 switch (owner->type) {
293                         case OB_ARMATURE:
294                                 type = CONSTRAINT_OBTYPE_BONE;
295                                 break;
296                         default:
297                                 type = CONSTRAINT_OBTYPE_OBJECT;
298                                 break;
299                 }
300         }
301         else
302                 type = CONSTRAINT_OBTYPE_OBJECT;
303         
304         /* Get the constraint list for this object */
305         switch (type) {
306                 case CONSTRAINT_OBTYPE_OBJECT:
307                         conlist = &owner->constraints;
308                         break;
309                 case CONSTRAINT_OBTYPE_BONE:
310                         {
311                                 Bone *bone;
312                                 bPoseChannel *chan;
313                                 
314                                 bone = get_named_bone( ((bArmature *)owner->data), substring );
315                                 chan = get_pose_channel(owner->pose, substring);
316                                 if (bone && chan) {
317                                         conlist = &chan->constraints;
318                                 }
319                         }
320                         break;
321         }
322         
323         /* Check all constraints - is constraint valid? */
324         if (conlist) {
325                 for (curcon = conlist->first; curcon; curcon=curcon->next) {
326                         bConstraintTypeInfo *cti= constraint_get_typeinfo(curcon);
327                         ListBase targets = {NULL, NULL};
328                         bConstraintTarget *ct;
329                         
330                         /* clear disabled-flag first */
331                         curcon->flag &= ~CONSTRAINT_DISABLE;
332
333                         if (curcon->type == CONSTRAINT_TYPE_KINEMATIC) {
334                                 bKinematicConstraint *data = curcon->data;
335                                 
336                                 /* bad: we need a separate set of checks here as poletarget is 
337                                  *              optional... otherwise poletarget must exist too or else
338                                  *              the constraint is deemed invalid
339                                  */
340                                 if (exist_object(data->tar) == 0) {
341                                         data->tar = NULL;
342                                         curcon->flag |= CONSTRAINT_DISABLE;
343                                 }
344                                 else if (data->tar == owner) {
345                                         if (!get_named_bone(get_armature(owner), data->subtarget)) {
346                                                 curcon->flag |= CONSTRAINT_DISABLE;
347                                         }
348                                 }
349                                 
350                                 if (data->poletar) {
351                                         if (exist_object(data->poletar) == 0) {
352                                                 data->poletar = NULL;
353                                                 curcon->flag |= CONSTRAINT_DISABLE;
354                                         }
355                                         else if (data->poletar == owner) {
356                                                 if (!get_named_bone(get_armature(owner), data->polesubtarget)) {
357                                                         curcon->flag |= CONSTRAINT_DISABLE;
358                                                 }
359                                         }
360                                 }
361                                 
362                                 /* targets have already been checked for this */
363                                 continue;
364                         }
365                         else if (curcon->type == CONSTRAINT_TYPE_ACTION) {
366                                 bActionConstraint *data = curcon->data;
367                                 
368                                 /* validate action */
369                                 if (data->act == NULL) 
370                                         curcon->flag |= CONSTRAINT_DISABLE;
371                         }
372                         else if (curcon->type == CONSTRAINT_TYPE_FOLLOWPATH) {
373                                 bFollowPathConstraint *data = curcon->data;
374                                 
375                                 /* don't allow track/up axes to be the same */
376                                 if (data->upflag==data->trackflag)
377                                         curcon->flag |= CONSTRAINT_DISABLE;
378                                 if (data->upflag+3==data->trackflag)
379                                         curcon->flag |= CONSTRAINT_DISABLE;
380                         }
381                         else if (curcon->type == CONSTRAINT_TYPE_TRACKTO) {
382                                 bTrackToConstraint *data = curcon->data;
383                                 
384                                 /* don't allow track/up axes to be the same */
385                                 if (data->reserved2==data->reserved1)
386                                         curcon->flag |= CONSTRAINT_DISABLE;
387                                 if (data->reserved2+3==data->reserved1)
388                                         curcon->flag |= CONSTRAINT_DISABLE;
389                         }
390                         else if (curcon->type == CONSTRAINT_TYPE_LOCKTRACK) {
391                                 bLockTrackConstraint *data = curcon->data;
392                                 
393                                 if (data->lockflag==data->trackflag)
394                                         curcon->flag |= CONSTRAINT_DISABLE;
395                                 if (data->lockflag+3==data->trackflag)
396                                         curcon->flag |= CONSTRAINT_DISABLE;
397                         }
398                         
399                         /* Check targets for constraints */
400                         if (cti && cti->get_constraint_targets) {
401                                 cti->get_constraint_targets(curcon, &targets);
402                                 
403                                 /* disable and clear constraints targets that are incorrect */
404                                 for (ct= targets.first; ct; ct= ct->next) {
405                                         /* general validity checks (for those constraints that need this) */
406                                         if (exist_object(ct->tar) == 0) {
407                                                 ct->tar = NULL;
408                                                 curcon->flag |= CONSTRAINT_DISABLE;
409                                         }
410                                         else if (ct->tar == owner) {
411                                                 if (!get_named_bone(get_armature(owner), ct->subtarget)) {
412                                                         curcon->flag |= CONSTRAINT_DISABLE;
413                                                 }
414                                         }
415                                         
416                                         /* target checks for specific constraints */
417                                         if (ELEM(curcon->type, CONSTRAINT_TYPE_FOLLOWPATH, CONSTRAINT_TYPE_CLAMPTO)) {
418                                                 if (ct->tar) {
419                                                         if (ct->tar->type != OB_CURVE) {
420                                                                 ct->tar= NULL;
421                                                                 curcon->flag |= CONSTRAINT_DISABLE;
422                                                         }
423                                                         else {
424                                                                 Curve *cu= ct->tar->data;
425                                                                 
426                                                                 /* auto-set 'Path' setting on curve so this works  */
427                                                                 cu->flag |= CU_PATH;
428                                                         }
429                                                 }                                               
430                                         }
431                                 }       
432                                 
433                                 /* free any temporary targets */
434                                 if (cti->flush_constraint_targets)
435                                         cti->flush_constraint_targets(curcon, &targets, 0);
436                         }
437                 }
438         }
439 }
440
441 static void test_bonelist_constraints (Object *owner, ListBase *list)
442 {
443         Bone *bone;
444
445         for (bone = list->first; bone; bone = bone->next) {
446                 test_constraints(owner, bone->name);
447                 test_bonelist_constraints(owner, &bone->childbase);
448         }
449 }
450
451 void object_test_constraints (Object *owner)
452 {
453         test_constraints(owner, "");
454
455         if (owner->type==OB_ARMATURE) {
456                 bArmature *arm= get_armature(owner);
457                 
458                 if (arm)
459                         test_bonelist_constraints(owner, &arm->bonebase);
460         }
461 }
462
463 /* ********************** CONSTRAINT-SPECIFIC STUFF ********************* */
464
465 /* ---------- Distance-Dependent Constraints ---------- */
466 /* StretchTo, Limit Distance */
467
468 static int stretchto_reset_exec (bContext *C, wmOperator *op)
469 {
470         PointerRNA ptr= CTX_data_pointer_get_type(C, "constraint", &RNA_StretchToConstraint);
471         
472         /* just set original length to 0.0, which will cause a reset on next recalc */
473         RNA_float_set(&ptr, "original_length", 0.0f);
474         
475         WM_event_add_notifier(C, NC_OBJECT|ND_CONSTRAINT, NULL);
476         return OPERATOR_FINISHED;
477 }
478
479 void CONSTRAINT_OT_stretchto_reset (wmOperatorType *ot)
480 {
481         /* identifiers */
482         ot->name= "Reset Original Length";
483         ot->idname= "CONSTRAINT_OT_stretchto_reset";
484         ot->description= "Reset original length of bone for Stretch To Constraint.";
485         
486         ot->exec= stretchto_reset_exec;
487         
488         /* flags */
489         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
490 }
491
492
493 static int limitdistance_reset_exec (bContext *C, wmOperator *op)
494 {
495         PointerRNA ptr= CTX_data_pointer_get_type(C, "constraint", &RNA_LimitDistanceConstraint);
496         
497         /* just set distance to 0.0, which will cause a reset on next recalc */
498         RNA_float_set(&ptr, "distance", 0.0f);
499         
500         WM_event_add_notifier(C, NC_OBJECT|ND_CONSTRAINT, NULL);
501         return OPERATOR_FINISHED;
502 }
503
504 void CONSTRAINT_OT_limitdistance_reset (wmOperatorType *ot)
505 {
506         /* identifiers */
507         ot->name= "Reset Distance";
508         ot->idname= "CONSTRAINT_OT_limitdistance_reset";
509         ot->description= "Reset limiting distance for Limit Distance Constraint.";
510         
511         ot->exec= limitdistance_reset_exec;
512         
513         /* flags */
514         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
515 }
516
517 /* ------------- Child-Of Constraint ------------------ */
518
519 /* ChildOf Constraint - set inverse callback */
520 static int childof_set_inverse_exec (bContext *C, wmOperator *op)
521 {
522         PointerRNA ptr= CTX_data_pointer_get_type(C, "constraint", &RNA_ChildOfConstraint);
523         Scene *scene= CTX_data_scene(C);
524         Object *ob= ptr.id.data;
525         bConstraint *con= ptr.data;
526         bChildOfConstraint *data= (bChildOfConstraint *)con->data;
527         bPoseChannel *pchan= NULL;
528
529         /* try to find a pose channel */
530         // TODO: get from context instead?
531         if (ob && ob->pose)
532                 pchan= get_active_posechannel(ob);
533         
534         /* calculate/set inverse matrix */
535         if (pchan) {
536                 float pmat[4][4], cinf;
537                 float imat[4][4], tmat[4][4];
538                 
539                 /* make copy of pchan's original pose-mat (for use later) */
540                 Mat4CpyMat4(pmat, pchan->pose_mat);
541                 
542                 /* disable constraint for pose to be solved without it */
543                 cinf= con->enforce;
544                 con->enforce= 0.0f;
545                 
546                 /* solve pose without constraint */
547                 where_is_pose(scene, ob);
548                 
549                 /* determine effect of constraint by removing the newly calculated 
550                  * pchan->pose_mat from the original pchan->pose_mat, thus determining 
551                  * the effect of the constraint
552                  */
553                 Mat4Invert(imat, pchan->pose_mat);
554                 Mat4MulMat4(tmat, imat, pmat);
555                 Mat4Invert(data->invmat, tmat);
556                 
557                 /* recalculate pose with new inv-mat */
558                 con->enforce= cinf;
559                 where_is_pose(scene, ob);
560         }
561         else if (ob) {
562                 Object workob;
563                 /* use what_does_parent to find inverse - just like for normal parenting.
564                  * NOTE: what_does_parent uses a static workob defined in object.c 
565                  */
566                 what_does_parent(scene, ob, &workob);
567                 Mat4Invert(data->invmat, workob.obmat);
568         }
569         else
570                 Mat4One(data->invmat);
571                 
572         WM_event_add_notifier(C, NC_OBJECT|ND_CONSTRAINT, ob);
573                 
574         return OPERATOR_FINISHED;
575 }
576
577 void CONSTRAINT_OT_childof_set_inverse (wmOperatorType *ot)
578 {
579         /* identifiers */
580         ot->name= "Set Inverse";
581         ot->idname= "CONSTRAINT_OT_childof_set_inverse";
582         ot->description= "Set inverse correction for ChildOf constraint.";
583         
584         ot->exec= childof_set_inverse_exec;
585         
586         /* flags */
587         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
588 }
589
590
591 /* ChildOf Constraint - clear inverse callback */
592 static int childof_clear_inverse_exec (bContext *C, wmOperator *op)
593 {
594         PointerRNA ptr= CTX_data_pointer_get_type(C, "constraint", &RNA_ChildOfConstraint);
595         Object *ob= ptr.id.data;
596         bConstraint *con= ptr.data;
597         bChildOfConstraint *data= (bChildOfConstraint *)con->data;
598         
599         /* simply clear the matrix */
600         Mat4One(data->invmat);
601         
602         WM_event_add_notifier(C, NC_OBJECT|ND_CONSTRAINT, ob);
603         
604         return OPERATOR_FINISHED;
605 }
606
607 void CONSTRAINT_OT_childof_clear_inverse (wmOperatorType *ot)
608 {
609         /* identifiers */
610         ot->name= "Clear Inverse";
611         ot->idname= "CONSTRAINT_OT_childof_clear_inverse";
612         ot->description= "Clear inverse correction for ChildOf constraint.";
613         
614         ot->exec= childof_clear_inverse_exec;
615         
616         /* flags */
617         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
618 }
619
620 /***************************** BUTTONS ****************************/
621
622 /* Rename the given constraint, con already has the new name */
623 void ED_object_constraint_rename(Object *ob, bConstraint *con, char *oldname)
624 {
625         bConstraint *tcon;
626         ListBase *conlist= NULL;
627         int from_object= 0;
628         
629         /* get context by searching for con (primitive...) */
630         for (tcon= ob->constraints.first; tcon; tcon= tcon->next) {
631                 if (tcon==con)
632                         break;
633         }
634         
635         if (tcon) {
636                 conlist= &ob->constraints;
637                 from_object= 1;
638         }
639         else if (ob->pose) {
640                 bPoseChannel *pchan;
641                 
642                 for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) {
643                         for (tcon= pchan->constraints.first; tcon; tcon= tcon->next) {
644                                 if (tcon==con)
645                                         break;
646                         }
647                         if (tcon) 
648                                 break;
649                 }
650                 
651                 if (tcon) {
652                         conlist= &pchan->constraints;
653                 }
654         }
655         
656         if (conlist==NULL) {
657                 printf("rename constraint failed\n");   /* should not happen in UI */
658                 return;
659         }
660         
661         /* first make sure it's a unique name within context */
662         unique_constraint_name(con, conlist);
663 }
664
665
666
667
668 void ED_object_constraint_set_active(Object *ob, bConstraint *con)
669 {
670         ListBase *lb;
671         bConstraint *origcon= con;
672         
673         /* lets be nice and escape if its active already */
674         if(con && (con->flag & CONSTRAINT_ACTIVE))
675                 return ;
676         
677         lb= get_active_constraints(ob);
678         if(lb == NULL)
679                 return;
680         
681         for(con= lb->first; con; con= con->next) {
682                 if(con==origcon) con->flag |= CONSTRAINT_ACTIVE;
683                 else con->flag &= ~CONSTRAINT_ACTIVE;
684         }
685 }
686
687 static int constraint_delete_exec (bContext *C, wmOperator *op)
688 {
689         PointerRNA ptr= CTX_data_pointer_get_type(C, "constraint", &RNA_Constraint);
690         Object *ob= ptr.id.data;
691         bConstraint *con= ptr.data;
692         ListBase *lb;
693         
694         /* remove constraint itself */
695         lb= get_active_constraints(ob);
696         free_constraint_data(con);
697         BLI_freelinkN(lb, con);
698         
699         ED_object_constraint_set_active(ob, NULL);
700         WM_event_add_notifier(C, NC_OBJECT|ND_CONSTRAINT, ob);
701
702         return OPERATOR_FINISHED;
703 }
704
705 void CONSTRAINT_OT_delete (wmOperatorType *ot)
706 {
707         /* identifiers */
708         ot->name= "Delete Constraint";
709         ot->idname= "CONSTRAINT_OT_delete";
710         ot->description= "Remove constraitn from constraint stack.";
711         
712         /* callbacks */
713         ot->exec= constraint_delete_exec;
714         
715         /* flags */
716         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 
717 }
718
719 static int constraint_move_down_exec (bContext *C, wmOperator *op)
720 {
721         PointerRNA ptr= CTX_data_pointer_get_type(C, "constraint", &RNA_Constraint);
722         Object *ob= ptr.id.data;
723         bConstraint *con= ptr.data;
724         
725         if (con->next) {
726                 ListBase *conlist= get_active_constraints(ob);
727                 bConstraint *nextCon= con->next;
728                 
729                 /* insert the nominated constraint after the one that used to be after it */
730                 BLI_remlink(conlist, con);
731                 BLI_insertlinkafter(conlist, nextCon, con);
732                 
733                 WM_event_add_notifier(C, NC_OBJECT|ND_CONSTRAINT, ob);
734                 
735                 return OPERATOR_FINISHED;
736         }
737         
738         return OPERATOR_CANCELLED;
739 }
740
741 void CONSTRAINT_OT_move_down (wmOperatorType *ot)
742 {
743         /* identifiers */
744         ot->name= "Move Constraint Down";
745         ot->idname= "CONSTRAINT_OT_move_down";
746         ot->description= "Move constraint down constraint stack.";
747         
748         /* callbacks */
749         ot->exec= constraint_move_down_exec;
750         
751         /* flags */
752         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 
753 }
754
755
756 static int constraint_move_up_exec (bContext *C, wmOperator *op)
757 {
758         PointerRNA ptr= CTX_data_pointer_get_type(C, "constraint", &RNA_Constraint);
759         Object *ob= ptr.id.data;
760         bConstraint *con= ptr.data;
761         
762         if (con->prev) {
763                 ListBase *conlist= get_active_constraints(ob);
764                 bConstraint *prevCon= con->prev;
765                 
766                 /* insert the nominated constraint before the one that used to be before it */
767                 BLI_remlink(conlist, con);
768                 BLI_insertlinkbefore(conlist, prevCon, con);
769                 
770                 WM_event_add_notifier(C, NC_OBJECT|ND_CONSTRAINT, ob);
771                 
772                 return OPERATOR_FINISHED;
773         }
774         
775         return OPERATOR_CANCELLED;
776 }
777
778 void CONSTRAINT_OT_move_up (wmOperatorType *ot)
779 {
780         /* identifiers */
781         ot->name= "Move Constraint Up";
782         ot->idname= "CONSTRAINT_OT_move_up";
783         ot->description= "Move constraint up constraint stack.";
784         
785         /* callbacks */
786         ot->exec= constraint_move_up_exec;
787         
788         /* flags */
789         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; 
790 }
791
792 /***************************** OPERATORS ****************************/
793
794 /************************ remove constraint operators *********************/
795
796 static int pose_constraints_clear_exec(bContext *C, wmOperator *op)
797 {
798         Scene *scene= CTX_data_scene(C);
799         Object *ob= CTX_data_active_object(C);
800         
801         /* free constraints for all selected bones */
802         CTX_DATA_BEGIN(C, bPoseChannel*, pchan, selected_pchans)
803         {
804                 free_constraints(&pchan->constraints);
805         }
806         CTX_DATA_END;
807         
808         /* do updates */
809         DAG_object_flush_update(scene, ob, OB_RECALC_OB);
810         WM_event_add_notifier(C, NC_OBJECT|ND_POSE|ND_CONSTRAINT|NA_REMOVED, ob);
811         
812         return OPERATOR_FINISHED;
813 }
814
815 void POSE_OT_constraints_clear(wmOperatorType *ot)
816 {
817         /* identifiers */
818         ot->name = "Clear Constraints";
819         ot->idname= "POSE_OT_constraints_clear";
820         ot->description= "Clear all the constraints for the selected bones.";
821         
822         /* callbacks */
823         ot->exec= pose_constraints_clear_exec;
824         ot->poll= ED_operator_posemode; // XXX - do we want to ensure there are selected bones too?
825 }
826
827
828 static int object_constraints_clear_exec(bContext *C, wmOperator *op)
829 {
830         Scene *scene= CTX_data_scene(C);
831         Object *ob= CTX_data_active_object(C);
832         
833         /* do freeing */
834         // TODO: we should free constraints for all selected objects instead (to be more consistent with bones)
835         free_constraints(&ob->constraints);
836         
837         /* do updates */
838         DAG_object_flush_update(scene, ob, OB_RECALC_OB);
839         WM_event_add_notifier(C, NC_OBJECT|ND_CONSTRAINT|NA_REMOVED, ob);
840         
841         return OPERATOR_FINISHED;
842 }
843
844 void OBJECT_OT_constraints_clear(wmOperatorType *ot)
845 {
846         /* identifiers */
847         ot->name = "Clear Constraints";
848         ot->idname= "OBJECT_OT_constraints_clear";
849         ot->description= "Clear all the constraints for the active Object only.";
850         
851         /* callbacks */
852         ot->exec= object_constraints_clear_exec;
853         ot->poll= ED_operator_object_active;
854 }
855
856 /************************ add constraint operators *********************/
857
858 /* get the Object and/or PoseChannel to use as target */
859 static short get_new_constraint_target(bContext *C, int con_type, Object **tar_ob, bPoseChannel **tar_pchan, short add)
860 {
861         Object *obact= CTX_data_active_object(C);
862         bPoseChannel *pchanact= get_active_posechannel(obact);
863         short only_curve= 0, only_mesh= 0, only_ob= 0;
864         short found= 0;
865         
866         /* clear tar_ob and tar_pchan fields before use 
867          *      - assume for now that both always exist...
868          */
869         *tar_ob= NULL;
870         *tar_pchan= NULL;
871         
872         /* check if constraint type doesn't requires a target
873          *      - if so, no need to get any targets 
874          */
875         switch (con_type) {
876                 /* no-target constraints --------------------------- */
877                         /* null constraint - shouldn't even be added! */
878                 case CONSTRAINT_TYPE_NULL:
879                         /* limit constraints - no targets needed */
880                 case CONSTRAINT_TYPE_LOCLIMIT:
881                 case CONSTRAINT_TYPE_ROTLIMIT:
882                 case CONSTRAINT_TYPE_SIZELIMIT:
883                         return 0;
884                         
885                 /* restricted target-type constraints -------------- */
886                 /* NOTE: for these, we cannot try to add a target object if no valid ones are found, since that doesn't work */
887                         /* curve-based constraints - set the only_curve and only_ob flags */
888                 case CONSTRAINT_TYPE_TRACKTO:
889                 case CONSTRAINT_TYPE_CLAMPTO:
890                 case CONSTRAINT_TYPE_FOLLOWPATH:
891                         only_curve= 1;
892                         only_ob= 1;
893                         add= 0;
894                         break;
895                         
896                         /* mesh only? */
897                 case CONSTRAINT_TYPE_SHRINKWRAP:
898                         only_mesh= 1;
899                         only_ob= 1;
900                         add= 0;
901                         break;
902                         
903                         /* object only - add here is ok? */
904                 case CONSTRAINT_TYPE_RIGIDBODYJOINT:
905                         only_ob= 1;
906                         break;
907         }
908         
909         /* if the active Object is Armature, and we can search for bones, do so... */
910         if ((obact->type == OB_ARMATURE) && (only_ob == 0)) {
911                 /* search in list of selected Pose-Channels for target */
912                 CTX_DATA_BEGIN(C, bPoseChannel*, pchan, selected_pchans) 
913                 {
914                         /* just use the first one that we encounter, as long as it is not the active one */
915                         if (pchan != pchanact) {
916                                 *tar_ob= obact;
917                                 *tar_pchan= pchan;
918                                 found= 1;
919                                 
920                                 break;
921                         }
922                 }
923                 CTX_DATA_END;
924         }
925         
926         /* if not yet found, try selected Objects... */
927         if (found == 0) {
928                 /* search in selected objects context */
929                 CTX_DATA_BEGIN(C, Object*, ob, selected_objects) 
930                 {
931                         /* just use the first object we encounter (that isn't the active object) 
932                          * and which fulfills the criteria for the object-target that we've got 
933                          */
934                         if ( (ob != obact) &&
935                                  ((!only_curve) || (ob->type == OB_CURVE)) && 
936                                  ((!only_mesh) || (ob->type == OB_MESH)) )
937                         {
938                                 /* set target */
939                                 *tar_ob= ob;
940                                 found= 1;
941                                 
942                                 /* perform some special operations on the target */
943                                 if (only_curve) {
944                                         /* Curve-Path option must be enabled for follow-path constraints to be able to work */
945                                         Curve *cu= (Curve *)ob->data;
946                                         cu->flag |= CU_PATH;
947                                 }
948                                 
949                                 break;
950                         }
951                 }
952                 CTX_DATA_END;
953         }
954         
955         /* if still not found, add a new empty to act as a target (if allowed) */
956         if ((found == 0) && (add)) {
957                 Scene *scene= CTX_data_scene(C);
958                 Base *base= BASACT, *newbase=NULL;
959                 Object *obt;
960                 
961                 /* add new target object */
962                 obt= add_object(scene, OB_EMPTY);
963                 
964                 /* set layers OK */
965                 newbase= BASACT;
966                 newbase->lay= base->lay;
967                 obt->lay= newbase->lay;
968                 
969                 /* transform cent to global coords for loc */
970                 if (pchanact) {
971                         /* since by default, IK targets the tip of the last bone, use the tip of the active PoseChannel 
972                          * if adding a target for an IK Constraint
973                          */
974                         if (con_type == CONSTRAINT_TYPE_KINEMATIC)
975                                 VecMat4MulVecfl(obt->loc, obact->obmat, pchanact->pose_tail);
976                         else
977                                 VecMat4MulVecfl(obt->loc, obact->obmat, pchanact->pose_head);
978                 }
979                 else
980                         VECCOPY(obt->loc, obact->obmat[3]);
981                 
982                 /* restore, add_object sets active */
983                 BASACT= base;
984                 base->flag |= SELECT;
985                 
986                 /* make our new target the new object */
987                 *tar_ob= obt;
988                 found= 1;
989         }
990         
991         /* return whether there's any target */
992         return found;
993 }
994
995 /* used by add constraint operators to add the constraint required */
996 static int constraint_add_exec(bContext *C, wmOperator *op, Object *ob, ListBase *list, int type, short setTarget)
997 {
998         Scene *scene= CTX_data_scene(C);
999         bPoseChannel *pchan= get_active_posechannel(ob);
1000         bConstraint *con;
1001         
1002         /* check if constraint to be added is valid for the given constraints stack */
1003         if (type == CONSTRAINT_TYPE_NULL) {
1004                 return OPERATOR_CANCELLED;
1005         }
1006         if ( (type == CONSTRAINT_TYPE_RIGIDBODYJOINT) && (list != &ob->constraints) ) {
1007                 BKE_report(op->reports, RPT_ERROR, "Rigid Body Joint Constraint can only be added to Objects.");
1008                 return OPERATOR_CANCELLED;
1009         }
1010         if ( (type == CONSTRAINT_TYPE_KINEMATIC) && ((!pchan) || (list != &pchan->constraints)) ) {
1011                 BKE_report(op->reports, RPT_ERROR, "IK Constraint can only be added to Bones.");
1012                 return OPERATOR_CANCELLED;
1013         }
1014         
1015         /* create a new constraint of the type requried, and add it to the active/given constraints list */
1016         con = add_new_constraint(type);
1017         
1018         if (list) {
1019                 bConstraint *coniter; 
1020                 
1021                 /* add new constraint to end of list of constraints before ensuring that it has a unique name 
1022                  * (otherwise unique-naming code will fail, since it assumes element exists in list)
1023                  */
1024                 BLI_addtail(list, con);
1025                 unique_constraint_name(con, list);
1026                 
1027                 /* if the target list is a list on some PoseChannel belonging to a proxy-protected 
1028                  * Armature layer, we must tag newly added constraints with a flag which allows them
1029                  * to persist after proxy syncing has been done
1030                  */
1031                 if (proxylocked_constraints_owner(ob, pchan))
1032                         con->flag |= CONSTRAINT_PROXY_LOCAL;
1033                 
1034                 /* make this constraint the active one 
1035                  *      - since constraint was added at end of stack, we can just go 
1036                  *        through deactivating all previous ones
1037                  */
1038                 con->flag |= CONSTRAINT_ACTIVE;
1039                 for (coniter= con->prev; coniter; coniter= coniter->prev)
1040                         coniter->flag &= ~CONSTRAINT_ACTIVE;
1041         }
1042         
1043         /* get the first selected object/bone, and make that the target
1044          *      - apart from the buttons-window add buttons, we shouldn't add in this way
1045          */
1046         if (setTarget) {
1047                 Object *tar_ob= NULL;
1048                 bPoseChannel *tar_pchan= NULL;
1049                 
1050                 /* get the target objects, adding them as need be */
1051                 if (get_new_constraint_target(C, type, &tar_ob, &tar_pchan, 1)) {
1052                         /* method of setting target depends on the type of target we've got 
1053                          *      - by default, just set the first target (distinction here is only for multiple-targetted constraints)
1054                          */
1055                         if (tar_pchan)
1056                                 set_constraint_nth_target(con, tar_ob, tar_pchan->name, 0);
1057                         else
1058                                 set_constraint_nth_target(con, tar_ob, "", 0);
1059                 }
1060         }
1061         
1062         /* do type-specific tweaking to the constraint settings  */
1063         switch (type) {
1064                 case CONSTRAINT_TYPE_CHILDOF:
1065                 {
1066                         /* if this constraint is being added to a posechannel, make sure
1067                          * the constraint gets evaluated in pose-space */
1068                         if (ob->mode & OB_MODE_POSE) {
1069                                 con->ownspace = CONSTRAINT_SPACE_POSE;
1070                                 con->flag |= CONSTRAINT_SPACEONCE;
1071                         }
1072                 }
1073                         break;
1074                         
1075                 case CONSTRAINT_TYPE_PYTHON: // FIXME: this code is not really valid anymore
1076                 {
1077                         char *menustr;
1078                         int scriptint= 0;
1079 #ifndef DISABLE_PYTHON
1080                         /* popup a list of usable scripts */
1081                         menustr = buildmenu_pyconstraints(NULL, &scriptint);
1082                         scriptint = pupmenu(menustr);
1083                         MEM_freeN(menustr);
1084                         
1085                         /* only add constraint if a script was chosen */
1086                         if (scriptint) {
1087                                 /* add constraint */
1088                                 validate_pyconstraint_cb(con->data, &scriptint);
1089                                 
1090                                 /* make sure target allowance is set correctly */
1091                                 BPY_pyconstraint_update(ob, con);
1092                         }
1093 #endif
1094                 }
1095                 default:
1096                         break;
1097         }
1098         
1099         /* make sure all settings are valid - similar to above checks, but sometimes can be wrong */
1100         object_test_constraints(ob);
1101         
1102         if (ob->pose)
1103                 update_pose_constraint_flags(ob->pose);
1104         
1105         
1106         /* force depsgraph to get recalculated since new relationships added */
1107         DAG_scene_sort(scene);          /* sort order of objects */
1108         
1109         if ((ob->type==OB_ARMATURE) && (pchan)) {
1110                 ob->pose->flag |= POSE_RECALC;  /* sort pose channels */
1111                 DAG_object_flush_update(scene, ob, OB_RECALC_DATA|OB_RECALC_OB);
1112         }
1113         else
1114                 DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
1115         
1116         /* notifiers for updates */
1117         WM_event_add_notifier(C, NC_OBJECT|ND_CONSTRAINT|NA_ADDED, ob);
1118         
1119         return OPERATOR_FINISHED;
1120 }
1121
1122 /* ------------------ */
1123
1124 /* dummy operator callback */
1125 static int object_constraint_add_exec(bContext *C, wmOperator *op)
1126 {
1127         ScrArea *sa= CTX_wm_area(C);
1128         Object *ob;
1129         int type= RNA_enum_get(op->ptr, "type");
1130         short with_targets= 0;
1131         
1132         /* get active object from context */
1133         if (sa->spacetype == SPACE_BUTS)
1134                 ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1135         else
1136                 ob= CTX_data_active_object(C);
1137         
1138         if (!ob) {
1139                 BKE_report(op->reports, RPT_ERROR, "No active object to add constraint to.");
1140                 return OPERATOR_CANCELLED;
1141         }
1142                 
1143         /* hack: set constraint targets from selected objects in context is allowed when
1144          *              operator name included 'with_targets', since the menu doesn't allow multiple properties
1145          */
1146         if (strstr(op->idname, "with_targets"))
1147                 with_targets= 1;
1148
1149         return constraint_add_exec(C, op, ob, &ob->constraints, type, with_targets);
1150 }
1151
1152 /* dummy operator callback */
1153 static int pose_constraint_add_exec(bContext *C, wmOperator *op)
1154 {
1155         ScrArea *sa= CTX_wm_area(C);
1156         Object *ob;
1157         int type= RNA_enum_get(op->ptr, "type");
1158         short with_targets= 0;
1159         
1160         /* get active object from context */
1161         if (sa->spacetype == SPACE_BUTS)
1162                 ob= CTX_data_pointer_get_type(C, "object", &RNA_Object).data;
1163         else
1164                 ob= CTX_data_active_object(C);
1165         
1166         if (!ob) {
1167                 BKE_report(op->reports, RPT_ERROR, "No active object to add constraint to.");
1168                 return OPERATOR_CANCELLED;
1169         }
1170                 
1171         /* hack: set constraint targets from selected objects in context is allowed when
1172          *              operator name included 'with_targets', since the menu doesn't allow multiple properties
1173          */
1174         if (strstr(op->idname, "with_targets"))
1175                 with_targets= 1;
1176         
1177         return constraint_add_exec(C, op, ob, get_active_constraints(ob), type, with_targets);
1178 }
1179
1180 /* ------------------ */
1181
1182 void OBJECT_OT_constraint_add(wmOperatorType *ot)
1183 {
1184         /* identifiers */
1185         ot->name= "Add Constraint";
1186         ot->description = "Add a constraint to the active object.";
1187         ot->idname= "OBJECT_OT_constraint_add";
1188         
1189         /* api callbacks */
1190         ot->invoke= WM_menu_invoke;
1191         ot->exec= object_constraint_add_exec;
1192         ot->poll= ED_operator_object_active;
1193         
1194         /* flags */
1195         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1196         
1197         /* properties */
1198         RNA_def_enum(ot->srna, "type", constraint_type_items, 0, "Type", "");
1199 }
1200
1201 void OBJECT_OT_constraint_add_with_targets(wmOperatorType *ot)
1202 {
1203         /* identifiers */
1204         ot->name= "Add Constraint (with Targets)";
1205         ot->description = "Add a constraint to the active object, with target (where applicable) set to the selected Objects/Bones.";
1206         ot->idname= "OBJECT_OT_constraint_add_with_targets";
1207         
1208         /* api callbacks */
1209         ot->invoke= WM_menu_invoke;
1210         ot->exec= object_constraint_add_exec;
1211         ot->poll= ED_operator_object_active;
1212         
1213         /* flags */
1214         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1215         
1216         /* properties */
1217         RNA_def_enum(ot->srna, "type", constraint_type_items, 0, "Type", "");
1218 }
1219
1220 void POSE_OT_constraint_add(wmOperatorType *ot)
1221 {
1222         /* identifiers */
1223         ot->name= "Add Constraint";
1224         ot->description = "Add a constraint to the active bone.";
1225         ot->idname= "POSE_OT_constraint_add";
1226         
1227         /* api callbacks */
1228         ot->invoke= WM_menu_invoke;
1229         ot->exec= pose_constraint_add_exec;
1230         ot->poll= ED_operator_posemode;
1231         
1232         /* flags */
1233         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1234         
1235         /* properties */
1236         RNA_def_enum(ot->srna, "type", constraint_type_items, 0, "Type", "");
1237 }
1238
1239 void POSE_OT_constraint_add_with_targets(wmOperatorType *ot)
1240 {
1241         /* identifiers */
1242         ot->name= "Add Constraint (with Targets)";
1243         ot->description = "Add a constraint to the active bone, with target (where applicable) set to the selected Objects/Bones.";
1244         ot->idname= "POSE_OT_constraint_add_with_targets";
1245         
1246         /* api callbacks */
1247         ot->invoke= WM_menu_invoke;
1248         ot->exec= pose_constraint_add_exec;
1249         ot->poll= ED_operator_posemode;
1250         
1251         /* flags */
1252         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1253         
1254         /* properties */
1255         RNA_def_enum(ot->srna, "type", constraint_type_items, 0, "Type", "");
1256 }
1257
1258 /************************ IK Constraint operators *********************/
1259 /* NOTE: only for Pose-Channels */
1260 // TODO: should these be here, or back in editors/armature/poseobject.c again?
1261
1262 /* present menu with options + validation for targets to use */
1263 static int pose_ik_add_invoke(bContext *C, wmOperator *op, wmEvent *evt)
1264 {
1265         Object *ob= CTX_data_active_object(C);
1266         bPoseChannel *pchan= get_active_posechannel(ob);
1267         bConstraint *con= NULL;
1268         
1269         uiPopupMenu *pup;
1270         uiLayout *layout;
1271         Object *tar_ob= NULL;
1272         bPoseChannel *tar_pchan= NULL;
1273         
1274         /* must have active bone */
1275         if (ELEM(NULL, ob, pchan)) {
1276                 BKE_report(op->reports, RPT_ERROR, "Must have active bone to add IK Constraint to.");
1277                 return OPERATOR_CANCELLED;
1278         }
1279         
1280         /* bone must not have any constraints already */
1281         for (con= pchan->constraints.first; con; con= con->next) {
1282                 if (con->type==CONSTRAINT_TYPE_KINEMATIC) break;
1283         }
1284         if (con) {
1285                 BKE_report(op->reports, RPT_ERROR, "Bone already has IK Constraint.");
1286                 return OPERATOR_CANCELLED;
1287         }
1288         
1289         /* prepare popup menu to choose targetting options */
1290         pup= uiPupMenuBegin(C, "Add IK", 0);
1291         layout= uiPupMenuLayout(pup);
1292         
1293         /* the type of targets we'll set determines the menu entries to show... */
1294         if (get_new_constraint_target(C, CONSTRAINT_TYPE_KINEMATIC, &tar_ob, &tar_pchan, 0)) {
1295                 /* bone target, or object target? 
1296                  *      - the only thing that matters is that we want a target...
1297                  */
1298                 if (tar_pchan)
1299                         uiItemBooleanO(layout, "To Active Bone", 0, "POSE_OT_ik_add", "with_targets", 1);
1300                 else
1301                         uiItemBooleanO(layout, "To Active Object", 0, "POSE_OT_ik_add", "with_targets", 1);
1302         }
1303         else {
1304                 /* we have a choice of adding to a new empty, or not setting any target (targetless IK) */
1305                 uiItemBooleanO(layout, "To New Empty Object", 0, "POSE_OT_ik_add", "with_targets", 1);
1306                 uiItemBooleanO(layout, "Without Targets", 0, "POSE_OT_ik_add", "with_targets", 0);
1307         }
1308         
1309         /* finish building the menu, and process it (should result in calling self again) */
1310         uiPupMenuEnd(C, pup);
1311         
1312         return OPERATOR_CANCELLED;
1313 }
1314
1315 /* call constraint_add_exec() to add the IK constraint */
1316 static int pose_ik_add_exec(bContext *C, wmOperator *op)
1317 {
1318         Object *ob= CTX_data_active_object(C);
1319         int with_targets= RNA_boolean_get(op->ptr, "with_targets");
1320         
1321         /* add the constraint - all necessary checks should have been done by the invoke() callback already... */
1322         return constraint_add_exec(C, op, ob, get_active_constraints(ob), CONSTRAINT_TYPE_KINEMATIC, with_targets);
1323 }
1324
1325 void POSE_OT_ik_add(wmOperatorType *ot)
1326 {
1327         /* identifiers */
1328         ot->name= "Add IK to Bone";
1329         ot->description= "Add IK Constraint to the active Bone.";
1330         ot->idname= "POSE_OT_ik_add";
1331         
1332         /* api callbacks */
1333         ot->invoke= pose_ik_add_invoke;
1334         ot->exec= pose_ik_add_exec;
1335         ot->poll= ED_operator_posemode;
1336         
1337         /* flags */
1338         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1339         
1340         /* properties */
1341         RNA_def_boolean(ot->srna, "with_targets", 1, "With Targets", "Assign IK Constraint with targets derived from the select bones/objects");
1342 }
1343
1344 /* ------------------ */
1345
1346 /* remove IK constraints from selected bones */
1347 static int pose_ik_clear_exec(bContext *C, wmOperator *op)
1348 {
1349         Scene *scene = CTX_data_scene(C);
1350         Object *ob= CTX_data_active_object(C);
1351         
1352         /* only remove IK Constraints */
1353         CTX_DATA_BEGIN(C, bPoseChannel*, pchan, selected_pchans) 
1354         {
1355                 bConstraint *con, *next;
1356                 
1357                 // TODO: should we be checking if these contraints were local before we try and remove them?
1358                 for (con= pchan->constraints.first; con; con= next) {
1359                         next= con->next;
1360                         if (con->type==CONSTRAINT_TYPE_KINEMATIC) {
1361                                 free_constraint_data(con);
1362                                 BLI_freelinkN(&pchan->constraints, con);
1363                         }
1364                 }
1365                 pchan->constflag &= ~(PCHAN_HAS_IK|PCHAN_HAS_TARGET);
1366         }
1367         CTX_DATA_END;
1368         
1369         /* */
1370         DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
1371
1372         /* note, notifier might evolve */
1373         WM_event_add_notifier(C, NC_OBJECT|ND_CONSTRAINT|NA_REMOVED, ob);
1374         
1375         return OPERATOR_FINISHED;
1376 }
1377
1378 void POSE_OT_ik_clear(wmOperatorType *ot)
1379 {
1380         /* identifiers */
1381         ot->name= "Remove IK";
1382         ot->description= "Remove all IK Constraints from selected bones.";
1383         ot->idname= "POSE_OT_ik_clear";
1384         
1385         /* api callbacks */
1386         ot->exec= pose_ik_clear_exec;
1387         ot->poll= ED_operator_posemode;
1388         
1389         /* flags */
1390         ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
1391 }