Constraint stuff from tuhopuu including (but probably not limited too):
authorMartin Poirier <theeth@yahoo.com>
Tue, 21 Oct 2003 13:22:07 +0000 (13:22 +0000)
committerMartin Poirier <theeth@yahoo.com>
Tue, 21 Oct 2003 13:22:07 +0000 (13:22 +0000)
Axis options for TrackTo
LockTrack
FollowPath

Auto creation of TrackTo constraint from Ctrl-T (old track still an option)

Auto creation of FollowPath when parenting to path (Normal parent still an option)

Backward compatibility stuff to convert the per object axis settings to per constraint when a Track constraint is present.

Function to convert old track to constraint (commented out)

Revamped the constraints interface with Matt's work from tuhopuu and the stuff we were discussing earlier.

--------------------
For coders:

unique_constraint_name and *new_constraint_data  moved to the kernel (constraint.c)

new Projf function in arithb gives the projection of a vector on another vector

add_new_constraint now takes a constraint type (int) parameter

add_constraint_to_object(bConstraint *con, Object *ob) to link a constraint to an object

add_constraint_to_client(bConstraint *con) to link constraint to current client (object or bone)

add_influence_key_to_constraint (bConstraint *con) to (eventually) add a keyframe to the influence IPO of a constraint

12 files changed:
source/blender/blenkernel/BKE_constraint.h
source/blender/blenkernel/intern/constraint.c
source/blender/blenlib/BLI_arithb.h
source/blender/blenlib/intern/arithb.c
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/writefile.c
source/blender/include/BIF_editconstraint.h
source/blender/include/butspace.h
source/blender/makesdna/DNA_constraint_types.h
source/blender/src/buttons_object.c
source/blender/src/editconstraint.c
source/blender/src/editobject.c

index 8da92f85c893c987a20f189e4637b20ecb0919be..0a878d93ebe8a5a553b154017bd534416b5abc9e 100644 (file)
@@ -41,6 +41,8 @@ struct bAction;
 struct bArmature;
 
 /* Function prototypes */
+void unique_constraint_name (struct bConstraint *con, struct ListBase *list);
+void *new_constraint_data (short type);
 void evaluate_constraint (struct bConstraint *constraint, struct Object *ob, short ownertype, void *ownerdata, float targetmat[][4]);
 void free_constraints (struct ListBase *conlist);
 void copy_constraints (struct ListBase *dst, struct ListBase *src);
index d4c535004b6d1a588e877e6bd5b26004b55f1399..7d591ad234f7e3780dd8950125c19b51c2f99284 100644 (file)
@@ -47,6 +47,7 @@
 
 #include "BKE_utildefines.h"
 #include "BKE_action.h"
+#include "BKE_anim.h" // for the curve calculation part
 #include "BKE_armature.h"
 #include "BKE_blender.h"
 #include "BKE_constraint.h"
