ab8920e67ad6b7fd6bd0c8c039fe44d1ff8481b7
[blender-staging.git] / source / blender / nodes / intern / TEX_nodes / TEX_output.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) 2006 Blender Foundation.
20  * All rights reserved.
21  *
22  * The Original Code is: all of this file.
23  *
24  * Contributor(s): Robin Allen
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28
29 #include "../TEX_util.h"
30
31 /* **************** COMPOSITE ******************** */
32 static bNodeSocketType inputs[]= {
33         { SOCK_RGBA,   1, "Color",  0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
34         { SOCK_VECTOR, 1, "Normal", 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f},
35         { -1, 0, ""     }
36 };
37
38 static void osa(
39         void (*input_fn)(float *, bNodeStack *, TexParams *, short),
40         float *out,
41         bNodeStack *in,
42         TexParams *p,
43         short thread
44 ){
45         if(!p->dxt) {
46                 input_fn(out, in, p, thread);
47         } else {
48                 float sample[4] = {0};
49                 float coord[3];
50                 TexParams sp = *p;
51                 int i;
52         
53                 sp.coord = coord;
54                 sp.dxt = sp.dyt = 0;
55                 
56                 QUATCOPY(out, sample);
57                 
58                 for(i=0; i<5; i++) {
59                         VECCOPY(coord, p->coord);
60                         
61                         if(i < 4)
62                         {
63                                 if(i % 2) VECADD(coord, coord, p->dxt);
64                                 if(i > 1) VECADD(coord, coord, p->dyt);
65                         }
66                         else
67                         {
68                                 VECADDFAC(coord, coord, p->dxt, 0.5);
69                                 VECADDFAC(coord, coord, p->dyt, 0.5);
70                         }
71                         
72                         input_fn(sample, in, &sp, thread);
73                         
74                         QUATADDFAC(out, out, sample, 0.2);
75                 }
76         }
77 }
78         
79
80 /* applies to render pipeline */
81 static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
82 {
83         TexCallData *cdata = (TexCallData *)data;
84         TexResult *target = cdata->target;
85         
86         if(cdata->do_preview) {
87                 TexParams params;
88                 params_from_cdata(&params, cdata);
89
90                 if(in[1]->hasinput && !in[0]->hasinput)
91                         tex_input_rgba(&target->tr, in[1], &params, cdata->thread);
92                 else
93                         tex_input_rgba(&target->tr, in[0], &params, cdata->thread);
94                 tex_do_preview(node, params.coord, &target->tr);
95         }
96         else {
97                 /* 0 means don't care, so just use first */
98                 if(cdata->which_output == node->custom1 || (cdata->which_output == 0 && node->custom1 == 1)) {
99                         TexParams params;
100                         params_from_cdata(&params, cdata);
101                         
102                         osa(tex_input_rgba, &target->tr, in[0], &params, cdata->thread);
103                 
104                         target->tin = (target->tr + target->tg + target->tb) / 3.0f;
105                         target->talpha = 1.0f;
106                 
107                         if(target->nor) {
108                                 if(in[1]->hasinput)
109                                         osa(tex_input_vec, target->nor, in[1], &params, cdata->thread);
110                                 else
111                                         target->nor = 0;
112                         }
113                 }
114         }
115 }
116
117 static void unique_name(bNode *node)
118 {
119         TexNodeOutput *tno = (TexNodeOutput *)node->storage;
120         char *new_name = 0;
121         int new_len = 0;
122         int suffix;
123         bNode *i;
124         char *name = tno->name;
125         
126         i = node;
127         while(i->prev) i = i->prev;
128         for(; i; i=i->next) {
129                 if(
130                         i == node ||
131                         i->type != TEX_NODE_OUTPUT ||
132                         strcmp(name, ((TexNodeOutput*)(i->storage))->name)
133                 )
134                         continue;
135                 
136                 if(!new_name) {
137                         int len = strlen(name);
138                         if(len >= 4 && sscanf(name + len - 4, ".%03d", &suffix) == 1) {
139                                 new_len = len;
140                         } else {
141                                 suffix = 0;
142                                 new_len = len + 4;
143                                 if(new_len > 31)
144                                         new_len = 31;
145                         }
146                         
147                         new_name = malloc(new_len + 1);
148                         strcpy(new_name, name);
149                         name = new_name;
150                 }
151                 sprintf(new_name + new_len - 4, ".%03d", ++suffix);
152         }
153         
154         if(new_name) {
155                 strcpy(tno->name, new_name);
156                 free(new_name);
157         }
158 }
159
160 static void assign_index(struct bNode *node)
161 {
162         bNode *tnode;
163         int index = 1;
164         
165         tnode = node;
166         while(tnode->prev)
167                 tnode = tnode->prev;
168         
169         check_index:
170         for(; tnode; tnode= tnode->next)
171                 if(tnode->type == TEX_NODE_OUTPUT && tnode != node)
172                         if(tnode->custom1 == index) {
173                                 index ++;
174                                 goto check_index;
175                         }
176                         
177         node->custom1 = index;
178 }
179
180 static void init(bNode *node)
181 {
182         TexNodeOutput *tno = MEM_callocN(sizeof(TexNodeOutput), "TEX_output");
183         node->storage= tno;
184         
185         strcpy(tno->name, "Default");
186         unique_name(node);
187         assign_index(node);
188 }
189
190 static void copy(bNode *orig, bNode *new)
191 {
192         node_copy_standard_storage(orig, new);
193         unique_name(new);
194         assign_index(new);
195 }
196
197 bNodeType tex_node_output= {
198         /* *next,*prev     */  NULL, NULL,
199         /* type code       */  TEX_NODE_OUTPUT,
200         /* name            */  "Output",
201         /* width+range     */  150, 60, 200,
202         /* class+opts      */  NODE_CLASS_OUTPUT, NODE_PREVIEW | NODE_OPTIONS, 
203         /* input sock      */  inputs,
204         /* output sock     */  NULL,
205         /* storage         */  "TexNodeOutput",
206         /* execfunc        */  exec,
207         /* butfunc         */  NULL,
208         /* initfunc        */  init,
209         /* freestoragefunc */  node_free_standard_storage,
210         /* copystoragefunc */  copy,  
211         /* id              */  NULL
212 };