static void update_output_file(bNodeTree *ntree, bNode *node) { bNodeSocket *sock, *sock_next; PointerRNA ptr; /* XXX fix for #36706: remove invalid sockets added with bpy API. * This is not ideal, but prevents crashes from missing storage. * FileOutput node needs a redesign to support this properly. */ for (sock = node->inputs.first; sock; sock = sock_next) { sock_next = sock->next; if (sock->storage == NULL) { nodeRemoveSocket(ntree, node, sock); } } for (sock = node->outputs.first; sock; sock = sock_next) { sock_next = sock->next; nodeRemoveSocket(ntree, node, sock); } cmp_node_update_default(ntree, node); /* automatically update the socket type based on linked input */ for (sock = node->inputs.first; sock; sock = sock->next) { if (sock->link) { RNA_pointer_create((ID *)ntree, &RNA_NodeSocket, sock, &ptr); RNA_enum_set(&ptr, "type", sock->link->fromsock->type); } } }
static void verify_socket_template_list(bNodeTree *ntree, bNode *node, int in_out, ListBase *socklist, bNodeSocketTemplate *stemp_first) { bNodeSocket *sock; bNodeSocketTemplate *stemp; /* no inputs anymore? */ if(stemp_first==NULL) { while(socklist->first) { sock = (bNodeSocket*)socklist->first; if (!(sock->flag & SOCK_DYNAMIC)) nodeRemoveSocket(ntree, node, socklist->first); } } else { /* step by step compare */ stemp= stemp_first; while(stemp->type != -1) { stemp->sock= verify_socket_template(ntree, node, in_out, socklist, stemp); stemp++; } /* leftovers are removed */ while(socklist->first) { sock = (bNodeSocket*)socklist->first; if (!(sock->flag & SOCK_DYNAMIC)) nodeRemoveSocket(ntree, node, socklist->first); } /* and we put back the verified sockets */ stemp= stemp_first; if (socklist->first) { /* some dynamic sockets left, store the list start * so we can add static sockets infront of it. */ sock = socklist->first; while(stemp->type != -1) { /* put static sockets infront of dynamic */ BLI_insertlinkbefore(socklist, sock, stemp->sock); stemp++; } } else { while(stemp->type != -1) { BLI_addtail(socklist, stemp->sock); stemp++; } } } }
/* used for both group nodes and interface nodes */ static void group_verify_socket_list(bNodeTree *ntree, bNode *gnode, ListBase *iosock_lb, ListBase *verify_lb, int in_out) { bNodeSocket *iosock, *sock, *nextsock; /* step by step compare */ iosock = iosock_lb->first; for (; iosock; iosock = iosock->next) { /* abusing new_sock pointer for verification here! only used inside this function */ iosock->new_sock = group_verify_socket(ntree, gnode, iosock, verify_lb, in_out); } /* leftovers are removed */ for (sock = verify_lb->first; sock; sock = nextsock) { nextsock = sock->next; nodeRemoveSocket(ntree, gnode, sock); } /* and we put back the verified sockets */ iosock = iosock_lb->first; for (; iosock; iosock = iosock->next) { if (iosock->new_sock) { BLI_addtail(verify_lb, iosock->new_sock); iosock->new_sock = NULL; } } }
/* XXX make this into a generic socket verification function for dynamic socket replacement (multilayer, groups, static templates) */ static void cmp_node_image_verify_outputs(bNodeTree *ntree, bNode *node) { bNodeSocket *newsock, *oldsock, *oldsock_next; ListBase oldsocklist; int oldindex; bNodeLink *link; /* store current nodes in oldsocklist, then clear socket list */ oldsocklist = node->outputs; BLI_listbase_clear(&node->outputs); /* XXX make callback */ cmp_node_image_create_outputs(ntree, node); for (newsock = node->outputs.first; newsock; newsock = newsock->next) { /* XXX make callback */ oldsock = cmp_node_image_output_find_match(node, newsock, &oldsocklist); if (oldsock) { /* XXX make callback */ cmp_node_image_sync_output(node, newsock, oldsock); } } /* move links to new socket */ for (oldsock = oldsocklist.first, oldindex = 0; oldsock; oldsock = oldsock->next, ++oldindex) { newsock = cmp_node_image_output_relink(node, oldsock, oldindex); if (newsock) { for (link = ntree->links.first; link; link = link->next) { if (link->fromsock == oldsock) link->fromsock = newsock; } } } /* delete old sockets * XXX oldsock is not actually in the node->outputs list any more, * but the nodeRemoveSocket function works anyway. In future this * should become part of the core code, so can take care of this behavior. */ for (oldsock = oldsocklist.first; oldsock; oldsock = oldsock_next) { oldsock_next = oldsock->next; MEM_freeN(oldsock->storage); nodeRemoveSocket(ntree, node, oldsock); } }
int ntreeCompositOutputFileRemoveActiveSocket(bNodeTree *ntree, bNode *node) { NodeImageMultiFile *nimf = node->storage; bNodeSocket *sock = BLI_findlink(&node->inputs, nimf->active_input); int totinputs = BLI_countlist(&node->inputs); if (!sock) return 0; if (nimf->active_input == totinputs-1) --nimf->active_input; /* free format data */ MEM_freeN(sock->storage); nodeRemoveSocket(ntree, node, sock); return 1; }
static void group_verify_socket_list(bNodeTree *ntree, bNode *node, ListBase *lb, int in_out, ListBase *glb) { bNodeSocket *sock, *nextsock, *gsock; /* step by step compare */ for (gsock= glb->first; gsock; gsock=gsock->next) { /* abusing new_sock pointer for verification here! only used inside this function */ gsock->new_sock= group_verify_socket(ntree, lb, in_out, gsock); } /* leftovers are removed */ for (sock=lb->first; sock; sock=nextsock) { nextsock=sock->next; if (sock->flag & SOCK_DYNAMIC) nodeRemoveSocket(ntree, node, sock); } /* and we put back the verified sockets */ for (gsock= glb->first; gsock; gsock=gsock->next) { if (gsock->new_sock) { BLI_addtail(lb, gsock->new_sock); gsock->new_sock = 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); }