Improved auto-hiding of unused sockets for collapsed nodes.
authorLukas Toenne <lukas.toenne@googlemail.com>
Sun, 8 Jan 2012 10:23:19 +0000 (10:23 +0000)
committerLukas Toenne <lukas.toenne@googlemail.com>
Sun, 8 Jan 2012 10:23:19 +0000 (10:23 +0000)
Instead of generally hiding all unused sockets in collapsed mode, the sockets now have a new explicit flag SOCK_AUTO_HIDDEN, which is only toggled when the hide_toggle operator is called. This way the auto-hidden sockets stay as they are when nodes are duplicated etc. The new flag is necessary to distinguish between manually hidden sockets (via hide_sockets_toggle operator) and automatically hidden sockets and restore the node state when unhiding a node.

source/blender/blenkernel/BKE_blender.h
source/blender/blenkernel/BKE_node.h
source/blender/blenkernel/intern/node.c
source/blender/blenloader/intern/readfile.c
source/blender/editors/space_node/node_draw.c
source/blender/editors/space_node/node_edit.c
source/blender/editors/space_node/node_intern.h
source/blender/makesdna/DNA_node_types.h
source/blender/nodes/intern/node_common.c
source/blender/nodes/shader/node_shader_util.c

index cb4fba4..49cde9d 100644 (file)
@@ -42,7 +42,7 @@ extern "C" {
  * and keep comment above the defines.
  * Use STRINGIFY() rather than defining with quotes */
 #define BLENDER_VERSION                        261
-#define BLENDER_SUBVERSION             0
+#define BLENDER_SUBVERSION             1
 
 #define BLENDER_MINVERSION             250
 #define BLENDER_MINSUBVERSION  0
index 6234308..9fdae5b 100644 (file)
@@ -374,6 +374,8 @@ int                         nodeUpdateID(struct bNodeTree *ntree, struct ID *id);
 
 void                   nodeFreePreview(struct bNode *node);
 
+int                            nodeSocketIsHidden(struct bNodeSocket *sock);
+
 /* ************** NODE TYPE ACCESS *************** */
 
 struct bNodeTemplate nodeMakeTemplate(struct bNode *node);
index ce1dd42..5253d7a 100644 (file)
@@ -1325,6 +1325,11 @@ void nodeSetActive(bNodeTree *ntree, bNode *node)
                node->flag |= NODE_ACTIVE_TEXTURE;
 }
 
+int nodeSocketIsHidden(bNodeSocket *sock)
+{
+       return ((sock->flag & (SOCK_HIDDEN | SOCK_AUTO_HIDDEN | SOCK_UNAVAIL)) != 0);
+}
+
 /* ************** dependency stuff *********** */
 
 /* node is guaranteed to be not checked before */
index 27a0ddd..bb5682f 100644 (file)
@@ -7547,6 +7547,32 @@ static void do_versions_nodetree_socket_use_flags_2_62(bNodeTree *ntree)
        }
 }
 
+/* set the SOCK_AUTO_HIDDEN flag on collapsed nodes */
+static void do_versions_nodetree_socket_auto_hidden_flags_2_62(bNodeTree *ntree)
+{
+       bNode *node;
+       bNodeSocket *sock;
+       
+       for (node=ntree->nodes.first; node; node=node->next) {
+               if (node->flag & NODE_HIDDEN) {
+                       for (sock=node->inputs.first; sock; sock=sock->next) {
+                               if (sock->link==NULL)
+                                       sock->flag |= SOCK_AUTO_HIDDEN;
+                       }
+                       for(sock=node->outputs.first; sock; sock= sock->next) {
+                               if(nodeCountSocketLinks(ntree, sock)==0)
+                                       sock->flag |= SOCK_AUTO_HIDDEN;
+                       }
+               }
+               else {
+                       for(sock=node->inputs.first; sock; sock= sock->next)
+                               sock->flag &= ~SOCK_AUTO_HIDDEN;
+                       for(sock=node->outputs.first; sock; sock= sock->next)
+                               sock->flag &= ~SOCK_AUTO_HIDDEN;
+               }
+       }
+}
+
 static void do_versions(FileData *fd, Library *lib, Main *main)
 {
        /* WATCH IT!!!: pointers from libdata have not been converted */
@@ -12779,7 +12805,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                }
        }
 
