Fix for #34708 and #34709, cycles group nodes were not working well with 0 or 2+ group input/output nodes.

The issue here was that the proxy nodes created for connecting extern group node sockets to the internal nodes were generated by the input/output nodes themselves.

0 input/output nodes: there would be no proxy that external group node sockets can map to
2+ input/output nodes: additional nodes would overwrite entries from previous nodes, so that only one of the input/output nodes would be used.

Solution is to always generate exactly 1 proxy node for every group socket in advance, regardless of whether it is used internally. Internal node sockets can then all map to this proxy node.

In the case out output nodes there should only ever be one active node, otherwise the connection to the proxy would be ambiguous. For this purpose the NODE_DO_OUTPUT flag has been exposed to RNA, so that cycles can check it and only use the active output.
This commit is contained in:
Lukas Toenne 2013-03-20 13:17:35 +00:00
parent 0130d7dcd4
commit 1c3b3321e7
2 changed files with 46 additions and 44 deletions

@ -680,66 +680,63 @@ static void add_nodes(Scene *scene, BL::BlendData b_data, BL::Scene b_scene, Sha
}
}
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_map;
if (!b_group_ntree)
continue;
add_nodes(scene, b_data, b_scene, graph, b_group_ntree, group_proxy_map);
/* map the outer socket to the internal proxy nodes */
/* 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);
/* get internal proxy node from group proxy map */
assert(group_proxy_map.find(b_input->identifier()) != group_proxy_map.end());
assert(group_proxy_map[b_input->identifier()]->special_type == SHADER_SPECIAL_TYPE_PROXY);
ProxyNode *proxy = group_proxy_map[b_input->identifier()];
/* register the proxy node for internal binding */
group_proxy_map[b_input->identifier()] = proxy;
input_map[b_input->ptr.data] = proxy->inputs[0];
/* input value for proxy inputs is defined by group node */
set_default_value(proxy->inputs[0], *b_node, *b_input, b_data, b_ntree);
}
/* map the outer socket to the internal proxy nodes */
for(b_node->outputs.begin(b_output); b_output != b_node->outputs.end(); ++b_output) {
/* get internal proxy node from group node map */
assert(group_proxy_map.find(b_output->identifier()) != group_proxy_map.end());
assert(group_proxy_map[b_output->identifier()]->special_type == SHADER_SPECIAL_TYPE_PROXY);
ProxyNode *proxy = group_proxy_map[b_output->identifier()];
output_map[b_output->ptr.data] = proxy->outputs[0];
}
}
else if (b_node->is_a(&RNA_NodeGroupInput)) {
/* add a proxy node for each socket */
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_map[b_output->identifier()] = proxy;
output_map[b_output->ptr.data] = proxy->outputs[0];
/* register the proxy node for external binding */
proxy_map[b_output->identifier()] = proxy;
graph->add(proxy);
}
if (b_group_ntree)
add_nodes(scene, b_data, b_scene, graph, b_group_ntree, group_proxy_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::iterator proxy_it = proxy_map.find(b_output->identifier());
if (proxy_it != proxy_map.end()) {
ProxyNode *proxy = proxy_it->second;
output_map[b_output->ptr.data] = proxy->outputs[0];
}
}
}
else if (b_node->is_a(&RNA_NodeGroupOutput)) {
/* add a proxy node for each socket */
for(b_node->inputs.begin(b_input); b_input != b_node->inputs.end(); ++b_input) {
ProxyNode *proxy = new ProxyNode(convert_socket_type(*b_input));
input_map[b_input->ptr.data] = proxy->inputs[0];
set_default_value(proxy->inputs[0], *b_node, *b_input, b_data, b_ntree);
/* register the proxy node for external binding */
proxy_map[b_input->identifier()] = proxy;
graph->add(proxy);
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::iterator proxy_it = proxy_map.find(b_input->identifier());
if (proxy_it != proxy_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 {

@ -2843,6 +2843,11 @@ static void def_group_output(StructRNA *srna)
RNA_def_property_struct_type(prop, "PropertyGroup");
RNA_def_property_flag(prop, PROP_IDPROPERTY);
RNA_def_property_ui_text(prop, "Interface", "Interface socket data");
prop = RNA_def_property(srna, "is_active_output", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", NODE_DO_OUTPUT);
RNA_def_property_ui_text(prop, "Active Output", "True if this node is used as the active group output");
RNA_def_property_update(prop, NC_NODE | NA_EDITED, "rna_Node_update");
}
static void def_group(StructRNA *srna)