8b247688e8ce876776feb7dd450756330153ab60
[blender-staging.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, TexParams *params, short thread)
51 {
52         if(dg->node->need_exec) {
53                 dg->fn(out, params, dg->node, dg->in, thread);
54
55                 if(dg->cdata->do_preview)
56                         tex_do_preview(dg->node, params->coord, out);
57         }
58 }
59
60 void tex_input(float *out, int sz, bNodeStack *in, TexParams *params, short thread)
61 {
62         TexDelegate *dg = in->data;
63         if(dg) {
64                 tex_call_delegate(dg, in->vec, params, thread);
65         
66                 if(in->hasoutput && in->sockettype == SOCK_VALUE)
67                         in->vec[1] = in->vec[2] = in->vec[0];
68         }
69         memcpy(out, in->vec, sz * sizeof(float));
70 }
71
72 void tex_input_vec(float *out, bNodeStack *in, TexParams *params, short thread)
73 {
74         tex_input(out, 3, in, params, thread);
75 }
76
77 void tex_input_rgba(float *out, bNodeStack *in, TexParams *params, short thread)
78 {
79         tex_input(out, 4, in, params, thread);
80         
81         if(in->hasoutput && in->sockettype == SOCK_VALUE)
82         {
83                 out[1] = out[2] = out[0];
84                 out[3] = 1;
85         }
86         
87         if(in->hasoutput && in->sockettype == SOCK_VECTOR) {
88                 out[0] = out[0] * .5f + .5f;
89                 out[1] = out[1] * .5f + .5f;
90                 out[2] = out[2] * .5f + .5f;
91                 out[3] = 1;
92         }
93 }
94
95 float tex_input_value(bNodeStack *in, TexParams *params, short thread)
96 {
97         float out[4];
98         tex_input_vec(out, in, params, thread);
99         return out[0];
100 }
101
102 void params_from_cdata(TexParams *out, TexCallData *in)
103 {
104         out->coord = in->coord;
105         out->dxt = in->dxt;
106         out->dyt = in->dyt;
107         out->cfra = in->cfra;
108 }
109
110 void tex_do_preview(bNode *node, float *coord, float *col)
111 {
112         bNodePreview *preview= node->preview;
113
114         if(preview) {
115                 int xs= ((coord[0] + 1.0f)*0.5f)*preview->xsize;
116                 int ys= ((coord[1] + 1.0f)*0.5f)*preview->ysize;
117
118                 nodeAddToPreview(node, col, xs, ys);
119         }
120 }
121
122 void tex_output(bNode *node, bNodeStack **in, bNodeStack *out, TexFn texfn, TexCallData *cdata)
123 {
124         TexDelegate *dg;
125         if(!out->data)
126                 /* Freed in tex_end_exec (node.c) */
127                 dg = out->data = MEM_mallocN(sizeof(TexDelegate), "tex delegate");
128         else
129                 dg = out->data;
130         
131         dg->cdata= cdata;
132         dg->fn = texfn;
133         dg->node = node;
134         memcpy(dg->in, in, MAX_SOCKET * sizeof(bNodeStack*));
135         dg->type = out->sockettype;
136 }
137
138 void ntreeTexCheckCyclics(struct bNodeTree *ntree)
139 {
140         bNode *node;
141         for(node= ntree->nodes.first; node; node= node->next) {
142                 
143                 if(node->type == TEX_NODE_TEXTURE && node->id)
144                 {
145                         /* custom2 stops the node from rendering */
146                         if(node->custom1) {
147                                 node->custom2 = 1;
148                                 node->custom1 = 0;
149                         } else {
150                                 Tex *tex = (Tex *)node->id;
151                                 
152                                 node->custom2 = 0;
153                         
154                                 node->custom1 = 1;
155                                 if(tex->use_nodes && tex->nodetree) {
156                                         ntreeTexCheckCyclics(tex->nodetree);
157                                 }
158                                 node->custom1 = 0;
159                         }
160                 }
161
162         }
163 }
164
165 void ntreeTexExecTree(
166         bNodeTree *nodes,
167         TexResult *texres,
168         float *coord,
169         float *dxt, float *dyt,
170         short thread, 
171         Tex *tex, 
172         short which_output, 
173         int cfra,
174         int preview
175 ){
176         TexResult dummy_texres;
177         TexCallData data;
178         
179         if(!texres) texres = &dummy_texres;
180         data.coord = coord;
181         data.dxt = dxt;
182         data.dyt = dyt;
183         data.target = texres;
184         data.do_preview = preview;
185         data.thread = thread;
186         data.which_output = which_output;
187         data.cfra= cfra;
188         
189         ntreeExecTree(nodes, &data, thread);
190 }
191
192 char* ntreeTexOutputMenu(bNodeTree *ntree)
193 {
194         bNode *node;
195         int len = 1;
196         char *str;
197         char ctrl[4];
198         int index = 0;
199         
200         for(node= ntree->nodes.first; node; node= node->next)
201                 if(node->type == TEX_NODE_OUTPUT) {
202                         len += strlen( 
203                                 ((TexNodeOutput*)node->storage)->name
204                         ) + strlen(" %xNNN|");
205                         index ++;
206                         
207                         if(node->custom1 > 999) {
208                                 printf("Error: too many outputs");
209                                 break;
210                         }
211                 }
212                         
213         str = malloc(len * sizeof(char));
214         *str = 0;
215
216         for(node= ntree->nodes.first; node; node= node->next)
217                 if(node->type == TEX_NODE_OUTPUT) {
218                         strcat(str, ((TexNodeOutput*)node->storage)->name);
219                         strcat(str, " %x");
220                         
221                         sprintf(ctrl, "%d", node->custom1);
222                         strcat(str, ctrl);
223                         
224                         if(--index)
225                                 strcat(str, "|");
226                         else
227                                 break;
228                 }
229         
230         return str;
231 }
232