Integration of new IK lib features in Armature Poses.
[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_editaction.h"
57 #include "BIF_editarmature.h"
58 #include "BIF_editconstraint.h"
59 #include "BIF_poseobject.h"
60 #include "BIF_interface.h"
61 #include "BIF_screen.h"
62 #include "BIF_toolbox.h"
63
64 #include "blendef.h"
65 #include "nla.h"
66
67
68 ListBase *get_active_constraint_channels (Object *ob, int forcevalid)
69 {
70         char ipstr[64];
71         
72         if (!ob)
73                 return NULL;
74         
75         /* See if we are a bone constraint */
76         if (ob->flag & OB_POSEMODE) {
77                 bActionChannel *achan;
78                 bPoseChannel *pchan;
79
80                 pchan = get_active_posechannel(ob);
81                 if (pchan) {
82                         
83                         /* Make sure we have an action */
84                         if (!ob->action){
85                                 if (!forcevalid)
86                                         return NULL;
87                                 
88                                 ob->action=add_empty_action();
89                         }
90                         
91                         /* Make sure we have an actionchannel */
92                         achan = get_named_actionchannel(ob->action, pchan->name);
93                         if (!achan){
94                                 if (!forcevalid)
95                                         return NULL;
96                                 
97                                 achan = MEM_callocN (sizeof(bActionChannel), "actionChannel");
98
99                                 strcpy (achan->name, pchan->name);
100                                 sprintf (ipstr, "%s.%s", ob->action->id.name+2, achan->name);
101                                 ipstr[23]=0;
102                                 achan->ipo=     add_ipo(ipstr, ID_AC);  
103                                 
104                                 BLI_addtail (&ob->action->chanbase, achan);
105                         }
106                         
107                         return &achan->constraintChannels;
108                 }
109                 else return NULL;
110         }
111         /* else we return object constraints */
112         return &ob->constraintChannels;
113 }
114
115
116 /* if object in posemode, active bone constraints, else object constraints */
117 ListBase *get_active_constraints(Object *ob)
118 {
119         if (!ob)
120                 return NULL;
121
122         if (ob->flag & OB_POSEMODE) {
123                 bPoseChannel *pchan;
124
125                 pchan = get_active_posechannel(ob);
126                 if (pchan)
127                         return &pchan->constraints;
128         }
129         else 
130                 return &ob->constraints;
131
132         return NULL;
133 }
134
135 /* single constraint */
136 bConstraint *get_active_constraint(Object *ob)
137 {
138         ListBase *lb= get_active_constraints(ob);
139
140         if(lb) {
141                 bConstraint *con;
142                 for(con= lb->first; con; con=con->next)
143                         if(con->flag & CONSTRAINT_ACTIVE)
144                                 return con;
145         }
146         return NULL;
147 }
148
149 /* single channel, for ipo */
150 bConstraintChannel *get_active_constraint_channel(Object *ob)
151 {
152         bConstraint *con;
153         bConstraintChannel *chan;
154         
155         if (ob->flag & OB_POSEMODE) {
156                 if(ob->action) {
157                         bPoseChannel *pchan;
158                         
159                         pchan = get_active_posechannel(ob);
160                         if(pchan) {
161                                 for(con= pchan->constraints.first; con; con= con->next)
162                                         if(con->flag & CONSTRAINT_ACTIVE)
163                                                 break;
164                                 if(con) {
165                                         bActionChannel *achan = get_named_actionchannel(ob->action, pchan->name);
166                                         if(achan) {
167                                                 for(chan= achan->constraintChannels.first; chan; chan= chan->next)
168                                                         if(!strcmp(chan->name, con->name))
169                                                                 break;
170                                                 return chan;
171                                         }
172                                 }
173                         }
174                 }
175         }
176         else {
177                 for(con= ob->constraints.first; con; con= con->next)
178                         if(con->flag & CONSTRAINT_ACTIVE)
179                                 break;
180                 if(con) {
181                         for(chan= ob->constraintChannels.first; chan; chan= chan->next)
182                                 if(!strcmp(chan->name, con->name))
183                                         break;
184                         return chan;
185                 }
186         }
187         
188         return NULL;
189 }
190
191
192
193 bConstraint *add_new_constraint(short type)
194 {
195         bConstraint *con;
196
197         con = MEM_callocN(sizeof(bConstraint), "constraint");
198
199         /* Set up a generic constraint datablock */
200         con->type = type;
201         con->flag |= CONSTRAINT_EXPAND;
202         con->enforce=1.0F;
203         /* Load the data for it */
204         con->data = new_constraint_data(con->type);
205         strcpy (con->name, "Const");
206         return con;
207 }
208
209 void add_constraint_to_object(bConstraint *con, Object *ob)
210 {
211         ListBase *list;
212         list = &ob->constraints;
213         
214         if (list) {
215                 unique_constraint_name(con, list);
216                 BLI_addtail(list, con);
217                 
218                 con->flag |= CONSTRAINT_ACTIVE;
219                 for(con= con->prev; con; con= con->prev)
220                         con->flag &= ~CONSTRAINT_ACTIVE;
221         }
222 }
223
224
225 char *get_con_subtarget_name(bConstraint *con, Object *target)
226 {
227         /*
228          * If the target for this constraint is target, return a pointer 
229          * to the name for this constraints subtarget ... NULL otherwise
230          */
231         switch (con->type) {
232
233                 case CONSTRAINT_TYPE_ACTION:
234                 {
235                         bActionConstraint *data = con->data;
236                         if (data->tar==target) return data->subtarget;
237                 }
238                 break;
239                 case CONSTRAINT_TYPE_LOCLIKE:
240                 {
241                         bLocateLikeConstraint *data = con->data;
242                         if (data->tar==target) return data->subtarget;
243                 }
244                 break;
245                 case CONSTRAINT_TYPE_ROTLIKE:
246                 {
247                         bRotateLikeConstraint *data = con->data;
248                         if (data->tar==target) return data->subtarget;
249                 }
250                 break;
251                 case CONSTRAINT_TYPE_KINEMATIC:
252                 {
253                         bKinematicConstraint *data = con->data;
254                         if (data->tar==target) return data->subtarget;
255                 }
256                 break;
257                 case CONSTRAINT_TYPE_TRACKTO:
258                 {
259                         bTrackToConstraint *data = con->data;
260                         if (data->tar==target) return data->subtarget;
261                 }
262                 break;
263                 case CONSTRAINT_TYPE_LOCKTRACK:
264                 {
265                         bLockTrackConstraint *data = con->data;
266                         if (data->tar==target) return data->subtarget;
267                 }
268                 break;
269                 case CONSTRAINT_TYPE_STRETCHTO:
270                 {
271                         bStretchToConstraint *data = con->data;
272                         if (data->tar==target) return data->subtarget;
273                 }
274                 break;
275                 case CONSTRAINT_TYPE_FOLLOWPATH: 
276                         /* wonder if this is relevent, since this constraint 
277                          * cannot have a subtarget - theeth 
278                          */
279                 {
280                         /*
281                          * bFollowPathConstraint *data = con->data;
282                          */
283                         return NULL;
284                 }
285                 break;
286         }
287         
288         return NULL;  
289 }
290
291 /* checks validity of object pointers, and NULLs,
292    if Bone doesnt exist it sets the CONSTRAINT_DISABLE flag */
293 static void test_constraints (Object *owner, const char* substring)
294 {
295         
296         bConstraint *curcon;
297         ListBase *conlist= NULL;
298         int type;
299         
300         if (owner==NULL) return;
301         
302         /* Check parents */
303         /* Get the constraint list for this object */
304         
305         if (strlen (substring)){
306                 switch (owner->type){
307                         case OB_ARMATURE:
308                                 type = TARGET_BONE;
309                                 break;
310                         default:
311                                 type = TARGET_OBJECT;
312                                 break;
313                 }
314         }
315         else
316                 type = TARGET_OBJECT;
317         
318         
319         switch (type){
320                 case TARGET_OBJECT:
321                         conlist = &owner->constraints;
322                         break;
323                 case TARGET_BONE:
324                         {
325                                 Bone *bone;
326                                 bPoseChannel *chan;
327                                 
328                                 bone = get_named_bone(((bArmature*)owner->data), substring);
329                                 chan = get_pose_channel (owner->pose, substring);
330                                 if (bone && chan){
331                                         conlist = &chan->constraints;
332                                 }
333                         }
334                         break;
335         }
336         
337         /* Cycle constraints */
338         if (conlist){
339                 for (curcon = conlist->first; curcon; curcon=curcon->next){
340                         curcon->flag &= ~CONSTRAINT_DISABLE;
341                         
342                         switch (curcon->type){
343                                 case CONSTRAINT_TYPE_ACTION:
344                                 {
345                                         bActionConstraint *data = curcon->data;
346                                         
347                                         if (!exist_object(data->tar)){
348                                                 data->tar = NULL;
349                                                 curcon->flag |= CONSTRAINT_DISABLE;
350                                                 break;
351                                         }
352                                         
353                                         if ( (data->tar == owner) &&
354                                                  (!get_named_bone(get_armature(owner), 
355                                                                                   data->subtarget))) {
356                                                 curcon->flag |= CONSTRAINT_DISABLE;
357                                                 break;
358                                         }
359                                 }
360                                         break;
361                                 case CONSTRAINT_TYPE_LOCLIKE:
362                                 {
363                                         bLocateLikeConstraint *data = curcon->data;
364                                         
365                                         if (!exist_object(data->tar)){
366                                                 data->tar = NULL;
367                                                 curcon->flag |= CONSTRAINT_DISABLE;
368                                                 break;
369                                         }
370                                         
371                                         if ( (data->tar == owner) &&
372                                                  (!get_named_bone(get_armature(owner), 
373                                                                                   data->subtarget))) {
374                                                 curcon->flag |= CONSTRAINT_DISABLE;
375                                                 break;
376                                         }
377                                 }
378                                         break;
379                                 case CONSTRAINT_TYPE_ROTLIKE:
380                                 {
381                                         bRotateLikeConstraint *data = curcon->data;
382                                         
383                                         if (!exist_object(data->tar)){
384                                                 data->tar = NULL;
385                                                 curcon->flag |= CONSTRAINT_DISABLE;
386                                                 break;
387                                         }
388                                         
389                                         if ( (data->tar == owner) &&
390                                                  (!get_named_bone(get_armature(owner), 
391                                                                                   data->subtarget))) {
392                                                 curcon->flag |= CONSTRAINT_DISABLE;
393                                                 break;
394                                         }
395                                 }
396                                         break;
397                                 case CONSTRAINT_TYPE_KINEMATIC:
398                                 {
399                                         bKinematicConstraint *data = curcon->data;
400                                         if (!exist_object(data->tar)){
401                                                 data->tar = NULL;
402                                                 curcon->flag |= CONSTRAINT_DISABLE;
403                                                 break;
404                                         }
405                                         
406                                         if ( (data->tar == owner) &&
407                                                  (!get_named_bone(get_armature(owner), 
408                                                                                   data->subtarget))) {
409                                                 curcon->flag |= CONSTRAINT_DISABLE;
410                                                 break;
411                                         }
412                                 }
413                                         break;
414                                 case CONSTRAINT_TYPE_TRACKTO:
415                                 {
416                                         bTrackToConstraint *data = curcon->data;
417                                         if (!exist_object(data->tar)) {
418                                                 data->tar = NULL;
419                                                 curcon->flag |= CONSTRAINT_DISABLE;
420                                                 break;
421                                         }
422                                         
423                                         if ( (data->tar == owner) &&
424                                                  (!get_named_bone(get_armature(owner), 
425                                                                                   data->subtarget))) {
426                                                 curcon->flag |= CONSTRAINT_DISABLE;
427                                                 break;
428                                         }
429                                         if (data->reserved2==data->reserved1){
430                                                 curcon->flag |= CONSTRAINT_DISABLE;
431                                                 break;
432                                         }
433                                         if (data->reserved2+3==data->reserved1){
434                                                 curcon->flag |= CONSTRAINT_DISABLE;
435                                                 break;
436                                         }
437                                 }
438                                         break;
439                                 case CONSTRAINT_TYPE_LOCKTRACK:
440                                 {
441                                         bLockTrackConstraint *data = curcon->data;
442                                         
443                                         if (!exist_object(data->tar)){
444                                                 data->tar = NULL;
445                                                 curcon->flag |= CONSTRAINT_DISABLE;
446                                                 break;
447                                         }
448                                         
449                                         if ( (data->tar == owner) &&
450                                                  (!get_named_bone(get_armature(owner), 
451                                                                                   data->subtarget))) {
452                                                 curcon->flag |= CONSTRAINT_DISABLE;
453                                                 break;
454                                         }
455
456                                         if (data->lockflag==data->trackflag){
457                                                 curcon->flag |= CONSTRAINT_DISABLE;
458                                                 break;
459                                         }
460                                         if (data->lockflag+3==data->trackflag){
461                                                 curcon->flag |= CONSTRAINT_DISABLE;
462                                                 break;
463                                         }
464                                 }
465                                         break;
466                                 case CONSTRAINT_TYPE_STRETCHTO:
467                                 {
468                                         bStretchToConstraint *data = curcon->data;
469                                         
470                                         if (!exist_object(data->tar)){
471                                                 data->tar = NULL;
472                                                 curcon->flag |= CONSTRAINT_DISABLE;
473                                                 break;
474                                         }
475                                         
476                                         if ( (data->tar == owner) &&
477                                                  (!get_named_bone(get_armature(owner), 
478                                                                                   data->subtarget))) {
479                                                 curcon->flag |= CONSTRAINT_DISABLE;
480                                                 break;
481                                         }
482                                 }
483                                         break;
484                                 case CONSTRAINT_TYPE_FOLLOWPATH:
485                                 {
486                                         bFollowPathConstraint *data = curcon->data;
487                                         
488                                         if (!exist_object(data->tar)){
489                                                 data->tar = NULL;
490                                                 curcon->flag |= CONSTRAINT_DISABLE;
491                                                 break;
492                                         }
493                                         if (data->tar->type != OB_CURVE){
494                                                 data->tar = NULL;
495                                                 curcon->flag |= CONSTRAINT_DISABLE;
496                                                 break;
497                                         }
498                                         if (data->upflag==data->trackflag){
499                                                 curcon->flag |= CONSTRAINT_DISABLE;
500                                                 break;
501                                         }
502                                         if (data->upflag+3==data->trackflag){
503                                                 curcon->flag |= CONSTRAINT_DISABLE;
504                                                 break;
505                                         }
506                                 }
507                                         break;
508                         }
509                 }
510         }
511 }
512
513 static void test_bonelist_constraints (Object *owner, ListBase *list)
514 {
515         Bone *bone;
516
517         for (bone = list->first; bone; bone=bone->next) {
518                 
519                 test_constraints(owner, bone->name);
520                 test_bonelist_constraints (owner, &bone->childbase);
521         }
522 }
523
524 void object_test_constraints (Object *owner)
525 {
526         test_constraints(owner, "");
527
528         if(owner->type==OB_ARMATURE) {
529                 bArmature *arm;
530                 arm = get_armature(owner);
531                 if (arm)
532                         test_bonelist_constraints (owner, &arm->bonebase);
533         }
534
535 }
536
537