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
diff options
context:
space:
mode:
authorJoshua Leung <aligorith@gmail.com>2012-07-03 09:11:37 +0400
committerJoshua Leung <aligorith@gmail.com>2012-07-03 09:11:37 +0400
commitc960d1692f4003c186b616806aa0c79e71ce4cb5 (patch)
tree76c2a6a01a2099bb9b2dc3980fea005371219c4e
parentf977da407b9229099da73ae71d51d0f3355132b1 (diff)
Bugfix [#31834] Cycles materials cannot be manipulated using drivers
Until now, there was never any code for making drivers on materials get recalculated when their dependencies were changed. However, since changing material colors with drivers is something that is quite common, a workaround was introduced to ensure that materials could still be driven (albeit with the relevant drivers rooted at object level). This worked well enough so far with traditional materials - though it was sometimes clunky and confusing for some users - and would have been ok to tide us over until the depsgraph refactor. The introduction of Cycles changed this, as it has in many other ways. Now that people use Cycles to render, they'll need to drive the material colors through the nested nodetree (and other things nested deeply within that). However, this is much more difficult to generate hacks to create the relevant paths needed to work around the problem. == This Commit... == * Adds a recursive driver calculation step to the BKE_object_handle_update() (which gets called whenever the depsgraph has finished tagging object datablocks for updates), which goes through calculating the drivers attached to the object (and the materials/nodetrees attached to that). This case gets handled everytime the object is tagged as needing updates to its "data" (OB_RECALC_DATA) * When building the depsgraph, every dependency that the drivers there have are treated as if they were attached to object.data instead. This should trick the depsgraph into tagging OB_RECALC_DATA to force recalculation of drivers, at the expense perhaps of modifiers getting recalculated again. == Todo == * The old workarounds noted are still in place (will be commented out in the next commit). This fix renders at least the material case redundant, although the textures case still needs a bit more work. * Check on whether similar hacks can be done for other datablock combinations * So far, only simple test cases have been tested. There is probably some performance penalty for heavy setups still (due to need to traverse down all parts of material/node hierarchy to find things that need updates). If there really is a problem here, we could try introducing some tags to limit this traversal (which get added at depsgraph build time). <--- USER TESTING NEEDED!!!
-rw-r--r--source/blender/blenkernel/BKE_material.h4
-rw-r--r--source/blender/blenkernel/intern/depsgraph.c50
-rw-r--r--source/blender/blenkernel/intern/material.c47
-rw-r--r--source/blender/blenkernel/intern/object.c22
4 files changed, 120 insertions, 3 deletions
diff --git a/source/blender/blenkernel/BKE_material.h b/source/blender/blenkernel/BKE_material.h
index 8aa25a235a8..2407330a237 100644
--- a/source/blender/blenkernel/BKE_material.h
+++ b/source/blender/blenkernel/BKE_material.h
@@ -42,6 +42,7 @@ struct ID;
struct Object;
struct Mesh;
struct MTFace;
+struct Scene;
/* materials */
@@ -92,6 +93,9 @@ int material_in_material(struct Material *parmat, struct Material *mat);
void ramp_blend(int type, float r_col[3], const float fac, const float col[3]);
+/* driver update hacks */
+void material_drivers_update(struct Scene *scene, struct Material *mat, float ctime);
+
/* copy/paste */
void clear_matcopybuf(void);
void free_matcopybuf(void);
diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c
index a1e67ebd414..99c3b17dee2 100644
--- a/source/blender/blenkernel/intern/depsgraph.c
+++ b/source/blender/blenkernel/intern/depsgraph.c
@@ -347,6 +347,44 @@ static void dag_add_driver_relation(AnimData *adt, DagForest *dag, DagNode *node
}
}
+/* XXX: forward def for material driver handling... */
+static void dag_add_material_driver_relations(DagForest *dag, DagNode *node, Material *ma);
+
+/* recursive handling for material nodetree drivers */
+static void dag_add_material_nodetree_driver_relations(DagForest *dag, DagNode *node, bNodeTree *ntree)
+{
+ bNode *n;
+
+ /* nodetree itself */
+ if (ntree->adt) {
+ dag_add_driver_relation(ntree->adt, dag, node, 1);
+ }
+
+ /* nodetree's nodes... */
+ for (n = ntree->nodes.first; n; n = n->next) {
+ if (n->id && GS(n->id->name) == ID_MA) {
+ dag_add_material_driver_relations(dag, node, (Material *)n->id);
+ }
+ else if (n->type == NODE_GROUP) {
+ dag_add_material_nodetree_driver_relations(dag, node, (bNodeTree *)n->id);
+ }
+ }
+}
+
+/* recursive handling for material drivers */
+static void dag_add_material_driver_relations(DagForest *dag, DagNode *node, Material *ma)
+{
+ /* material itself */
+ if (ma->adt) {
+ dag_add_driver_relation(ma->adt, dag, node, 1);
+ }
+
+ /* material's nodetree */
+ if (ma->nodetree) {
+ dag_add_material_nodetree_driver_relations(dag, node, ma->nodetree);
+ }
+}
+
static void dag_add_collision_field_relation(DagForest *dag, Scene *scene, Object *ob, DagNode *node)
{
Base *base;
@@ -572,6 +610,18 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O
break;
}
+ /* material drivers */
+ if (ob->totcol) {
+ int a;
+
+ for (a = 1; a <= ob->totcol; a++) {
+ Material *ma = give_current_material(ob, a);
+
+ /* recursively figure out if there are drivers, and hook these up to this object */
+ dag_add_material_driver_relations(dag, node, ma);
+ }
+ }
+
/* particles */
psys = ob->particlesystem.first;
if (psys) {
diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c
index 48d629a2944..7e8e5455df5 100644
--- a/source/blender/blenkernel/intern/material.c
+++ b/source/blender/blenkernel/intern/material.c
@@ -36,6 +36,7 @@
#include "MEM_guardedalloc.h"
+#include "DNA_anim_types.h"
#include "DNA_curve_types.h"
#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
@@ -1050,6 +1051,52 @@ int material_in_material(Material *parmat, Material *mat)
else
return 0;
}
+
+
+/* ****************** */
+
+/* Update drivers for materials in a nodetree */
+static void material_node_drivers_update(Scene *scene, bNodeTree *ntree, float ctime)
+{
+ bNode *node;
+
+ /* nodetree itself */
+ if (ntree->adt && ntree->adt->drivers.first) {
+ BKE_animsys_evaluate_animdata(scene, &ntree->id, ntree->adt, ctime, ADT_RECALC_DRIVERS);
+ }
+
+ /* nodes... */
+ for (node = ntree->nodes.first; node; node = node->next) {
+ if (node->id && GS(node->id->name) == ID_MA) {
+ /* TODO: prevent infinite recursion here... */
+ material_drivers_update(scene, (Material *)node->id, ctime);
+ }
+ else if (node->type == NODE_GROUP) {
+ material_node_drivers_update(scene, (bNodeTree *)node->id, ctime);
+ }
+ }
+}
+
+/* Calculate all drivers for materials
+ * FIXME: this is really a terrible method which may result in some things being calculated
+ * multiple times. However, without proper despgraph support for these things, we are forced
+ * into this sort of thing...
+ */
+void material_drivers_update(Scene *scene, Material *ma, float ctime)
+{
+ //if (G.f & G_DEBUG)
+ // printf("material_drivers_update(%s, %s)\n", scene->id.name, ma->id.name);
+
+ /* material itself */
+ if (ma->adt && ma->adt->drivers.first) {
+ BKE_animsys_evaluate_animdata(scene, &ma->id, ma->adt, ctime, ADT_RECALC_DRIVERS);
+ }
+
+ /* nodes */
+ if (ma->nodetree) {
+ material_node_drivers_update(scene, ma->nodetree, ctime);
+ }
+}
/* ****************** */
#if 0 /* UNUSED */
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 8fb8d863a8c..74f3d3ddb9d 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -2538,7 +2538,7 @@ void BKE_object_handle_update(Scene *scene, Object *ob)
printf("recalcdata %s\n", ob->id.name + 2);
if (adt) {
- /* evaluate drivers */
+ /* evaluate drivers - datalevel */
// XXX: for mesh types, should we push this to derivedmesh instead?
BKE_animsys_evaluate_animdata(scene, data_id, adt, ctime, ADT_RECALC_DRIVERS);
}
@@ -2595,8 +2595,24 @@ void BKE_object_handle_update(Scene *scene, Object *ob)
BKE_lattice_modifiers_calc(scene, ob);
break;
}
-
-
+
+ /* related materials */
+ /* XXX: without depsgraph tagging, this will always need to be run, which will be slow!
+ * However, not doing anything (or trying to hack around this lack) is not an option
+ * anymore, especially due to Cycles [#31834]
+ */
+ if (ob->totcol) {
+ int a;
+
+ for (a = 1; a <= ob->totcol; a++) {
+ Material *ma = give_current_material(ob, a);
+
+ /* recursively update drivers for this material */
+ material_drivers_update(scene, ma, ctime);
+ }
+ }
+
+ /* particles */
if (ob->particlesystem.first) {
ParticleSystem *tpsys, *psys;
DerivedMesh *dm;