From 5f6bd44c82bef24a43696449d8b905beeb53015b Mon Sep 17 00:00:00 2001 From: Lukas Toenne Date: Sun, 18 Dec 2011 15:34:06 +0000 Subject: Generalized node groups for Cycles. This allows group nodes inside other group nodes in cycles and makes the code more generic for all possible cases, like direct group input-to-output links and unused group sockets. Previous code tried to connect external nodes and internal group sockets by following links until a "real" node input/output. This quickly becomes complicated in corner cases as described above and can lead to unexpected behavior when the group socket is of a different type than the internal/external sockets, but that conversion is skipped. The new code uses the concept of "proxy nodes" similar to what the new compositor does. Each group socket is replaced with a proxy node with a single input and output, to which other nodes in the same tree and internal nodes can link to. After all groups have been expanded in the graph, these proxy nodes are removed again, adding converter nodes if necessary. --- intern/cycles/render/graph.cpp | 53 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 2 deletions(-) (limited to 'intern/cycles/render/graph.cpp') diff --git a/intern/cycles/render/graph.cpp b/intern/cycles/render/graph.cpp index cdded403cbe..cc29047f048 100644 --- a/intern/cycles/render/graph.cpp +++ b/intern/cycles/render/graph.cpp @@ -292,6 +292,42 @@ void ShaderGraph::copy_nodes(set& nodes, map& removed) +{ + foreach(ShaderNode *node, nodes) { + ProxyNode *proxy = dynamic_cast(node); + if (proxy) { + ShaderInput *input = proxy->inputs[0]; + ShaderOutput *output = proxy->outputs[0]; + + /* temp. copy of the output links list. + * output->links is modified when we disconnect! + */ + vector links(output->links); + ShaderOutput *from = input->link; + + /* bypass the proxy node */ + if (from) { + disconnect(input); + foreach(ShaderInput *to, links) { + disconnect(to); + connect(from, to); + } + } + else { + foreach(ShaderInput *to, links) { + disconnect(to); + + /* transfer the default input value to the target socket */ + to->set(input->value); + } + } + + removed[proxy->id] = true; + } + } +} + void ShaderGraph::break_cycles(ShaderNode *node, vector& visited, vector& on_stack) { visited[node->id] = true; @@ -322,15 +358,28 @@ void ShaderGraph::clean() nodes that don't feed into the output. how cycles are broken is undefined, they are invalid input, the important thing is to not crash */ + vector removed(nodes.size(), false); vector visited(nodes.size(), false); vector on_stack(nodes.size(), false); + + list newnodes; + + /* remove proxy nodes */ + remove_proxy_nodes(removed); + + foreach(ShaderNode *node, nodes) { + if(!removed[node->id]) + newnodes.push_back(node); + else + delete node; + } + nodes = newnodes; + newnodes.clear(); /* break cycles */ break_cycles(output(), visited, on_stack); /* remove unused nodes */ - list newnodes; - foreach(ShaderNode *node, nodes) { if(visited[node->id]) newnodes.push_back(node); -- cgit v1.2.3