diff options
author | Martin Poirier <theeth@yahoo.com> | 2006-08-13 18:18:15 +0400 |
---|---|---|
committer | Martin Poirier <theeth@yahoo.com> | 2006-08-13 18:18:15 +0400 |
commit | e341a4e1f45d8d3ba47dadc6ee72e94897369098 (patch) | |
tree | c856a30e057d743f82e751fe07376335b91392b6 /source | |
parent | cf1964cf9cea690d3800d9852567f01653b7b207 (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.c | 78 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/constraint.c | 286 | ||||
-rw-r--r-- | source/blender/blenloader/intern/readfile.c | 33 | ||||
-rw-r--r-- | source/blender/blenloader/intern/writefile.c | 9 | ||||
-rw-r--r-- | source/blender/include/butspace.h | 3 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_constraint_types.h | 44 | ||||
-rw-r--r-- | source/blender/python/api2_2x/Constraint.c | 251 | ||||
-rw-r--r-- | source/blender/python/api2_2x/doc/Constraint.py | 42 | ||||
-rw-r--r-- | source/blender/src/buttons_object.c | 183 | ||||
-rw-r--r-- | source/blender/src/editconstraint.c | 17 |
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 */ |