Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorMartin Poirier <theeth@yahoo.com>2006-08-13 18:18:15 +0400
committerMartin Poirier <theeth@yahoo.com>2006-08-13 18:18:15 +0400
commite341a4e1f45d8d3ba47dadc6ee72e94897369098 (patch)
treec856a30e057d743f82e751fe07376335b91392b6 /source
parentcf1964cf9cea690d3800d9852567f01653b7b207 (diff)
Patch: Constraints to Limit Transforms (#4662) by Joshua Leung (aligorith)
This adds three new constraints to limit the range of location, rotation and scaling values.
Diffstat (limited to 'source')
-rw-r--r--source/blender/blenkernel/intern/armature.c78
-rw-r--r--source/blender/blenkernel/intern/constraint.c286
-rw-r--r--source/blender/blenloader/intern/readfile.c33
-rw-r--r--source/blender/blenloader/intern/writefile.c9
-rw-r--r--source/blender/include/butspace.h3
-rw-r--r--source/blender/makesdna/DNA_constraint_types.h44
-rw-r--r--source/blender/python/api2_2x/Constraint.c251
-rw-r--r--source/blender/python/api2_2x/doc/Constraint.py42
-rw-r--r--source/blender/src/buttons_object.c183
-rw-r--r--source/blender/src/editconstraint.c17
10 files changed, 926 insertions, 20 deletions
diff --git a/source/blender/blenkernel/intern/armature.c b/source/blender/blenkernel/intern/armature.c
index 992c5a44548..b0341e6ddcc 100644
--- a/source/blender/blenkernel/intern/armature.c
+++ b/source/blender/blenkernel/intern/armature.c
@@ -1464,6 +1464,84 @@ static void do_local_constraint(bPoseChannel *pchan, bConstraint *con)
}
}
}
+ break;
+ case CONSTRAINT_TYPE_LOCLIMIT:
+ {
+ bLocLimitConstraint *data= con->data;
+
+ /* Aligorith: don't know whether this function really evaluates constraints, but here goes anyways */
+ if (data->flag & LIMIT_XMIN) {
+ if(pchan->loc[0] < data->xmin)
+ pchan->loc[0] = data->xmin;
+ }
+ if (data->flag & LIMIT_XMAX) {
+ if (pchan->loc[0] > data->xmax)
+ pchan->loc[0] = data->xmax;
+ }
+ if (data->flag & LIMIT_YMIN) {
+ if(pchan->loc[1] < data->ymin)
+ pchan->loc[1] = data->ymin;
+ }
+ if (data->flag & LIMIT_YMAX) {
+ if (pchan->loc[1] > data->ymax)
+ pchan->loc[1] = data->ymax;
+ }
+ if (data->flag & LIMIT_ZMIN) {
+ if(pchan->loc[2] < data->zmin)
+ pchan->loc[2] = data->zmin;
+ }
+ if (data->flag & LIMIT_ZMAX) {
+ if (pchan->loc[2] > data->zmax)
+ pchan->loc[2] = data->zmax;
+ }
+ }
+ break;
+ case CONSTRAINT_TYPE_ROTLIMIT:
+ {
+ bRotLimitConstraint *data = con->data;
+ float eul[3];
+
+ /*Aligorith: don't know whether this function is really for evaluating constraints, but here goes anyways */
+
+ QuatToEul(pchan->quat, eul);
+
+ /* eulers: radians to degrees! */
+ eul[0] = (eul[0] / (2*M_PI) * 360);
+ eul[1] = (eul[1] / (2*M_PI) * 360);
+ eul[2] = (eul[2] / (2*M_PI) * 360);
+
+ /* limiting of euler values... */
+ if (data->flag & LIMIT_XROT) {
+ if (eul[0] < data->xmin)
+ eul[0] = data->xmin;
+
+ if (eul[0] > data->xmax)
+ eul[0] = data->xmax;
+ }
+ if (data->flag & LIMIT_YROT) {
+ if (eul[1] < data->ymin)
+ eul[1] = data->ymin;
+
+ if (eul[1] > data->ymax)
+ eul[1] = data->ymax;
+ }
+ if (data->flag & LIMIT_ZROT) {
+ if (eul[2] < data->zmin)
+ eul[2] = data->zmin;
+
+ if (eul[2] > data->zmax)
+ eul[2] = data->zmax;
+ }
+
+ /* eulers: degrees to radians ! */
+ eul[0] = (eul[0] / 360 * (2*M_PI));
+ eul[1] = (eul[1] / 360 * (2*M_PI));
+ eul[2] = (eul[2] / 360 * (2*M_PI));
+
+ /* convert back */
+ EulToQuat(eul, pchan->quat);
+ }
+ break;
}
}
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index 381e6e004f9..1eb4856ca11 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -205,7 +205,24 @@ void relink_constraints (struct ListBase *list)
ID_NEW(data->tar);
}
break;
-
+ case CONSTRAINT_TYPE_LOCLIMIT:
+ {
+ bLocLimitConstraint *data;
+ data = con->data;
+ }
+ break;
+ case CONSTRAINT_TYPE_ROTLIMIT:
+ {
+ bRotLimitConstraint *data;
+ data = con->data;
+ }
+ break;
+ case CONSTRAINT_TYPE_SIZELIMIT:
+ {
+ bSizeLimitConstraint *data;
+ data = con->data;
+ }
+ break;
}
}
}
@@ -658,6 +675,55 @@ void *new_constraint_data (short type)
result = data;
}
break;
+ case CONSTRAINT_TYPE_LOCLIMIT:
+ {
+ bLocLimitConstraint *data;
+ data = MEM_callocN(sizeof(bLocLimitConstraint), "LocLimitConstraint");
+
+ data->flag = 0;
+ data->flag2 = 0;
+ data->xmin = 0.0f;
+ data->xmax = 0.0f;
+ data->ymin = 0.0f;
+ data->ymax = 0.0f;
+ data->zmin = 0.0f;
+ data->zmax = 0.0f;
+
+ result = data;
+ }
+ break;
+ case CONSTRAINT_TYPE_ROTLIMIT:
+ {
+ bRotLimitConstraint *data;
+ data = MEM_callocN(sizeof(bRotLimitConstraint), "RotLimitConstraint");
+
+ data->flag = 0;
+ data->xmin = 0.0f;
+ data->xmax = 0.0f;
+ data->ymin = 0.0f;
+ data->ymax = 0.0f;
+ data->zmin = 0.0f;
+ data->zmax = 0.0f;
+
+ result = data;
+ }
+ break;
+ case CONSTRAINT_TYPE_SIZELIMIT:
+ {
+ bSizeLimitConstraint *data;
+ data = MEM_callocN(sizeof(bSizeLimitConstraint), "SizeLimitConstraint");
+
+ data->flag = 0;
+ data->xmin = 0.0f;
+ data->xmax = 0.0f;
+ data->ymin = 0.0f;
+ data->ymax = 0.0f;
+ data->zmin = 0.0f;
+ data->zmax = 0.0f;
+
+ result = data;
+ }
+ break;
default:
result = NULL;
break;
@@ -1739,7 +1805,223 @@ void evaluate_constraint (bConstraint *constraint, Object *ob, short ownertype,
}
}
break;
-
+ case CONSTRAINT_TYPE_LOCLIMIT:
+ {
+ bLocLimitConstraint *data;
+
+ data = constraint->data;
+
+ /* limit location relative to origin or parent */
+ if (data->flag2 & LIMIT_NOPARENT) {
+ /* limiting relative to parent */
+ float parmat[4][4]; /* matrix of parent */
+ float objLoc[3], parLoc[3]; /* location of object, and location of parent */
+ float relLoc[3]; /* objLoc - parLoc*/
+
+ /* get matrix of parent */
+ Mat4CpyMat4(parmat, ob->parent->obmat);
+
+ /* get locations as vectors */
+ objLoc[0] = ob->obmat[3][0];
+ objLoc[1] = ob->obmat[3][1];
+ objLoc[2] = ob->obmat[3][2];
+
+ parLoc[0] = parmat[3][0];
+ parLoc[1] = parmat[3][1];
+ parLoc[2] = parmat[3][2];
+
+ /* get relative location of obj from parent */
+ VecSubf(relLoc, objLoc, parLoc);
+
+ /* limiting location */
+ if (data->flag & LIMIT_XMIN) {
+ if(relLoc[0] < data->xmin)
+ ob->obmat[3][0] = (parLoc[0]+data->xmin);
+ }
+ if (data->flag & LIMIT_XMAX) {
+ if (relLoc[0] > data->xmax)
+ ob->obmat[3][0] = (parLoc[0]+data->xmax);
+ }
+ if (data->flag & LIMIT_YMIN) {
+ if(relLoc[1] < data->ymin)
+ ob->obmat[3][1] = (parLoc[1]+data->ymin);
+ }
+ if (data->flag & LIMIT_YMAX) {
+ if (relLoc[1] > data->ymax)
+ ob->obmat[3][1] = (parLoc[1]+data->ymax);
+ }
+ if (data->flag & LIMIT_ZMIN) {
+ if(relLoc[2] < data->zmin)
+ ob->obmat[3][2] = (parLoc[2]+data->zmin);
+ }
+ if (data->flag & LIMIT_ZMAX) {
+ if (relLoc[2] > data->zmax)
+ ob->obmat[3][2] = (parLoc[2]+data->zmax);
+ }
+ } else {
+ /* limiting relative to origin */
+ if (data->flag & LIMIT_XMIN) {
+ if(ob->obmat[3][0] < data->xmin)
+ ob->obmat[3][0] = data->xmin;
+ }
+ if (data->flag & LIMIT_XMAX) {
+ if (ob->obmat[3][0] > data->xmax)
+ ob->obmat[3][0] = data->xmax;
+ }
+ if (data->flag & LIMIT_YMIN) {
+ if(ob->obmat[3][1] < data->ymin)
+ ob->obmat[3][1] = data->ymin;
+ }
+ if (data->flag & LIMIT_YMAX) {
+ if (ob->obmat[3][1] > data->ymax)
+ ob->obmat[3][1] = data->ymax;
+ }
+ if (data->flag & LIMIT_ZMIN) {
+ if(ob->obmat[3][2] < data->zmin)
+ ob->obmat[3][2] = data->zmin;
+ }
+ if (data->flag & LIMIT_ZMAX) {
+ if (ob->obmat[3][2] > data->zmax)
+ ob->obmat[3][2] = data->zmax;
+ }
+ }
+ }
+ break;
+ case CONSTRAINT_TYPE_ROTLIMIT:
+ {
+ bRotLimitConstraint *data;
+ float tmat[3][3];
+ float eul[3];
+ float size[3];
+
+ data = constraint->data;
+
+ Mat4ToSize(ob->obmat, size);
+
+ Mat3CpyMat4(tmat, ob->obmat);
+ Mat3Ortho(tmat);
+ Mat3ToEul(tmat, eul);
+
+ /* eulers: radians to degrees! */
+ eul[0] = (eul[0] / M_PI * 180);
+ eul[1] = (eul[1] / M_PI * 180);
+ eul[2] = (eul[2] / M_PI * 180);
+
+ /* limiting of euler values... */
+ if (data->flag & LIMIT_XROT) {
+ if (eul[0] < data->xmin)
+ eul[0] = data->xmin;
+
+ if (eul[0] > data->xmax)
+ eul[0] = data->xmax;
+ }
+ if (data->flag & LIMIT_YROT) {
+ if (eul[1] < data->ymin)
+ eul[1] = data->ymin;
+
+ if (eul[1] > data->ymax)
+ eul[1] = data->ymax;
+ }
+ if (data->flag & LIMIT_ZROT) {
+ if (eul[2] < data->zmin)
+ eul[2] = data->zmin;
+
+ if (eul[2] > data->zmax)
+ eul[2] = data->zmax;
+ }
+
+ /* eulers: degrees to radians ! */
+ eul[0] = (eul[0] / 180 * M_PI);
+ eul[1] = (eul[1] / 180 * M_PI);
+ eul[2] = (eul[2] / 180 * M_PI);
+
+ EulToMat3(eul, tmat);
+
+ ob->obmat[0][0] = tmat[0][0]*size[0];
+ ob->obmat[0][1] = tmat[0][1]*size[1];
+ ob->obmat[0][2] = tmat[0][2]*size[2];
+
+ ob->obmat[1][0] = tmat[1][0]*size[0];
+ ob->obmat[1][1] = tmat[1][1]*size[1];
+ ob->obmat[1][2] = tmat[1][2]*size[2];
+
+ ob->obmat[2][0] = tmat[2][0]*size[0];
+ ob->obmat[2][1] = tmat[2][1]*size[1];
+ ob->obmat[2][2] = tmat[2][2]*size[2];
+ }
+ break;
+ case CONSTRAINT_TYPE_SIZELIMIT:
+ {
+ bSizeLimitConstraint *data;
+ float obsize[3], size[3];
+ int clearNegScale=0;
+
+ data = constraint->data;
+
+ Mat4ToSize(ob->obmat, size);
+ Mat4ToSize(ob->obmat, obsize);
+
+ if (data->flag & LIMIT_XMIN) {
+ if (ob->transflag & OB_NEG_SCALE) {
+ size[0] *= -1;
+
+ if (size[0] < data->xmin) {
+ size[0] = data->xmin;
+ clearNegScale += 1;
+ }
+ } else {
+ if (size[0] < data->xmin)
+ size[0] = data->xmin;
+ }
+ }
+ if (data->flag & LIMIT_XMAX) {
+ if (size[0] > data->xmax)
+ size[0] = data->xmax;
+ }
+ if (data->flag & LIMIT_YMIN) {
+ if (ob->transflag & OB_NEG_SCALE) {
+ size[1] *= -1;
+
+ if (size[1] < data->ymin) {
+ size[1] = data->ymin;
+ clearNegScale += 1;
+ }
+ } else {
+ if (size[1] < data->ymin)
+ size[1] = data->ymin;
+ }
+ }
+ if (data->flag & LIMIT_YMAX) {
+ if (size[1] > data->ymax)
+ size[1] = data->ymax;
+ }
+ if (data->flag & LIMIT_ZMIN) {
+ if (ob->transflag & OB_NEG_SCALE) {
+ size[2] *= -1;
+
+ if (size[2] < data->zmin) {
+ size[2] = data->zmin;
+ clearNegScale += 1;
+ }
+ } else {
+ if (size[2] < data->zmin)
+ size[2] = data->zmin;
+ }
+ }
+ if (data->flag & LIMIT_ZMAX) {
+ if (size[2] > data->zmax)
+ size[2] = data->zmax;
+ }
+
+ if (clearNegScale != 0) {
+ ob->transflag &= ~OB_NEG_SCALE; /* is this how we remove that flag? */
+ }
+
+ VecMulf(ob->obmat[0], size[0]/obsize[0]);
+ VecMulf(ob->obmat[1], size[1]/obsize[1]);
+ VecMulf(ob->obmat[2], size[2]/obsize[2]);
+ }
+ break;
default:
printf ("Error: Unknown constraint type\n");
break;
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index dbf06794e30..87125c2130f 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -1497,6 +1497,24 @@ static void lib_link_constraints(FileData *fd, ID *id, ListBase *conlist)
data->tar = newlibadr(fd, id->lib, data->tar);
};
break;
+ case CONSTRAINT_TYPE_LOCLIMIT:
+ {
+ bLocLimitConstraint *data;
+ data= ((bLocLimitConstraint*)con->data);
+ };
+ break;
+ case CONSTRAINT_TYPE_ROTLIMIT:
+ {
+ bRotLimitConstraint *data;
+ data= ((bRotLimitConstraint*)con->data);
+ };
+ break;
+ case CONSTRAINT_TYPE_SIZELIMIT:
+ {
+ bSizeLimitConstraint *data;
+ data= ((bSizeLimitConstraint*)con->data);
+ };
+ break;
case CONSTRAINT_TYPE_NULL:
break;
@@ -6011,6 +6029,21 @@ static void expand_constraints(FileData *fd, Main *mainvar, ListBase *lb)
expand_doit(fd, mainvar, data->tar);
break;
}
+ case CONSTRAINT_TYPE_LOCLIMIT:
+ {
+ bLocLimitConstraint *data = (bLocLimitConstraint*)curcon->data;
+ break;
+ }
+ case CONSTRAINT_TYPE_ROTLIMIT:
+ {
+ bRotLimitConstraint *data = (bRotLimitConstraint*)curcon->data;
+ break;
+ }
+ case CONSTRAINT_TYPE_SIZELIMIT:
+ {
+ bSizeLimitConstraint *data = (bSizeLimitConstraint*)curcon->data;
+ break;
+ }
case CONSTRAINT_TYPE_NULL:
break;
default:
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index 7c0e81169f7..557c553d0fd 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -666,6 +666,15 @@ static void write_constraints(WriteData *wd, ListBase *conlist)
case CONSTRAINT_TYPE_MINMAX:
writestruct(wd, DATA, "bMinMaxConstraint", 1, con->data);
break;
+ case CONSTRAINT_TYPE_LOCLIMIT:
+ writestruct(wd, DATA, "bLocLimitConstraint", 1, con->data);
+ break;
+ case CONSTRAINT_TYPE_ROTLIMIT:
+ writestruct(wd, DATA, "bRotLimitConstraint", 1, con->data);
+ break;
+ case CONSTRAINT_TYPE_SIZELIMIT:
+ writestruct(wd, DATA, "bSizeLimitConstraint", 1, con->data);
+ break;
default:
break;
}
diff --git a/source/blender/include/butspace.h b/source/blender/include/butspace.h
index 9938274dd5a..63a5face413 100644
--- a/source/blender/include/butspace.h
+++ b/source/blender/include/butspace.h
@@ -618,6 +618,9 @@ enum {
B_CONSTRAINT_ADD_FOLLOWPATH,
B_CONSTRAINT_ADD_DISTANCELIMIT,
B_CONSTRAINT_ADD_STRETCHTO,
+ B_CONSTRAINT_ADD_LOCLIMIT,
+ B_CONSTRAINT_ADD_ROTLIMIT,
+ B_CONSTRAINT_ADD_SIZELIMIT,
B_CONSTRAINT_INF
};
diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h
index 21380bdcdab..ce351baa4f3 100644
--- a/source/blender/makesdna/DNA_constraint_types.h
+++ b/source/blender/makesdna/DNA_constraint_types.h
@@ -170,6 +170,30 @@ typedef struct bStretchToConstraint{
char subtarget[32];
} bStretchToConstraint;
+/* transform limiting constraints - zero target */
+typedef struct bLocLimitConstraint{
+ float xmin, xmax;
+ float ymin, ymax;
+ float zmin, zmax;
+ short flag;
+ short flag2;
+} bLocLimitConstraint;
+
+typedef struct bRotLimitConstraint{
+ float xmin, xmax;
+ float ymin, ymax;
+ float zmin, zmax;
+ short flag;
+ short pad1;
+} bRotLimitConstraint;
+
+typedef struct bSizeLimitConstraint{
+ float xmin, xmax;
+ float ymin, ymax;
+ float zmin, zmax;
+ short flag;
+ short pad1;
+} bSizeLimitConstraint;
/* bConstraint.type */
#define CONSTRAINT_TYPE_NULL 0
@@ -177,9 +201,9 @@ typedef struct bStretchToConstraint{
#define CONSTRAINT_TYPE_TRACKTO 2
#define CONSTRAINT_TYPE_KINEMATIC 3
#define CONSTRAINT_TYPE_FOLLOWPATH 4
-#define CONSTRAINT_TYPE_ROTLIMIT 5 /* Unimplemented */
-#define CONSTRAINT_TYPE_LOCLIMIT 6 /* Unimplemented */
-#define CONSTRAINT_TYPE_SIZELIMIT 7 /* Unimplemented */
+#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
@@ -254,5 +278,19 @@ typedef struct bStretchToConstraint{
#define CONSTRAINT_IK_AUTO 4
#define CONSTRAINT_IK_TEMP 8
+/* transform limiting constraints -> flag */
+#define LIMIT_XMIN 0x01
+#define LIMIT_XMAX 0x02
+#define LIMIT_YMIN 0x04
+#define LIMIT_YMAX 0x08
+#define LIMIT_ZMIN 0x10
+#define LIMIT_ZMAX 0x20
+
+#define LIMIT_XROT 0x01
+#define LIMIT_YROT 0x02
+#define LIMIT_ZROT 0x04
+
+#define LIMIT_NOPARENT 0x01
+
#endif
diff --git a/source/blender/python/api2_2x/Constraint.c b/source/blender/python/api2_2x/Constraint.c
index 1e16e360292..0b5cbd93cd5 100644
--- a/source/blender/python/api2_2x/Constraint.c
+++ b/source/blender/python/api2_2x/Constraint.c
@@ -102,6 +102,28 @@ enum constraint_constants {
EXPP_CONSTR_STICKY,
EXPP_CONSTR_COPY,
+ EXPP_CONSTR_LIMIT,
+
+ EXPP_CONSTR_LIMXMIN = LIMIT_XMIN,
+ EXPP_CONSTR_LIMXMAX = LIMIT_XMAX,
+ EXPP_CONSTR_LIMYMIN = LIMIT_YMIN,
+ EXPP_CONSTR_LIMYMAX = LIMIT_YMAX,
+ EXPP_CONSTR_LIMZMIN = LIMIT_ZMIN,
+ EXPP_CONSTR_LIMZMAX = LIMIT_ZMAX,
+
+ EXPP_CONSTR_LIMXROT = LIMIT_XROT,
+ EXPP_CONSTR_LIMYROT = LIMIT_YROT,
+ EXPP_CONSTR_LIMZROT = LIMIT_ZROT,
+
+ EXPP_CONSTR_XMIN,
+ EXPP_CONSTR_XMAX,
+ EXPP_CONSTR_YMIN,
+ EXPP_CONSTR_YMAX,
+ EXPP_CONSTR_ZMIN,
+ EXPP_CONSTR_ZMAX,
+
+ EXPP_CONSTR_LIMLOCALBONE,
+ EXPP_CONSTR_LIMLOCALNOPAR,
};
/*****************************************************************************/
@@ -959,6 +981,171 @@ static int sizelike_setter( BPy_Constraint *self, int type, PyObject *value )
}
}
+static PyObject *loclimit_getter( BPy_Constraint * self, int type)
+{
+ bLocLimitConstraint *con = (bLocLimitConstraint *)(self->con->data);
+
+ switch( type ) {
+ case EXPP_CONSTR_LIMIT:
+ return PyInt_FromLong( (long)con->flag );
+ case EXPP_CONSTR_LIMLOCALBONE:
+ return PyBool_FromLong( (long)
+ ( self->con->flag & CONSTRAINT_LOCAL ) ) ;
+ case EXPP_CONSTR_LIMLOCALNOPAR:
+ return PyBool_FromLong( (long)
+ ( con->flag2 & LIMIT_NOPARENT ) ) ;
+ case EXPP_CONSTR_XMIN:
+ return PyFloat_FromDouble( (double)con->xmin );
+ case EXPP_CONSTR_XMAX:
+ return PyFloat_FromDouble( (double)con->xmax );
+ case EXPP_CONSTR_YMIN:
+ return PyFloat_FromDouble( (double)con->ymin );
+ case EXPP_CONSTR_YMAX:
+ return PyFloat_FromDouble( (double)con->ymax );
+ case EXPP_CONSTR_ZMIN:
+ return PyFloat_FromDouble( (double)con->zmin );
+ case EXPP_CONSTR_ZMAX:
+ return PyFloat_FromDouble( (double)con->zmax );
+ default:
+ return EXPP_ReturnPyObjError( PyExc_KeyError, "key not found" );
+ }
+}
+
+static int loclimit_setter( BPy_Constraint *self, int type, PyObject *value )
+{
+ bLocLimitConstraint *con = (bLocLimitConstraint *)(self->con->data);
+
+ switch( type ) {
+ case EXPP_CONSTR_LIMIT:
+ return EXPP_setIValueRange( value, &con->flag, 0,
+ LIMIT_XMIN | LIMIT_XMAX | LIMIT_YMIN | LIMIT_YMAX | LIMIT_ZMIN | LIMIT_ZMAX , 'i' );
+ case EXPP_CONSTR_LIMLOCALBONE:
+ return EXPP_setBitfield( value, &self->con->flag,
+ CONSTRAINT_LOCAL, 'h' );
+ case EXPP_CONSTR_LIMLOCALNOPAR:
+ return EXPP_setBitfield( value, &con->flag2,
+ LIMIT_NOPARENT, 'h' );
+ case EXPP_CONSTR_XMIN:
+ return EXPP_setFloatClamped( value, &con->xmin, -1000.0, 1000.0 );
+ case EXPP_CONSTR_XMAX:
+ return EXPP_setFloatClamped( value, &con->xmax, -1000.0, 1000.0 );
+ case EXPP_CONSTR_YMIN:
+ return EXPP_setFloatClamped( value, &con->ymin, -1000.0, 1000.0 );
+ case EXPP_CONSTR_YMAX:
+ return EXPP_setFloatClamped( value, &con->ymax, -1000.0, 1000.0 );
+ case EXPP_CONSTR_ZMIN:
+ return EXPP_setFloatClamped( value, &con->zmin, -1000.0, 1000.0 );
+ case EXPP_CONSTR_ZMAX:
+ return EXPP_setFloatClamped( value, &con->zmax, -1000.0, 1000.0 );
+ default:
+ return EXPP_ReturnIntError( PyExc_KeyError, "key not found" );
+ }
+}
+
+static PyObject *rotlimit_getter( BPy_Constraint * self, int type )
+{
+ bRotLimitConstraint *con = (bRotLimitConstraint *)(self->con->data);
+
+ switch( type ) {
+ case EXPP_CONSTR_LIMIT:
+ return PyInt_FromLong( (long)con->flag );
+ case EXPP_CONSTR_LIMLOCALBONE:
+ return PyBool_FromLong( (long)
+ (self->con->flag & CONSTRAINT_LOCAL ) );
+ case EXPP_CONSTR_XMIN:
+ return PyFloat_FromDouble( (double)con->xmin );
+ case EXPP_CONSTR_XMAX:
+ return PyFloat_FromDouble( (double)con->xmax );
+ case EXPP_CONSTR_YMIN:
+ return PyFloat_FromDouble( (double)con->ymin );
+ case EXPP_CONSTR_YMAX:
+ return PyFloat_FromDouble( (double)con->ymax );
+ case EXPP_CONSTR_ZMIN:
+ return PyFloat_FromDouble( (double)con->zmin );
+ case EXPP_CONSTR_ZMAX:
+ return PyFloat_FromDouble( (double)con->zmax );
+ default:
+ return EXPP_ReturnPyObjError( PyExc_KeyError, "key not found" );
+ }
+}
+
+static int rotlimit_setter( BPy_Constraint *self, int type, PyObject *value )
+{
+ bRotLimitConstraint *con = (bRotLimitConstraint *)(self->con->data);
+
+ switch( type ) {
+ case EXPP_CONSTR_LIMIT:
+ return EXPP_setIValueRange( value, &con->flag, 0,
+ LIMIT_XROT | LIMIT_YROT | LIMIT_ZROT, 'i' );
+ case EXPP_CONSTR_LIMLOCALBONE:
+ return EXPP_setBitfield( value, &self->con->flag,
+ CONSTRAINT_LOCAL, 'h' );
+ case EXPP_CONSTR_XMIN:
+ return EXPP_setFloatClamped( value, &con->xmin, -360.0, 360.0 );
+ case EXPP_CONSTR_XMAX:
+ return EXPP_setFloatClamped( value, &con->xmax, -360.0, 360.0 );
+ case EXPP_CONSTR_YMIN:
+ return EXPP_setFloatClamped( value, &con->ymin, -360.0, 360.0 );
+ case EXPP_CONSTR_YMAX:
+ return EXPP_setFloatClamped( value, &con->ymax, -360.0, 360.0 );
+ case EXPP_CONSTR_ZMIN:
+ return EXPP_setFloatClamped( value, &con->zmin, -360.0, 360.0 );
+ case EXPP_CONSTR_ZMAX:
+ return EXPP_setFloatClamped( value, &con->zmax, -360.0, 360.0 );
+ default:
+ return EXPP_ReturnIntError( PyExc_KeyError, "key not found" );
+ }
+}
+
+static PyObject *sizelimit_getter( BPy_Constraint * self, int type)
+{
+ bSizeLimitConstraint *con = (bSizeLimitConstraint *)(self->con->data);
+
+ switch( type ) {
+ case EXPP_CONSTR_LIMIT:
+ return PyInt_FromLong( (long)con->flag );
+ case EXPP_CONSTR_XMIN:
+ return PyFloat_FromDouble( (double)con->xmin );
+ case EXPP_CONSTR_XMAX:
+ return PyFloat_FromDouble( (double)con->xmax );
+ case EXPP_CONSTR_YMIN:
+ return PyFloat_FromDouble( (double)con->ymin );
+ case EXPP_CONSTR_YMAX:
+ return PyFloat_FromDouble( (double)con->ymax );
+ case EXPP_CONSTR_ZMIN:
+ return PyFloat_FromDouble( (double)con->zmin );
+ case EXPP_CONSTR_ZMAX:
+ return PyFloat_FromDouble( (double)con->zmax );
+ default:
+ return EXPP_ReturnPyObjError( PyExc_KeyError, "key not found" );
+ }
+}
+
+static int sizelimit_setter( BPy_Constraint *self, int type, PyObject *value )
+{
+ bSizeLimitConstraint *con = (bSizeLimitConstraint *)(self->con->data);
+
+ switch( type ) {
+ case EXPP_CONSTR_LIMIT:
+ return EXPP_setIValueRange( value, &con->flag, 0,
+ LIMIT_XMIN | LIMIT_XMAX | LIMIT_YMIN | LIMIT_YMAX | LIMIT_ZMIN | LIMIT_ZMAX, 'i' );
+ case EXPP_CONSTR_XMIN:
+ return EXPP_setFloatClamped( value, &con->xmin, -1000.0, 1000.0 );
+ case EXPP_CONSTR_XMAX:
+ return EXPP_setFloatClamped( value, &con->xmax, -1000.0, 1000.0 );
+ case EXPP_CONSTR_YMIN:
+ return EXPP_setFloatClamped( value, &con->ymin, -1000.0, 1000.0 );
+ case EXPP_CONSTR_YMAX:
+ return EXPP_setFloatClamped( value, &con->ymax, -1000.0, 1000.0 );
+ case EXPP_CONSTR_ZMIN:
+ return EXPP_setFloatClamped( value, &con->zmin, -1000.0, 1000.0 );
+ case EXPP_CONSTR_ZMAX:
+ return EXPP_setFloatClamped( value, &con->zmax, -1000.0, 1000.0 );
+ default:
+ return EXPP_ReturnIntError( PyExc_KeyError, "key not found" );
+ }
+}
+
/*
* get data from a constraint
*/
@@ -999,11 +1186,13 @@ static PyObject *Constraint_getData( BPy_Constraint * self, PyObject * key )
return rotatelike_getter( self, setting );
case CONSTRAINT_TYPE_SIZELIKE:
return sizelike_getter( self, setting );
-
- case CONSTRAINT_TYPE_CHILDOF: /* Unimplemented */
case CONSTRAINT_TYPE_ROTLIMIT:
+ return rotlimit_getter( self, setting );
case CONSTRAINT_TYPE_LOCLIMIT:
+ return loclimit_getter( self, setting );
case CONSTRAINT_TYPE_SIZELIMIT:
+ return sizelimit_getter( self, setting );
+ case CONSTRAINT_TYPE_CHILDOF: /* Unimplemented */
case CONSTRAINT_TYPE_PYTHON:
default:
return EXPP_ReturnPyObjError( PyExc_KeyError,
@@ -1055,12 +1244,18 @@ static int Constraint_setData( BPy_Constraint * self, PyObject * key,
case CONSTRAINT_TYPE_SIZELIKE:
result = sizelike_setter( self, key_int, arg );
break;
- case CONSTRAINT_TYPE_NULL:
- return EXPP_ReturnIntError( PyExc_KeyError, "key not found" );
- case CONSTRAINT_TYPE_CHILDOF: /* Unimplemented */
case CONSTRAINT_TYPE_ROTLIMIT:
+ result = rotlimit_setter( self, key_int, arg );
+ break;
case CONSTRAINT_TYPE_LOCLIMIT:
+ result = loclimit_setter( self, key_int, arg );
+ break;
case CONSTRAINT_TYPE_SIZELIMIT:
+ result = sizelimit_setter( self, key_int, arg);
+ break;
+ case CONSTRAINT_TYPE_NULL:
+ return EXPP_ReturnIntError( PyExc_KeyError, "key not found" );
+ case CONSTRAINT_TYPE_CHILDOF: /* Unimplemented */
case CONSTRAINT_TYPE_PYTHON:
default:
return EXPP_ReturnIntError( PyExc_RuntimeError,
@@ -1535,6 +1730,12 @@ static PyObject *M_Constraint_TypeDict( void )
PyInt_FromLong( CONSTRAINT_TYPE_STRETCHTO ) );
PyConstant_Insert( d, "FLOOR",
PyInt_FromLong( CONSTRAINT_TYPE_MINMAX ) );
+ PyConstant_Insert( d, "LIMITLOC",
+ PyInt_FromLong( CONSTRAINT_TYPE_LOCLIMIT ) );
+ PyConstant_Insert( d, "LIMITROT",
+ PyInt_FromLong( CONSTRAINT_TYPE_ROTLIMIT ) );
+ PyConstant_Insert( d, "LIMITSIZE",
+ PyInt_FromLong( CONSTRAINT_TYPE_SIZELIMIT ) );
}
return S;
}
@@ -1675,6 +1876,46 @@ static PyObject *M_Constraint_SettingsDict( void )
PyConstant_Insert( d, "COPY",
PyInt_FromLong( EXPP_CONSTR_COPY ) );
+ PyConstant_Insert( d, "LIMIT",
+ PyInt_FromLong( EXPP_CONSTR_LIMIT ) );
+
+ PyConstant_Insert( d, "LIMIT_XMIN",
+ PyInt_FromLong( EXPP_CONSTR_LIMXMIN ) );
+ PyConstant_Insert( d, "LIMIT_XMAX",
+ PyInt_FromLong( EXPP_CONSTR_LIMXMAX ) );
+ PyConstant_Insert( d, "LIMIT_YMIN",
+ PyInt_FromLong( EXPP_CONSTR_LIMYMIN ) );
+ PyConstant_Insert( d, "LIMIT_YMAX",
+ PyInt_FromLong( EXPP_CONSTR_LIMYMAX ) );
+ PyConstant_Insert( d, "LIMIT_ZMIN",
+ PyInt_FromLong( EXPP_CONSTR_LIMZMIN ) );
+ PyConstant_Insert( d, "LIMIT_ZMAX",
+ PyInt_FromLong( EXPP_CONSTR_LIMZMAX ) );
+
+ PyConstant_Insert( d, "LIMIT_XROT",
+ PyInt_FromLong( EXPP_CONSTR_LIMXROT ) );
+ PyConstant_Insert( d, "LIMIT_YROT",
+ PyInt_FromLong( EXPP_CONSTR_LIMYROT ) );
+ PyConstant_Insert( d, "LIMIT_ZROT",
+ PyInt_FromLong( EXPP_CONSTR_LIMZROT ) );
+
+ PyConstant_Insert( d, "XMIN",
+ PyInt_FromLong( EXPP_CONSTR_XMIN ) );
+ PyConstant_Insert( d, "XMAX",
+ PyInt_FromLong( EXPP_CONSTR_XMAX ) );
+ PyConstant_Insert( d, "YMIN",
+ PyInt_FromLong( EXPP_CONSTR_YMIN ) );
+ PyConstant_Insert( d, "YMAX",
+ PyInt_FromLong( EXPP_CONSTR_YMAX ) );
+ PyConstant_Insert( d, "ZMIN",
+ PyInt_FromLong( EXPP_CONSTR_ZMIN ) );
+ PyConstant_Insert( d, "ZMAX",
+ PyInt_FromLong( EXPP_CONSTR_ZMAX ) );
+
+ PyConstant_Insert( d, "LIMIT_LOCAL_BONE",
+ PyInt_FromLong( EXPP_CONSTR_LIMLOCALBONE ) );
+ PyConstant_Insert( d, "LIMIT_LOCAL_NOPARENT",
+ PyInt_FromLong( EXPP_CONSTR_LIMLOCALNOPAR ) );
}
return S;
}
diff --git a/source/blender/python/api2_2x/doc/Constraint.py b/source/blender/python/api2_2x/doc/Constraint.py
index ae5d61687ad..546de98fbff 100644
--- a/source/blender/python/api2_2x/doc/Constraint.py
+++ b/source/blender/python/api2_2x/doc/Constraint.py
@@ -31,14 +31,16 @@ Or to print all the constraints attached to each bone in a pose::
@var Type: Constant Constraint dict used by L{Constraints.append()} and
for comparison with L{Constraint.type}. Values are
TRACKTO, IKSOLVER, FOLLOWPATH, COPYROT, COPYLOC, COPYSIZE, ACTION,
- LOCKTRACK, STRETCHTO, FLOOR, NULL
+ LOCKTRACK, STRETCHTO, FLOOR, LIMITLOC, LIMITROT, LIMITSIZE, NULL
@type Settings: readonly dictionary
@var Settings: Constant dict used for changing constraint settings.
- Used for all constraints
- - TARGET (Object)
+ - TARGET (Object) (Note: not used by Limit Location (LIMITLOC),
+ Limit Rotation (LIMITROT), Limit Scale (LIMITSIZE))
- BONE (string): name of Bone sub-target (for armature targets) (Note: not
- used by Stretch To (STRETCHTO))
+ used by Stretch To (STRETCHTO), Limit Location (LIMITLOC), Limit Rotation
+ (LIMITROT), Limit Scale (LIMITSIZE))
- Used by IK Solver (IKSOLVER) constraint:
- TOLERANCE (float): clamped to [0.0001:1.0]
- ITERATIONS (int): clamped to [1,10000]
@@ -84,6 +86,40 @@ Or to print all the constraints attached to each bone in a pose::
- LOCAL (bool): Only for constraints which Armature targets.
- Used by Copy Size (COPYSIZE) constraint:
- COPY (bitfield): any combination of COPYX, COPYY and COPYZ
+ - Used by Limit Location (LIMITLOC) constraint:
+ - LIMIT (bitfield): any combination of LIMIT_XMIN, LIMIT_XMAX,
+ LIMIT_YMIN, LIMIT_YMAX, LIMIT_ZMIN, LIMIT_ZMAX
+ - LIMIT_LOCAL_BONE (boolean): USE WITH CAUTION. Only do something
+ with this value if constraint is assigned to a bone.
+ - LIMIT_LOCAL_NOPARENT (boolean): USE WITH CAUTION. Only do something
+ with this value if constraint is assigned to an object with that
+ has been parented to something.
+ - XMIN (float): clamped to [-1000.0,1000.0]
+ - XMAX (float): clamped to [-1000.0,1000.0]
+ - YMIN (float): clamped to [-1000.0,1000.0]
+ - YMAX (float): clamped to [-1000.0,1000.0]
+ - ZMIN (float): clamped to [-1000.0,1000.0]
+ - ZMAX (float): clamped to [-1000.0,1000.0]
+ - Used by Limit Rotation (LIMITROT) constraint:
+ - LIMIT (bitfield): any combination of LIMIT_XROT, LIMIT_YROT,
+ LIMIT_ZROT
+ - LIMIT_LOCAL_BONE (boolean): USE WITH CAUTION. Only do something
+ with this value if constraint is assigned to a bone.
+ - XMIN (float): clamped to [-360.0,360.0]
+ - XMAX (float): clamped to [-360.0,360.0]
+ - YMIN (float): clamped to [-360.0,360.0]
+ - YMAX (float): clamped to [-360.0,360.0]
+ - ZMIN (float): clamped to [-360.0,360.0]
+ - ZMAX (float): clamped to [-360.0,360.0]
+ - Used by Limit Scale (LIMITSIZE) constraint:
+ - LIMIT (bitfield): any combination of LIMIT_XMIN, LIMIT_XMAX,
+ LIMIT_YMIN, LIMIT_YMAX, LIMIT_ZMIN, LIMIT_ZMAX
+ - XMIN (float): clamped to [-1000.0,1000.0]
+ - XMAX (float): clamped to [-1000.0,1000.0]
+ - YMIN (float): clamped to [-1000.0,1000.0]
+ - YMAX (float): clamped to [-1000.0,1000.0]
+ - ZMIN (float): clamped to [-1000.0,1000.0]
+ - ZMAX (float): clamped to [-1000.0,1000.0]
"""
diff --git a/source/blender/src/buttons_object.c b/source/blender/src/buttons_object.c
index 2e8c9bef420..523e8fd8301 100644
--- a/source/blender/src/buttons_object.c
+++ b/source/blender/src/buttons_object.c
@@ -355,6 +355,15 @@ void get_constraint_typestring (char *str, void *con_v)
case CONSTRAINT_TYPE_STRETCHTO:
strcpy (str, "Stretch To");
return;
+ case CONSTRAINT_TYPE_LOCLIMIT:
+ strcpy (str, "Limit Location");
+ return;
+ case CONSTRAINT_TYPE_ROTLIMIT:
+ strcpy (str, "Limit Rotation");
+ return;
+ case CONSTRAINT_TYPE_SIZELIMIT:
+ strcpy (str, "Limit Scale");
+ return;
default:
strcpy (str, "Unknown");
return;
@@ -386,6 +395,12 @@ static int get_constraint_col(bConstraint *con)
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;
default:
return TH_REDALERT;
}
@@ -985,6 +1000,138 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
uiBlockEndAlign(block);
}
break;
+ case CONSTRAINT_TYPE_LOCLIMIT:
+ {
+ bLocLimitConstraint *data = con->data;
+
+ int togButWidth = 50;
+ int textButWidth = ((width/2)-togButWidth);
+
+ height = 118;
+ uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+40,height-1, NULL, 5.0, 0.0, 12, rb_col, "");
+
+ /* Draw Pairs of LimitToggle+LimitValue */
+ uiBlockBeginAlign(block);
+ uiDefButBitS(block, TOG, LIMIT_XMIN, B_CONSTRAINT_TEST, "minX", *xco, *yco-28, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use minimum x value");
+ uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", *xco+togButWidth, *yco-28, (textButWidth-5), 18, &(data->xmin), -1000, 1000, 0.1,0.5,"Lowest x value to allow");
+ uiBlockEndAlign(block);
+
+ uiBlockBeginAlign(block);
+ uiDefButBitS(block, TOG, LIMIT_XMAX, B_CONSTRAINT_TEST, "maxX", *xco+(width-(textButWidth-5)-togButWidth), *yco-28, 50, 18, &data->flag, 0, 24, 0, 0, "Use maximum x value");
+ uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", *xco+(width-textButWidth-5), *yco-28, (textButWidth-5), 18, &(data->xmax), -1000, 1000, 0.1,0.5,"Highest x value to allow");
+ uiBlockEndAlign(block);
+
+ uiBlockBeginAlign(block);
+ uiDefButBitS(block, TOG, LIMIT_YMIN, B_CONSTRAINT_TEST, "minY", *xco, *yco-50, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use minimum y value");
+ uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", *xco+togButWidth, *yco-50, (textButWidth-5), 18, &(data->ymin), -1000, 1000, 0.1,0.5,"Lowest y value to allow");
+ uiBlockEndAlign(block);
+
+ uiBlockBeginAlign(block);
+ uiDefButBitS(block, TOG, LIMIT_YMAX, B_CONSTRAINT_TEST, "maxY", *xco+(width-(textButWidth-5)-togButWidth), *yco-50, 50, 18, &data->flag, 0, 24, 0, 0, "Use maximum y value");
+ uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", *xco+(width-textButWidth-5), *yco-50, (textButWidth-5), 18, &(data->ymax), -1000, 1000, 0.1,0.5,"Highest y value to allow");
+ uiBlockEndAlign(block);
+
+ uiBlockBeginAlign(block);
+ uiDefButBitS(block, TOG, LIMIT_ZMIN, B_CONSTRAINT_TEST, "minZ", *xco, *yco-72, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use minimum z value");
+ uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", *xco+togButWidth, *yco-72, (textButWidth-5), 18, &(data->zmin), -1000, 1000, 0.1,0.5,"Lowest z value to allow");
+ uiBlockEndAlign(block);
+
+ uiBlockBeginAlign(block);
+ uiDefButBitS(block, TOG, LIMIT_ZMAX, B_CONSTRAINT_TEST, "maxZ", *xco+(width-(textButWidth-5)-togButWidth), *yco-72, 50, 18, &data->flag, 0, 24, 0, 0, "Use maximum z value");
+ uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", *xco+(width-textButWidth-5), *yco-72, (textButWidth-5), 18, &(data->zmax), -1000, 1000, 0.1,0.5,"Highest z value to allow");
+ uiBlockEndAlign(block);
+
+ uiBlockBeginAlign(block);
+ uiDefBut(block, LABEL, B_CONSTRAINT_TEST,"Co-ordinate Space:",*xco, *yco-100,150,18, NULL, 0.0, 0.0, 0.0, 0.0, "");
+ if (ob->type == OB_ARMATURE)
+ uiDefButBitS(block, TOG, CONSTRAINT_LOCAL, B_CONSTRAINT_TEST, "Local", *xco+160, *yco-100, 60, 18, &con->flag, 0, 24, 0, 0, "Limit locations relative to the bone's rest-position");
+ else if (ob->parent != NULL)
+ uiDefButBitS(block, TOG, LIMIT_NOPARENT, B_CONSTRAINT_TEST, "Local", *xco+160, *yco-100, 60, 18, &data->flag2, 0, 24, 0, 0, "Limit locations relative to parent, not origin/world");
+ else
+ uiDefBut(block, LABEL, B_CONSTRAINT_TEST,"World",*xco+160, *yco-100,60,18, NULL, 0.0, 0.0, 0.0, 0.0, "Limit locations relative to origin/world");
+ uiBlockEndAlign(block);
+ }
+ break;
+ case CONSTRAINT_TYPE_ROTLIMIT:
+ {
+ bRotLimitConstraint *data = con->data;
+
+ int normButWidth = (width/3);
+
+ height = 118;
+ uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+40,height-1, NULL, 5.0, 0.0, 12, rb_col, "");
+
+ /* Draw Pairs of LimitToggle+LimitValue */
+ uiBlockBeginAlign(block);
+ uiDefButBitS(block, TOG, LIMIT_XROT, B_CONSTRAINT_TEST, "LimitX", *xco, *yco-28, normButWidth, 18, &data->flag, 0, 24, 0, 0, "Limit rotation on x-axis");
+ uiDefButF(block, NUM, B_CONSTRAINT_TEST, "min:", *xco+normButWidth, *yco-28, normButWidth, 18, &(data->xmin), -360, 360, 0.1,0.5,"Lowest x value to allow");
+ uiDefButF(block, NUM, B_CONSTRAINT_TEST, "max:", *xco+(normButWidth * 2), *yco-28, normButWidth, 18, &(data->xmax), -360, 360, 0.1,0.5,"Highest x value to allow");
+ uiBlockEndAlign(block);
+
+ uiBlockBeginAlign(block);
+ uiDefButBitS(block, TOG, LIMIT_YROT, B_CONSTRAINT_TEST, "LimitY", *xco, *yco-50, normButWidth, 18, &data->flag, 0, 24, 0, 0, "Limit rotation on y-axis");
+ uiDefButF(block, NUM, B_CONSTRAINT_TEST, "min:", *xco+normButWidth, *yco-50, normButWidth, 18, &(data->ymin), -360, 360, 0.1,0.5,"Lowest y value to allow");
+ uiDefButF(block, NUM, B_CONSTRAINT_TEST, "max:", *xco+(normButWidth * 2), *yco-50, normButWidth, 18, &(data->ymax), -360, 360, 0.1,0.5,"Highest y value to allow");
+ uiBlockEndAlign(block);
+
+ uiBlockBeginAlign(block);
+ uiDefButBitS(block, TOG, LIMIT_ZROT, B_CONSTRAINT_TEST, "LimitZ", *xco, *yco-72, normButWidth, 18, &data->flag, 0, 24, 0, 0, "Limit rotation on z-axis");
+ uiDefButF(block, NUM, B_CONSTRAINT_TEST, "min:", *xco+normButWidth, *yco-72, normButWidth, 18, &(data->zmin), -360, 360, 0.1,0.5,"Lowest z value to allow");
+ uiDefButF(block, NUM, B_CONSTRAINT_TEST, "max:", *xco+(normButWidth * 2), *yco-72, normButWidth, 18, &(data->zmax), -360, 360, 0.1,0.5,"Highest z value to allow");
+ uiBlockEndAlign(block);
+
+ if (ob->type == OB_ARMATURE) {
+ uiBlockBeginAlign(block);
+ uiDefBut(block, LABEL, B_CONSTRAINT_TEST,"Co-ordinate Space:",*xco, *yco-100,150,18, NULL, 0.0, 0.0, 0.0, 0.0, "");
+ uiDefButBitS(block, TOG, CONSTRAINT_LOCAL, B_CONSTRAINT_TEST, "Local", *xco+160, *yco-100, 60, 18, &con->flag, 0, 24, 0, 0, "Work on a Pose's local transform");
+ uiBlockEndAlign(block);
+ }
+ }
+ break;
+ case CONSTRAINT_TYPE_SIZELIMIT:
+ {
+ bSizeLimitConstraint *data = con->data;
+
+ int togButWidth = 50;
+ int textButWidth = ((width/2)-togButWidth);
+
+ height = 90;
+ uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+40,height-1, NULL, 5.0, 0.0, 12, rb_col, "");
+
+ /* Draw Pairs of LimitToggle+LimitValue */
+ uiBlockBeginAlign(block);
+ uiDefButBitS(block, TOG, LIMIT_XMIN, B_CONSTRAINT_TEST, "minX", *xco, *yco-28, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use minimum x value");
+ uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", *xco+togButWidth, *yco-28, (textButWidth-5), 18, &(data->xmin), 0.0001, 1000, 0.1,0.5,"Lowest x value to allow");
+ uiBlockEndAlign(block);
+
+ uiBlockBeginAlign(block);
+ uiDefButBitS(block, TOG, LIMIT_XMAX, B_CONSTRAINT_TEST, "maxX", *xco+(width-(textButWidth-5)-togButWidth), *yco-28, 50, 18, &data->flag, 0, 24, 0, 0, "Use maximum x value");
+ uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", *xco+(width-textButWidth-5), *yco-28, (textButWidth-5), 18, &(data->xmax), 0.0001, 1000, 0.1,0.5,"Highest x value to allow");
+ uiBlockEndAlign(block);
+
+
+ uiBlockBeginAlign(block);
+ uiDefButBitS(block, TOG, LIMIT_YMIN, B_CONSTRAINT_TEST, "minY", *xco, *yco-50, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use minimum y value");
+ uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", *xco+togButWidth, *yco-50, (textButWidth-5), 18, &(data->ymin), 0.0001, 1000, 0.1,0.5,"Lowest y value to allow");
+ uiBlockEndAlign(block);
+
+ uiBlockBeginAlign(block);
+ uiDefButBitS(block, TOG, LIMIT_YMAX, B_CONSTRAINT_TEST, "maxY", *xco+(width-(textButWidth-5)-togButWidth), *yco-50, 50, 18, &data->flag, 0, 24, 0, 0, "Use maximum y value");
+ uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", *xco+(width-textButWidth-5), *yco-50, (textButWidth-5), 18, &(data->ymax), 0.0001, 1000, 0.1,0.5,"Highest y value to allow");
+ uiBlockEndAlign(block);
+
+
+ uiBlockBeginAlign(block);
+ uiDefButBitS(block, TOG, LIMIT_ZMIN, B_CONSTRAINT_TEST, "minZ", *xco, *yco-72, togButWidth, 18, &data->flag, 0, 24, 0, 0, "Use minimum z value");
+ uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", *xco+togButWidth, *yco-72, (textButWidth-5), 18, &(data->zmin), 0.0001, 1000, 0.1,0.5,"Lowest z value to allow");
+ uiBlockEndAlign(block);
+
+ uiBlockBeginAlign(block);
+ uiDefButBitS(block, TOG, LIMIT_ZMAX, B_CONSTRAINT_TEST, "maxZ", *xco+(width-(textButWidth-5)-togButWidth), *yco-72, 50, 18, &data->flag, 0, 24, 0, 0, "Use maximum z value");
+ uiDefButF(block, NUM, B_CONSTRAINT_TEST, "", *xco+(width-textButWidth-5), *yco-72, (textButWidth-5), 18, &(data->zmax), 0.0001, 1000, 0.1,0.5,"Highest z value to allow");
+ uiBlockEndAlign(block);
+ }
+ break;
case CONSTRAINT_TYPE_NULL:
{
height = 17;
@@ -1034,6 +1181,12 @@ static uiBlock *add_constraintmenu(void *arg_unused)
uiDefBut(block, SEPR, 0, "", 0, yco-=6, 120, 6, NULL, 0.0, 0.0, 0, 0, "");
+ uiDefBut(block, BUTM, B_CONSTRAINT_ADD_LOCLIMIT,"Limit Location", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
+ uiDefBut(block, BUTM, B_CONSTRAINT_ADD_ROTLIMIT,"Limit Rotation", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
+ uiDefBut(block, BUTM, B_CONSTRAINT_ADD_SIZELIMIT,"Limit Scale", 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_TRACKTO,"Track To", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
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, "");
@@ -1185,6 +1338,36 @@ void do_constraintbuts(unsigned short event)
BIF_undo_push("Add constraint");
}
break;
+ case B_CONSTRAINT_ADD_LOCLIMIT:
+ {
+ bConstraint *con;
+
+ con = add_new_constraint(CONSTRAINT_TYPE_LOCLIMIT);
+ add_constraint_to_active(ob, con);
+
+ BIF_undo_push("Add constraint");
+ }
+ break;
+ case B_CONSTRAINT_ADD_ROTLIMIT:
+ {
+ bConstraint *con;
+
+ con = add_new_constraint(CONSTRAINT_TYPE_ROTLIMIT);
+ add_constraint_to_active(ob, con);
+
+ BIF_undo_push("Add constraint");
+ }
+ break;
+ case B_CONSTRAINT_ADD_SIZELIMIT:
+ {
+ bConstraint *con;
+
+ con = add_new_constraint(CONSTRAINT_TYPE_SIZELIMIT);
+ add_constraint_to_active(ob, con);
+
+ BIF_undo_push("Add constraint");
+ }
+ break;
default:
break;
diff --git a/source/blender/src/editconstraint.c b/source/blender/src/editconstraint.c
index b1ff54ae46f..aefec006930 100644
--- a/source/blender/src/editconstraint.c
+++ b/source/blender/src/editconstraint.c
@@ -653,21 +653,21 @@ void add_constraint(int only_IK)
else {
if(pchanact) {
if(pchansel)
- nr= pupmenu("Add Constraint to Active Bone%t|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7");
+ nr= pupmenu("Add Constraint to Active Bone%t|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7");
else if(obsel && obsel->type==OB_CURVE)
- nr= pupmenu("Add Constraint to Active Object%t|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|Track To%x3|Floor%x4|Locked Track%x5|Follow Path%x6|Stretch To%x7");
+ nr= pupmenu("Add Constraint to Active Object%t|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|Track To%x3|Floor%x4|Locked Track%x5|Follow Path%x6|Stretch To%x7");
else if(obsel)
- nr= pupmenu("Add Constraint to Active Object%t|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7");
+ nr= pupmenu("Add Constraint to Active Object%t|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7");
else
- nr= pupmenu("Add Constraint to New Empty Object%t|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7");
+ nr= pupmenu("Add Constraint to New Empty Object%t|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|Track To%x3|Floor%x4|Locked Track%x5|Stretch To%x7");
}
else {
if(obsel && obsel->type==OB_CURVE)
- nr= pupmenu("Add Constraint to Active Object%t|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|Track To%x3|Floor%x4|Locked Track%x5|Follow Path%x6");
+ nr= pupmenu("Add Constraint to Active Object%t|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|Track To%x3|Floor%x4|Locked Track%x5|Follow Path%x6");
else if(obsel)
- nr= pupmenu("Add Constraint to Active Object%t|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|Track To%x3|Floor%x4|Locked Track%x5");
+ nr= pupmenu("Add Constraint to Active Object%t|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|Track To%x3|Floor%x4|Locked Track%x5");
else
- nr= pupmenu("Add Constraint to New Empty Object%t|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|Track To%x3|Floor%x4|Locked Track%x5");
+ nr= pupmenu("Add Constraint to New Empty Object%t|Copy Location%x1|Copy Rotation%x2|Copy Scale%x8|Limit Location%x13|Limit Rotation%x14|Limit Scale%x15|Track To%x3|Floor%x4|Locked Track%x5");
}
}
@@ -718,6 +718,9 @@ void add_constraint(int only_IK)
}
else if(nr==7) con = add_new_constraint(CONSTRAINT_TYPE_STRETCHTO);
else if(nr==8) con = add_new_constraint(CONSTRAINT_TYPE_SIZELIKE);
+ else if(nr==13) con = add_new_constraint(CONSTRAINT_TYPE_LOCLIMIT);
+ else if(nr==14) con = add_new_constraint(CONSTRAINT_TYPE_ROTLIMIT);
+ else if(nr==15) con = add_new_constraint(CONSTRAINT_TYPE_SIZELIMIT);
if(con==NULL) return; /* paranoia */