@@ -69,6 +70,141 @@ static void constraint_target_to_mat4 (Object *ob, const char *substring, float
 
 /* Functions */
 
+void unique_constraint_name (bConstraint *con, ListBase *list){
+       char            tempname[64];
+       int                     number;
+       char            *dot;
+       int exists = 0;
+       bConstraint *curcon;
+       
+       /* See if we even need to do this */
+       for (curcon = list->first; curcon; curcon=curcon->next){
+               if (curcon!=con){
+                       if (!strcmp(curcon->name, con->name)){
+                               exists = 1;
+                               break;
+                       }
+               }
+       }
+       
+       if (!exists)
+               return;
+
+       /*      Strip off the suffix */
+       dot=strchr(con->name, '.');
+       if (dot)
+               *dot=0;
+       
+       for (number = 1; number <=999; number++){
+               sprintf (tempname, "%s.%03d", con->name, number);
+               
+               exists = 0;
+               for (curcon=list->first; curcon; curcon=curcon->next){
+                       if (con!=curcon){
+                               if (!strcmp (curcon->name, tempname)){
+                                       exists = 1;
+                                       break;
+                               }
+                       }
+               }
+               if (!exists){
+                       strcpy (con->name, tempname);
+                       return;
+               }
+       }
+}
+
+void   *new_constraint_data (short type)
+{
+       void    *result;
+       
+       switch (type){
+       case CONSTRAINT_TYPE_KINEMATIC:
+               {
+                       bKinematicConstraint *data;
+                       data = MEM_callocN(sizeof(bKinematicConstraint), "kinematicConstraint");
+
+                       data->tolerance = (float)0.001;
+                       data->iterations = 500;
+
+                       result = data;
+               }
+               break;
+       case CONSTRAINT_TYPE_NULL:
+               {
+                       result = NULL;
+               }
+               break;
+       case CONSTRAINT_TYPE_TRACKTO:
+               {
+                       bTrackToConstraint *data;
+                       data = MEM_callocN(sizeof(bTrackToConstraint), "tracktoConstraint");
+
+
+                       data->reserved1 = TRACK_Y;
+                       data->reserved2 = UP_Z;
+
+                       result = data;
+
+               }
+               break;
+       case CONSTRAINT_TYPE_ROTLIKE:
+               {
+                       bRotateLikeConstraint *data;
+                       data = MEM_callocN(sizeof(bRotateLikeConstraint), "rotlikeConstraint");
+
+                       result = data;
+               }
+               break;
+       case CONSTRAINT_TYPE_LOCLIKE:
+               {
+                       bLocateLikeConstraint *data;
+                       data = MEM_callocN(sizeof(bLocateLikeConstraint), "loclikeConstraint");
+
+                       data->flag |= LOCLIKE_X|LOCLIKE_Y|LOCLIKE_Z;
+                       result = data;
+               }
+               break;
+       case CONSTRAINT_TYPE_ACTION:
+               {
+                       bActionConstraint *data;
+                       data = MEM_callocN(sizeof(bActionConstraint), "actionConstraint");
+
+                       result = data;
+               }
+               break;
+       case CONSTRAINT_TYPE_LOCKTRACK:
+               {
+                       bLockTrackConstraint *data;
+                       data = MEM_callocN(sizeof(bLockTrackConstraint), "locktrackConstraint");
+
+                       data->trackflag = TRACK_Y;
+                       data->lockflag = LOCK_Z;
+
+                       result = data;
+               }
+               break;
+       case CONSTRAINT_TYPE_FOLLOWPATH:
+               {
+                       bFollowPathConstraint *data;
+                       data = MEM_callocN(sizeof(bFollowPathConstraint), "followpathConstraint");
+
+                       data->trackflag = TRACK_Y;
+                       data->upflag = UP_Z;
+                       data->offset = 0;
+                       data->followflag = 0;
+
+                       result = data;
+               }
+               break;
+       default:
+               result = NULL;
+               break;
+       }
+
+       return result;
+}
+
 bConstraintChannel *find_constraint_channel (ListBase *list, const char *name){
        bConstraintChannel *chan;
 
@@ -361,6 +497,77 @@ short get_constraint_target (bConstraint *con, short ownertype, void* ownerdata,
                                Mat4One (mat);
                } 
                break;
+       case CONSTRAINT_TYPE_LOCKTRACK:
+               {
+                       bLockTrackConstraint *data;
+                       data = (bLockTrackConstraint*)con->data;
+
+                       if (data->tar){
+                               constraint_target_to_mat4(data->tar, data->subtarget, mat, size, ctime);
+                               valid=1;
+                       }
+                       else
+                               Mat4One (mat);
+               } 
+               break;
+       case CONSTRAINT_TYPE_FOLLOWPATH:
+               {
+                       bFollowPathConstraint *data;
+                       data = (bFollowPathConstraint*)con->data;
+
+                       if (data->tar){
+                               Curve *cu;
+                               float q[4], vec[4], dir[3], *quat, x1, totmat[4][4];
+                               float curvetime;
+
+                               Mat4One (totmat);
+
+                               cu= data->tar->data;
+                               
+                               if(data->followflag) {
+                                       if(!(cu->flag & CU_FOLLOW)) cu->flag += CU_FOLLOW;
+                               }
+                               else {
+                                       if(cu->flag & CU_FOLLOW) cu->flag -= CU_FOLLOW;
+                               }
+
+                               if(!(cu->flag & CU_PATH)) cu->flag += CU_PATH;
+
+                               if(cu->path==0 || cu->path->data==0) calc_curvepath(data->tar);
+
+                               curvetime = ctime - data->offset;
+
+                               if(calc_ipo_spec(cu->ipo, CU_SPEED, &curvetime)==0) {
+                                       ctime /= cu->pathlen;
+                                       CLAMP(ctime, 0.0, 1.0);
+                               }
+
+                               if(where_on_path(data->tar, curvetime, vec, dir) ) {
+
+                                       if(data->followflag){
+                                               quat= vectoquat(dir, (short) data->trackflag, (short) data->upflag);
+
+                                               Normalise(dir);
+                                               q[0]= (float)cos(0.5*vec[3]);
+                                               x1= (float)sin(0.5*vec[3]);
+                                               q[1]= -x1*dir[0];
+                                               q[2]= -x1*dir[1];
+                                               q[3]= -x1*dir[2];
+                                               QuatMul(quat, q, quat);
+                                               
+
+                                               QuatToMat4(quat, totmat);
+                                       }
+                               VECCOPY(totmat[3], vec);
+
+                               Mat4MulSerie(mat, data->tar->obmat, totmat, NULL, NULL, NULL, NULL, NULL, NULL);
+                               }
+                               valid=1;
+                       }
+                       else
+                               Mat4One (mat);
+               }
+               break;
        default:
                Mat4One(mat);
                break;
@@ -594,6 +801,10 @@ void evaluate_constraint (bConstraint *constraint, Object *ob, short ownertype,
                {
                        bTrackToConstraint *data;
                        float   size[3];
+                       float *quat;
+                       float vec[3];
+                       float totmat[3][3];
+                       float tmat[4][4];
 
                        data=(bTrackToConstraint*)constraint->data;                     
                        
@@ -614,7 +825,16 @@ void evaluate_constraint (bConstraint *constraint, Object *ob, short ownertype,
                                ob->obmat[2][1]=0;
                                ob->obmat[2][2]=ob->size[2];
        
-                               solve_tracking(ob, targetmat);
+                       
+                               VecSubf(vec, ob->obmat[3], targetmat[3]);
+                               quat= vectoquat(vec, (short)data->reserved1, (short)data->reserved2);
+                               QuatToMat3(quat, totmat);
+
+                               Mat4CpyMat4(tmat, ob->obmat);
+                               
+                               Mat4MulMat34(ob->obmat, totmat, tmat);
+
+                       
                        }
                }
                break;
@@ -685,7 +905,343 @@ void evaluate_constraint (bConstraint *constraint, Object *ob, short ownertype,
                        }
                }
                break;
+       case CONSTRAINT_TYPE_LOCKTRACK:
+               {
+                       bLockTrackConstraint *data;
+                       float   size[3];
+                       float vec[3],vec2[3];
+                       float totmat[3][3];
+                       float tmpmat[3][3];
+                       float invmat[3][3];
+                       float tmat[4][4];
+                       float mdet;
+
+
+                       data=(bLockTrackConstraint*)constraint->data;                   
+                       
+
+                       if (data->tar){
+                                       
+                               Mat4ToSize (ob->obmat, size);
+       
+                               Mat4CpyMat4 (M_oldmat, ob->obmat);
+
+                               /* Vector object -> target */
+                               VecSubf(vec, targetmat[3], ob->obmat[3]);
+                               switch (data->lockflag){
+                               case LOCK_X: /* LOCK X */
+                                       {
+                                       switch (data->trackflag){
+                                       case TRACK_Y: /* LOCK X TRACK Y */
+                                               {
+                                               /* Projection of Vector on the plane */
+                                               Projf(vec2, vec, ob->obmat[0]);
+                                               VecSubf(totmat[1], vec, vec2);
+                                               Normalise(totmat[1]);
+
+                                               /* the x axis is fixed*/
+                                               totmat[0][0] = ob->obmat[0][0];
+                                               totmat[0][1] = ob->obmat[0][1];
+                                               totmat[0][2] = ob->obmat[0][2];
+                                               Normalise(totmat[0]);
+                               
+                                               /* the z axis gets mapped onto
+                                               a third orthogonal vector */
+                                               Crossf(totmat[2], totmat[0], totmat[1]);
+                                               }
+                                               break;
+                                       case TRACK_Z: /* LOCK X TRACK Z */
+                                               {
+                                               /* Projection of Vector on the plane */
+                                               Projf(vec2, vec, ob->obmat[0]);
+                                               VecSubf(totmat[2], vec, vec2);
+                                               Normalise(totmat[2]);
+
+                                               /* the x axis is fixed*/
+                                               totmat[0][0] = ob->obmat[0][0];
+                                               totmat[0][1] = ob->obmat[0][1];
+                                               totmat[0][2] = ob->obmat[0][2];
+                                               Normalise(totmat[0]);
+                               
+                                               /* the z axis gets mapped onto
+                                               a third orthogonal vector */
+                                               Crossf(totmat[1], totmat[2], totmat[0]);
+                                               }
+                                               break;
+                                       case TRACK_nY: /* LOCK X TRACK -Y */
+                                               {
+                                               /* Projection of Vector on the plane */
+                                               Projf(vec2, vec, ob->obmat[0]);
+                                               VecSubf(totmat[1], vec, vec2);
+                                               Normalise(totmat[1]);
+                                               VecMulf(totmat[1],-1);
+
+                                               /* the x axis is fixed*/
+                                               totmat[0][0] = ob->obmat[0][0];
+                                               totmat[0][1] = ob->obmat[0][1];
+                                               totmat[0][2] = ob->obmat[0][2];
+                                               Normalise(totmat[0]);
+                               
+                                               /* the z axis gets mapped onto
+                                               a third orthogonal vector */
+                                               Crossf(totmat[2], totmat[0], totmat[1]);
+                                               }
+                                               break;
+                                       case TRACK_nZ: /* LOCK X TRACK -Z */
+                                               {
+                                               /* Projection of Vector on the plane */
+                                               Projf(vec2, vec, ob->obmat[0]);
+                                               VecSubf(totmat[2], vec, vec2);
+                                               Normalise(totmat[2]);
+                                               VecMulf(totmat[2],-1);
+
+                                               /* the x axis is fixed*/
+                                               totmat[0][0] = ob->obmat[0][0];
+                                               totmat[0][1] = ob->obmat[0][1];
+                                               totmat[0][2] = ob->obmat[0][2];
+                                               Normalise(totmat[0]);
+                               
+                                               /* the z axis gets mapped onto
+                                               a third orthogonal vector */
+                                               Crossf(totmat[1], totmat[2], totmat[0]);
+                                               }
+                                               break;
+                                       default:
+                                               {
+                                                       totmat[0][0] = 1;totmat[0][1] = 0;totmat[0][2] = 0;
+                                                       totmat[1][0] = 0;totmat[1][1] = 1;totmat[1][2] = 0;
+                                                       totmat[2][0] = 0;totmat[2][1] = 0;totmat[2][2] = 1;
+                                               }
+                                               break;
+                                       }
+                                       }
+                                       break;
+                               case LOCK_Y: /* LOCK Y */
+                                       {
+                                       switch (data->trackflag){
+                                       case TRACK_X: /* LOCK Y TRACK X */
+                                               {
+                                               /* Projection of Vector on the plane */
+                                               Projf(vec2, vec, ob->obmat[1]);
+                                               VecSubf(totmat[0], vec, vec2);
+                                               Normalise(totmat[0]);
+
+                                               /* the y axis is fixed*/
+                                               totmat[1][0] = ob->obmat[1][0];
+                                               totmat[1][1] = ob->obmat[1][1];
+                                               totmat[1][2] = ob->obmat[1][2];
+                                               Normalise(totmat[1]);
+                                               
+                                               /* the z axis gets mapped onto
+                                               a third orthogonal vector */
+                                               Crossf(totmat[2], totmat[0], totmat[1]);
+                                               }
+                                               break;
+                                       case TRACK_Y: /* LOCK Y TRACK Z */
+                                               {
+                                               /* Projection of Vector on the plane */
+                                               Projf(vec2, vec, ob->obmat[1]);
+                                               VecSubf(totmat[2], vec, vec2);
+                                               Normalise(totmat[2]);
+
+                                               /* the y axis is fixed*/
+                                               totmat[1][0] = ob->obmat[1][0];
+                                               totmat[1][1] = ob->obmat[1][1];
+                                               totmat[1][2] = ob->obmat[1][2];
+                                               Normalise(totmat[1]);
+                                               
+                                               /* the z axis gets mapped onto
+                                               a third orthogonal vector */
+                                               Crossf(totmat[0], totmat[1], totmat[2]);
+                                               }
+                                               break;
+                                       case TRACK_nX: /* LOCK Y TRACK -X */
+                                               {
+                                               /* Projection of Vector on the plane */
+                                               Projf(vec2, vec, ob->obmat[1]);
+                                               VecSubf(totmat[0], vec, vec2);
+                                               Normalise(totmat[0]);
+                                               VecMulf(totmat[0],-1);
+
+                                               /* the y axis is fixed*/
+                                               totmat[1][0] = ob->obmat[1][0];
+                                               totmat[1][1] = ob->obmat[1][1];
+                                               totmat[1][2] = ob->obmat[1][2];
+                                               Normalise(totmat[1]);
+                                               
+                                               /* the z axis gets mapped onto
+                                               a third orthogonal vector */
+                                               Crossf(totmat[2], totmat[0], totmat[1]);
+                                               }
+                                               break;
+                                       case TRACK_nZ: /* LOCK Y TRACK -Z */
+                                               {
+                                               /* Projection of Vector on the plane */
+                                               Projf(vec2, vec, ob->obmat[1]);
+                                               VecSubf(totmat[2], vec, vec2);
+                                               Normalise(totmat[2]);
+                                               VecMulf(totmat[2],-1);
+
+                                               /* the y axis is fixed*/
+                                               totmat[1][0] = ob->obmat[1][0];
+                                               totmat[1][1] = ob->obmat[1][1];
+                                               totmat[1][2] = ob->obmat[1][2];
+                                               Normalise(totmat[1]);
+                                               
+                                               /* the z axis gets mapped onto
+                                               a third orthogonal vector */
+                                               Crossf(totmat[0], totmat[1], totmat[2]);
+                                               }
+                                               break;
+                                       default:
+                                               {
+                                                       totmat[0][0] = 1;totmat[0][1] = 0;totmat[0][2] = 0;
+                                                       totmat[1][0] = 0;totmat[1][1] = 1;totmat[1][2] = 0;
+                                                       totmat[2][0] = 0;totmat[2][1] = 0;totmat[2][2] = 1;
+                                               }
+                                               break;
+                                       }
+                                       }
+                                       break;
+                               case LOCK_Z: /* LOCK Z */
+                                       {
+                                       switch (data->trackflag){
+                                       case TRACK_X: /* LOCK Z TRACK X */
+                                               {
+                                               /* Projection of Vector on the plane */
+                                               Projf(vec2, vec, ob->obmat[2]);
+                                               VecSubf(totmat[0], vec, vec2);
+                                               Normalise(totmat[0]);
+
+                                               /* the z axis is fixed*/
+                                               totmat[2][0] = ob->obmat[2][0];
+                                               totmat[2][1] = ob->obmat[2][1];
+                                               totmat[2][2] = ob->obmat[2][2];
+                                               Normalise(totmat[2]);
+                                               
+                                               /* the x axis gets mapped onto
+                                               a third orthogonal vector */
+                                               Crossf(totmat[1], totmat[2], totmat[0]);
+                                               }
+                                               break;
+                                       case TRACK_Y: /* LOCK Z TRACK Y */
+                                               {
+                                               /* Projection of Vector on the plane */
+                                               Projf(vec2, vec, ob->obmat[2]);
+                                               VecSubf(totmat[1], vec, vec2);
+                                               Normalise(totmat[1]);
+
+                                               /* the z axis is fixed*/
+                                               totmat[2][0] = ob->obmat[2][0];
+                                               totmat[2][1] = ob->obmat[2][1];
+                                               totmat[2][2] = ob->obmat[2][2];
+                                               Normalise(totmat[2]);
+                                               
+                                               /* the x axis gets mapped onto
+                                               a third orthogonal vector */
+                                               Crossf(totmat[0], totmat[1], totmat[2]);
+                                               }
+                                               break;
+                                       case TRACK_nX: /* LOCK Z TRACK -X */
+                                               {
+                                               /* Projection of Vector on the plane */
+                                               Projf(vec2, vec, ob->obmat[2]);
+                                               VecSubf(totmat[0], vec, vec2);
+                                               Normalise(totmat[0]);
+                                               VecMulf(totmat[0],-1);
+
+                                               /* the z axis is fixed*/
+                                               totmat[2][0] = ob->obmat[2][0];
+                                               totmat[2][1] = ob->obmat[2][1];
+                                               totmat[2][2] = ob->obmat[2][2];
+                                               Normalise(totmat[2]);
+                                               
+                                               /* the x axis gets mapped onto
+                                               a third orthogonal vector */
+                                               Crossf(totmat[1], totmat[2], totmat[0]);
+                                               }
+                                               break;
+                                       case TRACK_nY: /* LOCK Z TRACK -Y */
+                                               {
+                                               /* Projection of Vector on the plane */
+                                               Projf(vec2, vec, ob->obmat[2]);
+                                               VecSubf(totmat[1], vec, vec2);
+                                               Normalise(totmat[1]);
+                                               VecMulf(totmat[1],-1);
+
+                                               /* the z axis is fixed*/
+                                               totmat[2][0] = ob->obmat[2][0];
+                                               totmat[2][1] = ob->obmat[2][1];
+                                               totmat[2][2] = ob->obmat[2][2];
+                                               Normalise(totmat[2]);
+                                               
+                                               /* the x axis gets mapped onto
+                                               a third orthogonal vector */
+                                               Crossf(totmat[0], totmat[1], totmat[2]);
+                                               }
+                                               break;
+                                       default:
+                                               {
+                                                       totmat[0][0] = 1;totmat[0][1] = 0;totmat[0][2] = 0;
+                                                       totmat[1][0] = 0;totmat[1][1] = 1;totmat[1][2] = 0;
+                                                       totmat[2][0] = 0;totmat[2][1] = 0;totmat[2][2] = 1;
+                                               }
+                                               break;
+                                       }
+                                       }
+                                       break;
+                               default:
+                                       {
+                                               totmat[0][0] = 1;totmat[0][1] = 0;totmat[0][2] = 0;
+                                               totmat[1][0] = 0;totmat[1][1] = 1;totmat[1][2] = 0;
+                                               totmat[2][0] = 0;totmat[2][1] = 0;totmat[2][2] = 1;
+                                       }
+                                       break;
+                               }
+                               /* Block to keep matrix heading */
+                               tmpmat[0][0] = ob->obmat[0][0];tmpmat[0][1] = ob->obmat[0][1];tmpmat[0][2] = ob->obmat[0][2];
+                               tmpmat[1][0] = ob->obmat[1][0];tmpmat[1][1] = ob->obmat[1][1];tmpmat[1][2] = ob->obmat[1][2];
+                               tmpmat[2][0] = ob->obmat[2][0];tmpmat[2][1] = ob->obmat[2][1];tmpmat[2][2] = ob->obmat[2][2];
+                               Normalise(tmpmat[0]);
+                               Normalise(tmpmat[1]);
+                               Normalise(tmpmat[2]);
+                               Mat3Inv(invmat,tmpmat);
+                               Mat3MulMat3(tmpmat,totmat,invmat);
+                               totmat[0][0] = tmpmat[0][0];totmat[0][1] = tmpmat[0][1];totmat[0][2] = tmpmat[0][2];
+                               totmat[1][0] = tmpmat[1][0];totmat[1][1] = tmpmat[1][1];totmat[1][2] = tmpmat[1][2];
+                               totmat[2][0] = tmpmat[2][0];totmat[2][1] = tmpmat[2][1];totmat[2][2] = tmpmat[2][2];
+
+                               Mat4CpyMat4(tmat, ob->obmat);
+
+                               mdet = Det3x3(  totmat[0][0],totmat[0][1],totmat[0][2],
+                                                               totmat[1][0],totmat[1][1],totmat[1][2],
+                                                               totmat[2][0],totmat[2][1],totmat[2][2]);
+                               if (mdet==0)
+                               {
+                                       totmat[0][0] = 1;totmat[0][1] = 0;totmat[0][2] = 0;
+                                       totmat[1][0] = 0;totmat[1][1] = 1;totmat[1][2] = 0;
+                                       totmat[2][0] = 0;totmat[2][1] = 0;totmat[2][2] = 1;
+                               }
+
+                               /* apply out transformaton to the object */
+                               Mat4MulMat34(ob->obmat, totmat, tmat);
+                       }
+               }
+               break;
        case CONSTRAINT_TYPE_FOLLOWPATH:
+               {
+                       bFollowPathConstraint *data;
+                       float obmat[4][4];
+
+                       data=(bFollowPathConstraint*)constraint->data;                  
+
+                       if (data->tar) {
+
+                               object_to_mat4(ob, obmat);
+
+                               Mat4MulSerie(ob->obmat, targetmat, obmat, NULL, NULL, NULL, NULL, NULL, NULL);
+                       }
+               }
                break;
        default:
                printf ("Error: Unknown constraint type\n");
index 497ff98b53aa1e6c6d3ac1943957e74e670751b4..eeb64d789ca5dcc0a176375da62cf847265cd948 100644 (file)
@@ -116,6 +116,11 @@ Crossf(
        float *c, float *a, float *b
 );
 
+       void 
+Projf(
+       float *c, const float *v1, const float *v2
+);
+
 /**
  * Euler conversion routines
  */
index fa13f8223a8e6f4b8a15b5f119e4f19c373e581c..715917d047fdfb3d17c9eb6427ddcf4f44ec7258 100644 (file)
@@ -119,6 +119,17 @@ float Inpf( float *v1, float *v2)
        return v1[0]*v2[0]+v1[1]*v2[1]+v1[2]*v2[2];
 }
 
+/* Project v1 on v2 */
+void Projf(float *c, const float *v1, const float *v2)
+{
+       float mul;
+       mul = Inpf(v1, v2) / Inpf(v2, v2);
+       
+       c[0] = mul * v2[0];
+       c[1] = mul * v2[1];
+       c[2] = mul * v2[2];
+}
+
 void Mat3Transp(float mat[][3])
 {
        float t;
index 358c99df3de5c2824d287becf4e7ce758c435a54..a7acb42fdef277fdb95df9cf7412d043bc44b319 100644 (file)
@@ -1227,8 +1227,6 @@ static void lib_link_constraints(FileData *fd, ID *id, ListBase *conlist)
                                data->tar = newlibadr(fd, id->lib, data->tar);
                        }
                        break;
-               case CONSTRAINT_TYPE_NULL:
-                       break;
                case CONSTRAINT_TYPE_TRACKTO:
                        {
                                bTrackToConstraint *data;
@@ -1236,7 +1234,22 @@ static void lib_link_constraints(FileData *fd, ID *id, ListBase *conlist)
                                data->tar = newlibadr(fd, id->lib, data->tar);
                        }
                        break;
-
+               case CONSTRAINT_TYPE_LOCKTRACK:
+                       {
+                               bLockTrackConstraint *data;
+                               data= ((bLockTrackConstraint*)con->data);
+                               data->tar = newlibadr(fd, id->lib, data->tar);
+                       };
+                       break;
+               case CONSTRAINT_TYPE_FOLLOWPATH:
+                       {
+                               bFollowPathConstraint *data;
+                               data= ((bFollowPathConstraint*)con->data);
+                               data->tar = newlibadr(fd, id->lib, data->tar);
+                       };
+                       break;
+               case CONSTRAINT_TYPE_NULL:
+                       break;
                }
        }
 }
