rename api functions...
[blender.git] / source / blender / editors / space_node / drawnode.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) 2005 Blender Foundation.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): David Millan Escriva, Juho Vepsäläinen, Bob Holcomb, Thomas Dinges
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/editors/space_node/drawnode.c
29  *  \ingroup spnode
30  *  \brief lower level node drawing for nodes (boarders, headers etc), also node layout.
31  */
32
33 #include "BLI_blenlib.h"
34 #include "BLI_math.h"
35
36 #include "DNA_node_types.h"
37 #include "DNA_object_types.h"
38 #include "DNA_space_types.h"
39 #include "DNA_screen_types.h"
40
41 #include "BKE_context.h"
42 #include "BKE_curve.h"
43 #include "BKE_image.h"
44 #include "BKE_main.h"
45 #include "BKE_node.h"
46 #include "BKE_tracking.h"
47
48 #include "BLF_api.h"
49 #include "BLF_translation.h"
50
51
52 #include "BIF_gl.h"
53 #include "BIF_glutil.h"
54
55 #include "MEM_guardedalloc.h"
56
57 #include "RNA_access.h"
58
59 #include "ED_node.h"
60
61 #include "WM_api.h"
62 #include "WM_types.h"
63
64 #include "UI_resources.h"
65
66 #include "IMB_colormanagement.h"
67 #include "IMB_imbuf.h"
68 #include "IMB_imbuf_types.h"
69
70 #include "node_intern.h"  /* own include */
71
72 /* ****************** SOCKET BUTTON DRAW FUNCTIONS ***************** */
73
74 static void node_sync_cb(bContext *UNUSED(C), void *snode_v, void *node_v)
75 {
76         SpaceNode *snode = snode_v;
77         
78         if (snode->treetype == NTREE_SHADER) {
79                 nodeShaderSynchronizeID(node_v, 1);
80                 // allqueue(REDRAWBUTSSHADING, 0);
81         }
82 }
83
84 static void node_socket_button_label(const bContext *UNUSED(C), uiBlock *block,
85                                      bNodeTree *UNUSED(ntree), bNode *UNUSED(node), bNodeSocket *sock,
86                                      const char *UNUSED(name), int x, int y, int width)
87 {
88         uiDefBut(block, LABEL, 0, IFACE_(sock->name), x, y, width, NODE_DY, NULL, 0, 0, 0, 0, "");
89 }
90
91 static void node_socket_button_default(const bContext *C, uiBlock *block,
92                                        bNodeTree *ntree, bNode *node, bNodeSocket *sock,
93                                        const char *name, int x, int y, int width)
94 {
95         if (sock->link || (sock->flag & SOCK_HIDE_VALUE))
96                 node_socket_button_label(C, block, ntree, node, sock, name, x, y, width);
97         else {
98                 PointerRNA ptr;
99                 uiBut *bt;
100                 
101                 RNA_pointer_create(&ntree->id, &RNA_NodeSocket, sock, &ptr);
102                 
103                 bt = uiDefButR(block, NUM, B_NODE_EXEC, IFACE_(name),
104                                x, y + 1, width, NODE_DY - 2,
105                                &ptr, "default_value", 0, 0, 0, -1, -1, NULL);
106                 if (node)
107                         uiButSetFunc(bt, node_sync_cb, CTX_wm_space_node(C), node);
108         }
109 }
110
111 typedef struct SocketComponentMenuArgs {
112         PointerRNA ptr;
113         int x, y, width;
114         uiButHandleFunc cb;
115         void *arg1, *arg2;
116 } SocketComponentMenuArgs;
117 /* NOTE: this is a block-menu, needs 0 events, otherwise the menu closes */
118 static uiBlock *socket_component_menu(bContext *C, ARegion *ar, void *args_v)
119 {
120         SocketComponentMenuArgs *args = (SocketComponentMenuArgs *)args_v;
121         uiBlock *block;
122         uiLayout *layout;
123         
124         block = uiBeginBlock(C, ar, __func__, UI_EMBOSS);
125         uiBlockSetFlag(block, UI_BLOCK_KEEP_OPEN);
126         
127         layout = uiLayoutColumn(uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL,
128                                               args->x, args->y + 2, args->width, NODE_DY, UI_GetStyle()), FALSE);
129         
130         uiItemR(layout, &args->ptr, "default_value", UI_ITEM_R_EXPAND, "", ICON_NONE);
131         
132         return block;
133 }
134 static void node_socket_button_components(const bContext *C, uiBlock *block,
135                                           bNodeTree *ntree, bNode *node, bNodeSocket *sock,
136                                           const char *name, int x, int y, int width)
137 {
138         if (sock->link || (sock->flag & SOCK_HIDE_VALUE))
139                 node_socket_button_label(C, block, ntree, node, sock, name, x, y, width);
140         else {
141                 PointerRNA ptr;
142                 SocketComponentMenuArgs *args;
143                 
144                 RNA_pointer_create(&ntree->id, &RNA_NodeSocket, sock, &ptr);
145                 
146                 args = MEM_callocN(sizeof(SocketComponentMenuArgs), "SocketComponentMenuArgs");
147                 
148                 args->ptr = ptr;
149                 args->x = x;
150                 args->y = y;
151                 args->width = width;
152                 args->cb = node_sync_cb;
153                 args->arg1 = CTX_wm_space_node(C);
154                 args->arg2 = node;
155                 
156                 uiDefBlockButN(block, socket_component_menu, args, IFACE_(name), x, y + 1, width, NODE_DY - 2, "");
157         }
158 }
159
160 static void node_socket_button_color(const bContext *C, uiBlock *block,
161                                      bNodeTree *ntree, bNode *node, bNodeSocket *sock,
162                                      const char *name, int x, int y, int width)
163 {
164         if (sock->link || (sock->flag & SOCK_HIDE_VALUE))
165                 node_socket_button_label(C, block, ntree, node, sock, IFACE_(name), x, y, width);
166         else {
167                 PointerRNA ptr;
168                 uiBut *bt;
169                 int labelw = width - 40;
170                 RNA_pointer_create(&ntree->id, &RNA_NodeSocket, sock, &ptr);
171                 
172                 bt = uiDefButR(block, COLOR, B_NODE_EXEC, "",
173                                x, y + 2, (labelw > 0 ? 40 : width), NODE_DY - 2,
174                                &ptr, "default_value", 0, 0, 0, -1, -1, NULL);
175                 if (node)
176                         uiButSetFunc(bt, node_sync_cb, CTX_wm_space_node(C), node);
177                 
178                 if (name[0] != '\0' && labelw > 0)
179                         uiDefBut(block, LABEL, 0, IFACE_(name), x + 40, y + 2, labelw, NODE_DY - 2, NULL, 0, 0, 0, 0, "");
180         }
181 }
182
183 /* standard draw function, display the default input value */
184 static void node_draw_input_default(const bContext *C, uiBlock *block,
185                                     bNodeTree *ntree, bNode *node, bNodeSocket *sock,
186                                     const char *name, int x, int y, int width)
187 {
188         bNodeSocketType *stype = ntreeGetSocketType(sock->type);
189         if (stype->buttonfunc)
190                 stype->buttonfunc(C, block, ntree, node, sock, name, x, y, width);
191         else
192                 node_socket_button_label(C, block, ntree, node, sock, IFACE_(name), x, y, width);
193 }
194
195 static void node_draw_output_default(const bContext *C, uiBlock *block,
196                                      bNodeTree *UNUSED(ntree), bNode *node, bNodeSocket *sock,
197                                      const char *name, int UNUSED(x), int UNUSED(y), int UNUSED(width))
198 {
199         SpaceNode *snode = CTX_wm_space_node(C);
200         const char *ui_name = IFACE_(name);
201         float slen;
202
203         UI_ThemeColor(TH_TEXT);
204         slen = (UI_GetStringWidth(ui_name) + NODE_MARGIN_X) * snode->aspect_sqrt;
205         while (slen > node->width && *ui_name) {
206                 ui_name = BLI_str_find_next_char_utf8(ui_name, NULL);
207                 slen = (UI_GetStringWidth(ui_name) + NODE_MARGIN_X) * snode->aspect_sqrt;
208         }
209         
210         if (*ui_name) {
211                 uiDefBut(block, LABEL, 0, ui_name,
212                                  (int)(sock->locx - slen), (int)(sock->locy - 9.0f),
213                                  (short)slen, (short)NODE_DY,
214                                  NULL, 0, 0, 0, 0, "");
215         }
216 }
217
218 /* ****************** BASE DRAW FUNCTIONS FOR NEW OPERATOR NODES ***************** */
219
220 #if 0 /* UNUSED */
221 static void node_draw_socket_new(bNodeSocket *sock, float size)
222 {
223         float x = sock->locx, y = sock->locy;
224         
225         /* 16 values of sin function */
226         static float si[16] = {
227                 0.00000000f, 0.39435585f, 0.72479278f, 0.93775213f,
228                 0.99871650f, 0.89780453f, 0.65137248f, 0.29936312f,
229                 -0.10116832f, -0.48530196f, -0.79077573f, -0.96807711f,
230                 -0.98846832f, -0.84864425f, -0.57126821f, -0.20129852f
231         };
232         /* 16 values of cos function */
233         static float co[16] = {
234                 1.00000000f, 0.91895781f, 0.68896691f, 0.34730525f,
235                 -0.05064916f, -0.44039415f, -0.75875812f, -0.95413925f,
236                 -0.99486932f, -0.87434661f, -0.61210598f, -0.25065253f,
237                 0.15142777f, 0.52896401f, 0.82076344f, 0.97952994f,
238         };
239         int a;
240         
241         glColor3ub(180, 180, 180);
242         
243         glBegin(GL_POLYGON);
244         for (a = 0; a < 16; a++)
245                 glVertex2f(x + size * si[a], y + size * co[a]);
246         glEnd();
247         
248         glColor4ub(0, 0, 0, 150);
249         glEnable(GL_BLEND);
250         glEnable(GL_LINE_SMOOTH);
251         glBegin(GL_LINE_LOOP);
252         for (a = 0; a < 16; a++)
253                 glVertex2f(x + size * si[a], y + size * co[a]);
254         glEnd();
255         glDisable(GL_LINE_SMOOTH);
256         glDisable(GL_BLEND);
257 }
258 #endif
259
260 /* ****************** BUTTON CALLBACKS FOR ALL TREES ***************** */
261
262 static void node_buts_value(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
263 {
264         PointerRNA sockptr;
265         PropertyRNA *prop;
266         
267         /* first socket stores value */
268         prop = RNA_struct_find_property(ptr, "outputs");
269         RNA_property_collection_lookup_int(ptr, prop, 0, &sockptr);
270         
271         uiItemR(layout, &sockptr, "default_value", 0, "", ICON_NONE);
272 }
273
274 static void node_buts_rgb(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
275 {
276         uiLayout *col;
277         PointerRNA sockptr;
278         PropertyRNA *prop;
279         
280         /* first socket stores value */
281         prop = RNA_struct_find_property(ptr, "outputs");
282         RNA_property_collection_lookup_int(ptr, prop, 0, &sockptr);
283         
284         col = uiLayoutColumn(layout, FALSE);
285         uiTemplateColorWheel(col, &sockptr, "default_value", 1, 0, 0, 0);
286         uiItemR(col, &sockptr, "default_value", 0, "", ICON_NONE);
287 }
288
289 static void node_buts_mix_rgb(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
290 {       
291         uiLayout *row, *col;
292
293         bNodeTree *ntree = (bNodeTree *)ptr->id.data;
294
295         col = uiLayoutColumn(layout, FALSE);
296         row = uiLayoutRow(col, TRUE);
297         uiItemR(row, ptr, "blend_type", 0, "", ICON_NONE);
298         if (ntree->type == NTREE_COMPOSIT)
299                 uiItemR(row, ptr, "use_alpha", 0, "", ICON_IMAGE_RGB_ALPHA);
300
301         uiItemR(col, ptr, "use_clamp", 0, NULL, ICON_NONE);
302 }
303
304 static void node_buts_time(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
305 {
306         uiLayout *row;
307 #if 0
308         /* XXX no context access here .. */
309         bNode *node = ptr->data;
310         CurveMapping *cumap = node->storage;
311         
312         if (cumap) {
313                 cumap->flag |= CUMA_DRAW_CFRA;
314                 if (node->custom1 < node->custom2)
315                         cumap->sample[0] = (float)(CFRA - node->custom1) / (float)(node->custom2 - node->custom1);
316         }
317 #endif
318
319         uiTemplateCurveMapping(layout, ptr, "curve", 's', 0, 0);
320
321         row = uiLayoutRow(layout, TRUE);
322         uiItemR(row, ptr, "frame_start", 0, IFACE_("Sta"), ICON_NONE);
323         uiItemR(row, ptr, "frame_end", 0, IFACE_("End"), ICON_NONE);
324 }
325
326 static void node_buts_colorramp(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
327 {
328         uiTemplateColorRamp(layout, ptr, "color_ramp", 0);
329 }
330
331 static void node_buts_curvevec(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
332 {
333         uiTemplateCurveMapping(layout, ptr, "mapping", 'v', 0, 0);
334 }
335
336 #define SAMPLE_FLT_ISNONE FLT_MAX
337 static float _sample_col[4] = {SAMPLE_FLT_ISNONE};  /* bad bad, 2.5 will do better?... no it won't... */
338 void ED_node_sample_set(const float col[4])
339 {
340         if (col) {
341                 copy_v4_v4(_sample_col, col);
342         }
343         else {
344                 copy_v4_fl(_sample_col, SAMPLE_FLT_ISNONE);
345         }
346 }
347
348 static void node_buts_curvecol(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
349 {
350         bNode *node = ptr->data;
351         CurveMapping *cumap = node->storage;
352
353         if (_sample_col[0] != SAMPLE_FLT_ISNONE) {
354                 cumap->flag |= CUMA_DRAW_SAMPLE;
355                 copy_v3_v3(cumap->sample, _sample_col);
356         }
357         else {
358                 cumap->flag &= ~CUMA_DRAW_SAMPLE;
359         }
360
361         uiTemplateCurveMapping(layout, ptr, "mapping", 'c', 0, 0);
362 }
363
364 static void node_normal_cb(bContext *C, void *ntree_v, void *node_v)
365 {
366         Main *bmain = CTX_data_main(C);
367
368         ED_node_generic_update(bmain, ntree_v, node_v);
369         WM_event_add_notifier(C, NC_NODE | NA_EDITED, ntree_v);
370 }
371
372 static void node_buts_normal(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
373 {
374         uiBlock *block = uiLayoutAbsoluteBlock(layout);
375         bNodeTree *ntree = ptr->id.data;
376         bNode *node = ptr->data;
377         rctf *butr = &node->butr;
378         bNodeSocket *sock = node->outputs.first;     /* first socket stores normal */
379         float *nor = ((bNodeSocketValueVector *)sock->default_value)->value;
380         uiBut *bt;
381         
382         bt = uiDefButF(block, BUT_NORMAL, B_NODE_EXEC, "",
383                        (int)butr->xmin, (int)butr->xmin,
384                        (short)BLI_rctf_size_x(butr), (short)BLI_rctf_size_x(butr),
385                        nor, 0.0f, 1.0f, 0, 0, "");
386         uiButSetFunc(bt, node_normal_cb, ntree, node);
387 }
388 #if 0 /* not used in 2.5x yet */
389 static void node_browse_tex_cb(bContext *C, void *ntree_v, void *node_v)
390 {
391         Main *bmain = CTX_data_main(C);
392         bNodeTree *ntree = ntree_v;
393         bNode *node = node_v;
394         Tex *tex;
395         
396         if (node->menunr < 1) return;
397         
398         if (node->id) {
399                 node->id->us--;
400                 node->id = NULL;
401         }
402         tex = BLI_findlink(&bmain->tex, node->menunr - 1);
403
404         node->id = &tex->id;
405         id_us_plus(node->id);
406         BLI_strncpy(node->name, node->id->name + 2, sizeof(node->name));
407         
408         nodeSetActive(ntree, node);
409         
410         if (ntree->type == NTREE_TEXTURE)
411                 ntreeTexCheckCyclics(ntree);
412         
413         // allqueue(REDRAWBUTSSHADING, 0);
414         // allqueue(REDRAWNODE, 0);
415         NodeTagChanged(ntree, node); 
416         
417         node->menunr = 0;
418 }
419 #endif
420
421 static void node_buts_texture(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
422 {
423         bNode *node = ptr->data;
424
425         short multi = (
426             node->id &&
427             ((Tex *)node->id)->use_nodes &&
428             (node->type != CMP_NODE_TEXTURE) &&
429             (node->type != TEX_NODE_TEXTURE)
430             );
431         
432         uiItemR(layout, ptr, "texture", 0, "", ICON_NONE);
433         
434         if (multi) {
435                 /* Number Drawing not optimal here, better have a list*/
436                 uiItemR(layout, ptr, "node_output", 0, "", ICON_NONE);
437         }
438 }
439
440 static void node_buts_math(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
441
442         uiItemR(layout, ptr, "operation", 0, "", ICON_NONE);
443         uiItemR(layout, ptr, "use_clamp", 0, NULL, ICON_NONE);
444 }
445
446 static int node_resize_area_default(bNode *node, int x, int y)
447 {
448         if (node->flag & NODE_HIDDEN) {
449                 rctf totr = node->totr;
450                 /* right part of node */
451                 totr.xmin = node->totr.xmax - 20.0f;
452                 if (BLI_rctf_isect_pt(&totr, x, y))
453                         return NODE_RESIZE_RIGHT;
454                 else
455                         return 0;
456         }
457         else {
458                 const float size = 10.0f;
459                 rctf totr = node->totr;
460                 int dir = 0;
461                 
462                 if (x >= totr.xmax - size && x < totr.xmax && y >= totr.ymin && y < totr.ymax)
463                         dir |= NODE_RESIZE_RIGHT;
464                 if (x >= totr.xmin && x < totr.xmin + size && y >= totr.ymin && y < totr.ymax)
465                         dir |= NODE_RESIZE_LEFT;
466                 return dir;
467         }
468 }
469
470 /* ****************** BUTTON CALLBACKS FOR COMMON NODES ***************** */
471
472 /* width of socket columns in group display */
473 #define NODE_GROUP_FRAME        120
474
475 /* based on settings in node, sets drawing rect info. each redraw! */
476 /* note: this assumes only 1 group at a time is drawn (linked data) */
477 /* in node->totr the entire boundbox for the group is stored */
478 static void node_update_group(const bContext *C, bNodeTree *ntree, bNode *gnode)
479 {
480         if (!(gnode->flag & NODE_GROUP_EDIT)) {
481                 node_update_default(C, ntree, gnode);
482         }
483         else {
484                 bNodeTree *ngroup = (bNodeTree *)gnode->id;
485                 bNode *node;
486                 bNodeSocket *sock, *gsock;
487                 float locx, locy;
488                 rctf *rect = &gnode->totr;
489                 float node_group_frame = U.dpi * NODE_GROUP_FRAME / 72;
490                 float group_header = 26 * U.dpi / 72;
491                 int counter;
492                 int dy;
493                 
494                 /* get "global" coords */
495                 nodeToView(gnode, 0.0f, 0.0f, &locx, &locy);
496                 
497                 /* center them, is a bit of abuse of locx and locy though */
498                 node_update_nodetree(C, ngroup, locx, locy);
499                 
500                 rect->xmin = rect->xmax = locx;
501                 rect->ymin = rect->ymax = locy;
502                 
503                 counter = 1;
504                 for (node = ngroup->nodes.first; node; node = node->next) {
505                         if (counter) {
506                                 *rect = node->totr;
507                                 counter = 0;
508                         }
509                         else
510                                 BLI_rctf_union(rect, &node->totr);
511                 }
512                 
513                 /* add some room for links to group sockets */
514                 rect->xmin -= 4 * NODE_DY;
515                 rect->xmax += 4 * NODE_DY;
516                 rect->ymin -= NODE_DY;
517                 rect->ymax += NODE_DY;
518                 
519                 /* input sockets */
520                 dy = BLI_rctf_cent_y(rect) + (NODE_DY * (BLI_countlist(&gnode->inputs) - 1));
521                 gsock = ngroup->inputs.first;
522                 sock = gnode->inputs.first;
523                 while (gsock || sock) {
524                         while (sock && !sock->groupsock) {
525                                 sock->locx = rect->xmin - node_group_frame;
526                                 sock->locy = dy;
527
528                                 /* prevent long socket lists from growing out of the group box */
529                                 if (dy - 3 * NODE_DYS < rect->ymin)
530                                         rect->ymin = dy - 3 * NODE_DYS;
531                                 if (dy + 3 * NODE_DYS > rect->ymax)
532                                         rect->ymax = dy + 3 * NODE_DYS;
533                                 dy -= 2 * NODE_DY;
534                                 
535                                 sock = sock->next;
536                         }
537                         while (gsock && (!sock || sock->groupsock != gsock)) {
538                                 gsock->locx = rect->xmin;
539                                 gsock->locy = dy;
540                                 
541                                 /* prevent long socket lists from growing out of the group box */
542                                 if (dy - 3 * NODE_DYS < rect->ymin)
543                                         rect->ymin = dy - 3 * NODE_DYS;
544                                 if (dy + 3 * NODE_DYS > rect->ymax)
545                                         rect->ymax = dy + 3 * NODE_DYS;
546                                 dy -= 2 * NODE_DY;
547                                 
548                                 gsock = gsock->next;
549                         }
550                         while (sock && gsock && sock->groupsock == gsock) {
551                                 gsock->locx = rect->xmin;
552                                 sock->locx = rect->xmin - node_group_frame;
553                                 sock->locy = gsock->locy = dy;
554                                 
555                                 /* prevent long socket lists from growing out of the group box */
556                                 if (dy - 3 * NODE_DYS < rect->ymin)
557                                         rect->ymin = dy - 3 * NODE_DYS;
558                                 if (dy + 3 * NODE_DYS > rect->ymax)
559                                         rect->ymax = dy + 3 * NODE_DYS;
560                                 dy -= 2 * NODE_DY;
561                                 
562                                 sock = sock->next;
563                                 gsock = gsock->next;
564                         }
565                 }
566                 
567                 /* output sockets */
568                 dy = BLI_rctf_cent_y(rect) + (NODE_DY * (BLI_countlist(&gnode->outputs) - 1));
569                 gsock = ngroup->outputs.first;
570                 sock = gnode->outputs.first;
571                 while (gsock || sock) {
572                         while (sock && !sock->groupsock) {
573                                 sock->locx = rect->xmax + node_group_frame;
574                                 sock->locy = dy - NODE_DYS;
575                                 
576                                 /* prevent long socket lists from growing out of the group box */
577                                 if (dy - 3 * NODE_DYS < rect->ymin)
578                                         rect->ymin = dy - 3 * NODE_DYS;
579                                 if (dy + 3 * NODE_DYS > rect->ymax)
580                                         rect->ymax = dy + 3 * NODE_DYS;
581                                 dy -= 2 * NODE_DY;
582                                 
583                                 sock = sock->next;
584                         }
585                         while (gsock && (!sock || sock->groupsock != gsock)) {
586                                 gsock->locx = rect->xmax;
587                                 gsock->locy = dy - NODE_DYS;
588                                 
589                                 /* prevent long socket lists from growing out of the group box */
590                                 if (dy - 3 * NODE_DYS < rect->ymin)
591                                         rect->ymin = dy - 3 * NODE_DYS;
592                                 if (dy + 3 * NODE_DYS > rect->ymax)
593                                         rect->ymax = dy + 3 * NODE_DYS;
594                                 dy -= 2 * NODE_DY;
595                                 
596                                 gsock = gsock->next;
597                         }
598                         while (sock && gsock && sock->groupsock == gsock) {
599                                 gsock->locx = rect->xmax;
600                                 sock->locx = rect->xmax + node_group_frame;
601                                 sock->locy = gsock->locy = dy - NODE_DYS;
602                                 
603                                 /* prevent long socket lists from growing out of the group box */
604                                 if (dy - 3 * NODE_DYS < rect->ymin)
605                                         rect->ymin = dy - 3 * NODE_DYS;
606                                 if (dy + 3 * NODE_DYS > rect->ymax)
607                                         rect->ymax = dy + 3 * NODE_DYS;
608                                 dy -= 2 * NODE_DY;
609                                 
610                                 sock = sock->next;
611                                 gsock = gsock->next;
612                         }
613                 }
614                 
615                 /* Set the block bounds to clip mouse events from underlying nodes.
616                  * Add margin for header and input/output columns.
617                  */
618                 uiExplicitBoundsBlock(gnode->block,
619                                       rect->xmin - node_group_frame,
620                                       rect->ymin,
621                                       rect->xmax + node_group_frame,
622                                       rect->ymax + group_header);
623         }
624 }
625
626 static void update_group_input_cb(bContext *UNUSED(C), void *UNUSED(snode_v), void *ngroup_v)
627 {
628         bNodeTree *ngroup = (bNodeTree *)ngroup_v;
629         
630         ngroup->update |= NTREE_UPDATE_GROUP_IN;
631         ntreeUpdateTree(ngroup);
632 }
633
634 static void update_group_output_cb(bContext *UNUSED(C), void *UNUSED(snode_v), void *ngroup_v)
635 {
636         bNodeTree *ngroup = (bNodeTree *)ngroup_v;
637         
638         ngroup->update |= NTREE_UPDATE_GROUP_OUT;
639         ntreeUpdateTree(ngroup);
640 }
641
642 static void draw_group_socket_name(SpaceNode *snode, bNode *gnode, bNodeSocket *sock,
643                                    int in_out, float xoffset, float yoffset, short width, short height)
644 {
645         if (sock->flag & SOCK_DYNAMIC) {
646                 bNodeTree *ngroup = (bNodeTree *)gnode->id;
647                 uiBut *but;
648                 but = uiDefBut(gnode->block, TEX, 0, "",
649                                sock->locx + xoffset, sock->locy + 1 + yoffset, width, height,
650                                sock->name, 0, sizeof(sock->name), 0, 0, "");
651                 if (in_out == SOCK_IN)
652                         uiButSetFunc(but, update_group_input_cb, snode, ngroup);
653                 else
654                         uiButSetFunc(but, update_group_output_cb, snode, ngroup);
655         }
656         else {
657                 const char *ui_name = IFACE_(sock->name);
658                 uiDefBut(gnode->block, LABEL, 0, ui_name,
659                          sock->locx + xoffset, sock->locy + 1 + yoffset, width, height,
660                          NULL, 0, 0, 0, 0, "");
661         }
662 }
663
664 static void draw_group_socket(const bContext *C, SpaceNode *snode, bNodeTree *ntree, bNode *gnode,
665                               bNodeSocket *sock, bNodeSocket *gsock, int index, int in_out)
666 {
667         const float dpi_fac = U.dpi / 72.0f;
668         bNodeTree *ngroup = (bNodeTree *)gnode->id;
669         bNodeSocketType *stype = ntreeGetSocketType(gsock ? gsock->type : sock->type);
670         uiBut *bt;
671         float offset;
672         int draw_value;
673         const float node_group_frame = NODE_GROUP_FRAME * dpi_fac;
674         const float socket_size      = NODE_SOCKSIZE * dpi_fac;
675         const float arrowbutw        = 0.8f * UI_UNIT_X;
676         const short co_text_w = 72 * dpi_fac;
677         const float co_margin = 6.0f * dpi_fac;
678         /* layout stuff for buttons on group left frame */
679         const float colw = 0.6f * node_group_frame;
680         const float col1 = co_margin - node_group_frame;
681         const float col2 = col1 + colw + co_margin;
682         const float col3 = -arrowbutw - co_margin;
683         /* layout stuff for buttons on group right frame */
684         const float cor1 = co_margin;
685         const float cor2 = cor1 + arrowbutw;
686         const float cor3 = cor2 + arrowbutw + co_margin;
687         
688         /* node and group socket circles */
689         if (sock)
690                 node_socket_circle_draw(ntree, sock, socket_size, sock->flag & SELECT);
691         if (gsock)
692                 node_socket_circle_draw(ngroup, gsock, socket_size, gsock->flag & SELECT);
693         
694         /* socket name */
695         offset = (in_out == SOCK_IN ? col1 : cor3);
696         if (!gsock)
697                 offset += (in_out == SOCK_IN ? node_group_frame : -node_group_frame);
698         
699         /* draw both name and value button if:
700          * 1) input: not internal
701          * 2) output: (node type uses const outputs) and (group output is unlinked)
702          */
703         draw_value = 0;
704         switch (in_out) {
705                 case SOCK_IN:
706                         draw_value = !(gsock && (gsock->flag & SOCK_INTERNAL));
707                         break;
708                 case SOCK_OUT:
709                         if (gnode->typeinfo->flag & NODE_CONST_OUTPUT)
710                                 draw_value = !(gsock && gsock->link);
711                         break;
712         }
713         if (draw_value) {
714                 /* both name and value buttons */
715                 if (gsock) {
716                         draw_group_socket_name(snode, gnode, gsock, in_out, offset, 0, co_text_w, NODE_DY);
717                         if (stype->buttonfunc)
718                                 stype->buttonfunc(C, gnode->block, ngroup, NULL, gsock, "",
719                                                   gsock->locx + offset, gsock->locy - NODE_DY, colw);
720                 }
721                 else {
722                         draw_group_socket_name(snode, gnode, sock, in_out, offset, 0, co_text_w, NODE_DY);
723                         if (stype->buttonfunc)
724                                 stype->buttonfunc(C, gnode->block, ngroup, NULL, sock, "",
725                                                   sock->locx + offset, sock->locy - NODE_DY, colw);
726                 }
727         }
728         else {
729                 /* only name, no value button */
730                 if (gsock)
731                         draw_group_socket_name(snode, gnode, gsock, in_out, offset, -NODE_DYS, co_text_w, NODE_DY);
732                 else
733                         draw_group_socket_name(snode, gnode, sock, in_out, offset, -NODE_DYS, co_text_w, NODE_DY);
734         }
735         
736         if (gsock && (gsock->flag & SOCK_DYNAMIC)) {
737                 /* up/down buttons */
738                 offset = (in_out == SOCK_IN ? col2 : cor2);
739                 uiBlockSetDirection(gnode->block, UI_TOP);
740                 uiBlockBeginAlign(gnode->block);
741                 bt = uiDefIconButO(gnode->block, BUT, "NODE_OT_group_socket_move_up", 0, ICON_TRIA_UP,
742                                    gsock->locx + offset, gsock->locy, arrowbutw, arrowbutw, "");
743                 if (!gsock->prev || !(gsock->prev->flag & SOCK_DYNAMIC))
744                         uiButSetFlag(bt, UI_BUT_DISABLED);
745                 RNA_int_set(uiButGetOperatorPtrRNA(bt), "index", index);
746                 RNA_enum_set(uiButGetOperatorPtrRNA(bt), "in_out", in_out);
747                 bt = uiDefIconButO(gnode->block, BUT, "NODE_OT_group_socket_move_down", 0, ICON_TRIA_DOWN,
748                                    gsock->locx + offset, gsock->locy - arrowbutw, arrowbutw, arrowbutw, "");
749                 if (!gsock->next || !(gsock->next->flag & SOCK_DYNAMIC))
750                         uiButSetFlag(bt, UI_BUT_DISABLED);
751                 RNA_int_set(uiButGetOperatorPtrRNA(bt), "index", index);
752                 RNA_enum_set(uiButGetOperatorPtrRNA(bt), "in_out", in_out);
753                 uiBlockEndAlign(gnode->block);
754                 uiBlockSetDirection(gnode->block, 0);
755                 
756                 /* remove button */
757                 offset = (in_out == SOCK_IN ? col3 : cor1);
758                 uiBlockSetEmboss(gnode->block, UI_EMBOSSN);
759                 bt = uiDefIconButO(gnode->block, BUT, "NODE_OT_group_socket_remove", 0, ICON_X,
760                                    gsock->locx + offset, gsock->locy - 0.5f * arrowbutw, arrowbutw, arrowbutw, "");
761                 RNA_int_set(uiButGetOperatorPtrRNA(bt), "index", index);
762                 RNA_enum_set(uiButGetOperatorPtrRNA(bt), "in_out", in_out);
763                 uiBlockSetEmboss(gnode->block, UI_EMBOSS);
764         }
765 }
766
767 /* groups are, on creation, centered around 0,0 */
768 static void node_draw_group(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *gnode)
769 {
770         if (!(gnode->flag & NODE_GROUP_EDIT)) {
771                 node_draw_default(C, ar, snode, ntree, gnode);
772         }
773         else {
774                 bNodeTree *ngroup = (bNodeTree *)gnode->id;
775                 bNodeSocket *sock, *gsock;
776                 uiLayout *layout;
777                 PointerRNA ptr;
778                 rctf rect = gnode->totr;
779                 const float dpi_fac = U.dpi / 72.0f;
780                 float node_group_frame = NODE_GROUP_FRAME * dpi_fac;
781                 float group_header = 26 * dpi_fac;
782                 
783                 int index;
784                 
785                 /* backdrop header */
786                 glEnable(GL_BLEND);
787                 uiSetRoundBox(UI_CNR_TOP_LEFT | UI_CNR_TOP_RIGHT);
788                 UI_ThemeColorShadeAlpha(TH_NODE_GROUP, 0, -70);
789                 uiDrawBox(GL_POLYGON,
790                           rect.xmin - node_group_frame, rect.ymax,
791                           rect.xmax + node_group_frame, rect.ymax + group_header, BASIS_RAD);
792                 
793                 /* backdrop body */
794                 UI_ThemeColorShadeAlpha(TH_BACK, -8, -70);
795                 uiSetRoundBox(UI_CNR_NONE);
796                 uiDrawBox(GL_POLYGON, rect.xmin, rect.ymin, rect.xmax, rect.ymax, BASIS_RAD);
797         
798                 /* input column */
799                 UI_ThemeColorShadeAlpha(TH_BACK, 10, -50);
800                 uiSetRoundBox(UI_CNR_BOTTOM_LEFT);
801                 uiDrawBox(GL_POLYGON, rect.xmin - node_group_frame, rect.ymin, rect.xmin, rect.ymax, BASIS_RAD);
802         
803                 /* output column */
804                 UI_ThemeColorShadeAlpha(TH_BACK, 10, -50);
805                 uiSetRoundBox(UI_CNR_BOTTOM_RIGHT);
806                 uiDrawBox(GL_POLYGON, rect.xmax, rect.ymin, rect.xmax + node_group_frame, rect.ymax, BASIS_RAD);
807         
808                 /* input column separator */
809                 glColor4ub(200, 200, 200, 140);
810                 glBegin(GL_LINES);
811                 glVertex2f(rect.xmin, rect.ymin);
812                 glVertex2f(rect.xmin, rect.ymax);
813                 glEnd();
814         
815                 /* output column separator */
816                 glColor4ub(200, 200, 200, 140);
817                 glBegin(GL_LINES);
818                 glVertex2f(rect.xmax, rect.ymin);
819                 glVertex2f(rect.xmax, rect.ymax);
820                 glEnd();
821         
822                 /* group node outline */
823                 uiSetRoundBox(UI_CNR_ALL);
824                 glColor4ub(200, 200, 200, 140);
825                 glEnable(GL_LINE_SMOOTH);
826                 uiDrawBox(GL_LINE_LOOP,
827                           rect.xmin - node_group_frame, rect.ymin,
828                           rect.xmax + node_group_frame, rect.ymax + group_header, BASIS_RAD);
829                 glDisable(GL_LINE_SMOOTH);
830                 glDisable(GL_BLEND);
831                 
832                 /* backdrop title */
833                 UI_ThemeColor(TH_TEXT_HI);
834         
835                 layout = uiBlockLayout(gnode->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL,
836                                        (int)(rect.xmin + NODE_MARGIN_X), (int)(rect.ymax + (group_header - (2.5f * dpi_fac))),
837                                        min_ii((int)(BLI_rctf_size_x(&rect) - 18.0f), node_group_frame + 20), group_header, UI_GetStyle());
838                 RNA_pointer_create(&ntree->id, &RNA_Node, gnode, &ptr);
839                 uiTemplateIDBrowse(layout, (bContext *)C, &ptr, "node_tree", NULL, NULL, NULL);
840                 uiBlockLayoutResolve(gnode->block, NULL, NULL);
841         
842                 /* draw the internal tree nodes and links */
843                 node_draw_nodetree(C, ar, snode, ngroup);
844         
845                 /* group sockets */
846                 gsock = ngroup->inputs.first;
847                 sock = gnode->inputs.first;
848                 index = 0;
849                 while (gsock || sock) {
850                         while (sock && !sock->groupsock) {
851                                 draw_group_socket(C, snode, ntree, gnode, sock, NULL, index, SOCK_IN);
852                                 sock = sock->next;
853                         }
854                         while (gsock && (!sock || sock->groupsock != gsock)) {
855                                 draw_group_socket(C, snode, ntree, gnode, NULL, gsock, index, SOCK_IN);
856                                 gsock = gsock->next;
857                                 index++;
858                         }
859                         while (sock && gsock && sock->groupsock == gsock) {
860                                 draw_group_socket(C, snode, ntree, gnode, sock, gsock, index, SOCK_IN);
861                                 sock = sock->next;
862                                 gsock = gsock->next;
863                                 index++;
864                         }
865                 }
866                 gsock = ngroup->outputs.first;
867                 sock = gnode->outputs.first;
868                 index = 0;
869                 while (gsock || sock) {
870                         while (sock && !sock->groupsock) {
871                                 draw_group_socket(C, snode, ntree, gnode, sock, NULL, index, SOCK_OUT);
872                                 sock = sock->next;
873                         }
874                         while (gsock && (!sock || sock->groupsock != gsock)) {
875                                 draw_group_socket(C, snode, ntree, gnode, NULL, gsock, index, SOCK_OUT);
876                                 gsock = gsock->next;
877                                 index++;
878                         }
879                         while (sock && gsock && sock->groupsock == gsock) {
880                                 draw_group_socket(C, snode, ntree, gnode, sock, gsock, index, SOCK_OUT);
881                                 sock = sock->next;
882                                 gsock = gsock->next;
883                                 index++;
884                         }
885                 }
886                 
887                 uiEndBlock(C, gnode->block);
888                 uiDrawBlock(C, gnode->block);
889                 gnode->block = NULL;
890         }
891 }
892
893 static void node_uifunc_group(uiLayout *layout, bContext *C, PointerRNA *ptr)
894 {
895         uiTemplateIDBrowse(layout, C, ptr, "node_tree", NULL, NULL, NULL);
896 }
897
898 static void node_common_buts_whileloop(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
899 {
900         uiItemR(layout, ptr, "max_iterations", 0, NULL, ICON_NONE);
901 }
902
903 /* XXX Does a bounding box update by iterating over all children.
904  * Not ideal to do this in every draw call, but doing as transform callback doesn't work,
905  * since the child node totr rects are not updated properly at that point.
906  */
907 static void node_update_frame(const bContext *UNUSED(C), bNodeTree *ntree, bNode *node)
908 {
909         const float margin = 30.0f;
910         NodeFrame *data = (NodeFrame *)node->storage;
911         int bbinit;
912         bNode *tnode;
913         rctf rect, noderect;
914         float xmax, ymax;
915         
916         /* init rect from current frame size */
917         nodeToView(node, node->offsetx, node->offsety, &rect.xmin, &rect.ymax);
918         nodeToView(node, node->offsetx + node->width, node->offsety - node->height, &rect.xmax, &rect.ymin);
919         
920         /* frame can be resized manually only if shrinking is disabled or no children are attached */
921         data->flag |= NODE_FRAME_RESIZEABLE;
922         /* for shrinking bbox, initialize the rect from first child node */
923         bbinit = (data->flag & NODE_FRAME_SHRINK);
924         /* fit bounding box to all children */
925         for (tnode = ntree->nodes.first; tnode; tnode = tnode->next) {
926                 if (tnode->parent != node)
927                         continue;
928                 
929                 /* add margin to node rect */
930                 noderect = tnode->totr;
931                 noderect.xmin -= margin;
932                 noderect.xmax += margin;
933                 noderect.ymin -= margin;
934                 noderect.ymax += margin;
935                 
936                 /* first child initializes frame */
937                 if (bbinit) {
938                         bbinit = 0;
939                         rect = noderect;
940                         data->flag &= ~NODE_FRAME_RESIZEABLE;
941                 }
942                 else
943                         BLI_rctf_union(&rect, &noderect);
944         }
945         
946         /* now adjust the frame size from view-space bounding box */
947         nodeFromView(node, rect.xmin, rect.ymax, &node->offsetx, &node->offsety);
948         nodeFromView(node, rect.xmax, rect.ymin, &xmax, &ymax);
949         node->width = xmax - node->offsetx;
950         node->height = -ymax + node->offsety;
951         
952         node->totr = rect;
953 }
954
955 static void node_draw_frame_label(bNode *node, const float aspect)
956 {
957         /* XXX font id is crap design */
958         const int fontid = UI_GetStyle()->widgetlabel.uifont_id;
959         NodeFrame *data = (NodeFrame *)node->storage;
960         rctf *rct = &node->totr;
961         int color_id = node_get_colorid(node);
962         const char *label = nodeLabel(node);
963         /* XXX a bit hacky, should use separate align values for x and y */
964         float width, ascender;
965         float x, y;
966         const int font_size = data->label_size / aspect;
967
968         BLF_enable(fontid, BLF_ASPECT);
969         BLF_aspect(fontid, aspect, aspect, 1.0f);
970         BLF_size(fontid, MIN2(24, font_size), U.dpi); /* clamp otherwise it can suck up a LOT of memory */
971         
972         /* title color */
973         UI_ThemeColorBlendShade(TH_TEXT, color_id, 0.8f, 10);
974
975         width = BLF_width(fontid, label);
976         ascender = BLF_ascender(fontid);
977         
978         /* 'x' doesn't need aspect correction */
979         x = BLI_rctf_cent_x(rct) - (0.5f * width);
980         y = rct->ymax - (((NODE_DY / 4) / aspect) + (ascender * aspect));
981
982         BLF_position(fontid, x, y, 0);
983         BLF_draw(fontid, label, BLF_DRAW_STR_DUMMY_MAX);
984
985         BLF_disable(fontid, BLF_ASPECT);
986 }
987
988 static void node_draw_frame(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *UNUSED(ntree), bNode *node)
989 {
990         rctf *rct = &node->totr;
991         int color_id = node_get_colorid(node);
992         unsigned char color[4];
993         float alpha;
994         
995         /* skip if out of view */
996         if (BLI_rctf_isect(&node->totr, &ar->v2d.cur, NULL) == FALSE) {
997                 uiEndBlock(C, node->block);
998                 node->block = NULL;
999                 return;
1000         }
1001
1002         UI_GetThemeColor4ubv(TH_NODE_FRAME, color);
1003         alpha = (float)(color[3]) / 255.0f;
1004         
1005         /* shadow */
1006         node_draw_shadow(snode, node, BASIS_RAD, alpha);
1007         
1008         /* body */
1009         if (node->flag & NODE_CUSTOM_COLOR)
1010                 glColor4f(node->color[0], node->color[1], node->color[2], alpha);
1011         else
1012                 UI_ThemeColor4(TH_NODE_FRAME);
1013         glEnable(GL_BLEND);
1014         uiSetRoundBox(UI_CNR_ALL);
1015         uiRoundBox(rct->xmin, rct->ymin, rct->xmax, rct->ymax, BASIS_RAD);
1016         glDisable(GL_BLEND);
1017
1018         /* outline active and selected emphasis */
1019         if (node->flag & SELECT) {
1020                 glEnable(GL_BLEND);
1021                 glEnable(GL_LINE_SMOOTH);
1022                 
1023                 if (node->flag & NODE_ACTIVE)
1024                         UI_ThemeColorShadeAlpha(TH_ACTIVE, 0, -40);
1025                 else
1026                         UI_ThemeColorShadeAlpha(TH_SELECT, 0, -40);
1027                 uiSetRoundBox(UI_CNR_ALL);
1028                 uiDrawBox(GL_LINE_LOOP,
1029                           rct->xmin, rct->ymin,
1030                           rct->xmax, rct->ymax, BASIS_RAD);
1031                 
1032                 glDisable(GL_LINE_SMOOTH);
1033                 glDisable(GL_BLEND);
1034         }
1035         
1036         /* label */
1037         node_draw_frame_label(node, snode->aspect);
1038         
1039         UI_ThemeClearColor(color_id);
1040                 
1041         uiEndBlock(C, node->block);
1042         uiDrawBlock(C, node->block);
1043         node->block = NULL;
1044 }
1045
1046 static int node_resize_area_frame(bNode *node, int x, int y)
1047 {
1048         const float size = 10.0f;
1049         NodeFrame *data = (NodeFrame *)node->storage;
1050         rctf totr = node->totr;
1051         int dir = 0;
1052         
1053         /* shrinking frame size is determined by child nodes */
1054         if (!(data->flag & NODE_FRAME_RESIZEABLE))
1055                 return 0;
1056         
1057         if (x >= totr.xmax - size && x < totr.xmax && y >= totr.ymin && y < totr.ymax)
1058                 dir |= NODE_RESIZE_RIGHT;
1059         if (x >= totr.xmin && x < totr.xmin + size && y >= totr.ymin && y < totr.ymax)
1060                 dir |= NODE_RESIZE_LEFT;
1061         if (x >= totr.xmin && x < totr.xmax && y >= totr.ymax - size && y < totr.ymax)
1062                 dir |= NODE_RESIZE_TOP;
1063         if (x >= totr.xmin && x < totr.xmax && y >= totr.ymin && y < totr.ymin + size)
1064                 dir |= NODE_RESIZE_BOTTOM;
1065         
1066         return dir;
1067 }
1068
1069 static void node_buts_frame_details(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1070 {
1071         uiItemR(layout, ptr, "label_size", 0, IFACE_("Label Size"), ICON_NONE);
1072         uiItemR(layout, ptr, "shrink", 0, IFACE_("Shrink"), ICON_NONE);
1073 }
1074
1075
1076 #define NODE_REROUTE_SIZE   8.0f
1077
1078 static void node_update_reroute(const bContext *UNUSED(C), bNodeTree *UNUSED(ntree), bNode *node)
1079 {
1080         bNodeSocket *nsock;
1081         float locx, locy;
1082         float size = NODE_REROUTE_SIZE;
1083         
1084         /* get "global" coords */
1085         nodeToView(node, 0.0f, 0.0f, &locx, &locy);
1086         
1087         /* reroute node has exactly one input and one output, both in the same place */
1088         nsock = node->outputs.first;
1089         nsock->locx = locx;
1090         nsock->locy = locy;
1091
1092         nsock = node->inputs.first;
1093         nsock->locx = locx;
1094         nsock->locy = locy;
1095
1096         node->width = size * 2;
1097         node->totr.xmin = locx - size;
1098         node->totr.xmax = locx + size;
1099         node->totr.ymax = locy + size;
1100         node->totr.ymin = locy - size;
1101 }
1102
1103 static void node_draw_reroute(const bContext *C, ARegion *ar, SpaceNode *UNUSED(snode),  bNodeTree *ntree, bNode *node)
1104 {
1105         bNodeSocket *sock;
1106 #if 0   /* UNUSED */
1107         rctf *rct = &node->totr;
1108         float size = NODE_REROUTE_SIZE;
1109 #endif
1110         float socket_size = NODE_SOCKSIZE;
1111
1112         /* skip if out of view */
1113         if (node->totr.xmax < ar->v2d.cur.xmin || node->totr.xmin > ar->v2d.cur.xmax ||
1114             node->totr.ymax < ar->v2d.cur.ymin || node->totr.ymin > ar->v2d.cur.ymax) {
1115
1116                 uiEndBlock(C, node->block);
1117                 node->block = NULL;
1118                 return;
1119         }
1120
1121         /* XXX only kept for debugging
1122          * selection state is indicated by socket outline below!
1123          */
1124 #if 0
1125         /* body */
1126         uiSetRoundBox(15);
1127         UI_ThemeColor4(TH_NODE);
1128         glEnable(GL_BLEND);
1129         uiRoundBox(rct->xmin, rct->ymin, rct->xmax, rct->ymax, size);
1130         glDisable(GL_BLEND);
1131
1132         /* outline active and selected emphasis */
1133         if (node->flag & SELECT) {
1134                 glEnable(GL_BLEND);
1135                 glEnable(GL_LINE_SMOOTH);
1136                 /* using different shades of TH_TEXT_HI for the empasis, like triangle */
1137                 if (node->flag & NODE_ACTIVE)
1138                         UI_ThemeColorShadeAlpha(TH_TEXT_HI, 0, -40);
1139                 else
1140                         UI_ThemeColorShadeAlpha(TH_TEXT_HI, -20, -120);
1141                 uiDrawBox(GL_LINE_LOOP, rct->xmin, rct->ymin, rct->xmax, rct->ymax, size);
1142
1143                 glDisable(GL_LINE_SMOOTH);
1144                 glDisable(GL_BLEND);
1145         }
1146 #endif
1147
1148         /* only draw input socket. as they all are placed on the same position.
1149          * highlight also if node itself is selected, since we don't display the node body separately!
1150          */
1151         for (sock = node->inputs.first; sock; sock = sock->next) {
1152                 node_socket_circle_draw(ntree, sock, socket_size, (sock->flag & SELECT) || (node->flag & SELECT));
1153         }
1154
1155         uiEndBlock(C, node->block);
1156         uiDrawBlock(C, node->block);
1157         node->block = NULL;
1158 }
1159
1160 /* Special tweak area for reroute node.
1161  * Since this node is quite small, we use a larger tweak area for grabbing than for selection.
1162  */
1163 static int node_tweak_area_reroute(bNode *node, int x, int y)
1164 {
1165         /* square of tweak radius */
1166         static const float tweak_radius_sq = 576;  /* 24 * 24 */
1167         
1168         bNodeSocket *sock = node->inputs.first;
1169         float dx = sock->locx - x;
1170         float dy = sock->locy - y;
1171         return (dx * dx + dy * dy <= tweak_radius_sq);
1172 }
1173
1174 static void node_common_set_butfunc(bNodeType *ntype)
1175 {
1176         switch (ntype->type) {
1177                 case NODE_GROUP:
1178                         ntype->uifunc = node_uifunc_group;
1179                         ntype->drawfunc = node_draw_group;
1180                         ntype->drawupdatefunc = node_update_group;
1181                         break;
1182                 case NODE_FORLOOP:
1183 //                      ntype->uifunc= node_common_buts_group;
1184                         ntype->drawfunc = node_draw_group;
1185                         ntype->drawupdatefunc = node_update_group;
1186                         break;
1187                 case NODE_WHILELOOP:
1188                         ntype->uifunc = node_common_buts_whileloop;
1189                         ntype->drawfunc = node_draw_group;
1190                         ntype->drawupdatefunc = node_update_group;
1191                         break;
1192                 case NODE_FRAME:
1193                         ntype->drawfunc = node_draw_frame;
1194                         ntype->drawupdatefunc = node_update_frame;
1195                         ntype->uifuncbut = node_buts_frame_details;
1196                         ntype->resize_area_func = node_resize_area_frame;
1197                         break;
1198                 case NODE_REROUTE:
1199                         ntype->drawfunc = node_draw_reroute;
1200                         ntype->drawupdatefunc = node_update_reroute;
1201                         ntype->tweak_area_func = node_tweak_area_reroute;
1202                         break;
1203         }
1204 }
1205
1206 /* ****************** BUTTON CALLBACKS FOR SHADER NODES ***************** */
1207
1208 static void node_buts_image_user(uiLayout *layout, bContext *C, PointerRNA *ptr,
1209                                  PointerRNA *imaptr, PointerRNA *iuserptr)
1210 {
1211         uiLayout *col;
1212         int source;
1213
1214         if (!imaptr->data)
1215                 return;
1216
1217         col = uiLayoutColumn(layout, FALSE);
1218         
1219         uiItemR(col, imaptr, "source", 0, "", ICON_NONE);
1220         
1221         source = RNA_enum_get(imaptr, "source");
1222
1223         if (source == IMA_SRC_SEQUENCE) {
1224                 /* don't use iuser->framenr directly because it may not be updated if auto-refresh is off */
1225                 Scene *scene = CTX_data_scene(C);
1226                 ImageUser *iuser = iuserptr->data;
1227                 char numstr[32];
1228                 const int framenr = BKE_image_user_frame_get(iuser, CFRA, 0, NULL);
1229                 BLI_snprintf(numstr, sizeof(numstr), IFACE_("Frame: %d"), framenr);
1230                 uiItemL(layout, numstr, ICON_NONE);
1231         }
1232
1233         if (ELEM(source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE)) {
1234                 col = uiLayoutColumn(layout, TRUE);
1235                 uiItemR(col, ptr, "frame_duration", 0, NULL, ICON_NONE);
1236                 uiItemR(col, ptr, "frame_start", 0, NULL, ICON_NONE);
1237                 uiItemR(col, ptr, "frame_offset", 0, NULL, ICON_NONE);
1238                 uiItemR(col, ptr, "use_cyclic", 0, NULL, ICON_NONE);
1239                 uiItemR(col, ptr, "use_auto_refresh", UI_ITEM_R_ICON_ONLY, NULL, ICON_NONE);
1240         }
1241
1242         col = uiLayoutColumn(layout, FALSE);
1243
1244         if (RNA_enum_get(imaptr, "type") == IMA_TYPE_MULTILAYER)
1245                 uiItemR(col, ptr, "layer", 0, NULL, ICON_NONE);
1246 }
1247
1248 static void node_shader_buts_material(uiLayout *layout, bContext *C, PointerRNA *ptr)
1249 {
1250         bNode *node = ptr->data;
1251         uiLayout *col;
1252         
1253         uiTemplateID(layout, C, ptr, "material", "MATERIAL_OT_new", NULL, NULL);
1254         
1255         if (!node->id) return;
1256         
1257         col = uiLayoutColumn(layout, FALSE);
1258         uiItemR(col, ptr, "use_diffuse", 0, NULL, ICON_NONE);
1259         uiItemR(col, ptr, "use_specular", 0, NULL, ICON_NONE);
1260         uiItemR(col, ptr, "invert_normal", 0, NULL, ICON_NONE);
1261 }
1262
1263 static void node_shader_buts_mapping(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1264 {
1265         uiLayout *row;
1266         
1267         uiItemL(layout, IFACE_("Location:"), ICON_NONE);
1268         row = uiLayoutRow(layout, TRUE);
1269         uiItemR(row, ptr, "translation", 0, "", ICON_NONE);
1270         
1271         uiItemL(layout, IFACE_("Rotation:"), ICON_NONE);
1272         row = uiLayoutRow(layout, TRUE);
1273         uiItemR(row, ptr, "rotation", 0, "", ICON_NONE);
1274         
1275         uiItemL(layout, IFACE_("Scale:"), ICON_NONE);
1276         row = uiLayoutRow(layout, TRUE);
1277         uiItemR(row, ptr, "scale", 0, "", ICON_NONE);
1278         
1279         row = uiLayoutRow(layout, TRUE);
1280         uiItemR(row, ptr, "use_min", 0, "Min", ICON_NONE);
1281         uiItemR(row, ptr, "min", 0, "", ICON_NONE);
1282         
1283         row = uiLayoutRow(layout, TRUE);
1284         uiItemR(row, ptr, "use_max", 0, "Max", ICON_NONE);
1285         uiItemR(row, ptr, "max", 0, "", ICON_NONE);
1286 }
1287
1288 static void node_shader_buts_vect_math(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1289
1290         uiItemR(layout, ptr, "operation", 0, "", ICON_NONE);
1291 }
1292
1293 static void node_shader_buts_geometry(uiLayout *layout, bContext *C, PointerRNA *ptr)
1294 {
1295         PointerRNA obptr = CTX_data_pointer_get(C, "active_object");
1296         uiLayout *col;
1297
1298         col = uiLayoutColumn(layout, FALSE);
1299
1300         if (obptr.data && RNA_enum_get(&obptr, "type") == OB_MESH) {
1301                 PointerRNA dataptr = RNA_pointer_get(&obptr, "data");
1302
1303                 uiItemPointerR(col, ptr, "uv_layer", &dataptr, "uv_textures", "", ICON_NONE);
1304                 uiItemPointerR(col, ptr, "color_layer", &dataptr, "vertex_colors", "", ICON_NONE);
1305         }
1306         else {
1307                 uiItemR(col, ptr, "uv_layer", 0, IFACE_("UV"), ICON_NONE);
1308                 uiItemR(col, ptr, "color_layer", 0, IFACE_("VCol"), ICON_NONE);
1309         }
1310 }
1311
1312 static void node_shader_buts_attribute(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1313 {
1314         uiItemR(layout, ptr, "attribute_name", 0, IFACE_("Name"), ICON_NONE);
1315 }
1316
1317 static void node_shader_buts_tex_image(uiLayout *layout, bContext *C, PointerRNA *ptr)
1318 {
1319         PointerRNA imaptr = RNA_pointer_get(ptr, "image");
1320         PointerRNA iuserptr = RNA_pointer_get(ptr, "image_user");
1321
1322         uiTemplateID(layout, C, ptr, "image", NULL, "IMAGE_OT_open", NULL);
1323         uiItemR(layout, ptr, "color_space", 0, "", ICON_NONE);
1324         uiItemR(layout, ptr, "projection", 0, "", ICON_NONE);
1325
1326         if (RNA_enum_get(ptr, "projection") == SHD_PROJ_BOX) {
1327                 uiItemR(layout, ptr, "projection_blend", 0, "Blend", ICON_NONE);
1328         }
1329
1330         /* note: image user properties used directly here, unlike compositor image node,
1331          * which redefines them in the node struct RNA to get proper updates.
1332          */
1333         node_buts_image_user(layout, C, &iuserptr, &imaptr, &iuserptr);
1334 }
1335
1336 static void node_shader_buts_tex_environment(uiLayout *layout, bContext *C, PointerRNA *ptr)
1337 {
1338         PointerRNA imaptr = RNA_pointer_get(ptr, "image");
1339         PointerRNA iuserptr = RNA_pointer_get(ptr, "image_user");
1340
1341         uiTemplateID(layout, C, ptr, "image", NULL, "IMAGE_OT_open", NULL);
1342         uiItemR(layout, ptr, "color_space", 0, "", ICON_NONE);
1343         uiItemR(layout, ptr, "projection", 0, "", ICON_NONE);
1344
1345         node_buts_image_user(layout, C, ptr, &imaptr, &iuserptr);
1346 }
1347
1348 static void node_shader_buts_tex_sky(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1349 {
1350         uiItemR(layout, ptr, "sun_direction", 0, "", ICON_NONE);
1351         uiItemR(layout, ptr, "turbidity", 0, NULL, ICON_NONE);
1352 }
1353
1354 static void node_shader_buts_tex_gradient(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1355 {
1356         uiItemR(layout, ptr, "gradient_type", 0, "", ICON_NONE);
1357 }
1358
1359 static void node_shader_buts_tex_magic(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1360 {
1361         uiItemR(layout, ptr, "turbulence_depth", 0, NULL, ICON_NONE);
1362 }
1363
1364 static void node_shader_buts_tex_brick(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1365 {
1366         uiLayout *col;
1367         
1368         col = uiLayoutColumn(layout, TRUE);
1369         uiItemR(col, ptr, "offset", 0, IFACE_("Offset"), ICON_NONE);
1370         uiItemR(col, ptr, "offset_frequency", 0, IFACE_("Frequency"), ICON_NONE);
1371         
1372         col = uiLayoutColumn(layout, TRUE);
1373         uiItemR(col, ptr, "squash", 0, IFACE_("Squash"), ICON_NONE);
1374         uiItemR(col, ptr, "squash_frequency", 0, IFACE_("Frequency"), ICON_NONE);
1375 }
1376
1377 static void node_shader_buts_tex_wave(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1378 {
1379         uiItemR(layout, ptr, "wave_type", 0, "", ICON_NONE);
1380 }
1381
1382 static void node_shader_buts_tex_musgrave(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1383 {
1384         uiItemR(layout, ptr, "musgrave_type", 0, "", ICON_NONE);
1385 }
1386
1387 static void node_shader_buts_tex_voronoi(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1388 {
1389         uiItemR(layout, ptr, "coloring", 0, "", ICON_NONE);
1390 }
1391
1392 static void node_shader_buts_tex_coord(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1393 {
1394         uiItemR(layout, ptr, "from_dupli", 0, NULL, 0);
1395 }
1396
1397 static void node_shader_buts_glossy(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1398 {
1399         uiItemR(layout, ptr, "distribution", 0, "", ICON_NONE);
1400 }
1401
1402 /* only once called */
1403 static void node_shader_set_butfunc(bNodeType *ntype)
1404 {
1405         switch (ntype->type) {
1406                 /* case NODE_GROUP:      note, typeinfo for group is generated... see "XXX ugly hack" */
1407
1408                 case SH_NODE_MATERIAL:
1409                 case SH_NODE_MATERIAL_EXT:
1410                         ntype->uifunc = node_shader_buts_material;
1411                         break;
1412                 case SH_NODE_TEXTURE:
1413                         ntype->uifunc = node_buts_texture;
1414                         break;
1415                 case SH_NODE_NORMAL:
1416                         ntype->uifunc = node_buts_normal;
1417                         break;
1418                 case SH_NODE_CURVE_VEC:
1419                         ntype->uifunc = node_buts_curvevec;
1420                         break;
1421                 case SH_NODE_CURVE_RGB:
1422                         ntype->uifunc = node_buts_curvecol;
1423                         break;
1424                 case SH_NODE_MAPPING:
1425                         ntype->uifunc = node_shader_buts_mapping;
1426                         break;
1427                 case SH_NODE_VALUE:
1428                         ntype->uifunc = node_buts_value;
1429                         break;
1430                 case SH_NODE_RGB:
1431                         ntype->uifunc = node_buts_rgb;
1432                         break;
1433                 case SH_NODE_MIX_RGB:
1434                         ntype->uifunc = node_buts_mix_rgb;
1435                         break;
1436                 case SH_NODE_VALTORGB:
1437                         ntype->uifunc = node_buts_colorramp;
1438                         break;
1439                 case SH_NODE_MATH: 
1440                         ntype->uifunc = node_buts_math;
1441                         break; 
1442                 case SH_NODE_VECT_MATH: 
1443                         ntype->uifunc = node_shader_buts_vect_math;
1444                         break; 
1445                 case SH_NODE_GEOMETRY:
1446                         ntype->uifunc = node_shader_buts_geometry;
1447                         break;
1448                 case SH_NODE_ATTRIBUTE:
1449                         ntype->uifunc = node_shader_buts_attribute;
1450                         break;
1451                 case SH_NODE_TEX_SKY:
1452                         ntype->uifunc = node_shader_buts_tex_sky;
1453                         break;
1454                 case SH_NODE_TEX_IMAGE:
1455                         ntype->uifunc = node_shader_buts_tex_image;
1456                         break;
1457                 case SH_NODE_TEX_ENVIRONMENT:
1458                         ntype->uifunc = node_shader_buts_tex_environment;
1459                         break;
1460                 case SH_NODE_TEX_GRADIENT:
1461                         ntype->uifunc = node_shader_buts_tex_gradient;
1462                         break;
1463                 case SH_NODE_TEX_MAGIC:
1464                         ntype->uifunc = node_shader_buts_tex_magic;
1465                         break;
1466                 case SH_NODE_TEX_BRICK:
1467                         ntype->uifunc = node_shader_buts_tex_brick;
1468                         break;
1469                 case SH_NODE_TEX_WAVE:
1470                         ntype->uifunc = node_shader_buts_tex_wave;
1471                         break;
1472                 case SH_NODE_TEX_MUSGRAVE:
1473                         ntype->uifunc = node_shader_buts_tex_musgrave;
1474                         break;
1475                 case SH_NODE_TEX_VORONOI:
1476                         ntype->uifunc = node_shader_buts_tex_voronoi;
1477                         break;
1478                 case SH_NODE_TEX_COORD:
1479                         ntype->uifunc = node_shader_buts_tex_coord;
1480                         break;
1481                 case SH_NODE_BSDF_GLOSSY:
1482                 case SH_NODE_BSDF_GLASS:
1483                         ntype->uifunc = node_shader_buts_glossy;
1484                         break;
1485         }
1486 }
1487
1488 /* ****************** BUTTON CALLBACKS FOR COMPOSITE NODES ***************** */
1489
1490 static void node_composit_buts_image(uiLayout *layout, bContext *C, PointerRNA *ptr)
1491 {
1492         bNode *node = ptr->data;
1493         PointerRNA imaptr, iuserptr;
1494         
1495         uiTemplateID(layout, C, ptr, "image", NULL, "IMAGE_OT_open", NULL);
1496         
1497         if (!node->id) return;
1498         
1499         imaptr = RNA_pointer_get(ptr, "image");
1500         RNA_pointer_create((ID *)ptr->id.data, &RNA_ImageUser, node->storage, &iuserptr);
1501         
1502         node_buts_image_user(layout, C, ptr, &imaptr, &iuserptr);
1503 }
1504
1505 static void node_composit_buts_image_details(uiLayout *layout, bContext *C, PointerRNA *ptr)
1506 {
1507         bNode *node = ptr->data;
1508         PointerRNA imaptr;
1509
1510         node_composit_buts_image(layout, C, ptr);
1511
1512         if (!node->id)
1513                 return;
1514
1515         imaptr = RNA_pointer_get(ptr, "image");
1516
1517         uiTemplateColorspaceSettings(layout, &imaptr, "colorspace_settings");
1518 }
1519
1520 static void node_composit_buts_renderlayers(uiLayout *layout, bContext *C, PointerRNA *ptr)
1521 {
1522         bNode *node = ptr->data;
1523         uiLayout *col, *row;
1524         PointerRNA op_ptr;
1525         PointerRNA scn_ptr;
1526         PropertyRNA *prop;
1527         const char *layer_name;
1528         char scene_name[MAX_ID_NAME - 2];
1529         wmOperatorType *ot = WM_operatortype_find("RENDER_OT_render", 1);
1530
1531         BLI_assert(ot != 0);
1532
1533         uiTemplateID(layout, C, ptr, "scene", NULL, NULL, NULL);
1534         
1535         if (!node->id) return;
1536
1537         col = uiLayoutColumn(layout, FALSE);
1538         row = uiLayoutRow(col, FALSE);
1539         uiItemR(row, ptr, "layer", 0, "", ICON_NONE);
1540         
1541         prop = RNA_struct_find_property(ptr, "layer");
1542         if (!(RNA_property_enum_identifier(C, ptr, prop, RNA_property_enum_get(ptr, prop), &layer_name)))
1543                 return;
1544         
1545         scn_ptr = RNA_pointer_get(ptr, "scene");
1546         RNA_string_get(&scn_ptr, "name", scene_name);
1547         
1548         WM_operator_properties_create_ptr(&op_ptr, ot);
1549         RNA_string_set(&op_ptr, "layer", layer_name);
1550         RNA_string_set(&op_ptr, "scene", scene_name);
1551         uiItemFullO_ptr(row, ot, "", ICON_RENDER_STILL, op_ptr.data, WM_OP_INVOKE_DEFAULT, 0);
1552
1553 }
1554
1555
1556 static void node_composit_buts_blur(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1557 {
1558         uiLayout *col, *row;
1559         int reference;
1560         int filter;
1561         
1562         col = uiLayoutColumn(layout, FALSE);
1563         filter = RNA_enum_get(ptr, "filter_type");
1564         reference = RNA_boolean_get(ptr, "use_variable_size");
1565
1566         uiItemR(col, ptr, "filter_type", 0, "", ICON_NONE);
1567         if (filter != R_FILTER_FAST_GAUSS) {
1568                 uiItemR(col, ptr, "use_variable_size", 0, NULL, ICON_NONE);
1569                 if (!reference) {
1570                         uiItemR(col, ptr, "use_bokeh", 0, NULL, ICON_NONE);
1571                 }
1572                 uiItemR(col, ptr, "use_gamma_correction", 0, NULL, ICON_NONE);
1573         }
1574         
1575         uiItemR(col, ptr, "use_relative", 0, NULL, ICON_NONE);
1576         
1577         if (RNA_boolean_get(ptr, "use_relative")) {
1578                 uiItemL(col, IFACE_("Aspect Correction"), ICON_NONE);
1579                 row = uiLayoutRow(layout, TRUE);
1580                 uiItemR(row, ptr, "aspect_correction", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
1581                 
1582                 col = uiLayoutColumn(layout, TRUE);
1583                 uiItemR(col, ptr, "factor_x", 0, IFACE_("X"), ICON_NONE);
1584                 uiItemR(col, ptr, "factor_y", 0, IFACE_("Y"), ICON_NONE);
1585         }
1586         else {
1587                 col = uiLayoutColumn(layout, TRUE);
1588                 uiItemR(col, ptr, "size_x", 0, IFACE_("X"), ICON_NONE);
1589                 uiItemR(col, ptr, "size_y", 0, IFACE_("Y"), ICON_NONE);
1590         }
1591 }
1592
1593 static void node_composit_buts_dblur(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1594 {
1595         uiLayout *col;
1596         
1597         uiItemR(layout, ptr, "iterations", 0, NULL, ICON_NONE);
1598         uiItemR(layout, ptr, "use_wrap", 0, NULL, ICON_NONE);
1599         
1600         col = uiLayoutColumn(layout, TRUE);
1601         uiItemL(col, IFACE_("Center:"), ICON_NONE);
1602         uiItemR(col, ptr, "center_x", 0, IFACE_("X"), ICON_NONE);
1603         uiItemR(col, ptr, "center_y", 0, IFACE_("Y"), ICON_NONE);
1604         
1605         uiItemS(layout);
1606         
1607         col = uiLayoutColumn(layout, TRUE);
1608         uiItemR(col, ptr, "distance", 0, NULL, ICON_NONE);
1609         uiItemR(col, ptr, "angle", 0, NULL, ICON_NONE);
1610         
1611         uiItemS(layout);
1612         
1613         uiItemR(layout, ptr, "spin", 0, NULL, ICON_NONE);
1614         uiItemR(layout, ptr, "zoom", 0, NULL, ICON_NONE);
1615 }
1616
1617 static void node_composit_buts_bilateralblur(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1618 {       
1619         uiLayout *col;
1620         
1621         col = uiLayoutColumn(layout, TRUE);
1622         uiItemR(col, ptr, "iterations", 0, NULL, ICON_NONE);
1623         uiItemR(col, ptr, "sigma_color", 0, NULL, ICON_NONE);
1624         uiItemR(col, ptr, "sigma_space", 0, NULL, ICON_NONE);
1625 }
1626
1627 static void node_composit_buts_defocus(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1628 {
1629         uiLayout *sub, *col;
1630         
1631         col = uiLayoutColumn(layout, FALSE);
1632         uiItemL(col, IFACE_("Bokeh Type:"), ICON_NONE);
1633         uiItemR(col, ptr, "bokeh", 0, "", ICON_NONE);
1634         uiItemR(col, ptr, "angle", 0, NULL, ICON_NONE);
1635
1636         uiItemR(layout, ptr, "use_gamma_correction", 0, NULL, ICON_NONE);
1637
1638         col = uiLayoutColumn(layout, FALSE);
1639         uiLayoutSetActive(col, RNA_boolean_get(ptr, "use_zbuffer") == TRUE);
1640         uiItemR(col, ptr, "f_stop", 0, NULL, ICON_NONE);
1641
1642         uiItemR(layout, ptr, "blur_max", 0, NULL, ICON_NONE);
1643         uiItemR(layout, ptr, "threshold", 0, NULL, ICON_NONE);
1644
1645         col = uiLayoutColumn(layout, FALSE);
1646         uiItemR(col, ptr, "use_preview", 0, NULL, ICON_NONE);
1647         
1648         col = uiLayoutColumn(layout, FALSE);
1649         uiItemR(col, ptr, "use_zbuffer", 0, NULL, ICON_NONE);
1650         sub = uiLayoutColumn(col, FALSE);
1651         uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_zbuffer") == FALSE);
1652         uiItemR(sub, ptr, "z_scale", 0, NULL, ICON_NONE);
1653 }
1654
1655 /* qdn: glare node */
1656 static void node_composit_buts_glare(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1657 {       
1658         uiItemR(layout, ptr, "glare_type", 0, "", ICON_NONE);
1659         uiItemR(layout, ptr, "quality", 0, "", ICON_NONE);
1660
1661         if (RNA_enum_get(ptr, "glare_type") != 1) {
1662                 uiItemR(layout, ptr, "iterations", 0, NULL, ICON_NONE);
1663         
1664                 if (RNA_enum_get(ptr, "glare_type") != 0)
1665                         uiItemR(layout, ptr, "color_modulation", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
1666         }
1667         
1668         uiItemR(layout, ptr, "mix", 0, NULL, ICON_NONE);
1669         uiItemR(layout, ptr, "threshold", 0, NULL, ICON_NONE);
1670
1671         if (RNA_enum_get(ptr, "glare_type") == 2) {
1672                 uiItemR(layout, ptr, "streaks", 0, NULL, ICON_NONE);
1673                 uiItemR(layout, ptr, "angle_offset", 0, NULL, ICON_NONE);
1674         }
1675         if (RNA_enum_get(ptr, "glare_type") == 0 || RNA_enum_get(ptr, "glare_type") == 2) {
1676                 uiItemR(layout, ptr, "fade", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
1677                 
1678                 if (RNA_enum_get(ptr, "glare_type") == 0)
1679                         uiItemR(layout, ptr, "use_rotate_45", 0, NULL, ICON_NONE);
1680         }
1681         if (RNA_enum_get(ptr, "glare_type") == 1) {
1682                 uiItemR(layout, ptr, "size", 0, NULL, ICON_NONE);
1683         }
1684 }
1685
1686 static void node_composit_buts_tonemap(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1687 {       
1688         uiLayout *col;
1689
1690         col = uiLayoutColumn(layout, FALSE);
1691         uiItemR(col, ptr, "tonemap_type", 0, "", ICON_NONE);
1692         if (RNA_enum_get(ptr, "tonemap_type") == 0) {
1693                 uiItemR(col, ptr, "key", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
1694                 uiItemR(col, ptr, "offset", 0, NULL, ICON_NONE);
1695                 uiItemR(col, ptr, "gamma", 0, NULL, ICON_NONE);
1696         }
1697         else {
1698                 uiItemR(col, ptr, "intensity", 0, NULL, ICON_NONE);
1699                 uiItemR(col, ptr, "contrast", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
1700                 uiItemR(col, ptr, "adaptation", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
1701                 uiItemR(col, ptr, "correction", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
1702         }
1703 }
1704
1705 static void node_composit_buts_lensdist(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1706 {
1707         uiLayout *col;
1708
1709         col = uiLayoutColumn(layout, FALSE);
1710         uiItemR(col, ptr, "use_projector", 0, NULL, ICON_NONE);
1711
1712         col = uiLayoutColumn(col, FALSE);
1713         uiLayoutSetActive(col, RNA_boolean_get(ptr, "use_projector") == FALSE);
1714         uiItemR(col, ptr, "use_jitter", 0, NULL, ICON_NONE);
1715         uiItemR(col, ptr, "use_fit", 0, NULL, ICON_NONE);
1716 }
1717
1718 static void node_composit_buts_vecblur(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1719 {
1720         uiLayout *col;
1721         
1722         col = uiLayoutColumn(layout, FALSE);
1723         uiItemR(col, ptr, "samples", 0, NULL, ICON_NONE);
1724         uiItemR(col, ptr, "factor", 0, IFACE_("Blur"), ICON_NONE);
1725         
1726         col = uiLayoutColumn(layout, TRUE);
1727         uiItemL(col, IFACE_("Speed:"), ICON_NONE);
1728         uiItemR(col, ptr, "speed_min", 0, IFACE_("Min"), ICON_NONE);
1729         uiItemR(col, ptr, "speed_max", 0, IFACE_("Max"), ICON_NONE);
1730
1731         uiItemR(layout, ptr, "use_curved", 0, NULL, ICON_NONE);
1732 }
1733
1734 static void node_composit_buts_filter(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1735 {
1736         uiItemR(layout, ptr, "filter_type", 0, "", ICON_NONE);
1737 }
1738
1739 static void node_composit_buts_flip(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1740 {
1741         uiItemR(layout, ptr, "axis", 0, "", ICON_NONE);
1742 }
1743
1744 static void node_composit_buts_crop(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1745 {
1746         uiLayout *col;
1747
1748         uiItemR(layout, ptr, "use_crop_size", 0, NULL, ICON_NONE);
1749         uiItemR(layout, ptr, "relative", 0, NULL, ICON_NONE);
1750
1751         col = uiLayoutColumn(layout, TRUE);
1752         if (RNA_boolean_get(ptr, "relative")) {
1753                 uiItemR(col, ptr, "rel_min_x", 0, IFACE_("Left"), ICON_NONE);
1754                 uiItemR(col, ptr, "rel_max_x", 0, IFACE_("Right"), ICON_NONE);
1755                 uiItemR(col, ptr, "rel_min_y", 0, IFACE_("Up"), ICON_NONE);
1756                 uiItemR(col, ptr, "rel_max_y", 0, IFACE_("Down"), ICON_NONE);
1757         }
1758         else {
1759                 uiItemR(col, ptr, "min_x", 0, IFACE_("Left"), ICON_NONE);
1760                 uiItemR(col, ptr, "max_x", 0, IFACE_("Right"), ICON_NONE);
1761                 uiItemR(col, ptr, "min_y", 0, IFACE_("Up"), ICON_NONE);
1762                 uiItemR(col, ptr, "max_y", 0, IFACE_("Down"), ICON_NONE);
1763         }
1764 }
1765
1766 static void node_composit_buts_splitviewer(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1767 {
1768         uiLayout *row, *col;
1769         
1770         col = uiLayoutColumn(layout, FALSE);
1771         row = uiLayoutRow(col, FALSE);
1772         uiItemR(row, ptr, "axis", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
1773         uiItemR(col, ptr, "factor", 0, NULL, ICON_NONE);
1774 }
1775
1776 static void node_composit_buts_double_edge_mask(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1777 {
1778         uiLayout *col;
1779
1780         col = uiLayoutColumn(layout, FALSE);
1781
1782         uiItemL(col, IFACE_("Inner Edge:"), ICON_NONE);
1783         uiItemR(col, ptr, "inner_mode", 0, "", ICON_NONE);
1784         uiItemL(col, IFACE_("Buffer Edge:"), ICON_NONE);
1785         uiItemR(col, ptr, "edge_mode", 0, "", ICON_NONE);
1786 }
1787
1788 static void node_composit_buts_map_value(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1789 {
1790         uiLayout *sub, *col;
1791         
1792         col = uiLayoutColumn(layout, TRUE);
1793         uiItemR(col, ptr, "offset", 0, NULL, ICON_NONE);
1794         uiItemR(col, ptr, "size", 0, NULL, ICON_NONE);
1795         
1796         col = uiLayoutColumn(layout, TRUE);
1797         uiItemR(col, ptr, "use_min", 0, NULL, ICON_NONE);
1798         sub = uiLayoutColumn(col, FALSE);
1799         uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_min"));
1800         uiItemR(sub, ptr, "min", 0, "", ICON_NONE);
1801         
1802         col = uiLayoutColumn(layout, TRUE);
1803         uiItemR(col, ptr, "use_max", 0, NULL, ICON_NONE);
1804         sub = uiLayoutColumn(col, FALSE);
1805         uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_max"));
1806         uiItemR(sub, ptr, "max", 0, "", ICON_NONE);
1807 }
1808
1809 static void node_composit_buts_alphaover(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1810 {       
1811         uiLayout *col;
1812         
1813         col = uiLayoutColumn(layout, TRUE);
1814         uiItemR(col, ptr, "use_premultiply", 0, NULL, ICON_NONE);
1815         uiItemR(col, ptr, "premul", 0, NULL, ICON_NONE);
1816 }
1817
1818 static void node_composit_buts_zcombine(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1819 {       
1820         uiLayout *col;
1821         
1822         col = uiLayoutColumn(layout, TRUE);
1823         uiItemR(col, ptr, "use_alpha", 0, NULL, ICON_NONE);
1824 }
1825
1826
1827 static void node_composit_buts_hue_sat(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1828 {
1829         uiLayout *col;
1830         
1831         col = uiLayoutColumn(layout, FALSE);
1832         uiItemR(col, ptr, "color_hue", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
1833         uiItemR(col, ptr, "color_saturation", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
1834         uiItemR(col, ptr, "color_value", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
1835 }
1836
1837 static void node_composit_buts_dilateerode(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1838 {
1839         uiItemR(layout, ptr, "type", 0, NULL, ICON_NONE);
1840         uiItemR(layout, ptr, "distance", 0, NULL, ICON_NONE);
1841         switch (RNA_enum_get(ptr, "type")) {
1842                 case CMP_NODE_DILATEERODE_DISTANCE_THRESH:
1843                         uiItemR(layout, ptr, "edge", 0, NULL, ICON_NONE);
1844                         break;
1845                 case CMP_NODE_DILATEERODE_DISTANCE_FEATHER:
1846                         uiItemR(layout, ptr, "falloff", 0, NULL, ICON_NONE);
1847                         break;
1848         }
1849 }
1850
1851 static void node_composit_buts_inpaint(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1852 {
1853         uiItemR(layout, ptr, "distance", 0, NULL, ICON_NONE);
1854 }
1855
1856 static void node_composit_buts_despeckle(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1857 {
1858         uiLayout *col;
1859
1860         col = uiLayoutColumn(layout, FALSE);
1861         uiItemR(col, ptr, "threshold", 0, NULL, ICON_NONE);
1862         uiItemR(col, ptr, "threshold_neighbour", 0, NULL, ICON_NONE);
1863 }
1864
1865 static void node_composit_buts_diff_matte(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1866 {
1867         uiLayout *col;
1868         
1869         col = uiLayoutColumn(layout, TRUE);
1870         uiItemR(col, ptr, "tolerance", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
1871         uiItemR(col, ptr, "falloff", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
1872 }
1873
1874 static void node_composit_buts_distance_matte(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1875 {
1876         uiLayout *col, *row;
1877         
1878         col = uiLayoutColumn(layout, TRUE);
1879    
1880         uiItemL(layout, IFACE_("Color Space:"), ICON_NONE);
1881         row = uiLayoutRow(layout, FALSE);
1882         uiItemR(row, ptr, "channel", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
1883
1884         uiItemR(col, ptr, "tolerance", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
1885         uiItemR(col, ptr, "falloff", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
1886 }
1887
1888 static void node_composit_buts_color_spill(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1889 {
1890         uiLayout *row, *col;
1891         
1892         uiItemL(layout, IFACE_("Despill Channel:"), ICON_NONE);
1893         row = uiLayoutRow(layout, FALSE);
1894         uiItemR(row, ptr, "channel", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
1895
1896         col = uiLayoutColumn(layout, FALSE);
1897         uiItemR(col, ptr, "limit_method", 0, NULL, ICON_NONE);
1898
1899         if (RNA_enum_get(ptr, "limit_method") == 0) {
1900                 uiItemL(col, IFACE_("Limiting Channel:"), ICON_NONE);
1901                 row = uiLayoutRow(col, FALSE);
1902                 uiItemR(row, ptr, "limit_channel", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
1903         }
1904
1905         uiItemR(col, ptr, "ratio", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
1906         uiItemR(col, ptr, "use_unspill", 0, NULL, ICON_NONE);
1907         if (RNA_boolean_get(ptr, "use_unspill") == TRUE) {
1908                 uiItemR(col, ptr, "unspill_red", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
1909                 uiItemR(col, ptr, "unspill_green", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
1910                 uiItemR(col, ptr, "unspill_blue", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
1911         }
1912 }
1913
1914 static void node_composit_buts_chroma_matte(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1915 {
1916         uiLayout *col;
1917         
1918         col = uiLayoutColumn(layout, FALSE);
1919         uiItemR(col, ptr, "tolerance", 0, NULL, ICON_NONE);
1920         uiItemR(col, ptr, "threshold", 0, NULL, ICON_NONE);
1921         
1922         col = uiLayoutColumn(layout, TRUE);
1923         /*uiItemR(col, ptr, "lift", UI_ITEM_R_SLIDER, NULL, ICON_NONE);  Removed for now */
1924         uiItemR(col, ptr, "gain", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
1925         /*uiItemR(col, ptr, "shadow_adjust", UI_ITEM_R_SLIDER, NULL, ICON_NONE);  Removed for now*/
1926 }
1927
1928 static void node_composit_buts_color_matte(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1929 {
1930         uiLayout *col;
1931         
1932         col = uiLayoutColumn(layout, TRUE);
1933         uiItemR(col, ptr, "color_hue", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
1934         uiItemR(col, ptr, "color_saturation", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
1935         uiItemR(col, ptr, "color_value", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
1936 }
1937
1938 static void node_composit_buts_channel_matte(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1939 {       
1940         uiLayout *col, *row;
1941
1942         uiItemL(layout, IFACE_("Color Space:"), ICON_NONE);
1943         row = uiLayoutRow(layout, FALSE);
1944         uiItemR(row, ptr, "color_space", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
1945
1946         col = uiLayoutColumn(layout, FALSE);
1947         uiItemL(col, IFACE_("Key Channel:"), ICON_NONE);
1948         row = uiLayoutRow(col, FALSE);
1949         uiItemR(row, ptr, "matte_channel", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
1950
1951         col = uiLayoutColumn(layout, FALSE);
1952
1953         uiItemR(col, ptr, "limit_method", 0, NULL, ICON_NONE);
1954         if (RNA_enum_get(ptr, "limit_method") == 0) {
1955                 uiItemL(col, IFACE_("Limiting Channel:"), ICON_NONE);
1956                 row = uiLayoutRow(col, FALSE);
1957                 uiItemR(row, ptr, "limit_channel", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
1958         }
1959
1960         uiItemR(col, ptr, "limit_max", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
1961         uiItemR(col, ptr, "limit_min", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
1962 }
1963
1964 static void node_composit_buts_luma_matte(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1965 {
1966         uiLayout *col;
1967         
1968         col = uiLayoutColumn(layout, TRUE);
1969         uiItemR(col, ptr, "limit_max", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
1970         uiItemR(col, ptr, "limit_min", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
1971 }
1972
1973 static void node_composit_buts_map_uv(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1974 {
1975         uiItemR(layout, ptr, "alpha", 0, NULL, ICON_NONE);
1976 }
1977
1978 static void node_composit_buts_id_mask(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1979 {
1980         uiItemR(layout, ptr, "index", 0, NULL, ICON_NONE);
1981         uiItemR(layout, ptr, "use_antialiasing", 0, NULL, ICON_NONE);
1982 }
1983
1984 /* draw function for file output node sockets, displays only sub-path and format, no value button */
1985 static void node_draw_input_file_output(const bContext *C, uiBlock *block,
1986                                         bNodeTree *ntree, bNode *node, bNodeSocket *sock,
1987                                         const char *UNUSED(name), int x, int y, int width)
1988 {
1989         uiLayout *layout, *row;
1990         PointerRNA nodeptr, inputptr, imfptr;
1991         int imtype;
1992         int rx, ry;
1993         RNA_pointer_create(&ntree->id, &RNA_Node, node, &nodeptr);
1994         
1995         layout = uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, x, y + NODE_DY, width, 20, UI_GetStyle());
1996         row = uiLayoutRow(layout, FALSE);
1997         
1998         imfptr = RNA_pointer_get(&nodeptr, "format");
1999         imtype = RNA_enum_get(&imfptr, "file_format");
2000         if (imtype == R_IMF_IMTYPE_MULTILAYER) {
2001                 NodeImageMultiFileSocket *input = sock->storage;
2002                 RNA_pointer_create(&ntree->id, &RNA_NodeOutputFileSlotLayer, input, &inputptr);
2003                 
2004                 uiItemL(row, input->layer, ICON_NONE);
2005         }
2006         else {
2007                 NodeImageMultiFileSocket *input = sock->storage;
2008                 PropertyRNA *imtype_prop;
2009                 const char *imtype_name;
2010                 RNA_pointer_create(&ntree->id, &RNA_NodeOutputFileSlotFile, input, &inputptr);
2011                 
2012                 uiItemL(row, input->path, ICON_NONE);
2013                 
2014                 if (!RNA_boolean_get(&inputptr, "use_node_format"))
2015                         imfptr = RNA_pointer_get(&inputptr, "format");
2016                 
2017                 imtype_prop = RNA_struct_find_property(&imfptr, "file_format");
2018                 RNA_property_enum_name((bContext *)C, &imfptr, imtype_prop,
2019                                        RNA_property_enum_get(&imfptr, imtype_prop), &imtype_name);
2020                 uiBlockSetEmboss(block, UI_EMBOSSP);
2021                 uiItemL(row, imtype_name, ICON_NONE);
2022                 uiBlockSetEmboss(block, UI_EMBOSSN);
2023         }
2024         
2025         uiBlockLayoutResolve(block, &rx, &ry);
2026 }
2027 static void node_composit_buts_file_output(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2028 {
2029         PointerRNA imfptr = RNA_pointer_get(ptr, "format");
2030         int multilayer = (RNA_enum_get(&imfptr, "file_format") == R_IMF_IMTYPE_MULTILAYER);
2031         
2032         if (multilayer)
2033                 uiItemL(layout, IFACE_("Path:"), ICON_NONE);
2034         else
2035                 uiItemL(layout, IFACE_("Base Path:"), ICON_NONE);
2036         uiItemR(layout, ptr, "base_path", 0, "", ICON_NONE);
2037 }
2038 static void node_composit_buts_file_output_details(uiLayout *layout, bContext *C, PointerRNA *ptr)
2039 {
2040         PointerRNA imfptr = RNA_pointer_get(ptr, "format");
2041         PointerRNA active_input_ptr, op_ptr;
2042         uiLayout *row, *col;
2043         int active_index;
2044         int multilayer = (RNA_enum_get(&imfptr, "file_format") == R_IMF_IMTYPE_MULTILAYER);
2045         
2046         node_composit_buts_file_output(layout, C, ptr);
2047         uiTemplateImageSettings(layout, &imfptr, FALSE);
2048         
2049         uiItemS(layout);
2050         
2051         uiItemO(layout, IFACE_("Add Input"), ICON_ZOOMIN, "NODE_OT_output_file_add_socket");
2052         
2053         row = uiLayoutRow(layout, FALSE);
2054         col = uiLayoutColumn(row, TRUE);
2055         
2056         active_index = RNA_int_get(ptr, "active_input_index");
2057         /* using different collection properties if multilayer format is enabled */
2058         if (multilayer) {
2059                 uiTemplateList(col, C, ptr, "layer_slots", ptr, "active_input_index", NULL, 0, 0, 0);
2060                 RNA_property_collection_lookup_int(ptr, RNA_struct_find_property(ptr, "layer_slots"),
2061                                                    active_index, &active_input_ptr);
2062         }
2063         else {
2064                 uiTemplateList(col, C, ptr, "file_slots", ptr, "active_input_index", NULL, 0, 0, 0);
2065                 RNA_property_collection_lookup_int(ptr, RNA_struct_find_property(ptr, "file_slots"),
2066                                                    active_index, &active_input_ptr);
2067         }
2068         /* XXX collection lookup does not return the ID part of the pointer, setting this manually here */
2069         active_input_ptr.id.data = ptr->id.data;
2070         
2071         col = uiLayoutColumn(row, TRUE);
2072         op_ptr = uiItemFullO(col, "NODE_OT_output_file_move_active_socket", "",
2073                              ICON_TRIA_UP, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS);
2074         RNA_enum_set(&op_ptr, "direction", 1);
2075         op_ptr = uiItemFullO(col, "NODE_OT_output_file_move_active_socket", "",
2076                              ICON_TRIA_DOWN, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS);
2077         RNA_enum_set(&op_ptr, "direction", 2);
2078         
2079         if (active_input_ptr.data) {
2080                 if (multilayer) {
2081                         col = uiLayoutColumn(layout, TRUE);
2082                         
2083                         uiItemL(col, IFACE_("Layer:"), ICON_NONE);
2084                         row = uiLayoutRow(col, FALSE);
2085                         uiItemR(row, &active_input_ptr, "name", 0, "", ICON_NONE);
2086                         uiItemFullO(row, "NODE_OT_output_file_remove_active_socket", "",
2087                                     ICON_X, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_R_ICON_ONLY);
2088                 }
2089                 else {
2090                         col = uiLayoutColumn(layout, TRUE);
2091                         
2092                         uiItemL(col, IFACE_("File Path:"), ICON_NONE);
2093                         row = uiLayoutRow(col, FALSE);
2094                         uiItemR(row, &active_input_ptr, "path", 0, "", ICON_NONE);
2095                         uiItemFullO(row, "NODE_OT_output_file_remove_active_socket", "",
2096                                     ICON_X, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_R_ICON_ONLY);
2097                         
2098                         /* format details for individual files */
2099                         imfptr = RNA_pointer_get(&active_input_ptr, "format");
2100                         
2101                         col = uiLayoutColumn(layout, TRUE);
2102                         uiItemL(col, IFACE_("Format:"), ICON_NONE);
2103                         uiItemR(col, &active_input_ptr, "use_node_format", 0, NULL, ICON_NONE);
2104                         
2105                         col = uiLayoutColumn(layout, FALSE);
2106                         uiLayoutSetActive(col, RNA_boolean_get(&active_input_ptr, "use_node_format") == FALSE);
2107                         uiTemplateImageSettings(col, &imfptr, FALSE);
2108                 }
2109         }
2110 }
2111
2112 static void node_composit_buts_scale(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2113 {
2114         uiItemR(layout, ptr, "space", 0, "", ICON_NONE);
2115
2116         if (RNA_enum_get(ptr, "space") == CMP_SCALE_RENDERPERCENT) {
2117                 uiLayout *row;
2118                 uiItemR(layout, ptr, "frame_method", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
2119                 row = uiLayoutRow(layout, TRUE);
2120                 uiItemR(row, ptr, "offset_x", 0, "X", ICON_NONE);
2121                 uiItemR(row, ptr, "offset_y", 0, "Y", ICON_NONE);
2122         }
2123 }
2124
2125 static void node_composit_buts_rotate(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2126 {
2127         uiItemR(layout, ptr, "filter_type", 0, "", ICON_NONE);
2128 }
2129
2130 static void node_composit_buts_invert(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2131 {
2132         uiLayout *col;
2133         
2134         col = uiLayoutColumn(layout, FALSE);
2135         uiItemR(col, ptr, "invert_rgb", 0, NULL, ICON_NONE);
2136         uiItemR(col, ptr, "invert_alpha", 0, NULL, ICON_NONE);
2137 }
2138
2139 static void node_composit_buts_premulkey(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2140 {
2141         uiItemR(layout, ptr, "mapping", 0, "", ICON_NONE);
2142 }
2143
2144 static void node_composit_buts_view_levels(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2145 {
2146         uiItemR(layout, ptr, "channel", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
2147 }
2148
2149 static void node_composit_buts_colorbalance(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2150 {
2151         uiLayout *split, *col, *row;
2152         
2153         uiItemR(layout, ptr, "correction_method", 0, NULL, ICON_NONE);
2154         
2155         if (RNA_enum_get(ptr, "correction_method") == 0) {
2156         
2157                 split = uiLayoutSplit(layout, 0.0f, FALSE);
2158                 col = uiLayoutColumn(split, FALSE);
2159                 uiTemplateColorWheel(col, ptr, "lift", 1, 1, 0, 1);
2160                 row = uiLayoutRow(col, FALSE);
2161                 uiItemR(row, ptr, "lift", 0, NULL, ICON_NONE);
2162                 
2163                 col = uiLayoutColumn(split, FALSE);
2164                 uiTemplateColorWheel(col, ptr, "gamma", 1, 1, 1, 1);
2165                 row = uiLayoutRow(col, FALSE);
2166                 uiItemR(row, ptr, "gamma", 0, NULL, ICON_NONE);
2167                 
2168                 col = uiLayoutColumn(split, FALSE);
2169                 uiTemplateColorWheel(col, ptr, "gain", 1, 1, 1, 1);
2170                 row = uiLayoutRow(col, FALSE);
2171                 uiItemR(row, ptr, "gain", 0, NULL, ICON_NONE);
2172
2173         }
2174         else {
2175                 
2176                 split = uiLayoutSplit(layout, 0.0f, FALSE);
2177                 col = uiLayoutColumn(split, FALSE);
2178                 uiTemplateColorWheel(col, ptr, "offset", 1, 1, 0, 1);
2179                 row = uiLayoutRow(col, FALSE);
2180                 uiItemR(row, ptr, "offset", 0, NULL, ICON_NONE);
2181                 
2182                 col = uiLayoutColumn(split, FALSE);
2183                 uiTemplateColorWheel(col, ptr, "power", 1, 1, 0, 1);
2184                 row = uiLayoutRow(col, FALSE);
2185                 uiItemR(row, ptr, "power", 0, NULL, ICON_NONE);
2186                 
2187                 col = uiLayoutColumn(split, FALSE);
2188                 uiTemplateColorWheel(col, ptr, "slope", 1, 1, 0, 1);
2189                 row = uiLayoutRow(col, FALSE);
2190                 uiItemR(row, ptr, "slope", 0, NULL, ICON_NONE);
2191         }
2192
2193 }
2194 static void node_composit_buts_colorbalance_but(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2195 {
2196         uiItemR(layout, ptr, "correction_method", 0, NULL, ICON_NONE);
2197
2198         if (RNA_enum_get(ptr, "correction_method") == 0) {
2199
2200                 uiTemplateColorWheel(layout, ptr, "lift", 1, 1, 0, 1);
2201                 uiItemR(layout, ptr, "lift", 0, NULL, ICON_NONE);
2202
2203                 uiTemplateColorWheel(layout, ptr, "gamma", 1, 1, 1, 1);
2204                 uiItemR(layout, ptr, "gamma", 0, NULL, ICON_NONE);
2205
2206                 uiTemplateColorWheel(layout, ptr, "gain", 1, 1, 1, 1);
2207                 uiItemR(layout, ptr, "gain", 0, NULL, ICON_NONE);
2208         }
2209         else {
2210                 uiTemplateColorWheel(layout, ptr, "offset", 1, 1, 0, 1);
2211                 uiItemR(layout, ptr, "offset", 0, NULL, ICON_NONE);
2212
2213                 uiTemplateColorWheel(layout, ptr, "power", 1, 1, 0, 1);
2214                 uiItemR(layout, ptr, "power", 0, NULL, ICON_NONE);
2215
2216                 uiTemplateColorWheel(layout, ptr, "slope", 1, 1, 0, 1);
2217                 uiItemR(layout, ptr, "slope", 0, NULL, ICON_NONE);
2218         }
2219 }
2220
2221
2222 static void node_composit_buts_huecorrect(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2223 {
2224         bNode *node = ptr->data;
2225         CurveMapping *cumap = node->storage;
2226
2227         if (_sample_col[0] != SAMPLE_FLT_ISNONE) {
2228                 cumap->flag |= CUMA_DRAW_SAMPLE;
2229                 copy_v3_v3(cumap->sample, _sample_col);
2230         }
2231         else {
2232                 cumap->flag &= ~CUMA_DRAW_SAMPLE;
2233         }
2234
2235         uiTemplateCurveMapping(layout, ptr, "mapping", 'h', 0, 0);
2236 }
2237
2238 static void node_composit_buts_ycc(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2239
2240         uiItemR(layout, ptr, "mode", 0, "", ICON_NONE);
2241 }
2242
2243 static void node_composit_buts_movieclip(uiLayout *layout, bContext *C, PointerRNA *ptr)
2244 {
2245         uiTemplateID(layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL);
2246 }
2247
2248 static void node_composit_buts_movieclip_details(uiLayout *layout, bContext *C, PointerRNA *ptr)
2249 {
2250         bNode *node = ptr->data;
2251         PointerRNA clipptr;
2252
2253         uiTemplateID(layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL);
2254
2255         if (!node->id)
2256                 return;
2257
2258         clipptr = RNA_pointer_get(ptr, "clip");
2259
2260         uiTemplateColorspaceSettings(layout, &clipptr, "colorspace_settings");
2261 }
2262
2263 static void node_composit_buts_stabilize2d(uiLayout *layout, bContext *C, PointerRNA *ptr)
2264 {
2265         bNode *node = ptr->data;
2266
2267         uiTemplateID(layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL);
2268
2269         if (!node->id)
2270                 return;
2271
2272         uiItemR(layout, ptr, "filter_type", 0, "", ICON_NONE);
2273 }
2274
2275 static void node_composit_buts_transform(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2276 {
2277         uiItemR(layout, ptr, "filter_type", 0, "", ICON_NONE);
2278 }
2279
2280 static void node_composit_buts_moviedistortion(uiLayout *layout, bContext *C, PointerRNA *ptr)
2281 {
2282         bNode *node = ptr->data;
2283
2284         uiTemplateID(layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL);
2285
2286         if (!node->id)
2287                 return;
2288
2289         uiItemR(layout, ptr, "distortion_type", 0, "", ICON_NONE);
2290 }
2291
2292 static void node_composit_buts_colorcorrection(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2293 {
2294         uiLayout *row;
2295         
2296         row = uiLayoutRow(layout, FALSE);
2297         uiItemR(row, ptr, "red", 0, NULL, ICON_NONE);
2298         uiItemR(row, ptr, "green", 0, NULL, ICON_NONE);
2299         uiItemR(row, ptr, "blue", 0, NULL, ICON_NONE);
2300
2301         row = uiLayoutRow(layout, FALSE);
2302         uiItemL(row, "", ICON_NONE);
2303         uiItemL(row, IFACE_("Saturation"), ICON_NONE);
2304         uiItemL(row, IFACE_("Contrast"), ICON_NONE);
2305         uiItemL(row, IFACE_("Gamma"), ICON_NONE);
2306         uiItemL(row, IFACE_("Gain"), ICON_NONE);
2307         uiItemL(row, IFACE_("Lift"), ICON_NONE);
2308
2309         row = uiLayoutRow(layout, FALSE);
2310         uiItemL(row, IFACE_("Master"), ICON_NONE);
2311         uiItemR(row, ptr, "master_saturation", UI_ITEM_R_SLIDER, "", ICON_NONE);
2312         uiItemR(row, ptr, "master_contrast", UI_ITEM_R_SLIDER, "", ICON_NONE);
2313         uiItemR(row, ptr, "master_gamma", UI_ITEM_R_SLIDER, "", ICON_NONE);
2314         uiItemR(row, ptr, "master_gain", UI_ITEM_R_SLIDER, "", ICON_NONE);
2315         uiItemR(row, ptr, "master_lift", UI_ITEM_R_SLIDER, "", ICON_NONE);
2316
2317         row = uiLayoutRow(layout, FALSE);
2318         uiItemL(row, IFACE_("Highlights"), ICON_NONE);
2319         uiItemR(row, ptr, "highlights_saturation", UI_ITEM_R_SLIDER, "", ICON_NONE);
2320         uiItemR(row, ptr, "highlights_contrast", UI_ITEM_R_SLIDER, "", ICON_NONE);
2321         uiItemR(row, ptr, "highlights_gamma", UI_ITEM_R_SLIDER, "", ICON_NONE);
2322         uiItemR(row, ptr, "highlights_gain", UI_ITEM_R_SLIDER, "", ICON_NONE);
2323         uiItemR(row, ptr, "highlights_lift", UI_ITEM_R_SLIDER, "", ICON_NONE);
2324
2325         row = uiLayoutRow(layout, FALSE);
2326         uiItemL(row, IFACE_("Midtones"), ICON_NONE);
2327         uiItemR(row, ptr, "midtones_saturation", UI_ITEM_R_SLIDER, "", ICON_NONE);
2328         uiItemR(row, ptr, "midtones_contrast", UI_ITEM_R_SLIDER, "", ICON_NONE);
2329         uiItemR(row, ptr, "midtones_gamma", UI_ITEM_R_SLIDER, "", ICON_NONE);
2330         uiItemR(row, ptr, "midtones_gain", UI_ITEM_R_SLIDER, "", ICON_NONE);
2331         uiItemR(row, ptr, "midtones_lift", UI_ITEM_R_SLIDER, "", ICON_NONE);
2332
2333         row = uiLayoutRow(layout, FALSE);
2334         uiItemL(row, IFACE_("Shadows"), ICON_NONE);
2335         uiItemR(row, ptr, "shadows_saturation", UI_ITEM_R_SLIDER, "", ICON_NONE);
2336         uiItemR(row, ptr, "shadows_contrast", UI_ITEM_R_SLIDER, "", ICON_NONE);
2337         uiItemR(row, ptr, "shadows_gamma", UI_ITEM_R_SLIDER, "", ICON_NONE);
2338         uiItemR(row, ptr, "shadows_gain", UI_ITEM_R_SLIDER, "", ICON_NONE);
2339         uiItemR(row, ptr, "shadows_lift", UI_ITEM_R_SLIDER, "", ICON_NONE);
2340
2341         row = uiLayoutRow(layout, FALSE);
2342         uiItemR(row, ptr, "midtones_start", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2343         uiItemR(row, ptr, "midtones_end", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2344 }
2345
2346 static void node_composit_buts_colorcorrection_but(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2347 {
2348         uiLayout *row;
2349         
2350         row = uiLayoutRow(layout, FALSE);
2351         uiItemR(row, ptr, "red", 0, NULL, ICON_NONE);
2352         uiItemR(row, ptr, "green", 0, NULL, ICON_NONE);
2353         uiItemR(row, ptr, "blue", 0, NULL, ICON_NONE);
2354         row = layout;
2355         uiItemL(row, IFACE_("Saturation"), ICON_NONE);
2356         uiItemR(row, ptr, "master_saturation", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2357         uiItemR(row, ptr, "highlights_saturation", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2358         uiItemR(row, ptr, "midtones_saturation", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2359         uiItemR(row, ptr, "shadows_saturation", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2360
2361         uiItemL(row, IFACE_("Contrast"), ICON_NONE);
2362         uiItemR(row, ptr, "master_contrast", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2363         uiItemR(row, ptr, "highlights_contrast", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2364         uiItemR(row, ptr, "midtones_contrast", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2365         uiItemR(row, ptr, "shadows_contrast", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2366
2367         uiItemL(row, IFACE_("Gamma"), ICON_NONE);
2368         uiItemR(row, ptr, "master_gamma", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2369         uiItemR(row, ptr, "highlights_gamma", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2370         uiItemR(row, ptr, "midtones_gamma", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2371         uiItemR(row, ptr, "shadows_gamma", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2372
2373         uiItemL(row, IFACE_("Gain"), ICON_NONE);
2374         uiItemR(row, ptr, "master_gain", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2375         uiItemR(row, ptr, "highlights_gain", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2376         uiItemR(row, ptr, "midtones_gain", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2377         uiItemR(row, ptr, "shadows_gain", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2378         
2379         uiItemL(row, IFACE_("Lift"), ICON_NONE);
2380         uiItemR(row, ptr, "master_lift", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2381         uiItemR(row, ptr, "highlights_lift", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2382         uiItemR(row, ptr, "midtones_lift", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2383         uiItemR(row, ptr, "shadows_lift", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2384
2385         row = uiLayoutRow(layout, FALSE);
2386         uiItemR(row, ptr, "midtones_start", 0, NULL, ICON_NONE);
2387         uiItemR(row, ptr, "midtones_end", 0, NULL, ICON_NONE);
2388 }
2389
2390 static void node_composit_buts_switch(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2391 {
2392         uiItemR(layout, ptr, "check", 0, NULL, ICON_NONE);
2393 }
2394
2395 static void node_composit_buts_boxmask(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2396 {
2397         uiLayout *row;
2398         
2399         row = uiLayoutRow(layout, TRUE);
2400         uiItemR(row, ptr, "x", 0, NULL, ICON_NONE);
2401         uiItemR(row, ptr, "y", 0, NULL, ICON_NONE);
2402         
2403         row = uiLayoutRow(layout, TRUE);
2404         uiItemR(row, ptr, "width", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2405         uiItemR(row, ptr, "height", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2406
2407         uiItemR(layout, ptr, "rotation", 0, NULL, ICON_NONE);
2408         uiItemR(layout, ptr, "mask_type", 0, NULL, ICON_NONE);
2409 }
2410
2411 static void node_composit_buts_bokehimage(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2412 {
2413         uiItemR(layout, ptr, "flaps", 0, NULL, ICON_NONE);
2414         uiItemR(layout, ptr, "angle", 0, NULL, ICON_NONE);
2415         uiItemR(layout, ptr, "rounding", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2416         uiItemR(layout, ptr, "catadioptric", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2417         uiItemR(layout, ptr, "shift", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2418 }
2419
2420 static void node_composit_buts_bokehblur(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2421 {
2422         uiItemR(layout, ptr, "use_variable_size", 0, NULL, ICON_NONE);
2423         // uiItemR(layout, ptr, "f_stop", 0, NULL, ICON_NONE);  // UNUSED
2424         uiItemR(layout, ptr, "blur_max", 0, NULL, ICON_NONE);
2425 }
2426
2427 static void node_composit_backdrop_viewer(SpaceNode *snode, ImBuf *backdrop, bNode *node, int x, int y)
2428 {
2429 //      node_composit_backdrop_canvas(snode, backdrop, node, x, y);
2430         if (node->custom1 == 0) {
2431                 const float backdropWidth = backdrop->x;
2432                 const float backdropHeight = backdrop->y;
2433                 const float cx  = x + snode->zoom * backdropWidth * node->custom3;
2434                 const float cy = y + snode->zoom * backdropHeight * node->custom4;
2435
2436                 glColor3f(1.0, 1.0, 1.0);
2437
2438                 glBegin(GL_LINES);
2439                 glVertex2f(cx - 25, cy - 25);
2440                 glVertex2f(cx + 25, cy + 25);
2441                 glVertex2f(cx + 25, cy - 25);
2442                 glVertex2f(cx - 25, cy + 25);
2443                 glEnd();
2444         }
2445 }
2446
2447 static void node_composit_backdrop_boxmask(SpaceNode *snode, ImBuf *backdrop, bNode *node, int x, int y)
2448 {
2449         NodeBoxMask *boxmask = node->storage;
2450         const float backdropWidth = backdrop->x;
2451         const float backdropHeight = backdrop->y;
2452         const float aspect = backdropWidth / backdropHeight;
2453         const float rad = DEG2RADF(-boxmask->rotation);
2454         const float cosine = cosf(rad);
2455         const float sine = sinf(rad);
2456         const float halveBoxWidth = backdropWidth * (boxmask->width / 2.0f);
2457         const float halveBoxHeight = backdropHeight * (boxmask->height / 2.0f) * aspect;
2458
2459         float cx, cy, x1, x2, x3, x4;
2460         float y1, y2, y3, y4;
2461
2462
2463         /* keep this, saves us from a version patch */
2464         if (snode->zoom == 0.0f) snode->zoom = 1.0f;
2465
2466         glColor3f(1.0, 1.0, 1.0);
2467
2468         cx  = x + snode->zoom * backdropWidth * boxmask->x;
2469         cy = y + snode->zoom * backdropHeight * boxmask->y;
2470
2471         x1 = cx - (cosine * halveBoxWidth + sine * halveBoxHeight) * snode->zoom;
2472         x2 = cx - (cosine * -halveBoxWidth + sine * halveBoxHeight) * snode->zoom;
2473         x3 = cx - (cosine * -halveBoxWidth + sine * -halveBoxHeight) * snode->zoom;
2474         x4 = cx - (cosine * halveBoxWidth + sine * -halveBoxHeight) * snode->zoom;
2475         y1 = cy - (-sine * halveBoxWidth + cosine * halveBoxHeight) * snode->zoom;
2476         y2 = cy - (-sine * -halveBoxWidth + cosine * halveBoxHeight) * snode->zoom;
2477         y3 = cy - (-sine * -halveBoxWidth + cosine * -halveBoxHeight) * snode->zoom;
2478         y4 = cy - (-sine * halveBoxWidth + cosine * -halveBoxHeight) * snode->zoom;
2479
2480         glBegin(GL_LINE_LOOP);
2481         glVertex2f(x1, y1);
2482         glVertex2f(x2, y2);
2483         glVertex2f(x3, y3);
2484         glVertex2f(x4, y4);
2485         glEnd();
2486 }
2487
2488 static void node_composit_backdrop_ellipsemask(SpaceNode *snode, ImBuf *backdrop, bNode *node, int x, int y)
2489 {
2490         NodeEllipseMask *ellipsemask = node->storage;
2491         const float backdropWidth = backdrop->x;
2492         const float backdropHeight = backdrop->y;
2493         const float aspect = backdropWidth / backdropHeight;
2494         const float rad = DEG2RADF(-ellipsemask->rotation);
2495         const float cosine = cosf(rad);
2496         const float sine = sinf(rad);
2497         const float halveBoxWidth = backdropWidth * (ellipsemask->width / 2.0f);
2498         const float halveBoxHeight = backdropHeight * (ellipsemask->height / 2.0f) * aspect;
2499
2500         float cx, cy, x1, x2, x3, x4;
2501         float y1, y2, y3, y4;
2502
2503
2504         /* keep this, saves us from a version patch */
2505         if (snode->zoom == 0.0f) snode->zoom = 1.0f;
2506
2507         glColor3f(1.0, 1.0, 1.0);
2508
2509         cx  = x + snode->zoom * backdropWidth * ellipsemask->x;
2510         cy = y + snode->zoom * backdropHeight * ellipsemask->y;
2511
2512         x1 = cx - (cosine * halveBoxWidth + sine * halveBoxHeight) * snode->zoom;
2513         x2 = cx - (cosine * -halveBoxWidth + sine * halveBoxHeight) * snode->zoom;
2514         x3 = cx - (cosine * -halveBoxWidth + sine * -halveBoxHeight) * snode->zoom;
2515         x4 = cx - (cosine * halveBoxWidth + sine * -halveBoxHeight) * snode->zoom;
2516         y1 = cy - (-sine * halveBoxWidth + cosine * halveBoxHeight) * snode->zoom;
2517         y2 = cy - (-sine * -halveBoxWidth + cosine * halveBoxHeight) * snode->zoom;
2518         y3 = cy - (-sine * -halveBoxWidth + cosine * -halveBoxHeight) * snode->zoom;
2519         y4 = cy - (-sine * halveBoxWidth + cosine * -halveBoxHeight) * snode->zoom;
2520
2521         glBegin(GL_LINE_LOOP);
2522
2523         glVertex2f(x1, y1);
2524         glVertex2f(x2, y2);
2525         glVertex2f(x3, y3);
2526         glVertex2f(x4, y4);
2527         glEnd();
2528 }
2529
2530 static void node_composit_buts_ellipsemask(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2531 {
2532         uiLayout *row;
2533         row = uiLayoutRow(layout, TRUE);
2534         uiItemR(row, ptr, "x", 0, NULL, ICON_NONE);
2535         uiItemR(row, ptr, "y", 0, NULL, ICON_NONE);
2536         row = uiLayoutRow(layout, TRUE);
2537         uiItemR(row, ptr, "width", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2538         uiItemR(row, ptr, "height", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2539
2540         uiItemR(layout, ptr, "rotation", 0, NULL, ICON_NONE);
2541         uiItemR(layout, ptr, "mask_type", 0, NULL, ICON_NONE);
2542 }
2543
2544 static void node_composit_buts_viewer_but(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2545 {
2546         uiLayout *col;
2547         
2548         uiItemR(layout, ptr, "tile_order", 0, NULL, ICON_NONE);
2549         if (RNA_enum_get(ptr, "tile_order") == 0) {
2550                 col = uiLayoutColumn(layout, TRUE);
2551                 uiItemR(col, ptr, "center_x", 0, NULL, ICON_NONE);
2552                 uiItemR(col, ptr, "center_y", 0, NULL, ICON_NONE);
2553         }
2554 }
2555
2556 static void node_composit_buts_mask(uiLayout *layout, bContext *C, PointerRNA *ptr)
2557 {
2558         bNode *node = ptr->data;
2559
2560         uiTemplateID(layout, C, ptr, "mask", NULL, NULL, NULL);
2561         uiItemR(layout, ptr, "use_antialiasing", 0, NULL, ICON_NONE);
2562         uiItemR(layout, ptr, "use_feather", 0, NULL, ICON_NONE);
2563
2564         uiItemR(layout, ptr, "size_source", 0, "", ICON_NONE);
2565
2566         if (node->custom1 & (CMP_NODEFLAG_MASK_FIXED | CMP_NODEFLAG_MASK_FIXED_SCENE)) {
2567                 uiItemR(layout, ptr, "size_x", 0, NULL, ICON_NONE);
2568                 uiItemR(layout, ptr, "size_y", 0, NULL, ICON_NONE);
2569         }
2570
2571         uiItemR(layout, ptr, "use_motion_blur", 0, NULL, ICON_NONE);
2572         if (node->custom1 & CMP_NODEFLAG_MASK_MOTION_BLUR) {
2573                 uiItemR(layout, ptr, "motion_blur_samples", 0, NULL, ICON_NONE);
2574                 uiItemR(layout, ptr, "motion_blur_shutter", 0, NULL, ICON_NONE);
2575         }
2576 }
2577
2578 static void node_composit_buts_keyingscreen(uiLayout *layout, bContext *C, PointerRNA *ptr)
2579 {
2580         bNode *node = ptr->data;
2581
2582         uiTemplateID(layout, C, ptr, "clip", NULL, NULL, NULL);
2583
2584         if (node->id) {
2585                 MovieClip *clip = (MovieClip *) node->id;
2586                 uiLayout *col;
2587                 PointerRNA tracking_ptr;
2588
2589                 RNA_pointer_create(&clip->id, &RNA_MovieTracking, &clip->tracking, &tracking_ptr);
2590
2591                 col = uiLayoutColumn(layout, TRUE);
2592                 uiItemPointerR(col, ptr, "tracking_object", &tracking_ptr, "objects", "", ICON_OBJECT_DATA);
2593         }
2594 }
2595
2596 static void node_composit_buts_keying(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2597 {
2598         /* bNode *node= ptr->data; */ /* UNUSED */
2599
2600         uiItemR(layout, ptr, "blur_pre", 0, NULL, ICON_NONE);
2601         uiItemR(layout, ptr, "screen_balance", 0, NULL, ICON_NONE);
2602         uiItemR(layout, ptr, "despill_factor", 0, NULL, ICON_NONE);
2603         uiItemR(layout, ptr, "despill_balance", 0, NULL, ICON_NONE);
2604         uiItemR(layout, ptr, "edge_kernel_radius", 0, NULL, ICON_NONE);
2605         uiItemR(layout, ptr, "edge_kernel_tolerance", 0, NULL, ICON_NONE);
2606         uiItemR(layout, ptr, "clip_black", 0, NULL, ICON_NONE);
2607         uiItemR(layout, ptr, "clip_white", 0, NULL, ICON_NONE);
2608         uiItemR(layout, ptr, "dilate_distance", 0, NULL, ICON_NONE);
2609         uiItemR(layout, ptr, "feather_falloff", 0, NULL, ICON_NONE);
2610         uiItemR(layout, ptr, "feather_distance", 0, NULL, ICON_NONE);
2611         uiItemR(layout, ptr, "blur_post", 0, NULL, ICON_NONE);
2612 }
2613
2614 static void node_composit_buts_trackpos(uiLayout *layout, bContext *C, PointerRNA *ptr)
2615 {
2616         bNode *node = ptr->data;
2617
2618         uiTemplateID(layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL);
2619
2620         if (node->id) {
2621                 MovieClip *clip = (MovieClip *) node->id;
2622                 MovieTracking *tracking = &clip->tracking;
2623                 MovieTrackingObject *object;
2624                 uiLayout *col;
2625                 PointerRNA tracking_ptr;
2626                 NodeTrackPosData *data = node->storage;
2627
2628                 RNA_pointer_create(&clip->id, &RNA_MovieTracking, tracking, &tracking_ptr);
2629
2630                 col = uiLayoutColumn(layout, FALSE);
2631                 uiItemPointerR(col, ptr, "tracking_object", &tracking_ptr, "objects", "", ICON_OBJECT_DATA);
2632
2633                 object = BKE_tracking_object_get_named(tracking, data->tracking_object);
2634                 if (object) {
2635                         PointerRNA object_ptr;
2636
2637                         RNA_pointer_create(&clip->id, &RNA_MovieTrackingObject, object, &object_ptr);
2638
2639                         uiItemPointerR(col, ptr, "track_name", &object_ptr, "tracks", "", ICON_ANIM_DATA);
2640                 }
2641                 else {
2642                         uiItemR(layout, ptr, "track_name", 0, "", ICON_ANIM_DATA);
2643                 }
2644
2645                 uiItemR(layout, ptr, "position", 0, NULL, ICON_NONE);
2646
2647                 if (node->custom1 == 2) {
2648                         uiItemR(layout, ptr, "frame_relative", 0, NULL, ICON_NONE);
2649                 }
2650         }
2651 }
2652
2653 /* only once called */
2654 static void node_composit_set_butfunc(bNodeType *ntype)
2655 {
2656         switch (ntype->type) {
2657                 /* case NODE_GROUP:      note, typeinfo for group is generated... see "XXX ugly hack" */
2658
2659                 case CMP_NODE_IMAGE:
2660                         ntype->uifunc = node_composit_buts_image;
2661                         ntype->uifuncbut = node_composit_buts_image_details;
2662                         break;
2663                 case CMP_NODE_R_LAYERS:
2664                         ntype->uifunc = node_composit_buts_renderlayers;
2665                         break;
2666                 case CMP_NODE_NORMAL:
2667                         ntype->uifunc = node_buts_normal;
2668                         break;
2669                 case CMP_NODE_CURVE_VEC:
2670                         ntype->uifunc = node_buts_curvevec;
2671                         break;
2672                 case CMP_NODE_CURVE_RGB:
2673                         ntype->uifunc = node_buts_curvecol;
2674                         break;
2675                 case CMP_NODE_VALUE:
2676                         ntype->uifunc = node_buts_value;
2677                         break;
2678                 case CMP_NODE_RGB:
2679                         ntype->uifunc = node_buts_rgb;
2680                         break;
2681                 case CMP_NODE_FLIP:
2682                         ntype->uifunc = node_composit_buts_flip;
2683                         break;
2684                 case CMP_NODE_SPLITVIEWER:
2685                         ntype->uifunc = node_composit_buts_splitviewer;
2686                         break;
2687                 case CMP_NODE_MIX_RGB:
2688                         ntype->uifunc = node_buts_mix_rgb;
2689                         break;
2690                 case CMP_NODE_VALTORGB:
2691                         ntype->uifunc = node_buts_colorramp;
2692                         break;
2693                 case CMP_NODE_CROP:
2694                         ntype->uifunc = node_composit_buts_crop;
2695                         break;
2696                 case CMP_NODE_BLUR:
2697                         ntype->uifunc = node_composit_buts_blur;
2698                         break;
2699                 case CMP_NODE_DBLUR:
2700                         ntype->uifunc = node_composit_buts_dblur;
2701                         break;
2702                 case CMP_NODE_BILATERALBLUR:
2703                         ntype->uifunc = node_composit_buts_bilateralblur;
2704                         break;
2705                 case CMP_NODE_DEFOCUS:
2706                         ntype->uifunc = node_composit_buts_defocus;
2707                         break;
2708                 case CMP_NODE_GLARE:
2709                         ntype->uifunc = node_composit_buts_glare;
2710                         break;
2711                 case CMP_NODE_TONEMAP:
2712                         ntype->uifunc = node_composit_buts_tonemap;
2713                         break;
2714                 case CMP_NODE_LENSDIST:
2715                         ntype->uifunc = node_composit_buts_lensdist;
2716                         break;
2717                 case CMP_NODE_VECBLUR:
2718                         ntype->uifunc = node_composit_buts_vecblur;
2719                         break;
2720                 case CMP_NODE_FILTER:
2721                         ntype->uifunc = node_composit_buts_filter;
2722                         break;
2723                 case CMP_NODE_MAP_VALUE:
2724                         ntype->uifunc = node_composit_buts_map_value;
2725                         break;
2726                 case CMP_NODE_TIME:
2727                         ntype->uifunc = node_buts_time;
2728                         break;
2729                 case CMP_NODE_ALPHAOVER:
2730                         ntype->uifunc = node_composit_buts_alphaover;
2731                         break;
2732                 case CMP_NODE_HUE_SAT:
2733                         ntype->uifunc = node_composit_buts_hue_sat;
2734                         break;
2735                 case CMP_NODE_TEXTURE:
2736                         ntype->uifunc = node_buts_texture;
2737                         break;
2738                 case CMP_NODE_DILATEERODE:
2739                         ntype->uifunc = node_composit_buts_dilateerode;
2740                         break;
2741                 case CMP_NODE_INPAINT:
2742                         ntype->uifunc = node_composit_buts_inpaint;
2743                         break;
2744                 case CMP_NODE_DESPECKLE:
2745                         ntype->uifunc = node_composit_buts_despeckle;
2746                         break;
2747                 case CMP_NODE_OUTPUT_FILE:
2748                         ntype->uifunc = node_composit_buts_file_output;
2749                         ntype->uifuncbut = node_composit_buts_file_output_details;
2750                         ntype->drawinputfunc = node_draw_input_file_output;
2751                         break;
2752                 case CMP_NODE_DIFF_MATTE:
2753                         ntype->uifunc = node_composit_buts_diff_matte;
2754                         break;
2755                 case CMP_NODE_DIST_MATTE:
2756                         ntype->uifunc = node_composit_buts_distance_matte;
2757                         break;
2758                 case CMP_NODE_COLOR_SPILL:
2759                         ntype->uifunc = node_composit_buts_color_spill;
2760                         break;
2761                 case CMP_NODE_CHROMA_MATTE:
2762                         ntype->uifunc = node_composit_buts_chroma_matte;
2763                         break;
2764                 case CMP_NODE_COLOR_MATTE:
2765                         ntype->uifunc = node_composit_buts_color_matte;
2766                         break;
2767                 case CMP_NODE_SCALE:
2768                         ntype->uifunc = node_composit_buts_scale;
2769                         break;
2770                 case CMP_NODE_ROTATE:
2771                         ntype->uifunc = node_composit_buts_rotate;
2772                         break;
2773                 case CMP_NODE_CHANNEL_MATTE:
2774                         ntype->uifunc = node_composit_buts_channel_matte;
2775                         break;
2776                 case CMP_NODE_LUMA_MATTE:
2777                         ntype->uifunc = node_composit_buts_luma_matte;
2778                         break;
2779                 case CMP_NODE_MAP_UV:
2780                         ntype->uifunc = node_composit_buts_map_uv;
2781                         break;
2782                 case CMP_NODE_ID_MASK:
2783                         ntype->uifunc = node_composit_buts_id_mask;
2784                         break;
2785                 case CMP_NODE_DOUBLEEDGEMASK:
2786                         ntype->uifunc = node_composit_buts_double_edge_mask;
2787                         break;
2788                 case CMP_NODE_MATH:
2789                         ntype->uifunc = node_buts_math;
2790                         break;
2791                 case CMP_NODE_INVERT:
2792                         ntype->uifunc = node_composit_buts_invert;
2793                         break;
2794                 case CMP_NODE_PREMULKEY:
2795                         ntype->uifunc = node_composit_buts_premulkey;
2796                         break;
2797                 case CMP_NODE_VIEW_LEVELS:
2798                         ntype->uifunc = node_composit_buts_view_levels;
2799                         break;
2800                 case CMP_NODE_COLORBALANCE:
2801                         ntype->uifunc = node_composit_buts_colorbalance;
2802                         ntype->uifuncbut = node_composit_buts_colorbalance_but;
2803                         break;
2804                 case CMP_NODE_HUECORRECT:
2805                         ntype->uifunc = node_composit_buts_huecorrect;
2806                         break;
2807                 case CMP_NODE_ZCOMBINE:
2808                         ntype->uifunc = node_composit_buts_zcombine;
2809                         break;
2810                 case CMP_NODE_COMBYCCA:
2811                 case CMP_NODE_SEPYCCA:
2812                         ntype->uifunc = node_composit_buts_ycc;
2813                         break;
2814                 case CMP_NODE_MOVIECLIP:
2815                         ntype->uifunc = node_composit_buts_movieclip;
2816                         ntype->uifuncbut = node_composit_buts_movieclip_details;
2817                         break;
2818                 case CMP_NODE_STABILIZE2D:
2819                         ntype->uifunc = node_composit_buts_stabilize2d;
2820                         break;
2821                 case CMP_NODE_TRANSFORM:
2822                         ntype->uifunc = node_composit_buts_transform;
2823                         break;
2824                 case CMP_NODE_MOVIEDISTORTION:
2825                         ntype->uifunc = node_composit_buts_moviedistortion;
2826                         break;
2827                 case CMP_NODE_COLORCORRECTION:
2828                         ntype->uifunc = node_composit_buts_colorcorrection;
2829                         ntype->uifuncbut = node_composit_buts_colorcorrection_but;
2830                         break;
2831                 case CMP_NODE_SWITCH:
2832                         ntype->uifunc = node_composit_buts_switch;
2833                         break;
2834                 case CMP_NODE_MASK_BOX:
2835                         ntype->uifunc = node_composit_buts_boxmask;
2836                         ntype->uibackdropfunc = node_composit_backdrop_boxmask;
2837                         break;
2838                 case CMP_NODE_MASK_ELLIPSE:
2839                         ntype->uifunc = node_composit_buts_ellipsemask;
2840                         ntype->uibackdropfunc = node_composit_backdrop_ellipsemask;
2841                         break;
2842                 case CMP_NODE_BOKEHIMAGE:
2843                         ntype->uifunc = node_composit_buts_bokehimage;
2844                         break;
2845                 case CMP_NODE_BOKEHBLUR:
2846                         ntype->uifunc = node_composit_buts_bokehblur;
2847                         break;
2848                 case CMP_NODE_VIEWER:
2849                         ntype->uifunc = NULL;
2850                         ntype->uifuncbut = node_composit_buts_viewer_but;
2851                         ntype->uibackdropfunc = node_composit_backdrop_viewer;
2852                         break;
2853                 case CMP_NODE_MASK:
2854                         ntype->uifunc = node_composit_buts_mask;
2855                         break;
2856                 case CMP_NODE_KEYINGSCREEN:
2857                         ntype->uifunc = node_composit_buts_keyingscreen;
2858                         break;
2859                 case CMP_NODE_KEYING:
2860                         ntype->uifunc = node_composit_buts_keying;
2861                         break;
2862                 case CMP_NODE_TRACKPOS:
2863                         ntype->uifunc = node_composit_buts_trackpos;
2864                         break;
2865                 default:
2866                         ntype->uifunc = NULL;
2867         }
2868 }
2869
2870 /* ****************** BUTTON CALLBACKS FOR TEXTURE NODES ***************** */
2871
2872 static void node_texture_buts_bricks(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2873 {
2874         uiLayout *col;
2875         
2876         col = uiLayoutColumn(layout, TRUE);
2877         uiItemR(col, ptr, "offset", 0, IFACE_("Offset"), ICON_NONE);
2878         uiItemR(col, ptr, "offset_frequency", 0, IFACE_("Frequency"), ICON_NONE);
2879         
2880         col = uiLayoutColumn(layout, TRUE);
2881         uiItemR(col, ptr, "squash", 0, IFACE_("Squash"), ICON_NONE);
2882         uiItemR(col, ptr, "squash_frequency", 0, IFACE_("Frequency"), ICON_NONE);
2883 }
2884
2885 static void node_texture_buts_proc(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2886 {
2887         PointerRNA tex_ptr;
2888         bNode *node = ptr->data;
2889         ID *id = ptr->id.data;
2890         Tex *tex = (Tex *)node->storage;
2891         uiLayout *col, *row;
2892         
2893         RNA_pointer_create(id, &RNA_Texture, tex, &tex_ptr);
2894
2895         col = uiLayoutColumn(layout, FALSE);
2896
2897         switch (tex->type) {
2898                 case TEX_BLEND:
2899                         uiItemR(col, &tex_ptr, "progression", 0, "", ICON_NONE);
2900                         row = uiLayoutRow(col, FALSE);
2901                         uiItemR(row, &tex_ptr, "use_flip_axis", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
2902                         break;
2903
2904                 case TEX_MARBLE:
2905                         row = uiLayoutRow(col, FALSE);
2906                         uiItemR(row, &tex_ptr, "marble_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
2907                         row = uiLayoutRow(col, FALSE);
2908                         uiItemR(row, &tex_ptr, "noise_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
2909                         row = uiLayoutRow(col, FALSE);
2910                         uiItemR(row, &tex_ptr, "noise_basis", 0, "", ICON_NONE);
2911                         row = uiLayoutRow(col, FALSE);
2912                         uiItemR(row, &tex_ptr, "noise_basis_2", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
2913                         break;
2914
2915                 case TEX_MAGIC:
2916                         uiItemR(col, &tex_ptr, "noise_depth", 0, NULL, ICON_NONE);
2917                         break;
2918
2919                 case TEX_STUCCI:
2920                         row = uiLayoutRow(col, FALSE);
2921                         uiItemR(row, &tex_ptr, "stucci_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
2922                         row = uiLayoutRow(col, FALSE);
2923                         uiItemR(row, &tex_ptr, "noise_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
2924                         uiItemR(col, &tex_ptr, "noise_basis", 0, "", ICON_NONE);
2925                         break;
2926
2927                 case TEX_WOOD:
2928                         uiItemR(col, &tex_ptr, "noise_basis", 0, "", ICON_NONE);
2929                         uiItemR(col, &tex_ptr, "wood_type", 0, "", ICON_NONE);
2930                         row = uiLayoutRow(col, FALSE);
2931                         uiItemR(row, &tex_ptr, "noise_basis_2", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
2932                         row = uiLayoutRow(col, FALSE);
2933                         uiLayoutSetActive(row, !(ELEM(tex->stype, TEX_BAND, TEX_RING)));
2934                         uiItemR(row, &tex_ptr, "noise_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
2935                         break;
2936                         
2937                 case TEX_CLOUDS:
2938                         uiItemR(col, &tex_ptr, "noise_basis", 0, "", ICON_NONE);
2939                         row = uiLayoutRow(col, FALSE);
2940                         uiItemR(row, &tex_ptr, "cloud_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
2941                         row = uiLayoutRow(col, FALSE);
2942                         uiItemR(row, &tex_ptr, "noise_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
2943                         uiItemR(col, &tex_ptr, "noise_depth", UI_ITEM_R_EXPAND, IFACE_("Depth"), ICON_NONE);
2944                         break;
2945                         
2946                 case TEX_DISTNOISE:
2947                         uiItemR(col, &tex_ptr, "noise_basis", 0, "", ICON_NONE);
2948                         uiItemR(col, &tex_ptr, "noise_distortion", 0, "", ICON_NONE);
2949                         break;
2950
2951                 case TEX_MUSGRAVE:
2952                         uiItemR(col, &tex_ptr, "musgrave_type", 0, "", ICON_NONE);
2953                         uiItemR(col, &tex_ptr, "noise_basis", 0, "", ICON_NONE);
2954                         break;
2955                 case TEX_VORONOI:
2956                         uiItemR(col, &tex_ptr, "distance_metric", 0, "", ICON_NONE);
2957                         if (tex->vn_distm == TEX_MINKOVSKY) {
2958                                 uiItemR(col, &tex_ptr, "minkovsky_exponent", 0, NULL, ICON_NONE);
2959                         }
2960                         uiItemR(col, &tex_ptr, "color_mode", 0, "", ICON_NONE);
2961                         break;
2962         }
2963 }
2964
2965 static void node_texture_buts_image(uiLayout *layout, bContext *C, PointerRNA *ptr)
2966 {
2967         uiTemplateID(layout, C, ptr, "image", NULL, "IMAGE_OT_open", NULL);
2968 }
2969
2970 static void node_texture_buts_output(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2971 {
2972         uiItemR(layout, ptr, "filepath", 0, "", ICON_NONE);
2973 }
2974
2975 /* only once called */
2976 static void node_texture_set_butfunc(bNodeType *ntype)
2977 {
2978         if (ntype->type >= TEX_NODE_PROC && ntype->type < TEX_NODE_PROC_MAX) {
2979                 ntype->uifunc = node_texture_buts_proc;
2980         }
2981         else {
2982                 switch (ntype->type) {
2983
2984                         case TEX_NODE_MATH:
2985                                 ntype->uifunc = node_buts_math;
2986                                 break;
2987
2988                         case TEX_NODE_MIX_RGB:
2989                                 ntype->uifunc = node_buts_mix_rgb;
2990                                 break;
2991
2992                         case TEX_NODE_VALTORGB:
2993                                 ntype->uifunc = node_buts_colorramp;
2994                                 break;
2995
2996                         case TEX_NODE_CURVE_RGB:
2997                                 ntype->uifunc = node_buts_curvecol;
2998                                 break;
2999
3000                         case TEX_NODE_CURVE_TIME:
3001                                 ntype->uifunc = node_buts_time;
3002                                 break;
3003
3004                         case TEX_NODE_TEXTURE:
3005                                 ntype->uifunc = node_buts_texture;
3006                                 break;
3007
3008                         case TEX_NODE_BRICKS:
3009                                 ntype->uifunc = node_texture_buts_bricks;
3010                                 break;
3011
3012                         case TEX_NODE_IMAGE:
3013                                 ntype->uifunc = node_texture_buts_image;
3014                                 break;
3015
3016                         case TEX_NODE_OUTPUT:
3017                                 ntype->uifunc = node_texture_buts_output;
3018                                 break;
3019                 }
3020         }
3021 }
3022
3023 /* ******* init draw callbacks for all tree types, only called in usiblender.c, once ************* */
3024
3025 void ED_node_init_butfuncs(void)
3026 {
3027         bNodeTreeType *treetype;
3028         bNodeType *ntype;
3029         bNodeSocketType *stype;
3030         int i;
3031         
3032         /* node type ui functions */
3033         for (i = 0; i < NUM_NTREE_TYPES; ++i) {
3034                 treetype = ntreeGetType(i);
3035                 if (treetype) {
3036                         for (ntype = treetype->node_types.first; ntype; ntype = ntype->next) {
3037                                 /* default ui functions */
3038                                 ntype->drawfunc = node_draw_default;
3039                                 ntype->drawupdatefunc = node_update_default;
3040                                 ntype->select_area_func = node_select_area_default;
3041                                 ntype->tweak_area_func = node_tweak_area_default;
3042                                 ntype->uifunc = NULL;
3043                                 ntype->uifuncbut = NULL;
3044                                 ntype->drawinputfunc = node_draw_input_default;
3045                                 ntype->drawoutputfunc = node_draw_output_default;
3046                                 ntype->resize_area_func = node_resize_area_default;
3047                                 
3048                                 node_common_set_butfunc(ntype);
3049                                 
3050                                 switch (i) {
3051                                         case NTREE_COMPOSIT:
3052                                                 node_composit_set_butfunc(ntype);
3053                                                 break;
3054                                         case NTREE_SHADER:
3055                                                 node_shader_set_butfunc(ntype);
3056                                                 break;
3057                                         case NTREE_TEXTURE:
3058                                                 node_texture_set_butfunc(ntype);
3059                                                 break;
3060                                 }
3061                         }
3062                 }
3063         }
3064         
3065         /* socket type ui functions */
3066         for (i = 0; i < NUM_SOCKET_TYPES; ++i) {
3067                 stype = ntreeGetSocketType(i);
3068                 if (stype) {
3069                         switch (stype->type) {
3070                                 case SOCK_FLOAT:
3071                                 case SOCK_INT:
3072                                 case SOCK_BOOLEAN:
3073                                         stype->buttonfunc = node_socket_button_default;
3074                                         break;
3075                                 case SOCK_VECTOR:
3076                                         stype->buttonfunc = node_socket_button_components;
3077                                         break;
3078                                 case SOCK_RGBA:
3079                                         stype->buttonfunc = node_socket_button_color;
3080                                         break;
3081                                 case SOCK_SHADER:
3082                                         stype->buttonfunc = node_socket_button_label;
3083                                         break;
3084                                 default:
3085                                         stype->buttonfunc = NULL;
3086                         }
3087                 }
3088         }
3089 }
3090
3091 /* ************** Generic drawing ************** */
3092
3093 void draw_nodespace_back_pix(const bContext *C, ARegion *ar, SpaceNode *snode)
3094 {
3095         
3096         if ((snode->flag & SNODE_BACKDRAW) && snode->treetype == NTREE_COMPOSIT) {
3097                 Image *ima = BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
3098                 void *lock;
3099                 ImBuf *ibuf = BKE_image_acquire_ibuf(ima, NULL, &lock);
3100                 if (ibuf) {
3101                         float x, y; 
3102                         unsigned char *display_buffer;
3103                         void *cache_handle;
3104                         
3105                         glMatrixMode(GL_PROJECTION);
3106                         glPushMatrix();
3107                         glMatrixMode(GL_MODELVIEW);
3108                         glPushMatrix();
3109
3110                         /* keep this, saves us from a version patch */
3111                         if (snode->zoom == 0.0f) snode->zoom = 1.0f;
3112                         
3113                         /* somehow the offset has to be calculated inverse */
3114                         
3115                         glaDefine2DArea(&ar->winrct);
3116                         /* ortho at pixel level curarea */
3117                         wmOrtho2(-GLA_PIXEL_OFS, ar->winx - GLA_PIXEL_OFS, -GLA_PIXEL_OFS, ar->winy - GLA_PIXEL_OFS);
3118                         
3119                         x = (ar->winx - snode->zoom * ibuf->x) / 2 + snode->xof;
3120                         y = (ar->winy - snode->zoom * ibuf->y) / 2 + snode->yof;
3121                         
3122
3123                         display_buffer = IMB_display_buffer_acquire_ctx(C, ibuf, &cache_handle);
3124
3125                         if (display_buffer) {
3126                                 if (snode->flag & (SNODE_SHOW_R | SNODE_SHOW_G | SNODE_SHOW_B)) {
3127                            &nb