forked from bartvdbraak/blender
Fixed do_versions for node groups which contain nodes that have changed sockets. do_versions is running before the lib_verify_nodetree function updates socket lists of nodes. This means that when adding unlinked sockets in do_versions to restore older node groups, the new sockets are not taken into account. To fix this a temporary node tree flag has been introduced, which delays actual group socket do_version until the group tree internal nodes have been updated. After that the unlinked group sockets are exposed (like old node groups did), then the external sockets look up the new index, so that external links to group instances are preserved.
This commit is contained in:
parent
33887fa41d
commit
4fb730d6d0
@ -878,14 +878,23 @@ void nodeAddAllGroupSockets(bNodeTree *ngroup)
|
|||||||
bNode *node;
|
bNode *node;
|
||||||
bNodeSocket *sock, *gsock;
|
bNodeSocket *sock, *gsock;
|
||||||
|
|
||||||
|
printf("Verifying group '%s':\n", ngroup->id.name+2);
|
||||||
for (node=ngroup->nodes.first; node; node=node->next) {
|
for (node=ngroup->nodes.first; node; node=node->next) {
|
||||||
|
printf("\tNode '%s':\n", node->name);
|
||||||
for (sock=node->inputs.first; sock; sock=sock->next) {
|
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)) {
|
if (!sock->link && !(sock->flag & SOCK_HIDDEN)) {
|
||||||
gsock = nodeAddGroupSocketCopy(ngroup, sock, SOCK_IN);
|
gsock = nodeAddGroupSocketCopy(ngroup, sock, SOCK_IN);
|
||||||
sock->link = nodeAddLink(ngroup, NULL, gsock, node, sock);
|
sock->link = nodeAddLink(ngroup, NULL, gsock, node, sock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (sock=node->outputs.first; sock; sock=sock->next) {
|
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)) {
|
if (nodeCountSocketLinks(ngroup, sock)==0 && !(sock->flag & SOCK_HIDDEN)) {
|
||||||
gsock = nodeAddGroupSocketCopy(ngroup, sock, SOCK_OUT);
|
gsock = nodeAddGroupSocketCopy(ngroup, sock, SOCK_OUT);
|
||||||
gsock->link = nodeAddLink(ngroup, node, sock, NULL, gsock);
|
gsock->link = nodeAddLink(ngroup, node, sock, NULL, gsock);
|
||||||
|
@ -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 */
|
/* 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
|
/* open = 0: appending/linking, open = 1: open new file (need to clean out dynamic
|
||||||
* typedefs*/
|
* typedefs*/
|
||||||
@ -2049,6 +2098,37 @@ static void lib_verify_nodetree(Main *main, int UNUSED(open))
|
|||||||
ntreeVerifyTypes(ntree); /* internal nodes, no groups! */
|
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 */
|
/* now verify all types in material trees, groups are set OK now */
|
||||||
for(ma= main->mat.first; ma; ma= ma->id.next) {
|
for(ma= main->mat.first; ma; ma= ma->id.next) {
|
||||||
if(ma->nodetree)
|
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.
|
* this mimics the old behaviour by adding all unlinked sockets to groups.
|
||||||
*/
|
*/
|
||||||
for (ntree=main->nodetree.first; ntree; ntree=ntree->id.next) {
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,7 +81,7 @@ typedef struct bNodeSocket {
|
|||||||
*/
|
*/
|
||||||
struct bNodeStack *stack_ptr; /* constant input value */
|
struct bNodeStack *stack_ptr; /* constant input value */
|
||||||
short stack_index; /* local stack index or external input number */
|
short stack_index; /* local stack index or external input number */
|
||||||
short pad;
|
short pad1;
|
||||||
|
|
||||||
float locx, locy;
|
float locx, locy;
|
||||||
|
|
||||||
@ -89,6 +89,8 @@ typedef struct bNodeSocket {
|
|||||||
|
|
||||||
int own_index; /* group socket identifiers, to find matching pairs after reading files */
|
int own_index; /* group socket identifiers, to find matching pairs after reading files */
|
||||||
struct bNodeSocket *groupsock;
|
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() */
|
struct bNodeLink *link; /* a link pointer, set in nodeSolveOrder() */
|
||||||
} bNodeSocket;
|
} bNodeSocket;
|
||||||
@ -219,7 +221,10 @@ typedef struct bNodeTree {
|
|||||||
|
|
||||||
/* ntree->flag */
|
/* ntree->flag */
|
||||||
#define NTREE_DS_EXPAND 1 /* for animation editors */
|
#define NTREE_DS_EXPAND 1 /* for animation editors */
|
||||||
#define NTREE_AUTO_EXPOSE 2 /* automatically make unhidden, unlinked group sockets external */
|
/* 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 */
|
/* data structs, for node->storage */
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user