diff options
author | Lukas Toenne <lukas.toenne@googlemail.com> | 2011-12-18 19:34:06 +0400 |
---|---|---|
committer | Lukas Toenne <lukas.toenne@googlemail.com> | 2011-12-18 19:34:06 +0400 |
commit | 5f6bd44c82bef24a43696449d8b905beeb53015b (patch) | |
tree | 7e955e53c4e9ee8a44c716b79ceaeebc34511b08 /intern/cycles/render/graph.cpp | |
parent | b49463c439820c5039caf63421bdc8f3a58554b2 (diff) |
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.
Diffstat (limited to 'intern/cycles/render/graph.cpp')
-rw-r--r-- | intern/cycles/render/graph.cpp | 53 |
1 files changed, 51 insertions, 2 deletions
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<ShaderNode*>& nodes, map<ShaderNode*, ShaderNod } } +void ShaderGraph::remove_proxy_nodes(vector<bool>& removed) +{ + foreach(ShaderNode *node, nodes) { + ProxyNode *proxy = dynamic_cast<ProxyNode*>(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<ShaderInput*> 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<bool>& visited, vector<bool>& 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<bool> removed(nodes.size(), false); vector<bool> visited(nodes.size(), false); vector<bool> on_stack(nodes.size(), false); + + list<ShaderNode*> 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<ShaderNode*> newnodes; - foreach(ShaderNode *node, nodes) { if(visited[node->id]) newnodes.push_back(node); |