static int node_select_linked_from_exec(bContext *C, wmOperator *UNUSED(op)) { SpaceNode *snode = CTX_wm_space_node(C); bNodeLink *link; bNode *node; for (node = snode->edittree->nodes.first; node; node = node->next) node->flag &= ~NODE_TEST; for (link = snode->edittree->links.first; link; link = link->next) { if (nodeLinkIsHidden(link)) continue; if (link->fromnode && link->tonode && (link->tonode->flag & NODE_SELECT)) link->fromnode->flag |= NODE_TEST; } for (node = snode->edittree->nodes.first; node; node = node->next) { if (node->flag & NODE_TEST) nodeSetSelected(node, true); } ED_node_sort(snode->edittree); WM_event_add_notifier(C, NC_NODE | NA_SELECTED, NULL); return OPERATOR_FINISHED; }
static void node_group_output_update(bNodeTree *ntree, bNode *node) { bNodeSocket *extsock = node->inputs.last; bNodeLink *link, *linknext, *exposelink; /* Adding a tree socket and verifying will remove the extension socket! * This list caches the existing links to the extension socket * so they can be recreated after verification. */ ListBase tmplinks; /* find links to the extension socket and store them */ BLI_listbase_clear(&tmplinks); for (link = ntree->links.first; link; link = linknext) { linknext = link->next; if (nodeLinkIsHidden(link)) continue; if (link->tosock == extsock) { bNodeLink *tlink = MEM_callocN(sizeof(bNodeLink), "temporary link"); *tlink = *link; BLI_addtail(&tmplinks, tlink); nodeRemLink(ntree, link); } } /* find valid link to expose */ exposelink = NULL; for (link = tmplinks.first; link; link = link->next) { /* XXX Multiple sockets can be connected to the extension socket at once, * in that case the arbitrary first link determines name and type. * This could be improved by choosing the "best" type among all links, * whatever that means. */ if (link->fromsock->type != SOCK_CUSTOM) { exposelink = link; break; } } if (exposelink) { bNodeSocket *gsock, *newsock; /* XXX what if connecting virtual to virtual socket?? */ gsock = ntreeAddSocketInterfaceFromSocket(ntree, exposelink->fromnode, exposelink->fromsock); node_group_output_verify(ntree, node, (ID *)ntree); newsock = node_group_output_find_socket(node, gsock->identifier); /* redirect links to the extension socket */ for (link = tmplinks.first; link; link = link->next) { nodeAddLink(ntree, link->fromnode, link->fromsock, node, newsock); } } BLI_freelistN(&tmplinks); }
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); } }
void node_update_internal_links_default(bNodeTree *ntree, bNode *node) { bNodeLink *link; bNodeSocket *output, *input; /* sanity check */ if (!ntree) return; /* use link pointer as a tag for handled sockets (for outputs is unused anyway) */ for (output = node->outputs.first; output; output = output->next) output->link = NULL; for (link = ntree->links.first; link; link = link->next) { if (nodeLinkIsHidden(link)) continue; output = link->fromsock; if (link->fromnode != node || output->link) continue; if (nodeSocketIsHidden(output) || output->flag & SOCK_NO_INTERNAL_LINK) continue; output->link = link; /* not really used, just for tagging handled sockets */ /* look for suitable input */ input = select_internal_link_input(node, output); if (input) { bNodeLink *ilink = MEM_callocN(sizeof(bNodeLink), "internal node link"); ilink->fromnode = node; ilink->fromsock = input; ilink->tonode = node; ilink->tosock = output; /* internal link is always valid */ ilink->flag |= NODE_LINK_VALID; BLI_addtail(&node->internal_links, ilink); } } /* clean up */ for (output = node->outputs.first; output; output = output->next) output->link = NULL; }
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); }