style cleanup: follow style guide for formatting of if/for/while loops, and else...
[blender.git] / source / blender / nodes / texture / nodes / node_texture_output.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version. 
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2006 Blender Foundation.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): Robin Allen
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/nodes/texture/nodes/node_texture_output.c
29  *  \ingroup texnodes
30  */
31
32
33 #include "node_texture_util.h"
34 #include "NOD_texture.h"
35
36 /* **************** COMPOSITE ******************** */
37 static bNodeSocketTemplate inputs[]= {
38         { SOCK_RGBA,   1, "Color",  0.0f, 0.0f, 0.0f, 1.0f},
39         { SOCK_VECTOR, 1, "Normal", 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, PROP_DIRECTION},
40         { -1, 0, ""     }
41 };
42
43 /* applies to render pipeline */
44 static void exec(void *data, bNode *node, bNodeStack **in, bNodeStack **UNUSED(out))
45 {
46         TexCallData *cdata = (TexCallData *)data;
47         TexResult *target = cdata->target;
48         
49         if (cdata->do_preview) {
50                 TexParams params;
51                 params_from_cdata(&params, cdata);
52
53                 if (in[1] && in[1]->hasinput && !in[0]->hasinput)
54                         tex_input_rgba(&target->tr, in[1], &params, cdata->thread);
55                 else
56                         tex_input_rgba(&target->tr, in[0], &params, cdata->thread);
57                 tex_do_preview(node, params.co, &target->tr);
58         }
59         else {
60                 /* 0 means don't care, so just use first */
61                 if (cdata->which_output == node->custom1 || (cdata->which_output == 0 && node->custom1 == 1)) {
62                         TexParams params;
63                         params_from_cdata(&params, cdata);
64                         
65                         tex_input_rgba(&target->tr, in[0], &params, cdata->thread);
66                 
67                         target->tin = (target->tr + target->tg + target->tb) / 3.0f;
68                         target->talpha = 1;
69                 
70                         if (target->nor) {
71                                 if (in[1] && in[1]->hasinput)
72                                         tex_input_vec(target->nor, in[1], &params, cdata->thread);
73                                 else
74                                         target->nor = NULL;
75                         }
76                 }
77         }
78 }
79
80 static void unique_name(bNode *node)
81 {
82         TexNodeOutput *tno = (TexNodeOutput *)node->storage;
83         char *new_name = NULL;
84         int new_len = 0;
85         int suffix;
86         bNode *i;
87         char *name = tno->name;
88         
89         i = node;
90         while(i->prev) i = i->prev;
91         for (; i; i=i->next) {
92                 if (
93                         i == node ||
94                         i->type != TEX_NODE_OUTPUT ||
95                         strcmp(name, ((TexNodeOutput*)(i->storage))->name)
96                 )
97                         continue;
98                 
99                 if (!new_name) {
100                         int len = strlen(name);
101                         if (len >= 4 && sscanf(name + len - 4, ".%03d", &suffix) == 1) {
102                                 new_len = len;
103                         }
104                         else {
105                                 suffix = 0;
106                                 new_len = len + 4;
107                                 if (new_len > (sizeof(tno->name) - 1))
108                                         new_len = (sizeof(tno->name) - 1);
109                         }
110                         
111                         new_name = MEM_mallocN(new_len + 1, "new_name");
112                         strcpy(new_name, name);
113                         name = new_name;
114                 }
115                 sprintf(new_name + new_len - 4, ".%03d", ++suffix);
116         }
117         
118         if (new_name) {
119                 strcpy(tno->name, new_name);
120                 MEM_freeN(new_name);
121         }
122 }
123
124 static void assign_index(struct bNode *node)
125 {
126         bNode *tnode;
127         int index = 1;
128         
129         tnode = node;
130         while(tnode->prev)
131                 tnode = tnode->prev;
132         
133         check_index:
134         for (; tnode; tnode= tnode->next)
135                 if (tnode->type == TEX_NODE_OUTPUT && tnode != node)
136                         if (tnode->custom1 == index) {
137                                 index ++;
138                                 goto check_index;
139                         }
140                         
141         node->custom1 = index;
142 }
143
144 static void init(bNodeTree *UNUSED(ntree), bNode* node, bNodeTemplate *UNUSED(ntemp))
145 {
146         TexNodeOutput *tno = MEM_callocN(sizeof(TexNodeOutput), "TEX_output");
147         node->storage= tno;
148         
149         strcpy(tno->name, "Default");
150         unique_name(node);
151         assign_index(node);
152 }
153
154 static void copy(bNode *orig, bNode *new)
155 {
156         node_copy_standard_storage(orig, new);
157         unique_name(new);
158         assign_index(new);
159 }
160
161 void register_node_type_tex_output(bNodeTreeType *ttype)
162 {
163         static bNodeType ntype;
164         
165         node_type_base(ttype, &ntype, TEX_NODE_OUTPUT, "Output", NODE_CLASS_OUTPUT, NODE_PREVIEW|NODE_OPTIONS);
166         node_type_socket_templates(&ntype, inputs, NULL);
167         node_type_size(&ntype, 150, 60, 200);
168         node_type_init(&ntype, init);
169         node_type_storage(&ntype, "TexNodeOutput", node_free_standard_storage, copy);
170         node_type_exec(&ntype, exec);
171         
172         /* Do not allow muting output. */
173         node_type_internal_connect(&ntype, NULL);
174         
175         nodeRegisterType(ttype, &ntype);
176 }