-       /* put compatibility code here until next subversion bump */
+       if (main->versionfile < 261 || (main->versionfile == 261 && main->subversionfile < 1))
        {
                {
                        /* update use flags for node sockets (was only temporary before) */
@@ -12879,6 +12905,43 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
                                }
                        }
                }
+               {
+                       /* set the SOCK_AUTO_HIDDEN flag on collapsed nodes */
+                       Scene *sce;
+                       Material *mat;
+                       Tex *tex;
+                       Lamp *lamp;
+                       World *world;
+                       bNodeTree *ntree;
+
+                       for (sce=main->scene.first; sce; sce=sce->id.next)
+                               if (sce->nodetree)
+                                       do_versions_nodetree_socket_auto_hidden_flags_2_62(sce->nodetree);
+
+                       for (mat=main->mat.first; mat; mat=mat->id.next)
+                               if (mat->nodetree)
+                                       do_versions_nodetree_socket_auto_hidden_flags_2_62(mat->nodetree);
+
+                       for (tex=main->tex.first; tex; tex=tex->id.next)
+                               if (tex->nodetree)
+                                       do_versions_nodetree_socket_auto_hidden_flags_2_62(tex->nodetree);
+
+                       for (lamp=main->lamp.first; lamp; lamp=lamp->id.next)
+                               if (lamp->nodetree)
+                                       do_versions_nodetree_socket_auto_hidden_flags_2_62(lamp->nodetree);
+
+                       for (world=main->world.first; world; world=world->id.next)
+                               if (world->nodetree)
+                                       do_versions_nodetree_socket_auto_hidden_flags_2_62(world->nodetree);
+
+                       for (ntree=main->nodetree.first; ntree; ntree=ntree->id.next)
+                               do_versions_nodetree_socket_auto_hidden_flags_2_62(ntree);
+               }
+       }
+
+       /* put compatibility code here until next subversion bump */
+       {
+               
        }
 
        /* WATCH IT!!!: pointers from libdata have not been converted yet here! */
