This commit adds local target rotation support to the floor constraint,
making it much more useful. Requested and taunted for frequently by Plumiferos folks. Click on "Use Rot" to take target object rotations into account. Good for using rotated empties, etc., as a sloped floor.
This commit is contained in:
@@ -598,8 +598,7 @@ void *new_constraint_data (short type)
|
||||
data->minmaxflag = TRACK_Z;
|
||||
data->offset = 0.0f;
|
||||
data->cache[0] = data->cache[1] = data->cache[2] = 0.0f;
|
||||
data->sticky = 0;
|
||||
data->stuck = 0;
|
||||
data->flag = 0;
|
||||
|
||||
result = data;
|
||||
|
||||
@@ -1250,38 +1249,50 @@ void evaluate_constraint (bConstraint *constraint, Object *ob, short ownertype,
|
||||
float val1, val2;
|
||||
int index;
|
||||
bMinMaxConstraint *data;
|
||||
float obmat[4][4],imat[4][4],tarmat[4][4],tmat[4][4];
|
||||
|
||||
data = constraint->data;
|
||||
|
||||
Mat4CpyMat4(obmat,ob->obmat);
|
||||
Mat4CpyMat4(tarmat,targetmat);
|
||||
|
||||
if (data->flag&MINMAX_USEROT) {
|
||||
/* take rotation of target into account by doing the transaction in target's localspace */
|
||||
Mat4Invert(imat,tarmat);
|
||||
Mat4MulMat4(tmat,obmat,imat);
|
||||
Mat4CpyMat4(obmat,tmat);
|
||||
Mat4One(tarmat);
|
||||
}
|
||||
|
||||
switch (data->minmaxflag){
|
||||
case TRACK_Z:
|
||||
val1 = targetmat[3][2];
|
||||
val2 = ob->obmat[3][2]-data->offset;
|
||||
val1 = tarmat[3][2];
|
||||
val2 = obmat[3][2]-data->offset;
|
||||
index = 2;
|
||||
break;
|
||||
case TRACK_Y:
|
||||
val1 = targetmat[3][1];
|
||||
val2 = ob->obmat[3][1]-data->offset;
|
||||
val1 = tarmat[3][1];
|
||||
val2 = obmat[3][1]-data->offset;
|
||||
index = 1;
|
||||
break;
|
||||
case TRACK_X:
|
||||
val1 = targetmat[3][0];
|
||||
val2 = ob->obmat[3][0]-data->offset;
|
||||
val1 = tarmat[3][0];
|
||||
val2 = obmat[3][0]-data->offset;
|
||||
index = 0;
|
||||
break;
|
||||
case TRACK_nZ:
|
||||
val2 = targetmat[3][2];
|
||||
val1 = ob->obmat[3][2]-data->offset;
|
||||
val2 = tarmat[3][2];
|
||||
val1 = obmat[3][2]-data->offset;
|
||||
index = 2;
|
||||
break;
|
||||
case TRACK_nY:
|
||||
val2 = targetmat[3][1];
|
||||
val1 = ob->obmat[3][1]-data->offset;
|
||||
val2 = tarmat[3][1];
|
||||
val1 = obmat[3][1]-data->offset;
|
||||
index = 1;
|
||||
break;
|
||||
case TRACK_nX:
|
||||
val2 = targetmat[3][0];
|
||||
val1 = ob->obmat[3][0]-data->offset;
|
||||
val2 = tarmat[3][0];
|
||||
val1 = obmat[3][0]-data->offset;
|
||||
index = 0;
|
||||
break;
|
||||
default:
|
||||
@@ -1289,18 +1300,27 @@ void evaluate_constraint (bConstraint *constraint, Object *ob, short ownertype,
|
||||
}
|
||||
|
||||
if (val1 > val2) {
|
||||
ob->obmat[3][index] = targetmat[3][index] + data->offset;
|
||||
if (data->sticky==1) {
|
||||
if (data->stuck==1) {
|
||||
VECCOPY(ob->obmat[3], data->cache);
|
||||
obmat[3][index] = tarmat[3][index] + data->offset;
|
||||
if (data->flag&MINMAX_STICKY) {
|
||||
if (data->flag&MINMAX_STUCK) {
|
||||
VECCOPY(obmat[3], data->cache);
|
||||
} else {
|
||||
VECCOPY(data->cache, ob->obmat[3]);
|
||||
data->stuck = 1;
|
||||
VECCOPY(data->cache, obmat[3]);
|
||||
data->flag|=MINMAX_STUCK;
|
||||
}
|
||||
}
|
||||
if (data->flag&MINMAX_USEROT) {
|
||||
/* get out of localspace */
|
||||
Mat4MulMat4(tmat,obmat,targetmat);
|
||||
Mat4CpyMat4(ob->obmat,tmat);
|
||||
} else {
|
||||
VECCOPY(ob->obmat[3],obmat[3]);
|
||||
}
|
||||
|
||||
} else {
|
||||
data->stuck=0;
|
||||
data->flag&=~MINMAX_STUCK;
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
case CONSTRAINT_TYPE_TRACKTO:
|
||||
|
||||
@@ -99,8 +99,7 @@ typedef struct bMinMaxConstraint{
|
||||
Object *tar;
|
||||
int minmaxflag;
|
||||
float offset;
|
||||
short sticky;
|
||||
short stuck;
|
||||
int flag;
|
||||
float cache[3];
|
||||
char subtarget[32];
|
||||
} bMinMaxConstraint;
|
||||
@@ -278,6 +277,11 @@ typedef struct bSizeLimitConstraint{
|
||||
#define CONSTRAINT_IK_AUTO 4
|
||||
#define CONSTRAINT_IK_TEMP 8
|
||||
|
||||
/* MinMax (floor) flags */
|
||||
#define MINMAX_STICKY 0x01
|
||||
#define MINMAX_STUCK 0x02
|
||||
#define MINMAX_USEROT 0x04
|
||||
|
||||
/* transform limiting constraints -> flag */
|
||||
#define LIMIT_XMIN 0x01
|
||||
#define LIMIT_XMAX 0x02
|
||||
|
||||
@@ -762,7 +762,7 @@ static PyObject *floor_getter( BPy_Constraint * self, int type )
|
||||
case EXPP_CONSTR_OFFSET:
|
||||
return PyFloat_FromDouble( (double)con->offset );
|
||||
case EXPP_CONSTR_STICKY:
|
||||
return PyBool_FromLong( (long)( con->sticky & SELECT ) ) ;
|
||||
return PyBool_FromLong( (long)( con->flag & MINMAX_STICKY ) ) ;
|
||||
default:
|
||||
return EXPP_ReturnPyObjError( PyExc_KeyError, "key not found" );
|
||||
}
|
||||
@@ -797,7 +797,7 @@ static int floor_setter( BPy_Constraint *self, int type, PyObject *value )
|
||||
case EXPP_CONSTR_OFFSET:
|
||||
return EXPP_setFloatClamped( value, &con->offset, -100.0, 100.0 );
|
||||
case EXPP_CONSTR_STICKY:
|
||||
return EXPP_setBitfield( value, &con->sticky, SELECT, 'h' );
|
||||
return EXPP_setBitfield( value, &con->flag, MINMAX_STICKY, 'h' );
|
||||
default:
|
||||
return EXPP_ReturnIntError( PyExc_KeyError, "key not found" );
|
||||
}
|
||||
|
||||
@@ -847,7 +847,8 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
|
||||
strcpy (data->subtarget, "");
|
||||
uiBlockEndAlign(block);
|
||||
|
||||
but=uiDefButBitS(block, TOG, 1, B_CONSTRAINT_TEST, "Sticky", *xco, *yco-24, 54, 18, &data->sticky, 0, 24, 0, 0, "Immobilize object while constrained");
|
||||
but=uiDefButI(block, TOG|BIT|0, B_CONSTRAINT_TEST, "Sticky", *xco, *yco-24, 44, 18, &data->flag, 0, 24, 0, 0, "Immobilize object while constrained");
|
||||
but=uiDefButI(block, TOG|BIT|2, B_CONSTRAINT_TEST, "Use Rot", *xco+44, *yco-24, 64, 18, &data->flag, 0, 24, 0, 0, "Use target object rotation");
|
||||
|
||||
uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Max/Min:", *xco-8, *yco-64, 54, 18, NULL, 0.0, 0.0, 0.0, 0.0, "");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user