Patch #7897 Texture Nodes!
authorTon Roosendaal <ton@blender.org>
Wed, 12 Nov 2008 19:03:50 +0000 (19:03 +0000)
committerTon Roosendaal <ton@blender.org>
Wed, 12 Nov 2008 19:03:50 +0000 (19:03 +0000)
Robin (Frrr) Allen did a decent job on this, so we can also welcome him
as a member in the svn committers team to maintain it!

I do the first commit with some minor fixes:
- get Makefiles work
- fix rounding issue with tiles on unit faces
- removed UI includes from tex node

A nice doc in wiki is here:
http://wiki.blender.org/index.php/User:Frr/TexnodeManual

On the todo for Robin is:
- When using one or more Texture-input nodes, you cannot edit them by activating
  (as works now for Material nodes).
- The new "output node" option fails on the default case, when only one
  output node is active. It then shows often a blank menu. Will get fixed asap.
- When using a NodeTree-Texture as input node, the menu for 'active output'
  should not show. NodeTree should ignore other nodetrees to keep things sane
  for now.
- On a future todo is proper usage of "Dxt" and "Dyt" texture vectors for
  superior antialising of checkers/bricks.

General note; I know people are dying to get a full integrated shader system
with nodes. In theory we could merge this with Material Nodetrees... but I
rather wait for a solid and very well thought out design proposal for this,
also including design ideas for unifying with a shader language (GPU, CPU).
For the time being this is a nice extension of current textures. :)

49 files changed:
source/Makefile
source/blender/blenkernel/BKE_node.h
source/blender/blenkernel/intern/library.c
source/blender/blenkernel/intern/material.c
source/blender/blenkernel/intern/node.c
source/blender/blenkernel/intern/texture.c
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/writefile.c
source/blender/include/BSE_node.h
source/blender/include/blendef.h
source/blender/include/butspace.h
source/blender/makesdna/DNA_node_types.h
source/blender/makesdna/DNA_texture_types.h
source/blender/nodes/Makefile
source/blender/nodes/SConscript
source/blender/nodes/intern/SHD_nodes/SHD_texture.c
source/blender/nodes/intern/SHD_util.c
source/blender/nodes/intern/TEX_nodes/Makefile [new file with mode: 0644]
source/blender/nodes/intern/TEX_nodes/TEX_bricks.c [new file with mode: 0644]
source/blender/nodes/intern/TEX_nodes/TEX_checker.c [new file with mode: 0644]
source/blender/nodes/intern/TEX_nodes/TEX_curves.c [new file with mode: 0644]
source/blender/nodes/intern/TEX_nodes/TEX_hueSatVal.c [new file with mode: 0644]
source/blender/nodes/intern/TEX_nodes/TEX_image.c [new file with mode: 0644]
source/blender/nodes/intern/TEX_nodes/TEX_invert.c [new file with mode: 0644]
source/blender/nodes/intern/TEX_nodes/TEX_math.c [new file with mode: 0644]
source/blender/nodes/intern/TEX_nodes/TEX_mixRgb.c [new file with mode: 0644]
source/blender/nodes/intern/TEX_nodes/TEX_output.c [new file with mode: 0644]
source/blender/nodes/intern/TEX_nodes/TEX_proc.c [new file with mode: 0644]
source/blender/nodes/intern/TEX_nodes/TEX_rotate.c [new file with mode: 0644]
source/blender/nodes/intern/TEX_nodes/TEX_texture.c [new file with mode: 0644]
source/blender/nodes/intern/TEX_nodes/TEX_translate.c [new file with mode: 0644]
source/blender/nodes/intern/TEX_nodes/TEX_valToRgb.c [new file with mode: 0644]
source/blender/nodes/intern/TEX_nodes/TEX_viewer.c [new file with mode: 0644]
source/blender/nodes/intern/TEX_util.h [new file with mode: 0644]
source/blender/render/extern/include/RE_shader_ext.h
source/blender/render/intern/include/pixelshading.h
source/blender/render/intern/include/texture.h
source/blender/render/intern/source/convertblender.c
source/blender/render/intern/source/pixelshading.c
source/blender/render/intern/source/rayshade.c
source/blender/render/intern/source/rendercore.c
source/blender/render/intern/source/texture.c
source/blender/src/butspace.c
source/blender/src/buttons_shading.c
source/blender/src/drawnode.c
source/blender/src/editnode.c
source/blender/src/header_node.c
source/blender/src/headerbuttons.c
source/blender/src/toolbox.c

index 558a844eca790df8d58096d6b7f3e663e45f54cd..662cb1df0a6e28a8258e52487342f177d8bbf951 100644 (file)
@@ -97,6 +97,7 @@ COMLIB += $(OCGDIR)/blender/blenloader/$(DEBUG_DIR)libblenloader.a
 COMLIB += $(OCGDIR)/blender/blenpluginapi/$(DEBUG_DIR)libblenpluginapi.a
 COMLIB += $(OCGDIR)/blender/nodes_shd/$(DEBUG_DIR)libnodes_shd.a
 COMLIB += $(OCGDIR)/blender/nodes_cmp/$(DEBUG_DIR)libnodes_cmp.a
+COMLIB += $(OCGDIR)/blender/nodes_tex/$(DEBUG_DIR)libnodes_tex.a
 COMLIB += $(OCGDIR)/blender/nodes/$(DEBUG_DIR)libnodes.a
 COMLIB += $(OCGDIR)/blender/imbuf/$(DEBUG_DIR)libimbuf.a
 COMLIB += $(OCGDIR)/blender/blenlib/$(DEBUG_DIR)libblenlib.a
index 01c54663c6d9e34b43a62eecd9d7a09ad40448b7..fa3a654c1c271572c096b517d859716061ac97cf 100644 (file)
@@ -47,6 +47,7 @@ struct rctf;
 struct ListBase;
 struct RenderData;
 struct Scene;
+struct Tex;
 struct GPUMaterial;
 struct GPUNode;
 struct GPUNodeStack;
@@ -118,6 +119,8 @@ typedef struct bNodeType {
 #define NODE_CLASS_MATTE               9
 #define NODE_CLASS_DISTORT             10
 #define NODE_CLASS_OP_DYNAMIC  11
+#define NODE_CLASS_PATTERN 12
+#define NODE_CLASS_TEXTURE 13
 
 /* ************** GENERIC API, TREES *************** */
 
@@ -377,6 +380,45 @@ void ntreeCompositForceHidden(struct bNodeTree *ntree);
 
 void free_compbuf(struct CompBuf *cbuf); /* internal...*/
 
+
+/* ************** TEXTURE NODES *************** */
+
+struct TexResult;
+
+#define TEX_NODE_OUTPUT     101
+#define TEX_NODE_CHECKER    102
+#define TEX_NODE_TEXTURE    103
+#define TEX_NODE_BRICKS     104
+#define TEX_NODE_MATH       105
+#define TEX_NODE_MIX_RGB    106
+#define TEX_NODE_RGBTOBW    107
+#define TEX_NODE_VALTORGB   108
+#define TEX_NODE_IMAGE      109
+#define TEX_NODE_CURVE_RGB  110
+#define TEX_NODE_INVERT     111
+#define TEX_NODE_HUE_SAT    112
+#define TEX_NODE_CURVE_TIME 113
+#define TEX_NODE_ROTATE     114
+#define TEX_NODE_VIEWER     115
+#define TEX_NODE_TRANSLATE  116
+
+/* 201-299 reserved. Use like this: TEX_NODE_PROC + TEX_CLOUDS, etc */
+#define TEX_NODE_PROC      200
+#define TEX_NODE_PROC_MAX  300
+
+extern struct ListBase node_all_textures;
+
+/* API */
+int  ntreeTexTagAnimated(struct bNodeTree *ntree);
+void ntreeTexUpdatePreviews( struct bNodeTree* nodetree );
+void ntreeTexExecTree(struct bNodeTree *ntree, struct TexResult *target, float *coord, char do_preview, short thread, struct Tex *tex, short which_output);
+void ntreeTexCheckCyclics(struct bNodeTree *ntree);
+void ntreeTexAssignIndex(struct bNodeTree *ntree, struct bNode *node);
+char* ntreeTexOutputMenu(struct bNodeTree *ntree);
+
+
+/**/
+
 void init_nodesystem(void);
 void free_nodesystem(void);
 
index 3d1b342bf732d88f942d0aa50abdac1e1cd9611a..33c1a4da4c786b5e2db7b677cacd0b8b2192752b 100644 (file)
@@ -597,6 +597,8 @@ static void get_flags_for_id(ID *id, char *buf)
 
        if(GS(id->name)==ID_MA)
                isnode= ((Material *)id)->use_nodes;
+       if(GS(id->name)==ID_TE)
+               isnode= ((Tex *)id)->use_nodes;
        
        if (id->us<0)
                sprintf(buf, "-1W ");
index 27f4fd3bc051110fa1458dbb6631a937cdd8aff3..753058b1fdda661d2048eb7515ceb7d4fe24c566 100644 (file)
@@ -650,7 +650,7 @@ static void do_init_render_material(Material *ma, int r_mode, float *amb)
                if(ma->septex & (1<<a)) continue;
 
                mtex= ma->mtex[a];
-               if(mtex && mtex->tex && mtex->tex->type) {
+               if(mtex && mtex->tex && (mtex->tex->type | (mtex->tex->use_nodes && mtex->tex->nodetree) )) {
                        
                        ma->texco |= mtex->texco;
                        ma->mapto |= mtex->mapto;
index b881b681ed9872cc1bb34cddcb7e6ee25c6f8cb6..ae81a31c37365b825dbfd6737fe9a315602a9213 100644 (file)
@@ -38,6 +38,7 @@
 #include "DNA_image_types.h"
 #include "DNA_node_types.h"
 #include "DNA_material_types.h"
+#include "DNA_texture_types.h"
 #include "DNA_text_types.h"
 #include "DNA_scene_types.h"
 
@@ -70,6 +71,8 @@
 #include "intern/CMP_util.h"   /* stupid include path... */
 
 #include "SHD_node.h"
+#include "TEX_node.h"
+#include "intern/TEX_util.h"
 
 #include "GPU_extensions.h"
 #include "GPU_material.h"
@@ -77,6 +80,7 @@
 static ListBase empty_list = {NULL, NULL};
 ListBase node_all_composit = {NULL, NULL};
 ListBase node_all_shaders = {NULL, NULL};
+ListBase node_all_textures = {NULL, NULL};
 
 /* ************** Type stuff **********  */
 
@@ -106,6 +110,8 @@ void ntreeInitTypes(bNodeTree *ntree)
                ntree->alltypes= node_all_shaders;
        else if(ntree->type==NTREE_COMPOSIT)
                ntree->alltypes= node_all_composit;
+       else if(ntree->type==NTREE_TEXTURE)
+               ntree->alltypes= node_all_textures;
        else {
                ntree->alltypes= empty_list;
                printf("Error: no type definitions for nodes\n");
@@ -661,6 +667,28 @@ void nodeVerifyGroup(bNodeTree *ngroup)
                        }
                }
        }
+       else if(ngroup->type==NTREE_TEXTURE) {
+               Tex *tx;
+               for(tx= G.main->tex.first; tx; tx= tx->id.next) {
+                       if(tx->nodetree) {
+                               bNode *node;
+                               
+                               /* find if group is in tree */
+                               for(node= tx->nodetree->nodes.first; node; node= node->next)
+                                       if(node->id == (ID *)ngroup)
+                                               break;
+                               
+                               if(node) {
+                                       /* set all type pointers OK */
+                                       ntreeInitTypes(tx->nodetree);
+                                       
+                                       for(node= tx->nodetree->nodes.first; node; node= node->next)
+                                               if(node->id == (ID *)ngroup)
+                                                       nodeVerifyType(tx->nodetree, node);
+                               }
+                       }
+               }
+       }
 }
 
 /* also to check all users of groups. Now only used in editor for hide/unhide */
@@ -717,6 +745,26 @@ void nodeGroupSocketUseFlags(bNodeTree *ngroup)
                        }
                }
        }
+       else if(ngroup->type==NTREE_TEXTURE) {
+               Tex *tx;
+               for(tx= G.main->tex.first; tx; tx= tx->id.next) {
+                       if(tx->nodetree) {
+                               for(node= tx->nodetree->nodes.first; node; node= node->next) {
+                                       if(node->id==(ID *)ngroup) {
+                                               for(sock= node->inputs.first; sock; sock= sock->next)
+                                                       if(sock->link)
+                                                               if(sock->tosock) 
+                                                                       sock->tosock->flag |= SOCK_IN_USE;
+                                               for(sock= node->outputs.first; sock; sock= sock->next)
+                                                       if(nodeCountSocketLinks(tx->nodetree, sock))
+                                                               if(sock->tosock) 
+                                                                       sock->tosock->flag |= SOCK_IN_USE;
+                                       }
+                               }
+                       }
+               }
+       }
+       
 }
 
 /* finds a node based on given socket */
@@ -901,9 +949,12 @@ bNode *nodeAddNodeType(bNodeTree *ntree, int type, bNodeTree *ngroup, ID *id)
        /* got it-bob*/
        if(ntype->initfunc!=NULL)
                ntype->initfunc(node);
+       
+       if(type==TEX_NODE_OUTPUT)
+               ntreeTexAssignIndex(ntree, node);
 
        nodeAddSockets(node, ntype);
-
+       
        return node;
 }
 
@@ -970,6 +1021,9 @@ bNode *nodeCopyNode(struct bNodeTree *ntree, struct bNode *node, int internal)
        node->new_node= nnode;
        nnode->new_node= NULL;
        nnode->preview= NULL;
+       
+       if(node->type==TEX_NODE_OUTPUT)
+               ntreeTexAssignIndex(ntree, node);
 
        return nnode;
 }
@@ -1260,6 +1314,22 @@ void ntreeMakeLocal(bNodeTree *ntree)
                        }
                }
        }
+       else if(ntree->type==NTREE_TEXTURE) {
+               Tex *tx;
+               for(tx= G.main->tex.first; tx; tx= tx->id.next) {
+                       if(tx->nodetree) {
+                               bNode *node;
+                               
+                               /* find if group is in tree */
+                               for(node= tx->nodetree->nodes.first; node; node= node->next) {
+                                       if(node->id == (ID *)ntree) {
+                                               if(tx->id.lib) lib= 1;
+                                               else local= 1;
+                                       }
+                               }
+                       }
+               }
+       }
        
        /* if all users are local, we simply make tree local */
        if(local && lib==0) {
@@ -1311,6 +1381,25 @@ void ntreeMakeLocal(bNodeTree *ntree)
                                }
                        }
                }
+               else if(ntree->type==NTREE_TEXTURE) {
+                       Tex *tx;
+                       for(tx= G.main->tex.first; tx; tx= tx->id.next) {
+                               if(tx->nodetree) {
+                                       bNode *node;
+                                       
+                                       /* find if group is in tree */
+                                       for(node= tx->nodetree->nodes.first; node; node= node->next) {
+                                               if(node->id == (ID *)ntree) {
+                                                       if(tx->id.lib==NULL) {
+                                                               node->id= &newtree->id;
+                                                               newtree->id.us++;
+                                                               ntree->id.us--;
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               }
        }
 }
 
@@ -1575,6 +1664,8 @@ void NodeTagChanged(bNodeTree *ntree, bNode *node)
                }
                node->need_exec= 1;
        }
+       else if(ntree->type == NTREE_TEXTURE)
+               ntreeTexUpdatePreviews(ntree);
 }
 
 void NodeTagIDChanged(bNodeTree *ntree, ID *id)
@@ -1813,7 +1904,7 @@ static void composit_begin_exec(bNodeTree *ntree, int is_group)
                                        sock->ns.data= NULL;
                                }
                        }
-               }               
+               }
                /* cannot initialize them while using in threads */
                if(ELEM3(node->type, CMP_NODE_TIME, CMP_NODE_CURVE_VEC, CMP_NODE_CURVE_RGB)) {
                        curvemapping_initialize(node->storage);
@@ -1929,12 +2020,28 @@ static void ntreeReleaseThreadStack(bNodeThreadStack *nts)
        nts->used= 0;
 }
 
+/* free texture delegates */
+static void tex_end_exec(bNodeTree *ntree)
+{
+       bNodeThreadStack *nts;
+       bNodeStack *ns;
+       int th, a;
+       
+       if(ntree->threadstack)
+               for(th=0; th<BLENDER_MAX_THREADS; th++)
+                       for(nts=ntree->threadstack[th].first; nts; nts=nts->next)
+                               for(ns= nts->stack, a=0; a<ntree->stacksize; a++, ns++)
+                                       if(ns->data)
+                                               MEM_freeN(ns->data);
+                                               
+}
+
 void ntreeBeginExecTree(bNodeTree *ntree)
 {
        /* let's make it sure */
        if(ntree->init & NTREE_EXEC_INIT)
                return;
-
+       
        /* allocate the thread stack listbase array */
        if(ntree->type!=NTREE_COMPOSIT)
                ntree->threadstack= MEM_callocN(BLENDER_MAX_THREADS*sizeof(ListBase), "thread stack array");
@@ -1986,6 +2093,8 @@ void ntreeEndExecTree(bNodeTree *ntree)
                /* another callback candidate! */
                if(ntree->type==NTREE_COMPOSIT)
                        composit_end_exec(ntree, 0);
+               else if(ntree->type==NTREE_TEXTURE)
+                       tex_end_exec(ntree);
                
                if(ntree->stack) {
                        MEM_freeN(ntree->stack);
@@ -2622,6 +2731,27 @@ void ntreeCompositTagGenerators(bNodeTree *ntree)
        }
 }
 
+int ntreeTexTagAnimated(bNodeTree *ntree)
+{
+       bNode *node;
+       
+       if(ntree==NULL) return 0;
+       
+       for(node= ntree->nodes.first; node; node= node->next) {
+               if(node->type==TEX_NODE_CURVE_TIME) {
+                       NodeTagChanged(ntree, node);
+                       return 1;
+               }
+               else if(node->type==NODE_GROUP) {
+                       if( ntreeTexTagAnimated((bNodeTree *)node->id) ) {
+                               return 1;
+                       }
+               }
+       }
+       
+       return 0;
+}
+
 /* ************* node definition init ********** */
 
 static bNodeType *is_nodetype_registered(ListBase *typelist, int type, ID *id) 
@@ -2745,6 +2875,41 @@ static void registerShaderNodes(ListBase *ntypelist)
        nodeRegisterType(ntypelist, &sh_node_hue_sat);
 }
 
