== Transformation Constraint ==
[blender-staging.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_text_types.h"
49 #include "DNA_view3d_types.h"
50
51 #include "BKE_action.h"
52 #include "BKE_armature.h"
53 #include "BKE_constraint.h"
54 #include "BKE_depsgraph.h"
55 #include "BKE_global.h"
56 #include "BKE_main.h"
57 #include "BKE_ipo.h"
58 #include "BKE_object.h"
59 #include "BKE_utildefines.h"
60
61 #include "BIF_editaction.h"
62 #include "BIF_editarmature.h"
63 #include "BIF_editconstraint.h"
64 #include "BIF_poseobject.h"
65 #include "BIF_interface.h"
66 #include "BIF_screen.h"
67 #include "BIF_space.h"
68 #include "BIF_toolbox.h"
69
70 #include "BPY_extern.h"
71
72 #include "blendef.h"
73 #include "nla.h"
74 #include "mydevice.h"
75
76
77 ListBase *get_active_constraint_channels (Object *ob, int forcevalid)
78 {
79         char ipstr[64];
80         
81         if (!ob)
82                 return NULL;
83         
84         /* See if we are a bone constraint */
85         if (ob->flag & OB_POSEMODE) {
86                 bActionChannel *achan;
87                 bPoseChannel *pchan;
88
89                 pchan = get_active_posechannel(ob);
90                 if (pchan) {
91                         
92                         /* Make sure we have an action */
93                         if (!ob->action){
94                                 if (!forcevalid)
95                                         return NULL;
96                                 
97                                 ob->action=add_empty_action("Action");
98                         }
99                         
100                         /* Make sure we have an actionchannel */
101                         achan = get_action_channel(ob->action, pchan->name);
102                         if (!achan){
103                                 if (!forcevalid)
104                                         return NULL;
105                                 
106                                 achan = MEM_callocN (sizeof(bActionChannel), "actionChannel");
107
108                                 strcpy (achan->name, pchan->name);
109                                 sprintf (ipstr, "%s.%s", ob->action->id.name+2, achan->name);
110                                 ipstr[23]=0;
111                                 achan->ipo=     add_ipo(ipstr, ID_AC);  
112                                 
113                                 BLI_addtail (&ob->action->chanbase, achan);
114                         }
115                         
116                         return &achan->constraintChannels;
117                 }
118                 else return NULL;
119         }
120         /* else we return object constraints */
121         else {
122                 if(ob->ipoflag & OB_ACTION_OB) {
123                         bActionChannel *achan = get_action_channel(ob->action, "Object");
124                         if(achan)
125                                 return &achan->constraintChannels;
126                         else 
127                                 return NULL;
128                 }
129                 
130                 return &ob->constraintChannels;
131         }
132 }
133
134
135 /* if object in posemode, active bone constraints, else object constraints */
136 ListBase *get_active_constraints(Object *ob)
137 {
138         if (!ob)
139                 return NULL;
140
141         if (ob->flag & OB_POSEMODE) {
142                 bPoseChannel *pchan;
143
144                 pchan = get_active_posechannel(ob);
145                 if (pchan)
146                         return &pchan->constraints;
147         }
148         else 
149                 return &ob->constraints;
150
151         return NULL;
152 }
153
154 /* single constraint */
155 bConstraint *get_active_constraint(Object *ob)
156 {
157         ListBase *lb= get_active_constraints(ob);
158
159         if(lb) {
160                 bConstraint *con;
161                 for(con= lb->first; con; con=con->next)
162                         if(con->flag & CONSTRAINT_ACTIVE)
163                                 return con;
164         }
165         return NULL;
166 }
167
168 /* single channel, for ipo */
169 bConstraintChannel *get_active_constraint_channel(Object *ob)
170 {
171         bConstraint *con;
172         bConstraintChannel *chan;
173         
174         if (ob->flag & OB_POSEMODE) {
175                 if(ob->action) {
176                         bPoseChannel *pchan;
177                         
178                         pchan = get_active_posechannel(ob);
179                         if(pchan) {
180                                 for(con= pchan->constraints.first; con; con= con->next)
181                                         if(con->flag & CONSTRAINT_ACTIVE)
182                                                 break;
183                                 if(con) {
184                                         bActionChannel *achan = get_action_channel(ob->action, pchan->name);
185                                         if(achan) {
186                                                 for(chan= achan->constraintChannels.first; chan; chan= chan->next)
187                                                         if(!strcmp(chan->name, con->name))
188                                                                 break;
189                                                 return chan;
190                                         }
191                                 }
192                         }
193                 }
194         }
195         else {
196                 for(con= ob->constraints.first; con; con= con->next)
197                         if(con->flag & CONSTRAINT_ACTIVE)
198                                 break;
199                 if(con) {
200                         ListBase *lb= get_active_constraint_channels(ob, 0);
201
202                         if(lb) {
203                                 for(chan= lb->first; chan; chan= chan->next)
204                                         if(!strcmp(chan->name, con->name))
205                                                 break;
206                                 return chan;
207                         }
208                 }
209         }
210         
211         return NULL;
212 }
213
214
215 bConstraint *add_new_constraint(short type)
216 {
217         bConstraint *con;
218
219         con = MEM_callocN(sizeof(bConstraint), "constraint");
220
221         /* Set up a generic constraint datablock */
222         con->type = type;
223         con->flag |= CONSTRAINT_EXPAND;
224         con->enforce=1.0F;
225         /* Load the data for it */
226         con->data = new_constraint_data(con->type);
227         strcpy (con->name, "Const");
228         return con;
229 }
230
231 void add_constraint_to_object(bConstraint *con, Object *ob)
232 {
233         ListBase *list;
234         list = &ob->constraints;
235         
236         if (list) {
237                 unique_constraint_name(con, list);
238                 BLI_addtail(list, con);
239                 
240                 con->flag |= CONSTRAINT_ACTIVE;
241                 for(con= con->prev; con; con= con->prev)
242                         con->flag &= ~CONSTRAINT_ACTIVE;
243         }
244 }
245
246
247 char *get_con_subtarget_name(bConstraint *con, Object *target)
248 {
249         /*
250          * If the target for this constraint is target, return a pointer 
251          * to the name for this constraints subtarget ... NULL otherwise
252          */
253          
254         if (constraint_has_target(con)) {
255                 Object *tar;
256                 char *subtarget;
257                 
258                 tar = get_constraint_target(con, &subtarget);
259                 if (tar==target) return subtarget;
260         }
261         
262         return NULL;  
263 }
264
265 /* checks validity of object pointers, and NULLs,
266    if Bone doesnt exist it sets the CONSTRAINT_DISABLE flag */
267 static void test_constraints (Object *owner, const char* substring)
268 {
269         
270         bConstraint *curcon;
271         ListBase *conlist= NULL;
272         int type;
273         
274         if (owner==NULL) return;
275         
276         /* Check parents */
277         /* Get the constraint list for this object */
278         
279         if (strlen (substring)) {
280                 switch (owner->type) {
281                         case OB_ARMATURE:
282                                 type = TARGET_BONE;
283                                 break;
284                         default:
285                                 type = TARGET_OBJECT;
286                                 break;
287                 }
288         }
289         else
290                 type = TARGET_OBJECT;
291         
292         
293         switch (type) {
294                 case TARGET_OBJECT:
295                         conlist = &owner->constraints;
296                         break;
297                 case TARGET_BONE:
298                         {
299                                 Bone *bone;
300                                 bPoseChannel *chan;
301                                 
302                                 bone = get_named_bone(((bArmature*)owner->data), substring);
303                                 chan = get_pose_channel (owner->pose, substring);
304                                 if (bone && chan){
305                                         conlist = &chan->constraints;
306                                 }
307                         }
308                         break;
309         }
310         
311         /* Check all constraints - is constraint valid? */
312         if (conlist) {
313                 for (curcon = conlist->first; curcon; curcon=curcon->next) {
314                         curcon->flag &= ~CONSTRAINT_DISABLE;
315                         
316                         switch (curcon->type) {
317                                 case CONSTRAINT_TYPE_PYTHON:
318                                 {
319                                         bPythonConstraint *data = curcon->data;
320                                         float dummy_matrix[4][4];
321                                         
322                                         /* is there are valid script? */
323                                         if (!data->text) {
324                                                 curcon->flag |= CONSTRAINT_DISABLE;
325                                                 break;
326                                         }
327                                         else if (!BPY_is_pyconstraint(data->text)) {
328                                                 curcon->flag |= CONSTRAINT_DISABLE;
329                                                 break;
330                                         }
331                                         data->flag &= ~PYCON_SCRIPTERROR;
332                                         
333                                         /* does the constraint require target input? */
334                                         if (BPY_pyconstraint_targets(data, dummy_matrix))
335                                                 data->flag |= PYCON_USETARGETS;
336                                         else
337                                                 data->flag &= ~PYCON_USETARGETS;
338                                         
339                                         /* check whether we have a valid target */
340                                         if (data->flag & PYCON_USETARGETS) {
341                                                 /* validate target */
342                                                 if (!exist_object(data->tar)) {
343                                                         data->tar = NULL;
344                                                         curcon->flag |= CONSTRAINT_DISABLE;
345                                                         break;
346                                                 }
347                                                 
348                                                 if ( (data->tar == owner) &&
349                                                          (!get_named_bone(get_armature(owner), 
350                                                                                           data->subtarget))) {
351                                                         curcon->flag |= CONSTRAINT_DISABLE;
352                                                         break;
353                                                 }
354                                         }
355                                         else {
356                                                 /* don't hold onto target */
357                                                 data->tar = NULL;
358                                                 BLI_strncpy(data->subtarget, "", 32);
359                                         }
360                                 }
361                                         break;
362                                 case CONSTRAINT_TYPE_ACTION:
363                                 {
364                                         bActionConstraint *data = curcon->data;
365                                         
366                                         if (!exist_object(data->tar)){
367                                                 data->tar = NULL;
368                                                 curcon->flag |= CONSTRAINT_DISABLE;
369                                                 break;
370                                         }
371                                         
372                                         if ( (data->tar == owner) &&
373                                                  (!get_named_bone(get_armature(owner), 
374                                                                                   data->subtarget))) {
375                                                 curcon->flag |= CONSTRAINT_DISABLE;
376                                                 break;
377                                         }
378                                 }
379                                         break;
380                                 case CONSTRAINT_TYPE_LOCLIKE:
381                                 {
382                                         bLocateLikeConstraint *data = curcon->data;
383                                         
384                                         if (!exist_object(data->tar)){
385                                                 data->tar = NULL;
386                                                 curcon->flag |= CONSTRAINT_DISABLE;
387                                                 break;
388                                         }
389                                         
390                                         if ( (data->tar == owner) &&
391                                                  (!get_named_bone(get_armature(owner), 
392                                                                                   data->subtarget))) {
393                                                 curcon->flag |= CONSTRAINT_DISABLE;
394                                                 break;
395                                         }
396                                 }
397                                         break;
398                                 case CONSTRAINT_TYPE_MINMAX:
399                                 {
400                                         bMinMaxConstraint *data = curcon->data;
401                                         
402                                         if (!exist_object(data->tar)){
403                                                 data->tar = NULL;
404                                                 curcon->flag |= CONSTRAINT_DISABLE;
405                                                 break;
406                                         }
407                                         
408                                         if ( (data->tar == owner) &&
409                                                  (!get_named_bone(get_armature(owner), 
410                                                                                   data->subtarget))) {
411                                                 curcon->flag |= CONSTRAINT_DISABLE;
412                                                 break;
413                                         }
414                                 }
415                                         break;
416                                 case CONSTRAINT_TYPE_ROTLIKE:
417                                 {
418                                         bRotateLikeConstraint *data = curcon->data;
419                                         
420                                         if (!exist_object(data->tar)){
421                                                 data->tar = NULL;
422                                                 curcon->flag |= CONSTRAINT_DISABLE;
423                                                 break;
424                                         }
425                                         
426                                         if ( (data->tar == owner) &&
427                                                  (!get_named_bone(get_armature(owner), 
428                                                                                   data->subtarget))) {
429                                                 curcon->flag |= CONSTRAINT_DISABLE;
430                                                 break;
431                                         }
432                                 }
433                                         break;
434                                 case CONSTRAINT_TYPE_SIZELIKE:
435                                 {
436                                         bSizeLikeConstraint *data = curcon->data;
437                                 
438                                         if (!exist_object(data->tar)){
439                                                 data->tar = NULL;
440                                                 curcon->flag |= CONSTRAINT_DISABLE;
441                                                 break;
442                                         }
443                                         
444                                         if ( (data->tar == owner) &&
445                                                  (!get_named_bone(get_armature(owner), 
446                                                                                   data->subtarget))) {
447                                                 curcon->flag |= CONSTRAINT_DISABLE;
448                                                 break;
449                                         }
450                                 }
451                                         break;
452                                 case CONSTRAINT_TYPE_KINEMATIC:
453                                 {
454                                         bKinematicConstraint *data = curcon->data;
455                                         if (!exist_object(data->tar)){
456                                                 data->tar = NULL;
457                                                 curcon->flag |= CONSTRAINT_DISABLE;
458                                                 break;
459                                         }
460                                         
461                                         if ( (data->tar == owner) &&
462                                                  (!get_named_bone(get_armature(owner), 
463                                                                                   data->subtarget))) {
464                                                 curcon->flag |= CONSTRAINT_DISABLE;
465                                                 break;
466                                         }
467                                 }
468                                         break;
469                                 case CONSTRAINT_TYPE_TRACKTO:
470                                 {
471                                         bTrackToConstraint *data = curcon->data;
472                                         if (!exist_object(data->tar)) {
473                                                 data->tar = NULL;
474                                                 curcon->flag |= CONSTRAINT_DISABLE;
475                                                 break;
476                                         }
477                                         
478                                         if ( (data->tar == owner) &&
479                                                  (!get_named_bone(get_armature(owner), 
480                                                                                   data->subtarget))) {
481                                                 curcon->flag |= CONSTRAINT_DISABLE;
482                                                 break;
483                                         }
484                                         if (data->reserved2==data->reserved1){
485                                                 curcon->flag |= CONSTRAINT_DISABLE;
486                                                 break;
487                                         }
488                                         if (data->reserved2+3==data->reserved1){
489                                                 curcon->flag |= CONSTRAINT_DISABLE;
490                                                 break;
491                                         }
492                                 }
493                                         break;
494                                 case CONSTRAINT_TYPE_LOCKTRACK:
495                                 {
496                                         bLockTrackConstraint *data = curcon->data;
497                                         
498                                         if (!exist_object(data->tar)){
499                                                 data->tar = NULL;
500                                                 curcon->flag |= CONSTRAINT_DISABLE;
501                                                 break;
502                                         }
503                                         
504                                         if ( (data->tar == owner) &&
505                                                  (!get_named_bone(get_armature(owner), 
506                                                                                   data->subtarget))) {
507                                                 curcon->flag |= CONSTRAINT_DISABLE;
508                                                 break;
509                                         }
510
511                                         if (data->lockflag==data->trackflag){
512                                                 curcon->flag |= CONSTRAINT_DISABLE;
513                                                 break;
514                                         }
515                                         if (data->lockflag+3==data->trackflag){
516                                                 curcon->flag |= CONSTRAINT_DISABLE;
517                                                 break;
518                                         }
519                                 }
520                                         break;
521                                 case CONSTRAINT_TYPE_STRETCHTO:
522                                 {
523                                         bStretchToConstraint *data = curcon->data;
524                                         
525                                         if (!exist_object(data->tar)){
526                                                 data->tar = NULL;
527                                                 curcon->flag |= CONSTRAINT_DISABLE;
528                                                 break;
529                                         }
530                                         
531                                         if ( (data->tar == owner) &&
532                                                  (!get_named_bone(get_armature(owner), 
533                                                                                   data->subtarget))) {
534                                                 curcon->flag |= CONSTRAINT_DISABLE;
535                                                 break;
536                                         }
537                                 }
538                                         break;
539                                 case CONSTRAINT_TYPE_FOLLOWPATH:
540                                 {
541                                         bFollowPathConstraint *data = curcon->data;
542                                         
543                                         if (!exist_object(data->tar)){
544                                                 data->tar = NULL;
545                                                 curcon->flag |= CONSTRAINT_DISABLE;
546                                                 break;
547                                         }
548                                         if (data->tar->type != OB_CURVE){
549                                                 data->tar = NULL;
550                                                 curcon->flag |= CONSTRAINT_DISABLE;
551                                                 break;
552                                         }
553                                         if (data->upflag==data->trackflag){
554                                                 curcon->flag |= CONSTRAINT_DISABLE;
555                                                 break;
556                                         }
557                                         if (data->upflag+3==data->trackflag){
558                                                 curcon->flag |= CONSTRAINT_DISABLE;
559                                                 break;
560                                         }
561                                 }
562                                         break;
563                                 case CONSTRAINT_TYPE_CLAMPTO:
564                                 {
565                                         bClampToConstraint *data = curcon->data;
566                                         
567                                         if (!exist_object(data->tar)){
568                                                 data->tar = NULL;
569                                                 curcon->flag |= CONSTRAINT_DISABLE;
570                                                 break;
571                                         }
572                                         
573                                         if (data->tar->type != OB_CURVE){
574                                                 data->tar = NULL;
575                                                 curcon->flag |= CONSTRAINT_DISABLE;
576                                                 break;
577                                         }
578                                         else {
579                                                 Curve *cu= data->tar->data;
580                                                 
581                                                 /* auto-set 'Path' setting on curve so this works  */
582                                                 cu->flag |= CU_PATH;
583                                         }                                       
584                                 }
585                                         break;
586                                 case CONSTRAINT_TYPE_TRANSFORM:
587                                 {
588                                         bTransformConstraint *data = curcon->data;
589                                         
590                                         if (!exist_object(data->tar)){
591                                                 data->tar = NULL;
592                                                 curcon->flag |= CONSTRAINT_DISABLE;
593                                                 break;
594                                         }
595                                         
596                                         if ( (data->tar == owner) &&
597                                                  (!get_named_bone(get_armature(owner), 
598                                                                                   data->subtarget))) {
599                                                 curcon->flag |= CONSTRAINT_DISABLE;
600                                                 break;
601                                         }
602                                 }
603                                         break;
604                         }
605                 }
606         }
607 }
608
609 static void test_bonelist_constraints (Object *owner, ListBase *list)
610 {
611         Bone *bone;
612
613         for (bone = list->first; bone; bone=bone->next) {
614                 
615                 test_constraints(owner, bone->name);
616                 test_bonelist_constraints (owner, &bone->childbase);
617         }
618 }
619
620 void object_test_constraints (Object *owner)
621 {
622         test_constraints(owner, "");
623
624         if(owner->type==OB_ARMATURE) {
625                 bArmature *arm;
626                 arm = get_armature(owner);
627                 if (arm)
628                         test_bonelist_constraints (owner, &arm->bonebase);
629         }
630
631 }
632
633 /* context: active object in posemode, active channel, optional selected channel */
634 void add_constraint(int only_IK)
635 {
636         Object *ob= OBACT, *obsel=NULL;
637         bPoseChannel *pchanact=NULL, *pchansel=NULL;
638         bConstraint *con=NULL;
639         Base *base;
640         short nr;
641         
642         /* paranoia checks */
643         if(ob==NULL || ob==G.obedit) return;
644
645         if(ob->pose && (ob->flag & OB_POSEMODE)) {
646                 bArmature *arm= ob->data;
647                 
648                 /* find active channel */
649                 pchanact= get_active_posechannel(ob);
650                 if(pchanact==NULL) return;
651         
652                 /* check protection */
653                 if(ob->proxy && (pchanact->bone->layer & arm->layer_protected)) {
654                         error("Bone is Proxy protected");
655                         return;
656                 }
657                 
658                 /* find selected bone */
659                 for(pchansel= ob->pose->chanbase.first; pchansel; pchansel= pchansel->next) {
660                         if(pchansel!=pchanact)
661                                 if(pchansel->bone->flag & BONE_SELECTED) 
662                                         if(pchansel->bone->layer & arm->layer)
663                                                 break;
664                 }
665         }
666         
667         /* find selected object */
668         for(base= FIRSTBASE; base; base= base->next)
669                 if( TESTBASE(base) && base->object!=ob ) 
670                         obsel= base->object;
671         
672         /* the only_IK caller has checked for posemode! */
673         if(only_IK) {
674                 for(con= pchanact->constraints.first; con; con= con->next) {
675                         if(con->type==CONSTRAINT_TYPE_KINEMATIC) break;
676                 }
677                 if(con) {
678                         error("Pose Channel already has IK");
679                         return;
680                 }
681                 
682                 if(pchansel)
683                         nr= pupmenu("Add IK Constraint%t|To Active Bone%x10");
684                 else if(obsel)
685                         nr= pupmenu("Add IK Constraint%t|To Active Object%x10");
686                 else 
687                         nr= pupmenu("Add IK Constraint%t|To New Empty Object%x10|Without Target%x11");
688         }
689         else {
690                 if(pchanact) {
691                         if(pchansel)
692                                 nr= pupmenu("Add Constraint to Active Bone%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|%l|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7|%l|Action%x16|Script%x18");
693                         else if(obsel && obsel->type==OB_CURVE)
694                                 nr= pupmenu("Add Constraint to Active Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|%l|Track To%x3|Floor%x4|Locked Track%x5|Follow Path%x6|Clamp To%x17|Stretch To%x7|%l|Action%x16|Script%x18");
695                         else if(obsel)
696                                 nr= pupmenu("Add Constraint to Active Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|%l|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7|%l|Action%x16|Script%x18");
697                         else
698                                 nr= pupmenu("Add Constraint to New Empty Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|%l|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7|%l|Script%x18");
699                 }
700                 else {
701                         if(obsel && obsel->type==OB_CURVE)
702                                 nr= pupmenu("Add Constraint to Active Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|%l|Track To%x3|Floor%x4|Locked Track%x5|Follow Path%x6|Clamp To%x17|%l|Script%x18");
703                         else if(obsel)
704                                 nr= pupmenu("Add Constraint to Active Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|%l|Track To%x3|Floor%x4|Locked Track%x5|%l|Script%x18");
705                         else
706                                 nr= pupmenu("Add Constraint to New Empty Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|%l|Track To%x3|Floor%x4|Locked Track%x5|%l|Script%x18");
707                 }
708         }
709         
710         if(nr<1) return;
711         
712         /* handle IK separate */
713         if(nr==10 || nr==11) {
714                 
715                 /* prevent weird chains... */
716                 if(pchansel) {
717                         bPoseChannel *pchan= pchanact;
718                         while(pchan) {
719                                 if(pchan==pchansel) break;
720                                 pchan= pchan->parent;
721                         }
722                         if(pchan) {
723                                 error("IK root cannot be linked to IK tip");
724                                 return;
725                         }
726                         pchan= pchansel;
727                         while(pchan) {
728                                 if(pchan==pchanact) break;
729                                 pchan= pchan->parent;
730                         }
731                         if(pchan) {
732                                 error("IK tip cannot be linked to IK root");
733                                 return;
734                         }               
735                 }
736                 
737                 con = add_new_constraint(CONSTRAINT_TYPE_KINEMATIC);
738                 BLI_addtail(&pchanact->constraints, con);
739                 unique_constraint_name(con, &pchanact->constraints);
740                 pchanact->constflag |= PCHAN_HAS_IK;    // for draw, but also for detecting while pose solving
741                 if(nr==11) pchanact->constflag |= PCHAN_HAS_TARGET;
742         }
743         else {
744                 
745                 if (nr==1) con = add_new_constraint(CONSTRAINT_TYPE_LOCLIKE);
746                 else if (nr==2) con = add_new_constraint(CONSTRAINT_TYPE_ROTLIKE);
747                 else if (nr==3) con = add_new_constraint(CONSTRAINT_TYPE_TRACKTO);
748                 else if (nr==4) con = add_new_constraint(CONSTRAINT_TYPE_MINMAX);
749                 else if (nr==5) con = add_new_constraint(CONSTRAINT_TYPE_LOCKTRACK);
750                 else if (nr==6) {
751                         Curve *cu= obsel->data;
752                         cu->flag |= CU_PATH;
753                         con = add_new_constraint(CONSTRAINT_TYPE_FOLLOWPATH);
754                 }
755                 else if (nr==7) con = add_new_constraint(CONSTRAINT_TYPE_STRETCHTO);
756                 else if (nr==8) con = add_new_constraint(CONSTRAINT_TYPE_SIZELIKE);
757                 else if (nr==13) con = add_new_constraint(CONSTRAINT_TYPE_LOCLIMIT);
758                 else if (nr==14) con = add_new_constraint(CONSTRAINT_TYPE_ROTLIMIT);
759                 else if (nr==15) con = add_new_constraint(CONSTRAINT_TYPE_SIZELIMIT);
760                 else if (nr==16) {
761                         /* TODO: add a popup-menu to display list of available actions to use (like for pyconstraints) */
762                         con = add_new_constraint(CONSTRAINT_TYPE_ACTION);
763                 }
764                 else if (nr==17) {
765                         Curve *cu= obsel->data;
766                         cu->flag |= CU_PATH;
767                         con = add_new_constraint(CONSTRAINT_TYPE_CLAMPTO);
768                 }
769                 else if (nr==18) {      
770                         char *menustr;
771                         int scriptint= 0, dummy_int=0;
772                         float dummy_matrix[4][4];
773                         
774                         /* popup a list of usable scripts */
775                         menustr = buildmenu_pyconstraints(NULL, &dummy_int);
776                         scriptint = pupmenu(menustr);
777                         MEM_freeN(menustr);
778                         
779                         /* only add constraint if a script was chosen */
780                         if (scriptint) {
781                                 /* add constraint */
782                                 con = add_new_constraint(CONSTRAINT_TYPE_PYTHON);
783                                 validate_pyconstraint_cb(con->data, &scriptint);
784                                 
785                                 /* make sure target allowance is set correctly */
786                                 dummy_int = BPY_pyconstraint_targets(con->data, dummy_matrix);
787                                 if (dummy_int) {
788                                         bPythonConstraint *pycon= (bPythonConstraint *)con->data;
789                                         pycon->flag |= PYCON_USETARGETS;
790                                 }
791                         }
792                 }
793                 else if (nr==19) {
794                         con = add_new_constraint(CONSTRAINT_TYPE_CHILDOF);
795                         
796                         /* if this constraint is being added to a posechannel, make sure
797                          * the constraint gets evaluated in pose-space
798                          */
799                         if (pchanact) {
800                                 con->ownspace = CONSTRAINT_SPACE_POSE;
801                                 con->flag |= CONSTRAINT_SPACEONCE;
802                         }
803                 }
804                 else if (nr==20) con = add_new_constraint(CONSTRAINT_TYPE_TRANSFORM);
805                 
806                 if (con==NULL) return;  /* paranoia */
807                 
808                 if (pchanact) {
809                         BLI_addtail(&pchanact->constraints, con);
810                         unique_constraint_name(con, &pchanact->constraints);
811                         pchanact->constflag |= PCHAN_HAS_CONST; /* for draw */
812                 }
813                 else {
814                         BLI_addtail(&ob->constraints, con);
815                         unique_constraint_name(con, &ob->constraints);
816                 }
817         }
818         
819         /* set the target */
820         if (pchansel) {
821                 set_constraint_target(con, ob, pchansel->name);
822         }
823         else if(obsel) {
824                 set_constraint_target(con, obsel, NULL);
825         }
826         else if (ELEM4(nr, 11, 13, 14, 15)==0) {        /* add new empty as target */
827                 Base *base= BASACT, *newbase;
828                 Object *obt;
829                 
830                 obt= add_object(OB_EMPTY);
831                 /* set layers OK */
832                 newbase= BASACT;
833                 newbase->lay= base->lay;
834                 obt->lay= newbase->lay;
835                 
836                 /* transform cent to global coords for loc */
837                 if (pchanact) {
838                         if(only_IK)
839                                 VecMat4MulVecfl(obt->loc, ob->obmat, pchanact->pose_tail);
840                         else
841                                 VecMat4MulVecfl(obt->loc, ob->obmat, pchanact->pose_head);
842                 }
843                 else
844                         VECCOPY(obt->loc, ob->obmat[3]);
845                 
846                 set_constraint_target(con, obt, NULL);
847                 
848                 /* restore, add_object sets active */
849                 BASACT= base;
850                 base->flag |= SELECT;
851         }
852         
853         /* active flag */
854         con->flag |= CONSTRAINT_ACTIVE;
855         for(con= con->prev; con; con= con->prev)
856                 con->flag &= ~CONSTRAINT_ACTIVE;
857
858         DAG_scene_sort(G.scene);                // sort order of objects
859         
860         if (pchanact) {
861                 ob->pose->flag |= POSE_RECALC;  // sort pose channels
862                 DAG_object_flush_update(G.scene, ob, OB_RECALC_DATA);   // and all its relations
863         }
864         else
865                 DAG_object_flush_update(G.scene, ob, OB_RECALC_OB);     // and all its relations
866
867         allqueue (REDRAWVIEW3D, 0);
868         allqueue (REDRAWBUTSOBJECT, 0);
869         allqueue (REDRAWOOPS, 0);
870         
871         if (only_IK)
872                 BIF_undo_push("Add IK Constraint");
873         else
874                 BIF_undo_push("Add Constraint");
875
876 }
877
878 void ob_clear_constraints(void)
879 {
880         Object *ob= OBACT;
881         
882         /* paranoia checks */
883         if(!ob) return;
884         if(ob==G.obedit || (ob->flag & OB_POSEMODE)) return;
885         
886         if(okee("Clear Constraints")==0) return;
887         
888         free_constraints(&ob->constraints);
889         
890         DAG_object_flush_update(G.scene, ob, OB_RECALC_OB);
891         
892         allqueue (REDRAWVIEW3D, 0);
893         allqueue (REDRAWBUTSOBJECT, 0);
894         allqueue (REDRAWOOPS, 0);
895         
896         BIF_undo_push("Clear Constraint(s)");
897         
898 }
899
900 /* con already has the new name */
901 void rename_constraint(Object *ob, bConstraint *con, char *oldname)
902 {
903         bConstraint *tcon;
904         bConstraintChannel *conchan;
905         ListBase *conlist= NULL;
906         int from_object= 0;
907         char *channame="";
908         
909         /* get context by searching for con (primitive...) */
910         for(tcon= ob->constraints.first; tcon; tcon= tcon->next)
911                 if(tcon==con)
912                         break;
913         
914         if(tcon) {
915                 conlist= &ob->constraints;
916                 channame= "Object";
917                 from_object= 1;
918         }
919         else if(ob->pose) {
920                 bPoseChannel *pchan;
921                 
922                 for(pchan= ob->pose->chanbase.first; pchan; pchan= pchan->next) {
923                         for(tcon= pchan->constraints.first; tcon; tcon= tcon->next) {
924                                 if(tcon==con)
925                                         break;
926                         }
927                         if(tcon)
928                                 break;
929                 }
930                 if(tcon) {
931                         conlist= &pchan->constraints;
932                         channame= pchan->name;
933                 }
934         }
935         
936         if(conlist==NULL) {
937                 printf("rename constraint failed\n");   /* should not happen in UI */
938                 return;
939         }
940         
941         /* first make sure it's a unique name within context */
942         unique_constraint_name (con, conlist);
943
944         /* own channels */
945         if(from_object) {
946                 for(conchan= ob->constraintChannels.first; conchan; conchan= conchan->next) {
947                         if( strcmp(oldname, conchan->name)==0 )
948                                 BLI_strncpy(conchan->name, con->name, sizeof(conchan->name));
949                 }
950         }
951         /* own action */
952         if(ob->action) {
953                 bActionChannel *achan= get_action_channel(ob->action, channame);
954                 if(achan) {
955                         conchan= get_constraint_channel(&achan->constraintChannels, oldname);
956                         if(conchan)
957                                 BLI_strncpy(conchan->name, con->name, sizeof(conchan->name));
958                 }
959         }
960         
961 }
962
963 /* ********************** CONSTRAINT-SPECIFIC STUFF ********************* */
964 /* ------------- PyConstraints ------------------ */
965
966 /* this callback sets the text-file to be used for selected menu item */
967 void validate_pyconstraint_cb(void *arg1, void *arg2)
968 {
969         bPythonConstraint *data = arg1;
970         Text *text;
971         int index = *((int *)arg2);
972         int i;
973         
974         /* innovative use of a for...loop to search */
975         for (text=G.main->text.first, i=1; text && index!=i; i++, text=text->id.next);
976         data->text = text;
977 }
978
979 /* this returns a string for the list of usable pyconstraint script names */
980 char *buildmenu_pyconstraints(Text *con_text, int *pyconindex)
981 {
982         Text *text;
983         char *menustr = MEM_callocN(128, "menustr pyconstraints");
984         char *name, stmp[128];
985         int buf = 128;
986         int used = strlen("Scripts: %t") + 1;
987         int i;
988                 
989         sprintf(menustr, "%s", "Scripts: %t");
990         
991         for (text=G.main->text.first, i=1; text; i++, text=text->id.next) {
992                 /* this is important to ensure that right script is shown as active */
993                 if (text == con_text) *pyconindex = i;
994                 
995                 /* menu entry is length of name + 3(len(|%X)) + 6 characters for the int.*/
996                 if (BPY_is_pyconstraint(text)) {
997                         name= text->id.name;
998                         if (strlen(name)+used+10 >= buf) {
999                                 char *newbuf = MEM_callocN(buf+128, "menustr pyconstraints 2");
1000                                 memcpy(newbuf, menustr, used);
1001                                 MEM_freeN(menustr);
1002                                 menustr = newbuf;
1003                                 buf += 128;
1004                         }
1005                         sprintf(stmp, "|%s%%x%d", name, i);
1006                         strcat(menustr, stmp);
1007                         used += strlen(name)+10;
1008                 }
1009         }
1010         
1011         return menustr;
1012 }