Copy Transforms: add a mixing mode option.
Allow combining location, rotation and scale at the same time, using one constraint. The mixing modes are based on matrix multiplication, but handle scale in a way that avoids creating shear. Reviewers: brecht Differential Revision: https://developer.blender.org/D5640
This commit is contained in:
parent
f4056e9ec3
commit
f8362836a5
@ -459,6 +459,8 @@ class ConstraintButtonsPanel:
|
|||||||
def COPY_TRANSFORMS(self, _context, layout, con):
|
def COPY_TRANSFORMS(self, _context, layout, con):
|
||||||
self.target_template(layout, con)
|
self.target_template(layout, con)
|
||||||
|
|
||||||
|
layout.prop(con, "mix_mode", text="Mix")
|
||||||
|
|
||||||
self.space_template(layout, con)
|
self.space_template(layout, con)
|
||||||
|
|
||||||
# def SCRIPT(self, context, layout, con):
|
# def SCRIPT(self, context, layout, con):
|
||||||
|
@ -2090,14 +2090,44 @@ static void translike_flush_tars(bConstraint *con, ListBase *list, bool no_copy)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void translike_evaluate(bConstraint *UNUSED(con), bConstraintOb *cob, ListBase *targets)
|
static void translike_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *targets)
|
||||||
{
|
{
|
||||||
|
bTransLikeConstraint *data = con->data;
|
||||||
bConstraintTarget *ct = targets->first;
|
bConstraintTarget *ct = targets->first;
|
||||||
|
|
||||||
if (VALID_CONS_TARGET(ct)) {
|
if (VALID_CONS_TARGET(ct)) {
|
||||||
|
if (data->mix_mode == TRANSLIKE_MIX_REPLACE) {
|
||||||
/* just copy the entire transform matrix of the target */
|
/* just copy the entire transform matrix of the target */
|
||||||
copy_m4_m4(cob->matrix, ct->matrix);
|
copy_m4_m4(cob->matrix, ct->matrix);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
float old_loc[3], old_rot[3][3], old_size[3];
|
||||||
|
float new_loc[3], new_rot[3][3], new_size[3];
|
||||||
|
|
||||||
|
/* Separate matrices so they can be combined in a way that avoids shear. */
|
||||||
|
mat4_to_loc_rot_size(old_loc, old_rot, old_size, cob->matrix);
|
||||||
|
mat4_to_loc_rot_size(new_loc, new_rot, new_size, ct->matrix);
|
||||||
|
|
||||||
|
switch (data->mix_mode) {
|
||||||
|
case TRANSLIKE_MIX_BEFORE:
|
||||||
|
mul_v3_m4v3(new_loc, ct->matrix, old_loc);
|
||||||
|
mul_m3_m3m3(new_rot, new_rot, old_rot);
|
||||||
|
mul_v3_v3(new_size, old_size);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TRANSLIKE_MIX_AFTER:
|
||||||
|
mul_v3_m4v3(new_loc, cob->matrix, new_loc);
|
||||||
|
mul_m3_m3m3(new_rot, old_rot, new_rot);
|
||||||
|
mul_v3_v3(new_size, old_size);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
BLI_assert(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
loc_rot_size_to_mat4(cob->matrix, new_loc, new_rot, new_size);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bConstraintTypeInfo CTI_TRANSLIKE = {
|
static bConstraintTypeInfo CTI_TRANSLIKE = {
|
||||||
|
@ -1335,6 +1335,15 @@ bool constraints_list_needinv(TransInfo *t, ListBase *list)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (con->type == CONSTRAINT_TYPE_TRANSLIKE) {
|
||||||
|
/* Copy Transforms constraint only does this in the Before mode. */
|
||||||
|
bTransLikeConstraint *data = (bTransLikeConstraint *)con->data;
|
||||||
|
|
||||||
|
if (ELEM(data->mix_mode, TRANSLIKE_MIX_BEFORE) &&
|
||||||
|
ELEM(t->mode, TFM_ROTATION, TFM_TRANSLATION)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (con->type == CONSTRAINT_TYPE_TRANSFORM) {
|
else if (con->type == CONSTRAINT_TYPE_TRANSFORM) {
|
||||||
/* Transform constraint needs it for rotation at least (r.57309),
|
/* Transform constraint needs it for rotation at least (r.57309),
|
||||||
* but doing so when translating may also mess things up [#36203]
|
* but doing so when translating may also mess things up [#36203]
|
||||||
|
@ -307,6 +307,8 @@ typedef struct bSameVolumeConstraint {
|
|||||||
/* Copy Transform Constraint */
|
/* Copy Transform Constraint */
|
||||||
typedef struct bTransLikeConstraint {
|
typedef struct bTransLikeConstraint {
|
||||||
struct Object *tar;
|
struct Object *tar;
|
||||||
|
char mix_mode;
|
||||||
|
char _pad[7];
|
||||||
/** MAX_ID_NAME-2. */
|
/** MAX_ID_NAME-2. */
|
||||||
char subtarget[64];
|
char subtarget[64];
|
||||||
} bTransLikeConstraint;
|
} bTransLikeConstraint;
|
||||||
@ -790,6 +792,16 @@ typedef enum eCopyScale_Flags {
|
|||||||
SIZELIKE_UNIFORM = (1 << 5),
|
SIZELIKE_UNIFORM = (1 << 5),
|
||||||
} eCopyScale_Flags;
|
} eCopyScale_Flags;
|
||||||
|
|
||||||
|
/* bTransLikeConstraint.mix_mode */
|
||||||
|
typedef enum eCopyTransforms_MixMode {
|
||||||
|
/* Replace rotation channel values. */
|
||||||
|
TRANSLIKE_MIX_REPLACE = 0,
|
||||||
|
/* Multiply the copied transformation on the left, with anti-shear scale handling. */
|
||||||
|
TRANSLIKE_MIX_BEFORE,
|
||||||
|
/* Multiply the copied transformation on the right, with anti-shear scale handling. */
|
||||||
|
TRANSLIKE_MIX_AFTER,
|
||||||
|
} eCopyTransforms_MixMode;
|
||||||
|
|
||||||
/* bTransformConstraint.to/from */
|
/* bTransformConstraint.to/from */
|
||||||
typedef enum eTransform_ToFrom {
|
typedef enum eTransform_ToFrom {
|
||||||
TRANS_LOCATION = 0,
|
TRANS_LOCATION = 0,
|
||||||
|
@ -1515,6 +1515,28 @@ static void rna_def_constraint_same_volume(BlenderRNA *brna)
|
|||||||
static void rna_def_constraint_transform_like(BlenderRNA *brna)
|
static void rna_def_constraint_transform_like(BlenderRNA *brna)
|
||||||
{
|
{
|
||||||
StructRNA *srna;
|
StructRNA *srna;
|
||||||
|
PropertyRNA *prop;
|
||||||
|
|
||||||
|
static const EnumPropertyItem mix_mode_items[] = {
|
||||||
|
{TRANSLIKE_MIX_REPLACE,
|
||||||
|
"REPLACE",
|
||||||
|
0,
|
||||||
|
"Replace",
|
||||||
|
"Replace the original transformation with copied"},
|
||||||
|
{TRANSLIKE_MIX_BEFORE,
|
||||||
|
"BEFORE",
|
||||||
|
0,
|
||||||
|
"Before Original",
|
||||||
|
"Apply copied transformation before original, as if the constraint target is a parent. "
|
||||||
|
"Scale is handled specially to avoid creating shear"},
|
||||||
|
{TRANSLIKE_MIX_AFTER,
|
||||||
|
"AFTER",
|
||||||
|
0,
|
||||||
|
"After Original",
|
||||||
|
"Apply copied transformation after original, as if the constraint target is a child. "
|
||||||
|
"Scale is handled specially to avoid creating shear"},
|
||||||
|
{0, NULL, 0, NULL, NULL},
|
||||||
|
};
|
||||||
|
|
||||||
srna = RNA_def_struct(brna, "CopyTransformsConstraint", "Constraint");
|
srna = RNA_def_struct(brna, "CopyTransformsConstraint", "Constraint");
|
||||||
RNA_def_struct_ui_text(
|
RNA_def_struct_ui_text(
|
||||||
@ -1527,6 +1549,13 @@ static void rna_def_constraint_transform_like(BlenderRNA *brna)
|
|||||||
RNA_def_struct_ui_icon(srna, ICON_CON_TRANSLIKE);
|
RNA_def_struct_ui_icon(srna, ICON_CON_TRANSLIKE);
|
||||||
|
|
||||||
rna_def_constraint_target_common(srna);
|
rna_def_constraint_target_common(srna);
|
||||||
|
|
||||||
|
prop = RNA_def_property(srna, "mix_mode", PROP_ENUM, PROP_NONE);
|
||||||
|
RNA_def_property_enum_sdna(prop, NULL, "mix_mode");
|
||||||
|
RNA_def_property_enum_items(prop, mix_mode_items);
|
||||||
|
RNA_def_property_ui_text(
|
||||||
|
prop, "Mix Mode", "Specify how the copied and existing transformations are combined");
|
||||||
|
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rna_def_constraint_minmax(BlenderRNA *brna)
|
static void rna_def_constraint_minmax(BlenderRNA *brna)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user