Initial commit. Not in build system so shouldn't interfere with anything at this...
[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_browse_image_cb(void *ntree_v, void *node_v)
205 {
206    bNodeTree *ntree= ntree_v;
207    bNode *node= node_v;
208
209    nodeSetActive(ntree, node);
210
211    if(node->menunr<1) return;
212    if(node->menunr==32767) {    /* code for Load New */
213       addqueue(curarea->win, UI_BUT_EVENT, B_NODE_LOADIMAGE);
214    }
215    else {
216       if(node->id) node->id->us--;
217       node->id= BLI_findlink(&G.main->image, node->menunr-1);
218       id_us_plus(node->id);
219
220       BLI_strncpy(node->name, node->id->name+2, 21);
221
222       NodeTagChanged(ntree, node); 
223       BKE_image_signal((Image *)node->id, node->storage, IMA_SIGNAL_USER_NEW_IMAGE);
224       addqueue(curarea->win, UI_BUT_EVENT, B_NODE_EXEC+node->nr);
225    }
226    node->menunr= 0;
227 };
228
229 static void node_active_cb(void *ntree_v, void *node_v)
230 {
231    nodeSetActive(ntree_v, node_v);
232 };
233
234 static void node_image_type_cb(void *node_v, void *unused)
235 {
236
237    allqueue(REDRAWNODE, 1);
238 };
239
240 static char *node_image_type_pup(void)
241 {
242    char *str= MEM_mallocN(256, "image type pup");
243    int a;
244
245    str[0]= 0;
246
247    a= sprintf(str, "Image Type %%t|");
248    a+= sprintf(str+a, "  Image %%x%d %%i%d|", IMA_SRC_FILE, ICON_IMAGE_DEHLT);
249    a+= sprintf(str+a, "  Movie %%x%d %%i%d|", IMA_SRC_MOVIE, ICON_SEQUENCE);
250    a+= sprintf(str+a, "  Sequence %%x%d %%i%d|", IMA_SRC_SEQUENCE, ICON_IMAGE_COL);
251    a+= sprintf(str+a, "  Generated %%x%d %%i%d", IMA_SRC_GENERATED, ICON_BLANK1);
252
253    return str;
254 };
255
256 /* copy from buttons_shading.c */
257 static char *layer_menu(RenderResult *rr)
258 {
259    RenderLayer *rl;
260    int len= 40 + 40*BLI_countlist(&rr->layers);
261    short a, nr;
262    char *str= MEM_callocN(len, "menu layers");
263
264    strcpy(str, "Layer %t");
265    a= strlen(str);
266    for(nr=0, rl= rr->layers.first; rl; rl= rl->next, nr++) {
267       a+= sprintf(str+a, "|%s %%x%d", rl->name, nr);
268    }
269
270    return str;
271 };
272
273 static void image_layer_cb(void *ima_v, void *iuser_v)
274 {
275
276    ntreeCompositForceHidden(G.scene->nodetree);
277    BKE_image_multilayer_index(ima_v, iuser_v);
278    allqueue(REDRAWNODE, 0);
279 };
280
281 static int node_composit_buts_image(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
282 {
283    ImageUser *iuser= node->storage;
284
285    if(block) {
286       uiBut *bt;
287       short dy= (short)butr->ymax-19;
288       char *strp;
289
290       uiBlockBeginAlign(block);
291       uiBlockSetCol(block, TH_BUT_SETTING2);
292
293       /* browse button */
294       IMAnames_to_pupstring(&strp, NULL, "LOAD NEW %x32767", &(G.main->image), NULL, NULL);
295       node->menunr= 0;
296       bt= uiDefButS(block, MENU, B_NOP, strp, 
297          butr->xmin, dy, 19, 19, 
298          &node->menunr, 0, 0, 0, 0, "Browses existing choices");
299       uiButSetFunc(bt, node_browse_image_cb, ntree, node);
300       if(strp) MEM_freeN(strp);
301
302       /* Add New button */
303       if(node->id==NULL) {
304          bt= uiDefBut(block, BUT, B_NODE_LOADIMAGE, "Load New",
305             butr->xmin+19, dy, (short)(butr->xmax-butr->xmin-19.0f), 19, 
306             NULL, 0.0, 0.0, 0, 0, "Add new Image");
307          uiButSetFunc(bt, node_active_cb, ntree, node);
308          uiBlockSetCol(block, TH_AUTO);
309       }
310       else {
311          /* name button + type */
312          Image *ima= (Image *)node->id;
313          short xmin= (short)butr->xmin, xmax= (short)butr->xmax;
314          short width= xmax - xmin - 45;
315          short icon= ICON_IMAGE_DEHLT;
316
317          if(ima->source==IMA_SRC_MOVIE) icon= ICON_SEQUENCE;
318          else if(ima->source==IMA_SRC_SEQUENCE) icon= ICON_IMAGE_COL;
319          else if(ima->source==IMA_SRC_GENERATED) icon= ICON_BLANK1;
320
321          bt= uiDefBut(block, TEX, B_NOP, "IM:",
322             xmin+19, dy, width, 19, 
323             node->id->name+2, 0.0, 19.0, 0, 0, "Image name");
324          uiButSetFunc(bt, node_ID_title_cb, node, NULL);
325
326          /* buffer type option */
327          strp= node_image_type_pup();
328          bt= uiDefIconTextButS(block, MENU, B_NOP, icon, strp,
329             xmax-26, dy, 26, 19, 
330             &ima->source, 0.0, 19.0, 0, 0, "Image type");
331          uiButSetFunc(bt, node_image_type_cb, node, ima);
332          MEM_freeN(strp);
333
334          if( ELEM(ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE) ) {
335             width= (xmax-xmin)/2;
336
337             dy-= 19;
338             uiDefButI(block, NUM, B_NODE_EXEC+node->nr, "Frs:",
339                xmin, dy, width, 19, 
340                &iuser->frames, 0.0, 10000.0, 0, 0, "Amount of images used in animation");
341             uiDefButI(block, NUM, B_NODE_EXEC+node->nr, "SFra:",
342                xmin+width, dy, width, 19, 
343                &iuser->sfra, 1.0, 10000.0, 0, 0, "Start frame of animation");
344             dy-= 19;
345             uiDefButI(block, NUM, B_NODE_EXEC+node->nr, "Offs:",
346                xmin, dy, width, 19, 
347                &iuser->offset, 0.0, 10000.0, 0, 0, "Offsets the number of the frame to use in the animation");
348             uiDefButS(block, TOG, B_NODE_EXEC+node->nr, "Cycl",
349                xmin+width, dy, width-20, 19, 
350                &iuser->cycl, 0.0, 0.0, 0, 0, "Make animation go cyclic");
351             uiDefIconButBitS(block, TOG, IMA_ANIM_ALWAYS, B_NODE_EXEC+node->nr, ICON_AUTO,
352                xmax-20, dy, 20, 19, 
353                &iuser->flag, 0.0, 0.0, 0, 0, "Always refresh Image on frame changes");
354          }
355          if( ima->type==IMA_TYPE_MULTILAYER && ima->rr) {
356             RenderLayer *rl= BLI_findlink(&ima->rr->layers, iuser->layer);
357             if(rl) {
358                width= (xmax-xmin);
359                dy-= 19;
360                strp= layer_menu(ima->rr);
361                bt= uiDefButS(block, MENU, B_NODE_EXEC+node->nr, strp,
362                   xmin, dy, width, 19, 
363                   &iuser->layer, 0.0, 10000.0, 0, 0, "Layer");
364                uiButSetFunc(bt, image_layer_cb, ima, node->storage);
365                MEM_freeN(strp);
366             }
367          }
368       }
369
370    }    
371    if(node->id) {
372       Image *ima= (Image *)node->id;
373       int retval= 19;
374
375       /* for each draw we test for anim refresh event */
376       if(iuser->flag & IMA_ANIM_REFRESHED) {
377          iuser->flag &= ~IMA_ANIM_REFRESHED;
378          addqueue(curarea->win, UI_BUT_EVENT, B_NODE_EXEC+node->nr);
379       }
380
381       if( ELEM(ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE) )
382          retval+= 38;
383       if( ima->type==IMA_TYPE_MULTILAYER)
384          retval+= 19;
385       return retval;
386    }
387    else
388       return 19;
389 };
390
391 static void node_composit_init_image(bNode* node)
392 {
393    ImageUser *iuser= MEM_callocN(sizeof(ImageUser), "node image user");
394    node->storage= iuser;
395    iuser->sfra= 1;
396    iuser->fie_ima= 2;
397    iuser->ok= 1;
398 }
399
400 bNodeType cmp_node_image= {
401    /* type code   */    CMP_NODE_IMAGE,
402    /* name        */    "Image",
403    /* width+range */    120, 80, 300,
404    /* class+opts  */    NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS,
405    /* input sock  */    NULL,
406    /* output sock */    cmp_node_rlayers_out,
407    /* storage     */    "ImageUser",
408    /* execfunc    */    node_composit_exec_image,
409    /* butfunc     */ node_composit_buts_image,
410                      node_composit_init_image
411 };
412
413 /* **************** RENDER RESULT ******************** */
414
415 static CompBuf *compbuf_from_pass(RenderData *rd, RenderLayer *rl, int rectx, int recty, int passcode)
416 {
417    float *fp= RE_RenderLayerGetPass(rl, passcode);
418    if(fp) {
419       CompBuf *buf;
420       int buftype= CB_VEC3;
421
422       if(ELEM(passcode, SCE_PASS_Z, SCE_PASS_INDEXOB))
423          buftype= CB_VAL;
424       else if(passcode==SCE_PASS_VECTOR)
425          buftype= CB_VEC4;
426       else if(ELEM(passcode, SCE_PASS_COMBINED, SCE_PASS_RGBA))
427          buftype= CB_RGBA;
428
429       if(rd->scemode & R_COMP_CROP)
430          buf= get_cropped_compbuf(&rd->disprect, fp, rectx, recty, buftype);
431       else {
432          buf= alloc_compbuf(rectx, recty, buftype, 0);
433          buf->rect= fp;
434       }
435       return buf;
436    }
437    return NULL;
438 };
439
440 void node_composit_rlayers_out(RenderData *rd, RenderLayer *rl, bNodeStack **out, int rectx, int recty)
441 {
442    if(out[RRES_OUT_Z]->hasoutput)
443       out[RRES_OUT_Z]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_Z);
444    if(out[RRES_OUT_VEC]->hasoutput)
445       out[RRES_OUT_VEC]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_VECTOR);
446    if(out[RRES_OUT_NORMAL]->hasoutput)
447       out[RRES_OUT_NORMAL]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_NORMAL);
448    if(out[RRES_OUT_UV]->hasoutput)
449       out[RRES_OUT_UV]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_UV);
450
451    if(out[RRES_OUT_RGBA]->hasoutput)
452       out[RRES_OUT_RGBA]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_RGBA);
453    if(out[RRES_OUT_DIFF]->hasoutput)
454       out[RRES_OUT_DIFF]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_DIFFUSE);
455    if(out[RRES_OUT_SPEC]->hasoutput)
456       out[RRES_OUT_SPEC]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_SPEC);
457    if(out[RRES_OUT_SHADOW]->hasoutput)
458       out[RRES_OUT_SHADOW]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_SHADOW);
459    if(out[RRES_OUT_AO]->hasoutput)
460       out[RRES_OUT_AO]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_AO);
461    if(out[RRES_OUT_REFLECT]->hasoutput)
462       out[RRES_OUT_REFLECT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_REFLECT);
463    if(out[RRES_OUT_REFRACT]->hasoutput)
464       out[RRES_OUT_REFRACT]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_REFRACT);
465    if(out[RRES_OUT_RADIO]->hasoutput)
466       out[RRES_OUT_RADIO]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_RADIO);
467    if(out[RRES_OUT_INDEXOB]->hasoutput)
468       out[RRES_OUT_INDEXOB]->data= compbuf_from_pass(rd, rl, rectx, recty, SCE_PASS_INDEXOB);
469
470 };
471
472 static void node_composit_exec_rlayers(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
473 {
474    Scene *sce= node->id?(Scene *)node->id:G.scene; /* G.scene is WEAK! */
475    RenderData *rd= data;
476    RenderResult *rr;
477
478    rr= RE_GetResult(RE_GetRender(sce->id.name));
479
480    if(rr) {
481       SceneRenderLayer *srl= BLI_findlink(&sce->r.layers, node->custom1);
482       if(srl) {
483          RenderLayer *rl= RE_GetRenderLayer(rr, srl->name);
484          if(rl && rl->rectf) {
485             CompBuf *stackbuf;
486
487             /* we put render rect on stack, cbuf knows rect is from other ibuf when freed! */
488             if(rd->scemode & R_COMP_CROP)
489                stackbuf= get_cropped_compbuf(&rd->disprect, rl->rectf, rr->rectx, rr->recty, CB_RGBA);
490             else {
491                stackbuf= alloc_compbuf(rr->rectx, rr->recty, CB_RGBA, 0);
492                stackbuf->rect= rl->rectf;
493             }
494             if(stackbuf==NULL) {
495                printf("Error; Preview Panel in UV Window returns zero sized image\n");
496             }
497             else {
498                stackbuf->xof= rr->xof;
499                stackbuf->yof= rr->yof;
500
501                /* put on stack */       
502                out[RRES_OUT_IMAGE]->data= stackbuf;
503
504                if(out[RRES_OUT_ALPHA]->hasoutput)
505                   out[RRES_OUT_ALPHA]->data= valbuf_from_rgbabuf(stackbuf, CHAN_A);
506
507                node_composit_rlayers_out(rd, rl, out, rr->rectx, rr->recty);
508
509                generate_preview(node, stackbuf);
510             }
511          }
512       }
513    }    
514 };
515
516 /* if we use render layers from other scene, we make a nice title */
517 static void set_render_layers_title(void *node_v, void *unused)
518 {
519    bNode *node= node_v;
520    Scene *sce;
521    SceneRenderLayer *srl;
522    char str[64];
523
524    if(node->id) {
525       BLI_strncpy(str, node->id->name+2, 21);
526       strcat(str, "|");
527       sce= (Scene *)node->id;
528    }
529    else {
530       str[0]= 0;
531       sce= G.scene;
532    }
533    srl= BLI_findlink(&sce->r.layers, node->custom1);
534    if(srl==NULL) {
535       node->custom1= 0;
536       srl= sce->r.layers.first;
537    }
538
539    strcat(str, srl->name);
540    BLI_strncpy(node->name, str, 32);
541 };
542
543 static char *scene_layer_menu(Scene *sce)
544 {
545    SceneRenderLayer *srl;
546    int len= 40 + 40*BLI_countlist(&sce->r.layers);
547    short a, nr;
548    char *str= MEM_callocN(len, "menu layers");
549
550    strcpy(str, "Active Layer %t");
551    a= strlen(str);
552    for(nr=0, srl= sce->r.layers.first; srl; srl= srl->next, nr++) {
553       a+= sprintf(str+a, "|%s %%x%d", srl->name, nr);
554    }
555
556    return str;
557 };
558
559 static void node_browse_scene_cb(void *ntree_v, void *node_v)
560 {
561    bNodeTree *ntree= ntree_v;
562    bNode *node= node_v;
563    Scene *sce;
564
565    if(node->menunr<1) return;
566
567    if(node->id) {
568       node->id->us--;
569       node->id= NULL;
570    }
571    sce= BLI_findlink(&G.main->scene, node->menunr-1);
572    if(sce!=G.scene) {
573       node->id= &sce->id;
574       id_us_plus(node->id);
575    }
576
577    set_render_layers_title(node, NULL);
578    nodeSetActive(ntree, node);
579
580    allqueue(REDRAWBUTSSHADING, 0);
581    allqueue(REDRAWNODE, 0);
582    NodeTagChanged(ntree, node); 
583
584    node->menunr= 0;
585 };
586
587 static int node_composit_buts_renderlayers(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
588 {
589    if(block) {
590       uiBut *bt;
591       char *strp;
592
593       /* browse button scene */
594       uiBlockBeginAlign(block);
595       IDnames_to_pupstring(&strp, NULL, "", &(G.main->scene), NULL, NULL);
596       node->menunr= 0;
597       bt= uiDefButS(block, MENU, B_NOP, strp, 
598          butr->xmin, butr->ymin, 20, 19, 
599          &node->menunr, 0, 0, 0, 0, "Browse Scene to use RenderLayer from");
600       uiButSetFunc(bt, node_browse_scene_cb, ntree, node);
601       if(strp) MEM_freeN(strp);
602
603       /* browse button layer */
604       strp= scene_layer_menu(node->id?(Scene *)node->id:G.scene);
605       if(node->id)
606          bt= uiDefIconTextButS(block, MENU, B_NODE_EXEC+node->nr, ICON_SCENE_DEHLT, strp, 
607          butr->xmin+20, butr->ymin, (butr->xmax-butr->xmin)-40, 19, 
608          &node->custom1, 0, 0, 0, 0, "Choose Render Layer");
609       else
610          bt= uiDefButS(block, MENU, B_NODE_EXEC+node->nr, strp, 
611          butr->xmin+20, butr->ymin, (butr->xmax-butr->xmin)-40, 19, 
612          &node->custom1, 0, 0, 0, 0, "Choose Render Layer");
613       uiButSetFunc(bt, set_render_layers_title, node, NULL);
614       MEM_freeN(strp);
615
616       /* re-render */
617       /* uses custom2, not the best implementation of the world... but we need it to work now :) */
618       bt= uiDefIconButS(block, TOG, B_NODE_EXEC+node->nr, ICON_SCENE, 
619          butr->xmax-20, butr->ymin, 20, 19, 
620          &node->custom2, 0, 0, 0, 0, "Re-render this Layer");
621
622    }
623    return 19;
624 };
625
626
627 bNodeType cmp_node_rlayers= {
628    /* type code   */    CMP_NODE_R_LAYERS,
629    /* name        */    "Render Layers",
630    /* width+range */    150, 100, 300,
631    /* class+opts  */    NODE_CLASS_INPUT, NODE_PREVIEW|NODE_OPTIONS,
632    /* input sock  */    NULL,
633    /* output sock */    cmp_node_rlayers_out,
634    /* storage     */    "",
635    /* execfunc    */    node_composit_exec_rlayers,
636    /* butfunc     */ node_composit_buts_renderlayers,
637                      NULL
638
639 };