Action Constraint: Add manual time factor input control
Adds an optional slider to the action constraint so that it can be driven without a constraint target. This is very helpful for more complex rigging and mechanical rigs, as it means the action constraint can be controlled with a driver/custom property directly, currently if we want to use a driver to control it we must add a "dummy" bone/object inbetween to act as a control. Reviewed By: Sebastian Parborg, Sybren A. Stüvel, Demeter Dzadik, Julian Eisel Differential Revision: http://developer.blender.org/D8022
This commit is contained in:
parent
569e2e6dba
commit
c9c0f89307
|
@ -508,7 +508,18 @@ class ConstraintButtonsPanel(Panel):
|
|||
layout.use_property_split = True
|
||||
layout.use_property_decorate = True
|
||||
|
||||
self.target_template(layout, con)
|
||||
target_row = layout.row(align=True)
|
||||
target_row.active = not con.use_eval_time
|
||||
self.target_template(target_row, con)
|
||||
|
||||
row = layout.row(align=True, heading="Evaluation Time")
|
||||
row.use_property_decorate = False
|
||||
sub = row.row(align=True)
|
||||
sub.prop(con, "use_eval_time", text="")
|
||||
subsub = sub.row(align=True)
|
||||
subsub.active = con.use_eval_time
|
||||
subsub.prop(con, "eval_time", text="")
|
||||
row.prop_decorator(con, "eval_time")
|
||||
|
||||
layout.prop(con, "mix_mode", text="Mix")
|
||||
|
||||
|
@ -1105,13 +1116,14 @@ class ConstraintButtonsSubPanel(Panel):
|
|||
layout.use_property_split = True
|
||||
layout.use_property_decorate = True
|
||||
|
||||
layout.prop(con, "transform_channel", text="Channel")
|
||||
layout.prop(con, "target_space")
|
||||
|
||||
col = layout.column(align=True)
|
||||
col.prop(con, "min", text="Range Min")
|
||||
col.prop(con, "max", text="Max")
|
||||
col = layout.column()
|
||||
col.active = not con.use_eval_time
|
||||
col.prop(con, "transform_channel", text="Channel")
|
||||
col.prop(con, "target_space")
|
||||
|
||||
sub = col.column(align=True)
|
||||
sub.prop(con, "min", text="Range Min")
|
||||
sub.prop(con, "max", text="Max")
|
||||
|
||||
def draw_action_action(self, context):
|
||||
layout = self.layout
|
||||
|
|
|
@ -2634,7 +2634,7 @@ static void actcon_get_tarmat(struct Depsgraph *depsgraph,
|
|||
{
|
||||
bActionConstraint *data = con->data;
|
||||
|
||||
if (VALID_CONS_TARGET(ct)) {
|
||||
if (VALID_CONS_TARGET(ct) || data->flag & ACTCON_USE_EVAL_TIME) {
|
||||
float tempmat[4][4], vec[3];
|
||||
float s, t;
|
||||
short axis;
|
||||
|
@ -2642,42 +2642,48 @@ static void actcon_get_tarmat(struct Depsgraph *depsgraph,
|
|||
/* initialize return matrix */
|
||||
unit_m4(ct->matrix);
|
||||
|
||||
/* get the transform matrix of the target */
|
||||
constraint_target_to_mat4(ct->tar,
|
||||
ct->subtarget,
|
||||
tempmat,
|
||||
CONSTRAINT_SPACE_WORLD,
|
||||
ct->space,
|
||||
con->flag,
|
||||
con->headtail);
|
||||
/* Skip targets if we're using local float property to set action time */
|
||||
if (data->flag & ACTCON_USE_EVAL_TIME) {
|
||||
s = data->eval_time;
|
||||
} else {
|
||||
/* get the transform matrix of the target */
|
||||
constraint_target_to_mat4(ct->tar,
|
||||
ct->subtarget,
|
||||
tempmat,
|
||||
CONSTRAINT_SPACE_WORLD,
|
||||
ct->space,
|
||||
con->flag,
|
||||
con->headtail);
|
||||
|
||||
/* determine where in transform range target is */
|
||||
/* data->type is mapped as follows for backwards compatibility:
|
||||
* 00,01,02 - rotation (it used to be like this)
|
||||
* 10,11,12 - scaling
|
||||
* 20,21,22 - location
|
||||
*/
|
||||
if (data->type < 10) {
|
||||
/* extract rotation (is in whatever space target should be in) */
|
||||
mat4_to_eul(vec, tempmat);
|
||||
mul_v3_fl(vec, RAD2DEGF(1.0f)); /* rad -> deg */
|
||||
axis = data->type;
|
||||
}
|
||||
else if (data->type < 20) {
|
||||
/* extract scaling (is in whatever space target should be in) */
|
||||
mat4_to_size(vec, tempmat);
|
||||
axis = data->type - 10;
|
||||
}
|
||||
else {
|
||||
/* extract location */
|
||||
copy_v3_v3(vec, tempmat[3]);
|
||||
axis = data->type - 20;
|
||||
/* determine where in transform range target is */
|
||||
/* data->type is mapped as follows for backwards compatibility:
|
||||
* 00,01,02 - rotation (it used to be like this)
|
||||
* 10,11,12 - scaling
|
||||
* 20,21,22 - location
|
||||
*/
|
||||
if (data->type < 10) {
|
||||
/* extract rotation (is in whatever space target should be in) */
|
||||
mat4_to_eul(vec, tempmat);
|
||||
mul_v3_fl(vec, RAD2DEGF(1.0f)); /* rad -> deg */
|
||||
axis = data->type;
|
||||
}
|
||||
else if (data->type < 20) {
|
||||
/* extract scaling (is in whatever space target should be in) */
|
||||
mat4_to_size(vec, tempmat);
|
||||
axis = data->type - 10;
|
||||
}
|
||||
else {
|
||||
/* extract location */
|
||||
copy_v3_v3(vec, tempmat[3]);
|
||||
axis = data->type - 20;
|
||||
}
|
||||
|
||||
BLI_assert((unsigned int)axis < 3);
|
||||
|
||||
/* Target defines the animation */
|
||||
s = (vec[axis] - data->min) / (data->max - data->min);
|
||||
}
|
||||
|
||||
BLI_assert((unsigned int)axis < 3);
|
||||
|
||||
/* Target defines the animation */
|
||||
s = (vec[axis] - data->min) / (data->max - data->min);
|
||||
CLAMP(s, 0, 1);
|
||||
t = (s * (data->end - data->start)) + data->start;
|
||||
const AnimationEvalContext anim_eval_context = BKE_animsys_eval_context_construct(depsgraph,
|
||||
|
@ -2734,7 +2740,7 @@ static void actcon_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *targ
|
|||
bActionConstraint *data = con->data;
|
||||
bConstraintTarget *ct = targets->first;
|
||||
|
||||
if (VALID_CONS_TARGET(ct)) {
|
||||
if (VALID_CONS_TARGET(ct) || data->flag & ACTCON_USE_EVAL_TIME) {
|
||||
switch (data->mix_mode) {
|
||||
case ACTCON_MIX_BEFORE:
|
||||
mul_m4_m4m4_aligned_scale(cob->matrix, ct->matrix, cob->matrix);
|
||||
|
|
|
@ -387,6 +387,11 @@ static void test_constraint(
|
|||
data->act = NULL;
|
||||
con->flag |= CONSTRAINT_DISABLE;
|
||||
}
|
||||
|
||||
/* Skip target checking if we're not using it */
|
||||
if (data->flag & ACTCON_USE_EVAL_TIME) {
|
||||
check_targets = false;
|
||||
}
|
||||
}
|
||||
else if (con->type == CONSTRAINT_TYPE_FOLLOWPATH) {
|
||||
bFollowPathConstraint *data = con->data;
|
||||
|
|
|
@ -337,7 +337,8 @@ typedef struct bActionConstraint {
|
|||
float max;
|
||||
int flag;
|
||||
char mix_mode;
|
||||
char _pad[7];
|
||||
char _pad[3];
|
||||
float eval_time; /* Only used when flag ACTCON_USE_EVAL_TIME is set. */
|
||||
struct bAction *act;
|
||||
/** MAX_ID_NAME-2. */
|
||||
char subtarget[64];
|
||||
|
@ -860,6 +861,8 @@ typedef enum eSameVolume_Mode {
|
|||
typedef enum eActionConstraint_Flags {
|
||||
/* Bones use "object" part of target action, instead of "same bone name" part */
|
||||
ACTCON_BONE_USE_OBJECT_ACTION = (1 << 0),
|
||||
/* Ignore the transform of 'tar' and use 'eval_time' instead: */
|
||||
ACTCON_USE_EVAL_TIME = (1 << 1),
|
||||
} eActionConstraint_Flags;
|
||||
|
||||
/* bActionConstraint.mix_mode */
|
||||
|
|
|
@ -1790,6 +1790,21 @@ static void rna_def_constraint_action(BlenderRNA *brna)
|
|||
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
|
||||
RNA_def_property_float_funcs(prop, NULL, NULL, "rna_ActionConstraint_minmax_range");
|
||||
|
||||
prop = RNA_def_property(srna, "eval_time", PROP_FLOAT, PROP_FACTOR);
|
||||
RNA_def_property_float_sdna(prop, NULL, "eval_time");
|
||||
RNA_def_property_range(prop, 0.f, 1.f);
|
||||
RNA_def_property_ui_text(
|
||||
prop, "Evaluation Time", "Interpolates between Action Start and End frames");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
|
||||
|
||||
prop = RNA_def_property(srna, "use_eval_time", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, NULL, "flag", ACTCON_USE_EVAL_TIME);
|
||||
RNA_def_property_ui_text(prop,
|
||||
"Use Evaluation Time",
|
||||
"Interpolate between Action Start and End frames, with the Evaluation "
|
||||
"Time slider instead of the Target object/bone");
|
||||
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
|
||||
|
||||
RNA_define_lib_overridable(false);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue