== Transformation Constraint ==
authorJoshua Leung <aligorith@gmail.com>
Sat, 21 Jul 2007 07:26:15 +0000 (07:26 +0000)
committerJoshua Leung <aligorith@gmail.com>
Sat, 21 Jul 2007 07:26:15 +0000 (07:26 +0000)
This commit adds a new constraint to Blender: the Transformation Constraint. This constraint gives you more freedom to choose how transforms are copied from one object/bone to another object/bone.

You can assign the Loc/Rot/Scale channels of a source to the Loc/Rot/Scale channels of a destination, specifying the range of motion (per axis) from the source to consider, and the range of motion (per axis) that will be applied to the destination. Also, for each destination axis, you can choose which of the source axes to copy from.

A similar constraint was coded by Jason Blary (snark), as Patch #4991. This constraint is basically rewritten from scratch, although there are some elements of the original patch which may be borrowed in future.

Various notes:
* PyAPI access has been coded.
* Space conversion is also enabled for this constraint.
* Also the useless get_constraint_col function has been removed
* Doing a rotation copy with a ratio that is not 1:1 doesn't always work correctly yet (like for the Copy Rotation constraint).

source/blender/blenkernel/intern/constraint.c
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/writefile.c
source/blender/include/butspace.h
source/blender/makesdna/DNA_constraint_types.h
source/blender/python/api2_2x/Constraint.c
source/blender/python/api2_2x/doc/Constraint.py
source/blender/src/buttons_object.c
source/blender/src/editconstraint.c

index dfa9ff8c9545dfcd4c48c635229109d5dfd2360d..d0bfd7113579587b4bb2da789eaa53efaf5039a9 100644 (file)
@@ -267,6 +267,12 @@ char constraint_has_target (bConstraint *con)
                        if (data->tar) return 1;
                }
                break;
+       case CONSTRAINT_TYPE_TRANSFORM:
+               {
+                       bTransformConstraint *data = con->data;
+                       if (data->tar) return 1;
+               }
+               break;
        }
        
        /* Unknown types or CONSTRAINT_TYPE_NULL or no target */
@@ -377,6 +383,13 @@ Object *get_constraint_target(bConstraint *con, char **subtarget)
                        return data->tar;
                }
                break;
+       case CONSTRAINT_TYPE_TRANSFORM: 
+               {
+                       bTransformConstraint *data = con->data;
+                       *subtarget= data->subtarget;
+                       return data->tar;
+               }
+               break;
        default:
                *subtarget= NULL;
                break;
@@ -484,6 +497,13 @@ void set_constraint_target(bConstraint *con, Object *ob, char *subtarget)
                        if (subtarget) BLI_strncpy(data->subtarget, subtarget, 32);
                }
                        break;
+               case CONSTRAINT_TYPE_TRANSFORM:
+               {
+                       bTransformConstraint *data = con->data;
+                       data->tar= ob;
+                       if (subtarget) BLI_strncpy(data->subtarget, subtarget, 32);
+               }
+                       break;
        }
 }
 
@@ -714,6 +734,18 @@ void *new_constraint_data (short type)
                        result = data;
                }
                break;
+       case CONSTRAINT_TYPE_TRANSFORM:
+               {
+                       bTransformConstraint *data;
+                       data = MEM_callocN(sizeof(bTransformConstraint), "TransformationConstraint");
+                       
+                       data->map[0]= 0;
+                       data->map[1]= 1;
+                       data->map[2]= 2;
+                       
+                       result = data;
+               }
+               break;
   
        default:
                result = NULL;
@@ -1504,6 +1536,19 @@ short get_constraint_target_matrix (bConstraint *con, short ownertype, void *own
                                Mat4One(mat);
                }
                break;
+       case CONSTRAINT_TYPE_TRANSFORM:
+               {
+                       bTransformConstraint *data;
+                       data= (bTransformConstraint *)con->data;
+                       
+                       if (data->tar) {
+                               constraint_target_to_mat4(data->tar, data->subtarget, mat, CONSTRAINT_SPACE_WORLD, con->tarspace);
+                               valid = 1;
+                       }
+                       else
+                               Mat4One(mat);
+               }
+               break;
 
        default:
                Mat4One(mat);
@@ -2466,8 +2511,114 @@ static void evaluate_constraint (bConstraint *constraint, float ownermat[][4], f
                        }
                }
                break;
+       case CONSTRAINT_TYPE_TRANSFORM:
+               {
+                       bTransformConstraint *data;
+                       
+                       data = constraint->data;
+                       
+                       /* only work if there is a target */
+                       if (data->tar) {
+                               float loc[3], eul[3], size[3];
+                               float dvec[3], sval[3];
+                               short i;
+                               
+                               /* obtain target effect */
+                               switch (data->from) {
+                                       case 2: /* scale */
+                                       {
+                                               Mat4ToSize(targetmat, dvec);
+                                       }
+                                               break;
+                                       case 1: /* rotation */
+                                       {
+                                               /* copy, and reduce to smallest rotation distance */
+                                               Mat4ToEul(targetmat, dvec);
+                                               
+                                               /* reduce rotation */
+                                               for (i=0; i<3; i++)
+                                                       dvec[i]= fmod(dvec[i], M_PI*2);
+                                       }
+                                               break;
+                                       default: /* location */
+                                       {
+                                               VECCOPY(dvec, targetmat[3]);
+                                       }
+                                               break;
+                               }
+                               
+                               /* extract components of owner's matrix */
+                               VECCOPY(loc, ownermat[3]);
+                               Mat4ToEul(ownermat, eul);
+                               Mat4ToSize(ownermat, size);
+                               
+                               /* determine where in range current transforms lie */
+                               if (data->expo) {
+                                       for (i=0; i<3; i++) {
+                                               if (data->from_max[i] - data->from_min[i])
+                                                       sval[i]= (dvec[i] - data->from_min[i]) / (data->from_max[i] - data->from_min[i]);
+                                               else
+                                                       sval[i]= 0.0f;
+                                       }
+                               }
+                               else {
+                                       /* clamp transforms out of range */
+                                       for (i=0; i<3; i++) {
+                                               CLAMP(dvec[i], data->from_min[i], data->from_max[i]);
+                                               if (data->from_max[i] - data->from_min[i])
+                                                       sval[i]= (dvec[i] - data->from_min[i]) / (data->from_max[i] - data->from_min[i]);
+                                               else
+                                                       sval[i]= 0.0f;
+                                       }
+                               }
+                               
+                               /* convert radian<->degree */
+                               if (data->from==1 && data->to==0) {
+                                       /* from radians to degrees */
+                                       for (i=0; i<3; i++) 
+                                               sval[i] = sval[i] / M_PI * 180;
+                               }
+                               else if (data->from==0 && data->to==1) {
+                                       /* from degrees to radians */
+                                       for (i=0; i<3; i++) 
+                                               sval[i] = sval[i] / 180 * M_PI;
+                               }
+                               else if (data->from == data->to == 1) {
+                                       /* degrees to radians */
+                                       for (i=0; i<3; i++) 
+                                               sval[i] = sval[i] / 180 * M_PI;
+                               }
+                               
+                               /* apply transforms */
+                               switch (data->to) {
+                                       case 2: /* scaling */
+                                               for (i=0; i<3; i++)
+                                                       size[i]= data->to_min[i] + (sval[data->map[i]] * (data->to_max[i] - data->to_min[i])); 
+                                               break;
+                                       case 1: /* rotation */
+                                               for (i=0; i<3; i++) {
+                                                       float tmin, tmax;
+                                                       
+                                                       /* convert destination min/max ranges from degrees to radians */
+                                                       tmin= data->to_min[i] / M_PI * 180;
+                                                       tmax= data->to_max[i] / M_PI * 180;
+                                                       
+                                                       eul[i]= tmin + (sval[data->map[i]] * (tmax - tmin)); 
+                                               }
+                                               break;
+                                       default: /* location */
+                                               for (i=0; i<3; i++)
+                                                       loc[i] += (data->to_min[i] + (sval[data->map[i]] * (data->to_max[i] - data->to_min[i]))); 
+                                               break;
+                               }
+                               
+                               /* apply to matrix */
+                               LocEulSizeToMat4(ownermat, loc, eul, size);
+                       }
+               }
+               break;
        default:
