2.50: svn merge https://svn.blender.org/svnroot/bf-blender/trunk/blender -r18677...
[blender.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_depsgraph.h"
53 #include "BKE_global.h"
54 #include "BKE_main.h"
55 #include "BKE_object.h"
56 #include "BKE_utildefines.h"
57
58 #ifndef DISABLE_PYTHON
59 #include "BPY_extern.h"
60 #endif
61
62 #include "ED_object.h"
63
64 #include "object_intern.h"
65
66 /* XXX */
67 static void BIF_undo_push() {}
68 static void error() {}
69 static int okee() {return 0;}
70 static int pupmenu() {return 0;}
71
72 /* -------------- Get Active Constraint Data ---------------------- */
73
74
75 /* if object in posemode, active bone constraints, else object constraints */
76 ListBase *get_active_constraints (Object *ob)
77 {
78         if (ob == NULL)
79                 return NULL;
80
81         if (ob->flag & OB_POSEMODE) {
82                 bPoseChannel *pchan;
83                 
84                 pchan = get_active_posechannel(ob);
85                 if (pchan)
86                         return &pchan->constraints;
87         }
88         else 
89                 return &ob->constraints;
90
91         return NULL;
92 }
93
94 /* single constraint */
95 bConstraint *get_active_constraint (Object *ob)
96 {
97         ListBase *lb= get_active_constraints(ob);
98
99         if (lb) {
100                 bConstraint *con;
101                 
102                 for (con= lb->first; con; con=con->next) {
103                         if (con->flag & CONSTRAINT_ACTIVE)
104                                 return con;
105                 }
106         }
107         
108         return NULL;
109 }
110
111 /* single channel, for ipo */
112 bConstraintChannel *get_active_constraint_channel (Scene *scene, Object *ob)
113 {
114         bConstraint *con;
115         
116         if (ob->flag & OB_POSEMODE) {
117                 //if (ob->action) { // XXX old animation system
118                         bPoseChannel *pchan;
119                         
120                         pchan = get_active_posechannel(ob);
121                         if (pchan) {
122                                 for (con= pchan->constraints.first; con; con= con->next) {
123                                         if (con->flag & CONSTRAINT_ACTIVE)
124                                                 break;
125                                 }
126                                 
127                                 if (con) {
128 #if 0 // XXX old animation system
129                                         bActionChannel *achan = get_action_channel(ob->action, pchan->name);
130                                         if (achan) {
131                                                 for (chan= achan->constraintChannels.first; chan; chan= chan->next) {
132                                                         if (!strcmp(chan->name, con->name))
133                                                                 break;
134                                                 }
135                                                 return chan;
136                                         }
137 #endif // XXX old animation system
138                                 }
139                         }
140                 //} // xxx old animation system
141         }
142         else {
143                 for (con= ob->constraints.first; con; con= con->next) {
144                         if (con->flag & CONSTRAINT_ACTIVE)
145                                 break;
146                 }
147                 
148                 if (con) {
149 #if 0 // XXX old animation system
150                         ListBase *lb= get_active_constraint_channels(scene, ob, 0);
151                         
152                         if (lb) {
153                                 for (chan= lb->first; chan; chan= chan->next) {
154                                         if (!strcmp(chan->name, con->name))
155                                                 break;
156                                 }
157                                 
158                                 return chan;
159                         }
160 #endif // XXX old animation system
161                 }
162         }
163         
164         return NULL;
165 }
166
167 /* -------------- Constraint Management (Add New, Remove, Rename) -------------------- */
168 /* ------------- PyConstraints ------------------ */
169
170 /* this callback sets the text-file to be used for selected menu item */
171 void validate_pyconstraint_cb (void *arg1, void *arg2)
172 {
173         bPythonConstraint *data = arg1;
174         Text *text= NULL;
175         int index = *((int *)arg2);
176         int i;
177         
178         /* exception for no script */
179         if (index) {
180                 /* innovative use of a for...loop to search */
181                 for (text=G.main->text.first, i=1; text && index!=i; i++, text=text->id.next);
182         }
183         data->text = text;
184 }
185
186 #ifndef DISABLE_PYTHON
187 /* this returns a string for the list of usable pyconstraint script names */
188 char *buildmenu_pyconstraints (Text *con_text, int *pyconindex)
189 {
190         DynStr *pupds= BLI_dynstr_new();
191         Text *text;
192         char *str;
193         char buf[64];
194         int i;
195         
196         /* add title first */
197         sprintf(buf, "Scripts: %%t|[None]%%x0|");
198         BLI_dynstr_append(pupds, buf);
199         
200         /* init active-index first */
201         if (con_text == NULL)
202                 *pyconindex= 0;
203         
204         /* loop through markers, adding them */
205         for (text=G.main->text.first, i=1; text; i++, text=text->id.next) {
206                 /* this is important to ensure that right script is shown as active */
207                 if (text == con_text) *pyconindex = i;
208                 
209                 /* only include valid pyconstraint scripts */
210                 if (BPY_is_pyconstraint(text)) {
211                         BLI_dynstr_append(pupds, text->id.name+2);
212                         
213                         sprintf(buf, "%%x%d", i);
214                         BLI_dynstr_append(pupds, buf);
215                         
216                         if (text->id.next)
217                                 BLI_dynstr_append(pupds, "|");
218                 }
219         }
220         
221         /* convert to normal MEM_malloc'd string */
222         str= BLI_dynstr_get_cstring(pupds);
223         BLI_dynstr_free(pupds);
224         
225         return str;
226 }
227 #endif /* DISABLE_PYTHON */
228
229 /* this callback gets called when the 'refresh' button of a pyconstraint gets pressed */
230 void update_pyconstraint_cb (void *arg1, void *arg2)
231 {
232         Object *owner= (Object *)arg1;
233         bConstraint *con= (bConstraint *)arg2;
234 #ifndef DISABLE_PYTHON
235         if (owner && con)
236                 BPY_pyconstraint_update(owner, con);
237 #endif
238 }
239
240 /* Creates a new constraint, initialises its data, and returns it */
241 bConstraint *add_new_constraint (short type)
242 {
243         bConstraint *con;
244         bConstraintTypeInfo *cti;
245
246         con = MEM_callocN(sizeof(bConstraint), "Constraint");
247         
248         /* Set up a generic constraint datablock */
249         con->type = type;
250         con->flag |= CONSTRAINT_EXPAND;
251         con->enforce = 1.0F;
252         strcpy(con->name, "Const");
253         
254         /* Load the data for it */
255         cti = constraint_get_typeinfo(con);
256         if (cti) {
257                 con->data = MEM_callocN(cti->size, cti->structName);
258                 
259                 /* only constraints that change any settings need this */
260                 if (cti->new_data)
261                         cti->new_data(con->data);
262         }
263         
264         return con;
265 }
266
267 /* Adds the given constraint to the Object-level set of constraints for the given Object */
268 void add_constraint_to_object (bConstraint *con, Object *ob)
269 {
270         ListBase *list;
271         list = &ob->constraints;
272         
273         if (list) {
274                 unique_constraint_name(con, list);
275                 BLI_addtail(list, con);
276                 
277                 if (proxylocked_constraints_owner(ob, NULL))
278                         con->flag |= CONSTRAINT_PROXY_LOCAL;
279                 
280                 con->flag |= CONSTRAINT_ACTIVE;
281                 for (con= con->prev; con; con= con->prev)
282                         con->flag &= ~CONSTRAINT_ACTIVE;
283         }
284 }
285
286 /* helper function for add_constriant - sets the last target for the active constraint */
287 static void set_constraint_nth_target (bConstraint *con, Object *target, char subtarget[], int index)
288 {
289         bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
290         ListBase targets = {NULL, NULL};
291         bConstraintTarget *ct;
292         int num_targets, i;
293         
294         if (cti && cti->get_constraint_targets) {
295                 cti->get_constraint_targets(con, &targets);
296                 num_targets= BLI_countlist(&targets);
297                 
298                 if (index < 0) {
299                         if (abs(index) < num_targets)
300                                 index= num_targets - abs(index);
301                         else
302                                 index= num_targets - 1;
303                 }
304                 else if (index >= num_targets) {
305                         index= num_targets - 1;
306                 }
307                 
308                 for (ct=targets.first, i=0; ct; ct= ct->next, i++) {
309                         if (i == index) {
310                                 ct->tar= target;
311                                 strcpy(ct->subtarget, subtarget);
312                                 break;
313                         }
314                 }
315                 
316                 if (cti->flush_constraint_targets)
317                         cti->flush_constraint_targets(con, &targets, 0);
318         }
319 }
320
321 /* context: active object in posemode, active channel, optional selected channel */
322 void add_constraint (Scene *scene, View3D *v3d, short only_IK)
323 {
324         Object *ob= OBACT, *obsel=NULL;
325         bPoseChannel *pchanact=NULL, *pchansel=NULL;
326         bConstraint *con=NULL;
327         Base *base;
328         short nr;
329         
330         /* paranoia checks */
331         if ((ob==NULL) || (ob==scene->obedit)) 
332                 return;
333
334         if ((ob->pose) && (ob->flag & OB_POSEMODE)) {
335                 bArmature *arm= ob->data;
336                 
337                 /* find active channel */
338                 pchanact= get_active_posechannel(ob);
339                 if (pchanact==NULL) 
340                         return;
341                 
342                 /* find selected bone */
343                 for (pchansel=ob->pose->chanbase.first; pchansel; pchansel=pchansel->next) {
344                         if (pchansel != pchanact) {
345                                 if (pchansel->bone->flag & BONE_SELECTED)  {
346                                         if (pchansel->bone->layer & arm->layer)
347                                                 break;
348                                 }
349                         }
350                 }
351         }
352         
353         /* find selected object */
354         for (base= FIRSTBASE; base; base= base->next) {
355                 if ((TESTBASE(v3d, base)) && (base->object!=ob)) 
356                         obsel= base->object;
357         }
358         
359         /* the only_IK caller has checked for posemode! */
360         if (only_IK) {
361                 for (con= pchanact->constraints.first; con; con= con->next) {
362                         if (con->type==CONSTRAINT_TYPE_KINEMATIC) break;
363                 }
364                 if (con) {
365                         error("Pose Channel already has IK");
366                         return;
367                 }
368                 
369                 if (pchansel)
370                         nr= pupmenu("Add IK Constraint%t|To Active Bone%x10");
371                 else if (obsel)
372                         nr= pupmenu("Add IK Constraint%t|To Active Object%x10");
373                 else 
374                         nr= pupmenu("Add IK Constraint%t|To New Empty Object%x10|Without Target%x11");
375         }
376         else {
377                 if (pchanact) {
378                         if (pchansel)
379                                 nr= pupmenu("Add Constraint to Active Bone%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|Limit Distance%x21|%l|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7|%l|Action%x16|Script%x18");
380                         else if ((obsel) && (obsel->type==OB_CURVE))
381                                 nr= pupmenu("Add Constraint to Active Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|Limit Distance%x21|%l|Track To%x3|Floor%x4|Locked Track%x5|Follow Path%x6|Clamp To%x17|Stretch To%x7|%l|Action%x16|Script%x18");
382                         else if (obsel)
383                                 nr= pupmenu("Add Constraint to Active Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|Limit Distance%x21|%l|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7|%l|Action%x16|Script%x18");
384                         else
385                                 nr= pupmenu("Add Constraint to New Empty Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|Limit Distance%x21|%l|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7|%l|Action%x16|Script%x18");
386                 }
387                 else {
388                         if ((obsel) && (obsel->type==OB_CURVE))
389                                 nr= pupmenu("Add Constraint to Active Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|Limit Distance%x21|%l|Track To%x3|Floor%x4|Locked Track%x5|Follow Path%x6|Clamp To%x17|%l|Action%x16|Script%x18");
390                         else if (obsel)
391                                 nr= pupmenu("Add Constraint to Active Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|Limit Distance%x21|%l|Track To%x3|Floor%x4|Locked Track%x5|%l|Action%x16|Script%x18");
392                         else
393                                 nr= pupmenu("Add Constraint to New Empty Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|Limit Distance%x21|%l|Track To%x3|Floor%x4|Locked Track%x5|%l|Action%x16|Script%x18");
394                 }
395         }
396         
397         if (nr < 1) return;
398         
399         /* handle IK separate */
400         if (nr==10 || nr==11) {
401                 /* ik - prevent weird chains... */
402                 if (pchansel) {
403                         bPoseChannel *pchan= pchanact;
404                         while (pchan) {
405                                 if (pchan==pchansel) break;
406                                 pchan= pchan->parent;
407                         }
408                         if (pchan) {
409                                 error("IK root cannot be linked to IK tip");
410                                 return;
411                         }
412                         
413                         pchan= pchansel;
414                         while (pchan) {
415                                 if (pchan==pchanact) break;
416                                 pchan= pchan->parent;
417                         }
418                         if (pchan) {
419                                 error("IK tip cannot be linked to IK root");
420                                 return;
421                         }               
422                 }
423                 
424                 con = add_new_constraint(CONSTRAINT_TYPE_KINEMATIC);
425                 BLI_addtail(&pchanact->constraints, con);
426                 unique_constraint_name(con, &pchanact->constraints);
427                 pchanact->constflag |= PCHAN_HAS_IK;    /* for draw, but also for detecting while pose solving */
428                 if (nr==11) 
429                         pchanact->constflag |= PCHAN_HAS_TARGET;
430                 if (proxylocked_constraints_owner(ob, pchanact))
431                         con->flag |= CONSTRAINT_PROXY_LOCAL;
432         }
433         else {
434                 /* normal constraints - add data */
435                 if (nr==1) con = add_new_constraint(CONSTRAINT_TYPE_LOCLIKE);
436                 else if (nr==2) con = add_new_constraint(CONSTRAINT_TYPE_ROTLIKE);
437                 else if (nr==3) con = add_new_constraint(CONSTRAINT_TYPE_TRACKTO);
438                 else if (nr==4) con = add_new_constraint(CONSTRAINT_TYPE_MINMAX);
439                 else if (nr==5) con = add_new_constraint(CONSTRAINT_TYPE_LOCKTRACK);
440                 else if (nr==6) {
441                         Curve *cu= obsel->data;
442                         cu->flag |= CU_PATH;
443                         con = add_new_constraint(CONSTRAINT_TYPE_FOLLOWPATH);
444                 }
445                 else if (nr==7) con = add_new_constraint(CONSTRAINT_TYPE_STRETCHTO);
446                 else if (nr==8) con = add_new_constraint(CONSTRAINT_TYPE_SIZELIKE);
447                 else if (nr==13) con = add_new_constraint(CONSTRAINT_TYPE_LOCLIMIT);
448                 else if (nr==14) con = add_new_constraint(CONSTRAINT_TYPE_ROTLIMIT);
449                 else if (nr==15) con = add_new_constraint(CONSTRAINT_TYPE_SIZELIMIT);
450                 else if (nr==16) {
451                         /* TODO: add a popup-menu to display list of available actions to use (like for pyconstraints) */
452                         con = add_new_constraint(CONSTRAINT_TYPE_ACTION);
453                 }
454                 else if (nr==17) {
455                         Curve *cu= obsel->data;
456                         cu->flag |= CU_PATH;
457                         con = add_new_constraint(CONSTRAINT_TYPE_CLAMPTO);
458                 }
459                 else if (nr==18) {      
460                         char *menustr;
461                         int scriptint= 0;
462 #ifndef DISABLE_PYTHON
463                         /* popup a list of usable scripts */
464                         menustr = buildmenu_pyconstraints(NULL, &scriptint);
465                         scriptint = pupmenu(menustr);
466                         MEM_freeN(menustr);
467                         
468                         /* only add constraint if a script was chosen */
469                         if (scriptint) {
470                                 /* add constraint */
471                                 con = add_new_constraint(CONSTRAINT_TYPE_PYTHON);
472                                 validate_pyconstraint_cb(con->data, &scriptint);
473                                 
474                                 /* make sure target allowance is set correctly */
475                                 BPY_pyconstraint_update(ob, con);
476                         }
477 #endif
478                 }
479                 else if (nr==19) {
480                         con = add_new_constraint(CONSTRAINT_TYPE_CHILDOF);
481                 
482                         /* if this constraint is being added to a posechannel, make sure
483                          * the constraint gets evaluated in pose-space
484                          */
485                         if (pchanact) {
486                                 con->ownspace = CONSTRAINT_SPACE_POSE;
487                                 con->flag |= CONSTRAINT_SPACEONCE;
488                         }
489                 }
490                 else if (nr==20) con = add_new_constraint(CONSTRAINT_TYPE_TRANSFORM);
491                 else if (nr==21) con = add_new_constraint(CONSTRAINT_TYPE_DISTLIMIT);
492                 
493                 if (con==NULL) return;  /* paranoia */
494                 
495                 if (pchanact) {
496                         BLI_addtail(&pchanact->constraints, con);
497                         unique_constraint_name(con, &pchanact->constraints);
498                         pchanact->constflag |= PCHAN_HAS_CONST; /* for draw */
499                         if (proxylocked_constraints_owner(ob, pchanact))
500                                 con->flag |= CONSTRAINT_PROXY_LOCAL;
501                 }
502                 else {
503                         BLI_addtail(&ob->constraints, con);
504                         unique_constraint_name(con, &ob->constraints);
505                         if (proxylocked_constraints_owner(ob, NULL))
506                                 con->flag |= CONSTRAINT_PROXY_LOCAL;
507                 }
508         }
509         
510         /* set the target */
511         if (pchansel) {
512                 set_constraint_nth_target(con, ob, pchansel->name, 0);
513         }
514         else if (obsel) {
515                 set_constraint_nth_target(con, obsel, "", 0);
516         }
517         else if (ELEM4(nr, 11, 13, 14, 15)==0) {        /* add new empty as target */
518                 Base *base= BASACT, *newbase;
519                 Object *obt;
520                 
521                 obt= add_object(scene, OB_EMPTY);
522                 /* set layers OK */
523                 newbase= BASACT;
524                 newbase->lay= base->lay;
525                 obt->lay= newbase->lay;
526                 
527                 /* transform cent to global coords for loc */
528                 if (pchanact) {
529                         if (only_IK)
530                                 VecMat4MulVecfl(obt->loc, ob->obmat, pchanact->pose_tail);
531                         else
532                                 VecMat4MulVecfl(obt->loc, ob->obmat, pchanact->pose_head);
533                 }
534                 else
535                         VECCOPY(obt->loc, ob->obmat[3]);
536                 
537                 set_constraint_nth_target(con, obt, "", 0);
538                 
539                 /* restore, add_object sets active */
540                 BASACT= base;
541                 base->flag |= SELECT;
542         }
543         
544         /* active flag */
545         con->flag |= CONSTRAINT_ACTIVE;
546         for (con= con->prev; con; con= con->prev)
547                 con->flag &= ~CONSTRAINT_ACTIVE;
548
549         DAG_scene_sort(scene);          // sort order of objects
550         
551         if (pchanact) {
552                 ob->pose->flag |= POSE_RECALC;  // sort pose channels
553                 DAG_object_flush_update(scene, ob, OB_RECALC_DATA);     // and all its relations
554         }
555         else
556                 DAG_object_flush_update(scene, ob, OB_RECALC_OB);       // and all its relations
557
558         if (only_IK)
559                 BIF_undo_push("Add IK Constraint");
560         else
561                 BIF_undo_push("Add Constraint");
562
563 }
564
565 /* Remove all constraints from the active object */
566 void ob_clear_constraints (Scene *scene)
567 {
568         Object *ob= OBACT;
569         
570         /* paranoia checks */
571         if ((ob==NULL) || (ob==scene->obedit) || (ob->flag & OB_POSEMODE)) 
572                 return;
573         
574         /* get user permission */
575         if (okee("Clear Constraints")==0) 
576                 return;
577         
578         /* do freeing */
579         free_constraints(&ob->constraints);
580         
581         /* do updates */
582         DAG_object_flush_update(scene, ob, OB_RECALC_OB);
583         
584         BIF_undo_push("Clear Constraint(s)");
585 }
586
587 /* Rename the given constraint 
588  *      - con already has the new name 
589  */
590 void rename_constraint (Object *ob, bConstraint *con, char *oldname)
591 {
592         bConstraint *tcon;
593         ListBase *conlist= NULL;
594         int from_object= 0;
595         char *channame="";
596         
597         /* get context by searching for con (primitive...) */
598         for (tcon= ob->constraints.first; tcon; tcon= tcon->next) {
599                 if (tcon==con)
600                         break;
601         }
602         
603         if (tcon) {
604                 conlist= &ob->constraints;
605                 channame= "Object";
606                 from_object= 1;
607         }
608         else if (ob->pose) {
609                 bPoseChannel *pchan;
610                 
611                 for (pchan=ob->pose->chanbase.first; pchan; pchan=pchan->next) {
612                         for (tcon= pchan->constraints.first; tcon; tcon= tcon->next) {
613                                 if (tcon==con)
614                                         break;
615                         }
616                         if (tcon) 
617                                 break;
618                 }
619                 
620                 if (tcon) {
621                         conlist= &pchan->constraints;
622                         channame= pchan->name;
623                 }
624         }
625         
626         if (conlist==NULL) {
627                 printf("rename constraint failed\n");   /* should not happen in UI */
628                 return;
629         }
630         
631         /* first make sure it's a unique name within context */
632         unique_constraint_name (con, conlist);
633 }
634
635
636 /* ------------- Constraint Sanity Testing ------------------- */
637
638 /* checks validity of object pointers, and NULLs,
639  * if Bone doesnt exist it sets the CONSTRAINT_DISABLE flag 
640  */
641 static void test_constraints (Object *owner, const char substring[])
642 {
643         bConstraint *curcon;
644         ListBase *conlist= NULL;
645         int type;
646         
647         if (owner==NULL) return;
648         
649         /* Check parents */
650         if (strlen(substring)) {
651                 switch (owner->type) {
652                         case OB_ARMATURE:
653                                 type = CONSTRAINT_OBTYPE_BONE;
654                                 break;
655                         default:
656                                 type = CONSTRAINT_OBTYPE_OBJECT;
657                                 break;
658                 }
659         }
660         else
661                 type = CONSTRAINT_OBTYPE_OBJECT;
662         
663         /* Get the constraint list for this object */
664         switch (type) {
665                 case CONSTRAINT_OBTYPE_OBJECT:
666                         conlist = &owner->constraints;
667                         break;
668                 case CONSTRAINT_OBTYPE_BONE:
669                         {
670                                 Bone *bone;
671                                 bPoseChannel *chan;
672                                 
673                                 bone = get_named_bone( ((bArmature *)owner->data), substring );
674                                 chan = get_pose_channel(owner->pose, substring);
675                                 if (bone && chan) {
676                                         conlist = &chan->constraints;
677                                 }
678                         }
679                         break;
680         }
681         
682         /* Check all constraints - is constraint valid? */
683         if (conlist) {
684                 for (curcon = conlist->first; curcon; curcon=curcon->next) {
685                         bConstraintTypeInfo *cti= constraint_get_typeinfo(curcon);
686                         ListBase targets = {NULL, NULL};
687                         bConstraintTarget *ct;
688                         
689                         /* clear disabled-flag first */
690                         curcon->flag &= ~CONSTRAINT_DISABLE;
691
692                         if (curcon->type == CONSTRAINT_TYPE_KINEMATIC) {
693                                 bKinematicConstraint *data = curcon->data;
694                                 
695                                 /* bad: we need a separate set of checks here as poletarget is 
696                                  *              optional... otherwise poletarget must exist too or else
697                                  *              the constraint is deemed invalid
698                                  */
699                                 if (exist_object(data->tar) == 0) {
700                                         data->tar = NULL;
701                                         curcon->flag |= CONSTRAINT_DISABLE;
702                                 }
703                                 else if (data->tar == owner) {
704                                         if (!get_named_bone(get_armature(owner), data->subtarget)) {
705                                                 curcon->flag |= CONSTRAINT_DISABLE;
706                                         }
707                                 }
708                                 
709                                 if (data->poletar) {
710                                         if (exist_object(data->poletar) == 0) {
711                                                 data->poletar = NULL;
712                                                 curcon->flag |= CONSTRAINT_DISABLE;
713                                         }
714                                         else if (data->poletar == owner) {
715                                                 if (!get_named_bone(get_armature(owner), data->polesubtarget)) {
716                                                         curcon->flag |= CONSTRAINT_DISABLE;
717                                                 }
718                                         }
719                                 }
720                                 
721                                 /* targets have already been checked for this */
722                                 continue;
723                         }
724                         else if (curcon->type == CONSTRAINT_TYPE_ACTION) {
725                                 bActionConstraint *data = curcon->data;
726                                 
727                                 /* validate action */
728                                 if (data->act == NULL) 
729                                         curcon->flag |= CONSTRAINT_DISABLE;
730                         }
731                         else if (curcon->type == CONSTRAINT_TYPE_FOLLOWPATH) {
732                                 bFollowPathConstraint *data = curcon->data;
733                                 
734                                 /* don't allow track/up axes to be the same */
735                                 if (data->upflag==data->trackflag)
736                                         curcon->flag |= CONSTRAINT_DISABLE;
737                                 if (data->upflag+3==data->trackflag)
738                                         curcon->flag |= CONSTRAINT_DISABLE;
739                         }
740                         else if (curcon->type == CONSTRAINT_TYPE_TRACKTO) {
741                                 bTrackToConstraint *data = curcon->data;
742                                 
743                                 /* don't allow track/up axes to be the same */
744                                 if (data->reserved2==data->reserved1)
745                                         curcon->flag |= CONSTRAINT_DISABLE;
746                                 if (data->reserved2+3==data->reserved1)
747                                         curcon->flag |= CONSTRAINT_DISABLE;
748                         }
749                         else if (curcon->type == CONSTRAINT_TYPE_LOCKTRACK) {
750                                 bLockTrackConstraint *data = curcon->data;
751                                 
752                                 if (data->lockflag==data->trackflag)
753                                         curcon->flag |= CONSTRAINT_DISABLE;
754                                 if (data->lockflag+3==data->trackflag)
755                                         curcon->flag |= CONSTRAINT_DISABLE;
756                         }
757                         
758                         /* Check targets for constraints */
759                         if (cti && cti->get_constraint_targets) {
760                                 cti->get_constraint_targets(curcon, &targets);
761                                 
762                                 /* disable and clear constraints targets that are incorrect */
763                                 for (ct= targets.first; ct; ct= ct->next) {
764                                         /* general validity checks (for those constraints that need this) */
765                                         if (exist_object(ct->tar) == 0) {
766                                                 ct->tar = NULL;
767                                                 curcon->flag |= CONSTRAINT_DISABLE;
768                                         }
769                                         else if (ct->tar == owner) {
770                                                 if (!get_named_bone(get_armature(owner), ct->subtarget)) {
771                                                         curcon->flag |= CONSTRAINT_DISABLE;
772                                                 }
773                                         }
774                                         
775                                         /* target checks for specific constraints */
776                                         if (ELEM(curcon->type, CONSTRAINT_TYPE_FOLLOWPATH, CONSTRAINT_TYPE_CLAMPTO)) {
777                                                 if (ct->tar) {
778                                                         if (ct->tar->type != OB_CURVE) {
779                                                                 ct->tar= NULL;
780                                                                 curcon->flag |= CONSTRAINT_DISABLE;
781                                                         }
782                                                         else {
783                                                                 Curve *cu= ct->tar->data;
784                                                                 
785                                                                 /* auto-set 'Path' setting on curve so this works  */
786                                                                 cu->flag |= CU_PATH;
787                                                         }
788                                                 }                                               
789                                         }
790                                 }       
791                                 
792                                 /* free any temporary targets */
793                                 if (cti->flush_constraint_targets)
794                                         cti->flush_constraint_targets(curcon, &targets, 0);
795                         }
796                 }
797         }
798 }
799
800 static void test_bonelist_constraints (Object *owner, ListBase *list)
801 {
802         Bone *bone;
803
804         for (bone = list->first; bone; bone = bone->next) {
805                 test_constraints(owner, bone->name);
806                 test_bonelist_constraints(owner, &bone->childbase);
807         }
808 }
809
810 void object_test_constraints (Object *owner)
811 {
812         test_constraints(owner, "");
813
814         if (owner->type==OB_ARMATURE) {
815                 bArmature *arm= get_armature(owner);
816                 
817                 if (arm)
818                         test_bonelist_constraints(owner, &arm->bonebase);
819         }
820 }
821
822 /* ********************** CONSTRAINT-SPECIFIC STUFF ********************* */
823
824 /* ------------- Child-Of Constraint ------------------ */
825
826 /* ChildOf Constraint - set inverse callback */
827 void childof_const_setinv (void *conv, void *scenev)
828 {
829         bConstraint *con= (bConstraint *)conv;
830         Scene *scene= (Scene *)scenev;
831         bChildOfConstraint *data= (bChildOfConstraint *)con->data;
832         Object *ob= OBACT;
833         bPoseChannel *pchan= NULL;
834
835         /* try to find a pose channel */
836         if (ob && ob->pose)
837                 pchan= get_active_posechannel(ob);
838         
839         /* calculate/set inverse matrix */
840         if (pchan) {
841                 float pmat[4][4], cinf;
842                 float imat[4][4], tmat[4][4];
843                 
844                 /* make copy of pchan's original pose-mat (for use later) */
845                 Mat4CpyMat4(pmat, pchan->pose_mat);
846                 
847                 /* disable constraint for pose to be solved without it */
848                 cinf= con->enforce;
849                 con->enforce= 0.0f;
850                 
851                 /* solve pose without constraint */
852                 where_is_pose(scene, ob);
853                 
854                 /* determine effect of constraint by removing the newly calculated 
855                  * pchan->pose_mat from the original pchan->pose_mat, thus determining 
856                  * the effect of the constraint
857                  */
858                 Mat4Invert(imat, pchan->pose_mat);
859                 Mat4MulMat4(tmat, imat, pmat);
860                 Mat4Invert(data->invmat, tmat);
861                 
862                 /* recalculate pose with new inv-mat */
863                 con->enforce= cinf;
864                 where_is_pose(scene, ob);
865         }
866         else if (ob) {
867                 Object workob;
868                 /* use what_does_parent to find inverse - just like for normal parenting.
869                  * NOTE: what_does_parent uses a static workob defined in object.c 
870                  */
871                 what_does_parent(scene, ob, &workob);
872                 Mat4Invert(data->invmat, workob.obmat);
873         }
874         else
875                 Mat4One(data->invmat);
876 }
877
878 /* ChildOf Constraint - clear inverse callback */
879 void childof_const_clearinv (void *conv, void *unused)
880 {
881         bConstraint *con= (bConstraint *)conv;
882         bChildOfConstraint *data= (bChildOfConstraint *)con->data;
883         
884         /* simply clear the matrix */
885         Mat4One(data->invmat);
886 }