Big node groups improvement patch. Node group trees now have their own lists of input/output sockets. Those can be linked to internal nodes just like links between regular nodes. In addition group sockets can be renamed and have a defined order, which can be modified, and they can be removed again.

More details can be found in the patch tracker description (#24883) and on the code.blender.org development blog.
This commit is contained in:
Lukas Toenne
2011-02-21 13:47:49 +00:00
parent 9ef0eed4b6
commit 1c7a422f78
15 changed files with 1231 additions and 742 deletions

View File

@@ -44,7 +44,7 @@ extern "C" {
* and keep comment above the defines.
* Use STRINGIFY() rather then defining with quotes */
#define BLENDER_VERSION 256
#define BLENDER_SUBVERSION 1
#define BLENDER_SUBVERSION 2
#define BLENDER_MINVERSION 250
#define BLENDER_MINSUBVERSION 0

View File

@@ -71,9 +71,6 @@ typedef struct bNodeSocketType {
/* after this line is used internal only */
struct bNodeSocket *sock; /* used during verify_types */
struct bNodeSocket *internsock; /* group nodes, the internal socket counterpart */
int own_index; /* verify group nodes */
} bNodeSocketType;
typedef struct bNodeType {
@@ -130,6 +127,10 @@ typedef struct bNodeType {
#define NODE_CLASS_PATTERN 12
#define NODE_CLASS_TEXTURE 13
/* enum values for input/output */
#define SOCK_IN 1
#define SOCK_OUT 2
/* ************** GENERIC API, TREES *************** */
void ntreeVerifyTypes(struct bNodeTree *ntree);
@@ -137,7 +138,7 @@ void ntreeVerifyTypes(struct bNodeTree *ntree);
struct bNodeTree *ntreeAddTree(const char *name, int type, const short is_group);
void ntreeInitTypes(struct bNodeTree *ntree);
void ntreeMakeOwnType(struct bNodeTree *ntree);
//void ntreeMakeGroupSockets(struct bNodeTree *ntree);
void ntreeUpdateType(struct bNodeTree *ntree, struct bNodeType *ntype);
void ntreeFreeTree(struct bNodeTree *ntree);
struct bNodeTree *ntreeCopyTree(struct bNodeTree *ntree);
@@ -178,7 +179,7 @@ void nodeUpdateType(struct bNodeTree *ntree, struct bNode* node, struct bNodeT
void nodeMakeDynamicType(struct bNode *node);
int nodeDynamicUnlinkText(struct ID *txtid);
void nodeFreeNode(struct bNodeTree *ntree, struct bNode *node);
struct bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node, int internal);
struct bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node);
struct bNodeLink *nodeAddLink(struct bNodeTree *ntree, struct bNode *fromnode, struct bNodeSocket *fromsock, struct bNode *tonode, struct bNodeSocket *tosock);
void nodeRemLink(struct bNodeTree *ntree, struct bNodeLink *link);
@@ -210,6 +211,11 @@ void nodeGroupSocketUseFlags(struct bNodeTree *ngroup);
void nodeCopyGroup(struct bNode *gnode);
struct bNodeSocket *nodeAddGroupSocket(struct bNodeTree *ngroup, const char *name, int type, int in_out);
struct bNodeSocket *nodeAddGroupSocketCopy(struct bNodeTree *ngroup, struct bNodeSocket *copy, int in_out);
void nodeAddAllGroupSockets(struct bNodeTree *ngroup);
void nodeRemGroupSocket(struct bNodeTree *ngroup, struct bNodeSocket *gsock, int in_out);
/* ************** COMMON NODES *************** */
/* Init a new node type struct with default values and callbacks */

File diff suppressed because it is too large Load Diff

View File

@@ -2046,8 +2046,7 @@ static void lib_verify_nodetree(Main *main, int UNUSED(open))
/* now create the own typeinfo structs an verify nodes */
/* here we still assume no groups in groups */
for(ntree= main->nodetree.first; ntree; ntree= ntree->id.next) {
ntreeVerifyTypes(ntree); /* internal nodes, no groups! */
ntreeMakeOwnType(ntree); /* for group usage */
ntreeVerifyTypes(ntree); /* internal nodes, no groups! */
}
/* now verify all types in material trees, groups are set OK now */
@@ -2078,7 +2077,6 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree)
bNodeLink *link;
ntree->init= 0; /* to set callbacks and force setting types */
ntree->owntype= NULL;
ntree->progress= NULL;
ntree->adt= newdataadr(fd, ntree->adt);
@@ -2116,6 +2114,10 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree)
}
link_list(fd, &ntree->links);
/* external sockets */
link_list(fd, &ntree->inputs);
link_list(fd, &ntree->outputs);
/* and we connect the rest */
for(node= ntree->nodes.first; node; node= node->next) {
node->preview= newimaadr(fd, node->preview);
@@ -2125,13 +2127,16 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree)
for(sock= node->outputs.first; sock; sock= sock->next)
sock->ns.data= NULL;
}
for(sock= ntree->outputs.first; sock; sock= sock->next)
sock->link= newdataadr(fd, sock->link);
for(link= ntree->links.first; link; link= link->next) {
link->fromnode= newdataadr(fd, link->fromnode);
link->tonode= newdataadr(fd, link->tonode);
link->fromsock= newdataadr(fd, link->fromsock);
link->tosock= newdataadr(fd, link->tosock);
}
/* type verification is in lib-link */
}
@@ -11363,8 +11368,19 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
}
}
if (main->versionfile < 256 || (main->versionfile == 256 && main->subversionfile < 2)) {
bNodeTree *ntree;
/* node sockets are not exposed automatically any more,
* this mimics the old behaviour by adding all unlinked sockets to groups.
*/
for (ntree=main->nodetree.first; ntree; ntree=ntree->id.next) {
nodeAddAllGroupSockets(ntree);
}
}
/* put compatibility code here until next subversion bump */
{
bScreen *sc;
@@ -11377,7 +11393,7 @@ static void do_versions(FileData *fd, Library *lib, Main *main)
}
}
}
/* WATCH IT!!!: pointers from libdata have not been converted yet here! */
/* WATCH IT 2!: Userdef struct init has to be in editors/interface/resources.c! */

View File

@@ -670,6 +670,12 @@ static void write_nodetree(WriteData *wd, bNodeTree *ntree)
for(link= ntree->links.first; link; link= link->next)
writestruct(wd, DATA, "bNodeLink", 1, link);
/* external sockets */
for(sock= ntree->inputs.first; sock; sock= sock->next)
writestruct(wd, DATA, "bNodeSocket", 1, sock);
for(sock= ntree->outputs.first; sock; sock= sock->next)
writestruct(wd, DATA, "bNodeSocket", 1, sock);
}
static void current_screen_compat(Main *mainvar, bScreen **screen)