-               printf ("Error: Unknown constraint type\n");
+               printf("Error: Unknown constraint type\n");
                break;
        }
 }
index b8323cbed81b3853172f05204162de50874dfed2..e5fdebae89d72fdb4eda102cd95b371eb168adfe 100644 (file)
@@ -1712,6 +1712,13 @@ static void lib_link_constraints(FileData *fd, ID *id, ListBase *conlist)
                                data->tar = newlibadr(fd, id->lib, data->tar);
                        }
                        break;
+               case CONSTRAINT_TYPE_TRANSFORM:
+                       {
+                               bTransformConstraint *data;
+                               data= ((bTransformConstraint*)con->data);
+                               data->tar = newlibadr(fd, id->lib, data->tar);
+                       }
+                       break;
                case CONSTRAINT_TYPE_NULL:
                        break;
                }
@@ -7095,6 +7102,12 @@ static void expand_constraints(FileData *fd, Main *mainvar, ListBase *lb)
                                expand_doit(fd, mainvar, data->tar);
                        }
                        break;
+               case CONSTRAINT_TYPE_TRANSFORM:
+                       {
+                               bTransformConstraint *data = (bTransformConstraint*)curcon->data;
+                               expand_doit(fd, mainvar, data->tar);
+                       }
+                       break;
                default:
                        break;
                }
index 5b29703fe35758f5273f765fae672cdfbe26895f..ca63b860f6c828106e1ab10ea4869d81fb994c2d 100644 (file)
@@ -760,6 +760,9 @@ static void write_constraints(WriteData *wd, ListBase *conlist)
                case CONSTRAINT_TYPE_CLAMPTO:
                        writestruct(wd, DATA, "bClampToConstraint", 1, con->data);
                        break;
+               case CONSTRAINT_TYPE_TRANSFORM:
+                       writestruct(wd, DATA, "bTransformConstraint", 1, con->data);
+                       break;
                default:
                        break;
                }
index 142d2ae1d0bd1aafd202e592f31bcd842974e7a6..4a106fb5b96c1f08d59d9d3b6b62f8064d88e508 100644 (file)
@@ -649,6 +649,7 @@ enum {
        B_CONSTRAINT_ADD_CHILDOF,
        B_CONSTRAINT_ADD_PYTHON,
        B_CONSTRAINT_ADD_CLAMPTO,
+       B_CONSTRAINT_ADD_TRANSFORM,
        B_CONSTRAINT_INF
 };
 
