Holiday coding log :)
[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", 0, 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 #if 0   /* UNUSED */
1125         rctf *rct = &node->totr;
1126         float size = NODE_REROUTE_SIZE;
1127 #endif
1128         float socket_size = NODE_SOCKSIZE;
1129
1130         /* skip if out of view */
1131         if (node->totr.xmax < ar->v2d.cur.xmin || node->totr.xmin > ar->v2d.cur.xmax ||
1132             node->totr.ymax < ar->v2d.cur.ymin || node->totr.ymin > ar->v2d.cur.ymax) {
1133
1134                 uiEndBlock(C, node->block);
1135                 node->block = NULL;
1136                 return;
1137         }
1138
1139         /* XXX only kept for debugging
1140          * selection state is indicated by socket outline below!
1141          */
1142 #if 0
1143         /* body */
1144         uiSetRoundBox(15);
1145         UI_ThemeColor4(TH_NODE);
1146         glEnable(GL_BLEND);
1147         uiRoundBox(rct->xmin, rct->ymin, rct->xmax, rct->ymax, size);
1148         glDisable(GL_BLEND);
1149
1150         /* outline active and selected emphasis */
1151         if (node->flag & SELECT) {
1152                 glEnable(GL_BLEND);
1153                 glEnable(GL_LINE_SMOOTH);
1154                 /* using different shades of TH_TEXT_HI for the empasis, like triangle */
1155                 if (node->flag & NODE_ACTIVE)
1156                         UI_ThemeColorShadeAlpha(TH_TEXT_HI, 0, -40);
1157                 else
1158                         UI_ThemeColorShadeAlpha(TH_TEXT_HI, -20, -120);
1159                 uiDrawBox(GL_LINE_LOOP, rct->xmin, rct->ymin, rct->xmax, rct->ymax, size);
1160
1161                 glDisable(GL_LINE_SMOOTH);
1162                 glDisable(GL_BLEND);
1163         }
1164 #endif
1165
1166         /* only draw input socket. as they all are placed on the same position.
1167          * highlight also if node itself is selected, since we don't display the node body separately!
1168          */
1169         for (sock = node->inputs.first; sock; sock = sock->next) {
1170                 node_socket_circle_draw(ntree, sock, socket_size, (sock->flag & SELECT) || (node->flag & SELECT));
1171         }
1172
1173         uiEndBlock(C, node->block);
1174         uiDrawBlock(C, node->block);
1175         node->block = NULL;
1176 }
1177
1178 /* Special tweak area for reroute node.
1179  * Since this node is quite small, we use a larger tweak area for grabbing than for selection.
1180  */
1181 static int node_tweak_area_reroute(bNode *node, int x, int y)
1182 {
1183         /* square of tweak radius */
1184         static const float tweak_radius_sq = 576;  /* 24 * 24 */
1185         
1186         bNodeSocket *sock = node->inputs.first;
1187         float dx = sock->locx - x;
1188         float dy = sock->locy - y;
1189         return (dx * dx + dy * dy <= tweak_radius_sq);
1190 }
1191
1192 static void node_common_set_butfunc(bNodeType *ntype)
1193 {
1194         switch (ntype->type) {
1195                 case NODE_GROUP:
1196                         ntype->uifunc = node_uifunc_group;
1197                         ntype->drawfunc = node_draw_group;
1198                         ntype->drawupdatefunc = node_update_group;
1199                         break;
1200                 case NODE_FRAME:
1201                         ntype->drawfunc = node_draw_frame;
1202                         ntype->drawupdatefunc = node_update_frame;
1203                         ntype->uifuncbut = node_buts_frame_details;
1204                         ntype->resize_area_func = node_resize_area_frame;
1205                         break;
1206                 case NODE_REROUTE:
1207                         ntype->drawfunc = node_draw_reroute;
1208                         ntype->drawupdatefunc = node_update_reroute;
1209                         ntype->tweak_area_func = node_tweak_area_reroute;
1210                         break;
1211         }
1212 }
1213
1214 /* ****************** BUTTON CALLBACKS FOR SHADER NODES ***************** */
1215
1216 static void node_buts_image_user(uiLayout *layout, bContext *C, PointerRNA *ptr,
1217                                  PointerRNA *imaptr, PointerRNA *iuserptr)
1218 {
1219         uiLayout *col;
1220         int source;
1221
1222         if (!imaptr->data)
1223                 return;
1224
1225         col = uiLayoutColumn(layout, FALSE);
1226         
1227         uiItemR(col, imaptr, "source", 0, "", ICON_NONE);
1228         
1229         source = RNA_enum_get(imaptr, "source");
1230
1231         if (source == IMA_SRC_SEQUENCE) {
1232                 /* don't use iuser->framenr directly because it may not be updated if auto-refresh is off */
1233                 Scene *scene = CTX_data_scene(C);
1234                 ImageUser *iuser = iuserptr->data;
1235                 char numstr[32];
1236                 const int framenr = BKE_image_user_frame_get(iuser, CFRA, 0, NULL);
1237                 BLI_snprintf(numstr, sizeof(numstr), IFACE_("Frame: %d"), framenr);
1238                 uiItemL(layout, numstr, ICON_NONE);
1239         }
1240
1241         if (ELEM(source, IMA_SRC_SEQUENCE, IMA_SRC_MOVIE)) {
1242                 col = uiLayoutColumn(layout, TRUE);
1243                 uiItemR(col, ptr, "frame_duration", 0, NULL, ICON_NONE);
1244                 uiItemR(col, ptr, "frame_start", 0, NULL, ICON_NONE);
1245                 uiItemR(col, ptr, "frame_offset", 0, NULL, ICON_NONE);
1246                 uiItemR(col, ptr, "use_cyclic", 0, NULL, ICON_NONE);
1247                 uiItemR(col, ptr, "use_auto_refresh", UI_ITEM_R_ICON_ONLY, NULL, ICON_NONE);
1248         }
1249
1250         col = uiLayoutColumn(layout, FALSE);
1251
1252         if (RNA_enum_get(imaptr, "type") == IMA_TYPE_MULTILAYER)
1253                 uiItemR(col, ptr, "layer", 0, NULL, ICON_NONE);
1254 }
1255
1256 static void node_shader_buts_material(uiLayout *layout, bContext *C, PointerRNA *ptr)
1257 {
1258         bNode *node = ptr->data;
1259         uiLayout *col;
1260         
1261         uiTemplateID(layout, C, ptr, "material", "MATERIAL_OT_new", NULL, NULL);
1262         
1263         if (!node->id) return;
1264         
1265         col = uiLayoutColumn(layout, FALSE);
1266         uiItemR(col, ptr, "use_diffuse", 0, NULL, ICON_NONE);
1267         uiItemR(col, ptr, "use_specular", 0, NULL, ICON_NONE);
1268         uiItemR(col, ptr, "invert_normal", 0, NULL, ICON_NONE);
1269 }
1270
1271 static void node_shader_buts_mapping(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1272 {
1273         uiLayout *row;
1274         
1275         uiItemL(layout, IFACE_("Location:"), ICON_NONE);
1276         row = uiLayoutRow(layout, TRUE);
1277         uiItemR(row, ptr, "translation", 0, "", ICON_NONE);
1278         
1279         uiItemL(layout, IFACE_("Rotation:"), ICON_NONE);
1280         row = uiLayoutRow(layout, TRUE);
1281         uiItemR(row, ptr, "rotation", 0, "", ICON_NONE);
1282         
1283         uiItemL(layout, IFACE_("Scale:"), ICON_NONE);
1284         row = uiLayoutRow(layout, TRUE);
1285         uiItemR(row, ptr, "scale", 0, "", ICON_NONE);
1286         
1287         row = uiLayoutRow(layout, TRUE);
1288         uiItemR(row, ptr, "use_min", 0, "Min", ICON_NONE);
1289         uiItemR(row, ptr, "min", 0, "", ICON_NONE);
1290         
1291         row = uiLayoutRow(layout, TRUE);
1292         uiItemR(row, ptr, "use_max", 0, "Max", ICON_NONE);
1293         uiItemR(row, ptr, "max", 0, "", ICON_NONE);
1294 }
1295
1296 static void node_shader_buts_vect_math(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1297
1298         uiItemR(layout, ptr, "operation", 0, "", ICON_NONE);
1299 }
1300
1301 static void node_shader_buts_geometry(uiLayout *layout, bContext *C, PointerRNA *ptr)
1302 {
1303         PointerRNA obptr = CTX_data_pointer_get(C, "active_object");
1304         uiLayout *col;
1305
1306         col = uiLayoutColumn(layout, FALSE);
1307
1308         if (obptr.data && RNA_enum_get(&obptr, "type") == OB_MESH) {
1309                 PointerRNA dataptr = RNA_pointer_get(&obptr, "data");
1310
1311                 uiItemPointerR(col, ptr, "uv_layer", &dataptr, "uv_textures", "", ICON_NONE);
1312                 uiItemPointerR(col, ptr, "color_layer", &dataptr, "vertex_colors", "", ICON_NONE);
1313         }
1314         else {
1315                 uiItemR(col, ptr, "uv_layer", 0, IFACE_("UV"), ICON_NONE);
1316                 uiItemR(col, ptr, "color_layer", 0, IFACE_("VCol"), ICON_NONE);
1317         }
1318 }
1319
1320 static void node_shader_buts_attribute(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1321 {
1322         uiItemR(layout, ptr, "attribute_name", 0, IFACE_("Name"), ICON_NONE);
1323 }
1324
1325 static void node_shader_buts_tex_image(uiLayout *layout, bContext *C, PointerRNA *ptr)
1326 {
1327         PointerRNA imaptr = RNA_pointer_get(ptr, "image");
1328         PointerRNA iuserptr = RNA_pointer_get(ptr, "image_user");
1329
1330         uiTemplateID(layout, C, ptr, "image", NULL, "IMAGE_OT_open", NULL);
1331         uiItemR(layout, ptr, "color_space", 0, "", ICON_NONE);
1332         uiItemR(layout, ptr, "projection", 0, "", ICON_NONE);
1333
1334         if (RNA_enum_get(ptr, "projection") == SHD_PROJ_BOX) {
1335                 uiItemR(layout, ptr, "projection_blend", 0, "Blend", ICON_NONE);
1336         }
1337
1338         /* note: image user properties used directly here, unlike compositor image node,
1339          * which redefines them in the node struct RNA to get proper updates.
1340          */
1341         node_buts_image_user(layout, C, &iuserptr, &imaptr, &iuserptr);
1342 }
1343
1344 static void node_shader_buts_tex_environment(uiLayout *layout, bContext *C, PointerRNA *ptr)
1345 {
1346         PointerRNA imaptr = RNA_pointer_get(ptr, "image");
1347         PointerRNA iuserptr = RNA_pointer_get(ptr, "image_user");
1348
1349         uiTemplateID(layout, C, ptr, "image", NULL, "IMAGE_OT_open", NULL);
1350         uiItemR(layout, ptr, "color_space", 0, "", ICON_NONE);
1351         uiItemR(layout, ptr, "projection", 0, "", ICON_NONE);
1352
1353         node_buts_image_user(layout, C, &iuserptr, &imaptr, &iuserptr);
1354 }
1355
1356 static void node_shader_buts_tex_sky(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1357 {
1358         uiItemR(layout, ptr, "sun_direction", 0, "", ICON_NONE);
1359         uiItemR(layout, ptr, "turbidity", 0, NULL, ICON_NONE);
1360 }
1361
1362 static void node_shader_buts_tex_gradient(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1363 {
1364         uiItemR(layout, ptr, "gradient_type", 0, "", ICON_NONE);
1365 }
1366
1367 static void node_shader_buts_tex_magic(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1368 {
1369         uiItemR(layout, ptr, "turbulence_depth", 0, NULL, ICON_NONE);
1370 }
1371
1372 static void node_shader_buts_tex_brick(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1373 {
1374         uiLayout *col;
1375         
1376         col = uiLayoutColumn(layout, TRUE);
1377         uiItemR(col, ptr, "offset", 0, IFACE_("Offset"), ICON_NONE);
1378         uiItemR(col, ptr, "offset_frequency", 0, IFACE_("Frequency"), ICON_NONE);
1379         
1380         col = uiLayoutColumn(layout, TRUE);
1381         uiItemR(col, ptr, "squash", 0, IFACE_("Squash"), ICON_NONE);
1382         uiItemR(col, ptr, "squash_frequency", 0, IFACE_("Frequency"), ICON_NONE);
1383 }
1384
1385 static void node_shader_buts_tex_wave(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1386 {
1387         uiItemR(layout, ptr, "wave_type", 0, "", ICON_NONE);
1388 }
1389
1390 static void node_shader_buts_tex_musgrave(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1391 {
1392         uiItemR(layout, ptr, "musgrave_type", 0, "", ICON_NONE);
1393 }
1394
1395 static void node_shader_buts_tex_voronoi(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1396 {
1397         uiItemR(layout, ptr, "coloring", 0, "", ICON_NONE);
1398 }
1399
1400 static void node_shader_buts_tex_coord(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1401 {
1402         uiItemR(layout, ptr, "from_dupli", 0, NULL, 0);
1403 }
1404
1405 static void node_shader_buts_normal_map(uiLayout *layout, bContext *C, PointerRNA *ptr)
1406 {
1407         uiItemR(layout, ptr, "space", 0, "", 0);
1408
1409         if (RNA_enum_get(ptr, "space") == SHD_NORMAL_MAP_TANGENT) {
1410                 PointerRNA obptr = CTX_data_pointer_get(C, "active_object");
1411
1412                 if (obptr.data && RNA_enum_get(&obptr, "type") == OB_MESH) {
1413                         PointerRNA dataptr = RNA_pointer_get(&obptr, "data");
1414                         uiItemPointerR(layout, ptr, "uv_map", &dataptr, "uv_textures", "", ICON_NONE);
1415                 }
1416                 else
1417                         uiItemR(layout, ptr, "uv_map", 0, "", 0);
1418         }
1419 }
1420
1421 static void node_shader_buts_tangent(uiLayout *layout, bContext *C, PointerRNA *ptr)
1422 {
1423         uiLayout *split, *row;
1424
1425         split = uiLayoutSplit(layout, 0.0f, FALSE);
1426
1427         uiItemR(split, ptr, "direction_type", 0, "", 0);
1428
1429         row = uiLayoutRow(split, FALSE);
1430
1431         if (RNA_enum_get(ptr, "direction_type") == SHD_TANGENT_UVMAP) {
1432                 PointerRNA obptr = CTX_data_pointer_get(C, "active_object");
1433
1434                 if (obptr.data && RNA_enum_get(&obptr, "type") == OB_MESH) {
1435                         PointerRNA dataptr = RNA_pointer_get(&obptr, "data");
1436                         uiItemPointerR(row, ptr, "uv_map", &dataptr, "uv_textures", "", ICON_NONE);
1437                 }
1438                 else
1439                         uiItemR(row, ptr, "uv_map", 0, "", 0);
1440         }
1441         else
1442                 uiItemR(row, ptr, "axis", UI_ITEM_R_EXPAND, NULL, 0);
1443 }
1444
1445 static void node_shader_buts_glossy(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1446 {
1447         uiItemR(layout, ptr, "distribution", 0, "", ICON_NONE);
1448 }
1449
1450 static void node_shader_buts_script(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1451 {
1452         uiLayout *row;
1453
1454         row = uiLayoutRow(layout, FALSE);
1455         uiItemR(row, ptr, "mode", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
1456
1457         row = uiLayoutRow(layout, TRUE);
1458
1459         if (RNA_enum_get(ptr, "mode") == NODE_SCRIPT_INTERNAL)
1460                 uiItemR(row, ptr, "script", 0, "", ICON_NONE);
1461         else
1462                 uiItemR(row, ptr, "filepath", 0, "", ICON_NONE);
1463
1464         uiItemO(row, "", ICON_FILE_REFRESH, "node.shader_script_update");
1465 }
1466
1467 static void node_shader_buts_script_details(uiLayout *layout, bContext *C, PointerRNA *ptr)
1468 {
1469         uiItemS(layout);
1470
1471         node_shader_buts_script(layout, C, ptr);
1472
1473 #if 0  /* not implemented yet */
1474         if (RNA_enum_get(ptr, "mode") == NODE_SCRIPT_EXTERNAL)
1475                 uiItemR(layout, ptr, "use_auto_update", 0, NULL, ICON_NONE);
1476 #endif
1477 }
1478
1479 /* only once called */
1480 static void node_shader_set_butfunc(bNodeType *ntype)
1481 {
1482         switch (ntype->type) {
1483                 /* case NODE_GROUP: note, typeinfo for group is generated... see "XXX ugly hack" */
1484
1485                 case SH_NODE_MATERIAL:
1486                 case SH_NODE_MATERIAL_EXT:
1487                         ntype->uifunc = node_shader_buts_material;
1488                         break;
1489                 case SH_NODE_TEXTURE:
1490                         ntype->uifunc = node_buts_texture;
1491                         break;
1492                 case SH_NODE_NORMAL:
1493                         ntype->uifunc = node_buts_normal;
1494                         break;
1495                 case SH_NODE_CURVE_VEC:
1496                         ntype->uifunc = node_buts_curvevec;
1497                         break;
1498                 case SH_NODE_CURVE_RGB:
1499                         ntype->uifunc = node_buts_curvecol;
1500                         break;
1501                 case SH_NODE_MAPPING:
1502                         ntype->uifunc = node_shader_buts_mapping;
1503                         break;
1504                 case SH_NODE_VALUE:
1505                         ntype->uifunc = node_buts_value;
1506                         break;
1507                 case SH_NODE_RGB:
1508                         ntype->uifunc = node_buts_rgb;
1509                         break;
1510                 case SH_NODE_MIX_RGB:
1511                         ntype->uifunc = node_buts_mix_rgb;
1512                         break;
1513                 case SH_NODE_VALTORGB:
1514                         ntype->uifunc = node_buts_colorramp;
1515                         break;
1516                 case SH_NODE_MATH: 
1517                         ntype->uifunc = node_buts_math;
1518                         break; 
1519                 case SH_NODE_VECT_MATH: 
1520                         ntype->uifunc = node_shader_buts_vect_math;
1521                         break; 
1522                 case SH_NODE_GEOMETRY:
1523                         ntype->uifunc = node_shader_buts_geometry;
1524                         break;
1525                 case SH_NODE_ATTRIBUTE:
1526                         ntype->uifunc = node_shader_buts_attribute;
1527                         break;
1528                 case SH_NODE_TEX_SKY:
1529                         ntype->uifunc = node_shader_buts_tex_sky;
1530                         break;
1531                 case SH_NODE_TEX_IMAGE:
1532                         ntype->uifunc = node_shader_buts_tex_image;
1533                         break;
1534                 case SH_NODE_TEX_ENVIRONMENT:
1535                         ntype->uifunc = node_shader_buts_tex_environment;
1536                         break;
1537                 case SH_NODE_TEX_GRADIENT:
1538                         ntype->uifunc = node_shader_buts_tex_gradient;
1539                         break;
1540                 case SH_NODE_TEX_MAGIC:
1541                         ntype->uifunc = node_shader_buts_tex_magic;
1542                         break;
1543                 case SH_NODE_TEX_BRICK:
1544                         ntype->uifunc = node_shader_buts_tex_brick;
1545                         break;
1546                 case SH_NODE_TEX_WAVE:
1547                         ntype->uifunc = node_shader_buts_tex_wave;
1548                         break;
1549                 case SH_NODE_TEX_MUSGRAVE:
1550                         ntype->uifunc = node_shader_buts_tex_musgrave;
1551                         break;
1552                 case SH_NODE_TEX_VORONOI:
1553                         ntype->uifunc = node_shader_buts_tex_voronoi;
1554                         break;
1555                 case SH_NODE_TEX_COORD:
1556                         ntype->uifunc = node_shader_buts_tex_coord;
1557                         break;
1558                 case SH_NODE_NORMAL_MAP:
1559                         ntype->uifunc = node_shader_buts_normal_map;
1560                         break;
1561                 case SH_NODE_TANGENT:
1562                         ntype->uifunc = node_shader_buts_tangent;
1563                         break;
1564                 case SH_NODE_BSDF_GLOSSY:
1565                 case SH_NODE_BSDF_GLASS:
1566                 case SH_NODE_BSDF_REFRACTION:
1567                         ntype->uifunc = node_shader_buts_glossy;
1568                         break;
1569                 case SH_NODE_SCRIPT:
1570                         ntype->uifunc = node_shader_buts_script;
1571                         ntype->uifuncbut = node_shader_buts_script_details;
1572                         break;
1573         }
1574 }
1575
1576 /* ****************** BUTTON CALLBACKS FOR COMPOSITE NODES ***************** */
1577
1578 static void node_composit_buts_image(uiLayout *layout, bContext *C, PointerRNA *ptr)
1579 {
1580         bNode *node = ptr->data;
1581         PointerRNA imaptr, iuserptr;
1582         
1583         uiTemplateID(layout, C, ptr, "image", NULL, "IMAGE_OT_open", NULL);
1584         
1585         if (!node->id) return;
1586         
1587         imaptr = RNA_pointer_get(ptr, "image");
1588         RNA_pointer_create((ID *)ptr->id.data, &RNA_ImageUser, node->storage, &iuserptr);
1589         
1590         node_buts_image_user(layout, C, ptr, &imaptr, &iuserptr);
1591 }
1592
1593 static void node_composit_buts_image_details(uiLayout *layout, bContext *C, PointerRNA *ptr)
1594 {
1595         bNode *node = ptr->data;
1596         PointerRNA imaptr;
1597
1598         node_composit_buts_image(layout, C, ptr);
1599
1600         if (!node->id)
1601                 return;
1602
1603         imaptr = RNA_pointer_get(ptr, "image");
1604
1605         uiTemplateColorspaceSettings(layout, &imaptr, "colorspace_settings");
1606 }
1607
1608 static void node_composit_buts_renderlayers(uiLayout *layout, bContext *C, PointerRNA *ptr)
1609 {
1610         bNode *node = ptr->data;
1611         uiLayout *col, *row;
1612         PointerRNA op_ptr;
1613         PointerRNA scn_ptr;
1614         PropertyRNA *prop;
1615         const char *layer_name;
1616         char scene_name[MAX_ID_NAME - 2];
1617         wmOperatorType *ot = WM_operatortype_find("RENDER_OT_render", 1);
1618
1619         BLI_assert(ot != 0);
1620
1621         uiTemplateID(layout, C, ptr, "scene", NULL, NULL, NULL);
1622         
1623         if (!node->id) return;
1624
1625         col = uiLayoutColumn(layout, FALSE);
1626         row = uiLayoutRow(col, FALSE);
1627         uiItemR(row, ptr, "layer", 0, "", ICON_NONE);
1628         
1629         prop = RNA_struct_find_property(ptr, "layer");
1630         if (!(RNA_property_enum_identifier(C, ptr, prop, RNA_property_enum_get(ptr, prop), &layer_name)))
1631                 return;
1632         
1633         scn_ptr = RNA_pointer_get(ptr, "scene");
1634         RNA_string_get(&scn_ptr, "name", scene_name);
1635         
1636         WM_operator_properties_create_ptr(&op_ptr, ot);
1637         RNA_string_set(&op_ptr, "layer", layer_name);
1638         RNA_string_set(&op_ptr, "scene", scene_name);
1639         uiItemFullO_ptr(row, ot, "", ICON_RENDER_STILL, op_ptr.data, WM_OP_INVOKE_DEFAULT, 0);
1640
1641 }
1642
1643
1644 static void node_composit_buts_blur(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1645 {
1646         uiLayout *col, *row;
1647         int reference;
1648         int filter;
1649         
1650         col = uiLayoutColumn(layout, FALSE);
1651         filter = RNA_enum_get(ptr, "filter_type");
1652         reference = RNA_boolean_get(ptr, "use_variable_size");
1653
1654         uiItemR(col, ptr, "filter_type", 0, "", ICON_NONE);
1655         if (filter != R_FILTER_FAST_GAUSS) {
1656                 uiItemR(col, ptr, "use_variable_size", 0, NULL, ICON_NONE);
1657                 if (!reference) {
1658                         uiItemR(col, ptr, "use_bokeh", 0, NULL, ICON_NONE);
1659                 }
1660                 uiItemR(col, ptr, "use_gamma_correction", 0, NULL, ICON_NONE);
1661         }
1662         
1663         uiItemR(col, ptr, "use_relative", 0, NULL, ICON_NONE);
1664         
1665         if (RNA_boolean_get(ptr, "use_relative")) {
1666                 uiItemL(col, IFACE_("Aspect Correction"), ICON_NONE);
1667                 row = uiLayoutRow(layout, TRUE);
1668                 uiItemR(row, ptr, "aspect_correction", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
1669                 
1670                 col = uiLayoutColumn(layout, TRUE);
1671                 uiItemR(col, ptr, "factor_x", 0, IFACE_("X"), ICON_NONE);
1672                 uiItemR(col, ptr, "factor_y", 0, IFACE_("Y"), ICON_NONE);
1673         }
1674         else {
1675                 col = uiLayoutColumn(layout, TRUE);
1676                 uiItemR(col, ptr, "size_x", 0, IFACE_("X"), ICON_NONE);
1677                 uiItemR(col, ptr, "size_y", 0, IFACE_("Y"), ICON_NONE);
1678         }
1679 }
1680
1681 static void node_composit_buts_dblur(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1682 {
1683         uiLayout *col;
1684         
1685         uiItemR(layout, ptr, "iterations", 0, NULL, ICON_NONE);
1686         uiItemR(layout, ptr, "use_wrap", 0, NULL, ICON_NONE);
1687         
1688         col = uiLayoutColumn(layout, TRUE);
1689         uiItemL(col, IFACE_("Center:"), ICON_NONE);
1690         uiItemR(col, ptr, "center_x", 0, IFACE_("X"), ICON_NONE);
1691         uiItemR(col, ptr, "center_y", 0, IFACE_("Y"), ICON_NONE);
1692         
1693         uiItemS(layout);
1694         
1695         col = uiLayoutColumn(layout, TRUE);
1696         uiItemR(col, ptr, "distance", 0, NULL, ICON_NONE);
1697         uiItemR(col, ptr, "angle", 0, NULL, ICON_NONE);
1698         
1699         uiItemS(layout);
1700         
1701         uiItemR(layout, ptr, "spin", 0, NULL, ICON_NONE);
1702         uiItemR(layout, ptr, "zoom", 0, NULL, ICON_NONE);
1703 }
1704
1705 static void node_composit_buts_bilateralblur(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1706 {       
1707         uiLayout *col;
1708         
1709         col = uiLayoutColumn(layout, TRUE);
1710         uiItemR(col, ptr, "iterations", 0, NULL, ICON_NONE);
1711         uiItemR(col, ptr, "sigma_color", 0, NULL, ICON_NONE);
1712         uiItemR(col, ptr, "sigma_space", 0, NULL, ICON_NONE);
1713 }
1714
1715 static void node_composit_buts_defocus(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1716 {
1717         uiLayout *sub, *col;
1718         
1719         col = uiLayoutColumn(layout, FALSE);
1720         uiItemL(col, IFACE_("Bokeh Type:"), ICON_NONE);
1721         uiItemR(col, ptr, "bokeh", 0, "", ICON_NONE);
1722         uiItemR(col, ptr, "angle", 0, NULL, ICON_NONE);
1723
1724         uiItemR(layout, ptr, "use_gamma_correction", 0, NULL, ICON_NONE);
1725
1726         col = uiLayoutColumn(layout, FALSE);
1727         uiLayoutSetActive(col, RNA_boolean_get(ptr, "use_zbuffer") == TRUE);
1728         uiItemR(col, ptr, "f_stop", 0, NULL, ICON_NONE);
1729
1730         uiItemR(layout, ptr, "blur_max", 0, NULL, ICON_NONE);
1731         uiItemR(layout, ptr, "threshold", 0, NULL, ICON_NONE);
1732
1733         col = uiLayoutColumn(layout, FALSE);
1734         uiItemR(col, ptr, "use_preview", 0, NULL, ICON_NONE);
1735         
1736         col = uiLayoutColumn(layout, FALSE);
1737         uiItemR(col, ptr, "use_zbuffer", 0, NULL, ICON_NONE);
1738         sub = uiLayoutColumn(col, FALSE);
1739         uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_zbuffer") == FALSE);
1740         uiItemR(sub, ptr, "z_scale", 0, NULL, ICON_NONE);
1741 }
1742
1743 /* qdn: glare node */
1744 static void node_composit_buts_glare(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1745 {       
1746         uiItemR(layout, ptr, "glare_type", 0, "", ICON_NONE);
1747         uiItemR(layout, ptr, "quality", 0, "", ICON_NONE);
1748
1749         if (RNA_enum_get(ptr, "glare_type") != 1) {
1750                 uiItemR(layout, ptr, "iterations", 0, NULL, ICON_NONE);
1751         
1752                 if (RNA_enum_get(ptr, "glare_type") != 0)
1753                         uiItemR(layout, ptr, "color_modulation", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
1754         }
1755         
1756         uiItemR(layout, ptr, "mix", 0, NULL, ICON_NONE);
1757         uiItemR(layout, ptr, "threshold", 0, NULL, ICON_NONE);
1758
1759         if (RNA_enum_get(ptr, "glare_type") == 2) {
1760                 uiItemR(layout, ptr, "streaks", 0, NULL, ICON_NONE);
1761                 uiItemR(layout, ptr, "angle_offset", 0, NULL, ICON_NONE);
1762         }
1763         if (RNA_enum_get(ptr, "glare_type") == 0 || RNA_enum_get(ptr, "glare_type") == 2) {
1764                 uiItemR(layout, ptr, "fade", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
1765                 
1766                 if (RNA_enum_get(ptr, "glare_type") == 0)
1767                         uiItemR(layout, ptr, "use_rotate_45", 0, NULL, ICON_NONE);
1768         }
1769         if (RNA_enum_get(ptr, "glare_type") == 1) {
1770                 uiItemR(layout, ptr, "size", 0, NULL, ICON_NONE);
1771         }
1772 }
1773
1774 static void node_composit_buts_tonemap(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1775 {       
1776         uiLayout *col;
1777
1778         col = uiLayoutColumn(layout, FALSE);
1779         uiItemR(col, ptr, "tonemap_type", 0, "", ICON_NONE);
1780         if (RNA_enum_get(ptr, "tonemap_type") == 0) {
1781                 uiItemR(col, ptr, "key", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
1782                 uiItemR(col, ptr, "offset", 0, NULL, ICON_NONE);
1783                 uiItemR(col, ptr, "gamma", 0, NULL, ICON_NONE);
1784         }
1785         else {
1786                 uiItemR(col, ptr, "intensity", 0, NULL, ICON_NONE);
1787                 uiItemR(col, ptr, "contrast", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
1788                 uiItemR(col, ptr, "adaptation", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
1789                 uiItemR(col, ptr, "correction", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
1790         }
1791 }
1792
1793 static void node_composit_buts_lensdist(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1794 {
1795         uiLayout *col;
1796
1797         col = uiLayoutColumn(layout, FALSE);
1798         uiItemR(col, ptr, "use_projector", 0, NULL, ICON_NONE);
1799
1800         col = uiLayoutColumn(col, FALSE);
1801         uiLayoutSetActive(col, RNA_boolean_get(ptr, "use_projector") == FALSE);
1802         uiItemR(col, ptr, "use_jitter", 0, NULL, ICON_NONE);
1803         uiItemR(col, ptr, "use_fit", 0, NULL, ICON_NONE);
1804 }
1805
1806 static void node_composit_buts_vecblur(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1807 {
1808         uiLayout *col;
1809         
1810         col = uiLayoutColumn(layout, FALSE);
1811         uiItemR(col, ptr, "samples", 0, NULL, ICON_NONE);
1812         uiItemR(col, ptr, "factor", 0, IFACE_("Blur"), ICON_NONE);
1813         
1814         col = uiLayoutColumn(layout, TRUE);
1815         uiItemL(col, IFACE_("Speed:"), ICON_NONE);
1816         uiItemR(col, ptr, "speed_min", 0, IFACE_("Min"), ICON_NONE);
1817         uiItemR(col, ptr, "speed_max", 0, IFACE_("Max"), ICON_NONE);
1818
1819         uiItemR(layout, ptr, "use_curved", 0, NULL, ICON_NONE);
1820 }
1821
1822 static void node_composit_buts_filter(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1823 {
1824         uiItemR(layout, ptr, "filter_type", 0, "", ICON_NONE);
1825 }
1826
1827 static void node_composit_buts_flip(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1828 {
1829         uiItemR(layout, ptr, "axis", 0, "", ICON_NONE);
1830 }
1831
1832 static void node_composit_buts_crop(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1833 {
1834         uiLayout *col;
1835
1836         uiItemR(layout, ptr, "use_crop_size", 0, NULL, ICON_NONE);
1837         uiItemR(layout, ptr, "relative", 0, NULL, ICON_NONE);
1838
1839         col = uiLayoutColumn(layout, TRUE);
1840         if (RNA_boolean_get(ptr, "relative")) {
1841                 uiItemR(col, ptr, "rel_min_x", 0, IFACE_("Left"), ICON_NONE);
1842                 uiItemR(col, ptr, "rel_max_x", 0, IFACE_("Right"), ICON_NONE);
1843                 uiItemR(col, ptr, "rel_min_y", 0, IFACE_("Up"), ICON_NONE);
1844                 uiItemR(col, ptr, "rel_max_y", 0, IFACE_("Down"), ICON_NONE);
1845         }
1846         else {
1847                 uiItemR(col, ptr, "min_x", 0, IFACE_("Left"), ICON_NONE);
1848                 uiItemR(col, ptr, "max_x", 0, IFACE_("Right"), ICON_NONE);
1849                 uiItemR(col, ptr, "min_y", 0, IFACE_("Up"), ICON_NONE);
1850                 uiItemR(col, ptr, "max_y", 0, IFACE_("Down"), ICON_NONE);
1851         }
1852 }
1853
1854 static void node_composit_buts_splitviewer(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1855 {
1856         uiLayout *row, *col;
1857         
1858         col = uiLayoutColumn(layout, FALSE);
1859         row = uiLayoutRow(col, FALSE);
1860         uiItemR(row, ptr, "axis", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
1861         uiItemR(col, ptr, "factor", 0, NULL, ICON_NONE);
1862 }
1863
1864 static void node_composit_buts_double_edge_mask(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1865 {
1866         uiLayout *col;
1867
1868         col = uiLayoutColumn(layout, FALSE);
1869
1870         uiItemL(col, IFACE_("Inner Edge:"), ICON_NONE);
1871         uiItemR(col, ptr, "inner_mode", 0, "", ICON_NONE);
1872         uiItemL(col, IFACE_("Buffer Edge:"), ICON_NONE);
1873         uiItemR(col, ptr, "edge_mode", 0, "", ICON_NONE);
1874 }
1875
1876 static void node_composit_buts_map_range(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1877 {
1878         uiLayout *col;
1879
1880         col = uiLayoutColumn(layout, TRUE);
1881         uiItemR(col, ptr, "use_clamp", 0, NULL, ICON_NONE);
1882 }
1883
1884 static void node_composit_buts_map_value(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1885 {
1886         uiLayout *sub, *col;
1887         
1888         col = uiLayoutColumn(layout, TRUE);
1889         uiItemR(col, ptr, "offset", 0, NULL, ICON_NONE);
1890         uiItemR(col, ptr, "size", 0, NULL, ICON_NONE);
1891         
1892         col = uiLayoutColumn(layout, TRUE);
1893         uiItemR(col, ptr, "use_min", 0, NULL, ICON_NONE);
1894         sub = uiLayoutColumn(col, FALSE);
1895         uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_min"));
1896         uiItemR(sub, ptr, "min", 0, "", ICON_NONE);
1897         
1898         col = uiLayoutColumn(layout, TRUE);
1899         uiItemR(col, ptr, "use_max", 0, NULL, ICON_NONE);
1900         sub = uiLayoutColumn(col, FALSE);
1901         uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_max"));
1902         uiItemR(sub, ptr, "max", 0, "", ICON_NONE);
1903 }
1904
1905 static void node_composit_buts_alphaover(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1906 {       
1907         uiLayout *col;
1908         
1909         col = uiLayoutColumn(layout, TRUE);
1910         uiItemR(col, ptr, "use_premultiply", 0, NULL, ICON_NONE);
1911         uiItemR(col, ptr, "premul", 0, NULL, ICON_NONE);
1912 }
1913
1914 static void node_composit_buts_zcombine(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1915 {       
1916         uiLayout *col;
1917         
1918         col = uiLayoutColumn(layout, TRUE);
1919         uiItemR(col, ptr, "use_alpha", 0, NULL, ICON_NONE);
1920 }
1921
1922
1923 static void node_composit_buts_hue_sat(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1924 {
1925         uiLayout *col;
1926         
1927         col = uiLayoutColumn(layout, FALSE);
1928         uiItemR(col, ptr, "color_hue", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
1929         uiItemR(col, ptr, "color_saturation", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
1930         uiItemR(col, ptr, "color_value", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
1931 }
1932
1933 static void node_composit_buts_dilateerode(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1934 {
1935         uiItemR(layout, ptr, "type", 0, NULL, ICON_NONE);
1936         uiItemR(layout, ptr, "distance", 0, NULL, ICON_NONE);
1937         switch (RNA_enum_get(ptr, "type")) {
1938                 case CMP_NODE_DILATEERODE_DISTANCE_THRESH:
1939                         uiItemR(layout, ptr, "edge", 0, NULL, ICON_NONE);
1940                         break;
1941                 case CMP_NODE_DILATEERODE_DISTANCE_FEATHER:
1942                         uiItemR(layout, ptr, "falloff", 0, NULL, ICON_NONE);
1943                         break;
1944         }
1945 }
1946
1947 static void node_composit_buts_inpaint(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1948 {
1949         uiItemR(layout, ptr, "distance", 0, NULL, ICON_NONE);
1950 }
1951
1952 static void node_composit_buts_despeckle(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1953 {
1954         uiLayout *col;
1955
1956         col = uiLayoutColumn(layout, FALSE);
1957         uiItemR(col, ptr, "threshold", 0, NULL, ICON_NONE);
1958         uiItemR(col, ptr, "threshold_neighbour", 0, NULL, ICON_NONE);
1959 }
1960
1961 static void node_composit_buts_diff_matte(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1962 {
1963         uiLayout *col;
1964         
1965         col = uiLayoutColumn(layout, TRUE);
1966         uiItemR(col, ptr, "tolerance", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
1967         uiItemR(col, ptr, "falloff", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
1968 }
1969
1970 static void node_composit_buts_distance_matte(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1971 {
1972         uiLayout *col, *row;
1973         
1974         col = uiLayoutColumn(layout, TRUE);
1975    
1976         uiItemL(layout, IFACE_("Color Space:"), ICON_NONE);
1977         row = uiLayoutRow(layout, FALSE);
1978         uiItemR(row, ptr, "channel", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
1979
1980         uiItemR(col, ptr, "tolerance", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
1981         uiItemR(col, ptr, "falloff", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
1982 }
1983
1984 static void node_composit_buts_color_spill(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
1985 {
1986         uiLayout *row, *col;
1987         
1988         uiItemL(layout, IFACE_("Despill Channel:"), ICON_NONE);
1989         row = uiLayoutRow(layout, FALSE);
1990         uiItemR(row, ptr, "channel", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
1991
1992         col = uiLayoutColumn(layout, FALSE);
1993         uiItemR(col, ptr, "limit_method", 0, NULL, ICON_NONE);
1994
1995         if (RNA_enum_get(ptr, "limit_method") == 0) {
1996                 uiItemL(col, IFACE_("Limiting Channel:"), ICON_NONE);
1997                 row = uiLayoutRow(col, FALSE);
1998                 uiItemR(row, ptr, "limit_channel", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
1999         }
2000
2001         uiItemR(col, ptr, "ratio", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2002         uiItemR(col, ptr, "use_unspill", 0, NULL, ICON_NONE);
2003         if (RNA_boolean_get(ptr, "use_unspill") == TRUE) {
2004                 uiItemR(col, ptr, "unspill_red", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2005                 uiItemR(col, ptr, "unspill_green", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2006                 uiItemR(col, ptr, "unspill_blue", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2007         }
2008 }
2009
2010 static void node_composit_buts_chroma_matte(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2011 {
2012         uiLayout *col;
2013         
2014         col = uiLayoutColumn(layout, FALSE);
2015         uiItemR(col, ptr, "tolerance", 0, NULL, ICON_NONE);
2016         uiItemR(col, ptr, "threshold", 0, NULL, ICON_NONE);
2017         
2018         col = uiLayoutColumn(layout, TRUE);
2019         /*uiItemR(col, ptr, "lift", UI_ITEM_R_SLIDER, NULL, ICON_NONE);  Removed for now */
2020         uiItemR(col, ptr, "gain", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2021         /*uiItemR(col, ptr, "shadow_adjust", UI_ITEM_R_SLIDER, NULL, ICON_NONE);  Removed for now*/
2022 }
2023
2024 static void node_composit_buts_color_matte(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2025 {
2026         uiLayout *col;
2027         
2028         col = uiLayoutColumn(layout, TRUE);
2029         uiItemR(col, ptr, "color_hue", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2030         uiItemR(col, ptr, "color_saturation", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2031         uiItemR(col, ptr, "color_value", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2032 }
2033
2034 static void node_composit_buts_channel_matte(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2035 {       
2036         uiLayout *col, *row;
2037
2038         uiItemL(layout, IFACE_("Color Space:"), ICON_NONE);
2039         row = uiLayoutRow(layout, FALSE);
2040         uiItemR(row, ptr, "color_space", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
2041
2042         col = uiLayoutColumn(layout, FALSE);
2043         uiItemL(col, IFACE_("Key Channel:"), ICON_NONE);
2044         row = uiLayoutRow(col, FALSE);
2045         uiItemR(row, ptr, "matte_channel", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
2046
2047         col = uiLayoutColumn(layout, FALSE);
2048
2049         uiItemR(col, ptr, "limit_method", 0, NULL, ICON_NONE);
2050         if (RNA_enum_get(ptr, "limit_method") == 0) {
2051                 uiItemL(col, IFACE_("Limiting Channel:"), ICON_NONE);
2052                 row = uiLayoutRow(col, FALSE);
2053                 uiItemR(row, ptr, "limit_channel", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
2054         }
2055
2056         uiItemR(col, ptr, "limit_max", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2057         uiItemR(col, ptr, "limit_min", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2058 }
2059
2060 static void node_composit_buts_luma_matte(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2061 {
2062         uiLayout *col;
2063         
2064         col = uiLayoutColumn(layout, TRUE);
2065         uiItemR(col, ptr, "limit_max", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2066         uiItemR(col, ptr, "limit_min", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2067 }
2068
2069 static void node_composit_buts_map_uv(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2070 {
2071         uiItemR(layout, ptr, "alpha", 0, NULL, ICON_NONE);
2072 }
2073
2074 static void node_composit_buts_id_mask(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2075 {
2076         uiItemR(layout, ptr, "index", 0, NULL, ICON_NONE);
2077         uiItemR(layout, ptr, "use_antialiasing", 0, NULL, ICON_NONE);
2078 }
2079
2080 /* draw function for file output node sockets, displays only sub-path and format, no value button */
2081 static void node_draw_input_file_output(const bContext *C, uiBlock *block,
2082                                         bNodeTree *ntree, bNode *node, bNodeSocket *sock,
2083                                         const char *UNUSED(name), int x, int y, int width)
2084 {
2085         uiLayout *layout, *row;
2086         PointerRNA nodeptr, inputptr, imfptr;
2087         int imtype;
2088         int rx, ry;
2089         RNA_pointer_create(&ntree->id, &RNA_Node, node, &nodeptr);
2090         
2091         layout = uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, x, y + NODE_DY, width, 20, UI_GetStyle());
2092         row = uiLayoutRow(layout, FALSE);
2093         
2094         imfptr = RNA_pointer_get(&nodeptr, "format");
2095         imtype = RNA_enum_get(&imfptr, "file_format");
2096         if (imtype == R_IMF_IMTYPE_MULTILAYER) {
2097                 NodeImageMultiFileSocket *input = sock->storage;
2098                 RNA_pointer_create(&ntree->id, &RNA_NodeOutputFileSlotLayer, input, &inputptr);
2099                 
2100                 uiItemL(row, input->layer, ICON_NONE);
2101         }
2102         else {
2103                 NodeImageMultiFileSocket *input = sock->storage;
2104                 PropertyRNA *imtype_prop;
2105                 const char *imtype_name;
2106                 RNA_pointer_create(&ntree->id, &RNA_NodeOutputFileSlotFile, input, &inputptr);
2107                 
2108                 uiItemL(row, input->path, ICON_NONE);
2109                 
2110                 if (!RNA_boolean_get(&inputptr, "use_node_format"))
2111                         imfptr = RNA_pointer_get(&inputptr, "format");
2112                 
2113                 imtype_prop = RNA_struct_find_property(&imfptr, "file_format");
2114                 RNA_property_enum_name((bContext *)C, &imfptr, imtype_prop,
2115                                        RNA_property_enum_get(&imfptr, imtype_prop), &imtype_name);
2116                 uiBlockSetEmboss(block, UI_EMBOSSP);
2117                 uiItemL(row, imtype_name, ICON_NONE);
2118                 uiBlockSetEmboss(block, UI_EMBOSSN);
2119         }
2120         
2121         uiBlockLayoutResolve(block, &rx, &ry);
2122 }
2123 static void node_composit_buts_file_output(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2124 {
2125         PointerRNA imfptr = RNA_pointer_get(ptr, "format");
2126         int multilayer = (RNA_enum_get(&imfptr, "file_format") == R_IMF_IMTYPE_MULTILAYER);
2127         
2128         if (multilayer)
2129                 uiItemL(layout, IFACE_("Path:"), ICON_NONE);
2130         else
2131                 uiItemL(layout, IFACE_("Base Path:"), ICON_NONE);
2132         uiItemR(layout, ptr, "base_path", 0, "", ICON_NONE);
2133 }
2134 static void node_composit_buts_file_output_details(uiLayout *layout, bContext *C, PointerRNA *ptr)
2135 {
2136         PointerRNA imfptr = RNA_pointer_get(ptr, "format");
2137         PointerRNA active_input_ptr, op_ptr;
2138         uiLayout *row, *col;
2139         int active_index;
2140         int multilayer = (RNA_enum_get(&imfptr, "file_format") == R_IMF_IMTYPE_MULTILAYER);
2141         
2142         node_composit_buts_file_output(layout, C, ptr);
2143         uiTemplateImageSettings(layout, &imfptr, FALSE);
2144         
2145         uiItemS(layout);
2146         
2147         uiItemO(layout, IFACE_("Add Input"), ICON_ZOOMIN, "NODE_OT_output_file_add_socket");
2148         
2149         row = uiLayoutRow(layout, FALSE);
2150         col = uiLayoutColumn(row, TRUE);
2151         
2152         active_index = RNA_int_get(ptr, "active_input_index");
2153         /* using different collection properties if multilayer format is enabled */
2154         if (multilayer) {
2155                 uiTemplateList(col, C, ptr, "layer_slots", ptr, "active_input_index", NULL, 0, 0, 0);
2156                 RNA_property_collection_lookup_int(ptr, RNA_struct_find_property(ptr, "layer_slots"),
2157                                                    active_index, &active_input_ptr);
2158         }
2159         else {
2160                 uiTemplateList(col, C, ptr, "file_slots", ptr, "active_input_index", NULL, 0, 0, 0);
2161                 RNA_property_collection_lookup_int(ptr, RNA_struct_find_property(ptr, "file_slots"),
2162                                                    active_index, &active_input_ptr);
2163         }
2164         /* XXX collection lookup does not return the ID part of the pointer, setting this manually here */
2165         active_input_ptr.id.data = ptr->id.data;
2166         
2167         col = uiLayoutColumn(row, TRUE);
2168         op_ptr = uiItemFullO(col, "NODE_OT_output_file_move_active_socket", "",
2169                              ICON_TRIA_UP, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS);
2170         RNA_enum_set(&op_ptr, "direction", 1);
2171         op_ptr = uiItemFullO(col, "NODE_OT_output_file_move_active_socket", "",
2172                              ICON_TRIA_DOWN, NULL, WM_OP_INVOKE_DEFAULT, UI_ITEM_O_RETURN_PROPS);
2173         RNA_enum_set(&op_ptr, "direction", 2);
2174         
2175         if (active_input_ptr.data) {
2176                 if (multilayer) {
2177                         col = uiLayoutColumn(layout, TRUE);
2178                         
2179                         uiItemL(col, IFACE_("Layer:"), ICON_NONE);
2180                         row = uiLayoutRow(col, FALSE);
2181                         uiItemR(row, &active_input_ptr, "name", 0, "", ICON_NONE);
2182                         uiItemFullO(row, "NODE_OT_output_file_remove_active_socket", "",
2183                                     ICON_X, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_R_ICON_ONLY);
2184                 }
2185                 else {
2186                         col = uiLayoutColumn(layout, TRUE);
2187                         
2188                         uiItemL(col, IFACE_("File Path:"), ICON_NONE);
2189                         row = uiLayoutRow(col, FALSE);
2190                         uiItemR(row, &active_input_ptr, "path", 0, "", ICON_NONE);
2191                         uiItemFullO(row, "NODE_OT_output_file_remove_active_socket", "",
2192                                     ICON_X, NULL, WM_OP_EXEC_DEFAULT, UI_ITEM_R_ICON_ONLY);
2193                         
2194                         /* format details for individual files */
2195                         imfptr = RNA_pointer_get(&active_input_ptr, "format");
2196                         
2197                         col = uiLayoutColumn(layout, TRUE);
2198                         uiItemL(col, IFACE_("Format:"), ICON_NONE);
2199                         uiItemR(col, &active_input_ptr, "use_node_format", 0, NULL, ICON_NONE);
2200                         
2201                         col = uiLayoutColumn(layout, FALSE);
2202                         uiLayoutSetActive(col, RNA_boolean_get(&active_input_ptr, "use_node_format") == FALSE);
2203                         uiTemplateImageSettings(col, &imfptr, FALSE);
2204                 }
2205         }
2206 }
2207
2208 static void node_composit_buts_scale(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2209 {
2210         uiItemR(layout, ptr, "space", 0, "", ICON_NONE);
2211
2212         if (RNA_enum_get(ptr, "space") == CMP_SCALE_RENDERPERCENT) {
2213                 uiLayout *row;
2214                 uiItemR(layout, ptr, "frame_method", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
2215                 row = uiLayoutRow(layout, TRUE);
2216                 uiItemR(row, ptr, "offset_x", 0, "X", ICON_NONE);
2217                 uiItemR(row, ptr, "offset_y", 0, "Y", ICON_NONE);
2218         }
2219 }
2220
2221 static void node_composit_buts_rotate(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2222 {
2223         uiItemR(layout, ptr, "filter_type", 0, "", ICON_NONE);
2224 }
2225
2226 static void node_composit_buts_invert(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2227 {
2228         uiLayout *col;
2229         
2230         col = uiLayoutColumn(layout, FALSE);
2231         uiItemR(col, ptr, "invert_rgb", 0, NULL, ICON_NONE);
2232         uiItemR(col, ptr, "invert_alpha", 0, NULL, ICON_NONE);
2233 }
2234
2235 static void node_composit_buts_premulkey(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2236 {
2237         uiItemR(layout, ptr, "mapping", 0, "", ICON_NONE);
2238 }
2239
2240 static void node_composit_buts_view_levels(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2241 {
2242         uiItemR(layout, ptr, "channel", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
2243 }
2244
2245 static void node_composit_buts_colorbalance(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2246 {
2247         uiLayout *split, *col, *row;
2248         
2249         uiItemR(layout, ptr, "correction_method", 0, NULL, ICON_NONE);
2250         
2251         if (RNA_enum_get(ptr, "correction_method") == 0) {
2252         
2253                 split = uiLayoutSplit(layout, 0.0f, FALSE);
2254                 col = uiLayoutColumn(split, FALSE);
2255                 uiTemplateColorPicker(col, ptr, "lift", 1, 1, 0, 1);
2256                 row = uiLayoutRow(col, FALSE);
2257                 uiItemR(row, ptr, "lift", 0, NULL, ICON_NONE);
2258                 
2259                 col = uiLayoutColumn(split, FALSE);
2260                 uiTemplateColorPicker(col, ptr, "gamma", 1, 1, 1, 1);
2261                 row = uiLayoutRow(col, FALSE);
2262                 uiItemR(row, ptr, "gamma", 0, NULL, ICON_NONE);
2263                 
2264                 col = uiLayoutColumn(split, FALSE);
2265                 uiTemplateColorPicker(col, ptr, "gain", 1, 1, 1, 1);
2266                 row = uiLayoutRow(col, FALSE);
2267                 uiItemR(row, ptr, "gain", 0, NULL, ICON_NONE);
2268
2269         }
2270         else {
2271                 
2272                 split = uiLayoutSplit(layout, 0.0f, FALSE);
2273                 col = uiLayoutColumn(split, FALSE);
2274                 uiTemplateColorPicker(col, ptr, "offset", 1, 1, 0, 1);
2275                 row = uiLayoutRow(col, FALSE);
2276                 uiItemR(row, ptr, "offset", 0, NULL, ICON_NONE);
2277                 
2278                 col = uiLayoutColumn(split, FALSE);
2279                 uiTemplateColorPicker(col, ptr, "power", 1, 1, 0, 1);
2280                 row = uiLayoutRow(col, FALSE);
2281                 uiItemR(row, ptr, "power", 0, NULL, ICON_NONE);
2282                 
2283                 col = uiLayoutColumn(split, FALSE);
2284                 uiTemplateColorPicker(col, ptr, "slope", 1, 1, 0, 1);
2285                 row = uiLayoutRow(col, FALSE);
2286                 uiItemR(row, ptr, "slope", 0, NULL, ICON_NONE);
2287         }
2288
2289 }
2290 static void node_composit_buts_colorbalance_but(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2291 {
2292         uiItemR(layout, ptr, "correction_method", 0, NULL, ICON_NONE);
2293
2294         if (RNA_enum_get(ptr, "correction_method") == 0) {
2295
2296                 uiTemplateColorPicker(layout, ptr, "lift", 1, 1, 0, 1);
2297                 uiItemR(layout, ptr, "lift", 0, NULL, ICON_NONE);
2298
2299                 uiTemplateColorPicker(layout, ptr, "gamma", 1, 1, 1, 1);
2300                 uiItemR(layout, ptr, "gamma", 0, NULL, ICON_NONE);
2301
2302                 uiTemplateColorPicker(layout, ptr, "gain", 1, 1, 1, 1);
2303                 uiItemR(layout, ptr, "gain", 0, NULL, ICON_NONE);
2304         }
2305         else {
2306                 uiTemplateColorPicker(layout, ptr, "offset", 1, 1, 0, 1);
2307                 uiItemR(layout, ptr, "offset", 0, NULL, ICON_NONE);
2308
2309                 uiTemplateColorPicker(layout, ptr, "power", 1, 1, 0, 1);
2310                 uiItemR(layout, ptr, "power", 0, NULL, ICON_NONE);
2311
2312                 uiTemplateColorPicker(layout, ptr, "slope", 1, 1, 0, 1);
2313                 uiItemR(layout, ptr, "slope", 0, NULL, ICON_NONE);
2314         }
2315 }
2316
2317
2318 static void node_composit_buts_huecorrect(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2319 {
2320         bNode *node = ptr->data;
2321         CurveMapping *cumap = node->storage;
2322
2323         if (_sample_col[0] != SAMPLE_FLT_ISNONE) {
2324                 cumap->flag |= CUMA_DRAW_SAMPLE;
2325                 copy_v3_v3(cumap->sample, _sample_col);
2326         }
2327         else {
2328                 cumap->flag &= ~CUMA_DRAW_SAMPLE;
2329         }
2330
2331         uiTemplateCurveMapping(layout, ptr, "mapping", 'h', 0, 0);
2332 }
2333
2334 static void node_composit_buts_ycc(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2335
2336         uiItemR(layout, ptr, "mode", 0, "", ICON_NONE);
2337 }
2338
2339 static void node_composit_buts_movieclip(uiLayout *layout, bContext *C, PointerRNA *ptr)
2340 {
2341         uiTemplateID(layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL);
2342 }
2343
2344 static void node_composit_buts_movieclip_details(uiLayout *layout, bContext *C, PointerRNA *ptr)
2345 {
2346         bNode *node = ptr->data;
2347         PointerRNA clipptr;
2348
2349         uiTemplateID(layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL);
2350
2351         if (!node->id)
2352                 return;
2353
2354         clipptr = RNA_pointer_get(ptr, "clip");
2355
2356         uiTemplateColorspaceSettings(layout, &clipptr, "colorspace_settings");
2357 }
2358
2359 static void node_composit_buts_stabilize2d(uiLayout *layout, bContext *C, PointerRNA *ptr)
2360 {
2361         bNode *node = ptr->data;
2362
2363         uiTemplateID(layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL);
2364
2365         if (!node->id)
2366                 return;
2367
2368         uiItemR(layout, ptr, "filter_type", 0, "", ICON_NONE);
2369 }
2370
2371 static void node_composit_buts_transform(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2372 {
2373         uiItemR(layout, ptr, "filter_type", 0, "", ICON_NONE);
2374 }
2375
2376 static void node_composit_buts_moviedistortion(uiLayout *layout, bContext *C, PointerRNA *ptr)
2377 {
2378         bNode *node = ptr->data;
2379
2380         uiTemplateID(layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL);
2381
2382         if (!node->id)
2383                 return;
2384
2385         uiItemR(layout, ptr, "distortion_type", 0, "", ICON_NONE);
2386 }
2387
2388 static void node_composit_buts_colorcorrection(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2389 {
2390         uiLayout *row;
2391         
2392         row = uiLayoutRow(layout, FALSE);
2393         uiItemR(row, ptr, "red", 0, NULL, ICON_NONE);
2394         uiItemR(row, ptr, "green", 0, NULL, ICON_NONE);
2395         uiItemR(row, ptr, "blue", 0, NULL, ICON_NONE);
2396
2397         row = uiLayoutRow(layout, FALSE);
2398         uiItemL(row, "", ICON_NONE);
2399         uiItemL(row, IFACE_("Saturation"), ICON_NONE);
2400         uiItemL(row, IFACE_("Contrast"), ICON_NONE);
2401         uiItemL(row, IFACE_("Gamma"), ICON_NONE);
2402         uiItemL(row, IFACE_("Gain"), ICON_NONE);
2403         uiItemL(row, IFACE_("Lift"), ICON_NONE);
2404
2405         row = uiLayoutRow(layout, FALSE);
2406         uiItemL(row, IFACE_("Master"), ICON_NONE);
2407         uiItemR(row, ptr, "master_saturation", UI_ITEM_R_SLIDER, "", ICON_NONE);
2408         uiItemR(row, ptr, "master_contrast", UI_ITEM_R_SLIDER, "", ICON_NONE);
2409         uiItemR(row, ptr, "master_gamma", UI_ITEM_R_SLIDER, "", ICON_NONE);
2410         uiItemR(row, ptr, "master_gain", UI_ITEM_R_SLIDER, "", ICON_NONE);
2411         uiItemR(row, ptr, "master_lift", UI_ITEM_R_SLIDER, "", ICON_NONE);
2412
2413         row = uiLayoutRow(layout, FALSE);
2414         uiItemL(row, IFACE_("Highlights"), ICON_NONE);
2415         uiItemR(row, ptr, "highlights_saturation", UI_ITEM_R_SLIDER, "", ICON_NONE);
2416         uiItemR(row, ptr, "highlights_contrast", UI_ITEM_R_SLIDER, "", ICON_NONE);
2417         uiItemR(row, ptr, "highlights_gamma", UI_ITEM_R_SLIDER, "", ICON_NONE);
2418         uiItemR(row, ptr, "highlights_gain", UI_ITEM_R_SLIDER, "", ICON_NONE);
2419         uiItemR(row, ptr, "highlights_lift", UI_ITEM_R_SLIDER, "", ICON_NONE);
2420
2421         row = uiLayoutRow(layout, FALSE);
2422         uiItemL(row, IFACE_("Midtones"), ICON_NONE);
2423         uiItemR(row, ptr, "midtones_saturation", UI_ITEM_R_SLIDER, "", ICON_NONE);
2424         uiItemR(row, ptr, "midtones_contrast", UI_ITEM_R_SLIDER, "", ICON_NONE);
2425         uiItemR(row, ptr, "midtones_gamma", UI_ITEM_R_SLIDER, "", ICON_NONE);
2426         uiItemR(row, ptr, "midtones_gain", UI_ITEM_R_SLIDER, "", ICON_NONE);
2427         uiItemR(row, ptr, "midtones_lift", UI_ITEM_R_SLIDER, "", ICON_NONE);
2428
2429         row = uiLayoutRow(layout, FALSE);
2430         uiItemL(row, IFACE_("Shadows"), ICON_NONE);
2431         uiItemR(row, ptr, "shadows_saturation", UI_ITEM_R_SLIDER, "", ICON_NONE);
2432         uiItemR(row, ptr, "shadows_contrast", UI_ITEM_R_SLIDER, "", ICON_NONE);
2433         uiItemR(row, ptr, "shadows_gamma", UI_ITEM_R_SLIDER, "", ICON_NONE);
2434         uiItemR(row, ptr, "shadows_gain", UI_ITEM_R_SLIDER, "", ICON_NONE);
2435         uiItemR(row, ptr, "shadows_lift", UI_ITEM_R_SLIDER, "", ICON_NONE);
2436
2437         row = uiLayoutRow(layout, FALSE);
2438         uiItemR(row, ptr, "midtones_start", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2439         uiItemR(row, ptr, "midtones_end", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2440 }
2441
2442 static void node_composit_buts_colorcorrection_but(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2443 {
2444         uiLayout *row;
2445         
2446         row = uiLayoutRow(layout, FALSE);
2447         uiItemR(row, ptr, "red", 0, NULL, ICON_NONE);
2448         uiItemR(row, ptr, "green", 0, NULL, ICON_NONE);
2449         uiItemR(row, ptr, "blue", 0, NULL, ICON_NONE);
2450         row = layout;
2451         uiItemL(row, IFACE_("Saturation"), ICON_NONE);
2452         uiItemR(row, ptr, "master_saturation", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2453         uiItemR(row, ptr, "highlights_saturation", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2454         uiItemR(row, ptr, "midtones_saturation", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2455         uiItemR(row, ptr, "shadows_saturation", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2456
2457         uiItemL(row, IFACE_("Contrast"), ICON_NONE);
2458         uiItemR(row, ptr, "master_contrast", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2459         uiItemR(row, ptr, "highlights_contrast", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2460         uiItemR(row, ptr, "midtones_contrast", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2461         uiItemR(row, ptr, "shadows_contrast", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2462
2463         uiItemL(row, IFACE_("Gamma"), ICON_NONE);
2464         uiItemR(row, ptr, "master_gamma", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2465         uiItemR(row, ptr, "highlights_gamma", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2466         uiItemR(row, ptr, "midtones_gamma", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2467         uiItemR(row, ptr, "shadows_gamma", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2468
2469         uiItemL(row, IFACE_("Gain"), ICON_NONE);
2470         uiItemR(row, ptr, "master_gain", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2471         uiItemR(row, ptr, "highlights_gain", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2472         uiItemR(row, ptr, "midtones_gain", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2473         uiItemR(row, ptr, "shadows_gain", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2474         
2475         uiItemL(row, IFACE_("Lift"), ICON_NONE);
2476         uiItemR(row, ptr, "master_lift", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2477         uiItemR(row, ptr, "highlights_lift", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2478         uiItemR(row, ptr, "midtones_lift", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2479         uiItemR(row, ptr, "shadows_lift", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2480
2481         row = uiLayoutRow(layout, FALSE);
2482         uiItemR(row, ptr, "midtones_start", 0, NULL, ICON_NONE);
2483         uiItemR(row, ptr, "midtones_end", 0, NULL, ICON_NONE);
2484 }
2485
2486 static void node_composit_buts_switch(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2487 {
2488         uiItemR(layout, ptr, "check", 0, NULL, ICON_NONE);
2489 }
2490
2491 static void node_composit_buts_boxmask(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2492 {
2493         uiLayout *row;
2494         
2495         row = uiLayoutRow(layout, TRUE);
2496         uiItemR(row, ptr, "x", 0, NULL, ICON_NONE);
2497         uiItemR(row, ptr, "y", 0, NULL, ICON_NONE);
2498         
2499         row = uiLayoutRow(layout, TRUE);
2500         uiItemR(row, ptr, "width", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2501         uiItemR(row, ptr, "height", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2502
2503         uiItemR(layout, ptr, "rotation", 0, NULL, ICON_NONE);
2504         uiItemR(layout, ptr, "mask_type", 0, NULL, ICON_NONE);
2505 }
2506
2507 static void node_composit_buts_bokehimage(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2508 {
2509         uiItemR(layout, ptr, "flaps", 0, NULL, ICON_NONE);
2510         uiItemR(layout, ptr, "angle", 0, NULL, ICON_NONE);
2511         uiItemR(layout, ptr, "rounding", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2512         uiItemR(layout, ptr, "catadioptric", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2513         uiItemR(layout, ptr, "shift", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2514 }
2515
2516 static void node_composit_buts_bokehblur(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2517 {
2518         uiItemR(layout, ptr, "use_variable_size", 0, NULL, ICON_NONE);
2519         // uiItemR(layout, ptr, "f_stop", 0, NULL, ICON_NONE);  // UNUSED
2520         uiItemR(layout, ptr, "blur_max", 0, NULL, ICON_NONE);
2521 }
2522
2523 static void node_composit_backdrop_viewer(SpaceNode *snode, ImBuf *backdrop, bNode *node, int x, int y)
2524 {
2525 //      node_composit_backdrop_canvas(snode, backdrop, node, x, y);
2526         if (node->custom1 == 0) {
2527                 const float backdropWidth = backdrop->x;
2528                 const float backdropHeight = backdrop->y;
2529                 const float cx  = x + snode->zoom * backdropWidth * node->custom3;
2530                 const float cy = y + snode->zoom * backdropHeight * node->custom4;
2531
2532                 glColor3f(1.0, 1.0, 1.0);
2533
2534                 glBegin(GL_LINES);
2535                 glVertex2f(cx - 25, cy - 25);
2536                 glVertex2f(cx + 25, cy + 25);
2537                 glVertex2f(cx + 25, cy - 25);
2538                 glVertex2f(cx - 25, cy + 25);
2539                 glEnd();
2540         }
2541 }
2542
2543 static void node_composit_backdrop_boxmask(SpaceNode *snode, ImBuf *backdrop, bNode *node, int x, int y)
2544 {
2545         NodeBoxMask *boxmask = node->storage;
2546         const float backdropWidth = backdrop->x;
2547         const float backdropHeight = backdrop->y;
2548         const float aspect = backdropWidth / backdropHeight;
2549         const float rad = DEG2RADF(-boxmask->rotation);
2550         const float cosine = cosf(rad);
2551         const float sine = sinf(rad);
2552         const float halveBoxWidth = backdropWidth * (boxmask->width / 2.0f);
2553         const float halveBoxHeight = backdropHeight * (boxmask->height / 2.0f) * aspect;
2554
2555         float cx, cy, x1, x2, x3, x4;
2556         float y1, y2, y3, y4;
2557
2558
2559         /* keep this, saves us from a version patch */
2560         if (snode->zoom == 0.0f) snode->zoom = 1.0f;
2561
2562         glColor3f(1.0, 1.0, 1.0);
2563
2564         cx  = x + snode->zoom * backdropWidth * boxmask->x;
2565         cy = y + snode->zoom * backdropHeight * boxmask->y;
2566
2567         x1 = cx - (cosine * halveBoxWidth + sine * halveBoxHeight) * snode->zoom;
2568         x2 = cx - (cosine * -halveBoxWidth + sine * halveBoxHeight) * snode->zoom;
2569         x3 = cx - (cosine * -halveBoxWidth + sine * -halveBoxHeight) * snode->zoom;
2570         x4 = cx - (cosine * halveBoxWidth + sine * -halveBoxHeight) * snode->zoom;
2571         y1 = cy - (-sine * halveBoxWidth + cosine * halveBoxHeight) * snode->zoom;
2572         y2 = cy - (-sine * -halveBoxWidth + cosine * halveBoxHeight) * snode->zoom;
2573         y3 = cy - (-sine * -halveBoxWidth + cosine * -halveBoxHeight) * snode->zoom;
2574         y4 = cy - (-sine * halveBoxWidth + cosine * -halveBoxHeight) * snode->zoom;
2575
2576         glBegin(GL_LINE_LOOP);
2577         glVertex2f(x1, y1);
2578         glVertex2f(x2, y2);
2579         glVertex2f(x3, y3);
2580         glVertex2f(x4, y4);
2581         glEnd();
2582 }
2583
2584 static void node_composit_backdrop_ellipsemask(SpaceNode *snode, ImBuf *backdrop, bNode *node, int x, int y)
2585 {
2586         NodeEllipseMask *ellipsemask = node->storage;
2587         const float backdropWidth = backdrop->x;
2588         const float backdropHeight = backdrop->y;
2589         const float aspect = backdropWidth / backdropHeight;
2590         const float rad = DEG2RADF(-ellipsemask->rotation);
2591         const float cosine = cosf(rad);
2592         const float sine = sinf(rad);
2593         const float halveBoxWidth = backdropWidth * (ellipsemask->width / 2.0f);
2594         const float halveBoxHeight = backdropHeight * (ellipsemask->height / 2.0f) * aspect;
2595
2596         float cx, cy, x1, x2, x3, x4;
2597         float y1, y2, y3, y4;
2598
2599
2600         /* keep this, saves us from a version patch */
2601         if (snode->zoom == 0.0f) snode->zoom = 1.0f;
2602
2603         glColor3f(1.0, 1.0, 1.0);
2604
2605         cx  = x + snode->zoom * backdropWidth * ellipsemask->x;
2606         cy = y + snode->zoom * backdropHeight * ellipsemask->y;
2607
2608         x1 = cx - (cosine * halveBoxWidth + sine * halveBoxHeight) * snode->zoom;
2609         x2 = cx - (cosine * -halveBoxWidth + sine * halveBoxHeight) * snode->zoom;
2610         x3 = cx - (cosine * -halveBoxWidth + sine * -halveBoxHeight) * snode->zoom;
2611         x4 = cx - (cosine * halveBoxWidth + sine * -halveBoxHeight) * snode->zoom;
2612         y1 = cy - (-sine * halveBoxWidth + cosine * halveBoxHeight) * snode->zoom;
2613         y2 = cy - (-sine * -halveBoxWidth + cosine * halveBoxHeight) * snode->zoom;
2614         y3 = cy - (-sine * -halveBoxWidth + cosine * -halveBoxHeight) * snode->zoom;
2615         y4 = cy - (-sine * halveBoxWidth + cosine * -halveBoxHeight) * snode->zoom;
2616
2617         glBegin(GL_LINE_LOOP);
2618
2619         glVertex2f(x1, y1);
2620         glVertex2f(x2, y2);
2621         glVertex2f(x3, y3);
2622         glVertex2f(x4, y4);
2623         glEnd();
2624 }
2625
2626 static void node_composit_buts_ellipsemask(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2627 {
2628         uiLayout *row;
2629         row = uiLayoutRow(layout, TRUE);
2630         uiItemR(row, ptr, "x", 0, NULL, ICON_NONE);
2631         uiItemR(row, ptr, "y", 0, NULL, ICON_NONE);
2632         row = uiLayoutRow(layout, TRUE);
2633         uiItemR(row, ptr, "width", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2634         uiItemR(row, ptr, "height", UI_ITEM_R_SLIDER, NULL, ICON_NONE);
2635
2636         uiItemR(layout, ptr, "rotation", 0, NULL, ICON_NONE);
2637         uiItemR(layout, ptr, "mask_type", 0, NULL, ICON_NONE);
2638 }
2639
2640 static void node_composit_buts_viewer_but(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2641 {
2642         uiLayout *col;
2643         
2644         uiItemR(layout, ptr, "tile_order", 0, NULL, ICON_NONE);
2645         if (RNA_enum_get(ptr, "tile_order") == 0) {
2646                 col = uiLayoutColumn(layout, TRUE);
2647                 uiItemR(col, ptr, "center_x", 0, NULL, ICON_NONE);
2648                 uiItemR(col, ptr, "center_y", 0, NULL, ICON_NONE);
2649         }
2650 }
2651
2652 static void node_composit_buts_mask(uiLayout *layout, bContext *C, PointerRNA *ptr)
2653 {
2654         bNode *node = ptr->data;
2655
2656         uiTemplateID(layout, C, ptr, "mask", NULL, NULL, NULL);
2657         uiItemR(layout, ptr, "use_antialiasing", 0, NULL, ICON_NONE);
2658         uiItemR(layout, ptr, "use_feather", 0, NULL, ICON_NONE);
2659
2660         uiItemR(layout, ptr, "size_source", 0, "", ICON_NONE);
2661
2662         if (node->custom1 & (CMP_NODEFLAG_MASK_FIXED | CMP_NODEFLAG_MASK_FIXED_SCENE)) {
2663                 uiItemR(layout, ptr, "size_x", 0, NULL, ICON_NONE);
2664                 uiItemR(layout, ptr, "size_y", 0, NULL, ICON_NONE);
2665         }
2666
2667         uiItemR(layout, ptr, "use_motion_blur", 0, NULL, ICON_NONE);
2668         if (node->custom1 & CMP_NODEFLAG_MASK_MOTION_BLUR) {
2669                 uiItemR(layout, ptr, "motion_blur_samples", 0, NULL, ICON_NONE);
2670                 uiItemR(layout, ptr, "motion_blur_shutter", 0, NULL, ICON_NONE);
2671         }
2672 }
2673
2674 static void node_composit_buts_keyingscreen(uiLayout *layout, bContext *C, PointerRNA *ptr)
2675 {
2676         bNode *node = ptr->data;
2677
2678         uiTemplateID(layout, C, ptr, "clip", NULL, NULL, NULL);
2679
2680         if (node->id) {
2681                 MovieClip *clip = (MovieClip *) node->id;
2682                 uiLayout *col;
2683                 PointerRNA tracking_ptr;
2684
2685                 RNA_pointer_create(&clip->id, &RNA_MovieTracking, &clip->tracking, &tracking_ptr);
2686
2687                 col = uiLayoutColumn(layout, TRUE);
2688                 uiItemPointerR(col, ptr, "tracking_object", &tracking_ptr, "objects", "", ICON_OBJECT_DATA);
2689         }
2690 }
2691
2692 static void node_composit_buts_keying(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2693 {
2694         /* bNode *node = ptr->data; */ /* UNUSED */
2695
2696         uiItemR(layout, ptr, "blur_pre", 0, NULL, ICON_NONE);
2697         uiItemR(layout, ptr, "screen_balance", 0, NULL, ICON_NONE);
2698         uiItemR(layout, ptr, "despill_factor", 0, NULL, ICON_NONE);
2699         uiItemR(layout, ptr, "despill_balance", 0, NULL, ICON_NONE);
2700         uiItemR(layout, ptr, "edge_kernel_radius", 0, NULL, ICON_NONE);
2701         uiItemR(layout, ptr, "edge_kernel_tolerance", 0, NULL, ICON_NONE);
2702         uiItemR(layout, ptr, "clip_black", 0, NULL, ICON_NONE);
2703         uiItemR(layout, ptr, "clip_white", 0, NULL, ICON_NONE);
2704         uiItemR(layout, ptr, "dilate_distance", 0, NULL, ICON_NONE);
2705         uiItemR(layout, ptr, "feather_falloff", 0, NULL, ICON_NONE);
2706         uiItemR(layout, ptr, "feather_distance", 0, NULL, ICON_NONE);
2707         uiItemR(layout, ptr, "blur_post", 0, NULL, ICON_NONE);
2708 }
2709
2710 static void node_composit_buts_trackpos(uiLayout *layout, bContext *C, PointerRNA *ptr)
2711 {
2712         bNode *node = ptr->data;
2713
2714         uiTemplateID(layout, C, ptr, "clip", NULL, "CLIP_OT_open", NULL);
2715
2716         if (node->id) {
2717                 MovieClip *clip = (MovieClip *) node->id;
2718                 MovieTracking *tracking = &clip->tracking;
2719                 MovieTrackingObject *object;
2720                 uiLayout *col;
2721                 PointerRNA tracking_ptr;
2722                 NodeTrackPosData *data = node->storage;
2723
2724                 RNA_pointer_create(&clip->id, &RNA_MovieTracking, tracking, &tracking_ptr);
2725
2726                 col = uiLayoutColumn(layout, FALSE);
2727                 uiItemPointerR(col, ptr, "tracking_object", &tracking_ptr, "objects", "", ICON_OBJECT_DATA);
2728
2729                 object = BKE_tracking_object_get_named(tracking, data->tracking_object);
2730                 if (object) {
2731                         PointerRNA object_ptr;
2732
2733                         RNA_pointer_create(&clip->id, &RNA_MovieTrackingObject, object, &object_ptr);
2734
2735                         uiItemPointerR(col, ptr, "track_name", &object_ptr, "tracks", "", ICON_ANIM_DATA);
2736                 }
2737                 else {
2738                         uiItemR(layout, ptr, "track_name", 0, "", ICON_ANIM_DATA);
2739                 }
2740
2741                 uiItemR(layout, ptr, "position", 0, NULL, ICON_NONE);
2742
2743                 if (node->custom1 == 2) {
2744                         uiItemR(layout, ptr, "frame_relative", 0, NULL, ICON_NONE);
2745                 }
2746         }
2747 }
2748
2749 /* only once called */
2750 static void node_composit_set_butfunc(bNodeType *ntype)
2751 {
2752         switch (ntype->type) {
2753                 /* case NODE_GROUP: note, typeinfo for group is generated... see "XXX ugly hack" */
2754
2755                 case CMP_NODE_IMAGE:
2756                         ntype->uifunc = node_composit_buts_image;
2757                         ntype->uifuncbut = node_composit_buts_image_details;
2758                         break;
2759                 case CMP_NODE_R_LAYERS:
2760                         ntype->uifunc = node_composit_buts_renderlayers;
2761                         break;
2762                 case CMP_NODE_NORMAL:
2763                         ntype->uifunc = node_buts_normal;
2764                         break;
2765                 case CMP_NODE_CURVE_VEC:
2766                         ntype->uifunc = node_buts_curvevec;
2767                         break;
2768                 case CMP_NODE_CURVE_RGB:
2769                         ntype->uifunc = node_buts_curvecol;
2770                         break;
2771                 case CMP_NODE_VALUE:
2772                         ntype->uifunc = node_buts_value;
2773                         break;
2774                 case CMP_NODE_RGB:
2775                         ntype->uifunc = node_buts_rgb;
2776                         break;
2777                 case CMP_NODE_FLIP:
2778                         ntype->uifunc = node_composit_buts_flip;
2779                         break;
2780                 case CMP_NODE_SPLITVIEWER:
2781                         ntype->uifunc = node_composit_buts_splitviewer;
2782                         break;
2783                 case CMP_NODE_MIX_RGB:
2784                         ntype->uifunc = node_buts_mix_rgb;
2785                         break;
2786                 case CMP_NODE_VALTORGB:
2787                         ntype->uifunc = node_buts_colorramp;
2788                         break;
2789                 case CMP_NODE_CROP:
2790                         ntype->uifunc = node_composit_buts_crop;
2791                         break;
2792                 case CMP_NODE_BLUR:
2793                         ntype->uifunc = node_composit_buts_blur;
2794                         break;
2795                 case CMP_NODE_DBLUR:
2796                         ntype->uifunc = node_composit_buts_dblur;
2797                         break;
2798                 case CMP_NODE_BILATERALBLUR:
2799                         ntype->uifunc = node_composit_buts_bilateralblur;
2800                         break;
2801                 case CMP_NODE_DEFOCUS:
2802                         ntype->uifunc = node_composit_buts_defocus;
2803                         break;
2804                 case CMP_NODE_GLARE:
2805                         ntype->uifunc = node_composit_buts_glare;
2806                         break;
2807                 case CMP_NODE_TONEMAP:
2808                         ntype->uifunc = node_composit_buts_tonemap;
2809                         break;
2810                 case CMP_NODE_LENSDIST:
2811                         ntype->uifunc = node_composit_buts_lensdist;
2812                         break;
2813                 case CMP_NODE_VECBLUR:
2814                         ntype->uifunc = node_composit_buts_vecblur;
2815                         break;
2816                 case CMP_NODE_FILTER:
2817                         ntype->uifunc = node_composit_buts_filter;
2818                         break;
2819                 case CMP_NODE_MAP_VALUE:
2820                         ntype->uifunc = node_composit_buts_map_value;
2821                         break;
2822                 case CMP_NODE_MAP_RANGE:
2823                         ntype->uifunc = node_composit_buts_map_range;
2824                         break;
2825                 case CMP_NODE_TIME:
2826                         ntype->uifunc = node_buts_time;
2827                         break;
2828                 case CMP_NODE_ALPHAOVER:
2829                         ntype->uifunc = node_composit_buts_alphaover;
2830                         break;
2831                 case CMP_NODE_HUE_SAT:
2832                         ntype->uifunc = node_composit_buts_hue_sat;
2833                         break;
2834                 case CMP_NODE_TEXTURE:
2835                         ntype->uifunc = node_buts_texture;
2836                         break;
2837                 case CMP_NODE_DILATEERODE:
2838                         ntype->uifunc = node_composit_buts_dilateerode;
2839                         break;
2840                 case CMP_NODE_INPAINT:
2841                         ntype->uifunc = node_composit_buts_inpaint;
2842                         break;
2843                 case CMP_NODE_DESPECKLE:
2844                         ntype->uifunc = node_composit_buts_despeckle;
2845                         break;
2846                 case CMP_NODE_OUTPUT_FILE:
2847                         ntype->uifunc = node_composit_buts_file_output;
2848                         ntype->uifuncbut = node_composit_buts_file_output_details;
2849                         ntype->drawinputfunc = node_draw_input_file_output;
2850                         break;
2851                 case CMP_NODE_DIFF_MATTE:
2852                         ntype->uifunc = node_composit_buts_diff_matte;
2853                         break;
2854                 case CMP_NODE_DIST_MATTE:
2855                         ntype->uifunc = node_composit_buts_distance_matte;
2856                         break;
2857                 case CMP_NODE_COLOR_SPILL:
2858                         ntype->uifunc = node_composit_buts_color_spill;
2859                         break;
2860                 case CMP_NODE_CHROMA_MATTE:
2861                         ntype->uifunc = node_composit_buts_chroma_matte;
2862                         break;
2863                 case CMP_NODE_COLOR_MATTE:
2864                         ntype->uifunc = node_composit_buts_color_matte;
2865                         break;
2866                 case CMP_NODE_SCALE:
2867                         ntype->uifunc = node_composit_buts_scale;
2868                         break;
2869                 case CMP_NODE_ROTATE:
2870                         ntype->uifunc = node_composit_buts_rotate;
2871                         break;
2872                 case CMP_NODE_CHANNEL_MATTE:
2873                         ntype->uifunc = node_composit_buts_channel_matte;
2874                         break;
2875                 case CMP_NODE_LUMA_MATTE:
2876                         ntype->uifunc = node_composit_buts_luma_matte;
2877                         break;
2878                 case CMP_NODE_MAP_UV:
2879                         ntype->uifunc = node_composit_buts_map_uv;
2880                         break;
2881                 case CMP_NODE_ID_MASK:
2882                         ntype->uifunc = node_composit_buts_id_mask;
2883                         break;
2884                 case CMP_NODE_DOUBLEEDGEMASK:
2885                         ntype->uifunc = node_composit_buts_double_edge_mask;
2886                         break;
2887                 case CMP_NODE_MATH:
2888                         ntype->uifunc = node_buts_math;
2889                         break;
2890                 case CMP_NODE_INVERT:
2891                         ntype->uifunc = node_composit_buts_invert;
2892                         break;
2893                 case CMP_NODE_PREMULKEY:
2894                         ntype->uifunc = node_composit_buts_premulkey;
2895                         break;
2896                 case CMP_NODE_VIEW_LEVELS:
2897                         ntype->uifunc = node_composit_buts_view_levels;
2898                         break;
2899                 case CMP_NODE_COLORBALANCE:
2900                         ntype->uifunc = node_composit_buts_colorbalance;
2901                         ntype->uifuncbut = node_composit_buts_colorbalance_but;
2902                         break;
2903                 case CMP_NODE_HUECORRECT:
2904                         ntype->uifunc = node_composit_buts_huecorrect;
2905                         break;
2906                 case CMP_NODE_ZCOMBINE:
2907                         ntype->uifunc = node_composit_buts_zcombine;
2908                         break;
2909                 case CMP_NODE_COMBYCCA:
2910                 case CMP_NODE_SEPYCCA:
2911                         ntype->uifunc = node_composit_buts_ycc;
2912                         break;
2913                 case CMP_NODE_MOVIECLIP:
2914                         ntype->uifunc = node_composit_buts_movieclip;
2915                         ntype->uifuncbut = node_composit_buts_movieclip_details;
2916                         break;
2917                 case CMP_NODE_STABILIZE2D:
2918                         ntype->uifunc = node_composit_buts_stabilize2d;
2919                         break;
2920                 case CMP_NODE_TRANSFORM:
2921                         ntype->uifunc = node_composit_buts_transform;
2922                         break;
2923                 case CMP_NODE_MOVIEDISTORTION:
2924                         ntype->uifunc = node_composit_buts_moviedistortion;
2925                         break;
2926                 case CMP_NODE_COLORCORRECTION:
2927                         ntype->uifunc = node_composit_buts_colorcorrection;
2928                         ntype->uifuncbut = node_composit_buts_colorcorrection_but;
2929                         break;
2930                 case CMP_NODE_SWITCH:
2931                         ntype->uifunc = node_composit_buts_switch;
2932                         break;
2933                 case CMP_NODE_MASK_BOX:
2934                         ntype->uifunc = node_composit_buts_boxmask;
2935                         ntype->uibackdropfunc = node_composit_backdrop_boxmask;
2936                         break;
2937                 case CMP_NODE_MASK_ELLIPSE:
2938                         ntype->uifunc = node_composit_buts_ellipsemask;
2939                         ntype->uibackdropfunc = node_composit_backdrop_ellipsemask;
2940                         break;
2941                 case CMP_NODE_BOKEHIMAGE:
2942                         ntype->uifunc = node_composit_buts_bokehimage;
2943                         break;
2944                 case CMP_NODE_BOKEHBLUR:
2945                         ntype->uifunc = node_composit_buts_bokehblur;
2946                         break;
2947                 case CMP_NODE_VIEWER:
2948                         ntype->uifunc = NULL;
2949                         ntype->uifuncbut = node_composit_buts_viewer_but;
2950                         ntype->uibackdropfunc = node_composit_backdrop_viewer;
2951                         break;
2952                 case CMP_NODE_MASK:
2953                         ntype->uifunc = node_composit_buts_mask;
2954                         break;
2955                 case CMP_NODE_KEYINGSCREEN:
2956                         ntype->uifunc = node_composit_buts_keyingscreen;
2957                         break;
2958                 case CMP_NODE_KEYING:
2959                         ntype->uifunc = node_composit_buts_keying;
2960                         break;
2961                 case CMP_NODE_TRACKPOS:
2962                         ntype->uifunc = node_composit_buts_trackpos;
2963                         break;
2964                 default:
2965                         ntype->uifunc = NULL;
2966         }
2967 }
2968
2969 /* ****************** BUTTON CALLBACKS FOR TEXTURE NODES ***************** */
2970
2971 static void node_texture_buts_bricks(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2972 {
2973         uiLayout *col;
2974         
2975         col = uiLayoutColumn(layout, TRUE);
2976         uiItemR(col, ptr, "offset", 0, IFACE_("Offset"), ICON_NONE);
2977         uiItemR(col, ptr, "offset_frequency", 0, IFACE_("Frequency"), ICON_NONE);
2978         
2979         col = uiLayoutColumn(layout, TRUE);
2980         uiItemR(col, ptr, "squash", 0, IFACE_("Squash"), ICON_NONE);
2981         uiItemR(col, ptr, "squash_frequency", 0, IFACE_("Frequency"), ICON_NONE);
2982 }
2983
2984 static void node_texture_buts_proc(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
2985 {
2986         PointerRNA tex_ptr;
2987         bNode *node = ptr->data;
2988         ID *id = ptr->id.data;
2989         Tex *tex = (Tex *)node->storage;
2990         uiLayout *col, *row;
2991         
2992         RNA_pointer_create(id, &RNA_Texture, tex, &tex_ptr);
2993
2994         col = uiLayoutColumn(layout, FALSE);
2995
2996         switch (tex->type) {
2997                 case TEX_BLEND:
2998                         uiItemR(col, &tex_ptr, "progression", 0, "", ICON_NONE);
2999                         row = uiLayoutRow(col, FALSE);
3000                         uiItemR(row, &tex_ptr, "use_flip_axis", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
3001                         break;
3002
3003                 case TEX_MARBLE:
3004                         row = uiLayoutRow(col, FALSE);
3005                         uiItemR(row, &tex_ptr, "marble_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
3006                         row = uiLayoutRow(col, FALSE);
3007                         uiItemR(row, &tex_ptr, "noise_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
3008                         row = uiLayoutRow(col, FALSE);
3009                         uiItemR(row, &tex_ptr, "noise_basis", 0, "", ICON_NONE);
3010                         row = uiLayoutRow(col, FALSE);
3011                         uiItemR(row, &tex_ptr, "noise_basis_2", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
3012                         break;
3013
3014                 case TEX_MAGIC:
3015                         uiItemR(col, &tex_ptr, "noise_depth", 0, NULL, ICON_NONE);
3016                         break;
3017
3018                 case TEX_STUCCI:
3019                         row = uiLayoutRow(col, FALSE);
3020                         uiItemR(row, &tex_ptr, "stucci_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
3021                         row = uiLayoutRow(col, FALSE);
3022                         uiItemR(row, &tex_ptr, "noise_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
3023                         uiItemR(col, &tex_ptr, "noise_basis", 0, "", ICON_NONE);
3024                         break;
3025
3026                 case TEX_WOOD:
3027                         uiItemR(col, &tex_ptr, "noise_basis", 0, "", ICON_NONE);
3028                         uiItemR(col, &tex_ptr, "wood_type", 0, "", ICON_NONE);
3029                         row = uiLayoutRow(col, FALSE);
3030                         uiItemR(row, &tex_ptr, "noise_basis_2", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
3031                         row = uiLayoutRow(col, FALSE);
3032                         uiLayoutSetActive(row, !(ELEM(tex->stype, TEX_BAND, TEX_RING)));
3033                         uiItemR(row, &tex_ptr, "noise_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
3034                         break;
3035                         
3036                 case TEX_CLOUDS:
3037                         uiItemR(col, &tex_ptr, "noise_basis", 0, "", ICON_NONE);
3038                         row = uiLayoutRow(col, FALSE);
3039                         uiItemR(row, &tex_ptr, "cloud_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
3040                         row = uiLayoutRow(col, FALSE);
3041                         uiItemR(row, &tex_ptr, "noise_type", UI_ITEM_R_EXPAND, NULL, ICON_NONE);
3042                         uiItemR(col, &tex_ptr, "noise_depth", UI_ITEM_R_EXPAND, IFACE_("Depth"), ICON_NONE);
3043                         break;
3044                         
3045                 case TEX_DISTNOISE:
3046                         uiItemR(col, &tex_ptr, "noise_basis", 0, "", ICON_NONE);
3047                         uiItemR(col, &tex_ptr, "noise_distortion", 0, "", ICON_NONE);
3048                         break;
3049
3050                 case TEX_MUSGRAVE:
3051                         uiItemR(col, &tex_ptr, "musgrave_type", 0, "", ICON_NONE);
3052                         uiItemR(col, &tex_ptr, "noise_basis", 0, "", ICON_NONE);
3053                         break;
3054                 case TEX_VORONOI:
3055                         uiItemR(col, &tex_ptr, "distance_metric", 0, "", ICON_NONE);
3056                         if (tex->vn_distm == TEX_MINKOVSKY) {
3057                                 uiItemR(col, &tex_ptr, "minkovsky_exponent", 0, NULL, ICON_NONE);
3058                         }
3059                         uiItemR(col, &tex_ptr, "color_mode", 0, "", ICON_NONE);
3060                         break;
3061         }
3062 }
3063
3064 static void node_texture_buts_image(uiLayout *layout, bContext *C, PointerRNA *ptr)
3065 {
3066         uiTemplateID(layout, C, ptr, "image", NULL, "IMAGE_OT_open", NULL);
3067 }
3068
3069 static void node_texture_buts_output(uiLayout *layout, bContext *UNUSED(C), PointerRNA *ptr)
3070 {
3071         uiItemR(layout, ptr, "filepath", 0, "", ICON_NONE);
3072 }
3073
3074 /* only once called */
3075 static void node_texture_set_butfunc(bNodeType *ntype)
3076 {
3077         if (ntype->type >= TEX_NODE_PROC && ntype->type < TEX_NODE_PROC_MAX) {
3078                 ntype->uifunc = node_texture_buts_proc;
3079         }
3080         else {
3081                 switch (ntype->type) {
3082
3083                         case TEX_NODE_MATH:
3084                                 ntype->uifunc = node_buts_math;
3085                                 break;
3086
3087                         case TEX_NODE_MIX_RGB:
3088                                 ntype->uifunc = node_buts_mix_rgb;
3089                                 break;
3090
3091                         case TEX_NODE_VALTORGB:
3092                                 ntype->uifunc = node_buts_colorramp;
3093                                 break;
3094
3095                         case TEX_NODE_CURVE_RGB:
3096                                 ntype->uifunc = node_buts_curvecol;
3097                                 break;
3098
3099                         case TEX_NODE_CURVE_TIME:
3100                                 ntype->uifunc = node_buts_time;
3101                                 break;
3102
3103                         case TEX_NODE_TEXTURE:
3104                                 ntype->uifunc = node_buts_texture;
3105                                 break;
3106
3107                         case TEX_NODE_BRICKS:
3108                                 ntype->uifunc = node_texture_buts_bricks;
3109                                 break;
3110
3111                         case TEX_NODE_IMAGE:
3112                                 ntype->uifunc = node_texture_buts_image;
3113                                 break;
3114
3115                         case TEX_NODE_OUTPUT:
3116                                 ntype->uifunc = node_texture_buts_output;
3117                                 break;
3118                 }
3119         }
3120 }
3121
3122 /* ******* init draw callbacks for all tree types, only called in usiblender.c, once ************* */
3123
3124 void ED_node_init_butfuncs(void)
3125 {
3126         bNodeTreeType *treetype;
3127         bNodeType *ntype;
3128         bNodeSocketType *stype;
3129         int i;
3130         
3131         /* node type ui functions */
3132         for (i = 0; i < NUM_NTREE_TYPES; ++i) {
3133                 treetype = ntreeGetType(i);
3134                 if (treetype) {
3135                         for (ntype = treetype->node_types.first; ntype; ntype = ntype->next) {
3136                                 /* default ui functions */
3137                                 ntype->drawfunc = node_draw_default;
3138                                 ntype->drawupdatefunc = node_update_default;
3139                                 ntype->select_area_func = node_select_area_default;
3140                                 ntype->tweak_area_func = node_tweak_area_default;
3141                                 ntype->uifunc = NULL;
3142                                 ntype->uifuncbut = NULL;
3143                                 ntype->drawinputfunc = node_draw_input_default;
3144                                 ntype->drawoutputfunc = node_draw_output_default;
3145                                 ntype->resize_area_func = node_resize_area_default;