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

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTon Roosendaal <ton@blender.org>2008-11-12 22:03:50 +0300
committerTon Roosendaal <ton@blender.org>2008-11-12 22:03:50 +0300
commit8030cb03fd41673b7d687128782a0e21417baaea (patch)
treeb2e25d9a91ecf3713c45a4263f88a934e973e593 /source/blender/src
parent3fd3a13efc81ce3eafadd5ab31a154bbc25d6e58 (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.c4
-rw-r--r--source/blender/src/buttons_shading.c25
-rw-r--r--source/blender/src/drawnode.c280
-rw-r--r--source/blender/src/editnode.c92
-rw-r--r--source/blender/src/header_node.c74
-rw-r--r--source/blender/src/headerbuttons.c42
-rw-r--r--source/blender/src/toolbox.c29
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;