+static void registerTextureNodes(ListBase *ntypelist)
+{
+       nodeRegisterType(ntypelist, &node_group_typeinfo);
+       nodeRegisterType(ntypelist, &tex_node_math);
+       nodeRegisterType(ntypelist, &tex_node_mix_rgb);
+       nodeRegisterType(ntypelist, &tex_node_valtorgb);
+       nodeRegisterType(ntypelist, &tex_node_rgbtobw);
+       nodeRegisterType(ntypelist, &tex_node_curve_rgb);
+       nodeRegisterType(ntypelist, &tex_node_curve_time);
+       nodeRegisterType(ntypelist, &tex_node_invert);
+       nodeRegisterType(ntypelist, &tex_node_hue_sat);
+       
+       nodeRegisterType(ntypelist, &tex_node_output);
+       nodeRegisterType(ntypelist, &tex_node_viewer);
+       
+       nodeRegisterType(ntypelist, &tex_node_checker);
+       nodeRegisterType(ntypelist, &tex_node_texture);
+       nodeRegisterType(ntypelist, &tex_node_bricks);
+       nodeRegisterType(ntypelist, &tex_node_image);
+       
+       nodeRegisterType(ntypelist, &tex_node_rotate);
+       nodeRegisterType(ntypelist, &tex_node_translate);
+       
+       nodeRegisterType(ntypelist, &tex_node_proc_voronoi);
+       nodeRegisterType(ntypelist, &tex_node_proc_blend);
+       nodeRegisterType(ntypelist, &tex_node_proc_magic);
+       nodeRegisterType(ntypelist, &tex_node_proc_marble);
+       nodeRegisterType(ntypelist, &tex_node_proc_clouds);
+       nodeRegisterType(ntypelist, &tex_node_proc_wood);
+       nodeRegisterType(ntypelist, &tex_node_proc_musgrave);
+       nodeRegisterType(ntypelist, &tex_node_proc_noise);
+       nodeRegisterType(ntypelist, &tex_node_proc_stucci);
+       nodeRegisterType(ntypelist, &tex_node_proc_distnoise);
+}
+
 static void remove_dynamic_typeinfos(ListBase *list)
 {
        bNodeType *ntype= list->first;
@@ -2782,6 +2947,7 @@ void init_nodesystem(void)
 {
        registerCompositNodes(&node_all_composit);
        registerShaderNodes(&node_all_shaders);
+       registerTextureNodes(&node_all_textures);
 }
 
 void free_nodesystem(void) 
@@ -2790,4 +2956,5 @@ void free_nodesystem(void)
        BLI_freelistN(&node_all_composit);
        remove_dynamic_typeinfos(&node_all_shaders);
        BLI_freelistN(&node_all_shaders);
+       BLI_freelistN(&node_all_textures);
 }
index ab9e6f9af415c33d5569a459b9369a6eb16c4986..52b88de06e0a1d3538d1cdb5fc3b1805838104ac 100644 (file)
@@ -421,6 +421,11 @@ void free_texture(Tex *tex)
        BKE_previewimg_free(&tex->preview);
        BKE_icon_delete((struct ID*)tex);
        tex->id.icon_id = 0;
+       
+       if(tex->nodetree) {
+               ntreeFreeTree(tex->nodetree);
+               MEM_freeN(tex->nodetree);
+       }
 }
 
 /* ------------------------------------------------------------------------- */
@@ -578,6 +583,11 @@ Tex *copy_texture(Tex *tex)
        
        if(tex->preview) texn->preview = BKE_previewimg_copy(tex->preview);
 
+       if(tex->nodetree) {
+               ntreeEndExecTree(tex->nodetree);
+               texn->nodetree= ntreeCopyTree(tex->nodetree, 0); /* 0 == full new tree */
+       }
+       
        return texn;
 }
 
@@ -728,6 +738,10 @@ void autotexname(Tex *tex)
        char di[FILE_MAXDIR], fi[FILE_MAXFILE];
        
        if(tex) {
+               if(tex->use_nodes) {
+                       new_id(&G.main->tex, (ID *)tex, "Noddy");
+               }
+               else
                if(tex->type==TEX_IMAGE) {
                        ima= tex->ima;
                        if(ima) {
index acedf51e6191f050d02e7e8c67f3d8bd12766661..423d050c8622d5b67929e6097a5f4e4e69f790a4 100644 (file)
@@ -1524,6 +1524,7 @@ static void lib_verify_nodetree(Main *main, int open)
 {
        Scene *sce;
        Material *ma;
+       Tex *tx;
        bNodeTree *ntree;
 
        /* this crashes blender on undo/redo
@@ -1548,6 +1549,11 @@ static void lib_verify_nodetree(Main *main, int open)
                if(sce->nodetree)
                        ntreeVerifyTypes(sce->nodetree);
        }
+       /* and texture trees */
+       for(tx= main->tex.first; tx; tx= tx->id.next) {
+               if(tx->nodetree)
+                       ntreeVerifyTypes(tx->nodetree);
+       }
 }
 
 
@@ -1584,6 +1590,9 @@ static void direct_link_nodetree(FileData *fd, bNodeTree *ntree)
                                else if(ELEM3(node->type, CMP_NODE_IMAGE, CMP_NODE_VIEWER, CMP_NODE_SPLITVIEWER))
                                        ((ImageUser *)node->storage)->ok= 1;
                        }
+                       else if( ntree->type==NTREE_TEXTURE && (node->type==TEX_NODE_CURVE_RGB || node->type==TEX_NODE_CURVE_TIME) ) {
+                               direct_link_curvemapping(fd, node->storage);
+                       }
                }
                link_list(fd, &node->inputs);
                link_list(fd, &node->outputs);
@@ -2490,6 +2499,9 @@ static void lib_link_texture(FileData *fd, Main *main)
                        tex->ipo= newlibadr_us(fd, tex->id.lib, tex->ipo);
                        if(tex->env) tex->env->object= newlibadr(fd, tex->id.lib, tex->env->object);
 
+                       if(tex->nodetree)
+                               lib_link_ntree(fd, &tex->id, tex->nodetree);
+                       
                        tex->id.flag -= LIB_NEEDLINK;
                }
                tex= tex->id.next;
@@ -2515,6 +2527,11 @@ static void direct_link_texture(FileData *fd, Tex *tex)
                memset(tex->env->cube, 0, 6*sizeof(void *));
                tex->env->ok= 0;
        }
+       
+       tex->nodetree= newdataadr(fd, tex->nodetree);
+       if(tex->nodetree)
+               direct_link_nodetree(fd, tex->nodetree);
+       
        tex->preview = direct_link_preview_image(fd, tex->preview);
 
        tex->iuser.ok= 1;
@@ -8306,11 +8323,23 @@ static void expand_key(FileData *fd, Main *mainvar, Key *key)
        expand_doit(fd, mainvar, key->ipo);
 }
 
+static void expand_nodetree(FileData *fd, Main *mainvar, bNodeTree *ntree)
+{
+       bNode *node;
+       
+       for(node= ntree->nodes.first; node; node= node->next)
+               if(node->id && node->type!=CMP_NODE_R_LAYERS)
+                       expand_doit(fd, mainvar, node->id);
+
+}
 
 static void expand_texture(FileData *fd, Main *mainvar, Tex *tex)
 {
        expand_doit(fd, mainvar, tex->ima);
        expand_doit(fd, mainvar, tex->ipo);
+       
+       if(tex->nodetree)
+               expand_nodetree(fd, mainvar, tex->nodetree);
 }
 
 static void expand_brush(FileData *fd, Main *mainvar, Brush *brush)
@@ -8323,16 +8352,6 @@ static void expand_brush(FileData *fd, Main *mainvar, Brush *brush)
        expand_doit(fd, mainvar, brush->clone.image);
 }
 
-static void expand_nodetree(FileData *fd, Main *mainvar, bNodeTree *ntree)
-{
-       bNode *node;
-       
-       for(node= ntree->nodes.first; node; node= node->next)
-               if(node->id && node->type!=CMP_NODE_R_LAYERS)
-                       expand_doit(fd, mainvar, node->id);
-
-}
-
 static void expand_material(FileData *fd, Main *mainvar, Material *ma)
 {
        int a;
index e9d9fae0936eb80574348d013fa11958771609d3..e06e7eb2d85f2aa35488630cfb43920055a01bb6 100644 (file)
@@ -470,6 +470,8 @@ static void write_nodetree(WriteData *wd, bNodeTree *ntree)
                                write_curvemapping(wd, node->storage);
                        else if(ntree->type==NTREE_COMPOSIT && (node->type==CMP_NODE_TIME || node->type==CMP_NODE_CURVE_VEC || node->type==CMP_NODE_CURVE_RGB))
                                write_curvemapping(wd, node->storage);
+                       else if(ntree->type==NTREE_TEXTURE && (node->type==TEX_NODE_CURVE_RGB || node->type==TEX_NODE_CURVE_TIME) )
+                               write_curvemapping(wd, node->storage);
                        else 
                                writestruct(wd, DATA, node->typeinfo->storagename, 1, node->storage);
                }
@@ -1334,6 +1336,12 @@ static void write_textures(WriteData *wd, ListBase *idbase)
                        if(tex->coba) writestruct(wd, DATA, "ColorBand", 1, tex->coba);
                        if(tex->env) writestruct(wd, DATA, "EnvMap", 1, tex->env);
                        
+                       /* nodetree is integral part of texture, no libdata */
+                       if(tex->nodetree) {
+                               writestruct(wd, DATA, "bNodeTree", 1, tex->nodetree);
+                               write_nodetree(wd, tex->nodetree);
+                       }
+                       
                        write_previews(wd, tex->preview);
                }
                tex= tex->id.next;
index 0e9e511e9e6dd406c38a3e2bf539cbc15d552f31..d0656f09a462b0499700e3e82e5e0b669d69653d 100644 (file)
@@ -81,6 +81,7 @@ void node_active_link_viewer(struct SpaceNode *snode);
 void node_transform_ext(int mode, int unused);
 void node_shader_default(struct Material *ma);
 void node_composit_default(struct Scene *scene);
+void node_texture_default(struct Tex *tx);
 
 int node_has_hidden_sockets(struct bNode *node);
 
index 50179325609961cc41ed265259d215cd280baea0..60d3a589c513fced9341fc6f94dde9ff2b8cd5e0 100644 (file)
 /* NODE: 851-900 */
 #define B_NODE_USEMAT          851
 #define B_NODE_USESCENE                852
+#define B_NODE_USETEX          853
 
 /* FREE 901 - 999 */
 
