- rna sequence sound was referencing unknown struct
[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         if(!texres) texres = &dummy_texres;
201         data.coord = coord;
202         data.target = texres;
203         data.do_preview = do_preview;
204         data.thread = thread;
205         data.which_output = which_output;
206         data.cfra= cfra;
207         
208         ntreeExecTree(nodes, &data, thread);
209 }
210
211 void ntreeTexUpdatePreviews(bNodeTree* nodetree)
212 {
213         Tex *tex;
214         float coord[] = {0,0,0};
215         TexResult dummy_texres;
216         
217         for(tex= G.main->tex.first; tex; tex= tex->id.next)
218                 if(tex->nodetree == nodetree) break;
219         if(!tex) return;
220         
221         dummy_texres.nor = 0;
222         
223         ntreeBeginExecTree(nodetree);
224         ntreeTexExecTree(nodetree, &dummy_texres, coord, 1, 0, tex, 0, 0);
225         ntreeEndExecTree(nodetree);
226         
227 }
228
229 char* ntreeTexOutputMenu(bNodeTree *ntree)
230 {
231         bNode *node;
232         int len = 1;
233         char *str;
234         char ctrl[4];
235         int index = 0;
236         
237         for(node= ntree->nodes.first; node; node= node->next)
238                 if(node->type == TEX_NODE_OUTPUT) {
239                         len += strlen( 
240                                 ((TexNodeOutput*)node->storage)->name
241                         ) + strlen(" %xNNN|");
242                         index ++;
243                         
244                         if(node->custom1 > 999) {
245                                 printf("Error: too many outputs");
246                                 break;
247                         }
248                 }
249                         
250         str = malloc(len * sizeof(char));
251         *str = 0;
252
253         for(node= ntree->nodes.first; node; node= node->next)
254                 if(node->type == TEX_NODE_OUTPUT) {
255                         strcat(str, ((TexNodeOutput*)node->storage)->name);
256                         strcat(str, " %x");
257                         
258                         sprintf(ctrl, "%d", node->custom1);
259                         strcat(str, ctrl);
260                         
261                         if(--index)
262                                 strcat(str, "|");
263                         else
264                                 break;
265                 }
266         
267         return str;
268 }
269
270 void ntreeTexAssignIndex(struct bNodeTree *ntree, struct bNode *node)
271 {
272         bNode *tnode;
273         int index = 0;
274         
275         check_index:
276         for(tnode= ntree->nodes.first; tnode; tnode= tnode->next)
277                 if(tnode->type == TEX_NODE_OUTPUT && tnode != node)
278                         if(tnode->custom1 == index) {
279                                 index ++;
280                                 goto check_index;
281                         }
282                         
283         node->custom1 = index;
284 }
285