static void node_reroute_inherit_type_recursive(bNodeTree *ntree, bNode *node) { bNodeSocket *input = node->inputs.first; bNodeSocket *output = node->outputs.first; bNodeLink *link; int type = SOCK_FLOAT; /* XXX it would be a little bit more efficient to restrict actual updates * to rerout nodes connected to an updated node, but there's no reliable flag * to indicate updated nodes (node->update is not set on linking). */ node->done = 1; /* recursive update */ for (link = ntree->links.first; link; link = link->next) { bNode *fromnode = link->fromnode; bNode *tonode = link->tonode; if (!tonode || !fromnode) continue; if (nodeLinkIsHidden(link)) continue; if (tonode == node && fromnode->type == NODE_REROUTE && !fromnode->done) node_reroute_inherit_type_recursive(ntree, fromnode); if (fromnode == node && tonode->type == NODE_REROUTE && !tonode->done) node_reroute_inherit_type_recursive(ntree, tonode); } /* determine socket type from unambiguous input/output connection if possible */ if (input->limit == 1 && input->link) type = input->link->fromsock->type; else if (output->limit == 1 && output->link) type = output->link->tosock->type; /* arbitrary, could also test output->type, both are the same */ if (input->type != type) { PointerRNA input_ptr, output_ptr; /* same type for input/output */ RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, input, &input_ptr); RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, output, &output_ptr); RNA_enum_set(&input_ptr, "type", type); RNA_enum_set(&output_ptr, "type", type); } }
/* Global update function for Reroute node types. * This depends on connected nodes, so must be done as a tree-wide update. */ void ntree_update_reroute_nodes(bNodeTree *ntree) { bNode *node; /* clear tags */ for (node = ntree->nodes.first; node; node = node->next) node->done = 0; for (node = ntree->nodes.first; node; node = node->next) if (node->type == NODE_REROUTE && !node->done) node_reroute_inherit_type_recursive(ntree, node, REFINE_FORWARD | REFINE_BACKWARD); }
static void node_reroute_inherit_type_recursive(bNodeTree *ntree, bNode *node, int flag) { bNodeSocket *input = node->inputs.first; bNodeSocket *output = node->outputs.first; bNodeLink *link; int type = SOCK_FLOAT; const char *type_idname = nodeStaticSocketType(type, PROP_NONE); /* XXX it would be a little bit more efficient to restrict actual updates * to rerout nodes connected to an updated node, but there's no reliable flag * to indicate updated nodes (node->update is not set on linking). */ node->done = 1; /* recursive update */ for (link = ntree->links.first; link; link = link->next) { bNode *fromnode = link->fromnode; bNode *tonode = link->tonode; if (!tonode || !fromnode) continue; if (nodeLinkIsHidden(link)) continue; if (flag & REFINE_FORWARD) { if (tonode == node && fromnode->type == NODE_REROUTE && !fromnode->done) node_reroute_inherit_type_recursive(ntree, fromnode, REFINE_FORWARD); } if (flag & REFINE_BACKWARD) { if (fromnode == node && tonode->type == NODE_REROUTE && !tonode->done) node_reroute_inherit_type_recursive(ntree, tonode, REFINE_BACKWARD); } } /* determine socket type from unambiguous input/output connection if possible */ if (input->limit == 1 && input->link) { type = input->link->fromsock->type; type_idname = nodeStaticSocketType(type, PROP_NONE); } else if (output->limit == 1 && output->link) { type = output->link->tosock->type; type_idname = nodeStaticSocketType(type, PROP_NONE); } if (input->type != type) { bNodeSocket *ninput = nodeAddSocket(ntree, node, SOCK_IN, type_idname, "input", "Input"); for (link = ntree->links.first; link; link = link->next) { if (link->tosock == input) { link->tosock = ninput; ninput->link = link; } } nodeRemoveSocket(ntree, node, input); } if (output->type != type) { bNodeSocket *noutput = nodeAddSocket(ntree, node, SOCK_OUT, type_idname, "output", "Output"); for (link = ntree->links.first; link; link = link->next) { if (link->fromsock == output) { link->fromsock = noutput; } } nodeRemoveSocket(ntree, node, output); } nodeUpdateInternalLinks(ntree, node); }