[Bf-blender-cvs] [69ee6c9] master: Drivers Editing: Added "Copy/Paste" buttons beside "Add Variable" for copying all variables from one driver to another

Joshua Leung noreply at git.blender.org
Fri Apr 15 10:19:33 CEST 2016


Commit: 69ee6c986657bf0d6bf631277751d24e72d76bac
Author: Joshua Leung
Date:   Fri Apr 15 20:04:07 2016 +1200
Branches: master
https://developer.blender.org/rB69ee6c986657bf0d6bf631277751d24e72d76bac

Drivers Editing: Added "Copy/Paste" buttons beside "Add Variable" for copying all variables from one driver to another

This was a feature request from a few years back (IIRC from ZanQdo?) to make it
easier to reuse one set of driver variables across several different drivers.

Dev Notes:
* Finally it's done! All that trouble for two little buttons.
* Grr... cmake... grrr!

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

M	source/blender/blenkernel/BKE_fcurve.h
M	source/blender/blenkernel/intern/fcurve.c
M	source/blender/editors/animation/CMakeLists.txt
M	source/blender/editors/animation/drivers.c
M	source/blender/editors/include/ED_keyframing.h
M	source/blender/editors/space_graph/graph_buttons.c
M	source/blender/editors/space_graph/graph_edit.c
M	source/blender/editors/space_graph/graph_intern.h
M	source/blender/editors/space_graph/graph_ops.c
M	source/blender/makesrna/intern/rna_fcurve.c
M	source/blender/windowmanager/intern/wm_init_exit.c

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

diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h
index 6643382..2022d11 100644
--- a/source/blender/blenkernel/BKE_fcurve.h
+++ b/source/blender/blenkernel/BKE_fcurve.h
@@ -93,7 +93,11 @@ void bezt_add_to_cfra_elem(ListBase *lb, struct BezTriple *bezt);
 void fcurve_free_driver(struct FCurve *fcu);
 struct ChannelDriver *fcurve_copy_driver(struct ChannelDriver *driver);
 
-void driver_free_variable(struct ChannelDriver *driver, struct DriverVar *dvar);
+void driver_variables_copy(struct ListBase *dst_list, const struct ListBase *src_list);
+
+void driver_free_variable(struct ListBase *variables, struct DriverVar *dvar);
+void driver_free_variable_ex(struct ChannelDriver *driver, struct DriverVar *dvar);
+
 void driver_change_variable_type(struct DriverVar *dvar, int type);
 void driver_variable_name_validate(struct DriverVar *dvar);
 struct DriverVar *driver_add_new_variable(struct ChannelDriver *driver);
diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c
index 11b1bbd..a2b5a05 100644
--- a/source/blender/blenkernel/intern/fcurve.c
+++ b/source/blender/blenkernel/intern/fcurve.c
@@ -1600,8 +1600,8 @@ static const DriverVarTypeInfo *get_dvar_typeinfo(int type)
 
 /* Driver API --------------------------------- */
 
-/* This frees the driver variable itself */
-void driver_free_variable(ChannelDriver *driver, DriverVar *dvar)
+/* Perform actual freeing driver variable and remove it from the given list */
+void driver_free_variable(ListBase *variables, DriverVar *dvar)
 {
 	/* sanity checks */
 	if (dvar == NULL)
@@ -1621,8 +1621,15 @@ void driver_free_variable(ChannelDriver *driver, DriverVar *dvar)
 	DRIVER_TARGETS_LOOPER_END
 	
 	/* remove the variable from the driver */
-	BLI_freelinkN(&driver->variables, dvar);
+	BLI_freelinkN(variables, dvar);
+}
 
+/* Free the driver variable and do extra updates */
+void driver_free_variable_ex(ChannelDriver *driver, DriverVar *dvar)
+{
+	/* remove and free the driver variable */
+	driver_free_variable(&driver->variables, dvar);
+	
 #ifdef WITH_PYTHON
 	/* since driver variables are cached, the expression needs re-compiling too */
 	if (driver->type == DRIVER_TYPE_PYTHON)
@@ -1630,6 +1637,24 @@ void driver_free_variable(ChannelDriver *driver, DriverVar *dvar)
 #endif
 }
 
