2.5 Nodes:
[blender.git] / source / blender / editors / space_node / drawnode.c
1 /**
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. 
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19  *
20  * The Original Code is Copyright (C) 2005 Blender Foundation.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): David Millan Escriva, Juho Vepsäläinen, Bob Holcomb, Thomas Dinges
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30 #include <math.h>
31 #include <stdio.h>
32 #include <string.h>
33
34 #include "BLI_blenlib.h"
35 #include "BLI_arithb.h"
36
37 #include "DNA_ID.h"
38 #include "DNA_node_types.h"
39 #include "DNA_image_types.h"
40 #include "DNA_material_types.h"
41 #include "DNA_mesh_types.h"
42 #include "DNA_action_types.h"
43 #include "DNA_color_types.h"
44 #include "DNA_customdata_types.h"
45 #include "DNA_gpencil_types.h"
46 #include "DNA_ipo_types.h"
47 #include "DNA_object_types.h"
48 #include "DNA_scene_types.h"
49 #include "DNA_space_types.h"
50 #include "DNA_screen_types.h"
51 #include "DNA_texture_types.h"
52 #include "DNA_text_types.h"
53 #include "DNA_userdef_types.h"
54
55 #include "BKE_context.h"
56 #include "BKE_curve.h"
57 #include "BKE_global.h"
58 #include "BKE_image.h"
59 #include "BKE_library.h"
60 #include "BKE_main.h"
61 #include "BKE_material.h"
62 #include "BKE_node.h"
63 #include "BKE_object.h"
64 #include "BKE_texture.h"
65 #include "BKE_text.h"
66 #include "BKE_utildefines.h"
67
68 #include "CMP_node.h"
69 #include "SHD_node.h"
70
71 #include "BIF_gl.h"
72 #include "BIF_glutil.h"
73
74 #include "MEM_guardedalloc.h"
75
76 #include "ED_node.h"
77 #include "ED_space_api.h"
78 #include "ED_screen.h"
79 #include "ED_types.h"
80
81 #include "RNA_access.h"
82 #include "RNA_define.h"
83
84 #include "WM_api.h"
85 #include "WM_types.h"
86
87 #include "UI_view2d.h"
88 #include "UI_interface.h"
89 #include "UI_resources.h"
90
91 #include "RE_pipeline.h"
92 #include "IMB_imbuf.h"
93 #include "IMB_imbuf_types.h"
94
95 #include "node_intern.h"
96
97
98 /* autocomplete callback for buttons */
99 static void autocomplete_vcol(bContext *C, char *str, void *arg_v)
100 {
101         Mesh *me;
102         CustomDataLayer *layer;
103         AutoComplete *autocpl;
104         int a;
105
106         if(str[0]==0)
107                 return;
108
109         autocpl= autocomplete_begin(str, 32);
110                 
111         /* search if str matches the beginning of name */
112         for(me= G.main->mesh.first; me; me=me->id.next)
113                 for(a=0, layer= me->fdata.layers; a<me->fdata.totlayer; a++, layer++)
114                         if(layer->type == CD_MCOL)
115                                 autocomplete_do_name(autocpl, layer->name);
116         
117         autocomplete_end(autocpl, str);
118 }
119
120 static int verify_valid_vcol_name(char *str)
121 {
122         Mesh *me;
123         CustomDataLayer *layer;
124         int a;
125         
126         if(str[0]==0)
127                 return 1;
128
129         /* search if str matches the name */
130         for(me= G.main->mesh.first; me; me=me->id.next)
131                 for(a=0, layer= me->fdata.layers; a<me->fdata.totlayer; a++, layer++)
132                         if(layer->type == CD_MCOL)
133                                 if(strcmp(layer->name, str)==0)
134                                         return 1;
135         
136         return 0;
137 }
138
139 /* ****************** GENERAL CALLBACKS FOR NODES ***************** */
140
141 static void node_ID_title_cb(bContext *C, void *node_v, void *unused_v)
142 {
143         bNode *node= node_v;
144         
145         if(node->id) {
146                 test_idbutton(node->id->name+2);        /* library.c, verifies unique name */
147                 BLI_strncpy(node->name, node->id->name+2, 21);
148         }
149 }
150
151 #if 0
152 /* XXX not used yet, make compiler happy :) */
153 static void node_group_alone_cb(bContext *C, void *node_v, void *unused_v)
154 {
155         bNode *node= node_v;
156         
157         nodeCopyGroup(node);
158
159         // allqueue(REDRAWNODE, 0);
160 }
161
162 /* ****************** BUTTON CALLBACKS FOR ALL TREES ***************** */
163
164 static void node_buts_group(uiLayout *layout, PointerRNA *ptr)
165 {
166         uiBlock *block= uiLayoutAbsoluteBlock(layout);
167         bNode *node= ptr->data;
168         rctf *butr= &node->butr;
169
170         if(node->id) {
171                 uiBut *bt;
172                 short width;
173                 
174                 uiBlockBeginAlign(block);
175                 
176                 /* name button */
177                 width= (short)(butr->xmax-butr->xmin - (node->id->us>1?19.0f:0.0f));
178                 bt= uiDefBut(block, TEX, B_NOP, "NT:",
179                                          (short)butr->xmin, (short)butr->ymin, width, 19, 
180                                          node->id->name+2, 0.0, 19.0, 0, 0, "NodeTree name");
181                 uiButSetFunc(bt, node_ID_title_cb, node, NULL);
182                 
183                 /* user amount */
184                 if(node->id->us>1) {
185                         char str1[32];
186                         sprintf(str1, "%d", node->id->us);
187                         bt= uiDefBut(block, BUT, B_NOP, str1, 
188                                                  (short)butr->xmax-19, (short)butr->ymin, 19, 19, 
189                                                  NULL, 0, 0, 0, 0, "Displays number of users.");
190                         uiButSetFunc(bt, node_group_alone_cb, node, NULL);
191                 }
192                 
193                 uiBlockEndAlign(block);
194         }       
195 }
196 #endif
197
198 static void node_buts_value(uiLayout *layout, PointerRNA *ptr)
199 {
200         uiBlock *block= uiLayoutAbsoluteBlock(layout);
201         bNode *node= ptr->data;
202         rctf *butr= &node->butr;
203         bNodeSocket *sock= node->outputs.first;         /* first socket stores value */
204         
205         uiDefButF(block, NUM, B_NODE_EXEC, "", 
206                           (short)butr->xmin, (short)butr->ymin, butr->xmax-butr->xmin, 20, 
207                           sock->ns.vec, sock->ns.min, sock->ns.max, 10, 2, "");
208 }
209
210 static void node_buts_rgb(uiLayout *layout, PointerRNA *ptr)
211 {
212         uiBlock *block= uiLayoutAbsoluteBlock(layout);
213         bNode *node= ptr->data;
214         rctf *butr= &node->butr;
215         bNodeSocket *sock= node->outputs.first;         /* first socket stores value */
216
217         if(sock) {
218                 /* enforce square box drawing */
219                 uiBlockSetEmboss(block, UI_EMBOSSP);
220                 
221                 uiDefButF(block, HSVCUBE, B_NODE_EXEC, "", 
222                                   (short)butr->xmin, (short)butr->ymin, butr->xmax-butr->xmin, 12, 
223                                   sock->ns.vec, 0.0f, 1.0f, 3, 0, "");
224                 uiDefButF(block, HSVCUBE, B_NODE_EXEC, "", 
225                                   (short)butr->xmin, (short)butr->ymin+15, butr->xmax-butr->xmin, butr->xmax-butr->xmin -15 -15, 
226                                   sock->ns.vec, 0.0f, 1.0f, 2, 0, "");
227                 uiDefButF(block, COL, B_NOP, "",                
228                                   (short)butr->xmin, (short)butr->ymax-12, butr->xmax-butr->xmin, 12, 
229                                   sock->ns.vec, 0.0, 0.0, -1, 0, "");
230                 /* the -1 above prevents col button to popup a color picker */
231                 
232                 uiBlockSetEmboss(block, UI_EMBOSS);
233         }
234 }
235
236 static void node_buts_mix_rgb(uiLayout *layout, PointerRNA *ptr)
237 {       
238         uiLayout *row;
239
240         bNodeTree *ntree= (bNodeTree*)ptr->id.data;
241
242         row= uiLayoutRow(layout, 1);
243         uiItemR(row, "", 0, ptr, "blend_type", 0);
244         if(ntree->type == NTREE_COMPOSIT)
245                 uiItemR(row, "", ICON_IMAGE_RGB_ALPHA, ptr, "alpha", 0);
246 }
247
248 static void node_buts_time(uiLayout *layout, PointerRNA *ptr)
249 {
250         uiLayout *row;
251 #if 0
252         /* XXX no context access here .. */
253         bNode *node= ptr->data;
254         CurveMapping *cumap= node->storage;
255         
256         if(cumap) {
257                 cumap->flag |= CUMA_DRAW_CFRA;
258                 if(node->custom1<node->custom2)
259                         cumap->sample[0]= (float)(CFRA - node->custom1)/(float)(node->custom2-node->custom1);
260         }
261 #endif
262
263         uiTemplateCurveMapping(layout, ptr, "curve", 's', 0);
264
265         row= uiLayoutRow(layout, 1);
266         uiItemR(row, "Sta", 0, ptr, "start", 0);
267         uiItemR(row, "End", 0, ptr, "end", 0);
268 }
269
270 static void node_buts_valtorgb(uiLayout *layout, PointerRNA *ptr)
271 {
272         uiBlock *block= uiLayoutAbsoluteBlock(layout);
273         bNode *node= ptr->data;
274         rctf *butr= &node->butr;
275
276         if(node->storage) {
277                 uiBlockColorbandButtons(block, node->storage, butr, B_NODE_EXEC);
278         }
279 }
280
281 static void node_buts_curvevec(uiLayout *layout, PointerRNA *ptr)
282 {
283         uiTemplateCurveMapping(layout, ptr, "mapping", 'v', 0);
284 }
285
286 static float *_sample_col= NULL;        // bad bad, 2.5 will do better?
287 void node_curvemap_sample(float *col)
288 {
289         _sample_col= col;
290 }
291
292 static void node_buts_curvecol(uiLayout *layout, PointerRNA *ptr)
293 {
294         bNode *node= ptr->data;
295         CurveMapping *cumap= node->storage;
296
297         if(_sample_col) {
298                 cumap->flag |= CUMA_DRAW_SAMPLE;
299                 VECCOPY(cumap->sample, _sample_col);
300         }
301         else 
302                 cumap->flag &= ~CUMA_DRAW_SAMPLE;
303
304         uiTemplateCurveMapping(layout, ptr, "mapping", 'c', 0);
305 }
306
307 static void node_buts_normal(uiLayout *layout, PointerRNA *ptr)
308 {
309         uiBlock *block= uiLayoutAbsoluteBlock(layout);
310         bNode *node= ptr->data;
311         rctf *butr= &node->butr;
312         bNodeSocket *sock= node->outputs.first;         /* first socket stores normal */
313         
314         uiDefButF(block, BUT_NORMAL, B_NODE_EXEC, "", 
315                           (short)butr->xmin, (short)butr->xmin, butr->xmax-butr->xmin, butr->xmax-butr->xmin, 
316                           sock->ns.vec, 0.0f, 1.0f, 0, 0, "");
317 }
318
319 static void node_browse_tex_cb(bContext *C, void *ntree_v, void *node_v)
320 {
321         bNodeTree *ntree= ntree_v;
322         bNode *node= node_v;
323         Tex *tex;
324         
325         if(node->menunr<1) return;
326         
327         if(node->id) {
328                 node->id->us--;
329                 node->id= NULL;
330         }
331         tex= BLI_findlink(&G.main->tex, node->menunr-1);
332
333         node->id= &tex->id;
334         id_us_plus(node->id);
335         BLI_strncpy(node->name, node->id->name+2, 21);
336         
337         nodeSetActive(ntree, node);
338         
339         if( ntree->type == NTREE_TEXTURE )
340                 ntreeTexCheckCyclics( ntree );
341         
342         // allqueue(REDRAWBUTSSHADING, 0);
343         // allqueue(REDRAWNODE, 0);
344         NodeTagChanged(ntree, node); 
345         
346         node->menunr= 0;
347 }
348
349 static void node_dynamic_update_cb(bContext *C, void *ntree_v, void *node_v)
350 {
351         Material *ma;
352         bNode *node= (bNode *)node_v;
353         ID *id= node->id;
354         int error= 0;
355
356         if (BTST(node->custom1, NODE_DYNAMIC_ERROR)) error= 1;
357
358         /* Users only have to press the "update" button in one pynode
359          * and we also update all others sharing the same script */
360         for (ma= G.main->mat.first; ma; ma= ma->id.next) {
361                 if (ma->nodetree) {
362                         bNode *nd;
363                         for (nd= ma->nodetree->nodes.first; nd; nd= nd->next) {
364                                 if ((nd->type == NODE_DYNAMIC) && (nd->id == id)) {
365                                         nd->custom1= 0;
366                                         nd->custom1= BSET(nd->custom1, NODE_DYNAMIC_REPARSE);
367                                         nd->menunr= 0;
368                                         if (error)
369                                                 nd->custom1= BSET(nd->custom1, NODE_DYNAMIC_ERROR);
370                                 }
371                         }
372                 }
373         }
374
375         // allqueue(REDRAWBUTSSHADING, 0);
376         // allqueue(REDRAWNODE, 0);
377         // XXX BIF_preview_changed(ID_MA);
378 }
379
380 static void node_buts_texture(uiLayout *layout, PointerRNA *ptr)
381 {
382         bNode *node= ptr->data;
383
384         short multi = (
385                 node->id &&
386                 ((Tex*)node->id)->use_nodes &&
387                 (node->type != CMP_NODE_TEXTURE) &&
388                 (node->type != TEX_NODE_TEXTURE)
389         );
390         
391         uiItemR(layout, "", 0, ptr, "texture", 0);
392         
393         if(multi) {
394                 /* Number Drawing not optimal here, better have a list*/
395                 uiItemR(layout, "", 0, ptr, "node_output", 0);
396         }
397 }
398
399 static void node_buts_math(uiLayout *layout, PointerRNA *ptr)
400
401         uiItemR(layout, "", 0, ptr, "operation", 0);
402 }
403
404 /* ****************** BUTTON CALLBACKS FOR SHADER NODES ***************** */
405
406 static void node_browse_text_cb(bContext *C, void *ntree_v, void *node_v)
407 {
408         bNodeTree *ntree= ntree_v;
409         bNode *node= node_v;
410         ID *oldid;
411         
412         if(node->menunr<1) return;
413         
414         if(node->id) {
415                 node->id->us--;
416         }
417         oldid= node->id;
418         node->id= BLI_findlink(&G.main->text, node->menunr-1);
419         id_us_plus(node->id);
420         BLI_strncpy(node->name, node->id->name+2, 21); /* huh? why 21? */
421
422         node->custom1= BSET(node->custom1, NODE_DYNAMIC_NEW);
423         
424         nodeSetActive(ntree, node);
425
426         // allqueue(REDRAWBUTSSHADING, 0);
427         // allqueue(REDRAWNODE, 0);
428
429         node->menunr= 0;
430 }
431
432 static void node_mat_alone_cb(bContext *C, void *node_v, void *unused)
433 {
434         bNode *node= node_v;
435         
436         node->id= (ID *)copy_material((Material *)node->id);
437         
438         //BIF_undo_push("Single user material");
439         // allqueue(REDRAWBUTSSHADING, 0);
440         // allqueue(REDRAWNODE, 0);
441         // allqueue(REDRAWOOPS, 0);
442 }
443
444 static void node_browse_mat_cb(bContext *C, void *ntree_v, void *node_v)
445 {
446         bNodeTree *ntree= ntree_v;
447         bNode *node= node_v;
448         
449         if(node->menunr<1) return;
450         
451         if(node->menunr==32767) {       /* code for Add New */
452                 if(node->id) {
453                         /* make copy, but make sure it doesnt have the node tag nor nodes */
454                         Material *ma= (Material *)node->id;
455                         ma->id.us--;
456                         ma= copy_material(ma);
457                         ma->use_nodes= 0;
458                         if(ma->nodetree) {
459                                 ntreeFreeTree(ma->nodetree);
460                                 MEM_freeN(ma->nodetree);
461                         }
462                         ma->nodetree= NULL;
463                         node->id= (ID *)ma;
464                 }
465                 else node->id= (ID *)add_material("MatNode");
466         }
467         else {
468                 if(node->id) node->id->us--;
469                 node->id= BLI_findlink(&G.main->mat, node->menunr-1);
470                 id_us_plus(node->id);
471         }
472         BLI_strncpy(node->name, node->id->name+2, 21);
473         
474         nodeSetActive(ntree, node);
475
476         // allqueue(REDRAWBUTSSHADING, 0);
477         // allqueue(REDRAWNODE, 0);
478         // XXX BIF_preview_changed(ID_MA);
479
480         node->menunr= 0;
481 }
482
483 static void node_new_mat_cb(bContext *C, void *ntree_v, void *node_v)
484 {
485         bNodeTree *ntree= ntree_v;
486         bNode *node= node_v;
487         
488         node->id= (ID *)add_material("MatNode");
489         BLI_strncpy(node->name, node->id->name+2, 21);
490
491         nodeSetActive(ntree, node);
492
493         // allqueue(REDRAWBUTSSHADING, 0);
494         // allqueue(REDRAWNODE, 0);
495         // XXX BIF_preview_changed(ID_MA);
496
497 }
498
499 static void node_texmap_cb(bContext *C, void *texmap_v, void *unused_v)
500 {
501         init_mapping(texmap_v);
502 }
503
504 static void node_shader_buts_material(uiLayout *layout, PointerRNA *ptr)
505 {
506         uiBlock *block= uiLayoutAbsoluteBlock(layout);
507         bNode *node= ptr->data;
508         bNodeTree *ntree= ptr->id.data;
509         rctf *butr= &node->butr;
510         uiBut *bt;
511         short dx= (short)((butr->xmax-butr->xmin)/3.0f), has_us= (node->id && node->id->us>1);
512         short dy= (short)butr->ymin;
513         char *strp;
514         
515         /* WATCH IT: we use this callback in material buttons, but then only want first row */
516         if(butr->ymax-butr->ymin > 21.0f) dy+= 19;
517         
518         uiBlockBeginAlign(block);
519         /* XXX
520         if(node->id==NULL) uiBlockSetCol(block, TH_REDALERT);
521         else if(has_us) uiBlockSetCol(block, TH_BUT_SETTING1);
522         else uiBlockSetCol(block, TH_BUT_SETTING2);
523         */
524         
525         /* browse button */
526         IDnames_to_pupstring(&strp, NULL, "ADD NEW %x32767", &(G.main->mat), NULL, NULL);
527         node->menunr= 0;
528         bt= uiDefButS(block, MENU, B_NOP, strp, 
529                           butr->xmin, dy, 19, 19, 
530                           &node->menunr, 0, 0, 0, 0, "Browses existing choices or adds NEW");
531         uiButSetFunc(bt, node_browse_mat_cb, ntree, node);
532         if(strp) MEM_freeN(strp);
533         
534         /* Add New button */
535         if(node->id==NULL) {
536                 bt= uiDefBut(block, BUT, B_NOP, "Add New",
537                                          butr->xmin+19, dy, (short)(butr->xmax-butr->xmin-19.0f), 19, 
538                                          NULL, 0.0, 0.0, 0, 0, "Add new Material");
539                 uiButSetFunc(bt, node_new_mat_cb, ntree, node);
540         }
541         else {
542                 /* name button */
543                 short width= (short)(butr->xmax-butr->xmin-19.0f - (has_us?19.0f:0.0f));
544                 bt= uiDefBut(block, TEX, B_NOP, "MA:",
545                                           butr->xmin+19, dy, width, 19, 
546                                           node->id->name+2, 0.0, 19.0, 0, 0, "Material name");
547                 uiButSetFunc(bt, node_ID_title_cb, node, NULL);
548                 
549                 /* user amount */
550                 if(has_us) {
551                         char str1[32];
552                         sprintf(str1, "%d", node->id->us);
553                         bt= uiDefBut(block, BUT, B_NOP, str1, 
554                                                   butr->xmax-19, dy, 19, 19, 
555                                                   NULL, 0, 0, 0, 0, "Displays number of users. Click to make a single-user copy.");
556                         uiButSetFunc(bt, node_mat_alone_cb, node, NULL);
557                 }
558                 
559                 /* WATCH IT: we use this callback in material buttons, but then only want first row */
560                 if(butr->ymax-butr->ymin > 21.0f) {
561                         /* node options */
562                         uiDefButBitS(block, TOG, SH_NODE_MAT_DIFF, B_NODE_EXEC, "Diff",
563                                                  butr->xmin, butr->ymin, dx, 19, 
564                                                  &node->custom1, 0, 0, 0, 0, "Material Node outputs Diffuse");
565                         uiDefButBitS(block, TOG, SH_NODE_MAT_SPEC, B_NODE_EXEC, "Spec",
566                                                  butr->xmin+dx, butr->ymin, dx, 19, 
567                                                  &node->custom1, 0, 0, 0, 0, "Material Node outputs Specular");
568                         uiDefButBitS(block, TOG, SH_NODE_MAT_NEG, B_NODE_EXEC, "Neg Normal",
569                                                  butr->xmax-dx, butr->ymin, dx, 19,
570                                                  &node->custom1, 0, 0, 0, 0, "Material Node uses inverted Normal");
571                 }
572         }
573         uiBlockEndAlign(block);
574 }
575
576 static void node_shader_buts_mapping(uiLayout *layout, PointerRNA *ptr)
577 {
578         uiBlock *block= uiLayoutAbsoluteBlock(layout);
579         bNode *node= ptr->data;
580         rctf *butr= &node->butr;
581         TexMapping *texmap= node->storage;
582         short dx= (short)((butr->xmax-butr->xmin)/7.0f);
583         short dy= (short)(butr->ymax-19);
584         
585         uiBlockSetFunc(block, node_texmap_cb, texmap, NULL);    /* all buttons get this */
586         
587         uiBlockBeginAlign(block);
588         uiDefButF(block, NUM, B_NODE_EXEC, "", butr->xmin+dx, dy, 2*dx, 19, texmap->loc, -1000.0f, 1000.0f, 10, 2, "");
589         uiDefButF(block, NUM, B_NODE_EXEC, "", butr->xmin+3*dx, dy, 2*dx, 19, texmap->loc+1, -1000.0f, 1000.0f, 10, 2, "");
590         uiDefButF(block, NUM, B_NODE_EXEC, "", butr->xmin+5*dx, dy, 2*dx, 19, texmap->loc+2, -1000.0f, 1000.0f, 10, 2, "");
591         dy-= 19;
592         uiDefButF(block, NUM, B_NODE_EXEC, "", butr->xmin+dx, dy, 2*dx, 19, texmap->rot, -1000.0f, 1000.0f, 1000, 1, "");
593         uiDefButF(block, NUM, B_NODE_EXEC, "", butr->xmin+3*dx, dy, 2*dx, 19, texmap->rot+1, -1000.0f, 1000.0f, 1000, 1, "");
594         uiDefButF(block, NUM, B_NODE_EXEC, "", butr->xmin+5*dx, dy, 2*dx, 19, texmap->rot+2, -1000.0f, 1000.0f, 1000, 1, "");
595         dy-= 19;
596         uiDefButF(block, NUM, B_NODE_EXEC, "", butr->xmin+dx, dy, 2*dx, 19, texmap->size, -1000.0f, 1000.0f, 10, 2, "");
597         uiDefButF(block, NUM, B_NODE_EXEC, "", butr->xmin+3*dx, dy, 2*dx, 19, texmap->size+1, -1000.0f, 1000.0f, 10, 2, "");
598         uiDefButF(block, NUM, B_NODE_EXEC, "", butr->xmin+5*dx, dy, 2*dx, 19, texmap->size+2, -1000.0f, 1000.0f, 10, 2, "");
599         dy-= 25;
600         uiBlockBeginAlign(block);
601         uiDefButF(block, NUM, B_NODE_EXEC, "", butr->xmin+dx, dy, 2*dx, 19, texmap->min, -10.0f, 10.0f, 100, 2, "");
602         uiDefButF(block, NUM, B_NODE_EXEC, "", butr->xmin+3*dx, dy, 2*dx, 19, texmap->min+1, -10.0f, 10.0f, 100, 2, "");
603         uiDefButF(block, NUM, B_NODE_EXEC, "", butr->xmin+5*dx, dy, 2*dx, 19, texmap->min+2, -10.0f, 10.0f, 100, 2, "");
604         dy-= 19;
605         uiDefButF(block, NUM, B_NODE_EXEC, "", butr->xmin+dx, dy, 2*dx, 19, texmap->max, -10.0f, 10.0f, 10, 2, "");
606         uiDefButF(block, NUM, B_NODE_EXEC, "", butr->xmin+3*dx, dy, 2*dx, 19, texmap->max+1, -10.0f, 10.0f, 10, 2, "");
607         uiDefButF(block, NUM, B_NODE_EXEC, "", butr->xmin+5*dx, dy, 2*dx, 19, texmap->max+2, -10.0f, 10.0f, 10, 2, "");
608         uiBlockEndAlign(block);
609         
610         /* labels/options */
611         
612         dy= (short)(butr->ymax-19);
613         uiDefBut(block, LABEL, B_NOP, "Loc", butr->xmin, dy, dx, 19, NULL, 0.0f, 0.0f, 0, 0, "");
614         dy-= 19;
615         uiDefBut(block, LABEL, B_NOP, "Rot", butr->xmin, dy, dx, 19, NULL, 0.0f, 0.0f, 0, 0, "");
616         dy-= 19;
617         uiDefBut(block, LABEL, B_NOP, "Size", butr->xmin, dy, dx, 19, NULL, 0.0f, 0.0f, 0, 0, "");
618         dy-= 25;
619         uiDefButBitI(block, TOG, TEXMAP_CLIP_MIN, B_NODE_EXEC, "Min", butr->xmin, dy, dx-4, 19, &texmap->flag, 0.0f, 0.0f, 0, 0, "");
620         dy-= 19;
621         uiDefButBitI(block, TOG, TEXMAP_CLIP_MAX, B_NODE_EXEC, "Max", butr->xmin, dy, dx-4, 19, &texmap->flag, 0.0f, 0.0f, 0, 0, "");
622 }
623
624 static void node_shader_buts_vect_math(uiLayout *layout, PointerRNA *ptr)
625
626         uiItemR(layout, "", 0, ptr, "operation", 0);
627 }
628
629 static void node_shader_buts_geometry(uiLayout *layout, PointerRNA *ptr)
630 {
631         uiBlock *block= uiLayoutAbsoluteBlock(layout);
632         bNode *node= ptr->data;
633         rctf *butr= &node->butr;
634         uiBut *but;
635         NodeGeometry *ngeo= (NodeGeometry*)node->storage;
636
637         // XXX if(!verify_valid_uv_name(ngeo->uvname))
638         // XXX  uiBlockSetCol(block, TH_REDALERT);
639         but= uiDefBut(block, TEX, B_NODE_EXEC, "UV:", butr->xmin, butr->ymin+20, butr->xmax-butr->xmin, 20, ngeo->uvname, 0, 31, 0, 0, "Set name of UV layer to use, default is active UV layer");
640         // XXX uiButSetCompleteFunc(but, autocomplete_uv, NULL);
641
642         if(!verify_valid_vcol_name(ngeo->colname));
643 //                      uiBlockSetCol(block, TH_REDALERT);
644         but= uiDefBut(block, TEX, B_NODE_EXEC, "Col:", butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20, ngeo->colname, 0, 31, 0, 0, "Set name of vertex color layer to use, default is active vertex color layer");
645         uiButSetCompleteFunc(but, autocomplete_vcol, NULL);
646 }
647
648 static void node_shader_buts_dynamic(uiLayout *layout, PointerRNA *ptr)
649
650         uiBlock *block= uiLayoutAbsoluteBlock(layout);
651         bNode *node= ptr->data;
652         bNodeTree *ntree= ptr->id.data;
653         rctf *butr= &node->butr;
654         uiBut *bt;
655         // XXX SpaceNode *snode= curarea->spacedata.first;
656         short dy= (short)butr->ymin;
657         int xoff=0;
658
659         /* B_NODE_EXEC is handled in butspace.c do_node_buts */
660         if(!node->id) {
661                         char *strp;
662                         IDnames_to_pupstring(&strp, NULL, "", &(G.main->text), NULL, NULL);
663                         node->menunr= 0;
664                         bt= uiDefButS(block, MENU, B_NODE_EXEC/*+node->nr*/, strp, 
665                                                         butr->xmin, dy, 19, 19, 
666                                                         &node->menunr, 0, 0, 0, 0, "Browses existing choices");
667                         uiButSetFunc(bt, node_browse_text_cb, ntree, node);
668                         xoff=19;
669                         if(strp) MEM_freeN(strp);       
670         }
671         else {
672                 bt = uiDefBut(block, BUT, B_NOP, "Update",
673                                 butr->xmin+xoff, butr->ymin+20, 50, 19,
674                                 &node->menunr, 0.0, 19.0, 0, 0, "Refresh this node (and all others that use the same script)");
675                 uiButSetFunc(bt, node_dynamic_update_cb, ntree, node);
676
677                 if (BTST(node->custom1, NODE_DYNAMIC_ERROR)) {
678                         // UI_ThemeColor(TH_REDALERT);
679                         // XXX ui_rasterpos_safe(butr->xmin + xoff, butr->ymin + 5, snode->aspect);
680                         // XXX snode_drawstring(snode, "Error! Check console...", butr->xmax - butr->xmin);
681                         ;
682                 }
683         }
684 }
685
686 /* only once called */
687 static void node_shader_set_butfunc(bNodeType *ntype)
688 {
689         switch(ntype->type) {
690                 /* case NODE_GROUP:      note, typeinfo for group is generated... see "XXX ugly hack" */
691
692                 case SH_NODE_MATERIAL:
693                 case SH_NODE_MATERIAL_EXT:
694                         ntype->uifunc= node_shader_buts_material;
695                         break;
696                 case SH_NODE_TEXTURE:
697                         ntype->uifunc= node_buts_texture;
698                         break;
699                 case SH_NODE_NORMAL:
700                         ntype->uifunc= node_buts_normal;
701                         break;
702                 case SH_NODE_CURVE_VEC:
703                         ntype->uifunc= node_buts_curvevec;
704                         break;
705                 case SH_NODE_CURVE_RGB:
706                         ntype->uifunc= node_buts_curvecol;
707                         break;
708                 case SH_NODE_MAPPING:
709                         ntype->uifunc= node_shader_buts_mapping;
710                         break;
711                 case SH_NODE_VALUE:
712                         ntype->uifunc= node_buts_value;
713                         break;
714                 case SH_NODE_RGB:
715                         ntype->uifunc= node_buts_rgb;
716                         break;
717                 case SH_NODE_MIX_RGB:
718                         ntype->uifunc= node_buts_mix_rgb;
719                         break;
720                 case SH_NODE_VALTORGB:
721                         ntype->uifunc= node_buts_valtorgb;
722                         break;
723                 case SH_NODE_MATH: 
724                         ntype->uifunc= node_buts_math;
725                         break; 
726                 case SH_NODE_VECT_MATH: 
727                         ntype->uifunc= node_shader_buts_vect_math;
728                         break; 
729                 case SH_NODE_GEOMETRY:
730                         ntype->uifunc= node_shader_buts_geometry;
731                         break;
732                 case NODE_DYNAMIC:
733                         ntype->uifunc= node_shader_buts_dynamic;
734                         break;
735                 default:
736                         ntype->uifunc= NULL;
737         }
738 }
739
740 /* ****************** BUTTON CALLBACKS FOR COMPOSITE NODES ***************** */
741
742 static void node_browse_image_cb(bContext *C, void *ntree_v, void *node_v)
743 {
744         bNodeTree *ntree= ntree_v;
745         bNode *node= node_v;
746         
747         nodeSetActive(ntree, node);
748         
749         if(node->menunr<1) return;
750         if(node->menunr==32767) {       /* code for Load New */
751                 /// addqueue(curarea->win, UI_BUT_EVENT, B_NODE_LOADIMAGE); XXX
752         }
753         else {
754                 if(node->id) node->id->us--;
755                 node->id= BLI_findlink(&G.main->image, node->menunr-1);
756                 id_us_plus(node->id);
757
758                 BLI_strncpy(node->name, node->id->name+2, 21);
759
760                 NodeTagChanged(ntree, node); 
761                 BKE_image_signal((Image *)node->id, node->storage, IMA_SIGNAL_USER_NEW_IMAGE);
762                 // addqueue(curarea->win, UI_BUT_EVENT, B_NODE_EXEC); XXX
763         }
764         node->menunr= 0;
765 }
766
767 static void node_active_cb(bContext *C, void *ntree_v, void *node_v)
768 {
769         nodeSetActive(ntree_v, node_v);
770 }
771 static void node_image_type_cb(bContext *C, void *node_v, void *unused)
772 {
773         
774         // allqueue(REDRAWNODE, 1);
775 }
776
777 static char *node_image_type_pup(void)
778 {
779         char *str= MEM_mallocN(256, "image type pup");
780         int a;
781         
782         str[0]= 0;
783         
784         a= sprintf(str, "Image Type %%t|");
785         a+= sprintf(str+a, "  Image %%x%d %%i%d|", IMA_SRC_FILE, ICON_IMAGE_DATA);
786         a+= sprintf(str+a, "  Movie %%x%d %%i%d|", IMA_SRC_MOVIE, ICON_SEQUENCE);
787         a+= sprintf(str+a, "  Sequence %%x%d %%i%d|", IMA_SRC_SEQUENCE, ICON_IMAGE_COL);
788         a+= sprintf(str+a, "  Generated %%x%d %%i%d", IMA_SRC_GENERATED, ICON_BLANK1);
789         
790         return str;
791 }
792
793 /* copy from buttons_shading.c */
794 static char *layer_menu(RenderResult *rr)
795 {
796         RenderLayer *rl;
797         int len= 40 + 40*BLI_countlist(&rr->layers);
798         short a, nr;
799         char *str= MEM_callocN(len, "menu layers");
800         
801         strcpy(str, "Layer %t");
802         a= strlen(str);
803         for(nr=0, rl= rr->layers.first; rl; rl= rl->next, nr++) {
804                 a+= sprintf(str+a, "|%s %%x%d", rl->name, nr);
805         }
806         
807         return str;
808 }
809
810 static void image_layer_cb(bContext *C, void *ima_v, void *iuser_v)
811 {
812         Scene *scene= CTX_data_scene(C);
813         
814         ntreeCompositForceHidden(scene->nodetree, scene);
815         BKE_image_multilayer_index(ima_v, iuser_v);
816         // allqueue(REDRAWNODE, 0);
817 }
818
819 static void node_composit_buts_image(uiLayout *layout, PointerRNA *ptr)
820 {
821         uiBlock *block= uiLayoutAbsoluteBlock(layout);
822         bNode *node= ptr->data;
823         bNodeTree *ntree= ptr->id.data;
824         rctf *butr= &node->butr;
825         ImageUser *iuser= node->storage;
826         uiBut *bt;
827         short dy= (short)butr->ymax-19;
828         char *strp;
829         
830         uiBlockBeginAlign(block);
831         
832         /* browse button */
833         IMAnames_to_pupstring(&strp, NULL, "LOAD NEW %x32767", &(G.main->image), NULL, NULL);
834         node->menunr= 0;
835         bt= uiDefButS(block, MENU, B_NOP, strp, 
836                                   butr->xmin, dy, 19, 19, 
837                                   &node->menunr, 0, 0, 0, 0, "Browses existing choices");
838         uiButSetFunc(bt, node_browse_image_cb, ntree, node);
839         if(strp) MEM_freeN(strp);
840         
841         /* Add New button */
842         if(node->id==NULL) {
843                 bt= uiDefBut(block, BUT, B_NODE_LOADIMAGE, "Load New",
844                                          butr->xmin+19, dy, (short)(butr->xmax-butr->xmin-19.0f), 19, 
845                                          NULL, 0.0, 0.0, 0, 0, "Add new Image");
846                 uiButSetFunc(bt, node_active_cb, ntree, node);
847         }
848         else {
849                 /* name button + type */
850                 Image *ima= (Image *)node->id;
851                 short xmin= (short)butr->xmin, xmax= (short)butr->xmax;
852                 short width= xmax - xmin - 45;
853                 short icon= ICON_IMAGE_DATA;
854                 
855                 if(ima->source==IMA_SRC_MOVIE) icon= ICON_SEQUENCE;
856                 else if(ima->source==IMA_SRC_SEQUENCE) icon= ICON_IMAGE_COL;
857                 else if(ima->source==IMA_SRC_GENERATED) icon= ICON_BLANK1;
858                 
859                 bt= uiDefBut(block, TEX, B_NOP, "IM:",
860                                          xmin+19, dy, width, 19, 
861                                          node->id->name+2, 0.0, 19.0, 0, 0, "Image name");
862                 uiButSetFunc(bt, node_ID_title_cb, node, NULL);
863                 
864                 /* buffer type option */
865                 strp= node_image_type_pup();
866                 bt= uiDefIconTextButS(block, MENU, B_NOP, icon, strp,
867                                          xmax-26, dy, 26, 19, 
868                                          &ima->source, 0.0, 19.0, 0, 0, "Image type");
869                 uiButSetFunc(bt, node_image_type_cb, node, ima);
870                 MEM_freeN(strp);
871                 
872                 if( ELEM(ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE) ) {
873                         width= (xmax-xmin)/2;
874                         
875                         dy-= 19;
876                         uiDefButI(block, NUM, B_NODE_EXEC, "Frs:",
877                                           xmin, dy, width, 19, 
878                                           &iuser->frames, 1.0, MAXFRAMEF, 0, 0, "Amount of images used in animation");
879                         uiDefButI(block, NUM, B_NODE_EXEC, "SFra:",
880                                           xmin+width, dy, width, 19, 
881                                           &iuser->sfra, 1.0, MAXFRAMEF, 0, 0, "Start frame of animation");
882                         dy-= 19;
883                         uiDefButI(block, NUM, B_NODE_EXEC, "Offs:",
884                                           xmin, dy, width, 19, 
885                                           &iuser->offset, -MAXFRAMEF, MAXFRAMEF, 0, 0, "Offsets the number of the frame to use in the animation");
886                         uiDefButS(block, TOG, B_NODE_EXEC, "Cycl",
887                                           xmin+width, dy, width-20, 19, 
888                                           &iuser->cycl, 0.0, 0.0, 0, 0, "Make animation go cyclic");
889                         uiDefIconButBitS(block, TOG, IMA_ANIM_ALWAYS, B_NODE_EXEC, ICON_AUTO,
890                                           xmax-20, dy, 20, 19, 
891                                           &iuser->flag, 0.0, 0.0, 0, 0, "Always refresh Image on frame changes");
892                 }
893                 if( ima->type==IMA_TYPE_MULTILAYER && ima->rr) {
894                         RenderLayer *rl= BLI_findlink(&ima->rr->layers, iuser->layer);
895                         if(rl) {
896                                 width= (xmax-xmin);
897                                 dy-= 19;
898                                 strp= layer_menu(ima->rr);
899                                 bt= uiDefButS(block, MENU, B_NODE_EXEC, strp,
900                                                   xmin, dy, width, 19, 
901                                                   &iuser->layer, 0.0, 10000.0, 0, 0, "Layer");
902                                 uiButSetFunc(bt, image_layer_cb, ima->rr, node->storage);
903                                 MEM_freeN(strp);
904                         }
905                 }
906         }
907                 
908         if(node->id) {
909                 /* for each draw we test for anim refresh event */
910                 if(iuser->flag & IMA_ANIM_REFRESHED) {
911                         iuser->flag &= ~IMA_ANIM_REFRESHED;
912                         // addqueue(curarea->win, UI_BUT_EVENT, B_NODE_EXEC); XXX
913                 }
914         }
915 }
916
917 /* if we use render layers from other scene, we make a nice title */
918 static void set_render_layers_title(bContext *C, void *node_v, void *unused)
919 {
920         bNode *node= node_v;
921         Scene *sce;
922         SceneRenderLayer *srl;
923         char str[64];
924         
925         if(node->id) {
926                 BLI_strncpy(str, node->id->name+2, 21);
927                 strcat(str, "|");
928                 sce= (Scene *)node->id;
929         }
930         else {
931                 str[0]= 0;
932                 sce= CTX_data_scene(C);
933         }
934         srl= BLI_findlink(&sce->r.layers, node->custom1);
935         if(srl==NULL) {
936                 node->custom1= 0;
937                 srl= sce->r.layers.first;
938         }
939         
940         strcat(str, srl->name);
941         BLI_strncpy(node->name, str, 32);
942 }
943
944 static char *scene_layer_menu(Scene *sce)
945 {
946         SceneRenderLayer *srl;
947         int len= 40 + 40*BLI_countlist(&sce->r.layers);
948         short a, nr;
949         char *str= MEM_callocN(len, "menu layers");
950         
951         strcpy(str, "Active Layer %t");
952         a= strlen(str);
953         for(nr=0, srl= sce->r.layers.first; srl; srl= srl->next, nr++) {
954                 a+= sprintf(str+a, "|%s %%x%d", srl->name, nr);
955         }
956         
957         return str;
958 }
959
960 static void node_browse_scene_cb(bContext *C, void *ntree_v, void *node_v)
961 {
962         bNodeTree *ntree= ntree_v;
963         bNode *node= node_v;
964         Scene *sce;
965         
966         if(node->menunr<1) return;
967         
968         if(node->id) {
969                 node->id->us--;
970                 node->id= NULL;
971         }
972         sce= BLI_findlink(&G.main->scene, node->menunr-1);
973         node->id= &sce->id;
974         id_us_plus(node->id);
975         
976         set_render_layers_title(C, node, NULL);
977         nodeSetActive(ntree, node);
978
979         // allqueue(REDRAWBUTSSHADING, 0);
980         // allqueue(REDRAWNODE, 0);
981         NodeTagChanged(ntree, node); 
982
983         node->menunr= 0;
984 }
985
986
987 static void node_composit_buts_renderlayers(uiLayout *layout, PointerRNA *ptr)
988 {
989         uiBlock *block= uiLayoutAbsoluteBlock(layout);
990         bNode *node= ptr->data;
991         bNodeTree *ntree= ptr->id.data;
992         rctf *butr= &node->butr;
993
994         if(node->id) {
995                 Scene *scene= (Scene *)node->id;
996                 uiBut *bt;
997                 char *strp;
998                 
999                 /* browse button scene */
1000                 uiBlockBeginAlign(block);
1001                 IDnames_to_pupstring(&strp, NULL, "", &(G.main->scene), NULL, NULL);
1002                 node->menunr= 0;
1003                 bt= uiDefButS(block, MENU, B_NOP, strp, 
1004                                           butr->xmin, butr->ymin, 20, 19, 
1005                                           &node->menunr, 0, 0, 0, 0, "Browse Scene to use RenderLayer from");
1006                 uiButSetFunc(bt, node_browse_scene_cb, ntree, node);
1007                 if(strp) MEM_freeN(strp);
1008                 
1009                 /* browse button layer */
1010                 strp= scene_layer_menu(node->id?(Scene *)node->id:scene);
1011                 if(node->id)
1012                         bt= uiDefIconTextButS(block, MENU, B_NODE_EXEC, ICON_RENDERLAYERS, strp, 
1013                                   butr->xmin+20, butr->ymin, (butr->xmax-butr->xmin)-40, 19, 
1014                                   &node->custom1, 0, 0, 0, 0, "Choose Render Layer");
1015                 else
1016                         bt= uiDefButS(block, MENU, B_NODE_EXEC, strp, 
1017                                   butr->xmin+20, butr->ymin, (butr->xmax-butr->xmin)-40, 19, 
1018                                   &node->custom1, 0, 0, 0, 0, "Choose Render Layer");
1019                 uiButSetFunc(bt, set_render_layers_title, node, NULL);
1020                 MEM_freeN(strp);
1021                 
1022                 /* re-render */
1023                 /* uses custom2, not the best implementation of the world... but we need it to work now :) */
1024                 bt= uiDefIconButS(block, TOG, B_NODE_EXEC, ICON_SCENE, 
1025                                   butr->xmax-20, butr->ymin, 20, 19, 
1026                                   &node->custom2, 0, 0, 0, 0, "Re-render this Layer");
1027                 
1028         }
1029 }
1030
1031
1032 static void node_composit_buts_blur(uiLayout *layout, PointerRNA *ptr)
1033 {
1034         uiLayout *col;
1035         
1036         col= uiLayoutColumn(layout, 0);
1037         
1038         uiItemR(col, "", 0, ptr, "filter_type", 0);
1039         /* Only for "Fast Gaussian" */
1040         if (RNA_enum_get(ptr, "filter_type")!= 7) {
1041                 uiItemR(col, NULL, 0, ptr, "bokeh", 0);
1042                 uiItemR(col, NULL, 0, ptr, "gamma", 0);
1043         }
1044         
1045         uiItemR(col, NULL, 0, ptr, "relative", 0);
1046         col= uiLayoutColumn(layout, 1);
1047         if (RNA_boolean_get(ptr, "relative")== 1) {
1048                 uiItemR(col, "X", 0, ptr, "factor_x", 0);
1049                 uiItemR(col, "Y", 0, ptr, "factor_y", 0);
1050         }
1051         else {
1052                 uiItemR(col, "X", 0, ptr, "sizex", 0);
1053                 uiItemR(col, "Y", 0, ptr, "sizey", 0);
1054         }
1055 }
1056
1057 static void node_composit_buts_dblur(uiLayout *layout, PointerRNA *ptr)
1058 {
1059         uiLayout *col;
1060         
1061         uiItemR(layout, NULL, 0, ptr, "iterations", 0);
1062         uiItemR(layout, NULL, 0, ptr, "wrap", 0);
1063         
1064         col= uiLayoutColumn(layout, 1);
1065         uiItemL(col, "Center:", 0);
1066         uiItemR(col, "X", 0, ptr, "center_x", 0);
1067         uiItemR(col, "Y", 0, ptr, "center_y", 0);
1068         
1069         uiItemS(layout);
1070         
1071         col= uiLayoutColumn(layout, 1);
1072         uiItemR(col, NULL, 0, ptr, "distance", 0);
1073         uiItemR(col, NULL, 0, ptr, "angle", 0);
1074         
1075         uiItemS(layout);
1076         
1077         uiItemR(layout, NULL, 0, ptr, "spin", 0);
1078         uiItemR(layout, NULL, 0, ptr, "zoom", 0);
1079 }
1080
1081 static void node_composit_buts_bilateralblur(uiLayout *layout, PointerRNA *ptr)
1082 {       
1083         uiLayout *col;
1084         
1085         col= uiLayoutColumn(layout, 1);
1086         uiItemR(col, NULL, 0, ptr, "iterations", 0);
1087         uiItemR(col, NULL, 0, ptr, "sigma_color", 0);
1088         uiItemR(col, NULL, 0, ptr, "sigma_space", 0);
1089 }
1090
1091 /* qdn: defocus node */
1092 static void node_composit_buts_defocus(uiLayout *layout, PointerRNA *ptr)
1093 {
1094         uiLayout *sub, *col;
1095         
1096         col= uiLayoutColumn(layout, 0);
1097         uiItemL(col, "Bokeh Type:", 0);
1098         uiItemR(col, "", 0, ptr, "bokeh", 0);
1099         uiItemR(col, NULL, 0, ptr, "angle", 0);
1100
1101         uiItemR(layout, NULL, 0, ptr, "gamma_correction", 0);
1102
1103         col = uiLayoutColumn(layout, 0);
1104         uiLayoutSetActive(col, RNA_boolean_get(ptr, "use_zbuffer")==0);
1105         uiItemR(col, NULL, 0, ptr, "f_stop", 0);
1106
1107         uiItemR(layout, NULL, 0, ptr, "max_blur", 0);
1108         uiItemR(layout, NULL, 0, ptr, "threshold", 0);
1109         
1110         // Preview
1111         col = uiLayoutColumn(layout, 0);
1112         uiItemR(col, NULL, 0, ptr, "preview", 0);
1113         sub = uiLayoutColumn(col, 0);
1114         uiLayoutSetActive(sub, RNA_boolean_get(ptr, "preview"));
1115         uiItemR(sub, NULL, 0, ptr, "samples", 0);
1116         
1117         // Z-Buffer
1118         col = uiLayoutColumn(layout, 0);
1119         uiItemR(col, NULL, 0, ptr, "use_zbuffer", 0);
1120         sub = uiLayoutColumn(col, 0);
1121         uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_zbuffer"));
1122         uiItemR(sub, NULL, 0, ptr, "z_scale", 0);
1123 }
1124
1125 /* qdn: glare node */
1126 static void node_composit_buts_glare(uiLayout *layout, PointerRNA *ptr)
1127 {       
1128         uiItemR(layout, "", 0, ptr, "glare_type", 0);
1129         uiItemR(layout, "", 0, ptr, "quality", 0);
1130
1131         if (RNA_enum_get(ptr, "glare_type")!= 1) {
1132                 uiItemR(layout, NULL, 0, ptr, "iterations", 0);
1133         
1134                 if (RNA_enum_get(ptr, "glare_type")!= 0) 
1135                         uiItemR(layout, NULL, 0, ptr, "color_modulation", UI_ITEM_R_SLIDER);
1136         }
1137         
1138         uiItemR(layout, NULL, 0, ptr, "mix", 0);                
1139         uiItemR(layout, NULL, 0, ptr, "threshold", 0);
1140
1141         if (RNA_enum_get(ptr, "glare_type")== 2) {
1142                 uiItemR(layout, NULL, 0, ptr, "streaks", 0);            
1143                 uiItemR(layout, NULL, 0, ptr, "angle_offset", 0);
1144         }
1145         if (RNA_enum_get(ptr, "glare_type")== 0 || RNA_enum_get(ptr, "glare_type")== 2) {
1146                 uiItemR(layout, NULL, 0, ptr, "fade", UI_ITEM_R_SLIDER);
1147                 
1148                 if (RNA_enum_get(ptr, "glare_type")== 0) 
1149                         uiItemR(layout, NULL, 0, ptr, "rotate_45", 0);
1150         }
1151         if (RNA_enum_get(ptr, "glare_type")== 1) {
1152                 uiItemR(layout, NULL, 0, ptr, "size", 0);
1153         }
1154 }
1155
1156 /* qdn: tonemap node */
1157 static void node_composit_buts_tonemap(uiLayout *layout, PointerRNA *ptr)
1158 {       
1159         uiLayout *col;
1160
1161         col = uiLayoutColumn(layout, 0);
1162         uiItemR(col, "", 0, ptr, "tonemap_type", 0);
1163         if (RNA_enum_get(ptr, "tonemap_type")== 0) {
1164                 uiItemR(col, NULL, 0, ptr, "key", UI_ITEM_R_SLIDER);
1165                 uiItemR(col, NULL, 0, ptr, "offset", 0);
1166                 uiItemR(col, NULL, 0, ptr, "gamma", 0);
1167         }
1168         else {
1169                 uiItemR(col, NULL, 0, ptr, "intensity", 0);
1170                 uiItemR(col, NULL, 0, ptr, "contrast", UI_ITEM_R_SLIDER);
1171                 uiItemR(col, NULL, 0, ptr, "adaptation", UI_ITEM_R_SLIDER);
1172                 uiItemR(col, NULL, 0, ptr, "correction", UI_ITEM_R_SLIDER);
1173         }
1174 }
1175
1176 /* qdn: lens distortion node */
1177 static void node_composit_buts_lensdist(uiLayout *layout, PointerRNA *ptr)
1178 {
1179         uiLayout *col;
1180
1181         col= uiLayoutColumn(layout, 0);
1182         uiItemR(col, NULL, 0, ptr, "projector", 0);
1183
1184         col = uiLayoutColumn(col, 0);
1185         uiLayoutSetActive(col, RNA_boolean_get(ptr, "projector")==0);
1186         uiItemR(col, NULL, 0, ptr, "jitter", 0);
1187         uiItemR(col, NULL, 0, ptr, "fit", 0);
1188 }
1189
1190 static void node_composit_buts_vecblur(uiLayout *layout, PointerRNA *ptr)
1191 {
1192         uiLayout *col;
1193         
1194         col= uiLayoutColumn(layout, 0);
1195         uiItemR(col, NULL, 0, ptr, "samples", 0);
1196         uiItemR(col, "Blur", 0, ptr, "factor", 0);
1197         
1198         col= uiLayoutColumn(layout, 1);
1199         uiItemL(col, "Speed:", 0);
1200         uiItemR(col, "Min", 0, ptr, "min_speed", 0);
1201         uiItemR(col, "Max", 0, ptr, "max_speed", 0);
1202
1203         uiItemR(layout, NULL, 0, ptr, "curved", 0);
1204 }
1205
1206 static void node_composit_buts_filter(uiLayout *layout, PointerRNA *ptr)
1207 {
1208         uiItemR(layout, "", 0, ptr, "filter_type", 0);
1209 }
1210
1211 static void node_composit_buts_flip(uiLayout *layout, PointerRNA *ptr)
1212 {
1213         uiItemR(layout, "", 0, ptr, "axis", 0);
1214 }
1215
1216 static void node_composit_buts_crop(uiLayout *layout, PointerRNA *ptr)
1217 {
1218         uiLayout *col;
1219         
1220         uiItemR(layout, NULL, 0, ptr, "crop_size", 0);
1221         
1222         col= uiLayoutColumn(layout, 1);
1223         uiItemR(col, "Left", 0, ptr, "x1", 0);
1224         uiItemR(col, "Right", 0, ptr, "x2", 0);
1225         uiItemR(col, "Up", 0, ptr, "y1", 0);
1226         uiItemR(col, "Down", 0, ptr, "y2", 0);
1227 }
1228
1229 static void node_composit_buts_splitviewer(uiLayout *layout, PointerRNA *ptr)
1230 {
1231         uiLayout *row, *col;
1232         
1233         col= uiLayoutColumn(layout, 0);
1234         row= uiLayoutRow(col, 0);
1235         uiItemR(row, NULL, 0, ptr, "axis", UI_ITEM_R_EXPAND);
1236         uiItemR(col, NULL, 0, ptr, "factor", 0);
1237 }
1238
1239 static void node_composit_buts_map_value(uiLayout *layout, PointerRNA *ptr)
1240 {
1241         uiLayout *sub, *col;
1242         
1243         col =uiLayoutColumn(layout, 1);
1244         uiItemR(col, NULL, 0, ptr, "offset", 0);
1245         uiItemR(col, NULL, 0, ptr, "size", 0);
1246         
1247         col =uiLayoutColumn(layout, 1);
1248         uiItemR(col, NULL, 0, ptr, "use_min", 0);
1249         sub =uiLayoutColumn(col, 0);
1250         uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_min"));
1251         uiItemR(sub, "", 0, ptr, "min", 0);
1252         
1253         col =uiLayoutColumn(layout, 1);
1254         uiItemR(col, NULL, 0, ptr, "use_max", 0);
1255         sub =uiLayoutColumn(col, 0);
1256         uiLayoutSetActive(sub, RNA_boolean_get(ptr, "use_max"));
1257         uiItemR(sub, "", 0, ptr, "max", 0);
1258 }
1259
1260 static void node_composit_buts_alphaover(uiLayout *layout, PointerRNA *ptr)
1261 {       
1262         uiLayout *col;
1263         
1264         col =uiLayoutColumn(layout, 1);
1265         /* alpha type */
1266         uiItemR(col, NULL, 0, ptr, "convert_premul", 0);
1267         /* mix factor */
1268         uiItemR(col, NULL, 0, ptr, "premul", 0);
1269 }
1270
1271 static void node_composit_buts_hue_sat(uiLayout *layout, PointerRNA *ptr)
1272 {
1273         uiLayout *col;
1274         
1275         col =uiLayoutColumn(layout, 0);
1276         uiItemR(col, NULL, 0, ptr, "hue", UI_ITEM_R_SLIDER);
1277         uiItemR(col, NULL, 0, ptr, "sat", UI_ITEM_R_SLIDER);
1278         uiItemR(col, NULL, 0, ptr, "val", UI_ITEM_R_SLIDER);
1279 }
1280
1281 static void node_composit_buts_dilateerode(uiLayout *layout, PointerRNA *ptr)
1282 {
1283         uiItemR(layout, NULL, 0, ptr, "distance", 0);
1284 }
1285
1286 static void node_composit_buts_diff_matte(uiLayout *layout, PointerRNA *ptr)
1287 {
1288         uiLayout *col;
1289         
1290         col =uiLayoutColumn(layout, 1);
1291         uiItemR(col, NULL, 0, ptr, "tolerance", UI_ITEM_R_SLIDER);
1292         uiItemR(col, NULL, 0, ptr, "falloff", UI_ITEM_R_SLIDER);
1293 }
1294
1295 static void node_composit_buts_distance_matte(uiLayout *layout, PointerRNA *ptr)
1296 {
1297         uiLayout *col;
1298         
1299         col =uiLayoutColumn(layout, 1);
1300         uiItemR(col, NULL, 0, ptr, "tolerance", UI_ITEM_R_SLIDER);
1301         uiItemR(col, NULL, 0, ptr, "falloff", UI_ITEM_R_SLIDER);
1302 }
1303
1304 static void node_composit_buts_color_spill(uiLayout *layout, PointerRNA *ptr)
1305 {
1306         uiLayout *row, *col;
1307         
1308         col =uiLayoutColumn(layout, 0);
1309         uiItemR(col, NULL, 0, ptr, "factor", 0);
1310         row= uiLayoutRow(col, 0);
1311         uiItemR(row, NULL, 0, ptr, "channel", UI_ITEM_R_EXPAND);
1312 }
1313
1314 static void node_composit_buts_chroma_matte(uiLayout *layout, PointerRNA *ptr)
1315 {
1316         uiLayout *col;
1317         
1318         col= uiLayoutColumn(layout, 0);
1319         uiItemR(col, NULL, 0, ptr, "acceptance", 0);
1320         uiItemR(col, NULL, 0, ptr, "cutoff", 0);
1321         
1322         col= uiLayoutColumn(layout, 1);
1323         uiItemR(col, NULL, 0, ptr, "lift", UI_ITEM_R_SLIDER);
1324         uiItemR(col, NULL, 0, ptr, "gain", UI_ITEM_R_SLIDER);
1325         uiItemR(col, NULL, 0, ptr, "shadow_adjust", UI_ITEM_R_SLIDER);
1326 }
1327
1328 static void node_composit_buts_color_matte(uiLayout *layout, PointerRNA *ptr)
1329 {
1330         uiLayout *col;
1331         
1332         col= uiLayoutColumn(layout, 1);
1333         uiItemR(col, NULL, 0, ptr, "h", UI_ITEM_R_SLIDER);
1334         uiItemR(col, NULL, 0, ptr, "s", UI_ITEM_R_SLIDER);
1335         uiItemR(col, NULL, 0, ptr, "v", UI_ITEM_R_SLIDER);
1336 }
1337
1338 static void node_composit_buts_channel_matte(uiLayout *layout, PointerRNA *ptr)
1339 {       
1340         uiLayout *col, *row;
1341         
1342         uiBlock *block= uiLayoutAbsoluteBlock(layout);
1343         bNode *node= ptr->data;
1344         rctf *butr= &node->butr;
1345         short sx= (butr->xmax-butr->xmin)/4;
1346         short cx= (butr->xmax-butr->xmin)/3;
1347         NodeChroma *c=node->storage;
1348         char *c1, *c2, *c3;
1349
1350         /*color space selector*/
1351         row= uiLayoutRow(layout, 0);
1352         uiItemR(row, NULL, 0, ptr, "color_space", UI_ITEM_R_EXPAND);
1353
1354         if (node->custom1==1) {
1355                 c1="R"; c2="G"; c3="B";
1356         }
1357         else if(node->custom1==2){
1358                 c1="H"; c2="S"; c3="V";
1359         }
1360         else if(node->custom1==3){
1361                 c1="Y"; c2="U"; c3="V";
1362         }
1363         else { // if(node->custom1==4){
1364                 c1="Y"; c2="Cb"; c3="Cr";
1365         }
1366
1367         /*channel selector */
1368         row= uiLayoutRow(layout, 0);
1369         uiBlockBeginAlign(block);
1370         uiDefButS(block, ROW, B_NODE_EXEC, c1,
1371                 butr->xmin,butr->ymin+40,cx,20,&node->custom2,1, 1, 0, 0, "Channel 1");
1372         uiDefButS(block, ROW, B_NODE_EXEC, c2,
1373                 butr->xmin+cx,butr->ymin+40,cx,20,&node->custom2,1, 2, 0, 0, "Channel 2");
1374         uiDefButS(block, ROW, B_NODE_EXEC, c3,
1375                 butr->xmin+cx+cx,butr->ymin+40,cx,20,&node->custom2, 1, 3, 0, 0, "Channel 3");
1376         uiBlockEndAlign(block);
1377
1378         /*tolerance sliders */
1379         col =uiLayoutColumn(layout, 1);
1380         uiItemR(col, NULL, 0, ptr, "high", UI_ITEM_R_SLIDER);
1381         uiItemR(col, NULL, 0, ptr, "low", UI_ITEM_R_SLIDER);
1382
1383 }
1384
1385 static void node_composit_buts_luma_matte(uiLayout *layout, PointerRNA *ptr)
1386 {
1387         uiLayout *col;
1388         
1389         col= uiLayoutColumn(layout, 1);
1390         uiItemR(col, NULL, 0, ptr, "high", UI_ITEM_R_SLIDER);
1391         uiItemR(col, NULL, 0, ptr, "low", UI_ITEM_R_SLIDER);
1392 }
1393
1394 static void node_composit_buts_map_uv(uiLayout *layout, PointerRNA *ptr)
1395 {
1396         uiItemR(layout, NULL, 0, ptr, "alpha", 0);
1397 }
1398
1399 static void node_composit_buts_id_mask(uiLayout *layout, PointerRNA *ptr)
1400 {
1401         uiBlock *block= uiLayoutAbsoluteBlock(layout);
1402         bNode *node= ptr->data;
1403         rctf *butr= &node->butr;
1404
1405         uiDefButS(block, NUM, B_NODE_EXEC, "ID:",
1406                           butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20, 
1407                           &node->custom1, 0, 10000, 0, 0, "Pass Index number to convert to Alpha");
1408 }
1409
1410 /* allocate sufficient! */
1411 /*
1412 static void node_imagetype_string(char *str)
1413 {
1414         str += sprintf(str, "Save Image as: %%t|");
1415         str += sprintf(str, "Targa %%x%d|", R_TARGA);
1416         str += sprintf(str, "Targa Raw %%x%d|", R_RAWTGA);
1417         str += sprintf(str, "PNG %%x%d|", R_PNG);
1418         str += sprintf(str, "BMP %%x%d|", R_BMP);
1419         str += sprintf(str, "Jpeg %%x%d|", R_JPEG90);
1420         str += sprintf(str, "Iris %%x%d|", R_IRIS);
1421         str += sprintf(str, "Radiance HDR %%x%d|", R_RADHDR);
1422         str += sprintf(str, "Cineon %%x%d|", R_CINEON);
1423         str += sprintf(str, "DPX %%x%d|", R_DPX);
1424         str += sprintf(str, "OpenEXR %%x%d", R_OPENEXR);
1425 }
1426 */
1427
1428 /*static void node_set_image_cb(bContext *C, void *ntree_v, void *node_v)
1429 {
1430         bNodeTree *ntree= ntree_v;
1431         bNode *node= node_v;
1432         
1433         nodeSetActive(ntree, node);
1434 }
1435 */
1436
1437 static void node_composit_buts_file_output(uiLayout *layout, PointerRNA *ptr)
1438 {
1439         uiLayout *col, *row;
1440
1441         col= uiLayoutColumn(layout, 0);
1442         uiItemR(col, "", 0, ptr, "filename", 0);
1443         uiItemR(col, "", 0, ptr, "image_type", 0);
1444         
1445         row= uiLayoutRow(layout, 0);
1446         if (RNA_enum_get(ptr, "image_type")== R_OPENEXR) {
1447                 uiItemR(row, NULL, 0, ptr, "exr_half", 0);
1448                 uiItemR(row, "", 0, ptr, "exr_codec", 0);
1449         }
1450         else if (RNA_enum_get(ptr, "image_type")== R_JPEG90) {
1451                 uiItemR(row, NULL, 0, ptr, "quality", UI_ITEM_R_SLIDER);
1452         }
1453         
1454         row= uiLayoutRow(layout, 1);
1455         uiItemR(row, "Start", 0, ptr, "start_frame", 0);
1456         uiItemR(row, "End", 0, ptr, "end_frame", 0);
1457 }
1458
1459 static void node_scale_cb(bContext *C, void *node_v, void *unused_v)
1460 {
1461         bNode *node= node_v;
1462         bNodeSocket *nsock;
1463
1464         /* check the 2 inputs, and set them to reasonable values */
1465         for(nsock= node->inputs.first; nsock; nsock= nsock->next) {
1466                 if(ELEM(node->custom1, CMP_SCALE_RELATIVE, CMP_SCALE_SCENEPERCENT))
1467                         nsock->ns.vec[0]= 1.0;
1468                 else {
1469                         if(nsock->next==NULL)
1470                                 nsock->ns.vec[0]= (float)CTX_data_scene(C)->r.ysch;
1471                         else
1472                                 nsock->ns.vec[0]= (float)CTX_data_scene(C)->r.xsch;
1473                 }
1474         }       
1475 }
1476
1477 static void node_composit_buts_scale(uiLayout *layout, PointerRNA *ptr)
1478 {
1479         uiBlock *block= uiLayoutAbsoluteBlock(layout);
1480         bNode *node= ptr->data;
1481         rctf *butr= &node->butr;
1482         uiBut *bt= uiDefButS(block, MENU, B_NODE_EXEC, "Relative %x0|Absolute %x1|Scene Size % %x2|",
1483                           butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20, 
1484                           &node->custom1, 0, 0, 0, 0, "Scale new image to absolute pixel size, size relative to the incoming image, or using the 'percent' size of the scene");
1485         uiButSetFunc(bt, node_scale_cb, node, NULL);
1486 }
1487
1488 static void node_composit_buts_invert(uiLayout *layout, PointerRNA *ptr)
1489 {
1490         uiLayout *col;
1491         
1492         col= uiLayoutColumn(layout, 0);
1493         uiItemR(col, NULL, 0, ptr, "rgb", 0);
1494         uiItemR(col, NULL, 0, ptr, "alpha", 0);
1495 }
1496
1497 static void node_composit_buts_premulkey(uiLayout *layout, PointerRNA *ptr)
1498 {
1499         uiItemR(layout, "", 0, ptr, "mapping", 0);
1500 }
1501
1502 static void node_composit_buts_view_levels(uiLayout *layout, PointerRNA *ptr)
1503 {
1504         uiItemR(layout, NULL, 0, ptr, "color_space", UI_ITEM_R_EXPAND);
1505 }
1506
1507 /* only once called */
1508 static void node_composit_set_butfunc(bNodeType *ntype)
1509 {
1510         switch(ntype->type) {
1511                 /* case NODE_GROUP:      note, typeinfo for group is generated... see "XXX ugly hack" */
1512
1513                 case CMP_NODE_IMAGE:
1514                         ntype->uifunc= node_composit_buts_image;
1515                         break;
1516                 case CMP_NODE_R_LAYERS:
1517                         ntype->uifunc= node_composit_buts_renderlayers;
1518                         break;
1519                 case CMP_NODE_NORMAL:
1520                         ntype->uifunc= node_buts_normal;
1521                         break;
1522                 case CMP_NODE_CURVE_VEC:
1523                         ntype->uifunc= node_buts_curvevec;
1524                         break;
1525                 case CMP_NODE_CURVE_RGB:
1526                         ntype->uifunc= node_buts_curvecol;
1527                         break;
1528                 case CMP_NODE_VALUE:
1529                         ntype->uifunc= node_buts_value;
1530                         break;
1531                 case CMP_NODE_RGB:
1532                         ntype->uifunc= node_buts_rgb;
1533                         break;
1534                 case CMP_NODE_FLIP:
1535                         ntype->uifunc= node_composit_buts_flip;
1536                         break;
1537                 case CMP_NODE_SPLITVIEWER:
1538                         ntype->uifunc= node_composit_buts_splitviewer;
1539                         break;
1540                 case CMP_NODE_MIX_RGB:
1541                         ntype->uifunc= node_buts_mix_rgb;
1542                         break;
1543                 case CMP_NODE_VALTORGB:
1544                         ntype->uifunc= node_buts_valtorgb;
1545                         break;
1546                 case CMP_NODE_CROP:
1547                         ntype->uifunc= node_composit_buts_crop;
1548                         break;
1549                 case CMP_NODE_BLUR:
1550                         ntype->uifunc= node_composit_buts_blur;
1551                         break;
1552                 case CMP_NODE_DBLUR:
1553                         ntype->uifunc= node_composit_buts_dblur;
1554                         break;
1555                 case CMP_NODE_BILATERALBLUR:
1556                         ntype->uifunc= node_composit_buts_bilateralblur;
1557                         break;
1558                 /* qdn: defocus node */
1559                 case CMP_NODE_DEFOCUS:
1560                         ntype->uifunc = node_composit_buts_defocus;
1561                         break;
1562                 /* qdn: glare node */
1563                 case CMP_NODE_GLARE:
1564                         ntype->uifunc = node_composit_buts_glare;
1565                         break;
1566                 /* qdn: tonemap node */
1567                 case CMP_NODE_TONEMAP:
1568                         ntype->uifunc = node_composit_buts_tonemap;
1569                         break;
1570                 /* qdn: lens distortion node */
1571                 case CMP_NODE_LENSDIST:
1572                         ntype->uifunc = node_composit_buts_lensdist;
1573                         break;
1574                 case CMP_NODE_VECBLUR:
1575                         ntype->uifunc= node_composit_buts_vecblur;
1576                         break;
1577                 case CMP_NODE_FILTER:
1578                         ntype->uifunc= node_composit_buts_filter;
1579                         break;
1580                 case CMP_NODE_MAP_VALUE:
1581                         ntype->uifunc= node_composit_buts_map_value;
1582                         break;
1583                 case CMP_NODE_TIME:
1584                         ntype->uifunc= node_buts_time;
1585                         break;
1586                 case CMP_NODE_ALPHAOVER:
1587                         ntype->uifunc= node_composit_buts_alphaover;
1588                         break;
1589                 case CMP_NODE_HUE_SAT:
1590                         ntype->uifunc= node_composit_buts_hue_sat;
1591                         break;
1592                 case CMP_NODE_TEXTURE:
1593                         ntype->uifunc= node_buts_texture;
1594                         break;
1595                 case CMP_NODE_DILATEERODE:
1596                         ntype->uifunc= node_composit_buts_dilateerode;
1597                         break;
1598                 case CMP_NODE_OUTPUT_FILE:
1599                         ntype->uifunc= node_composit_buts_file_output;
1600                         break;  
1601                 case CMP_NODE_DIFF_MATTE:
1602                         ntype->uifunc=node_composit_buts_diff_matte;
1603                         break;
1604                 case CMP_NODE_DIST_MATTE:
1605                         ntype->uifunc=node_composit_buts_distance_matte;
1606                         break;
1607                 case CMP_NODE_COLOR_SPILL:
1608                         ntype->uifunc=node_composit_buts_color_spill;
1609                         break;
1610                 case CMP_NODE_CHROMA_MATTE:
1611                         ntype->uifunc=node_composit_buts_chroma_matte;
1612                         break;
1613                 case CMP_NODE_COLOR_MATTE:
1614                         ntype->uifunc=node_composit_buts_color_matte;
1615                         break;
1616                 case CMP_NODE_SCALE:
1617                         ntype->uifunc= node_composit_buts_scale;
1618                         break;
1619                 case CMP_NODE_CHANNEL_MATTE:
1620                         ntype->uifunc= node_composit_buts_channel_matte;
1621                         break;
1622                 case CMP_NODE_LUMA_MATTE:
1623                         ntype->uifunc= node_composit_buts_luma_matte;
1624                         break;
1625                 case CMP_NODE_MAP_UV:
1626                         ntype->uifunc= node_composit_buts_map_uv;
1627                         break;
1628                 case CMP_NODE_ID_MASK:
1629                         ntype->uifunc= node_composit_buts_id_mask;
1630                         break;
1631                 case CMP_NODE_MATH:
1632                         ntype->uifunc= node_buts_math;
1633                         break;
1634                 case CMP_NODE_INVERT:
1635                         ntype->uifunc= node_composit_buts_invert;
1636                         break;
1637                 case CMP_NODE_PREMULKEY:
1638                         ntype->uifunc= node_composit_buts_premulkey;
1639                         break;
1640       case CMP_NODE_VIEW_LEVELS:
1641                         ntype->uifunc=node_composit_buts_view_levels;
1642                         break;
1643                 default:
1644                         ntype->uifunc= NULL;
1645         }
1646 }
1647
1648 /* ****************** BUTTON CALLBACKS FOR TEXTURE NODES ***************** */
1649
1650 static void node_texture_buts_bricks(uiLayout *layout, PointerRNA *ptr)
1651 {
1652         uiLayout *col;
1653         
1654         col= uiLayoutColumn(layout, 1);
1655         uiItemR(col, "Offset", 0, ptr, "offset", 0);
1656         uiItemR(col, "Frequency", 0, ptr, "offset_frequency", 0);
1657         
1658         col= uiLayoutColumn(layout, 1);
1659         uiItemR(col, "Squash", 0, ptr, "squash", 0);
1660         uiItemR(col, "Frequency", 0, ptr, "squash_frequency", 0);
1661 }
1662
1663 /* Copied from buttons_shading.c -- needs unifying */
1664 static char* noisebasis_menu()
1665 {
1666         static char nbmenu[256];
1667         sprintf(nbmenu, "Noise Basis %%t|Blender Original %%x%d|Original Perlin %%x%d|Improved Perlin %%x%d|Voronoi F1 %%x%d|Voronoi F2 %%x%d|Voronoi F3 %%x%d|Voronoi F4 %%x%d|Voronoi F2-F1 %%x%d|Voronoi Crackle %%x%d|CellNoise %%x%d", TEX_BLENDER, TEX_STDPERLIN, TEX_NEWPERLIN, TEX_VORONOI_F1, TEX_VORONOI_F2, TEX_VORONOI_F3, TEX_VORONOI_F4, TEX_VORONOI_F2F1, TEX_VORONOI_CRACKLE, TEX_CELLNOISE);
1668         return nbmenu;
1669 }
1670
1671 static void node_texture_buts_proc(uiLayout *layout, PointerRNA *ptr)
1672 {
1673         uiBlock *block= uiLayoutAbsoluteBlock(layout);
1674         bNode *node= ptr->data;
1675         rctf *butr= &node->butr;
1676         Tex *tex = (Tex *)node->storage;
1677         short x,y,w,h;
1678         
1679         x = butr->xmin;
1680         y = butr->ymin;
1681         w = butr->xmax - x;
1682         h = butr->ymax - y;
1683         
1684         switch( tex->type ) {
1685                 case TEX_BLEND:
1686                         uiBlockBeginAlign( block );
1687                         uiDefButS( block, MENU, B_NODE_EXEC,
1688                                 "Linear %x0|Quad %x1|Ease %x2|Diag %x3|Sphere %x4|Halo %x5|Radial %x6",
1689                                 x, y+20, w, 20, &tex->stype, 0, 1, 0, 0, "Blend Type" );
1690                         uiDefButBitS(block, TOG, TEX_FLIPBLEND, B_NODE_EXEC, "Flip XY", x, y, w, 20,
1691                                 &tex->flag, 0, 0, 0, 0, "Flips the direction of the progression 90 degrees");
1692                         uiBlockEndAlign( block );
1693                         break;
1694                         
1695                 case TEX_MARBLE:
1696                         uiBlockBeginAlign(block);
1697                 
1698                         uiDefButS(block, ROW, B_NODE_EXEC, "Soft",       0*w/3+x, 40+y, w/3, 18, &tex->stype, 2.0, (float)TEX_SOFT, 0, 0, "Uses soft marble"); 
1699                         uiDefButS(block, ROW, B_NODE_EXEC, "Sharp",      1*w/3+x, 40+y, w/3, 18, &tex->stype, 2.0, (float)TEX_SHARP, 0, 0, "Uses more clearly defined marble"); 
1700                         uiDefButS(block, ROW, B_NODE_EXEC, "Sharper",    2*w/3+x, 40+y, w/3, 18, &tex->stype, 2.0, (float)TEX_SHARPER, 0, 0, "Uses very clearly defined marble"); 
1701                         
1702                         uiDefButS(block, ROW, B_NODE_EXEC, "Soft noise", 0*w/2+x, 20+y, w/2, 19, &tex->noisetype, 12.0, (float)TEX_NOISESOFT, 0, 0, "Generates soft noise");
1703                         uiDefButS(block, ROW, B_NODE_EXEC, "Hard noise", 1*w/2+x, 20+y, w/2, 19, &tex->noisetype, 12.0, (float)TEX_NOISEPERL, 0, 0, "Generates hard noise");
1704                         
1705                         uiDefButS(block, ROW, B_NODE_EXEC, "Sin",        0*w/3+x,  0+y, w/3, 18, &tex->noisebasis2, 8.0, 0.0, 0, 0, "Uses a sine wave to produce bands."); 
1706                         uiDefButS(block, ROW, B_NODE_EXEC, "Saw",        1*w/3+x,  0+y, w/3, 18, &tex->noisebasis2, 8.0, 1.0, 0, 0, "Uses a saw wave to produce bands"); 
1707                         uiDefButS(block, ROW, B_NODE_EXEC, "Tri",        2*w/3+x,  0+y, w/3, 18, &tex->noisebasis2, 8.0, 2.0, 0, 0, "Uses a triangle wave to produce bands"); 
1708                 
1709                         uiBlockEndAlign(block);
1710                         break;
1711                         
1712                 case TEX_WOOD:
1713                         uiDefButS(block, MENU, B_TEXPRV, noisebasis_menu(), x, y+64, w, 18, &tex->noisebasis, 0,0,0,0, "Sets the noise basis used for turbulence");
1714                         
1715                         uiBlockBeginAlign(block);
1716                         uiDefButS(block, ROW, B_TEXPRV,             "Bands",     x,  40+y, w/2, 18, &tex->stype, 2.0, (float)TEX_BANDNOISE, 0, 0, "Uses standard noise"); 
1717                         uiDefButS(block, ROW, B_TEXPRV,             "Rings", w/2+x,  40+y, w/2, 18, &tex->stype, 2.0, (float)TEX_RINGNOISE, 0, 0, "Lets Noise return RGB value"); 
1718                         
1719                         uiDefButS(block, ROW, B_NODE_EXEC, "Sin", 0*w/3+x,  20+y, w/3, 18, &tex->noisebasis2, 8.0, (float)TEX_SIN, 0, 0, "Uses a sine wave to produce bands."); 
1720                         uiDefButS(block, ROW, B_NODE_EXEC, "Saw", 1*w/3+x,  20+y, w/3, 18, &tex->noisebasis2, 8.0, (float)TEX_SAW, 0, 0, "Uses a saw wave to produce bands"); 
1721                         uiDefButS(block, ROW, B_NODE_EXEC, "Tri", 2*w/3+x,  20+y, w/3, 18, &tex->noisebasis2, 8.0, (float)TEX_TRI, 0, 0, "Uses a triangle wave to produce bands");
1722                         
1723                         uiDefButS(block, ROW, B_NODE_EXEC, "Soft noise", 0*w/2+x, 0+y, w/2, 19, &tex->noisetype, 12.0, (float)TEX_NOISESOFT, 0, 0, "Generates soft noise");
1724                         uiDefButS(block, ROW, B_NODE_EXEC, "Hard noise", 1*w/2+x, 0+y, w/2, 19, &tex->noisetype, 12.0, (float)TEX_NOISEPERL, 0, 0, "Generates hard noise");
1725                         uiBlockEndAlign(block);
1726                         break;
1727                         
1728                 case TEX_CLOUDS:
1729                         uiDefButS(block, MENU, B_TEXPRV, noisebasis_menu(), x, y+60, w, 18, &tex->noisebasis, 0,0,0,0, "Sets the noise basis used for turbulence");
1730                         
1731                         uiBlockBeginAlign(block);
1732                         uiDefButS(block, ROW, B_TEXPRV, "B/W",       x, y+38, w/2, 18, &tex->stype, 2.0, (float)TEX_DEFAULT, 0, 0, "Uses standard noise"); 
1733                         uiDefButS(block, ROW, B_TEXPRV, "Color", w/2+x, y+38, w/2, 18, &tex->stype, 2.0, (float)TEX_COLOR, 0, 0, "Lets Noise return RGB value"); 
1734                         uiDefButS(block, ROW, B_TEXPRV, "Soft",      x, y+20, w/2, 18, &tex->noisetype, 12.0, (float)TEX_NOISESOFT, 0, 0, "Generates soft noise");
1735                         uiDefButS(block, ROW, B_TEXPRV, "Hard",  w/2+x, y+20, w/2, 18, &tex->noisetype, 12.0, (float)TEX_NOISEPERL, 0, 0, "Generates hard noise");
1736                         uiBlockEndAlign(block);
1737                         
1738                         uiDefButS(block, NUM, B_TEXPRV, "Depth:", x, y, w, 18, &tex->noisedepth, 0.0, 6.0, 0, 0, "Sets the depth of the cloud calculation");
1739                         break;
1740                         
1741                 case TEX_DISTNOISE:
1742                         uiBlockBeginAlign(block);
1743                         uiDefButS(block, MENU, B_TEXPRV, noisebasis_menu(), x, y+18, w, 18, &tex->noisebasis2, 0,0,0,0, "Sets the noise basis to distort");
1744                         uiDefButS(block, MENU, B_TEXPRV, noisebasis_menu(), x, y,    w, 18, &tex->noisebasis,  0,0,0,0, "Sets the noise basis which does the distortion");
1745                         uiBlockEndAlign(block);
1746                         break;
1747         }
1748 }
1749
1750 static void node_texture_buts_image(uiLayout *layout, PointerRNA *ptr)
1751 {
1752         uiBlock *block= uiLayoutAbsoluteBlock(layout);
1753         bNode *node= ptr->data;
1754         bNodeTree *ntree= ptr->id.data;
1755         rctf *butr= &node->butr;
1756         char *strp;
1757         uiBut *bt;
1758
1759         uiBlockBeginAlign(block);
1760         
1761         /* browse button */
1762         IMAnames_to_pupstring(&strp, NULL, "LOAD NEW %x32767", &(G.main->image), NULL, NULL);
1763         node->menunr= 0;
1764         bt= uiDefButS(block, MENU, B_NOP, strp, 
1765                                   butr->xmin, butr->ymin, 19, 19, 
1766                                   &node->menunr, 0, 0, 0, 0, "Browses existing choices");
1767         uiButSetFunc(bt, node_browse_image_cb, ntree, node);
1768         if(strp) MEM_freeN(strp);
1769         
1770         /* Add New button */
1771         if(node->id==NULL) {
1772                 bt= uiDefBut(block, BUT, B_NODE_LOADIMAGE, "Load New",
1773                                          butr->xmin+19, butr->ymin, (short)(butr->xmax-butr->xmin-19.0f), 19, 
1774                                          NULL, 0.0, 0.0, 0, 0, "Add new Image");
1775                 uiButSetFunc(bt, node_active_cb, ntree, node);
1776         }
1777         else {
1778                 /* name button */
1779                 short xmin= (short)butr->xmin, xmax= (short)butr->xmax;
1780                 short width= xmax - xmin - 19;
1781                 
1782                 bt= uiDefBut(block, TEX, B_NOP, "IM:",
1783                                          xmin+19, butr->ymin, width, 19, 
1784                                          node->id->name+2, 0.0, 19.0, 0, 0, "Image name");
1785                 uiButSetFunc(bt, node_ID_title_cb, node, NULL);
1786         }
1787 }
1788
1789 static void node_texture_buts_output(uiLayout *layout, PointerRNA *ptr)
1790 {
1791         uiItemR(layout, "", 0, ptr, "output_name", 0);
1792 }
1793
1794 /* only once called */
1795 static void node_texture_set_butfunc(bNodeType *ntype)
1796 {
1797         if( ntype->type >= TEX_NODE_PROC && ntype->type < TEX_NODE_PROC_MAX ) {
1798                 ntype->uifunc = node_texture_buts_proc;
1799         }
1800         else switch(ntype->type) {
1801                 
1802                 case TEX_NODE_MATH:
1803                         ntype->uifunc = node_buts_math;
1804                         break;
1805                 
1806                 case TEX_NODE_MIX_RGB:
1807                         ntype->uifunc = node_buts_mix_rgb;
1808                         break;
1809                         
1810                 case TEX_NODE_VALTORGB:
1811                         ntype->uifunc = node_buts_valtorgb;
1812                         break;
1813                         
1814                 case TEX_NODE_CURVE_RGB:
1815                         ntype->uifunc= node_buts_curvecol;
1816                         break;
1817                         
1818                 case TEX_NODE_CURVE_TIME:
1819                         ntype->uifunc = node_buts_time;
1820                         break;
1821                         
1822                 case TEX_NODE_TEXTURE:
1823                         ntype->uifunc = node_buts_texture;
1824                         break;
1825                         
1826                 case TEX_NODE_BRICKS:
1827                         ntype->uifunc = node_texture_buts_bricks;
1828                         break;
1829                         
1830                 case TEX_NODE_IMAGE:
1831                         ntype->uifunc = node_texture_buts_image;
1832                         break;
1833                         
1834                 case TEX_NODE_OUTPUT:
1835                         ntype->uifunc = node_texture_buts_output;
1836                         break;
1837                         
1838                 default:
1839                         ntype->uifunc= NULL;
1840         }
1841 }
1842
1843 /* ******* init draw callbacks for all tree types, only called in usiblender.c, once ************* */
1844
1845 void ED_init_node_butfuncs(void)
1846 {
1847         bNodeType *ntype;
1848         
1849         /* shader nodes */
1850         ntype= node_all_shaders.first;
1851         while(ntype) {
1852                 node_shader_set_butfunc(ntype);
1853                 ntype= ntype->next;
1854         }
1855         /* composit nodes */
1856         ntype= node_all_composit.first;
1857         while(ntype) {
1858                 node_composit_set_butfunc(ntype);
1859                 ntype= ntype->next;
1860         }
1861         ntype = node_all_textures.first;
1862         while(ntype) {
1863                 node_texture_set_butfunc(ntype);
1864                 ntype= ntype->next;
1865         }
1866 }
1867
1868 /* ************** Generic drawing ************** */
1869
1870 #if 0
1871 void node_rename_but(char *s)
1872 {
1873         uiBlock *block;
1874         ListBase listb={0, 0};
1875         int dy, x1, y1, sizex=80, sizey=30;
1876         short pivot[2], mval[2], ret=0;
1877         
1878         getmouseco_sc(mval);
1879
1880         pivot[0]= CLAMPIS(mval[0], (sizex+10), G.curscreen->sizex-30);
1881         pivot[1]= CLAMPIS(mval[1], (sizey/2)+10, G.curscreen->sizey-(sizey/2)-10);
1882         
1883         if (pivot[0]!=mval[0] || pivot[1]!=mval[1])
1884                 warp_pointer(pivot[0], pivot[1]);
1885
1886         mywinset(G.curscreen->mainwin);
1887         
1888         x1= pivot[0]-sizex+10;
1889         y1= pivot[1]-sizey/2;
1890         dy= sizey/2;
1891         
1892         block= uiNewBlock(&listb, "button", UI_EMBOSS, UI_HELV, G.curscreen->mainwin);
1893         uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_NUMSELECT|UI_BLOCK_ENTER_OK);
1894         
1895         /* buttons have 0 as return event, to prevent menu to close on hotkeys */
1896         uiBlockBeginAlign(block);
1897         
1898         uiDefBut(block, TEX, B_NOP, "Name: ", (short)(x1),(short)(y1+dy), 150, 19, s, 0.0, 19.0, 0, 0, "Node user name");
1899         
1900         uiBlockEndAlign(block);
1901
1902         uiDefBut(block, BUT, 32767, "OK", (short)(x1+150), (short)(y1+dy), 29, 19, NULL, 0, 0, 0, 0, "");
1903
1904         uiBoundsBlock(block, 2);
1905
1906         ret= uiDoBlocks(&listb, 0, 0);
1907 }
1908
1909 #endif
1910
1911 void draw_nodespace_back_pix(ARegion *ar, SpaceNode *snode, int color_manage)
1912 {
1913         
1914         if((snode->flag & SNODE_BACKDRAW) && snode->treetype==NTREE_COMPOSIT) {
1915                 Image *ima= BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
1916                 void *lock;
1917                 ImBuf *ibuf= BKE_image_acquire_ibuf(ima, NULL, &lock);
1918                 if(ibuf) {
1919                         float x, y; 
1920                         
1921                         wmPushMatrix();
1922                         
1923                         /* somehow the offset has to be calculated inverse */
1924                         
1925                         glaDefine2DArea(&ar->winrct);
1926                         /* ortho at pixel level curarea */
1927                         wmOrtho2(-0.375, ar->winx-0.375, -0.375, ar->winy-0.375);
1928                         
1929                         x = (ar->winx-ibuf->x)/2 + snode->xof;
1930                         y = (ar->winy-ibuf->y)/2 + snode->yof;
1931                         
1932                         if(!ibuf->rect) {
1933                                 if(color_manage)
1934                                         ibuf->profile= IB_PROFILE_SRGB;
1935                                 else
1936                                         ibuf->profile = IB_PROFILE_NONE;
1937                                 IMB_rect_from_float(ibuf);
1938                         }
1939
1940                         if(ibuf->rect)
1941                                 glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect);
1942                         
1943                         wmPopMatrix();
1944                 }
1945
1946                 BKE_image_release_ibuf(ima, lock);
1947         }
1948 }
1949
1950 #if 0
1951 /* note: needs to be userpref or opengl profile option */
1952 static void draw_nodespace_back_tex(ScrArea *sa, SpaceNode *snode)
1953 {
1954
1955         draw_nodespace_grid(snode);
1956         
1957         if(snode->flag & SNODE_BACKDRAW) {
1958                 Image *ima= BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
1959                 ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL);
1960                 if(ibuf) {
1961                         int x, y;
1962                         float zoom = 1.0;
1963
1964                         glMatrixMode(GL_PROJECTION);
1965                         glPushMatrix();
1966                         glMatrixMode(GL_MODELVIEW);
1967                         glPushMatrix();
1968                         
1969                         glaDefine2DArea(&sa->winrct);
1970
1971                         if(ibuf->x > sa->winx || ibuf->y > sa->winy) {
1972                                 float zoomx, zoomy;
1973                                 zoomx= (float)sa->winx/ibuf->x;
1974                                 zoomy= (float)sa->winy/ibuf->y;
1975                                 zoom = MIN2(zoomx, zoomy);
1976                         }
1977                         
1978                         x = (sa->winx-zoom*ibuf->x)/2 + snode->xof;
1979                         y = (sa->winy-zoom*ibuf->y)/2 + snode->yof;
1980
1981                         glPixelZoom(zoom, zoom);
1982
1983                         glColor4f(1.0, 1.0, 1.0, 1.0);
1984                         if(ibuf->rect)
1985                                 glaDrawPixelsTex(x, y, ibuf->x, ibuf->y, GL_UNSIGNED_BYTE, ibuf->rect);
1986                         else if(ibuf->channels==4)
1987                                 glaDrawPixelsTex(x, y, ibuf->x, ibuf->y, GL_FLOAT, ibuf->rect_float);
1988
1989                         glPixelZoom(1.0, 1.0);
1990
1991                         glMatrixMode(GL_PROJECTION);
1992                         glPopMatrix();
1993                         glMatrixMode(GL_MODELVIEW);
1994                         glPopMatrix();
1995                 }
1996         }
1997 }
1998 #endif
1999
2000 /* if v2d not NULL, it clips and returns 0 if not visible */
2001 int node_link_bezier_points(View2D *v2d, SpaceNode *snode, bNodeLink *link, float coord_array[][2], int resol)
2002 {
2003         float dist, vec[4][2];
2004         
2005         /* in v0 and v3 we put begin/end points */
2006         if(link->fromsock) {
2007                 vec[0][0]= link->fromsock->locx;
2008                 vec[0][1]= link->fromsock->locy;
2009         }
2010         else {
2011                 if(snode==NULL) return 0;
2012                 vec[0][0]= snode->mx;
2013                 vec[0][1]= snode->my;
2014         }
2015         if(link->tosock) {
2016                 vec[3][0]= link->tosock->locx;
2017                 vec[3][1]= link->tosock->locy;
2018         }
2019         else {
2020                 if(snode==NULL) return 0;
2021                 vec[3][0]= snode->mx;
2022                 vec[3][1]= snode->my;
2023         }
2024         
2025         dist= 0.5f*ABS(vec[0][0] - vec[3][0]);
2026         
2027         /* check direction later, for top sockets */
2028         vec[1][0]= vec[0][0]+dist;
2029         vec[1][1]= vec[0][1];
2030         
2031         vec[2][0]= vec[3][0]-dist;
2032         vec[2][1]= vec[3][1];
2033         
2034         if(v2d && MIN4(vec[0][0], vec[1][0], vec[2][0], vec[3][0]) > v2d->cur.xmax); /* clipped */      
2035         else if (v2d && MAX4(vec[0][0], vec[1][0], vec[2][0], vec[3][0]) < v2d->cur.xmin); /* clipped */
2036         else {
2037                 
2038                 /* always do all three, to prevent data hanging around */
2039                 forward_diff_bezier(vec[0][0], vec[1][0], vec[2][0], vec[3][0], coord_array[0], resol, sizeof(float)*2);
2040                 forward_diff_bezier(vec[0][1], vec[1][1], vec[2][1], vec[3][1], coord_array[0]+1, resol, sizeof(float)*2);
2041                 
2042                 return 1;
2043         }
2044         return 0;
2045 }
2046
2047 #define LINK_RESOL      24
2048 void node_draw_link_bezier(View2D *v2d, SpaceNode *snode, bNodeLink *link, int th_col1, int th_col2, int do_shaded)
2049 {
2050         float coord_array[LINK_RESOL+1][2];
2051         
2052         if(node_link_bezier_points(v2d, snode, link, coord_array, LINK_RESOL)) {
2053                 float dist, spline_step = 0.0f;
2054                 int i;
2055                 
2056                 /* we can reuse the dist variable here to increment the GL curve eval amount*/
2057                 dist = 1.0f/(float)LINK_RESOL;
2058                 
2059                 glBegin(GL_LINE_STRIP);
2060                 for(i=0; i<=LINK_RESOL; i++) {
2061                         if(do_shaded) {
2062                                 UI_ThemeColorBlend(th_col1, th_col2, spline_step);
2063                                 spline_step += dist;
2064                         }                               
2065                         glVertex2fv(coord_array[i]);
2066                 }
2067                 glEnd();
2068         }
2069 }
2070
2071 /* note; this is used for fake links in groups too */
2072 void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link)
2073 {
2074         int do_shaded= 1, th_col1= TH_WIRE, th_col2= TH_WIRE;
2075         
2076         if(link->fromnode==NULL && link->tonode==NULL)
2077                 return;
2078         
2079         if(link->fromnode==NULL || link->tonode==NULL) {
2080                 UI_ThemeColor(TH_WIRE);
2081                 do_shaded= 0;
2082         }
2083         else {
2084                 /* going to give issues once... */
2085                 if(link->tosock->flag & SOCK_UNAVAIL)
2086                         return;
2087                 if(link->fromsock->flag & SOCK_UNAVAIL)
2088                         return;
2089                 
2090                 /* a bit ugly... but thats how we detect the internal group links */
2091                 if(link->fromnode==link->tonode) {
2092                         UI_ThemeColorBlend(TH_BACK, TH_WIRE, 0.25f);
2093                         do_shaded= 0;
2094                 }
2095                 else {
2096                         /* check cyclic */
2097                         if(link->fromnode->level >= link->tonode->level && link->tonode->level!=0xFFF) {
2098                                 if(link->fromnode->flag & SELECT)
2099                                         th_col1= TH_EDGE_SELECT;
2100                                 if(link->tonode->flag & SELECT)
2101                                         th_col2= TH_EDGE_SELECT;
2102                         }                               
2103                         else {
2104                                 UI_ThemeColor(TH_REDALERT);
2105                                 do_shaded= 0;
2106                         }
2107                 }
2108         }
2109         
2110         node_draw_link_bezier(v2d, snode, link, th_col1, th_col2, do_shaded);
2111 }
2112
2113