index 8cac5a074ab54916c39505c6f0682c108c5a3c47..fd3f6e926b9ec98badc464205632c5fc30dd6169 100644 (file)
@@ -258,6 +258,7 @@ void curvemap_buttons(struct uiBlock *block, struct CurveMapping *cumap, char la
 #define B_ENV_OB               1354
 
 #define B_ENV_FREE_ALL 1357
+#define B_TEX_USENODES         1358
 
 
 /* **************** animbuts = object buttons ******* */
index eda37d952c111198ea82994845d3cdca135f5dc0..d5eb4024dcc8ee26b782f2c22c47307a8ec71d1a 100644 (file)
@@ -121,6 +121,7 @@ typedef struct bNode {
        float locx, locy;               /* root offset for drawing */
        float width, miniwidth;                 
        short custom1, custom2; /* to be abused for buttons */
+       float custom3, custom4;
        
        short need_exec, exec;  /* need_exec is set as UI execution event, exec is flag during exec */
        
@@ -156,7 +157,7 @@ typedef struct bNodeLink {
 } bNodeLink;
 
 /* the basis for a Node tree, all links and nodes reside internal here */
-/* only re-usable node trees are in the library though, materials allocate own tree struct */
+/* only re-usable node trees are in the library though, materials and textures allocate own tree struct */
 typedef struct bNodeTree {
        ID id;
        
@@ -185,6 +186,7 @@ typedef struct bNodeTree {
 /* ntree->type, index */
 #define NTREE_SHADER   0
 #define NTREE_COMPOSIT 1
+#define NTREE_TEXTURE   2
 
 /* ntree->init, flag */
 #define NTREE_TYPE_INIT        1
@@ -285,4 +287,9 @@ typedef struct NodeLensDist {
        short jit, proj, fit, pad;
 } NodeLensDist;
 
+/* TEX_output */
+typedef struct TexNodeOutput {
+       char name[32];
+} TexNodeOutput;
+
 #endif
index 111dc08ee02dafe9eded41146af798b96338343a..6e07336a4b153ae32c752103a7666a78b445f513 100644 (file)
@@ -55,13 +55,13 @@ typedef struct MTex {
        float ofs[3], size[3];
        
        short texflag, colormodel, pmapto, pmaptoneg;
-       short normapspace, pad[3];
+       short normapspace, which_output, pad[2];
        float r, g, b, k;
        float def_var, rt;
        
        float colfac, norfac, varfac;
        float dispfac; 
-       float warpfac; 
+       float warpfac;
        
 } MTex;
 
@@ -166,6 +166,7 @@ typedef struct Tex {
        
        struct ImageUser iuser;
        
+       struct bNodeTree *nodetree;
        struct Ipo *ipo;
        struct Image *ima;
        struct PluginTex *plugin;
@@ -173,6 +174,9 @@ typedef struct Tex {
        struct EnvMap *env;
        struct PreviewImage * preview;
        
+       char use_nodes;
+       char pad[7];
+       
 } Tex;
 
 /* used for mapping node. note: rot is in degrees */
index ee0c82fad623c8c8359ac4d2180503b3f0e42dbb..39d85d26feffde6209b60b59d76e100242dd4e7c 100644 (file)
@@ -29,6 +29,6 @@
 # Bounces make to subdirectories.
 
 SOURCEDIR = source/blender/nodes
-DIRS = intern intern/CMP_nodes intern/SHD_nodes
+DIRS = intern intern/CMP_nodes intern/SHD_nodes intern/TEX_nodes
 
 include nan_subdirs.mk
index 0cfef20dae78e453783c59a9c50242c694fb6050..91ca6cd8c813e12bb58b7b9eb1384f792d59dce3 100644 (file)
@@ -4,6 +4,7 @@ Import ('env')
 sources = env.Glob('intern/*.c')
 sources += env.Glob('intern/CMP_nodes/*.c')
 sources += env.Glob('intern/SHD_nodes/*.c')
+sources += env.Glob('intern/TEX_nodes/*.c')
 
 incs = '. ./intern '
 incs += '#/intern/guardedalloc ../include ../blenlib ../makesdna'
index 31dbde940fd5eb637bf6aa2b6a45049fca3ff3ab..908cbf5abfdc179f1994f5b0fc2bad81ace90153 100644 (file)
@@ -50,6 +50,9 @@ static void node_shader_exec_texture(void *data, bNode *node, bNodeStack **in, b
                TexResult texres;
                float vec[3], nor[3]={0.0f, 0.0f, 0.0f};
                int retval;
+               short which_output = node->custom1;
+               
+               short thread = shi->thread;
                
                /* out: value, color, normal */
                
@@ -61,7 +64,7 @@ static void node_shader_exec_texture(void *data, bNode *node, bNodeStack **in, b
                        
                        if(in[0]->datatype==NS_OSA_VECTORS) {
                                float *fp= in[0]->data;
-                               retval= multitex_ext((Tex *)node->id, vec, fp, fp+3, shi->osatex, &texres);
+                               retval= multitex_thread((Tex *)node->id, vec, fp, fp+3, shi->osatex, &texres, thread, which_output);
                        }
                        else if(in[0]->datatype==NS_OSA_VALUES) {
                                float *fp= in[0]->data;
@@ -69,14 +72,14 @@ static void node_shader_exec_texture(void *data, bNode *node, bNodeStack **in, b
                                
                                dxt[0]= fp[0]; dxt[1]= dxt[2]= 0.0f;
                                dyt[0]= fp[1]; dyt[1]= dyt[2]= 0.0f;
-                               retval= multitex_ext((Tex *)node->id, vec, dxt, dyt, shi->osatex, &texres);
+                               retval= multitex_thread((Tex *)node->id, vec, dxt, dyt, shi->osatex, &texres, thread, which_output);
                        }
                        else
-                               retval= multitex_ext((Tex *)node->id, vec, NULL, NULL, 0, &texres);
+                               retval= multitex_thread((Tex *)node->id, vec, NULL, NULL, 0, &texres, thread, which_output);
                }
-               else {  /* only for previewrender, so we see stuff */
+               else {
                        VECCOPY(vec, shi->lo);
-                       retval= multitex_ext((Tex *)node->id, vec, NULL, NULL, 0, &texres);
+                       retval= multitex_thread((Tex *)node->id, vec, NULL, NULL, 0, &texres, thread, which_output);
                }
                
                /* stupid exception */
index f673834d2b77280fa83bc34f89660aa8b08d417a..b5e82db8a933ea8a68bc9dc0ebcafb585a287c36 100644 (file)
@@ -82,6 +82,7 @@ void ntreeShaderExecTree(bNodeTree *ntree, ShadeInput *shi, ShadeResult *shr)
        /* convert caller data to struct */
        scd.shi= shi;
        scd.shr= shr;
+       
        /* each material node has own local shaderesult, with optional copying */
        memset(shr, 0, sizeof(ShadeResult));
                   
diff --git a/source/blender/nodes/intern/TEX_nodes/Makefile b/source/blender/nodes/intern/TEX_nodes/Makefile
new file mode 100644 (file)
index 0000000..7fad19a
--- /dev/null
@@ -0,0 +1,48 @@
+#
+# $Id: Makefile 12796 2007-12-05 16:58:52Z sirdude $
+#
+# ***** BEGIN GPL/BL DUAL 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. The Blender
+# Foundation also sells licenses for use in proprietary software under
+# the Blender License.  See http://www.blender.org/BL/ for information
+# about this.
+#
+# 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) 2001-2002 by NaN Holding BV.
+# All rights reserved.
+#
+# The Original Code is: all of this file.
+#
+# Contributor(s): none yet.
+#
+# ***** END GPL/BL DUAL LICENSE BLOCK *****
+#
+#
+
+LIBNAME = nodes_tex
+DIR = $(OCGDIR)/blender/$(LIBNAME)
+
+include nan_compile.mk
+
+CFLAGS += $(LEVEL_1_C_WARNINGS)
+
+CPPFLAGS += -I../../../blenkernel
+CPPFLAGS += -I$(NAN_GUARDEDALLOC)/include
+CPPFLAGS += -I../../../makesdna
+CPPFLAGS += -I../../../blenlib
+CPPFLAGS += -I../../../include
+CPPFLAGS += -I../../../imbuf
+CPPFLAGS += -I../../../render/extern/include
+CPPFLAGS += -I$(OPENGL_HEADERS)
diff --git a/source/blender/nodes/intern/TEX_nodes/TEX_bricks.c b/source/blender/nodes/intern/TEX_nodes/TEX_bricks.c
new file mode 100644 (file)
index 0000000..c9fa352
--- /dev/null
@@ -0,0 +1,123 @@
+/**
+ *
+ * ***** 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 "../TEX_util.h"                                                   
+#include <math.h>
+
+static bNodeSocketType inputs[]= {
+       { SOCK_RGBA,  1, "Bricks 1",    0.596f, 0.282f, 0.0f,  1.0f,  0.0f,    1.0f },
+       { SOCK_RGBA,  1, "Bricks 2",    0.632f, 0.504f, 0.05f, 1.0f,  0.0f,    1.0f },
+       { SOCK_RGBA,  1, "Mortar",      0.0f,   0.0f,   0.0f,  1.0f,  0.0f,    1.0f },
+       { SOCK_VALUE, 1, "Thickness",   0.02f,  0.0f,   0.0f,  0.0f,  0.0f,    1.0f },
+       { SOCK_VALUE, 1, "Bias",        0.0f,   0.0f,   0.0f,  0.0f, -1.0f,    1.0f },
+       { SOCK_VALUE, 1, "Brick Width", 0.5f,   0.0f,   0.0f,  0.0f,  0.001f, 99.0f },
+       { SOCK_VALUE, 1, "Row Height",  0.25f,  0.0f,   0.0f,  0.0f,  0.001f, 99.0f },
+       { -1, 0, "" }
+};
+static bNodeSocketType outputs[]= {
+       { SOCK_RGBA, 0, "Color", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+       { -1, 0, ""     }
+};
+
+static void init(bNode *node) {
+       node->custom3 = 0.5; /* offset */
+       node->custom4 = 1.0; /* squash */
+}
+
+static void colorfn(float *out, float *coord, bNode *node, bNodeStack **in, short thread)
+{
+       float x = coord[0];
+       float y = coord[1];
+       
+       float bricknum, rownum, offset = 0;
+       float ins_x, ins_y;
+       float tint;
+       
+       float bricks1[4];
+       float bricks2[4];
+       float mortar[4];
+       
+       float mortar_thickness = tex_input_value(in[3], coord, thread);
+       float bias             = tex_input_value(in[4], coord, thread);
+       float brick_width      = tex_input_value(in[5], coord, thread);
+       float row_height       = tex_input_value(in[6], coord, thread);
+       
+       tex_input_rgba(bricks1, in[0], coord, thread);
+       tex_input_rgba(bricks2, in[1], coord, thread);
+       tex_input_rgba(mortar,  in[2], coord, thread);
+       
+       rownum = floor(y / row_height);
+       
+       if( node->custom1 && node->custom2 ) {
+               brick_width *= ((int)(rownum) % node->custom2 ) ? 1.0f : node->custom4;      /* squash */
+               offset = ((int)(rownum) % node->custom1 ) ? 0 : (brick_width*node->custom3); /* offset */
+       }
+       
+       bricknum = floor((x+offset) / brick_width);
+       
+       ins_x = (x+offset) - brick_width*bricknum;
+       ins_y = y - row_height*rownum;
+       
+       srand( (123456*rownum) + bricknum );
+       tint = rand() / (float)RAND_MAX + bias;
+       CLAMP(tint,0.0f,1.0f);
+       
+       if( ins_x < mortar_thickness || ins_y < mortar_thickness ||
+               ins_x > (brick_width - mortar_thickness) ||
+               ins_y > (row_height - mortar_thickness) ) {
+               QUATCOPY( out, mortar );
+       } else {
+               QUATCOPY( out, bricks1 );
+               ramp_blend( MA_RAMP_BLEND, out, out+1, out+2, tint, bricks2 );
+       }
+}
+
+static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+       tex_output(node, in, out[0], &colorfn);
+       
+       tex_do_preview(node, out[0], data);
+}
+
+bNodeType tex_node_bricks= {
+       /* *next,*prev */       NULL, NULL,
+       /* type code   */       TEX_NODE_BRICKS,
+       /* name        */       "Bricks",
+       /* width+range */       150, 60, 150,
+       /* class+opts  */       NODE_CLASS_PATTERN, NODE_OPTIONS | NODE_PREVIEW,
+       /* input sock  */       inputs,
+       /* output sock */       outputs,
+       /* storage     */       "", 
+       /* execfunc    */       exec,
+       /* butfunc     */       NULL,
+       /* initfunc    */       init,
+       /* freestoragefunc    */        NULL,
+       /* copystoragefunc    */        NULL,
+       /* id          */       NULL
+       
+};
diff --git a/source/blender/nodes/intern/TEX_nodes/TEX_checker.c b/source/blender/nodes/intern/TEX_nodes/TEX_checker.c
new file mode 100644 (file)
index 0000000..6035778
--- /dev/null
@@ -0,0 +1,85 @@
+/**
+ *
+ * ***** 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 "../TEX_util.h"                                                   
+#include <math.h>
+
+static bNodeSocketType inputs[]= {
+       { SOCK_RGBA, 1, "Color1", 1.0f, 0.0f, 0.0f, 1.0f,  0.0f, 1.0f },
+       { SOCK_RGBA, 1, "Color2", 1.0f, 1.0f, 1.0f, 1.0f,  0.0f, 1.0f },
+       { SOCK_VALUE, 1, "Size",   0.5f, 0.0f, 0.0f, 0.0f,  0.0f, 100.0f },
+       { -1, 0, "" }
+};
+static bNodeSocketType outputs[]= {
+       { SOCK_RGBA, 0, "Color", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f },
+       { -1, 0, "" }
+};
+
+static void colorfn(float *out, float *coord, bNode *node, bNodeStack **in, short thread)
+{
+       float x  = coord[0];
+       float y  = coord[1];
+       float z  = coord[2];
+       float sz = tex_input_value(in[2], coord, thread);
+       
+       /* 0.00001  because of unit sized stuff */
+       int xi = (int)fabs(floor(0.00001 + x / sz));
+       int yi = (int)fabs(floor(0.00001 + y / sz));
+       int zi = (int)fabs(floor(0.00001 + z / sz));
+       
+       if( (xi % 2 == yi % 2) == (zi % 2) ) {
+               tex_input_rgba(out, in[0], coord, thread);
+       } else {
+               tex_input_rgba(out, in[1], coord, thread);
+       } 
+}
+
+static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+       tex_output(node, in, out[0], &colorfn);
+       
+       tex_do_preview(node, out[0], data);
+}
+
+bNodeType tex_node_checker= {
+       /* *next,*prev */       NULL, NULL,
+       /* type code   */       TEX_NODE_CHECKER,
+       /* name        */       "Checker",
+       /* width+range */       100, 60, 150,
+       /* class+opts  */       NODE_CLASS_PATTERN, NODE_OPTIONS | NODE_PREVIEW,
+       /* input sock  */       inputs,
+       /* output sock */       outputs,
+       /* storage     */       "", 
+       /* execfunc    */       exec,
+       /* butfunc     */       NULL,
+       /* initfunc    */       NULL,
+       /* freestoragefunc    */        NULL,
+       /* copystoragefunc    */        NULL,
+       /* id          */       NULL
+       
+};
diff --git a/source/blender/nodes/intern/TEX_nodes/TEX_curves.c b/source/blender/nodes/intern/TEX_nodes/TEX_curves.c
new file mode 100644 (file)
index 0000000..8c86656
--- /dev/null
@@ -0,0 +1,127 @@
+/**
+ *
+ * ***** 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 "../TEX_util.h"
+
+/* **************** CURVE Time  ******************** */
+
+/* custom1 = sfra, custom2 = efra */
+static bNodeSocketType time_outputs[]= {
+       { SOCK_VALUE, 0, "Value",       1.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f },
+       { -1, 0, "" }
+};
+
+static void time_colorfn(float *out, float *coord, bNode *node, bNodeStack **in, short thread)
+{
+       /* stack order output: fac */
+       float fac= 0.0f;
+       
+       if(node->custom1 < node->custom2)
+               fac = (G.scene->r.cfra - node->custom1)/(float)(node->custom2-node->custom1);
+       
+       fac = curvemapping_evaluateF(node->storage, 0, fac);
+       out[0] = CLAMPIS(fac, 0.0f, 1.0f);
+}
+
+static void time_exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+       tex_output(node, in, out[0], &time_colorfn);
+}
+
+
+static void time_init(bNode* node)
+{
+   node->custom1= G.scene->r.sfra;
+   node->custom2= G.scene->r.efra;
+   node->storage= curvemapping_add(1, 0.0f, 0.0f, 1.0f, 1.0f);
+}
+
+bNodeType tex_node_curve_time= {
+       /* *next,*prev */       NULL, NULL,
+       /* type code   */       TEX_NODE_CURVE_TIME,
+       /* name        */       "Time",
+       /* width+range */       140, 100, 320,
+       /* class+opts  */       NODE_CLASS_INPUT, NODE_OPTIONS,
+       /* input sock  */       NULL,
+       /* output sock */       time_outputs,
+       /* storage     */       "CurveMapping",
+       /* execfunc    */       time_exec,
+       /* butfunc     */       NULL,
+       /* initfunc    */       time_init,
+       /* freestoragefunc    */        node_free_curves,
+       /* copystoragefunc    */        node_copy_curves,
+       /* id          */       NULL
+};
+
+/* **************** CURVE RGB  ******************** */
+static bNodeSocketType rgb_inputs[]= {
+       {       SOCK_RGBA, 1, "Color",  0.0f, 0.0f, 0.0f, 1.0f, -1.0f, 1.0f},
+       {       -1, 0, ""       }
+};
+
+static bNodeSocketType rgb_outputs[]= {
+       {       SOCK_RGBA, 0, "Color",  0.0f, 0.0f, 1.0f, 1.0f, -1.0f, 1.0f},
+       {       -1, 0, ""       }
+};
+
+static void rgb_colorfn(float *out, float *coord, bNode *node, bNodeStack **in, short thread)
+{
+       float cin[4];
+       tex_input_rgba(cin, in[0], coord, thread);
+       
+       curvemapping_evaluateRGBF(node->storage, out, cin);
+       out[3] = cin[3];
+}
+
+static void rgb_exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+       tex_output(node, in, out[0], &rgb_colorfn);
+}
+
+static void rgb_init(bNode *node)
+{
+       node->storage= curvemapping_add(4, 0.0f, 0.0f, 1.0f, 1.0f);
+}
+
+bNodeType tex_node_curve_rgb= {
+       /* *next,*prev */    NULL, NULL,
+       /* type code   */    TEX_NODE_CURVE_RGB,
+       /* name        */    "RGB Curves",
+       /* width+range */    200, 140, 320,
+       /* class+opts  */    NODE_CLASS_OP_COLOR, NODE_OPTIONS,
+       /* input sock  */    rgb_inputs,
+       /* output sock */    rgb_outputs,
+       /* storage     */    "CurveMapping",
+       /* execfunc    */    rgb_exec,
+       /* butfunc     */    NULL,      
+       /* initfunc    */     rgb_init,
+       /* freestoragefunc */ node_free_curves,
+       /* copystoragefunc */ node_copy_curves,
+       /* id          */     NULL
+};
+
diff --git a/source/blender/nodes/intern/TEX_nodes/TEX_hueSatVal.c b/source/blender/nodes/intern/TEX_nodes/TEX_hueSatVal.c
new file mode 100644 (file)
index 0000000..d1a3389
--- /dev/null
@@ -0,0 +1,104 @@
+/**
+ *
+ * ***** 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) 2006 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): Juho Vepsäläinen
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "../TEX_util.h"
+
+
+static bNodeSocketType inputs[]= {
+       {       SOCK_VALUE, 1, "Hue",                   0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+       {       SOCK_VALUE, 1, "Saturation",            1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 2.0f},
+       {       SOCK_VALUE, 1, "Value",                 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 2.0f},
+       {       SOCK_VALUE, 1, "Fac",                   1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+       {       SOCK_RGBA, 1, "Color",                  0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
+       {       -1, 0, ""       }
+};
+static bNodeSocketType outputs[]= {
+       {       SOCK_RGBA, 0, "Color",                  0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+       {       -1, 0, ""       }
+};
+
+static void do_hue_sat_fac(bNode *node, float *out, float hue, float sat, float val, float *in, float fac)
+{
+       if(fac != 0 && (hue != 0.5f || sat != 1 || val != 1)) {
+               float col[3], hsv[3], mfac= 1.0f - fac;
+               
+               rgb_to_hsv(in[0], in[1], in[2], hsv, hsv+1, hsv+2);
+               hsv[0]+= (hue - 0.5f);
+               if(hsv[0]>1.0) hsv[0]-=1.0; else if(hsv[0]<0.0) hsv[0]+= 1.0;
+               hsv[1]*= sat;
+               if(hsv[1]>1.0) hsv[1]= 1.0; else if(hsv[1]<0.0) hsv[1]= 0.0;
+               hsv[2]*= val;
+               if(hsv[2]>1.0) hsv[2]= 1.0; else if(hsv[2]<0.0) hsv[2]= 0.0;
+               hsv_to_rgb(hsv[0], hsv[1], hsv[2], col, col+1, col+2);
+               
+               out[0]= mfac*in[0] + fac*col[0];
+               out[1]= mfac*in[1] + fac*col[1];
+               out[2]= mfac*in[2] + fac*col[2];
+       }
+       else {
+               QUATCOPY(out, in);
+       }
+}
+
+static void colorfn(float *out, float *coord, bNode *node, bNodeStack **in, short thread)
+{      
+       float in0 = tex_input_value(in[0], coord, thread);
+       float in1 = tex_input_value(in[1], coord, thread);
+       float in2 = tex_input_value(in[2], coord, thread);
+       float in3 = tex_input_value(in[3], coord, thread);
+       
+       float in4[4];
+       tex_input_rgba(in4, in[4], coord, thread);
+       
+       do_hue_sat_fac(node, out, in0, in1, in2, in4, in3);
+}
+
+static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+       tex_output(node, in, out[0], &colorfn);
+}
+
+bNodeType tex_node_hue_sat= {
+       /* *next,*prev */       NULL, NULL,
+       /* type code   */       TEX_NODE_HUE_SAT,
+       /* name        */       "Hue Saturation Value",
+       /* width+range */       150, 80, 250,
+       /* class+opts  */       NODE_CLASS_OP_COLOR, NODE_OPTIONS,
+       /* input sock  */       inputs,
+       /* output sock */       outputs,
+       /* storage     */       "", 
+       /* execfunc    */       exec,
+       /* butfunc     */       NULL,
+       /* initfunc    */       NULL,
+       /* freestoragefunc    */        NULL,
+       /* copystoragefunc    */        NULL,
+       /* id          */       NULL
+       
+};
+
+
diff --git a/source/blender/nodes/intern/TEX_nodes/TEX_image.c b/source/blender/nodes/intern/TEX_nodes/TEX_image.c
new file mode 100644 (file)
index 0000000..f9477fe
--- /dev/null
@@ -0,0 +1,106 @@
+/**
+ * $Id: TEX_image.c 10456 2007-04-04 13:58:12Z jesterking $
+ *
+ * ***** 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) 2006 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "../TEX_util.h"
+
+static bNodeSocketType outputs[]= {
+       { SOCK_RGBA, 0, "Image",  0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+       { -1, 0, "" }
+};
+
+static void colorfn(float *out, float *coord, bNode *node, bNodeStack **in, short thread)
+{
+       float x = coord[0];
+       float y = coord[1];
+       Image *ima= (Image *)node->id;
+       ImageUser *iuser= (ImageUser *)node->storage;
+       
+       if( ima ) {
+               ImBuf *ibuf = BKE_image_get_ibuf(ima, iuser);
+               if( ibuf ) {
+                       float xsize, ysize;
+                       float xoff, yoff;
+                       int px, py;
+                       
+                       float *result;
+
+                       xsize = ibuf->x / 2;
+                       ysize = ibuf->y / 2;
+                       xoff = yoff = -1;
+                                       
+                       px = (int)( (x-xoff) * xsize );
+                       py = (int)( (y-yoff) * ysize );
+               
+                       if( (!xsize) || (!ysize) ) return;
+                       if( !ibuf->rect_float ) IMB_float_from_rect(ibuf);
+                       
+                       while( px < 0 ) px += ibuf->x;
+                       while( py < 0 ) py += ibuf->y;
+                       while( px >= ibuf->x ) px -= ibuf->x;
+                       while( py >= ibuf->y ) py -= ibuf->y;
+                       
+                       result = ibuf->rect_float + py*ibuf->x*4 + px*4;
+                       QUATCOPY( out, result );
+               }
+       }
+};
+
+static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+       tex_output(node, in, out[0], &colorfn);
+       
+       tex_do_preview(node, out[0], data);
+}
+
+static void init(bNode* node)
+{
+   ImageUser *iuser= MEM_callocN(sizeof(ImageUser), "node image user");
+   node->storage= iuser;
+   iuser->sfra= 1;
+   iuser->fie_ima= 2;
+   iuser->ok= 1;
+}
+
+bNodeType tex_node_image= {
+       /* *next,*prev */       NULL, NULL,
+       /* type code   */       TEX_NODE_IMAGE,
+       /* name        */       "Image",
+       /* width+range */       120, 80, 300,
+       /* class+opts  */       NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS,
+       /* input sock  */       NULL,
+       /* output sock */       outputs,
+       /* storage     */       "ImageUser",
+       /* execfunc    */       exec,
+       /* butfunc     */       NULL,
+       /* initfunc    */       init,
+       /* freestoragefunc    */        node_free_standard_storage,
+       /* copystoragefunc    */        node_copy_standard_storage,
+       /* id          */       NULL
+};
+
diff --git a/source/blender/nodes/intern/TEX_nodes/TEX_invert.c b/source/blender/nodes/intern/TEX_nodes/TEX_invert.c
new file mode 100644 (file)
index 0000000..0971695
--- /dev/null
@@ -0,0 +1,79 @@
+/**
+ *
+ * ***** 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 "../TEX_util.h"
+
+/* **************** INVERT ******************** */ 
+static bNodeSocketType inputs[]= { 
+       { SOCK_RGBA, 1, "Color", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, 
+       { -1, 0, "" } 
+};
+
+static bNodeSocketType outputs[]= { 
+       { SOCK_RGBA, 0, "Color", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, 
+       { -1, 0, "" } 
+};
+
+static void colorfn(float *out, float *coord, bNode *node, bNodeStack **in, short thread)
+{
+       float col[4];
+       
+       tex_input_rgba(col, in[0], coord, thread);
+
+       col[0] = 1.0f - col[0];
+       col[1] = 1.0f - col[1];
+       col[2] = 1.0f - col[2];
+       
+       VECCOPY(out, col);
+       out[3] = col[3];
+}
+
+static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+       tex_output(node, in, out[0], &colorfn);
+       
+       tex_do_preview(node, out[0], data);
+}
+
+bNodeType tex_node_invert= {
+       /* *next,*prev */       NULL, NULL,
+       /* type code   */       TEX_NODE_INVERT, 
+       /* name        */       "Invert", 
+       /* width+range */       90, 80, 100, 
+       /* class+opts  */       NODE_CLASS_OP_COLOR, NODE_OPTIONS, 
+       /* input sock  */       inputs, 
+       /* output sock */       outputs, 
+       /* storage     */       "", 
+       /* execfunc    */       exec,
+       /* butfunc     */       NULL,
+       /* initfunc    */       NULL,
+       /* freestoragefunc    */        NULL,
+       /* copystoragefunc    */        NULL,
+       /* id          */       NULL
+};
+
diff --git a/source/blender/nodes/intern/TEX_nodes/TEX_math.c b/source/blender/nodes/intern/TEX_nodes/TEX_math.c
new file mode 100644 (file)
index 0000000..a2c6607
--- /dev/null
@@ -0,0 +1,172 @@
+/**
+ *
+ * ***** 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 "../TEX_util.h"
+
+
+
+/* **************** SCALAR MATH ******************** */ 
+static bNodeSocketType inputs[]= { 
+       { SOCK_VALUE, 1, "Value", 0.5f, 0.5f, 0.5f, 1.0f, -100.0f, 100.0f}, 
+       { SOCK_VALUE, 1, "Value", 0.5f, 0.5f, 0.5f, 1.0f, -100.0f, 100.0f}, 
+       { -1, 0, "" } 
+};
+
+static bNodeSocketType outputs[]= { 
+       { SOCK_VALUE, 0, "Value", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, 
+       { -1, 0, "" } 
+};
+
+static void valuefn(float *out, float *coord, bNode *node, bNodeStack **in, short thread)
+{
+       float in0 = tex_input_value(in[0], coord, thread);
+       float in1 = tex_input_value(in[1], coord, thread);
+       
+       switch(node->custom1){ 
+       
+       case 0: /* Add */
+               *out= in0 + in1; 
+               break; 
+       case 1: /* Subtract */
+               *out= in0 - in1;
+               break; 
+       case 2: /* Multiply */
+               *out= in0 * in1; 
+               break; 
+       case 3: /* Divide */
+               {
+                       if(in1==0)      /* We don't want to divide by zero. */
+                               *out= 0.0;
+                       else
+                               *out= in0 / in1;
+                       }
+               break;
+       case 4: /* Sine */
+               {
+                       *out= sin(in0);
+               }
+               break;
+       case 5: /* Cosine */
+               {
+                       *out= cos(in0);
+               }
+               break;
+       case 6: /* Tangent */
+               {
+                       *out= tan(in0);
+               }
+               break;
+       case 7: /* Arc-Sine */
+               {
+                       /* Can't do the impossible... */
+                       if( in0 <= 1 && in0 >= -1 )
+                               *out= asin(in0);
+                       else
+                               *out= 0.0;
+               }
+               break;
+       case 8: /* Arc-Cosine */
+               {
+                       /* Can't do the impossible... */
+                       if( in0 <= 1 && in0 >= -1 )
+                               *out= acos(in0);
+                       else
+                               *out= 0.0;
+               }
+               break;
+       case 9: /* Arc-Tangent */
+               {
+                       *out= atan(in0);
+               }
+               break;
+       case 10: /* Power */
+               {
+                       /* Don't want any imaginary numbers... */
+                       if( in0 >= 0 )
+                               *out= pow(in0, in1);
+                       else
+                               *out= 0.0;
+               }
+               break;
+       case 11: /* Logarithm */
+               {
+                       /* Don't want any imaginary numbers... */
+                       if( in0 > 0  && in1 > 0 )
+                               *out= log(in0) / log(in1);
+                       else
+                               *out= 0.0;
+               }
+               break;
+       case 12: /* Minimum */
+               {
+                       if( in0 < in1 )
+                               *out= in0;
+                       else
+                               *out= in1;
+               }
+               break;
+       case 13: /* Maximum */
+               {
+                       if( in0 > in1 )
+                               *out= in0;
+                       else
+                               *out= in1;
+               }
+               break;
+       case 14: /* Round */
+               {
+                       *out= (int)(in0 + 0.5f);
+               }
+               break; 
+       } 
+}
+
+static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+       tex_output(node, in, out[0], &valuefn);
+       
+       tex_do_preview(node, out[0], data);
+}
+
+bNodeType tex_node_math= {
+       /* *next,*prev */       NULL, NULL,
+       /* type code   */       TEX_NODE_MATH, 
+       /* name        */       "Math", 
+       /* width+range */       120, 110, 160, 
+       /* class+opts  */       NODE_CLASS_CONVERTOR, NODE_OPTIONS, 
+       /* input sock  */       inputs, 
+       /* output sock */       outputs, 
+       /* storage     */       "node_math", 
+       /* execfunc    */       exec,
+       /* butfunc     */       NULL,
+       /* initfunc    */       NULL,
+       /* freestoragefunc    */        NULL,
+       /* copystoragefunc    */        NULL,
+       /* id          */       NULL
+};
+
diff --git a/source/blender/nodes/intern/TEX_nodes/TEX_mixRgb.c b/source/blender/nodes/intern/TEX_nodes/TEX_mixRgb.c
new file mode 100644 (file)
index 0000000..b1ccb7a
--- /dev/null
@@ -0,0 +1,81 @@
+/**
+ *
+ * ***** 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 "../TEX_util.h"
+
+
+/* **************** MIX RGB ******************** */
+static bNodeSocketType inputs[]= {
+       { SOCK_VALUE, 1, "Factor", 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f },
+       { SOCK_RGBA,  1, "Color1", 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 1.0f },
+       { SOCK_RGBA , 1, "Color2", 0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 1.0f },
+       { -1, 0, "" }
+};
+static bNodeSocketType outputs[]= {
+       { SOCK_RGBA, 0, "Color", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f },
+       { -1, 0, "" }
+};
+
+static void colorfn(float *out, float *coord, bNode *node, bNodeStack **in, short thread)
+{
+       float fac  = tex_input_value(in[0], coord, thread);
+       float col1[4], col2[4];
+       
+       tex_input_rgba(col1, in[1], coord, thread);
+       tex_input_rgba(col2, in[2], coord, thread);
+       
+       CLAMP(fac, 0.0f, 1.0f);
+       
+       QUATCOPY(out, col1);
+       ramp_blend(node->custom1, out, out+1, out+2, fac, col2);
+}
+
+static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+       tex_output(node, in, out[0], &colorfn);
+       
+       tex_do_preview(node, out[0], data);
+}
+
+bNodeType tex_node_mix_rgb= {
+       /* *next,*prev */       NULL, NULL,
+       /* type code   */       TEX_NODE_MIX_RGB,
+       /* name        */       "Mix",
+       /* width+range */       100, 60, 150,
+       /* class+opts  */       NODE_CLASS_OP_COLOR, NODE_OPTIONS,
+       /* input sock  */       inputs,
+       /* output sock */       outputs,
+       /* storage     */       "", 
+       /* execfunc    */       exec,
+       /* butfunc     */       NULL,
+       /* initfunc    */       NULL,
+       /* freestoragefunc    */        NULL,
+       /* copystoragefunc    */        NULL,
+       /* id          */       NULL
+       
+};
diff --git a/source/blender/nodes/intern/TEX_nodes/TEX_output.c b/source/blender/nodes/intern/TEX_nodes/TEX_output.c
new file mode 100644 (file)
index 0000000..060ea8d
--- /dev/null
@@ -0,0 +1,90 @@
+/**
+ *
+ * ***** 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) 2006 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#include "../TEX_util.h"
+
+/* **************** COMPOSITE ******************** */
+static bNodeSocketType inputs[]= {
+       { SOCK_RGBA,   1, "Color",  0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+       { SOCK_VECTOR, 1, "Normal", 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f},
+       { -1, 0, ""     }
+};
+
+/* applies to render pipeline */
+static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+       TexCallData *cdata = (TexCallData *)data;
+       TexResult *target = cdata->target;
+       
+       if(in[1]->hasinput && !in[0]->hasinput)
+               tex_do_preview(node, in[1], data);
+       else
+               tex_do_preview(node, in[0], data);
+       
+       if(!cdata->do_preview) {
+               if(cdata->which_output == node->custom1)
+               {
+                       tex_input_rgba(&target->tr, in[0], cdata->coord, cdata->thread);
+               
+                       target->tin = (target->tr + target->tg + target->tb) / 3.0f;
+                       target->talpha = 1.0f;
+               
+                       if(target->nor) {
+                               if(in[1]->hasinput)
+                                       tex_input_vec(target->nor, in[1], cdata->coord, cdata->thread);
+                               else
+                                       target->nor = 0;
+                       }
+               }
+       }
+}
+
+static void init(bNode* node)
+{
+   TexNodeOutput *tno = MEM_callocN(sizeof(TexNodeOutput), "TEX_output");
+   strcpy(tno->name, "Default");
+   node->storage= tno;
+}
+
+
+bNodeType tex_node_output= {
+       /* *next,*prev     */  NULL, NULL,
+       /* type code       */  TEX_NODE_OUTPUT,
+       /* name            */  "Output",
+       /* width+range     */  150, 60, 200,
+       /* class+opts      */  NODE_CLASS_OUTPUT, NODE_PREVIEW | NODE_OPTIONS, 
+       /* input sock      */  inputs,
+       /* output sock     */  NULL,
+       /* storage         */  "TexNodeOutput",
+       /* execfunc        */  exec,
+       /* butfunc         */  NULL,
+       /* initfunc        */  init,
+       /* freestoragefunc */  node_free_standard_storage,
+       /* copystoragefunc */  node_copy_standard_storage,  
+       /* id              */  NULL
+};
diff --git a/source/blender/nodes/intern/TEX_nodes/TEX_proc.c b/source/blender/nodes/intern/TEX_nodes/TEX_proc.c
new file mode 100644 (file)
index 0000000..9078dd1
--- /dev/null
@@ -0,0 +1,310 @@
+/**
+ *
+ * ***** 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 "../TEX_util.h"
+#include "RE_shader_ext.h"
+
+/* 
+       In this file: wrappers to use procedural textures as nodes
+*/
+
+
+static bNodeSocketType outputs_both[]= {
+       { SOCK_RGBA, 0, "Color",  1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f },
+       { SOCK_VECTOR, 0, "Normal", 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f },
+       { -1, 0, "" }
+};
+static bNodeSocketType outputs_color_only[]= {
+       { SOCK_RGBA, 0, "Color",  1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f },
+       { -1, 0, "" }
+};
+
+/* Inputs common to all, #defined because nodes will need their own inputs too */
+#define I 2 /* count */
+#define COMMON_INPUTS \
+       { SOCK_RGBA, 1, "Color 1", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f }, \
+       { SOCK_RGBA, 1, "Color 2", 1.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f }
+
+/* Calls multitex and copies the result to the outputs. Called by xxx_exec, which handles inputs. */
+static void do_proc(float *result, float *coord, float *col1, float *col2, char is_normal, Tex *tex, short thread)
+{
+       TexResult texres;
+       int textype;
+       
+       if(is_normal) {
+               texres.nor = result;
+       }
+       else
+               texres.nor = NULL;
+       
+       textype = multitex_thread(tex, coord, 0, 0, 0, &texres, thread, 0);
+       
+       if(is_normal)
+               return;
+       
+       if(textype & TEX_RGB) {
+               QUATCOPY(result, &texres.tr);
+       }
+       else {
+               QUATCOPY(result, col1);
+               ramp_blend(MA_RAMP_BLEND, result, result+1, result+2, texres.tin, col2);
+       }
+}
+
+typedef void (*MapFn) (Tex *tex, bNodeStack **in, float *coord, short thread);
+
+static void texfn(
+       float *result, 
+       float *coord, 
+       bNode *node, 
+       bNodeStack **in,
+       char is_normal, 
+       MapFn map_inputs,
+       short thread)
+{
+       Tex tex = *((Tex*)(node->storage));
+       float col1[4], col2[4];
+       tex_input_rgba(col1, in[0], coord, thread);
+       tex_input_rgba(col2, in[1], coord, thread);
+       
+       map_inputs(&tex, in, coord, thread);
+       
+       do_proc(result, coord, col1, col2, is_normal, &tex, thread);
+}
+
+static int count_outputs(bNode *node)
+{
+       bNodeSocket *sock;
+       int num = 0;
+       for(sock= node->outputs.first; sock; sock= sock->next) {
+               num++;
+       }
+       return num;
+}
+
+/* Boilerplate generators */
+
+#define ProcNoInputs(name) \
+       static void name##_map_inputs(Tex *tex, bNodeStack **in, float *coord, short thread) \
+       {}
+
+#define ProcDef(name) \
+       static void name##_colorfn(float *result, float *coord, bNode *node, bNodeStack **in, short thread)  \
+       {                                                                                                    \
+               texfn(result, coord, node, in, 0, &name##_map_inputs, thread);                               \
+       }                                                                                                    \
+       static void name##_normalfn(float *result, float *coord, bNode *node, bNodeStack **in, short thread) \
+       {                                                                                                    \
+               texfn(result, coord, node, in, 1, &name##_map_inputs, thread);                               \
+       }                                                                                                    \
+       static void name##_exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out)                  \
+       {                                                                                                    \
+               int outs = count_outputs(node);                                                              \
+               if(outs >= 1) tex_output(node, in, out[0], &name##_colorfn);                                 \
+               if(outs >= 2) tex_output(node, in, out[1], &name##_normalfn);                                \
+               if(outs >= 1) tex_do_preview(node, out[0], data);                                            \
+       }
+
+
+/* --- VORONOI -- */
+static bNodeSocketType voronoi_inputs[]= {
+       COMMON_INPUTS,
+       { SOCK_VALUE, 1, "W1", 1.0f, 0.0f, 0.0f, 0.0f,   -2.0f, 2.0f },
+       { SOCK_VALUE, 1, "W2", 0.0f, 0.0f, 0.0f, 0.0f,   -2.0f, 2.0f },
+       { SOCK_VALUE, 1, "W3", 0.0f, 0.0f, 0.0f, 0.0f,   -2.0f, 2.0f },
+       { SOCK_VALUE, 1, "W4", 0.0f, 0.0f, 0.0f, 0.0f,   -2.0f, 2.0f },
+       
+       { SOCK_VALUE, 1, "iScale", 1.0f, 0.0f, 0.0f, 0.0f,    0.01f,  10.0f },
+       { SOCK_VALUE, 1, "Size",   0.25f, 0.0f, 0.0f, 0.0f,   0.0001f, 4.0f },
+       
+       { -1, 0, "" }
+};
+static void voronoi_map_inputs(Tex *tex, bNodeStack **in, float *coord, short thread)
+{
+       tex->vn_w1 = tex_input_value(in[I+0], coord, thread);
+       tex->vn_w2 = tex_input_value(in[I+1], coord, thread);
+       tex->vn_w3 = tex_input_value(in[I+2], coord, thread);
+       tex->vn_w4 = tex_input_value(in[I+3], coord, thread);
+       
+       tex->ns_outscale = tex_input_value(in[I+4], coord, thread);
+       tex->noisesize   = tex_input_value(in[I+5], coord, thread);
+}
+ProcDef(voronoi)
+
+/* --- BLEND -- */
+static bNodeSocketType blend_inputs[]= {
+       COMMON_INPUTS,
+       { -1, 0, "" }
+};
+ProcNoInputs(blend)
+ProcDef(blend)
+
+/* -- MAGIC -- */
+static bNodeSocketType magic_inputs[]= {
+       COMMON_INPUTS,
+       { SOCK_VALUE, 1, "Turbulence", 5.0f, 0.0f, 0.0f, 0.0f,   0.0f, 200.0f },
+       { -1, 0, "" }
+};
+static void magic_map_inputs(Tex *tex, bNodeStack **in, float *coord, short thread)
+{
+       tex->turbul = tex_input_value(in[I+0], coord, thread);
+}
+ProcDef(magic)
+
+/* --- MARBLE --- */
+static bNodeSocketType marble_inputs[]= {
+       COMMON_INPUTS,
+       { SOCK_VALUE, 1, "Size",       0.25f, 0.0f, 0.0f, 0.0f,   0.0001f, 2.0f },
+       { SOCK_VALUE, 1, "Turbulence", 5.0f,  0.0f, 0.0f, 0.0f,   0.0f, 200.0f },
+       { -1, 0, "" }
+};
+static void marble_map_inputs(Tex *tex, bNodeStack **in, float *coord, short thread)
+{
+       tex->noisesize = tex_input_value(in[I+0], coord, thread);
+       tex->turbul    = tex_input_value(in[I+1], coord, thread);
+}
+ProcDef(marble)
+
+/* --- CLOUDS --- */
+static bNodeSocketType clouds_inputs[]= {
+       COMMON_INPUTS,
+       { SOCK_VALUE, 1, "Size",       0.25f, 0.0f, 0.0f, 0.0f,   0.0001f, 2.0f },
+       { -1, 0, "" }
+};
+static void clouds_map_inputs(Tex *tex, bNodeStack **in, float *coord, short thread)
+{
+       tex->noisesize = tex_input_value(in[I+0], coord, thread);
+}
+ProcDef(clouds)
+
+/* --- DISTORTED NOISE --- */
+static bNodeSocketType distnoise_inputs[]= {
+       COMMON_INPUTS,
+       { SOCK_VALUE, 1, "Size",       0.25f, 0.0f, 0.0f, 0.0f,   0.0001f,  2.0f },
+       { SOCK_VALUE, 1, "Distortion", 1.00f, 0.0f, 0.0f, 0.0f,   0.0000f, 10.0f },
+       { -1, 0, "" }
+};
+static void distnoise_map_inputs(Tex *tex, bNodeStack **in, float *coord, short thread)
+{
+       tex->noisesize   = tex_input_value(in[I+0], coord, thread);
+       tex->dist_amount = tex_input_value(in[I+1], coord, thread);
+}
+ProcDef(distnoise)
+
+/* --- WOOD --- */
+static bNodeSocketType wood_inputs[]= {
+       COMMON_INPUTS,
+       { SOCK_VALUE, 1, "Size",       0.25f, 0.0f, 0.0f, 0.0f,   0.0001f, 2.0f },
+       { SOCK_VALUE, 1, "Turbulence", 5.0f,  0.0f, 0.0f, 0.0f,   0.0f, 200.0f },
+       { -1, 0, "" }
+};
+static void wood_map_inputs(Tex *tex, bNodeStack **in, float *coord, short thread)
+{
+       tex->noisesize = tex_input_value(in[I+0], coord, thread);
+       tex->turbul    = tex_input_value(in[I+1], coord, thread);
+}
+ProcDef(wood)
+
+/* --- MUSGRAVE --- */
+static bNodeSocketType musgrave_inputs[]= {
+       COMMON_INPUTS,
+       { SOCK_VALUE, 1, "H",          1.0f, 0.0f, 0.0f, 0.0f,   0.0001f, 2.0f },
+       { SOCK_VALUE, 1, "Lacunarity", 2.0f, 0.0f, 0.0f, 0.0f,   0.0f,    6.0f },
+       { SOCK_VALUE, 1, "Octaves",    2.0f, 0.0f, 0.0f, 0.0f,   0.0f,    8.0f },
+       
+       { SOCK_VALUE, 1, "iScale",     1.0f,  0.0f, 0.0f, 0.0f,  0.0f,   10.0f },
+       { SOCK_VALUE, 1, "Size",       0.25f, 0.0f, 0.0f, 0.0f,  0.0001f, 2.0f },
+       { -1, 0, "" }
+};
+static void musgrave_map_inputs(Tex *tex, bNodeStack **in, float *coord, short thread)
+{
+       tex->mg_H          = tex_input_value(in[I+0], coord, thread);
+       tex->mg_lacunarity = tex_input_value(in[I+1], coord, thread);
+       tex->mg_octaves    = tex_input_value(in[I+2], coord, thread);
+       tex->ns_outscale   = tex_input_value(in[I+3], coord, thread);
+       tex->noisesize     = tex_input_value(in[I+4], coord, thread);
+}
+ProcDef(musgrave)
+
+/* --- NOISE --- */
+static bNodeSocketType noise_inputs[]= {
+       COMMON_INPUTS,
+       { -1, 0, "" }
+};
+ProcNoInputs(noise)
+ProcDef(noise)
+
+/* --- STUCCI --- */
+static bNodeSocketType stucci_inputs[]= {
+       COMMON_INPUTS,
+       { SOCK_VALUE, 1, "Size",       0.25f, 0.0f, 0.0f, 0.0f,   0.0001f, 2.0f },
+       { SOCK_VALUE, 1, "Turbulence", 5.0f,  0.0f, 0.0f, 0.0f,   0.0f, 200.0f },
+       { -1, 0, "" }
+};
+static void stucci_map_inputs(Tex *tex, bNodeStack **in, float *coord, short thread)
+{
+       tex->noisesize = tex_input_value(in[I+0], coord, thread);
+       tex->turbul    = tex_input_value(in[I+1], coord, thread);
+}
+ProcDef(stucci)
+
+/* --- */
+
+static void init(bNode *node)
+{
+       Tex *tex = MEM_callocN(sizeof(Tex), "Tex");
+       node->storage= tex;
+       
+       default_tex(tex);
+       tex->type = node->type - TEX_NODE_PROC;
+       
+       if(tex->type == TEX_WOOD)
+               tex->stype = TEX_BANDNOISE;
+       
+}
+
+/* Node type definitions */
+#define TexDef(TEXTYPE, outputs, name, Name) \
+       { NULL, NULL, TEX_NODE_PROC+TEXTYPE, Name, 140,80,140, NODE_CLASS_TEXTURE, \
+       NODE_OPTIONS | NODE_PREVIEW, name##_inputs, outputs, "Tex", name##_exec, NULL, init, \
+       node_free_standard_storage, node_copy_standard_storage, NULL }
+       
+#define C outputs_color_only
+#define CV outputs_both
+       
+bNodeType tex_node_proc_voronoi   = TexDef(TEX_VORONOI,   CV, voronoi,   "Voronoi"  );
+bNodeType tex_node_proc_blend     = TexDef(TEX_BLEND,     C,  blend,     "Blend"    );
+bNodeType tex_node_proc_magic     = TexDef(TEX_MAGIC,     C,  magic,     "Magic"    );
+bNodeType tex_node_proc_marble    = TexDef(TEX_MARBLE,    CV, marble,    "Marble"   );
+bNodeType tex_node_proc_clouds    = TexDef(TEX_CLOUDS,    CV, clouds,    "Clouds"   );
+bNodeType tex_node_proc_wood      = TexDef(TEX_WOOD,      CV, wood,      "Wood"     );
+bNodeType tex_node_proc_musgrave  = TexDef(TEX_MUSGRAVE,  CV, musgrave,  "Musgrave" );
+bNodeType tex_node_proc_noise     = TexDef(TEX_NOISE,     C,  noise,     "Noise"    );
+bNodeType tex_node_proc_stucci    = TexDef(TEX_STUCCI,    CV, stucci,    "Stucci"   );
+bNodeType tex_node_proc_distnoise = TexDef(TEX_DISTNOISE, CV, distnoise, "Distorted Noise" );
+
diff --git a/source/blender/nodes/intern/TEX_nodes/TEX_rotate.c b/source/blender/nodes/intern/TEX_nodes/TEX_rotate.c
new file mode 100644 (file)
index 0000000..93bf17d
--- /dev/null
@@ -0,0 +1,114 @@
+/**
+ *
+ * ***** 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 <math.h>
+#include "MTC_vectorops.h"
+#include "../TEX_util.h"
+
+static bNodeSocketType inputs[]= { 
+       { SOCK_RGBA, 1, "Color", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+       { SOCK_VALUE, 1, "Turns",   0.0f, 0.0f, 0.0f, 0.0f,  -1.0f, 1.0f },
+       { SOCK_VECTOR, 1, "Axis",   0.0f, 0.0f, 1.0f, 0.0f,  -1.0f, 1.0f },
+       { -1, 0, "" } 
+};
+
+static bNodeSocketType outputs[]= { 
+       { SOCK_RGBA, 0, "Color", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, 
+       { -1, 0, "" } 
+};
+
+static void colorfn(float *out, float *coord, bNode *node, bNodeStack **in, short thread)
+{
+       float new_coord[3];
+       
+       float ax[4];
+       float para[3];
+       float perp[3];
+       float cp[3];
+       
+       float magsq, ndx;
+       
+       float a = tex_input_value(in[1], coord, thread);
+       float cos_a = cos(a * 2 * M_PI);
+       float sin_a = sin(a * 2 * M_PI);
+       
+       // x' = xcosa + n(n.x)(1-cosa)+(x*n)sina
+       
+       tex_input_vec(ax, in[2], coord, thread);
+       magsq = ax[0]*ax[0] + ax[1]*ax[1] + ax[2]*ax[2];
+       
+       if(magsq == 0) magsq = 1;
+       
+       ndx = MTC_dot3Float(coord, ax);
+       
+       para[0] = ax[0] * ndx * (1 - cos_a);
+       para[1] = ax[1] * ndx * (1 - cos_a);
+       para[2] = ax[2] * ndx * (1 - cos_a);
+       
+       MTC_diff3Float(perp, coord, para);
+       
+       perp[0] = coord[0] * cos_a;
+       perp[1] = coord[1] * cos_a;
+       perp[2] = coord[2] * cos_a;
+       
+       MTC_cross3Float(cp, ax, coord);
+       
+       cp[0] = cp[0] * sin_a;
+       cp[1] = cp[1] * sin_a;
+       cp[2] = cp[2] * sin_a;
+       
+       new_coord[0] = para[0] + perp[0] + cp[0];
+       new_coord[1] = para[1] + perp[1] + cp[1];
+       new_coord[2] = para[2] + perp[2] + cp[2];
+       
+       tex_input_rgba(out, in[0], new_coord, thread);
+}
+static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) 
+{
+       tex_output(node, in, out[0], &colorfn);
+       
+       tex_do_preview(node, out[0], data);
+}
+
+bNodeType tex_node_rotate= {
+       /* *next,*prev */       NULL, NULL,
+       /* type code   */       TEX_NODE_ROTATE, 
+       /* name        */       "Rotate", 
+       /* width+range */       90, 80, 100, 
+       /* class+opts  */       NODE_CLASS_DISTORT, NODE_OPTIONS, 
+       /* input sock  */       inputs, 
+       /* output sock */       outputs, 
+       /* storage     */       "", 
+       /* execfunc    */       exec,
+       /* butfunc     */       NULL,
+       /* initfunc    */       NULL,
+       /* freestoragefunc    */        NULL,
+       /* copystoragefunc    */        NULL,
+       /* id          */       NULL
+};
+
diff --git a/source/blender/nodes/intern/TEX_nodes/TEX_texture.c b/source/blender/nodes/intern/TEX_nodes/TEX_texture.c
new file mode 100644 (file)
index 0000000..884d2cd
--- /dev/null
@@ -0,0 +1,103 @@
+/**
+ *
+ * ***** 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 "../TEX_util.h"
+#include "RE_shader_ext.h"
+
+static bNodeSocketType inputs[]= {
+       { SOCK_RGBA, 1, "Color1", 1.0f, 1.0f, 1.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 outputs[]= {
+       { SOCK_RGBA, 0, "Color", 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f },
+       { -1, 0, "" }
+};
+
+static void colorfn(float *out, float *coord, bNode *node, bNodeStack **in, short thread)
+{
+       static float red[] = {1,0,0,1};
+       static float white[] = {1,1,1,1};
+       
+       Tex *nodetex = (Tex *)node->id;
+       
+       if(node->custom2) {
+               /* this node refers to its own texture tree! */
+               QUATCOPY(
+                       out,
+                       (fabs(coord[0] - coord[1]) < .01) ? white : red 
+               );
+       }
+       else if(nodetex) {
+               TexResult texres;
+               int textype;
+               float nor[] = {0,0,0};
+               float col1[4], col2[4];
+               
+               tex_input_rgba(col1, in[0], coord, thread);
+               tex_input_rgba(col2, in[1], coord, thread);
+               
+               texres.nor = nor;
+               textype = multitex_ext(nodetex, coord, 0, 0, 0, &texres);
+               
+               if(textype & TEX_RGB) {
+                       QUATCOPY(out, &texres.tr);
+               }
+               else {
+                       QUATCOPY(out, col1);
+                       ramp_blend(MA_RAMP_BLEND, out, out+1, out+2, texres.tin, col2);
+               }
+       }
+}
+
+static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+       tex_output(node, in, out[0], &colorfn);
+       
+       tex_do_preview(node, out[0], data);
+}
+
+bNodeType tex_node_texture= {
+       /* *next,*prev */       NULL, NULL,
+       /* type code   */       TEX_NODE_TEXTURE,
+       /* name        */       "Texture",
+       /* width+range */       120, 80, 240,
+       /* class+opts  */       NODE_CLASS_INPUT, NODE_OPTIONS|NODE_PREVIEW,
+       /* input sock  */       inputs,
+       /* output sock */       outputs,
+       /* storage     */       "",
+       /* execfunc    */       exec,
+       /* butfunc     */       NULL,
+       /* initfunc        */   NULL,
+       /* freestoragefunc */   NULL,
+       /* copystoragefunc */   NULL, 
+       /* id          */       NULL
+       
+};
+
diff --git a/source/blender/nodes/intern/TEX_nodes/TEX_translate.c b/source/blender/nodes/intern/TEX_nodes/TEX_translate.c
new file mode 100644 (file)
index 0000000..bd7e61d
--- /dev/null
@@ -0,0 +1,78 @@
+/**
+ *
+ * ***** 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 <math.h>
+#include "../TEX_util.h"
+
+static bNodeSocketType inputs[]= { 
+       { SOCK_RGBA, 1, "Color", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+       { SOCK_VECTOR, 1, "Offset",   0.0f, 0.0f, 0.0f, 0.0f,  -1.0f, 1.0f },
+       { -1, 0, "" } 
+};
+
+static bNodeSocketType outputs[]= { 
+       { SOCK_RGBA, 0, "Color", 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f}, 
+       { -1, 0, "" } 
+};
+
+static void colorfn(float *out, float *coord, bNode *node, bNodeStack **in, short thread)
+{
+       float offset[3], new_coord[3];
+       
+       tex_input_vec(offset, in[1], coord, thread);
+       
+       new_coord[0] = coord[0] + offset[0];
+       new_coord[1] = coord[1] + offset[1];
+       new_coord[2] = coord[2] + offset[2];
+       
+       tex_input_rgba(out, in[0], new_coord, thread);
+}
+static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) 
+{
+       tex_output(node, in, out[0], &colorfn);
+       
+       tex_do_preview(node, out[0], data);
+}
+
+bNodeType tex_node_translate = {
+       /* *next,*prev */       NULL, NULL,
+       /* type code   */       TEX_NODE_TRANSLATE, 
+       /* name        */       "Translate", 
+       /* width+range */       90, 80, 100, 
+       /* class+opts  */       NODE_CLASS_DISTORT, NODE_OPTIONS, 
+       /* input sock  */       inputs, 
+       /* output sock */       outputs, 
+       /* storage     */       "", 
+       /* execfunc    */       exec,
+       /* butfunc     */       NULL,
+       /* initfunc    */       NULL,
+       /* freestoragefunc    */        NULL,
+       /* copystoragefunc    */        NULL,
+       /* id          */       NULL
+};
+
diff --git a/source/blender/nodes/intern/TEX_nodes/TEX_valToRgb.c b/source/blender/nodes/intern/TEX_nodes/TEX_valToRgb.c
new file mode 100644 (file)
index 0000000..ec59769
--- /dev/null
@@ -0,0 +1,122 @@
+/**
+ * $Id: SHD_valToRgb.c 10456 2007-04-04 13:58:12Z jesterking $
+ *
+ * ***** 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 "../TEX_util.h"
+
+/* **************** VALTORGB ******************** */
+static bNodeSocketType valtorgb_in[]= {
+       {       SOCK_VALUE, 1, "Fac",                   0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
+       {       -1, 0, ""       }
+};
+static bNodeSocketType valtorgb_out[]= {
+       {       SOCK_RGBA, 0, "Color",                  0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+       {       -1, 0, ""       }
+};
+
+static void valtorgb_colorfn(float *out, float *coord, bNode *node, bNodeStack **in, short thread)
+{
+       if(node->storage) {
+               float fac = tex_input_value(in[0], coord, thread);
+
+               do_colorband(node->storage, fac, out);
+       }
+}
+
+static void valtorgb_exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out) 
+{
+       tex_output(node, in, out[0], &valtorgb_colorfn);
+}
+
+static void valtorgb_init(bNode *node)
+{
+       node->storage = add_colorband(1);
+}
+
+bNodeType tex_node_valtorgb= {
+       /* *next,*prev */       NULL, NULL,
+       /* type code   */       TEX_NODE_VALTORGB,
+       /* name        */       "ColorRamp",
+       /* width+range */       240, 200, 300,
+       /* class+opts  */       NODE_CLASS_CONVERTOR, NODE_OPTIONS,
+       /* input sock  */       valtorgb_in,
+       /* output sock */       valtorgb_out,
+       /* storage     */       "ColorBand",
+       /* execfunc    */       valtorgb_exec,
+       /* butfunc     */       NULL,
+       /* initfunc    */       valtorgb_init,
+       /* freestoragefunc    */        node_free_standard_storage,
+       /* copystoragefunc    */        node_copy_standard_storage,
+       /* id          */       NULL
+       
+};
+
+/* **************** RGBTOBW ******************** */
+static bNodeSocketType rgbtobw_in[]= {
+   {   SOCK_RGBA, 1, "Color",                  0.5f, 0.5f, 0.5f, 1.0f, 0.0f, 1.0f},
+   {   -1, 0, ""       }
+};
+static bNodeSocketType rgbtobw_out[]= {
+   {   SOCK_VALUE, 0, "Val",                   0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
+   {   -1, 0, ""       }
+};
+
+
+static void rgbtobw_valuefn(float *out, float *coord, bNode *node, bNodeStack **in, short thread)
+{
+       float cin[4];
+       tex_input_rgba(cin, in[0], coord, thread);
+       
+       *out = cin[0] * 0.35f + cin[1] * 0.45f + cin[2] * 0.2f;
+}
+
+static void rgbtobw_exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+       tex_output(node, in, out[0], &rgbtobw_valuefn);
+       
+       tex_do_preview(node, out[0], data);
+}
+
+bNodeType tex_node_rgbtobw= {
+       /* *next,*prev */       NULL, NULL,
+       /* type code   */       TEX_NODE_RGBTOBW,
+       /* name        */       "RGB to BW",
+       /* width+range */       80, 40, 120,
+       /* class+opts  */       NODE_CLASS_CONVERTOR, 0,
+       /* input sock  */       rgbtobw_in,
+       /* output sock */       rgbtobw_out,
+       /* storage     */       "",
+       /* execfunc    */       rgbtobw_exec,
+       /* butfunc     */       NULL,
+       /* initfunc    */       NULL,
+       /* freestoragefunc    */        NULL,
+       /* copystoragefunc    */        NULL,
+       /* id          */       NULL
+
+};
+
diff --git a/source/blender/nodes/intern/TEX_nodes/TEX_viewer.c b/source/blender/nodes/intern/TEX_nodes/TEX_viewer.c
new file mode 100644 (file)
index 0000000..acdaacf
--- /dev/null
@@ -0,0 +1,61 @@
+/**
+ *
+ * ***** 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 "../TEX_util.h"                                                   
+#include <math.h>
+
+static bNodeSocketType inputs[]= {
+       { SOCK_RGBA, 1, "Color", 1.0f, 0.0f, 0.0f, 1.0f,  0.0f, 1.0f },
+       { -1, 0, "" }
+};
+static bNodeSocketType outputs[]= {
+       { -1, 0, "" }
+};
+
+static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+{
+       tex_do_preview(node, in[0], data);
+}
+
+bNodeType tex_node_viewer = {
+       /* *next,*prev */       NULL, NULL,
+       /* type code   */       TEX_NODE_VIEWER,
+       /* name        */       "Viewer",
+       /* width+range */       100, 60, 150,
+       /* class+opts  */       NODE_CLASS_OUTPUT, NODE_PREVIEW,
+       /* input sock  */       inputs,
+       /* output sock */       outputs,
+       /* storage     */       "", 
+       /* execfunc    */       exec,
+       /* butfunc     */       NULL,
+       /* initfunc    */       NULL,
+       /* freestoragefunc    */        NULL,
+       /* copystoragefunc    */        NULL,
+       /* id          */       NULL
+       
+};
diff --git a/source/blender/nodes/intern/TEX_util.h b/source/blender/nodes/intern/TEX_util.h
new file mode 100644 (file)
index 0000000..69cf207
--- /dev/null
@@ -0,0 +1,104 @@
+/**
+ *
+ * ***** 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 *****
+ */
+
+#ifndef TEX_NODE_UTIL_H_
+#define TEX_NODE_UTIL_H_
+
+#include <math.h>
+#include <string.h>
+
+#include "MEM_guardedalloc.h"
+
+#include "DNA_action_types.h"
+#include "DNA_color_types.h"
+#include "DNA_ipo_types.h"
+#include "DNA_ID.h"
+#include "DNA_image_types.h"
+#include "DNA_material_types.h"
+#include "DNA_node_types.h"
+#include "DNA_object_types.h"
+#include "DNA_scene_types.h"
+#include "DNA_space_types.h"
+#include "DNA_screen_types.h"
+#include "DNA_texture_types.h"
+#include "DNA_userdef_types.h"
+
+#include "BKE_blender.h"
+#include "BKE_colortools.h"
+#include "BKE_global.h"
+#include "BKE_image.h"
+#include "BKE_main.h"
+#include "BKE_material.h"
+#include "BKE_texture.h"
+#include "BKE_utildefines.h"
+#include "BKE_library.h"
+
+#include "../SHD_node.h"
+#include "node_util.h"
+
+#include "BLI_arithb.h"
+#include "BLI_blenlib.h"
+#include "BLI_rand.h"
+#include "BLI_threads.h"
+
+#include "IMB_imbuf_types.h"
+#include "IMB_imbuf.h"
+
+#include "RE_pipeline.h"
+#include "RE_shader_ext.h"
+
+typedef struct TexCallData {
+       TexResult *target;
+       float *coord;
+       char do_preview;
+       short thread;
+       short which_output;
+} TexCallData;
+
+typedef void(*TexFn) (float *out, float *coord, bNode *node, bNodeStack **in, short thread);
+
+typedef struct TexDelegate {
+       TexFn fn;
+       bNode *node;
+       bNodeStack *in[MAX_SOCKET];
+       int type;
+} TexDelegate;
+
+void tex_call_delegate(TexDelegate*, float *out, float *coord, short thread);
+
+void tex_input_rgba(float *out, bNodeStack *in, float *coord, short thread);
+void tex_input_vec(float *out, bNodeStack *in, float *coord, short thread);
+float tex_input_value(bNodeStack *in, float *coord, short thread);
+
+void tex_output(bNode *node, bNodeStack **in, bNodeStack *out, TexFn texfn);
+void tex_do_preview(bNode *node, bNodeStack *ns, TexCallData *cdata);
+
+void ntreeTexUpdatePreviews( bNodeTree* nodetree );
+void ntreeTexExecTree(bNodeTree *nodes, TexResult *texres, float *coord, char do_preview, short thread, struct Tex *tex, short which_output);
+#endif
index 888474ffa18bd2c492563dc2212d3def7589644b..2cee2673a269f8591b4fea9f78e36b7ff2bbfead 100644 (file)
@@ -183,6 +183,7 @@ typedef struct ShadeInput
 /* node shaders... */
 struct Tex;
 int    multitex_ext(struct Tex *tex, float *texvec, float *dxt, float *dyt, int osatex, struct TexResult *texres);
+int    multitex_thread(struct Tex *tex, float *texvec, float *dxt, float *dyt, int osatex, struct TexResult *texres, short thread, short which_output);
 
 /* shaded view and bake */
 struct Render;
index c6b11b4af9af8cde41004ff78fddb8a92f5d9796..799f55210171b3618ae51b716525a95624d72849 100644 (file)
@@ -53,8 +53,8 @@ int shadeHaloFloat(HaloRen *har,
 /**
  * Render the sky at pixel (x, y).
  */
-void shadeSkyPixel(float *collector, float fx, float fy);
-void shadeSkyView(float *colf, float *rco, float *view, float *dxyview);
+void shadeSkyPixel(float *collector, float fx, float fy, short thread);
+void shadeSkyView(float *colf, float *rco, float *view, float *dxyview, short thread);
 void shadeAtmPixel(struct SunSky *sunsky, float *collector, float fx, float fy, float distance);
 void shadeSunView(float *colf, float *view);
 /* ------------------------------------------------------------------------- */
index be5471e07c4d451a5b6ce0ce31d34697c0393a8d..c254b76829294761c66f40b5f9e4d97292bcafa6 100644 (file)
@@ -53,11 +53,12 @@ struct ImBuf;
 /* texture.h */
 
 void do_halo_tex(struct HaloRen *har, float xn, float yn, float *colf);
-void do_sky_tex(float *rco, float *lo, float *dxyview, float *hor, float *zen, float *blend, int skyflag);
+void do_sky_tex(float *rco, float *lo, float *dxyview, float *hor, float *zen, float *blend, int skyflag, short thread);
 void do_material_tex(struct ShadeInput *shi);
 void do_lamp_tex(LampRen *la, float *lavec, struct ShadeInput *shi, float *colf, int effect);
 
 void init_render_textures(Render *re);
+void end_render_textures(void);
 
 void render_realtime_texture(struct ShadeInput *shi, struct Image *ima);
 
index 1a387ad74667bde1e8f9096fb6b5a854ac0c868c..4e4e27fe286370818eb7b876c749911124433cc7 100644 (file)
@@ -2272,6 +2272,7 @@ static void displace_render_face(Render *re, ObjectRen *obr, VlakRen *vlr, float
 
        shi.vlr= vlr;           /* current render face */
        shi.mat= vlr->mat;              /* current input material */
+       shi.thread= 0;
        
        /* Displace the verts, flag is set when done */
        if (!vlr->v1->flag)
@@ -4407,6 +4408,7 @@ void RE_Database_Free(Render *re)
 
        end_radio_render();
        end_render_materials();
+       end_render_textures();
        
        if(re->wrld.aosphere) {
                MEM_freeN(re->wrld.aosphere);
index 60723963af93bf14ba67cbb06653192076acaa36..af6093ab36c7c1ae84dcf45aa44ad00b40a55288 100644 (file)
@@ -511,7 +511,7 @@ static void fillBackgroundImage(float *collector, float fx, float fy)
 }
 
 /* Only view vector is important here. Result goes to colf[3] */
-void shadeSkyView(float *colf, float *rco, float *view, float *dxyview)
+void shadeSkyView(float *colf, float *rco, float *view, float *dxyview, short thread)
 {
        float lo[3], zen[3], hor[3], blend, blendm;
        int skyflag;
@@ -550,7 +550,7 @@ void shadeSkyView(float *colf, float *rco, float *view, float *dxyview)
                        SWAP(float, lo[1],  lo[2]);
                        
                }
-               do_sky_tex(rco, lo, dxyview, hor, zen, &blend, skyflag);
+               do_sky_tex(rco, lo, dxyview, hor, zen, &blend, skyflag, thread);
        }
        
        if(blend>1.0) blend= 1.0;
@@ -607,7 +607,7 @@ void shadeSunView(float *colf, float *view)
 /*
   Stuff the sky color into the collector.
  */
-void shadeSkyPixel(float *collector, float fx, float fy) 
+void shadeSkyPixel(float *collector, float fx, float fy, short thread
 {
        float view[3], dxyview[2];
 
@@ -653,7 +653,7 @@ void shadeSkyPixel(float *collector, float fx, float fy)
                }
                
                /* get sky color in the collector */
-               shadeSkyView(collector, NULL, view, dxyview);
+               shadeSkyView(collector, NULL, view, dxyview, thread);
                collector[3] = 0.0f;
        }
        
index f822d41bb85c11b11fea21cf0a294cd3f6b8061a..46a7a1c556c596aa1feab2e2e3de3e9cd7d6b7c6 100644 (file)
@@ -396,7 +396,7 @@ static void ray_fadeout_endcolor(float *col, ShadeInput *origshi, ShadeInput *sh
                VECCOPY(shi->view, vec);
                Normalize(shi->view);
                
-               shadeSkyView(col, isec->start, shi->view, NULL);
+               shadeSkyView(col, isec->start, shi->view, NULL, shi->thread);
                shadeSunView(col, shi->view);
        }
 }