index ce2b558e714241d7d19e2708e9cac9dd66bc9a5b..9a0d5a095e5b3ff3c5a9361add8bcdf4e0e52830 100644 (file)
@@ -210,13 +210,29 @@ typedef struct bClampToConstraint {
 
 /* Child Of Constraint */
 typedef struct bChildOfConstraint {
-       Object          *tar;                   /* object which may/may not be the parent */
+       Object          *tar;                   /* object which will act as parent (or target comes from) */
        int             flag;                   /* settings */
        int                     pad;
        float           invmat[4][4];   /* parent-inverse matrix to use */
        char            subtarget[32];  /* string to specify a subobject target */
 } bChildOfConstraint;
 
+/* Generic Transform->Transform Constraint */
+typedef struct bTransformConstraint {
+       Object          *tar;                   /* target (i.e. 'driver' object/bone) */
+       char            subtarget[32];  
+       
+       short           from, to;               /* can be loc(0) , rot(1),  or size(2) */
+       char            map[3];                 /* defines which target-axis deform is copied by each owner-axis */
+       char            expo;                   /* extrapolate motion? if 0, confine to ranges */
+       
+       float           from_min[3];    /* from_min/max defines range of target transform       */
+       float           from_max[3];    /*      to map on to to_min/max range.                  */
+       
+       float           to_min[3];              /* range of motion on owner caused by target  */
+       float           to_max[3];      
+} bTransformConstraint;
+
 /* transform limiting constraints - zero target ----------------------------  */
 /* Limit Location Constraint */
 typedef struct bLocLimitConstraint {
@@ -247,26 +263,27 @@ typedef struct bSizeLimitConstraint {
 
 /* bConstraint.type */
 #define CONSTRAINT_TYPE_NULL           0
-#define CONSTRAINT_TYPE_CHILDOF                1       /* Unimplemented non longer :) - during constraints recode, Aligorith */
+#define CONSTRAINT_TYPE_CHILDOF                1               /* Unimplemented non longer :) - during constraints recode, Aligorith */
 #define CONSTRAINT_TYPE_TRACKTO                2       
 #define CONSTRAINT_TYPE_KINEMATIC      3       
 #define CONSTRAINT_TYPE_FOLLOWPATH     4
-#define CONSTRAINT_TYPE_ROTLIMIT       5       /* Unimplemented no longer :) - Aligorith */
-#define CONSTRAINT_TYPE_LOCLIMIT       6       /* Unimplemented no longer :) - Aligorith */
-#define CONSTRAINT_TYPE_SIZELIMIT      7       /* Unimplemented no longer :) - Aligorith */
+#define CONSTRAINT_TYPE_ROTLIMIT       5               /* Unimplemented no longer :) - Aligorith */
+#define CONSTRAINT_TYPE_LOCLIMIT       6               /* Unimplemented no longer :) - Aligorith */
+#define CONSTRAINT_TYPE_SIZELIMIT      7               /* Unimplemented no longer :) - Aligorith */
 #define CONSTRAINT_TYPE_ROTLIKE                8       
 #define CONSTRAINT_TYPE_LOCLIKE                9       
 #define CONSTRAINT_TYPE_SIZELIKE       10
-#define CONSTRAINT_TYPE_PYTHON         11      /* Unimplemented no longer :) - Aligorith. Scripts */
+#define CONSTRAINT_TYPE_PYTHON         11              /* Unimplemented no longer :) - Aligorith. Scripts */
 #define CONSTRAINT_TYPE_ACTION         12
-#define CONSTRAINT_TYPE_LOCKTRACK      13      /* New Tracking constraint that locks an axis in place - theeth */
-#define CONSTRAINT_TYPE_DISTANCELIMIT  14 /* was never properly coded - removed! */
-#define CONSTRAINT_TYPE_STRETCHTO      15  /* claiming this to be mine :) is in tuhopuu bjornmose */ 
-#define CONSTRAINT_TYPE_MINMAX      16  /* floor constraint */
-#define CONSTRAINT_TYPE_RIGIDBODYJOINT 17 /* rigidbody constraint */
-#define CONSTRAINT_TYPE_CLAMPTO                18  /* clampto constraint */            
-
-/* bConstraint.flag */
+#define CONSTRAINT_TYPE_LOCKTRACK      13              /* New Tracking constraint that locks an axis in place - theeth */
+#define CONSTRAINT_TYPE_DISTANCELIMIT 14       /* was never properly coded - removed! */
+#define CONSTRAINT_TYPE_STRETCHTO      15      /* claiming this to be mine :) is in tuhopuu bjornmose */ 
+#define CONSTRAINT_TYPE_MINMAX      16         /* floor constraint */
+#define CONSTRAINT_TYPE_RIGIDBODYJOINT 17      /* rigidbody constraint */
+#define CONSTRAINT_TYPE_CLAMPTO                18      /* clampto constraint */        
+#define CONSTRAINT_TYPE_TRANSFORM      19              /* transformation constraint */ 
+
+/* bConstraint->flag */
                /* expand for UI */
 #define CONSTRAINT_EXPAND              0x01
                /* pre-check for illegal object name or bone name */
@@ -278,7 +295,7 @@ typedef struct bSizeLimitConstraint {
                /* to indicate that the owner's space should only be changed into ownspace, but not out of it */
 #define CONSTRAINT_SPACEONCE   0x40
 
-/* bConstraint.ownspace/tarspace */
+/* bConstraint->ownspace/tarspace */
        /* default for all - worldspace */
 #define CONSTRAINT_SPACE_WORLD                 0
        /* for objects (relative to parent/without parent influence), for bones (along normals of bone, without parent/restposi) */
index 0f94fa7195b61f32e0eed8fe12dfa44cbe18f282..aca052a7694fd8b07c2b4e72c5e2483ae3babab5 100644 (file)
@@ -25,7 +25,7 @@
  *
  * This is a new part of Blender.
  *
- * Contributor(s): Joseph Gilbert, Ken Hughes
+ * Contributor(s): Joseph Gilbert, Ken Hughes, Joshua Leung
  *
  * ***** END GPL/BL DUAL LICENSE BLOCK *****
  */
@@ -134,6 +134,25 @@ enum constraint_constants {
        EXPP_CONSTR_SCRIPT,
        EXPP_CONSTR_PROPS,
        
+       EXPP_CONSTR_FROM,
+       EXPP_CONSTR_TO,
+       EXPP_CONSTR_EXPO,
+       EXPP_CONSTR_FROMMINX,
+       EXPP_CONSTR_FROMMAXX,
+       EXPP_CONSTR_FROMMINY,
+       EXPP_CONSTR_FROMMAXY,
+       EXPP_CONSTR_FROMMINZ,
+       EXPP_CONSTR_FROMMAXZ,
+       EXPP_CONSTR_TOMINX,
+       EXPP_CONSTR_TOMAXX,
+       EXPP_CONSTR_TOMINY,
+       EXPP_CONSTR_TOMAXY,
+       EXPP_CONSTR_TOMINZ,
+       EXPP_CONSTR_TOMAXZ,
+       EXPP_CONSTR_MAPX,
+       EXPP_CONSTR_MAPY,
+       EXPP_CONSTR_MAPZ,
+       
        EXPP_CONSTR_OWNSPACE,
        EXPP_CONSTR_TARSPACE,
                
@@ -1397,6 +1416,147 @@ static int childof_setter( BPy_Constraint *self, int type, PyObject *value )
        }
 }
 
+static PyObject *transf_getter( BPy_Constraint * self, int type )
+{
+       bTransformConstraint *con = (bTransformConstraint *)(self->con->data);
+
+       switch( type ) {
+       case EXPP_CONSTR_TARGET:
+               return Object_CreatePyObject( con->tar );
+       case EXPP_CONSTR_BONE:
+               return PyString_FromString( con->subtarget );
+       case EXPP_CONSTR_FROM:
+               return PyInt_FromLong( (long)con->from );
+       case EXPP_CONSTR_TO:
+               return PyInt_FromLong( (long)con->to );
+       case EXPP_CONSTR_MAPX:
+               return PyInt_FromLong( (long)con->map[0] );
+       case EXPP_CONSTR_MAPY:
+               return PyInt_FromLong( (long)con->map[1] );
+       case EXPP_CONSTR_MAPZ:
+               return PyInt_FromLong( (long)con->map[2] );
+       case EXPP_CONSTR_FROMMINX:
+               return PyFloat_FromDouble( (double)con->from_min[0] );
+       case EXPP_CONSTR_FROMMAXX:
+               return PyFloat_FromDouble( (double)con->from_max[0] );
+       case EXPP_CONSTR_FROMMINY:
+               return PyFloat_FromDouble( (double)con->from_min[1] );
+       case EXPP_CONSTR_FROMMAXY:
+               return PyFloat_FromDouble( (double)con->from_max[1] );
+       case EXPP_CONSTR_FROMMINZ:
+               return PyFloat_FromDouble( (double)con->from_min[2] );
+       case EXPP_CONSTR_FROMMAXZ:
+               return PyFloat_FromDouble( (double)con->from_max[2] );
+       case EXPP_CONSTR_TOMINX:
+               return PyFloat_FromDouble( (double)con->to_min[0] );
+       case EXPP_CONSTR_TOMAXX:
+               return PyFloat_FromDouble( (double)con->to_max[0] );
+       case EXPP_CONSTR_TOMINY:
+               return PyFloat_FromDouble( (double)con->to_min[1] );
+       case EXPP_CONSTR_TOMAXY:
+               return PyFloat_FromDouble( (double)con->to_max[1] );
+       case EXPP_CONSTR_TOMINZ:
+               return PyFloat_FromDouble( (double)con->to_min[2] );
+       case EXPP_CONSTR_TOMAXZ:
+               return PyFloat_FromDouble( (double)con->to_max[2] );
+       case EXPP_CONSTR_EXPO:
+               return PyBool_FromLong( (long)con->expo );
+       default:
+               return EXPP_ReturnPyObjError( PyExc_KeyError, "key not found" );
+       }
+}
+
+static int transf_setter( BPy_Constraint *self, int type, PyObject *value )
+{
+       bTransformConstraint *con = (bTransformConstraint *)(self->con->data);
+       float fmin, fmax, tmin, tmax;
+       
+       if (con->from == 2) {
+               fmin = 0.0001;
+               fmax = 1000.0;
+       }
+       else if (con->from == 1) {
+               fmin = -360.0;
+               fmax = 360.0;
+       }
+       else {
+               fmin = -1000.0;
+               fmax = 1000.0;
+       }
+       
+       if (con->to == 2) {
+               tmin = 0.0001;
+               tmax = 1000.0;
+       }
+       else if (con->to == 1) {
+               tmin = -360.0;
+               tmax = 360.0;
+       }
+       else {
+               tmin = -1000.0;
+               tmax = 1000.0;
+       }
+       
+       switch( type ) {
+       case EXPP_CONSTR_TARGET: {
+               Object *obj = (( BPy_Object * )value)->object;
+               if( !BPy_Object_Check( value ) )
+                       return EXPP_ReturnIntError( PyExc_TypeError, 
+                                       "expected BPy object argument" );
+               con->tar = obj;
+               return 0;
+               }
+       case EXPP_CONSTR_BONE: {
+               char *name = PyString_AsString( value );
+               if( !name )
+                       return EXPP_ReturnIntError( PyExc_TypeError,
+                                       "expected string arg" );
+
+               BLI_strncpy( con->subtarget, name, sizeof( con->subtarget ) );
+
+               return 0;
+               }
+       case EXPP_CONSTR_FROM:
+               return EXPP_setIValueClamped( value, &con->from, 0, 3, 'h' );
+       case EXPP_CONSTR_TO:
+               return EXPP_setIValueClamped( value, &con->to, 0, 3, 'h' );
+       case EXPP_CONSTR_MAPX:
+               return EXPP_setIValueClamped( value, &con->map[0], 0, 3, 'h' );
+       case EXPP_CONSTR_MAPY:
+               return EXPP_setIValueClamped( value, &con->map[1], 0, 3, 'h' );
+       case EXPP_CONSTR_MAPZ:
+               return EXPP_setIValueClamped( value, &con->map[2], 0, 3, 'h' );
+       case EXPP_CONSTR_FROMMINX:
+               return EXPP_setFloatClamped( value, &con->from_min[0], fmin, fmax );
+       case EXPP_CONSTR_FROMMAXX:
+               return EXPP_setFloatClamped( value, &con->from_max[0], fmin, fmax );
+       case EXPP_CONSTR_FROMMINY:
+               return EXPP_setFloatClamped( value, &con->from_min[1], fmin, fmax );
+       case EXPP_CONSTR_FROMMAXY:
+               return EXPP_setFloatClamped( value, &con->from_max[1], fmin, fmax );
+       case EXPP_CONSTR_FROMMINZ:
+               return EXPP_setFloatClamped( value, &con->from_min[2], fmin, fmax );
+       case EXPP_CONSTR_FROMMAXZ:
+               return EXPP_setFloatClamped( value, &con->from_max[2], fmin, fmax );
+       case EXPP_CONSTR_TOMINX:
+               return EXPP_setFloatClamped( value, &con->to_min[0], tmin, tmax );
+       case EXPP_CONSTR_TOMAXX:
+               return EXPP_setFloatClamped( value, &con->to_max[0], tmin, tmax );
+       case EXPP_CONSTR_TOMINY:
+               return EXPP_setFloatClamped( value, &con->to_min[1], tmin, tmax );
+       case EXPP_CONSTR_TOMAXY:
+               return EXPP_setFloatClamped( value, &con->to_max[1], tmin, tmax );
+       case EXPP_CONSTR_TOMINZ:
+               return EXPP_setFloatClamped( value, &con->to_min[2], tmin, tmax );
+       case EXPP_CONSTR_TOMAXZ:
+               return EXPP_setFloatClamped( value, &con->to_max[2], tmin, tmax );
+       case EXPP_CONSTR_EXPO:
+               return EXPP_setBitfield( value, &con->expo, 1, 'h' );
+       default:
+               return EXPP_ReturnIntError( PyExc_KeyError, "key not found" );
+       }
+}
+
 /*
  * get data from a constraint
  */
@@ -1451,6 +1611,8 @@ static PyObject *Constraint_getData( BPy_Constraint * self, PyObject * key )
                        return script_getter( self, setting );
                case CONSTRAINT_TYPE_CHILDOF:
                        return childof_getter( self, setting );
+               case CONSTRAINT_TYPE_TRANSFORM:
+                       return transf_getter( self, setting );
                default:
                        return EXPP_ReturnPyObjError( PyExc_KeyError,
                                        "unknown constraint type" );
@@ -1522,6 +1684,9 @@ static int Constraint_setData( BPy_Constraint * self, PyObject * key,
        case CONSTRAINT_TYPE_CHILDOF:
                result = childof_setter( self, key_int, arg);
                break;
+       case CONSTRAINT_TYPE_TRANSFORM:
+               result = transf_setter( self, key_int, arg);
+               break;
        case CONSTRAINT_TYPE_NULL:
                return EXPP_ReturnIntError( PyExc_KeyError, "key not found" );
        default:
@@ -1995,6 +2160,8 @@ static PyObject *M_Constraint_TypeDict( void )
                                PyInt_FromLong( CONSTRAINT_TYPE_PYTHON ) );
                PyConstant_Insert( d, "CHILDOF",
                                PyInt_FromLong( CONSTRAINT_TYPE_CHILDOF ) );
+               PyConstant_Insert( d, "TRANSFORM",
+                               PyInt_FromLong( CONSTRAINT_TYPE_TRANSFORM ) );
        }
        return S;
 }
@@ -2222,6 +2389,50 @@ static PyObject *M_Constraint_SettingsDict( void )
                PyConstant_Insert( d, "PROPERTIES",
                                PyInt_FromLong( EXPP_CONSTR_PROPS ) );
                                
+               PyConstant_Insert( d, "FROM",
+                               PyInt_FromLong( EXPP_CONSTR_FROM ) );
+               PyConstant_Insert( d, "TO",
+                               PyInt_FromLong( EXPP_CONSTR_TO ) );
+               PyConstant_Insert( d, "EXTRAPOLATE",
+                               PyInt_FromLong( EXPP_CONSTR_EXPO ) );
+               PyConstant_Insert( d, "MAPX",
+                               PyInt_FromLong( EXPP_CONSTR_MAPX ) );
+               PyConstant_Insert( d, "MAPY",
+                               PyInt_FromLong( EXPP_CONSTR_MAPY ) );
+               PyConstant_Insert( d, "MAPZ",
+                               PyInt_FromLong( EXPP_CONSTR_MAPZ ) );
+               PyConstant_Insert( d, "FROM_MINX",
+                               PyInt_FromLong( EXPP_CONSTR_FROMMINX ) );
+               PyConstant_Insert( d, "FROM_MAXX",
+                               PyInt_FromLong( EXPP_CONSTR_FROMMAXX ) );
+               PyConstant_Insert( d, "FROM_MINY",
+                               PyInt_FromLong( EXPP_CONSTR_FROMMINY ) );
+               PyConstant_Insert( d, "FROM_MAXY",
+                               PyInt_FromLong( EXPP_CONSTR_FROMMAXY ) );
+               PyConstant_Insert( d, "FROM_MINZ",
+                               PyInt_FromLong( EXPP_CONSTR_FROMMINZ ) );
+               PyConstant_Insert( d, "FROM_MAXZ",
+                               PyInt_FromLong( EXPP_CONSTR_FROMMAXZ ) );
+               PyConstant_Insert( d, "TO_MINX",
+                               PyInt_FromLong( EXPP_CONSTR_TOMINX ) );
+               PyConstant_Insert( d, "TO_MAXX",
+                               PyInt_FromLong( EXPP_CONSTR_TOMAXX ) );
+               PyConstant_Insert( d, "TO_MINY",
+                               PyInt_FromLong( EXPP_CONSTR_TOMINY ) );
+               PyConstant_Insert( d, "TO_MAXY",
+                               PyInt_FromLong( EXPP_CONSTR_TOMAXY ) );
+               PyConstant_Insert( d, "TO_MINZ",
+                               PyInt_FromLong( EXPP_CONSTR_TOMINZ ) );
+               PyConstant_Insert( d, "TO_MAXZ",
+                               PyInt_FromLong( EXPP_CONSTR_TOMAXZ ) );
+                               
+               PyConstant_Insert( d, "LOC",
+                               PyInt_FromLong( 0 ) );
+               PyConstant_Insert( d, "ROT",
+                               PyInt_FromLong( 1 ) );
+               PyConstant_Insert( d, "SCALE",
+                               PyInt_FromLong( 2 ) );
+                               
                PyConstant_Insert( d, "CONSTR_RB_TYPE",
                                PyInt_FromLong( EXPP_CONSTR_RB_TYPE ) );
                PyConstant_Insert( d, "CONSTR_RB_BALL",
index 122756a9ae25676842ac9c12b411022e8538d0ae..1d52c755d3310ef8cf058f7a84ad5576dbe21ef0 100644 (file)
@@ -32,7 +32,7 @@ Or to print all the constraints attached to each bone in a pose::
        for comparison with L{Constraint.type}.  Values are
        TRACKTO, IKSOLVER, FOLLOWPATH, COPYROT, COPYLOC, COPYSIZE, ACTION,
        LOCKTRACK, STRETCHTO, FLOOR, LIMITLOC, LIMITROT, LIMITSIZE, CLAMPTO, 
-       PYTHON, CHILDOF, NULL
+       PYTHON, CHILDOF, TRANSFORM, NULL
 
 @type Settings: readonly dictionary
 @var Settings: Constant dict used for changing constraint settings.
@@ -120,6 +120,20 @@ Or to print all the constraints attached to each bone in a pose::
        - Used by Child Of (CHILDOF) constraint:
                - COPY (bitfield): any combination of PARLOCX, PARLOCY, PARLOCZ, 
                        PARROTX, PARROTY, PARROTZ, PARSIZEX, PARSIZEY, PARSIZEZ.
+       - Used by Transformation (TRANSFORM) constraint:
+               - FROM (int): values are LOC, ROT, SCALE
+               - TO (int): values are LOC, ROT, SCALE
+               - MAPX, MAPY, MAPZ (int): values are LOC, ROT, SCALE
+               - EXTRAPOLATE (bool)
+               - FROM_MINX, FROM_MINY, FROM_MINZ, FROM_MAXX, 
+                 FROM_MAXY, FROM_MAXZ (float):
+                 If FROM==LOC, then is clamped to [-1000.0, 1000.0]
+                 If FROM==ROT, then is clamped to [-360.0, 360.0]
+                 If FROM==SCALE, then is clamped to [0.0001, 1000.0]
+               - TO_MINX, TO_MINY, TO_MINZ, TO_MAXX, TO_MAXY, TO_MAXZ (float):
+                 If TO==LOC, then is clamped to [-1000.0, 1000.0]
+                 If TO==ROT, then is clamped to [-360.0, 360.0]
+                 If TO==SCALE, then is clamped to [0.0001, 1000.0]
 
 """
 
index 0f7aee08afc4a47ac2fa1da811a3ba3bcf58b14c..d2ca53743f74e1794b35f94335eb5f77bf7e7473 100644 (file)
@@ -329,105 +329,70 @@ void get_constraint_typestring (char *str, void *con_v)
 {
        bConstraint *con= con_v;
 
-       switch (con->type){
+       switch (con->type) {
        case CONSTRAINT_TYPE_PYTHON:
                strcpy(str, "Script");
                return;
        case CONSTRAINT_TYPE_CHILDOF:
-               strcpy (str, "Child Of");
+               strcpy(str, "Child Of");
                return;
        case CONSTRAINT_TYPE_NULL:
-               strcpy (str, "Null");
+               strcpy(str, "Null");
                return;
        case CONSTRAINT_TYPE_TRACKTO:
-               strcpy (str, "Track To");
+               strcpy(str, "Track To");
                return;
        case CONSTRAINT_TYPE_MINMAX:
-               strcpy (str, "Floor");
+               strcpy(str, "Floor");
                return;
        case CONSTRAINT_TYPE_KINEMATIC:
-               strcpy (str, "IK Solver");
+               strcpy(str, "IK Solver");
                return;
        case CONSTRAINT_TYPE_ROTLIKE:
-               strcpy (str, "Copy Rotation");
+               strcpy(str, "Copy Rotation");
                return;
        case CONSTRAINT_TYPE_LOCLIKE:
-               strcpy (str, "Copy Location");
+               strcpy(str, "Copy Location");
                return;
        case CONSTRAINT_TYPE_SIZELIKE:
-               strcpy (str, "Copy Scale");
+               strcpy(str, "Copy Scale");
                return;
        case CONSTRAINT_TYPE_ACTION:
-               strcpy (str, "Action");
+               strcpy(str, "Action");
                return;
        case CONSTRAINT_TYPE_LOCKTRACK:
-               strcpy (str, "Locked Track");
+               strcpy(str, "Locked Track");
                return;
        case CONSTRAINT_TYPE_FOLLOWPATH:
-               strcpy (str, "Follow Path");
+               strcpy(str, "Follow Path");
                return;
        case CONSTRAINT_TYPE_STRETCHTO:
-               strcpy (str, "Stretch To");
+               strcpy(str, "Stretch To");
                return;
        case CONSTRAINT_TYPE_LOCLIMIT:
-               strcpy (str, "Limit Location");
+               strcpy(str, "Limit Location");
                return;
        case CONSTRAINT_TYPE_ROTLIMIT:
-               strcpy (str, "Limit Rotation");
+               strcpy(str, "Limit Rotation");
                return;
        case CONSTRAINT_TYPE_SIZELIMIT:
-               strcpy (str, "Limit Scale");
+               strcpy(str, "Limit Scale");
                return;
        case CONSTRAINT_TYPE_RIGIDBODYJOINT:
-               strcpy (str, "Rigid Body");
+               strcpy(str, "Rigid Body");
                return;
        case CONSTRAINT_TYPE_CLAMPTO:
-               strcpy (str, "Clamp To");
+               strcpy(str, "Clamp To");
                return;
+       case CONSTRAINT_TYPE_TRANSFORM:
+               strcpy(str, "Transformation");
+               break;
        default:
                strcpy (str, "Unknown");
                return;
        }
 }
 
-static int get_constraint_col(bConstraint *con)
-{
-       switch (con->type) {
-       case CONSTRAINT_TYPE_NULL:
-               return TH_BUT_NEUTRAL;
-       case CONSTRAINT_TYPE_KINEMATIC:
-               return TH_BUT_SETTING2;
-       case CONSTRAINT_TYPE_TRACKTO:
-               return TH_BUT_SETTING;
-       case CONSTRAINT_TYPE_ROTLIKE:
-               return TH_BUT_SETTING1;
-       case CONSTRAINT_TYPE_LOCLIKE:
-               return TH_BUT_POPUP;
-       case CONSTRAINT_TYPE_MINMAX:
-               return TH_BUT_POPUP;
-       case CONSTRAINT_TYPE_SIZELIKE:
-               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;
-       case CONSTRAINT_TYPE_STRETCHTO:
-               return TH_BUT_SETTING;
-       case CONSTRAINT_TYPE_LOCLIMIT:
-               return TH_BUT_POPUP;
-       case CONSTRAINT_TYPE_ROTLIMIT:
-               return TH_BUT_POPUP;
-       case CONSTRAINT_TYPE_SIZELIMIT:
-               return TH_BUT_POPUP;
-       case CONSTRAINT_TYPE_RIGIDBODYJOINT:
-               return TH_BUT_SETTING;
-       default:
-               return TH_REDALERT;
-       }
-}
-
 void const_moveUp(void *ob_v, void *con_v)
 {
        bConstraint *con, *constr= con_v;
@@ -602,7 +567,7 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
        char typestr[64], *subtarget;
        short height, width = 265;
        short is_armature_target, is_armature_owner;
-       int curCol, rb_col;
+       int rb_col;
 
        target= get_constraint_target(con, &subtarget);
        is_armature_target= (target && target->type==OB_ARMATURE);
@@ -613,8 +578,6 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
        
        get_constraint_typestring(typestr, con);
 
-       curCol = get_constraint_col(con);
-
        /* Draw constraint header */
        uiBlockSetEmboss(block, UI_EMBOSSN);
        
@@ -635,12 +598,8 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
        uiButSetFunc(but, constraint_moveDown, ob, con);
        
        if (con->flag & CONSTRAINT_EXPAND) {
-               if (con->flag & CONSTRAINT_DISABLE) {
-                       BIF_ThemeColor(TH_REDALERT);
+               if (con->flag & CONSTRAINT_DISABLE)
                        uiBlockSetCol(block, TH_REDALERT);
-               }
-               else 
-                       BIF_ThemeColor(curCol);
                
                uiBlockSetEmboss(block, UI_EMBOSS);
                
@@ -652,12 +611,8 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
        else {
                uiBlockSetEmboss(block, UI_EMBOSSN);
                
-               if (con->flag & CONSTRAINT_DISABLE) {
+               if (con->flag & CONSTRAINT_DISABLE)
                        uiBlockSetCol(block, TH_REDALERT);
-                       BIF_ThemeColor(TH_REDALERT);
-               }
-               else
-                       BIF_ThemeColor(curCol);
                
                uiDefBut(block, LABEL, B_CONSTRAINT_TEST, typestr, *xco+10, *yco, 100, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
                
@@ -1095,13 +1050,13 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
                                bLockTrackConstraint *data = con->data;
                                height = 66;
                                uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+40,height-1, NULL, 5.0, 0.0, 12, rb_col, ""); 
-
+                               
                                uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Target:", *xco+65, *yco-24, 50, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
-
+                               
                                /* Draw target parameters */
                                uiBlockBeginAlign(block);
                                uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+120, *yco-24, 135, 18, &data->tar, "Target Object"); 
-
+                               
                                if (is_armature_target) {
                                        but=uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "BO:", *xco+120, *yco-42,135,18, &data->subtarget, 0, 24, 0, 0, "Subtarget Bone");
                                        uiButSetCompleteFunc(but, autocomplete_bone, (void *)data->tar);
@@ -1135,21 +1090,21 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
                case CONSTRAINT_TYPE_FOLLOWPATH:
                        {
                                bFollowPathConstraint *data = con->data;
-
+                               
                                height = 66;
                                uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+40,height-1, NULL, 5.0, 0.0, 12, rb_col, ""); 
                                
                                uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Target:", *xco+65, *yco-24, 50, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
-
+                               
                                /* Draw target parameters */
                                uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+120, *yco-24, 135, 18, &data->tar, "Target Object"); 
                                
                                /* Draw Curve Follow toggle */
                                but=uiDefButBitI(block, TOG, 1, B_CONSTRAINT_TEST, "CurveFollow", *xco+39, *yco-44, 100, 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_TEST, "Offset:", *xco+155, *yco-44, 100, 18, &data->offset, -MAXFRAMEF, MAXFRAMEF, 100.0, 0.0, "Offset from the position corresponding to the time frame"); 
-
+                               
                                uiBlockBeginAlign(block);
                                uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Fw:", *xco+12, *yco-64, 27, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
                                
@@ -1455,11 +1410,127 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
                                uiBlockEndAlign(block);
                        }
                        break;
+               case CONSTRAINT_TYPE_TRANSFORM:
+                       {
+                               bTransformConstraint *data = con->data;
+                               float fmin, fmax, tmin, tmax;
+                               
+                               height = 178;
+                               uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+40,height-1, NULL, 5.0, 0.0, 12, rb_col, ""); 
+                               
+                               /* Draw target parameters */                    
+                               uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Target:", *xco+65, *yco-24, 50, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
+                               
+                               /* Draw target parameters */
+                               uiBlockBeginAlign(block);
+                               uiDefIDPoinBut(block, test_obpoin_but, ID_OB, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+120, *yco-24, 135, 18, &data->tar, "Target Object to use as Parent"); 
+                               
+                               if (is_armature_target) {
+                                       but= uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "BO:", *xco+120, *yco-42,135,18, &data->subtarget, 0, 24, 0, 0, "Subtarget Bone to use as Parent");
+                                       uiButSetCompleteFunc(but, autocomplete_bone, (void *)data->tar);
+                               }
+                               else {
+                                       strcpy(data->subtarget, "");
+                               }
+                               
+                               uiBlockEndAlign(block);
+                               
+                               /* Extrapolate Ranges? */
+                               uiDefButBitC(block, TOG, 1, B_CONSTRAINT_TEST, "Extrapolate", *xco, *yco-42,80,19, &data->expo, 0, 0, 0, 0, "Extrapolate ranges");
+                               
+                               /* Draw options for source motion */
+                               uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Source:", *xco-10, *yco-62, 50, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
+                               
+                               /*      draw Loc/Rot/Size toggles       */
+                               uiBlockBeginAlign(block);
+                               uiDefButS(block, ROW, B_CONSTRAINT_TEST, "Loc", *xco-5, *yco-82, 45, 18, &data->from, 12.0, 0, 0, 0, "Use Location transform channels from Target");
+                               uiDefButS(block, ROW, B_CONSTRAINT_TEST, "Rot", *xco+40, *yco-82, 45, 18, &data->from, 12.0, 1, 0, 0, "Use Rotation transform channels from Target");
+                               uiDefButS(block, ROW, B_CONSTRAINT_TEST, "Scale", *xco+85, *yco-82, 45, 18, &data->from, 12.0, 2, 0, 0, "Use Scale transform channels from Target");
+                               uiBlockEndAlign(block);
+                               
+                               /* Draw Pairs of Axis: Min/Max Value*/
+                               if (data->from == 2) {
+                                       fmin= 0.0001;
+                                       fmax= 1000.0;
+                               }
+                               else if (data->from == 1) {
+                                       fmin= -360.0;
+                                       fmax= 360.0;
+                               }
+                               else {
+                                       fmin = -1000.0;
+                                       fmax= 1000.0;
+                               }
+                               
+                               uiBlockBeginAlign(block); 
+                               uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "X:", *xco-10, *yco-107, 30, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
+                               uiDefButF(block, NUM, B_CONSTRAINT_TEST, "min", *xco+20, *yco-107, 55, 18, &data->from_min[0], fmin, fmax, 0, 0, "Bottom of range of x-axis source motion for source->target mapping"); 
+                               uiDefButF(block, NUM, B_CONSTRAINT_TEST, "max", *xco+75, *yco-107, 55, 18, &data->from_max[0], fmin, fmax, 0, 0, "Top of range of x-axis source motion for source->target mapping"); 
+                               uiBlockEndAlign(block); 
+                               
+                               uiBlockBeginAlign(block); 
+                               uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Y:", *xco-10, *yco-127, 30, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
+                               uiDefButF(block, NUM, B_CONSTRAINT_TEST, "min", *xco+20, *yco-127, 55, 18, &data->from_min[1], fmin, fmax, 0, 0, "Bottom of range of y-axis source motion for source->target mapping"); 
+                               uiDefButF(block, NUM, B_CONSTRAINT_TEST, "max", *xco+75, *yco-127, 55, 18, &data->from_max[1], fmin, fmax, 0, 0, "Top of range of y-axis source motion for source->target mapping"); 
+                               uiBlockEndAlign(block);
+                               
+                               uiBlockBeginAlign(block); 
+                               uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Z:", *xco-10, *yco-147, 30, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
+                               uiDefButF(block, NUM, B_CONSTRAINT_TEST, "min", *xco+20, *yco-147, 55, 18, &data->from_min[2], fmin, fmax, 0, 0, "Bottom of range of z-axis source motion for source->target mapping"); 
+                               uiDefButF(block, NUM, B_CONSTRAINT_TEST, "max", *xco+75, *yco-147, 55, 18, &data->from_max[2], fmin, fmax, 0, 0, "Top of range of z-axis source motion for source->target mapping"); 
+                               uiBlockEndAlign(block); 
+                               
+                               
+                               /* Draw options for target motion */
+                               uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Destination:", *xco+150, *yco-62, 150, 18, NULL, 0.0, 0.0, 0.0, 0.0, ""); 
+                               
+                               /*      draw Loc/Rot/Size toggles       */
+                               uiBlockBeginAlign(block);
+                               uiDefButS(block, ROW, B_CONSTRAINT_TEST, "Loc", *xco+150, *yco-82, 45, 18, &data->to, 12.0, 0, 0, 0, "Use as Location transform");
+                               uiDefButS(block, ROW, B_CONSTRAINT_TEST, "Rot", *xco+195, *yco-82, 45, 18, &data->to, 12.0, 1, 0, 0, "Use as Rotation transform");
+                               uiDefButS(block, ROW, B_CONSTRAINT_TEST, "Scale", *xco+245, *yco-82, 45, 18, &data->to, 12.0, 2, 0, 0, "Use as Scale transform");
+                               uiBlockEndAlign(block);
+                               
+                               /* Draw Pairs of Source-Axis: Min/Max Value*/
+                               if (data->to == 2) {
+                                       tmin= 0.0001;
+                                       tmax= 1000.0;
+                               }
+                               else if (data->to == 1) {
+                                       tmin= -360.0;
+                                       tmax= 360.0;
+                               }
+                               else {
+                                       tmin = -1000.0;
+                                       tmax= 1000.0;
+                               }
+                               
+                               uiBlockBeginAlign(block); 
+                               uiDefButC(block, MENU, B_CONSTRAINT_TEST, "Axis Mapping%t|X->X%x0|Y->X%x1|Z->X%x2", *xco+150, *yco-107, 40, 18, &data->map[0], 0, 24, 0, 0, "Specify which source axis the x-axis destination uses");
+                               uiDefButF(block, NUM, B_CONSTRAINT_TEST, "min", *xco+175, *yco-107, 50, 18, &data->to_min[0], tmin, tmax, 0, 0, "Bottom of range of x-axis destination motion for source->target mapping"); 
+                               uiDefButF(block, NUM, B_CONSTRAINT_TEST, "max", *xco+240, *yco-107, 50, 18, &data->to_max[0], tmin, tmax, 0, 0, "Top of range of x-axis destination motion for source->target mapping"); 
+                               uiBlockEndAlign(block); 
+                               
+                               uiBlockBeginAlign(block); 
+                               uiDefButC(block, MENU, B_CONSTRAINT_TEST, "Axis Mapping%t|X->Y%x0|Y->Y%x1|Z->Y%x2", *xco+150, *yco-127, 40, 18, &data->map[1], 0, 24, 0, 0, "Specify which source axis the y-axis destination uses");
+                               uiDefButF(block, NUM, B_CONSTRAINT_TEST, "min", *xco+175, *yco-127, 50, 18, &data->to_min[1], tmin, tmax, 0, 0, "Bottom of range of y-axis destination motion for source->target mapping"); 
+                               uiDefButF(block, NUM, B_CONSTRAINT_TEST, "max", *xco+240, *yco-127, 50, 18, &data->to_max[1], tmin, tmax, 0, 0, "Top of range of y-axis destination motion for source->target mapping"); 
+                               uiBlockEndAlign(block);
+                               
+                               uiBlockBeginAlign(block); 
+                               uiDefButC(block, MENU, B_CONSTRAINT_TEST, "Axis Mapping%t|X->Z%x0|Y->Z%x1|Z->Z%x2", *xco+150, *yco-147, 40, 18, &data->map[2], 0, 24, 0, 0, "Specify which source axis the z-axis destination uses");
+                               uiDefButF(block, NUM, B_CONSTRAINT_TEST, "min", *xco+175, *yco-147, 50, 18, &data->to_min[2], tmin, tmax, 0, 0, "Bottom of range of z-axis destination motion for source->target mapping"); 
+                               uiDefButF(block, NUM, B_CONSTRAINT_TEST, "max", *xco+240, *yco-147, 50, 18, &data->to_max[2], tmin, tmax, 0, 0, "Top of range of z-axis destination motion for source->target mapping"); 
+                               uiBlockEndAlign(block); 
+                               
+                               /* constraint space settings */
+                               draw_constraint_spaceselect(block, con, *xco, *yco-170, is_armature_owner, is_armature_target);
+                       }
+                       break;
                case CONSTRAINT_TYPE_NULL:
                        {
                                height = 17;
                                uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+40,height-1, NULL, 5.0, 0.0, 12, rb_col, ""); 
-                               
                        }
                        break;
                default:
@@ -1499,6 +1570,7 @@ static uiBlock *add_constraintmenu(void *arg_unused)
        block= uiNewBlock(&curarea->uiblocks, "add_constraintmenu", UI_EMBOSSP, UI_HELV, curarea->win);
 
        uiDefBut(block, BUTM, B_CONSTRAINT_ADD_CHILDOF, "Child Of",                     0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
+       uiDefBut(block, BUTM, B_CONSTRAINT_ADD_TRANSFORM, "Transformation", 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, "");
        
@@ -1518,10 +1590,10 @@ static uiBlock *add_constraintmenu(void *arg_unused)
        uiDefBut(block, BUTM, B_CONSTRAINT_ADD_MINMAX, "Floor", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
        uiDefBut(block, BUTM, B_CONSTRAINT_ADD_LOCKTRACK, "Locked Track", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
        uiDefBut(block, BUTM, B_CONSTRAINT_ADD_FOLLOWPATH, "Follow Path", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
-       uiDefBut(block, BUTM, B_CONSTRAINT_ADD_CLAMPTO, "Clamp To", 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, "");
        
+       uiDefBut(block, BUTM, B_CONSTRAINT_ADD_CLAMPTO, "Clamp To", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
        uiDefBut(block, BUTM, B_CONSTRAINT_ADD_STRETCHTO, "Stretch To", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
 
        uiDefBut(block, BUTM, B_CONSTRAINT_ADD_RIGIDBODYJOINT, "Rigid Body Joint", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");//rcruiz
@@ -1735,6 +1807,14 @@ void do_constraintbuts(unsigned short event)
                        BIF_undo_push("Add constraint");
                }
                break;
+       case B_CONSTRAINT_ADD_TRANSFORM:
+               {
+                       con = add_new_constraint(CONSTRAINT_TYPE_TRANSFORM);
+                       add_constraint_to_active(ob, con);
+                       
+                       BIF_undo_push("Add constraint");
+               }
+               break;
 
        default:
                break;
index db1ee37405f35cb4cadf7cccff2ada7d890148b4..4ef1b4e961a1af715b5dc1eba3e0189c31e37802 100644 (file)
@@ -583,6 +583,24 @@ static void test_constraints (Object *owner, const char* substring)
                                        }                                       
                                }
                                        break;
+                               case CONSTRAINT_TYPE_TRANSFORM:
+                               {
+                                       bTransformConstraint *data = curcon->data;
+                                       
+                                       if (!exist_object(data->tar)){
+                                               data->tar = NULL;
+                                               curcon->flag |= CONSTRAINT_DISABLE;
+                                               break;
+                                       }
+                                       
+                                       if ( (data->tar == owner) &&
+                                                (!get_named_bone(get_armature(owner), 
+                                                                                 data->subtarget))) {
+                                               curcon->flag |= CONSTRAINT_DISABLE;
+                                               break;
+                                       }
+                               }
+                                       break;
                        }
                }
        }
@@ -671,21 +689,21 @@ void add_constraint(int only_IK)
        else {
                if(pchanact) {
                        if(pchansel)
-                               nr= pupmenu("Add Constraint to Active Bone%t|Child Of%x19|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|%l|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7|%l|Action%x16|Script%x18");
+                               nr= pupmenu("Add Constraint to Active Bone%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|%l|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7|%l|Action%x16|Script%x18");
                        else if(obsel && obsel->type==OB_CURVE)
-                               nr= pupmenu("Add Constraint to Active Object%t|Child Of%x19|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|%l|Track To%x3|Floor%x4|Locked Track%x5|Follow Path%x6|Clamp To%x17|Stretch To%x7|%l|Action%x16|Script%x18");
+                               nr= pupmenu("Add Constraint to Active Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|%l|Track To%x3|Floor%x4|Locked Track%x5|Follow Path%x6|Clamp To%x17|Stretch To%x7|%l|Action%x16|Script%x18");
                        else if(obsel)
-                               nr= pupmenu("Add Constraint to Active Object%t|Child Of%x19|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|%l|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7|%l|Action%x16|Script%x18");
+                               nr= pupmenu("Add Constraint to Active Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|%l|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7|%l|Action%x16|Script%x18");
                        else
-                               nr= pupmenu("Add Constraint to New Empty Object%t|Child Of%x19|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|%l|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7|%l|Script%x18");
+                               nr= pupmenu("Add Constraint to New Empty Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|%l|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7|%l|Script%x18");
                }
                else {
                        if(obsel && obsel->type==OB_CURVE)
-                               nr= pupmenu("Add Constraint to Active Object%t|Child Of%x19|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|%l|Track To%x3|Floor%x4|Locked Track%x5|Follow Path%x6|Clamp To%x17|%l|Script%x18");
+                               nr= pupmenu("Add Constraint to Active Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|%l|Track To%x3|Floor%x4|Locked Track%x5|Follow Path%x6|Clamp To%x17|%l|Script%x18");
                        else if(obsel)
-                               nr= pupmenu("Add Constraint to Active Object%t|Child Of%x19|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|%l|Track To%x3|Floor%x4|Locked Track%x5|%l|Script%x18");
+                               nr= pupmenu("Add Constraint to Active Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|%l|Track To%x3|Floor%x4|Locked Track%x5|%l|Script%x18");
                        else
-                               nr= pupmenu("Add Constraint to New Empty Object%t|Child Of%x19|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|%l|Track To%x3|Floor%x4|Locked Track%x5|%l|Script%x18");
+                               nr= pupmenu("Add Constraint to New Empty Object%t|Child Of%x19|Transformation%x20|%l|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|%l|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|%l|Track To%x3|Floor%x4|Locked Track%x5|%l|Script%x18");
                }
        }
        
@@ -773,7 +791,7 @@ void add_constraint(int only_IK)
                        }
                }
                else if (nr==19) {
-                       con= add_new_constraint(CONSTRAINT_TYPE_CHILDOF);
+                       con = add_new_constraint(CONSTRAINT_TYPE_CHILDOF);
                        
                        /* if this constraint is being added to a posechannel, make sure
                         * the constraint gets evaluated in pose-space
@@ -783,6 +801,7 @@ void add_constraint(int only_IK)
                                con->flag |= CONSTRAINT_SPACEONCE;
                        }
                }
+               else if (nr==20) con = add_new_constraint(CONSTRAINT_TYPE_TRANSFORM);
                
                if (con==NULL) return;  /* paranoia */