index 7b692f5..da7f22b 100644 (file)
@@ -233,7 +233,7 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node)
 
        /* output sockets */
        for(nsock= node->outputs.first; nsock; nsock= nsock->next) {
-               if(!(nsock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) {
+               if(!nodeSocketIsHidden(nsock)) {
                        nsock->locx= locx + node->width;
                        nsock->locy= dy - NODE_DYS;
                        dy-= NODE_DY;
@@ -312,7 +312,7 @@ static void node_update_basis(const bContext *C, bNodeTree *ntree, bNode *node)
 
        /* input sockets */
        for(nsock= node->inputs.first; nsock; nsock= nsock->next) {
-               if(!(nsock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) {
+               if(!nodeSocketIsHidden(nsock)) {
                        nsock->locx= locx;
                        nsock->locy= dy - NODE_DYS;
                        dy-= NODE_DY;
@@ -351,10 +351,10 @@ static void node_update_hidden(bNode *node)
 
        /* calculate minimal radius */
        for(nsock= node->inputs.first; nsock; nsock= nsock->next)
-               if(!(nsock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL)) && (nsock->flag & SOCK_IN_USE))
+               if(!nodeSocketIsHidden(nsock))
                        totin++;
        for(nsock= node->outputs.first; nsock; nsock= nsock->next)
-               if(!(nsock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL)) && (nsock->flag & SOCK_IN_USE))
+               if(!nodeSocketIsHidden(nsock))
                        totout++;
        
        tot= MAX2(totin, totout);
@@ -371,7 +371,7 @@ static void node_update_hidden(bNode *node)
        rad=drad= (float)M_PI/(1.0f + (float)totout);
        
        for(nsock= node->outputs.first; nsock; nsock= nsock->next) {
-               if(!(nsock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL)) && (nsock->flag & SOCK_IN_USE)) {
+               if(!nodeSocketIsHidden(nsock)) {
                        nsock->locx= node->totr.xmax - hiddenrad + (float)sin(rad)*hiddenrad;
                        nsock->locy= node->totr.ymin + hiddenrad + (float)cos(rad)*hiddenrad;
                        rad+= drad;
@@ -382,7 +382,7 @@ static void node_update_hidden(bNode *node)
        rad=drad= - (float)M_PI/(1.0f + (float)totin);
        
        for(nsock= node->inputs.first; nsock; nsock= nsock->next) {
-               if(!(nsock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL)) && (nsock->flag & SOCK_IN_USE)) {
+               if(!nodeSocketIsHidden(nsock)) {
                        nsock->locx= node->totr.xmin + hiddenrad + (float)sin(rad)*hiddenrad;
                        nsock->locy= node->totr.ymin + hiddenrad + (float)cos(rad)*hiddenrad;
                        rad+= drad;
@@ -713,7 +713,7 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
        for(sock= node->inputs.first; sock; sock= sock->next) {
                bNodeSocketType *stype= ntreeGetSocketType(sock->type);
                
-               if(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))
+               if(nodeSocketIsHidden(sock))
                        continue;
                
                node_socket_circle_draw(ntree, sock, NODE_SOCKSIZE);
@@ -736,7 +736,7 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
                
                RNA_pointer_create((ID*)ntree, &RNA_NodeSocket, sock, &sockptr);
                
-               if(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))
+               if(nodeSocketIsHidden(sock))
                        continue;
                
                node_socket_circle_draw(ntree, sock, NODE_SOCKSIZE);
@@ -854,12 +854,12 @@ static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, b
        
        /* sockets */
        for(sock= node->inputs.first; sock; sock= sock->next) {
-               if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL)) && (sock->flag & SOCK_IN_USE))
+               if(!nodeSocketIsHidden(sock))
                        node_socket_circle_draw(snode->nodetree, sock, socket_size);
        }
        
        for(sock= node->outputs.first; sock; sock= sock->next) {
-               if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL)) && (sock->flag & SOCK_IN_USE))
+               if(!nodeSocketIsHidden(sock))
                        node_socket_circle_draw(snode->nodetree, sock, socket_size);
        }
        
index 87a5627..20fb385 100644 (file)
@@ -1600,40 +1600,38 @@ void NODE_OT_resize(wmOperatorType *ot)
 
 /* ********************** hidden sockets ******************** */
 
-int node_has_hidden_sockets(bNode *node)
+int node_has_hidden_sockets(bNode *node, short flag)
 {
        bNodeSocket *sock;
        
        for(sock= node->inputs.first; sock; sock= sock->next)
-               if(sock->flag & SOCK_HIDDEN)
+               if(sock->flag & flag)
                        return 1;
        for(sock= node->outputs.first; sock; sock= sock->next)
-               if(sock->flag & SOCK_HIDDEN)
+               if(sock->flag & flag)
                        return 1;
        return 0;
 }
 
-/* note: call node_tree_verify_groups(snode->nodetree) after this
- */
-void node_set_hidden_sockets(SpaceNode *snode, bNode *node, int set)
+void node_set_hidden_sockets(SpaceNode *snode, bNode *node, short flag, int set)
 {      
        bNodeSocket *sock;
 
        if(set==0) {
                for(sock= node->inputs.first; sock; sock= sock->next)
-                       sock->flag &= ~SOCK_HIDDEN;
+                       sock->flag &= ~flag;
                for(sock= node->outputs.first; sock; sock= sock->next)
-                       sock->flag &= ~SOCK_HIDDEN;
+                       sock->flag &= ~flag;
        }
        else {
                /* hide unused sockets */
                for(sock= node->inputs.first; sock; sock= sock->next) {
                        if(sock->link==NULL)
-                               sock->flag |= SOCK_HIDDEN;
+                               sock->flag |= flag;
                }
                for(sock= node->outputs.first; sock; sock= sock->next) {
                        if(nodeCountSocketLinks(snode->edittree, sock)==0)
-                               sock->flag |= SOCK_HIDDEN;
+                               sock->flag |= flag;
                }
        }
 }
@@ -1680,14 +1678,14 @@ static void node_link_viewer(SpaceNode *snode, bNode *tonode)
 
                        /* find a socket after the previously connected socket */
                        for(sock=sock->next; sock; sock= sock->next)
-                               if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL)))
+                               if(!nodeSocketIsHidden(sock))
                                        break;
                }
 
                /* find a socket starting from the first socket */
                if(!sock) {
                        for(sock= tonode->outputs.first; sock; sock= sock->next)
-                               if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL)))
+                               if(!nodeSocketIsHidden(sock))
                                        break;
                }
                