@@ -1627,7 +1627,7 @@ static void ray_ao_qmc(ShadeInput *shi, float *shadfac)
                                shadfac[2]+= (1.0f-skyfac)*R.wrld.horb + skyfac*R.wrld.zenb;
                        }
                        else {  /* WO_AOSKYTEX */
-                               shadeSkyView(skycol, isec.start, view, dxyview);
+                               shadeSkyView(skycol, isec.start, view, dxyview, shi->thread);
                                shadeSunView(skycol, shi->view);
                                shadfac[0]+= skycol[0];
                                shadfac[1]+= skycol[1];
@@ -1752,7 +1752,7 @@ static void ray_ao_spheresamp(ShadeInput *shi, float *shadfac)
                                        shadfac[2]+= (1.0f-fac)*R.wrld.horb + fac*R.wrld.zenb;
                                }
                                else {  /* WO_AOSKYTEX */
-                                       shadeSkyView(skycol, isec.start, view, dxyview);
+                                       shadeSkyView(skycol, isec.start, view, dxyview, shi->thread);
                                        shadeSunView(skycol, shi->view);
                                        shadfac[0]+= skycol[0];
                                        shadfac[1]+= skycol[1];
index 1eb42bca5692da603b5125918acedb78310fc549..c3b281f2a2335b99acf27b57352c75dc132ed1a8 100644 (file)
@@ -647,7 +647,7 @@ static void sky_tile(RenderPart *pa, RenderLayer *rl)
                                if(pass[3]<1.0f) {
                                        
                                        if(done==0) {
-                                               shadeSkyPixel(col, x, y);
+                                               shadeSkyPixel(col, x, y, pa->thread);
                                                done= 1;
                                        }
                                        
index 7ce66ff6d1265388d31aa082f0d162f5e5148999..61e9d9cf4128948900e6c250c0a30c0e116cfa96 100644 (file)
 #include "DNA_meshdata_types.h"
 #include "DNA_material_types.h"
 #include "DNA_image_types.h"
+#include "DNA_node_types.h"
 
 #include "IMB_imbuf_types.h"
 #include "IMB_imbuf.h"
 
 #include "BKE_image.h"
+#include "BKE_node.h"
 #include "BKE_plugin_types.h"
 #include "BKE_utildefines.h"
 
@@ -114,6 +116,10 @@ void init_render_texture(Render *re, Tex *tex)
                        }
                }
        }
