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