@@ -1805,7 +1803,7 @@ static int find_indicated_socket(SpaceNode *snode, bNode **nodep, bNodeSocket **
                
                if(in_out & SOCK_IN) {
                        for(sock= node->inputs.first; sock; sock= sock->next) {
-                               if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) {
+                               if(!nodeSocketIsHidden(sock)) {
                                        if(BLI_in_rctf(&rect, sock->locx, sock->locy)) {
                                                if(node == visible_node(snode, &rect)) {
                                                        *nodep= node;
@@ -1818,7 +1816,7 @@ static int find_indicated_socket(SpaceNode *snode, bNode **nodep, bNodeSocket **
                }
                if(in_out & SOCK_OUT) {
                        for(sock= node->outputs.first; sock; sock= sock->next) {
-                               if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) {
+                               if(!nodeSocketIsHidden(sock)) {
                                        if(BLI_in_rctf(&rect, sock->locx, sock->locy)) {
                                                if(node == visible_node(snode, &rect)) {
                                                        *nodep= node;
@@ -1836,7 +1834,7 @@ static int find_indicated_socket(SpaceNode *snode, bNode **nodep, bNodeSocket **
         */
        if(in_out & SOCK_IN) {
                for(sock= snode->edittree->outputs.first; sock; sock= sock->next) {
-                       if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) {
+                       if(!nodeSocketIsHidden(sock)) {
                                if(BLI_in_rctf(&rect, sock->locx, sock->locy)) {
                                        *nodep= NULL;   /* NULL node pointer indicates group socket */
                                        *sockp= sock;
@@ -1847,7 +1845,7 @@ static int find_indicated_socket(SpaceNode *snode, bNode **nodep, bNodeSocket **
        }
        if(in_out & SOCK_OUT) {
                for(sock= snode->edittree->inputs.first; sock; sock= sock->next) {
-                       if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) {
+                       if(!nodeSocketIsHidden(sock)) {
                                if(BLI_in_rctf(&rect, sock->locx, sock->locy)) {
                                        *nodep= NULL;   /* NULL node pointer indicates group socket */
                                        *sockp= sock;
@@ -1930,13 +1928,12 @@ static int sort_nodes_locx(void *a, void *b)
 
 static int socket_is_available(bNodeTree *ntree, bNodeSocket *sock, int allow_used)
 {
-       if (sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))
+       if (nodeSocketIsHidden(sock))
+               return 0;
+       
+       if (!allow_used && (sock->flag & SOCK_IN_USE))
                return 0;
        
-       if (!allow_used) {
-               if (nodeCountSocketLinks(ntree, sock) > 0)
-                       return 0;
-       }
        return 1;
 }
 
@@ -2246,7 +2243,7 @@ static void node_remove_extra_links(SpaceNode *snode, bNodeSocket *tsock, bNodeL
                                }
                                if(sock) {
                                        tlink->tosock= sock;
-                                       sock->flag &= ~SOCK_HIDDEN;
+                                       sock->flag &= ~(SOCK_HIDDEN|SOCK_AUTO_HIDDEN);
                                }
                                else {
                                        nodeRemLink(snode->edittree, tlink);
@@ -2644,26 +2641,26 @@ static bNodeSocket *socket_best_match(ListBase *sockets, int type)
        
        /* first, match type */
        for(sock= sockets->first; sock; sock= sock->next)
-               if(!(sock->flag & SOCK_HIDDEN))
+               if(!nodeSocketIsHidden(sock))
                        if(type == sock->type)
                                return sock;
        
        /* then just use first unhidden socket */
        for(sock= sockets->first; sock; sock= sock->next)
-               if(!(sock->flag & SOCK_HIDDEN))
+               if(!nodeSocketIsHidden(sock))
                        return sock;
 
        /* OK, let's unhide proper one */
        for(sock= sockets->first; sock; sock= sock->next) {
                if(type == sock->type) {
-                       sock->flag &= ~SOCK_HIDDEN;
+                       sock->flag &= ~(SOCK_HIDDEN|SOCK_AUTO_HIDDEN);
                        return sock;
                }
        }
        
        /* just the first */
        sock= sockets->first;
-       sock->flag &= ~SOCK_HIDDEN;
+       sock->flag &= ~(SOCK_HIDDEN|SOCK_AUTO_HIDDEN);
        
        return sockets->first;
 }
@@ -3003,10 +3000,20 @@ static void node_flag_toggle_exec(SpaceNode *snode, int toggle_flag)
                        if(toggle_flag== NODE_OPTIONS && (node->typeinfo->flag & NODE_OPTIONS)==0)
                                continue;
                        
-                       if( (tot_eq && tot_neq) || tot_eq==0)
+                       if( (tot_eq && tot_neq) || tot_eq==0) {
                                node->flag |= toggle_flag;
-                       else
+                               
+                               /* hide/unhide node also toggles unlinked socket display */
+                               if (toggle_flag== NODE_HIDDEN)
+                                       node_set_hidden_sockets(snode, node, SOCK_AUTO_HIDDEN, 1);
+                       }
+                       else {
                                node->flag &= ~toggle_flag;
+                               
+                               /* hide/unhide node also toggles unlinked socket display */
+                               if (toggle_flag== NODE_HIDDEN)
+                                       node_set_hidden_sockets(snode, node, SOCK_AUTO_HIDDEN, 0);
+                       }
                }
        }
 }
@@ -3119,7 +3126,7 @@ static int node_socket_toggle_exec(bContext *C, wmOperator *UNUSED(op))
        hidden = 0;
        for(node= snode->edittree->nodes.first; node; node= node->next) {
                if(node->flag & SELECT) {
-                       if(node_has_hidden_sockets(node)) {
+                       if(node_has_hidden_sockets(node, SOCK_HIDDEN)) {
                                hidden= 1;
                                break;
                        }
@@ -3128,7 +3135,7 @@ static int node_socket_toggle_exec(bContext *C, wmOperator *UNUSED(op))
        
        for(node= snode->edittree->nodes.first; node; node= node->next) {
                if(node->flag & SELECT) {
-                       node_set_hidden_sockets(snode, node, !hidden);
+                       node_set_hidden_sockets(snode, node, SOCK_HIDDEN, !hidden);
                }
        }
 
index 9068493..186ad37 100644 (file)
@@ -118,8 +118,8 @@ void snode_composite_job(const struct bContext *C, ScrArea *sa);
 bNode *node_tree_get_editgroup(bNodeTree *ntree);
 void node_tree_verify_groups(bNodeTree *nodetree);
 void snode_autoconnect(SpaceNode *snode, int allow_multiple, int replace);
-int node_has_hidden_sockets(bNode *node);
-void node_set_hidden_sockets(SpaceNode *snode, bNode *node, int set);
+int node_has_hidden_sockets(bNode *node, short flag);
+void node_set_hidden_sockets(SpaceNode *snode, bNode *node, short flag, int set);
 int node_render_changed_exec(bContext *, wmOperator *);
 
 void NODE_OT_duplicate(struct wmOperatorType *ot);
index aa9b435..e2d6121 100644 (file)
@@ -129,6 +129,8 @@ typedef struct bNodeSocket {
 #define SOCK_COLLAPSED                 64
        /* hide socket value, if it gets auto default */
 #define SOCK_HIDE_VALUE                        128
+       /* socket hidden automatically, to distinguish from manually hidden */
+#define SOCK_AUTO_HIDDEN               256
 
 typedef struct bNodePreview {
        unsigned char *rect;
index 5ad84da..fdce1f9 100644 (file)
@@ -609,7 +609,7 @@ void node_group_expose_all_sockets(bNodeTree *ngroup)
        
        for (node=ngroup->nodes.first; node; node=node->next) {
                for (sock=node->inputs.first; sock; sock=sock->next) {
-                       if (!sock->link && !(sock->flag & SOCK_HIDDEN)) {
+                       if (!sock->link && !nodeSocketIsHidden(sock)) {
                                gsock = node_group_add_socket(ngroup, sock->name, sock->type, SOCK_IN);
                                
                                /* initialize the default value. */
@@ -619,7 +619,7 @@ void node_group_expose_all_sockets(bNodeTree *ngroup)
                        }
                }
                for (sock=node->outputs.first; sock; sock=sock->next) {
-                       if (nodeCountSocketLinks(ngroup, sock)==0 && !(sock->flag & SOCK_HIDDEN)) {
+                       if (nodeCountSocketLinks(ngroup, sock)==0 && !nodeSocketIsHidden(sock)) {
                                gsock = node_group_add_socket(ngroup, sock->name, sock->type, SOCK_OUT);
                                
                                /* initialize the default value. */
index 8b8afc3..1bfb986 100644 (file)
@@ -184,7 +184,7 @@ void nodeShaderSynchronizeID(bNode *node, int copyto)
                
                /* hrmf, case in loop isnt super fast, but we dont edit 100s of material at same time either! */
                for(a=0, sock= node->inputs.first; sock; sock= sock->next, a++) {
-                       if(!(sock->flag & SOCK_HIDDEN)) {
+                       if(!nodeSocketIsHidden(sock)) {
                                if(copyto) {
                                        switch(a) {
                                                case MAT_IN_COLOR: