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