Two new IK features.
[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 #include "BLI_arithb.h"
40
41 #include "DNA_action_types.h"
42 #include "DNA_armature_types.h"
43 #include "DNA_constraint_types.h"
44 #include "DNA_curve_types.h"
45 #include "DNA_object_types.h"
46 #include "DNA_scene_types.h"
47 #include "DNA_screen_types.h"
48 #include "DNA_view3d_types.h"
49
50 #include "BKE_action.h"
51 #include "BKE_armature.h"
52 #include "BKE_constraint.h"
53 #include "BKE_depsgraph.h"
54 #include "BKE_global.h"
55 #include "BKE_ipo.h"
56 #include "BKE_object.h"
57 #include "BKE_utildefines.h"
58
59 #include "BIF_editaction.h"
60 #include "BIF_editarmature.h"
61 #include "BIF_editconstraint.h"
62 #include "BIF_poseobject.h"
63 #include "BIF_interface.h"
64 #include "BIF_screen.h"
65 #include "BIF_space.h"
66 #include "BIF_toolbox.h"
67
68 #include "blendef.h"
69 #include "nla.h"
70 #include "mydevice.h"
71
72
73 ListBase *get_active_constraint_channels (Object *ob, int forcevalid)
74 {
75         char ipstr[64];
76         
77         if (!ob)
78                 return NULL;
79         
80         /* See if we are a bone constraint */
81         if (ob->flag & OB_POSEMODE) {
82                 bActionChannel *achan;
83                 bPoseChannel *pchan;
84
85                 pchan = get_active_posechannel(ob);
86                 if (pchan) {
87                         
88                         /* Make sure we have an action */
89                         if (!ob->action){
90                                 if (!forcevalid)
91                                         return NULL;
92                                 
93                                 ob->action=add_empty_action(ID_PO);
94                         }
95                         
96                         /* Make sure we have an actionchannel */
97                         achan = get_action_channel(ob->action, pchan->name);
98                         if (!achan){
99                                 if (!forcevalid)
100                                         return NULL;
101                                 
102                                 achan = MEM_callocN (sizeof(bActionChannel), "actionChannel");
103
104                                 strcpy (achan->name, pchan->name);
105                                 sprintf (ipstr, "%s.%s", ob->action->id.name+2, achan->name);
106                                 ipstr[23]=0;
107                                 achan->ipo=     add_ipo(ipstr, ID_AC);  
108                                 
109                                 BLI_addtail (&ob->action->chanbase, achan);
110                         }
111                         
112                         return &achan->constraintChannels;
113                 }
114                 else return NULL;
115         }
116         /* else we return object constraints */
117         else {
118                 if(ob->ipoflag & OB_ACTION_OB) {
119                         bActionChannel *achan = get_action_channel(ob->action, "Object");
120                         if(achan)
121                                 return &achan->constraintChannels;
122                         else 
123                                 return NULL;
124                 }
125                 
126                 return &ob->constraintChannels;
127         }
128 }
129
130
131 /* if object in posemode, active bone constraints, else object constraints */
132 ListBase *get_active_constraints(Object *ob)
133 {
134         if (!ob)
135                 return NULL;
136
137         if (ob->flag & OB_POSEMODE) {
138                 bPoseChannel *pchan;
139
140                 pchan = get_active_posechannel(ob);
141                 if (pchan)
142                         return &pchan->constraints;
143         }
144         else 
145                 return &ob->constraints;
146
147         return NULL;
148 }
149
150 /* single constraint */
151 bConstraint *get_active_constraint(Object *ob)
152 {
153         ListBase *lb= get_active_constraints(ob);
154
155         if(lb) {
156                 bConstraint *con;
157                 for(con= lb->first; con; con=con->next)
158                         if(con->flag & CONSTRAINT_ACTIVE)
159                                 return con;
160         }
161         return NULL;
162 }
163
164 /* single channel, for ipo */
165 bConstraintChannel *get_active_constraint_channel(Object *ob)
166 {
167         bConstraint *con;
168         bConstraintChannel *chan;
169         
170         if (ob->flag & OB_POSEMODE) {
171                 if(ob->action) {
172                         bPoseChannel *pchan;
173                         
174                         pchan = get_active_posechannel(ob);
175                         if(pchan) {
176                                 for(con= pchan->constraints.first; con; con= con->next)
177                                         if(con->flag & CONSTRAINT_ACTIVE)
178                                                 break;
179                                 if(con) {
180                                         bActionChannel *achan = get_action_channel(ob->action, pchan->name);
181                                         if(achan) {
182                                                 for(chan= achan->constraintChannels.first; chan; chan= chan->next)
183                                                         if(!strcmp(chan->name, con->name))
184                                                                 break;
185                                                 return chan;
186                                         }
187                                 }
188                         }
189                 }
190         }
191         else {
192                 for(con= ob->constraints.first; con; con= con->next)
193                         if(con->flag & CONSTRAINT_ACTIVE)
194                                 break;
195                 if(con) {
196                         ListBase *lb= get_active_constraint_channels(ob, 0);
197
198                         if(lb) {
199                                 for(chan= lb->first; chan; chan= chan->next)
200                                         if(!strcmp(chan->name, con->name))
201                                                 break;
202                                 return chan;
203                         }
204                 }
205         }
206         
207         return NULL;
208 }
209
210
211 bConstraint *add_new_constraint(short type)
212 {
213         bConstraint *con;
214
215         con = MEM_callocN(sizeof(bConstraint), "constraint");
216
217         /* Set up a generic constraint datablock */
218         con->type = type;
219         con->flag |= CONSTRAINT_EXPAND;
220         con->enforce=1.0F;
221         /* Load the data for it */
222         con->data = new_constraint_data(con->type);
223         strcpy (con->name, "Const");
224         return con;
225 }
226
227 void add_constraint_to_object(bConstraint *con, Object *ob)
228 {
229         ListBase *list;
230         list = &ob->constraints;
231         
232         if (list) {
233                 unique_constraint_name(con, list);
234                 BLI_addtail(list, con);
235                 
236                 con->flag |= CONSTRAINT_ACTIVE;
237                 for(con= con->prev; con; con= con->prev)
238                         con->flag &= ~CONSTRAINT_ACTIVE;
239         }
240 }
241
242
243 char *get_con_subtarget_name(bConstraint *con, Object *target)
244 {
245         /*
246          * If the target for this constraint is target, return a pointer 
247          * to the name for this constraints subtarget ... NULL otherwise
248          */
249         switch (con->type) {
250
251                 case CONSTRAINT_TYPE_ACTION:
252                 {
253                         bActionConstraint *data = con->data;
254                         if (data->tar==target) return data->subtarget;
255                 }
256                 break;
257                 case CONSTRAINT_TYPE_LOCLIKE:
258                 {
259                         bLocateLikeConstraint *data = con->data;
260                         if (data->tar==target) return data->subtarget;
261                 }
262                 break;
263                 case CONSTRAINT_TYPE_ROTLIKE:
264                 {
265                         bRotateLikeConstraint *data = con->data;
266                         if (data->tar==target) return data->subtarget;
267                 }
268                 break;
269                 case CONSTRAINT_TYPE_KINEMATIC:
270                 {
271                         bKinematicConstraint *data = con->data;
272                         if (data->tar==target) return data->subtarget;
273                 }
274                 break;
275                 case CONSTRAINT_TYPE_TRACKTO:
276                 {
277                         bTrackToConstraint *data = con->data;
278                         if (data->tar==target) return data->subtarget;
279                 }
280                 break;
281                 case CONSTRAINT_TYPE_MINMAX:
282                 {
283                         bMinMaxConstraint *data = con->data;
284                         if (data->tar==target) return data->subtarget;
285                 }
286                 break;
287                 case CONSTRAINT_TYPE_LOCKTRACK:
288                 {
289                         bLockTrackConstraint *data = con->data;
290                         if (data->tar==target) return data->subtarget;
291                 }
292                 break;
293                 case CONSTRAINT_TYPE_STRETCHTO:
294                 {
295                         bStretchToConstraint *data = con->data;
296                         if (data->tar==target) return data->subtarget;
297                 }
298                 break;
299                 case CONSTRAINT_TYPE_FOLLOWPATH: 
300                         /* wonder if this is relevent, since this constraint 
301                          * cannot have a subtarget - theeth 
302                          */
303                 {
304                         /*
305                          * bFollowPathConstraint *data = con->data;
306                          */
307                         return NULL;
308                 }
309                 break;
310         }
311         
312         return NULL;  
313 }
314
315 /* checks validity of object pointers, and NULLs,
316    if Bone doesnt exist it sets the CONSTRAINT_DISABLE flag */
317 static void test_constraints (Object *owner, const char* substring)
318 {
319         
320         bConstraint *curcon;
321         ListBase *conlist= NULL;
322         int type;
323         
324         if (owner==NULL) return;
325         
326         /* Check parents */
327         /* Get the constraint list for this object */
328         
329         if (strlen (substring)){
330                 switch (owner->type){
331                         case OB_ARMATURE:
332                                 type = TARGET_BONE;
333                                 break;
334                         default:
335                                 type = TARGET_OBJECT;
336                                 break;
337                 }
338         }
339         else
340                 type = TARGET_OBJECT;
341         
342         
343         switch (type){
344                 case TARGET_OBJECT:
345                         conlist = &owner->constraints;
346                         break;
347                 case TARGET_BONE:
348                         {
349                                 Bone *bone;
350                                 bPoseChannel *chan;
351                                 
352                                 bone = get_named_bone(((bArmature*)owner->data), substring);
353                                 chan = get_pose_channel (owner->pose, substring);
354                                 if (bone && chan){
355                                         conlist = &chan->constraints;
356                                 }
357                         }
358                         break;
359         }
360         
361         /* Cycle constraints */
362         if (conlist){
363                 for (curcon = conlist->first; curcon; curcon=curcon->next){
364                         curcon->flag &= ~CONSTRAINT_DISABLE;
365                         
366                         switch (curcon->type){
367                                 case CONSTRAINT_TYPE_ACTION:
368                                 {
369                                         bActionConstraint *data = curcon->data;
370                                         
371                                         if (!exist_object(data->tar)){
372                                                 data->tar = NULL;
373                                                 curcon->flag |= CONSTRAINT_DISABLE;
374                                                 break;
375                                         }
376                                         
377                                         if ( (data->tar == owner) &&
378                                                  (!get_named_bone(get_armature(owner), 
379                                                                                   data->subtarget))) {
380                                                 curcon->flag |= CONSTRAINT_DISABLE;
381                                                 break;
382                                         }
383                                 }
384                                         break;
385                                 case CONSTRAINT_TYPE_LOCLIKE:
386                                 {
387                                         bLocateLikeConstraint *data = curcon->data;
388                                         
389                                         if (!exist_object(data->tar)){
390                                                 data->tar = NULL;
391                                                 curcon->flag |= CONSTRAINT_DISABLE;
392                                                 break;
393                                         }
394                                         
395                                         if ( (data->tar == owner) &&
396                                                  (!get_named_bone(get_armature(owner), 
397                                                                                   data->subtarget))) {
398                                                 curcon->flag |= CONSTRAINT_DISABLE;
399                                                 break;
400                                         }
401                                 }
402                                         break;
403                                 case CONSTRAINT_TYPE_MINMAX:
404                                 {
405                                         bMinMaxConstraint *data = curcon->data;
406                                         
407                                         if (!exist_object(data->tar)){
408                                                 data->tar = NULL;
409                                                 curcon->flag |= CONSTRAINT_DISABLE;
410                                                 break;
411                                         }
412                                         
413                                         if ( (data->tar == owner) &&
414                                                  (!get_named_bone(get_armature(owner), 
415                                                                                   data->subtarget))) {
416                                                 curcon->flag |= CONSTRAINT_DISABLE;
417                                                 break;
418                                         }
419                                 }
420                                         break;
421                                 case CONSTRAINT_TYPE_ROTLIKE:
422                                 {
423                                         bRotateLikeConstraint *data = curcon->data;
424                                         
425                                         if (!exist_object(data->tar)){
426                                                 data->tar = NULL;
427                                                 curcon->flag |= CONSTRAINT_DISABLE;
428                                                 break;
429                                         }
430                                         
431                                         if ( (data->tar == owner) &&
432                                                  (!get_named_bone(get_armature(owner), 
433                                                                                   data->subtarget))) {
434                                                 curcon->flag |= CONSTRAINT_DISABLE;
435                                                 break;
436                                         }
437                                 }
438                                         break;
439                                 case CONSTRAINT_TYPE_KINEMATIC:
440                                 {
441                                         bKinematicConstraint *data = curcon->data;
442                                         if (!exist_object(data->tar)){
443                                                 data->tar = NULL;
444                                                 curcon->flag |= CONSTRAINT_DISABLE;
445                                                 break;
446                                         }
447                                         
448                                         if ( (data->tar == owner) &&
449                                                  (!get_named_bone(get_armature(owner), 
450                                                                                   data->subtarget))) {
451                                                 curcon->flag |= CONSTRAINT_DISABLE;
452                                                 break;
453                                         }
454                                 }
455                                         break;
456                                 case CONSTRAINT_TYPE_TRACKTO:
457                                 {
458                                         bTrackToConstraint *data = curcon->data;
459                                         if (!exist_object(data->tar)) {
460                                                 data->tar = NULL;
461                                                 curcon->flag |= CONSTRAINT_DISABLE;
462                                                 break;
463                                         }
464                                         
465                                         if ( (data->tar == owner) &&
466                                                  (!get_named_bone(get_armature(owner), 
467                                                                                   data->subtarget))) {
468                                                 curcon->flag |= CONSTRAINT_DISABLE;
469                                                 break;
470                                         }
471                                         if (data->reserved2==data->reserved1){
472                                                 curcon->flag |= CONSTRAINT_DISABLE;
473                                                 break;
474                                         }
475                                         if (data->reserved2+3==data->reserved1){
476                                                 curcon->flag |= CONSTRAINT_DISABLE;
477                                                 break;
478                                         }
479                                 }
480                                         break;
481                                 case CONSTRAINT_TYPE_LOCKTRACK:
482                                 {
483                                         bLockTrackConstraint *data = curcon->data;
484                                         
485                                         if (!exist_object(data->tar)){
486                                                 data->tar = NULL;
487                                                 curcon->flag |= CONSTRAINT_DISABLE;
488                                                 break;
489                                         }
490                                         
491                                         if ( (data->tar == owner) &&
492                                                  (!get_named_bone(get_armature(owner), 
493                                                                                   data->subtarget))) {
494                                                 curcon->flag |= CONSTRAINT_DISABLE;
495                                                 break;
496                                         }
497
498                                         if (data->lockflag==data->trackflag){
499                                                 curcon->flag |= CONSTRAINT_DISABLE;
500                                                 break;
501                                         }
502                                         if (data->lockflag+3==data->trackflag){
503                                                 curcon->flag |= CONSTRAINT_DISABLE;
504                                                 break;
505                                         }
506                                 }
507                                         break;
508                                 case CONSTRAINT_TYPE_STRETCHTO:
509                                 {
510                                         bStretchToConstraint *data = curcon->data;
511                                         
512                                         if (!exist_object(data->tar)){
513                                                 data->tar = NULL;
514                                                 curcon->flag |= CONSTRAINT_DISABLE;
515                                                 break;
516                                         }
517                                         
518                                         if ( (data->tar == owner) &&
519                                                  (!get_named_bone(get_armature(owner), 
520                                                                                   data->subtarget))) {
521                                                 curcon->flag |= CONSTRAINT_DISABLE;
522                                                 break;
523                                         }
524                                 }
525                                         break;
526                                 case CONSTRAINT_TYPE_FOLLOWPATH:
527                                 {
528                                         bFollowPathConstraint *data = curcon->data;
529                                         
530                                         if (!exist_object(data->tar)){
531                                                 data->tar = NULL;
532                                                 curcon->flag |= CONSTRAINT_DISABLE;
533                                                 break;
534                                         }
535                                         if (data->tar->type != OB_CURVE){
536                                                 data->tar = NULL;
537                                                 curcon->flag |= CONSTRAINT_DISABLE;
538                                                 break;
539                                         }
540                                         if (data->upflag==data->trackflag){
541                                                 curcon->flag |= CONSTRAINT_DISABLE;
542                                                 break;
543                                         }
544                                         if (data->upflag+3==data->trackflag){
545                                                 curcon->flag |= CONSTRAINT_DISABLE;
546                                                 break;
547                                         }
548                                 }
549                                         break;
550                         }
551                 }
552         }
553 }
554
555 static void test_bonelist_constraints (Object *owner, ListBase *list)
556 {
557         Bone *bone;
558
559         for (bone = list->first; bone; bone=bone->next) {
560                 
561                 test_constraints(owner, bone->name);
562                 test_bonelist_constraints (owner, &bone->childbase);
563         }
564 }
565
566 void object_test_constraints (Object *owner)
567 {
568         test_constraints(owner, "");
569
570         if(owner->type==OB_ARMATURE) {
571                 bArmature *arm;
572                 arm = get_armature(owner);
573                 if (arm)
574                         test_bonelist_constraints (owner, &arm->bonebase);
575         }
576
577 }
578
579 /* context: active object in posemode, active channel, optional selected channel */
580 void add_constraint(int only_IK)
581 {
582         Object *ob= OBACT, *obsel=NULL;
583         bPoseChannel *pchanact=NULL, *pchansel=NULL;
584         bConstraint *con=NULL;
585         Base *base;
586         short nr;
587         
588         /* paranoia checks */
589         if(ob==NULL || ob==G.obedit) return;
590         
591         if(ob->pose && (ob->flag & OB_POSEMODE)) {
592         
593                 /* find active channel */
594                 for(pchanact= ob->pose->chanbase.first; pchanact; pchanact= pchanact->next)
595                         if(pchanact->bone->flag & BONE_ACTIVE) break;
596                 if(pchanact==NULL) return;
597         
598                 /* find selected bone */
599                 for(pchansel= ob->pose->chanbase.first; pchansel; pchansel= pchansel->next) {
600                         if(pchansel!=pchanact)
601                                 if(pchansel->bone->flag & BONE_SELECTED) break;
602                 }
603         }
604         
605         /* find selected object */
606         for(base= FIRSTBASE; base; base= base->next)
607                 if( TESTBASE(base) && base->object!=ob ) 
608                         obsel= base->object;
609         
610         /* the only_IK caller has checked for posemode! */
611         if(only_IK) {
612                 for(con= pchanact->constraints.first; con; con= con->next) {
613                         if(con->type==CONSTRAINT_TYPE_KINEMATIC) break;
614                 }
615                 if(con) {
616                         error("Pose Channel already has IK");
617                         return;
618                 }
619                 
620                 if(pchansel)
621                         nr= pupmenu("Add IK Constraint%t|To Selected Bone%x10");
622                 else if(obsel)
623                         nr= pupmenu("Add IK Constraint%t|To Selected Object%x10");
624                 else 
625                         nr= pupmenu("Add IK Constraint%t|To New Empty Object%x10|Without Target%x11");
626         }
627         else {
628                 if(pchanact) {
629                         if(pchansel)
630                                 nr= pupmenu("Add Constraint to selected Bone%t|Copy Location%x1|Copy Rotation%x2|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7");
631                         else if(obsel && obsel->type==OB_CURVE)
632                                 nr= pupmenu("Add Constraint to selected Object%t|Copy Location%x1|Copy Rotation%x2|Track To%x3|Floor%x4|Locked Track%x5|Follow Path%x6|Stretch To%x7");
633                         else if(obsel)
634                                 nr= pupmenu("Add Constraint to selected Object%t|Copy Location%x1|Copy Rotation%x2|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7");
635                         else
636                                 nr= pupmenu("Add Constraint to New Empty Object%t|Copy Location%x1|Copy Rotation%x2|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7");
637                 }
638                 else {
639                         if(obsel && obsel->type==OB_CURVE)
640                                 nr= pupmenu("Add Constraint to selected Object%t|Copy Location%x1|Copy Rotation%x2|Track To%x3|Floor%x4|Locked Track%x5|Follow Path%x6");
641                         else if(obsel)
642                                 nr= pupmenu("Add Constraint to selected Object%t|Copy Location%x1|Copy Rotation%x2|Track To%x3|Floor%x4|Locked Track%x5");
643                         else
644                                 nr= pupmenu("Add Constraint to New Empty Object%t|Copy Location%x1|Copy Rotation%x2|Track To%x3|Floor%x4|Locked Track%x5");
645                 }
646         }
647         
648         if(nr<1) return;
649         
650         /* handle IK separate */
651         if(nr==10 || nr==11) {
652                 
653                 /* prevent weird chains... */
654                 if(pchansel) {
655                         bPoseChannel *pchan= pchanact;
656                         while(pchan) {
657                                 if(pchan==pchansel) break;
658                                 pchan= pchan->parent;
659                         }
660                         if(pchan) {
661                                 error("IK root cannot be linked to IK tip");
662                                 return;
663                         }
664                         pchan= pchansel;
665                         while(pchan) {
666                                 if(pchan==pchanact) break;
667                                 pchan= pchan->parent;
668                         }
669                         if(pchan) {
670                                 error("IK tip cannot be linked to IK root");
671                                 return;
672                         }               
673                 }
674                 
675                 con = add_new_constraint(CONSTRAINT_TYPE_KINEMATIC);
676                 BLI_addtail(&pchanact->constraints, con);
677                 pchanact->constflag |= PCHAN_HAS_IK;    // for draw, but also for detecting while pose solving
678                 if(nr==11) pchanact->constflag |= PCHAN_HAS_TARGET;
679         }
680         else {
681                 
682                 if(nr==1) con = add_new_constraint(CONSTRAINT_TYPE_LOCLIKE);
683                 else if(nr==2) con = add_new_constraint(CONSTRAINT_TYPE_ROTLIKE);
684                 else if(nr==3) con = add_new_constraint(CONSTRAINT_TYPE_TRACKTO);
685                 else if(nr==4) con = add_new_constraint(CONSTRAINT_TYPE_MINMAX);
686                 else if(nr==5) con = add_new_constraint(CONSTRAINT_TYPE_LOCKTRACK);
687                 else if(nr==6) con = add_new_constraint(CONSTRAINT_TYPE_FOLLOWPATH);
688                 else if(nr==7) con = add_new_constraint(CONSTRAINT_TYPE_STRETCHTO);
689                 
690                 if(con==NULL) return;   /* paranoia */
691                 
692                 if(pchanact) {
693                         BLI_addtail(&pchanact->constraints, con);
694                         pchanact->constflag |= PCHAN_HAS_CONST; /* for draw */
695                 }
696                 else {
697                         BLI_addtail(&ob->constraints, con);
698                 }
699         }
700         
701         /* set the target */
702         if(pchansel) {
703                 set_constraint_target(con, ob, pchansel->name);
704         }
705         else if(obsel) {
706                 set_constraint_target(con, obsel, NULL);
707         }
708         else if(nr!=11) {       /* add new empty as target */
709                 Base *base= BASACT, *newbase;
710                 Object *obt;
711                 
712                 obt= add_object(OB_EMPTY);
713                 /* set layers OK */
714                 newbase= BASACT;
715                 newbase->lay= base->lay;
716                 obt->lay= newbase->lay;
717                 
718                 /* transform cent to global coords for loc */
719                 if(pchanact) {
720                         if(only_IK)
721                                 VecMat4MulVecfl(obt->loc, ob->obmat, pchanact->pose_tail);
722                         else
723                                 VecMat4MulVecfl(obt->loc, ob->obmat, pchanact->pose_head);
724                 }
725                 else
726                         VECCOPY(obt->loc, ob->obmat[3]);
727                 
728                 set_constraint_target(con, obt, NULL);
729                 
730                 /* restore, add_object sets active */
731                 BASACT= base;
732                 base->flag |= SELECT;
733         }
734
735
736         /* active flag */
737         con->flag |= CONSTRAINT_ACTIVE;
738         for(con= con->prev; con; con= con->prev)
739                 con->flag &= ~CONSTRAINT_ACTIVE;
740
741         DAG_scene_sort(G.scene);                // sort order of objects
742         
743         if(pchanact) {
744                 ob->pose->flag |= POSE_RECALC;  // sort pose channels
745                 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);   // and all its relations
746         }
747         else
748                 DAG_object_flush_update(G.scene, ob, OB_RECALC_OB);     // and all its relations
749
750         allqueue (REDRAWVIEW3D, 0);
751         allqueue (REDRAWBUTSOBJECT, 0);
752         allqueue (REDRAWOOPS, 0);
753         
754         if(only_IK)
755                 BIF_undo_push("Add IK Constraint");
756         else
757                 BIF_undo_push("Add Constraint");
758
759 }
760
761