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.c65
-rw-r--r--source/blender/blenlib/BLI_math_matrix.h6
-rw-r--r--source/blender/blenlib/intern/math_matrix.c16
-rw-r--r--source/blender/blenloader/intern/versioning_280.c23
-rw-r--r--source/blender/editors/transform/transform_convert.c3
-rw-r--r--source/blender/makesdna/DNA_constraint_types.h19
-rw-r--r--source/blender/makesrna/intern/rna_constraint.c54
8 files changed, 169 insertions, 19 deletions
diff --git a/release/scripts/startup/bl_ui/properties_constraint.py b/release/scripts/startup/bl_ui/properties_constraint.py
index 0ba9fd0630c..ac1ebedeba4 100644
--- a/release/scripts/startup/bl_ui/properties_constraint.py
+++ b/release/scripts/startup/bl_ui/properties_constraint.py
@@ -392,7 +392,7 @@ class ConstraintButtonsPanel:
sub.active = con.use_z
sub.prop(con, "invert_z", text="Invert")
- layout.prop(con, "use_offset")
+ layout.prop(con, "mix_mode", text="Mix")
self.space_template(layout, con)
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index ccacb85651c..803aae76422 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -1802,12 +1802,10 @@ static void rotlike_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *tar
bConstraintTarget *ct = targets->first;
if (VALID_CONS_TARGET(ct)) {
- float loc[3];
- float eul[3], obeul[3];
- float size[3];
+ float loc[3], size[3], oldrot[3][3], newrot[3][3];
+ float eul[3], obeul[3], defeul[3];
- copy_v3_v3(loc, cob->matrix[3]);
- mat4_to_size(size, cob->matrix);
+ mat4_to_loc_rot_size(loc, oldrot, size, cob->matrix);
/* Select the Euler rotation order, defaulting to the owner. */
short rot_order = cob->rotOrder;
@@ -1822,11 +1820,28 @@ static void rotlike_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *tar
* some of them can be modified below (see bug T21875). */
mat4_to_compatible_eulO(eul, obeul, rot_order, ct->matrix);
+ /* Prepare the copied euler rotation. */
+ bool legacy_offset = false;
+
+ switch (data->mix_mode) {
+ case ROTLIKE_MIX_OFFSET:
+ legacy_offset = true;
+ copy_v3_v3(defeul, obeul);
+ break;
+
+ case ROTLIKE_MIX_REPLACE:
+ copy_v3_v3(defeul, obeul);
+ break;
+
+ default:
+ zero_v3(defeul);
+ }
+
if ((data->flag & ROTLIKE_X) == 0) {
- eul[0] = obeul[0];
+ eul[0] = defeul[0];
}
else {
- if (data->flag & ROTLIKE_OFFSET) {
+ if (legacy_offset) {
rotate_eulO(eul, rot_order, 'X', obeul[0]);
}
@@ -1836,10 +1851,10 @@ static void rotlike_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *tar
}
if ((data->flag & ROTLIKE_Y) == 0) {
- eul[1] = obeul[1];
+ eul[1] = defeul[1];
}
else {
- if (data->flag & ROTLIKE_OFFSET) {
+ if (legacy_offset) {
rotate_eulO(eul, rot_order, 'Y', obeul[1]);
}
@@ -1849,10 +1864,10 @@ static void rotlike_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *tar
}
if ((data->flag & ROTLIKE_Z) == 0) {
- eul[2] = obeul[2];
+ eul[2] = defeul[2];
}
else {
- if (data->flag & ROTLIKE_OFFSET) {
+ if (legacy_offset) {
rotate_eulO(eul, rot_order, 'Z', obeul[2]);
}
@@ -1861,10 +1876,36 @@ static void rotlike_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *tar
}
}
+ /* Add the euler components together if needed. */
+ if (data->mix_mode == ROTLIKE_MIX_ADD) {
+ add_v3_v3(eul, obeul);
+ }
+
/* Good to make eulers compatible again,
* since we don't know how much they were changed above. */
compatible_eul(eul, obeul);
- loc_eulO_size_to_mat4(cob->matrix, loc, eul, size, rot_order);
+ eulO_to_mat3(newrot, eul, rot_order);
+
+ /* Mix the rotation matrices: */
+ switch (data->mix_mode) {
+ case ROTLIKE_MIX_REPLACE:
+ case ROTLIKE_MIX_OFFSET:
+ case ROTLIKE_MIX_ADD:
+ break;
+
+ case ROTLIKE_MIX_BEFORE:
+ mul_m3_m3m3(newrot, newrot, oldrot);
+ break;
+
+ case ROTLIKE_MIX_AFTER:
+ mul_m3_m3m3(newrot, oldrot, newrot);
+ break;
+
+ default:
+ BLI_assert(false);
+ }
+
+ loc_rot_size_to_mat4(cob->matrix, loc, newrot, size);
}
}
diff --git a/source/blender/blenlib/BLI_math_matrix.h b/source/blender/blenlib/BLI_math_matrix.h
index 00c301a01bc..814b13fa47f 100644
--- a/source/blender/blenlib/BLI_math_matrix.h
+++ b/source/blender/blenlib/BLI_math_matrix.h
@@ -310,7 +310,7 @@ void mat4_to_size_fix_shear(float r[3], const float M[4][4]);
void translate_m4(float mat[4][4], float tx, float ty, float tz);
void rotate_m4(float mat[4][4], const char axis, const float angle);
-void rescale_m4(float mat[4][4], float scale[3]);
+void rescale_m4(float mat[4][4], const float scale[3]);
void transform_pivot_set_m4(float mat[4][4], const float pivot[3]);
void mat3_to_rot_size(float rot[3][3], float size[3], const float mat3[3][3]);
@@ -320,6 +320,10 @@ void mat4_decompose(float loc[3], float quat[4], float size[3], const float wmat
void mat3_polar_decompose(const float mat3[3][3], float r_U[3][3], float r_P[3][3]);
+void loc_rot_size_to_mat4(float R[4][4],
+ const float loc[3],
+ const float rot[3][3],
+ const float size[3]);
void loc_eul_size_to_mat4(float R[4][4],
const float loc[3],
const float eul[3],
diff --git a/source/blender/blenlib/intern/math_matrix.c b/source/blender/blenlib/intern/math_matrix.c
index 7c1b44978e2..e9d196ccdbb 100644
--- a/source/blender/blenlib/intern/math_matrix.c
+++ b/source/blender/blenlib/intern/math_matrix.c
@@ -2164,7 +2164,7 @@ void rotate_m4(float mat[4][4], const char axis, const float angle)
}
/** Scale a matrix in-place. */
-void rescale_m4(float mat[4][4], float scale[3])
+void rescale_m4(float mat[4][4], const float scale[3])
{
mul_v3_fl(mat[0], scale[0]);
mul_v3_fl(mat[1], scale[1]);
@@ -2359,6 +2359,20 @@ bool equals_m4m4(const float mat1[4][4], const float mat2[4][4])
/**
* Make a 4x4 matrix out of 3 transform components.
* Matrices are made in the order: `scale * rot * loc`
+ */
+void loc_rot_size_to_mat4(float mat[4][4],
+ const float loc[3],
+ const float rot[3][3],
+ const float size[3])
+{
+ copy_m4_m3(mat, rot);
+ rescale_m4(mat, size);
+ copy_v3_v3(mat[3], loc);
+}
+
+/**
+ * Make a 4x4 matrix out of 3 transform components.
+ * Matrices are made in the order: `scale * rot * loc`
*
* TODO: need to have a version that allows for rotation order...
*/
diff --git a/source/blender/blenloader/intern/versioning_280.c b/source/blender/blenloader/intern/versioning_280.c
index 54d2bd8499f..0d108704b4e 100644
--- a/source/blender/blenloader/intern/versioning_280.c
+++ b/source/blender/blenloader/intern/versioning_280.c
@@ -727,6 +727,17 @@ static void do_version_constraints_copy_scale_power(ListBase *lb)
}
}
+static void do_version_constraints_copy_rotation_mix_mode(ListBase *lb)
+{
+ for (bConstraint *con = lb->first; con; con = con->next) {
+ if (con->type == CONSTRAINT_TYPE_ROTLIKE) {
+ bRotateLikeConstraint *data = (bRotateLikeConstraint *)con->data;
+ data->mix_mode = (data->flag & ROTLIKE_OFFSET) ? ROTLIKE_MIX_OFFSET : ROTLIKE_MIX_REPLACE;
+ data->flag &= ~ROTLIKE_OFFSET;
+ }
+ }
+}
+
static void do_versions_seq_alloc_transform_and_crop(ListBase *seqbase)
{
for (Sequence *seq = seqbase->first; seq != NULL; seq = seq->next) {
@@ -3797,5 +3808,17 @@ void blo_do_versions_280(FileData *fd, Library *UNUSED(lib), Main *bmain)
do_version_bones_inherit_scale(&arm->bonebase);
}
}
+
+ /* Convert the Offset flag to the mix mode enum. */
+ if (!DNA_struct_elem_find(fd->filesdna, "bRotateLikeConstraint", "char", "mix_mode")) {
+ LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
+ do_version_constraints_copy_rotation_mix_mode(&ob->constraints);
+ if (ob->pose) {
+ LISTBASE_FOREACH (bPoseChannel *, pchan, &ob->pose->chanbase) {
+ do_version_constraints_copy_rotation_mix_mode(&pchan->constraints);
+ }
+ }
+ }
+ }
}
}
diff --git a/source/blender/editors/transform/transform_convert.c b/source/blender/editors/transform/transform_convert.c
index 69bc6afd23f..14eee2318cd 100644
--- a/source/blender/editors/transform/transform_convert.c
+++ b/source/blender/editors/transform/transform_convert.c
@@ -1330,7 +1330,8 @@ bool constraints_list_needinv(TransInfo *t, ListBase *list)
/* CopyRot constraint only does this when rotating, and offset is on */
bRotateLikeConstraint *data = (bRotateLikeConstraint *)con->data;
- if ((data->flag & ROTLIKE_OFFSET) && (t->mode == TFM_ROTATION)) {
+ if (ELEM(data->mix_mode, ROTLIKE_MIX_OFFSET, ROTLIKE_MIX_BEFORE) &&
+ ELEM(t->mode, TFM_ROTATION)) {
return true;
}
}
diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h
index 42d58cb34d0..a7f900ddc9b 100644
--- a/source/blender/makesdna/DNA_constraint_types.h
+++ b/source/blender/makesdna/DNA_constraint_types.h
@@ -272,7 +272,8 @@ typedef struct bRotateLikeConstraint {
struct Object *tar;
int flag;
char euler_order;
- char _pad[3];
+ char mix_mode;
+ char _pad[2];
/** MAX_ID_NAME-2. */
char subtarget[64];
} bRotateLikeConstraint;
@@ -747,9 +748,25 @@ typedef enum eCopyRotation_Flags {
ROTLIKE_X_INVERT = (1 << 4),
ROTLIKE_Y_INVERT = (1 << 5),
ROTLIKE_Z_INVERT = (1 << 6),
+#ifdef DNA_DEPRECATED
ROTLIKE_OFFSET = (1 << 7),
+#endif
} eCopyRotation_Flags;
+/* bRotateLikeConstraint.mix_mode */
+typedef enum eCopyRotation_MixMode {
+ /* Replace rotation channel values. */
+ ROTLIKE_MIX_REPLACE = 0,
+ /* Legacy Offset mode - don't use. */
+ ROTLIKE_MIX_OFFSET,
+ /* Add Euler components together. */
+ ROTLIKE_MIX_ADD,
+ /* Multiply the copied rotation on the left. */
+ ROTLIKE_MIX_BEFORE,
+ /* Multiply the copied rotation on the right. */
+ ROTLIKE_MIX_AFTER,
+} eCopyRotation_MixMode;
+
/* bLocateLikeConstraint.flag */
typedef enum eCopyLocation_Flags {
LOCLIKE_X = (1 << 0),
diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c
index 05154dcc20e..79e38717569 100644
--- a/source/blender/makesrna/intern/rna_constraint.c
+++ b/source/blender/makesrna/intern/rna_constraint.c
@@ -530,6 +530,24 @@ static void rna_Constraint_ik_type_set(struct PointerRNA *ptr, int value)
}
}
+/* DEPRECATED: use_offset replaced with mix_mode */
+static bool rna_Constraint_RotLike_use_offset_get(struct PointerRNA *ptr)
+{
+ bConstraint *con = ptr->data;
+ bRotateLikeConstraint *rotlike = con->data;
+ return rotlike->mix_mode != ROTLIKE_MIX_REPLACE;
+}
+
+static void rna_Constraint_RotLike_use_offset_set(struct PointerRNA *ptr, bool value)
+{
+ bConstraint *con = ptr->data;
+ bRotateLikeConstraint *rotlike = con->data;
+ bool curval = (rotlike->mix_mode != ROTLIKE_MIX_REPLACE);
+ if (curval != value) {
+ rotlike->mix_mode = (value ? ROTLIKE_MIX_OFFSET : ROTLIKE_MIX_REPLACE);
+ }
+}
+
static const EnumPropertyItem *rna_Constraint_owner_space_itemf(bContext *UNUSED(C),
PointerRNA *ptr,
PropertyRNA *UNUSED(prop),
@@ -1298,6 +1316,28 @@ static void rna_def_constraint_rotate_like(BlenderRNA *brna)
StructRNA *srna;
PropertyRNA *prop;
+ static const EnumPropertyItem mix_mode_items[] = {
+ {ROTLIKE_MIX_REPLACE, "REPLACE", 0, "Replace", "Replace the original rotation with copied"},
+ {ROTLIKE_MIX_ADD, "ADD", 0, "Add", "Add euler component values together"},
+ {ROTLIKE_MIX_BEFORE,
+ "BEFORE",
+ 0,
+ "Before Original",
+ "Apply copied rotation before original, as if the constraint target is a parent"},
+ {ROTLIKE_MIX_AFTER,
+ "AFTER",
+ 0,
+ "After Original",
+ "Apply copied rotation after original, as if the constraint target is a child"},
+ {ROTLIKE_MIX_OFFSET,
+ "OFFSET",
+ 0,
+ "Offset (Legacy)",
+ "Combine rotations like the original Offset checkbox. Does not work well for "
+ "multiple axis rotations"},
+ {0, NULL, 0, NULL, NULL},
+ };
+
srna = RNA_def_struct(brna, "CopyRotationConstraint", "Constraint");
RNA_def_struct_ui_text(srna, "Copy Rotation Constraint", "Copy the rotation of the target");
RNA_def_struct_sdna_from(srna, "bRotateLikeConstraint", "data");
@@ -1341,9 +1381,19 @@ static void rna_def_constraint_rotate_like(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Euler Order", "Explicitly specify the euler rotation order");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+ 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 rotations are combined");
+ RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ /* DEPRECATED: replaced with mix_mode */
prop = RNA_def_property(srna, "use_offset", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", ROTLIKE_OFFSET);
- RNA_def_property_ui_text(prop, "Offset", "Add original rotation into copied rotation");
+ RNA_def_property_boolean_funcs(
+ prop, "rna_Constraint_RotLike_use_offset_get", "rna_Constraint_RotLike_use_offset_set");
+ RNA_def_property_ui_text(
+ prop, "Offset", "DEPRECATED: Add original rotation into copied rotation");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
}