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