ffc780ebf6971600440a6f3e6ff413dedcadb7e1
[blender.git] / source / blender / editors / space_node / drawnode.c
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version. 
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * The Original Code is Copyright (C) 2005 Blender Foundation.
19  * All rights reserved.
20  *
21  * The Original Code is: all of this file.
22  *
23  * Contributor(s): David Millan Escriva, Juho Vepsäläinen, Bob Holcomb, Thomas Dinges
24  *
25  * ***** END GPL LICENSE BLOCK *****
26  */
27
28 /** \file blender/editors/space_node/drawnode.c
29  *  \ingroup spnode
30  *  \brief lower level node drawing for nodes (boarders, headers etc), also node layout.
31  */
32
33 #include "BLI_blenlib.h"
34 #include "BLI_math.h"
35
36 #include "DNA_node_types.h"
37 #include "DNA_object_types.h"
38 #include "DNA_space_types.h"
39 #include "DNA_screen_types.h"
40
41 #include "BKE_context.h"
42 #include "BKE_curve.h"
43 #include "BKE_image.h"
44 #include "BKE_main.h"
45 #include "BKE_node.h"
46 #include "BKE_tracking.h"
47
48 #include "BLF_api.h"
49 #include "BLF_translation.h"
50
51
52 #include "BIF_gl.h"
53 #include "BIF_glutil.h"
54
55 #include "MEM_guardedalloc.h"
56
57 #include "RNA_access.h"
58
59 #include "ED_node.h"
60
61 #include "WM_api.h"
62 #include "WM_types.h"
63
64 #include "UI_resources.h"
65
66 #include "IMB_colormanagement.h"
67 #include "IMB_imbuf.h"
68 #include "IMB_imbuf_types.h"
69
70 #include "node_intern.h"  /* own include */
71
72 /* ****************** SOCKET BUTTON DRAW FUNCTIONS ***************** */
73
74 static void node_sync_cb(bContext *UNUSED(C), void *snode_v, void *node_v)
75 {
76         SpaceNode *snode = snode_v;
77         
78         if (snode->treetype == NTREE_SHADER) {
79                 nodeShaderSynchronizeID(node_v, 1);
80                 // allqueue(REDRAWBUTSSHADING, 0);
81         }
82 }
83
84 static void node_socket_button_label(const bContext *UNUSED(C), uiBlock *block,
85                                      bNodeTree *UNUSED(ntree), bNode *UNUSED(node), bNodeSocket *sock,
86                                      const char *UNUSED(name), int x, int y, int width)
87 {
88         uiDefBut(block, LABEL, 0, IFACE_(sock->name), x, y, width, NODE_DY, NULL, 0, 0, 0, 0, "");
89 }
90
91 static void node_socket_button_default(const bContext *C, uiBlock *block,
92                                        bNodeTree *ntree, bNode *node, bNodeSocket *sock,
93                                        const char *name, int x, int y, int width)
94 {
95         if (sock->link || (sock->flag & SOCK_HIDE_VALUE))
96                 node_socket_button_label(C, block, ntree, node, sock, name, x, y, width);
97         else {
98                 PointerRNA ptr;
99                 uiBut *bt;
100                 
101                 RNA_pointer_create(&ntree->id, &RNA_NodeSocket, sock, &ptr);
102                 
103                 bt = uiDefButR(block, NUM, B_NODE_EXEC, IFACE_(name),
104                                x, y + 1, width, NODE_DY - 2,
105                                &ptr, "default_value", 0, 0, 0, -1, -1, NULL);
106                 if (node)
107                         uiButSetFunc(bt, node_sync_cb, CTX_wm_space_node(C), node);
108         }
109 }
110
111 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, "");
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         if (!node->id)
1612                 return;
1613
1614         imaptr = RNA_pointer_get(ptr, "image");
1615
1616         uiTemplateColorspaceSettings(layout, &imaptr, "colorspace_settings");
1617 }
1618
1619 static void node_composit_buts_renderlayers(uiLayout *layout, bContext *C, PointerRNA *ptr)
1620 {
1621         bNode *node = ptr->data;
1622         uiLayout *col, *row;
1623         PointerRNA op_ptr;
1624         PointerRNA scn_ptr;
1625         PropertyRNA *prop;
1626         const char *layer_name;
1627         char scene_name[MAX_ID_NAME - 2];
1628         wmOperatorType *ot = WM_operatortype_find("RENDER_OT_render", 1);
1629
1630         BLI_assert(ot != 0);
1631
1632         uiTemplateID(layout, C, ptr, "scene", NULL, NULL, NULL);
1633         
1634         if (!node->id) return;
1635
1636         col = uiLayoutColumn(layout, FALSE);
1637         row = uiLayoutRow(col, FALSE);
1638         uiItemR(row, ptr, "layer", 0, "", ICON_NONE);
1639         
1640         prop = RNA_struct_find_property(ptr, "layer");
1641         if (!(RNA_property_enum_identifier(C, ptr, prop, RNA_property_enum_get(ptr, prop), &layer_name)))
1642                 return;
1643         
1644         scn_ptr = RNA_pointer_get(ptr, "scene");
1645         RNA_string_get(&scn_ptr, "name", scene_name);
1646         
1647         WM_operator_properties_create_ptr(&op_ptr, ot);
1648         RNA_string_set(&op_ptr, "layer", layer_name);
1649         RNA_string_set(&op_ptr, "scene", scene_name);
1650         uiItemFullO_ptr(row, ot, "", ICON_RENDER_STILL, op_ptr.data, WM_OP_INVOKE_DEFAULT, 0);
1651
1652 }
1653
1654
1655 static void node_composit_buts_blur(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1656 {
1657         uiLayout *col, *row;
1658         int reference;
1659         int filter;
1660         
1661         col = uiLayoutColumn(layout, FALSE);
1662         filter = RNA_enum_get(ptr, "filter_type");
1663         reference = RNA_boolean_get(ptr, "use_variable_size");
1664
1665         uiItemR(col, ptr, "filter_type", 0, "", ICON_NONE);
1666         if (filter != R_FILTER_FAST_GAUSS) {
1667                 uiItemR(col, ptr, "use_variable_size", 0, NULL, ICON_NONE);
1668                 if (!reference) {
1669                         uiItemR(col, ptr, "use_bokeh", 0, NULL, ICON_NONE);
1670                 }
1671                 uiItemR(col, ptr, "use_gamma_correction", 0, NULL, ICON_NONE);
1672         }
1673         
1674         uiItemR(col, ptr, "use_relative", 0, NULL, ICON_NONE);
1675         
1676         if (RNA_boolean_get(ptr, "use_relative")) {
1677                 uiItemL(col, IFACE_("Aspect Correction"), ICON_NONE);
1678                 row = uiLayoutRow(layout, TRUE);
1679                 uiItemR(row, ptr, "aspect_correction", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
1680                 
1681                 col = uiLayoutColumn(layout, TRUE);
1682                 uiItemR(col, ptr, "factor_x", 0, IFACE_("X"), ICON_NONE);
1683                 uiItemR(col, ptr, "factor_y", 0, IFACE_("Y"), ICON_NONE);
1684         }
1685         else {
1686                 col = uiLayoutColumn(layout, TRUE);
1687                 uiItemR(col, ptr, "size_x", 0, IFACE_("X"), ICON_NONE);
1688                 uiItemR(col, ptr, "size_y", 0, IFACE_("Y"), ICON_NONE);
1689         }
1690 }
1691
1692 static void node_composit_buts_dblur(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1693 {
1694         uiLayout *col;
1695         
1696         uiItemR(layout, ptr, "iterations", 0, NULL, ICON_NONE);
1697         uiItemR(layout, ptr, "use_wrap", 0, NULL, ICON_NONE);
1698         
1699         col = uiLayoutColumn(layout, TRUE);
1700         uiItemL(col, IFACE_("Center:"), ICON_NONE);
1701         uiItemR(col, ptr, "center_x", 0, IFACE_("X"), ICON_NONE);
1702         uiItemR(col, ptr, "center_y", 0, IFACE_("Y"), ICON_NONE);
1703         
1704         uiItemS(layout);
1705         
1706         col = uiLayoutColumn(layout, TRUE);
1707         uiItemR(col, ptr, "distance", 0, NULL, ICON_NONE);
1708         uiItemR(col, ptr, "angle", 0, NULL, ICON_NONE);
1709         
1710         uiItemS(layout);
1711         
1712         uiItemR(layout, ptr, "spin", 0, NULL, ICON_NONE);
1713         uiItemR(layout, ptr, "zoom", 0, NULL, ICON_NONE);
1714 }
1715
1716 static void node_composit_buts_bilateralblur(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1717 {       
1718         uiLayout *col;
1719         
1720         col = uiLayoutColumn(layout, TRUE);
1721         uiItemR(col, ptr, "iterations", 0, NULL, ICON_NONE);
1722         uiItemR(col, ptr, "sigma_color", 0, NULL, ICON_NONE);
1723         uiItemR(col, ptr, "sigma_space", 0, NULL, ICON_NONE);
1724 }
1725
1726 static void node_composit_buts_defocus(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1727 {
1728         uiLayout *sub, *col;
1729         
1730         col = uiLayoutColumn(layout, FALSE);
1731         uiItemL(col, IFACE_("Bokeh Type:"), ICON_NONE);
1732         uiItemR(col, ptr, "bokeh", 0, "", ICON_NONE);
1733         uiItemR(col, ptr, "angle", 0, NULL, ICON_NONE);
1734
1735         uiItemR(layout, ptr, "use_gamma_correction", 0, NULL, ICON_NONE);
1736
1737         col = uiLayoutColumn(layout, FALSE);
1738         uiLayoutSetActive(col, RNA_boolean_get(ptr, "use_zbuffer") == TRUE);
1739         uiItemR(col, ptr, "f_stop", 0, NULL, ICON_NONE);
1740
1741         uiItemR(layout, ptr, "blur_max", 0, NULL, ICON_NONE);
1742         uiItemR(layout, ptr, "threshold", 0, NULL, ICON_NONE);
1743
1744         col = uiLayoutColumn(layout, FALSE);
1745         uiItemR(col, ptr, "use_preview", 0, NULL, ICON_NONE);
1746         
1747         col = uiLayoutColumn(layout, FALSE);
1748         uiItemR(col, ptr, "use_zbuffer", 0, NULL, ICON_NONE);
1749         sub = uiLayoutColumn(col, FALSE);
1750         uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_zbuffer") == FALSE);
1751         uiItemR(sub, ptr, "z_scale", 0, NULL, ICON_NONE);
1752 }
1753
1754 /* qdn: glare node */
1755 static void node_composit_buts_glare(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1756 {       
1757         uiItemR(layout, ptr, "glare_type", 0, "", ICON_NONE);
1758         uiItemR(layout, ptr, "quality", 0, "", ICON_NONE);
1759
1760         if (RNA_enum_get(ptr, "glare_type") != 1) {
1761                 uiItemR(layout, ptr, "iterations", 0, NULL, ICON_NONE);
1762         
1763                 if (RNA_enum_get(ptr, "glare_type") != 0)
1764                         uiItemR(layout, ptr, "color_modulation", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
1765         }
1766         
1767         uiItemR(layout, ptr, "mix", 0, NULL, ICON_NONE);
1768         uiItemR(layout, ptr, "threshold", 0, NULL, ICON_NONE);
1769
1770         if (RNA_enum_get(ptr, "glare_type") == 2) {
1771                 uiItemR(layout, ptr, "streaks", 0, NULL, ICON_NONE);
1772                 uiItemR(layout, ptr, "angle_offset", 0, NULL, ICON_NONE);
1773         }
1774         if (RNA_enum_get(ptr, "glare_type") == 0 || RNA_enum_get(ptr, "glare_type") == 2) {
1775                 uiItemR(layout, ptr, "fade", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
1776                 
1777                 if (RNA_enum_get(ptr, "glare_type") == 0)
1778                         uiItemR(layout, ptr, "use_rotate_45", 0, NULL, ICON_NONE);
1779         }
1780         if (RNA_enum_get(ptr, "glare_type") == 1) {
1781                 uiItemR(layout, ptr, "size", 0, NULL, ICON_NONE);
1782         }
1783 }
1784
1785 static void node_composit_buts_tonemap(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1786 {       
1787         uiLayout *col;
1788
1789         col = uiLayoutColumn(layout, FALSE);
1790         uiItemR(col, ptr, "tonemap_type", 0, "", ICON_NONE);
1791         if (RNA_enum_get(ptr, "tonemap_type") == 0) {
1792                 uiItemR(col, ptr, "key", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
1793                 uiItemR(col, ptr, "offset", 0, NULL, ICON_NONE);
1794                 uiItemR(col, ptr, "gamma", 0, NULL, ICON_NONE);
1795         }
1796         else {
1797                 uiItemR(col, ptr, "intensity", 0, NULL, ICON_NONE);
1798                 uiItemR(col, ptr, "contrast", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
1799                 uiItemR(col, ptr, "adaptation", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
1800                 uiItemR(col, ptr, "correction", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
1801         }
1802 }
1803
1804 static void node_composit_buts_lensdist(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1805 {
1806         uiLayout *col;
1807
1808         col = uiLayoutColumn(layout, FALSE);
1809         uiItemR(col, ptr, "use_projector", 0, NULL, ICON_NONE);
1810
1811         col = uiLayoutColumn(col, FALSE);
1812         uiLayoutSetActive(col, RNA_boolean_get(ptr, "use_projector") == FALSE);
1813         uiItemR(col, ptr, "use_jitter", 0, NULL, ICON_NONE);
1814         uiItemR(col, ptr, "use_fit", 0, NULL, ICON_NONE);
1815 }
1816
1817 static void node_composit_buts_vecblur(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1818 {
1819         uiLayout *col;
1820         
1821         col = uiLayoutColumn(layout, FALSE);
1822         uiItemR(col, ptr, "samples", 0, NULL, ICON_NONE);
1823         uiItemR(col, ptr, "factor", 0, IFACE_("Blur"), ICON_NONE);
1824         
1825         col = uiLayoutColumn(layout, TRUE);
1826         uiItemL(col, IFACE_("Speed:"), ICON_NONE);
1827         uiItemR(col, ptr, "speed_min", 0, IFACE_("Min"), ICON_NONE);
1828         uiItemR(col, ptr, "speed_max", 0, IFACE_("Max"), ICON_NONE);
1829
1830         uiItemR(layout, ptr, "use_curved", 0, NULL, ICON_NONE);
1831 }
1832
1833 static void node_composit_buts_filter(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1834 {
1835         uiItemR(layout, ptr, "filter_type", 0, "", ICON_NONE);
1836 }
1837
1838 static void node_composit_buts_flip(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1839 {
1840         uiItemR(layout, ptr, "axis", 0, "", ICON_NONE);
1841 }
1842
1843 static void node_composit_buts_crop(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1844 {
1845         uiLayout *col;
1846
1847         uiItemR(layout, ptr, "use_crop_size", 0, NULL, ICON_NONE);
1848         uiItemR(layout, ptr, "relative", 0, NULL, ICON_NONE);
1849
1850         col = uiLayoutColumn(layout, TRUE);
1851         if (RNA_boolean_get(ptr, "relative")) {
1852                 uiItemR(col, ptr, "rel_min_x", 0, IFACE_("Left"), ICON_NONE);
1853                 uiItemR(col, ptr, "rel_max_x", 0, IFACE_("Right"), ICON_NONE);
1854                 uiItemR(col, ptr, "rel_min_y", 0, IFACE_("Up"), ICON_NONE);
1855                 uiItemR(col, ptr, "rel_max_y", 0, IFACE_("Down"), ICON_NONE);
1856         }
1857         else {
1858                 uiItemR(col, ptr, "min_x", 0, IFACE_("Left"), ICON_NONE);
1859                 uiItemR(col, ptr, "max_x", 0, IFACE_("Right"), ICON_NONE);
1860                 uiItemR(col, ptr, "min_y", 0, IFACE_("Up"), ICON_NONE);
1861                 uiItemR(col, ptr, "max_y", 0, IFACE_("Down"), ICON_NONE);
1862         }
1863 }
1864
1865 static void node_composit_buts_splitviewer(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1866 {
1867         uiLayout *row, *col;
1868         
1869         col = uiLayoutColumn(layout, FALSE);
1870         row = uiLayoutRow(col, FALSE);
1871         uiItemR(row, ptr, "axis", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
1872         uiItemR(col, ptr, "factor", 0, NULL, ICON_NONE);
1873 }
1874
1875 static void node_composit_buts_double_edge_mask(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1876 {
1877         uiLayout *col;
1878
1879         col = uiLayoutColumn(layout, FALSE);
1880
1881         uiItemL(col, IFACE_("Inner Edge:"), ICON_NONE);
1882         uiItemR(col, ptr, "inner_mode", 0, "", ICON_NONE);
1883         uiItemL(col, IFACE_("Buffer Edge:"), ICON_NONE);
1884         uiItemR(col, ptr, "edge_mode", 0, "", ICON_NONE);
1885 }
1886
1887 static void node_composit_buts_map_range(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1888 {
1889         uiLayout *col;
1890
1891         col = uiLayoutColumn(layout, TRUE);
1892         uiItemR(col, ptr, "use_clamp", 0, NULL, ICON_NONE);
1893 }
1894
1895 static void node_composit_buts_map_value(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1896 {
1897         uiLayout *sub, *col;
1898         
1899         col = uiLayoutColumn(layout, TRUE);
1900         uiItemR(col, ptr, "offset", 0, NULL, ICON_NONE);
1901         uiItemR(col, ptr, "size", 0, NULL, ICON_NONE);
1902         
1903         col = uiLayoutColumn(layout, TRUE);
1904         uiItemR(col, ptr, "use_min", 0, NULL, ICON_NONE);
1905         sub = uiLayoutColumn(col, FALSE);
1906         uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_min"));
1907         uiItemR(sub, ptr, "min", 0, "", ICON_NONE);
1908         
1909         col = uiLayoutColumn(layout, TRUE);
1910         uiItemR(col, ptr, "use_max", 0, NULL, ICON_NONE);
1911         sub = uiLayoutColumn(col, FALSE);
1912         uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_max"));
1913         uiItemR(sub, ptr, "max", 0, "", ICON_NONE);
1914 }
1915
1916 static void node_composit_buts_alphaover(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1917 {       
1918         uiLayout *col;
1919         
1920         col = uiLayoutColumn(layout, TRUE);
1921         uiItemR(col, ptr, "use_premultiply", 0, NULL, ICON_NONE);
1922         uiItemR(col, ptr, "premul", 0, NULL, ICON_NONE);
1923 }
1924
1925 static void node_composit_buts_zcombine(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1926 {       
1927         uiLayout *col;
1928         
1929         col = uiLayoutColumn(layout, TRUE);
1930         uiItemR(col, ptr, "use_alpha", 0, NULL, ICON_NONE);
1931 }
1932
1933
1934 static void node_composit_buts_hue_sat(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1935 {
1936         uiLayout *col;
1937         
1938         col = uiLayoutColumn(layout, FALSE);
1939         uiItemR(col, ptr, "color_hue", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
1940         uiItemR(col, ptr, "color_saturation", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
1941         uiItemR(col, ptr, "color_value", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
1942 }
1943
1944 static void node_composit_buts_dilateerode(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1945 {
1946         uiItemR(layout, ptr, "mode", 0, NULL, ICON_NONE);
1947         uiItemR(layout, ptr, "distance", 0, NULL, ICON_NONE);
1948         switch (RNA_enum_get(ptr, "mode")) {
1949                 case CMP_NODE_DILATEERODE_DISTANCE_THRESH:
1950                         uiItemR(layout, ptr, "edge", 0, NULL, ICON_NONE);
1951                         break;
1952                 case CMP_NODE_DILATEERODE_DISTANCE_FEATHER:
1953                         uiItemR(layout, ptr, "falloff", 0, NULL, ICON_NONE);
1954                         break;
1955         }
1956 }
1957
1958 static void node_composit_buts_inpaint(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1959 {
1960         uiItemR(layout, ptr, "distance", 0, NULL, ICON_NONE);
1961 }
1962
1963 static void node_composit_buts_despeckle(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1964 {
1965         uiLayout *col;
1966
1967         col = uiLayoutColumn(layout, FALSE);
1968         uiItemR(col, ptr, "threshold", 0, NULL, ICON_NONE);
1969         uiItemR(col, ptr, "threshold_neighbour", 0, NULL, ICON_NONE);
1970 }
1971
1972 static void node_composit_buts_diff_matte(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1973 {
1974         uiLayout *col;
1975         
1976         col = uiLayoutColumn(layout, TRUE);
1977         uiItemR(col, ptr, "tolerance", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
1978         uiItemR(col, ptr, "falloff", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
1979 }
1980
1981 static void node_composit_buts_distance_matte(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1982 {
1983         uiLayout *col, *row;
1984         
1985         col = uiLayoutColumn(layout, TRUE);
1986    
1987         uiItemL(layout, IFACE_("Color Space:"), ICON_NONE);
1988         row = uiLayoutRow(layout, FALSE);
1989         uiItemR(row, ptr, "channel", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
1990
1991         uiItemR(col, ptr, "tolerance", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
1992         uiItemR(col, ptr, "falloff", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
1993 }
1994
1995 static void node_composit_buts_color_spill(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1996 {
1997         uiLayout *row, *col;
1998         
1999         uiItemL(layout, IFACE_("Despill Channel:"), ICON_NONE);
2000         row = uiLayoutRow(layout, FALSE);
2001         uiItemR(row, ptr, "channel", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
2002
2003         col = uiLayoutColumn(layout, FALSE);
2004         uiItemR(col, ptr, "limit_method", 0, NULL, ICON_NONE);
2005
2006         if (RNA_enum_get(ptr, "limit_method") == 0) {
2007                 uiItemL(col, IFACE_("Limiting Channel:"), ICON_NONE);
2008                 row = uiLayoutRow(col, FALSE);
2009                 uiItemR(row, ptr, "limit_channel", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
2010         }
2011
2012         uiItemR(col, ptr, "ratio", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2013         uiItemR(col, ptr, "use_unspill", 0, NULL, ICON_NONE);
2014         if (RNA_boolean_get(ptr, "use_unspill") == TRUE) {
2015                 uiItemR(col, ptr, "unspill_red", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2016                 uiItemR(col, ptr, "unspill_green", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2017                 uiItemR(col, ptr, "unspill_blue", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2018         }
2019 }
2020
2021 static void node_composit_buts_chroma_matte(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2022 {
2023         uiLayout *col;
2024         
2025         col = uiLayoutColumn(layout, FALSE);
2026         uiItemR(col, ptr, "tolerance", 0, NULL, ICON_NONE);
2027         uiItemR(col, ptr, "threshold", 0, NULL, ICON_NONE);
2028         
2029         col = uiLayoutColumn(layout, TRUE);
2030         /*uiItemR(col, ptr, "lift", UI_ITEM_R_SLIDER, NULL, ICON_NONE);  Removed for now */
2031         uiItemR(col, ptr, "gain", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2032         /*uiItemR(col, ptr, "shadow_adjust", UI_ITEM_R_SLIDER, NULL, ICON_NONE);  Removed for now*/
2033 }
2034
2035 static void node_composit_buts_color_matte(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2036 {
2037         uiLayout *col;
2038         
2039         col = uiLayoutColumn(layout, TRUE);
2040         uiItemR(col, ptr, "color_hue", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2041         uiItemR(col, ptr, "color_saturation", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2042         uiItemR(col, ptr, "color_value", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2043 }
2044
2045 static void node_composit_buts_channel_matte(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2046 {       
2047         uiLayout *col, *row;
2048
2049         uiItemL(layout, IFACE_("Color Space:"), ICON_NONE);
2050         row = uiLayoutRow(layout, FALSE);
2051         uiItemR(row, ptr, "color_space", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
2052
2053         col = uiLayoutColumn(layout, FALSE);
2054         uiItemL(col, IFACE_("Key Channel:"), ICON_NONE);
2055         row = uiLayoutRow(col, FALSE);
2056         uiItemR(row, ptr, "matte_channel", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
2057
2058         col = uiLayoutColumn(layout, FALSE);
2059
2060         uiItemR(col, ptr, "limit_method", 0, NULL, ICON_NONE);
2061         if (RNA_enum_get(ptr, "limit_method") == 0) {
2062                 uiItemL(col, IFACE_("Limiting Channel:"), ICON_NONE);
2063                 row = uiLayoutRow(col, FALSE);
2064                 uiItemR(row, ptr, "limit_channel", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
2065         }
2066
2067         uiItemR(col, ptr, "limit_max", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2068         uiItemR(col, ptr, "limit_min", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2069 }
2070
2071 static void node_composit_buts_luma_matte(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2072 {
2073         uiLayout *col;
2074         
2075         col = uiLayoutColumn(layout, TRUE);
2076         uiItemR(col, ptr, "limit_max", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2077         uiItemR(col, ptr, "limit_min", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2078 }
2079
2080 static void node_composit_buts_map_uv(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2081 {
2082         uiItemR(layout, ptr, "alpha", 0, NULL, ICON_NONE);
2083 }
2084
2085 static void node_composit_buts_id_mask(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2086 {
2087         uiItemR(layout, ptr, "index", 0, NULL, ICON_NONE);
2088         uiItemR(layout, ptr, "use_antialiasing", 0, NULL, ICON_NONE);
2089 }
2090
2091 /* draw function for file output node sockets, displays only sub-path and format, no value button */
2092 static void node_draw_input_file_output(const bContext *C, uiBlock *block,
2093                                         bNodeTree *ntree, bNode *node, bNodeSocket *sock,
2094                                         const char *UNUSED(name), int x, int y, int width)
2095 {
2096         uiLayout *layout, *row;
2097         PointerRNA nodeptr, inputptr, imfptr;
2098         int imtype;
2099         int rx, ry;
2100         RNA_pointer_create(&ntree->id, &RNA_Node, node, &nodeptr);
2101         
2102         layout = uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, x, y + NODE_DY, width, 20, UI_GetStyle());
2103         row = uiLayoutRow(layout, FALSE);
2104         
2105         imfptr = RNA_pointer_get(&nodeptr, "format");
2106         imtype = RNA_enum_get(&imfptr, "file_format");
2107         if (imtype == R_IMF_IMTYPE_MULTILAYER) {
2108                 NodeImageMultiFileSocket *input = sock->storage;
2109                 RNA_pointer_create(&ntree->id, &RNA_NodeOutputFileSlotLayer, input, &inputptr);
2110                 
2111                 uiItemL(row, input->layer, ICON_NONE);
2112         }
2113         else {
2114                 NodeImageMultiFileSocket *input = sock->storage;
2115                 PropertyRNA *imtype_prop;
2116                 const char *imtype_name;
2117                 RNA_pointer_create(&ntree->id, &RNA_NodeOutputFileSlotFile, input, &inputptr);
2118                 
2119                 uiItemL(row, input->path, ICON_NONE);
2120                 
2121                 if (!RNA_boolean_get(&inputptr, "use_node_format"))
2122                         imfptr = RNA_pointer_get(&inputptr, "format");
2123                 
2124                 imtype_prop = RNA_struct_find_property(&imfptr, "file_format");
2125                 RNA_property_enum_name((bContext *)C, &imfptr, imtype_prop,
2126                                        RNA_property_enum_get(&imfptr, imtype_prop), &imtype_name);
2127                 uiBlockSetEmboss(block, UI_EMBOSSP);
2128                 uiItemL(row, imtype_name, ICON_NONE);
2129                 uiBlockSetEmboss(block, UI_EMBOSSN);
2130         }
2131         
2132         uiBlockLayoutResolve(block, &rx, &ry);
2133 }
2134 static void node_composit_buts_file_output(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2135 {
2136         PointerRNA imfptr = RNA_pointer_get(ptr, "format");
2137         int multilayer = (RNA_enum_get(&imfptr, "file_format") == R_IMF_IMTYPE_MULTILAYER);
2138         
2139         if (multilayer)
2140                 uiItemL(layout, IFACE_("Path:"), ICON_NONE);
2141         else
2142                 uiItemL(layout, IFACE_("Base Path:"), ICON_NONE);
2143         uiItemR(layout, ptr, "base_path", 0, "", ICON_NONE);
2144 }
2145 static void node_composit_buts_file_output_details(uiLayout *layout, bContext *C, PointerRNA *ptr)
2146 {
2147         PointerRNA imfptr = RNA_pointer_get(ptr, "format");
2148         PointerRNA active_input_ptr, op_ptr;
2149         uiLayout *row, *col;
2150         int active_index;
2151         int multilayer = (RNA_enum_get(&imfptr, "file_format") == R_IMF_IMTYPE_MULTILAYER);
2152         
2153         node_composit_buts_file_output(layout, C, ptr);
2154         uiTemplateImageSettings(layout, &imfptr, FALSE);
2155         
2156         uiItemS(layout);
2157         
2158         uiItemO(layout, IFACE_("Add Input"), ICON_ZOOMIN, "NODE_OT_output_file_add_socket");
2159         
2160         row = uiLayoutRow(layout, FALSE);
2161         col = uiLayoutColumn(row, TRUE);
2162         
2163         active_index = RNA_int_get(ptr, "active_input_index");
2164         /* using different collection properties if multilayer format is enabled */
2165         if (multilayer) {
2166                 uiTemplateList(col, C, "UI_UL_list", "", ptr, "layer_slots", ptr, "active_input_index", 0, 0, 0);
2167                 RNA_property_collection_lookup_int(ptr, RNA_struct_find_property(ptr, "layer_slots"),
2168                                                    active_index, &active_input_ptr);
2169         }
2170         else {
2171                 uiTemplateList(col, C, "UI_UL_list", "", ptr, "file_slots", ptr, "active_input_index", 0, 0, 0);
2172                 RNA_property_collection_lookup_int(ptr, RNA_struct_find_property(ptr, "file_slots"),
2173                                                    active_index, &active_input_ptr);
2174         }
2175         /* XXX collection lookup does not return the ID part of the pointer, setting this manually here */
2176         active_input_ptr.id.data = ptr->id.data;
2177         
2178         col = uiLayoutColumn(row, TRUE);
2179         op_ptr = uiItemFullO(col, "NODE_OT_output_file_move_active_socket", "",
2180                              ICON_TRIA_UP, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS);
2181         RNA_enum_set(&op_ptr, "direction", 1);
2182         op_ptr = uiItemFullO(col, "NODE_OT_output_file_move_active_socket", "",
2183                              ICON_TRIA_DOWN, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS);
2184         RNA_enum_set(&op_ptr, "direction", 2);
2185         
2186         if (active_input_ptr.data) {
2187                 if (multilayer) {
2188                         col = uiLayoutColumn(layout, TRUE);
2189                         
2190                         uiItemL(col, IFACE_("Layer:"), ICON_NONE);
2191                         row = uiLayoutRow(col, FALSE);
2192                         uiItemR(row, &active_input_ptr, "name", 0, "", ICON_NONE);
2193                         uiItemFullO(row, "NODE_OT_output_file_remove_active_socket", "",
2194                                     ICON_X, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_R_ICON_ONLY);
2195                 }
2196                 else {
2197                         col = uiLayoutColumn(layout, TRUE);
2198                         
2199                         uiItemL(col, IFACE_("File Path:"), ICON_NONE);
2200                         row = uiLayoutRow(col, FALSE);
2201                         uiItemR(row, &active_input_ptr, "path", 0, "", ICON_NONE);
2202                         uiItemFullO(row, "NODE_OT_output_file_remove_active_socket", "",
2203                                     ICON_X, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_R_ICON_ONLY);
2204                         
2205                         /* format details for individual files */
2206                         imfptr = RNA_pointer_get(&active_input_ptr, "format");
2207                         
2208                         col = uiLayoutColumn(layout, TRUE);
2209                         uiItemL(col, IFACE_("Format:"), ICON_NONE);
2210                         uiItemR(col, &active_input_ptr, "use_node_format", 0, NULL, ICON_NONE);
2211                         
2212                         col = uiLayoutColumn(layout, FALSE);
2213                         uiLayoutSetActive(col, RNA_boolean_get(&active_input_ptr, "use_node_format") == FALSE);
2214                         uiTemplateImageSettings(col, &imfptr, FALSE);
2215                 }
2216         }
2217 }
2218
2219 static void node_composit_buts_scale(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2220 {
2221         uiItemR(layout, ptr, "space", 0, "", ICON_NONE);
2222
2223         if (RNA_enum_get(ptr, "space") == CMP_SCALE_RENDERPERCENT) {
2224                 uiLayout *row;
2225                 uiItemR(layout, ptr, "frame_method", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
2226                 row = uiLayoutRow(layout, TRUE);
2227                 uiItemR(row, ptr, "offset_x", 0, "X", ICON_NONE);
2228                 uiItemR(row, ptr, "offset_y", 0, "Y", ICON_NONE);
2229         }
2230 }
2231
2232 static void node_composit_buts_rotate(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2233 {
2234         uiItemR(layout, ptr, "filter_type", 0, "", ICON_NONE);
2235 }
2236
2237 static void node_composit_buts_invert(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2238 {
2239         uiLayout *col;
2240         
2241         col = uiLayoutColumn(layout, FALSE);
2242         uiItemR(col, ptr, "invert_rgb", 0, NULL, ICON_NONE);
2243         uiItemR(col, ptr, "invert_alpha", 0, NULL, ICON_NONE);
2244 }
2245
2246 static void node_composit_buts_premulkey(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2247 {
2248         uiItemR(layout, ptr, "mapping", 0, "", ICON_NONE);
2249 }
2250
2251 static void node_composit_buts_view_levels(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2252 {
2253         uiItemR(layout, ptr, "channel", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
2254 }
2255
2256 static void node_composit_buts_colorbalance(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2257 {
2258         uiLayout *split, *col, *row;
2259         
2260         uiItemR(layout, ptr, "correction_method", 0, NULL, ICON_NONE);
2261         
2262         if (RNA_enum_get(ptr, "correction_method") == 0) {
2263         
2264                 split = uiLayoutSplit(layout, 0.0f, FALSE);
2265                 col = uiLayoutColumn(split, FALSE);
2266                 uiTemplateColorPicker(col, ptr, "lift", 1, 1, 0, 1);
2267                 row = uiLayoutRow(col, FALSE);
2268                 uiItemR(row, ptr, "lift", 0, NULL, ICON_NONE);
2269                 
2270                 col = uiLayoutColumn(split, FALSE);
2271                 uiTemplateColorPicker(col, ptr, "gamma", 1, 1, 1, 1);
2272                 row = uiLayoutRow(col, FALSE);
2273                 uiItemR(row, ptr, "gamma", 0, NULL, ICON_NONE);
2274                 
2275                 col = uiLayoutColumn(split, FALSE);
2276                 uiTemplateColorPicker(col, ptr, "gain", 1, 1, 1, 1);
2277                 row = uiLayoutRow(col, FALSE);
2278                 uiItemR(row, ptr, "gain", 0, NULL, ICON_NONE);
2279
2280         }
2281         else {
2282                 
2283                 split = uiLayoutSplit(layout, 0.0f, FALSE);
2284                 col = uiLayoutColumn(split, FALSE);
2285                 uiTemplateColorPicker(col, ptr, "offset", 1, 1, 0, 1);
2286                 row = uiLayoutRow(col, FALSE);
2287                 uiItemR(row, ptr, "offset", 0, NULL, ICON_NONE);
2288                 
2289                 col = uiLayoutColumn(split, FALSE);
2290                 uiTemplateColorPicker(col, ptr, "power", 1, 1, 0, 1);
2291                 row = uiLayoutRow(col, FALSE);
2292                 uiItemR(row, ptr, "power", 0, NULL, ICON_NONE);
2293                 
2294                 col = uiLayoutColumn(split, FALSE);
2295                 uiTemplateColorPicker(col, ptr, "slope", 1, 1, 0, 1);
2296                 row = uiLayoutRow(col, FALSE);
2297                 uiItemR(row, ptr, "slope", 0, NULL, ICON_NONE);
2298         }
2299
2300 }
2301 static void node_composit_buts_colorbalance_but(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2302 {
2303         uiItemR(layout, ptr, "correction_method", 0, NULL, ICON_NONE);
2304
2305         if (RNA_enum_get(ptr, "correction_method") == 0) {
2306
2307                 uiTemplateColorPicker(layout, ptr, "lift", 1, 1, 0, 1);
2308                 uiItemR(layout, ptr, "lift", 0, NULL, ICON_NONE);
2309
2310                 uiTemplateColorPicker(layout, ptr, "gamma", 1, 1, 1, 1);
2311                 uiItemR(layout, ptr, "gamma", 0, NULL, ICON_NONE);
2312
2313                 uiTemplateColorPicker(layout, ptr, "gain", 1, 1, 1, 1);
2314                 uiItemR(layout, ptr, "gain", 0, NULL, ICON_NONE);
2315         }
2316         else {
2317                 uiTemplateColorPicker(layout, ptr, "offset", 1, 1, 0, 1);
2318                 uiItemR(layout, ptr, "offset", 0, NULL, ICON_NONE);
2319
2320                 uiTemplateColorPicker(layout, ptr, "power", 1, 1, 0, 1);
2321                 uiItemR(layout, ptr, "power", 0, NULL, ICON_NONE);
2322
2323                 uiTemplateColorPicker(layout, ptr, "slope", 1, 1, 0, 1);
2324                 uiItemR(layout, ptr, "slope", 0, NULL, ICON_NONE);
2325         }
2326 }
2327
2328
2329 static void node_composit_buts_huecorrect(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2330 {
2331         bNode *node = ptr->data;
2332         CurveMapping *cumap = node->storage;
2333
2334         if (_sample_col[0] != SAMPLE_FLT_ISNONE) {
2335                 cumap->flag |= CUMA_DRAW_SAMPLE;
2336                 copy_v3_v3(cumap->sample, _sample_col);
2337         }
2338         else {
2339                 cumap->flag &= ~CUMA_DRAW_SAMPLE;
2340         }
2341
2342         uiTemplateCurveMapping(layout, ptr, "mapping", 'h', 0, 0);
2343 }
2344
2345 static void node_composit_buts_ycc(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2346
2347         uiItemR(layout, ptr, "mode", 0, "", ICON_NONE);
2348 }
2349
2350 static void node_composit_buts_movieclip(uiLayout *layout, bContext *C, PointerRNA *ptr)
2351 {
2352         uiTemplateID(layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL);
2353 }
2354
2355 static void node_composit_buts_movieclip_details(uiLayout *layout, bContext *C, PointerRNA *ptr)
2356 {
2357         bNode *node = ptr->data;
2358         PointerRNA clipptr;
2359
2360         uiTemplateID(layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL);
2361
2362         if (!node->id)
2363                 return;
2364
2365         clipptr = RNA_pointer_get(ptr, "clip");
2366
2367         uiTemplateColorspaceSettings(layout, &clipptr, "colorspace_settings");
2368 }
2369
2370 static void node_composit_buts_stabilize2d(uiLayout *layout, bContext *C, PointerRNA *ptr)
2371 {
2372         bNode *node = ptr->data;
2373
2374         uiTemplateID(layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL);
2375
2376         if (!node->id)
2377                 return;
2378
2379         uiItemR(layout, ptr, "filter_type", 0, "", ICON_NONE);
2380 }
2381
2382 static void node_composit_buts_transform(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2383 {
2384         uiItemR(layout, ptr, "filter_type", 0, "", ICON_NONE);
2385 }
2386
2387 static void node_composit_buts_moviedistortion(uiLayout *layout, bContext *C, PointerRNA *ptr)
2388 {
2389         bNode *node = ptr->data;
2390
2391         uiTemplateID(layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL);
2392
2393         if (!node->id)
2394                 return;
2395
2396         uiItemR(layout, ptr, "distortion_type", 0, "", ICON_NONE);
2397 }
2398
2399 static void node_composit_buts_colorcorrection(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2400 {
2401         uiLayout *row;
2402         
2403         row = uiLayoutRow(layout, FALSE);
2404         uiItemR(row, ptr, "red", 0, NULL, ICON_NONE);
2405         uiItemR(row, ptr, "green", 0, NULL, ICON_NONE);
2406         uiItemR(row, ptr, "blue", 0, NULL, ICON_NONE);
2407
2408         row = uiLayoutRow(layout, FALSE);
2409         uiItemL(row, "", ICON_NONE);
2410         uiItemL(row, IFACE_("Saturation"), ICON_NONE);
2411         uiItemL(row, IFACE_("Contrast"), ICON_NONE);
2412         uiItemL(row, IFACE_("Gamma"), ICON_NONE);
2413         uiItemL(row, IFACE_("Gain"), ICON_NONE);
2414         uiItemL(row, IFACE_("Lift"), ICON_NONE);
2415
2416         row = uiLayoutRow(layout, FALSE);
2417         uiItemL(row, IFACE_("Master"), ICON_NONE);
2418         uiItemR(row, ptr, "master_saturation", UI_ITEM_R_SLIDER, "", ICON_NONE);
2419         uiItemR(row, ptr, "master_contrast", UI_ITEM_R_SLIDER, "", ICON_NONE);
2420         uiItemR(row, ptr, "master_gamma", UI_ITEM_R_SLIDER, "", ICON_NONE);
2421         uiItemR(row, ptr, "master_gain", UI_ITEM_R_SLIDER, "", ICON_NONE);
2422         uiItemR(row, ptr, "master_lift", UI_ITEM_R_SLIDER, "", ICON_NONE);
2423
2424         row = uiLayoutRow(layout, FALSE);
2425         uiItemL(row, IFACE_("Highlights"), ICON_NONE);
2426         uiItemR(row, ptr, "highlights_saturation", UI_ITEM_R_SLIDER, "", ICON_NONE);
2427         uiItemR(row, ptr, "highlights_contrast", UI_ITEM_R_SLIDER, "", ICON_NONE);
2428         uiItemR(row, ptr, "highlights_gamma", UI_ITEM_R_SLIDER, "", ICON_NONE);
2429         uiItemR(row, ptr, "highlights_gain", UI_ITEM_R_SLIDER, "", ICON_NONE);
2430         uiItemR(row, ptr, "highlights_lift", UI_ITEM_R_SLIDER, "", ICON_NONE);
2431
2432         row = uiLayoutRow(layout, FALSE);
2433         uiItemL(row, IFACE_("Midtones"), ICON_NONE);
2434         uiItemR(row, ptr, "midtones_saturation", UI_ITEM_R_SLIDER, "", ICON_NONE);
2435         uiItemR(row, ptr, "midtones_contrast", UI_ITEM_R_SLIDER, "", ICON_NONE);
2436         uiItemR(row, ptr, "midtones_gamma", UI_ITEM_R_SLIDER, "", ICON_NONE);
2437         uiItemR(row, ptr, "midtones_gain", UI_ITEM_R_SLIDER, "", ICON_NONE);
2438         uiItemR(row, ptr, "midtones_lift", UI_ITEM_R_SLIDER, "", ICON_NONE);
2439
2440         row = uiLayoutRow(layout, FALSE);
2441         uiItemL(row, IFACE_("Shadows"), ICON_NONE);
2442         uiItemR(row, ptr, "shadows_saturation", UI_ITEM_R_SLIDER, "", ICON_NONE);
2443         uiItemR(row, ptr, "shadows_contrast", UI_ITEM_R_SLIDER, "", ICON_NONE);
2444         uiItemR(row, ptr, "shadows_gamma", UI_ITEM_R_SLIDER, "", ICON_NONE);
2445         uiItemR(row, ptr, "shadows_gain", UI_ITEM_R_SLIDER, "", ICON_NONE);
2446         uiItemR(row, ptr, "shadows_lift", UI_ITEM_R_SLIDER, "", ICON_NONE);
2447
2448         row = uiLayoutRow(layout, FALSE);
2449         uiItemR(row, ptr, "midtones_start", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2450         uiItemR(row, ptr, "midtones_end", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2451 }
2452
2453 static void node_composit_buts_colorcorrection_but(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2454 {
2455         uiLayout *row;
2456         
2457         row = uiLayoutRow(layout, FALSE);
2458         uiItemR(row, ptr, "red", 0, NULL, ICON_NONE);
2459         uiItemR(row, ptr, "green", 0, NULL, ICON_NONE);
2460         uiItemR(row, ptr, "blue", 0, NULL, ICON_NONE);
2461         row = layout;
2462         uiItemL(row, IFACE_("Saturation"), ICON_NONE);
2463         uiItemR(row, ptr, "master_saturation", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2464         uiItemR(row, ptr, "highlights_saturation", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2465         uiItemR(row, ptr, "midtones_saturation", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2466         uiItemR(row, ptr, "shadows_saturation", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2467
2468         uiItemL(row, IFACE_("Contrast"), ICON_NONE);
2469         uiItemR(row, ptr, "master_contrast", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2470         uiItemR(row, ptr, "highlights_contrast", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2471         uiItemR(row, ptr, "midtones_contrast", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2472         uiItemR(row, ptr, "shadows_contrast", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2473
2474         uiItemL(row, IFACE_("Gamma"), ICON_NONE);
2475         uiItemR(row, ptr, "master_gamma", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2476         uiItemR(row, ptr, "highlights_gamma", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2477         uiItemR(row, ptr, "midtones_gamma", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2478         uiItemR(row, ptr, "shadows_gamma", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2479
2480         uiItemL(row, IFACE_("Gain"), ICON_NONE);
2481         uiItemR(row, ptr, "master_gain", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2482         uiItemR(row, ptr, "highlights_gain", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2483         uiItemR(row, ptr, "midtones_gain", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2484         uiItemR(row, ptr, "shadows_gain", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2485         
2486         uiItemL(row, IFACE_("Lift"), ICON_NONE);
2487         uiItemR(row, ptr, "master_lift", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2488         uiItemR(row, ptr, "highlights_lift", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2489         uiItemR(row, ptr, "midtones_lift", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2490         uiItemR(row, ptr, "shadows_lift", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2491
2492         row = uiLayoutRow(layout, FALSE);
2493         uiItemR(row, ptr, "midtones_start", 0, NULL, ICON_NONE);
2494         uiItemR(row, ptr, "midtones_end", 0, NULL, ICON_NONE);
2495 }
2496
2497 static void node_composit_buts_switch(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2498 {
2499         uiItemR(layout, ptr, "check", 0, NULL, ICON_NONE);
2500 }
2501
2502 static void node_composit_buts_boxmask(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2503 {
2504         uiLayout *row;
2505         
2506         row = uiLayoutRow(layout, TRUE);
2507         uiItemR(row, ptr, "x", 0, NULL, ICON_NONE);
2508         uiItemR(row, ptr, "y", 0, NULL, ICON_NONE);
2509         
2510         row = uiLayoutRow(layout, TRUE);
2511         uiItemR(row, ptr, "width", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2512         uiItemR(row, ptr, "height", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2513
2514         uiItemR(layout, ptr, "rotation", 0, NULL, ICON_NONE);
2515         uiItemR(layout, ptr, "mask_type", 0, NULL, ICON_NONE);
2516 }
2517
2518 static void node_composit_buts_bokehimage(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2519 {
2520         uiItemR(layout, ptr, "flaps", 0, NULL, ICON_NONE);
2521         uiItemR(layout, ptr, "angle", 0, NULL, ICON_NONE);
2522         uiItemR(layout, ptr, "rounding", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2523         uiItemR(layout, ptr, "catadioptric", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2524         uiItemR(layout, ptr, "shift", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2525 }
2526
2527 static void node_composit_buts_bokehblur(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2528 {
2529         uiItemR(layout, ptr, "use_variable_size", 0, NULL, ICON_NONE);
2530         // uiItemR(layout, ptr, "f_stop", 0, NULL, ICON_NONE);  // UNUSED
2531         uiItemR(layout, ptr, "blur_max", 0, NULL, ICON_NONE);
2532 }
2533
2534 static void node_composit_backdrop_viewer(SpaceNode *snode, ImBuf *backdrop, bNode *node, int x, int y)
2535 {
2536 //      node_composit_backdrop_canvas(snode, backdrop, node, x, y);
2537         if (node->custom1 == 0) {
2538                 const float backdropWidth = backdrop->x;
2539                 const float backdropHeight = backdrop->y;
2540                 const float cx  = x + snode->zoom * backdropWidth * node->custom3;
2541                 const float cy = y + snode->zoom * backdropHeight * node->custom4;
2542
2543                 glColor3f(1.0, 1.0, 1.0);
2544
2545                 glBegin(GL_LINES);
2546                 glVertex2f(cx - 25, cy - 25);
2547                 glVertex2f(cx + 25, cy + 25);
2548                 glVertex2f(cx + 25, cy - 25);
2549                 glVertex2f(cx - 25, cy + 25);
2550                 glEnd();
2551         }
2552 }
2553
2554 static void node_composit_backdrop_boxmask(SpaceNode *snode, ImBuf *backdrop, bNode *node, int x, int y)
2555 {
2556         NodeBoxMask *boxmask = node->storage;
2557         const float backdropWidth = backdrop->x;
2558         const float backdropHeight = backdrop->y;
2559         const float aspect = backdropWidth / backdropHeight;
2560         const float rad = DEG2RADF(-boxmask->rotation);
2561         const float cosine = cosf(rad);
2562         const float sine = sinf(rad);
2563         const float halveBoxWidth = backdropWidth * (boxmask->width / 2.0f);
2564         const float halveBoxHeight = backdropHeight * (boxmask->height / 2.0f) * aspect;
2565
2566         float cx, cy, x1, x2, x3, x4;
2567         float y1, y2, y3, y4;
2568
2569
2570         /* keep this, saves us from a version patch */
2571         if (snode->zoom == 0.0f) snode->zoom = 1.0f;
2572
2573         glColor3f(1.0, 1.0, 1.0);
2574
2575         cx  = x + snode->zoom * backdropWidth * boxmask->x;
2576         cy = y + snode->zoom * backdropHeight * boxmask->y;
2577
2578         x1 = cx - (cosine * halveBoxWidth + sine * halveBoxHeight) * snode->zoom;
2579         x2 = cx - (cosine * -halveBoxWidth + sine * halveBoxHeight) * snode->zoom;
2580         x3 = cx - (cosine * -halveBoxWidth + sine * -halveBoxHeight) * snode->zoom;
2581         x4 = cx - (cosine * halveBoxWidth + sine * -halveBoxHeight) * snode->zoom;
2582         y1 = cy - (-sine * halveBoxWidth + cosine * halveBoxHeight) * snode->zoom;
2583         y2 = cy - (-sine * -halveBoxWidth + cosine * halveBoxHeight) * snode->zoom;
2584         y3 = cy - (-sine * -halveBoxWidth + cosine * -halveBoxHeight) * snode->zoom;
2585         y4 = cy - (-sine * halveBoxWidth + cosine * -halveBoxHeight) * snode->zoom;
2586
2587         glBegin(GL_LINE_LOOP);
2588         glVertex2f(x1, y1);
2589         glVertex2f(x2, y2);
2590         glVertex2f(x3, y3);
2591         glVertex2f(x4, y4);
2592         glEnd();
2593 }
2594
2595 static void node_composit_backdrop_ellipsemask(SpaceNode *snode, ImBuf *backdrop, bNode *node, int x, int y)
2596 {
2597         NodeEllipseMask *ellipsemask = node->storage;
2598         const float backdropWidth = backdrop->x;
2599         const float backdropHeight = backdrop->y;
2600         const float aspect = backdropWidth / backdropHeight;
2601         const float rad = DEG2RADF(-ellipsemask->rotation);
2602         const float cosine = cosf(rad);
2603         const float sine = sinf(rad);
2604         const float halveBoxWidth = backdropWidth * (ellipsemask->width / 2.0f);
2605         const float halveBoxHeight = backdropHeight * (ellipsemask->height / 2.0f) * aspect;
2606
2607         float cx, cy, x1, x2, x3, x4;
2608         float y1, y2, y3, y4;
2609
2610
2611         /* keep this, saves us from a version patch */
2612         if (snode->zoom == 0.0f) snode->zoom = 1.0f;
2613
2614         glColor3f(1.0, 1.0, 1.0);
2615
2616         cx  = x + snode->zoom * backdropWidth * ellipsemask->x;
2617         cy = y + snode->zoom * backdropHeight * ellipsemask->y;
2618
2619         x1 = cx - (cosine * halveBoxWidth + sine * halveBoxHeight) * snode->zoom;
2620         x2 = cx - (cosine * -halveBoxWidth + sine * halveBoxHeight) * snode->zoom;
2621         x3 = cx - (cosine * -halveBoxWidth + sine * -halveBoxHeight) * snode->zoom;
2622         x4 = cx - (cosine * halveBoxWidth + sine * -halveBoxHeight) * snode->zoom;
2623         y1 = cy - (-sine * halveBoxWidth + cosine * halveBoxHeight) * snode->zoom;
2624         y2 = cy - (-sine * -halveBoxWidth + cosine * halveBoxHeight) * snode->zoom;
2625         y3 = cy - (-sine * -halveBoxWidth + cosine * -halveBoxHeight) * snode->zoom;
2626         y4 = cy - (-sine * halveBoxWidth + cosine * -halveBoxHeight) * snode->zoom;
2627
2628         glBegin(GL_LINE_LOOP);
2629
2630         glVertex2f(x1, y1);
2631         glVertex2f(x2, y2);
2632         glVertex2f(x3, y3);
2633         glVertex2f(x4, y4);
2634         glEnd();
2635 }
2636
2637 static void node_composit_buts_ellipsemask(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2638 {
2639         uiLayout *row;
2640         row = uiLayoutRow(layout, TRUE);
2641         uiItemR(row, ptr, "x", 0, NULL, ICON_NONE);
2642         uiItemR(row, ptr, "y", 0, NULL, ICON_NONE);
2643         row = uiLayoutRow(layout, TRUE);
2644         uiItemR(row, ptr, "width", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2645         uiItemR(row, ptr, "height", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2646
2647         uiItemR(layout, ptr, "rotation", 0, NULL, ICON_NONE);
2648         uiItemR(layout, ptr, "mask_type", 0, NULL, ICON_NONE);
2649 }
2650
2651 static void node_composit_buts_viewer_but(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2652 {
2653         uiLayout *col;
2654         
2655         uiItemR(layout, ptr, "tile_order", 0, NULL, ICON_NONE);
2656         if (RNA_enum_get(ptr, "tile_order") == 0) {
2657                 col = uiLayoutColumn(layout, TRUE);
2658                 uiItemR(col, ptr, "center_x", 0, NULL, ICON_NONE);
2659                 uiItemR(col, ptr, "center_y", 0, NULL, ICON_NONE);
2660         }
2661 }
2662
2663 static void node_composit_buts_mask(uiLayout *layout, bContext *C, PointerRNA *ptr)
2664 {
2665         bNode *node = ptr->data;
2666
2667         uiTemplateID(layout, C, ptr, "mask", NULL, NULL, NULL);
2668         uiItemR(layout, ptr, "use_antialiasing", 0, NULL, ICON_NONE);
2669         uiItemR(layout, ptr, "use_feather", 0, NULL, ICON_NONE);
2670
2671         uiItemR(layout, ptr, "size_source", 0, "", ICON_NONE);
2672
2673         if (node->custom1 & (CMP_NODEFLAG_MASK_FIXED | CMP_NODEFLAG_MASK_FIXED_SCENE)) {
2674                 uiItemR(layout, ptr, "size_x", 0, NULL, ICON_NONE);
2675                 uiItemR(layout, ptr, "size_y", 0, NULL, ICON_NONE);
2676         }
2677
2678         uiItemR(layout, ptr, "use_motion_blur", 0, NULL, ICON_NONE);
2679         if (node->custom1 & CMP_NODEFLAG_MASK_MOTION_BLUR) {
2680                 uiItemR(layout, ptr, "motion_blur_samples", 0, NULL, ICON_NONE);
2681                 uiItemR(layout, ptr, "motion_blur_shutter", 0, NULL, ICON_NONE);
2682         }
2683 }
2684
2685 static void node_composit_buts_keyingscreen(uiLayout *layout, bContext *C, PointerRNA *ptr)
2686 {
2687         bNode *node = ptr->data;
2688
2689         uiTemplateID(layout, C, ptr, "clip", NULL, NULL, NULL);
2690
2691         if (node->id) {
2692                 MovieClip *clip = (MovieClip *) node->id;
2693                 uiLayout *col;
2694                 PointerRNA tracking_ptr;
2695
2696                 RNA_pointer_create(&clip->id, &RNA_MovieTracking, &clip->tracking, &tracking_ptr);
2697
2698                 col = uiLayoutColumn(layout, TRUE);
2699                 uiItemPointerR(col, ptr, "tracking_object", &tracking_ptr, "objects", "", ICON_OBJECT_DATA);
2700         }
2701 }
2702
2703 static void node_composit_buts_keying(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2704 {
2705         /* bNode *node = ptr->data; */ /* UNUSED */
2706
2707         uiItemR(layout, ptr, "blur_pre", 0, NULL, ICON_NONE);
2708         uiItemR(layout, ptr, "screen_balance", 0, NULL, ICON_NONE);
2709         uiItemR(layout, ptr, "despill_factor", 0, NULL, ICON_NONE);
2710         uiItemR(layout, ptr, "despill_balance", 0, NULL, ICON_NONE);
2711         uiItemR(layout, ptr, "edge_kernel_radius", 0, NULL, ICON_NONE);
2712         uiItemR(layout, ptr, "edge_kernel_tolerance", 0, NULL, ICON_NONE);
2713         uiItemR(layout, ptr, "clip_black", 0, NULL, ICON_NONE);
2714         uiItemR(layout, ptr, "clip_white", 0, NULL, ICON_NONE);
2715         uiItemR(layout, ptr, "dilate_distance", 0, NULL, ICON_NONE);
2716         uiItemR(layout, ptr, "feather_falloff", 0, NULL, ICON_NONE);
2717         uiItemR(layout, ptr, "feather_distance", 0, NULL, ICON_NONE);
2718         uiItemR(layout, ptr, "blur_post", 0, NULL, ICON_NONE);
2719 }
2720
2721 static void node_composit_buts_trackpos(uiLayout *layout, bContext *C, PointerRNA *ptr)
2722 {
2723         bNode *node = ptr->data;
2724
2725         uiTemplateID(layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL);
2726
2727         if (node->id) {
2728                 MovieClip *clip = (MovieClip *) node->id;
2729                 MovieTracking *tracking = &clip->tracking;
2730                 MovieTrackingObject *object;
2731                 uiLayout *col;
2732                 PointerRNA tracking_ptr;
2733                 NodeTrackPosData *data = node->storage;
2734
2735                 RNA_pointer_create(&clip->id, &RNA_MovieTracking, tracking, &tracking_ptr);
2736
2737                 col = uiLayoutColumn(layout, FALSE);
2738                 uiItemPointerR(col, ptr, "tracking_object", &tracking_ptr, "objects", "", ICON_OBJECT_DATA);
2739
2740                 object = BKE_tracking_object_get_named(tracking, data->tracking_object);
2741                 if (object) {
2742                         PointerRNA object_ptr;
2743
2744                         RNA_pointer_create(&clip->id, &RNA_MovieTrackingObject, object, &object_ptr);
2745
2746                         uiItemPointerR(col, ptr, "track_name", &object_ptr, "tracks", "", ICON_ANIM_DATA);
2747                 }
2748                 else {
2749                         uiItemR(layout, ptr, "track_name", 0, "", ICON_ANIM_DATA);
2750                 }
2751
2752                 uiItemR(layout, ptr, "position", 0, NULL, ICON_NONE);
2753
2754                 if (node->custom1 == 2) {
2755                         uiItemR(layout, ptr, "frame_relative", 0, NULL, ICON_NONE);
2756                 }
2757         }
2758 }
2759
2760 /* only once called */
2761 static void node_composit_set_butfunc(bNodeType *ntype)
2762 {
2763         switch (ntype->type) {
2764                 /* case NODE_GROUP: note, typeinfo for group is generated... see "XXX ugly hack" */
2765
2766                 case CMP_NODE_IMAGE:
2767                         ntype->uifunc = node_composit_buts_image;
2768                         ntype->uifuncbut = node_composit_buts_image_details;
2769                         break;
2770                 case CMP_NODE_R_LAYERS:
2771                         ntype->uifunc = node_composit_buts_renderlayers;
2772                         break;
2773                 case CMP_NODE_NORMAL:
2774                         ntype->uifunc = node_buts_normal;
2775                         break;
2776                 case CMP_NODE_CURVE_VEC:
2777                         ntype->uifunc = node_buts_curvevec;
2778                         break;
2779                 case CMP_NODE_CURVE_RGB:
2780                         ntype->uifunc = node_buts_curvecol;
2781                         break;
2782                 case CMP_NODE_VALUE:
2783                         ntype->uifunc = node_buts_value;
2784                         break;
2785                 case CMP_NODE_RGB:
2786                         ntype->uifunc = node_buts_rgb;
2787                         break;
2788                 case CMP_NODE_FLIP:
2789                         ntype->uifunc = node_composit_buts_flip;
2790                         break;
2791                 case CMP_NODE_SPLITVIEWER:
2792                         ntype->uifunc = node_composit_buts_splitviewer;
2793                         break;
2794                 case CMP_NODE_MIX_RGB:
2795                         ntype->uifunc = node_buts_mix_rgb;
2796                         break;
2797                 case CMP_NODE_VALTORGB:
2798                         ntype->uifunc = node_buts_colorramp;
2799                         break;
2800                 case CMP_NODE_CROP:
2801                         ntype->uifunc = node_composit_buts_crop;
2802                         break;
2803                 case CMP_NODE_BLUR:
2804                         ntype->uifunc = node_composit_buts_blur;
2805                         break;
2806                 case CMP_NODE_DBLUR:
2807                         ntype->uifunc = node_composit_buts_dblur;
2808                         break;
2809                 case CMP_NODE_BILATERALBLUR:
2810                         ntype->uifunc = node_composit_buts_bilateralblur;
2811                         break;
2812                 case CMP_NODE_DEFOCUS:
2813                         ntype->uifunc = node_composit_buts_defocus;
2814                         break;
2815                 case CMP_NODE_GLARE:
2816                         ntype->uifunc = node_composit_buts_glare;
2817                         break;
2818                 case CMP_NODE_TONEMAP:
2819                         ntype->uifunc = node_composit_buts_tonemap;
2820                         break;
2821                 case CMP_NODE_LENSDIST:
2822                         ntype->uifunc = node_composit_buts_lensdist;
2823                         break;
2824                 case CMP_NODE_VECBLUR:
2825                         ntype->uifunc = node_composit_buts_vecblur;
2826                         break;
2827                 case CMP_NODE_FILTER:
2828                         ntype->uifunc = node_composit_buts_filter;
2829                         break;
2830                 case CMP_NODE_MAP_VALUE:
2831                         ntype->uifunc = node_composit_buts_map_value;
2832                         break;
2833                 case CMP_NODE_MAP_RANGE:
2834                         ntype->uifunc = node_composit_buts_map_range;
2835                         break;
2836                 case CMP_NODE_TIME:
2837                         ntype->uifunc = node_buts_time;
2838                         break;
2839                 case CMP_NODE_ALPHAOVER:
2840                         ntype->uifunc = node_composit_buts_alphaover;
2841                         break;
2842                 case CMP_NODE_HUE_SAT:
2843                         ntype->uifunc = node_composit_buts_hue_sat;
2844                         break;
2845                 case CMP_NODE_TEXTURE:
2846                         ntype->uifunc = node_buts_texture;
2847                         break;
2848                 case CMP_NODE_DILATEERODE:
2849                         ntype->uifunc = node_composit_buts_dilateerode;
2850                         break;
2851                 case CMP_NODE_INPAINT:
2852                         ntype->uifunc = node_composit_buts_inpaint;
2853                         break;
2854                 case CMP_NODE_DESPECKLE:
2855                         ntype->uifunc = node_composit_buts_despeckle;
2856                         break;
2857                 case CMP_NODE_OUTPUT_FILE:
2858                         ntype->uifunc = node_composit_buts_file_output;
2859                         ntype->uifuncbut = node_composit_buts_file_output_details;
2860                         ntype->drawinputfunc = node_draw_input_file_output;
2861                         break;
2862                 case CMP_NODE_DIFF_MATTE:
2863                         ntype->uifunc = node_composit_buts_diff_matte;
2864                         break;
2865                 case CMP_NODE_DIST_MATTE:
2866                         ntype->uifunc = node_composit_buts_distance_matte;
2867                         break;
2868                 case CMP_NODE_COLOR_SPILL:
2869                         ntype->uifunc = node_composit_buts_color_spill;
2870                         break;
2871                 case CMP_NODE_CHROMA_MATTE:
2872                         ntype->uifunc = node_composit_buts_chroma_matte;
2873                         break;
2874                 case CMP_NODE_COLOR_MATTE:
2875                         ntype->uifunc = node_composit_buts_color_matte;
2876                         break;
2877                 case CMP_NODE_SCALE:
2878                         ntype->uifunc = node_composit_buts_scale;
2879                         break;
2880                 case CMP_NODE_ROTATE:
2881                         ntype->uifunc = node_composit_buts_rotate;
2882                         break;
2883                 case CMP_NODE_CHANNEL_MATTE:
2884                         ntype->uifunc = node_composit_buts_channel_matte;
2885                         break;
2886                 case CMP_NODE_LUMA_MATTE:
2887                         ntype->uifunc = node_composit_buts_luma_matte;
2888                         break;
2889                 case CMP_NODE_MAP_UV:
2890                         ntype->uifunc = node_composit_buts_map_uv;
2891                         break;
2892                 case CMP_NODE_ID_MASK:
2893                         ntype->uifunc = node_composit_buts_id_mask;
2894                         break;
2895                 case CMP_NODE_DOUBLEEDGEMASK:
2896                         ntype->uifunc = node_composit_buts_double_edge_mask;
2897                         break;
2898                 case CMP_NODE_MATH:
2899                         ntype->uifunc = node_buts_math;
2900                         break;
2901                 case CMP_NODE_INVERT:
2902                         ntype->uifunc = node_composit_buts_invert;
2903                         break;
2904                 case CMP_NODE_PREMULKEY:
2905                         ntype->uifunc = node_composit_buts_premulkey;
2906                         break;
2907                 case CMP_NODE_VIEW_LEVELS:
2908                         ntype->uifunc = node_composit_buts_view_levels;
2909                         break;
2910                 case CMP_NODE_COLORBALANCE:
2911                         ntype->uifunc = node_composit_buts_colorbalance;
2912                         ntype->uifuncbut = node_composit_buts_colorbalance_but;
2913                         break;
2914                 case CMP_NODE_HUECORRECT:
2915                         ntype->uifunc = node_composit_buts_huecorrect;
2916                         break;
2917                 case CMP_NODE_ZCOMBINE:
2918                         ntype->uifunc = node_composit_buts_zcombine;
2919                         break;
2920                 case CMP_NODE_COMBYCCA:
2921                 case CMP_NODE_SEPYCCA:
2922                         ntype->uifunc = node_composit_buts_ycc;
2923                         break;
2924                 case CMP_NODE_MOVIECLIP:
2925                         ntype->uifunc = node_composit_buts_movieclip;
2926                         ntype->uifuncbut = node_composit_buts_movieclip_details;
2927                         break;
2928                 case CMP_NODE_STABILIZE2D:
2929                         ntype->uifunc = node_composit_buts_stabilize2d;
2930                         break;
2931                 case CMP_NODE_TRANSFORM:
2932                         ntype->uifunc = node_composit_buts_transform;
2933                         break;
2934                 case CMP_NODE_MOVIEDISTORTION:
2935                         ntype->uifunc = node_composit_buts_moviedistortion;
2936                         break;
2937                 case CMP_NODE_COLORCORRECTION:
2938                         ntype->uifunc = node_composit_buts_colorcorrection;
2939                         ntype->uifuncbut = node_composit_buts_colorcorrection_but;
2940                         break;
2941                 case CMP_NODE_SWITCH:
2942                         ntype->uifunc = node_composit_buts_switch;
2943                         break;
2944                 case CMP_NODE_MASK_BOX:
2945                         ntype->uifunc = node_composit_buts_boxmask;
2946                         ntype->uibackdropfunc = node_composit_backdrop_boxmask;
2947                         break;
2948                 case CMP_NODE_MASK_ELLIPSE:
2949                         ntype->uifunc = node_composit_buts_ellipsemask;
2950                         ntype->uibackdropfunc = node_composit_backdrop_ellipsemask;
2951                         break;
2952                 case CMP_NODE_BOKEHIMAGE:
2953                         ntype->uifunc = node_composit_buts_bokehimage;
2954                         break;
2955                 case CMP_NODE_BOKEHBLUR:
2956                         ntype->uifunc = node_composit_buts_bokehblur;
2957                         break;
2958                 case CMP_NODE_VIEWER:
2959                         ntype->uifunc = NULL;
2960                         ntype->uifuncbut = node_composit_buts_viewer_but;
2961                         ntype->uibackdropfunc = node_composit_backdrop_viewer;
2962                         break;
2963                 case CMP_NODE_MASK:
2964                         ntype->uifunc = node_composit_buts_mask;
2965                         break;
2966                 case CMP_NODE_KEYINGSCREEN:
2967                         ntype->uifunc = node_composit_buts_keyingscreen;
2968                         break;
2969                 case CMP_NODE_KEYING:
2970                         ntype->uifunc = node_composit_buts_keying;
2971                         break;
2972                 case CMP_NODE_TRACKPOS:
2973                         ntype->uifunc = node_composit_buts_trackpos;
2974                         break;
2975                 default:
2976                         ntype->uifunc = NULL;
2977         }
2978 }
2979
2980 /* ****************** BUTTON CALLBACKS FOR TEXTURE NODES ***************** */
2981
2982 static void node_texture_buts_bricks(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2983 {
2984         uiLayout *col;
2985         
2986         col = uiLayoutColumn(layout, TRUE);
2987         uiItemR(col, ptr, "offset", 0, IFACE_("Offset"), ICON_NONE);
2988         uiItemR(col, ptr, "offset_frequency", 0, IFACE_("Frequency"), ICON_NONE);
2989         
2990         col = uiLayoutColumn(layout, TRUE);
2991         uiItemR(col, ptr, "squash", 0, IFACE_("Squash"), ICON_NONE);
2992         uiItemR(col, ptr, "squash_frequency", 0, IFACE_("Frequency"), ICON_NONE);
2993 }
2994
2995 static void node_texture_buts_proc(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2996 {
2997         PointerRNA tex_ptr;
2998         bNode *node = ptr->data;
2999         ID *id = ptr->id.data;
3000         Tex *tex = (Tex *)node->storage;
3001         uiLayout *col, *row;
3002         
3003         RNA_pointer_create(id, &RNA_Texture, tex, &tex_ptr);
3004
3005         col = uiLayoutColumn(layout, FALSE);
3006
3007         switch (tex->type) {
3008                 case TEX_BLEND:
3009                         uiItemR(col, &tex_ptr, "progression", 0, "", ICON_NONE);
3010                         row = uiLayoutRow(col, FALSE);
3011                         uiItemR(row, &tex_ptr, "use_flip_axis", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
3012                         break;
3013
3014                 case TEX_MARBLE:
3015                         row = uiLayoutRow(col, FALSE);
3016                         uiItemR(row, &tex_ptr, "marble_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
3017                         row = uiLayoutRow(col, FALSE);
3018                         uiItemR(row, &tex_ptr, "noise_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
3019                         row = uiLayoutRow(col, FALSE);
3020                         uiItemR(row, &tex_ptr, "noise_basis", 0, "", ICON_NONE);
3021                         row = uiLayoutRow(col, FALSE);
3022                         uiItemR(row, &tex_ptr, "noise_basis_2", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
3023                         break;
3024
3025                 case TEX_MAGIC:
3026                         uiItemR(col, &tex_ptr, "noise_depth", 0, NULL, ICON_NONE);
3027                         break;
3028
3029                 case TEX_STUCCI:
3030                         row = uiLayoutRow(col, FALSE);
3031                         uiItemR(row, &tex_ptr, "stucci_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
3032                         row = uiLayoutRow(col, FALSE);
3033                         uiItemR(row, &tex_ptr, "noise_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
3034                         uiItemR(col, &tex_ptr, "noise_basis", 0, "", ICON_NONE);
3035                         break;
3036
3037                 case TEX_WOOD:
3038                         uiItemR(col, &tex_ptr, "noise_basis", 0, "", ICON_NONE);
3039                         uiItemR(col, &tex_ptr, "wood_type", 0, "", ICON_NONE);
3040                         row = uiLayoutRow(col, FALSE);
3041                         uiItemR(row, &tex_ptr, "noise_basis_2", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
3042                         row = uiLayoutRow(col, FALSE);
3043                         uiLayoutSetActive(row, !(ELEM(tex->stype, TEX_BAND, TEX_RING)));
3044                         uiItemR(row, &tex_ptr, "noise_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
3045                         break;
3046                         
3047                 case TEX_CLOUDS:
3048                         uiItemR(col, &tex_ptr, "noise_basis", 0, "", ICON_NONE);
3049                         row = uiLayoutRow(col, FALSE);
3050                         uiItemR(row, &tex_ptr, "cloud_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
3051                         row = uiLayoutRow(col, FALSE);
3052                         uiItemR(row, &tex_ptr, "noise_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
3053                         uiItemR(col, &tex_ptr, "noise_depth", UI_ITEM_R_EXPAND, IFACE_("Depth"), ICON_NONE);
3054                         break;
3055                         
3056                 case TEX_DISTNOISE:
3057                         uiItemR(col, &tex_ptr, "noise_basis", 0, "", ICON_NONE);
3058                         uiItemR(col, &tex_ptr, "noise_distortion", 0, "", ICON_NONE);
3059                         break;
3060
3061                 case TEX_MUSGRAVE:
3062                         uiItemR(col, &tex_ptr, "musgrave_type", 0, "", ICON_NONE);
3063                         uiItemR(col, &tex_ptr, "noise_basis", 0, "", ICON_NONE);
3064                         break;
3065                 case TEX_VORONOI:
3066                         uiItemR(col, &tex_ptr, "distance_metric", 0, "", ICON_NONE);
3067                         if (tex->vn_distm == TEX_MINKOVSKY) {
3068                                 uiItemR(col, &tex_ptr, "minkovsky_exponent", 0, NULL, ICON_NONE);
3069                         }
3070                         uiItemR(col, &tex_ptr, "color_mode", 0, "", ICON_NONE);
3071                         break;
3072         }
3073 }
3074
3075 static void node_texture_buts_image(uiLayout *layout, bContext *C, PointerRNA *ptr)
3076 {
3077         uiTemplateID(layout, C, ptr, "image", NULL, "IMAGE_OT_open", NULL);
3078 }
3079
3080 static void node_texture_buts_output(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
3081 {
3082         uiItemR(layout, ptr, "filepath", 0, "", ICON_NONE);
3083 }
3084
3085 /* only once called */
3086 static void node_texture_set_butfunc(bNodeType *ntype)
3087 {
3088         if (ntype->type >= TEX_NODE_PROC && ntype->type < TEX_NODE_PROC_MAX) {
3089                 ntype->uifunc = node_texture_buts_proc;
3090         }
3091         else {
3092                 switch (ntype->type) {
3093
3094                         case TEX_NODE_MATH:
3095                                 ntype->uifunc = node_buts_math;
3096                                 break;
3097
3098                         case TEX_NODE_MIX_RGB:
3099                                 ntype->uifunc = node_buts_mix_rgb;
3100                                 break;
3101
3102                         case TEX_NODE_VALTORGB:
3103                                 ntype->uifunc = node_buts_colorramp;
3104                                 break;
3105
3106                         case TEX_NODE_CURVE_RGB:
3107                                 ntype->uifunc = node_buts_curvecol;
3108                                 break;
3109
3110                         case TEX_NODE_CURVE_TIME:
3111                                 ntype->uifunc = node_buts_time;
3112                                 break;
3113
3114                         case TEX_NODE_TEXTURE:
3115                                 ntype->uifunc = node_buts_texture;
3116                                 break;
3117
3118                         case TEX_NODE_BRICKS:
3119                                 ntype->uifunc = node_texture_buts_bricks;
3120                                 break;
3121
3122                         case TEX_NODE_IMAGE:
3123                                 ntype->uifunc = node_texture_buts_image;
3124                                 break;
3125
3126                         case TEX_NODE_OUTPUT:
3127                                 ntype->uifunc = node_texture_buts_output;
3128                                 break;
3129                 }
3130         }
3131 }
3132
3133 /* ******* init draw callbacks for all tree types, only called in usiblender.c, once ************* */
3134
3135 void ED_node_init_butfuncs(void)
3136 {
3137         bNodeTreeType *treetype;
3138         bNodeType *ntype;
3139         bNodeSocketType *stype;
3140         int i;
3141         
3142         /* node type ui functions */
3143         for (i = 0; i < NUM_NTREE_TYPES; ++i) {
3144     &nb