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