Fix for incomplete Reroute node updates. Adding reroute nodes by spliting links would...
authorLukas Toenne <lukas.toenne@googlemail.com>
Mon, 6 Aug 2012 18:49:28 +0000 (18:49 +0000)
committerLukas Toenne <lukas.toenne@googlemail.com>
Mon, 6 Aug 2012 18:49:28 +0000 (18:49 +0000)
The reason is that the per-node updates used for Reroute node type inheritance are not supposed to be looking at connected nodes, they are purely for "local" updates. For this sort of "global" update which requires depth-first search, the update function on the node tree level must be used instead.

source/blender/blenkernel/intern/node.c
source/blender/nodes/composite/node_composite_tree.c
source/blender/nodes/intern/node_common.c
source/blender/nodes/intern/node_common.h
source/blender/nodes/shader/node_shader_tree.c
source/blender/nodes/texture/node_texture_tree.c

index 8670f86cd678d8f477bb53c2a1b8d0cb32d072ad..7cee9626c3f971d265fb8674d3f8d0de44cf7c6a 100644 (file)
@@ -1660,8 +1660,6 @@ void ntreeUpdateTree(bNodeTree *ntree)
                        else if (node->typeinfo->updatefunc)
                                node->typeinfo->updatefunc(ntree, node);
                }
-               /* clear update flag */
-               node->update = 0;
        }
        
        /* check link validity */
@@ -1683,7 +1681,10 @@ void ntreeUpdateTree(bNodeTree *ntree)
        /* XXX hack, should be done by depsgraph!! */
        ntreeVerifyNodes(G.main, &ntree->id);
        
-       /* clear the update flag */
+       /* clear update flags */
+       for (node = ntree->nodes.first; node; node = node->next) {
+               node->update = 0;
+       }
        ntree->update = 0;
 }
 
index 18ab3b7d6d144d2fab200863cfde23a4b252cb86..917c1163096ad9c69f1a50f9c1ac273cc2f4d397 100644 (file)
@@ -50,6 +50,7 @@
 #include "BKE_tracking.h"
 #include "BKE_utildefines.h"
 
+#include "node_common.h"
 #include "node_exec.h"
 #include "node_util.h"
 
@@ -247,6 +248,8 @@ static void local_merge(bNodeTree *localtree, bNodeTree *ntree)
 static void update(bNodeTree *ntree)
 {
        ntreeSetOutput(ntree);
+       
+       ntree_update_reroute_nodes(ntree);
 }
 
 bNodeTreeType ntreeType_Composite = {
index 463c938f6b741e4922c8308e3e0ecf99cf6f75a0..8e550ef3d4b9969e757bef986a96becc4cf9f4e2 100644 (file)
@@ -580,33 +580,74 @@ static void node_reroute_init(bNodeTree *ntree, bNode* node, bNodeTemplate *UNUS
        nodeAddSocket(ntree, node, SOCK_OUT, "Output", SOCK_RGBA);
 }
 
-static void node_reroute_update(bNodeTree *UNUSED(ntree), bNode *node)
+void register_node_type_reroute(bNodeTreeType *ttype)
+{
+       /* frame type is used for all tree types, needs dynamic allocation */
+       bNodeType *ntype= MEM_callocN(sizeof(bNodeType), "frame node type");
+       
+       node_type_base(ttype, ntype, NODE_REROUTE, "Reroute", NODE_CLASS_LAYOUT, 0);
+       node_type_init(ntype, node_reroute_init);
+       node_type_internal_connect(ntype, node_reroute_internal_connect);
+       
+       ntype->needs_free = 1;
+       nodeRegisterType(ttype, ntype);
+}
+
+static void node_reroute_inherit_type_recursive(bNodeTree *ntree, bNode *node)
 {
        bNodeSocket *input = node->inputs.first;
        bNodeSocket *output = node->outputs.first;
        int type = SOCK_FLOAT;
+       bNodeLink *link;
+       
+       /* XXX it would be a little bit more efficient to restrict actual updates
+        * to rerout nodes connected to an updated node, but there's no reliable flag
+        * to indicate updated nodes (node->update is not set on linking).
+        */
+       
+       node->done = 1;
+       
+       /* recursive update */
+       for (link = ntree->links.first; link; link = link->next)
+       {
+               bNode *fromnode = link->fromnode;
+               bNode *tonode = link->tonode;
+               if (!tonode || !fromnode)
+                       continue;
+               
+               if (tonode == node && fromnode->type == NODE_REROUTE && !fromnode->done)
+                       node_reroute_inherit_type_recursive(ntree, fromnode);
+               
+               if (fromnode == node && tonode->type == NODE_REROUTE && !tonode->done)
+                       node_reroute_inherit_type_recursive(ntree, tonode);
+       }
        
        /* determine socket type from unambiguous input/output connection if possible */
        if (input->limit==1 && input->link)
                type = input->link->fromsock->type;
        else if (output->limit==1 && output->link)
-                       type = output->link->tosock->type;
+               type = output->link->tosock->type;
        
-       /* same type for input/output */
-       nodeSocketSetType(input, type);
-       nodeSocketSetType(output, type);
+       /* arbitrary, could also test output->type, both are the same */
+       if (input->type != type) {
+               /* same type for input/output */
+               nodeSocketSetType(input, type);
+               nodeSocketSetType(output, type);
+       }
 }
 
-void register_node_type_reroute(bNodeTreeType *ttype)
+/* Global update function for Reroute node types.
+ * This depends on connected nodes, so must be done as a tree-wide update.
+ */
+void ntree_update_reroute_nodes(bNodeTree *ntree)
 {
-       /* frame type is used for all tree types, needs dynamic allocation */
-       bNodeType *ntype= MEM_callocN(sizeof(bNodeType), "frame node type");
+       bNode *node;
        
-       node_type_base(ttype, ntype, NODE_REROUTE, "Reroute", NODE_CLASS_LAYOUT, 0);
-       node_type_init(ntype, node_reroute_init);
-       node_type_internal_connect(ntype, node_reroute_internal_connect);
-       node_type_update(ntype, node_reroute_update, NULL);
+       /* clear tags */
+       for (node = ntree->nodes.first; node; node = node->next)
+               node->done = 0;
        
-       ntype->needs_free = 1;
-       nodeRegisterType(ttype, ntype);
+       for (node = ntree->nodes.first; node; node = node->next)
+               if (node->type == NODE_REROUTE && !node->done)
+                       node_reroute_inherit_type_recursive(ntree, node);
 }
index f1bb837e48310bfdb7f46da415ab8d08d5ca3f29..00f72469b0ff7ec744974e29e3d241bf7a96803f 100644 (file)
@@ -59,4 +59,6 @@ void node_group_edit_clear(bNode *node);
 
 void node_loop_update_tree(struct bNodeTree *ngroup);
 
+void ntree_update_reroute_nodes(struct bNodeTree *ntree);
+
 #endif
index a1d873231e7d405139ceaad5065ebc696f743398..fa623eaad3d9fd6047b6ca23f1413879678f1a05 100644 (file)
@@ -55,6 +55,7 @@
 
 #include "RE_shader_ext.h"
 
+#include "node_common.h"
 #include "node_exec.h"
 #include "node_util.h"
 #include "node_shader_util.h"
@@ -133,6 +134,8 @@ static void local_sync(bNodeTree *localtree, bNodeTree *ntree)
 static void update(bNodeTree *ntree)
 {
        ntreeSetOutput(ntree);
+       
+       ntree_update_reroute_nodes(ntree);
 }
 
 bNodeTreeType ntreeType_Shader = {
index 1a11a7075b82fad3b0a25572510f9a669fa85477..063cc31e6f6033d785e29381ecadffdeb673ecac 100644 (file)
@@ -45,6 +45,7 @@
 #include "BKE_main.h"
 #include "BKE_node.h"
 
+#include "node_common.h"
 #include "node_exec.h"
 #include "node_util.h"
 #include "NOD_texture.h"
@@ -112,6 +113,11 @@ static void local_sync(bNodeTree *localtree, bNodeTree *ntree)
        }
 }
 
+static void update(bNodeTree *ntree)
+{
+       ntree_update_reroute_nodes(ntree);
+}
+
 bNodeTreeType ntreeType_Texture = {
        /* type */                              NTREE_TEXTURE,
        /* id_name */                   "NTTexture Nodetree",
@@ -125,7 +131,7 @@ bNodeTreeType ntreeType_Texture = {
        /* localize */                  localize,
        /* local_sync */                local_sync,
        /* local_merge */               NULL,
-       /* update */                    NULL,
+       /* update */                    update,
        /* update_node */               NULL,
        /* validate_link */             NULL,
        /* internal_connect */  node_internal_connect_default