View File

@@ -1604,11 +1604,11 @@ void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link)
int do_shaded= 0, th_col1= TH_HEADER, th_col2= TH_HEADER;
int do_triple= 0, th_col3= TH_WIRE;
if(link->fromnode==NULL && link->tonode==NULL)
if(link->fromsock==NULL && link->tosock==NULL)
return;
/* new connection */
if(link->fromnode==NULL || link->tonode==NULL) {
if(!link->fromsock || !link->tosock) {
th_col1 = TH_ACTIVE;
do_triple = 1;
}
@@ -1620,8 +1620,9 @@ void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link)
return;
/* a bit ugly... but thats how we detect the internal group links */
if(link->fromnode==link->tonode) {
th_col1 = TH_GRID;
if(!link->fromnode || !link->tonode) {
UI_ThemeColorBlend(TH_BACK, TH_WIRE, 0.5f);
do_shaded= 0;
}
else {
/* check cyclic */

View File

@@ -30,6 +30,8 @@
#include <stdio.h>
#include <string.h>
#include "MEM_guardedalloc.h"
#include "DNA_node_types.h"
#include "DNA_material_types.h"
#include "DNA_object_types.h"
@@ -68,6 +70,9 @@
#include "node_intern.h"
/* width of socket columns in group display */
#define NODE_GROUP_FRAME 120
// XXX interface.h
extern void ui_dropshadow(rctf *rct, float radius, float aspect, int select);
@@ -380,9 +385,10 @@ static void node_update_group(const bContext *C, bNodeTree *ntree, bNode *gnode)
{
bNodeTree *ngroup= (bNodeTree *)gnode->id;
bNode *node;
bNodeSocket *nsock;
bNodeSocket *sock, *gsock;
rctf *rect= &gnode->totr;
int counter;
int dy;
/* center them, is a bit of abuse of locx and locy though */
for(node= ngroup->nodes.first; node; node= node->next) {
@@ -405,6 +411,11 @@ static void node_update_group(const bContext *C, bNodeTree *ntree, bNode *gnode)
else
BLI_union_rctf(rect, &node->totr);
}
/* add some room for links to group sockets */
rect->xmin -= 3*NODE_DY;
rect->xmax += 3*NODE_DY;
if(counter==1) return; /* should be prevented? */
rect->xmin-= NODE_DY;
@@ -412,16 +423,22 @@ static void node_update_group(const bContext *C, bNodeTree *ntree, bNode *gnode)
rect->xmax+= NODE_DY;
rect->ymax+= NODE_DY;
/* output sockets */
for(nsock= gnode->outputs.first; nsock; nsock= nsock->next) {
nsock->locx= rect->xmax;
nsock->locy= nsock->tosock->locy;
/* input sockets */
dy = 0.5f*(rect->ymin+rect->ymax) + NODE_DY*(BLI_countlist(&gnode->inputs)-1);
for(gsock=ngroup->inputs.first, sock=gnode->inputs.first; gsock; gsock=gsock->next, sock=sock->next) {
gsock->locx = rect->xmin;
sock->locx = rect->xmin - NODE_GROUP_FRAME;
sock->locy = gsock->locy = dy;
dy -= 2*NODE_DY;
}
/* input sockets */
for(nsock= gnode->inputs.first; nsock; nsock= nsock->next) {
nsock->locx= rect->xmin;
nsock->locy= nsock->tosock->locy;
/* output sockets */
dy = 0.5f*(rect->ymin+rect->ymax) + NODE_DY*(BLI_countlist(&gnode->outputs)-1);
for(gsock=ngroup->outputs.first, sock=gnode->outputs.first; gsock; gsock=gsock->next, sock=sock->next) {
gsock->locx = rect->xmax;
sock->locx = rect->xmax + NODE_GROUP_FRAME;
sock->locy = gsock->locy = dy - NODE_DYS;
dy -= 2*NODE_DY;
}
}
@@ -549,29 +566,6 @@ static void node_sync_cb(bContext *UNUSED(C), void *snode_v, void *node_v)
/* ************** Socket callbacks *********** */
/* NOTE: this is a block-menu, needs 0 events, otherwise the menu closes */
static uiBlock *socket_vector_menu(bContext *C, ARegion *ar, void *socket_v)
{
bNodeSocket *sock= socket_v;
uiBlock *block;
SpaceNode *snode= CTX_wm_space_node(C);
bNodeTree *ntree = snode->nodetree;
PointerRNA ptr;
uiLayout *layout;
RNA_pointer_create(&ntree->id, &RNA_NodeSocket, sock, &ptr);
block= uiBeginBlock(C, ar, "socket menu", UI_EMBOSS);
uiBlockSetFlag(block, UI_BLOCK_KEEP_OPEN);
layout= uiLayoutColumn(uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, sock->locx, sock->locy-8, 140, 20, U.uistyles.first), 0);
uiItemR(layout, &ptr, "default_value", UI_ITEM_R_EXPAND, "", ICON_NULL);
return block;
}
/* not a callback */
static void node_draw_preview(bNodePreview *preview, rctf *prv)
{
@@ -626,16 +620,91 @@ static void node_draw_preview(bNodePreview *preview, rctf *prv)
}
typedef struct SocketVectorMenuArgs {
PointerRNA ptr;
int x, y, width;
uiButHandleFunc cb;
void *arg1, *arg2;
} SocketVectorMenuArgs;
/* NOTE: this is a block-menu, needs 0 events, otherwise the menu closes */
static uiBlock *socket_vector_menu(bContext *C, ARegion *ar, void *args_v)
{
SocketVectorMenuArgs *args= (SocketVectorMenuArgs*)args_v;
uiBlock *block;
uiLayout *layout;
block= uiBeginBlock(C, ar, "socket menu", UI_EMBOSS);
uiBlockSetFlag(block, UI_BLOCK_KEEP_OPEN);
layout= uiLayoutColumn(uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, args->x, args->y+2, args->width, 20, U.uistyles.first), 0);
uiItemR(layout, &args->ptr, "default_value", UI_ITEM_R_EXPAND, "", ICON_NULL);
return block;
}
static void node_draw_socket_button(bNodeTree *ntree, bNodeSocket *sock, const char *name,
uiBlock *block, int x, int y, int width,
uiButHandleFunc cb, void *arg1, void *arg2)
{
uiBut *bt= NULL;
PointerRNA ptr;
int labelw;
SocketVectorMenuArgs *args;
RNA_pointer_create(&ntree->id, &RNA_NodeSocket, sock, &ptr);
switch (sock->type) {
case SOCK_VALUE:
bt=uiDefButR(block, NUM, B_NODE_EXEC, name,
x, y+1, width, 17,
&ptr, "default_value", 0, sock->ns.min, sock->ns.max, -1, -1, NULL);
if (cb)
uiButSetFunc(bt, cb, arg1, arg2);
break;
case SOCK_VECTOR:
args= MEM_callocN(sizeof(SocketVectorMenuArgs), "SocketVectorMenuArgs");
args->ptr = ptr;
args->x = x;
args->y = y;
args->width = width;
args->cb = cb;
args->arg1 = arg1;
args->arg2 = arg2;
uiDefBlockButN(block, socket_vector_menu, args, name,
x, y+1, width, 17,
"");
break;
case SOCK_RGBA:
labelw= width - 40;
bt=uiDefButR(block, COL, B_NODE_EXEC, "",
x, y+2, (labelw>0 ? 40 : width), 15,
&ptr, "default_value", 0, sock->ns.min, sock->ns.max, -1, -1, NULL);
if (cb)
uiButSetFunc(bt, cb, arg1, arg2);
if (name[0]!='\0' && labelw>0)
uiDefBut(block, LABEL, 0, name,
x + 40, y+2, labelw, 15,
NULL, 0, 0, 0, 0, "");
break;
}
}
static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node)
{
bNodeSocket *sock;
uiBut *bt;
rctf *rct= &node->totr;
float /*slen,*/ iconofs;
int /*ofs,*/ color_id= node_get_colorid(node);
float iconofs;
int color_id= node_get_colorid(node);
char showname[128]; /* 128 used below */
View2D *v2d = &ar->v2d;
PointerRNA ptr;
/* hurmf... another candidate for callback, have to see how this works first */
if(node->id && node->block && snode->treetype==NTREE_SHADER)
@@ -765,38 +834,10 @@ static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bN
if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) {
socket_circle_draw(sock, NODE_SOCKSIZE);
RNA_pointer_create(&ntree->id, &RNA_NodeSocket, sock, &ptr);
if(node->block && sock->link==NULL) {
if(sock->type==SOCK_VALUE) {
bt=uiDefButR(node->block, NUM, B_NODE_EXEC, sock->name,
(short)sock->locx+NODE_DYS, (short)(sock->locy)-9, (short)node->width-NODE_DY, 17,
&ptr, "default_value", 0, sock->ns.min, sock->ns.max, -1, -1, NULL);
uiButSetFunc(bt, node_sync_cb, snode, node);
}
else if(sock->type==SOCK_VECTOR) {
uiDefBlockBut(node->block, socket_vector_menu, sock, sock->name,
(short)sock->locx+NODE_DYS, (short)sock->locy-9, (short)node->width-NODE_DY, 17,
"");
}
else if(node->block && sock->type==SOCK_RGBA) {
short labelw= (short)node->width-NODE_DY-40, width;
if(labelw>0) width= 40; else width= (short)node->width-NODE_DY;
bt=uiDefButR(node->block, COL, B_NODE_EXEC, "",
(short)sock->locx+NODE_DYS, (short)(sock->locy)-8, width, 15,
&ptr, "default_value", 0, sock->ns.min, sock->ns.max, -1, -1, NULL);
uiButSetFunc(bt, node_sync_cb, snode, node);
if(labelw>0) uiDefBut(node->block, LABEL, 0, sock->name,
(short)(sock->locx+NODE_DYS) + 40, (short)sock->locy-8, labelw, 15,
NULL, 0, 0, 0, 0, "");
}
node_draw_socket_button(ntree, sock, sock->name, node->block, sock->locx+NODE_DYS, sock->locy-NODE_DYS, node->width-NODE_DY, node_sync_cb, snode, node);
}
else {
uiDefBut(node->block, LABEL, 0, sock->name, (short)(sock->locx+7), (short)(sock->locy-9.0f),
(short)(node->width-NODE_DY), NODE_DY, NULL, 0, 0, 0, 0, "");
}
@@ -969,39 +1010,11 @@ static void node_draw_nodetree(const bContext *C, ARegion *ar, SpaceNode *snode,
}
}
/* fake links from groupnode to internal nodes */
static void node_draw_group_links(View2D *v2d, SpaceNode *snode, bNode *gnode)
static void group_verify_cb(bContext *UNUSED(C), void *UNUSED(snode_v), void *ngroup_v)
{
bNodeLink fakelink;
bNodeSocket *sock;
bNodeTree *ngroup= (bNodeTree*)ngroup_v;
glEnable(GL_BLEND);
glEnable(GL_LINE_SMOOTH);
fakelink.tonode= fakelink.fromnode= gnode;
for(sock= gnode->inputs.first; sock; sock= sock->next) {
if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) {
if(sock->tosock) {
fakelink.fromsock= sock;
fakelink.tosock= sock->tosock;
node_draw_link(v2d, snode, &fakelink);
}
}
}
for(sock= gnode->outputs.first; sock; sock= sock->next) {
if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) {
if(sock->tosock) {
fakelink.tosock= sock;
fakelink.fromsock= sock->tosock;
node_draw_link(v2d, snode, &fakelink);
}
}
}
glDisable(GL_BLEND);
glDisable(GL_LINE_SMOOTH);
nodeVerifyGroup(ngroup);
}
/* groups are, on creation, centered around 0,0 */
@@ -1010,25 +1023,51 @@ static void node_draw_group(const bContext *C, ARegion *ar, SpaceNode *snode, bN
bNodeTree *ngroup= (bNodeTree *)gnode->id;
bNodeSocket *sock;
rctf rect= gnode->totr;
int index;
uiLayout *layout;
PointerRNA ptr;
uiBut *bt;
/* backdrop header */
glEnable(GL_BLEND);
uiSetRoundBox(3);
UI_ThemeColorShadeAlpha(TH_NODE_GROUP, 0, -70);
uiDrawBox(GL_POLYGON, rect.xmin, rect.ymax, rect.xmax, rect.ymax+26, BASIS_RAD);
uiDrawBox(GL_POLYGON, rect.xmin-NODE_GROUP_FRAME, rect.ymax, rect.xmax+NODE_GROUP_FRAME, rect.ymax+26, BASIS_RAD);
/* backdrop body */
UI_ThemeColorShadeAlpha(TH_BACK, -8, -70);
uiSetRoundBox(12);
uiSetRoundBox(0);
uiDrawBox(GL_POLYGON, rect.xmin, rect.ymin, rect.xmax, rect.ymax, BASIS_RAD);
/* selection outline */
/* input column */
UI_ThemeColorShadeAlpha(TH_BACK, 10, -50);
uiSetRoundBox(8);
uiDrawBox(GL_POLYGON, rect.xmin-NODE_GROUP_FRAME, rect.ymin, rect.xmin, rect.ymax, BASIS_RAD);
/* output column */
UI_ThemeColorShadeAlpha(TH_BACK, 10, -50);
uiSetRoundBox(4);
uiDrawBox(GL_POLYGON, rect.xmax, rect.ymin, rect.xmax+NODE_GROUP_FRAME, rect.ymax, BASIS_RAD);
/* input column separator */
glColor4ub(200, 200, 200, 140);
glBegin(GL_LINES);
glVertex2f(rect.xmin, rect.ymin);
glVertex2f(rect.xmin, rect.ymax);
glEnd();
/* output column separator */
glColor4ub(200, 200, 200, 140);
glBegin(GL_LINES);
glVertex2f(rect.xmax, rect.ymin);
glVertex2f(rect.xmax, rect.ymax);
glEnd();
/* group node outline */
uiSetRoundBox(15);
glColor4ub(200, 200, 200, 140);
glEnable( GL_LINE_SMOOTH );
uiDrawBox(GL_LINE_LOOP, rect.xmin, rect.ymin, rect.xmax, rect.ymax+26, BASIS_RAD);
uiDrawBox(GL_LINE_LOOP, rect.xmin-NODE_GROUP_FRAME, rect.ymin, rect.xmax+NODE_GROUP_FRAME, rect.ymax+26, BASIS_RAD);
glDisable( GL_LINE_SMOOTH );
glDisable(GL_BLEND);
@@ -1041,26 +1080,101 @@ static void node_draw_group(const bContext *C, ARegion *ar, SpaceNode *snode, bN
uiTemplateIDBrowse(layout, (bContext*)C, &ptr, "node_tree", NULL, NULL, NULL);
uiBlockLayoutResolve(gnode->block, NULL, NULL);
/* draw the internal tree nodes and links */
node_draw_nodetree(C, ar, snode, ngroup);
/* group sockets */
for(sock=ngroup->inputs.first, index=0; sock; sock=sock->next, ++index) {
socket_circle_draw(sock, NODE_SOCKSIZE);
/* small hack to use socket_circle_draw function with offset */
sock->locx -= NODE_GROUP_FRAME;
socket_circle_draw(sock, NODE_SOCKSIZE);
sock->locx += NODE_GROUP_FRAME;
bt = uiDefBut(gnode->block, TEX, 0, "",
sock->locx-114, sock->locy+1, 72, NODE_DY,
sock->name, 0, 31, 0, 0, "");
uiButSetFunc(bt, group_verify_cb, snode, ngroup);
node_draw_socket_button(ngroup, sock, "", gnode->block,
sock->locx-114, sock->locy-NODE_DY, 72,
NULL, NULL, NULL);
uiBlockSetDirection(gnode->block, UI_TOP);
uiBlockBeginAlign(gnode->block);
bt = uiDefIconButO(gnode->block, BUT, "NODE_OT_group_socket_move_up", 0, ICON_TRIA_UP,
sock->locx-40, sock->locy, 16, 16, "");
if (!sock->prev)
uiButSetFlag(bt, UI_BUT_DISABLED);
RNA_int_set(uiButGetOperatorPtrRNA(bt), "index", index);
RNA_enum_set(uiButGetOperatorPtrRNA(bt), "in_out", SOCK_IN);
bt = uiDefIconButO(gnode->block, BUT, "NODE_OT_group_socket_move_down", 0, ICON_TRIA_DOWN,
sock->locx-40, sock->locy-16, 16, 16, "");
if (!sock->next)
uiButSetFlag(bt, UI_BUT_DISABLED);
RNA_int_set(uiButGetOperatorPtrRNA(bt), "index", index);
RNA_enum_set(uiButGetOperatorPtrRNA(bt), "in_out", SOCK_IN);
uiBlockEndAlign(gnode->block);
uiBlockSetDirection(gnode->block, 0);
uiBlockSetEmboss(gnode->block, UI_EMBOSSN);
bt = uiDefIconButO(gnode->block, BUT, "NODE_OT_group_socket_remove", 0, ICON_X,
sock->locx-22, sock->locy-8, 16, 16, "");
RNA_int_set(uiButGetOperatorPtrRNA(bt), "index", index);
RNA_enum_set(uiButGetOperatorPtrRNA(bt), "in_out", SOCK_IN);
uiBlockSetEmboss(gnode->block, UI_EMBOSS);
}
for(sock=ngroup->outputs.first, index=0; sock; sock=sock->next, ++index) {
socket_circle_draw(sock, NODE_SOCKSIZE);
/* small hack to use socket_circle_draw function with offset */
sock->locx += NODE_GROUP_FRAME;
socket_circle_draw(sock, NODE_SOCKSIZE);
sock->locx -= NODE_GROUP_FRAME;
uiBlockSetEmboss(gnode->block, UI_EMBOSSN);
bt = uiDefIconButO(gnode->block, BUT, "NODE_OT_group_socket_remove", 0, ICON_X,
sock->locx+6, sock->locy-8, 16, 16, "");
RNA_int_set(uiButGetOperatorPtrRNA(bt), "index", index);
RNA_enum_set(uiButGetOperatorPtrRNA(bt), "in_out", SOCK_OUT);
uiBlockSetEmboss(gnode->block, UI_EMBOSS);
uiBlockSetDirection(gnode->block, UI_TOP);
uiBlockBeginAlign(gnode->block);
bt = uiDefIconButO(gnode->block, BUT, "NODE_OT_group_socket_move_up", 0, ICON_TRIA_UP,
sock->locx+24, sock->locy, 16, 16, "");
if (!sock->prev)
uiButSetFlag(bt, UI_BUT_DISABLED);
RNA_int_set(uiButGetOperatorPtrRNA(bt), "index", index);
RNA_enum_set(uiButGetOperatorPtrRNA(bt), "in_out", SOCK_OUT);
bt = uiDefIconButO(gnode->block, BUT, "NODE_OT_group_socket_move_down", 0, ICON_TRIA_DOWN,
sock->locx+24, sock->locy-16, 16, 16, "");
if (!sock->next)
uiButSetFlag(bt, UI_BUT_DISABLED);
RNA_int_set(uiButGetOperatorPtrRNA(bt), "index", index);
RNA_enum_set(uiButGetOperatorPtrRNA(bt), "in_out", SOCK_OUT);
uiBlockEndAlign(gnode->block);
uiBlockSetDirection(gnode->block, 0);
if (sock->link) {
bt = uiDefBut(gnode->block, TEX, 0, "",
sock->locx+42, sock->locy-NODE_DYS+1, 72, NODE_DY,
sock->name, 0, 31, 0, 0, "");
uiButSetFunc(bt, group_verify_cb, snode, ngroup);
}
else {
bt = uiDefBut(gnode->block, TEX, 0, "",
sock->locx+42, sock->locy+1, 72, NODE_DY,
sock->name, 0, 31, 0, 0, "");
uiButSetFunc(bt, group_verify_cb, snode, ngroup);
node_draw_socket_button(ngroup, sock, "", gnode->block, sock->locx+42, sock->locy-NODE_DY, 72, NULL, NULL, NULL);
}
}
uiEndBlock(C, gnode->block);
uiDrawBlock(C, gnode->block);
gnode->block= NULL;
/* links from groupsockets to the internal nodes */
node_draw_group_links(&ar->v2d, snode, gnode);
/* group sockets */
for(sock= gnode->inputs.first; sock; sock= sock->next)
if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL)))
socket_circle_draw(sock, NODE_SOCKSIZE);
for(sock= gnode->outputs.first; sock; sock= sock->next)
if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL)))
socket_circle_draw(sock, NODE_SOCKSIZE);
/* and finally the whole tree */
node_draw_nodetree(C, ar, snode, ngroup);
}
void drawnodespace(const bContext *C, ARegion *ar, View2D *v2d)