+       
+       if(tex->nodetree && tex->use_nodes) {
+               ntreeBeginExecTree(tex->nodetree); /* has internal flag to detect it only does it once */
+       }
 }
 
 /* ------------------------------------------------------------------------- */
@@ -129,6 +135,20 @@ void init_render_textures(Render *re)
        }
 }
 
+void end_render_texture(Tex *tex)
+{
+       if(tex && tex->use_nodes && tex->nodetree)
+               ntreeEndExecTree(tex->nodetree);
+}
+
+void end_render_textures(void)
+{
+       Tex *tex;
+       for(tex= G.main->tex.first; tex; tex= tex->id.next)
+               if(tex->id.us)
+                       end_render_texture(tex);
+}
+
 /* ------------------------------------------------------------------------- */
 
 
@@ -691,6 +711,19 @@ static float voronoiTex(Tex *tex, float *texvec, TexResult *texres)
 
 }
 
+/* ------------------------------------------------------------------------- */
+
+static int evalnodes(Tex *tex, float *texvec, TexResult *texres, short thread, short which_output)
+{
+       short rv = TEX_INT;
+       bNodeTree *nodes = tex->nodetree;
+       
+       ntreeTexExecTree(nodes, texres, texvec, 0, thread, tex, which_output);
+       
+       if(texres->nor) rv |= TEX_NOR;
+       rv |= TEX_RGB;
+       return rv;
+}
 
 /* ------------------------------------------------------------------------- */
 
