= Limit Distance Constraint - 'For Transform' Option =
The Limit Distance Constraint now has a "For Transform" option just like all the other Limit constraints. This option controls whether the constraint gets applied to interactive transforms in the 3D View too, preventing controllers from getting large values without the animator knowing. Additional code changes: * Split code to get constraint targets and grab their matrices for solving out to a separate helper function: get_constraint_targets_for_solving() * Fixed a bug where "found constraint ...." prints would appear in the console. Looks like some warning print that was forgotten TODO: * While coding this, I noticed potential division by zero bugs with the Limit Distance constraint. Looking into these after this commit.
This commit is contained in:
@@ -476,6 +476,11 @@ class ConstraintButtonsPanel():
|
||||
row.label(text="Clamp Region:")
|
||||
row.prop(con, "limit_mode", text="")
|
||||
|
||||
row = layout.row()
|
||||
row.prop(con, "use_transform_limit")
|
||||
row.label()
|
||||
|
||||
|
||||
def STRETCH_TO(self, context, layout, con):
|
||||
self.target_template(layout, con)
|
||||
|
||||
|
@@ -154,6 +154,7 @@ void constraints_clear_evalob(struct bConstraintOb *cob);
|
||||
void constraint_mat_convertspace(struct Object *ob, struct bPoseChannel *pchan, float mat[][4], short from, short to);
|
||||
|
||||
void get_constraint_target_matrix(struct Scene *scene, struct bConstraint *con, int n, short ownertype, void *ownerdata, float mat[][4], float ctime);
|
||||
void get_constraint_targets_for_solving(struct bConstraint *con, struct bConstraintOb *ob, struct ListBase *targets, float ctime);
|
||||
void solve_constraints(struct ListBase *conlist, struct bConstraintOb *cob, float ctime);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@@ -2643,6 +2643,8 @@ static void distlimit_evaluate (bConstraint *con, bConstraintOb *cob, ListBase *
|
||||
if (data->dist == 0)
|
||||
data->dist= dist;
|
||||
|
||||
// FIXME: dist may be 0!
|
||||
|
||||
/* check if we're which way to clamp from, and calculate interpolation factor (if needed) */
|
||||
if (data->mode == LIMITDIST_OUTSIDE) {
|
||||
/* if inside, then move to surface */
|
||||
@@ -4428,6 +4430,34 @@ void get_constraint_target_matrix (struct Scene *scene, bConstraint *con, int n,
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the list of targets required for solving a constraint */
|
||||
void get_constraint_targets_for_solving (bConstraint *con, bConstraintOb *cob, ListBase *targets, float ctime)
|
||||
{
|
||||
bConstraintTypeInfo *cti= constraint_get_typeinfo(con);
|
||||
|
||||
if (cti && cti->get_constraint_targets) {
|
||||
bConstraintTarget *ct;
|
||||
|
||||
/* get targets
|
||||
* - constraints should use ct->matrix, not directly accessing values
|
||||
* - ct->matrix members have not yet been calculated here!
|
||||
*/
|
||||
cti->get_constraint_targets(con, targets);
|
||||
|
||||
/* set matrices
|
||||
* - calculate if possible, otherwise just initialise as identity matrix
|
||||
*/
|
||||
if (cti->get_target_matrix) {
|
||||
for (ct= targets->first; ct; ct= ct->next)
|
||||
cti->get_target_matrix(con, cob, ct, ctime);
|
||||
}
|
||||
else {
|
||||
for (ct= targets->first; ct; ct= ct->next)
|
||||
unit_m4(ct->matrix);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------- Evaluation ----------- */
|
||||
|
||||
/* This function is called whenever constraints need to be evaluated. Currently, all
|
||||
@@ -4471,27 +4501,7 @@ void solve_constraints (ListBase *conlist, bConstraintOb *cob, float ctime)
|
||||
constraint_mat_convertspace(cob->ob, cob->pchan, cob->matrix, CONSTRAINT_SPACE_WORLD, con->ownspace);
|
||||
|
||||
/* prepare targets for constraint solving */
|
||||
if (cti->get_constraint_targets) {
|
||||
bConstraintTarget *ct;
|
||||
|
||||
/* get targets
|
||||
* - constraints should use ct->matrix, not directly accessing values
|
||||
* - ct->matrix members have not yet been calculated here!
|
||||
*/
|
||||
cti->get_constraint_targets(con, &targets);
|
||||
|
||||
/* set matrices
|
||||
* - calculate if possible, otherwise just initialise as identity matrix
|
||||
*/
|
||||
if (cti->get_target_matrix) {
|
||||
for (ct= targets.first; ct; ct= ct->next)
|
||||
cti->get_target_matrix(con, cob, ct, ctime);
|
||||
}
|
||||
else {
|
||||
for (ct= targets.first; ct; ct= ct->next)
|
||||
unit_m4(ct->matrix);
|
||||
}
|
||||
}
|
||||
get_constraint_targets_for_solving(con, cob, &targets, ctime);
|
||||
|
||||
/* Solve the constraint and put result in cob->matrix */
|
||||
cti->evaluate_constraint(con, cob, &targets);
|
||||
|
@@ -567,7 +567,8 @@ static bConstraint *edit_constraint_property_get(wmOperator *op, Object *ob, int
|
||||
}
|
||||
|
||||
con = constraints_findByName(list, constraint_name);
|
||||
printf("constraint found = %p, %s\n", (void *)con, (con)?con->name:"<Not found>");
|
||||
//if (G.f & G_DEBUG)
|
||||
//printf("constraint found = %p, %s\n", (void *)con, (con)?con->name:"<Not found>");
|
||||
|
||||
if (con && (type != 0) && (con->type != type))
|
||||
con = NULL;
|
||||
|
@@ -1982,12 +1982,15 @@ static void protectedQuaternionBits(short protectflag, float *quat, float *oldqu
|
||||
|
||||
/* ******************* TRANSFORM LIMITS ********************** */
|
||||
|
||||
static void constraintTransLim(TransInfo *UNUSED(t), TransData *td)
|
||||
static void constraintTransLim(TransInfo *t, TransData *td)
|
||||
{
|
||||
if (td->con) {
|
||||
bConstraintTypeInfo *cti= get_constraint_typeinfo(CONSTRAINT_TYPE_LOCLIMIT);
|
||||
bConstraintTypeInfo *ctiLoc= get_constraint_typeinfo(CONSTRAINT_TYPE_LOCLIMIT);
|
||||
bConstraintTypeInfo *ctiDist= get_constraint_typeinfo(CONSTRAINT_TYPE_DISTLIMIT);
|
||||
|
||||
bConstraintOb cob= {NULL};
|
||||
bConstraint *con;
|
||||
float ctime = (float)(t->scene->r.cfra);
|
||||
|
||||
/* Make a temporary bConstraintOb for using these limit constraints
|
||||
* - they only care that cob->matrix is correctly set ;-)
|
||||
@@ -1998,6 +2001,8 @@ static void constraintTransLim(TransInfo *UNUSED(t), TransData *td)
|
||||
|
||||
/* Evaluate valid constraints */
|
||||
for (con= td->con; con; con= con->next) {
|
||||
bConstraintTypeInfo *cti = NULL;
|
||||
ListBase targets = {NULL, NULL};
|
||||
float tmat[4][4];
|
||||
|
||||
/* only consider constraint if enabled */
|
||||
@@ -2010,7 +2015,17 @@ static void constraintTransLim(TransInfo *UNUSED(t), TransData *td)
|
||||
|
||||
if ((data->flag2 & LIMIT_TRANSFORM)==0)
|
||||
continue;
|
||||
cti = ctiLoc;
|
||||
}
|
||||
else if (con->type == CONSTRAINT_TYPE_DISTLIMIT) {
|
||||
bDistLimitConstraint *data= con->data;
|
||||
|
||||
if ((data->flag & LIMITDIST_TRANSFORM)==0)
|
||||
continue;
|
||||
cti = ctiDist;
|
||||
}
|
||||
|
||||
if (cti) {
|
||||
/* do space conversions */
|
||||
if (con->ownspace == CONSTRAINT_SPACE_WORLD) {
|
||||
/* just multiply by td->mtx (this should be ok) */
|
||||
@@ -2022,8 +2037,11 @@ static void constraintTransLim(TransInfo *UNUSED(t), TransData *td)
|
||||
continue;
|
||||
}
|
||||
|
||||
/* get constraint targets if needed */
|
||||
get_constraint_targets_for_solving(con, &cob, &targets, ctime);
|
||||
|
||||
/* do constraint */
|
||||
cti->evaluate_constraint(con, &cob, NULL);
|
||||
cti->evaluate_constraint(con, &cob, &targets);
|
||||
|
||||
/* convert spaces again */
|
||||
if (con->ownspace == CONSTRAINT_SPACE_WORLD) {
|
||||
@@ -2031,6 +2049,9 @@ static void constraintTransLim(TransInfo *UNUSED(t), TransData *td)
|
||||
copy_m4_m4(tmat, cob.matrix);
|
||||
mul_m4_m3m4(cob.matrix, td->smtx, tmat);
|
||||
}
|
||||
|
||||
/* free targets list */
|
||||
BLI_freelistN(&targets);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -677,7 +677,10 @@ typedef enum eRotLimit_Flags {
|
||||
/* distance limit constraint */
|
||||
/* bDistLimitConstraint->flag */
|
||||
typedef enum eDistLimit_Flag {
|
||||
LIMITDIST_USESOFT = (1<<0)
|
||||
/* "soft" cushion effect when reaching the limit sphere */ // NOT IMPLEMENTED!
|
||||
LIMITDIST_USESOFT = (1<<0),
|
||||
/* as for all Limit constraints - allow to be used during transform? */
|
||||
LIMITDIST_TRANSFORM = (1<<1)
|
||||
} eDistLimit_Flag;
|
||||
|
||||
/* bDistLimitConstraint->mode */
|
||||
|
@@ -1787,6 +1787,11 @@ static void rna_def_constraint_distance_limit(BlenderRNA *brna)
|
||||
RNA_def_property_enum_items(prop, constraint_distance_items);
|
||||
RNA_def_property_ui_text(prop, "Limit Mode", "Distances in relation to sphere of influence to allow");
|
||||
RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update");
|
||||
|
||||
prop= RNA_def_property(srna, "use_transform_limit", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", LIMITDIST_TRANSFORM);
|
||||
RNA_def_property_ui_text(prop, "For Transform", "Transforms are affected by this constraint as well");
|
||||
RNA_def_property_update(prop, NC_OBJECT|ND_CONSTRAINT, "rna_Constraint_update");
|
||||
}
|
||||
|
||||
static void rna_def_constraint_shrinkwrap(BlenderRNA *brna)
|
||||
|
Reference in New Issue
Block a user