diff options
-rw-r--r-- | intern/cycles/blender/blender_shader.cpp | 212 | ||||
-rw-r--r-- | intern/cycles/render/graph.cpp | 53 | ||||
-rw-r--r-- | intern/cycles/render/graph.h | 1 | ||||
-rw-r--r-- | intern/cycles/render/nodes.cpp | 20 | ||||
-rw-r--r-- | intern/cycles/render/nodes.h | 8 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_nodetree.c | 10 |
6 files changed, 200 insertions, 104 deletions
diff --git a/intern/cycles/blender/blender_shader.cpp b/intern/cycles/blender/blender_shader.cpp index ecc85a92ae0..5c39a3f169d 100644 --- a/intern/cycles/blender/blender_shader.cpp +++ b/intern/cycles/blender/blender_shader.cpp @@ -50,28 +50,6 @@ void BlenderSync::find_shader(BL::ID id, vector<uint>& used_shaders, int default /* Graph */ -static BL::NodeSocket get_node_input(BL::Node *b_group_node, BL::NodeSocket b_in) -{ - if(b_group_node) { - - BL::NodeTree b_ntree = BL::NodeGroup(*b_group_node).node_tree(); - BL::NodeTree::links_iterator b_link; - - for(b_ntree.links.begin(b_link); b_link != b_ntree.links.end(); ++b_link) { - if(b_link->to_socket().ptr.data == b_in.ptr.data) { - BL::Node::inputs_iterator b_gin; - - for(b_group_node->inputs.begin(b_gin); b_gin != b_group_node->inputs.end(); ++b_gin) - if(b_gin->group_socket().ptr.data == b_link->from_socket().ptr.data) - return *b_gin; - - } - } - } - - return b_in; -} - static BL::NodeSocket get_node_output(BL::Node b_node, const string& name) { BL::Node::outputs_iterator b_out; @@ -121,7 +99,7 @@ static void get_tex_mapping(TextureMapping *mapping, BL::ShaderNodeMapping b_map mapping->scale = get_float3(b_mapping.scale()); } -static ShaderNode *add_node(BL::BlendData b_data, ShaderGraph *graph, BL::Node *b_group_node, BL::ShaderNode b_node) +static ShaderNode *add_node(BL::BlendData b_data, ShaderGraph *graph, BL::ShaderNode b_node) { ShaderNode *node = NULL; @@ -470,59 +448,115 @@ static SocketPair node_socket_map_pair(PtrNodeMap& node_map, BL::Node b_node, BL return SocketPair(node_map[b_node.ptr.data], name); } -static void add_nodes(BL::BlendData b_data, ShaderGraph *graph, BL::ShaderNodeTree b_ntree, BL::Node *b_group_node, PtrSockMap& sockets_map) +static ShaderSocketType convert_socket_type(BL::NodeSocket::type_enum b_type) +{ + switch (b_type) { + case BL::NodeSocket::type_VALUE: + return SHADER_SOCKET_FLOAT; + case BL::NodeSocket::type_VECTOR: + return SHADER_SOCKET_VECTOR; + case BL::NodeSocket::type_RGBA: + return SHADER_SOCKET_COLOR; + case BL::NodeSocket::type_SHADER: + return SHADER_SOCKET_CLOSURE; + + case BL::NodeSocket::type_BOOLEAN: + case BL::NodeSocket::type_MESH: + case BL::NodeSocket::type_INT: + default: + return SHADER_SOCKET_FLOAT; + } +} + +static void set_default_value(ShaderInput *input, BL::NodeSocket sock) +{ + /* copy values for non linked inputs */ + switch(input->type) { + case SHADER_SOCKET_FLOAT: { + BL::NodeSocketFloatNone value_sock(sock); + input->set(value_sock.default_value()); + break; + } + case SHADER_SOCKET_COLOR: { + BL::NodeSocketRGBA rgba_sock(sock); + input->set(get_float3(rgba_sock.default_value())); + break; + } + case SHADER_SOCKET_NORMAL: + case SHADER_SOCKET_POINT: + case SHADER_SOCKET_VECTOR: { + BL::NodeSocketVectorNone vec_sock(sock); + input->set(get_float3(vec_sock.default_value())); + break; + } + case SHADER_SOCKET_CLOSURE: + break; + } +} + +static void add_nodes(BL::BlendData b_data, ShaderGraph *graph, BL::ShaderNodeTree b_ntree, PtrSockMap& sockets_map) { /* add nodes */ BL::ShaderNodeTree::nodes_iterator b_node; PtrNodeMap node_map; - map<void*, PtrSockMap> node_groups; + PtrSockMap proxy_map; for(b_ntree.nodes.begin(b_node); b_node != b_ntree.nodes.end(); ++b_node) { if(b_node->is_a(&RNA_NodeGroup)) { + /* add proxy converter nodes for inputs and outputs */ BL::NodeGroup b_gnode(*b_node); BL::ShaderNodeTree b_group_ntree(b_gnode.node_tree()); - - node_groups[b_node->ptr.data] = PtrSockMap(); - add_nodes(b_data, graph, b_group_ntree, &b_gnode, node_groups[b_node->ptr.data]); + BL::Node::inputs_iterator b_input; + BL::Node::outputs_iterator b_output; + + PtrSockMap group_sockmap; + + for(b_node->inputs.begin(b_input); b_input != b_node->inputs.end(); ++b_input) { + ShaderSocketType extern_type = convert_socket_type(b_input->type()); + ShaderSocketType intern_type = convert_socket_type(b_input->group_socket().type()); + ShaderNode *proxy = graph->add(new ProxyNode(extern_type, intern_type)); + + /* map the external node socket to the proxy node socket */ + proxy_map[b_input->ptr.data] = SocketPair(proxy, proxy->inputs[0]->name); + /* map the internal group socket to the proxy node socket */ + group_sockmap[b_input->group_socket().ptr.data] = SocketPair(proxy, proxy->outputs[0]->name); + + /* default input values of the group node */ + set_default_value(proxy->inputs[0], *b_input); + } + + for(b_node->outputs.begin(b_output); b_output != b_node->outputs.end(); ++b_output) { + ShaderSocketType extern_type = convert_socket_type(b_output->type()); + ShaderSocketType intern_type = convert_socket_type(b_output->group_socket().type()); + ShaderNode *proxy = graph->add(new ProxyNode(intern_type, extern_type)); + + /* map the external node socket to the proxy node socket */ + proxy_map[b_output->ptr.data] = SocketPair(proxy, proxy->outputs[0]->name); + /* map the internal group socket to the proxy node socket */ + group_sockmap[b_output->group_socket().ptr.data] = SocketPair(proxy, proxy->inputs[0]->name); + + /* default input values of internal, unlinked group outputs */ + set_default_value(proxy->inputs[0], b_output->group_socket()); + } + + add_nodes(b_data, graph, b_group_ntree, group_sockmap); } else { - ShaderNode *node = add_node(b_data, graph, b_group_node, BL::ShaderNode(*b_node)); - + ShaderNode *node = add_node(b_data, graph, BL::ShaderNode(*b_node)); + if(node) { BL::Node::inputs_iterator b_input; - BL::Node::outputs_iterator b_output; - + node_map[b_node->ptr.data] = node; - + for(b_node->inputs.begin(b_input); b_input != b_node->inputs.end(); ++b_input) { SocketPair pair = node_socket_map_pair(node_map, *b_node, *b_input); ShaderInput *input = pair.first->input(pair.second.c_str()); - BL::NodeSocket sock(get_node_input(b_group_node, *b_input)); - + assert(input); - + /* copy values for non linked inputs */ - switch(input->type) { - case SHADER_SOCKET_FLOAT: { - BL::NodeSocketFloatNone value_sock(sock); - input->set(value_sock.default_value()); - break; - } - case SHADER_SOCKET_COLOR: { - BL::NodeSocketRGBA rgba_sock(sock); - input->set(get_float3(rgba_sock.default_value())); - break; - } - case SHADER_SOCKET_NORMAL: - case SHADER_SOCKET_POINT: - case SHADER_SOCKET_VECTOR: { - BL::NodeSocketVectorNone vec_sock(sock); - input->set(get_float3(vec_sock.default_value())); - break; - } - case SHADER_SOCKET_CLOSURE: - break; - } + set_default_value(input, *b_input); } } } @@ -539,54 +573,34 @@ static void add_nodes(BL::BlendData b_data, ShaderGraph *graph, BL::ShaderNodeTr BL::NodeSocket b_from_sock = b_link->from_socket(); BL::NodeSocket b_to_sock = b_link->to_socket(); - /* if link with group socket, add to map so we can connect it later */ - if(b_group_node) { - if(!b_from_node) { - sockets_map[b_from_sock.ptr.data] = - node_socket_map_pair(node_map, b_to_node, b_to_sock); - - continue; - } - else if(!b_to_node) { - sockets_map[b_to_sock.ptr.data] = - node_socket_map_pair(node_map, b_from_node, b_from_sock); - - continue; - } - } - SocketPair from_pair, to_pair; + /* links without a node pointer are connections to group inputs/outputs */ + /* from sock */ - if(b_from_node.is_a(&RNA_NodeGroup)) { - /* group node */ - BL::NodeSocket group_sock = b_from_sock.group_socket(); - from_pair = node_groups[b_from_node.ptr.data][group_sock.ptr.data]; - } - else { - /* regular node */ - from_pair = node_socket_map_pair(node_map, b_from_node, b_from_sock); + if(b_from_node) { + if (b_from_node.is_a(&RNA_NodeGroup)) + from_pair = proxy_map[b_from_sock.ptr.data]; + else + from_pair = node_socket_map_pair(node_map, b_from_node, b_from_sock); } + else + from_pair = sockets_map[b_from_sock.ptr.data]; /* to sock */ - if(b_to_node.is_a(&RNA_NodeGroup)) { - /* group node */ - BL::NodeSocket group_sock = b_to_sock.group_socket(); - to_pair = node_groups[b_to_node.ptr.data][group_sock.ptr.data]; - } - else { - /* regular node */ - to_pair = node_socket_map_pair(node_map, b_to_node, b_to_sock); + if(b_to_node) { + if (b_to_node.is_a(&RNA_NodeGroup)) + to_pair = proxy_map[b_to_sock.ptr.data]; + else + to_pair = node_socket_map_pair(node_map, b_to_node, b_to_sock); } + else + to_pair = sockets_map[b_to_sock.ptr.data]; - /* in case of groups there may not actually be a node inside the group - that the group socket connects to, so from_node or to_node may be NULL */ - if(from_pair.first && to_pair.first) { - ShaderOutput *output = from_pair.first->output(from_pair.second.c_str()); - ShaderInput *input = to_pair.first->input(to_pair.second.c_str()); + ShaderOutput *output = from_pair.first->output(from_pair.second.c_str()); + ShaderInput *input = to_pair.first->input(to_pair.second.c_str()); - graph->connect(output, input); - } + graph->connect(output, input); } } @@ -613,7 +627,7 @@ void BlenderSync::sync_materials() PtrSockMap sock_to_node; BL::ShaderNodeTree b_ntree(b_mat->node_tree()); - add_nodes(b_data, graph, b_ntree, NULL, sock_to_node); + add_nodes(b_data, graph, b_ntree, sock_to_node); } else { ShaderNode *closure, *out; @@ -654,7 +668,7 @@ void BlenderSync::sync_world() PtrSockMap sock_to_node; BL::ShaderNodeTree b_ntree(b_world.node_tree()); - add_nodes(b_data, graph, b_ntree, NULL, sock_to_node); + add_nodes(b_data, graph, b_ntree, sock_to_node); } else if(b_world) { ShaderNode *closure, *out; @@ -703,7 +717,7 @@ void BlenderSync::sync_lamps() PtrSockMap sock_to_node; BL::ShaderNodeTree b_ntree(b_lamp->node_tree()); - add_nodes(b_data, graph, b_ntree, NULL, sock_to_node); + add_nodes(b_data, graph, b_ntree, sock_to_node); } else { ShaderNode *closure, *out; 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); diff --git a/intern/cycles/render/graph.h b/intern/cycles/render/graph.h index 2a2df5e1377..91ec83aba21 100644 --- a/intern/cycles/render/graph.h +++ b/intern/cycles/render/graph.h @@ -217,6 +217,7 @@ protected: void find_dependencies(set<ShaderNode*>& dependencies, ShaderInput *input); void copy_nodes(set<ShaderNode*>& nodes, map<ShaderNode*, ShaderNode*>& nnodemap); + void remove_proxy_nodes(vector<bool>& removed); void break_cycles(ShaderNode *node, vector<bool>& visited, vector<bool>& on_stack); void clean(); void bump_from_displacement(); diff --git a/intern/cycles/render/nodes.cpp b/intern/cycles/render/nodes.cpp index 5cabb248709..7d873221cd6 100644 --- a/intern/cycles/render/nodes.cpp +++ b/intern/cycles/render/nodes.cpp @@ -869,6 +869,26 @@ void ConvertNode::compile(OSLCompiler& compiler) assert(0); } +/* Proxy */ + +ProxyNode::ProxyNode(ShaderSocketType from_, ShaderSocketType to_) +: ShaderNode("proxy") +{ + from = from_; + to = to_; + + add_input("Input", from); + add_output("Output", to); +} + +void ProxyNode::compile(SVMCompiler& compiler) +{ +} + +void ProxyNode::compile(OSLCompiler& compiler) +{ +} + /* BSDF Closure */ BsdfNode::BsdfNode() diff --git a/intern/cycles/render/nodes.h b/intern/cycles/render/nodes.h index 28fff22fc34..f0a669f3f87 100644 --- a/intern/cycles/render/nodes.h +++ b/intern/cycles/render/nodes.h @@ -158,6 +158,14 @@ public: ShaderSocketType from, to; }; +class ProxyNode : public ShaderNode { +public: + ProxyNode(ShaderSocketType from, ShaderSocketType to); + SHADER_NODE_BASE_CLASS(ProxyNode) + + ShaderSocketType from, to; +}; + class BsdfNode : public ShaderNode { public: SHADER_NODE_CLASS(BsdfNode) diff --git a/source/blender/makesrna/intern/rna_nodetree.c b/source/blender/makesrna/intern/rna_nodetree.c index c588dc9c8ac..c15758eed1f 100644 --- a/source/blender/makesrna/intern/rna_nodetree.c +++ b/source/blender/makesrna/intern/rna_nodetree.c @@ -64,9 +64,13 @@ EnumPropertyItem nodetree_type_items[] = { EnumPropertyItem node_socket_type_items[] = { - {SOCK_FLOAT, "VALUE", 0, "Value", ""}, - {SOCK_VECTOR, "VECTOR", 0, "Vector", ""}, - {SOCK_RGBA, "RGBA", 0, "RGBA", ""}, + {SOCK_FLOAT, "VALUE", 0, "Value", ""}, + {SOCK_VECTOR, "VECTOR", 0, "Vector", ""}, + {SOCK_RGBA, "RGBA", 0, "RGBA", ""}, + {SOCK_SHADER, "SHADER", 0, "Shader", ""}, + {SOCK_BOOLEAN, "BOOLEAN", 0, "Boolean", ""}, + {SOCK_MESH, "MESH", 0, "Mesh", ""}, + {SOCK_INT, "INT", 0, "Int", ""}, {0, NULL, 0, NULL, NULL}}; EnumPropertyItem node_math_items[] = { |