@@ -1130,13 +1163,17 @@ static void do_2d_mapping(MTex *mtex, float *t, VlakRen *vlr, float *n, float *d
 
 /* ************************************** */
 
-static int multitex(Tex *tex, float *texvec, float *dxt, float *dyt, int osatex, TexResult *texres)
+static int multitex(Tex *tex, float *texvec, float *dxt, float *dyt, int osatex, TexResult *texres, short thread, short which_output)
 {
        float tmpvec[3];
        int retval=0; /* return value, int:0, col:1, nor:2, everything:3 */
 
        texres->talpha= 0;      /* is set when image texture returns alpha (considered premul) */
        
+       if(tex->use_nodes && tex->nodetree) {
+               retval = evalnodes(tex, texvec, texres, thread, which_output);
+       }
+       else
        switch(tex->type) {
        
        case 0:
@@ -1236,7 +1273,11 @@ static int multitex(Tex *tex, float *texvec, float *dxt, float *dyt, int osatex,
  * the color values are set before using the r/g/b values, otherwise you may use uninitialized values - Campbell */
 int multitex_ext(Tex *tex, float *texvec, float *dxt, float *dyt, int osatex, TexResult *texres)
 {
-       
+       return multitex_thread(tex, texvec, dxt, dyt, osatex, texres, 0, 0);
+}
+
+int multitex_thread(Tex *tex, float *texvec, float *dxt, float *dyt, int osatex, TexResult *texres, short thread, short which_output)
+{
        if(tex==NULL) {
                memset(texres, 0, sizeof(TexResult));
                return 0;
@@ -1264,10 +1305,10 @@ int multitex_ext(Tex *tex, float *texvec, float *dxt, float *dyt, int osatex, Te
                
                do_2d_mapping(&mtex, texvec_l, NULL, NULL, dxt_l, dyt_l);
 
-               return multitex(tex, texvec_l, dxt_l, dyt_l, osatex, texres);
+               return multitex(tex, texvec_l, dxt_l, dyt_l, osatex, texres, thread, which_output);
        }
        else
-               return multitex(tex, texvec, dxt, dyt, osatex, texres);
+               return multitex(tex, texvec, dxt, dyt, osatex, texres, thread, which_output);
 }
 
 /* ------------------------------------------------------------------------- */
@@ -1671,7 +1712,7 @@ void do_material_tex(ShadeInput *shi)
                                }
                        }
 
-                       rgbnor= multitex(tex, texvec, dxt, dyt, shi->osatex, &texres);
+                       rgbnor= multitex(tex, texvec, dxt, dyt, shi->osatex, &texres, shi->thread, mtex->which_output);
 
                        /* texture output */
 
@@ -2055,7 +2096,7 @@ void do_halo_tex(HaloRen *har, float xn, float yn, float *colf)
 
        if(mtex->tex->type==TEX_IMAGE) do_2d_mapping(mtex, texvec, NULL, NULL, dxt, dyt);
        
-       rgb= multitex(mtex->tex, texvec, dxt, dyt, osatex, &texres);
+       rgb= multitex(mtex->tex, texvec, dxt, dyt, osatex, &texres, 0, mtex->which_output);
 
        /* texture output */
        if(rgb && (mtex->texflag & MTEX_RGBTOINT)) {
@@ -2126,7 +2167,7 @@ void do_halo_tex(HaloRen *har, float xn, float yn, float *colf)
 /* ------------------------------------------------------------------------- */
 
 /* hor and zen are RGB vectors, blend is 1 float, should all be initialized */
-void do_sky_tex(float *rco, float *lo, float *dxyview, float *hor, float *zen, float *blend, int skyflag)
+void do_sky_tex(float *rco, float *lo, float *dxyview, float *hor, float *zen, float *blend, int skyflag, short thread)
 {
        MTex *mtex;
        TexResult texres= {0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0, NULL};
@@ -2226,7 +2267,7 @@ void do_sky_tex(float *rco, float *lo, float *dxyview, float *hor, float *zen, f
                        /* texture */
                        if(mtex->tex->type==TEX_IMAGE) do_2d_mapping(mtex, texvec, NULL, NULL, dxt, dyt);
                
-                       rgb= multitex(mtex->tex, texvec, dxt, dyt, R.osa, &texres);
+                       rgb= multitex(mtex->tex, texvec, dxt, dyt, R.osa, &texres, thread, mtex->which_output);
                        
                        /* texture output */
                        if(rgb && (mtex->texflag & MTEX_RGBTOINT)) {
@@ -2407,7 +2448,7 @@ void do_lamp_tex(LampRen *la, float *lavec, ShadeInput *shi, float *colf, int ef
                                do_2d_mapping(mtex, texvec, NULL, NULL, dxt, dyt);
                        }
                        
-                       rgb= multitex(tex, texvec, dxt, dyt, shi->osatex, &texres);
+                       rgb= multitex(tex, texvec, dxt, dyt, shi->osatex, &texres, shi->thread, mtex->which_output);
 
                        /* texture output */
                        if(rgb && (mtex->texflag & MTEX_RGBTOINT)) {
@@ -2492,7 +2533,7 @@ int externtex(MTex *mtex, float *vec, float *tin, float *tr, float *tg, float *t
                do_2d_mapping(mtex, texvec, NULL, NULL, dxt, dyt);
        }
        
-       rgb= multitex(tex, texvec, dxt, dyt, 0, &texr);
+       rgb= multitex(tex, texvec, dxt, dyt, 0, &texr, 0, mtex->which_output);
        
        if(rgb) {
                texr.tin= (0.35*texr.tr+0.45*texr.tg+0.2*texr.tb);
index 5b5c7f2d5ba9540bfb9397c4b7574ce894e6353b..ba4d02d2355f6b78aed344f9d3c8154974f92495 100644 (file)
@@ -511,7 +511,8 @@ void curvemap_buttons(uiBlock *block, CurveMapping *cumap, char labeltype, short
 static void do_node_buts(unsigned short event)
 {
        Material *ma;
-
+       SpaceNode *snode = curarea->spacedata.first;
+       
        /* all operations default on active material layer here */
        /* but this also gets called for lamp and world... */
        ma= G.buts->lockpoin;
@@ -523,6 +524,7 @@ static void do_node_buts(unsigned short event)
        if(event>=B_NODE_EXEC) {
                if(ma) end_render_material(ma); /// temporal... 3d preview
                BIF_preview_changed(ID_MA);
+               BIF_preview_changed(ID_TE);
                allqueue(REDRAWNODE, 0);
                allqueue(REDRAWBUTSSHADING, 0);
        }               
index f1250c975fb894a2b9819434a8d21078f3f43885..6c1eff290724cc7f1217079b01ef08f159749cc5 100644 (file)
@@ -286,6 +286,7 @@ void do_texbuts(unsigned short event)
                scrarea_queue_headredraw(curarea);
                BIF_preview_changed(ID_TE);
                allqueue(REDRAWBUTSSHADING, 0);
+               allqueue(REDRAWNODE, 0);
                if(G.buts->texfrom == 3) /* brush texture */
                        allqueue(REDRAWIMAGE, 0);
                break;
@@ -414,6 +415,16 @@ void do_texbuts(unsigned short event)
                        }
                }
                break;
+       case B_TEX_USENODES:
+               if(tex->use_nodes && tex->nodetree==NULL) {
+                       node_texture_default(tex);
+               }
+               tex->type = 0;
+               BIF_preview_changed(ID_TE);
+               allqueue(REDRAWNODE, 0);
+               allqueue(REDRAWBUTSSHADING, 0);
+               allqueue(REDRAWIPO, 0);
+               break;
                
        default:
                if(event>=B_PLUGBUT && event<=B_PLUGBUT+23) {
@@ -1687,10 +1698,13 @@ static void texture_panel_texture(MTex *actmtex, Material *ma, World *wrld, Lamp
                
                /* newnoise: all texture types as menu, not enough room for more buttons.
                 * Can widen panel, but looks ugly when other panels overlap it */
+               if( !tex->use_nodes ) {
+                       sprintf(textypes, "Texture Type %%t|None %%x%d|Image %%x%d|EnvMap %%x%d|Clouds %%x%d|Marble %%x%d|Stucci %%x%d|Wood %%x%d|Magic %%x%d|Blend %%x%d|Noise %%x%d|Plugin %%x%d|Musgrave %%x%d|Voronoi %%x%d|DistortedNoise %%x%d", 0, TEX_IMAGE, TEX_ENVMAP, TEX_CLOUDS, TEX_MARBLE, TEX_STUCCI, TEX_WOOD, TEX_MAGIC, TEX_BLEND, TEX_NOISE, TEX_PLUGIN, TEX_MUSGRAVE, TEX_VORONOI, TEX_DISTNOISE);
+                       uiDefBut(block, LABEL, 0, "Texture Type",               160, 150, 140, 20, 0, 0.0, 0.0, 0, 0, "");
+                       uiDefButS(block, MENU, B_TEXTYPE, textypes,     160, 125, 140, 25, &tex->type, 0,0,0,0, "Select texture type");
+               }
                
-               sprintf(textypes, "Texture Type %%t|None %%x%d|Image %%x%d|EnvMap %%x%d|Clouds %%x%d|Marble %%x%d|Stucci %%x%d|Wood %%x%d|Magic %%x%d|Blend %%x%d|Noise %%x%d|Plugin %%x%d|Musgrave %%x%d|Voronoi %%x%d|DistortedNoise %%x%d", 0, TEX_IMAGE, TEX_ENVMAP, TEX_CLOUDS, TEX_MARBLE, TEX_STUCCI, TEX_WOOD, TEX_MAGIC, TEX_BLEND, TEX_NOISE, TEX_PLUGIN, TEX_MUSGRAVE, TEX_VORONOI, TEX_DISTNOISE);
-               uiDefBut(block, LABEL, 0, "Texture Type",               160, 150, 140, 20, 0, 0.0, 0.0, 0, 0, "");
-               uiDefButS(block, MENU, B_TEXTYPE, textypes,     160, 125, 140, 25, &tex->type, 0,0,0,0, "Select texture type");
+               uiDefButC(block, TOG, B_TEX_USENODES, "Nodes", 160, 100, 140, 25, &tex->use_nodes, 0.0f, 0.0f, 0, 0, "");
 
        }
        else {
@@ -3684,6 +3698,11 @@ static void material_panel_texture(Object *ob, Material *ma)
                uiBlockSetCol(block, TH_AUTO);
                uiDefBut(block, BUT, B_TEXCLEAR, "Clear",                       122, 130, 72, 20, 0, 0, 0, 0, 0, "Erases link to texture");
                
+               if(mtex->tex->use_nodes) {
+                       char *menustr = ntreeTexOutputMenu(mtex->tex->nodetree);
+                       uiDefButS(block, MENU, B_MATPRV, menustr, 100, 100, 163, 20, &mtex->which_output, 0, 0, 0, 0, "Which output to use, for multi-output textures");
+                       free(menustr);
+               }
        }
        else 
                uiDefButS(block, TOG, B_EXTEXBROWSE, "Add New" ,100, 150, 163, 20, &(G.buts->texnr), -1.0, 32767.0, 0, 0, "Adds a new texture datablock");
index 618eca15ac63df4f5ac251444fcba889afe073c8..ddde111f14b57741225931e8e6eb55176bd95570 100644 (file)
@@ -451,6 +451,9 @@ static void node_browse_tex_cb(void *ntree_v, void *node_v)
        
        nodeSetActive(ntree, node);
        
+       if( ntree->type == NTREE_TEXTURE )
+               ntreeTexCheckCyclics( ntree );
+       
        allqueue(REDRAWBUTSSHADING, 0);
        allqueue(REDRAWNODE, 0);
        NodeTagChanged(ntree, node); 
@@ -491,29 +494,40 @@ static void node_dynamic_update_cb(void *ntree_v, void *node_v)
 
 static int node_buts_texture(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
 {
+       short multi = (node->id && ((Tex*)node->id)->use_nodes && (node->type != CMP_NODE_TEXTURE));
+       
        if(block) {
                uiBut *bt;
                char *strp;
+               short width = (short)(butr->xmax - butr->xmin);
                
                /* browse button texture */
                uiBlockBeginAlign(block);
                IDnames_to_pupstring(&strp, NULL, "", &(G.main->tex), NULL, NULL);
                node->menunr= 0;
                bt= uiDefButS(block, MENU, B_NODE_EXEC+node->nr, strp, 
-                                         butr->xmin, butr->ymin, 20, 19, 
+                               butr->xmin, butr->ymin+(multi?30:0), 20, 19, 
                                          &node->menunr, 0, 0, 0, 0, "Browse texture");
                uiButSetFunc(bt, node_browse_tex_cb, ntree, node);
                if(strp) MEM_freeN(strp);
                
                if(node->id) {
                        bt= uiDefBut(block, TEX, B_NOP, "TE:",
-                                                butr->xmin+19, butr->ymin, butr->xmax-butr->xmin-19, 19, 
+                                       butr->xmin+19, butr->ymin+(multi?30:0), butr->xmax-butr->xmin-19, 19, 
                                                 node->id->name+2, 0.0, 19.0, 0, 0, "Texture name");
                        uiButSetFunc(bt, node_ID_title_cb, node, NULL);
                }
+               uiBlockEndAlign(block);
                
+               if(multi) {
+                       char *menustr = ntreeTexOutputMenu(((Tex*)node->id)->nodetree);
+                       uiDefButS(block, MENU, B_MATPRV, menustr, butr->xmin, butr->ymin, width, 19, &node->custom1, 0, 0, 0, 0, "Which output to use, for multi-output textures");
+                       free(menustr);
+                       return 50;
+               }
+               return 20;
        }       
-       return 19;
+       else return multi? 50: 20;
 }
 
 static int node_buts_math(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) 
@@ -2183,6 +2197,261 @@ static void node_composit_set_butfunc(bNodeType *ntype)
        }
 }
 
+/* ****************** BUTTON CALLBACKS FOR TEXTURE NODES ***************** */
+
+static int node_texture_buts_bricks(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+       if(block) {
+               short w = butr->xmax-butr->xmin;
+               short ofw = 32;
+               
+               uiBlockBeginAlign(block);
+               
+               /* Offset */
+               uiDefButF(
+                       block, NUM, B_NODE_EXEC+node->nr, "Offset",
+                       butr->xmin, butr->ymin+20, w-ofw, 20,
+                       &node->custom3,
+                       0, 1, 0.25, 2,
+                       "Offset amount" );
+               uiDefButS(
+                       block, NUM, B_NODE_EXEC+node->nr, "",
+                       butr->xmin+w-ofw, butr->ymin+20, ofw, 20,
+                       &node->custom1,
+                       2, 99, 0, 0,
+                       "Offset every N rows" );
+               
+               /* Squash */
+               uiDefButF(
+                       block, NUM, B_NODE_EXEC+node->nr, "Squash",
+                       butr->xmin, butr->ymin+0, w-ofw, 20,
+                       &node->custom4,
+                       0, 99, 0.25, 2,
+                       "Stretch amount" );
+               uiDefButS(
+                       block, NUM, B_NODE_EXEC+node->nr, "",
+                       butr->xmin+w-ofw, butr->ymin+0, ofw, 20,
+                       &node->custom2,
+                       2, 99, 0, 0,
+                       "Stretch every N rows" );
+               
+               uiBlockEndAlign(block);
+       }
+       return 40;
+}
+
+/* Copied from buttons_shading.c -- needs unifying */
+static char* noisebasis_menu()
+{
+       static char nbmenu[256];
+       sprintf(nbmenu, "Noise Basis %%t|Blender Original %%x%d|Original Perlin %%x%d|Improved Perlin %%x%d|Voronoi F1 %%x%d|Voronoi F2 %%x%d|Voronoi F3 %%x%d|Voronoi F4 %%x%d|Voronoi F2-F1 %%x%d|Voronoi Crackle %%x%d|CellNoise %%x%d", TEX_BLENDER, TEX_STDPERLIN, TEX_NEWPERLIN, TEX_VORONOI_F1, TEX_VORONOI_F2, TEX_VORONOI_F3, TEX_VORONOI_F4, TEX_VORONOI_F2F1, TEX_VORONOI_CRACKLE, TEX_CELLNOISE);
+       return nbmenu;
+}
+
+static int node_texture_buts_proc(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+       Tex *tex = (Tex *)node->storage;
+       short x,y,w,h;
+       
+       if( block ) {
+               x = butr->xmin;
+               y = butr->ymin;
+               w = butr->xmax - x;
+               h = butr->ymax - y;
+       }
+       
+       switch( tex->type ) {
+               case TEX_BLEND:
+                       if( block ) {
+                               uiBlockBeginAlign( block );
+                               uiDefButS( block, MENU, B_NODE_EXEC+node->nr,
+                                       "Linear %x0|Quad %x1|Ease %x2|Diag %x3|Sphere %x4|Halo %x5|Radial %x6",
+                                       x, y+20, w, 20, &tex->stype, 0, 1, 0, 0, "Blend Type" );
+                               uiDefButBitS(block, TOG, TEX_FLIPBLEND, B_NODE_EXEC+node->nr, "Flip XY", x, y, w, 20,
+                                       &tex->flag, 0, 0, 0, 0, "Flips the direction of the progression 90 degrees");
+                               uiBlockEndAlign( block );
+                       }
+                       return 40;
+                       
+                       
+               case TEX_MARBLE:
+                       if( block ) {
+                               uiBlockBeginAlign(block);
+                       
+                               uiDefButS(block, ROW, B_NODE_EXEC+node->nr, "Soft",       0*w/3+x, 40+y, w/3, 18, &tex->stype, 2.0, (float)TEX_SOFT, 0, 0, "Uses soft marble"); 
+                               uiDefButS(block, ROW, B_NODE_EXEC+node->nr, "Sharp",      1*w/3+x, 40+y, w/3, 18, &tex->stype, 2.0, (float)TEX_SHARP, 0, 0, "Uses more clearly defined marble"); 
+                               uiDefButS(block, ROW, B_NODE_EXEC+node->nr, "Sharper",    2*w/3+x, 40+y, w/3, 18, &tex->stype, 2.0, (float)TEX_SHARPER, 0, 0, "Uses very clearly defined marble"); 
+                               
+                               uiDefButS(block, ROW, B_NODE_EXEC+node->nr, "Soft noise", 0*w/2+x, 20+y, w/2, 19, &tex->noisetype, 12.0, (float)TEX_NOISESOFT, 0, 0, "Generates soft noise");
+                               uiDefButS(block, ROW, B_NODE_EXEC+node->nr, "Hard noise", 1*w/2+x, 20+y, w/2, 19, &tex->noisetype, 12.0, (float)TEX_NOISEPERL, 0, 0, "Generates hard noise");
+                               
+                               uiDefButS(block, ROW, B_NODE_EXEC+node->nr, "Sin",        0*w/3+x,  0+y, w/3, 18, &tex->noisebasis2, 8.0, 0.0, 0, 0, "Uses a sine wave to produce bands."); 
+                               uiDefButS(block, ROW, B_NODE_EXEC+node->nr, "Saw",        1*w/3+x,  0+y, w/3, 18, &tex->noisebasis2, 8.0, 1.0, 0, 0, "Uses a saw wave to produce bands"); 
+                               uiDefButS(block, ROW, B_NODE_EXEC+node->nr, "Tri",        2*w/3+x,  0+y, w/3, 18, &tex->noisebasis2, 8.0, 2.0, 0, 0, "Uses a triangle wave to produce bands"); 
+            
+                               uiBlockEndAlign(block);
+                       }
+                       return 60;
+                       
+               case TEX_WOOD:
+                       if( block ) {
+                               uiDefButS(block, MENU, B_TEXPRV, noisebasis_menu(), x, y+64, w, 18, &tex->noisebasis, 0,0,0,0, "Sets the noise basis used for turbulence");
+                               
+                               uiBlockBeginAlign(block);
+                               uiDefButS(block, ROW, B_TEXPRV,             "Bands",     x,  40+y, w/2, 18, &tex->stype, 2.0, (float)TEX_BANDNOISE, 0, 0, "Uses standard noise"); 
+                               uiDefButS(block, ROW, B_TEXPRV,             "Rings", w/2+x,  40+y, w/2, 18, &tex->stype, 2.0, (float)TEX_RINGNOISE, 0, 0, "Lets Noise return RGB value"); 
+                               
+                               uiDefButS(block, ROW, B_NODE_EXEC+node->nr, "Sin", 0*w/3+x,  20+y, w/3, 18, &tex->noisebasis2, 8.0, (float)TEX_SIN, 0, 0, "Uses a sine wave to produce bands."); 
+                               uiDefButS(block, ROW, B_NODE_EXEC+node->nr, "Saw", 1*w/3+x,  20+y, w/3, 18, &tex->noisebasis2, 8.0, (float)TEX_SAW, 0, 0, "Uses a saw wave to produce bands"); 
+                               uiDefButS(block, ROW, B_NODE_EXEC+node->nr, "Tri", 2*w/3+x,  20+y, w/3, 18, &tex->noisebasis2, 8.0, (float)TEX_TRI, 0, 0, "Uses a triangle wave to produce bands");
+                               
+                               uiDefButS(block, ROW, B_NODE_EXEC+node->nr, "Soft noise", 0*w/2+x, 0+y, w/2, 19, &tex->noisetype, 12.0, (float)TEX_NOISESOFT, 0, 0, "Generates soft noise");
+                               uiDefButS(block, ROW, B_NODE_EXEC+node->nr, "Hard noise", 1*w/2+x, 0+y, w/2, 19, &tex->noisetype, 12.0, (float)TEX_NOISEPERL, 0, 0, "Generates hard noise");
+                               uiBlockEndAlign(block);
+                       }
+                       return 80; 
+                       
+               case TEX_CLOUDS:
+                       if( block ) {
+                               uiDefButS(block, MENU, B_TEXPRV, noisebasis_menu(), x, y+60, w, 18, &tex->noisebasis, 0,0,0,0, "Sets the noise basis used for turbulence");
+                               
+                               uiBlockBeginAlign(block);
+                               uiDefButS(block, ROW, B_TEXPRV, "B/W",       x, y+38, w/2, 18, &tex->stype, 2.0, (float)TEX_DEFAULT, 0, 0, "Uses standard noise"); 
+                               uiDefButS(block, ROW, B_TEXPRV, "Color", w/2+x, y+38, w/2, 18, &tex->stype, 2.0, (float)TEX_COLOR, 0, 0, "Lets Noise return RGB value"); 
+                               uiDefButS(block, ROW, B_TEXPRV, "Soft",      x, y+20, w/2, 18, &tex->noisetype, 12.0, (float)TEX_NOISESOFT, 0, 0, "Generates soft noise");
+                               uiDefButS(block, ROW, B_TEXPRV, "Hard",  w/2+x, y+20, w/2, 18, &tex->noisetype, 12.0, (float)TEX_NOISEPERL, 0, 0, "Generates hard noise");
+                               uiBlockEndAlign(block);
+                               
+                               uiDefButS(block, NUM, B_TEXPRV, "Depth:", x, y, w, 18, &tex->noisedepth, 0.0, 6.0, 0, 0, "Sets the depth of the cloud calculation");
+                       }
+                       return 80;
+                       
+               case TEX_DISTNOISE:
+                       if( block ) {
+                               uiBlockBeginAlign(block);
+                               uiDefButS(block, MENU, B_TEXPRV, noisebasis_menu(), x, y+18, w, 18, &tex->noisebasis2, 0,0,0,0, "Sets the noise basis to distort");
+                               uiDefButS(block, MENU, B_TEXPRV, noisebasis_menu(), x, y,    w, 18, &tex->noisebasis,  0,0,0,0, "Sets the noise basis which does the distortion");
+                               uiBlockEndAlign(block);
+                       }
+                       return 36;
+       }
+       return 0;
+}
+
+static int node_texture_buts_image(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+       char *strp;
+       uiBut *bt;
+       
+       if( block ) {
+               uiBlockBeginAlign(block);
+               uiBlockSetCol(block, TH_BUT_SETTING2);
+               
+               /* browse button */
+               IMAnames_to_pupstring(&strp, NULL, "LOAD NEW %x32767", &(G.main->image), NULL, NULL);
+               node->menunr= 0;
+               bt= uiDefButS(block, MENU, B_NOP, strp, 
+                                         butr->xmin, butr->ymin, 19, 19, 
+                                         &node->menunr, 0, 0, 0, 0, "Browses existing choices");
+               uiButSetFunc(bt, node_browse_image_cb, ntree, node);
+               if(strp) MEM_freeN(strp);
+               
+               /* Add New button */
+               if(node->id==NULL) {
+                       bt= uiDefBut(block, BUT, B_NODE_LOADIMAGE, "Load New",
+                                                butr->xmin+19, butr->ymin, (short)(butr->xmax-butr->xmin-19.0f), 19, 
+                                                NULL, 0.0, 0.0, 0, 0, "Add new Image");
+                       uiButSetFunc(bt, node_active_cb, ntree, node);
+                       uiBlockSetCol(block, TH_AUTO);
+               }
+               else {
+                       /* name button */
+                       short xmin= (short)butr->xmin, xmax= (short)butr->xmax;
+                       short width= xmax - xmin - 19;
+                       
+                       bt= uiDefBut(block, TEX, B_NOP, "IM:",
+                                                xmin+19, butr->ymin, width, 19, 
+                                                node->id->name+2, 0.0, 19.0, 0, 0, "Image name");
+                       uiButSetFunc(bt, node_ID_title_cb, node, NULL);
+               }
+       }
+       return 20;
+}
+
+static int node_texture_buts_output(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
+{
+       if( block ) {
+               uiBut *bt;
+               short width;
+               char *name = ((TexNodeOutput*)node->storage)->name;
+               
+               uiBlockBeginAlign(block);
+               
+               width = (short)(butr->xmax - butr->xmin);
+               
+               bt = uiDefBut(
+                       block, TEX, B_NOP,
+                       "Name:",
+                       butr->xmin, butr->ymin,
+                       width, 19, 
+                       name, 0, 31,
+                       0, 0, 
+                       "Name this output"
+               );
+               
+               uiBlockEndAlign(block);
+       }
+       return 19;
+}
+
+/* only once called */
+static void node_texture_set_butfunc(bNodeType *ntype)
+{
+       if( ntype->type >= TEX_NODE_PROC && ntype->type < TEX_NODE_PROC_MAX ) {
+               ntype->butfunc = node_texture_buts_proc;
+       }
+       else switch(ntype->type) {
+               
+               case TEX_NODE_MATH:
+                       ntype->butfunc = node_buts_math;
+                       break;
+               
+               case TEX_NODE_MIX_RGB:
+                       ntype->butfunc = node_buts_mix_rgb;
+                       break;
+                       
+               case TEX_NODE_VALTORGB:
+                       ntype->butfunc = node_buts_valtorgb;
+                       break;
+                       
+               case TEX_NODE_CURVE_RGB:
+                       ntype->butfunc= node_buts_curvecol;
+                       break;
+                       
+               case TEX_NODE_CURVE_TIME:
+                       ntype->butfunc = node_buts_time;
+                       break;
+                       
+               case TEX_NODE_TEXTURE:
+                       ntype->butfunc = node_buts_texture;
+                       break;
+                       
+               case TEX_NODE_BRICKS:
+                       ntype->butfunc = node_texture_buts_bricks;
+                       break;
+                       
+               case TEX_NODE_IMAGE:
+                       ntype->butfunc = node_texture_buts_image;
+                       break;
+                       
+               case TEX_NODE_OUTPUT:
+                       ntype->butfunc = node_texture_buts_output;
+                       break;
+                       
+               default:
+                       ntype->butfunc= NULL;
+       }
+}
 
 /* ******* init draw callbacks for all tree types, only called in usiblender.c, once ************* */
 
@@ -2202,6 +2471,11 @@ void init_node_butfuncs(void)
                node_composit_set_butfunc(ntype);
                ntype= ntype->next;
        }
+       ntype = node_all_textures.first;
+       while(ntype) {
+               node_texture_set_butfunc(ntype);
+               ntype= ntype->next;
+       }
 }
 
 /* ************** Generic drawing ************** */
index 23387673f950f843f276d7428d08f38d8cffc209..8fb47510485262ae2b6fc0046573835a0bd9aee1 100644 (file)
@@ -40,6 +40,7 @@
 #include "DNA_ipo_types.h"
 #include "DNA_object_types.h"
 #include "DNA_material_types.h"
+#include "DNA_texture_types.h"
 #include "DNA_node_types.h"
 #include "DNA_space_types.h"
 #include "DNA_screen_types.h"
@@ -53,6 +54,7 @@
 #include "BKE_main.h"
 #include "BKE_node.h"
 #include "BKE_material.h"
+#include "BKE_texture.h"
 #include "BKE_scene.h"
 #include "BKE_utildefines.h"
 
@@ -176,6 +178,9 @@ static void snode_handle_recalc(SpaceNode *snode)
 
                allqueue(REDRAWNODE, 1);
        }
+       else if(snode->treetype==NTREE_TEXTURE) {
+               ntreeTexUpdatePreviews(snode->nodetree);
+       }
 }
 
 static void shader_node_event(SpaceNode *snode, short event)
@@ -423,6 +428,36 @@ static void composit_node_event(SpaceNode *snode, short event)
        }
 }
 
+static void texture_node_event(SpaceNode *snode, short event)
+{
+       switch(event) {
+               case B_REDR:
+                       allqueue(REDRAWNODE, 1);
+                       break;
+               case B_NODE_LOADIMAGE:
+               {
+                       bNode *node= nodeGetActive(snode->edittree);
+                       char name[FILE_MAXDIR+FILE_MAXFILE];
+                       
+                       if(node->id)
+                               strcpy(name, ((Image *)node->id)->name);
+                       else strcpy(name, U.textudir);
+                       if (G.qual & LR_CTRLKEY) {
+                               activate_imageselect(FILE_SPECIAL, "SELECT IMAGE", name, load_node_image);
+                       } else {
+                               activate_fileselect(FILE_SPECIAL, "SELECT IMAGE", name, load_node_image);
+                       }
+                       break;
+               }
+               default:
+                       /* B_NODE_EXEC */
+                       ntreeTexCheckCyclics( snode->nodetree );
+                       snode_handle_recalc(snode);
+                       allqueue(REDRAWNODE, 1);
+                       break;
+       }
+}
+
 
 /* assumes nothing being done in ntree yet, sets the default in/out node */
 /* called from shading buttons or header */
@@ -486,6 +521,36 @@ void node_composit_default(Scene *sce)
        ntreeCompositForceHidden(sce->nodetree);
 }
 
+/* assumes nothing being done in ntree yet, sets the default in/out node */
+/* called from shading buttons or header */
+void node_texture_default(Tex *tx)
+{
+       bNode *in, *out;
+       bNodeSocket *fromsock, *tosock;
+       
+       /* but lets check it anyway */
+       if(tx->nodetree) {
+               printf("error in texture initialize\n");
+               return;
+       }
+       
+       tx->nodetree= ntreeAddTree(NTREE_TEXTURE);
+       
+       out= nodeAddNodeType(tx->nodetree, TEX_NODE_OUTPUT, NULL, NULL);
+       out->locx= 300.0f; out->locy= 300.0f;
+       
+       in= nodeAddNodeType(tx->nodetree, TEX_NODE_CHECKER, NULL, NULL);
+       in->locx= 10.0f; in->locy= 300.0f;
+       nodeSetActive(tx->nodetree, in);
+       
+       fromsock= in->outputs.first;
+       tosock= out->inputs.first;
+       nodeAddLink(tx->nodetree, in, fromsock, out, tosock);
+       
+       ntreeSolveOrder(tx->nodetree);  /* needed for pointers */
+       ntreeTexUpdatePreviews(tx->nodetree);
+}
+
 /* Here we set the active tree(s), even called for each redraw now, so keep it fast :) */
 void snode_set_context(SpaceNode *snode)
 {
@@ -516,6 +581,16 @@ void snode_set_context(SpaceNode *snode)
                
                snode->nodetree= G.scene->nodetree;
        }
+       else if(snode->treetype==NTREE_TEXTURE) {
+               if(ob) {
+                       Tex *tx= give_current_texture(ob, ob->actcol);
+                       if(tx) {
+                               snode->from= (ID*)ob; /* please check this; i have no idea what 'from' is. */
+                               snode->id= &tx->id;
+                               snode->nodetree= tx->nodetree;
+                       }
+               }
+       }
        
        /* find editable group */
        if(snode->nodetree)
@@ -608,6 +683,12 @@ static void node_set_active(SpaceNode *snode, bNode *node)
                                }
                        }
                }
