New Constraint option for Pose: "Local" Copy Location/Rotation.
The locality is restricted to action or user-transform only. Or as it goes in the code now: by setting a constraint local, it executes the constraint before it calculates the influence of Action or user transforms. ALso note that this works in Evil Eulerians. Meaning that when you only want to copy the X,Y or Z compenent of a euler, it can give unpredictable results when the other euler values are set, this because euler axis rotations work on top of each other.
This commit is contained in:
@@ -1401,6 +1401,52 @@ static void where_is_ik_bone(bPoseChannel *pchan, float ik_mat[][3]) // nr = t
|
||||
pchan->flag |= POSE_DONE;
|
||||
}
|
||||
|
||||
static void do_local_constraint(bPoseChannel *pchan, bConstraint *con)
|
||||
{
|
||||
switch(con->type) {
|
||||
case CONSTRAINT_TYPE_LOCLIKE:
|
||||
{
|
||||
bLocateLikeConstraint *data= con->data;
|
||||
|
||||
if(data->tar && data->subtarget[0]) {
|
||||
bPoseChannel *pchant= get_pose_channel(data->tar->pose, data->subtarget);
|
||||
if(pchant) {
|
||||
if (data->flag & LOCLIKE_X)
|
||||
pchan->loc[0]= pchant->loc[0];
|
||||
if (data->flag & LOCLIKE_Y)
|
||||
pchan->loc[1]= pchant->loc[1];
|
||||
if (data->flag & LOCLIKE_Z)
|
||||
pchan->loc[2]= pchant->loc[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CONSTRAINT_TYPE_ROTLIKE:
|
||||
{
|
||||
bRotateLikeConstraint *data= con->data;
|
||||
if(data->tar && data->subtarget[0]) {
|
||||
bPoseChannel *pchant= get_pose_channel(data->tar->pose, data->subtarget);
|
||||
if(pchant) {
|
||||
if(data->flag != (ROTLIKE_X|ROTLIKE_Y|ROTLIKE_Z)) {
|
||||
float eul[3], eult[3], fac= con->enforce;
|
||||
|
||||
QuatToEul(pchan->quat, eul);
|
||||
QuatToEul(pchant->quat, eult);
|
||||
if(data->flag & ROTLIKE_X) eul[0]= fac*eult[0] + (1.0f-fac)*eul[0];
|
||||
if(data->flag & ROTLIKE_Y) eul[1]= fac*eult[1] + (1.0f-fac)*eul[1];
|
||||
if(data->flag & ROTLIKE_Z) eul[2]= fac*eult[2] + (1.0f-fac)*eul[2];
|
||||
EulToQuat(eul, pchan->quat);
|
||||
}
|
||||
else {
|
||||
QuatInterpol(pchan->quat, pchan->quat, pchant->quat, con->enforce);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* The main armature solver, does all constraints excluding IK */
|
||||
/* pchan is validated, as having bone and parent pointer */
|
||||
static void where_is_pose_bone(Object *ob, bPoseChannel *pchan, float ctime)
|
||||
@@ -1414,6 +1460,15 @@ static void where_is_pose_bone(Object *ob, bPoseChannel *pchan, float ctime)
|
||||
parbone= bone->parent;
|
||||
parchan= pchan->parent;
|
||||
|
||||
/* Do local constraints, these only work on the channel data (loc rot size) */
|
||||
if(pchan->constraints.first) {
|
||||
bConstraint *con;
|
||||
for(con=pchan->constraints.first; con; con= con->next) {
|
||||
if(con->flag & CONSTRAINT_LOCAL)
|
||||
do_local_constraint(pchan, con);
|
||||
}
|
||||
}
|
||||
|
||||
/* this gives a chan_mat with actions (ipos) results */
|
||||
chan_calc_mat(pchan);
|
||||
|
||||
|
||||
@@ -1016,6 +1016,7 @@ short get_constraint_target_matrix (bConstraint *con, short ownertype, void* own
|
||||
|
||||
/* only called during solve_constraints */
|
||||
/* bone constraints create a fake object to work on, then ob is a workob */
|
||||
/* if ownerdata is set, it's the posechannel */
|
||||
void evaluate_constraint (bConstraint *constraint, Object *ob, short ownertype, void *ownerdata, float targetmat[][4])
|
||||
{
|
||||
float M_oldmat[4][4];
|
||||
|
||||
@@ -1574,7 +1574,9 @@ void solve_constraints (Object *ob, short obtype, void *obdata, float ctime)
|
||||
if (con->type==CONSTRAINT_TYPE_KINEMATIC) continue;
|
||||
// and this we can skip completely
|
||||
if (con->flag & CONSTRAINT_DISABLE) continue;
|
||||
|
||||
// local constraints are handled in armature.c only
|
||||
if (con->flag & CONSTRAINT_LOCAL) continue;
|
||||
|
||||
/* Clear accumulators if necessary*/
|
||||
if (clear) {
|
||||
clear= 0;
|
||||
|
||||
@@ -191,6 +191,9 @@ typedef struct bStretchToConstraint{
|
||||
/* flags 0x2 and 0x8 were used in past, skip this */
|
||||
/* to indicate which Ipo should be shown, maybe for 3d access later too */
|
||||
#define CONSTRAINT_ACTIVE 0x10
|
||||
/* only for Pose, evaluates constraints in posechannel local space */
|
||||
#define CONSTRAINT_LOCAL 0x20
|
||||
|
||||
|
||||
/* bConstraintChannel.flag */
|
||||
#define CONSTRAINT_CHANNEL_SELECT 0x01
|
||||
|
||||
@@ -638,6 +638,8 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
|
||||
|
||||
/* Draw XYZ toggles */
|
||||
uiBlockBeginAlign(block);
|
||||
if (arm)
|
||||
uiDefButBitS(block, TOG, CONSTRAINT_LOCAL, B_CONSTRAINT_TEST, "Local", *xco+((width/2)-98), *yco-64, 50, 18, &con->flag, 0, 24, 0, 0, "Work on a Pose's local transform");
|
||||
but=uiDefButBitI(block, TOG, LOCLIKE_X, B_CONSTRAINT_TEST, "X", *xco+((width/2)-48), *yco-64, 32, 18, &data->flag, 0, 24, 0, 0, "Copy X component");
|
||||
but=uiDefButBitI(block, TOG, LOCLIKE_Y, B_CONSTRAINT_TEST, "Y", *xco+((width/2)-16), *yco-64, 32, 18, &data->flag, 0, 24, 0, 0, "Copy Y component");
|
||||
but=uiDefButBitI(block, TOG, LOCLIKE_Z, B_CONSTRAINT_TEST, "Z", *xco+((width/2)+16), *yco-64, 32, 18, &data->flag, 0, 24, 0, 0, "Copy Z component");
|
||||
@@ -672,9 +674,11 @@ static void draw_constraint (uiBlock *block, ListBase *list, bConstraint *con, s
|
||||
|
||||
/* Draw XYZ toggles */
|
||||
uiBlockBeginAlign(block);
|
||||
but=uiDefButBitI(block, TOG, ROTLIKE_X, B_CONSTRAINT_TEST, "X", *xco+((width/2)-48), *yco-64, 32, 18, &data->flag, 0, 24, 0, 0, "Copy X component");
|
||||
but=uiDefButBitI(block, TOG, ROTLIKE_Y, B_CONSTRAINT_TEST, "Y", *xco+((width/2)-16), *yco-64, 32, 18, &data->flag, 0, 24, 0, 0, "Copy Y component");
|
||||
but=uiDefButBitI(block, TOG, ROTLIKE_Z, B_CONSTRAINT_TEST, "Z", *xco+((width/2)+16), *yco-64, 32, 18, &data->flag, 0, 24, 0, 0, "Copy Z component");
|
||||
if (arm)
|
||||
uiDefButBitS(block, TOG, CONSTRAINT_LOCAL, B_CONSTRAINT_TEST, "Local", *xco+((width/2)-98), *yco-64, 50, 18, &con->flag, 0, 24, 0, 0, "Work on a Pose's local transform");
|
||||
uiDefButBitI(block, TOG, ROTLIKE_X, B_CONSTRAINT_TEST, "X", *xco+((width/2)-48), *yco-64, 32, 18, &data->flag, 0, 24, 0, 0, "Copy X component");
|
||||
uiDefButBitI(block, TOG, ROTLIKE_Y, B_CONSTRAINT_TEST, "Y", *xco+((width/2)-16), *yco-64, 32, 18, &data->flag, 0, 24, 0, 0, "Copy Y component");
|
||||
uiDefButBitI(block, TOG, ROTLIKE_Z, B_CONSTRAINT_TEST, "Z", *xco+((width/2)+16), *yco-64, 32, 18, &data->flag, 0, 24, 0, 0, "Copy Z component");
|
||||
uiBlockEndAlign(block);
|
||||
}
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user