Index: source/blender/include/BSE_node.h =================================================================== --- source/blender/include/BSE_node.h (revision 11762) +++ source/blender/include/BSE_node.h (working copy) @@ -40,6 +40,7 @@ struct SpaceNode; struct bNode; +struct bNodeSocket; struct bNodeTree; struct Material; struct ID; @@ -78,6 +79,7 @@ void node_composit_default(struct Scene *scene); int node_has_hidden_sockets(struct bNode *node); +float socket_in_visible_category(struct bNodeSocket *currentsock); struct bNode *node_add_node(struct SpaceNode *snode, int type, float locx, float locy); void node_adduplicate(struct SpaceNode *snode); Index: source/blender/makesdna/DNA_node_types.h =================================================================== --- source/blender/makesdna/DNA_node_types.h (revision 11762) +++ source/blender/makesdna/DNA_node_types.h (working copy) @@ -84,6 +84,7 @@ #define SOCK_VALUE 0 #define SOCK_VECTOR 1 #define SOCK_RGBA 2 +#define SOCK_CATEGORY 4 /* sock->flag, first bit is select */ /* hidden is user defined, to hide unused */ Index: source/blender/src/editnode.c =================================================================== --- source/blender/src/editnode.c (revision 11762) +++ source/blender/src/editnode.c (working copy) @@ -1147,7 +1147,18 @@ return 0; } +float socket_in_visible_category(bNodeSocket *currentsock) +{ + bNodeSocket *sock; + if(currentsock->type==SOCK_CATEGORY) return 1.0; /* category names are always visible */ + + for(sock= currentsock; sock; sock= sock->prev) + if(sock->type==SOCK_CATEGORY) return *sock->ns.vec; + + return 1.0; +} + static void node_hide_unhide_sockets(SpaceNode *snode, bNode *node) { bNodeSocket *sock; @@ -1591,7 +1602,7 @@ if(in_out==SOCK_OUT) { if(find_indicated_socket(snode, &tnode, &tsock, SOCK_IN)) { - if(nodeFindLink(snode->edittree, sock, tsock)==NULL) { + if(tsock->type!=SOCK_CATEGORY && socket_in_visible_category(tsock) && nodeFindLink(snode->edittree, sock, tsock)==NULL) { if(tnode!=node && link->tonode!=tnode && link->tosock!= tsock) { link->tonode= tnode; link->tosock= tsock; @@ -1606,7 +1617,7 @@ } else { if(find_indicated_socket(snode, &tnode, &tsock, SOCK_OUT)) { - if(nodeFindLink(snode->edittree, sock, tsock)==NULL) { + if(tsock->type!=SOCK_CATEGORY && socket_in_visible_category(tsock) && nodeFindLink(snode->edittree, sock, tsock)==NULL) { if(nodeCountSocketLinks(snode->edittree, tsock) < tsock->limit) { if(tnode!=node && link->fromnode!=tnode && link->fromsock!= tsock) { link->fromnode= tnode; Index: source/blender/src/drawnode.c =================================================================== --- source/blender/src/drawnode.c (revision 11762) +++ source/blender/src/drawnode.c (working copy) @@ -1767,6 +1767,8 @@ 0.15142777,0.52896401,0.82076344,0.97952994, }; int a; + + if(type==SOCK_CATEGORY) return; /* don't draw circles for categories */ if(select==0) { if(type==-1) @@ -1979,7 +1981,7 @@ /* input sockets */ for(nsock= node->inputs.first; nsock; nsock= nsock->next) { - if(!(nsock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) { + if(!(nsock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL)) && (socket_in_visible_category(nsock) || nsock->link)) { nsock->locx= node->locx; nsock->locy= dy - NODE_DYS; dy-= NODE_DY; @@ -2083,6 +2085,26 @@ return TH_NODE; } +static void node_draw_category_triangle(uiBlock *block, short xloc, short yloc, float *butpoin, SpaceNode *snode, bNode *node, bNodeSocket *sock) +{ + uiBut *bt; + + uiBlockSetEmboss(block, UI_EMBOSSN); + + if(*butpoin != 1.0) { + bt= uiDefIconButBitF(block, TOG, HEADER_NO_PULLDOWN, B_FLIPINFOMENU, ICON_DISCLOSURE_TRI_RIGHT, + xloc, yloc, 20, 17, + butpoin, 0, 0, 0, 0, "Show category"); + } else { + bt= uiDefIconButBitF(block, TOG, HEADER_NO_PULLDOWN, B_FLIPINFOMENU, ICON_DISCLOSURE_TRI_DOWN, + xloc, yloc, 20, 17, + butpoin, 0, 0, 0, 0, "Hide category"); + } + uiButSetFunc(bt, node_sync_cb, snode, node); + + uiBlockSetEmboss(block, UI_EMBOSS); +} + static void node_draw_basis(ScrArea *sa, SpaceNode *snode, bNode *node) { bNodeSocket *sock; @@ -2192,19 +2214,16 @@ glDisable(GL_BLEND); } - /* we make buttons for input sockets, if... */ - if(node->flag & NODE_OPTIONS) { - if(node->inputs.first || node->typeinfo->butfunc) { - char str[32]; - - /* make unique block name, also used for handling blocks in editnode.c */ - sprintf(str, "node buttons %p", node); - - block= uiNewBlock(&sa->uiblocks, str, UI_EMBOSS, UI_HELV, sa->win); - uiBlockSetFlag(block, UI_BLOCK_NO_HILITE); - if(snode->id) - uiSetButLock(snode->id->lib!=NULL, ERROR_LIBDATA_MESSAGE); - } + if(node->inputs.first || node->typeinfo->butfunc) { + char str[32]; + + /* make unique block name, also used for handling blocks in editnode.c */ + sprintf(str, "node buttons %p", node); + + block= uiNewBlock(&sa->uiblocks, str, UI_EMBOSS, UI_HELV, sa->win); + uiBlockSetFlag(block, UI_BLOCK_NO_HILITE); + if(snode->id) + uiSetButLock(snode->id->lib!=NULL, ERROR_LIBDATA_MESSAGE); } /* hurmf... another candidate for callback, have to see how this works first */ @@ -2214,42 +2233,62 @@ /* socket inputs, buttons */ for(sock= node->inputs.first; sock; sock= sock->next) { if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) { - socket_circle_draw(sock->locx, sock->locy, NODE_SOCKSIZE, sock->type, sock->flag & SELECT); + if((socket_in_visible_category(sock) || sock->link) && (sock->type!=SOCK_CATEGORY)) socket_circle_draw(sock->locx, sock->locy, NODE_SOCKSIZE, sock->type, sock->flag & SELECT); - if(block && sock->link==NULL) { + if((node->flag & NODE_OPTIONS) && (sock->link==NULL)) { float *butpoin= sock->ns.vec; - if(sock->type==SOCK_VALUE) { - bt= uiDefButF(block, NUM, B_NODE_EXEC+node->nr, sock->name, - (short)sock->locx+NODE_DYS, (short)(sock->locy)-9, (short)node->width-NODE_DY, 17, - butpoin, sock->ns.min, sock->ns.max, 10, 2, ""); - uiButSetFunc(bt, node_sync_cb, snode, node); + if(socket_in_visible_category(sock)) { + if(sock->type==SOCK_VALUE) { + bt= uiDefButF(block, NUM, B_NODE_EXEC+node->nr, sock->name, + (short)sock->locx+NODE_DYS, (short)(sock->locy)-9, (short)node->width-NODE_DY, 17, + butpoin, sock->ns.min, sock->ns.max, 10, 2, ""); + uiButSetFunc(bt, node_sync_cb, snode, node); + } + else if(sock->type==SOCK_VECTOR) { + uiDefBlockBut(block, socket_vector_menu, sock, sock->name, + (short)sock->locx+NODE_DYS, (short)sock->locy-9, (short)node->width-NODE_DY, 17, + ""); + } + else if(sock->type==SOCK_RGBA) { + short labelw= node->width-NODE_DY-40, width; + + if(labelw>0) width= 40; else width= node->width-NODE_DY; + + bt= uiDefButF(block, COL, B_NODE_EXEC+node->nr, "", + (short)(sock->locx+NODE_DYS), (short)sock->locy-8, width, 15, + butpoin, 0, 0, 0, 0, ""); + uiButSetFunc(bt, node_sync_cb, snode, node); + + if(labelw>0) uiDefBut(block, LABEL, 0, sock->name, + (short)(sock->locx+NODE_DYS) + 40, (short)sock->locy-8, labelw, 15, + NULL, 0, 0, 0, 0, ""); + } + else if(sock->type==SOCK_CATEGORY) { + node_draw_category_triangle(block, + (short)sock->locx+NODE_DYS, + (short)sock->locy-9, butpoin, snode, node, sock); + + uiDefBut(block, LABEL, 0, sock->name, + (short)sock->locx+NODE_DYS+NODE_DY, (short)sock->locy-9, + (short)node->width-NODE_DY, 17, 0, 0, 0, 0, 0, ""); + } } - else if(sock->type==SOCK_VECTOR) { - uiDefBlockBut(block, socket_vector_menu, sock, sock->name, - (short)sock->locx+NODE_DYS, (short)sock->locy-9, (short)node->width-NODE_DY, 17, - ""); + } + else { + /* exception! uiDefBut won't work in this case so have to use ui_rasterpos_safe instead */ + if(((node->typeinfo->flag & NODE_OPTIONS) && (socket_in_visible_category(sock) || sock->link)) + || (node->typeinfo->nclass & NODE_CLASS_OUTPUT)) { + BIF_ThemeColor(TH_TEXT); + ui_rasterpos_safe(sock->locx+8.0f, sock->locy-5.0f, snode->aspect); + BIF_DrawString(snode->curfont, sock->name, 0); } - else if(block && sock->type==SOCK_RGBA) { - short labelw= node->width-NODE_DY-40, width; - - if(labelw>0) width= 40; else width= node->width-NODE_DY; - - bt= uiDefButF(block, COL, B_NODE_EXEC+node->nr, "", - (short)(sock->locx+NODE_DYS), (short)sock->locy-8, width, 15, - butpoin, 0, 0, 0, 0, ""); - uiButSetFunc(bt, node_sync_cb, snode, node); - - if(labelw>0) uiDefBut(block, LABEL, 0, sock->name, - (short)(sock->locx+NODE_DYS) + 40, (short)sock->locy-8, labelw, 15, - NULL, 0, 0, 0, 0, ""); + else { + uiDefBut(block, LABEL, 0, sock->name, + (short)sock->locx+NODE_DYS, (short)sock->locy-9, + (short)node->width-NODE_DY, 17, 0, 0, 0, 0, 0, ""); } } - else { - BIF_ThemeColor(TH_TEXT); - ui_rasterpos_safe(sock->locx+8.0f, sock->locy-5.0f, snode->aspect); - BIF_DrawString(snode->curfont, sock->name, 0); - } } } @@ -2354,6 +2393,7 @@ } /* note; this is used for fake links in groups too */ +/* TODO: fix issue that appears when a category is hidden and cursor is dragged above an item just below category name (has to be last on node) -> node_add_link_drag at editnode.c */ void node_draw_link(SpaceNode *snode, bNodeLink *link) { float vec[4][3]; @@ -2373,9 +2413,9 @@ } else { /* going to give issues once... */ - if(link->tosock->flag & SOCK_UNAVAIL) + if((link->tosock->flag & SOCK_UNAVAIL) || (link->tosock->type==SOCK_CATEGORY)) return; - if(link->fromsock->flag & SOCK_UNAVAIL) + if((link->fromsock->flag & SOCK_UNAVAIL) || (link->fromsock->type==SOCK_CATEGORY)) return; /* a bit ugly... but thats how we detect the internal group links */ Index: source/blender/nodes/intern/SHD_util.h =================================================================== --- source/blender/nodes/intern/SHD_util.h (revision 11762) +++ source/blender/nodes/intern/SHD_util.h (working copy) @@ -101,29 +101,30 @@ } ShaderCallData; /* output socket defines */ -#define GEOM_OUT_GLOB 0 -#define GEOM_OUT_LOCAL 1 -#define GEOM_OUT_VIEW 2 -#define GEOM_OUT_ORCO 3 +#define GEOM_OUT_GLOB 0 +#define GEOM_OUT_LOCAL 1 +#define GEOM_OUT_VIEW 2 +#define GEOM_OUT_ORCO 3 #define GEOM_OUT_UV 4 -#define GEOM_OUT_NORMAL 5 -#define GEOM_OUT_VCOL 6 +#define GEOM_OUT_NORMAL 5 +#define GEOM_OUT_VCOL 6 #define GEOM_OUT_FRONTBACK 7 /* input socket defines */ -#define MAT_IN_COLOR 0 +#define MAT_IN_COLOR 0 #define MAT_IN_SPEC 1 #define MAT_IN_REFL 2 -#define MAT_IN_NORMAL 3 -#define MAT_IN_MIR 4 -#define MAT_IN_AMBCOL 5 -#define MAT_IN_AMB 6 -#define MAT_IN_EMIT 7 -#define MAT_IN_SPECTRA 8 -#define MAT_IN_RAY_MIRROR 9 -#define MAT_IN_ALPHA 10 -#define MAT_IN_TRANSLUCENCY 11 +#define MAT_IN_NORMAL 3 +/* 4 is reserved by category */ +#define MAT_IN_MIR 5 +#define MAT_IN_AMBCOL 6 +#define MAT_IN_AMB 7 +#define MAT_IN_EMIT 8 +#define MAT_IN_SPECTRA 9 +#define MAT_IN_RAY_MIRROR 10 +#define MAT_IN_ALPHA 11 +#define MAT_IN_TRANSLUCENCY 12 /* output socket defines */ #define MAT_OUT_COLOR 0 Index: source/blender/nodes/intern/SHD_nodes/SHD_material.c =================================================================== --- source/blender/nodes/intern/SHD_nodes/SHD_material.c (revision 11762) +++ source/blender/nodes/intern/SHD_nodes/SHD_material.c (working copy) @@ -53,6 +53,7 @@ { SOCK_RGBA, 1, "Spec", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, { SOCK_VALUE, 1, "Refl", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, { SOCK_VECTOR, 1, "Normal", 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f}, + { SOCK_CATEGORY, 1, "Extended", 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f}, { SOCK_RGBA, 1, "Mirror", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, { SOCK_RGBA, 1, "AmbCol", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, { SOCK_VALUE, 1, "Ambient", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, Index: source/blender/nodes/intern/SHD_util.c =================================================================== --- source/blender/nodes/intern/SHD_util.c (revision 11762) +++ source/blender/nodes/intern/SHD_util.c (working copy) @@ -55,7 +55,7 @@ VECCOPY(in, from); } } - else { /* type_in==SOCK_RGBA */ + else if(type_in==SOCK_RGBA) { if(ns->sockettype==SOCK_RGBA) { QUATCOPY(in, from); }