[Bf-blender-cvs] [47335b4e61d] master: Add a new Copy As Driver context menu option for properties.

Alexander Gavrilov noreply at git.blender.org
Sun Aug 4 13:27:05 CEST 2019


Commit: 47335b4e61db11e1ee2e38f421dc86fa3c3dd375
Author: Alexander Gavrilov
Date:   Wed Jul 31 18:42:03 2019 +0300
Branches: master
https://developer.blender.org/rB47335b4e61db11e1ee2e38f421dc86fa3c3dd375

Add a new Copy As Driver context menu option for properties.

It is a very common need to create drivers that set the value of
a property to the value of some other property, but it currently
requires multiple actions: Copy Data Path on the input property,
adding a driver to the output property, selecting the input ID
reference, and pasting the path.

This adds a new Copy As Driver context menu option, which creates
a complete driver in the clipboard that reads the current property,
so all that remains is to paste it to the output property. It is
also possible to paste just the new driver variable into an existing
driver to combine multiple inputs.

Reviewers: brecht, billreynish

Differential Revision: https://developer.blender.org/D5382

===================================================================

M	source/blender/editors/animation/drivers.c
M	source/blender/editors/include/ED_keyframing.h
M	source/blender/editors/interface/interface_context_menu.c
M	source/blender/editors/interface/interface_ops.c

===================================================================

diff --git a/source/blender/editors/animation/drivers.c b/source/blender/editors/animation/drivers.c
index 7ca0f95d6c4..935d11a388f 100644
--- a/source/blender/editors/animation/drivers.c
+++ b/source/blender/editors/animation/drivers.c
@@ -23,6 +23,7 @@
 
 #include <stdio.h>
 #include <string.h>
+#include <ctype.h>
 
 #include "MEM_guardedalloc.h"
 
@@ -95,56 +96,65 @@ FCurve *verify_driver_fcurve(ID *id, const char rna_path[], const int array_inde
 
   if ((fcu == NULL) && (add)) {
     /* use default settings to make a F-Curve */
-    fcu = MEM_callocN(sizeof(FCurve), "FCurve");
+    fcu = alloc_driver_fcurve(rna_path, array_index, add);
 
-    fcu->flag = (FCURVE_VISIBLE | FCURVE_SELECTED);
-    fcu->auto_smoothing = FCURVE_SMOOTH_CONT_ACCEL;
+    /* just add F-Curve to end of driver list */
+    BLI_addtail(&adt->drivers, fcu);
+  }
 
-    /* store path - make copy, and store that */
-    fcu->rna_path = BLI_strdup(rna_path);
-    fcu->array_index = array_index;
-
-    /* If add is negative, don't init this data yet,
-     * since it will be filled in by the pasted driver. */
-    if (add > 0) {
-      BezTriple *bezt;
-      size_t i;
-
-      /* add some new driver data */
-      fcu->driver = MEM_callocN(sizeof(ChannelDriver), "ChannelDriver");
-
-      /* F-Modifier or Keyframes? */
-      // FIXME: replace these magic numbers with defines
-      if (add == 2) {
-        /* Python API Backwards compatibility hack:
-         * Create FModifier so that old scripts won't break
-         * for now before 2.7 series -- (September 4, 2013)
-         */
-        add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_GENERATOR, fcu);
-      }
-      else {
-        /* add 2 keyframes so that user has something to work with
-         * - These are configured to 0,0 and 1,1 to give a 1-1 mapping
-         *   which can be easily tweaked from there.
-         */
-        insert_vert_fcurve(fcu, 0.0f, 0.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_FAST);
-        insert_vert_fcurve(fcu, 1.0f, 1.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_FAST);
+  /* return the F-Curve */
+  return fcu;
+}
 
-        /* configure this curve to extrapolate */
-        for (i = 0, bezt = fcu->bezt; (i < fcu->totvert) && bezt; i++, bezt++) {
-          bezt->h1 = bezt->h2 = HD_VECT;
-        }
+struct FCurve *alloc_driver_fcurve(const char rna_path[], const int array_index, short add)
+{
+  FCurve *fcu = MEM_callocN(sizeof(FCurve), "FCurve");
 
-        fcu->extend = FCURVE_EXTRAPOLATE_LINEAR;
-        calchandles_fcurve(fcu);
-      }
+  fcu->flag = (FCURVE_VISIBLE | FCURVE_SELECTED);
+  fcu->auto_smoothing = FCURVE_SMOOTH_CONT_ACCEL;
+
+  /* store path - make copy, and store that */
+  if (rna_path) {
+    fcu->rna_path = BLI_strdup(rna_path);
+  }
+  fcu->array_index = array_index;
+
+  /* If add is negative, don't init this data yet,
+   * since it will be filled in by the pasted driver. */
+  if (add > 0) {
+    BezTriple *bezt;
+    size_t i;
+
+    /* add some new driver data */
+    fcu->driver = MEM_callocN(sizeof(ChannelDriver), "ChannelDriver");
+
+    /* F-Modifier or Keyframes? */
+    // FIXME: replace these magic numbers with defines
+    if (add == 2) {
+      /* Python API Backwards compatibility hack:
+       * Create FModifier so that old scripts won't break
+       * for now before 2.7 series -- (September 4, 2013)
+       */
+      add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_GENERATOR, fcu);
     }
+    else {
+      /* add 2 keyframes so that user has something to work with
+       * - These are configured to 0,0 and 1,1 to give a 1-1 mapping
+       *   which can be easily tweaked from there.
+       */
+      insert_vert_fcurve(fcu, 0.0f, 0.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_FAST);
+      insert_vert_fcurve(fcu, 1.0f, 1.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_FAST);
 
-    /* just add F-Curve to end of driver list */
-    BLI_addtail(&adt->drivers, fcu);
+      /* configure this curve to extrapolate */
+      for (i = 0, bezt = fcu->bezt; (i < fcu->totvert) && bezt; i++, bezt++) {
+        bezt->h1 = bezt->h2 = HD_VECT;
+      }
+
+      fcu->extend = FCURVE_EXTRAPOLATE_LINEAR;
+      calchandles_fcurve(fcu);
+    }
   }
 
-  /* return the F-Curve */
   return fcu;
 }
 
@@ -834,6 +844,48 @@ bool ANIM_driver_vars_paste(ReportList *reports, FCurve *fcu, bool replace)
   return true;
 }
 
+/* -------------------------------------------------- */
+
+/* Create a driver & variable that reads the specified property,
+ * and store it in the buffers for Paste Driver and Paste Variables. */
+void ANIM_copy_as_driver(struct ID *target_id, const char *target_path, const char *var_name)
+{
+  /* Clear copy/paste buffer first (for consistency with other copy/paste buffers). */
+  ANIM_drivers_copybuf_free();
+  ANIM_driver_vars_copybuf_free();
+
+  /* Create a dummy driver F-Curve. */
+  FCurve *fcu = alloc_driver_fcurve(NULL, 0, 1);
+  ChannelDriver *driver = fcu->driver;
+
+  /* Create a variable. */
+  DriverVar *var = driver_add_new_variable(driver);
+  DriverTarget *target = &var->targets[0];
+
+  target->idtype = GS(target_id->name);
+  target->id = target_id;
+  target->rna_path = MEM_dupallocN(target_path);
+
+  /* Set the variable name. */
+  if (var_name) {
+    BLI_strncpy(var->name, var_name, sizeof(var->name));
+
+    /* Sanitize the name. */
+    for (int i = 0; var->name[i]; i++) {
+      if (!(i > 0 ? isalnum(var->name[i]) : isalpha(var->name[i]))) {
+        var->name[i] = '_';
+      }
+    }
+  }
+
+  BLI_strncpy(driver->expression, var->name, sizeof(driver->expression));
+
+  /* Store the driver into the copy/paste buffers. */
+  channeldriver_copypaste_buf = fcu;
+
+  driver_variables_copy(&driver_vars_copybuf, &driver->variables);
+}
+
 /* ************************************************** */
 /* UI-Button Interface */
 
diff --git a/source/blender/editors/include/ED_keyframing.h b/source/blender/editors/include/ED_keyframing.h
index 8f197fa9afe..bbeeeade822 100644
--- a/source/blender/editors/include/ED_keyframing.h
+++ b/source/blender/editors/include/ED_keyframing.h
@@ -320,6 +320,8 @@ struct FCurve *verify_driver_fcurve(struct ID *id,
                                     const int array_index,
                                     short add);
 
+struct FCurve *alloc_driver_fcurve(const char rna_path[], const int array_index, short add);
+
 /* -------- */
 
 /* Main Driver Management API calls:
@@ -399,6 +401,12 @@ bool ANIM_driver_vars_copy(struct ReportList *reports, struct FCurve *fcu);
 /* Paste the variables in the buffer to the given FCurve */
 bool ANIM_driver_vars_paste(struct ReportList *reports, struct FCurve *fcu, bool replace);
 
