Fixed the lag with Follow Path and optimized constraint loops with Track To and Lock...
[blender.git] / source / blender / src / editconstraint.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL/BL DUAL 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. The Blender
10  * Foundation also sells licenses for use in proprietary software under
11  * the Blender License.  See http://www.blender.org/BL/ for information
12  * about this.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software Foundation,
21  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22  *
23  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
24  * All rights reserved.
25  *
26  * The Original Code is: all of this file.
27  *
28  * Contributor(s): none yet.
29  *
30  * ***** END GPL/BL DUAL LICENSE BLOCK *****
31  */
32
33 #include <stdio.h>
34 #include <string.h>
35
36 #include "MEM_guardedalloc.h"
37
38 #include "BLI_blenlib.h"
39
40 #include "DNA_action_types.h"
41 #include "DNA_armature_types.h"
42 #include "DNA_object_types.h"
43 #include "DNA_scene_types.h"
44 #include "DNA_screen_types.h"
45 #include "DNA_constraint_types.h"
46 #include "DNA_curve_types.h"
47
48 #include "BKE_utildefines.h"
49 #include "BKE_action.h"
50 #include "BKE_armature.h"
51 #include "BKE_object.h"
52 #include "BKE_global.h"
53 #include "BKE_constraint.h"
54 #include "BKE_ipo.h"
55
56 #include "BIF_editarmature.h"
57 #include "BIF_editconstraint.h"
58 #include "BIF_interface.h"
59 #include "BIF_screen.h"
60 #include "BIF_toolbox.h"
61
62 #include "BSE_editaction.h"
63
64 #include "blendef.h"
65 #include "nla.h"
66
67 #ifdef HAVE_CONFIG_H
68 #include <config.h>
69 #endif
70
71 static short add_constraint_element (Object *owner, const char *substring, Object *parent, const char *parentstring);
72 static short detect_constraint_loop (Object *owner, const char* substring, int disable, char type);
73 static void test_bonelist_constraints (Object *owner, ListBase *list);
74 static void clear_object_constraint_loop_flags(Object *ob);
75 //static int is_child_of(struct Object *owner, struct Object *parent);
76 //static int is_bonechild_of(struct Bone *bone, struct Bone *parent);
77 static int is_child_of_ex(Object *owner, const char *ownersubstr, Object *parent, const char *parsubstr);
78
79 ListBase g_conBase;
80 const char *g_conString;
81 Object *g_conObj;
82
83
84 static int is_child_of_ex(Object *owner, const char *ownersubstr, Object *parent, const char *parsubstr)
85 {
86         Object *curob;
87         Bone *bone = NULL;
88         Bone *parbone= NULL;
89
90         curob=owner;
91
92         /* If this is a bone */
93         if (strlen(ownersubstr))
94                 bone = get_named_bone(get_armature(owner->parent), ownersubstr);
95         
96         if (strlen(parsubstr))
97                 parbone = get_named_bone(get_armature(parent), parsubstr);
98
99
100         /* Traverse the scene graph */
101         while (curob && !bone){
102                 switch (curob->partype){
103                 case PARBONE:
104                         if (strlen(parsubstr)){
105                                 bone = get_named_bone(get_armature(curob->parent), curob->parsubstr);
106                                 break;
107                         }
108                         /* The break is supposed to be missing */
109                 default:
110                         if (curob==parent){
111                                 if (parbone)
112                                         return 0;
113                                 else
114                                         return 1;
115                         }
116                         curob=curob->parent;
117                 }
118         }
119
120
121         /* Descend into the armature scene graph */
122         while (bone){
123                 if (bone==parbone)
124                         return 1;
125                 bone=bone->parent;
126         }
127         
128         return 0;
129 }
130 /*
131 static int is_child_of(Object *owner, Object *parent)
132 {
133         Object *curpar;
134
135         for (curpar = owner->parent; curpar; curpar=curpar->parent){
136                 if (curpar==parent)
137                         return 1;
138         }
139
140         return 0;
141 }
142
143
144 static int is_bonechild_of(Bone *bone, Bone *parent)
145 {
146         Bone *curpar;
147
148         if (!bone)
149                 return 0;
150
151         for (curpar = bone->parent; curpar; curpar=curpar->parent){
152                 if (curpar==parent)
153                         return 1;
154         }
155         return 0;
156 }
157 */
158 static short add_constraint_element (Object *owner, const char *substring, Object *parent, const char *parentstring)
159 {
160         
161         if (!owner)
162                 return 0;
163
164         /* See if this is the original object */
165         if (parent == owner){
166                 if (!strcmp (parentstring, substring))
167                                 return 1;
168         }
169
170         if (owner == g_conObj){
171                 if (!strcmp (g_conString, substring))
172                         return 1;
173         }
174
175         /* See if this is a child of the adding object */
176         if (parent){
177 //              if (is_child_of (owner, parent))
178                 if (is_child_of_ex (owner, substring, parent, parentstring))
179                         return 1;
180                 /* Parent is a bone */
181 /*              if ((owner==parent) && (owner->type == OB_ARMATURE)){
182                         if (strlen (substring) && strlen(parentstring)){
183                                 if (is_bonechild_of(get_named_bone(owner->data, substring), get_named_bone(parent->data, parentstring)))
184                                         return 1;
185                         }
186                 }
187                 */
188         }
189         return 0;
190 }
191
192 static void test_bonelist_constraints (Object *owner, ListBase *list)
193 {
194         Bone *bone;
195         Base    *base1;
196
197
198         for (bone = list->first; bone; bone=bone->next){
199                 for (base1 = G.scene->base.first; base1; base1=base1->next){
200                         clear_object_constraint_loop_flags(base1->object);
201                 }
202                 test_constraints(owner, bone->name, 1);
203                 test_bonelist_constraints (owner, &bone->childbase);
204         }
205 }
206
207
208 static void clear_object_constraint_loop_flags(Object *ob)
209 {
210         bConstraint *con;
211
212         if (!ob)
213                 return;
214
215         /* Test object constraints */
216         for (con = ob->constraints.first; con; con=con->next){
217                 con->flag &= ~CONSTRAINT_LOOPTESTED;
218         }
219
220         switch (ob->type){
221         case OB_ARMATURE:
222                 if (ob->pose){
223                         bPoseChannel *pchan;
224                         for (pchan = ob->pose->chanbase.first; pchan; pchan=pchan->next){
225                                 for (con = pchan->constraints.first; con; con=con->next){
226                                         con->flag &= ~CONSTRAINT_LOOPTESTED;
227                                 }
228                         }
229                 }
230                 break;
231         default:
232                 break;
233         }
234 }
235 void test_scene_constraints (void)
236 {
237         Base *base, *base1;
238
239 /*      Clear the "done" flags of all constraints */
240
241         for (base = G.scene->base.first; base; base=base->next){
242                 clear_object_constraint_loop_flags(base->object);
243         }
244
245         /*      Test all constraints */
246         for (base = G.scene->base.first; base; base=base->next){
247                 /* Test the object */
248                 
249                 for (base1 = G.scene->base.first; base1; base1=base1->next)
250                         clear_object_constraint_loop_flags(base1->object);
251                 
252
253                 test_constraints (base->object, "", 1);
254
255         
256                 /* Test the subobject constraints */
257                 switch (base->object->type){
258                 case OB_ARMATURE:
259                         {
260                                 bArmature *arm;
261                                 arm = get_armature(base->object);
262                                 if (arm)
263                                         test_bonelist_constraints (base->object, &arm->bonebase);
264                         }
265                         break;
266                 default:
267                         break;
268                 }
269
270
271         }
272 }
273
274 int test_constraints (Object *owner, const char *substring, int disable)
275 {
276 /*      init_constraint_elements();*/
277         g_conObj = owner;
278         g_conString = substring;
279
280         if (detect_constraint_loop (owner, substring, disable, 0))
281                 return 1;
282         else
283                 return 0;
284
285 /*      free_constraint_elements();     */
286 }
287
288 static short detect_constraint_loop (Object *owner, const char* substring, int disable, char typefrom)
289 {
290
291         bConstraint *curcon;
292         ListBase *conlist;
293         int             type;
294         int             result = 0;
295
296         if (!owner)
297                 return result;
298
299         /* Check parents */
300         /* Get the constraint list for this object */
301
302         if (strlen (substring)){
303                 switch (owner->type){
304                 case OB_ARMATURE:
305                         type = TARGET_BONE;
306                         break;
307                 default:
308                         type = TARGET_OBJECT;
309                         break;
310                 }
311         }
312         else
313                 type = TARGET_OBJECT;
314
315
316         switch (type){
317         case TARGET_OBJECT:
318                 conlist = &owner->constraints;
319                 /* Check parents */
320 #if 0
321                 if (owner->parent && (ELEM (owner->partype, PAROBJECT, PARBONE))){
322                         if (add_constraint_element (owner->parent, "", NULL, NULL)){
323                                 return 1;
324                         }
325                 /*      if (detect_constraint_loop (owner->parent, "", disable)){
326                                 return 1;
327                         }
328                 */
329                 }
330                 /* Check tracking */
331                 if (owner->track && (ELEM (owner->partype, PAROBJECT, PARBONE))){
332                         if (add_constraint_element (owner->track, "", NULL, NULL)){
333                                 return 1;
334                         }
335                 /*      if (detect_constraint_loop (owner->track, "", disable)){
336                                 return 1;
337                         }
338                 */
339                 }
340 #else
341                 if (owner->parent && (owner->partype==PAROBJECT))
342                         if (add_constraint_element (owner->parent, "", NULL, NULL))
343                                 return 1;
344
345                 if (owner->parent && (owner->partype==PARBONE))
346                         if (add_constraint_element (owner->parent, owner->parsubstr, NULL, NULL))
347                                 return 1;
348
349                 /* Check tracking */
350                 if (owner->track)
351                         if (add_constraint_element (owner->track, "", NULL, NULL))
352                                 return 1;
353 #endif
354
355                 break;
356         case TARGET_BONE:
357                 {
358                         Bone *bone;
359                         bPoseChannel *chan;
360
361                         bone = get_named_bone(((bArmature*)owner->data), substring);
362                         chan = get_pose_channel (owner->pose, substring);
363                         if (bone){
364                                 conlist = &chan->constraints;
365                                 if (bone->parent){
366                                         if (add_constraint_element (owner, bone->parent->name, NULL, NULL))
367                                                 return 1;
368                                         if (detect_constraint_loop (owner, bone->parent->name, disable, 0))
369                                                 return 1;
370                                 }
371                                 else{
372                                         if (add_constraint_element (owner, "", NULL, NULL))
373                                                 return 1;
374                                         if (detect_constraint_loop (owner, "", disable, 0))
375                                                 return 1;
376                                 }
377                         }
378                         else
379                                 conlist = NULL;
380                 }
381                 break;
382         default:
383                 conlist = NULL;
384                 break;
385         }
386         
387         /* Cycle constraints */
388         if (conlist){
389                 for (curcon = conlist->first; curcon; curcon=curcon->next){
390                         
391                         /* Clear the disable flag */
392                         
393                         if (curcon->flag & CONSTRAINT_LOOPTESTED){
394                                 return 0;
395                         }
396                         else {
397                                 curcon->flag &= ~CONSTRAINT_DISABLE;
398                                 curcon->flag |= CONSTRAINT_LOOPTESTED;
399                                 switch (curcon->type){
400                                 case CONSTRAINT_TYPE_ACTION:
401                                         {
402                                                 bActionConstraint *data = curcon->data;
403
404                                                 if (!exist_object(data->tar)){
405                                                         data->tar = NULL;
406                                                         break;
407                                                 }
408                                                 
409                                                 if (add_constraint_element (data->tar, data->subtarget, owner, substring)){
410                                                         curcon->flag |= CONSTRAINT_DISABLE;
411                                                         result = 1;
412                                                         break;
413                                                         //              return 1;
414                                                 }
415                                                 if (detect_constraint_loop (data->tar, data->subtarget, disable, CONSTRAINT_TYPE_ACTION)){
416                                                         curcon->flag |= CONSTRAINT_DISABLE;
417                                                         result = 1;
418                                                         break;
419                                                         //              return 1;
420                                                 }
421                                         }
422                                         break;
423                                 case CONSTRAINT_TYPE_LOCLIKE:
424                                         {
425                                                 bLocateLikeConstraint *data = curcon->data;
426                                         
427                                                 if (!exist_object(data->tar)){
428                                                         data->tar = NULL;
429                                                         break;
430                                                 }
431                                                 
432                                                 if (add_constraint_element (data->tar, data->subtarget, owner, substring)){
433                                                         curcon->flag |= CONSTRAINT_DISABLE;
434                                                         result = 1;
435                                                         break;
436                                                         //              return 1;
437                                                 }
438                                                 if (detect_constraint_loop (data->tar, data->subtarget, disable, CONSTRAINT_TYPE_LOCLIKE)){
439                                                         curcon->flag |= CONSTRAINT_DISABLE;
440                                                         result = 1;
441                                                         break;
442                                                         //              return 1;
443                                                 }
444                                         }
445                                         break;
446                                 case CONSTRAINT_TYPE_ROTLIKE:
447                                         {
448                                                 bRotateLikeConstraint *data = curcon->data;
449                                         
450                                                 if (!exist_object(data->tar)){
451                                                         data->tar = NULL;
452                                                         break;
453                                                 }
454                                                 
455                                                 if (add_constraint_element (data->tar, data->subtarget, owner, substring)){
456                                                         curcon->flag |= CONSTRAINT_DISABLE;
457                                                         result = 1;
458                                                         break;
459                                                         //              return 1;
460                                                 }
461                                                 if (detect_constraint_loop (data->tar, data->subtarget, disable, CONSTRAINT_TYPE_ROTLIKE)){
462                                                         curcon->flag |= CONSTRAINT_DISABLE;
463                                                         result = 1;
464                                                         break;
465                                                         //              return 1;
466                                                 }
467                                         }
468                                         break;
469                                 case CONSTRAINT_TYPE_KINEMATIC:
470                                         {
471                                                 bKinematicConstraint *data = curcon->data;
472                                                 if (!exist_object(data->tar)){
473                                                         data->tar = NULL;
474                                                         break;
475                                                 }
476                                                 
477                                                 if (add_constraint_element (data->tar, data->subtarget, owner, substring)){
478                                                         curcon->flag |= CONSTRAINT_DISABLE;
479                                                         result = 1;
480                                                         break;
481                                                         //      return 1;
482                                                 }
483                                                 if (detect_constraint_loop (data->tar, data->subtarget, disable, CONSTRAINT_TYPE_KINEMATIC)){
484                                                         curcon->flag |= CONSTRAINT_DISABLE;
485                                                         result = 1;
486                                                         break;
487                                                         //              return 1;
488                                                 }
489                                         }
490                                         break;
491                                 case CONSTRAINT_TYPE_TRACKTO:
492                                         {
493                                                 bTrackToConstraint *data = curcon->data;
494                                                 if (!exist_object(data->tar)) data->tar = NULL;
495                                                 
496                                                 if (typefrom != CONSTRAINT_TYPE_TRACKTO && typefrom != CONSTRAINT_TYPE_LOCKTRACK){
497                                                         if (add_constraint_element (data->tar, data->subtarget, owner, substring)){
498                                                                 curcon->flag |= CONSTRAINT_DISABLE;
499                                                                 result = 1;
500                                                                 break;
501                                                                 //      return 1;
502                                                         }
503                                                 }
504                                                 if (typefrom == CONSTRAINT_TYPE_TRACKTO && typefrom == CONSTRAINT_TYPE_LOCKTRACK){
505                                                         curcon->flag |= CONSTRAINT_NOREFRESH;
506                                                 }
507                                                 if (detect_constraint_loop (data->tar, data->subtarget, disable, CONSTRAINT_TYPE_TRACKTO)){
508                                                         curcon->flag |= CONSTRAINT_DISABLE;
509                                                         result = 1;
510                                                         break;
511                                                         //              return 1;
512                                                 }
513                                                 if (data->reserved2==data->reserved1){
514                                                         curcon->flag |= CONSTRAINT_DISABLE;
515                                                         result = 1;
516                                                         break;
517                                                         //              return 1;
518                                                 }
519                                                 if (data->reserved2+3==data->reserved1){
520                                                         curcon->flag |= CONSTRAINT_DISABLE;
521                                                         result = 1;
522                                                         break;
523                                                         //              return 1;
524                                                 }
525                                         }
526                                         break;
527                                 case CONSTRAINT_TYPE_LOCKTRACK:
528                                         {
529                                                 bLockTrackConstraint *data = curcon->data;
530                                         
531                                                 if (!exist_object(data->tar)){
532                                                         data->tar = NULL;
533                                                         break;
534                                                 }
535                                                 
536                                                 if (typefrom != CONSTRAINT_TYPE_TRACKTO && typefrom != CONSTRAINT_TYPE_LOCKTRACK){
537                                                         if (add_constraint_element (data->tar, data->subtarget, owner, substring)){
538                                                                 curcon->flag |= CONSTRAINT_DISABLE;
539                                                                 result = 1;
540                                                                 break;
541                                                                 //              return 1;
542                                                         }
543                                                 }
544                                                 if (typefrom == CONSTRAINT_TYPE_TRACKTO && typefrom == CONSTRAINT_TYPE_LOCKTRACK){
545                                                         curcon->flag |= CONSTRAINT_NOREFRESH;
546                                                 }
547                                                 if (detect_constraint_loop (data->tar, data->subtarget, disable, CONSTRAINT_TYPE_LOCKTRACK)){
548                                                         curcon->flag |= CONSTRAINT_DISABLE;
549                                                         result = 1;
550                                                         break;
551                                                         //              return 1;
552                                                 }
553                                                 if (data->lockflag==data->trackflag){
554                                                         curcon->flag |= CONSTRAINT_DISABLE;
555                                                         result = 1;
556                                                         break;
557                                                         //              return 1;
558                                                 }
559                                                 if (data->lockflag+3==data->trackflag){
560                                                         curcon->flag |= CONSTRAINT_DISABLE;
561                                                         result = 1;
562                                                         break;
563                                                         //              return 1;
564                                                 }
565                                         }
566                                         break;
567                                 case CONSTRAINT_TYPE_FOLLOWPATH:
568                                         {
569                                                 bFollowPathConstraint *data = curcon->data;
570                                         
571                                                 if (!exist_object(data->tar)){
572                                                         data->tar = NULL;
573                                                         break;
574                                                 }
575                                                 if (data->tar->type != OB_CURVE){
576                                                         data->tar = NULL;
577                                                         break;
578                                                 }
579                                                 if (add_constraint_element (data->tar, "", owner, substring)){
580                                                         curcon->flag |= CONSTRAINT_DISABLE;
581                                                         result = 1;
582                                                         break;
583                                                         //              return 1;
584                                                 }
585                                                 if (detect_constraint_loop (data->tar, "", disable, CONSTRAINT_TYPE_FOLLOWPATH)){
586                                                         curcon->flag |= CONSTRAINT_DISABLE;
587                                                         result = 1;
588                                                         break;
589                                                         //              return 1;
590                                                 }
591                                                 if (data->upflag==data->trackflag){
592                                                         curcon->flag |= CONSTRAINT_DISABLE;
593                                                         result = 1;
594                                                         break;
595                                                         //              return 1;
596                                                 }
597                                                 if (data->upflag+3==data->trackflag){
598                                                         curcon->flag |= CONSTRAINT_DISABLE;
599                                                         result = 1;
600                                                         break;
601                                                         //              return 1;
602                                                 }
603                                         }
604                                         break;
605                                 }
606                         }
607                 }
608         }
609         
610         return result;
611 }
612
613 ListBase *get_constraint_client_channels (int forcevalid)
614 {
615
616         Object *ob;
617         char ipstr[64];
618
619         ob=OBACT;
620         
621         if (!ob)
622                 return NULL;
623         
624         /* See if we are a bone constraint */
625         if (G.obpose){
626                 switch (G.obpose->type){
627                 case OB_ARMATURE:
628                         {
629                                 bActionChannel *achan;
630                                 Bone *bone;
631
632                                 bone = get_first_selected_bone();
633                                 if (!bone) break;
634                                 
635                                 /* Make sure we have an action */
636                                 if (!G.obpose->action){
637                                         if (!forcevalid)
638                                                 return NULL;
639                                         
640                                         G.obpose->action=add_empty_action();
641                                 }
642                                 
643                                 /* Make sure we have an actionchannel */
644                                 achan = get_named_actionchannel(G.obpose->action, bone->name);
645                                 if (!achan){
646                                         if (!forcevalid)
647                                                 return NULL;
648                                         
649                                         achan = MEM_callocN (sizeof(bActionChannel), "actionChannel");
650
651                                         strcpy (achan->name, bone->name);
652                                         sprintf (ipstr, "%s.%s", G.obpose->action->id.name+2, achan->name);
653                                         ipstr[23]=0;
654                                         achan->ipo=     add_ipo(ipstr, ID_AC);  
655                                         
656                                         BLI_addtail (&G.obpose->action->chanbase, achan);
657                                 }
658                                 
659                                 return &achan->constraintChannels;
660                         }
661                 }
662         }
663         
664         return &ob->constraintChannels;
665 }
666
667 ListBase *get_constraint_client(char *name, short *clientType, void **clientdata)
668 {
669         Object *ob;
670         ListBase *list;
671
672         ob=OBACT;
673         if (clientType)
674                 *clientType = -1;
675
676         if (!ob)
677                 return NULL;
678
679         list = &ob->constraints;
680
681         /* Prep the object's constraint channels */
682         if (clientType)
683                 *clientType = TARGET_OBJECT;
684         
685         if (name)
686                 strcpy (name, ob->id.name+2);
687
688         if (G.obpose){
689                 switch (G.obpose->type){
690                 case OB_ARMATURE:
691                         {
692                                 Bone *bone;
693
694                                 bone = get_first_selected_bone();
695                                 if (!bone) break;
696
697                                 {
698                                         bPoseChannel    *chan;
699                                         
700                                         /* Is the bone the client? */
701                                         if (clientType)
702                                                 *clientType = TARGET_BONE;
703                                         if (clientdata)
704                                                 *clientdata = bone;
705                                         if (name)
706                                                 sprintf (name, "%s>>%s", name, bone->name);
707                                         verify_pose_channel(G.obpose->pose, bone->name);
708                                         chan = get_pose_channel (G.obpose->pose, bone->name);
709                                         list = &chan->constraints;
710
711                                 }                       
712                         }
713                         break;
714                 }
715         }
716
717         return list;
718 }
719
720 bConstraint * add_new_constraint(char type)
721 {
722         bConstraint *con;
723
724         con = MEM_callocN(sizeof(bConstraint), "constraint");
725
726         /* Set up a generic constraint datablock */
727         con->type = type;
728         con->flag |= CONSTRAINT_EXPAND;
729         con->enforce=1.0F;
730         /* Load the data for it */
731         con->data = new_constraint_data(con->type);
732         strcpy (con->name, "Const");
733         return con;
734 }
735
736 void add_constraint_to_object(bConstraint *con, Object *ob)
737 {
738         ListBase *list;
739         list = &ob->constraints;
740         if (list)
741         {
742                 unique_constraint_name(con, list);
743                 BLI_addtail(list, con);
744         }
745 }
746
747 void add_constraint_to_client(bConstraint *con)
748 {
749         ListBase *list;
750         short type;
751         list = get_constraint_client(NULL, &type, NULL);
752         if (list)
753         {
754                 unique_constraint_name(con, list);
755                 BLI_addtail(list, con);
756         }
757 }
758
759 bConstraintChannel *add_new_constraint_channel(const char* name)
760 {
761         bConstraintChannel *chan = NULL;
762
763         chan = MEM_callocN(sizeof(bConstraintChannel), "constraintChannel");
764         strcpy(chan->name, name);
765         
766         return chan;
767 }
768
769 void add_influence_key_to_constraint (bConstraint *con){
770         printf("doesn't do anything yet\n");
771 }