Roland Hess' Floor Constraint patch: https://projects.blender.org/tracker/?func=detail&aid=2993&group_id=9&atid=127
Minor modifications to simplify the code in evaluate_constraint. The "Stick" feature will need more work as it gives bad results when skipping frames, jumping around on the timeline and when going backward in time. Suggestion: Would be nice if it could use the local space too, not just global space planes.
This commit is contained in:
@@ -137,6 +137,14 @@ void relink_constraints (struct ListBase *list)
|
||||
bTrackToConstraint *data;
|
||||
data = con->data;
|
||||
|
||||
ID_NEW(data->tar);
|
||||
}
|
||||
break;
|
||||
case CONSTRAINT_TYPE_MINMAX:
|
||||
{
|
||||
bMinMaxConstraint *data;
|
||||
data = con->data;
|
||||
|
||||
ID_NEW(data->tar);
|
||||
}
|
||||
break;
|
||||
@@ -272,6 +280,13 @@ char constraint_has_target (bConstraint *con)
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case CONSTRAINT_TYPE_MINMAX:
|
||||
{
|
||||
bMinMaxConstraint *data = con->data;
|
||||
if (data->tar)
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case CONSTRAINT_TYPE_ACTION:
|
||||
{
|
||||
bActionConstraint *data = con->data;
|
||||
@@ -339,6 +354,13 @@ Object *get_constraint_target(bConstraint *con, char **subtarget)
|
||||
return data->tar;
|
||||
}
|
||||
break;
|
||||
case CONSTRAINT_TYPE_MINMAX:
|
||||
{
|
||||
bMinMaxConstraint *data = con->data;
|
||||
*subtarget= data->subtarget;
|
||||
return data->tar;
|
||||
}
|
||||
break;
|
||||
case CONSTRAINT_TYPE_LOCKTRACK:
|
||||
{
|
||||
bLockTrackConstraint *data = con->data;
|
||||
@@ -508,6 +530,22 @@ void *new_constraint_data (short type)
|
||||
|
||||
result = data;
|
||||
|
||||
}
|
||||
break;
|
||||
case CONSTRAINT_TYPE_MINMAX:
|
||||
{
|
||||
bMinMaxConstraint *data;
|
||||
data = MEM_callocN(sizeof(bMinMaxConstraint), "minmaxConstraint");
|
||||
|
||||
|
||||
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;
|
||||
|
||||
result = data;
|
||||
|
||||
}
|
||||
break;
|
||||
case CONSTRAINT_TYPE_ROTLIKE:
|
||||
@@ -801,6 +839,18 @@ short get_constraint_target_matrix (bConstraint *con, short ownertype, void* own
|
||||
Mat4One (mat);
|
||||
}
|
||||
break;
|
||||
case CONSTRAINT_TYPE_MINMAX:
|
||||
{
|
||||
bMinMaxConstraint *data = (bMinMaxConstraint*)con->data;
|
||||
|
||||
if (data->tar){
|
||||
constraint_target_to_mat4(data->tar, data->subtarget, mat, size, ctime);
|
||||
valid=1;
|
||||
}
|
||||
else
|
||||
Mat4One (mat);
|
||||
}
|
||||
break;
|
||||
case CONSTRAINT_TYPE_ROTLIKE:
|
||||
{
|
||||
bRotateLikeConstraint *data;
|
||||
@@ -993,6 +1043,64 @@ void evaluate_constraint (bConstraint *constraint, Object *ob, short ownertype,
|
||||
{
|
||||
}
|
||||
break;
|
||||
case CONSTRAINT_TYPE_MINMAX:
|
||||
{
|
||||
float val1, val2;
|
||||
int index;
|
||||
bMinMaxConstraint *data;
|
||||
|
||||
data = constraint->data;
|
||||
|
||||
switch (data->minmaxflag){
|
||||
case TRACK_Z:
|
||||
val1 = targetmat[3][2];
|
||||
val2 = ob->obmat[3][2]-data->offset;
|
||||
index = 2;
|
||||
break;
|
||||
case TRACK_Y:
|
||||
val1 = targetmat[3][1];
|
||||
val2 = ob->obmat[3][1]-data->offset;
|
||||
index = 1;
|
||||
break;
|
||||
case TRACK_X:
|
||||
val1 = targetmat[3][0];
|
||||
val2 = ob->obmat[3][0]-data->offset;
|
||||
index = 0;
|
||||
break;
|
||||
case TRACK_nZ:
|
||||
val2 = targetmat[3][2];
|
||||
val1 = ob->obmat[3][2]-data->offset;
|
||||
index = 2;
|
||||
break;
|
||||
case TRACK_nY:
|
||||
val2 = targetmat[3][1];
|
||||
val1 = ob->obmat[3][1]-data->offset;
|
||||
index = 1;
|
||||
break;
|
||||
case TRACK_nX:
|
||||
val2 = targetmat[3][0];
|
||||
val1 = ob->obmat[3][0]-data->offset;
|
||||
index = 0;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
} else {
|
||||
VECCOPY(data->cache, ob->obmat[3]);
|
||||
data->stuck = 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
data->stuck=0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CONSTRAINT_TYPE_TRACKTO:
|
||||
{
|
||||
bTrackToConstraint *data;
|
||||
|
||||
@@ -1320,6 +1320,13 @@ static void lib_link_constraints(FileData *fd, ID *id, ListBase *conlist)
|
||||
data->tar = newlibadr(fd, id->lib, data->tar);
|
||||
}
|
||||
break;
|
||||
case CONSTRAINT_TYPE_MINMAX:
|
||||
{
|
||||
bMinMaxConstraint *data;
|
||||
data = ((bMinMaxConstraint*)con->data);
|
||||
data->tar = newlibadr(fd, id->lib, data->tar);
|
||||
}
|
||||
break;
|
||||
case CONSTRAINT_TYPE_LOCKTRACK:
|
||||
{
|
||||
bLockTrackConstraint *data;
|
||||
@@ -5278,6 +5285,12 @@ static void expand_constraints(FileData *fd, Main *mainvar, ListBase *lb)
|
||||
expand_doit(fd, mainvar, data->tar);
|
||||
break;
|
||||
}
|
||||
case CONSTRAINT_TYPE_MINMAX:
|
||||
{
|
||||
bMinMaxConstraint *data = (bMinMaxConstraint*)curcon->data;
|
||||
expand_doit(fd, mainvar, data->tar);
|
||||
break;
|
||||
}
|
||||
case CONSTRAINT_TYPE_LOCKTRACK:
|
||||
{
|
||||
bLockTrackConstraint *data = (bLockTrackConstraint*)curcon->data;
|
||||
|
||||
@@ -612,6 +612,9 @@ static void write_constraints(WriteData *wd, ListBase *conlist)
|
||||
case CONSTRAINT_TYPE_STRETCHTO:
|
||||
writestruct(wd, DATA, "bStretchToConstraint", 1, con->data);
|
||||
break;
|
||||
case CONSTRAINT_TYPE_MINMAX:
|
||||
writestruct(wd, DATA, "bMinMaxConstraint", 1, con->data);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -552,6 +552,7 @@ enum {
|
||||
B_CONSTRAINT_ADD_NULL,
|
||||
B_CONSTRAINT_ADD_KINEMATIC,
|
||||
B_CONSTRAINT_ADD_TRACKTO,
|
||||
B_CONSTRAINT_ADD_MINMAX,
|
||||
B_CONSTRAINT_ADD_ROTLIKE,
|
||||
B_CONSTRAINT_ADD_LOCLIKE,
|
||||
B_CONSTRAINT_ADD_ACTION,
|
||||
|
||||
@@ -93,6 +93,16 @@ typedef struct bLocateLikeConstraint{
|
||||
char subtarget[32];
|
||||
} bLocateLikeConstraint;
|
||||
|
||||
typedef struct bMinMaxConstraint{
|
||||
Object *tar;
|
||||
int minmaxflag;
|
||||
float offset;
|
||||
short sticky;
|
||||
short stuck;
|
||||
float cache[3];
|
||||
char subtarget[32];
|
||||
} bMinMaxConstraint;
|
||||
|
||||
typedef struct bActionConstraint{
|
||||
Object *tar;
|
||||
short type;
|
||||
@@ -168,6 +178,7 @@ typedef struct bStretchToConstraint{
|
||||
#define CONSTRAINT_TYPE_LOCKTRACK 13 /* New Tracking constraint that locks an axis in place - theeth */
|
||||
#define CONSTRAINT_TYPE_DISTANCELIMIT 14
|
||||
#define CONSTRAINT_TYPE_STRETCHTO 15 /* claiming this to be mine :) is in tuhopuu bjornmose */
|
||||
#define CONSTRAINT_TYPE_MINMAX 16 /* floor constraint */
|
||||
|
||||
|
||||
/* bConstraint.flag */
|
||||
|
||||
@@ -313,6 +313,9 @@ static void get_constraint_typestring (char *str, bConstraint *con)
|
||||
case CONSTRAINT_TYPE_TRACKTO:
|
||||
strcpy (str, "Track To");
|
||||
return;
|
||||
case CONSTRAINT_TYPE_MINMAX:
|
||||
strcpy (str, "Floor");
|
||||
return;
|
||||
case CONSTRAINT_TYPE_KINEMATIC:
|
||||
strcpy (str, "IK Solver");
|
||||
return;
|
||||
@@ -353,6 +356,8 @@ static int get_constraint_col(bConstraint *con)
|
||||
return TH_BUT_SETTING1;
|
||||
case CONSTRAINT_TYPE_LOCLIKE:
|
||||
return TH_BUT_POPUP;
|
||||
case CONSTRAINT_TYPE_MINMAX:
|
||||
return TH_BUT_POPUP;
|
||||
case CONSTRAINT_TYPE_ACTION:
|
||||
return TH_BUT_ACTION;
|
||||
case CONSTRAINT_TYPE_LOCKTRACK:
|
||||
@@ -656,6 +661,44 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
|
||||
uiBlockEndAlign(block);
|
||||
}
|
||||
break;
|
||||
case CONSTRAINT_TYPE_MINMAX:
|
||||
{
|
||||
bMinMaxConstraint *data = con->data;
|
||||
bArmature *arm;
|
||||
|
||||
height = 66;
|
||||
uiDefBut(block, ROUNDBOX, B_DIFF, "", *xco-10, *yco-height, width+40,height-1, NULL, 5.0, 0.0, 12, rb_col, "");
|
||||
|
||||
uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Target:", *xco+65, *yco-24, 50, 18, NULL, 0.0, 0.0, 0.0, 0.0, "");
|
||||
|
||||
uiDefButF(block, NUM, B_CONSTRAINT_TEST, "Offset:", *xco, *yco-44, 100, 18, &data->offset, -100, 100, 100.0, 0.0, "Offset from the position of the object center");
|
||||
|
||||
/* Draw target parameters */
|
||||
uiBlockBeginAlign(block);
|
||||
uiDefIDPoinBut(block, test_obpoin_but, B_CONSTRAINT_CHANGETARGET, "OB:", *xco+120, *yco-24, 135, 18, &data->tar, "Target Object");
|
||||
|
||||
arm = get_armature(data->tar);
|
||||
if (arm){
|
||||
but=uiDefBut(block, TEX, B_CONSTRAINT_CHANGETARGET, "BO:", *xco+120, *yco-42,135,18, &data->subtarget, 0, 24, 0, 0, "Subtarget Bone");
|
||||
}
|
||||
else
|
||||
strcpy (data->subtarget, "");
|
||||
uiBlockEndAlign(block);
|
||||
|
||||
but=uiDefButBitI(block, TOG, 1, B_CONSTRAINT_TEST, "Sticky", *xco, *yco-24, 54, 18, &data->sticky, 0, 24, 0, 0, "Immobilize object while constrained");
|
||||
|
||||
uiDefBut(block, LABEL, B_CONSTRAINT_TEST, "Max/Min:", *xco-8, *yco-64, 54, 18, NULL, 0.0, 0.0, 0.0, 0.0, "");
|
||||
|
||||
uiBlockBeginAlign(block);
|
||||
uiDefButI(block, ROW,B_CONSTRAINT_TEST,"X", *xco+51, *yco-64,17,18, &data->minmaxflag, 12.0, 0.0, 0, 0, "Will not pass below X of target");
|
||||
uiDefButI(block, ROW,B_CONSTRAINT_TEST,"Y", *xco+67, *yco-64,17,18, &data->minmaxflag, 12.0, 1.0, 0, 0, "Will not pass below Y of target");
|
||||
uiDefButI(block, ROW,B_CONSTRAINT_TEST,"Z", *xco+85, *yco-64,17,18, &data->minmaxflag, 12.0, 2.0, 0, 0, "Will not pass below Z of target");
|
||||
uiDefButI(block, ROW,B_CONSTRAINT_TEST,"-X", *xco+102, *yco-64,24,18, &data->minmaxflag, 12.0, 3.0, 0, 0, "Will not pass above X of target");
|
||||
uiDefButI(block, ROW,B_CONSTRAINT_TEST,"-Y", *xco+126, *yco-64,24,18, &data->minmaxflag, 12.0, 4.0, 0, 0, "Will not pass above Y of target");
|
||||
uiDefButI(block, ROW,B_CONSTRAINT_TEST,"-Z", *xco+150, *yco-64,24,18, &data->minmaxflag, 12.0, 5.0, 0, 0, "Will not pass above Z of target");
|
||||
uiBlockEndAlign(block);
|
||||
}
|
||||
break;
|
||||
case CONSTRAINT_TYPE_LOCKTRACK:
|
||||
{
|
||||
bLockTrackConstraint *data = con->data;
|
||||
@@ -831,6 +874,7 @@ 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_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, "");
|
||||
uiDefBut(block, BUTM, B_CONSTRAINT_ADD_FOLLOWPATH,"Follow Path", 0, yco-=20, 160, 19, NULL, 0.0, 0.0, 1, 0, "");
|
||||
|
||||
@@ -898,6 +942,16 @@ void do_constraintbuts(unsigned short event)
|
||||
BIF_undo_push("Add constraint");
|
||||
}
|
||||
break;
|
||||
case B_CONSTRAINT_ADD_MINMAX:
|
||||
{
|
||||
bConstraint *con;
|
||||
|
||||
con = add_new_constraint(CONSTRAINT_TYPE_MINMAX);
|
||||
add_constraint_to_active(ob, con);
|
||||
|
||||
BIF_undo_push("Add constraint");
|
||||
}
|
||||
break;
|
||||
case B_CONSTRAINT_ADD_ROTLIKE:
|
||||
{
|
||||
bConstraint *con;
|
||||
|
||||
@@ -260,6 +260,12 @@ char *get_con_subtarget_name(bConstraint *con, Object *target)
|
||||
if (data->tar==target) return data->subtarget;
|
||||
}
|
||||
break;
|
||||
case CONSTRAINT_TYPE_MINMAX:
|
||||
{
|
||||
bMinMaxConstraint *data = con->data;
|
||||
if (data->tar==target) return data->subtarget;
|
||||
}
|
||||
break;
|
||||
case CONSTRAINT_TYPE_LOCKTRACK:
|
||||
{
|
||||
bLockTrackConstraint *data = con->data;
|
||||
@@ -368,6 +374,24 @@ static void test_constraints (Object *owner, const char* substring)
|
||||
break;
|
||||
}
|
||||
|
||||
if ( (data->tar == owner) &&
|
||||
(!get_named_bone(get_armature(owner),
|
||||
data->subtarget))) {
|
||||
curcon->flag |= CONSTRAINT_DISABLE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CONSTRAINT_TYPE_MINMAX:
|
||||
{
|
||||
bMinMaxConstraint *data = curcon->data;
|
||||
|
||||
if (!exist_object(data->tar)){
|
||||
data->tar = NULL;
|
||||
curcon->flag |= CONSTRAINT_DISABLE;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( (data->tar == owner) &&
|
||||
(!get_named_bone(get_armature(owner),
|
||||
data->subtarget))) {
|
||||
|
||||
Reference in New Issue
Block a user