@@ -3746,6 +3759,80 @@ static void do_versions(Main *main)
        if(main->versionfile <= 228) {
                Scene *sce;
                bScreen *sc;
+               Object *ob;
+
+
+               /*  As of now, this insures that the transition from the old Track system
+                   to the new full constraint Track is painless for everyone.*/
+               ob = main->object.first;
+       
+               while (ob) {
+                       ListBase *list;
+                       list = &ob->constraints;
+                       
+                       /* check for already existing TrackTo constraint
+                          set their track and up flag correctly */
+
+                       if (list){
+                               bConstraint *curcon;
+                               for (curcon = list->first; curcon; curcon=curcon->next){
+                                       if (curcon->type == CONSTRAINT_TYPE_TRACKTO){
+                                               bTrackToConstraint *data = curcon->data;
+                                               data->reserved1 = ob->trackflag;
+                                               data->reserved2 = ob->upflag;
+                                       }
+                               }
+                       }
+
+                       if (ob->type == OB_ARMATURE) {
+                               if (ob->pose){
+                                       bConstraint *curcon;
+                                       bPoseChannel *pchan;
+                                       for (pchan = ob->pose->chanbase.first; 
+                                                pchan; pchan=pchan->next){
+                                               for (curcon = pchan->constraints.first; 
+                                                        curcon; curcon=curcon->next){
+                                                       if (curcon->type == CONSTRAINT_TYPE_TRACKTO){
+                                                               bTrackToConstraint *data = curcon->data;
+                                                               data->reserved1 = ob->trackflag;
+                                                               data->reserved2 = ob->upflag;
+                                                       }
+                                               }
+                                       }
+                }
+                       }
+
+                       /* Change Ob->Track in real TrackTo constraint
+
+                       NOT SURE IF PEOPLE WANT THIS SO I DISABLED IT
+                       
+                       if (ob->track){
+                               bConstraint *con;
+                               bTrackToConstraint *data;
+
+                               list = &ob->constraints;
+                               if (list)
+                               {
+                                       con = MEM_callocN(sizeof(bConstraint), "constraint");
+                                       strcpy (con->name, "AutoTrack");
+                                       unique_constraint_name(con, list);
+                                       con->flag |= CONSTRAINT_EXPAND;
+                                       con->enforce=1.0F;
+                                       con->type = CONSTRAINT_TYPE_TRACKTO;
+                                       data = (bTrackToConstraint *) 
+                                               new_constraint_data(CONSTRAINT_TYPE_TRACKTO);
+
+                                       data->tar = ob->track;
+                                       data->reserved1 = ob->trackflag;
+                                       data->reserved2 = ob->upflag;
+                                       con->data= (void*) data;
+                                       BLI_addtail(list, con);
+                               }
+                               ob->track = 0;
+                       }*/
+
+                       ob = ob->id.next;
+               }
 
                for (sce= main->scene.first; sce; sce= sce->id.next) {
                        sce->r.mode |= R_ENVMAP;
@@ -4189,6 +4276,18 @@ static void expand_constraints(FileData *fd, Main *mainvar, ListBase *lb)
                                expand_doit(fd, mainvar, data->tar);
                                break;
                        }
+               case CONSTRAINT_TYPE_LOCKTRACK:
+                       {
+                               bLockTrackConstraint *data = (bLockTrackConstraint*)curcon->data;
+                               expand_doit(fd, mainvar, data->tar);
+                               break;
+                       }
+               case CONSTRAINT_TYPE_FOLLOWPATH:
+                       {
+                               bFollowPathConstraint *data = (bFollowPathConstraint*)curcon->data;
+                               expand_doit(fd, mainvar, data->tar);
+                               break;
+                       }
                case CONSTRAINT_TYPE_NULL:
                        break;
                default:
index 546ff3b60e6603dc7cd9689028c5b6f5c2965092..4d11e6d7041fe2ba2ca29e8341ce3c2c034f96e7 100644 (file)
@@ -691,6 +691,12 @@ static void write_constraints(WriteData *wd, ListBase *conlist)
                case CONSTRAINT_TYPE_ACTION:
                        writestruct(wd, DATA, "bActionConstraint", 1, con->data);
                        break;
+               case CONSTRAINT_TYPE_LOCKTRACK:
+                       writestruct(wd, DATA, "bLockTrackConstraint", 1, con->data);
+                       break;
+               case CONSTRAINT_TYPE_FOLLOWPATH:
+                       writestruct(wd, DATA, "bFollowPathConstraint", 1, con->data);
+                       break;
                default:
                        break;
                }