View File

@@ -77,10 +77,15 @@
#include "IMB_imbuf.h"
#include "RNA_enum_types.h"
#include "node_intern.h"
#define SOCK_IN 1
#define SOCK_OUT 2
static EnumPropertyItem socket_in_out_items[] = {
{ SOCK_IN, "IN", 0, "In", "" },
{ SOCK_OUT, "OUT", 0, "Out", "" },
{ 0, NULL, 0, NULL, NULL}
};
/* ***************** composite job manager ********************** */
@@ -634,6 +639,241 @@ void NODE_OT_group_edit(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
}
/* ***************** Add Group Socket operator ************* */
static int node_group_socket_add_exec(bContext *C, wmOperator *op)
{
SpaceNode *snode = CTX_wm_space_node(C);
int in_out= -1;
char name[32]= "";
int type= SOCK_VALUE;
bNodeTree *ngroup= snode->edittree;
bNodeSocket *sock;
ED_preview_kill_jobs(C);
if (RNA_property_is_set(op->ptr, "name"))
RNA_string_get(op->ptr, "name", name);
if (RNA_property_is_set(op->ptr, "type"))
type = RNA_enum_get(op->ptr, "type");
if (RNA_property_is_set(op->ptr, "in_out"))
in_out = RNA_enum_get(op->ptr, "in_out");
else
return OPERATOR_CANCELLED;
sock = nodeAddGroupSocket(ngroup, name, type, in_out);
node_tree_verify_groups(snode->nodetree);
snode_notify(C, snode);
return OPERATOR_FINISHED;
}
void NODE_OT_group_socket_add(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Add Group Socket";
ot->description = "Add node group socket";
ot->idname = "NODE_OT_group_socket_add";
/* api callbacks */
ot->exec = node_group_socket_add_exec;
ot->poll = ED_operator_node_active;
/* flags */
ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
RNA_def_enum(ot->srna, "in_out", socket_in_out_items, SOCK_IN, "Socket Type", "Input or Output");
RNA_def_string(ot->srna, "name", "", 32, "Name", "Group socket name");
RNA_def_enum(ot->srna, "type", node_socket_type_items, SOCK_VALUE, "Type", "Type of the group socket");
}
/* ***************** Remove Group Socket operator ************* */
static int node_group_socket_remove_exec(bContext *C, wmOperator *op)
{
SpaceNode *snode = CTX_wm_space_node(C);
int index= -1;
int in_out= -1;
bNodeTree *ngroup= snode->edittree;
bNodeSocket *sock;
ED_preview_kill_jobs(C);
if (RNA_property_is_set(op->ptr, "index"))
index = RNA_int_get(op->ptr, "index");
else
return OPERATOR_CANCELLED;
if (RNA_property_is_set(op->ptr, "in_out"))
in_out = RNA_enum_get(op->ptr, "in_out");
else
return OPERATOR_CANCELLED;
sock = (bNodeSocket*)BLI_findlink(in_out==SOCK_IN ? &ngroup->inputs : &ngroup->outputs, index);
if (sock) {
nodeRemGroupSocket(ngroup, sock, in_out);
node_tree_verify_groups(snode->nodetree);
snode_notify(C, snode);
}
return OPERATOR_FINISHED;
}
void NODE_OT_group_socket_remove(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Remove Group Socket";
ot->description = "Removed node group socket";
ot->idname = "NODE_OT_group_socket_remove";
/* api callbacks */
ot->exec = node_group_socket_remove_exec;
ot->poll = ED_operator_node_active;
/* flags */
ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "", 0, INT_MAX);
RNA_def_enum(ot->srna, "in_out", socket_in_out_items, SOCK_IN, "Socket Type", "Input or Output");
}
/* ***************** Move Group Socket Up operator ************* */
static int node_group_socket_move_up_exec(bContext *C, wmOperator *op)
{
SpaceNode *snode = CTX_wm_space_node(C);
int index= -1;
int in_out= -1;
bNodeTree *ngroup= snode->edittree;
bNodeSocket *sock, *prev;
ED_preview_kill_jobs(C);
if (RNA_property_is_set(op->ptr, "index"))
index = RNA_int_get(op->ptr, "index");
else
return OPERATOR_CANCELLED;
if (RNA_property_is_set(op->ptr, "in_out"))
in_out = RNA_enum_get(op->ptr, "in_out");
else
return OPERATOR_CANCELLED;
/* swap */
if (in_out==SOCK_IN) {
sock = (bNodeSocket*)BLI_findlink(&ngroup->inputs, index);
prev = sock->prev;
/* can't move up the first socket */
if (!prev)
return OPERATOR_CANCELLED;
BLI_remlink(&ngroup->inputs, sock);
BLI_insertlinkbefore(&ngroup->inputs, prev, sock);
}
else if (in_out==SOCK_OUT) {
sock = (bNodeSocket*)BLI_findlink(&ngroup->outputs, index);
prev = sock->prev;
/* can't move up the first socket */
if (!prev)
return OPERATOR_CANCELLED;
BLI_remlink(&ngroup->outputs, sock);
BLI_insertlinkbefore(&ngroup->outputs, prev, sock);
}
node_tree_verify_groups(snode->nodetree);
snode_notify(C, snode);
return OPERATOR_FINISHED;
}
void NODE_OT_group_socket_move_up(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Move Group Socket Up";
ot->description = "Move up node group socket";
ot->idname = "NODE_OT_group_socket_move_up";
/* api callbacks */
ot->exec = node_group_socket_move_up_exec;
ot->poll = ED_operator_node_active;
/* flags */
ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "", 0, INT_MAX);
RNA_def_enum(ot->srna, "in_out", socket_in_out_items, SOCK_IN, "Socket Type", "Input or Output");
}
/* ***************** Move Group Socket Up operator ************* */
static int node_group_socket_move_down_exec(bContext *C, wmOperator *op)
{
SpaceNode *snode = CTX_wm_space_node(C);
int index= -1;
int in_out= -1;
bNodeTree *ngroup= snode->edittree;
bNodeSocket *sock, *next;
ED_preview_kill_jobs(C);
if (RNA_property_is_set(op->ptr, "index"))
index = RNA_int_get(op->ptr, "index");
else
return OPERATOR_CANCELLED;
if (RNA_property_is_set(op->ptr, "in_out"))
in_out = RNA_enum_get(op->ptr, "in_out");
else
return OPERATOR_CANCELLED;
/* swap */
if (in_out==SOCK_IN) {
sock = (bNodeSocket*)BLI_findlink(&ngroup->inputs, index);
next = sock->next;
/* can't move down the last socket */
if (!next)
return OPERATOR_CANCELLED;
BLI_remlink(&ngroup->inputs, sock);
BLI_insertlinkafter(&ngroup->inputs, next, sock);
}
else if (in_out==SOCK_OUT) {
sock = (bNodeSocket*)BLI_findlink(&ngroup->outputs, index);
next = sock->next;
/* can't move down the last socket */
if (!next)
return OPERATOR_CANCELLED;
BLI_remlink(&ngroup->outputs, sock);
BLI_insertlinkafter(&ngroup->outputs, next, sock);
}
node_tree_verify_groups(snode->nodetree);
snode_notify(C, snode);
return OPERATOR_FINISHED;
}
void NODE_OT_group_socket_move_down(wmOperatorType *ot)
{
/* identifiers */
ot->name = "Move Group Socket Down";
ot->description = "Move down node group socket";
ot->idname = "NODE_OT_group_socket_move_down";
/* api callbacks */
ot->exec = node_group_socket_move_down_exec;
ot->poll = ED_operator_node_active;
/* flags */
ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "", 0, INT_MAX);
RNA_def_enum(ot->srna, "in_out", socket_in_out_items, SOCK_IN, "Socket Type", "Input or Output");
}
/* ******************** Ungroup operator ********************** */
static int node_group_ungroup_exec(bContext *C, wmOperator *op)
@@ -1433,6 +1673,33 @@ static int find_indicated_socket(SpaceNode *snode, bNode **nodep, bNodeSocket **
}
}
}
/* check group sockets
* NB: using ngroup->outputs as input sockets and vice versa here!
*/
if(in_out & SOCK_IN) {
for(sock= snode->edittree->outputs.first; sock; sock= sock->next) {
if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) {
if(BLI_in_rctf(&rect, sock->locx, sock->locy)) {
*nodep= NULL; /* NULL node pointer indicates group socket */
*sockp= sock;
return 1;
}
}
}
}
if(in_out & SOCK_OUT) {
for(sock= snode->edittree->inputs.first; sock; sock= sock->next) {
if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) {
if(BLI_in_rctf(&rect, sock->locx, sock->locy)) {
*nodep= NULL; /* NULL node pointer indicates group socket */
*sockp= sock;
return 1;
}
}
}
}
return 0;
}
@@ -1473,6 +1740,16 @@ static int node_socket_hilights(SpaceNode *snode, int in_out)
return redraw;
}
static int outside_group_rect(SpaceNode *snode)
{
bNode *gnode= node_tree_get_editgroup(snode->nodetree);
if (gnode) {
return (snode->mx < gnode->totr.xmin || snode->mx >= gnode->totr.xmax
|| snode->my < gnode->totr.ymin || snode->my >= gnode->totr.ymax);
}
return 0;
}
/* ****************** Add *********************** */
@@ -1701,7 +1978,7 @@ static int node_duplicate_exec(bContext *C, wmOperator *UNUSED(op))
last = ntree->nodes.last;
for(node= ntree->nodes.first; node; node= node->next) {
if(node->flag & SELECT) {
newnode = nodeCopyNode(ntree, node, 1);
newnode = nodeCopyNode(ntree, node);
/* deselect old node, select the copy instead */
node->flag &= ~(NODE_SELECT|NODE_ACTIVE);
@@ -1767,19 +2044,24 @@ static void node_remove_extra_links(SpaceNode *snode, bNodeSocket *tsock, bNodeL
break;
}
if(tlink) {
/* is there a free input socket with same type? */
for(sock= tlink->tonode->inputs.first; sock; sock= sock->next) {
if(sock->type==tlink->fromsock->type)
if(nodeCountSocketLinks(snode->edittree, sock) < sock->limit)
break;
/* try to move the existing link to the next available socket */
if (tlink->tonode) {
/* is there a free input socket with same type? */
for(sock= tlink->tonode->inputs.first; sock; sock= sock->next) {
if(sock->type==tlink->fromsock->type)
if(nodeCountSocketLinks(snode->edittree, sock) < sock->limit)
break;
}
if(sock) {
tlink->tosock= sock;
sock->flag &= ~SOCK_HIDDEN;
}
else {
nodeRemLink(snode->edittree, tlink);
}
}
if(sock) {
tlink->tosock= sock;
sock->flag &= ~SOCK_HIDDEN;
}
else {
else
nodeRemLink(snode->edittree, tlink);
}
}
}
}
@@ -1810,7 +2092,7 @@ static int node_link_modal(bContext *C, wmOperator *op, wmEvent *event)
if(in_out==SOCK_OUT) {
if(find_indicated_socket(snode, &tnode, &tsock, SOCK_IN)) {
if(nodeFindLink(snode->edittree, sock, tsock)==NULL) {
if(tnode!=node && link->tonode!=tnode && link->tosock!= tsock) {
if( link->tosock!= tsock && (!tnode || (tnode!=node && link->tonode!=tnode)) ) {
link->tonode= tnode;
link->tosock= tsock;
ntreeSolveOrder(snode->edittree); /* for interactive red line warning */
@@ -1826,7 +2108,7 @@ static int node_link_modal(bContext *C, wmOperator *op, wmEvent *event)
if(find_indicated_socket(snode, &tnode, &tsock, SOCK_OUT)) {
if(nodeFindLink(snode->edittree, sock, tsock)==NULL) {
if(nodeCountSocketLinks(snode->edittree, tsock) < tsock->limit) {
if(tnode!=node && link->fromnode!=tnode && link->fromsock!= tsock) {
if( link->fromsock!= tsock && (!tnode || (tnode!=node && link->fromnode!=tnode)) ) {
link->fromnode= tnode;
link->fromsock= tsock;
ntreeSolveOrder(snode->edittree); /* for interactive red line warning */
@@ -1847,19 +2129,28 @@ static int node_link_modal(bContext *C, wmOperator *op, wmEvent *event)
case LEFTMOUSE:
case RIGHTMOUSE:
case MIDDLEMOUSE:
/* remove link? */
if(link->tonode==NULL || link->fromnode==NULL) {
nodeRemLink(snode->edittree, link);
}
else {
if(link->tosock && link->fromsock) {
/* send changed events for original tonode and new */
if(link->tonode)
if(link->tonode)
NodeTagChanged(snode->edittree, link->tonode);
/* we might need to remove a link */
if(in_out==SOCK_OUT) node_remove_extra_links(snode, link->tosock, link);
if(in_out==SOCK_OUT)
node_remove_extra_links(snode, link->tosock, link);
}
else if (outside_group_rect(snode) && (link->tonode || link->fromnode)) {
/* automatically add new group socket */
if (link->tonode && link->tosock) {
link->fromsock = nodeAddGroupSocketCopy(snode->edittree, link->tosock, SOCK_IN);
link->fromnode = NULL;
}
else if (link->fromnode && link->fromsock) {
link->tosock = nodeAddGroupSocketCopy(snode->edittree, link->fromsock, SOCK_OUT);
link->tonode = NULL;
}
}
else
nodeRemLink(snode->edittree, link);
ntreeSolveOrder(snode->edittree);
node_tree_verify_groups(snode->nodetree);

View File

@@ -103,6 +103,10 @@ void NODE_OT_links_cut(struct wmOperatorType *ot);
void NODE_OT_group_make(struct wmOperatorType *ot);
void NODE_OT_group_ungroup(struct wmOperatorType *ot);
void NODE_OT_group_edit(struct wmOperatorType *ot);
void NODE_OT_group_socket_add(struct wmOperatorType *ot);
void NODE_OT_group_socket_remove(struct wmOperatorType *ot);
void NODE_OT_group_socket_move_up(struct wmOperatorType *ot);
void NODE_OT_group_socket_move_down(struct wmOperatorType *ot);
void NODE_OT_mute_toggle(struct wmOperatorType *ot);
void NODE_OT_hide_toggle(struct wmOperatorType *ot);

View File

@@ -74,6 +74,10 @@ void node_operatortypes(void)
WM_operatortype_append(NODE_OT_group_make);
WM_operatortype_append(NODE_OT_group_ungroup);
WM_operatortype_append(NODE_OT_group_edit);
WM_operatortype_append(NODE_OT_group_socket_add);
WM_operatortype_append(NODE_OT_group_socket_remove);
WM_operatortype_append(NODE_OT_group_socket_move_up);
WM_operatortype_append(NODE_OT_group_socket_move_down);
WM_operatortype_append(NODE_OT_link_viewer);

View File

@@ -288,7 +288,7 @@ static int node_select_linked_to_exec(bContext *C, wmOperator *UNUSED(op))
node->flag &= ~NODE_TEST;
for (link=snode->edittree->links.first; link; link=link->next) {
if (link->fromnode->flag & NODE_SELECT)
if (link->fromnode && link->tonode && (link->fromnode->flag & NODE_SELECT))
link->tonode->flag |= NODE_TEST;
}
@@ -328,7 +328,7 @@ static int node_select_linked_from_exec(bContext *C, wmOperator *UNUSED(op))
node->flag &= ~NODE_TEST;
for(link=snode->edittree->links.first; link; link=link->next) {
if(link->tonode->flag & NODE_SELECT)
if(link->fromnode && link->tonode && (link->tonode->flag & NODE_SELECT))
link->fromnode->flag |= NODE_TEST;
}

View File

@@ -70,21 +70,27 @@ typedef struct bNodeSocket {
char name[32];
bNodeStack ns; /* custom data for inputs, only UI writes in this */
short type, flag; /* type is copy from socket type struct */
short limit, stack_index; /* limit for dependency sort, stack_index for exec */
short intern; /* intern = tag for group nodes */
short stack_index_ext; /* for groups, to find the caller stack index */
int pad1;
short type, flag;
short limit; /* max. number of links */
/* stack data info (only during execution!) */
short stack_type; /* type of stack reference */
/* XXX only one of stack_ptr or stack_index is used (depending on stack_type).
* could store the index in the pointer with SET_INT_IN_POINTER (a bit ugly).
* (union won't work here, not supported by DNA)
*/
struct bNodeStack *stack_ptr; /* constant input value */
short stack_index; /* local stack index or external input number */
short pad;
float locx, locy;
/* internal data to retrieve relations and groups */
int own_index, to_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 *tosock; /* group-node sockets point to the internal group counterpart sockets, set after read file */
struct bNodeLink *link; /* a link pointer, set in nodeSolveOrder() */
} bNodeSocket;
/* sock->type */
@@ -99,11 +105,16 @@ typedef struct bNodeSocket {
#define SOCK_IN_USE 4
/* unavailable is for dynamic sockets */
#define SOCK_UNAVAIL 8
#
#
/* sock->stack_type */
#define SOCK_STACK_LOCAL 1 /* part of the local tree stack */
#define SOCK_STACK_EXTERN 2 /* use input stack pointer */
#define SOCK_STACK_CONST 3 /* use pointer to constant input value */
typedef struct bNodePreview {
unsigned char *rect;
short xsize, ysize;
int pad;
} bNodePreview;
@@ -185,7 +196,7 @@ typedef struct bNodeTree {
int flag, pad;
ListBase alltypes; /* type definitions */
struct bNodeType *owntype; /* for groups or dynamic trees, no read/write */
ListBase inputs, outputs; /* external sockets for group nodes */
int pad2[2];
@@ -208,6 +219,7 @@ typedef struct bNodeTree {
/* ntree->flag */
#define NTREE_DS_EXPAND 1 /* for animation editors */
#define NTREE_AUTO_EXPOSE 2 /* automatically make unhidden, unlinked group sockets external */
/* data structs, for node->storage */

View File

@@ -100,6 +100,8 @@ extern EnumPropertyItem property_unit_items[];
extern EnumPropertyItem viewport_shade_items[];
extern EnumPropertyItem node_socket_type_items[];
extern EnumPropertyItem node_blend_type_items[];
extern EnumPropertyItem node_math_items[];
extern EnumPropertyItem node_vec_math_items[];

View File

@@ -205,7 +205,7 @@ struct bNodeTree *rna_Main_nodetree_new(Main *bmain, const char *name, int type)
{
bNodeTree *tree = ntreeAddTree(name, type, TRUE);
ntreeMakeOwnType(tree);
// ntreeMakeGroupSockets(tree);
id_us_min(&tree->id);
return tree;

View File

@@ -47,6 +47,13 @@
#include "MEM_guardedalloc.h"
EnumPropertyItem node_socket_type_items[] = {
{SOCK_VALUE, "VALUE", 0, "Value", ""},
{SOCK_VECTOR, "VECTOR", 0, "Vector", ""},
{SOCK_RGBA, "RGBA", 0, "RGBA", ""},
{0, NULL, 0, NULL, NULL}};
EnumPropertyItem node_blend_type_items[] = {
{ 0, "MIX", 0, "Mix", ""},
{ 1, "ADD", 0, "Add", ""},
@@ -185,12 +192,22 @@ static char *rna_NodeSocket_path(PointerRNA *ptr)
bNode *node;
int socketindex;
/* group sockets */
socketindex = BLI_findindex(&ntree->inputs, sock);
if (socketindex != -1)
return BLI_sprintfN("inputs[%d]", socketindex);
socketindex = BLI_findindex(&ntree->outputs, sock);
if (socketindex != -1)
return BLI_sprintfN("outputs[%d]", socketindex);
/* node sockets */
if (!nodeFindNode(ntree, sock, &node, NULL)) return NULL;
socketindex = BLI_findindex(&node->inputs, sock);
if (socketindex != -1)
return BLI_sprintfN("nodes[\"%s\"].inputs[%d]", node->name, socketindex);
socketindex = BLI_findindex(&node->outputs, sock);
if (socketindex != -1)
return BLI_sprintfN("nodes[\"%s\"].outputs[%d]", node->name, socketindex);
@@ -354,6 +371,18 @@ static void rna_NodeSocket_update(Main *bmain, Scene *scene, PointerRNA *ptr)
node_update(bmain, scene, ntree, node);
}
static void rna_NodeGroupSocket_update(Main *bmain, Scene *scene, PointerRNA *ptr)
{
bNodeTree *ntree= (bNodeTree*)ptr->id.data;
bNodeSocket *sock= (bNodeSocket*)ptr->data;
bNode *node;
nodeVerifyGroup(ntree);
if (nodeFindNode(ntree, sock, &node, NULL))
node_update(bmain, scene, ntree, node);
}
static void rna_NodeSocket_defvalue_range(PointerRNA *ptr, float *min, float *max)
{
bNodeSocket *sock= (bNodeSocket*)ptr->data;
@@ -2473,12 +2502,6 @@ static void rna_def_node_socket(BlenderRNA *brna)
StructRNA *srna;
PropertyRNA *prop;
static EnumPropertyItem node_socket_type_items[] = {
{SOCK_VALUE, "VALUE", 0, "Value", ""},
{SOCK_VECTOR, "VECTOR", 0, "Vector", ""},
{SOCK_RGBA, "RGBA", 0, "RGBA", ""},
{0, NULL, 0, NULL, NULL}};
srna = RNA_def_struct(brna, "NodeSocket", NULL);
RNA_def_struct_ui_text(srna, "Node Socket", "Input or output socket of a node");
RNA_def_struct_refine_func(srna, "rna_NodeSocketType_refine");
@@ -2487,9 +2510,11 @@ static void rna_def_node_socket(BlenderRNA *brna)
RNA_def_struct_path_func(srna, "rna_NodeSocket_path");
prop = RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
/* XXX must be editable for group sockets. if necessary use a special rna definition for these */
// RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Name", "Socket name");
RNA_def_struct_name_property(srna, prop);
RNA_def_property_update(prop, NC_NODE|NA_EDITED, "rna_NodeGroupSocket_update");
/* can add back if there is any use in reading them */
#if 0
@@ -2671,29 +2696,22 @@ static void rna_def_nodetree(BlenderRNA *brna)
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_struct_type(prop, "GreasePencil");
RNA_def_property_ui_text(prop, "Grease Pencil Data", "Grease Pencil datablock");
/* these are too much like operators, better to have data level access
* ngroup = bpy.data.node_groups.new()
* ngroup.nodes.new(....) etc. */
#if 0
func= RNA_def_function(srna, "group_add", "nodeMakeGroupFromSelected");
RNA_def_function_ui_description(func, "Make a group from the active nodes.");
/* return */
parm= RNA_def_pointer(func, "group", "Node", "", "New group.");
RNA_def_function_return(func, parm);
func= RNA_def_function(srna, "ungroup", "nodeGroupUnGroup");
RNA_def_function_ui_description(func, "Ungroup node group");
parm= RNA_def_pointer(func, "group", "Node", "", "The group to ungroup.");
RNA_def_property_flag(parm, PROP_REQUIRED);
parm= RNA_def_int(func, "bool", 0, 0, 1, "Bool", "", 0, 1);
RNA_def_function_return(func, parm);
#endif
prop = RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
RNA_def_property_enum_items(prop, nodetree_type_items);
RNA_def_property_ui_text(prop, "Type", "Node Tree type");
/* group sockets */
prop = RNA_def_property(srna, "inputs", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "inputs", NULL);
RNA_def_property_struct_type(prop, "NodeSocket");
RNA_def_property_ui_text(prop, "Inputs", "");
prop = RNA_def_property(srna, "outputs", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, NULL, "outputs", NULL);
RNA_def_property_struct_type(prop, "NodeSocket");
RNA_def_property_ui_text(prop, "Outputs", "");
}
static void rna_def_composite_nodetree(BlenderRNA *brna)