Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTon Roosendaal <ton@blender.org>2005-12-28 18:42:51 +0300
committerTon Roosendaal <ton@blender.org>2005-12-28 18:42:51 +0300
commit9df1460777cceed839721ea99fd9623aedbb26f5 (patch)
treef4ad7ebfb6294be13c01a3dba67e55354973818e /source/blender/blenkernel
parent7837866b1e226925b2a50041e3f0f56ac9e82021 (diff)
Christmas coding work!
********* Node editor work: - To enable Nodes for Materials, you have to set the "Use Nodes" button, in the new Material buttons "Nodes" Panel or in header of the Node editor. Doing this will disable Material-Layers. - Nodes now execute materials ("shaders"), but still only using the previewrender code. - Nodes have (optional) previews for rendered images. - Node headers allow to hide buttons and/or preview image - Nodes can be dragged larger/smaller (right-bottom corner) - Nodes can be hidden (minimized) with hotkey H - CTRL+click on an Input Socket gives a popup with default values. - Changing Material/Texture or Mix node will adjust Node title. - Click-drag outside of a Node changes cursor to "Knife' and allows to draw a rect where to cut Links. - Added new node types RGBtoBW, Texture, In/Output, ColorRamp - Material Nodes have options to ouput diffuse or specular, or to use a negative normal. The input socket 'Normal' will force the material to use that normal, otherwise it uses the normal from the Material that has the node tree. - When drawing a link between two not-matching sockets, Blender inserts a converting node (now only for value/rgb combos) - When drawing a link to an input socket that's already in use, the old link will either disappear or flip to another unused socket. - A click on a Material Node will activate it, and show all its settings in the Material Buttons. Active Material Nodes draw the material icon in red. - A click on any node will show its options in the Node Panel in the Material buttons. - Multiple Output Nodes can be used, to sample contents of a tree, but only one Output is the real one, which is indicated in a different color and red material icon. - Added ThemeColors for node types - ALT+C will convert existing Material-Layers to Node... this currently only adds the material/mix nodes and connects them. Dunno if this is worth a lot of coding work to make perfect? - Press C to call another "Solve order", which will show all possible cyclic conflicts (if there are). - Technical: nodes now use "Type" structs which define the structure of nodes and in/output sockets. The Type structs store all fixed info, callbacks, and allow to reconstruct saved Nodes to match what is required by Blender. - Defining (new) nodes now is as simple as filling in a fixed Type struct, plus code some callbacks. A doc will be made! - Node preview images are by default float ********* Icon drawing: - Cleanup of how old icons were implemented in new system, making them 16x16 too, correctly centered *and* scaled. - Made drawing Icons use float coordinates - Moved BIF_calcpreview_image() into interface_icons.c, renamed it icon_from_image(). Removed a lot of unneeded Imbuf magic here! :) - Skipped scaling and imbuf copying when icons are OK size ********* Preview render: - Huge cleanup of code.... - renaming BIF_xxx calls that only were used internally - BIF_previewrender() now accepts an argument for rendering method, so it supports icons, buttonwindow previewrender and node editor - Only a single BIF_preview_changed() call now exists, supporting all signals as needed for buttos and node editor ********* More stuff: - glutil.c, glaDrawPixelsSafe() and glaDrawPixelsTex() now accept format argument for GL_FLOAT rects - Made the ColorBand become a built-in button for interface.c Was a load of cleanup work in buttons_shading.c... - removed a load of unneeded glBlendFunc() calls - Fixed bug in calculating text length for buttons (ancient!)
Diffstat (limited to 'source/blender/blenkernel')
-rw-r--r--source/blender/blenkernel/BKE_node.h107
-rw-r--r--source/blender/blenkernel/BKE_texture.h2
-rw-r--r--source/blender/blenkernel/intern/material.c29
-rw-r--r--source/blender/blenkernel/intern/node.c440
-rw-r--r--source/blender/blenkernel/intern/node_shaders.c518
-rw-r--r--source/blender/blenkernel/intern/texture.c34
6 files changed, 919 insertions, 211 deletions
diff --git a/source/blender/blenkernel/BKE_node.h b/source/blender/blenkernel/BKE_node.h
index 4146ebc71a0..83087204567 100644
--- a/source/blender/blenkernel/BKE_node.h
+++ b/source/blender/blenkernel/BKE_node.h
@@ -37,40 +37,113 @@ struct bNodeTree;
struct bNode;
struct bNodeLink;
struct bNodeSocket;
+struct bNodeStack;
+struct uiBlock;
+struct rctf;
struct ListBase;
#define SOCK_IN 1
#define SOCK_OUT 2
+/* ************** NODE TYPE DEFINITIONS ***** */
-/* ************** GENERIC API *************** */
+typedef struct bNodeSocketType {
+ int type, limit;
+ char *name;
+ float val1, val2, val3, val4; /* default alloc value for inputs */
+ float min, max; /* default range for inputs */
+
+ /* after this line is used internal only */
+ struct bNodeSocket *sock; /* to verify */
+
+} bNodeSocketType;
-void nodeFreeNode(struct bNodeTree *ntree, struct bNode *node);
-void nodeFreeTree(struct bNodeTree *ntree);
+typedef struct bNodeType {
+ int type;
+ char *name;
+ float width, minwidth, maxwidth;
+ short nclass, flag;
+
+ bNodeSocketType *inputs, *outputs;
+
+ char storagename[64]; /* struct name for DNA */
+
+ void (*execfunc)(void *data, struct bNode *, struct bNodeStack **, struct bNodeStack **);
+
+ /* after this line is set on startup of blender */
+ int (*butfunc)(struct uiBlock *, struct bNode *, rctf *);
-struct bNode *nodeAddNode(struct bNodeTree *ntree, char *name);
-struct bNodeLink *nodeAddLink(struct bNodeTree *ntree, struct bNode *fromnode, struct bNodeSocket *fromsock, struct bNode *tonode, struct bNodeSocket *tosock);
+} bNodeType;
+
+/* nodetype->nclass, also for themes */
+#define NODE_CLASS_INPUT 0
+#define NODE_CLASS_OUTPUT 1
+#define NODE_CLASS_GENERATOR 2
+#define NODE_CLASS_OPERATOR 3
+
+/* ************** GENERIC API, TREES *************** */
+
+struct bNodeTree *ntreeAddTree(int type);
+void ntreeInitTypes(struct bNodeTree *ntree);
+void ntreeFreeTree(struct bNodeTree *ntree);
+struct bNodeTree *ntreeCopyTree(struct bNodeTree *ntree, int internal_select);
+
+void ntreeSolveOrder(struct bNodeTree *ntree);
+
+void ntreeBeginExecTree(struct bNodeTree *ntree, int xsize, int ysize);
+void ntreeExecTree(struct bNodeTree *ntree);
+void ntreeEndExecTree(struct bNodeTree *ntree);
+void ntreeClearPixelTree(struct bNodeTree *, int, int);
+
+/* ************** GENERIC API, NODES *************** */
+
+void nodeAddToPreview(struct bNode *, float *, int, int);
+
+struct bNode *nodeAddNodeType(struct bNodeTree *ntree, int type);
+void nodeFreeNode(struct bNodeTree *ntree, struct bNode *node);
struct bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node);
-struct bNodeSocket *nodeAddSocket(struct bNode *node, int type, int where, int limit, char *name);
+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);
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 nodeExecTree(struct bNodeTree *ntree);
+struct bNode *nodeGetActive(struct bNodeTree *ntree);
+struct bNode *nodeGetActiveID(struct bNodeTree *ntree, short idtype);
/* ************** 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 ShadeInput;
+struct ShadeResult;
+
+/* note: types are needed to restore callbacks, don't change values */
+#define SH_NODE_INPUT 0
+#define SH_NODE_OUTPUT 1
+
+#define SH_NODE_MATERIAL 100
+#define SH_NODE_RGB 101
+#define SH_NODE_VALUE 102
+#define SH_NODE_MIX_RGB 103
+#define SH_NODE_VALTORGB 104
+#define SH_NODE_RGBTOBW 105
+#define SH_NODE_TEXTURE 106
+
+/* custom defines: options for Material node */
+#define SH_NODE_MAT_DIFF 1
+#define SH_NODE_MAT_SPEC 2
+#define SH_NODE_MAT_NEG 4
+
+/* the type definitions array */
+extern bNodeType *node_all_shaders[];
+
+/* API */
+struct bNode *nodeShaderAdd(struct bNodeTree *ntree, int type);
+void nodeShaderSetExecfunc(struct bNode *node);
+
+void ntreeShaderExecTree(struct bNodeTree *ntree, struct ShadeInput *shi, struct ShadeResult *shr);
-struct bNode *node_shader_add(struct bNodeTree *ntree, int type);
-void node_shader_set_execfunc(struct bNode *node);
+ /* switch material render loop */
+void set_node_shader_lamp_loop(void (*lamp_loop_func)(struct ShadeInput *, struct ShadeResult *));
#endif
diff --git a/source/blender/blenkernel/BKE_texture.h b/source/blender/blenkernel/BKE_texture.h
index 23c31564a66..4db98599206 100644
--- a/source/blender/blenkernel/BKE_texture.h
+++ b/source/blender/blenkernel/BKE_texture.h
@@ -50,7 +50,7 @@ int test_dlerr(const char *name, const char *symbol);
void open_plugin_tex(struct PluginTex *pit);
struct PluginTex *add_plugin_tex(char *str);
void free_plugin_tex(struct PluginTex *pit);
-struct ColorBand *add_colorband(void);
+struct ColorBand *add_colorband(int rangetype);
int do_colorband(struct ColorBand *coba, float in, float out[4]);
void default_tex(struct Tex *tex);
struct Tex *add_texture(char *name);
diff --git a/source/blender/blenkernel/intern/material.c b/source/blender/blenkernel/intern/material.c
index 47b3f1e34ea..5054774f339 100644
--- a/source/blender/blenkernel/intern/material.c
+++ b/source/blender/blenkernel/intern/material.c
@@ -40,6 +40,7 @@
#include "DNA_material_types.h"
#include "DNA_mesh_types.h"
#include "DNA_meta_types.h"
+#include "DNA_node_types.h"
#include "DNA_object_types.h"
#include "DNA_scene_types.h"
#include "DNA_texture_types.h"
@@ -55,6 +56,7 @@
#include "BKE_main.h"
#include "BKE_material.h"
#include "BKE_mesh.h"
+#include "BKE_node.h"
#include "BKE_utildefines.h"
#include "BPY_extern.h"
@@ -84,6 +86,10 @@ void free_material(Material *ma)
if(ml->mat) ml->mat->id.us--;
BLI_freelistN(&ma->layers);
+
+ if(ma->nodetree)
+ ntreeFreeTree(ma->nodetree);
+
}
void init_material(Material *ma)
@@ -169,6 +175,10 @@ Material *copy_material(Material *ma)
for(ml= man->layers.first; ml; ml= ml->next)
id_us_plus((ID *)ml->mat);
+ if(ma->nodetree) {
+ man->nodetree= ntreeCopyTree(ma->nodetree, 0); /* 0 == full new tree */
+ }
+
return man;
}
@@ -567,16 +577,25 @@ void new_material_to_objectdata(Object *ob)
ob->actcol= ob->totcol;
}
+/* will be renamed... now easy to re-use for nodes! */
Material *get_active_matlayer(Material *ma)
{
- MaterialLayer *ml;
if(ma==NULL) return NULL;
- for(ml= ma->layers.first; ml; ml= ml->next)
- if(ml->flag & ML_ACTIVE) break;
- if(ml)
- return ml->mat;
+ if(ma->use_nodes) {
+ bNode *node= nodeGetActiveID(ma->nodetree, ID_MA);
+ if(node && node->id) {
+ return (Material *)node->id;
+ }
+ }
+ else {
+ MaterialLayer *ml;
+ for(ml= ma->layers.first; ml; ml= ml->next)
+ if(ml->flag & ML_ACTIVE) break;
+ if(ml)
+ return ml->mat;
+ }
return ma;
}
diff --git a/source/blender/blenkernel/intern/node.c b/source/blender/blenkernel/intern/node.c
index 3d568e4e391..fbaa0b35c5e 100644
--- a/source/blender/blenkernel/intern/node.c
+++ b/source/blender/blenkernel/intern/node.c
@@ -28,33 +28,197 @@
*/
#include <stdlib.h>
+#include <string.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"
+/* ************** Type stuff ********** */
+
+static bNodeType *nodeGetType(bNodeTree *ntree, int type)
+{
+ bNodeType **typedefs= ntree->alltypes;
+
+ while( *typedefs && (*typedefs)->type!=type)
+ typedefs++;
+
+ return *typedefs;
+}
+
+void ntreeInitTypes(bNodeTree *ntree)
+{
+ bNode *node;
+
+ if(ntree->type==NTREE_SHADER)
+ ntree->alltypes= node_all_shaders;
+ else {
+ ntree->alltypes= NULL;
+ printf("Error: no type definitions for nodes\n");
+ }
+
+ for(node= ntree->nodes.first; node; node= node->next) {
+ node->typeinfo= nodeGetType(ntree, node->type);
+ if(node->typeinfo==NULL)
+ printf("Error: no typeinfo for node %s\n", node->name);
+ }
+
+ ntree->init |= NTREE_TYPE_INIT;
+}
+
+/* only used internal... we depend on type definitions! */
+static bNodeSocket *node_add_socket_type(ListBase *lb, bNodeSocketType *stype)
+{
+ bNodeSocket *sock= MEM_callocN(sizeof(bNodeSocket), "sock");
+
+ BLI_strncpy(sock->name, stype->name, NODE_MAXSTR);
+ if(stype->limit==0) sock->limit= 0xFFF;
+ else sock->limit= stype->limit;
+ sock->type= stype->type;
+
+ sock->ns.vec[0]= stype->val1;
+ sock->ns.vec[1]= stype->val2;
+ sock->ns.vec[2]= stype->val3;
+ sock->ns.vec[3]= stype->val4;
+
+ if(lb)
+ BLI_addtail(lb, sock);
+
+ return sock;
+}
+
+static void node_rem_socket(bNodeTree *ntree, ListBase *lb, bNodeSocket *sock)
+{
+ bNodeLink *link, *next;
+
+ for(link= ntree->links.first; link; link= next) {
+ next= link->next;
+ if(link->fromsock==sock || link->tosock==sock) {
+ nodeRemLink(ntree, link);
+ }
+ }
+
+ BLI_remlink(lb, sock);
+ MEM_freeN(sock);
+}
+
+static bNodeSocket *verify_socket(ListBase *lb, bNodeSocketType *stype)
+{
+ bNodeSocket *sock;
+
+ for(sock= lb->first; sock; sock= sock->next) {
+ if(strncmp(sock->name, stype->name, NODE_MAXSTR)==0)
+ break;
+ }
+ if(sock) {
+ sock->type= stype->type; /* in future, read this from tydefs! */
+ if(stype->limit==0) sock->limit= 0xFFF;
+ else sock->limit= stype->limit;
+ BLI_remlink(lb, sock);
+ return sock;
+ }
+ else {
+ return node_add_socket_type(NULL, stype);
+ }
+}
+
+static void verify_socket_list(bNodeTree *ntree, ListBase *lb, bNodeSocketType *stype_first)
+{
+ bNodeSocketType *stype;
+
+ /* no inputs anymore? */
+ if(stype_first==NULL) {
+ while(lb->first)
+ node_rem_socket(ntree, lb, lb->first);
+ }
+ else {
+ /* step by step compare */
+ stype= stype_first;
+ while(stype->type != -1) {
+ stype->sock= verify_socket(lb, stype);
+ stype++;
+ }
+ /* leftovers are removed */
+ while(lb->first)
+ node_rem_socket(ntree, lb, lb->first);
+ /* and we put back the verified sockets */
+ stype= stype_first;
+ while(stype->type != -1) {
+ BLI_addtail(lb, stype->sock);
+ stype++;
+ }
+ }
+}
+
+void ntreeVerifyTypes(bNodeTree *ntree)
+{
+ bNode *node;
+ bNodeType *ntype;
+
+ if((ntree->init & NTREE_TYPE_INIT)==0)
+ ntreeInitTypes(ntree);
+
+ /* check inputs and outputs, and remove or insert them */
+ for(node= ntree->nodes.first; node; node= node->next) {
+ ntype= node->typeinfo;
+ if(ntype) {
+ /* might add some other verify stuff here */
+
+ verify_socket_list(ntree, &node->inputs, ntype->inputs);
+ verify_socket_list(ntree, &node->outputs, ntype->outputs);
+ }
+ }
+}
+
+
+
/* ************** 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 *nodeAddNodeType(bNodeTree *ntree, int type)
{
- bNode *node= MEM_callocN(sizeof(bNode), "new node");
+ bNode *node;
+ bNodeType *ntype= nodeGetType(ntree, type);
+ bNodeSocketType *stype;
+ node= MEM_callocN(sizeof(bNode), "new node");
BLI_addtail(&ntree->nodes, node);
- BLI_strncpy(node->name, name, NODE_MAXSTR);
+ node->typeinfo= ntype;
+
+ BLI_strncpy(node->name, ntype->name, NODE_MAXSTR);
+ node->type= ntype->type;
+ node->flag= NODE_SELECT|ntype->flag;
+ node->width= ntype->width;
+
+ if(ntype->inputs) {
+ stype= ntype->inputs;
+ while(stype->type != -1) {
+ node_add_socket_type(&node->inputs, stype);
+ stype++;
+ }
+ }
+ if(ntype->outputs) {
+ stype= ntype->outputs;
+ while(stype->type != -1) {
+ node_add_socket_type(&node->outputs, stype);
+ stype++;
+ }
+ }
return node;
}
-/* keep listorder identical, for copying links */
+/* keep socket listorder identical, for copying links */
+/* ntree is the target tree */
bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node)
{
bNode *nnode= MEM_callocN(sizeof(bNode), "dupli node");
@@ -67,8 +231,13 @@ bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node)
if(nnode->id)
nnode->id->us++;
- node->flag= NODE_SELECT;
-
+ if(nnode->storage)
+ nnode->storage= MEM_dupallocN(nnode->storage);
+
+ node->new= nnode;
+ nnode->new= NULL;
+ nnode->preview= NULL;
+
return nnode;
}
@@ -85,19 +254,22 @@ bNodeLink *nodeAddLink(bNodeTree *ntree, bNode *fromnode, bNodeSocket *fromsock,
return link;
}
-bNodeSocket *nodeAddSocket(bNode *node, int type, int where, int limit, char *name)
+void nodeRemLink(bNodeTree *ntree, bNodeLink *link)
{
- bNodeSocket *sock= MEM_callocN(sizeof(bNodeSocket), "sock");
+ BLI_remlink(&ntree->links, link);
+ if(link->tosock)
+ link->tosock->link= NULL;
+ MEM_freeN(link);
+}
+
+
+bNodeTree *ntreeAddTree(int type)
+{
+ bNodeTree *ntree= MEM_callocN(sizeof(bNodeTree), "new node tree");
+ ntree->type= type;
- BLI_strncpy(sock->name, name, NODE_MAXSTR);
- sock->limit= limit;
- sock->type= type;
- if(where==SOCK_IN)
- BLI_addtail(&node->inputs, sock);
- else
- BLI_addtail(&node->outputs, sock);
-
- return sock;
+ ntreeInitTypes(ntree);
+ return ntree;
}
/* ************** Free stuff ********** */
@@ -125,8 +297,7 @@ static void node_unlink_node(bNodeTree *ntree, bNode *node)
break;
}
if(sock) {
- BLI_remlink(&ntree->links, link);
- MEM_freeN(link);
+ nodeRemLink(ntree, link);
}
}
}
@@ -144,10 +315,18 @@ void nodeFreeNode(bNodeTree *ntree, bNode *node)
BLI_freelistN(&node->inputs);
BLI_freelistN(&node->outputs);
+ if(node->preview) {
+ if(node->preview->rect)
+ MEM_freeN(node->preview->rect);
+ MEM_freeN(node->preview);
+ }
+ if(node->storage)
+ MEM_freeN(node->storage);
+
MEM_freeN(node);
}
-void nodeFreeTree(bNodeTree *ntree)
+void ntreeFreeTree(bNodeTree *ntree)
{
bNode *node, *next;
@@ -156,12 +335,64 @@ void nodeFreeTree(bNodeTree *ntree)
nodeFreeNode(NULL, node); /* NULL -> no unlinking needed */
}
BLI_freelistN(&ntree->links);
- BLI_freelistN(&ntree->inputs);
- BLI_freelistN(&ntree->outputs);
MEM_freeN(ntree);
}
+bNodeTree *ntreeCopyTree(bNodeTree *ntree, int internal_select)
+{
+ bNodeTree *newtree;
+ bNode *node, *nnode, *last;
+ bNodeLink *link, *nlink;
+ bNodeSocket *sock;
+ int a;
+
+ if(ntree==NULL) return NULL;
+
+ if(internal_select==0) {
+ newtree= MEM_dupallocN(ntree);
+ newtree->nodes.first= newtree->nodes.last= NULL;
+ newtree->links.first= newtree->links.last= NULL;
+ }
+ else
+ newtree= ntree;
+
+ last= ntree->nodes.last;
+ for(node= ntree->nodes.first; node; node= node->next) {
+
+ node->new= NULL;
+ if(internal_select==0 || (node->flag & NODE_SELECT)) {
+ nnode= nodeCopyNode(newtree, node); /* sets node->new */
+ if(internal_select) {
+ node->flag &= ~NODE_SELECT;
+ nnode->flag |= NODE_SELECT;
+ }
+ node->flag &= ~NODE_ACTIVE;
+ }
+ if(node==last) break;
+ }
+
+ /* check for copying links */
+ for(link= ntree->links.first; link; link= link->next) {
+ if(link->fromnode->new && link->tonode->new) {
+ nlink= nodeAddLink(newtree, link->fromnode->new, NULL, link->tonode->new, NULL);
+ /* sockets were copied in order */
+ for(a=0, sock= link->fromnode->outputs.first; sock; sock= sock->next, a++) {
+ if(sock==link->fromsock)
+ break;
+ }
+ nlink->fromsock= BLI_findlink(&link->fromnode->new->outputs, a);
+
+ for(a=0, sock= link->tonode->inputs.first; sock; sock= sock->next, a++) {
+ if(sock==link->tosock)
+ break;
+ }
+ nlink->tosock= BLI_findlink(&link->tonode->new->inputs, a);
+ }
+ }
+ return newtree;
+}
+
/* ************ find stuff *************** */
bNodeLink *nodeFindLink(bNodeTree *ntree, bNodeSocket *from, bNodeSocket *to)
@@ -189,6 +420,31 @@ int nodeCountSocketLinks(bNodeTree *ntree, bNodeSocket *sock)
return tot;
}
+bNode *nodeGetActive(bNodeTree *ntree)
+{
+ bNode *node;
+
+ if(ntree==NULL) return NULL;
+
+ for(node= ntree->nodes.first; node; node= node->next)
+ if(node->flag & NODE_ACTIVE)
+ break;
+ return node;
+}
+
+bNode *nodeGetActiveID(bNodeTree *ntree, short idtype)
+{
+ bNode *node;
+
+ if(ntree==NULL) return NULL;
+
+ for(node= ntree->nodes.first; node; node= node->next)
+ if(node->id && GS(node->id->name)==idtype)
+ if(node->flag & NODE_ACTIVE_ID)
+ break;
+ return node;
+}
+
/* ************** dependency stuff *********** */
/* node is guaranteed to be not checked before */
@@ -220,7 +476,7 @@ static int node_recurs_check(bNode *node, bNode ***nsort, int level)
return 0xFFF;
}
-void nodeSolveOrder(bNodeTree *ntree)
+void ntreeSolveOrder(bNodeTree *ntree)
{
bNode *node, **nodesort, **nsort;
bNodeSocket *sock;
@@ -266,78 +522,164 @@ void nodeSolveOrder(bNodeTree *ntree)
MEM_freeN(nodesort);
+ /* find the active outputs, tree type dependant, might become handler */
+ if(ntree->type==NTREE_SHADER) {
+ /* shader nodes only accepts one output */
+ int output= 0;
+
+ for(node= ntree->nodes.first; node; node= node->next) {
+ if(node->typeinfo->nclass==NODE_CLASS_OUTPUT) {
+ if(output==0)
+ node->flag |= NODE_DO_OUTPUT;
+ else
+ node->flag &= ~NODE_DO_OUTPUT;
+ output= 1;
+ }
+ }
+ }
+
+ /* here we could recursively set which nodes have to be done,
+ might be different for editor or for "real" use... */
+
+
+
}
+/* *************** preview *********** */
+
+/* if node->preview, then we assume the rect to exist */
+
+static void nodeInitPreview(bNode *node, int xsize, int ysize)
+{
+ /* signal we don't do anything, preview writing is protected */
+ if(xsize==0 || ysize==0)
+ return;
+
+ /* sanity checks & initialize */
+ if(node->preview) {
+ if(node->preview->xsize!=xsize && node->preview->ysize!=ysize) {
+ MEM_freeN(node->preview->rect);
+ node->preview->rect= NULL;
+ }
+ }
+
+ if(node->preview==NULL) {
+ node->preview= MEM_callocN(sizeof(bNodePreview), "node preview");
+ }
+ if(node->preview->rect==NULL) {
+ node->preview->rect= MEM_callocN(4*xsize + xsize*ysize*sizeof(float)*4, "node preview rect");
+ node->preview->xsize= xsize;
+ node->preview->ysize= ysize;
+ }
+}
+
+void nodeAddToPreview(bNode *node, float *col, int x, int y)
+{
+ bNodePreview *preview= node->preview;
+ if(preview) {
+ if(x>=0 && y>=0) {
+ if(x<preview->xsize && y<preview->ysize) {
+ float *tar= preview->rect+ 4*((preview->xsize*y) + x);
+ QUATCOPY(tar, col);
+ }
+ else printf("prv out bound x y %d %d\n", x, y);
+ }
+ else printf("prv out bound x y %d %d\n", x, y);
+ }
+}
+
+
+
/* ******************* executing ************* */
-void nodeBeginExecTree(bNodeTree *ntree)
+void ntreeBeginExecTree(bNodeTree *ntree, int xsize, int ysize)
{
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;
- }
+ if((ntree->init & NTREE_TYPE_INIT)==0)
+ ntreeInitTypes(ntree);
- /* create indices for stack */
+ /* create indices for stack, check preview */
for(node= ntree->nodes.first; node; node= node->next) {
-
for(sock= node->outputs.first; sock; sock= sock->next) {
sock->stack_index= index++;
}
+
+ if(node->typeinfo->flag & NODE_PREVIEW) /* hrms, check for closed nodes? */
+ nodeInitPreview(node, xsize, ysize);
+
}
if(index) {
- ntree->stack= MEM_callocN(index*sizeof(bNodeStack), "node stack");
+ bNodeStack *ns;
+ int a;
+
+ ns=ntree->stack= MEM_callocN(index*sizeof(bNodeStack), "node stack");
+ for(a=0; a<index; a++, ns++) ns->hasinput= 1;
}
+
+ ntree->init |= NTREE_EXEC_INIT;
}
-void nodeEndExecTree(bNodeTree *ntree)
+void ntreeEndExecTree(bNodeTree *ntree)
{
if(ntree->stack) {
MEM_freeN(ntree->stack);
ntree->stack= NULL;
}
+
+ ntree->init &= ~NTREE_EXEC_INIT;
}
-static void node_get_stack(bNode *node, bNodeStack *stack, bNodeStack **spp)
+static void node_get_stack(bNode *node, bNodeStack *stack, bNodeStack **in, bNodeStack **out)
{
- 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;
+ *(in++)= stack + sock->link->fromsock->stack_index;
else
- *(spp++)= &empty; /* input is not written into */
+ *(in++)= &sock->ns;
}
for(sock= node->outputs.first; sock; sock= sock->next) {
- *(spp++)= stack + sock->stack_index;
+ *(out++)= stack + sock->stack_index;
}
}
/* nodes are presorted, so exec is in order of list */
-void nodeExecTree(bNodeTree *ntree)
+void ntreeExecTree(bNodeTree *ntree)
{
bNode *node;
- bNodeStack *ns[MAX_SOCKET]; /* arbitrary... watch this */
+ bNodeStack *nsin[MAX_SOCKET]; /* arbitrary... watch this */
+ bNodeStack *nsout[MAX_SOCKET]; /* arbitrary... watch this */
- nodeBeginExecTree(ntree);
+ /* only when initialized */
+ if(ntree->init & NTREE_EXEC_INIT) {
- for(node= ntree->nodes.first; node; node= node->next) {
- if(node->execfunc) {
- node_get_stack(node, ntree->stack, ns);
- node->execfunc(node, ns);
+ for(node= ntree->nodes.first; node; node= node->next) {
+ if(node->typeinfo->execfunc) {
+ node_get_stack(node, ntree->stack, nsin, nsout);
+ node->typeinfo->execfunc(ntree->data, node, nsin, nsout);
+ }
}
}
-
- nodeEndExecTree(ntree);
}
+/* clear one pixel in all the preview images */
+void ntreeClearPixelTree(bNodeTree *ntree, int x, int y)
+{
+ bNode *node;
+ float vec[4]= {0.0f, 0.0f, 0.0f, 0.0f};
+
+ /* only when initialized */
+ if(ntree->init & NTREE_EXEC_INIT) {
+ for(node= ntree->nodes.first; node; node= node->next) {
+ if(node->preview)
+ nodeAddToPreview(node, vec, x, y);
+ }
+ }
+}
diff --git a/source/blender/blenkernel/intern/node_shaders.c b/source/blender/blenkernel/intern/node_shaders.c
index 74728abac9c..f2ece280d58 100644
--- a/source/blender/blenkernel/intern/node_shaders.c
+++ b/source/blender/blenkernel/intern/node_shaders.c
@@ -30,10 +30,13 @@
#include <stdlib.h>
#include "DNA_ID.h"
+#include "DNA_material_types.h"
#include "DNA_node_types.h"
+#include "DNA_texture_types.h"
#include "BKE_blender.h"
#include "BKE_node.h"
+#include "BKE_texture.h"
#include "BKE_utildefines.h"
#include "BLI_arithb.h"
@@ -41,186 +44,443 @@
#include "MEM_guardedalloc.h"
-/* **************** testnode ************ */
+#include "render.h" /* <- shadeinput/output */
-static void blendcolor(float *col1, float *col2, float *output, float fac)
+/* ********* exec data struct, remains internal *********** */
+
+typedef struct ShaderCallData {
+ ShadeInput *shi;
+ ShadeResult *shr;
+} ShaderCallData;
+
+
+/* **************** call to switch lamploop for material node ************ */
+
+static void (*node_shader_lamp_loop)(ShadeInput *, ShadeResult *);
+
+void set_node_shader_lamp_loop(void (*lamp_loop_func)(ShadeInput *, ShadeResult *))
{
- 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];
+ node_shader_lamp_loop= lamp_loop_func;
}
-static void node_shader_exec_test(bNode *node, bNodeStack **ns)
+/* **************** input node ************ */
+
+static void node_shader_exec_input(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
{
-
- blendcolor(ns[0]->vec, ns[1]->vec, ns[2]->vec, 0.5);
+ if(data) {
+ ShadeResult *shr= ((ShaderCallData *)data)->shr;
+ ShadeInput *shi= ((ShaderCallData *)data)->shi;
+ float col[4];
+
+ /* stack order output sockets: color, alpha, normal */
+ VecAddf(col, shr->diff, shr->spec);
+ col[3]= shr->alpha;
+
+ VECCOPY(out[0]->vec, col);
+ out[1]->vec[0]= shr->alpha;
+ VECCOPY(out[2]->vec, shi->vn);
+
+ if(shi->do_preview)
+ nodeAddToPreview(node, col, shi->xs, shi->ys);
+
+ }
+}
-// printvecf(node->name, ns[2]->vec);
+
+/* **************** output node ************ */
+
+static void node_shader_exec_output(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+ if(data) {
+ ShadeInput *shi= ((ShaderCallData *)data)->shi;
+ float col[4];
+
+ /* stack order input sockets: col, alpha, normal */
+ VECCOPY(col, in[0]->vec);
+ col[3]= in[1]->vec[0];
+
+ if(shi->do_preview) {
+ nodeAddToPreview(node, col, shi->xs, shi->ys);
+ node->lasty= shi->ys;
+ }
+
+ if(node->flag & NODE_DO_OUTPUT) {
+ ShadeResult *shr= ((ShaderCallData *)data)->shr;
+
+ VECCOPY(shr->diff, col);
+ col[0]= col[1]= col[2]= 0.0f;
+ VECCOPY(shr->spec, col);
+ shr->alpha= col[3];
+
+ // VECCOPY(shr->nor, in[3]->vec);
+ }
+ }
}
-static bNode *node_shader_add_test(bNodeTree *ntree)
+/* **************** material node ************ */
+
+static void node_shader_exec_material(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
{
- bNode *node= nodeAddNode(ntree, "TestNode");
- static int tot= 0;
+ if(data && node->id) {
+ ShadeResult shrnode;
+ ShadeInput *shi;
+ float col[4], *nor;
- 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;
+ shi= ((ShaderCallData *)data)->shi;
+
+ shi->mat= (Material *)node->id;
+
+ /* retrieve normal */
+ if(in[0]->hasinput)
+ nor= in[0]->vec;
+ else
+ nor= shi->vno;
+
+ if(node->custom1 & SH_NODE_MAT_NEG) {
+ shi->vn[0]= -nor[0];
+ shi->vn[1]= -nor[1];
+ shi->vn[2]= -nor[2];
+ }
+ else {
+ VECCOPY(shi->vn, nor);
+ }
+
+ node_shader_lamp_loop(shi, &shrnode);
+
+ if(node->custom1 & SH_NODE_MAT_DIFF) {
+ VECCOPY(col, shrnode.diff);
+ if(node->custom1 & SH_NODE_MAT_SPEC) {
+ VecAddf(col, col, shrnode.spec);
+ }
+ }
+ else if(node->custom1 & SH_NODE_MAT_SPEC) {
+ VECCOPY(col, shrnode.spec);
+ }
+ else
+ col[0]= col[1]= col[2]= 0.0f;
+
+ col[3]= shrnode.alpha;
+
+ if(shi->do_preview)
+ nodeAddToPreview(node, col, shi->xs, shi->ys);
+
+ /* stack order output: color, alpha, normal */
+ VECCOPY(out[0]->vec, col);
+ out[1]->vec[0]= shrnode.alpha;
+
+ if(node->custom1 & SH_NODE_MAT_NEG) {
+ shi->vn[0]= -shi->vn[0];
+ shi->vn[1]= -shi->vn[1];
+ shi->vn[2]= -shi->vn[2];
+ }
+ VECCOPY(out[2]->vec, shi->vn);
+ }
}
-/* **************** value node ************ */
+/* **************** texture node ************ */
-static void node_shader_exec_value(bNode *node, bNodeStack **ns)
+static void node_shader_exec_texture(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
{
- /* no input node! */
- ns[0]->vec[0]= node->ns.vec[0];
-// printf("%s %f\n", node->name, ns[0]->vec[0]);
+ if(data && node->id) {
+ ShadeInput *shi;
+
+ shi= ((ShaderCallData *)data)->shi;
+
+ multitex_ext((Tex *)node->id, shi->co, out[0]->vec, out[1]->vec, out[1]->vec+1, out[1]->vec+2, out[1]->vec+3);
+
+ if(shi->do_preview)
+ nodeAddToPreview(node, out[1]->vec, shi->xs, shi->ys);
+
+ }
}
-static bNode *node_shader_add_value(bNodeTree *ntree)
+/* **************** value node ************ */
+
+static void node_shader_exec_value(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
{
- bNode *node= nodeAddNode(ntree, "Value");
-
- node->type= SH_NODE_VALUE;
- node->width= 80.0f;
- node->prv_h= 20.0f;
+ bNodeSocket *sock= node->outputs.first;
- /* add sockets */
- nodeAddSocket(node, SOCK_VALUE, SOCK_OUT, 0xFFF, "");
-
- return node;
+ out[0]->vec[0]= sock->ns.vec[0];
}
/* **************** rgba node ************ */
-static void node_shader_exec_rgb(bNode *node, bNodeStack **ns)
+static void node_shader_exec_rgb(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
{
- /* no input node! */
- QUATCOPY(ns[0]->vec, node->ns.vec);
+ bNodeSocket *sock= node->outputs.first;
-// printvecf(node->name, ns[0]->vec);
+ VECCOPY(out[0]->vec, sock->ns.vec);
}
+
+
+/* **************** mix rgb node ************ */
-static bNode *node_shader_add_rgb(bNodeTree *ntree)
+static void node_shader_exec_mix_rgb(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
{
- bNode *node= nodeAddNode(ntree, "RGB");
+ /* stack order in: fac, col1, col2 */
+ /* stack order out: col */
+ float col[3];
- 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, "");
+ VECCOPY(col, in[1]->vec);
+ ramp_blend(node->custom1, col, col+1, col+2, in[0]->vec[0], in[2]->vec);
+ VECCOPY(out[0]->vec, col);
+}
+
+/* **************** val to rgb node ************ */
+
+static void node_shader_exec_valtorgb(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+ /* stack order in: fac */
+ /* stack order out: col, alpha */
- return node;
+ if(node->storage) {
+ do_colorband(node->storage, in[0]->vec[0], out[0]->vec);
+ out[1]->vec[0]= out[0]->vec[3];
+ }
}
-/* **************** mix rgba node ************ */
+/* **************** rgb to bw node ************ */
-static void node_shader_exec_mix_rgb(bNode *node, bNodeStack **ns)
+static void node_shader_exec_rgbtobw(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
{
- /* stack order is fac, col1, col2, out */
- blendcolor(ns[1]->vec, ns[2]->vec, ns[3]->vec, ns[0]->vec[0]);
+ /* stack order out: bw */
+ /* stack order in: col */
+
+ out[0]->vec[0]= in[0]->vec[0]*0.35f + in[0]->vec[1]*0.45f + in[0]->vec[2]*0.2f;
}
-static bNode *node_shader_add_mix_rgb(bNodeTree *ntree)
+
+/* ******************* execute ************ */
+
+void ntreeShaderExecTree(bNodeTree *ntree, ShadeInput *shi, ShadeResult *shr)
{
- bNode *node= nodeAddNode(ntree, "Mix RGB");
+ ShaderCallData scd;
- node->type= SH_NODE_MIX_RGB;
- node->width= 80.0f;
- node->prv_h= 0.0f;
+ /* convert caller data to struct */
+ scd.shi= shi;
+ scd.shr= shr;
+ ntree->data= &scd;
- /* 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");
+ ntreeExecTree(ntree);
- return node;
}
-/* **************** show rgba node ************ */
+/* ******************************************************** */
+/* ********* Shader Node type definitions ***************** */
+/* ******************************************************** */
-static void node_shader_exec_show_rgb(bNode *node, bNodeStack **ns)
-{
- /* only input node! */
- QUATCOPY(node->ns.vec, ns[0]->vec);
+/* SocketType syntax:
+ socket type, max connections (0 is no limit), name, 4 values for default, 2 values for range */
+
+/* Verification rule: If name changes, a saved socket and its links will be removed! Type changes are OK */
+
+/* *************** INPUT ********************* */
+static bNodeSocketType sh_node_input_out[]= {
+ { SOCK_RGBA, 0, "Color", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+ { SOCK_VALUE, 0, "Alpha", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_VECTOR, 0, "Normal", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+ { -1, 0, "" }
+};
+
+static bNodeType sh_node_input= {
+ /* type code */ SH_NODE_INPUT,
+ /* name */ "Input",
+ /* width+range */ 80, 60, 200,
+ /* class+opts */ NODE_CLASS_INPUT, NODE_PREVIEW,
+ /* input sock */ NULL,
+ /* output sock */ sh_node_input_out,
+ /* storage */ "",
+ /* execfunc */ node_shader_exec_input,
-// printvecf(node->name, ns[0]->vec);
-}
+};
-static bNode *node_shader_add_show_rgb(bNodeTree *ntree)
-{
- bNode *node= nodeAddNode(ntree, "Show RGB");
+/* **************** OUTPUT ******************** */
+static bNodeSocketType sh_node_output_in[]= {
+ { SOCK_RGBA, 1, "Color", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+ { SOCK_VALUE, 1, "Alpha", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_VECTOR, 1, "Normal", 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f},
+ { -1, 0, "" }
+};
+
+static bNodeType sh_node_output= {
+ /* type code */ SH_NODE_OUTPUT,
+ /* name */ "Output",
+ /* width+range */ 80, 60, 200,
+ /* class+opts */ NODE_CLASS_OUTPUT, NODE_PREVIEW,
+ /* input sock */ sh_node_output_in,
+ /* output sock */ NULL,
+ /* storage */ "",
+ /* execfunc */ node_shader_exec_output,
- node->type= SH_NODE_SHOW_RGB;
- node->width= 80.0f;
- node->prv_h= 0.0f;
- node->ns.vec[3]= 1.0f; /* alpha init */
+};
+
+/* **************** MATERIAL ******************** */
+static bNodeSocketType sh_node_material_in[]= {
+ { SOCK_VECTOR, 1, "Normal", 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f},
+ { -1, 0, "" }
+};
+
+static bNodeSocketType sh_node_material_out[]= {
+ { SOCK_RGBA, 0, "Color", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+ { SOCK_VALUE, 0, "Alpha", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_VECTOR, 0, "Normal", 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f},
+ { -1, 0, "" }
+};
+
+static bNodeType sh_node_material= {
+ /* type code */ SH_NODE_MATERIAL,
+ /* name */ "Material",
+ /* width+range */ 120, 60, 200,
+ /* class+opts */ NODE_CLASS_GENERATOR, NODE_OPTIONS|NODE_PREVIEW,
+ /* input sock */ sh_node_material_in,
+ /* output sock */ sh_node_material_out,
+ /* storage */ "",
+ /* execfunc */ node_shader_exec_material,
- /* add sockets */
- nodeAddSocket(node, SOCK_RGBA, SOCK_IN, 1, "");
+};
+
+/* **************** TEXTURE ******************** */
+static bNodeSocketType sh_node_texture_out[]= {
+ { SOCK_VALUE, 0, "Value", 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+ { SOCK_RGBA , 0, "Color", 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f},
+ { SOCK_VECTOR, 0, "Normal", 0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f},
+ { -1, 0, "" }
+};
+
+static bNodeType sh_node_texture= {
+ /* type code */ SH_NODE_TEXTURE,
+ /* name */ "Texture",
+ /* width+range */ 120, 60, 200,
+ /* class+opts */ NODE_CLASS_GENERATOR, NODE_OPTIONS|NODE_PREVIEW,
+ /* input sock */ NULL,
+ /* output sock */ sh_node_texture_out,
+ /* storage */ "",
+ /* execfunc */ node_shader_exec_texture,
- return node;
-}
+};
+
+/* **************** VALUE ******************** */
+static bNodeSocketType sh_node_value_out[]= {
+ { SOCK_VALUE, 0, "Value", 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { -1, 0, "" }
+};
+static bNodeType sh_node_value= {
+ /* type code */ SH_NODE_VALUE,
+ /* name */ "Value",
+ /* width+range */ 80, 40, 120,
+ /* class+opts */ NODE_CLASS_GENERATOR, NODE_OPTIONS,
+ /* input sock */ NULL,
+ /* output sock */ sh_node_value_out,
+ /* storage */ "",
+ /* execfunc */ node_shader_exec_value,
+
+};
-/* **************** API for add ************** */
+/* **************** RGB ******************** */
+static bNodeSocketType sh_node_rgb_out[]= {
+ { SOCK_RGBA, 0, "Color", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+ { -1, 0, "" }
+};
-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;
-}
+static bNodeType sh_node_rgb= {
+ /* type code */ SH_NODE_RGB,
+ /* name */ "RGB",
+ /* width+range */ 100, 60, 140,
+ /* class+opts */ NODE_CLASS_GENERATOR, NODE_OPTIONS,
+ /* input sock */ NULL,
+ /* output sock */ sh_node_rgb_out,
+ /* storage */ "",
+ /* execfunc */ node_shader_exec_rgb,
+
+};
-/* ******************* set the callbacks, called from UI, loader ***** */
+/* **************** MIX RGB ******************** */
+static bNodeSocketType sh_node_mix_rgb_in[]= {
+ { SOCK_VALUE, 1, "Fac", 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { SOCK_RGBA, 1, "Color1", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+ { SOCK_RGBA, 1, "Color2", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+ { -1, 0, "" }
+};
+static bNodeSocketType sh_node_mix_rgb_out[]= {
+ { SOCK_RGBA, 0, "Color", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+ { -1, 0, "" }
+};
+
+static bNodeType sh_node_mix_rgb= {
+ /* type code */ SH_NODE_MIX_RGB,
+ /* name */ "Mix",
+ /* width+range */ 80, 40, 120,
+ /* class+opts */ NODE_CLASS_OPERATOR, NODE_OPTIONS,
+ /* input sock */ sh_node_mix_rgb_in,
+ /* output sock */ sh_node_mix_rgb_out,
+ /* storage */ "",
+ /* execfunc */ node_shader_exec_mix_rgb,
+
+};
+
+
+/* **************** VALTORGB ******************** */
+static bNodeSocketType sh_node_valtorgb_in[]= {
+ { SOCK_VALUE, 1, "Fac", 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { -1, 0, "" }
+};
+static bNodeSocketType sh_node_valtorgb_out[]= {
+ { SOCK_RGBA, 0, "Color", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+ { SOCK_VALUE, 0, "Alpha", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+ { -1, 0, "" }
+};
+
+static bNodeType sh_node_valtorgb= {
+ /* type code */ SH_NODE_VALTORGB,
+ /* name */ "ColorRamp",
+ /* width+range */ 240, 200, 300,
+ /* class+opts */ NODE_CLASS_OPERATOR, NODE_OPTIONS,
+ /* input sock */ sh_node_valtorgb_in,
+ /* output sock */ sh_node_valtorgb_out,
+ /* storage */ "ColorBand",
+ /* execfunc */ node_shader_exec_valtorgb,
+
+};
+
+
+/* **************** RGBTOBW ******************** */
+static bNodeSocketType sh_node_rgbtobw_in[]= {
+ { SOCK_RGBA, 1, "Color", 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 1.0f},
+ { -1, 0, "" }
+};
+static bNodeSocketType sh_node_rgbtobw_out[]= {
+ { SOCK_VALUE, 0, "Val", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+ { -1, 0, "" }
+};
+
+static bNodeType sh_node_rgbtobw= {
+ /* type code */ SH_NODE_RGBTOBW,
+ /* name */ "RGB to BW",
+ /* width+range */ 80, 40, 120,
+ /* class+opts */ NODE_CLASS_OPERATOR, 0,
+ /* input sock */ sh_node_rgbtobw_in,
+ /* output sock */ sh_node_rgbtobw_out,
+ /* storage */ "ColorBand",
+ /* execfunc */ node_shader_exec_rgbtobw,
+
+};
+
+
+/* ****************** types array for all shaders ****************** */
+
+bNodeType *node_all_shaders[]= {
+ &sh_node_input,
+ &sh_node_output,
+ &sh_node_material,
+ &sh_node_value,
+ &sh_node_rgb,
+ &sh_node_mix_rgb,
+ &sh_node_valtorgb,
+ &sh_node_rgbtobw,
+ &sh_node_texture,
+ NULL
+};
-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;
- }
-}
diff --git a/source/blender/blenkernel/intern/texture.c b/source/blender/blenkernel/intern/texture.c
index 7873340f7d8..123298c723a 100644
--- a/source/blender/blenkernel/intern/texture.c
+++ b/source/blender/blenkernel/intern/texture.c
@@ -199,25 +199,39 @@ void free_plugin_tex(PluginTex *pit)
/* ****************** COLORBAND ******************* */
-ColorBand *add_colorband()
+ColorBand *add_colorband(int rangetype)
{
ColorBand *coba;
int a;
coba= MEM_callocN( sizeof(ColorBand), "colorband");
- coba->data[0].r= 0.0;
- coba->data[0].g= 0.0;
- coba->data[0].b= 0.0;
- coba->data[0].a= 0.0;
coba->data[0].pos= 0.0;
-
- coba->data[1].r= 0.0;
- coba->data[1].g= 1.0;
- coba->data[1].b= 1.0;
- coba->data[1].a= 1.0;
coba->data[1].pos= 1.0;
+ if(rangetype==0) {
+ coba->data[0].r= 0.0;
+ coba->data[0].g= 0.0;
+ coba->data[0].b= 0.0;
+ coba->data[0].a= 0.0;
+
+ coba->data[1].r= 0.0;
+ coba->data[1].g= 1.0;
+ coba->data[1].b= 1.0;
+ coba->data[1].a= 1.0;
+ }
+ else {
+ coba->data[0].r= 0.0;
+ coba->data[0].g= 0.0;
+ coba->data[0].b= 0.0;
+ coba->data[0].a= 1.0;
+
+ coba->data[1].r= 1.0;
+ coba->data[1].g= 1.0;
+ coba->data[1].b= 1.0;
+ coba->data[1].a= 1.0;
+ }
+
for(a=2; a<MAXCOLORBAND; a++) {
coba->data[a].r= 0.5;
coba->data[a].g= 0.5;