index 5d6d38fd5292a4fa7f0f14a2d01d18736a753f7c..f28b07797f0df57ebb305aa8889a8990b3fa6ed2 100644 (file)
@@ -48,13 +48,14 @@ typedef struct ConstraintElement{
 } ConstraintElement;
 
 struct bConstraintChannel *add_new_constraint_channel(const char *name);
-struct bConstraint * add_new_constraint(void);
+struct bConstraint * add_new_constraint(int type);
+void add_influence_key_to_constraint (struct bConstraint *con);
+void add_constraint_to_object(struct bConstraint *con, struct Object *ob);
+void add_constraint_to_client(struct bConstraint *con);
 struct ListBase *get_constraint_client_channels (int forcevalid);
 struct ListBase *get_constraint_client(char *name, short *clienttype, void** clientdata);
 int test_constraints (struct Object *owner, const char *substring, int disable);
 void test_scene_constraints (void);
-void unique_constraint_name (struct bConstraint *con, struct ListBase *list);
-void *new_constraint_data (short type);
 
 /*  void unique_constraint_name (struct bConstraint *con, struct ListBase *list); */
 
index 7d708b3627905db2e7b7b29312f17dfb6e6b4179..4b41667bc4378cd02745999d3b14527b6a304de6 100644 (file)
@@ -485,12 +485,19 @@ enum B_SOUND_BUTTONS {
 #define B_CONSTRAINTBUTS       3300
 enum {
        B_CONSTRAINT_REDRAW = 3201,
-       B_CONSTRAINT_ADD,
        B_CONSTRAINT_DEL,
        B_CONSTRAINT_TEST,
        B_CONSTRAINT_CHANGETYPE,
        B_CONSTRAINT_CHANGENAME,
-       B_CONSTRAINT_CHANGETARGET
+       B_CONSTRAINT_CHANGETARGET,
+       B_CONSTRAINT_ADD_NULL,
+       B_CONSTRAINT_ADD_KINEMATIC,
+       B_CONSTRAINT_ADD_TRACKTO,
+       B_CONSTRAINT_ADD_ROTLIKE,
+       B_CONSTRAINT_ADD_LOCLIKE,
+       B_CONSTRAINT_ADD_ACTION,
+       B_CONSTRAINT_ADD_LOCKTRACK,
+       B_CONSTRAINT_ADD_FOLLOWPATH
 };
 /* *********************** */
 
index 02199b9aa0115d01307a5f715e5d2ba99bf25c46..7cd0272a8cbc0520cbef37d2eb7ea572c3047dcc 100644 (file)
@@ -109,9 +109,21 @@ typedef struct bActionConstraint{
        char            subtarget[32];
 } bActionConstraint;
 
-/* Single-target object constraints */
+/* Locked Axis Tracking constraint */
+typedef struct bLockTrackConstraint{
+       Object          *tar;
+       int                     trackflag;
+       int                     lockflag;
+       char            subtarget[32];
+} bLockTrackConstraint;
+
+/* Follow Path constraints */
 typedef struct bFollowPathConstraint{
        Object          *tar;   /* Must be path object */
+       float           offset; /* Offset in time on the path (in frame) */
+       int                     followflag;
+       int                     trackflag;
+       int                     upflag;
 } bFollowPathConstraint;
 
 /* Zero-target constraints */
@@ -126,7 +138,7 @@ typedef struct bRotationConstraint{
 #define CONSTRAINT_TYPE_CHILDOF                1       /* Unimplemented */
 #define CONSTRAINT_TYPE_TRACKTO                2       
 #define CONSTRAINT_TYPE_KINEMATIC      3       
-#define CONSTRAINT_TYPE_FOLLOWPATH     4       /* Unimplemented */
+#define CONSTRAINT_TYPE_FOLLOWPATH     4
 #define CONSTRAINT_TYPE_ROTLIMIT       5       /* Unimplemented */
 #define CONSTRAINT_TYPE_LOCLIMIT       6       /* Unimplemented */
 #define CONSTRAINT_TYPE_SIZELIMIT      7       /* Unimplemented */
@@ -135,6 +147,7 @@ typedef struct bRotationConstraint{
 #define CONSTRAINT_TYPE_SIZELIKE       10      /* Unimplemented */
 #define CONSTRAINT_TYPE_PYTHON         11      /* Unimplemented */
 #define CONSTRAINT_TYPE_ACTION         12
+#define CONSTRAINT_TYPE_LOCKTRACK      13      /* New Tracking constraint that locks an axis in place - theeth */
 
 /* bConstraint.flag */
 #define CONSTRAINT_EXPAND              0x00000001
@@ -154,5 +167,21 @@ typedef struct bRotationConstraint{
 #define LOCLIKE_Y              0x00000002
 #define LOCLIKE_Z              0x00000004
 
+/* Tracking flags */
+#define LOCK_X         0x00000000
+#define LOCK_Y         0x00000001
+#define LOCK_Z         0x00000002
+
+#define UP_X           0x00000000
+#define UP_Y           0x00000001
+#define UP_Z           0x00000002
+
+#define TRACK_X                0x00000000
+#define TRACK_Y                0x00000001
+#define TRACK_Z                0x00000002
+#define TRACK_nX       0x00000003
+#define TRACK_nY       0x00000004
+#define TRACK_nZ       0x00000005
+
 #endif
 
index 637220c27e6609561cb6500adeee9850d791572d..b88995ec8de01e61fb24e1eafa9f02c5be1be756 100644 (file)
@@ -278,6 +278,12 @@ static void get_constraint_typestring (char *str, bConstraint *con)
        case CONSTRAINT_TYPE_ACTION:
                strcpy (str, "Action");
                return;
+       case CONSTRAINT_TYPE_LOCKTRACK:
+               strcpy (str, "Locked Track");
+               return;
+       case CONSTRAINT_TYPE_FOLLOWPATH:
+               strcpy (str, "Follow Path");
+               return;
        default:
                strcpy (str, "Unknown");
                return;
@@ -299,6 +305,10 @@ static int get_constraint_col(bConstraint *con)
                return TH_BUT_POPUP;
        case CONSTRAINT_TYPE_ACTION:
                return TH_BUT_ACTION;
+       case CONSTRAINT_TYPE_LOCKTRACK:
+               return TH_BUT_SETTING;
+       case CONSTRAINT_TYPE_FOLLOWPATH:
+               return TH_BUT_SETTING2;
        default:
                return TH_REDALERT;
        }
@@ -326,14 +336,22 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
 
        if (con->flag & CONSTRAINT_EXPAND) {
                
-               if (con->flag & CONSTRAINT_DISABLE)
+               if (con->flag & CONSTRAINT_DISABLE) {
+                       BIF_ThemeColor(TH_REDALERT);
                        uiBlockSetCol(block, TH_REDALERT);
-               
-               if (type==TARGET_BONE)
+               }
+               else
+                       BIF_ThemeColor(curCol);
+
+               /*if (type==TARGET_BONE)
                        but = uiDefButC(block, MENU, B_CONSTRAINT_TEST, "Bone Constraint%t|Track To%x2|IK Solver%x3|Copy Rotation%x8|Copy Location%x9|Action%x12|Null%x0", *xco+20, *yco, 100, 20, &con->type, 0.0, 0.0, 0.0, 0.0, "Constraint type"); 
                else
                        but = uiDefButC(block, MENU, B_CONSTRAINT_TEST, "Object Constraint%t|Track To%x2|Copy Rotation%x8|Copy Location%x9|Null%x0", *xco+20, *yco, 100, 20, &con->type, 0.0, 0.0, 0.0, 0.0, "Constraint type"); 
+               */
                
+               glRects(*xco+34, *yco-12, *xco+138, *yco+5);
+               but = uiDefBut(block, LABEL, B_CONSTRAINT_TEST, typestr, *xco+20, *yco, 100, 20, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
+
                uiButSetFunc(but, constraint_changed_func, con, NULL);
                con->otype = con->type;
                
@@ -364,168 +382,276 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
        uiDefIconButS(block, ICONTOG|BIT|CONSTRAINT_EXPAND_BIT, B_CONSTRAINT_REDRAW, ICON_RIGHTARROW, *xco+248, *yco, 20, 20, &con->flag, 0.0, 0.0, 0.0, 0.0, "Collapse");
 
 
-       if (!(con->flag & CONSTRAINT_EXPAND)) {
-               (*yco)-=21;
-               return;
-       }
 
-       if (con->type!=CONSTRAINT_TYPE_NULL) {
-               uiDefBut(block, NUMSLI|FLO, B_CONSTRAINT_REDRAW, "Influence:", *xco, *yco-20, 196, 20, &con->enforce, 0.0, 1.0, 0.0, 0.0, "Amount of influence this constraint will have on the final solution");
-               but = uiDefBut(block, BUT, B_CONSTRAINT_REDRAW, "Edit Ipo", *xco+200, *yco-20, 64, 20, 0, 0.0, 1.0, 0.0, 0.0, "Show this constraint's ipo in the object's Ipo window");
-               /* If this is on an object, add the constraint to the object */
-               uiButSetFunc (but, activate_constraint_ipo_func, con, NULL);
-               /* If this is on a bone, add the constraint to the action (if any) */
+       /* Draw constraint data*/
+       if (!(con->flag & CONSTRAINT_EXPAND)) {
                (*yco)-=21;
        }
+       else {
+               switch (con->type){
+               case CONSTRAINT_TYPE_ACTION:
+                       {
+                               bActionConstraint *data = con->data;
+                               bArmature *arm;
+
+                               height = 86;
+                               BIF_ThemeColor(curCol);
+                               glRects(*xco+40, *yco-height-16, *xco+width+50, *yco-14);
+                               uiEmboss((float)*xco+40, (float)*yco-height-16, (float)*xco+width+50, (float)*yco-14, 1);
+
+                               /* Draw target parameters */
+                               uiDefIDPoinBut(block, test_obpoin_but, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+((width/2)-48), *yco-20, 96, 18, &data->tar, "Target Object"); 
+
+                               arm = get_armature(data->tar);
+                               if (arm){
+                                       but=uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "BO:", *xco+((width/2)-48), *yco-40,96,18, &data->subtarget, 0, 24, 0, 0, "Bone");
+                               }
+                               else
+                                       strcpy (data->subtarget, "");
 
-       /* Draw constraint data*/
-
-       switch (con->type){
-       case CONSTRAINT_TYPE_ACTION:
-               {
-                       bActionConstraint *data = con->data;
-                       bArmature *arm;
-
-                       height = 86;
-                       BIF_ThemeColor(curCol);
-                       glRects(*xco+34, *yco-height-16, *xco+width+24, *yco-14);
-                       uiEmboss((float)*xco+34, (float)*yco-height-16, (float)*xco+width+24, (float)*yco-14, 1);
-
-                       /* Draw target parameters */
-                       uiDefIDPoinBut(block, test_obpoin_but, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+((width/2)-48), *yco-20, 96, 18, &data->tar, "Target Object"); 
+                               /* Draw action button */
+                               uiDefIDPoinBut(block, test_actionpoin_but, B_CONSTRAINT_CHANGETARGET, "AC:", *xco+((width/2)-90), *yco-60, 75, 18, &data->act, "Action containing the keyed motion for this bone"); 
+                               uiDefButI(block, MENU, B_CONSTRAINT_REDRAW, "Key on%t|X Rot%x0|Y Rot%x1|Z Rot%x2", *xco+((width/2)-90), *yco-80, 75, 18, &data->type, 0, 24, 0, 0, "Specify which transformation channel from the target is used to key the action");
 
-                       arm = get_armature(data->tar);
-                       if (arm){
-                               but=uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "BO:", *xco+((width/2)-48), *yco-40,96,18, &data->subtarget, 0, 24, 0, 0, "Bone");
+                               uiDefButS(block, NUM, B_CONSTRAINT_CHANGETARGET, "Start:", *xco+((width/2)-15), *yco-60, 70, 18, &data->start, 1, 18000, 0.0, 0.0, "Starting frame of the keyed motion"); 
+                               uiDefButS(block, NUM, B_CONSTRAINT_CHANGETARGET, "End:", *xco+((width/2)-15), *yco-80, 70, 18, &data->end, 1, 18000, 0.0, 0.0, "Ending frame of the keyed motion"); 
+                               
+                               uiDefButF(block, NUM, B_CONSTRAINT_REDRAW, "Min:", *xco+((width/2)+55), *yco-60, 80, 18, &data->min, -180, 180, 0, 0, "Minimum value for target channel range");
+                               uiDefButF(block, NUM, B_CONSTRAINT_REDRAW, "Max:", *xco+((width/2)+55), *yco-80, 80, 18, &data->max, -180, 180, 0, 0, "Maximum value for target channel range");
+                               
                        }
-                       else
-                               strcpy (data->subtarget, "");
-
-                       /* Draw action button */
-                       uiDefIDPoinBut(block, test_actionpoin_but, B_CONSTRAINT_CHANGETARGET, "AC:", *xco+((width/2)-120), *yco-60, 80, 18, &data->act, "Action containing the keyed motion for this bone"); 
-
-                       uiDefButS(block, NUM, B_CONSTRAINT_CHANGETARGET, "Start:", *xco+((width/2)-40), *yco-60, 80, 18, &data->start, 1, 18000, 0.0, 0.0, "Starting frame of the keyed motion"); 
-                       uiDefButS(block, NUM, B_CONSTRAINT_CHANGETARGET, "End:", *xco+((width/2)+40), *yco-60, 80, 18, &data->end, 1, 18000, 0.0, 0.0, "Ending frame of the keyed motion"); 
-                       
-                       /* Draw XYZ toggles */
-                       uiDefButI(block, MENU, B_CONSTRAINT_REDRAW, "Key on%t|X Rot%x0|Y Rot%x1|Z Rot%x2", *xco+((width/2)-120), *yco-80, 80, 18, &data->type, 0, 24, 0, 0, "Specify which transformation channel from the target is used to key the action");
-                       uiDefButF(block, NUM, B_CONSTRAINT_REDRAW, "Min:", *xco+((width/2)-40), *yco-80, 80, 18, &data->min, -180, 180, 0, 0, "Minimum value for target channel range");
-                       uiDefButF(block, NUM, B_CONSTRAINT_REDRAW, "Max:", *xco+((width/2)+40), *yco-80, 80, 18, &data->max, -180, 180, 0, 0, "Maximum value for target channel range");
-                       
-               }
-               break;
-       case CONSTRAINT_TYPE_LOCLIKE:
-               {
-                       bLocateLikeConstraint *data = con->data;
-                       bArmature *arm;
-                       height = 66;
-                       BIF_ThemeColor(curCol);
-                       glRects(*xco+34, *yco-height-16, *xco+width+24, *yco-14);
-                       uiEmboss((float)*xco+34, (float)*yco-height-16, (float)*xco+width+24, (float)*yco-14, 1);
+                       break;
+               case CONSTRAINT_TYPE_LOCLIKE:
+                       {
+                               bLocateLikeConstraint *data = con->data;
+                               bArmature *arm;
+                               height = 66;
+                               BIF_ThemeColor(curCol);
+                               glRects(*xco+40, *yco-height-16, *xco+width+50, *yco-14);
+                               uiEmboss((float)*xco+40, (float)*yco-height-16, (float)*xco+width+50, (float)*yco-14, 1);
+
+                               /* Draw target parameters */
+                               uiDefIDPoinBut(block, test_obpoin_but, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+((width/2)-48), *yco-20, 96, 18, &data->tar, "Target Object"); 
+
+                               arm = get_armature(data->tar);
+                               if (arm){
+                                       but=uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "BO:", *xco+((width/2)-48), *yco-40,96,18, &data->subtarget, 0, 24, 0, 0, "Bone");
+                               }
+                               else
+                                       strcpy (data->subtarget, "");
 
-                       /* Draw target parameters */
-                       uiDefIDPoinBut(block, test_obpoin_but, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+((width/2)-48), *yco-20, 96, 18, &data->tar, "Target Object"); 
+                               /* Draw XYZ toggles */
+                                       but=uiDefButI(block, TOG|BIT|0, B_CONSTRAINT_TEST, "X", *xco+((width/2)-48), *yco-60, 32, 18, &data->flag, 0, 24, 0, 0, "Copy X component");
+                                       but=uiDefButI(block, TOG|BIT|1, B_CONSTRAINT_TEST, "Y", *xco+((width/2)-16), *yco-60, 32, 18, &data->flag, 0, 24, 0, 0, "Copy Y component");
+                                       but=uiDefButI(block, TOG|BIT|2, B_CONSTRAINT_TEST, "Z", *xco+((width/2)+16), *yco-60, 32, 18, &data->flag, 0, 24, 0, 0, "Copy Z component");
+                       }
+                       break;
+               case CONSTRAINT_TYPE_ROTLIKE:
+                       {
+                               bRotateLikeConstraint *data = con->data;
+                               bArmature *arm;
+                               height = 46;
+                               BIF_ThemeColor(curCol);
+                               glRects(*xco+40, *yco-height-16, *xco+width+50, *yco-14);
+                               uiEmboss((float)*xco+40, (float)*yco-height-16, (float)*xco+width+50, (float)*yco-14, 1);
+
+                               uiDefIDPoinBut(block, test_obpoin_but, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+((width/2)-48), *yco-20, 96, 18, &data->tar, "Target Object"); 
+
+                               arm = get_armature(data->tar);
+                               if (arm){
+                                       but=uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "BO:", *xco+((width/2)-48), *yco-40,96,18, &data->subtarget, 0, 24, 0, 0, "Bone");
+                               }
+                               else
+                                       strcpy (data->subtarget, "");
 
-                       arm = get_armature(data->tar);
-                       if (arm){
-                               but=uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "BO:", *xco+((width/2)-48), *yco-40,96,18, &data->subtarget, 0, 24, 0, 0, "Bone");
                        }
-                       else
-                               strcpy (data->subtarget, "");
+                       break;
+               case CONSTRAINT_TYPE_KINEMATIC:
+                       {
+                               bKinematicConstraint *data = con->data;
+                               bArmature *arm;
+                               
+                               height = 66;
+                               BIF_ThemeColor(curCol);
+                               glRects(*xco+40, *yco-height-16, *xco+width+50, *yco-14);
+                               uiEmboss((float)*xco+40, (float)*yco-height-16, (float)*xco+width+50, (float)*yco-14, 1);
+                               
+                               uiDefButF(block, NUM, B_CONSTRAINT_REDRAW, "Tolerance:", *xco+((width/2)-96), *yco-20, 96, 18, &data->tolerance, 0.0001, 1.0, 0.0, 0.0, "Maximum distance to target after solving"); 
+                               uiDefButI(block, NUM, B_CONSTRAINT_REDRAW, "Iterations:", *xco+((width/2)), *yco-20, 96, 18, &data->iterations, 1, 10000, 0.0, 0.0, "Maximum number of solving iterations"); 
 
-                       /* Draw XYZ toggles */
-                               but=uiDefButI(block, TOG|BIT|0, B_CONSTRAINT_TEST, "X", *xco+((width/2)-48), *yco-60, 32, 18, &data->flag, 0, 24, 0, 0, "Copy X component");
-                               but=uiDefButI(block, TOG|BIT|1, B_CONSTRAINT_TEST, "Y", *xco+((width/2)-16), *yco-60, 32, 18, &data->flag, 0, 24, 0, 0, "Copy Y component");
-                               but=uiDefButI(block, TOG|BIT|2, B_CONSTRAINT_TEST, "Z", *xco+((width/2)+16), *yco-60, 32, 18, &data->flag, 0, 24, 0, 0, "Copy Z component");
+                               uiDefIDPoinBut(block, test_obpoin_but, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+((width/2)-48), *yco-40, 96, 18, &data->tar, "Target Object"); 
+                               
+                               arm = get_armature(data->tar);
+                               if (arm){
+                                       but=uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "BO:", *xco+((width/2)-48), *yco-60,96,18, &data->subtarget, 0, 24, 0, 0, "Bone");
+                               }
+                               else
+                                       strcpy (data->subtarget, "");
+                               
+                       }
+                       break;
+               case CONSTRAINT_TYPE_TRACKTO:
+                       {
+                               bTrackToConstraint *data = con->data;
+                               bArmature *arm;
+
+                               height = 66;
+                               BIF_ThemeColor(curCol);
+                               glRects(*xco+40, *yco-height-16, *xco+width+50, *yco-14);
+                               uiEmboss((float)*xco+40, (float)*yco-height-16, (float)*xco+width+50, (float)*yco-14, 1);
+                               
+                               uiDefIDPoinBut(block, test_obpoin_but, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+((width/2)-48), *yco-20, 96, 18, &data->tar, "Target Object"); 
+                               
+                               arm = get_armature(data->tar);
+                               if (arm){
+                                       but=uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "BO:", *xco+((width/2)-48), *yco-40,96,18, &data->subtarget, 0, 24, 0, 0, "Bone");
+                               }
+                               else
+                                       strcpy (data->subtarget, "");
+
+                               uiDefButC(block, ROW,B_CONSTRAINT_REDRAW,"X",   *xco+((width/2)-84), *yco-60,19,18, &data->reserved1, 12.0, 0.0, 0, 0, "Specify the axis that points to another object");
+                               uiDefButC(block, ROW,B_CONSTRAINT_REDRAW,"Y",   *xco+((width/2)-65), *yco-60,19,18, &data->reserved1, 12.0, 1.0, 0, 0, "Specify the axis that points to another object");
+                               uiDefButC(block, ROW,B_CONSTRAINT_REDRAW,"Z",   *xco+((width/2)-46), *yco-60,19,18, &data->reserved1, 12.0, 2.0, 0, 0, "Specify the axis that points to another object");
+                               uiDefButC(block, ROW,B_CONSTRAINT_REDRAW,"-X",  *xco+((width/2)-27), *yco-60,24,18, &data->reserved1, 12.0, 3.0, 0, 0, "Specify the axis that points to another object");
+                               uiDefButC(block, ROW,B_CONSTRAINT_REDRAW,"-Y",  *xco+((width/2)-3), *yco-60,24,18, &data->reserved1, 12.0, 4.0, 0, 0, "Specify the axis that points to another object");
+                               uiDefButC(block, ROW,B_CONSTRAINT_REDRAW,"-Z",  *xco+((width/2)+21), *yco-60,24,18, &data->reserved1, 12.0, 5.0, 0, 0, "Specify the axis that points to another object");
+                               uiDefButC(block, ROW,B_CONSTRAINT_REDRAW,"X",   *xco+((width/2)+60), *yco-60,19,18, &data->reserved2, 13.0, 0.0, 0, 0, "Specify the axis that is points upward");
+                               uiDefButC(block, ROW,B_CONSTRAINT_REDRAW,"Y",   *xco+((width/2)+79), *yco-60,19,18, &data->reserved2, 13.0, 1.0, 0, 0, "Specify the axis that is points upward");
+                               uiDefButC(block, ROW,B_CONSTRAINT_REDRAW,"Z",   *xco+((width/2)+98), *yco-60,19,18, &data->reserved2, 13.0, 2.0, 0, 0, "Specify the axis that is points upward");
+                       }
+                       break;
+               case CONSTRAINT_TYPE_LOCKTRACK:
+                       {
+                               bLockTrackConstraint *data = con->data;
+                               bArmature *arm;
+                               height = 66;
+                               BIF_ThemeColor(curCol);
+                               glRects(*xco+40, *yco-height-16, *xco+width+50, *yco-14);
+                               uiEmboss((float)*xco+40, (float)*yco-height-16, (float)*xco+width+50, (float)*yco-14, 1);
+
+                               /* Draw target parameters */
+                               uiDefIDPoinBut(block, test_obpoin_but, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+((width/2)-48), *yco-20, 96, 18, &data->tar, "Target Object"); 
+
+                               arm = get_armature(data->tar);
+                               if (arm){
+                                       but=uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "BO:", *xco+((width/2)-48), *yco-40,96,18, &data->subtarget, 0, 24, 0, 0, "Bone");
+                               }
+                               else
+                                       strcpy (data->subtarget, "");
+
+                               uiDefButC(block, ROW,B_CONSTRAINT_REDRAW,"X",           *xco+((width/2)-84), *yco-60,19,18, &data->trackflag, 12.0, 0.0, 0, 0, "Specify the axis that points to another object");
+                               uiDefButC(block, ROW,B_CONSTRAINT_REDRAW,"Y",           *xco+((width/2)-65), *yco-60,19,18, &data->trackflag, 12.0, 1.0, 0, 0, "Specify the axis that points to another object");
+                               uiDefButC(block, ROW,B_CONSTRAINT_REDRAW,"Z",           *xco+((width/2)-46), *yco-60,19,18, &data->trackflag, 12.0, 2.0, 0, 0, "Specify the axis that points to another object");
+                               uiDefButC(block, ROW,B_CONSTRAINT_REDRAW,"-X",          *xco+((width/2)-27), *yco-60,24,18, &data->trackflag, 12.0, 3.0, 0, 0, "Specify the axis that points to another object");
+                               uiDefButC(block, ROW,B_CONSTRAINT_REDRAW,"-Y",          *xco+((width/2)-3), *yco-60,24,18, &data->trackflag, 12.0, 4.0, 0, 0, "Specify the axis that points to another object");
+                               uiDefButC(block, ROW,B_CONSTRAINT_REDRAW,"-Z",          *xco+((width/2)+21), *yco-60,24,18, &data->trackflag, 12.0, 5.0, 0, 0, "Specify the axis that points to another object");
+                               uiDefButC(block, ROW,B_CONSTRAINT_REDRAW,"X",           *xco+((width/2)+60), *yco-60,19,18, &data->lockflag, 13.0, 0.0, 0, 0, "Specify the axis that is locked");
+                               uiDefButC(block, ROW,B_CONSTRAINT_REDRAW,"Y",           *xco+((width/2)+79), *yco-60,19,18, &data->lockflag, 13.0, 1.0, 0, 0, "Specify the axis that is locked");
+                               uiDefButC(block, ROW,B_CONSTRAINT_REDRAW,"Z",           *xco+((width/2)+98), *yco-60,19,18, &data->lockflag, 13.0, 2.0, 0, 0, "Specify the axis that is locked");
+                       }
+                       break;
+               case CONSTRAINT_TYPE_FOLLOWPATH:
+                       {
+                               bFollowPathConstraint *data = con->data;
+
+                               height = 66;
+                               BIF_ThemeColor(curCol);
+                               glRects(*xco+40, *yco-height-16, *xco+width+50, *yco-14);
+                               uiEmboss((float)*xco+40, (float)*yco-height-16, (float)*xco+width+50, (float)*yco-14, 1);
+                               
+                               uiDefIDPoinBut(block, test_obpoin_but, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+((width/2)-48), *yco-20, 96, 18, &data->tar, "Target Object"); 
+                               
+                               /* Draw Curve Follow toggle */
+                               but=uiDefButI(block, TOG|BIT|0, B_CONSTRAINT_TEST, "CurveFollow", *xco+((width/2)-84), *yco-40, 90, 18, &data->followflag, 0, 24, 0, 0, "Object will follow the heading and banking of the curve");
+
+                               /* Draw Offset number button */
+                               uiDefButF(block, NUM, B_CONSTRAINT_REDRAW, "Offset:", *xco+((width/2))+20, *yco-40, 96, 18, &data->offset, -9000, 9000, 100.0, 0.0, "Offset from the position corresponding to the time frame"); 
+
+                               uiDefButC(block, ROW,B_CONSTRAINT_REDRAW,"X",           *xco+((width/2)-84), *yco-60,19,18, &data->trackflag, 12.0, 0.0, 0, 0, "Specify the axis that points to another object");
+                               uiDefButC(block, ROW,B_CONSTRAINT_REDRAW,"Y",           *xco+((width/2)-65), *yco-60,19,18, &data->trackflag, 12.0, 1.0, 0, 0, "Specify the axis that points to another object");
+                               uiDefButC(block, ROW,B_CONSTRAINT_REDRAW,"Z",           *xco+((width/2)-46), *yco-60,19,18, &data->trackflag, 12.0, 2.0, 0, 0, "Specify the axis that points to another object");
+                               uiDefButC(block, ROW,B_CONSTRAINT_REDRAW,"-X",          *xco+((width/2)-27), *yco-60,24,18, &data->trackflag, 12.0, 3.0, 0, 0, "Specify the axis that points to another object");
+                               uiDefButC(block, ROW,B_CONSTRAINT_REDRAW,"-Y",          *xco+((width/2)-3), *yco-60,24,18, &data->trackflag, 12.0, 4.0, 0, 0, "Specify the axis that points to another object");
+                               uiDefButC(block, ROW,B_CONSTRAINT_REDRAW,"-Z",          *xco+((width/2)+21), *yco-60,24,18, &data->trackflag, 12.0, 5.0, 0, 0, "Specify the axis that points to another object");
+                               uiDefButC(block, ROW,B_CONSTRAINT_REDRAW,"X",           *xco+((width/2)+60), *yco-60,19,18, &data->upflag, 13.0, 0.0, 0, 0, "Specify the axis that is points upward");
+                               uiDefButC(block, ROW,B_CONSTRAINT_REDRAW,"Y",           *xco+((width/2)+79), *yco-60,19,18, &data->upflag, 13.0, 1.0, 0, 0, "Specify the axis that is points upward");
+                               uiDefButC(block, ROW,B_CONSTRAINT_REDRAW,"Z",           *xco+((width/2)+98), *yco-60,19,18, &data->upflag, 13.0, 2.0, 0, 0, "Specify the axis that is points upward");
+                       }
+                       break;
+               case CONSTRAINT_TYPE_NULL:
+                       {
+                               height = 20;
+                               BIF_ThemeColor(curCol);
+                               glRects(*xco+40, *yco-height-16, *xco+width+50, *yco-14);
+                               uiEmboss((float)*xco+40, (float)*yco-height-16, (float)*xco+width+50, (float)*yco-14, 1);
+                       }
+                       break;
+               default:
+                       height = 0;
+                       break;
                }
-               break;
-       case CONSTRAINT_TYPE_ROTLIKE:
-               {
-                       bRotateLikeConstraint *data = con->data;
-                       bArmature *arm;
-                       height = 46;
-                       BIF_ThemeColor(curCol);
-                       glRects(*xco+34, *yco-height-16, *xco+width+24, *yco-14);
-                       uiEmboss((float)*xco+34, (float)*yco-height-16, (float)*xco+width+24, (float)*yco-14, 1);
 
-                       uiDefIDPoinBut(block, test_obpoin_but, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+((width/2)-48), *yco-20, 96, 18, &data->tar, "Target Object"); 
-
-                       arm = get_armature(data->tar);
-                       if (arm){
-                               but=uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "BO:", *xco+((width/2)-48), *yco-40,96,18, &data->subtarget, 0, 24, 0, 0, "Bone");
-                       }
-                       else
-                               strcpy (data->subtarget, "");
+               (*yco)-=(22+height);
+       }
 
-               }
-               break;
-       case CONSTRAINT_TYPE_KINEMATIC:
-               {
-                       bKinematicConstraint *data = con->data;
-                       bArmature *arm;
-                       
-                       height = 66;
-                       BIF_ThemeColor(curCol);
-                       glRects(*xco+34, *yco-height-16, *xco+width+24, *yco-14);
-                       uiEmboss((float)*xco+34, (float)*yco-height-16, (float)*xco+width+24, (float)*yco-14, 1);
-                       
-                       uiDefButF(block, NUM, B_CONSTRAINT_REDRAW, "Tolerance:", *xco+((width/2)-96), *yco-20, 96, 18, &data->tolerance, 0.0001, 1.0, 0.0, 0.0, "Maximum distance to target after solving"); 
-                       uiDefButI(block, NUM, B_CONSTRAINT_REDRAW, "Iterations:", *xco+((width/2)), *yco-20, 96, 18, &data->iterations, 1, 10000, 0.0, 0.0, "Maximum number of solving iterations"); 
+       if (con->type!=CONSTRAINT_TYPE_NULL) {
+               uiDefButF(block, NUMSLI, B_CONSTRAINT_REDRAW, "Inf:", *xco+20, *yco, 166, 20, &(con->enforce), 0.0, 1.0, 0.0, 0.0, "Amount of influence this constraint will have on the final solution");
+               but = uiDefBut(block, BUT, B_CONSTRAINT_REDRAW, "Edit", *xco+186, *yco, 41, 20, 0, 0.0, 1.0, 0.0, 0.0, "Show this constraint's ipo in the object's Ipo window");
+               /* If this is on an object, add the constraint to the object */
+               uiButSetFunc (but, activate_constraint_ipo_func, con, NULL);
+               /* If this is on a bone, add the constraint to the action (if any) */
+               but = uiDefBut(block, BUT, B_CONSTRAINT_REDRAW, "Key", *xco+227, *yco, 41, 20, 0, 0.0, 1.0, 0.0, 0.0, "Add an influence keyframe to the constraint");
+               /* Add a keyframe to the influence IPO */
+               uiButSetFunc (but, add_influence_key_to_constraint, con, NULL);
+               (*yco)-=24;
+       }
+}
 
-                       uiDefIDPoinBut(block, test_obpoin_but, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+((width/2)-48), *yco-40, 96, 18, &data->tar, "Target Object"); 
-                       
-                       arm = get_armature(data->tar);
-                       if (arm){
-                               but=uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "BO:", *xco+((width/2)-48), *yco-60,96,18, &data->subtarget, 0, 24, 0, 0, "Bone");
-                       }
-                       else
-                               strcpy (data->subtarget, "");
-                       
-               }
-               break;
-       case CONSTRAINT_TYPE_NULL:
-               {
-                       height = 20;
-                       BIF_ThemeColor(curCol);
-                       glRects(*xco+34, *yco-height-16, *xco+width+24, *yco-14);
-                       uiEmboss((float)*xco+34, (float)*yco-height-16, (float)*xco+width+24, (float)*yco-14, 1);
-               }
-               break;
-       case CONSTRAINT_TYPE_TRACKTO:
-               {
-                       bTrackToConstraint *data = con->data;
-                       bArmature *arm;
+static uiBlock *add_constraintmenu(void *arg_unused)
+{
+       uiBlock *block;
+       
+       ListBase *conlist;
+       char ownerstr[64];
+       short type;
+       short yco= 0;
+       
+       conlist = get_constraint_client(ownerstr, &type, NULL);
+       
+       block= uiNewBlock(&curarea->uiblocks, "add_constraintmenu", UI_EMBOSSP, UI_HELV, curarea->win);
 
-                       height = 46;
-                       BIF_ThemeColor(curCol);
-                       glRects(*xco+34, *yco-height-16, *xco+width+24, *yco-14);
-                       uiEmboss((float)*xco+34, (float)*yco-height-16, (float)*xco+width+24, (float)*yco-14, 1);
-                       
-                       uiDefIDPoinBut(block, test_obpoin_but, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+((width/2)-48), *yco-20, 96, 18, &data->tar, "Target Object"); 
-                       
-                       arm = get_armature(data->tar);
-                       if (arm){
-                               but=uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "BO:", *xco+((width/2)-48), *yco-40,96,18, &data->subtarget, 0, 24, 0, 0, "Bone");
-                       }
-                       else
-                               strcpy (data->subtarget, "");
-               }
-               break;
-       default:
-               height = 0;
-               break;
+       uiDefIconTextBut(block, BUTM, B_CONSTRAINT_ADD_LOCLIKE, ICON_BLANK1,"Copy Location",            0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
+       uiDefIconTextBut(block, BUTM, B_CONSTRAINT_ADD_ROTLIKE, ICON_BLANK1,"Copy Rotation",            0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
+       
+       uiDefBut(block, SEPR, 0, "",                                    0, yco-=6, 120, 6, NULL, 0.0, 0.0, 0, 0, "");
+       
+       uiDefIconTextBut(block, BUTM, B_CONSTRAINT_ADD_TRACKTO, ICON_BLANK1,"Track To",         0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
+       uiDefIconTextBut(block, BUTM, B_CONSTRAINT_ADD_LOCKTRACK, ICON_BLANK1,"Lock Track",             0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
+       uiDefIconTextBut(block, BUTM, B_CONSTRAINT_ADD_FOLLOWPATH, ICON_BLANK1,"Follow Path",           0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
+       
+       if (type==TARGET_BONE) {
+       
+               uiDefBut(block, SEPR, 0, "",                                    0, yco-=6, 120, 6, NULL, 0.0, 0.0, 0, 0, "");
+               
+               uiDefIconTextBut(block, BUTM, B_CONSTRAINT_ADD_KINEMATIC, ICON_BLANK1,"IK Solver",              0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
+               uiDefIconTextBut(block, BUTM, B_CONSTRAINT_ADD_ACTION, ICON_BLANK1,"Action",            0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
+               
        }
+       
+       uiDefBut(block, SEPR, 0, "",                                    0, yco-=6, 120, 6, NULL, 0.0, 0.0, 0, 0, "");
+       
+       uiDefIconTextBut(block, BUTM, B_CONSTRAINT_ADD_NULL, ICON_BLANK1,"Null",                0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
+       
 
-       (*yco)-=(24+height);
 
+       uiBlockSetDirection(block, UI_RIGHT);
+       uiTextBoundsBlock(block, 50);
+               
+       return block;
 }
 
-
 void do_constraintbuts(unsigned short event)
 {
-       ListBase *list;
-       short   type;
-
        switch(event) {
        case B_CONSTRAINT_CHANGENAME:
                break;
@@ -549,23 +675,97 @@ void do_constraintbuts(unsigned short event)
                allqueue (REDRAWVIEW3D, 0);
                allqueue (REDRAWBUTSOBJECT, 0);
                break;
-       case B_CONSTRAINT_ADD:
+       case B_CONSTRAINT_ADD_NULL:
                {
                        bConstraint *con;
-               //      ListBase *chanbase;
-               //      bConstraintChannel *chan;
-
-               //      Object *ob = OBACT;
-                       list = get_constraint_client(NULL, &type, NULL);
-               //      chanbase= get_constraint_client_channels(0);
-                       if (list){
-                               con = add_new_constraint();
-                               unique_constraint_name(con, list);
-               //              chan = add_new_constraint_channel(con->name);
-               //              ob->activecon = chan;
-               //              BLI_addtail(chanbase, chan);
-                               BLI_addtail(list, con);
-                       }
+                       
+                       con = add_new_constraint(CONSTRAINT_TYPE_NULL);
+                       add_constraint_to_client(con);
+
+                       test_scene_constraints();
+                       allqueue (REDRAWVIEW3D, 0);
+                       allqueue (REDRAWBUTSOBJECT, 0);
+               }
+               break;
+       case B_CONSTRAINT_ADD_KINEMATIC:
+               {
+                       bConstraint *con;
+                       
+                       con = add_new_constraint(CONSTRAINT_TYPE_KINEMATIC);
+                       add_constraint_to_client(con);
+
+                       test_scene_constraints();
+                       allqueue (REDRAWVIEW3D, 0);
+                       allqueue (REDRAWBUTSOBJECT, 0);
+               }
+               break;
+       case B_CONSTRAINT_ADD_TRACKTO:
+               {
+                       bConstraint *con;
+
+                       con = add_new_constraint(CONSTRAINT_TYPE_TRACKTO);
+                       add_constraint_to_client(con);
+
+                       test_scene_constraints();
+                       allqueue (REDRAWVIEW3D, 0);
+                       allqueue (REDRAWBUTSOBJECT, 0);
+               }
+               break;
+       case B_CONSTRAINT_ADD_ROTLIKE:
+               {
+                       bConstraint *con;
+
+                       con = add_new_constraint(CONSTRAINT_TYPE_ROTLIKE);
+                       add_constraint_to_client(con);
+
+                       test_scene_constraints();
+                       allqueue (REDRAWVIEW3D, 0);
+                       allqueue (REDRAWBUTSOBJECT, 0);
+               }
+               break;
+       case B_CONSTRAINT_ADD_LOCLIKE:
+               {
+                       bConstraint *con;
+
+                       con = add_new_constraint(CONSTRAINT_TYPE_LOCLIKE);
+                       add_constraint_to_client(con);
+
+                       test_scene_constraints();
+                       allqueue (REDRAWVIEW3D, 0);
+                       allqueue (REDRAWBUTSOBJECT, 0);
+               }
+               break;
+       case B_CONSTRAINT_ADD_ACTION:
+               {
+                       bConstraint *con;
+
+                       con = add_new_constraint(CONSTRAINT_TYPE_ACTION);
+                       add_constraint_to_client(con);
+
+                       test_scene_constraints();
+                       allqueue (REDRAWVIEW3D, 0);
+                       allqueue (REDRAWBUTSOBJECT, 0);
+               }
+               break;
+       case B_CONSTRAINT_ADD_LOCKTRACK:
+               {
+                       bConstraint *con;
+
+                       con = add_new_constraint(CONSTRAINT_TYPE_LOCKTRACK);
+                       add_constraint_to_client(con);
+
+                       test_scene_constraints();
+                       allqueue (REDRAWVIEW3D, 0);
+                       allqueue (REDRAWBUTSOBJECT, 0);
+               }
+               break;
+       case B_CONSTRAINT_ADD_FOLLOWPATH:
+               {
+                       bConstraint *con;
+
+                       con = add_new_constraint(CONSTRAINT_TYPE_FOLLOWPATH);
+                       add_constraint_to_client(con);
+
                        test_scene_constraints();
                        allqueue (REDRAWVIEW3D, 0);
                        allqueue (REDRAWBUTSOBJECT, 0);
@@ -601,7 +801,7 @@ static void object_panel_constraint(void)
        
        if (conlist) {
                 
-               uiDefBut(block, BUT, B_CONSTRAINT_ADD, "Add", 10, 190, 95, 20, 0, 0.0, 0, 0, 0,"Add new constraint");
+               uiDefBlockBut(block, add_constraintmenu, NULL, "Add|>> ", 10, 190, 70, 20, "Add a new constraint");
                
                /* Go through the list of constraints and draw them */
                xco = 10;
index 60798fe0b8bafbae9221ea113e7afa0886f5c21d..55fa359314009acef6c1aef1ab833a196b1d841f 100644 (file)
@@ -81,50 +81,6 @@ const char *g_conString;
 Object *g_conObj;
 
 
-void unique_constraint_name (bConstraint *con, ListBase *list){
-       char            tempname[64];
-       int                     number;
-       char            *dot;
-       int exists = 0;
-       bConstraint *curcon;
-       
-       /* See if we even need to do this */
-       for (curcon = list->first; curcon; curcon=curcon->next){
-               if (curcon!=con){
-                       if (!strcmp(curcon->name, con->name)){
-                               exists = 1;
-                               break;
-                       }
-               }
-       }
-       
-       if (!exists)
-               return;
-
-       /*      Strip off the suffix */
-       dot=strchr(con->name, '.');
-       if (dot)
-               *dot=0;
-       
-       for (number = 1; number <=999; number++){
-               sprintf (tempname, "%s.%03d", con->name, number);
-               
-               exists = 0;
-               for (curcon=list->first; curcon; curcon=curcon->next){
-                       if (con!=curcon){
-                               if (!strcmp (curcon->name, tempname)){
-                                       exists = 1;
-                                       break;
-                               }
-                       }
-               }
-               if (!exists){
-                       strcpy (con->name, tempname);
-                       return;
-               }
-       }
-}
-
 static int is_child_of_ex(Object *owner, const char *ownersubstr, Object *parent, const char *parsubstr)
 {
        Object *curob;
@@ -549,6 +505,79 @@ static short detect_constraint_loop (Object *owner, const char* substring, int d
                                                        break;
                                                        //              return 1;
                                                }
+                                               if (data->reserved2==data->reserved1){
+                                                       curcon->flag |= CONSTRAINT_DISABLE;
+                                                       result = 1;
+                                                       break;
+                                                       //              return 1;
+                                               }
+                                               if (data->reserved2+3==data->reserved1){
+                                                       curcon->flag |= CONSTRAINT_DISABLE;
+                                                       result = 1;
+                                                       break;
+                                                       //              return 1;
+                                               }
+                                       }
+                                       break;
+                               case CONSTRAINT_TYPE_LOCKTRACK:
+                                       {
+                                               bLockTrackConstraint *data = curcon->data;
+                                       
+                                               if (!exist_object(data->tar)){
+                                                       data->tar = NULL;
+                                                       break;
+                                               }
+                                               
+                                               if (add_constraint_element (data->tar, data->subtarget, owner, substring)){
+                                                       curcon->flag |= CONSTRAINT_DISABLE;
+                                                       result = 1;
+                                                       break;
+                                                       //              return 1;
+                                               }
+                                               if (detect_constraint_loop (data->tar, data->subtarget, disable)){
+                                                       curcon->flag |= CONSTRAINT_DISABLE;
+                                                       result = 1;
+                                                       break;
+                                                       //              return 1;
+                                               }
+                                               if (data->lockflag==data->trackflag){
+                                                       curcon->flag |= CONSTRAINT_DISABLE;
+                                                       result = 1;
+                                                       break;
+                                                       //              return 1;
+                                               }
+                                               if (data->lockflag+3==data->trackflag){
+                                                       curcon->flag |= CONSTRAINT_DISABLE;
+                                                       result = 1;
+                                                       break;
+                                                       //              return 1;
+                                               }
+                                       }
+                                       break;
+                               case CONSTRAINT_TYPE_FOLLOWPATH:
+                                       {
+                                               bFollowPathConstraint *data = curcon->data;
+                                       
+                                               if (!exist_object(data->tar)){
+                                                       data->tar = NULL;
+                                                       break;
+                                               }
+                                               if (data->tar->type != OB_CURVE){
+                                                       data->tar = NULL;
+                                                       break;
+                                               }
+                                               if (data->upflag==data->trackflag){
+                                                       curcon->flag |= CONSTRAINT_DISABLE;
+                                                       result = 1;
+                                                       break;
+                                                       //              return 1;
+                                               }
+                                               if (data->upflag+3==data->trackflag){
+                                                       curcon->flag |= CONSTRAINT_DISABLE;
+                                                       result = 1;
+                                                       break;
+                                                       //              return 1;
+                                               }
                                        }
                                        break;
                                }
@@ -666,77 +695,14 @@ ListBase *get_constraint_client(char *name, short *clientType, void **clientdata
        return list;
 }
 
-void   *new_constraint_data (short type)
-{
-       void    *result;
-       
-       switch (type){
-       case CONSTRAINT_TYPE_KINEMATIC:
-               {
-                       bKinematicConstraint *data;
-                       data = MEM_callocN(sizeof(bKinematicConstraint), "kinematicConstraint");
-
-                       data->tolerance = 0.001;
-                       data->iterations = 500;
-
-                       result = data;
-               }
-               break;
-       case CONSTRAINT_TYPE_NULL:
-               {
-                       result = NULL;
-               }
-               break;
-       case CONSTRAINT_TYPE_TRACKTO:
-               {
-                       bTrackToConstraint *data;
-                       data = MEM_callocN(sizeof(bTrackToConstraint), "tracktoConstraint");
-
-                       result = data;
-
-               }
-               break;
-       case CONSTRAINT_TYPE_ROTLIKE:
-               {
-                       bRotateLikeConstraint *data;
-                       data = MEM_callocN(sizeof(bRotateLikeConstraint), "rotlikeConstraint");
-
-                       result = data;
-               }
-               break;
-       case CONSTRAINT_TYPE_LOCLIKE:
-               {
-                       bLocateLikeConstraint *data;
-                       data = MEM_callocN(sizeof(bLocateLikeConstraint), "loclikeConstraint");
-
-                       data->flag |= LOCLIKE_X|LOCLIKE_Y|LOCLIKE_Z;
-                       result = data;
-               }
-               break;
-       case CONSTRAINT_TYPE_ACTION:
-               {
-                       bActionConstraint *data;
-                       data = MEM_callocN(sizeof(bActionConstraint), "actionConstraint");
-
-                       result = data;
-               }
-               break;
-       default:
-               result = NULL;
-               break;
-       }
-
-       return result;
-}
-
-bConstraint * add_new_constraint(void)
+bConstraint * add_new_constraint(int type)
 {
        bConstraint *con;
 
        con = MEM_callocN(sizeof(bConstraint), "constraint");
 
        /* Set up a generic constraint datablock */
-       con->type = CONSTRAINT_TYPE_TRACKTO;
+       con->type = type;
        con->flag |= CONSTRAINT_EXPAND;
        con->enforce=1.0F;
        /* Load the data for it */
@@ -745,6 +711,29 @@ bConstraint * add_new_constraint(void)
        return con;
 }
 
+void add_constraint_to_object(bConstraint *con, Object *ob)
+{
+       ListBase *list;
+       list = &ob->constraints;
+       if (list)
+       {
+               unique_constraint_name(con, list);
+               BLI_addtail(list, con);
+       }
+}
+
+void add_constraint_to_client(bConstraint *con)
+{
+       ListBase *list;
+       short type;
+       list = get_constraint_client(NULL, &type, NULL);
+       if (list)
+       {
+               unique_constraint_name(con, list);
+               BLI_addtail(list, con);
+       }
+}
+
 bConstraintChannel *add_new_constraint_channel(const char* name)
 {
        bConstraintChannel *chan = NULL;
@@ -755,3 +744,6 @@ bConstraintChannel *add_new_constraint_channel(const char* name)
        return chan;
 }
 
+void add_influence_key_to_constraint (bConstraint *con){
+       printf("doesn't do anything yet\n");
+}
\ No newline at end of file
index 0e12094a845f5c512cf79bfab3cb56a32c571cfd..fe9d9d92d119174f13ee8e077ec07d015a8f385e 100644 (file)
@@ -258,38 +258,59 @@ extern int undo_push(char *);
 void make_track(void)
 {
        Base *base;
+       short mode=0;
        
        if(G.scene->id.lib) return;
        if(G.obedit) {
                return;
        }
        if(BASACT==0) return;
-       
-#if 0
-       /* Not yet */
-       notice ("Make Track no longer supported.  Use constraints instead.");
-       return;
 
-       /* hrms, i would suppose then just to add a constraint for the user. be nice! (ton) */
-#endif
+       mode= pupmenu("Make Track %t|Constraint %x1|Old Track %x2");
+       if (mode == 0){
+               return;
+       }
+       else if (mode == 1){
+               bConstraint *con;
+               bTrackToConstraint *data;
 
-       if(okee("Make Track")==0) return;
-       
-       base= FIRSTBASE;
-       while(base) {
-               if TESTBASELIB(base) {
-                       if(base!=BASACT) {
+               base= FIRSTBASE;
+               while(base) {
+                       if TESTBASELIB(base) {
+                               if(base!=BASACT) {
+                                       con = add_new_constraint(CONSTRAINT_TYPE_TRACKTO);
+                                       strcpy (con->name, "AutoTrack");
+
+                                       data = con->data;
+                                       data->tar = BASACT->object;
 
-                               base->object->track= BASACT->object;
+                                       add_constraint_to_object(con, base->object);
+                               }
                        }
+                       base= base->next;
                }
-               base= base->next;
+
+               test_scene_constraints();
+               allqueue(REDRAWVIEW3D, 0);
+               sort_baselist(G.scene);
        }
+       else if (mode == 2){
+               base= FIRSTBASE;
+               while(base) {
+                       if TESTBASELIB(base) {
+                               if(base!=BASACT) {
 
-       test_scene_constraints();
-       allqueue(REDRAWVIEW3D, 0);
-       allqueue(REDRAWOOPS, 0);
-       sort_baselist(G.scene);
+                                       base->object->track= BASACT->object;
+                               }
+                       }
+                       base= base->next;
+               }
+
+               test_scene_constraints();
+               allqueue(REDRAWVIEW3D, 0);
+               allqueue(REDRAWOOPS, 0);
+               sort_baselist(G.scene);
+       }
 }
 
 void apply_obmat(Object *ob)
@@ -699,6 +720,47 @@ void make_parent(void)
                        base= base->next;
                }
        }
+       else if(par->type == OB_CURVE){
+               bConstraint *con;
+               bFollowPathConstraint *data;
+
+               mode= pupmenu("Make Parent %t|Normal Parent %x1|Follow Path %x2");
+               if (mode == 0){
+                       return;
+               }
+               else if (mode == 2){
+
+                       base= FIRSTBASE;
+                       while(base) {
+                               if TESTBASELIB(base) {
+                                       if(base!=BASACT) {
+                                               float cmat[4][4], vec[3], size[3];
+
+                                               con = add_new_constraint(CONSTRAINT_TYPE_FOLLOWPATH);
+                                               strcpy (con->name, "AutoPath");
+
+                                               data = con->data;
+                                               data->tar = BASACT->object;
+
+                                               add_constraint_to_object(con, base->object);
+
+                                               get_constraint_target(con, TARGET_OBJECT, NULL, cmat, size, G.scene->r.cfra - base->object->sf);
+                                               VecSubf(vec, &base->object->obmat[3], cmat[3]);
+
+                                               base->object->loc[0] = vec[0];
+                                               base->object->loc[1] = vec[1];
+                                               base->object->loc[2] = vec[2];
+                                       }
+                               }
+                               base= base->next;
+                       }
+
+                       test_scene_constraints();
+                       allqueue(REDRAWVIEW3D, 0);
+                       sort_baselist(G.scene);
+                       return;
+               }
+       }
        else if(par->type == OB_ARMATURE){
                        mode= pupmenu("Make Parent %t|Use Bone %x1|Use Armature %x2|Use Object %x3");
                        switch (mode){