+/* -------- */
+
+/* Create a driver & variable that reads the specified property,
+ * and store it in the buffers for Paste Driver and Paste Variables. */
+void ANIM_copy_as_driver(struct ID *target_id, const char *target_path, const char *var_name);
+
 /* ************ Auto-Keyframing ********************** */
 /* Notes:
  * - All the defines for this (User-Pref settings and Per-Scene settings)
diff --git a/source/blender/editors/interface/interface_context_menu.c b/source/blender/editors/interface/interface_context_menu.c
index 7cec8af46de..88fe8704082 100644
--- a/source/blender/editors/interface/interface_context_menu.c
+++ b/source/blender/editors/interface/interface_context_menu.c
@@ -899,6 +899,13 @@ bool ui_popup_context_menu_for_button(bContext *C, uiBut *but)
             ICON_NONE,
             "UI_OT_copy_data_path_button");
 
+    if (ptr->id.data && ELEM(type, PROP_BOOLEAN, PROP_INT, PROP_FLOAT, PROP_ENUM)) {
+      uiItemO(layout,
+              CTX_IFACE_(BLT_I18NCONTEXT_OPERATOR_DEFAULT, "Copy As New Driver"),
+              ICON_NONE,
+              "UI_OT_copy_as_driver_button");
+    }
+
     uiItemS(layout);
 
     if (type == PROP_STRING && ELEM(subtype, PROP_FILEPATH, PROP_DIRPATH)) {
diff --git a/source/blender/editors/interface/interface_ops.c b/source/blender/editors/interface/interface_ops.c
index f2b2a478ba9..f5a894d7620 100644
--- a/source/blender/editors/interface/interface_ops.c
+++ b/source/blender/editors/interface/interface_ops.c
@@ -65,6 +65,9 @@
 #include "ED_object.h"
 #include "ED_paint.h"
 
+/* for Copy As Driver */
+#include "ED_keyframing.h"
+
 /* only for UI_OT_editsource */
 #include "ED_screen.h"
 #include "BKE_main.h"
@@ -153,23 +156,92 @@ static void UI_OT_copy_data_path_button(wmOperatorType *ot)
   RNA_def_property_flag(prop, PROP_SKIP_SAVE);
 }
 
-static bool copy_python_command_button_poll(bContext *C)
+/** \} */
+
+/* -------------------------------------------------------------------- */
+/** \name Copy As Driver Operator
+ * \{ */
+
+static bool copy_as_driver_button_poll(bContext *C)
 {
-  uiBut *but = UI_context_active_but_get(C);
+  PointerRNA ptr;
+  PropertyRNA *prop;
+  char *path;
+  int index;
 
-  if (but && (but->optype != NULL)) {
-    return 1;
+  UI_context_active_but_prop_get(C, &ptr, &prop, &index);
+
+  if (ptr.id.data && ptr.data && prop &&
+      ELEM(RNA_property_type(prop), PROP_BOOLEAN, PROP_INT, PROP_FLOAT, PROP_ENUM)) {
+    path = RNA_path_from_ID_to_property(&ptr, prop);
+
+    if (path) {
+      MEM_freeN(path);
+      return 1;
+    }
   }
 
   return 0;
 }
 
+static int copy_as_driver_button_exec(bContext *C, wmOperator *UNUSED(op))
+{
+  PointerRNA ptr;
+  PropertyRNA *prop;
+  int index;
+
+  /* try to create driver using property retrieved from UI */
+  UI_context_active_but_prop_get(C, &ptr, &prop, &index);
+
+  if (ptr.id.data && ptr.data && prop) {
+    int dim = RNA_property_array_dimension(&ptr, prop, NULL);
+    char *path = RNA_path_from_ID_to_property_index(&ptr, prop, dim, index);
+
+    if (path) {
+      ANIM_copy_as_driver(ptr.id.data, path, RNA_property_identifier(prop));
+      MEM_freeN(path);
+      return OPERATOR_FINISHED;
+    }
+  }
+
+  return OPERATOR_CANCELLED;
+}
+
+static void UI_OT_copy_as_driver_button(wmOperatorType *ot)
+{
+  /* identifiers */
+  ot->name = "Copy As New Driver";
+  ot->idname = "UI_OT_copy_as_driver_button";
+  ot->description =
+      "Create a new driver with this property as input, and copy it to the "
+      "clipboard. Use Paste Driver to add it to the target property, or Paste "
+    

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list