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
path: root/source
diff options
context:
space:
mode:
authorJoshua Leung <aligorith@gmail.com>2009-04-16 11:37:06 +0400
committerJoshua Leung <aligorith@gmail.com>2009-04-16 11:37:06 +0400
commit079304d199f7619f7eb0e8c256953505df1fcb53 (patch)
treeb6b101f1ce5dae1b4f8af5eeb7729aaacda67be7 /source
parent88d394d47dc0d1933faa06b50068f761d79a97ba (diff)
Animato - Drivers with Multiple Targets:
Drivers now support multiple targets which act as 'variables'. The targets have a short 'name' (see later), and reference some property (in much the same way as F-Curves do, using RNA-Paths) which acts as the 'value'. These named variables can then be used in a Python Expression which relates them to each other for more fine-grained control over the result of the driver. By using only the names of these variables in the expressions, we are able to define expressions/relationships in a much more readable way, as data access is separated from data use. This makes the underlying relationships easier to understand. By default, if no Python Expression is given, the variables are simply averaged together, so old files won't break. :) For example, check the following diagram (thanks Cessen/Nathan V from Peach team): http://download.blender.org/ftp/incoming/250_drivers_mockup_cessen.png TODO List: * Depsgraph building for new driver relationships doesn't work yet. This needs to be recoded again, but this new system makes this much easier, since the targets are clearly defined (i.e. no need to parse py expressions to get list of objects) * Graph Editor interface for editing these needs to be rewritten * Python function for evaluating these expressions is needed (Campbell?)
Diffstat (limited to 'source')
-rw-r--r--source/blender/blenkernel/BKE_fcurve.h6
-rw-r--r--source/blender/blenkernel/intern/depsgraph.c2
-rw-r--r--source/blender/blenkernel/intern/fcurve.c121
-rw-r--r--source/blender/blenkernel/intern/ipo.c49
-rw-r--r--source/blender/blenloader/intern/readfile.c18
-rw-r--r--source/blender/blenloader/intern/writefile.c12
-rw-r--r--source/blender/editors/space_graph/graph_buttons.c6
-rw-r--r--source/blender/editors/space_outliner/outliner.c12
-rw-r--r--source/blender/makesdna/DNA_anim_types.h57
-rw-r--r--source/blender/makesrna/RNA_access.h1
-rw-r--r--source/blender/makesrna/intern/rna_action.c81
11 files changed, 248 insertions, 117 deletions
diff --git a/source/blender/blenkernel/BKE_fcurve.h b/source/blender/blenkernel/BKE_fcurve.h
index 63ecc9d548a..f973f86972d 100644
--- a/source/blender/blenkernel/BKE_fcurve.h
+++ b/source/blender/blenkernel/BKE_fcurve.h
@@ -6,9 +6,12 @@
#define BKE_FCURVE_H
//struct ListBase;
+
struct FCurve;
struct FModifier;
struct ChannelDriver;
+struct DriverTarget;
+
struct BezTriple;
/* ************** Keyframe Tools ***************** */
@@ -27,6 +30,9 @@ 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_target(struct ChannelDriver *driver, struct DriverTarget *dtar);
+struct DriverTarget *driver_add_new_target(struct ChannelDriver *driver);
+
/* ************** F-Curve Modifiers *************** */
/* F-Curve Modifier Type-Info (fmi):
diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c
index 917fb7d1de4..088fd524b43 100644
--- a/source/blender/blenkernel/intern/depsgraph.c
+++ b/source/blender/blenkernel/intern/depsgraph.c
@@ -346,6 +346,7 @@ static void dag_add_driver_relation(AnimData *adt, DagForest *dag, DagNode *node
else if (driver->type == DRIVER_TYPE_ROTDIFF) {
// XXX rotational difference
}
+#if 0 // XXX old animato
else if (driver->id) {
if(GS(driver->id->name)==ID_OB) {
/* normal channel-drives-channel */
@@ -358,6 +359,7 @@ static void dag_add_driver_relation(AnimData *adt, DagForest *dag, DagNode *node
dag_add_relation(dag, node1, node, isdata?DAG_RL_OB_DATA:DAG_RL_OB_OB, "Ipo Driver");
}
}
+#endif // XXX old animato
#if 0 // XXX old 'normal' type
else if (icu->driver->ob) {
diff --git a/source/blender/blenkernel/intern/fcurve.c b/source/blender/blenkernel/intern/fcurve.c
index 2783c135cb9..5d475767369 100644
--- a/source/blender/blenkernel/intern/fcurve.c
+++ b/source/blender/blenkernel/intern/fcurve.c
@@ -558,19 +558,60 @@ short test_time_fcurve (FCurve *fcu)
/* Driver API --------------------------------- */
+/* This frees the driver target itself */
+void driver_free_target (ChannelDriver *driver, DriverTarget *dtar)
+{
+ /* sanity checks */
+ if (dtar == NULL)
+ return;
+
+ /* free target vars */
+ if (dtar->rna_path)
+ MEM_freeN(dtar->rna_path);
+
+ /* remove the target from the driver */
+ if (driver)
+ BLI_freelinkN(&driver->targets, dtar);
+ else
+ MEM_freeN(dtar);
+}
+
+/* Add a new driver target variable */
+DriverTarget *driver_add_new_target (ChannelDriver *driver)
+{
+ DriverTarget *dtar;
+
+ /* sanity checks */
+ if (driver == NULL)
+ return NULL;
+
+ /* make a new target */
+ dtar= MEM_callocN(sizeof(DriverTarget), "DriverTarget");
+ BLI_addtail(&driver->targets, dtar);
+
+ /* give the target a name */
+ strcpy(dtar->name, "a"); // XXX fimxe... this needs more work to get unique names without dots...
+
+ /* return the target */
+ return dtar;
+}
+
/* This frees the driver itself */
void fcurve_free_driver(FCurve *fcu)
{
ChannelDriver *driver;
+ DriverTarget *dtar, *dtarn;
/* sanity checks */
if ELEM(NULL, fcu, fcu->driver)
return;
driver= fcu->driver;
- /* free RNA-paths, as these were allocated when getting the path string */
- if (driver->rna_path) MEM_freeN(driver->rna_path);
- if (driver->rna_path2) MEM_freeN(driver->rna_path2);
+ /* free driver targets */
+ for (dtar= driver->targets.first; dtar; dtar= dtarn) {
+ dtarn= dtar->next;
+ driver_free_target(driver, dtar);
+ }
/* free driver itself, then set F-Curve's point to this to NULL (as the curve may still be used) */
MEM_freeN(driver);
@@ -581,6 +622,7 @@ void fcurve_free_driver(FCurve *fcu)
ChannelDriver *fcurve_copy_driver (ChannelDriver *driver)
{
ChannelDriver *ndriver;
+ DriverTarget *dtar;
/* sanity checks */
if (driver == NULL)
@@ -588,8 +630,16 @@ ChannelDriver *fcurve_copy_driver (ChannelDriver *driver)
/* copy all data */
ndriver= MEM_dupallocN(driver);
- ndriver->rna_path= MEM_dupallocN(ndriver->rna_path);
- ndriver->rna_path2= MEM_dupallocN(ndriver->rna_path2);
+
+ /* copy targets */
+ ndriver->targets.first= ndriver->targets.last= NULL;
+ BLI_duplicatelist(&ndriver->targets, &driver->targets);
+
+ for (dtar= ndriver->targets.first; dtar; dtar= dtar->next) {
+ /* make a copy of target's rna path if available */
+ if (dtar->rna_path)
+ dtar->rna_path = MEM_dupallocN(dtar->rna_path);
+ }
/* return the new driver */
return ndriver;
@@ -597,10 +647,8 @@ ChannelDriver *fcurve_copy_driver (ChannelDriver *driver)
/* Driver Evaluation -------------------------- */
-/* Helper function to obtain a value using RNA from the specified source (for evaluating drivers)
- * - target: used to specify which of the two driver-targets to use
- */
-static float driver_get_driver_value (ChannelDriver *driver, short target)
+/* Helper function to obtain a value using RNA from the specified source (for evaluating drivers) */
+static float driver_get_target_value (ChannelDriver *driver, DriverTarget *dtar)
{
PointerRNA id_ptr, ptr;
PropertyRNA *prop;
@@ -609,21 +657,15 @@ static float driver_get_driver_value (ChannelDriver *driver, short target)
int index;
float value= 0.0f;
- /* get RNA-pointer for the ID-block given in driver */
- if (target == 1) {
- /* second target */
- RNA_id_pointer_create(driver->id2, &id_ptr);
- id= driver->id2;
- path= driver->rna_path2;
- index= driver->array_index2;
- }
- else {
- /* first/main target */
- RNA_id_pointer_create(driver->id, &id_ptr);
- id= driver->id;
- path= driver->rna_path;
- index= driver->array_index;
- }
+ /* sanity check */
+ if ELEM(NULL, driver, dtar)
+ return 0.0f;
+
+ /* get RNA-pointer for the ID-block given in target */
+ RNA_id_pointer_create(dtar->id, &id_ptr);
+ id= dtar->id;
+ path= dtar->rna_path;
+ index= dtar->array_index;
/* error check for missing pointer... */
if (id == NULL) {
@@ -671,14 +713,37 @@ static float driver_get_driver_value (ChannelDriver *driver, short target)
*/
static float evaluate_driver (ChannelDriver *driver, float evaltime)
{
+ DriverTarget *dtar;
+
/* check if driver can be evaluated */
- if (driver->flag & DRIVER_FLAG_DISABLED)
+ if (driver->flag & DRIVER_FLAG_INVALID)
return 0.0f;
+ // TODO: the flags for individual targets need to be used too for more fine-grained support...
switch (driver->type) {
- case DRIVER_TYPE_CHANNEL: /* channel/setting drivers channel/setting */
- return driver_get_driver_value(driver, 0);
-
+ case DRIVER_TYPE_AVERAGE: /* average values of driver targets */
+ {
+ /* check how many targets there are first (i.e. just one?) */
+ if (driver->targets.first == driver->targets.last) {
+ /* just one target, so just use that */
+ dtar= driver->targets.first;
+ return driver_get_target_value(driver, dtar);
+ }
+ else {
+ /* more than one target, so average the values of the targets */
+ int tot = 0;
+ float value = 0.0f;
+
+ /* loop through targets, adding (hopefully we don't get any overflow!) */
+ for (dtar= driver->targets.first; dtar; dtar=dtar->next) {
+ value += driver_get_target_value(driver, dtar);
+ tot++;
+ }
+
+ /* return the average of these */
+ return (value / (float)tot);
+ }
+ }
case DRIVER_TYPE_PYTHON: /* expression */
{
diff --git a/source/blender/blenkernel/intern/ipo.c b/source/blender/blenkernel/intern/ipo.c
index b9417ccb467..48ffdca3a83 100644
--- a/source/blender/blenkernel/intern/ipo.c
+++ b/source/blender/blenkernel/intern/ipo.c
@@ -950,6 +950,7 @@ char *get_rna_access (int blocktype, int adrcode, char actname[], char constname
static ChannelDriver *idriver_to_cdriver (IpoDriver *idriver)
{
ChannelDriver *cdriver;
+ DriverTarget *dtar=NULL, *dtar2=NULL;
/* allocate memory for new driver */
cdriver= MEM_callocN(sizeof(ChannelDriver), "ChannelDriver");
@@ -957,6 +958,7 @@ static ChannelDriver *idriver_to_cdriver (IpoDriver *idriver)
/* if 'pydriver', just copy data across */
if (idriver->type == IPO_DRIVER_TYPE_PYTHON) {
/* PyDriver only requires the expression to be copied */
+ // TODO: but the expression will be useless...
cdriver->type = DRIVER_TYPE_PYTHON;
strcpy(cdriver->expression, idriver->name); // XXX is this safe?
}
@@ -965,12 +967,15 @@ static ChannelDriver *idriver_to_cdriver (IpoDriver *idriver)
if (idriver->blocktype == ID_AR) {
/* ID_PO */
if (idriver->adrcode == OB_ROT_DIFF) {
- if (G.f & G_DEBUG) printf("idriver_to_cdriver - rotdiff %p \n", idriver->ob);
/* Rotational Difference is a special type of driver now... */
cdriver->type= DRIVER_TYPE_ROTDIFF;
+ /* make 2 driver targets */
+ dtar= driver_add_new_target(cdriver);
+ dtar2= driver_add_new_target(cdriver);
+
/* driver must use bones from same armature... */
- cdriver->id= cdriver->id2= (ID *)idriver->ob;
+ dtar->id= dtar2->id= (ID *)idriver->ob;
/* paths for the two targets get the pointers to the relevant Pose-Channels
* - return pointers to Pose-Channels not rotation channels, as calculation code is picky
@@ -979,34 +984,36 @@ static ChannelDriver *idriver_to_cdriver (IpoDriver *idriver)
* - we use several hacks here - blocktype == -1 specifies that no property needs to be found, and
* providing a name for 'actname' will automatically imply Pose-Channel with name 'actname'
*/
- cdriver->rna_path= get_rna_access(-1, -1, idriver->name, NULL, NULL);
- cdriver->rna_path2= get_rna_access(-1, -1, idriver->name+DRIVER_NAME_OFFS, NULL, NULL);
+ dtar->rna_path= get_rna_access(-1, -1, idriver->name, NULL, NULL);
+ dtar2->rna_path= get_rna_access(-1, -1, idriver->name+DRIVER_NAME_OFFS, NULL, NULL);
}
else {
- if (G.f & G_DEBUG) printf("idriver_to_cdriver - arm %p \n", idriver->ob);
/* 'standard' driver */
- cdriver->type= DRIVER_TYPE_CHANNEL;
- cdriver->id= (ID *)idriver->ob;
+ cdriver->type= DRIVER_TYPE_AVERAGE;
+
+ /* make 1 driver target */
+ dtar= driver_add_new_target(cdriver);
+ dtar->id= (ID *)idriver->ob;
switch (idriver->adrcode) {
case OB_LOC_X: /* x,y,z location are quite straightforward */
- cdriver->rna_path= get_rna_access(ID_PO, AC_LOC_X, idriver->name, NULL, &cdriver->array_index);
+ dtar->rna_path= get_rna_access(ID_PO, AC_LOC_X, idriver->name, NULL, &dtar->array_index);
break;
case OB_LOC_Y:
- cdriver->rna_path= get_rna_access(ID_PO, AC_LOC_Y, idriver->name, NULL, &cdriver->array_index);
+ dtar->rna_path= get_rna_access(ID_PO, AC_LOC_Y, idriver->name, NULL, &dtar->array_index);
break;
case OB_LOC_Z:
- cdriver->rna_path= get_rna_access(ID_PO, AC_LOC_Z, idriver->name, NULL, &cdriver->array_index);
+ dtar->rna_path= get_rna_access(ID_PO, AC_LOC_Z, idriver->name, NULL, &dtar->array_index);
break;
case OB_SIZE_X: /* x,y,z scaling are also quite straightforward */
- cdriver->rna_path= get_rna_access(ID_PO, AC_SIZE_X, idriver->name, NULL, &cdriver->array_index);
+ dtar->rna_path= get_rna_access(ID_PO, AC_SIZE_X, idriver->name, NULL, &dtar->array_index);
break;
case OB_SIZE_Y:
- cdriver->rna_path= get_rna_access(ID_PO, AC_SIZE_Y, idriver->name, NULL, &cdriver->array_index);
+ dtar->rna_path= get_rna_access(ID_PO, AC_SIZE_Y, idriver->name, NULL, &dtar->array_index);
break;
case OB_SIZE_Z:
- cdriver->rna_path= get_rna_access(ID_PO, AC_SIZE_Z, idriver->name, NULL, &cdriver->array_index);
+ dtar->rna_path= get_rna_access(ID_PO, AC_SIZE_Z, idriver->name, NULL, &dtar->array_index);
break;
case OB_ROT_X: /* rotation - we need to be careful with this... XXX (another reason why we need eulers) */
@@ -1015,8 +1022,8 @@ static ChannelDriver *idriver_to_cdriver (IpoDriver *idriver)
{
// XXX this is not yet a 1:1 map, since we'd need euler rotations to make this work nicely (unless we make some hacks)
// XXX -1 here is a special hack...
- cdriver->rna_path= get_rna_access(ID_PO, -1, idriver->name, NULL, NULL);
- cdriver->array_index= idriver->adrcode - OB_ROT_X;
+ dtar->rna_path= get_rna_access(ID_PO, -1, idriver->name, NULL, NULL);
+ dtar->array_index= idriver->adrcode - OB_ROT_X;
}
break;
}
@@ -1024,14 +1031,16 @@ static ChannelDriver *idriver_to_cdriver (IpoDriver *idriver)
}
else {
/* ID_OB */
- if (G.f & G_DEBUG) printf("idriver_to_cdriver - ob %p \n", idriver->ob);
- cdriver->type= DRIVER_TYPE_CHANNEL;
- cdriver->id= (ID *)idriver->ob;
- cdriver->rna_path= get_rna_access(ID_OB, idriver->adrcode, NULL, NULL, &cdriver->array_index);
+ cdriver->type= DRIVER_TYPE_AVERAGE;
+
+ /* make 1 driver target */
+ dtar= driver_add_new_target(cdriver);
+
+ dtar->id= (ID *)idriver->ob;
+ dtar->rna_path= get_rna_access(ID_OB, idriver->adrcode, NULL, NULL, &dtar->array_index);
}
}
- if (G.f & G_DEBUG) printf("\tcdriver -> id = %p \n", cdriver->id);
/* free old driver */
MEM_freeN(idriver);
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 6508bed7437..8ea1c4a08f4 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -1667,8 +1667,10 @@ static void lib_link_fcurves(FileData *fd, ID *id, ListBase *list)
/* driver data */
if (fcu->driver) {
ChannelDriver *driver= fcu->driver;
- driver->id= newlibadr(fd, id->lib, driver->id);
- driver->id2= newlibadr(fd, id->lib, driver->id2);
+ DriverTarget *dtar;
+
+ for (dtar= driver->targets.first; dtar; dtar= dtar->next)
+ dtar->id= newlibadr(fd, id->lib, dtar->id);
}
/* modifiers */
@@ -1708,9 +1710,12 @@ static void direct_link_fcurves(FileData *fd, ListBase *list)
fcu->driver= newdataadr(fd, fcu->driver);
if (fcu->driver) {
ChannelDriver *driver= fcu->driver;
+ DriverTarget *dtar;
- driver->rna_path= newdataadr(fd, driver->rna_path);
- driver->rna_path2= newdataadr(fd, driver->rna_path2);
+ /* relink targets and their paths */
+ link_list(fd, &driver->targets);
+ for (dtar= driver->targets.first; dtar; dtar= dtar->next)
+ dtar->rna_path= newdataadr(fd, dtar->rna_path);
}
/* modifiers */
@@ -9193,9 +9198,10 @@ static void expand_animdata(FileData *fd, Main *mainvar, AnimData *adt)
/* drivers - assume that these F-Curves have driver data to be in this list... */
for (fcd= adt->drivers.first; fcd; fcd= fcd->next) {
ChannelDriver *driver= fcd->driver;
+ DriverTarget *dtar;
- expand_doit(fd, mainvar, driver->id);
- expand_doit(fd, mainvar, driver->id2);
+ for (dtar= driver->targets.first; dtar; dtar= dtar->next)
+ expand_doit(fd, mainvar, dtar->id);
}
}
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index 076edcd59d6..10f88e4d291 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -781,13 +781,17 @@ static void write_fcurves(WriteData *wd, ListBase *fcurves)
/* driver data */
if (fcu->driver) {
ChannelDriver *driver= fcu->driver;
+ DriverTarget *dtar;
writestruct(wd, DATA, "ChannelDriver", 1, driver);
- if (driver->rna_path)
- writedata(wd, DATA, strlen(driver->rna_path)+1, driver->rna_path);
- if (driver->rna_path2)
- writedata(wd, DATA, strlen(driver->rna_path2)+1, driver->rna_path2);
+ /* targets */
+ for (dtar= driver->targets.first; dtar; dtar= dtar->next) {
+ writestruct(wd, DATA, "DriverTarget", 1, dtar);
+
+ if (dtar->rna_path)
+ writedata(wd, DATA, strlen(dtar->rna_path)+1, dtar->rna_path);
+ }
}
/* Modifiers */
diff --git a/source/blender/editors/space_graph/graph_buttons.c b/source/blender/editors/space_graph/graph_buttons.c
index a54147f91e2..7a94614607d 100644
--- a/source/blender/editors/space_graph/graph_buttons.c
+++ b/source/blender/editors/space_graph/graph_buttons.c
@@ -157,6 +157,8 @@ static void do_graph_region_driver_buttons(bContext *C, void *arg, int event)
//WM_event_add_notifier(C, NC_OBJECT|ND_TRANSFORM, ob);
}
+#if 0
+
/* callback to copy over RNA-Paths accordingly */
static void driver_rnapath_copy_cb (bContext *C, void *driver_v, void *strbuf_v)
{
@@ -194,6 +196,8 @@ static void driver_update_flags_cb (bContext *C, void *fcu_v, void *dummy_v)
driver->flag &= ~DRIVER_FLAG_INVALID;
}
+#endif
+
static void graph_panel_drivers(const bContext *C, ARegion *ar, short cntrl, bAnimListElem *ale)
{
FCurve *fcu= (FCurve *)ale->data;
@@ -208,6 +212,7 @@ static void graph_panel_drivers(const bContext *C, ARegion *ar, short cntrl, bAn
/* to force height */
uiNewPanelHeight(block, 204);
+#if 0
/* general actions */
but= uiDefBut(block, BUT, B_IPO_DEPCHANGE, "Update Dependencies", 10, 200, 180, 22, NULL, 0.0, 0.0, 0, 0, "Force updates of dependencies");
uiButSetFunc(but, driver_update_flags_cb, fcu, NULL);
@@ -267,6 +272,7 @@ static void graph_panel_drivers(const bContext *C, ARegion *ar, short cntrl, bAn
30,70,230,19, NULL, 0, 0, 0, 0, "");
}
}
+#endif
}
/* ******************* f-modifiers ******************************** */
diff --git a/source/blender/editors/space_outliner/outliner.c b/source/blender/editors/space_outliner/outliner.c
index a3fd16940ae..6bd1e915b2b 100644
--- a/source/blender/editors/space_outliner/outliner.c
+++ b/source/blender/editors/space_outliner/outliner.c
@@ -929,14 +929,18 @@ static TreeElement *outliner_add_element(SpaceOops *soops, ListBase *lb, void *i
TreeElement *ted= outliner_add_element(soops, &te->subtree, adt, te, TSE_DRIVER_BASE, 0);
ID *lastadded= NULL;
FCurve *fcu;
+ DriverTarget *dtar;
ted->name= "Drivers";
for (fcu= adt->drivers.first; fcu; fcu= fcu->next) {
- if (fcu->driver && fcu->driver->id) {
- if (lastadded != fcu->driver->id) {
- outliner_add_element(soops, &ted->subtree, fcu->driver->id, ted, TSE_LINKED_OB, 0);
- lastadded= fcu->driver->id;
+ if (fcu->driver && fcu->driver->targets.first) {
+ for (dtar= fcu->driver->targets.first; dtar; dtar= dtar->next) {
+ if (lastadded != dtar->id) {
+ // XXX this lastadded check is rather lame, and also fails quite badly...
+ outliner_add_element(soops, &ted->subtree, dtar->id, ted, TSE_LINKED_OB, 0);
+ lastadded= dtar->id;
+ }
}
}
}
diff --git a/source/blender/makesdna/DNA_anim_types.h b/source/blender/makesdna/DNA_anim_types.h
index 0c04d046fda..e63c30faed0 100644
--- a/source/blender/makesdna/DNA_anim_types.h
+++ b/source/blender/makesdna/DNA_anim_types.h
@@ -168,6 +168,25 @@ enum {
/* Drivers -------------------------------------- */
+/* Driver Target
+ *
+ * A 'variable' for use as a target of the driver/expression.
+ * Defines a way of accessing some channel to use, that can be
+ * referred to in the expression as a variable, thus simplifying
+ * expressions and also Depsgraph building.
+ */
+typedef struct DriverTarget {
+ struct DriverTarget *next, *prev;
+
+ ID *id; /* ID-block which owns the target */
+ char *rna_path; /* target channel to use as driver value */
+ int array_index; /* if applicable, the index of the RNA-array item to use as driver */
+
+ int flags; /* flags for the validity of the target */
+
+ char name[64]; /* name of the variable */
+} DriverTarget;
+
/* Channel Driver (i.e. Drivers / Expressions) (driver)
*
* Channel Drivers are part of the dependency system, and are executed in addition to
@@ -180,34 +199,26 @@ enum {
* evaluated in. This order is set by the Depsgraph's sorting stuff.
*/
typedef struct ChannelDriver {
- /* primary target */
- ID *id; /* ID-block which owns the target */
- char *rna_path; /* target channel to use as driver value */
- int array_index; /* if applicable, the index of the RNA-array item to use as driver */
+ ListBase targets; /* targets for this driver (i.e. list of DriverTarget) */
+
+ /* python expression to execute (may call functions defined in an accessory file)
+ * which relates the target 'variables' in some way to yield a single usable value
+ */
+ char expression[256];
- /* value cache (placed here for alignment reasons) */
float curval; /* result of previous evaluation, for subtraction from result under certain circumstances */
+ float influence; /* influence of driver on result */ // XXX to be implemented... this is like the constraint influence setting
- /* secondary target (for rotational difference) */
- ID *id2; /* ID-block which owns the second target */
- char *rna_path2; /* second target channel to use as driver value */
- int array_index2; /* if applicable, the index of the RNA-array item to use as driver */
-
- /* general settings (placed here for alignment reasons) */
+ /* general settings */
int type; /* type of driver */
int flag; /* settings of driver */
-
- float influence; /* influence of driver on result */ // XXX to be implemented... this is like the constraint influence setting
-
- /* settings for Python Drivers (PyDrivers) */
- char expression[256]; /* python expression to execute (may call functions defined in an accessory file) */
} ChannelDriver;
/* driver type */
enum {
- /* channel drives channel */
- DRIVER_TYPE_CHANNEL = 0,
- /* py-expression used as driver */
+ /* target values are averaged together */
+ DRIVER_TYPE_AVERAGE = 0,
+ /* python expression/function relates targets */
DRIVER_TYPE_PYTHON,
/* rotational difference (must use rotation channels only) */
DRIVER_TYPE_ROTDIFF,
@@ -217,13 +228,11 @@ enum {
enum {
/* driver has invalid settings (internal flag) */
DRIVER_FLAG_INVALID = (1<<0),
- /* driver was disabled temporarily, so shouldn't be evaluated (set by user) */
- DRIVER_FLAG_DISABLED = (1<<1),
/* driver needs recalculation (set by depsgraph) */
- DRIVER_FLAG_RECALC = (1<<2),
+ DRIVER_FLAG_RECALC = (1<<1),
/* driver does replace value, but overrides (for layering of animation over driver) */
- // TODO: is this necessary?
- DRIVER_FLAG_LAYERING = (1<<3),
+ // TODO: this needs to be implemented at some stage or left out...
+ DRIVER_FLAG_LAYERING = (1<<2),
} eDriver_Flags;
/* F-Curves -------------------------------------- */
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index f6ec657b36f..b29170c435e 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -93,6 +93,7 @@ extern StructRNA RNA_DisplaceModifier;
extern StructRNA RNA_DistortedNoiseTexture;
extern StructRNA RNA_DomainFluidSettings;
extern StructRNA RNA_Driver;
+extern StructRNA RNA_DriverTarget;
extern StructRNA RNA_EdgeSplitModifier;
extern StructRNA RNA_EffectSequence;
extern StructRNA RNA_EnumProperty;
diff --git a/source/blender/makesrna/intern/rna_action.c b/source/blender/makesrna/intern/rna_action.c
index a73f9627121..4c8d0c88866 100644
--- a/source/blender/makesrna/intern/rna_action.c
+++ b/source/blender/makesrna/intern/rna_action.c
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
- * Contributor(s): Blender Foundation (2008), Roland Hess
+ * Contributor(s): Blender Foundation (2008), Roland Hess, Joshua Leung
*
* ***** END GPL LICENSE BLOCK *****
*/
@@ -37,38 +37,38 @@
#ifdef RNA_RUNTIME
-static void rna_Driver_RnaPath_get(PointerRNA *ptr, char *value)
+static void rna_DriverTarget_RnaPath_get(PointerRNA *ptr, char *value)
{
- ChannelDriver *driver= (ChannelDriver *)ptr->data;
+ DriverTarget *dtar= (DriverTarget *)ptr->data;
- if (driver->rna_path)
- strcpy(value, driver->rna_path);
+ if (dtar->rna_path)
+ strcpy(value, dtar->rna_path);
else
strcpy(value, "");
}
-static int rna_Driver_RnaPath_length(PointerRNA *ptr)
+static int rna_DriverTarget_RnaPath_length(PointerRNA *ptr)
{
- ChannelDriver *driver= (ChannelDriver *)ptr->data;
+ DriverTarget *dtar= (DriverTarget *)ptr->data;
- if (driver->rna_path)
- return strlen(driver->rna_path);
+ if (dtar->rna_path)
+ return strlen(dtar->rna_path);
else
return 0;
}
-static void rna_Driver_RnaPath_set(PointerRNA *ptr, const char *value)
+static void rna_DriverTarget_RnaPath_set(PointerRNA *ptr, const char *value)
{
- ChannelDriver *driver= (ChannelDriver *)ptr->data;
+ DriverTarget *dtar= (DriverTarget *)ptr->data;
// XXX in this case we need to be very careful, as this will require some new dependencies to be added!
- if (driver->rna_path)
- MEM_freeN(driver->rna_path);
+ if (dtar->rna_path)
+ MEM_freeN(dtar->rna_path);
if (strlen(value))
- driver->rna_path= BLI_strdup(value);
+ dtar->rna_path= BLI_strdup(value);
else
- driver->rna_path= NULL;
+ dtar->rna_path= NULL;
}
@@ -108,13 +108,39 @@ static void rna_FCurve_RnaPath_set(PointerRNA *ptr, const char *value)
#else
// XXX maybe this should be in a separate file?
+void rna_def_drivertarget(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna= RNA_def_struct(brna, "DriverTarget", NULL);
+ RNA_def_struct_ui_text(srna, "Driver Target", "Variable from some source/target for driver relationship");
+
+ /* Variable Name */
+ prop= RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
+ RNA_def_property_ui_text(prop, "Name", "Name to use in scripted expressions/functions.");
+
+ /* Target Properties */
+ prop= RNA_def_property(srna, "target", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "id");
+ RNA_def_property_ui_text(prop, "Object", "Object the specific property used can be found from");
+
+ prop= RNA_def_property(srna, "rna_path", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_funcs(prop, "rna_DriverTarget_RnaPath_get", "rna_DriverTarget_RnaPath_length", "rna_DriverTarget_RnaPath_set");
+ RNA_def_property_ui_text(prop, "RNA Path", "RNA Path (from Object) to property used");
+
+ prop= RNA_def_property(srna, "array_index", PROP_INT, PROP_NONE);
+ RNA_def_property_ui_text(prop, "RNA Array Index", "Index to the specific property used (if applicable)");
+}
+
+// XXX maybe this should be in a separate file?
void rna_def_channeldriver(BlenderRNA *brna)
{
StructRNA *srna;
PropertyRNA *prop;
static EnumPropertyItem prop_type_items[] = {
- {DRIVER_TYPE_CHANNEL, "NORMAL", "Normal", ""},
+ {DRIVER_TYPE_AVERAGE, "AVERAGE", "Averaged Value", ""},
{DRIVER_TYPE_PYTHON, "SCRIPTED", "Scripted Expression", ""},
{DRIVER_TYPE_ROTDIFF, "ROTDIFF", "Rotational Difference", ""},
{0, NULL, NULL, NULL}};
@@ -131,17 +157,11 @@ void rna_def_channeldriver(BlenderRNA *brna)
prop= RNA_def_property(srna, "expression", PROP_STRING, PROP_NONE);
RNA_def_property_ui_text(prop, "Expression", "Expression to use for Scripted Expression.");
- /* Pointers */
- prop= RNA_def_property(srna, "target", PROP_POINTER, PROP_NONE);
- RNA_def_property_pointer_sdna(prop, NULL, "id");
- RNA_def_property_ui_text(prop, "Driver Object", "Object that controls this Driver.");
-
- prop= RNA_def_property(srna, "rna_path", PROP_STRING, PROP_NONE);
- RNA_def_property_string_funcs(prop, "rna_Driver_RnaPath_get", "rna_Driver_RnaPath_length", "rna_Driver_RnaPath_set");
- RNA_def_property_ui_text(prop, "Driver RNA Path", "RNA Path (from Driver Object) to property used as Driver.");
-
- prop= RNA_def_property(srna, "array_index", PROP_INT, PROP_NONE);
- RNA_def_property_ui_text(prop, "Driver RNA Array Index", "Index to the specific property used as Driver if applicable.");
+ /* Collections */
+ prop= RNA_def_property(srna, "targets", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "targets", NULL);
+ RNA_def_property_struct_type(prop, "DriverTarget");
+ RNA_def_property_ui_text(prop, "Target Variables", "Properties acting as targets for this driver.");
}
// XXX maybe this should be in a separate file?
@@ -171,17 +191,15 @@ void rna_def_fcurve(BlenderRNA *brna)
/* Pointers */
prop= RNA_def_property(srna, "driver", PROP_POINTER, PROP_NONE);
- RNA_def_property_clear_flag(prop, PROP_EDITABLE); // xxx?
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Driver", "Channel Driver (only set for Driver F-Curves)");
/* Path + Array Index */
prop= RNA_def_property(srna, "rna_path", PROP_STRING, PROP_NONE);
- //RNA_def_property_clear_flag(prop, PROP_EDITABLE); // XXX for now editable
RNA_def_property_string_funcs(prop, "rna_FCurve_RnaPath_get", "rna_FCurve_RnaPath_length", "rna_FCurve_RnaPath_set");
RNA_def_property_ui_text(prop, "RNA Path", "RNA Path to property affected by F-Curve.");
prop= RNA_def_property(srna, "array_index", PROP_INT, PROP_NONE);
- //RNA_def_property_clear_flag(prop, PROP_EDITABLE); // XXX for now editable
RNA_def_property_ui_text(prop, "RNA Array Index", "Index to the specific property affected by F-Curve if applicable.");
/* Color */
@@ -196,7 +214,7 @@ void rna_def_fcurve(BlenderRNA *brna)
/* Collections */
prop= RNA_def_property(srna, "sampled_points", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "fpt", "totvert");
- RNA_def_property_struct_type(prop, "CurvePoint");
+ RNA_def_property_struct_type(prop, "CurvePoint"); // XXX FPoints not BPoints here! FPoints are much smaller!
RNA_def_property_ui_text(prop, "Sampled Points", "Sampled animation data");
prop= RNA_def_property(srna, "keyframe_points", PROP_COLLECTION, PROP_NONE);
@@ -281,6 +299,7 @@ void RNA_def_action(BlenderRNA *brna)
// should these be in their own file, or is that overkill?
rna_def_fcurve(brna);
+ rna_def_drivertarget(brna);
rna_def_channeldriver(brna);
}