static void add_nodes(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, ShaderGraph *graph, BL::ShaderNodeTree b_ntree, PtrSockMap& sockets_map) { /* add nodes */ BL::ShaderNodeTree::nodes_iterator b_node; PtrNodeMap node_map; PtrSockMap proxy_map; for(b_ntree.nodes.begin(b_node); b_node != b_ntree.nodes.end(); ++b_node) { if(b_node->mute()) { BL::Node::inputs_iterator b_input; BL::Node::outputs_iterator b_output; bool found_match = false; /* this is slightly different than blender logic, we just connect a * single pair for of input/output, but works ok for the node we have */ for(b_node->inputs.begin(b_input); b_input != b_node->inputs.end(); ++b_input) { if(b_input->is_linked()) { for(b_node->outputs.begin(b_output); b_output != b_node->outputs.end(); ++b_output) { if(b_output->is_linked() && b_input->type() == b_output->type()) { ProxyNode *proxy = new ProxyNode(convert_socket_type(b_input->type()), convert_socket_type(b_output->type())); graph->add(proxy); proxy_map[b_input->ptr.data] = SocketPair(proxy, proxy->inputs[0]->name); proxy_map[b_output->ptr.data] = SocketPair(proxy, proxy->outputs[0]->name); found_match = true; break; } } } if(found_match) break; } } else 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()); if (!b_group_ntree) continue; 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, b_data, b_group_ntree); } 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(), b_data, b_group_ntree); } add_nodes(scene, b_data, b_scene, graph, b_group_ntree, group_sockmap); } else { ShaderNode *node = add_node(scene, b_data, b_scene, graph, b_ntree, BL::ShaderNode(*b_node)); if(node) { BL::Node::inputs_iterator b_input; 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()); assert(input); /* copy values for non linked inputs */ set_default_value(input, *b_input, b_data, b_ntree); } } } } /* connect nodes */ BL::NodeTree::links_iterator b_link; for(b_ntree.links.begin(b_link); b_link != b_ntree.links.end(); ++b_link) { /* get blender link data */ BL::Node b_from_node = b_link->from_node(); BL::Node b_to_node = b_link->to_node(); BL::NodeSocket b_from_sock = b_link->from_socket(); BL::NodeSocket b_to_sock = b_link->to_socket(); SocketPair from_pair, to_pair; /* links without a node pointer are connections to group inputs/outputs */ /* from sock */ if(b_from_node) { if (b_from_node.mute() || 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) { if (b_to_node.mute() || 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]; /* either node may be NULL when the node was not exported, typically * because the node type is not supported */ 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()); graph->connect(output, input); } } }
static void add_nodes(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, ShaderGraph *graph, BL::ShaderNodeTree b_ntree, const ProxyMap &proxy_input_map, const ProxyMap &proxy_output_map) { /* add nodes */ BL::ShaderNodeTree::nodes_iterator b_node; PtrInputMap input_map; PtrOutputMap output_map; BL::Node::inputs_iterator b_input; BL::Node::outputs_iterator b_output; for(b_ntree.nodes.begin(b_node); b_node != b_ntree.nodes.end(); ++b_node) { if (b_node->mute() || b_node->is_a(&RNA_NodeReroute)) { /* replace muted node with internal links */ BL::Node::internal_links_iterator b_link; for (b_node->internal_links.begin(b_link); b_link != b_node->internal_links.end(); ++b_link) { ProxyNode *proxy = new ProxyNode(convert_socket_type(b_link->to_socket())); input_map[b_link->from_socket().ptr.data] = proxy->inputs[0]; output_map[b_link->to_socket().ptr.data] = proxy->outputs[0]; graph->add(proxy); } } else if (b_node->is_a(&RNA_ShaderNodeGroup)) { BL::NodeGroup b_gnode(*b_node); BL::ShaderNodeTree b_group_ntree(b_gnode.node_tree()); ProxyMap group_proxy_input_map, group_proxy_output_map; /* Add a proxy node for each socket * Do this even if the node group has no internal tree, * so that links have something to connect to and assert won't fail. */ for(b_node->inputs.begin(b_input); b_input != b_node->inputs.end(); ++b_input) { ProxyNode *proxy = new ProxyNode(convert_socket_type(*b_input)); graph->add(proxy); /* register the proxy node for internal binding */ group_proxy_input_map[b_input->identifier()] = proxy; input_map[b_input->ptr.data] = proxy->inputs[0]; set_default_value(proxy->inputs[0], *b_node, *b_input, b_data, b_ntree); } for(b_node->outputs.begin(b_output); b_output != b_node->outputs.end(); ++b_output) { ProxyNode *proxy = new ProxyNode(convert_socket_type(*b_output)); graph->add(proxy); /* register the proxy node for internal binding */ group_proxy_output_map[b_output->identifier()] = proxy; output_map[b_output->ptr.data] = proxy->outputs[0]; } if (b_group_ntree) add_nodes(scene, b_data, b_scene, graph, b_group_ntree, group_proxy_input_map, group_proxy_output_map); } else if (b_node->is_a(&RNA_NodeGroupInput)) { /* map each socket to a proxy node */ for(b_node->outputs.begin(b_output); b_output != b_node->outputs.end(); ++b_output) { ProxyMap::const_iterator proxy_it = proxy_input_map.find(b_output->identifier()); if (proxy_it != proxy_input_map.end()) { ProxyNode *proxy = proxy_it->second; output_map[b_output->ptr.data] = proxy->outputs[0]; } } } else if (b_node->is_a(&RNA_NodeGroupOutput)) { BL::NodeGroupOutput b_output_node(*b_node); /* only the active group output is used */ if (b_output_node.is_active_output()) { /* map each socket to a proxy node */ for(b_node->inputs.begin(b_input); b_input != b_node->inputs.end(); ++b_input) { ProxyMap::const_iterator proxy_it = proxy_output_map.find(b_input->identifier()); if (proxy_it != proxy_output_map.end()) { ProxyNode *proxy = proxy_it->second; input_map[b_input->ptr.data] = proxy->inputs[0]; set_default_value(proxy->inputs[0], *b_node, *b_input, b_data, b_ntree); } } } } else { ShaderNode *node = add_node(scene, b_data, b_scene, graph, b_ntree, BL::ShaderNode(*b_node)); if(node) { /* map node sockets for linking */ for(b_node->inputs.begin(b_input); b_input != b_node->inputs.end(); ++b_input) { ShaderInput *input = node_find_input_by_name(node, *b_node, *b_input); input_map[b_input->ptr.data] = input; set_default_value(input, *b_node, *b_input, b_data, b_ntree); } for(b_node->outputs.begin(b_output); b_output != b_node->outputs.end(); ++b_output) { ShaderOutput *output = node_find_output_by_name(node, *b_node, *b_output); output_map[b_output->ptr.data] = output; } } } } /* connect nodes */ BL::NodeTree::links_iterator b_link; for(b_ntree.links.begin(b_link); b_link != b_ntree.links.end(); ++b_link) { /* get blender link data */ BL::NodeSocket b_from_sock = b_link->from_socket(); BL::NodeSocket b_to_sock = b_link->to_socket(); ShaderOutput *output = 0; ShaderInput *input = 0; PtrOutputMap::iterator output_it = output_map.find(b_from_sock.ptr.data); if (output_it != output_map.end()) output = output_it->second; PtrInputMap::iterator input_it = input_map.find(b_to_sock.ptr.data); if (input_it != input_map.end()) input = input_it->second; /* either node may be NULL when the node was not exported, typically * because the node type is not supported */ if(output && input) graph->connect(output, input); } }