f9f289297d7e1f71521cde8710985e00249574c4
[blender-staging.git] / source / blender / nodes / composite / nodes / node_composite_image.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): none yet.
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/nodes/composite/nodes/node_composite_image.c
29  *  \ingroup cmpnodes
30  */
31
32 #include "node_composite_util.h"
33
34 /* **************** IMAGE (and RenderResult, multilayer image) ******************** */
35
36 static bNodeSocketTemplate cmp_node_rlayers_out[] = {
37         {       SOCK_RGBA, 0, N_("Image"),                                      0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
38         {       SOCK_FLOAT, 0, N_("Alpha"),                                     1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
39         {       SOCK_FLOAT, 0, N_("Z"),                                         1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
40         {       SOCK_VECTOR, 0, N_("Normal"),                           0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
41         {       SOCK_VECTOR, 0, N_("UV"),                                       1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
42         {       SOCK_VECTOR, 0, N_("Speed"),                            1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
43         {       SOCK_RGBA, 0, N_("Color"),                                      0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
44         {       SOCK_RGBA, 0, N_("Diffuse"),                            0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
45         {       SOCK_RGBA, 0, N_("Specular"),                           0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
46         {       SOCK_RGBA, 0, N_("Shadow"),                                     0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
47         {       SOCK_RGBA, 0, N_("AO"),                                         0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
48         {       SOCK_RGBA, 0, N_("Reflect"),                            0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
49         {       SOCK_RGBA, 0, N_("Refract"),                            0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
50         {       SOCK_RGBA, 0, N_("Indirect"),                           0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
51         {       SOCK_FLOAT, 0, N_("IndexOB"),                           0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
52         {       SOCK_FLOAT, 0, N_("IndexMA"),                           0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
53         {       SOCK_FLOAT, 0, N_("Mist"),                                      0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
54         {       SOCK_RGBA, 0, N_("Emit"),                                       0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
55         {       SOCK_RGBA, 0, N_("Environment"),                        0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
56         {       SOCK_RGBA, 0, N_("Diffuse Direct"),                     0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
57         {       SOCK_RGBA, 0, N_("Diffuse Indirect"),           0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
58         {       SOCK_RGBA, 0, N_("Diffuse Color"),                      0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
59         {       SOCK_RGBA, 0, N_("Glossy Direct"),                      0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
60         {       SOCK_RGBA, 0, N_("Glossy Indirect"),            0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
61         {       SOCK_RGBA, 0, N_("Glossy Color"),                       0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
62         {       SOCK_RGBA, 0, N_("Transmission Direct"),        0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
63         {       SOCK_RGBA, 0, N_("Transmission Indirect"),      0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
64         {       SOCK_RGBA, 0, N_("Transmission Color"),         0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
65         {       -1, 0, ""       }
66 };
67
68 static bNodeSocket *cmp_node_image_add_render_pass_output(bNodeTree *ntree, bNode *node, int pass, int rres_index)
69 {
70         bNodeSocket *sock;
71         NodeImageLayer *sockdata;
72         
73         sock = node_add_socket_from_template(ntree, node, &cmp_node_rlayers_out[rres_index], SOCK_OUT);
74         /* extra socket info */
75         sockdata = MEM_callocN(sizeof(NodeImageLayer), "node image layer");
76         sock->storage = sockdata;
77         
78         sockdata->pass_flag = pass;
79         
80         return sock;
81 }
82
83 static void cmp_node_image_add_render_pass_outputs(bNodeTree *ntree, bNode *node, int passflag)
84 {
85         if (passflag & SCE_PASS_COMBINED) {
86                 cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_COMBINED, RRES_OUT_IMAGE);
87                 cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_COMBINED, RRES_OUT_ALPHA);
88         }
89         
90         if (passflag & SCE_PASS_Z)
91                 cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_Z, RRES_OUT_Z);
92         if (passflag & SCE_PASS_NORMAL)
93                 cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_NORMAL, RRES_OUT_NORMAL);
94         if (passflag & SCE_PASS_VECTOR)
95                 cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_VECTOR, RRES_OUT_VEC);
96         if (passflag & SCE_PASS_UV)
97                 cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_UV, RRES_OUT_UV);
98         if (passflag & SCE_PASS_RGBA)
99                 cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_RGBA, RRES_OUT_RGBA);
100         if (passflag & SCE_PASS_DIFFUSE)
101                 cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_DIFFUSE, RRES_OUT_DIFF);
102         if (passflag & SCE_PASS_SPEC)
103                 cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_SPEC, RRES_OUT_SPEC);
104         if (passflag & SCE_PASS_SHADOW)
105                 cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_SHADOW, RRES_OUT_SHADOW);
106         if (passflag & SCE_PASS_AO)
107                 cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_AO, RRES_OUT_AO);
108         if (passflag & SCE_PASS_REFLECT)
109                 cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_REFLECT, RRES_OUT_REFLECT);
110         if (passflag & SCE_PASS_REFRACT)
111                 cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_REFRACT, RRES_OUT_REFRACT);
112         if (passflag & SCE_PASS_INDIRECT)
113                 cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_INDIRECT, RRES_OUT_INDIRECT);
114         if (passflag & SCE_PASS_INDEXOB)
115                 cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_INDEXOB, RRES_OUT_INDEXOB);
116         if (passflag & SCE_PASS_INDEXMA)
117                 cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_INDEXMA, RRES_OUT_INDEXMA);
118         if (passflag & SCE_PASS_MIST)
119                 cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_MIST, RRES_OUT_MIST);
120         if (passflag & SCE_PASS_EMIT)
121                 cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_EMIT, RRES_OUT_EMIT);
122         if (passflag & SCE_PASS_ENVIRONMENT)
123                 cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_ENVIRONMENT, RRES_OUT_ENV);
124         
125         if (passflag & SCE_PASS_DIFFUSE_DIRECT)
126                 cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_DIFFUSE_DIRECT, RRES_OUT_DIFF_DIRECT);
127         if (passflag & SCE_PASS_DIFFUSE_INDIRECT)
128                 cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_DIFFUSE_INDIRECT, RRES_OUT_DIFF_INDIRECT);
129         if (passflag & SCE_PASS_DIFFUSE_COLOR)
130                 cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_DIFFUSE_COLOR, RRES_OUT_DIFF_COLOR);
131         
132         if (passflag & SCE_PASS_GLOSSY_DIRECT)
133                 cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_GLOSSY_DIRECT, RRES_OUT_GLOSSY_DIRECT);
134         if (passflag & SCE_PASS_GLOSSY_INDIRECT)
135                 cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_GLOSSY_INDIRECT, RRES_OUT_GLOSSY_INDIRECT);
136         if (passflag & SCE_PASS_GLOSSY_COLOR)
137                 cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_GLOSSY_COLOR, RRES_OUT_GLOSSY_COLOR);
138         
139         if (passflag & SCE_PASS_TRANSM_DIRECT)
140                 cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_TRANSM_DIRECT, RRES_OUT_TRANSM_DIRECT);
141         if (passflag & SCE_PASS_TRANSM_INDIRECT)
142                 cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_TRANSM_INDIRECT, RRES_OUT_TRANSM_INDIRECT);
143         if (passflag & SCE_PASS_TRANSM_COLOR)
144                 cmp_node_image_add_render_pass_output(ntree, node, SCE_PASS_TRANSM_COLOR, RRES_OUT_TRANSM_COLOR);
145 }
146
147 static void cmp_node_image_add_multilayer_outputs(bNodeTree *ntree, bNode *node, RenderLayer *rl)
148 {
149         bNodeSocket *sock;
150         NodeImageLayer *sockdata;
151         RenderPass *rpass;
152         int index;
153         for (rpass=rl->passes.first, index=0; rpass; rpass=rpass->next, ++index) {
154                 int type;
155                 if (rpass->channels == 1)
156                         type = SOCK_FLOAT;
157                 else
158                         type = SOCK_RGBA;
159                 
160                 sock = nodeAddStaticSocket(ntree, node, SOCK_OUT, type, PROP_NONE, rpass->name, rpass->name);
161                 /* extra socket info */
162                 sockdata = MEM_callocN(sizeof(NodeImageLayer), "node image layer");
163                 sock->storage = sockdata;
164                 
165                 sockdata->pass_index = index;
166                 sockdata->pass_flag = rpass->passtype;
167         }
168 }
169
170 static void cmp_node_image_create_outputs(bNodeTree *ntree, bNode *node)
171 {
172         Image *ima= (Image *)node->id;
173         if (ima) {
174                 ImageUser *iuser= node->storage;
175                 ImBuf *ibuf;
176                 
177                 /* make sure ima->type is correct */
178                 ibuf = BKE_image_acquire_ibuf(ima, iuser, NULL);
179                 
180                 if (ima->rr) {
181                         RenderLayer *rl= BLI_findlink(&ima->rr->layers, iuser->layer);
182                         
183                         if (rl) {
184                                 if (ima->type!=IMA_TYPE_MULTILAYER)
185                                         cmp_node_image_add_render_pass_outputs(ntree, node, rl->passflag);
186                                 else
187                                         cmp_node_image_add_multilayer_outputs(ntree, node, rl);
188                         }
189                         else
190                                 cmp_node_image_add_render_pass_outputs(ntree, node, RRES_OUT_IMAGE|RRES_OUT_ALPHA);
191                 }
192                 else
193                         cmp_node_image_add_render_pass_outputs(ntree, node, RRES_OUT_IMAGE|RRES_OUT_ALPHA|RRES_OUT_Z);
194                 
195                 BKE_image_release_ibuf(ima, ibuf, NULL);
196         }
197         else
198                 cmp_node_image_add_render_pass_outputs(ntree, node, RRES_OUT_IMAGE|RRES_OUT_ALPHA);
199 }
200
201 static bNodeSocket *cmp_node_image_output_find_match(bNode *UNUSED(node), bNodeSocket *newsock, ListBase *oldsocklist)
202 {
203         bNodeSocket *sock;
204         
205         for (sock=oldsocklist->first; sock; sock=sock->next)
206                 if (strcmp(sock->name, newsock->name)==0)
207                         return sock;
208         return NULL;
209 }
210
211 static bNodeSocket *cmp_node_image_output_relink(bNode *node, bNodeSocket *oldsock, int oldindex)
212 {
213         bNodeSocket *sock;
214         
215         /* first try to find matching socket name */
216         for (sock=node->outputs.first; sock; sock=sock->next)
217                 if (strcmp(sock->name, oldsock->name)==0)
218                         return sock;
219         
220         /* no matching name, simply link to same index */
221         return BLI_findlink(&node->outputs, oldindex);
222 }
223
224 static void cmp_node_image_sync_output(bNode *UNUSED(node), bNodeSocket *UNUSED(newsock), bNodeSocket *UNUSED(oldsock))
225 {
226         /* pass */
227 }
228
229 /* XXX make this into a generic socket verification function for dynamic socket replacement (multilayer, groups, static templates) */
230 static void cmp_node_image_verify_outputs(bNodeTree *ntree, bNode *node)
231 {
232         bNodeSocket *newsock, *oldsock, *oldsock_next;
233         ListBase oldsocklist;
234         int oldindex;
235         bNodeLink *link;
236         
237         /* store current nodes in oldsocklist, then clear socket list */
238         oldsocklist = node->outputs;
239         node->outputs.first = node->outputs.last = NULL;
240         
241         /* XXX make callback */
242         cmp_node_image_create_outputs(ntree, node);
243         
244         for (newsock=node->outputs.first; newsock; newsock=newsock->next) {
245                 /* XXX make callback */
246                 oldsock = cmp_node_image_output_find_match(node, newsock, &oldsocklist);
247                 if (oldsock) {
248                         /* XXX make callback */
249                         cmp_node_image_sync_output(node, newsock, oldsock);
250                 }
251         }
252         
253         /* move links to new socket */
254         for (oldsock=oldsocklist.first, oldindex=0; oldsock; oldsock=oldsock->next, ++oldindex) {
255                 newsock = cmp_node_image_output_relink(node, oldsock, oldindex);
256                 
257                 if (newsock) {
258                         for (link=ntree->links.first; link; link=link->next) {
259                                 if (link->fromsock == oldsock)
260                                         link->fromsock = newsock;
261                         }
262                 }
263         }
264         
265         /* delete old sockets
266          * XXX oldsock is not actually in the node->outputs list any more,
267          * but the nodeRemoveSocket function works anyway. In future this
268          * should become part of the core code, so can take care of this behavior.
269          */
270         for (oldsock=oldsocklist.first; oldsock; oldsock=oldsock_next) {
271                 oldsock_next = oldsock->next;
272                 MEM_freeN(oldsock->storage);
273                 nodeRemoveSocket(ntree, node, oldsock);
274         }
275 }
276
277 static void cmp_node_image_update(bNodeTree *ntree, bNode *node)
278 {
279         /* avoid unnecessary updates, only changes to the image/image user data are of interest */
280         if (node->update & NODE_UPDATE_ID)
281                 cmp_node_image_verify_outputs(ntree, node);
282 }
283
284 static void node_composit_init_image(bNodeTree *ntree, bNode *node)
285 {
286         ImageUser *iuser= MEM_callocN(sizeof(ImageUser), "node image user");
287         node->storage= iuser;
288         iuser->frames= 1;
289         iuser->sfra= 1;
290         iuser->fie_ima= 2;
291         iuser->ok= 1;
292         
293         /* setup initial outputs */
294         cmp_node_image_verify_outputs(ntree, node);
295 }
296
297 static void node_composit_free_image(bNode *node)
298 {
299         bNodeSocket *sock;
300         
301         /* free extra socket info */
302         for (sock=node->outputs.first; sock; sock=sock->next)
303                 MEM_freeN(sock->storage);
304         
305         MEM_freeN(node->storage);
306 }
307
308 static void node_composit_copy_image(bNodeTree *UNUSED(dest_ntree), bNode *dest_node, bNode *src_node)
309 {
310         bNodeSocket *sock;
311         
312         dest_node->storage= MEM_dupallocN(src_node->storage);
313         
314         /* copy extra socket info */
315         for (sock=src_node->outputs.first; sock; sock=sock->next)
316                 sock->new_sock->storage = MEM_dupallocN(sock->storage);
317 }
318
319 void register_node_type_cmp_image()
320 {
321         static bNodeType ntype;
322
323         cmp_node_type_base(&ntype, CMP_NODE_IMAGE, "Image", NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS);
324         node_type_init(&ntype, node_composit_init_image);
325         node_type_storage(&ntype, "ImageUser", node_composit_free_image, node_composit_copy_image);
326         node_type_update(&ntype, cmp_node_image_update, NULL);
327
328         nodeRegisterType(&ntype);
329 }
330
331
332 /* **************** RENDER RESULT ******************** */
333
334 static int node_composit_poll_rlayers(bNodeType *UNUSED(ntype), bNodeTree *ntree)
335 {
336         PointerRNA ptr;
337         
338         /* render layers node can only be used in local scene->nodetree, since it directly links to the scene */
339         RNA_id_pointer_create((ID *)ntree, &ptr);
340         return (strcmp(ntree->idname, "CompositorNodeTree")==0 && RNA_boolean_get(&ptr, "is_local_tree"));
341 }
342
343 void register_node_type_cmp_rlayers()
344 {
345         static bNodeType ntype;
346
347         cmp_node_type_base(&ntype, CMP_NODE_R_LAYERS, "Render Layers", NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS);
348         node_type_socket_templates(&ntype, NULL, cmp_node_rlayers_out);
349         ntype.poll = node_composit_poll_rlayers;
350
351         nodeRegisterType(&ntype);
352 }