Orange; daily noodler update commit.

- Adding execution code for Node trees. Was a bit a puzzle, since I want
  it to be multithreading by design. This now is solved by defining a
  stack per tree for all data that's being written into. This stack, which
  resides now in the NodeTree itself, then can be allocated per thread.

- For testing pleasure, I've added a 'mix node' and a 'show node', so
  you can already see it do something. :)

- reshuffled structure, to put things nice together, and have easier node
  adding. Current state is still WIP though, structure might change.
  For the record; new file node_shaders.c will contain all shader node
  definitions, apart from the drawing callbacks.

Next: I'm going to check on Andrea's work on icons now, since this is very
much needed for true shader/composit work.
Now back to release work...
This commit is contained in:
Ton Roosendaal
2005-12-21 14:24:51 +00:00
parent b33c68c906
commit ce52827a05
10 changed files with 657 additions and 287 deletions

View File

@@ -43,6 +43,8 @@ struct ListBase;
#define SOCK_OUT 2
/* ************** GENERIC API *************** */
void nodeFreeNode(struct bNodeTree *ntree, struct bNode *node);
void nodeFreeTree(struct bNodeTree *ntree);
@@ -55,8 +57,20 @@ struct bNodeSocket *nodeAddSocket(struct bNode *node, int type, int where, int l
struct bNodeLink *nodeFindLink(struct bNodeTree *ntree, struct bNodeSocket *from, struct bNodeSocket *to);
int nodeCountSocketLinks(struct bNodeTree *ntree, struct bNodeSocket *sock);
void nodeSolveOrder(struct bNodeTree *ntree);
void nodeSolveOrder(struct bNodeTree *ntree);
void nodeExecTree(struct bNodeTree *ntree);
/* ************** SHADER NODES *************** */
/* types are needed to restore callbacks */
#define SH_NODE_TEST 0
#define SH_NODE_RGB 1
#define SH_NODE_VALUE 2
#define SH_NODE_MIX_RGB 3
#define SH_NODE_SHOW_RGB 4
struct bNode *node_shader_add(struct bNodeTree *ntree, int type);
void node_shader_set_execfunc(struct bNode *node);
#endif

View File

@@ -44,6 +44,7 @@ source_files = ['intern/constraint.c',
'intern/property.c',
'intern/softbody.c',
'intern/node.c',
'intern/node_shaders.c',
'intern/texture.c']
blenkernel_env.Append (CPPPATH = ['.',

View File

@@ -35,12 +35,16 @@
#include "BKE_blender.h"
#include "BKE_node.h"
#include "BLI_arithb.h"
#include "BLI_blenlib.h"
#include "MEM_guardedalloc.h"
/* ************** Add stuff ********** */
/* not very important, but the stack solver likes to know a maximum */
#define MAX_SOCKET 64
bNode *nodeAddNode(struct bNodeTree *ntree, char *name)
{
bNode *node= MEM_callocN(sizeof(bNode), "new node");
@@ -185,23 +189,24 @@ int nodeCountSocketLinks(bNodeTree *ntree, bNodeSocket *sock)
return tot;
}
/* ************** solve stuff *********** */
/* ************** dependency stuff *********** */
/* node is guaranteed to be not checked before */
static int node_recurs_check(bNode *node, bNode ***nsort, int level)
{
bNode *fromnode;
bNodeSocket *sock;
bNodeLink *link;
int has_inputlinks= 0;
node->done= 1;
level++;
for(sock= node->inputs.first; sock; sock= sock->next) {
for(link= sock->links.first; link; link= link->next) {
if(sock->link) {
has_inputlinks= 1;
if(link->fromnode->done==0) {
link->fromnode->level= node_recurs_check(link->fromnode, nsort, level);
fromnode= sock->link->fromnode;
if(fromnode->done==0) {
fromnode->level= node_recurs_check(fromnode, nsort, level);
}
}
}
@@ -222,20 +227,19 @@ void nodeSolveOrder(bNodeTree *ntree)
bNodeLink *link;
int a, totnode=0;
/* move all links into the input sockets, to find dependencies */
/* set links pointers the input sockets, to find dependencies */
/* first clear data */
for(node= ntree->nodes.first; node; node= node->next) {
node->done= 0;
totnode++;
for(sock= node->inputs.first; sock; sock= sock->next)
sock->links.first= sock->links.last= NULL;
sock->link= NULL;
}
if(totnode==0)
return;
while((link= ntree->links.first)) {
BLI_remlink(&ntree->links, link);
BLI_addtail(&link->tosock->links, link);
for(link= ntree->links.first; link; link= link->next) {
link->tosock->link= link;
}
nsort= nodesort= MEM_callocN(totnode*sizeof(void *), "sorted node array");
@@ -262,13 +266,78 @@ void nodeSolveOrder(bNodeTree *ntree)
MEM_freeN(nodesort);
/* move links back */
}
/* ******************* executing ************* */
void nodeBeginExecTree(bNodeTree *ntree)
{
bNode *node;
bNodeSocket *sock;
int index= 0;
if((ntree->init & NTREE_EXEC_SET)==0) {
for(node= ntree->nodes.first; node; node= node->next) {
if(ntree->type==NTREE_SHADER)
node_shader_set_execfunc(node);
}
ntree->init |= NTREE_EXEC_SET;
}
/* create indices for stack */
for(node= ntree->nodes.first; node; node= node->next) {
for(sock= node->inputs.first; sock; sock= sock->next) {
while((link= sock->links.first)) {
BLI_remlink(&sock->links, link);
BLI_addtail(&ntree->links, link);
}
for(sock= node->outputs.first; sock; sock= sock->next) {
sock->stack_index= index++;
}
}
if(index) {
ntree->stack= MEM_callocN(index*sizeof(bNodeStack), "node stack");
}
}
void nodeEndExecTree(bNodeTree *ntree)
{
if(ntree->stack) {
MEM_freeN(ntree->stack);
ntree->stack= NULL;
}
}
static void node_get_stack(bNode *node, bNodeStack *stack, bNodeStack **spp)
{
static bNodeStack empty= {{1.0f, 1.0f, 1.0f, 1.0f}, NULL};
bNodeSocket *sock;
/* build pointer stack */
for(sock= node->inputs.first; sock; sock= sock->next) {
if(sock->link)
*(spp++)= stack + sock->link->fromsock->stack_index;
else
*(spp++)= ∅ /* input is not written into */
}
for(sock= node->outputs.first; sock; sock= sock->next) {
*(spp++)= stack + sock->stack_index;
}
}
/* nodes are presorted, so exec is in order of list */
void nodeExecTree(bNodeTree *ntree)
{
bNode *node;
bNodeStack *ns[MAX_SOCKET]; /* arbitrary... watch this */
nodeBeginExecTree(ntree);
for(node= ntree->nodes.first; node; node= node->next) {
if(node->execfunc) {
node_get_stack(node, ntree->stack, ns);
node->execfunc(node, ns);
}
}
nodeEndExecTree(ntree);
}

View File

@@ -0,0 +1,226 @@
/**
* $Id$
*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* The Original Code is Copyright (C) 2005 Blender Foundation.
* All rights reserved.
*
* The Original Code is: all of this file.
*
* Contributor(s): none yet.
*
* ***** END GPL LICENSE BLOCK *****
*/
#include <stdlib.h>
#include "DNA_ID.h"
#include "DNA_node_types.h"
#include "BKE_blender.h"
#include "BKE_node.h"
#include "BKE_utildefines.h"
#include "BLI_arithb.h"
#include "BLI_blenlib.h"
#include "MEM_guardedalloc.h"
/* **************** testnode ************ */
static void blendcolor(float *col1, float *col2, float *output, float fac)
{
output[0]= (1.0f-fac)*col1[0] + (fac)*col2[0];
output[1]= (1.0f-fac)*col1[1] + (fac)*col2[1];
output[2]= (1.0f-fac)*col1[2] + (fac)*col2[2];
}
static void node_shader_exec_test(bNode *node, bNodeStack **ns)
{
blendcolor(ns[0]->vec, ns[1]->vec, ns[2]->vec, 0.5);
// printvecf(node->name, ns[2]->vec);
}
static bNode *node_shader_add_test(bNodeTree *ntree)
{
bNode *node= nodeAddNode(ntree, "TestNode");
static int tot= 0;
sprintf(node->name, "Testnode%d", tot++);
node->type= SH_NODE_TEST;
node->width= 80.0f;
/* add sockets */
nodeAddSocket(node, SOCK_RGBA, SOCK_IN, 1, "Col");
nodeAddSocket(node, SOCK_RGBA, SOCK_IN, 1, "Spec");
nodeAddSocket(node, SOCK_RGBA, SOCK_OUT, 0xFFF, "Diffuse");
return node;
}
/* **************** value node ************ */
static void node_shader_exec_value(bNode *node, bNodeStack **ns)
{
/* no input node! */
ns[0]->vec[0]= node->ns.vec[0];
// printf("%s %f\n", node->name, ns[0]->vec[0]);
}
static bNode *node_shader_add_value(bNodeTree *ntree)
{
bNode *node= nodeAddNode(ntree, "Value");
node->type= SH_NODE_VALUE;
node->width= 80.0f;
node->prv_h= 20.0f;
/* add sockets */
nodeAddSocket(node, SOCK_VALUE, SOCK_OUT, 0xFFF, "");
return node;
}
/* **************** rgba node ************ */
static void node_shader_exec_rgb(bNode *node, bNodeStack **ns)
{
/* no input node! */
QUATCOPY(ns[0]->vec, node->ns.vec);
// printvecf(node->name, ns[0]->vec);
}
static bNode *node_shader_add_rgb(bNodeTree *ntree)
{
bNode *node= nodeAddNode(ntree, "RGB");
node->type= SH_NODE_RGB;
node->width= 100.0f;
node->prv_h= 100.0f;
node->ns.vec[3]= 1.0f; /* alpha init */
/* add sockets */
nodeAddSocket(node, SOCK_RGBA, SOCK_OUT, 0xFFF, "");
return node;
}
/* **************** mix rgba node ************ */
static void node_shader_exec_mix_rgb(bNode *node, bNodeStack **ns)
{
/* stack order is fac, col1, col2, out */
blendcolor(ns[1]->vec, ns[2]->vec, ns[3]->vec, ns[0]->vec[0]);
}
static bNode *node_shader_add_mix_rgb(bNodeTree *ntree)
{
bNode *node= nodeAddNode(ntree, "Mix RGB");
node->type= SH_NODE_MIX_RGB;
node->width= 80.0f;
node->prv_h= 0.0f;
/* add sockets */
nodeAddSocket(node, SOCK_VALUE, SOCK_IN, 1, "Fac");
nodeAddSocket(node, SOCK_RGBA, SOCK_IN, 1, "Color1");
nodeAddSocket(node, SOCK_RGBA, SOCK_IN, 1, "Color2");
nodeAddSocket(node, SOCK_RGBA, SOCK_OUT, 0xFFF, "Color");
return node;
}
/* **************** show rgba node ************ */
static void node_shader_exec_show_rgb(bNode *node, bNodeStack **ns)
{
/* only input node! */
QUATCOPY(node->ns.vec, ns[0]->vec);
// printvecf(node->name, ns[0]->vec);
}
static bNode *node_shader_add_show_rgb(bNodeTree *ntree)
{
bNode *node= nodeAddNode(ntree, "Show RGB");
node->type= SH_NODE_SHOW_RGB;
node->width= 80.0f;
node->prv_h= 0.0f;
node->ns.vec[3]= 1.0f; /* alpha init */
/* add sockets */
nodeAddSocket(node, SOCK_RGBA, SOCK_IN, 1, "");
return node;
}
/* **************** API for add ************** */
bNode *node_shader_add(bNodeTree *ntree, int type)
{
bNode *node= NULL;
switch(type) {
case SH_NODE_TEST:
node= node_shader_add_test(ntree);
break;
case SH_NODE_VALUE:
node= node_shader_add_value(ntree);
break;
case SH_NODE_RGB:
node= node_shader_add_rgb(ntree);
break;
case SH_NODE_SHOW_RGB:
node= node_shader_add_show_rgb(ntree);
break;
case SH_NODE_MIX_RGB:
node= node_shader_add_mix_rgb(ntree);
break;
}
return node;
}
/* ******************* set the callbacks, called from UI, loader ***** */
void node_shader_set_execfunc(bNode *node)
{
switch(node->type) {
case SH_NODE_TEST:
node->execfunc= node_shader_exec_test;
break;
case SH_NODE_VALUE:
node->execfunc= node_shader_exec_value;
break;
case SH_NODE_RGB:
node->execfunc= node_shader_exec_rgb;
break;
case SH_NODE_SHOW_RGB:
node->execfunc= node_shader_exec_show_rgb;
break;
case SH_NODE_MIX_RGB:
node->execfunc= node_shader_exec_mix_rgb;
break;
}
}

View File

@@ -77,6 +77,7 @@ struct ScrArea;
#define UI_BLOCK_ENTER_OK 32
#define UI_BLOCK_NOSHADOW 64
#define UI_BLOCK_FRONTBUFFER 128
#define UI_BLOCK_NO_HILITE 256
/* block->flag bits 12-15 are identical to but->flag bits */

View File

@@ -30,10 +30,27 @@
#ifndef BSE_NODE_H
#define BSE_NODE_H
#define NODE_DY 20
#define NODE_DYS 10
#define NODE_SOCK 5
struct SpaceNode;
struct bNode;
/* ************* button events *********** */
#define B_NODE_EXEC 1
/* ************* API for editnode.c *********** */
void node_deselectall(struct SpaceNode *snode, int swap);
void node_transform_ext(int mode, int unused);
/* ************* Shader nodes ***************** */
void node_shader_set_drawfunc(struct bNode *node);
#endif

View File

@@ -35,6 +35,7 @@
struct ID;
struct SpaceNode;
struct bNodeLink;
#define NODE_MAXSTR 32
@@ -42,10 +43,10 @@ typedef struct bNodeSocket {
struct bNodeSocket *next, *prev;
char name[32];
short type, flag, limit, pad;
short type, flag, limit, stack_index;
float locx, locy;
ListBase links; /* now only used temporal for sorting */
struct bNodeLink *link; /* input link to parent, max one! */
} bNodeSocket;
@@ -57,6 +58,10 @@ typedef struct bNodeSocket {
/* sock->flag, first bit is select */
typedef struct bNodeStack {
float vec[4];
void *data;
} bNodeStack;
/* limit data in bNode to what we want to see saved? */
typedef struct bNode {
@@ -67,16 +72,15 @@ typedef struct bNode {
ListBase inputs, outputs;
struct ID *id; /* optional link to libdata */
void *data; /* custom data */
float vec[4]; /* builtin custom data */
bNodeStack ns; /* builtin data, for UI to write into */
float locx, locy; /* root offset for drawing */
float width, prv_h;
rctf tot; /* entire boundbox */
rctf prv; /* optional preview area */
int (*drawfunc)(struct SpaceNode *, struct bNode *);
int (*execfunc)(struct bNode *);
void (*drawfunc)(struct SpaceNode *, struct bNode *);
void (*execfunc)(struct bNode *, struct bNodeStack **);
} bNode;
@@ -96,9 +100,20 @@ typedef struct bNodeTree {
ListBase nodes, links;
ListBase inputs, outputs; /* default inputs and outputs, for solving tree */
bNodeStack *stack;
int type, init;
} bNodeTree;
/* ntree->type, index */
#define NTREE_SHADER 0
#define NTREE_COMPOSIT 1
/* ntree->init, flag */
#define NTREE_EXEC_SET 1
#define NTREE_DRAW_SET 2
#endif

View File

@@ -42,6 +42,7 @@
#include "DNA_scene_types.h"
#include "DNA_space_types.h"
#include "DNA_screen_types.h"
#include "DNA_userdef_types.h"
#include "BKE_global.h"
#include "BKE_object.h"
@@ -51,17 +52,117 @@
#include "BIF_gl.h"
#include "BIF_interface.h"
#include "BIF_language.h"
#include "BIF_mywindow.h"
#include "BIF_resources.h"
#include "BIF_screen.h"
#include "BSE_drawipo.h"
#include "BSE_node.h"
#include "BSE_view.h"
#include "BMF_Api.h"
#include "blendef.h"
#include "interface.h" /* urm... for rasterpos_safe, roundbox */
#include "MEM_guardedalloc.h"
/* ************** Draw callbacks *********** */
static void node_shader_draw_value(SpaceNode *snode, bNode *node)
{
if(snode->block) {
uiBut *bt;
bt= uiDefButF(snode->block, NUM, B_NODE_EXEC, "",
node->prv.xmin, node->prv.ymin, node->prv.xmax-node->prv.xmin, node->prv.ymax-node->prv.ymin,
node->ns.vec, 0.0f, 1.0f, 100, 2, "");
}
}
static void node_shader_draw_rgb(SpaceNode *snode, bNode *node)
{
if(snode->block) {
/* enforce square box drawing */
uiBlockSetEmboss(snode->block, UI_EMBOSSP);
uiDefButF(snode->block, HSVCUBE, B_NODE_EXEC, "",
node->prv.xmin, node->prv.ymin, node->prv.xmax-node->prv.xmin, 10.0f,
node->ns.vec, 0.0f, 1.0f, 3, 0, "");
uiDefButF(snode->block, HSVCUBE, B_NODE_EXEC, "",
node->prv.xmin, node->prv.ymin+14.0f, node->prv.xmax-node->prv.xmin, node->prv.ymax-node->prv.ymin-14.0f,
node->ns.vec, 0.0f, 1.0f, 2, 0, "");
uiDefButF(snode->block, COL, B_NOP, "",
node->prv.xmin, node->prv.ymax+10.0f, node->prv.xmax-node->prv.xmin, 15.0f,
node->ns.vec, 0.0, 0.0, -1, 0, "");
/* the -1 above prevents col button to popup a color picker */
uiBlockSetEmboss(snode->block, UI_EMBOSS);
}
}
static void node_shader_draw_show_rgb(SpaceNode *snode, bNode *node)
{
if(snode->block) {
/* enforce square box drawing */
uiBlockSetEmboss(snode->block, UI_EMBOSSP);
uiDefButF(snode->block, COL, B_NOP, "",
node->prv.xmin, node->prv.ymin-NODE_DY, node->prv.xmax-node->prv.xmin, NODE_DY,
node->ns.vec, 0.0f, 0.0f, -1, 0, "");
/* the -1 above prevents col button to popup a color picker */
uiBlockSetEmboss(snode->block, UI_EMBOSS);
}
}
/* exported to editnode.c */
void node_shader_set_drawfunc(bNode *node)
{
switch(node->type) {
case SH_NODE_TEST:
node->drawfunc= NULL;
break;
case SH_NODE_VALUE:
node->drawfunc= node_shader_draw_value;
break;
case SH_NODE_RGB:
node->drawfunc= node_shader_draw_rgb;
break;
case SH_NODE_SHOW_RGB:
node->drawfunc= node_shader_draw_show_rgb;
break;
case SH_NODE_MIX_RGB:
node->drawfunc= NULL;
break;
}
}
/* ******* init draw callbacks for all tree types ************* */
static void ntree_init_callbacks(bNodeTree *ntree)
{
bNode *node;
for(node= ntree->nodes.first; node; node= node->next) {
if(ntree->type==NTREE_SHADER)
node_shader_set_drawfunc(node);
}
ntree->init |= NTREE_DRAW_SET;
}
/* ************** Generic drawing ************** */
static void draw_nodespace_grid(SpaceNode *snode)
{
// float fac, step= 20.0f;
@@ -80,10 +181,138 @@ static void get_nodetree(SpaceNode *snode)
/* note: once proper coded, remove free from freespacelist() */
if(snode->nodetree==NULL) {
snode->nodetree= MEM_callocN(sizeof(bNodeTree), "new node tree");
}
}
static void nodeshadow(rctf *rct, int select)
{
int a;
char alpha= 2;
uiSetRoundBox(15);
glEnable(GL_BLEND);
if(select) a= 10; else a=7;
for(; a>0; a-=1) {
/* alpha ranges from 2 to 20 or so */
glColor4ub(0, 0, 0, alpha);
alpha+= 2;
gl_round_box(GL_POLYGON, rct->xmin - a, rct->ymin - a, rct->xmax + a, rct->ymax-10.0f + a, 8.0f+a);
}
/* outline emphasis */
glEnable( GL_LINE_SMOOTH );
glColor4ub(0, 0, 0, 100);
gl_round_box(GL_LINE_LOOP, rct->xmin-0.5f, rct->ymin-0.5f, rct->xmax+0.5f, rct->ymax+0.5f, 8.0f);
glDisable( GL_LINE_SMOOTH );
glDisable(GL_BLEND);
}
/* nice AA filled circle */
static void socket_circle_draw(float x, float y, float size, int type, int select)
{
/* 16 values of sin function */
static float si[16] = {
0.00000000, 0.39435585,0.72479278,0.93775213,
0.99871650,0.89780453,0.65137248,0.29936312,
-0.10116832,-0.48530196,-0.79077573,-0.96807711,
-0.98846832,-0.84864425,-0.57126821,-0.20129852
};
/* 16 values of cos function */
static float co[16] ={
1.00000000,0.91895781,0.68896691,0.34730525,
-0.05064916,-0.44039415,-0.75875812,-0.95413925,
-0.99486932,-0.87434661,-0.61210598,-0.25065253,
0.15142777,0.52896401,0.82076344,0.97952994,
};
int a;
if(select==0) {
if(type==SOCK_VALUE)
glColor3ub(160, 160, 160);
else if(type==SOCK_VECTOR)
glColor3ub(100, 100, 200);
else if(type==SOCK_RGBA)
glColor3ub(200, 200, 40);
else
glColor3ub(100, 200, 100);
}
else {
if(type==SOCK_VALUE)
glColor3ub(200, 200, 200);
else if(type==SOCK_VECTOR)
glColor3ub(140, 140, 240);
else if(type==SOCK_RGBA)
glColor3ub(240, 240, 100);
else
glColor3ub(140, 240, 140);
}
glBegin(GL_POLYGON);
for(a=0; a<16; a++)
glVertex2f(x+size*si[a], y+size*co[a]);
glEnd();
glColor4ub(0, 0, 0, 150);
glEnable(GL_BLEND);
glEnable( GL_LINE_SMOOTH );
glBegin(GL_LINE_LOOP);
for(a=0; a<16; a++)
glVertex2f(x+size*si[a], y+size*co[a]);
glEnd();
glDisable( GL_LINE_SMOOTH );
glDisable(GL_BLEND);
}
static int node_basis_draw(SpaceNode *snode, bNode *node)
{
bNodeSocket *sock;
rctf *rct= &node->tot;
float slen;
int trans= (U.transopts & USER_TR_BUTTONS);
nodeshadow(rct, node->flag & SELECT);
BIF_ThemeColorShade(TH_HEADER, 0);
uiSetRoundBox(3);
uiRoundBox(rct->xmin, rct->ymax-NODE_DY, rct->xmax, rct->ymax, 8);
BIF_ThemeColorShade(TH_HEADER, 20);
uiSetRoundBox(12);
uiRoundBox(rct->xmin, rct->ymin, rct->xmax, rct->ymax-NODE_DY, 8);
ui_rasterpos_safe(rct->xmin+4.0f, rct->ymax-NODE_DY+5.0f, snode->aspect);
if(node->flag & SELECT)
BIF_ThemeColor(TH_TEXT_HI);
else
BIF_ThemeColor(TH_TEXT);
BIF_DrawString(snode->curfont, node->name, trans);
for(sock= node->inputs.first; sock; sock= sock->next) {
socket_circle_draw(sock->locx, sock->locy, NODE_SOCK, sock->type, sock->flag & SELECT);
BIF_ThemeColor(TH_TEXT);
ui_rasterpos_safe(sock->locx+8.0f, sock->locy-5.0f, snode->aspect);
BIF_DrawString(snode->curfont, sock->name, trans);
}
for(sock= node->outputs.first; sock; sock= sock->next) {
socket_circle_draw(sock->locx, sock->locy, NODE_SOCK, sock->type, sock->flag & SELECT);
BIF_ThemeColor(TH_TEXT);
slen= snode->aspect*BIF_GetStringWidth(snode->curfont, sock->name, trans);
ui_rasterpos_safe(sock->locx-8.0f-slen, sock->locy-5.0f, snode->aspect);
BIF_DrawString(snode->curfont, sock->name, trans);
}
return 0;
}
static void node_draw_link(SpaceNode *snode, bNodeLink *link)
{
float vec[4][3];
@@ -103,7 +332,7 @@ static void node_draw_link(SpaceNode *snode, bNodeLink *link)
}
else {
/* check cyclic */
if(link->fromnode->level >= link->tonode->level)
if(link->fromnode->level >= link->tonode->level && link->tonode->level!=0xFFF)
BIF_ThemeColor(TH_WIRE);
else
BIF_ThemeColor(TH_REDALERT);
@@ -185,11 +414,15 @@ void drawnodespace(ScrArea *sa, void *spacedata)
draw_nodespace_grid(snode);
/* nodes */
get_nodetree(snode);
get_nodetree(snode); /* editor context */
if(snode->nodetree) {
bNode *node;
bNodeLink *link;
if((snode->nodetree->init & NTREE_DRAW_SET)==0)
ntree_init_callbacks(snode->nodetree);
/* node lines */
glEnable(GL_BLEND);
glEnable( GL_LINE_SMOOTH );
@@ -200,20 +433,27 @@ void drawnodespace(ScrArea *sa, void *spacedata)
/* not selected */
snode->block= uiNewBlock(&sa->uiblocks, "node buttons1", UI_EMBOSS, UI_HELV, sa->win);
uiBlockSetFlag(snode->block, UI_BLOCK_NO_HILITE);
for(node= snode->nodetree->nodes.first; node; node= node->next)
if(!(node->flag & SELECT))
node->drawfunc(snode, node);
for(node= snode->nodetree->nodes.first; node; node= node->next) {
if(!(node->flag & SELECT)) {
node_basis_draw(snode, node);
if(node->drawfunc) node->drawfunc(snode, node);
}
}
uiDrawBlock(snode->block);
/* selected */
snode->block= uiNewBlock(&sa->uiblocks, "node buttons2", UI_EMBOSS, UI_HELV, sa->win);
uiBlockSetFlag(snode->block, UI_BLOCK_NO_HILITE);
for(node= snode->nodetree->nodes.first; node; node= node->next)
if(node->flag & SELECT)
node->drawfunc(snode, node);
for(node= snode->nodetree->nodes.first; node; node= node->next) {
if(node->flag & SELECT) {
node_basis_draw(snode, node);
if(node->drawfunc) node->drawfunc(snode, node);
}
}
uiDrawBlock(snode->block);
}

View File

@@ -42,7 +42,7 @@
#include "DNA_space_types.h"
#include "DNA_screen_types.h"
#include "DNA_scene_types.h"
#include "DNA_userdef_types.h"
#include "BKE_global.h"
#include "BKE_library.h"
@@ -54,7 +54,7 @@
#include "BIF_editview.h"
#include "BIF_gl.h"
#include "BIF_interface.h"
#include "BIF_language.h"
#include "BIF_mywindow.h"
#include "BIF_resources.h"
#include "BIF_space.h"
@@ -72,143 +72,9 @@
#include "BDR_editobject.h"
#include "blendef.h"
#include "interface.h" /* urm... for rasterpos_safe, roundbox */
#include "PIL_time.h"
#include "mydevice.h"
#define NODE_DY 20
#define NODE_DYS 10
#define NODE_SOCK 5
/* **************** NODE draw callbacks ************* */
static void nodeshadow(rctf *rct, int select)
{
int a;
char alpha= 2;
uiSetRoundBox(15);
glEnable(GL_BLEND);
if(select) a= 10; else a=7;
for(; a>0; a-=1) {
/* alpha ranges from 2 to 20 or so */
glColor4ub(0, 0, 0, alpha);
alpha+= 2;
gl_round_box(GL_POLYGON, rct->xmin - a, rct->ymin - a, rct->xmax + a, rct->ymax-10.0f + a, 8.0f+a);
}
/* outline emphasis */
glEnable( GL_LINE_SMOOTH );
glColor4ub(0, 0, 0, 100);
gl_round_box(GL_LINE_LOOP, rct->xmin-0.5f, rct->ymin-0.5f, rct->xmax+0.5f, rct->ymax+0.5f, 8.0f);
glDisable( GL_LINE_SMOOTH );
glDisable(GL_BLEND);
}
/* nice AA filled circle */
static void socket_circle_draw(float x, float y, float size, int type, int select)
{
/* 16 values of sin function */
static float si[16] = {
0.00000000, 0.39435585,0.72479278,0.93775213,
0.99871650,0.89780453,0.65137248,0.29936312,
-0.10116832,-0.48530196,-0.79077573,-0.96807711,
-0.98846832,-0.84864425,-0.57126821,-0.20129852
};
/* 16 values of cos function */
static float co[16] ={
1.00000000,0.91895781,0.68896691,0.34730525,
-0.05064916,-0.44039415,-0.75875812,-0.95413925,
-0.99486932,-0.87434661,-0.61210598,-0.25065253,
0.15142777,0.52896401,0.82076344,0.97952994,
};
int a;
if(select==0) {
if(type==SOCK_VALUE)
glColor3ub(160, 160, 160);
else if(type==SOCK_VECTOR)
glColor3ub(100, 100, 200);
else if(type==SOCK_RGBA)
glColor3ub(200, 200, 40);
else
glColor3ub(100, 200, 100);
}
else {
if(type==SOCK_VALUE)
glColor3ub(200, 200, 200);
else if(type==SOCK_VECTOR)
glColor3ub(140, 140, 240);
else if(type==SOCK_RGBA)
glColor3ub(240, 240, 100);
else
glColor3ub(140, 240, 140);
}
glBegin(GL_POLYGON);
for(a=0; a<16; a++)
glVertex2f(x+size*si[a], y+size*co[a]);
glEnd();
glColor4ub(0, 0, 0, 150);
glEnable(GL_BLEND);
glEnable( GL_LINE_SMOOTH );
glBegin(GL_LINE_LOOP);
for(a=0; a<16; a++)
glVertex2f(x+size*si[a], y+size*co[a]);
glEnd();
glDisable( GL_LINE_SMOOTH );
glDisable(GL_BLEND);
}
static int node_basis_draw(SpaceNode *snode, bNode *node)
{
bNodeSocket *sock;
rctf *rct= &node->tot;
float slen;
int trans= (U.transopts & USER_TR_BUTTONS);
nodeshadow(rct, node->flag & SELECT);
BIF_ThemeColorShade(TH_HEADER, 0);
uiSetRoundBox(3);
uiRoundBox(rct->xmin, rct->ymax-NODE_DY, rct->xmax, rct->ymax, 8);
BIF_ThemeColorShade(TH_HEADER, 20);
uiSetRoundBox(12);
uiRoundBox(rct->xmin, rct->ymin, rct->xmax, rct->ymax-NODE_DY, 8);
ui_rasterpos_safe(rct->xmin+4.0f, rct->ymax-NODE_DY+5.0f, snode->aspect);
if(node->flag & SELECT)
BIF_ThemeColor(TH_TEXT_HI);
else
BIF_ThemeColor(TH_TEXT);
BIF_DrawString(snode->curfont, node->name, trans);
for(sock= node->inputs.first; sock; sock= sock->next) {
socket_circle_draw(sock->locx, sock->locy, NODE_SOCK, sock->type, sock->flag & SELECT);
BIF_ThemeColor(TH_TEXT);
ui_rasterpos_safe(sock->locx+8.0f, sock->locy-5.0f, snode->aspect);
BIF_DrawString(snode->curfont, sock->name, trans);
}
for(sock= node->outputs.first; sock; sock= sock->next) {
socket_circle_draw(sock->locx, sock->locy, NODE_SOCK, sock->type, sock->flag & SELECT);
BIF_ThemeColor(TH_TEXT);
slen= snode->aspect*BIF_GetStringWidth(snode->curfont, sock->name, trans);
ui_rasterpos_safe(sock->locx-8.0f-slen, sock->locy-5.0f, snode->aspect);
BIF_DrawString(snode->curfont, sock->name, trans);
}
return 0;
}
/* ************************** Node generic ************** */
@@ -532,135 +398,42 @@ void node_border_select(SpaceNode *snode)
/* ****************** Add *********************** */
/* keep adding nodes outside of space context? to kernel maybe? */
bNode *add_test_node(bNodeTree *ntree, float locx, float locy)
/* can be called from menus too */
void node_add_shader_node(SpaceNode *snode, int type, float locx, float locy)
{
bNode *node= nodeAddNode(ntree, "TestNode");
static int tot= 0;
bNode *node= NULL;
sprintf(node->name, "Testnode%d", tot++);
node_deselectall(snode, 0);
node->locx= locx;
node->locy= locy;
node->width= 80.0f;
node->drawfunc= node_basis_draw;
node= node_shader_add(snode->nodetree, type);
/* add fake sockets */
nodeAddSocket(node, SOCK_RGBA, SOCK_IN, 1, "Col");
nodeAddSocket(node, SOCK_RGBA, SOCK_IN, 1, "Spec");
nodeAddSocket(node, SOCK_RGBA, SOCK_OUT, 0xFFF, "Diffuse");
/* always end with calculating size etc */
node_update(ntree, node);
return node;
}
static int value_drawfunc(SpaceNode *snode, bNode *node)
{
node_basis_draw(snode, node);
if(snode->block) {
uiBut *bt;
/* generics */
if(node) {
node->locx= locx;
node->locy= locy;
node->flag |= SELECT;
bt= uiDefButF(snode->block, NUM, B_NOP, "",
node->prv.xmin, node->prv.ymin, node->prv.xmax-node->prv.xmin, node->prv.ymax-node->prv.ymin,
node->vec, 0.0f, 1.0f, 100, 2, "");
node_shader_set_execfunc(node);
node_shader_set_drawfunc(node);
/* update calculates all coords for usage */
node_update(snode->nodetree, node);
}
return 1;
}
static int hsv_drawfunc(SpaceNode *snode, bNode *node)
{
node_basis_draw(snode, node);
if(snode->block) {
uiBut *bt;
uiBlockSetEmboss(snode->block, UI_EMBOSSP);
bt= uiDefButF(snode->block, HSVCUBE, B_NOP, "",
node->prv.xmin, node->prv.ymin, node->prv.xmax-node->prv.xmin, 10.0f,
node->vec, 0.0f, 1.0f, 3, 0, "");
bt= uiDefButF(snode->block, HSVCUBE, B_NOP, "",
node->prv.xmin, node->prv.ymin+14.0f, node->prv.xmax-node->prv.xmin, node->prv.ymax-node->prv.ymin-14.0f,
node->vec, 0.0f, 1.0f, 2, 0, "");
uiDefButF(snode->block, COL, B_NOP, "",
node->prv.xmin, node->prv.ymax+10.0f, node->prv.xmax-node->prv.xmin, 15.0f,
node->vec, 0.0, 0.0, -1, 0, "");
}
return 1;
}
bNode *add_value_node(bNodeTree *ntree, float locx, float locy)
{
bNode *node= nodeAddNode(ntree, "Value");
node->locx= locx;
node->locy= locy;
node->width= 80.0f;
node->prv_h= 20.0f;
node->drawfunc= value_drawfunc;
/* add sockets */
nodeAddSocket(node, SOCK_VALUE, SOCK_OUT, 0xFFF, "");
/* always end with calculating size etc */
node_update(ntree, node);
return node;
}
bNode *add_hsv_node(bNodeTree *ntree, float locx, float locy)
{
bNode *node= nodeAddNode(ntree, "RGB");
node->locx= locx;
node->locy= locy;
node->width= 100.0f;
node->prv_h= 100.0f;
node->vec[3]= 1.0f; /* alpha init */
node->drawfunc= hsv_drawfunc;
/* add sockets */
nodeAddSocket(node, SOCK_RGBA, SOCK_OUT, 0xFFF, "");
/* always end with calculating size etc */
node_update(ntree, node);
return node;
}
/* editor context */
/* hotkey context */
static void node_add_menu(SpaceNode *snode)
{
float locx, locy;
short event, mval[2];
event= pupmenu("Add Node%t|Testnode%x1|Value %x2|Color %x3");
if(event<1) return;
/* shader menu */
event= pupmenu("Add Node%t|Testnode%x0|Value %x2|Color %x1|Mix Color %x3|Show Color %x4");
if(event<0) return;
getmouseco_areawin(mval);
areamouseco_to_ipoco(G.v2d, mval, &locx, &locy);
node_deselectall(snode, 0);
if(event==1)
add_test_node(snode->nodetree, locx, locy);
else if(event==2)
add_value_node(snode->nodetree, locx, locy);
else if(event==3)
add_hsv_node(snode->nodetree, locx, locy);
node_add_shader_node(snode, event, locx, locy);
allqueue(REDRAWNODE, 0);
BIF_undo_push("Add Node");
@@ -734,9 +507,10 @@ static int node_draw_link_drag(SpaceNode *snode, bNode *node, bNodeSocket *sock,
if(find_indicated_socket(snode, &tnode, &tsock, sock->type, SOCK_IN)) {
if(nodeFindLink(snode->nodetree, sock, tsock)==NULL) {
if(nodeCountSocketLinks(snode->nodetree, tsock) < tsock->limit) {
if(tnode!=node) {
if(tnode!=node && link->tonode!=tnode && link->tosock!= tsock) {
link->tonode= tnode;
link->tosock= tsock;
nodeSolveOrder(snode->nodetree); /* for interactive red line warning */
}
}
}
@@ -750,9 +524,10 @@ static int node_draw_link_drag(SpaceNode *snode, bNode *node, bNodeSocket *sock,
if(find_indicated_socket(snode, &tnode, &tsock, sock->type, SOCK_OUT)) {
if(nodeFindLink(snode->nodetree, sock, tsock)==NULL) {
if(nodeCountSocketLinks(snode->nodetree, tsock) < tsock->limit) {
if(tnode!=node) {
if(tnode!=node && link->fromnode!=tnode && link->fromsock!= tsock) {
link->fromnode= tnode;
link->fromsock= tsock;
nodeSolveOrder(snode->nodetree); /* for interactive red line warning */
}
}
}
@@ -776,7 +551,7 @@ static int node_draw_link_drag(SpaceNode *snode, bNode *node, bNodeSocket *sock,
}
nodeSolveOrder(snode->nodetree);
nodeExecTree(snode->nodetree);
allqueue(REDRAWNODE, 0);
return 1;
@@ -878,6 +653,13 @@ void winqreadnodespace(ScrArea *sa, void *spacedata, BWinEvent *evt)
case MOUSEY:
doredraw= node_socket_hilights(snode, -1, SOCK_IN|SOCK_OUT);
break;
case UI_BUT_EVENT:
if(val==B_NODE_EXEC) {
nodeExecTree(snode->nodetree);
doredraw= 1;
}
break;
case PADPLUSKEY:
dx= (float)(0.1154*(G.v2d->cur.xmax-G.v2d->cur.xmin));
@@ -909,13 +691,16 @@ void winqreadnodespace(ScrArea *sa, void *spacedata, BWinEvent *evt)
if(G.qual==0)
node_border_select(snode);
break;
case CKEY: /* sort again, showing cyclics */
nodeSolveOrder(snode->nodetree);
doredraw= 1;
break;
case DKEY:
if(G.qual==LR_SHIFTKEY)
node_adduplicate(snode);
break;
case CKEY: /* sort again, showing cyclics */
nodeSolveOrder(snode->nodetree);
doredraw= 1;
case EKEY:
nodeExecTree(snode->nodetree);
break;
case GKEY:
transform_nodes(snode, "Translate Node");

View File

@@ -5198,6 +5198,8 @@ static uiBut *ui_def_but(uiBlock *block, int type, int retval, char *str, short
but->flag |= UI_NO_HILITE;
but->flag |= (block->flag & UI_BUT_ALIGN);
if(block->flag & UI_BLOCK_NO_HILITE)
but->flag |= UI_NO_HILITE;
return but;
}