+/* Copy driver variables from src_vars list to dst_vars list */
+void driver_variables_copy(ListBase *dst_vars, const ListBase *src_vars)
+{
+	BLI_assert(BLI_listbase_is_empty(dst_vars));
+	BLI_duplicatelist(dst_vars, src_vars);
+	
+	for (DriverVar *dvar = dst_vars->first; dvar; dvar = dvar->next) {
+		/* need to go over all targets so that we don't leave any dangling paths */
+		DRIVER_TARGETS_LOOPER(dvar) 
+		{
+			/* make a copy of target's rna path if available */
+			if (dtar->rna_path)
+				dtar->rna_path = MEM_dupallocN(dtar->rna_path);
+		}
+		DRIVER_TARGETS_LOOPER_END
+	}
+}
+
 /* Change the type of driver variable */
 void driver_change_variable_type(DriverVar *dvar, int type)
 {
@@ -1770,7 +1795,7 @@ void fcurve_free_driver(FCurve *fcu)
 	/* free driver targets */
 	for (dvar = driver->variables.first; dvar; dvar = dvarn) {
 		dvarn = dvar->next;
-		driver_free_variable(driver, dvar);
+		driver_free_variable_ex(driver, dvar);
 	}
 
 #ifdef WITH_PYTHON
@@ -1788,7 +1813,6 @@ void fcurve_free_driver(FCurve *fcu)
 ChannelDriver *fcurve_copy_driver(ChannelDriver *driver)
 {
 	ChannelDriver *ndriver;
-	DriverVar *dvar;
 	
 	/* sanity checks */
 	if (driver == NULL)
@@ -1799,19 +1823,8 @@ ChannelDriver *fcurve_copy_driver(ChannelDriver *driver)
 	ndriver->expr_comp = NULL;
 	
 	/* copy variables */
-	BLI_listbase_clear(&ndriver->variables);
-	BLI_duplicatelist(&ndriver->variables, &driver->variables);
-	
-	for (dvar = ndriver->variables.first; dvar; dvar = dvar->next) {
-		/* need to go over all targets so that we don't leave any dangling paths */
-		DRIVER_TARGETS_LOOPER(dvar) 
-		{
-			/* make a copy of target's rna path if available */
-			if (dtar->rna_path)
-				dtar->rna_path = MEM_dupallocN(dtar->rna_path);
-		}
-		DRIVER_TARGETS_LOOPER_END
-	}
+	BLI_listbase_clear(&ndriver->variables); /* to get rid of refs to non-copied data (that's still used on original) */ 
+	driver_variables_copy(&ndriver->variables, &driver->variables);
 	
 	/* return the new driver */
 	return ndriver;
diff --git a/source/blender/editors/animation/CMakeLists.txt b/source/blender/editors/animation/CMakeLists.txt
index 473b0e6..1bf1bb2 100644
--- a/source/blender/editors/animation/CMakeLists.txt
+++ b/source/blender/editors/animation/CMakeLists.txt
@@ -59,6 +59,10 @@ if(WITH_INTERNATIONAL)
 	add_definitions(-DWITH_INTERNATIONAL)
 endif()
 
+if(WITH_PYTHON)
+	add_definitions(-DWITH_PYTHON)
+endif()
+
 add_definitions(${GL_DEFINITIONS})
 
 blender_add_lib(bf_editor_animation "${SRC}" "${INC}" "${INC_SYS}")
diff --git a/source/blender/editors/animation/drivers.c b/source/blender/editors/animation/drivers.c
index 4ddf37a..27bed69 100644
--- a/source/blender/editors/animation/drivers.c
+++ b/source/blender/editors/animation/drivers.c
@@ -600,7 +600,7 @@ bool ANIM_paste_driver(ReportList *reports, ID *id, const char rna_path[], int a
 	
 	/* create Driver F-Curve, but without data which will be copied across... */
 	fcu = verify_driver_fcurve(id, rna_path, array_index, -1);
-
+	
 	if (fcu) {
 		/* copy across the curve data from the buffer curve 
 		 * NOTE: this step needs care to not miss new settings
@@ -625,6 +625,120 @@ bool ANIM_paste_driver(ReportList *reports, ID *id, const char rna_path[], int a
 }
 
 /* ************************************************** */
+/* Driver Management API - Copy/Paste Driver Variables */
+
+/* Copy/Paste Buffer for Driver Variables... */
+static ListBase driver_vars_copybuf = {NULL, NULL};
+
+/* This function frees any MEM_calloc'ed copy/paste buffer data */
+void ANIM_driver_vars_copybuf_free(void)
+{
+	/* Free the driver variables kept in the buffer */
+	if (driver_vars_copybuf.first) {
+		/* We use a dummy driver here, as the variable freeing code assumes there's a driver */
+		ChannelDriver dummy_driver = {{NULL}};
+		dummy_driver.variables = driver_vars_copybuf;
+		
+		/* Free variables (and any data they use) */
+		DriverVar *dvar, *dvarn;
+		for (dvar = driver_vars_copybuf.first; dvar; dvar = dvarn) {
+			dvarn = dvar->next;
+			driver_free_variable(&driver_vars_copybuf, dvar);
+		}
+	}
+	
+	BLI_listbase_clear(&driver_vars_copybuf);
+}
+
+/* Checks if there are driver variables in the copy/paste buffer */
+bool ANIM_driver_vars_can_paste(void)
+{
+	return (BLI_listbase_is_empty(&driver_vars_copybuf) == false);
+}
+
+/* -------------------------------------------------- */
+
+/* Copy the given driver's variables to the buffer */
+bool ANIM_driver_vars_copy(ReportList *reports, FCurve *fcu)
+{
+	/* sanity checks */
+	if (ELEM(NULL, fcu, fcu->driver)) {
+		BKE_report(reports, RPT_ERROR, "No driver to copy variables from");
+		return false;
+	}
+	
+	if (BLI_listbase_is_empty(&fcu->driver->variables)) {
+		BKE_report(reports, RPT_ERROR, "Driver has no variables to copy");
+		return false;
+	}
+	
+	/* clear buffer */
+	ANIM_driver_vars_copybuf_free();
+	
+	/* copy over the variables */
+	driver_variables_copy(&driver_vars_copybuf, &fcu->driver->variables);
+	
+	return (BLI_listbase_is_empty(&driver_vars_copybuf) == false);
+}
+
+/* Paste the variables in the buffer to the given FCurve */
+bool ANIM_driver_vars_paste(ReportList *reports, FCurve *fcu, bool replace)
+{
+	ChannelDriver *driver = (fcu) ? fcu->driver : NULL;
+	ListBase tmp_list = {NULL, NULL};
+	
+	/* sanity checks */
+	if (BLI_listbase_is_empty(&driver_vars_copybuf)) {
+		BKE_report(reports, RPT_ERROR, "No driver variables in clipboard to paste");
+		return false;
+	}
+	
+	if (ELEM(NULL, fcu, fcu->driver)) {
+		BKE_report(reports, RPT_ERROR, "Cannot paste driver variables without a driver");
+		return false;
+	}
+	
+	/* 1) Make a new copy of the variables in the buffer - these will get pasted later... */
+	driver_variables_copy(&tmp_list, &driver_vars_copybuf);
+	
+	/* 2) Prepare destination array */
+	if (replace) {
+		DriverVar *dvar, *dvarn;
+		
+		/* Free all existing vars first - We aren't retaining anything */
+		for (dvar = driver->variables.first; dvar; dvar = dvarn) {
+			dvarn = dvar->next;
+			driver_free_variable_ex(driver, dvar);
+		}
+		
+		BLI_listbase_clear(&driver->variables);
+	}
+	
+	/* 3) Add new vars */
+	if (driver->variables.last) {
+		DriverVar *last = driver->variables.last;
+		DriverVar *first = tmp_list.first;
+		
+		last->next = first;
+		first->prev = last;
+		
+		driver->variables.last = tmp_list.last;
+	}
+	else {
+		driver->variables.first = tmp_list.first;
+		driver->variables.last = tmp_list.last;
+	}
+	
+#ifdef WITH_PYTHON
+	/* since driver variables are cached, the expression needs re-compiling too */
+	if (driver->type == DRIVER_TYPE_PYTHON)
+		driver->flag |= DRIVER_FLAG_RENAMEVAR;
+#endif
+	
+	return true;
+}
+
+/* ************************************************** */
 /* UI-Button Interface */
 
 /* Add Driver - Enum Defines ------------------------- */
diff --git a/source/blender/editors/include/ED_keyframing.h b/source/blender/editors/include/ED_keyframing.h
index 9a41197..81e2558 100644
--- a/source/blender/editors/include/ED_keyframing.h
+++ b/source/blender/editors/include/ED_keyframing.h
@@ -291,6 +291,9 @@ bool ANIM_remove_driver(struct ReportList *reports, struct ID *id, const char rn
 /* Clear copy-paste buffer for drivers */
 void ANIM_drivers_copybuf_free(void);
 
+/* Clear copy-paste buffer for driver variable sets */
+void ANIM_driver_vars_copybuf_free(void);
+
 /* -------- */
 
 /* Returns whether there is a driver in the copy/paste buffer to paste */
@@ -307,6 +310,17 @@ bool ANIM_copy_driver(struct ReportList *reports, struct ID *id, const char rna_
  */
 bool ANIM_paste_driver(struct ReportList *reports, struct ID *id, const char rna_path[], int array_index, short flag);
 
+/* -------- */
+
+/* Checks if there are driver variables in the copy/paste buffer */
+bool ANIM_driver_vars_can_paste(void);
+
+/* Copy the given driver's variables to the buffer */
+bool ANIM_driver_vars_copy(struct ReportList *reports, struct

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list