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.py8
-rw-r--r--source/blender/blenkernel/BKE_fcurve.h3
-rw-r--r--source/blender/blenkernel/intern/constraint.c37
-rw-r--r--source/blender/blenkernel/intern/fcurve.c68
-rw-r--r--source/blender/makesdna/DNA_constraint_types.h24
-rw-r--r--source/blender/makesrna/RNA_enum_types.h1
-rw-r--r--source/blender/makesrna/intern/rna_constraint.c29
-rw-r--r--source/blender/makesrna/intern/rna_fcurve.c26
8 files changed, 154 insertions, 42 deletions
diff --git a/release/scripts/startup/bl_ui/properties_constraint.py b/release/scripts/startup/bl_ui/properties_constraint.py
index d8eb0db62fc..0ba9fd0630c 100644
--- a/release/scripts/startup/bl_ui/properties_constraint.py
+++ b/release/scripts/startup/bl_ui/properties_constraint.py
@@ -370,6 +370,8 @@ class ConstraintButtonsPanel:
def COPY_ROTATION(self, _context, layout, con):
self.target_template(layout, con)
+ layout.prop(con, "euler_order", text="Order")
+
split = layout.split()
col = split.column()
@@ -685,6 +687,9 @@ class ConstraintButtonsPanel:
col.row().label(text="Source:")
col.row().prop(con, "map_from", expand=True)
+ if con.map_from == 'ROTATION':
+ layout.prop(con, "from_rotation_mode", text="Mode")
+
split = layout.split()
ext = "" if con.map_from == 'LOCATION' else "_rot" if con.map_from == 'ROTATION' else "_scale"
@@ -727,6 +732,9 @@ class ConstraintButtonsPanel:
col.label(text="Destination:")
col.row().prop(con, "map_to", expand=True)
+ if con.map_to == 'ROTATION':
+ layout.prop(con, "to_euler_order", text="Order")
+
split = layout.split()
ext = "" if con.map_to == 'LOCATION' else "_rot" if con.map_to == 'ROTATION' else "_scale"
diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h
index 4c1a115eb23..5be9a35b168 100644
--- a/source/blender/blenkernel/BKE_fcurve.h
+++ b/source/blender/blenkernel/BKE_fcurve.h
@@ -89,6 +89,9 @@ struct ChannelDriver *fcurve_copy_driver(const struct ChannelDriver *driver);
void driver_variables_copy(struct ListBase *dst_list, const struct ListBase *src_list);
+void BKE_driver_target_matrix_to_rot_channels(
+ float mat[4][4], int auto_order, int rotation_mode, int channel, bool angles, float r_buf[4]);
+
void driver_free_variable(struct ListBase *variables, struct DriverVar *dvar);
void driver_free_variable_ex(struct ChannelDriver *driver, struct DriverVar *dvar);
diff --git a/source/blender/blenkernel/intern/constraint.c b/source/blender/blenkernel/intern/constraint.c
index 1a3c562941e..ccacb85651c 100644
--- a/source/blender/blenkernel/intern/constraint.c
+++ b/source/blender/blenkernel/intern/constraint.c
@@ -62,6 +62,7 @@
#include "BKE_deform.h"
#include "BKE_displist.h"
#include "BKE_editmesh.h"
+#include "BKE_fcurve.h"
#include "BKE_global.h"
#include "BKE_idprop.h"
#include "BKE_library.h"
@@ -1808,18 +1809,25 @@ static void rotlike_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *tar
copy_v3_v3(loc, cob->matrix[3]);
mat4_to_size(size, cob->matrix);
+ /* Select the Euler rotation order, defaulting to the owner. */
+ short rot_order = cob->rotOrder;
+
+ if (data->euler_order != CONSTRAINT_EULER_AUTO) {
+ rot_order = data->euler_order;
+ }
+
/* To allow compatible rotations, must get both rotations in the order of the owner... */
- mat4_to_eulO(obeul, cob->rotOrder, cob->matrix);
+ mat4_to_eulO(obeul, rot_order, cob->matrix);
/* We must get compatible eulers from the beginning because
* some of them can be modified below (see bug T21875). */
- mat4_to_compatible_eulO(eul, obeul, cob->rotOrder, ct->matrix);
+ mat4_to_compatible_eulO(eul, obeul, rot_order, ct->matrix);
if ((data->flag & ROTLIKE_X) == 0) {
eul[0] = obeul[0];
}
else {
if (data->flag & ROTLIKE_OFFSET) {
- rotate_eulO(eul, cob->rotOrder, 'X', obeul[0]);
+ rotate_eulO(eul, rot_order, 'X', obeul[0]);
}
if (data->flag & ROTLIKE_X_INVERT) {
@@ -1832,7 +1840,7 @@ static void rotlike_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *tar
}
else {
if (data->flag & ROTLIKE_OFFSET) {
- rotate_eulO(eul, cob->rotOrder, 'Y', obeul[1]);
+ rotate_eulO(eul, rot_order, 'Y', obeul[1]);
}
if (data->flag & ROTLIKE_Y_INVERT) {
@@ -1845,7 +1853,7 @@ static void rotlike_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *tar
}
else {
if (data->flag & ROTLIKE_OFFSET) {
- rotate_eulO(eul, cob->rotOrder, 'Z', obeul[2]);
+ rotate_eulO(eul, rot_order, 'Z', obeul[2]);
}
if (data->flag & ROTLIKE_Z_INVERT) {
@@ -1856,7 +1864,7 @@ static void rotlike_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *tar
/* 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, cob->rotOrder);
+ loc_eulO_size_to_mat4(cob->matrix, loc, eul, size, rot_order);
}
}
@@ -3719,7 +3727,8 @@ static void transform_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t
if (VALID_CONS_TARGET(ct)) {
float *from_min, *from_max, *to_min, *to_max;
float loc[3], eul[3], size[3];
- float dvec[3], sval[3];
+ float dbuf[4], sval[3];
+ float *const dvec = dbuf + 1;
int i;
/* obtain target effect */
@@ -3738,7 +3747,8 @@ static void transform_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t
from_max = data->from_max_scale;
break;
case TRANS_ROTATION:
- mat4_to_eulO(dvec, cob->rotOrder, ct->matrix);
+ BKE_driver_target_matrix_to_rot_channels(
+ ct->matrix, cob->rotOrder, data->from_rotation_mode, -1, true, dbuf);
from_min = data->from_min_rot;
from_max = data->from_max_rot;
break;
@@ -3750,9 +3760,16 @@ static void transform_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t
break;
}
+ /* Select the output Euler rotation order, defaulting to the owner. */
+ short rot_order = cob->rotOrder;
+
+ if (data->to == TRANS_ROTATION && data->to_euler_order != CONSTRAINT_EULER_AUTO) {
+ rot_order = data->to_euler_order;
+ }
+
/* extract components of owner's matrix */
copy_v3_v3(loc, cob->matrix[3]);
- mat4_to_eulO(eul, cob->rotOrder, cob->matrix);
+ mat4_to_eulO(eul, rot_order, cob->matrix);
mat4_to_size(size, cob->matrix);
/* determine where in range current transforms lie */
@@ -3811,7 +3828,7 @@ static void transform_evaluate(bConstraint *con, bConstraintOb *cob, ListBase *t
}
/* apply to matrix */
- loc_eulO_size_to_mat4(cob->matrix, loc, eul, size, cob->rotOrder);
+ loc_eulO_size_to_mat4(cob->matrix, loc, eul, size, rot_order);
}
}
diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c
index ef53c926daa..c4da2d2efc9 100644
--- a/source/blender/blenkernel/intern/fcurve.c
+++ b/source/blender/blenkernel/intern/fcurve.c
@@ -1732,35 +1732,21 @@ static float dvar_eval_transChan(ChannelDriver *driver, DriverVar *dvar)
* - only an option for "transform space", if quality is really bad with a)
*/
float quat[4];
- float *const eul = quat + 1;
int channel;
if (dtar->transChan == DTAR_TRANSCHAN_ROTW) {
channel = 0;
- quat[0] = 0.0f;
}
else {
channel = 1 + dtar->transChan - DTAR_TRANSCHAN_ROTX;
BLI_assert(channel < 4);
}
- if (dtar->rotation_mode == DTAR_ROTMODE_AUTO) {
- mat4_to_eulO(eul, rot_order, mat);
+ BKE_driver_target_matrix_to_rot_channels(
+ mat, rot_order, dtar->rotation_mode, channel, false, quat);
- if (use_eulers) {
- compatible_eul(eul, oldEul);
- }
- }
- else if (dtar->rotation_mode >= DTAR_ROTMODE_EULER_MIN &&
- dtar->rotation_mode <= DTAR_ROTMODE_EULER_MAX) {
- mat4_to_eulO(eul, dtar->rotation_mode, mat);
- }
- else if (dtar->rotation_mode == DTAR_ROTMODE_QUATERNION) {
- mat4_to_quat(quat, mat);
- }
- else {
- BLI_assert(false);
- zero_v3(eul);
+ if (use_eulers && dtar->rotation_mode == DTAR_ROTMODE_AUTO) {
+ compatible_eul(quat + 1, oldEul);
}
return quat[channel];
@@ -1771,6 +1757,52 @@ static float dvar_eval_transChan(ChannelDriver *driver, DriverVar *dvar)
}
}
+/* Convert a quaternion to pseudo-angles representing the weighted amount of rotation. */
+static void quaternion_to_angles(float quat[4], int channel)
+{
+ if (channel < 0) {
+ quat[0] = 2.0f * saacosf(quat[0]);
+
+ for (int i = 1; i < 4; i++) {
+ quat[i] = 2.0f * saasinf(quat[i]);
+ }
+ }
+ else if (channel == 0) {
+ quat[0] = 2.0f * saacosf(quat[0]);
+ }
+ else {
+ quat[channel] = 2.0f * saasinf(quat[channel]);
+ }
+}
+
+/* Compute channel values for a rotational Transform Channel driver variable. */
+void BKE_driver_target_matrix_to_rot_channels(
+ float mat[4][4], int auto_order, int rotation_mode, int channel, bool angles, float r_buf[4])
+{
+ float *const quat = r_buf;
+ float *const eul = r_buf + 1;
+
+ zero_v4(r_buf);
+
+ if (rotation_mode == DTAR_ROTMODE_AUTO) {
+ mat4_to_eulO(eul, auto_order, mat);
+ }
+ else if (rotation_mode >= DTAR_ROTMODE_EULER_MIN && rotation_mode <= DTAR_ROTMODE_EULER_MAX) {
+ mat4_to_eulO(eul, rotation_mode, mat);
+ }
+ else if (rotation_mode == DTAR_ROTMODE_QUATERNION) {
+ mat4_to_quat(quat, mat);
+
+ /* For Transformation constraint convenience, convert to pseudo-angles. */
+ if (angles) {
+ quaternion_to_angles(quat, channel);
+ }
+ }
+ else {
+ BLI_assert(false);
+ }
+}
+
/* ......... */
/* Table of Driver Variable Type Info Data */
diff --git a/source/blender/makesdna/DNA_constraint_types.h b/source/blender/makesdna/DNA_constraint_types.h
index 17ce279f1b7..42d58cb34d0 100644
--- a/source/blender/makesdna/DNA_constraint_types.h
+++ b/source/blender/makesdna/DNA_constraint_types.h
@@ -271,7 +271,8 @@ typedef struct bTrackToConstraint {
typedef struct bRotateLikeConstraint {
struct Object *tar;
int flag;
- int reserved1;
+ char euler_order;
+ char _pad[3];
/** MAX_ID_NAME-2. */
char subtarget[64];
} bRotateLikeConstraint;
@@ -441,6 +442,13 @@ typedef struct bTransformConstraint {
/** Extrapolate motion? if 0, confine to ranges. */
char expo;
+ /** Input rotation type - uses the same values as driver targets. */
+ char from_rotation_mode;
+ /** Output euler order override. */
+ char to_euler_order;
+
+ char _pad[6];
+
/** From_min/max defines range of target transform. */
float from_min[3];
/** To map on to to_min/max range. */
@@ -715,6 +723,20 @@ typedef enum eConstraintChannel_Flags {
CONSTRAINT_CHANNEL_PROTECTED = (1 << 1),
} eConstraintChannel_Flags;
+/* Common enum for constraints that support override. */
+typedef enum eConstraint_EulerOrder {
+ /** Automatic euler mode. */
+ CONSTRAINT_EULER_AUTO = 0,
+
+ /** Explicit euler rotation modes - must sync with BLI_math_rotation.h defines. */
+ CONSTRAINT_EULER_XYZ = 1,
+ CONSTRAINT_EULER_XZY,
+ CONSTRAINT_EULER_YXZ,
+ CONSTRAINT_EULER_YZX,
+ CONSTRAINT_EULER_ZXY,
+ CONSTRAINT_EULER_ZYX,
+} eConstraint_EulerOrder;
+
/* -------------------------------------- */
/* bRotateLikeConstraint.flag */
diff --git a/source/blender/makesrna/RNA_enum_types.h b/source/blender/makesrna/RNA_enum_types.h
index 02aaef44a1f..b3e1f22f413 100644
--- a/source/blender/makesrna/RNA_enum_types.h
+++ b/source/blender/makesrna/RNA_enum_types.h
@@ -91,6 +91,7 @@ extern const EnumPropertyItem rna_enum_beztriple_keyframe_type_items[];
extern const EnumPropertyItem rna_enum_beztriple_interpolation_mode_items[];
extern const EnumPropertyItem rna_enum_beztriple_interpolation_easing_items[];
extern const EnumPropertyItem rna_enum_keyframe_handle_type_items[];
+extern const EnumPropertyItem rna_enum_driver_target_rotation_mode_items[];
extern const EnumPropertyItem rna_enum_keyblock_type_items[];
diff --git a/source/blender/makesrna/intern/rna_constraint.c b/source/blender/makesrna/intern/rna_constraint.c
index 539e2a66296..05154dcc20e 100644
--- a/source/blender/makesrna/intern/rna_constraint.c
+++ b/source/blender/makesrna/intern/rna_constraint.c
@@ -256,6 +256,17 @@ static const EnumPropertyItem track_axis_items[] = {
{0, NULL, 0, NULL, NULL},
};
+static const EnumPropertyItem euler_order_items[] = {
+ {CONSTRAINT_EULER_AUTO, "AUTO", 0, "Default", "Euler using the default rotation order"},
+ {CONSTRAINT_EULER_XYZ, "XYZ", 0, "XYZ Euler", "Euler using the XYZ rotation order"},
+ {CONSTRAINT_EULER_XZY, "XZY", 0, "XZY Euler", "Euler using the XZY rotation order"},
+ {CONSTRAINT_EULER_YXZ, "YXZ", 0, "YXZ Euler", "Euler using the YXZ rotation order"},
+ {CONSTRAINT_EULER_YZX, "YZX", 0, "YZX Euler", "Euler using the YZX rotation order"},
+ {CONSTRAINT_EULER_ZXY, "ZXY", 0, "ZXY Euler", "Euler using the ZXY rotation order"},
+ {CONSTRAINT_EULER_ZYX, "ZYX", 0, "ZYX Euler", "Euler using the ZYX rotation order"},
+ {0, NULL, 0, NULL, NULL},
+};
+
#ifdef RNA_RUNTIME
static const EnumPropertyItem space_object_items[] = {
@@ -1324,6 +1335,12 @@ static void rna_def_constraint_rotate_like(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Invert Z", "Invert the Z rotation");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+ prop = RNA_def_property(srna, "euler_order", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "euler_order");
+ RNA_def_property_enum_items(prop, euler_order_items);
+ 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, "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");
@@ -1885,6 +1902,18 @@ static void rna_def_constraint_transform(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Extrapolate Motion", "Extrapolate ranges");
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+ prop = RNA_def_property(srna, "from_rotation_mode", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "from_rotation_mode");
+ RNA_def_property_enum_items(prop, rna_enum_driver_target_rotation_mode_items);
+ RNA_def_property_ui_text(prop, "From Mode", "Specify the type of rotation channels to use");
+ RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
+ prop = RNA_def_property(srna, "to_euler_order", PROP_ENUM, PROP_NONE);
+ RNA_def_property_enum_sdna(prop, NULL, "to_euler_order");
+ RNA_def_property_enum_items(prop, euler_order_items);
+ RNA_def_property_ui_text(prop, "To Order", "Explicitly specify the output euler rotation order");
+ RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
+
/* Loc */
prop = RNA_def_property(srna, "from_min_x", PROP_FLOAT, PROP_DISTANCE);
RNA_def_property_float_sdna(prop, NULL, "from_min[0]");
diff --git a/source/blender/makesrna/intern/rna_fcurve.c b/source/blender/makesrna/intern/rna_fcurve.c
index 684c786b1b9..b6b759882b3 100644
--- a/source/blender/makesrna/intern/rna_fcurve.c
+++ b/source/blender/makesrna/intern/rna_fcurve.c
@@ -132,6 +132,18 @@ const EnumPropertyItem rna_enum_beztriple_interpolation_easing_items[] = {
{0, NULL, 0, NULL, NULL},
};
+const EnumPropertyItem rna_enum_driver_target_rotation_mode_items[] = {
+ {DTAR_ROTMODE_AUTO, "AUTO", 0, "Auto Euler", "Euler using the rotation order of the target"},
+ {DTAR_ROTMODE_EULER_XYZ, "XYZ", 0, "XYZ Euler", "Euler using the XYZ rotation order"},
+ {DTAR_ROTMODE_EULER_XZY, "XZY", 0, "XZY Euler", "Euler using the XZY rotation order"},
+ {DTAR_ROTMODE_EULER_YXZ, "YXZ", 0, "YXZ Euler", "Euler using the YXZ rotation order"},
+ {DTAR_ROTMODE_EULER_YZX, "YZX", 0, "YZX Euler", "Euler using the YZX rotation order"},
+ {DTAR_ROTMODE_EULER_ZXY, "ZXY", 0, "ZXY Euler", "Euler using the ZXY rotation order"},
+ {DTAR_ROTMODE_EULER_ZYX, "ZYX", 0, "ZYX Euler", "Euler using the ZYX rotation order"},
+ {DTAR_ROTMODE_QUATERNION, "QUATERNION", 0, "Quaternion", "Quaternion rotation"},
+ {0, NULL, 0, NULL, NULL},
+};
+
#ifdef RNA_RUNTIME
# include "WM_api.h"
@@ -1702,18 +1714,6 @@ static void rna_def_drivertarget(BlenderRNA *brna)
{0, NULL, 0, NULL, NULL},
};
- static const EnumPropertyItem prop_rotation_mode_items[] = {
- {DTAR_ROTMODE_AUTO, "AUTO", 0, "Auto Euler", "Euler using the rotation order of the target"},
- {DTAR_ROTMODE_EULER_XYZ, "XYZ", 0, "XYZ Euler", "Euler using the XYZ rotation order"},
- {DTAR_ROTMODE_EULER_XZY, "XZY", 0, "XZY Euler", "Euler using the XZY rotation order"},
- {DTAR_ROTMODE_EULER_YXZ, "YXZ", 0, "YXZ Euler", "Euler using the YXZ rotation order"},
- {DTAR_ROTMODE_EULER_YZX, "YZX", 0, "YZX Euler", "Euler using the YZX rotation order"},
- {DTAR_ROTMODE_EULER_ZXY, "ZXY", 0, "ZXY Euler", "Euler using the ZXY rotation order"},
- {DTAR_ROTMODE_EULER_ZYX, "ZYX", 0, "ZYX Euler", "Euler using the ZYX rotation order"},
- {DTAR_ROTMODE_QUATERNION, "QUATERNION", 0, "Quaternion", "Quaternion rotation"},
- {0, NULL, 0, NULL, NULL},
- };
-
srna = RNA_def_struct(brna, "DriverTarget", NULL);
RNA_def_struct_ui_text(srna, "Driver Target", "Source of input values for driver variables");
@@ -1764,7 +1764,7 @@ static void rna_def_drivertarget(BlenderRNA *brna)
prop = RNA_def_property(srna, "rotation_mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "rotation_mode");
- RNA_def_property_enum_items(prop, prop_rotation_mode_items);
+ RNA_def_property_enum_items(prop, rna_enum_driver_target_rotation_mode_items);
RNA_def_property_ui_text(prop, "Rotation Mode", "Mode for calculating rotation channel values");
RNA_def_property_update(prop, 0, "rna_DriverTarget_update_data");