Made texture nodes accessible in the interface.
[blender.git] / source / blender / nodes / intern / TEX_util.c
1 /**
2  *
3  * ***** BEGIN GPL LICENSE BLOCK *****
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License
7  * as published by the Free Software Foundation; either version 2
8  * of the License, or (at your option) any later version. 
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software Foundation,
17  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18  *
19  * The Original Code is Copyright (C) 2005 Blender Foundation.
20  * All rights reserved.
21  *
22  * The Original Code is: all of this file.
23  *
24  * Contributor(s): none yet.
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28  
29 /*
30         HOW TEXTURE NODES WORK
31
32         In contrast to Shader nodes, which place a colour into the output
33         stack when executed, Texture nodes place a TexDelegate* there. To
34         obtain a colour value from this, a node further up the chain reads
35         the TexDelegate* from its input stack, and uses tex_call_delegate to
36         retrieve the colour from the delegate.
37  
38     comments: (ton)
39     
40     This system needs recode, a node system should rely on the stack, and 
41         callbacks for nodes only should evaluate own node, not recursively go
42     over other previous ones.
43 */
44
45 #include <assert.h>
46 #include "TEX_util.h"
47
48 #define PREV_RES 128 /* default preview resolution */
49
50 void tex_call_delegate(TexDelegate *dg, float *out, float *coord, short thread)
51 {
52         if(dg->node->need_exec)
53                 dg->fn(out, coord, dg->node, dg->in, thread);
54 }
55
56 void tex_input(float *out, int sz, bNodeStack *in, float *coord, short thread)
57 {
58         TexDelegate *dg = in->data;
59         if(dg) {
60                 tex_call_delegate(dg, in->vec, coord, thread);
61         
62                 if(in->hasoutput && in->sockettype == SOCK_VALUE)
63                         in->vec[1] = in->vec[2] = in->vec[0];
64         }
65         memcpy(out, in->vec, sz * sizeof(float));
66 }
67
68 void tex_input_vec(float *out, bNodeStack *in, float *coord, short thread)
69 {
70         tex_input(out, 3, in, coord, thread);
71 }
72
73 void tex_input_rgba(float *out, bNodeStack *in, float *coord, short thread)
74 {
75         tex_input(out, 4, in, coord, thread);
76         
77         if(in->hasoutput && in->sockettype == SOCK_VALUE)
78         {
79                 out[1] = out[2] = out[0];
80                 out[3] = 1;
81         }
82         
83         if(in->hasoutput && in->sockettype == SOCK_VECTOR) {
84                 out[0] = out[0] * .5f + .5f;
85                 out[1] = out[1] * .5f + .5f;
86                 out[2] = out[2] * .5f + .5f;
87                 out[3] = 1;
88         }
89 }
90
91 float tex_input_value(bNodeStack *in, float *coord, short thread)
92 {
93         float out[4];
94         tex_input_vec(out, in, coord, thread);
95         return out[0];
96 }
97
98 static void init_preview(bNode *node)
99 {
100         int xsize = (int)(node->prvr.xmax - node->prvr.xmin);
101         int ysize = (int)(node->prvr.ymax - node->prvr.ymin);
102         
103         if(xsize == 0) {
104                 xsize = PREV_RES;
105                 ysize = PREV_RES;
106         }
107         
108         if(node->preview==NULL)
109                 node->preview= MEM_callocN(sizeof(bNodePreview), "node preview");
110         
111         if(node->preview->rect)
112                 if(node->preview->xsize!=xsize && node->preview->ysize!=ysize) {
113                         MEM_freeN(node->preview->rect);
114                         node->preview->rect= NULL;
115                 }
116         
117         if(node->preview->rect==NULL) {
118                 node->preview->rect= MEM_callocN(4*xsize + xsize*ysize*sizeof(float)*4, "node preview rect");
119                 node->preview->xsize= xsize;
120                 node->preview->ysize= ysize;
121         }
122 }
123
124 void tex_do_preview(bNode *node, bNodeStack *ns, TexCallData *cdata)
125 {
126         int x, y;
127         float *result;
128         bNodePreview *preview;
129         
130         if(!cdata->do_preview)
131                 return;
132         
133         if(!(node->typeinfo->flag & NODE_PREVIEW))
134                 return;
135         
136         init_preview(node);
137         
138         preview = node->preview;
139         
140         for(x=0; x<preview->xsize; x++)
141         for(y=0; y<preview->ysize; y++)
142         {
143                 cdata->coord[0] = ((float) x / preview->xsize) * 2 - 1;
144                 cdata->coord[1] = ((float) y / preview->ysize) * 2 - 1;
145                 
146                 result = preview->rect + 4 * (preview->xsize*y + x);
147                 
148                 tex_input_rgba(result, ns, cdata->coord, cdata->thread);
149         }
150 }
151
152 void tex_output(bNode *node, bNodeStack **in, bNodeStack *out, TexFn texfn)
153 {
154         TexDelegate *dg;
155         if(!out->data)
156                 /* Freed in tex_end_exec (node.c) */
157                 dg = out->data = MEM_mallocN(sizeof(TexDelegate), "tex delegate");
158         else
159                 dg = out->data;
160         
161         
162         dg->fn = texfn;
163         dg->node = node;
164         memcpy(dg->in, in, MAX_SOCKET * sizeof(bNodeStack*));
165         dg->type = out->sockettype;
166 }
167
168 void ntreeTexCheckCyclics(struct bNodeTree *ntree)
169 {
170         bNode *node;
171         for(node= ntree->nodes.first; node; node= node->next) {
172                 
173                 if(node->type == TEX_NODE_TEXTURE && node->id)
174                 {
175                         /* custom2 stops the node from rendering */
176                         if(node->custom1) {
177                                 node->custom2 = 1;
178                                 node->custom1 = 0;
179                         } else {
180                                 Tex *tex = (Tex *)node->id;
181                                 
182                                 node->custom2 = 0;
183                         
184                                 node->custom1 = 1;
185                                 if(tex->use_nodes && tex->nodetree) {
186                                         ntreeTexCheckCyclics(tex->nodetree);
187                                 }
188                                 node->custom1 = 0;
189                         }
190                 }
191
192         }
193 }
194
195 void ntreeTexExecTree(bNodeTree *nodes, TexResult *texres, float *coord, char do_preview, short thread, Tex *tex, short which_output, int cfra)
196 {
197         TexResult dummy_texres;
198         TexCallData data;
199         
200         /* 0 means don't care, so just use first */
201         if(which_output == 0)
202                 which_output = 1;
203         
204         if(!texres) texres = &dummy_texres;
205         data.coord = coord;
206         data.target = texres;
207         data.do_preview = do_preview;
208         data.thread = thread;
209         data.which_output = which_output;
210         data.cfra= cfra;
211         
212         ntreeExecTree(nodes, &data, thread);
213 }
214
215 void ntreeTexUpdatePreviews(bNodeTree* nodetree)
216 {
217         Tex *tex;
218         float coord[] = {0,0,0};
219         TexResult dummy_texres;
220         
221         for(tex= G.main->tex.first; tex; tex= tex->id.next)
222                 if(tex->nodetree == nodetree) break;
223         if(!tex) return;
224         
225         dummy_texres.nor = 0;
226         
227         ntreeBeginExecTree(nodetree);
228         ntreeTexExecTree(nodetree, &dummy_texres, coord, 1, 0, tex, 0, 0);
229         ntreeEndExecTree(nodetree);
230         
231 }
232
233 char* ntreeTexOutputMenu(bNodeTree *ntree)
234 {
235         bNode *node;
236         int len = 1;
237         char *str;
238         char ctrl[4];
239         int index = 0;
240         
241         for(node= ntree->nodes.first; node; node= node->next)
242                 if(node->type == TEX_NODE_OUTPUT) {
243                         len += strlen( 
244                                 ((TexNodeOutput*)node->storage)->name
245                         ) + strlen(" %xNNN|");
246                         index ++;
247                         
248                         if(node->custom1 > 999) {
249                                 printf("Error: too many outputs");
250                                 break;
251                         }
252                 }
253                         
254         str = malloc(len * sizeof(char));
255         *str = 0;
256
257         for(node= ntree->nodes.first; node; node= node->next)
258                 if(node->type == TEX_NODE_OUTPUT) {
259                         strcat(str, ((TexNodeOutput*)node->storage)->name);
260                         strcat(str, " %x");
261                         
262                         sprintf(ctrl, "%d", node->custom1);
263                         strcat(str, ctrl);
264                         
265                         if(--index)
266                                 strcat(str, "|");
267                         else
268                                 break;
269                 }
270         
271         return str;
272 }
273
274 void ntreeTexAssignIndex(struct bNodeTree *ntree, struct bNode *node)
275 {
276         bNode *tnode;
277         int index = 1;
278         
279         if(ntree) 
280                 tnode = ntree->nodes.first;
281         else {
282                 tnode = node;
283                 while(tnode->prev) tnode = tnode->prev;
284         }
285         
286         check_index:
287         for(; tnode; tnode= tnode->next)
288                 if(tnode->type == TEX_NODE_OUTPUT && tnode != node)
289                         if(tnode->custom1 == index) {
290                                 index ++;
291                                 goto check_index;
292                         }
293                         
294         node->custom1 = index;
295 }
296