All UI code reverted to drawnode.c
[blender-staging.git] / source / blender / nodes / intern / CMP_nodes / CMP_image.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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, 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): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30 #include "../CMP_util.h"
31
32
33 /* **************** IMAGE (and RenderResult, multilayer image) ******************** */
34
35 static bNodeSocketType cmp_node_rlayers_out[]= {
36         {       SOCK_RGBA, 0, "Image",          0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
37         {       SOCK_VALUE, 0, "Alpha",         1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
38         {       SOCK_VALUE, 0, "Z",                     1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
39         {       SOCK_VECTOR, 0, "Normal",       0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
40         {       SOCK_VECTOR, 0, "UV",           1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
41         {       SOCK_VECTOR, 0, "Speed",        1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
42         {       SOCK_RGBA, 0, "Color",          0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
43         {       SOCK_RGBA, 0, "Diffuse",        0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
44         {       SOCK_RGBA, 0, "Specular",       0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
45         {       SOCK_RGBA, 0, "Shadow",         0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
46         {       SOCK_RGBA, 0, "AO",                     0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
47         {       SOCK_RGBA, 0, "Reflect",        0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
48         {       SOCK_RGBA, 0, "Refract",        0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
49         {       SOCK_RGBA, 0, "Radio",          0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
50         {       SOCK_VALUE, 0, "IndexOB",       0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
51         {       -1, 0, ""       }
52 };
53
54
55 /* note: this function is used for multilayer too, to ensure uniform 
56    handling with BKE_image_get_ibuf() */
57 static CompBuf *node_composit_get_image(RenderData *rd, Image *ima, ImageUser *iuser)
58 {
59         ImBuf *ibuf;
60         CompBuf *stackbuf;
61         int type;
62         
63         ibuf= BKE_image_get_ibuf(ima, iuser);
64         if(ibuf==NULL)
65                 return NULL;
66         
67         if(ibuf->rect_float==NULL)
68                 IMB_float_from_rect(ibuf);
69         
70         type= ibuf->channels;
71         
72         if(rd->scemode & R_COMP_CROP) {
73                 stackbuf= get_cropped_compbuf(&rd->disprect, ibuf->rect_float, ibuf->x, ibuf->y, type);
74         }
75         else {
76                 /* we put imbuf copy on stack, cbuf knows rect is from other ibuf when freed! */
77                 stackbuf= alloc_compbuf(ibuf->x, ibuf->y, type, 0);
78                 stackbuf->rect= ibuf->rect_float;
79         }
80         
81         return stackbuf;
82 };
83
84 static CompBuf *node_composit_get_zimage(bNode *node, RenderData *rd)
85 {
86         ImBuf *ibuf= BKE_image_get_ibuf((Image *)node->id, node->storage);
87         CompBuf *zbuf= NULL;
88         
89         if(ibuf && ibuf->zbuf_float) {
90                 if(rd->scemode & R_COMP_CROP) {
91                         zbuf= get_cropped_compbuf(&rd->disprect, ibuf->zbuf_float, ibuf->x, ibuf->y, CB_VAL);
92                 }
93                 else {
94                         zbuf= alloc_compbuf(ibuf->x, ibuf->y, CB_VAL, 0);
95                         zbuf->rect= ibuf->zbuf_float;
96                 }
97         }
98         return zbuf;
99 };
100
101 /* check if layer is available, returns pass buffer */
102 static CompBuf *compbuf_multilayer_get(RenderData *rd, RenderLayer *rl, Image *ima, ImageUser *iuser, int passtype)
103 {
104         RenderPass *rpass;
105         short index;
106         
107         for(index=0, rpass= rl->passes.first; rpass; rpass= rpass->next, index++)
108                 if(rpass->passtype==passtype)
109                         break;
110         
111         if(rpass) {
112                 CompBuf *cbuf;
113                 
114                 iuser->pass= index;
115                 BKE_image_multilayer_index(ima->rr, iuser);
116                 cbuf= node_composit_get_image(rd, ima, iuser);
117                 
118                 return cbuf;
119         }
120         return NULL;
121 };
122
123 void outputs_multilayer_get(RenderData *rd, RenderLayer *rl, bNodeStack **out, Image *ima, ImageUser *iuser)
124 {
125         if(out[RRES_OUT_Z]->hasoutput)
126                 out[RRES_OUT_Z]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_Z);
127         if(out[RRES_OUT_VEC]->hasoutput)
128                 out[RRES_OUT_VEC]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_VECTOR);
129         if(out[RRES_OUT_NORMAL]->hasoutput)
130                 out[RRES_OUT_NORMAL]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_NORMAL);
131         if(out[RRES_OUT_UV]->hasoutput)
132                 out[RRES_OUT_UV]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_UV);
133         
134         if(out[RRES_OUT_RGBA]->hasoutput)
135                 out[RRES_OUT_RGBA]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_RGBA);
136         if(out[RRES_OUT_DIFF]->hasoutput)
137                 out[RRES_OUT_DIFF]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_DIFFUSE);
138         if(out[RRES_OUT_SPEC]->hasoutput)
139                 out[RRES_OUT_SPEC]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_SPEC);
140         if(out[RRES_OUT_SHADOW]->hasoutput)
141                 out[RRES_OUT_SHADOW]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_SHADOW);
142         if(out[RRES_OUT_AO]->hasoutput)
143                 out[RRES_OUT_AO]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_AO);
144         if(out[RRES_OUT_REFLECT]->hasoutput)
145                 out[RRES_OUT_REFLECT]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_REFLECT);
146         if(out[RRES_OUT_REFRACT]->hasoutput)
147                 out[RRES_OUT_REFRACT]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_REFRACT);
148         if(out[RRES_OUT_RADIO]->hasoutput)
149                 out[RRES_OUT_RADIO]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_RADIO);
150         if(out[RRES_OUT_INDEXOB]->hasoutput)
151                 out[RRES_OUT_INDEXOB]->data= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_INDEXOB);
152         
153 };
154
155
156 static void node_composit_exec_image(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
157 {
158         
159         /* image assigned to output */
160         /* stack order input sockets: col, alpha */
161         if(node->id) {
162                 RenderData *rd= data;
163                 Image *ima= (Image *)node->id;
164                 ImageUser *iuser= (ImageUser *)node->storage;
165                 CompBuf *stackbuf= NULL;
166                 
167                 /* first set the right frame number in iuser */
168                 BKE_image_user_calc_imanr(iuser, rd->cfra, 0);
169                 
170                 /* force a load, we assume iuser index will be set OK anyway */
171                 if(ima->type==IMA_TYPE_MULTILAYER)
172                         BKE_image_get_ibuf(ima, iuser);
173                 
174                 if(ima->type==IMA_TYPE_MULTILAYER && ima->rr) {
175                         RenderLayer *rl= BLI_findlink(&ima->rr->layers, iuser->layer);
176                         
177                         if(rl) {
178                                 out[0]->data= stackbuf= compbuf_multilayer_get(rd, rl, ima, iuser, SCE_PASS_COMBINED);
179                                 
180                                 /* go over all layers */
181                                 outputs_multilayer_get(rd, rl, out, ima, iuser);
182                         }
183                 }
184                 else {
185                         stackbuf= node_composit_get_image(rd, ima, iuser);
186
187                         /* put image on stack */        
188                         out[0]->data= stackbuf;
189                         
190                         if(out[2]->hasoutput)
191                                 out[2]->data= node_composit_get_zimage(node, rd);
192                 }
193                 
194                 /* alpha and preview for both types */
195                 if(stackbuf) {
196                         if(out[1]->hasoutput)
197                                 out[1]->data= valbuf_from_rgbabuf(stackbuf, CHAN_A);
198
199                         generate_preview(node, stackbuf);
200                 }
201         }       
202 };
203
204 static void node_composit_init_image(bNode* node)
205 {
206    ImageUser *iuser= MEM_callocN(sizeof(ImageUser), "node image user");
207    node->storage= iuser;
208    iuser->sfra= 1;
209    iuser->fie_ima= 2;
210    iuser->ok= 1;
211 }
212
213 bNodeType cmp_node_image= {
214    /* type code   */    CMP_NODE_IMAGE,
215    /* name        */    "Image",
216    /* width+range */    120, 80, 300,
217    /* class+opts  */    NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS,
218    /* input sock  */    NULL,
219    /* output sock */    cmp_node_rlayers_out,
220    /* storage     */    "ImageUser",
221    /* execfunc    */    node_composit_exec_image,
222    /* butfunc     */    NULL,
223         /* initfunc   */    node_composit_init_image
224 };
225
226 /* **************** RENDER RESULT ******************** */
227
228 static CompBuf *compbuf_from_pass(RenderData *rd, RenderLayer *rl, int rectx, int recty, int passcode)
229 {
230    float *fp= RE_RenderLayerGetPass(rl, passcode);
231    if(fp) {
232       CompBuf *buf;
233       int buftype= CB_VEC3;
234
235       if(ELEM(passcode, SCE_PASS_Z, SCE_PASS_INDEXOB))
236          buftype= CB_VAL;
237       else if(passcode==SCE_PASS_VECTOR)
238          buftype= CB_VEC4;
239       else if(ELEM(passcode, SCE_PASS_COMBINED, SCE_PASS_RGBA))
240          buftype= CB_RGBA;
241
242       if(rd->scemode & R_COMP_CROP)
243          buf= get_cropped_compbuf(&rd->disprect, fp, rectx, recty, buftype);
244       else {
245          buf= alloc_compbuf(rectx, recty, buftype, 0);
246          buf->rect= fp;
247       }
248       return buf;
249    }
250    return NULL;
251 };
252
253 void node_composit_rlayers_out(RenderData *rd, RenderLayer *rl, bNodeStack **out, int rectx, int recty)
254 {
255    if(out[RRES_OUT_Z]->hasoutput)
256       out[RRES_OUT_Z]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_Z);
257    if(out[RRES_OUT_VEC]->hasoutput)
258       out[RRES_OUT_VEC]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_VECTOR);
259    if(out[RRES_OUT_NORMAL]->hasoutput)
260       out[RRES_OUT_NORMAL]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_NORMAL);
261    if(out[RRES_OUT_UV]->hasoutput)
262       out[RRES_OUT_UV]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_UV);
263
264    if(out[RRES_OUT_RGBA]->hasoutput)
265       out[RRES_OUT_RGBA]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_RGBA);
266    if(out[RRES_OUT_DIFF]->hasoutput)
267       out[RRES_OUT_DIFF]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_DIFFUSE);
268    if(out[RRES_OUT_SPEC]->hasoutput)
269       out[RRES_OUT_SPEC]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_SPEC);
270    if(out[RRES_OUT_SHADOW]->hasoutput)
271       out[RRES_OUT_SHADOW]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_SHADOW);
272    if(out[RRES_OUT_AO]->hasoutput)
273       out[RRES_OUT_AO]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_AO);
274    if(out[RRES_OUT_REFLECT]->hasoutput)
275       out[RRES_OUT_REFLECT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_REFLECT);
276    if(out[RRES_OUT_REFRACT]->hasoutput)
277       out[RRES_OUT_REFRACT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_REFRACT);
278    if(out[RRES_OUT_RADIO]->hasoutput)
279       out[RRES_OUT_RADIO]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_RADIO);
280    if(out[RRES_OUT_INDEXOB]->hasoutput)
281       out[RRES_OUT_INDEXOB]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_INDEXOB);
282
283 };
284
285 static void node_composit_exec_rlayers(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
286 {
287    Scene *sce= node->id?(Scene *)node->id:G.scene; /* G.scene is WEAK! */
288    RenderData *rd= data;
289    RenderResult *rr;
290
291    rr= RE_GetResult(RE_GetRender(sce->id.name));
292
293    if(rr) {
294       SceneRenderLayer *srl= BLI_findlink(&sce->r.layers, node->custom1);
295       if(srl) {
296          RenderLayer *rl= RE_GetRenderLayer(rr, srl->name);
297          if(rl && rl->rectf) {
298             CompBuf *stackbuf;
299
300             /* we put render rect on stack, cbuf knows rect is from other ibuf when freed! */
301             if(rd->scemode & R_COMP_CROP)
302                stackbuf= get_cropped_compbuf(&rd->disprect, rl->rectf, rr->rectx, rr->recty, CB_RGBA);
303             else {
304                stackbuf= alloc_compbuf(rr->rectx, rr->recty, CB_RGBA, 0);
305                stackbuf->rect= rl->rectf;
306             }
307             if(stackbuf==NULL) {
308                printf("Error; Preview Panel in UV Window returns zero sized image\n");
309             }
310             else {
311                stackbuf->xof= rr->xof;
312                stackbuf->yof= rr->yof;
313
314                /* put on stack */       
315                out[RRES_OUT_IMAGE]->data= stackbuf;
316
317                if(out[RRES_OUT_ALPHA]->hasoutput)
318                   out[RRES_OUT_ALPHA]->data= valbuf_from_rgbabuf(stackbuf, CHAN_A);
319
320                node_composit_rlayers_out(rd, rl, out, rr->rectx, rr->recty);
321
322                generate_preview(node, stackbuf);
323             }
324          }
325       }
326    }    
327 };
328
329
330 bNodeType cmp_node_rlayers= {
331    /* type code   */    CMP_NODE_R_LAYERS,
332    /* name        */    "Render Layers",
333    /* width+range */    150, 100, 300,
334    /* class+opts  */    NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS,
335    /* input sock  */    NULL,
336    /* output sock */    cmp_node_rlayers_out,
337    /* storage     */    "",
338    /* execfunc    */    node_composit_exec_rlayers,
339    /* butfunc     */    NULL,
340         /* initfunc   */        NULL
341
342 };
343
344