void node_group_init(bNodeTree *ntree, bNode *node, bNodeTemplate *ntemp) { node->id = (ID*)ntemp->ngroup; /* NB: group socket input/output roles are inverted internally! * Group "inputs" work as outputs in links and vice versa. */ if (ntemp->ngroup) { bNodeSocket *gsock; for (gsock=ntemp->ngroup->inputs.first; gsock; gsock=gsock->next) node_group_add_extern_socket(ntree, &node->inputs, SOCK_IN, gsock); for (gsock=ntemp->ngroup->outputs.first; gsock; gsock=gsock->next) node_group_add_extern_socket(ntree, &node->outputs, SOCK_OUT, gsock); } }
static bNodeSocket *group_verify_socket(bNodeTree *ntree, ListBase *lb, int in_out, bNodeSocket *gsock) { bNodeSocket *sock; /* group sockets tagged as internal are not exposed ever */ if (gsock->flag & SOCK_INTERNAL) return NULL; for (sock= lb->first; sock; sock= sock->next) { if (sock->own_index==gsock->own_index) break; } if (sock) { sock->groupsock = gsock; BLI_strncpy(sock->name, gsock->name, sizeof(sock->name)); if (gsock->type != sock->type) nodeSocketSetType(sock, gsock->type); /* XXX hack: group socket input/output roles are inverted internally, * need to change the limit value when making actual node sockets from them. */ sock->limit = (in_out==SOCK_IN ? 1 : 0xFFF); BLI_remlink(lb, sock); return sock; } else { return node_group_add_extern_socket(ntree, NULL, in_out, gsock); } }
void node_forloop_init(bNodeTree *ntree, bNode *node, bNodeTemplate *ntemp) { /* bNodeSocket *sock; */ /* UNUSED */ node->id = (ID*)ntemp->ngroup; /* sock = */ nodeAddInputFloat(ntree, node, "Iterations", PROP_UNSIGNED, 1, 0, 10000); /* NB: group socket input/output roles are inverted internally! * Group "inputs" work as outputs in links and vice versa. */ if (ntemp->ngroup) { bNodeSocket *gsock; for (gsock=ntemp->ngroup->inputs.first; gsock; gsock=gsock->next) node_group_add_extern_socket(ntree, &node->inputs, SOCK_IN, gsock); for (gsock=ntemp->ngroup->outputs.first; gsock; gsock=gsock->next) node_group_add_extern_socket(ntree, &node->outputs, SOCK_OUT, gsock); } }
void node_forloop_init(bNodeTree *ntree, bNode *node, bNodeTemplate *ntemp) { bNodeSocket *sock; node->id = (ID*)ntemp->ngroup; sock = nodeAddSocket(ntree, node, SOCK_IN, "Iterations", SOCK_FLOAT); node_socket_set_default_value_float(sock->default_value, PROP_UNSIGNED, 1, 0, 10000); /* NB: group socket input/output roles are inverted internally! * Group "inputs" work as outputs in links and vice versa. */ if (ntemp->ngroup) { bNodeSocket *gsock; for (gsock=ntemp->ngroup->inputs.first; gsock; gsock=gsock->next) node_group_add_extern_socket(ntree, &node->inputs, SOCK_IN, gsock); for (gsock=ntemp->ngroup->outputs.first; gsock; gsock=gsock->next) node_group_add_extern_socket(ntree, &node->outputs, SOCK_OUT, gsock); } }
bNode *node_group_make_from_selected(bNodeTree *ntree) { bNodeLink *link, *linkn; bNode *node, *gnode, *nextn; bNodeTree *ngroup; bNodeSocket *gsock; ListBase anim_basepaths = {NULL, NULL}; float min[2], max[2]; int totnode=0; bNodeTemplate ntemp; INIT_MINMAX2(min, max); /* is there something to group? also do some clearing */ for(node= ntree->nodes.first; node; node= node->next) { if(node->flag & NODE_SELECT) { /* no groups in groups */ if(node->type==NODE_GROUP) return NULL; DO_MINMAX2( (&node->locx), min, max); totnode++; } node->done= 0; } if(totnode==0) return NULL; /* check if all connections are OK, no unselected node has both inputs and outputs to a selection */ for(link= ntree->links.first; link; link= link->next) { if(link->fromnode && link->tonode && link->fromnode->flag & NODE_SELECT) link->tonode->done |= 1; if(link->fromnode && link->tonode && link->tonode->flag & NODE_SELECT) link->fromnode->done |= 2; } for(node= ntree->nodes.first; node; node= node->next) { if((node->flag & NODE_SELECT)==0) if(node->done==3) break; } if(node) return NULL; /* OK! new nodetree */ ngroup= ntreeAddTree("NodeGroup", ntree->type, NODE_GROUP); /* move nodes over */ for(node= ntree->nodes.first; node; node= nextn) { nextn= node->next; if(node->flag & NODE_SELECT) { /* keep track of this node's RNA "base" path (the part of the pat identifying the node) * if the old nodetree has animation data which potentially covers this node */ if (ntree->adt) { PointerRNA ptr; char *path; RNA_pointer_create(&ntree->id, &RNA_Node, node, &ptr); path = RNA_path_from_ID_to_struct(&ptr); if (path) BLI_addtail(&anim_basepaths, BLI_genericNodeN(path)); } /* change node-collection membership */ BLI_remlink(&ntree->nodes, node); BLI_addtail(&ngroup->nodes, node); node->locx-= 0.5f*(min[0]+max[0]); node->locy-= 0.5f*(min[1]+max[1]); } } /* move animation data over */ if (ntree->adt) { LinkData *ld, *ldn=NULL; BKE_animdata_separate_by_basepath(&ntree->id, &ngroup->id, &anim_basepaths); /* paths + their wrappers need to be freed */ for (ld = anim_basepaths.first; ld; ld = ldn) { ldn = ld->next; MEM_freeN(ld->data); BLI_freelinkN(&anim_basepaths, ld); } } /* make group node */ ntemp.type = NODE_GROUP; ntemp.ngroup = ngroup; gnode= nodeAddNode(ntree, &ntemp); gnode->locx= 0.5f*(min[0]+max[0]); gnode->locy= 0.5f*(min[1]+max[1]); /* relink external sockets */ for(link= ntree->links.first; link; link= linkn) { linkn= link->next; if(link->fromnode && link->tonode && (link->fromnode->flag & link->tonode->flag & NODE_SELECT)) { BLI_remlink(&ntree->links, link); BLI_addtail(&ngroup->links, link); } else if(link->tonode && (link->tonode->flag & NODE_SELECT)) { gsock = node_group_expose_socket(ngroup, link->tosock, SOCK_IN); link->tosock->link = nodeAddLink(ngroup, NULL, gsock, link->tonode, link->tosock); link->tosock = node_group_add_extern_socket(ntree, &gnode->inputs, SOCK_IN, gsock); link->tonode = gnode; } else if(link->fromnode && (link->fromnode->flag & NODE_SELECT)) { /* search for existing group node socket */ for (gsock=ngroup->outputs.first; gsock; gsock=gsock->next) if (gsock->link && gsock->link->fromsock==link->fromsock) break; if (!gsock) { gsock = node_group_expose_socket(ngroup, link->fromsock, SOCK_OUT); gsock->link = nodeAddLink(ngroup, link->fromnode, link->fromsock, NULL, gsock); link->fromsock = node_group_add_extern_socket(ntree, &gnode->outputs, SOCK_OUT, gsock); } else link->fromsock = node_group_find_output(gnode, gsock); link->fromnode = gnode; } } ngroup->update |= NTREE_UPDATE; ntreeUpdateTree(ngroup); ntree->update |= NTREE_UPDATE_NODES|NTREE_UPDATE_LINKS; ntreeUpdateTree(ntree); return gnode; }