+               else if(snode->treetype==NTREE_TEXTURE) {
+                       if(node->id)
+                               BIF_preview_changed(-1);
+                       allqueue(REDRAWBUTSSHADING, 1);
+                       allqueue(REDRAWIPO, 0);
+               }
        }
 }
 
@@ -1188,6 +1269,9 @@ static void scale_node(SpaceNode *snode, bNode *node)
                BIF_undo_push("Scale Node");
        
        allqueue(REDRAWNODE, 1);
+       
+       if(snode->nodetree->type == NTREE_TEXTURE)
+               ntreeTexUpdatePreviews(snode->nodetree);
 }
 
 /* ******************** rename ******************* */
@@ -1702,6 +1786,12 @@ bNode *node_add_node(SpaceNode *snode, int type, float locx, float locy)
                
                NodeTagChanged(snode->edittree, node);
        }
+       
+       if(snode->nodetree->type==NTREE_TEXTURE) {
+               ntreeTexCheckCyclics(snode->edittree);
+               ntreeTexUpdatePreviews(snode->edittree);
+       }
+       
        return node;
 }
 
@@ -2481,6 +2571,8 @@ void winqreadnodespace(ScrArea *sa, void *spacedata, BWinEvent *evt)
                                shader_node_event(snode, val);
                        else if(snode->treetype==NTREE_COMPOSIT)
                                composit_node_event(snode, val);
+                       else if(snode->treetype==NTREE_TEXTURE)
+                               texture_node_event(snode, val);
                        break;
                        
                case RENDERPREVIEW:
index d27a41c59f5cfd93993d140ae9fc196a86a4019d..2bd028766d1da30bb449aa9c3656a8353481c0cd 100644 (file)
@@ -68,6 +68,7 @@ void do_node_buttons(ScrArea *sa, unsigned short event)
 {
        SpaceNode *snode= sa->spacedata.first;
        Material *ma;
+       Tex *tx;
        
        switch(event) {
                case B_NODE_USEMAT:
@@ -93,6 +94,21 @@ void do_node_buttons(ScrArea *sa, unsigned short event)
                        snode_set_context(snode);
                        allqueue(REDRAWNODE, 0);
                        break;
+                       
+               case B_NODE_USETEX:
+                       tx = (Tex *)snode->id;
+                       if(tx) {
+                               tx->type = 0;
+                               if(tx->use_nodes && tx->nodetree==NULL) {
+                                       node_texture_default(tx);
+                                       snode_set_context(snode);
+                               }
+                               BIF_preview_changed(ID_TE);
+                               allqueue(REDRAWNODE, 0);
+                               allqueue(REDRAWBUTSSHADING, 0);
+                               allqueue(REDRAWIPO, 0);
+                       }
+                       break;
        }
 }
 
@@ -424,6 +440,36 @@ static uiBlock *node_add_distortmenu(void *arg_unused)
        
        return block;
 }
+static uiBlock *node_add_patternmenu(void *arg_unused)
+{
+       SpaceNode *snode= curarea->spacedata.first;
+       uiBlock *block;
+       
+       block= uiNewBlock(&curarea->uiblocks, "node_add_patternmenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
+       uiBlockSetButmFunc(block, do_node_addmenu, NULL);
+       
+       node_make_addmenu(snode, NODE_CLASS_PATTERN, block);
+       
+       uiBlockSetDirection(block, UI_RIGHT);
+       uiTextBoundsBlock(block, 60);
+       
+       return block;
+}
+static uiBlock *node_add_texturemenu(void *arg_unused)
+{
+       SpaceNode *snode= curarea->spacedata.first;
+       uiBlock *block;
+       
+       block= uiNewBlock(&curarea->uiblocks, "node_add_texturemenu", UI_EMBOSSP, UI_HELV, G.curscreen->mainwin);
+       uiBlockSetButmFunc(block, do_node_addmenu, NULL);
+       
+       node_make_addmenu(snode, NODE_CLASS_TEXTURE, block);
+       
+       uiBlockSetDirection(block, UI_RIGHT);
+       uiTextBoundsBlock(block, 60);
+       
+       return block;
+}
 static uiBlock *node_add_groupmenu(void *arg_unused)
 {
        SpaceNode *snode= curarea->spacedata.first;
@@ -486,7 +532,17 @@ static uiBlock *node_addmenu(void *arg_unused)
                uiDefIconTextBlockBut(block, node_add_distortmenu, NULL, ICON_RIGHTARROW_THIN, "Distort", 0, yco-=20, 120, 19, "");
                uiDefIconTextBlockBut(block, node_add_groupmenu, NULL, ICON_RIGHTARROW_THIN, "Group", 0, yco-=20, 120, 19, "");
 
-       } else
+       } else if(snode->treetype==NTREE_TEXTURE) {
+               uiDefIconTextBlockBut(block, node_add_inputmenu, NULL, ICON_RIGHTARROW_THIN, "Input", 0, yco-=20, 120, 19, "");
+               uiDefIconTextBlockBut(block, node_add_outputmenu, NULL, ICON_RIGHTARROW_THIN, "Output", 0, yco-=20, 120, 19, "");
+               uiDefIconTextBlockBut(block, node_add_colormenu, NULL, ICON_RIGHTARROW_THIN, "Color", 0, yco-=20, 120, 19, "");
+               uiDefIconTextBlockBut(block, node_add_patternmenu, NULL, ICON_RIGHTARROW_THIN, "Patterns", 0, yco-=20, 120, 19, "");
+               uiDefIconTextBlockBut(block, node_add_texturemenu, NULL, ICON_RIGHTARROW_THIN, "Textures", 0, yco-=20, 120, 19, "");
+               uiDefIconTextBlockBut(block, node_add_convertermenu, NULL, ICON_RIGHTARROW_THIN, "Convertor", 0, yco-=20, 120, 19, "");
+               uiDefIconTextBlockBut(block, node_add_distortmenu, NULL, ICON_RIGHTARROW_THIN, "Distort", 0, yco-=20, 120, 19, "");
+               uiDefIconTextBlockBut(block, node_add_groupmenu, NULL, ICON_RIGHTARROW_THIN, "Group", 0, yco-=20, 120, 19, "");
+       }
+       else
                uiDefBut(block, SEPR, 0, "",        0, yco-=6, menuwidth, 6, NULL, 0.0, 0.0, 0, 0, ""); 
        
        if(curarea->headertype==HEADERTOP) {
@@ -696,6 +752,9 @@ void node_buttons(ScrArea *sa)
        xco+= XIC;
        uiDefIconButI(block, ROW, B_REDR, ICON_IMAGE_DEHLT, xco,2,XIC,YIC-2,
                                  &(snode->treetype), 2, 1, 0, 0, "Composite Nodes");
+       xco+= XIC;
+       uiDefIconButI(block, ROW, B_REDR, ICON_TEXTURE_DEHLT, xco,2,XIC,YIC-2,
+                                 &(snode->treetype), 2, 2, 0, 0, "Texture Nodes");
        xco+= 2*XIC;
        uiBlockEndAlign(block);
        
@@ -723,6 +782,19 @@ void node_buttons(ScrArea *sa)
                uiDefButBitS(block, TOG, SNODE_BACKDRAW, REDRAWNODE, "Backdrop", xco+5,0,80,19, &snode->flag, 0.0f, 0.0f, 0, 0, "Use active Viewer Node output as backdrop");
                xco+= 80;
        }
+       else if(snode->treetype==NTREE_TEXTURE) {
+               if(snode->from) {
+                       
+                       xco= std_libbuttons(block, xco, 0, 0, NULL, B_TEXBROWSE, ID_TE, 1, snode->id, snode->from, &(snode->menunr), 
+                                          B_TEXALONE, B_TEXLOCAL, B_TEXDELETE, B_AUTOTEXNAME, B_KEEPDATA);
+                       
+                       if(snode->id) {
+                               Tex *tx= (Tex *)snode->id;
+                               uiDefButC(block, TOG, B_NODE_USETEX, "Use Nodes", xco+5,0,70,19, &tx->use_nodes, 0.0f, 0.0f, 0, 0, "");
+                               xco+=80;
+                       }
+               }
+       }
        
        /* always as last  */
        sa->headbutlen= xco+2*XIC;
index 7c97fa8431d70c424f637acfdd76cfe232561f34..f4135071e3ef7ed87fad3624a3513c664541c203 100644 (file)
@@ -427,6 +427,15 @@ static void do_update_for_newframe(int mute, int events)
        /* composite */
        if(G.scene->use_nodes && G.scene->nodetree)
                ntreeCompositTagAnimated(G.scene->nodetree);
+       
+       /* update animated texture nodes */
+       {
+               Tex *tex;
+               for(tex= G.main->tex.first; tex; tex= tex->id.next)
+               if( tex->use_nodes && tex->nodetree ) {
+                       ntreeTexTagAnimated( tex->nodetree );
+               }
+       }
 }
 
 void update_for_newframe(void)
@@ -858,10 +867,25 @@ void do_global_buttons(unsigned short event)
                break;
        case B_EXTEXBROWSE: 
        case B_TEXBROWSE:
-
-               if(G.buts->texnr== -2) {
+       {
+               void  *lockpoin = NULL;
+               short *menunr = 0;
+               
+               /* this is called now from Node editor too, buttons might not exist */
+               if(curarea->spacetype==SPACE_NODE) {
+                       SpaceNode *snode = curarea->spacedata.first;
+                       menunr = &snode->menunr;
+                       lockpoin = snode->id;
+               }
+               else if(G.buts) {
+                       menunr = &G.buts->texnr;
+                       lockpoin = G.buts->lockpoin;
+               }
+               else return;
+               
+               if(*menunr == -2) {
                        
-                       id= G.buts->lockpoin;
+                       id= lockpoin;
                        if(event==B_EXTEXBROWSE) {
                                id= NULL;
                                ma= give_current_material(ob, ob->actcol);
@@ -872,16 +896,16 @@ void do_global_buttons(unsigned short event)
                                }
                        }
                        if(G.qual & LR_CTRLKEY) {
-                               activate_databrowse_imasel(id, ID_TE, 0, B_TEXBROWSE, &G.buts->texnr, do_global_buttons);
+                               activate_databrowse_imasel((ID*)lockpoin, ID_TE, 0, B_TEXBROWSE, menunr, do_global_buttons);
                        }
                        else {
-                               activate_databrowse(id, ID_TE, 0, B_TEXBROWSE, &G.buts->texnr, do_global_buttons);
+                               activate_databrowse((ID*)lockpoin, ID_TE, 0, B_TEXBROWSE, menunr, do_global_buttons);
                        }
                        return;
                }
-               if(G.buts->texnr < 0) break;
+               if(*menunr < 0) break;
                
-               if(G.buts->pin) {
+               if(G.buts && G.buts->pin) {
                        
                }
                else {
@@ -896,7 +920,7 @@ void do_global_buttons(unsigned short event)
 
                        idtest= G.main->tex.first;
                        while(idtest) {
-                               if(nr==G.buts->texnr) {
+                               if(nr==*menunr) {
                                        break;
                                }
                                nr++;
@@ -919,10 +943,12 @@ void do_global_buttons(unsigned short event)
                                allqueue(REDRAWBUTSSHADING, 0);
                                allqueue(REDRAWIPO, 0);
                                allqueue(REDRAWOOPS, 0);
+                               allqueue(REDRAWNODE, 0);
                                BIF_preview_changed(ID_MA);
                        }
                }
                break;
+       }
        case B_ACTIONDELETE:
                /* only available when not pinned */
                if (G.saction->pin == 0) {
index 1c028c3f18be4e898b0d840888cb14cb1bcbaecd..b675f6868f839a19594679af057e36aa7df8ad7f 100644 (file)
@@ -1595,6 +1595,17 @@ static TBitem tb_node_addcomp[]= {
        {       0, "Group",             9, NULL},
        {       0, "Dynamic",   10, NULL},
        {       -1, "",                 0, NULL}};
+       
+static TBitem tb_node_addtex[]= {
+       {    0, "Input",        1, NULL},
+       {    0, "Output",       2, NULL},
+       {    0, "Color",        3, NULL},
+       {    0, "Convertor",    4, NULL},
+       {    0, "Patterns",     5, NULL},
+       {    0, "Textures",     6, NULL},
+       {    0, "Distort",      7, NULL},
+       {    0, "Group",        8, NULL},
+       {   -1, "",             0, NULL}};
 
 /* do_node_addmenu() in header_node.c, prototype in BSE_headerbuttons.h */
 
@@ -2126,7 +2137,7 @@ void toolbox_n(void)
                                        menu3= tb__select;
                                        menu4= tb_edit;
                                        menu5= tb_transform_editmode2;
-                               }
+                               }                                                               
                                else if(G.obedit->type==OB_LATTICE) {
                                        menu1= tb_empty;str1= "Lattice";
                                        menu2= tb_empty;
@@ -2145,8 +2156,11 @@ void toolbox_n(void)
                
                if(snode->treetype==NTREE_COMPOSIT)
                        menu1= tb_node_addcomp; 
-               else
+               else if(snode->treetype==NTREE_SHADER)
                        menu1= tb_node_addsh; 
+               else if(snode->treetype==NTREE_TEXTURE)
+                       menu1= tb_node_addtex;
+               
                str1= "Add";
                menu2= tb_node_node; str2= "Node";
                menu3= tb_node_select; str3= "Select";
@@ -2173,8 +2187,17 @@ void toolbox_n(void)
                        menu1[7].poin= node_add_sublevel(&storage, snode->nodetree, NODE_CLASS_DISTORT);
                        menu1[8].poin= node_add_sublevel(&storage, snode->nodetree, NODE_CLASS_GROUP);
                        menu1[9].poin= node_add_sublevel(&storage, snode->nodetree, NODE_CLASS_OP_DYNAMIC);
-
                }
+               else if(snode->treetype==NTREE_TEXTURE) {
+                       menu1[0].poin= node_add_sublevel(&storage, snode->nodetree, NODE_CLASS_INPUT);
+                       menu1[1].poin= node_add_sublevel(&storage, snode->nodetree, NODE_CLASS_OUTPUT);
+                       menu1[2].poin= node_add_sublevel(&storage, snode->nodetree, NODE_CLASS_OP_COLOR);
+                       menu1[3].poin= node_add_sublevel(&storage, snode->nodetree, NODE_CLASS_CONVERTOR);
+                       menu1[4].poin= node_add_sublevel(&storage, snode->nodetree, NODE_CLASS_PATTERN);
+                       menu1[5].poin= node_add_sublevel(&storage, snode->nodetree, NODE_CLASS_TEXTURE);
+                       menu1[6].poin= node_add_sublevel(&storage, snode->nodetree, NODE_CLASS_DISTORT);
+                       menu1[7].poin= node_add_sublevel(&storage, snode->nodetree, NODE_CLASS_GROUP);
+               }                                                                     
                
                dx= 96;
                tot= 5;