Drivers: support explicit euler rotation order for transform channels.
authorAlexander Gavrilov <angavrilov@gmail.com>
Sat, 31 Aug 2019 09:43:42 +0000 (12:43 +0300)
committerAlexander Gavrilov <angavrilov@gmail.com>
Sat, 31 Aug 2019 11:22:12 +0000 (14:22 +0300)
The meaning of the euler angles completely depends on the rotation
order. Currently the rotation order is taken from the target of the
driver variable, which somewhat makes sense if it uses euler, but if
it's quaternion, then the order is always set to XYZ.

Add a new option for the rotation channels of the Transform Channel
driver variables that defaults to the old behavior, but allows setting
an explicit rotation order.

source/blender/blenkernel/intern/fcurve.c
source/blender/editors/space_graph/graph_buttons.c
source/blender/makesdna/DNA_anim_types.h
source/blender/makesrna/intern/rna_fcurve.c

index 657a08877b032359af4e974c07734ee0f7bb9ff4..dec410c819261043bde5210aad7959e4a1308154 100644 (file)
@@ -1730,10 +1730,20 @@ static float dvar_eval_transChan(ChannelDriver *driver, DriverVar *dvar)
      */
     float eul[3];
 
-    mat4_to_eulO(eul, rot_order, mat);
+    if (dtar->rotation_mode == DTAR_ROTMODE_AUTO) {
+      mat4_to_eulO(eul, rot_order, mat);
 
-    if (use_eulers) {
-      compatible_eul(eul, oldEul);
+      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 {
+      BLI_assert(false);
+      zero_v3(eul);
     }
 
     return eul[dtar->transChan - DTAR_TRANSCHAN_ROTX];
index b264a5cb260649e2f657dc92996ec094852bf944..708d91a82bbfeceb42d2bd1fc12495495f66e3fa 100644 (file)
@@ -861,6 +861,11 @@ static void graph_panel_driverVar__transChan(uiLayout *layout, ID *id, DriverVar
 
   sub = uiLayoutColumn(layout, true);
   uiItemR(sub, &dtar_ptr, "transform_type", 0, NULL, ICON_NONE);
+
+  if (ELEM(dtar->transChan, DTAR_TRANSCHAN_ROTX, DTAR_TRANSCHAN_ROTY, DTAR_TRANSCHAN_ROTZ)) {
+    uiItemR(sub, &dtar_ptr, "rotation_mode", 0, IFACE_("Mode"), ICON_NONE);
+  }
+
   uiItemR(sub, &dtar_ptr, "transform_space", 0, IFACE_("Space"), ICON_NONE);
 }
 
index 1718aabc51dbb807b8e11c90c88c7d16aba19a57..8c25d470a36eb8feaec8a9fa175d4f5c6fa6f133 100644 (file)
@@ -319,6 +319,10 @@ typedef struct DriverTarget {
   /** Transform channel index (for DVAR_TYPE_TRANSFORM_CHAN.)*/
   short transChan;
 
+  /** Rotation channel calculation type. */
+  char rotation_mode;
+  char _pad[7];
+
   /**
    * Flags for the validity of the target
    * (NOTE: these get reset every time the types change).
@@ -362,6 +366,23 @@ typedef enum eDriverTarget_TransformChannels {
   MAX_DTAR_TRANSCHAN_TYPES,
 } eDriverTarget_TransformChannels;
 
+/* Rotation channel mode for Driver Targets */
+typedef enum eDriverTarget_RotationMode {
+  /** Automatic euler mode. */
+  DTAR_ROTMODE_AUTO = 0,
+
+  /** Explicit euler rotation modes - must sync with BLI_math_rotation.h defines. */
+  DTAR_ROTMODE_EULER_XYZ = 1,
+  DTAR_ROTMODE_EULER_XZY,
+  DTAR_ROTMODE_EULER_YXZ,
+  DTAR_ROTMODE_EULER_YZX,
+  DTAR_ROTMODE_EULER_ZXY,
+  DTAR_ROTMODE_EULER_ZYX,
+
+  DTAR_ROTMODE_EULER_MIN = DTAR_ROTMODE_EULER_XYZ,
+  DTAR_ROTMODE_EULER_MAX = DTAR_ROTMODE_EULER_ZYX,
+} eDriverTarget_RotationMode;
+
 /* --- */
 
 /* maximum number of driver targets per variable */
index 6c546940e6ddea7181fdf86c5e6d301abd3a7f5f..6cb3a18605c8b3bfd385a6583e0cffd417ea55b1 100644 (file)
@@ -1701,6 +1701,17 @@ 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"},
+      {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");
 
@@ -1749,6 +1760,12 @@ static void rna_def_drivertarget(BlenderRNA *brna)
   RNA_def_property_ui_text(prop, "Type", "Driver variable type");
   RNA_def_property_update(prop, 0, "rna_DriverTarget_update_data");
 
+  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_ui_text(prop, "Rotation Mode", "Mode for calculating rotation channel values");
+  RNA_def_property_update(prop, 0, "rna_DriverTarget_update_data");
+
   prop = RNA_def_property(srna, "transform_space", PROP_ENUM, PROP_NONE);
   RNA_def_property_enum_bitflag_sdna(prop, NULL, "flag");
   RNA_def_property_enum_items(prop, prop_local_space_items);