Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--release/scripts/startup/bl_ui/properties_constraint.py2
-rw-r--r--source/blender/blenkernel/intern/constraint.c66
-rw-r--r--source/blender/blenlib/BLI_math_matrix.h2
-rw-r--r--source/blender/blenlib/intern/math_matrix.c21
-rw-r--r--source/blender/editors/transform/transform_convert.c9
-rw-r--r--source/blender/makesdna/DNA_constraint_types.h12
-rw-r--r--source/blender/makesrna/intern/rna_constraint.c50
7 files changed, 128 insertions, 34 deletions
diff --git a/release/scripts/startup/bl_ui/properties_constraint.py b/release/scripts/startup/bl_ui/properties_constraint.py
index b75d67b5350..3fc54ff6d12 100644
--- a/release/scripts/startup/bl_ui/properties_constraint.py
+++ b/release/scripts/startup/bl_ui/properties_constraint.py
@@ -492,6 +492,8 @@ class ConstraintButtonsPanel:
col.prop(con, "frame_start", text="Start")
col.prop(con, "frame_end", text="End")
+ layout.prop(con, "mix_mode", text="Mix")
+
def LOCKED_TRACK(self, _context, layout, con):
self.target_template(layout, con)
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index c397fbcf115..a17a09297c5 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -2062,36 +2062,21 @@ static void translike_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t
bConstraintTarget *ct = targets->first;
if (VALID_CONS_TARGET(ct)) {
- if (data->mix_mode == TRANSLIKE_MIX_REPLACE) {
- /* just copy the entire transform matrix of the target */
- 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;
+ switch (data->mix_mode) {
+ case TRANSLIKE_MIX_REPLACE:
+ copy_m4_m4(cob->matrix, ct->matrix);
+ 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;
+ case TRANSLIKE_MIX_BEFORE:
+ mul_m4_m4m4_aligned_scale(cob->matrix, ct->matrix, cob->matrix);
+ break;
- default:
- BLI_assert(false);
- }
+ case TRANSLIKE_MIX_AFTER:
+ mul_m4_m4m4_aligned_scale(cob->matrix, cob->matrix, ct->matrix);
+ break;
- loc_rot_size_to_mat4(cob->matrix, new_loc, new_rot, new_size);
+ default:
+ BLI_assert(!"Unknown Copy Transforms mix mode");
}
}
}
@@ -2555,6 +2540,9 @@ static void actcon_new_data(void *cdata)
/* set type to 20 (Loc X), as 0 is Rot X for backwards compatibility */
data->type = 20;
+
+ /* Set the mix mode to After Original with anti-shear scale handling. */
+ data->mix_mode = ACTCON_MIX_AFTER;
}
static void actcon_id_looper(bConstraint *con, ConstraintIDFunc func, void *userdata)
@@ -2695,18 +2683,28 @@ static void actcon_get_tarmat(struct Depsgraph *UNUSED(depsgraph),
}
}
-static void actcon_evaluate(bConstraint *UNUSED(con), bConstraintOb *cob, ListBase *targets)
+static void actcon_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *targets)
{
+ bActionConstraint *data = con->data;
bConstraintTarget *ct = targets->first;
if (VALID_CONS_TARGET(ct)) {
- float temp[4][4];
+ switch (data->mix_mode) {
+ case ACTCON_MIX_BEFORE:
+ mul_m4_m4m4_aligned_scale(cob->matrix, ct->matrix, cob->matrix);
+ break;
- /* Nice and simple... we just need to multiply the matrices, as the get_target_matrix
- * function has already taken care of everything else.
- */
- copy_m4_m4(temp, cob->matrix);
- mul_m4_m4m4(cob->matrix, temp, ct->matrix);
+ case ACTCON_MIX_AFTER:
+ mul_m4_m4m4_aligned_scale(cob->matrix, cob->matrix, ct->matrix);
+ break;
+
+ case ACTCON_MIX_AFTER_FULL:
+ mul_m4_m4m4(cob->matrix, cob->matrix, ct->matrix);
+ break;
+
+ default:
+ BLI_assert(!"Unknown Action mix mode");
+ }
}
}
diff --git a/source/blender/blenlib/BLI_math_matrix.h b/source/blender/blenlib/BLI_math_matrix.h
index 814b13fa47f..ac0f5f44c74 100644
--- a/source/blender/blenlib/BLI_math_matrix.h
+++ b/source/blender/blenlib/BLI_math_matrix.h
@@ -205,6 +205,8 @@ void mul_transposed_m3_v3(const float M[3][3], float r[3]);
void mul_transposed_mat3_m4_v3(const float M[4][4], float r[3]);
void mul_m3_v3_double(const float M[3][3], double r[3]);
+void mul_m4_m4m4_aligned_scale(float R[4][4], const float A[4][4], const float B[4][4]);
+
void mul_m3_fl(float R[3][3], float f);
void mul_m4_fl(float R[4][4], float f);
void mul_mat3_m4_fl(float R[4][4], float f);
diff --git a/source/blender/blenlib/intern/math_matrix.c b/source/blender/blenlib/intern/math_matrix.c
index 5118d8a698e..4d8a2f72eca 100644
--- a/source/blender/blenlib/intern/math_matrix.c
+++ b/source/blender/blenlib/intern/math_matrix.c
@@ -1235,6 +1235,27 @@ bool invert_m4_m4(float inverse[4][4], const float mat[4][4])
#endif
}
+/**
+ * Combines transformations, handling scale separately in a manner equivalent
+ * to the Aligned Inherit Scale mode, in order to avoid creating shear.
+ * If A scale is uniform, the result is equivalent to ordinary multiplication.
+ */
+void mul_m4_m4m4_aligned_scale(float R[4][4], const float A[4][4], const float B[4][4])
+{
+ float loc_a[3], rot_a[3][3], size_a[3];
+ float loc_b[3], rot_b[3][3], size_b[3];
+ float loc_r[3], rot_r[3][3], size_r[3];
+
+ mat4_to_loc_rot_size(loc_a, rot_a, size_a, A);
+ mat4_to_loc_rot_size(loc_b, rot_b, size_b, B);
+
+ mul_v3_m4v3(loc_r, A, loc_b);
+ mul_m3_m3m3_uniq(rot_r, rot_a, rot_b);
+ mul_v3_v3v3(size_r, size_a, size_b);
+
+ loc_rot_size_to_mat4(R, loc_r, rot_r, size_r);
+}
+
/****************************** Linear Algebra *******************************/
void transpose_m3(float mat[3][3])
diff --git a/source/blender/editors/transform/transform_convert.c b/source/blender/editors/transform/transform_convert.c
index db8f36883f8..2001d42a5eb 100644
--- a/source/blender/editors/transform/transform_convert.c
+++ b/source/blender/editors/transform/transform_convert.c
@@ -1350,6 +1350,15 @@ bool constraints_list_needinv(TransInfo *t, ListBase *list)
return true;
}
}
+ else if (con->type == CONSTRAINT_TYPE_ACTION) {
+ /* The Action constraint only does this in the Before mode. */
+ bActionConstraint *data = (bActionConstraint *)con->data;
+
+ if (ELEM(data->mix_mode, ACTCON_MIX_BEFORE) &&
+ ELEM(t->mode, TFM_ROTATION, TFM_TRANSLATION)) {
+ return true;
+ }
+ }
else if (con->type == CONSTRAINT_TYPE_TRANSFORM) {
/* Transform constraint needs it for rotation at least (r.57309),
* but doing so when translating may also mess things up [#36203]
diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h
index 0baa11c3059..f816041010b 100644
--- a/source/blender/makesdna/DNA_constraint_types.h
+++ b/source/blender/makesdna/DNA_constraint_types.h
@@ -336,6 +336,8 @@ typedef struct bActionConstraint {
float min;
float max;
int flag;
+ char mix_mode;
+ char _pad[7];
struct bAction *act;
/** MAX_ID_NAME-2. */
char subtarget[64];
@@ -865,6 +867,16 @@ typedef enum eActionConstraint_Flags {
ACTCON_BONE_USE_OBJECT_ACTION = (1 << 0),
} eActionConstraint_Flags;
+/* bActionConstraint.mix_mode */
+typedef enum eActionConstraint_MixMode {
+ /* Multiply the action transformation on the right. */
+ ACTCON_MIX_AFTER_FULL = 0,
+ /* Multiply the action transformation on the right, with anti-shear scale handling. */
+ ACTCON_MIX_AFTER,
+ /* Multiply the action transformation on the left, with anti-shear scale handling. */
+ ACTCON_MIX_BEFORE,
+} eActionConstraint_MixMode;
+
/* Locked-Axis Values (Locked Track) */
typedef enum eLockAxis_Modes {
LOCK_X = 0,
diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c
index 6a10074810d..8e57de9baeb 100644
--- a/source/blender/makesrna/intern/rna_constraint.c
+++ b/source/blender/makesrna/intern/rna_constraint.c
@@ -633,6 +633,23 @@ static void rna_ArmatureConstraint_target_clear(ID *id, bConstraint *con, Main *
ED_object_constraint_dependency_tag_update(bmain, (Object *)id, con);
}
+static void rna_ActionConstraint_mix_mode_set(PointerRNA *ptr, int value)
+{
+ bConstraint *con = (bConstraint *)ptr->data;
+ bActionConstraint *acon = (bActionConstraint *)con->data;
+
+ acon->mix_mode = value;
+
+ /* The After mode can be computed in world space for efficiency
+ * and backward compatibility, while Before requires Local. */
+ if (ELEM(value, ACTCON_MIX_AFTER, ACTCON_MIX_AFTER_FULL)) {
+ con->ownspace = CONSTRAINT_SPACE_WORLD;
+ }
+ else {
+ con->ownspace = CONSTRAINT_SPACE_LOCAL;
+ }
+}
+
static void rna_ActionConstraint_minmax_range(
PointerRNA *ptr, float *min, float *max, float *UNUSED(softmin), float *UNUSED(softmax))
{
@@ -1618,6 +1635,29 @@ static void rna_def_constraint_action(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL},
};
+ static const EnumPropertyItem mix_mode_items[] = {
+ {ACTCON_MIX_BEFORE,
+ "BEFORE",
+ 0,
+ "Before Original",
+ "Apply the action channels before the original transformation, "
+ "as if applied to an imaginary parent with Aligned Inherit Scale"},
+ {ACTCON_MIX_AFTER,
+ "AFTER",
+ 0,
+ "After Original",
+ "Apply the action channels after the original transformation, "
+ "as if applied to an imaginary child with Aligned Inherit Scale"},
+ {ACTCON_MIX_AFTER_FULL,
+ "AFTER_FULL",
+ 0,
+ "After Original (Full Scale)",
+ "Apply the action channels after the original transformation, as if "
+ "applied to an imaginary child with Full Inherit Scale. This mode "
+ "can create shear and is provided only for backward compatibility"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
srna = RNA_def_struct(brna, "ActionConstraint", "Constraint");
RNA_def_struct_ui_text(
srna, "Action Constraint", "Map an action to the transform axes of a bone");
@@ -1626,6 +1666,16 @@ static void rna_def_constraint_action(BlenderRNA *brna)
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_enum_funcs(prop, NULL, "rna_ActionConstraint_mix_mode_set", NULL);
+ RNA_def_property_ui_text(
+ prop,
+ "Mix Mode",
+ "Specify how existing transformations and the action channels are combined");
+ RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
prop = RNA_def_property(srna, "transform_channel", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "type");
RNA_def_property_enum_items(prop, transform_channel_items);