fix for [#28012] Mat ID messy with shader nodes
[blender.git] / source / blender / nodes / intern / SHD_util.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) 2005 Blender Foundation.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30 /** \file blender/nodes/intern/SHD_util.c
31  *  \ingroup nodes
32  */
33
34
35 #include "SHD_util.h"
36
37
38
39
40
41 /* ****** */
42
43 void nodestack_get_vec(float *in, short type_in, bNodeStack *ns)
44 {
45         float *from= ns->vec;
46                 
47         if(type_in==SOCK_VALUE) {
48                 if(ns->sockettype==SOCK_VALUE)
49                         *in= *from;
50                 else 
51                         *in= 0.333333f*(from[0]+from[1]+from[2]);
52         }
53         else if(type_in==SOCK_VECTOR) {
54                 if(ns->sockettype==SOCK_VALUE) {
55                         in[0]= from[0];
56                         in[1]= from[0];
57                         in[2]= from[0];
58                 }
59                 else {
60                         VECCOPY(in, from);
61                 }
62         }
63         else { /* type_in==SOCK_RGBA */
64                 if(ns->sockettype==SOCK_RGBA) {
65                         QUATCOPY(in, from);
66                 }
67                 else if(ns->sockettype==SOCK_VALUE) {
68                         in[0]= from[0];
69                         in[1]= from[0];
70                         in[2]= from[0];
71                         in[3]= 1.0f;
72                 }
73                 else {
74                         VECCOPY(in, from);
75                         in[3]= 1.0f;
76                 }
77         }
78 }
79
80
81 /* ******************* execute and parse ************ */
82
83 void ntreeShaderExecTree(bNodeTree *ntree, ShadeInput *shi, ShadeResult *shr)
84 {
85         ShaderCallData scd;
86         /*
87          @note: preserve material from ShadeInput for material id, nodetree execs change it
88          fix for bug "[#28012] Mat ID messy with shader nodes"
89          */
90         Material *mat = shi->mat;
91         /* convert caller data to struct */
92         scd.shi= shi;
93         scd.shr= shr;
94         
95         /* each material node has own local shaderesult, with optional copying */
96         memset(shr, 0, sizeof(ShadeResult));
97                    
98         ntreeExecTree(ntree, &scd, shi->thread);        /* threads */
99         // @note: set material back to preserved material
100         shi->mat = mat;
101         /* better not allow negative for now */
102         if(shr->combined[0]<0.0f) shr->combined[0]= 0.0f;
103         if(shr->combined[1]<0.0f) shr->combined[1]= 0.0f;
104         if(shr->combined[2]<0.0f) shr->combined[2]= 0.0f;
105         
106 }
107
108 /* go over all used Geometry and Texture nodes, and return a texco flag */
109 /* no group inside needed, this function is called for groups too */
110 void ntreeShaderGetTexcoMode(bNodeTree *ntree, int r_mode, short *texco, int *mode)
111 {
112         bNode *node;
113         bNodeSocket *sock;
114         int a;
115         
116         ntreeSocketUseFlags(ntree);
117
118         for(node= ntree->nodes.first; node; node= node->next) {
119                 if(node->type==SH_NODE_TEXTURE) {
120                         if((r_mode & R_OSA) && node->id) {
121                                 Tex *tex= (Tex *)node->id;
122                                 if ELEM3(tex->type, TEX_IMAGE, TEX_PLUGIN, TEX_ENVMAP) 
123                                         *texco |= TEXCO_OSA|NEED_UV;
124                         }
125                         /* usability exception... without input we still give the node orcos */
126                         sock= node->inputs.first;
127                         if(sock==NULL || sock->link==NULL)
128                                 *texco |= TEXCO_ORCO|NEED_UV;
129                 }
130                 else if(node->type==SH_NODE_GEOMETRY) {
131                         /* note; sockets always exist for the given type! */
132                         for(a=0, sock= node->outputs.first; sock; sock= sock->next, a++) {
133                                 if(sock->flag & SOCK_IN_USE) {
134                                         switch(a) {
135                                                 case GEOM_OUT_GLOB: 
136                                                         *texco |= TEXCO_GLOB|NEED_UV; break;
137                                                 case GEOM_OUT_VIEW: 
138                                                         *texco |= TEXCO_VIEW|NEED_UV; break;
139                                                 case GEOM_OUT_ORCO: 
140                                                         *texco |= TEXCO_ORCO|NEED_UV; break;
141                                                 case GEOM_OUT_UV: 
142                                                         *texco |= TEXCO_UV|NEED_UV; break;
143                                                 case GEOM_OUT_NORMAL: 
144                                                         *texco |= TEXCO_NORM|NEED_UV; break;
145                                                 case GEOM_OUT_VCOL:
146                                                         *texco |= NEED_UV; *mode |= MA_VERTEXCOL; break;
147                                         }
148                                 }
149                         }
150                 }
151         }
152 }
153
154 /* nodes that use ID data get synced with local data */
155 void nodeShaderSynchronizeID(bNode *node, int copyto)
156 {
157         if(node->id==NULL) return;
158         
159         if(ELEM(node->type, SH_NODE_MATERIAL, SH_NODE_MATERIAL_EXT)) {
160                 bNodeSocket *sock;
161                 Material *ma= (Material *)node->id;
162                 int a;
163                 
164                 /* hrmf, case in loop isnt super fast, but we dont edit 100s of material at same time either! */
165                 for(a=0, sock= node->inputs.first; sock; sock= sock->next, a++) {
166                         if(!(sock->flag & SOCK_HIDDEN)) {
167                                 if(copyto) {
168                                         switch(a) {
169                                                 case MAT_IN_COLOR:
170                                                         VECCOPY(&ma->r, sock->ns.vec); break;
171                                                 case MAT_IN_SPEC:
172                                                         VECCOPY(&ma->specr, sock->ns.vec); break;
173                                                 case MAT_IN_REFL:
174                                                         ma->ref= sock->ns.vec[0]; break;
175                                                 case MAT_IN_MIR:
176                                                         VECCOPY(&ma->mirr, sock->ns.vec); break;
177                                                 case MAT_IN_AMB:
178                                                         ma->amb= sock->ns.vec[0]; break;
179                                                 case MAT_IN_EMIT:
180                                                         ma->emit= sock->ns.vec[0]; break;
181                                                 case MAT_IN_SPECTRA:
182                                                         ma->spectra= sock->ns.vec[0]; break;
183                                                 case MAT_IN_RAY_MIRROR:
184                                                         ma->ray_mirror= sock->ns.vec[0]; break;
185                                                 case MAT_IN_ALPHA:
186                                                         ma->alpha= sock->ns.vec[0]; break;
187                                                 case MAT_IN_TRANSLUCENCY:
188                                                         ma->translucency= sock->ns.vec[0]; break;
189                                         }
190                                 }
191                                 else {
192                                         switch(a) {
193                                                 case MAT_IN_COLOR:
194                                                         VECCOPY(sock->ns.vec, &ma->r); break;
195                                                 case MAT_IN_SPEC:
196                                                         VECCOPY(sock->ns.vec, &ma->specr); break;
197                                                 case MAT_IN_REFL:
198                                                         sock->ns.vec[0]= ma->ref; break;
199                                                 case MAT_IN_MIR:
200                                                         VECCOPY(sock->ns.vec, &ma->mirr); break;
201                                                 case MAT_IN_AMB:
202                                                         sock->ns.vec[0]= ma->amb; break;
203                                                 case MAT_IN_EMIT:
204                                                         sock->ns.vec[0]= ma->emit; break;
205                                                 case MAT_IN_SPECTRA:
206                                                         sock->ns.vec[0]= ma->spectra; break;
207                                                 case MAT_IN_RAY_MIRROR:
208                                                         sock->ns.vec[0]= ma->ray_mirror; break;
209                                                 case MAT_IN_ALPHA:
210                                                         sock->ns.vec[0]= ma->alpha; break;
211                                                 case MAT_IN_TRANSLUCENCY:
212                                                         sock->ns.vec[0]= ma->translucency; break;
213                                         }
214                                 }
215                         }
216                 }
217         }
218         
219 }