Drivers Code Cleanups and UI Tweaks:

- Adding drivers from the UI (not from py-scripts though) will now
automatically add a "Transform Channel" driver variable to the newly
created drivers. This makes setting up drivers a bit more convenient
for the most commonly used case.

- Drivers now report their errors using the Reports system instead of
writing these directly to the console.

- Clarified some comments to be more insightful about the "why's" of
some design decisions, and related formatting/cleanup tweaks
- Reduced scope of "path" vars to just the scope they're required in

- Removed some unused defines from a failed experiment in the original
Keying Sets code ("templates" and "template flags") which was
superseeded by the more flexible + nicer "Builtin KeyingSets"
This commit is contained in:
2010-12-28 05:45:15 +00:00
parent 24ae6f8c91
commit 71da1e96d1
7 changed files with 85 additions and 70 deletions

View File

@@ -1329,7 +1329,7 @@ DriverVar *driver_add_new_variable (ChannelDriver *driver)
#ifdef WITH_PYTHON
/* since driver variables are cached, the expression needs re-compiling too */
if(driver->type==DRIVER_TYPE_PYTHON)
if (driver->type==DRIVER_TYPE_PYTHON)
driver->flag |= DRIVER_FLAG_RENAMEVAR;
#endif

View File

@@ -39,6 +39,9 @@
#include "BKE_depsgraph.h"
#include "BKE_fcurve.h"
#include "BKE_context.h"
#include "BKE_report.h"
#include "ED_keyframing.h"
#include "UI_interface.h"
@@ -115,7 +118,7 @@ FCurve *verify_driver_fcurve (ID *id, const char rna_path[], const int array_ind
/* Main Driver Management API calls:
* Add a new driver for the specified property on the given ID block
*/
short ANIM_add_driver (ID *id, const char rna_path[], int array_index, short UNUSED(flag), int type)
short ANIM_add_driver (ReportList *reports, ID *id, const char rna_path[], int array_index, short flag, int type)
{
PointerRNA id_ptr, ptr;
PropertyRNA *prop;
@@ -126,7 +129,9 @@ short ANIM_add_driver (ID *id, const char rna_path[], int array_index, short UNU
/* validate pointer first - exit if failure */
RNA_id_pointer_create(id, &id_ptr);
if ((RNA_path_resolve(&id_ptr, rna_path, &ptr, &prop) == 0) || (prop == NULL)) {
printf("Add Driver: Could not add Driver, as RNA Path is invalid for the given ID (ID = %s, Path = %s)\n", id->name, rna_path);
BKE_reportf(reports, RPT_ERROR,
"Could not add Driver, as RNA Path is invalid for the given ID (ID = %s, Path = %s)",
id->name, rna_path);
return 0;
}
@@ -153,7 +158,10 @@ short ANIM_add_driver (ID *id, const char rna_path[], int array_index, short UNU
/* set the type of the driver */
driver->type= type;
/* fill in current value for python */
/* creating drivers for buttons will create the driver(s) with type
* "scripted expression" so that their values won't be lost immediately,
* so here we copy those values over to the driver's expression
*/
if (type == DRIVER_TYPE_PYTHON) {
PropertyType proptype= RNA_property_type(prop);
int array= RNA_property_array_length(&ptr, prop);
@@ -180,6 +188,17 @@ short ANIM_add_driver (ID *id, const char rna_path[], int array_index, short UNU
BLI_snprintf(expression, maxlen, "%.3f", fval);
}
}
/* for easier setup of drivers from UI, a driver variable should be
* added if flag is set (UI calls only)
*/
if (flag & CREATEDRIVER_WITH_DEFAULT_DVAR) {
/* assume that users will mostly want this to be of type "Transform Channel" too,
* since this allows the easiest setting up of common rig components
*/
DriverVar *dvar = driver_add_new_variable(driver);
driver_change_variable_type(dvar, DVAR_TYPE_TRANSFORM_CHAN);
}
}
/* set the done status */
@@ -193,23 +212,21 @@ short ANIM_add_driver (ID *id, const char rna_path[], int array_index, short UNU
/* Main Driver Management API calls:
* Remove the driver for the specified property on the given ID block (if available)
*/
short ANIM_remove_driver (struct ID *id, const char rna_path[], int array_index, short UNUSED(flag))
short ANIM_remove_driver (ReportList *reports, ID *id, const char rna_path[], int array_index, short UNUSED(flag))
{
AnimData *adt;
FCurve *fcu;
int success= 0;
/* get F-Curve
* Note: here is one of the places where we don't want new F-Curve + Driver added!
* so 'add' var must be 0
*/
/* we don't check the validity of the path here yet, but it should be ok... */
adt= BKE_animdata_from_id(id);
if(adt) {
if(array_index == -1) {
if (adt) {
if (array_index == -1) {
/* step through all drivers, removing all of those with the same base path */
FCurve *fcu_iter= adt->drivers.first;
while((fcu= iter_step_fcurve(fcu_iter, rna_path))) {
while ((fcu = iter_step_fcurve(fcu_iter, rna_path)) != NULL) {
/* store the next fcurve for looping */
fcu_iter= fcu->next;
@@ -222,8 +239,12 @@ short ANIM_remove_driver (struct ID *id, const char rna_path[], int array_index,
}
}
else {
/* find the matching driver and remove it only
* Note: here is one of the places where we don't want new F-Curve + Driver added!
* so 'add' var must be 0
*/
fcu= verify_driver_fcurve(id, rna_path, array_index, 0);
if(fcu) {
if (fcu) {
BLI_remlink(&adt->drivers, fcu);
free_fcurve(fcu);
@@ -262,7 +283,7 @@ short ANIM_driver_can_paste (void)
/* Main Driver Management API calls:
* Make a copy of the driver for the specified property on the given ID block
*/
short ANIM_copy_driver (ID *id, const char rna_path[], int array_index, short UNUSED(flag))
short ANIM_copy_driver (ReportList *reports, ID *id, const char rna_path[], int array_index, short UNUSED(flag))
{
PointerRNA id_ptr, ptr;
PropertyRNA *prop;
@@ -271,7 +292,9 @@ short ANIM_copy_driver (ID *id, const char rna_path[], int array_index, short UN
/* validate pointer first - exit if failure */
RNA_id_pointer_create(id, &id_ptr);
if ((RNA_path_resolve(&id_ptr, rna_path, &ptr, &prop) == 0) || (prop == NULL)) {
printf("Copy Driver: Could not find Driver, as RNA Path is invalid for the given ID (ID = %s, Path = %s)\n", id->name, rna_path);
BKE_reportf(reports, RPT_ERROR,
"Could not find Driver to copy, as RNA Path is invalid for the given ID (ID = %s, Path = %s)",
id->name, rna_path);
return 0;
}
@@ -307,7 +330,7 @@ short ANIM_copy_driver (ID *id, const char rna_path[], int array_index, short UN
* Add a new driver for the specified property on the given ID block or replace an existing one
* with the driver + driver-curve data from the buffer
*/
short ANIM_paste_driver (ID *id, const char rna_path[], int array_index, short UNUSED(flag))
short ANIM_paste_driver (ReportList *reports, ID *id, const char rna_path[], int array_index, short UNUSED(flag))
{
PointerRNA id_ptr, ptr;
PropertyRNA *prop;
@@ -316,13 +339,15 @@ short ANIM_paste_driver (ID *id, const char rna_path[], int array_index, short U
/* validate pointer first - exit if failure */
RNA_id_pointer_create(id, &id_ptr);
if ((RNA_path_resolve(&id_ptr, rna_path, &ptr, &prop) == 0) || (prop == NULL)) {
printf("Paste Driver: Could not add Driver, as RNA Path is invalid for the given ID (ID = %s, Path = %s)\n", id->name, rna_path);
BKE_reportf(reports, RPT_ERROR,
"Could not paste Driver, as RNA Path is invalid for the given ID (ID = %s, Path = %s)",
id->name, rna_path);
return 0;
}
/* if the buffer is empty, cannot paste... */
if (channeldriver_copypaste_buf == NULL) {
printf("Paste Driver: No Driver to paste. \n");
BKE_report(reports, RPT_ERROR, "Paste Driver: No Driver to paste.");
return 0;
}
@@ -366,7 +391,6 @@ static int add_driver_button_exec (bContext *C, wmOperator *op)
{
PointerRNA ptr= {{0}};
PropertyRNA *prop= NULL;
char *path;
short success= 0;
int index, all= RNA_boolean_get(op->ptr, "all");
@@ -377,10 +401,11 @@ static int add_driver_button_exec (bContext *C, wmOperator *op)
index= -1;
if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) {
path= RNA_path_from_ID_to_property(&ptr, prop);
char *path= RNA_path_from_ID_to_property(&ptr, prop);
short flags = CREATEDRIVER_WITH_DEFAULT_DVAR;
if (path) {
success+= ANIM_add_driver(ptr.id.data, path, index, 0, DRIVER_TYPE_PYTHON);
success+= ANIM_add_driver(op->reports, ptr.id.data, path, index, flags, DRIVER_TYPE_PYTHON);
MEM_freeN(path);
}
@@ -389,7 +414,7 @@ static int add_driver_button_exec (bContext *C, wmOperator *op)
if (success) {
/* send updates */
uiContextAnimUpdate(C);
DAG_ids_flush_update(CTX_data_main(C), 0);
WM_event_add_notifier(C, NC_ANIMATION|ND_FCURVES_ORDER, NULL); // XXX
@@ -422,7 +447,6 @@ static int remove_driver_button_exec (bContext *C, wmOperator *op)
{
PointerRNA ptr= {{0}};
PropertyRNA *prop= NULL;
char *path;
short success= 0;
int index, all= RNA_boolean_get(op->ptr, "all");
@@ -433,15 +457,16 @@ static int remove_driver_button_exec (bContext *C, wmOperator *op)
index= -1;
if (ptr.id.data && ptr.data && prop) {
path= RNA_path_from_ID_to_property(&ptr, prop);
success= ANIM_remove_driver(ptr.id.data, path, index, 0);
char *path= RNA_path_from_ID_to_property(&ptr, prop);
success= ANIM_remove_driver(op->reports, ptr.id.data, path, index, 0);
MEM_freeN(path);
}
if (success) {
/* send updates */
uiContextAnimUpdate(C);
DAG_ids_flush_update(CTX_data_main(C), 0);
WM_event_add_notifier(C, NC_ANIMATION|ND_FCURVES_ORDER, NULL); // XXX
@@ -470,11 +495,10 @@ void ANIM_OT_driver_button_remove (wmOperatorType *ot)
/* Copy Driver Button Operator ------------------------ */
static int copy_driver_button_exec (bContext *C, wmOperator *UNUSED(op))
static int copy_driver_button_exec (bContext *C, wmOperator *op)
{
PointerRNA ptr= {{0}};
PropertyRNA *prop= NULL;
char *path;
short success= 0;
int index;
@@ -482,12 +506,12 @@ static int copy_driver_button_exec (bContext *C, wmOperator *UNUSED(op))
uiContextActiveProperty(C, &ptr, &prop, &index);
if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) {
path= RNA_path_from_ID_to_property(&ptr, prop);
char *path= RNA_path_from_ID_to_property(&ptr, prop);
if (path) {
/* only copy the driver for the button that this was involved for */
success= ANIM_copy_driver(ptr.id.data, path, index, 0);
success= ANIM_copy_driver(op->reports, ptr.id.data, path, index, 0);
uiContextAnimUpdate(C);
MEM_freeN(path);
@@ -515,11 +539,10 @@ void ANIM_OT_copy_driver_button (wmOperatorType *ot)
/* Paste Driver Button Operator ------------------------ */
static int paste_driver_button_exec (bContext *C, wmOperator *UNUSED(op))
static int paste_driver_button_exec (bContext *C, wmOperator *op)
{
PointerRNA ptr= {{0}};
PropertyRNA *prop= NULL;
char *path;
short success= 0;
int index;
@@ -527,12 +550,12 @@ static int paste_driver_button_exec (bContext *C, wmOperator *UNUSED(op))
uiContextActiveProperty(C, &ptr, &prop, &index);
if (ptr.id.data && ptr.data && prop && RNA_property_animateable(&ptr, prop)) {
path= RNA_path_from_ID_to_property(&ptr, prop);
char *path= RNA_path_from_ID_to_property(&ptr, prop);
if (path) {
/* only copy the driver for the button that this was involved for */
success= ANIM_paste_driver(ptr.id.data, path, index, 0);
success= ANIM_paste_driver(op->reports, ptr.id.data, path, index, 0);
uiContextAnimUpdate(C);
MEM_freeN(path);

View File

@@ -209,29 +209,36 @@ short ANIM_keyingset_context_ok_poll(struct bContext *C, struct KeyingSet *ks);
/* ************ Drivers ********************** */
/* Flags for use by driver creation calls */
typedef enum eCreateDriverFlags {
CREATEDRIVER_WITH_DEFAULT_DVAR = (1<<0), /* create drivers with a default variable for nicer UI */
} eCreateDriverFlags;
/* -------- */
/* Returns whether there is a driver in the copy/paste buffer to paste */
short ANIM_driver_can_paste(void);
/* Main Driver Management API calls:
* Add a new driver for the specified property on the given ID block
*/
short ANIM_add_driver(struct ID *id, const char rna_path[], int array_index, short flag, int type);
short ANIM_add_driver(struct ReportList *reports, struct ID *id, const char rna_path[], int array_index, short flag, int type);
/* Main Driver Management API calls:
* Remove the driver for the specified property on the given ID block (if available)
*/
short ANIM_remove_driver(struct ID *id, const char rna_path[], int array_index, short flag);
short ANIM_remove_driver(struct ReportList *reports, struct ID *id, const char rna_path[], int array_index, short flag);
/* Main Driver Management API calls:
* Make a copy of the driver for the specified property on the given ID block
*/
short ANIM_copy_driver(struct ID *id, const char rna_path[], int array_index, short flag);
short ANIM_copy_driver(struct ReportList *reports, struct ID *id, const char rna_path[], int array_index, short flag);
/* Main Driver Management API calls:
* Add a new driver for the specified property on the given ID block or replace an existing one
* with the driver + driver-curve data from the buffer
*/
short ANIM_paste_driver(struct ID *id, const char rna_path[], int array_index, short flag);
short ANIM_paste_driver(struct ReportList *reports, struct ID *id, const char rna_path[], int array_index, short flag);
/* ************ Auto-Keyframing ********************** */
/* Notes:

View File

@@ -310,18 +310,19 @@ static void do_graph_region_driver_buttons(bContext *C, void *UNUSED(arg), int e
}
/* callback to remove the active driver */
static void driver_remove_cb (bContext *UNUSED(C), void *ale_v, void *UNUSED(arg))
static void driver_remove_cb (bContext *C, void *ale_v, void *UNUSED(arg))
{
bAnimListElem *ale= (bAnimListElem *)ale_v;
ID *id= ale->id;
FCurve *fcu= ale->data;
ReportList *reports = CTX_wm_reports(C);
/* try to get F-Curve that driver lives on, and ID block which has this AnimData */
if (ELEM(NULL, id, fcu))
return;
/* call API method to remove this driver */
ANIM_remove_driver(id, fcu->rna_path, fcu->array_index, 0);
ANIM_remove_driver(reports, id, fcu->rna_path, fcu->array_index, 0);
}
/* callback to add a target variable to the active driver */

View File

@@ -3924,7 +3924,7 @@ enum {
/* Utilities ---------------------------------- */
/* Recursively iterate over tree, finding and working on selected items */
static void do_outliner_drivers_editop(SpaceOops *soops, ListBase *tree, short mode)
static void do_outliner_drivers_editop(SpaceOops *soops, ListBase *tree, ReportList *reports, short mode)
{
TreeElement *te;
TreeStoreElem *tselem;
@@ -3949,6 +3949,7 @@ static void do_outliner_drivers_editop(SpaceOops *soops, ListBase *tree, short m
/* only if ID and path were set, should we perform any actions */
if (id && path) {
short dflags = CREATEDRIVER_WITH_DEFAULT_DVAR;
int arraylen = 1;
/* array checks */
@@ -3970,13 +3971,13 @@ static void do_outliner_drivers_editop(SpaceOops *soops, ListBase *tree, short m
case DRIVERS_EDITMODE_ADD:
{
/* add a new driver with the information obtained (only if valid) */
ANIM_add_driver(id, path, array_index, flag, DRIVER_TYPE_PYTHON);
ANIM_add_driver(reports, id, path, array_index, dflags, DRIVER_TYPE_PYTHON);
}
break;
case DRIVERS_EDITMODE_REMOVE:
{
/* remove driver matching the information obtained (only if valid) */
ANIM_remove_driver(id, path, array_index, flag);
ANIM_remove_driver(reports, id, path, array_index, dflags);
}
break;
}
@@ -3991,13 +3992,13 @@ static void do_outliner_drivers_editop(SpaceOops *soops, ListBase *tree, short m
/* go over sub-tree */
if ((tselem->flag & TSE_CLOSED)==0)
do_outliner_drivers_editop(soops, &te->subtree, mode);
do_outliner_drivers_editop(soops, &te->subtree, reports, mode);
}
}
/* Add Operator ---------------------------------- */
static int outliner_drivers_addsel_exec(bContext *C, wmOperator *UNUSED(op))
static int outliner_drivers_addsel_exec(bContext *C, wmOperator *op)
{
SpaceOops *soutliner= CTX_wm_space_outliner(C);
@@ -4006,10 +4007,10 @@ static int outliner_drivers_addsel_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_CANCELLED;
/* recursively go into tree, adding selected items */
do_outliner_drivers_editop(soutliner, &soutliner->tree, DRIVERS_EDITMODE_ADD);
do_outliner_drivers_editop(soutliner, &soutliner->tree, op->reports, DRIVERS_EDITMODE_ADD);
/* send notifiers */
WM_event_add_notifier(C, ND_KEYS, NULL); // XXX
WM_event_add_notifier(C, NC_ANIMATION|ND_FCURVES_ORDER, NULL); // XXX
return OPERATOR_FINISHED;
}
@@ -4032,7 +4033,7 @@ void OUTLINER_OT_drivers_add_selected(wmOperatorType *ot)
/* Remove Operator ---------------------------------- */
static int outliner_drivers_deletesel_exec(bContext *C, wmOperator *UNUSED(op))
static int outliner_drivers_deletesel_exec(bContext *C, wmOperator *op)
{
SpaceOops *soutliner= CTX_wm_space_outliner(C);
@@ -4041,7 +4042,7 @@ static int outliner_drivers_deletesel_exec(bContext *C, wmOperator *UNUSED(op))
return OPERATOR_CANCELLED;
/* recursively go into tree, adding selected items */
do_outliner_drivers_editop(soutliner, &soutliner->tree, DRIVERS_EDITMODE_REMOVE);
do_outliner_drivers_editop(soutliner, &soutliner->tree, op->reports, DRIVERS_EDITMODE_REMOVE);
/* send notifiers */
WM_event_add_notifier(C, ND_KEYS, NULL); // XXX

View File

@@ -722,23 +722,6 @@ typedef enum eKSP_Grouping {
KSP_GROUP_TEMPLATE_ITEM
} eKSP_Grouping;
/* KS_Path->templates (Template Flags)
*
* Templates in paths are used to substitute information from the
* active context into relavent places in the path strings. This
* enum here defines the flags which define which templates are
* required by a path before it can be used
*/
typedef enum eKSP_TemplateTypes {
KSP_TEMPLATE_OBJECT = (1<<0), /* #obj - selected object */
KSP_TEMPLATE_PCHAN = (1<<1), /* #pch - selected posechannel */
KSP_TEMPLATE_CONSTRAINT = (1<<2), /* #con - active only */
KSP_TEMPLATE_NODE = (1<<3), /* #nod - selected node */
KSP_TEMPLATE_MODIFIER = (1<<4), /* #mod - active only */
KSP_TEMPLATE_ROT = (1<<16) /* modify rotation paths based on rotation mode of Object or Pose Channel */
} eKSP_TemplateTypes;
/* ---------------- */
/* KeyingSet definition (ks)

View File

@@ -2241,7 +2241,7 @@ static PyObject *pyrna_struct_driver_add(BPy_StructRNA *self, PyObject *args)
if(pyrna_struct_anim_args_parse(&self->ptr, "bpy_struct.driver_add():", path, &path_full, &index) < 0)
return NULL;
if(ANIM_add_driver((ID *)self->ptr.id.data, path_full, index, 0, DRIVER_TYPE_PYTHON)) {
if(ANIM_add_driver(/*ReportList*/NULL, (ID *)self->ptr.id.data, path_full, index, 0, DRIVER_TYPE_PYTHON)) {
ID *id= self->ptr.id.data;
AnimData *adt= BKE_animdata_from_id(id);
FCurve *fcu;
@@ -2300,7 +2300,7 @@ static PyObject *pyrna_struct_driver_remove(BPy_StructRNA *self, PyObject *args)
if(pyrna_struct_anim_args_parse(&self->ptr, "bpy_struct.driver_remove():", path, &path_full, &index) < 0)
return NULL;
ret= PyBool_FromLong(ANIM_remove_driver((ID *)self->ptr.id.data, path_full, index, 0));
ret= PyBool_FromLong(ANIM_remove_driver(/*ReportList*/NULL, (ID *)self->ptr.id.data, path_full, index, 0));
MEM_freeN(path_full);