diff options
author | Ton Roosendaal <ton@blender.org> | 2008-11-12 22:03:50 +0300 |
---|---|---|
committer | Ton Roosendaal <ton@blender.org> | 2008-11-12 22:03:50 +0300 |
commit | 8030cb03fd41673b7d687128782a0e21417baaea (patch) | |
tree | b2e25d9a91ecf3713c45a4263f88a934e973e593 /source/blender/src | |
parent | 3fd3a13efc81ce3eafadd5ab31a154bbc25d6e58 (diff) |
Patch #7897 Texture Nodes!
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. :)
Diffstat (limited to 'source/blender/src')
-rw-r--r-- | source/blender/src/butspace.c | 4 | ||||
-rw-r--r-- | source/blender/src/buttons_shading.c | 25 | ||||
-rw-r--r-- | source/blender/src/drawnode.c | 280 | ||||
-rw-r--r-- | source/blender/src/editnode.c | 92 | ||||
-rw-r--r-- | source/blender/src/header_node.c | 74 | ||||
-rw-r--r-- | source/blender/src/headerbuttons.c | 42 | ||||
-rw-r--r-- | source/blender/src/toolbox.c | 29 |
7 files changed, 527 insertions, 19 deletions
diff --git a/source/blender/src/butspace.c b/source/blender/src/butspace.c index 5b5c7f2d5ba..ba4d02d2355 100644 --- a/source/blender/src/butspace.c +++ b/source/blender/src/butspace.c @@ -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); } diff --git a/source/blender/src/buttons_shading.c b/source/blender/src/buttons_shading.c index f1250c975fb..6c1eff29072 100644 --- a/source/blender/src/buttons_shading.c +++ b/source/blender/src/buttons_shading.c @@ -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"); diff --git a/source/blender/src/drawnode.c b/source/blender/src/drawnode.c index 618eca15ac6..ddde111f14b 100644 --- a/source/blender/src/drawnode.c +++ b/source/blender/src/drawnode.c @@ -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 ************** */ diff --git a/source/blender/src/editnode.c b/source/blender/src/editnode.c index 23387673f95..8fb47510485 100644 --- a/source/blender/src/editnode.c +++ b/source/blender/src/editnode.c @@ -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: diff --git a/source/blender/src/header_node.c b/source/blender/src/header_node.c index d27a41c59f5..2bd028766d1 100644 --- a/source/blender/src/header_node.c +++ b/source/blender/src/header_node.c @@ -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; diff --git a/source/blender/src/headerbuttons.c b/source/blender/src/headerbuttons.c index 7c97fa8431d..f4135071e3e 100644 --- a/source/blender/src/headerbuttons.c +++ b/source/blender/src/headerbuttons.c @@ -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) { diff --git a/source/blender/src/toolbox.c b/source/blender/src/toolbox.c index 1c028c3f18b..b675f6868f8 100644 --- a/source/blender/src/toolbox.c +++ b/source/blender/src/toolbox.c @@ -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; |