diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c index cebbab45928..7fd0a2d661a 100644 --- a/source/blender/blenkernel/intern/node.c +++ b/source/blender/blenkernel/intern/node.c @@ -878,14 +878,23 @@ void nodeAddAllGroupSockets(bNodeTree *ngroup) bNode *node; bNodeSocket *sock, *gsock; + printf("Verifying group '%s':\n", ngroup->id.name+2); for (node=ngroup->nodes.first; node; node=node->next) { + printf("\tNode '%s':\n", node->name); for (sock=node->inputs.first; sock; sock=sock->next) { + printf("\t\tInput '%s': link=%p, hidden=%d\n", sock->name, sock->link, (sock->flag & SOCK_HIDDEN)); +// if (sock->link) { +// if (sock->link->fromnode) +// printf("fromnode=%s ", sock->link->fromnode->name); +// printf("fromsock=%s") +// } if (!sock->link && !(sock->flag & SOCK_HIDDEN)) { gsock = nodeAddGroupSocketCopy(ngroup, sock, SOCK_IN); sock->link = nodeAddLink(ngroup, NULL, gsock, node, sock); } } for (sock=node->outputs.first; sock; sock=sock->next) { + printf("\t\tOutput '%s': #links=%d, hidden=%d\n", sock->name, nodeCountSocketLinks(ngroup, sock), (sock->flag & SOCK_HIDDEN)); if (nodeCountSocketLinks(ngroup, sock)==0 && !(sock->flag & SOCK_HIDDEN)) { gsock = nodeAddGroupSocketCopy(ngroup, sock, SOCK_OUT); gsock->link = nodeAddLink(ngroup, node, sock, NULL, gsock); diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index 3f722cc8cf3..8e9273fafc5 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -2028,6 +2028,55 @@ static void lib_link_nodetree(FileData *fd, Main *main) } } +/* updates group node socket own_index so that + * external links to/from the group node are preserved. + */ +static void lib_node_do_versions_group(bNode *gnode) +{ + bNodeTree *ngroup= (bNodeTree*)gnode->id; + bNode *intnode; + bNodeSocket *sock, *gsock, *intsock; + int found; + + for (sock=gnode->outputs.first; sock; sock=sock->next) { + int old_index = sock->to_index; + for (gsock=ngroup->outputs.first; gsock; gsock=gsock->next) { + if (gsock->link && gsock->link->fromsock->own_index == old_index) { + sock->own_index = gsock->own_index; + break; + } + } + } + for (sock=gnode->inputs.first; sock; sock=sock->next) { + int old_index = sock->to_index; + /* can't use break in double loop */ + found = 0; + for (intnode=ngroup->nodes.first; intnode && !found; intnode=intnode->next) { + for (intsock=intnode->inputs.first; intsock; intsock=intsock->next) { + if (intsock->own_index == old_index && intsock->link) { + sock->own_index = intsock->link->fromsock->own_index; + found = 1; + break; + } + } + } + } +} + +/* updates external links for all group nodes in a tree */ +static void lib_nodetree_do_versions_group(bNodeTree *ntree) +{ + bNode *node; + + for (node=ntree->nodes.first; node; node=node->next) { + if (node->type==NODE_GROUP) { + bNodeTree *ngroup= (bNodeTree*)node->id; + if (ngroup->flag & NTREE_DO_VERSIONS) + lib_node_do_versions_group(node); + } + } +} + /* verify types for nodes and groups, all data has to be read */ /* open = 0: appending/linking, open = 1: open new file (need to clean out dynamic * typedefs*/ @@ -2049,6 +2098,37 @@ static void lib_verify_nodetree(Main *main, int UNUSED(open)) ntreeVerifyTypes(ntree); /* internal nodes, no groups! */ } + { + int has_old_groups=0; + /* XXX this should actually be part of do_versions, but since we need + * finished library linking, it is not possible there. Instead in do_versions + * we have set the NTREE_DO_VERSIONS flag, so at this point we can do the + * actual group node updates. + */ + for(ntree= main->nodetree.first; ntree; ntree= ntree->id.next) { + if (ntree->flag & NTREE_DO_VERSIONS) { + /* this adds copies and links from all unlinked internal sockets to group inputs/outputs. */ + nodeAddAllGroupSockets(ntree); + has_old_groups = 1; + } + } + /* now verify all types in material trees, groups are set OK now */ + for(ma= main->mat.first; ma; ma= ma->id.next) { + if(ma->nodetree) + lib_nodetree_do_versions_group(ma->nodetree); + } + /* and scene trees */ + for(sce= main->scene.first; sce; sce= sce->id.next) { + if(sce->nodetree) + lib_nodetree_do_versions_group(ma->nodetree); + } + /* and texture trees */ + for(tx= main->tex.first; tx; tx= tx->id.next) { + if(tx->nodetree) + lib_nodetree_do_versions_group(ma->nodetree); + } + } + /* now verify all types in material trees, groups are set OK now */ for(ma= main->mat.first; ma; ma= ma->id.next) { if(ma->nodetree) @@ -11375,7 +11455,11 @@ static void do_versions(FileData *fd, Library *lib, Main *main) * this mimics the old behaviour by adding all unlinked sockets to groups. */ for (ntree=main->nodetree.first; ntree; ntree=ntree->id.next) { - nodeAddAllGroupSockets(ntree); + /* XXX Only setting a flag here. Actual adding of group sockets + * is done in lib_verify_nodetree, because at this point the internal + * nodes may not be up-to-date! (missing lib-link) + */ + ntree->flag |= NTREE_DO_VERSIONS; } } diff --git a/source/blender/makesdna/DNA_node_types.h b/source/blender/makesdna/DNA_node_types.h index 0a4c672273b..803e5418bcc 100644 --- a/source/blender/makesdna/DNA_node_types.h +++ b/source/blender/makesdna/DNA_node_types.h @@ -81,7 +81,7 @@ typedef struct bNodeSocket { */ struct bNodeStack *stack_ptr; /* constant input value */ short stack_index; /* local stack index or external input number */ - short pad; + short pad1; float locx, locy; @@ -89,6 +89,8 @@ typedef struct bNodeSocket { int own_index; /* group socket identifiers, to find matching pairs after reading files */ struct bNodeSocket *groupsock; + int to_index; /* XXX deprecated, only used for restoring old group node links */ + int pad2; struct bNodeLink *link; /* a link pointer, set in nodeSolveOrder() */ } bNodeSocket; @@ -218,8 +220,11 @@ typedef struct bNodeTree { #define NTREE_EXEC_INIT 2 /* ntree->flag */ -#define NTREE_DS_EXPAND 1 /* for animation editors */ -#define NTREE_AUTO_EXPOSE 2 /* automatically make unhidden, unlinked group sockets external */ +#define NTREE_DS_EXPAND 1 /* for animation editors */ +/* XXX not nice, but needed as a temporary flag + * for group updates after library linking. + */ +#define NTREE_DO_VERSIONS 1024 /* data structs, for node->storage */