2.5 - node editor
[blender-staging.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
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_global.h"
56 #include "BKE_image.h"
57 #include "BKE_library.h"
58 #include "BKE_main.h"
59 #include "BKE_material.h"
60 #include "BKE_node.h"
61 #include "BKE_object.h"
62 #include "BKE_texture.h"
63 #include "BKE_text.h"
64 #include "BKE_utildefines.h"
65
66 #include "CMP_node.h"
67 #include "SHD_node.h"
68
69 /* #include "BDR_gpencil.h" XXX */
70
71 #include "BIF_gl.h"
72 #include "BIF_glutil.h"
73 /*
74 #include "BIF_drawgpencil.h"
75 #include "BIF_interface.h"
76 #include "BIF_interface_icons.h"
77 #include "BIF_language.h"
78 #include "BIF_mywindow.h"
79 #include "BIF_previewrender.h"
80 #include "BIF_resources.h"
81 #include "BIF_screen.h"
82 #include "BIF_space.h"
83 */
84
85 /* XXX
86 #include "BSE_drawipo.h"
87 #include "BSE_node.h"
88 #include "BSE_view.h"
89 */
90
91
92 #include "BMF_Api.h"
93
94 #include "MEM_guardedalloc.h"
95
96 #include "UI_text.h"
97 #include "UI_interface.h"
98 #include "UI_resources.h"
99
100 /*
101 #include "RE_pipeline.h"
102 #include "IMB_imbuf_types.h"*/
103
104 /*#include "blendef.h"
105 #include "butspace.h"*/
106 /*#include "interface.h"*/      /* urm...  for rasterpos_safe, roundbox */
107 /*#include "mydevice.h"*/
108 #if 0
109 //extern void autocomplete_uv(char *str, void *arg_v);
110 extern int verify_valid_uv_name(char *str);
111
112 /* autocomplete callback for buttons */
113 static void autocomplete_vcol(char *str, void *arg_v)
114 {
115         Mesh *me;
116         CustomDataLayer *layer;
117         AutoComplete *autocpl;
118         int a;
119
120         if(str[0]==0)
121                 return;
122
123         autocpl= autocomplete_begin(str, 32);
124                 
125         /* search if str matches the beginning of name */
126         for(me= G.main->mesh.first; me; me=me->id.next)
127                 for(a=0, layer= me->fdata.layers; a<me->fdata.totlayer; a++, layer++)
128                         if(layer->type == CD_MCOL)
129                                 autocomplete_do_name(autocpl, layer->name);
130         
131         autocomplete_end(autocpl, str);
132 }
133
134 static int verify_valid_vcol_name(char *str)
135 {
136         Mesh *me;
137         CustomDataLayer *layer;
138         int a;
139         
140         if(str[0]==0)
141                 return 1;
142
143         /* search if str matches the name */
144         for(me= G.main->mesh.first; me; me=me->id.next)
145                 for(a=0, layer= me->fdata.layers; a<me->fdata.totlayer; a++, layer++)
146                         if(layer->type == CD_MCOL)
147                                 if(strcmp(layer->name, str)==0)
148                                         return 1;
149         
150         return 0;
151 }
152
153 static void snode_drawstring(SpaceNode *snode, char *str, int okwidth)
154 {
155         char drawstr[NODE_MAXSTR];
156         int width;
157         
158         if(str[0]==0 || okwidth<4) return;
159         
160         BLI_strncpy(drawstr, str, NODE_MAXSTR);
161         width= snode->aspect*UI_GetStringWidth(snode->curfont, drawstr, 0);
162
163         if(width > okwidth) {
164                 int len= strlen(drawstr)-1;
165                 
166                 while(width > okwidth && len>=0) {
167                         drawstr[len]= 0;
168                         
169                         width= snode->aspect*UI_GetStringWidth(snode->curfont, drawstr, 0);
170                         len--;
171                 }
172                 if(len==0) return;
173         }
174         UI_DrawString(snode->curfont, drawstr, 0);
175
176 }
177
178 /* ****************** GENERAL CALLBACKS FOR NODES ***************** */
179
180 static void node_ID_title_cb(void *node_v, void *unused_v)
181 {
182         bNode *node= node_v;
183         
184         if(node->id) {
185                 test_idbutton(node->id->name+2);        /* library.c, verifies unique name */
186                 BLI_strncpy(node->name, node->id->name+2, 21);
187                 
188                 // allqueue(REDRAWBUTSSHADING, 0);
189                 // allqueue(REDRAWNODE, 0);
190                 // allqueue(REDRAWOOPS, 0);
191         }
192 }
193
194
195 static void node_but_title_cb(void *node_v, void *but_v)
196 {
197         bNode *node= node_v;
198         struct uiBut *bt= but_v;
199         BLI_strncpy(node->name, bt->drawstr, NODE_MAXSTR);
200         
201         // allqueue(REDRAWNODE, 0);
202 }
203
204 static void node_group_alone_cb(void *node_v, void *unused_v)
205 {
206         bNode *node= node_v;
207         
208         nodeCopyGroup(node);
209
210         // allqueue(REDRAWNODE, 0);
211 }
212
213 /* ****************** BUTTON CALLBACKS FOR ALL TREES ***************** */
214
215 static int node_buts_group(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
216 {
217         if(block && node->id) {
218                 uiBut *bt;
219                 short width;
220                 
221                 uiBlockBeginAlign(block);
222                 
223                 /* name button */
224                 width= (short)(butr->xmax-butr->xmin - (node->id->us>1?19.0f:0.0f));
225                 bt= uiDefBut(block, TEX, B_NOP, "NT:",
226                                          butr->xmin, butr->ymin, width, 19, 
227                                          node->id->name+2, 0.0, 19.0, 0, 0, "NodeTree name");
228                 uiButSetFunc(bt, node_ID_title_cb, node, NULL);
229                 
230                 /* user amount */
231                 if(node->id->us>1) {
232                         char str1[32];
233                         sprintf(str1, "%d", node->id->us);
234                         bt= uiDefBut(block, BUT, B_NOP, str1, 
235                                                  butr->xmax-19, butr->ymin, 19, 19, 
236                                                  NULL, 0, 0, 0, 0, "Displays number of users.");
237                         uiButSetFunc(bt, node_group_alone_cb, node, NULL);
238                 }
239                 
240                 uiBlockEndAlign(block);
241         }       
242         return 19;
243 }
244
245 static int node_buts_value(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
246 {
247         if(block) {
248                 bNodeSocket *sock= node->outputs.first;         /* first socket stores value */
249                 
250                 uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "", 
251                                   butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20, 
252                                   sock->ns.vec, sock->ns.min, sock->ns.max, 10, 2, "");
253                 
254         }
255         return 20;
256 }
257
258 static int node_buts_rgb(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
259 {
260         if(block) {
261                 bNodeSocket *sock= node->outputs.first;         /* first socket stores value */
262                 if(sock) {
263                         /* enforce square box drawing */
264                         uiBlockSetEmboss(block, UI_EMBOSSP);
265                         
266                         uiDefButF(block, HSVCUBE, B_NODE_EXEC+node->nr, "", 
267                                           butr->xmin, butr->ymin, butr->xmax-butr->xmin, 12, 
268                                           sock->ns.vec, 0.0f, 1.0f, 3, 0, "");
269                         uiDefButF(block, HSVCUBE, B_NODE_EXEC+node->nr, "", 
270                                           butr->xmin, butr->ymin+15, butr->xmax-butr->xmin, butr->ymax-butr->ymin -15 -15, 
271                                           sock->ns.vec, 0.0f, 1.0f, 2, 0, "");
272                         uiDefButF(block, COL, B_NOP, "",                
273                                           butr->xmin, butr->ymax-12, butr->xmax-butr->xmin, 12, 
274                                           sock->ns.vec, 0.0, 0.0, -1, 0, "");
275                         /* the -1 above prevents col button to popup a color picker */
276                         
277                         uiBlockSetEmboss(block, UI_EMBOSS);
278                 }
279         }
280         return 30 + (int)(node->width-NODE_DY);
281 }
282
283 static int node_buts_mix_rgb(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
284 {
285         if(block) {
286                 uiBut *bt;
287                 int a_but= (ntree->type==NTREE_COMPOSIT);
288                 
289                 /* blend type */
290                 uiBlockBeginAlign(block);
291                 bt=uiDefButS(block, MENU, B_NODE_EXEC+node->nr, "Mix %x0|Add %x1|Subtract %x3|Multiply %x2|Screen %x4|Overlay %x9|Divide %x5|Difference %x6|Darken %x7|Lighten %x8|Dodge %x10|Burn %x11|Color %x15|Value %x14|Saturation %x13|Hue %x12",
292                                          butr->xmin, butr->ymin, butr->xmax-butr->xmin -(a_but?20:0), 20, 
293                                          &node->custom1, 0, 0, 0, 0, "");
294                 uiButSetFunc(bt, node_but_title_cb, node, bt);
295                 /* Alpha option, composite */
296                 if(a_but)
297                         uiDefButS(block, TOG, B_NODE_EXEC+node->nr, "A",
298                                   butr->xmax-20, butr->ymin, 20, 20, 
299                                   &node->custom2, 0, 0, 0, 0, "Include Alpha of 2nd input in this operation");
300         }
301         return 20;
302 }
303
304 static int node_buts_time(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
305 {
306         if(block) {
307                 CurveMapping *cumap= node->storage;
308                 short dx= (short)((butr->xmax-butr->xmin)/2);
309                 butr->ymin += 26;
310
311                 curvemap_buttons(block, node->storage, 's', B_NODE_EXEC+node->nr, B_REDR, butr);
312                 
313                 if(cumap) {
314                         cumap->flag |= CUMA_DRAW_CFRA;
315                         if(node->custom1<node->custom2)
316                                 cumap->sample[0]= (float)(CFRA - node->custom1)/(float)(node->custom2-node->custom1);
317                 }
318
319                 uiBlockBeginAlign(block);
320                 uiDefButS(block, NUM, B_NODE_EXEC+node->nr, "Sta:",
321                                   butr->xmin, butr->ymin-22, dx, 19, 
322                                   &node->custom1, 1.0, 20000.0, 0, 0, "Start frame");
323                 uiDefButS(block, NUM, B_NODE_EXEC+node->nr, "End:",
324                                   butr->xmin+dx, butr->ymin-22, dx, 19, 
325                                   &node->custom2, 1.0, 20000.0, 0, 0, "End frame");
326         }
327         
328         return node->width-NODE_DY;
329 }
330
331 static int node_buts_valtorgb(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
332 {
333         if(block) {
334                 if(node->storage) {
335                         draw_colorband_buts_small(block, node->storage, butr, B_NODE_EXEC+node->nr);
336                 }
337         }
338         return 40;
339 }
340
341 static int node_buts_curvevec(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
342 {
343         if(block) {
344                 curvemap_buttons(block, node->storage, 'v', B_NODE_EXEC+node->nr, B_REDR, butr);
345         }       
346         return (int)(node->width-NODE_DY);
347 }
348
349 static float *_sample_col= NULL;        // bad bad, 2.5 will do better?
350 void node_curvemap_sample(float *col)
351 {
352         _sample_col= col;
353 }
354
355 static int node_buts_curvecol(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
356 {
357         if(block) {
358                 CurveMapping *cumap= node->storage;
359                 if(_sample_col) {
360                         cumap->flag |= CUMA_DRAW_SAMPLE;
361                         VECCOPY(cumap->sample, _sample_col);
362                 }
363                 else 
364                         cumap->flag &= ~CUMA_DRAW_SAMPLE;
365
366                 curvemap_buttons(block, node->storage, 'c', B_NODE_EXEC+node->nr, B_REDR, butr);
367         }       
368         return (int)(node->width-NODE_DY);
369 }
370
371 static int node_buts_normal(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
372 {
373         if(block) {
374                 bNodeSocket *sock= node->outputs.first;         /* first socket stores normal */
375                 
376                 uiDefButF(block, BUT_NORMAL, B_NODE_EXEC+node->nr, "", 
377                                   butr->xmin, butr->ymin, butr->xmax-butr->xmin, butr->ymax-butr->ymin, 
378                                   sock->ns.vec, 0.0f, 1.0f, 0, 0, "");
379                 
380         }       
381         return (int)(node->width-NODE_DY);
382 }
383
384 static void node_browse_tex_cb(void *ntree_v, void *node_v)
385 {
386         bNodeTree *ntree= ntree_v;
387         bNode *node= node_v;
388         Tex *tex;
389         
390         if(node->menunr<1) return;
391         
392         if(node->id) {
393                 node->id->us--;
394                 node->id= NULL;
395         }
396         tex= BLI_findlink(&G.main->tex, node->menunr-1);
397
398         node->id= &tex->id;
399         id_us_plus(node->id);
400         BLI_strncpy(node->name, node->id->name+2, 21);
401         
402         nodeSetActive(ntree, node);
403         
404         if( ntree->type == NTREE_TEXTURE )
405                 ntreeTexCheckCyclics( ntree );
406         
407         // allqueue(REDRAWBUTSSHADING, 0);
408         // allqueue(REDRAWNODE, 0);
409         NodeTagChanged(ntree, node); 
410         
411         node->menunr= 0;
412 }
413
414 static void node_dynamic_update_cb(void *ntree_v, void *node_v)
415 {
416         Material *ma;
417         bNode *node= (bNode *)node_v;
418         ID *id= node->id;
419         int error= 0;
420
421         if (BTST(node->custom1, NODE_DYNAMIC_ERROR)) error= 1;
422
423         /* Users only have to press the "update" button in one pynode
424          * and we also update all others sharing the same script */
425         for (ma= G.main->mat.first; ma; ma= ma->id.next) {
426                 if (ma->nodetree) {
427                         bNode *nd;
428                         for (nd= ma->nodetree->nodes.first; nd; nd= nd->next) {
429                                 if ((nd->type == NODE_DYNAMIC) && (nd->id == id)) {
430                                         nd->custom1= 0;
431                                         nd->custom1= BSET(nd->custom1, NODE_DYNAMIC_REPARSE);
432                                         nd->menunr= 0;
433                                         if (error)
434                                                 nd->custom1= BSET(nd->custom1, NODE_DYNAMIC_ERROR);
435                                 }
436                         }
437                 }
438         }
439
440         // allqueue(REDRAWBUTSSHADING, 0);
441         // allqueue(REDRAWNODE, 0);
442         BIF_preview_changed(ID_MA);
443 }
444
445 static int node_buts_texture(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
446 {
447         short multi = (
448                 node->id &&
449                 ((Tex*)node->id)->use_nodes &&
450                 (node->type != CMP_NODE_TEXTURE) &&
451                 (node->type != TEX_NODE_TEXTURE)
452         );
453         
454         if(block) {
455                 uiBut *bt;
456                 char *strp;
457                 short width = (short)(butr->xmax - butr->xmin);
458                 
459                 /* browse button texture */
460                 uiBlockBeginAlign(block);
461                 IDnames_to_pupstring(&strp, NULL, "", &(G.main->tex), NULL, NULL);
462                 node->menunr= 0;
463                 bt= uiDefButS(block, MENU, B_NODE_EXEC+node->nr, strp, 
464                                 butr->xmin, butr->ymin+(multi?30:0), 20, 19, 
465                                           &node->menunr, 0, 0, 0, 0, "Browse texture");
466                 uiButSetFunc(bt, node_browse_tex_cb, ntree, node);
467                 if(strp) MEM_freeN(strp);
468                 
469                 if(node->id) {
470                         bt= uiDefBut(block, TEX, B_NOP, "TE:",
471                                         butr->xmin+19, butr->ymin+(multi?30:0), butr->xmax-butr->xmin-19, 19, 
472                                                  node->id->name+2, 0.0, 19.0, 0, 0, "Texture name");
473                         uiButSetFunc(bt, node_ID_title_cb, node, NULL);
474                 }
475                 uiBlockEndAlign(block);
476                 
477                 if(multi) {
478                         char *menustr = ntreeTexOutputMenu(((Tex*)node->id)->nodetree);
479                         uiDefButS(block, MENU, B_MATPRV, menustr, butr->xmin, butr->ymin, width, 19, &node->custom1, 0, 0, 0, 0, "Which output to use, for multi-output textures");
480                         free(menustr);
481                         return 50;
482                 }
483                 return 20;
484         }       
485         else return multi? 50: 20;
486 }
487
488 static int node_buts_math(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) 
489
490         if(block) { 
491                 uiBut *bt; 
492
493                 bt=uiDefButS(block, MENU, B_NODE_EXEC,  "Add %x0|Subtract %x1|Multiply %x2|Divide %x3|Sine %x4|Cosine %x5|Tangent %x6|Arcsine %x7|Arccosine %x8|Arctangent %x9|Power %x10|Logarithm %x11|Minimum %x12|Maximum %x13|Round %x14|Less Than %x15|Greater Than %x16", butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20, &node->custom1, 0, 0, 0, 0, ""); 
494                 uiButSetFunc(bt, node_but_title_cb, node, bt); 
495         } 
496         return 20; 
497 }
498
499
500 /* ****************** BUTTON CALLBACKS FOR SHADER NODES ***************** */
501
502 static void node_browse_text_cb(void *ntree_v, void *node_v)
503 {
504         bNodeTree *ntree= ntree_v;
505         bNode *node= node_v;
506         ID *oldid;
507         
508         if(node->menunr<1) return;
509         
510         if(node->id) {
511                 node->id->us--;
512         }
513         oldid= node->id;
514         node->id= BLI_findlink(&G.main->text, node->menunr-1);
515         id_us_plus(node->id);
516         BLI_strncpy(node->name, node->id->name+2, 21); /* huh? why 21? */
517
518         node->custom1= BSET(node->custom1, NODE_DYNAMIC_NEW);
519         
520         nodeSetActive(ntree, node);
521
522         // allqueue(REDRAWBUTSSHADING, 0);
523         // allqueue(REDRAWNODE, 0);
524
525         node->menunr= 0;
526 }
527
528 static void node_mat_alone_cb(void *node_v, void *unused)
529 {
530         bNode *node= node_v;
531         
532         node->id= (ID *)copy_material((Material *)node->id);
533         
534         //BIF_undo_push("Single user material");
535         // allqueue(REDRAWBUTSSHADING, 0);
536         // allqueue(REDRAWNODE, 0);
537         // allqueue(REDRAWOOPS, 0);
538 }
539
540 static void node_browse_mat_cb(void *ntree_v, void *node_v)
541 {
542         bNodeTree *ntree= ntree_v;
543         bNode *node= node_v;
544         
545         if(node->menunr<1) return;
546         
547         if(node->menunr==32767) {       /* code for Add New */
548                 if(node->id) {
549                         /* make copy, but make sure it doesnt have the node tag nor nodes */
550                         Material *ma= (Material *)node->id;
551                         ma->id.us--;
552                         ma= copy_material(ma);
553                         ma->use_nodes= 0;
554                         if(ma->nodetree) {
555                                 ntreeFreeTree(ma->nodetree);
556                                 MEM_freeN(ma->nodetree);
557                         }
558                         ma->nodetree= NULL;
559                         node->id= (ID *)ma;
560                 }
561                 else node->id= (ID *)add_material("MatNode");
562         }
563         else {
564                 if(node->id) node->id->us--;
565                 node->id= BLI_findlink(&G.main->mat, node->menunr-1);
566                 id_us_plus(node->id);
567         }
568         BLI_strncpy(node->name, node->id->name+2, 21);
569         
570         nodeSetActive(ntree, node);
571
572         // allqueue(REDRAWBUTSSHADING, 0);
573         // allqueue(REDRAWNODE, 0);
574         BIF_preview_changed(ID_MA);
575
576         node->menunr= 0;
577 }
578
579 static void node_new_mat_cb(void *ntree_v, void *node_v)
580 {
581         bNodeTree *ntree= ntree_v;
582         bNode *node= node_v;
583         
584         node->id= (ID *)add_material("MatNode");
585         BLI_strncpy(node->name, node->id->name+2, 21);
586
587         nodeSetActive(ntree, node);
588
589         // allqueue(REDRAWBUTSSHADING, 0);
590         // allqueue(REDRAWNODE, 0);
591         BIF_preview_changed(ID_MA);
592
593 }
594
595 static void node_texmap_cb(void *texmap_v, void *unused_v)
596 {
597         init_mapping(texmap_v);
598 }
599
600 static int node_shader_buts_material(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
601 {
602         if(block) {
603                 uiBut *bt;
604                 short dx= (short)((butr->xmax-butr->xmin)/3.0f), has_us= (node->id && node->id->us>1);
605                 short dy= (short)butr->ymin;
606                 char *strp;
607                 
608                 /* WATCH IT: we use this callback in material buttons, but then only want first row */
609                 if(butr->ymax-butr->ymin > 21.0f) dy+= 19;
610                 
611                 uiBlockBeginAlign(block);
612                 if(node->id==NULL) uiBlockSetCol(block, TH_REDALERT);
613                 else if(has_us) uiBlockSetCol(block, TH_BUT_SETTING1);
614                 else uiBlockSetCol(block, TH_BUT_SETTING2);
615                 
616                 /* browse button */
617                 IDnames_to_pupstring(&strp, NULL, "ADD NEW %x32767", &(G.main->mat), NULL, NULL);
618                 node->menunr= 0;
619                 bt= uiDefButS(block, MENU, B_NOP, strp, 
620                                   butr->xmin, dy, 19, 19, 
621                                   &node->menunr, 0, 0, 0, 0, "Browses existing choices or adds NEW");
622                 uiButSetFunc(bt, node_browse_mat_cb, ntree, node);
623                 if(strp) MEM_freeN(strp);
624                 
625                 /* Add New button */
626                 if(node->id==NULL) {
627                         bt= uiDefBut(block, BUT, B_NOP, "Add New",
628                                                  butr->xmin+19, dy, (short)(butr->xmax-butr->xmin-19.0f), 19, 
629                                                  NULL, 0.0, 0.0, 0, 0, "Add new Material");
630                         uiButSetFunc(bt, node_new_mat_cb, ntree, node);
631                         uiBlockSetCol(block, TH_AUTO);
632                 }
633                 else {
634                         /* name button */
635                         short width= (short)(butr->xmax-butr->xmin-19.0f - (has_us?19.0f:0.0f));
636                         bt= uiDefBut(block, TEX, B_NOP, "MA:",
637                                                   butr->xmin+19, dy, width, 19, 
638                                                   node->id->name+2, 0.0, 19.0, 0, 0, "Material name");
639                         uiButSetFunc(bt, node_ID_title_cb, node, NULL);
640                         
641                         /* user amount */
642                         if(has_us) {
643                                 char str1[32];
644                                 sprintf(str1, "%d", node->id->us);
645                                 bt= uiDefBut(block, BUT, B_NOP, str1, 
646                                                           butr->xmax-19, dy, 19, 19, 
647                                                           NULL, 0, 0, 0, 0, "Displays number of users. Click to make a single-user copy.");
648                                 uiButSetFunc(bt, node_mat_alone_cb, node, NULL);
649                         }
650                         
651                         /* WATCH IT: we use this callback in material buttons, but then only want first row */
652                         if(butr->ymax-butr->ymin > 21.0f) {
653                                 /* node options */
654                                 uiBlockSetCol(block, TH_AUTO);
655                                 uiDefButBitS(block, TOG, SH_NODE_MAT_DIFF, B_NODE_EXEC+node->nr, "Diff",
656                                                          butr->xmin, butr->ymin, dx, 19, 
657                                                          &node->custom1, 0, 0, 0, 0, "Material Node outputs Diffuse");
658                                 uiDefButBitS(block, TOG, SH_NODE_MAT_SPEC, B_NODE_EXEC+node->nr, "Spec",
659                                                          butr->xmin+dx, butr->ymin, dx, 19, 
660                                                          &node->custom1, 0, 0, 0, 0, "Material Node outputs Specular");
661                                 uiDefButBitS(block, TOG, SH_NODE_MAT_NEG, B_NODE_EXEC+node->nr, "Neg Normal",
662                                                          butr->xmax-dx, butr->ymin, dx, 19,
663                                                          &node->custom1, 0, 0, 0, 0, "Material Node uses inverted Normal");
664                         }
665                 }
666                 uiBlockEndAlign(block);
667         }       
668         return 38;
669 }
670
671 static int node_shader_buts_mapping(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
672 {
673         if(block) {
674                 TexMapping *texmap= node->storage;
675                 short dx= (short)((butr->xmax-butr->xmin)/7.0f);
676                 short dy= (short)(butr->ymax-19);
677                 
678                 uiBlockSetFunc(block, node_texmap_cb, texmap, NULL);    /* all buttons get this */
679                 
680                 uiBlockBeginAlign(block);
681                 uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "", butr->xmin+dx, dy, 2*dx, 19, texmap->loc, -1000.0f, 1000.0f, 10, 2, "");
682                 uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "", butr->xmin+3*dx, dy, 2*dx, 19, texmap->loc+1, -1000.0f, 1000.0f, 10, 2, "");
683                 uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "", butr->xmin+5*dx, dy, 2*dx, 19, texmap->loc+2, -1000.0f, 1000.0f, 10, 2, "");
684                 dy-= 19;
685                 uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "", butr->xmin+dx, dy, 2*dx, 19, texmap->rot, -1000.0f, 1000.0f, 1000, 1, "");
686                 uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "", butr->xmin+3*dx, dy, 2*dx, 19, texmap->rot+1, -1000.0f, 1000.0f, 1000, 1, "");
687                 uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "", butr->xmin+5*dx, dy, 2*dx, 19, texmap->rot+2, -1000.0f, 1000.0f, 1000, 1, "");
688                 dy-= 19;
689                 uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "", butr->xmin+dx, dy, 2*dx, 19, texmap->size, -1000.0f, 1000.0f, 10, 2, "");
690                 uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "", butr->xmin+3*dx, dy, 2*dx, 19, texmap->size+1, -1000.0f, 1000.0f, 10, 2, "");
691                 uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "", butr->xmin+5*dx, dy, 2*dx, 19, texmap->size+2, -1000.0f, 1000.0f, 10, 2, "");
692                 dy-= 25;
693                 uiBlockBeginAlign(block);
694                 uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "", butr->xmin+dx, dy, 2*dx, 19, texmap->min, -10.0f, 10.0f, 100, 2, "");
695                 uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "", butr->xmin+3*dx, dy, 2*dx, 19, texmap->min+1, -10.0f, 10.0f, 100, 2, "");
696                 uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "", butr->xmin+5*dx, dy, 2*dx, 19, texmap->min+2, -10.0f, 10.0f, 100, 2, "");
697                 dy-= 19;
698                 uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "", butr->xmin+dx, dy, 2*dx, 19, texmap->max, -10.0f, 10.0f, 10, 2, "");
699                 uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "", butr->xmin+3*dx, dy, 2*dx, 19, texmap->max+1, -10.0f, 10.0f, 10, 2, "");
700                 uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "", butr->xmin+5*dx, dy, 2*dx, 19, texmap->max+2, -10.0f, 10.0f, 10, 2, "");
701                 uiBlockEndAlign(block);
702                 
703                 /* labels/options */
704                 
705                 dy= (short)(butr->ymax-19);
706                 uiDefBut(block, LABEL, B_NOP, "Loc", butr->xmin, dy, dx, 19, NULL, 0.0f, 0.0f, 0, 0, "");
707                 dy-= 19;
708                 uiDefBut(block, LABEL, B_NOP, "Rot", butr->xmin, dy, dx, 19, NULL, 0.0f, 0.0f, 0, 0, "");
709                 dy-= 19;
710                 uiDefBut(block, LABEL, B_NOP, "Size", butr->xmin, dy, dx, 19, NULL, 0.0f, 0.0f, 0, 0, "");
711                 dy-= 25;
712                 uiDefButBitI(block, TOG, TEXMAP_CLIP_MIN, B_NODE_EXEC+node->nr, "Min", butr->xmin, dy, dx-4, 19, &texmap->flag, 0.0f, 0.0f, 0, 0, "");
713                 dy-= 19;
714                 uiDefButBitI(block, TOG, TEXMAP_CLIP_MAX, B_NODE_EXEC+node->nr, "Max", butr->xmin, dy, dx-4, 19, &texmap->flag, 0.0f, 0.0f, 0, 0, "");
715                 
716         }       
717         return 5*19 + 6;
718 }
719
720 static int node_shader_buts_vect_math(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) 
721
722         if(block) { 
723                 uiBut *bt; 
724         
725                 bt=uiDefButS(block, MENU, B_NODE_EXEC,  "Add %x0|Subtract %x1|Average %x2|Dot Product %x3 |Cross Product %x4|Normalize %x5", butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20, &node->custom1, 0, 0, 0, 0, ""); 
726                 uiButSetFunc(bt, node_but_title_cb, node, bt); 
727         } 
728         return 20; 
729 }
730
731 static int node_shader_buts_geometry(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
732 {
733         if(block) {
734                 uiBut *but;
735                 NodeGeometry *ngeo= (NodeGeometry*)node->storage;
736
737                 if(!verify_valid_uv_name(ngeo->uvname))
738                         uiBlockSetCol(block, TH_REDALERT);
739                 but= uiDefBut(block, TEX, B_NODE_EXEC+node->nr, "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");
740                 // uiButSetCompleteFunc(but, autocomplete_uv, NULL);
741                 uiBlockSetCol(block, TH_AUTO);
742
743                 if(!verify_valid_vcol_name(ngeo->colname))
744                         uiBlockSetCol(block, TH_REDALERT);
745                 but= uiDefBut(block, TEX, B_NODE_EXEC+node->nr, "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");
746                 uiButSetCompleteFunc(but, autocomplete_vcol, NULL);
747                 uiBlockSetCol(block, TH_AUTO);
748         }
749
750         return 40;
751 }
752
753 static int node_shader_buts_dynamic(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) 
754
755         if (block) { 
756                 uiBut *bt;
757                 SpaceNode *snode= curarea->spacedata.first;
758                 short dy= (short)butr->ymin;
759                 int xoff=0;
760
761                 /* B_NODE_EXEC is handled in butspace.c do_node_buts */
762                 if(!node->id) {
763                                 char *strp;
764                                 IDnames_to_pupstring(&strp, NULL, "", &(G.main->text), NULL, NULL);
765                                 node->menunr= 0;
766                                 bt= uiDefButS(block, MENU, B_NODE_EXEC/*+node->nr*/, strp, 
767                                                                 butr->xmin, dy, 19, 19, 
768                                                                 &node->menunr, 0, 0, 0, 0, "Browses existing choices");
769                                 uiButSetFunc(bt, node_browse_text_cb, ntree, node);
770                                 xoff=19;
771                                 if(strp) MEM_freeN(strp);       
772                 }
773                 else {
774                         bt = uiDefBut(block, BUT, B_NOP, "Update",
775                                         butr->xmin+xoff, butr->ymin+20, 50, 19,
776                                         &node->menunr, 0.0, 19.0, 0, 0, "Refresh this node (and all others that use the same script)");
777                         uiButSetFunc(bt, node_dynamic_update_cb, ntree, node);
778
779                         if (BTST(node->custom1, NODE_DYNAMIC_ERROR)) {
780                                 UI_ThemeColor(TH_REDALERT);
781                                 ui_rasterpos_safe(butr->xmin + xoff, butr->ymin + 5, snode->aspect);
782                                 snode_drawstring(snode, "Error! Check console...", butr->xmax - butr->xmin);
783                         }
784                 }
785         }
786         return 20+19; 
787 }
788
789 /* only once called */
790 static void node_shader_set_butfunc(bNodeType *ntype)
791 {
792         switch(ntype->type) {
793                 /* case NODE_GROUP:      note, typeinfo for group is generated... see "XXX ugly hack" */
794
795                 case SH_NODE_MATERIAL:
796                 case SH_NODE_MATERIAL_EXT:
797                         ntype->butfunc= node_shader_buts_material;
798                         break;
799                 case SH_NODE_TEXTURE:
800                         ntype->butfunc= node_buts_texture;
801                         break;
802                 case SH_NODE_NORMAL:
803                         ntype->butfunc= node_buts_normal;
804                         break;
805                 case SH_NODE_CURVE_VEC:
806                         ntype->butfunc= node_buts_curvevec;
807                         break;
808                 case SH_NODE_CURVE_RGB:
809                         ntype->butfunc= node_buts_curvecol;
810                         break;
811                 case SH_NODE_MAPPING:
812                         ntype->butfunc= node_shader_buts_mapping;
813                         break;
814                 case SH_NODE_VALUE:
815                         ntype->butfunc= node_buts_value;
816                         break;
817                 case SH_NODE_RGB:
818                         ntype->butfunc= node_buts_rgb;
819                         break;
820                 case SH_NODE_MIX_RGB:
821                         ntype->butfunc= node_buts_mix_rgb;
822                         break;
823                 case SH_NODE_VALTORGB:
824                         ntype->butfunc= node_buts_valtorgb;
825                         break;
826                 case SH_NODE_MATH: 
827                         ntype->butfunc= node_buts_math;
828                         break; 
829                 case SH_NODE_VECT_MATH: 
830                         ntype->butfunc= node_shader_buts_vect_math;
831                         break; 
832                 case SH_NODE_GEOMETRY:
833                         ntype->butfunc= node_shader_buts_geometry;
834                         break;
835                 case NODE_DYNAMIC:
836                         ntype->butfunc= node_shader_buts_dynamic;
837                         break;
838                 default:
839                         ntype->butfunc= NULL;
840         }
841 }
842
843 /* ****************** BUTTON CALLBACKS FOR COMPOSITE NODES ***************** */
844
845
846
847 static void node_browse_image_cb(void *ntree_v, void *node_v)
848 {
849         bNodeTree *ntree= ntree_v;
850         bNode *node= node_v;
851         
852         nodeSetActive(ntree, node);
853         
854         if(node->menunr<1) return;
855         if(node->menunr==32767) {       /* code for Load New */
856                 /// addqueue(curarea->win, UI_BUT_EVENT, B_NODE_LOADIMAGE); XXX
857         }
858         else {
859                 if(node->id) node->id->us--;
860                 node->id= BLI_findlink(&G.main->image, node->menunr-1);
861                 id_us_plus(node->id);
862
863                 BLI_strncpy(node->name, node->id->name+2, 21);
864
865                 NodeTagChanged(ntree, node); 
866                 BKE_image_signal((Image *)node->id, node->storage, IMA_SIGNAL_USER_NEW_IMAGE);
867                 // addqueue(curarea->win, UI_BUT_EVENT, B_NODE_EXEC+node->nr); XXX
868         }
869         node->menunr= 0;
870 }
871
872 static void node_active_cb(void *ntree_v, void *node_v)
873 {
874         nodeSetActive(ntree_v, node_v);
875 }
876 static void node_image_type_cb(void *node_v, void *unused)
877 {
878         
879         // allqueue(REDRAWNODE, 1);
880 }
881
882 static char *node_image_type_pup(void)
883 {
884         char *str= MEM_mallocN(256, "image type pup");
885         int a;
886         
887         str[0]= 0;
888         
889         a= sprintf(str, "Image Type %%t|");
890         a+= sprintf(str+a, "  Image %%x%d %%i%d|", IMA_SRC_FILE, ICON_IMAGE_DEHLT);
891         a+= sprintf(str+a, "  Movie %%x%d %%i%d|", IMA_SRC_MOVIE, ICON_SEQUENCE);
892         a+= sprintf(str+a, "  Sequence %%x%d %%i%d|", IMA_SRC_SEQUENCE, ICON_IMAGE_COL);
893         a+= sprintf(str+a, "  Generated %%x%d %%i%d", IMA_SRC_GENERATED, ICON_BLANK1);
894         
895         return str;
896 }
897
898 /* copy from buttons_shading.c */
899 static char *layer_menu(RenderResult *rr)
900 {
901         RenderLayer *rl;
902         int len= 40 + 40*BLI_countlist(&rr->layers);
903         short a, nr;
904         char *str= MEM_callocN(len, "menu layers");
905         
906         strcpy(str, "Layer %t");
907         a= strlen(str);
908         for(nr=0, rl= rr->layers.first; rl; rl= rl->next, nr++) {
909                 a+= sprintf(str+a, "|%s %%x%d", rl->name, nr);
910         }
911         
912         return str;
913 }
914
915 static void image_layer_cb(void *ima_v, void *iuser_v)
916 {
917         
918         ntreeCompositForceHidden(G.scene->nodetree);
919         BKE_image_multilayer_index(ima_v, iuser_v);
920         // allqueue(REDRAWNODE, 0);
921 }
922
923 static int node_composit_buts_image(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
924 {
925         ImageUser *iuser= node->storage;
926         
927         if(block) {
928                 uiBut *bt;
929                 short dy= (short)butr->ymax-19;
930                 char *strp;
931                 
932                 uiBlockBeginAlign(block);
933                 uiBlockSetCol(block, TH_BUT_SETTING2);
934                 
935                 /* browse button */
936                 IMAnames_to_pupstring(&strp, NULL, "LOAD NEW %x32767", &(G.main->image), NULL, NULL);
937                 node->menunr= 0;
938                 bt= uiDefButS(block, MENU, B_NOP, strp, 
939                                           butr->xmin, dy, 19, 19, 
940                                           &node->menunr, 0, 0, 0, 0, "Browses existing choices");
941                 uiButSetFunc(bt, node_browse_image_cb, ntree, node);
942                 if(strp) MEM_freeN(strp);
943                 
944                 /* Add New button */
945                 if(node->id==NULL) {
946                         bt= uiDefBut(block, BUT, B_NODE_LOADIMAGE, "Load New",
947                                                  butr->xmin+19, dy, (short)(butr->xmax-butr->xmin-19.0f), 19, 
948                                                  NULL, 0.0, 0.0, 0, 0, "Add new Image");
949                         uiButSetFunc(bt, node_active_cb, ntree, node);
950                         uiBlockSetCol(block, TH_AUTO);
951                 }
952                 else {
953                         /* name button + type */
954                         Image *ima= (Image *)node->id;
955                         short xmin= (short)butr->xmin, xmax= (short)butr->xmax;
956                         short width= xmax - xmin - 45;
957                         short icon= ICON_IMAGE_DEHLT;
958                         
959                         if(ima->source==IMA_SRC_MOVIE) icon= ICON_SEQUENCE;
960                         else if(ima->source==IMA_SRC_SEQUENCE) icon= ICON_IMAGE_COL;
961                         else if(ima->source==IMA_SRC_GENERATED) icon= ICON_BLANK1;
962                         
963                         bt= uiDefBut(block, TEX, B_NOP, "IM:",
964                                                  xmin+19, dy, width, 19, 
965                                                  node->id->name+2, 0.0, 19.0, 0, 0, "Image name");
966                         uiButSetFunc(bt, node_ID_title_cb, node, NULL);
967                         
968                         /* buffer type option */
969                         strp= node_image_type_pup();
970                         bt= uiDefIconTextButS(block, MENU, B_NOP, icon, strp,
971                                                  xmax-26, dy, 26, 19, 
972                                                  &ima->source, 0.0, 19.0, 0, 0, "Image type");
973                         uiButSetFunc(bt, node_image_type_cb, node, ima);
974                         MEM_freeN(strp);
975                         
976                         if( ELEM(ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE) ) {
977                                 width= (xmax-xmin)/2;
978                                 
979                                 dy-= 19;
980                                 uiDefButI(block, NUM, B_NODE_EXEC+node->nr, "Frs:",
981                                                   xmin, dy, width, 19, 
982                                                   &iuser->frames, 1.0, MAXFRAMEF, 0, 0, "Amount of images used in animation");
983                                 uiDefButI(block, NUM, B_NODE_EXEC+node->nr, "SFra:",
984                                                   xmin+width, dy, width, 19, 
985                                                   &iuser->sfra, 1.0, MAXFRAMEF, 0, 0, "Start frame of animation");
986                                 dy-= 19;
987                                 uiDefButI(block, NUM, B_NODE_EXEC+node->nr, "Offs:",
988                                                   xmin, dy, width, 19, 
989                                                   &iuser->offset, -MAXFRAMEF, MAXFRAMEF, 0, 0, "Offsets the number of the frame to use in the animation");
990                                 uiDefButS(block, TOG, B_NODE_EXEC+node->nr, "Cycl",
991                                                   xmin+width, dy, width-20, 19, 
992                                                   &iuser->cycl, 0.0, 0.0, 0, 0, "Make animation go cyclic");
993                                 uiDefIconButBitS(block, TOG, IMA_ANIM_ALWAYS, B_NODE_EXEC+node->nr, ICON_AUTO,
994                                                   xmax-20, dy, 20, 19, 
995                                                   &iuser->flag, 0.0, 0.0, 0, 0, "Always refresh Image on frame changes");
996                         }
997                         if( ima->type==IMA_TYPE_MULTILAYER && ima->rr) {
998                                 RenderLayer *rl= BLI_findlink(&ima->rr->layers, iuser->layer);
999                                 if(rl) {
1000                                         width= (xmax-xmin);
1001                                         dy-= 19;
1002                                         strp= layer_menu(ima->rr);
1003                                         bt= uiDefButS(block, MENU, B_NODE_EXEC+node->nr, strp,
1004                                                           xmin, dy, width, 19, 
1005                                                           &iuser->layer, 0.0, 10000.0, 0, 0, "Layer");
1006                                         uiButSetFunc(bt, image_layer_cb, ima->rr, node->storage);
1007                                         MEM_freeN(strp);
1008                                 }
1009                         }
1010                 }
1011                 
1012         }       
1013         if(node->id) {
1014                 Image *ima= (Image *)node->id;
1015                 int retval= 19;
1016                 
1017                 /* for each draw we test for anim refresh event */
1018                 if(iuser->flag & IMA_ANIM_REFRESHED) {
1019                         iuser->flag &= ~IMA_ANIM_REFRESHED;
1020                         // addqueue(curarea->win, UI_BUT_EVENT, B_NODE_EXEC+node->nr); XXX
1021                 }
1022                 
1023                 if( ELEM(ima->source, IMA_SRC_MOVIE, IMA_SRC_SEQUENCE) )
1024                         retval+= 38;
1025                 if( ima->type==IMA_TYPE_MULTILAYER)
1026                         retval+= 19;
1027                 return retval;
1028         }
1029         else
1030                 return 19;
1031 }
1032
1033 /* if we use render layers from other scene, we make a nice title */
1034 static void set_render_layers_title(void *node_v, void *unused)
1035 {
1036         bNode *node= node_v;
1037         Scene *sce;
1038         SceneRenderLayer *srl;
1039         char str[64];
1040         
1041         if(node->id) {
1042                 BLI_strncpy(str, node->id->name+2, 21);
1043                 strcat(str, "|");
1044                 sce= (Scene *)node->id;
1045         }
1046         else {
1047                 str[0]= 0;
1048                 sce= G.scene;
1049         }
1050         srl= BLI_findlink(&sce->r.layers, node->custom1);
1051         if(srl==NULL) {
1052                 node->custom1= 0;
1053                 srl= sce->r.layers.first;
1054         }
1055         
1056         strcat(str, srl->name);
1057         BLI_strncpy(node->name, str, 32);
1058 }
1059
1060 static char *scene_layer_menu(Scene *sce)
1061 {
1062         SceneRenderLayer *srl;
1063         int len= 40 + 40*BLI_countlist(&sce->r.layers);
1064         short a, nr;
1065         char *str= MEM_callocN(len, "menu layers");
1066         
1067         strcpy(str, "Active Layer %t");
1068         a= strlen(str);
1069         for(nr=0, srl= sce->r.layers.first; srl; srl= srl->next, nr++) {
1070                 a+= sprintf(str+a, "|%s %%x%d", srl->name, nr);
1071         }
1072         
1073         return str;
1074 }
1075
1076 static void node_browse_scene_cb(void *ntree_v, void *node_v)
1077 {
1078         bNodeTree *ntree= ntree_v;
1079         bNode *node= node_v;
1080         Scene *sce;
1081         
1082         if(node->menunr<1) return;
1083         
1084         if(node->id) {
1085                 node->id->us--;
1086                 node->id= NULL;
1087         }
1088         sce= BLI_findlink(&G.main->scene, node->menunr-1);
1089         if(sce!=G.scene) {
1090                 node->id= &sce->id;
1091                 id_us_plus(node->id);
1092         }
1093         
1094         set_render_layers_title(node, NULL);
1095         nodeSetActive(ntree, node);
1096
1097         // allqueue(REDRAWBUTSSHADING, 0);
1098         // allqueue(REDRAWNODE, 0);
1099         NodeTagChanged(ntree, node); 
1100
1101         node->menunr= 0;
1102 }
1103
1104
1105 static int node_composit_buts_renderlayers(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
1106 {
1107         if(block) {
1108                 uiBut *bt;
1109                 char *strp;
1110                 
1111                 /* browse button scene */
1112                 uiBlockBeginAlign(block);
1113                 IDnames_to_pupstring(&strp, NULL, "", &(G.main->scene), NULL, NULL);
1114                 node->menunr= 0;
1115                 bt= uiDefButS(block, MENU, B_NOP, strp, 
1116                                           butr->xmin, butr->ymin, 20, 19, 
1117                                           &node->menunr, 0, 0, 0, 0, "Browse Scene to use RenderLayer from");
1118                 uiButSetFunc(bt, node_browse_scene_cb, ntree, node);
1119                 if(strp) MEM_freeN(strp);
1120                 
1121                 /* browse button layer */
1122                 strp= scene_layer_menu(node->id?(Scene *)node->id:G.scene);
1123                 if(node->id)
1124                         bt= uiDefIconTextButS(block, MENU, B_NODE_EXEC+node->nr, ICON_SCENE_DEHLT, strp, 
1125                                   butr->xmin+20, butr->ymin, (butr->xmax-butr->xmin)-40, 19, 
1126                                   &node->custom1, 0, 0, 0, 0, "Choose Render Layer");
1127                 else
1128                         bt= uiDefButS(block, MENU, B_NODE_EXEC+node->nr, strp, 
1129                                   butr->xmin+20, butr->ymin, (butr->xmax-butr->xmin)-40, 19, 
1130                                   &node->custom1, 0, 0, 0, 0, "Choose Render Layer");
1131                 uiButSetFunc(bt, set_render_layers_title, node, NULL);
1132                 MEM_freeN(strp);
1133                 
1134                 /* re-render */
1135                 /* uses custom2, not the best implementation of the world... but we need it to work now :) */
1136                 bt= uiDefIconButS(block, TOG, B_NODE_EXEC+node->nr, ICON_SCENE, 
1137                                   butr->xmax-20, butr->ymin, 20, 19, 
1138                                   &node->custom2, 0, 0, 0, 0, "Re-render this Layer");
1139                 
1140         }
1141         return 19;
1142 }
1143
1144 static void node_blur_relative_cb(void *node, void *poin2)
1145 {
1146         bNode *nodev= node;
1147         NodeBlurData *nbd= nodev->storage;
1148         if(nbd->image_in_width != 0){
1149                 if(nbd->relative){ /* convert absolute values to relative */
1150                         nbd->percentx= (float)(nbd->sizex)/nbd->image_in_width;
1151                         nbd->percenty= (float)(nbd->sizey)/nbd->image_in_height;
1152                 }else{ /* convert relative values to absolute */
1153                         nbd->sizex= (int)(nbd->percentx*nbd->image_in_width);
1154                         nbd->sizey= (int)(nbd->percenty*nbd->image_in_height);
1155                 }
1156         }
1157         // allqueue(REDRAWNODE, 0);
1158 }
1159 static void node_blur_update_sizex_cb(void *node, void *poin2)
1160 {
1161         bNode *nodev= node;
1162         NodeBlurData *nbd= nodev->storage;
1163
1164         nbd->sizex= (int)(nbd->percentx*nbd->image_in_width);
1165 }
1166 static void node_blur_update_sizey_cb(void *node, void *poin2)
1167 {
1168         bNode *nodev= node;
1169         NodeBlurData *nbd= nodev->storage;
1170
1171         nbd->sizey= (int)(nbd->percenty*nbd->image_in_height);
1172 }
1173 static int node_composit_buts_blur(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
1174 {
1175         if(block) {
1176                 NodeBlurData *nbd= node->storage;
1177                 uiBut *bt;
1178                 short dy= butr->ymin+58;
1179                 short dx= (butr->xmax-butr->xmin)/2;
1180                 char str[256];
1181                 
1182                 uiBlockBeginAlign(block);
1183                 sprintf(str, "Filter Type%%t|Flat %%x%d|Tent %%x%d|Quad %%x%d|Cubic %%x%d|Gauss %%x%d|Fast Gauss%%x%d|CatRom %%x%d|Mitch %%x%d", R_FILTER_BOX, R_FILTER_TENT, R_FILTER_QUAD, R_FILTER_CUBIC, R_FILTER_GAUSS, R_FILTER_FAST_GAUSS, R_FILTER_CATROM, R_FILTER_MITCH);
1184                 uiDefButS(block, MENU, B_NODE_EXEC+node->nr,str,
1185                                   butr->xmin, dy, dx*2, 19, 
1186                                   &nbd->filtertype, 0, 0, 0, 0, "Set sampling filter for blur");
1187                 dy-=19;
1188                 if (nbd->filtertype != R_FILTER_FAST_GAUSS) { 
1189                         uiDefButC(block, TOG, B_NODE_EXEC+node->nr, "Bokeh",
1190                                         butr->xmin, dy, dx, 19, 
1191                                         &nbd->bokeh, 0, 0, 0, 0, "Uses circular filter, warning it's slow!");
1192                         uiDefButC(block, TOG, B_NODE_EXEC+node->nr, "Gamma",
1193                                         butr->xmin+dx, dy, dx, 19, 
1194                                         &nbd->gamma, 0, 0, 0, 0, "Applies filter on gamma corrected values");
1195                 } else {
1196                         uiBlockEndAlign(block);
1197                         uiBlockBeginAlign(block);
1198                 }
1199                 dy-=19;
1200                 bt= uiDefButS(block, TOG, B_NOP, "Relative",
1201                                   butr->xmin, dy, dx*2, 19,
1202                                   &nbd->relative, 0, 0, 0, 0, "Use relative (percent) values to define blur radius");
1203                 uiButSetFunc(bt, node_blur_relative_cb, node, NULL);
1204
1205                 dy-=19;
1206                 if(nbd->relative) {
1207                         bt= uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "X:",
1208                                                  butr->xmin, dy, dx, 19, 
1209                                                  &nbd->percentx, 0.0f, 1.0f, 0, 0, "");
1210                         uiButSetFunc(bt, node_blur_update_sizex_cb, node, NULL);
1211                         bt= uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "Y:",
1212                                                  butr->xmin+dx, dy, dx, 19, 
1213                                                  &nbd->percenty, 0.0f, 1.0f, 0, 0, "");
1214                         uiButSetFunc(bt, node_blur_update_sizey_cb, node, NULL);
1215                 }
1216                 else {
1217                         uiDefButS(block, NUM, B_NODE_EXEC+node->nr, "X:",
1218                                                  butr->xmin, dy, dx, 19, 
1219                                                  &nbd->sizex, 0, 256, 0, 0, "");
1220                         uiDefButS(block, NUM, B_NODE_EXEC+node->nr, "Y:",
1221                                                  butr->xmin+dx, dy, dx, 19, 
1222                                                  &nbd->sizey, 0, 256, 0, 0, "");
1223                 }
1224                 uiBlockEndAlign(block);
1225         }
1226         return 77;
1227 }
1228
1229 static int node_composit_buts_dblur(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
1230 {
1231         if(block) {
1232                 NodeDBlurData *ndbd = node->storage;
1233                 short dy = butr->ymin + 171;
1234                 short dx = butr->xmax - butr->xmin;
1235                 short halfdx= (short)dx/2;
1236
1237                 uiBlockBeginAlign(block);
1238                 uiDefButS(block, NUM, B_NODE_EXEC+node->nr, "Iterations:",
1239                                 butr->xmin, dy, dx, 19,
1240                                 &ndbd->iter, 1, 32, 10, 0, "Amount of iterations");
1241                 uiDefButC(block, TOG, B_NODE_EXEC+node->nr, "Wrap",
1242                                 butr->xmin, dy-= 19, dx, 19, 
1243                                 &ndbd->wrap, 0, 0, 0, 0, "Wrap blur");
1244                 uiBlockEndAlign(block);
1245
1246                 dy-= 9;
1247
1248                 uiDefBut(block, LABEL, B_NOP, "Center", butr->xmin, dy-= 19, dx, 19, NULL, 0.0f, 0.0f, 0, 0, "");
1249
1250                 uiBlockBeginAlign(block);
1251                 uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "X:",
1252                                 butr->xmin, dy-= 19, halfdx, 19,
1253                                 &ndbd->center_x, 0.0f, 1.0f, 10, 0, "X center in percents");
1254                 uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "Y:",
1255                                 butr->xmin+halfdx, dy, halfdx, 19,
1256                                 &ndbd->center_y, 0.0f, 1.0f, 10, 0, "Y center in percents");
1257                 uiBlockEndAlign(block);
1258
1259                 dy-= 9;
1260
1261                 uiBlockBeginAlign(block);
1262                 uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "Distance:",
1263                                 butr->xmin, dy-= 19, dx, 19,
1264                                 &ndbd->distance, -1.0f, 1.0f, 10, 0, "Amount of which the image moves");
1265                 uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "Angle:",
1266                                 butr->xmin, dy-= 19, dx, 19,
1267                                 &ndbd->angle, 0.0f, 360.0f, 1000, 0, "Angle in which the image will be moved");
1268                 uiBlockEndAlign(block);
1269
1270                 dy-= 9;
1271
1272                 uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "Spin:",
1273                                 butr->xmin, dy-= 19, dx, 19,
1274                                 &ndbd->spin, -360.0f, 360.0f, 1000, 0, "Angle that is used to spin the image");
1275
1276                 dy-= 9;
1277
1278                 uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "Zoom:",
1279                                 butr->xmin, dy-= 19, dx, 19,
1280                                 &ndbd->zoom, 0.0f, 100.0f, 100, 0, "Amount of which the image is zoomed");
1281
1282         }
1283         return 190;
1284 }
1285
1286 static int node_composit_buts_bilateralblur(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
1287 {
1288         if(block) {
1289                 NodeBilateralBlurData *nbbd= node->storage;
1290                 short dy= butr->ymin+38;
1291                 short dx= (butr->xmax-butr->xmin);
1292                 
1293                 uiBlockBeginAlign(block);
1294                 uiDefButS(block, NUM, B_NODE_EXEC+node->nr, "Iterations:",
1295                                  butr->xmin, dy, dx, 19, 
1296                                  &nbbd->iter, 1, 128, 0, 0, "Amount of iterations");
1297                 dy-=19;
1298                 uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "Color Sigma:",
1299                                   butr->xmin, dy, dx, 19, 
1300                                   &nbbd->sigma_color,0.01, 3, 10, 0, "Sigma value used to modify color");
1301                 dy-=19;
1302                 uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "Space Sigma:",
1303                                   butr->xmin, dy, dx, 19, 
1304                                   &nbbd->sigma_space ,0.01, 30, 10, 0, "Sigma value used to modify space");
1305                 
1306         }
1307         return 57;
1308 }
1309
1310 /* qdn: defocus node */
1311 static int node_composit_buts_defocus(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
1312 {
1313         if(block) {
1314                 NodeDefocus *nqd = node->storage;
1315                 short dy = butr->ymin + 209;
1316                 short dx = butr->xmax - butr->xmin; 
1317                 char* mstr1 = "Bokeh Type%t|Octagon %x8|Heptagon %x7|Hexagon %x6|Pentagon %x5|Square %x4|Triangle %x3|Disk %x0";
1318
1319                 uiDefBut(block, LABEL, B_NOP, "Bokeh Type", butr->xmin, dy, dx, 19, NULL, 0, 0, 0, 0, "");
1320                 uiDefButC(block, MENU, B_NODE_EXEC+node->nr, mstr1,
1321                           butr->xmin, dy-19, dx, 19,
1322                           &nqd->bktype, 0, 0, 0, 0, "Bokeh type");
1323                 if (nqd->bktype) { /* for some reason rotating a disk doesn't seem to work... ;) */
1324                         uiDefButC(block, NUM, B_NODE_EXEC+node->nr, "Rotate:",
1325                                   butr->xmin, dy-38, dx, 19,
1326                                   &nqd->rotation, 0, 90, 0, 0, "Bokeh shape rotation offset in degrees");
1327                 }
1328                 uiDefButC(block, TOG, B_NODE_EXEC+node->nr, "Gamma Correct",
1329                           butr->xmin, dy-57, dx, 19,
1330                           &nqd->gamco, 0, 0, 0, 0, "Enable gamma correction before and after main process");
1331                 if (nqd->no_zbuf==0) {
1332                         // only needed for zbuffer input
1333                         uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "fStop:",
1334                                   butr->xmin, dy-76, dx, 19,
1335                                   &nqd->fstop, 0.5, 128, 10, 0, "Amount of focal blur, 128=infinity=perfect focus, half the value doubles the blur radius");
1336                 }
1337                 uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "Maxblur:",
1338                           butr->xmin, dy-95, dx, 19,
1339                           &nqd->maxblur, 0, 10000, 1000, 0, "blur limit, maximum CoC radius, 0=no limit");
1340                 uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "BThreshold:",
1341                           butr->xmin, dy-114, dx, 19,
1342                           &nqd->bthresh, 0, 100, 100, 0, "CoC radius threshold, prevents background bleed on in-focus midground, 0=off");
1343                 uiDefButC(block, TOG, B_NODE_EXEC+node->nr, "Preview",
1344                           butr->xmin, dy-142, dx, 19,
1345                           &nqd->preview, 0, 0, 0, 0, "Enable sampling mode, useful for preview when using low samplecounts");
1346                 if (nqd->preview) {
1347                         /* only visible when sampling mode enabled */
1348                         uiDefButS(block, NUM, B_NODE_EXEC+node->nr, "Samples:",
1349                                   butr->xmin, dy-161, dx, 19,
1350                                   &nqd->samples, 16, 256, 0, 0, "Number of samples (16=grainy, higher=less noise)");
1351                 }
1352                 uiDefButS(block, TOG, B_NODE_EXEC+node->nr, "No zbuffer",
1353                           butr->xmin, dy-190, dx, 19,
1354                           &nqd->no_zbuf, 0, 0, 0, 0, "Enable when using an image as input instead of actual zbuffer (auto enabled if node not image based, eg. time node)");
1355                 if (nqd->no_zbuf) {
1356                         uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "Zscale:",
1357                             butr->xmin, dy-209, dx, 19,
1358                             &nqd->scale, 0, 1000, 100, 0, "Scales the Z input when not using a zbuffer, controls maximum blur designated by the color white or input value 1");
1359                 }
1360         }
1361         return 228;
1362 }
1363
1364
1365 /* qdn: glare node */
1366 static int node_composit_buts_glare(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
1367 {
1368         if(block) {
1369                 NodeGlare *ndg = node->storage;
1370                 short dy = butr->ymin + 152, dx = butr->xmax - butr->xmin; 
1371                 char* mn1 = "Type%t|Ghosts%x3|Streaks%x2|Fog Glow%x1|Simple Star%x0";
1372                 char* mn2 = "Quality/Speed%t|High/Slow%x0|Medium/Medium%x1|Low/Fast%x2";
1373                 uiDefButC(block, MENU, B_NODE_EXEC+node->nr, mn1,
1374                           butr->xmin, dy, dx, 19,
1375                           &ndg->type, 0, 0, 0, 0, "Glow/Flare/Bloom type");
1376                 uiDefButC(block, MENU, B_NODE_EXEC+node->nr, mn2,
1377                           butr->xmin, dy-19, dx, 19,
1378                           &ndg->quality, 0, 0, 0, 0,
1379                           "Quality speed trade off, if not set to high quality, effect will be applied to low-res copy of source image");
1380                 if (ndg->type != 1) {
1381                         uiDefButC(block, NUM, B_NODE_EXEC+node->nr, "Iterations:",
1382                                   butr->xmin, dy-38, dx, 19,
1383                                   &ndg->iter, 2, 5, 1, 0,
1384                                   "higher values will generate longer/more streaks/ghosts");
1385                         if (ndg->type != 0)
1386                                 uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "ColMod:",
1387                                           butr->xmin, dy-57, dx, 19,
1388                                           &ndg->colmod, 0, 1, 10, 0,
1389                                           "Amount of Color Modulation, modulates colors of streaks and ghosts for a spectral dispersion effect");
1390                 }
1391                 uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "Mix:",
1392                           butr->xmin, dy-76, dx, 19,
1393                           &ndg->mix, -1, 1, 10, 0,
1394                           "Mix balance, -1 is original image only, 0 is exact 50/50 mix, 1 is processed image only");
1395                 uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "Threshold:",
1396                           butr->xmin, dy-95, dx, 19,
1397                           &ndg->threshold, 0, 1000, 10, 0,
1398                           "Brightness threshold, the glarefilter will be applied only to pixels brighter than this value");
1399                 if ((ndg->type == 2) || (ndg->type == 0))
1400                 {
1401                         if (ndg->type == 2) {
1402                                 uiDefButC(block, NUM, B_NODE_EXEC+node->nr, "streaks:",
1403                                           butr->xmin, dy-114, dx, 19,
1404                                           &ndg->angle, 2, 16, 1000, 0,
1405                                           "Total number of streaks");
1406                                 uiDefButC(block, NUM, B_NODE_EXEC+node->nr, "AngOfs:",
1407                                           butr->xmin, dy-133, dx, 19,
1408                                           &ndg->angle_ofs, 0, 180, 1000, 0,
1409                                           "Streak angle rotation offset in degrees");
1410                         }
1411                         uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "Fade:",
1412                                   butr->xmin, dy-152, dx, 19,
1413                                   &ndg->fade, 0.75, 1, 5, 0,
1414                                   "Streak fade out factor");
1415                 }
1416                 if (ndg->type == 0)
1417                         uiDefButC(block, TOG, B_NODE_EXEC+node->nr, "Rot45",
1418                                   butr->xmin, dy-114, dx, 19,
1419                                   &ndg->angle, 0, 0, 0, 0,
1420                                   "simple star filter, add 45 degree rotation offset");
1421                 if ((ndg->type == 1) || (ndg->type > 3))        // PBGH and fog glow
1422                         uiDefButC(block, NUM, B_NODE_EXEC+node->nr, "Size:",
1423                                   butr->xmin, dy-114, dx, 19,
1424                                   &ndg->size, 6, 9, 1000, 0,
1425                                   "glow/glare size (not actual size, relative to initial size of bright area of pixels)");
1426         }
1427         return 171;
1428 }
1429
1430 /* qdn: tonemap node */
1431 static int node_composit_buts_tonemap(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
1432 {
1433         if(block) {
1434                 NodeTonemap *ntm = node->storage;
1435                 short dy = butr->ymin + 76, dx = butr->xmax - butr->xmin; 
1436                 char* mn = "Type%t|R/D Photoreceptor%x1|Rh Simple%x0";
1437                 
1438                 uiBlockBeginAlign(block);
1439                 uiDefButI(block, MENU, B_NODE_EXEC+node->nr, mn,
1440                           butr->xmin, dy, dx, 19,
1441                           &ntm->type, 0, 0, 0, 0,
1442                           "Tone mapping type");
1443                 if (ntm->type == 0) {
1444                         uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "Key:",
1445                                   butr->xmin, dy-19, dx, 19,
1446                                   &ntm->key, 0, 1, 5, 0,
1447                                   "The value the average luminance is mapped to");
1448                         uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "Offset:",
1449                                   butr->xmin, dy-38, dx, 19,
1450                                   &ntm->offset, 0.001, 10, 5, 0,
1451                                   "Tonemap offset, normally always 1, but can be used as an extra control to alter the brightness curve");
1452                         uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "Gamma:",
1453                                   butr->xmin, dy-57, dx, 19,
1454                                   &ntm->gamma, 0.001, 3, 5, 0,
1455                                   "Gamma factor, if not used, set to 1");
1456                 }
1457                 else {
1458                         uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "Intensity:",
1459                                   butr->xmin, dy-19, dx, 19,
1460                                   &ntm->f, -8, 8, 10, 0, "if less than zero, darkens image, otherwise makes it brighter");
1461                         uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "Contrast:",
1462                                   butr->xmin, dy-38, dx, 19,
1463                                   &ntm->m, 0, 1, 5, 0, "Set to 0 to use estimate from input image");
1464                         uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "Adaptation:",
1465                                   butr->xmin, dy-57, dx, 19,
1466                                   &ntm->a, 0, 1, 5, 0, "if 0, global, if 1, based on pixel intensity");
1467                         uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "ColCorrect:",
1468                                   butr->xmin, dy-76, dx, 19,
1469                                   &ntm->c, 0, 1, 5, 0, "color correction, if 0, same for all channels, if 1, each independent");
1470                 }
1471                 uiBlockEndAlign(block);
1472         }
1473         return 95;
1474 }
1475
1476 /* qdn: lens distortion node */
1477 static int node_composit_buts_lensdist(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
1478 {
1479         if(block) {
1480                 NodeLensDist *nld = node->storage;
1481                 short dy = butr->ymin + 19, dx = butr->xmax - butr->xmin; 
1482                 uiBlockBeginAlign(block);
1483                 uiDefButS(block, TOG, B_NODE_EXEC+node->nr, "Projector",
1484                           butr->xmin, dy, dx, 19,
1485                           &nld->proj, 0, 0, 0, 0,
1486                           "Enable/disable projector mode, effect is applied in horizontal direction only");
1487                 if (!nld->proj) {
1488                         uiDefButS(block, TOG, B_NODE_EXEC+node->nr, "Jitter",
1489                                   butr->xmin, dy-19, dx/2, 19,
1490                                   &nld->jit, 0, 0, 0, 0,
1491                                   "Enable/disable jittering, faster, but also noisier");
1492                         uiDefButS(block, TOG, B_NODE_EXEC+node->nr, "Fit",
1493                                   butr->xmin+dx/2, dy-19, dx/2, 19,
1494                                   &nld->fit, 0, 0, 0, 0,
1495                                   "For positive distortion factor only, scale image such that black areas are not visible");
1496                 }
1497                 uiBlockEndAlign(block);
1498         }
1499         return 38;
1500 }
1501
1502
1503 static int node_composit_buts_vecblur(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
1504 {
1505         if(block) {
1506                 NodeBlurData *nbd= node->storage;
1507                 short dy= butr->ymin;
1508                 short dx= (butr->xmax-butr->xmin);
1509                 
1510                 uiBlockBeginAlign(block);
1511                 uiDefButS(block, NUM, B_NODE_EXEC+node->nr, "Samples:",
1512                                  butr->xmin, dy+76, dx, 19, 
1513                                  &nbd->samples, 1, 256, 0, 0, "Amount of samples");
1514                 uiDefButS(block, NUM, B_NODE_EXEC+node->nr, "MinSpeed:",
1515                                   butr->xmin, dy+57, dx, 19, 
1516                                   &nbd->minspeed, 0, 1024, 0, 0, "Minimum speed for a pixel to be blurred, used to separate background from foreground");
1517                 uiDefButS(block, NUM, B_NODE_EXEC+node->nr, "MaxSpeed:",
1518                                   butr->xmin, dy+38, dx, 19, 
1519                                   &nbd->maxspeed, 0, 1024, 0, 0, "If not zero, maximum speed in pixels");
1520                 uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "BlurFac:",
1521                                   butr->xmin, dy+19, dx, 19, 
1522                                   &nbd->fac, 0.0f, 2.0f, 10, 2, "Scaling factor for motion vectors, actually 'shutter speed' in frames");
1523                 uiDefButS(block, TOG, B_NODE_EXEC+node->nr, "Curved",
1524                                   butr->xmin, dy, dx, 19, 
1525                                   &nbd->curved, 0.0f, 2.0f, 10, 2, "Interpolate between frames in a bezier curve, rather than linearly");
1526                 uiBlockEndAlign(block);
1527         }
1528         return 95;
1529 }
1530
1531 static int node_composit_buts_filter(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
1532 {
1533         if(block) {
1534                 uiBut *bt;
1535                 
1536                 /* blend type */
1537                 bt=uiDefButS(block, MENU, B_NODE_EXEC+node->nr, "Soften %x0|Sharpen %x1|Laplace %x2|Sobel %x3|Prewitt %x4|Kirsch %x5|Shadow %x6",
1538                                          butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20, 
1539                                          &node->custom1, 0, 0, 0, 0, "");
1540                 uiButSetFunc(bt, node_but_title_cb, node, bt);
1541         }
1542         return 20;
1543 }
1544
1545 static int node_composit_buts_flip(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) 
1546 {
1547         if(block) {
1548                 uiBut *bt;
1549                 
1550                 /* flip x\y */
1551                 bt=uiDefButS(block, MENU, B_NODE_EXEC+node->nr, "Flip X %x0|Flip Y %x1|Flip X & Y %x2",
1552                                          butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20, 
1553                                          &node->custom1, 0, 0, 0, 0, "");
1554                 uiButSetFunc(bt, node_but_title_cb, node, bt);
1555         }
1556         return 20;      
1557 }
1558
1559 static int node_composit_buts_crop(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
1560 {
1561         if(block) {
1562                 NodeTwoXYs *ntxy= node->storage;
1563                 char elementheight = 19;
1564                 short dx= (butr->xmax-butr->xmin)/2;
1565                 short dy= butr->ymax - elementheight;
1566                 short xymin= 0, xymax= 10000;
1567
1568                 uiBlockBeginAlign(block);
1569
1570                 /* crop image size toggle */
1571                 uiDefButS(block, TOG, B_NODE_EXEC+node->nr, "Crop Image Size",
1572                                   butr->xmin, dy, dx*2, elementheight, 
1573                                   &node->custom1, 0, 0, 0, 0, "Crop the size of the input image.");
1574
1575                 dy-=elementheight;
1576
1577                 /* x1 */
1578                 uiDefButS(block, NUM, B_NODE_EXEC+node->nr, "X1:",
1579                                          butr->xmin, dy, dx, elementheight,
1580                                          &ntxy->x1, xymin, xymax, 0, 0, "");
1581                 /* y1 */
1582                 uiDefButS(block, NUM, B_NODE_EXEC+node->nr, "Y1:",
1583                                          butr->xmin+dx, dy, dx, elementheight,
1584                                          &ntxy->y1, xymin, xymax, 0, 0, "");
1585
1586                 dy-=elementheight;
1587
1588                 /* x2 */
1589                 uiDefButS(block, NUM, B_NODE_EXEC+node->nr, "X2:",
1590                                          butr->xmin, dy, dx, elementheight,
1591                                          &ntxy->x2, xymin, xymax, 0, 0, "");
1592                 /* y2 */
1593                 uiDefButS(block, NUM, B_NODE_EXEC+node->nr, "Y2:",
1594                                          butr->xmin+dx, dy, dx, elementheight,
1595                                          &ntxy->y2, xymin, xymax, 0, 0, "");
1596
1597                 uiBlockEndAlign(block);
1598         }
1599         return 60;
1600 }
1601
1602 static int node_composit_buts_splitviewer(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
1603 {
1604         if(block) {     
1605                 uiBlockBeginAlign(block);
1606                 
1607                 uiDefButS(block, ROW, B_NODE_EXEC+node->nr, "X",
1608                                   butr->xmin, butr->ymin+19, (butr->xmax-butr->xmin)/2, 20, 
1609                                   &node->custom2, 0.0, 0.0, 0, 0, "");
1610                 uiDefButS(block, ROW, B_NODE_EXEC+node->nr, "Y",
1611                                   butr->xmin+(butr->xmax-butr->xmin)/2, butr->ymin+19, (butr->xmax-butr->xmin)/2, 20, 
1612                                   &node->custom2, 0.0, 1.0, 0, 0, "");
1613                                   
1614                 uiDefButS(block, NUMSLI, B_NODE_EXEC+node->nr, "Split %: ",
1615                                 butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20, &node->custom1, 0, 100, 10, 0, "");
1616         }
1617         return 40;
1618 }
1619
1620 static int node_composit_buts_map_value(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
1621 {
1622         if(block) {
1623                 TexMapping *texmap= node->storage;
1624                 short xstart= (short)butr->xmin;
1625                 short dy= (short)(butr->ymax-19.0f);
1626                 short dx= (short)(butr->xmax-butr->xmin)/2;
1627                 
1628                 uiBlockBeginAlign(block);
1629                 uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "Offs:", xstart, dy, 2*dx, 19, texmap->loc, -1000.0f, 1000.0f, 10, 2, "");
1630                 dy-= 19;
1631                 uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "Size:", xstart, dy, 2*dx, 19, texmap->size, -1000.0f, 1000.0f, 10, 3, "");
1632                 dy-= 23;
1633                 uiBlockBeginAlign(block);
1634                 uiDefButBitI(block, TOG, TEXMAP_CLIP_MIN, B_NODE_EXEC+node->nr, "Min", xstart, dy, dx, 19, &texmap->flag, 0.0f, 0.0f, 0, 0, "");
1635                 uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "", xstart+dx, dy, dx, 19, texmap->min, -1000.0f, 1000.0f, 10, 2, "");
1636                 dy-= 19;
1637                 uiDefButBitI(block, TOG, TEXMAP_CLIP_MAX, B_NODE_EXEC+node->nr, "Max", xstart, dy, dx, 19, &texmap->flag, 0.0f, 0.0f, 0, 0, "");
1638                 uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "", xstart+dx, dy, dx, 19, texmap->max, -1000.0f, 1000.0f, 10, 2, "");
1639         }
1640         return 80;
1641 }
1642
1643 static int node_composit_buts_alphaover(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
1644 {
1645         if(block) {
1646                 NodeTwoFloats *ntf= node->storage;
1647                 
1648                 /* alpha type */
1649                 uiDefButS(block, TOG, B_NODE_EXEC+node->nr, "ConvertPremul",
1650                                   butr->xmin, butr->ymin+19, butr->xmax-butr->xmin, 19, 
1651                                   &node->custom1, 0, 0, 0, 0, "");
1652                 /* mix factor */
1653                 uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "Premul: ",
1654                                   butr->xmin, butr->ymin, butr->xmax-butr->xmin, 19, 
1655                                   &ntf->x, 0.0f, 1.0f, 100, 0, "");
1656         }
1657         return 38;
1658 }
1659
1660 static int node_composit_buts_hue_sat(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
1661 {
1662         if(block) {
1663                 NodeHueSat *nhs= node->storage;
1664                 
1665                 uiBlockBeginAlign(block);
1666                 uiDefButF(block, NUMSLI, B_NODE_EXEC+node->nr, "Hue: ",
1667                                   butr->xmin, butr->ymin+40.0f, butr->xmax-butr->xmin, 20, 
1668                                   &nhs->hue, 0.0f, 1.0f, 100, 0, "");
1669                 uiDefButF(block, NUMSLI, B_NODE_EXEC+node->nr, "Sat: ",
1670                                   butr->xmin, butr->ymin+20.0f, butr->xmax-butr->xmin, 20, 
1671                                   &nhs->sat, 0.0f, 2.0f, 100, 0, "");
1672                 uiDefButF(block, NUMSLI, B_NODE_EXEC+node->nr, "Val: ",
1673                                   butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20, 
1674                                   &nhs->val, 0.0f, 2.0f, 100, 0, "");
1675         }
1676         return 60;
1677 }
1678
1679 static int node_composit_buts_dilateerode(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
1680 {
1681         if(block) {
1682                 uiDefButS(block, NUM, B_NODE_EXEC+node->nr, "Distance:",
1683                                   butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20, 
1684                                   &node->custom2, -100, 100, 0, 0, "Distance to grow/shrink (number of iterations)");
1685         }
1686         return 20;
1687 }
1688
1689 static int node_composit_buts_diff_matte(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
1690 {
1691         if(block) {
1692                 short sx= (butr->xmax-butr->xmin)/4;
1693                 short dx= (butr->xmax-butr->xmin)/3;
1694                 NodeChroma *c= node->storage;
1695                 
1696                 uiBlockBeginAlign(block);
1697                 /*color space selectors*/
1698                 uiDefButS(block, ROW,B_NODE_EXEC+node->nr,"RGB",
1699                                                         butr->xmin,butr->ymin+60,sx,20,
1700                                                         &node->custom1,1,1, 0, 0, "RGB Color Space");
1701                 uiDefButS(block, ROW,B_NODE_EXEC+node->nr,"HSV",
1702                                                         butr->xmin+sx,butr->ymin+60,sx,20,
1703                                                         &node->custom1,1,2, 0, 0, "HSV Color Space");
1704                 uiDefButS(block, ROW,B_NODE_EXEC+node->nr,"YUV",
1705                                                         butr->xmin+2*sx,butr->ymin+60,sx,20,
1706                                                         &node->custom1,1,3, 0, 0, "YUV Color Space");
1707                                         uiDefButS(block, ROW,B_NODE_EXEC+node->nr,"YCC",
1708                                                         butr->xmin+3*sx,butr->ymin+60,sx,20,
1709                                                         &node->custom1,1,4, 0, 0, "YCbCr Color Space");
1710                 /*channel tolorences*/
1711                 uiDefButF(block, NUM, B_NODE_EXEC+node->nr, " ",
1712                                                         butr->xmin, butr->ymin+40, dx, 20,
1713                                                         &c->t1, 0.0f, 1.0f, 100, 0, "Channel 1 Tolerance");
1714                 uiDefButF(block, NUM, B_NODE_EXEC+node->nr, " ",
1715                                                         butr->xmin+dx, butr->ymin+40, dx, 20,
1716                                                         &c->t2, 0.0f, 1.0f, 100, 0, "Channel 2 Tolorence");
1717                 uiDefButF(block, NUM, B_NODE_EXEC+node->nr, " ",
1718                                                         butr->xmin+2*dx, butr->ymin+40, dx, 20,
1719                                                         &c->t3, 0.0f, 1.0f, 100, 0, "Channel 3 Tolorence");
1720                 /*falloff parameters*/
1721                 /*
1722                 uiDefButF(block, NUMSLI, B_NODE_EXEC+node->nr, "Falloff Size ",
1723                         butr->xmin, butr->ymin+20, butr->xmax-butr->xmin, 20,
1724                         &c->fsize, 0.0f, 1.0f, 100, 0, "");
1725                 */
1726                 uiDefButF(block, NUMSLI, B_NODE_EXEC+node->nr, "Falloff: ",
1727                         butr->xmin, butr->ymin+20, butr->xmax-butr->xmin, 20,
1728                         &c->fstrength, 0.0f, 1.0f, 100, 0, "");
1729         }
1730         return 80;
1731 }
1732
1733 static int node_composit_buts_color_spill(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
1734 {
1735         if(block) {
1736                 short dx= (butr->xmax-butr->xmin)/3;
1737
1738                 NodeChroma *c=node->storage;
1739                 uiBlockBeginAlign(block);
1740                 uiDefButF(block, NUM, B_NODE_EXEC+node->nr, "Enhance: ", 
1741                                 butr->xmin, butr->ymin+20.0, butr->xmax-butr->xmin, 20,
1742                                 &c->t1, 0.0f, 0.5f, 100, 2, "Adjusts how much selected channel is affected by color spill algorithm");
1743                 uiDefButS(block, ROW, B_NODE_EXEC+node->nr, "R",
1744                                 butr->xmin,butr->ymin,dx,20,
1745                                 &node->custom1,1,1, 0, 0, "Red Spill Suppression");
1746                 uiDefButS(block, ROW, B_NODE_EXEC+node->nr, "G",
1747                                 butr->xmin+dx,butr->ymin,dx,20,
1748                                 &node->custom1,1,2, 0, 0, "Green Spill Suppression");
1749                 uiDefButS(block, ROW, B_NODE_EXEC+node->nr, "B",
1750                                 butr->xmin+2*dx,butr->ymin,dx,20,
1751                                 &node->custom1, 1, 3, 0, 0, "Blue Spill Suppression");
1752                 uiBlockEndAlign(block);
1753         }
1754         return 60;
1755 }
1756
1757 static int node_composit_buts_chroma_matte(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
1758 {
1759         if(block) {
1760                 short dx=(butr->xmax-butr->xmin)/2;
1761                 NodeChroma *c= node->storage;
1762                 uiBlockBeginAlign(block);
1763
1764                 uiDefButF(block, NUMSLI, B_NODE_EXEC+node->nr, "Acceptance ",
1765                         butr->xmin, butr->ymin+60, butr->xmax-butr->xmin, 20,
1766                         &c->t1, 1.0f, 80.0f, 100, 0, "Tolerance for colors to be considered a keying color");
1767                 uiDefButF(block, NUMSLI, B_NODE_EXEC+node->nr, "Cutoff ",
1768                         butr->xmin, butr->ymin+40, butr->xmax-butr->xmin, 20,
1769                         &c->t2, 0.0f, 30.0f, 100, 0, "Colors below this will be considered as exact matches for keying color");
1770
1771                 uiDefButF(block, NUMSLI, B_NODE_EXEC+node->nr, "Lift ",
1772                         butr->xmin, butr->ymin+20, dx, 20,
1773                         &c->fsize, 0.0f, 1.0f, 100, 0, "Alpha Lift");
1774                 uiDefButF(block, NUMSLI, B_NODE_EXEC+node->nr, "Gain ",
1775                         butr->xmin+dx, butr->ymin+20, dx, 20,
1776                         &c->fstrength, 0.0f, 1.0f, 100, 0, "Alpha Gain");
1777
1778                 uiDefButF(block, NUMSLI, B_NODE_EXEC+node->nr, "Shadow Adjust ",
1779                         butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20,
1780                         &c->t3, 0.0f, 1.0f, 100, 0, "Adjusts the brightness of any shadows captured");
1781
1782                 if(c->t2 > c->t1)
1783                         c->t2=c->t1;
1784         }
1785         return 80;
1786 }
1787
1788 static int node_composit_buts_channel_matte(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
1789 {
1790         if(block) {
1791                 short sx= (butr->xmax-butr->xmin)/4;
1792                 short cx= (butr->xmax-butr->xmin)/3;
1793                 NodeChroma *c=node->storage;
1794                 char *c1, *c2, *c3;
1795         
1796                 /*color space selectors*/
1797                 uiBlockBeginAlign(block);
1798                 uiDefButS(block, ROW,B_NODE_EXEC+node->nr,"RGB",
1799                         butr->xmin,butr->ymin+60,sx,20,&node->custom1,1,1, 0, 0, "RGB Color Space");
1800                 uiDefButS(block, ROW,B_NODE_EXEC+node->nr,"HSV",
1801                         butr->xmin+sx,butr->ymin+60,sx,20,&node->custom1,1,2, 0, 0, "HSV Color Space");
1802                 uiDefButS(block, ROW,B_NODE_EXEC+node->nr,"YUV",
1803                         butr->xmin+2*sx,butr->ymin+60,sx,20,&node->custom1,1,3, 0, 0, "YUV Color Space");
1804                 uiDefButS(block, ROW,B_NODE_EXEC+node->nr,"YCC",
1805                         butr->xmin+3*sx,butr->ymin+60,sx,20,&node->custom1,1,4, 0, 0, "YCbCr Color Space");
1806         
1807                 if (node->custom1==1) {
1808                         c1="R"; c2="G"; c3="B";
1809                 }
1810                 else if(node->custom1==2){
1811                         c1="H"; c2="S"; c3="V";
1812                 }
1813                 else if(node->custom1==3){
1814                         c1="Y"; c2="U"; c3="V";
1815                 }
1816                 else { // if(node->custom1==4){
1817                         c1="Y"; c2="Cb"; c3="Cr";
1818                 }
1819         
1820                 /*channel selector */
1821                 uiDefButS(block, ROW, B_NODE_EXEC+node->nr, c1,
1822                         butr->xmin,butr->ymin+40,cx,20,&node->custom2,1, 1, 0, 0, "Channel 1");
1823                 uiDefButS(block, ROW, B_NODE_EXEC+node->nr, c2,
1824                         butr->xmin+cx,butr->ymin+40,cx,20,&node->custom2,1, 2, 0, 0, "Channel 2");
1825                 uiDefButS(block, ROW, B_NODE_EXEC+node->nr, c3,
1826                         butr->xmin+cx+cx,butr->ymin+40,cx,20,&node->custom2, 1, 3, 0, 0, "Channel 3");
1827         
1828                 /*tolerance sliders */
1829                 uiDefButF(block, NUMSLI, B_NODE_EXEC+node->nr, "High ", 
1830                         butr->xmin, butr->ymin+20.0, butr->xmax-butr->xmin, 20,
1831                         &c->t1, 0.0f, 1.0f, 100, 0, "Values higher than this setting are 100% opaque");
1832                 uiDefButF(block, NUMSLI, B_NODE_EXEC+node->nr, "Low ", 
1833                         butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20,
1834                         &c->t2, 0.0f, 1.0f, 100, 0, "Values lower than this setting are 100% keyed");
1835                 uiBlockEndAlign(block);
1836         
1837                 /*keep t2 (low) less than t1 (high) */
1838                 if(c->t2 > c->t1) {
1839                         c->t2=c->t1;
1840                 }
1841         }
1842         return 80;
1843 }
1844
1845 static int node_composit_buts_luma_matte(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
1846 {
1847         if(block) {
1848                 NodeChroma *c=node->storage;
1849         
1850                 /*tolerance sliders */
1851                 uiDefButF(block, NUMSLI, B_NODE_EXEC+node->nr, "High ", 
1852                         butr->xmin, butr->ymin+20.0, butr->xmax-butr->xmin, 20,
1853                         &c->t1, 0.0f, 1.0f, 100, 0, "Values higher than this setting are 100% opaque");
1854                 uiDefButF(block, NUMSLI, B_NODE_EXEC+node->nr, "Low ", 
1855                         butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20,
1856                         &c->t2, 0.0f, 1.0f, 100, 0, "Values lower than this setting are 100% keyed");
1857                 uiBlockEndAlign(block);
1858         
1859                 /*keep t2 (low) less than t1 (high) */
1860                 if(c->t2 > c->t1) {
1861                         c->t2=c->t1;
1862                 }
1863         }
1864         return 40;
1865 }
1866
1867 static int node_composit_buts_map_uv(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
1868 {
1869         if(block) {
1870                 uiDefButS(block, NUM, B_NODE_EXEC+node->nr, "Alpha:",
1871                                   butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20, 
1872                                   &node->custom1, 0, 100, 0, 0, "Conversion percentage of UV differences to Alpha");
1873         }
1874         return 20;
1875 }
1876
1877 static int node_composit_buts_id_mask(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
1878 {
1879         if(block) {
1880                 uiDefButS(block, NUM, B_NODE_EXEC+node->nr, "ID:",
1881                                   butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20, 
1882                                   &node->custom1, 0, 10000, 0, 0, "Pass Index number to convert to Alpha");
1883         }
1884         return 20;
1885 }
1886
1887 /* allocate sufficient! */
1888 static void node_imagetype_string(char *str)
1889 {
1890         str += sprintf(str, "Save Image as: %%t|");
1891         str += sprintf(str, "Targa %%x%d|", R_TARGA);
1892         str += sprintf(str, "Targa Raw %%x%d|", R_RAWTGA);
1893         str += sprintf(str, "PNG %%x%d|", R_PNG);
1894         str += sprintf(str, "BMP %%x%d|", R_BMP);
1895         str += sprintf(str, "Jpeg %%x%d|", R_JPEG90);
1896         str += sprintf(str, "Iris %%x%d|", R_IRIS);
1897         str += sprintf(str, "Radiance HDR %%x%d|", R_RADHDR);
1898         str += sprintf(str, "Cineon %%x%d|", R_CINEON);
1899         str += sprintf(str, "DPX %%x%d|", R_DPX);
1900         str += sprintf(str, "OpenEXR %%x%d", R_OPENEXR);
1901 }
1902
1903 static void node_set_image_cb(void *ntree_v, void *node_v)
1904 {
1905         bNodeTree *ntree= ntree_v;
1906         bNode *node= node_v;
1907         
1908         nodeSetActive(ntree, node);
1909 }
1910
1911 static int node_composit_buts_file_output(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
1912 {
1913         if(block) {
1914                 NodeImageFile *nif= node->storage;
1915                 uiBut *bt;
1916                 short x= (short)butr->xmin;
1917                 short y= (short)butr->ymin;
1918                 short w= (short)butr->xmax-butr->xmin;
1919                 char str[320];
1920                 
1921                 node_imagetype_string(str);
1922                 
1923                 uiBlockBeginAlign(block);
1924                 
1925                 bt = uiDefIconBut(block, BUT, B_NODE_SETIMAGE, ICON_FILESEL,
1926                                   x, y+60, 20, 20,
1927                                   0, 0, 0, 0, 0, "Open Fileselect to get Backbuf image");
1928                 uiButSetFunc(bt, node_set_image_cb, ntree, node);
1929                 
1930                 uiDefBut(block, TEX, B_NOP, "",
1931                                   20+x, y+60, w-20, 20, 
1932                                   nif->name, 0.0f, 240.0f, 0, 0, "");
1933                 
1934                 uiDefButS(block, MENU, B_NOP, str,
1935                                   x, y+40, w, 20, 
1936                                   &nif->imtype, 0.0f, 1.0f, 0, 0, "");
1937                 
1938                 if(nif->imtype==R_OPENEXR) {
1939                         uiDefButBitS(block, TOG, R_OPENEXR_HALF, B_REDR, "Half",        
1940                                                 x, y+20, w/2, 20, 
1941                                                 &nif->subimtype, 0, 0, 0, 0, "");
1942
1943                         uiDefButS(block, MENU,B_NOP, "Codec %t|None %x0|Pxr24 (lossy) %x1|ZIP (lossless) %x2|PIZ (lossless) %x3|RLE (lossless) %x4",  
1944                                                 x+w/2, y+20, w/2, 20, 
1945                                                 &nif->codec, 0, 0, 0, 0, "");
1946                 }
1947                 else {
1948                         uiDefButS(block, NUM, B_NOP, "Quality: ",
1949                                   x, y+20, w, 20, 
1950                                   &nif->quality, 10.0f, 100.0f, 10, 0, "");
1951                 }
1952                 
1953                 /* start frame, end frame */
1954                 uiDefButI(block, NUM, B_NODE_EXEC+node->nr, "SFra: ", 
1955                                   x, y, w/2, 20, 
1956                                   &nif->sfra, 1, MAXFRAMEF, 10, 0, "");
1957                 uiDefButI(block, NUM, B_NODE_EXEC+node->nr, "EFra: ", 
1958                                   x+w/2, y, w/2, 20, 
1959                                   &nif->efra, 1, MAXFRAMEF, 10, 0, "");
1960                 
1961         }
1962         return 80;
1963 }
1964
1965 static void node_scale_cb(void *node_v, void *unused_v)
1966 {
1967         bNode *node= node_v;
1968         bNodeSocket *nsock;
1969
1970         /* check the 2 inputs, and set them to reasonable values */
1971         for(nsock= node->inputs.first; nsock; nsock= nsock->next) {
1972                 if(ELEM(node->custom1, CMP_SCALE_RELATIVE, CMP_SCALE_SCENEPERCENT))
1973                         nsock->ns.vec[0]= 1.0;
1974                 else {
1975                         if(nsock->next==NULL)
1976                                 nsock->ns.vec[0]= (float)G.scene->r.ysch;
1977                         else
1978                                 nsock->ns.vec[0]= (float)G.scene->r.xsch;
1979                 }
1980         }       
1981 }
1982
1983 static int node_composit_buts_scale(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
1984 {
1985         if(block) {
1986                 uiBut *bt= uiDefButS(block, MENU, B_NODE_EXEC+node->nr, "Relative %x0|Absolute %x1|Scene Size % %x2|",
1987                                   butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20, 
1988                                   &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");
1989                 uiButSetFunc(bt, node_scale_cb, node, NULL);
1990         }
1991         return 20;
1992 }
1993
1994 static int node_composit_buts_invert(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr) 
1995 {
1996         if(block) {
1997                 uiBlockBeginAlign(block);
1998                 uiDefButBitS(block, TOG, CMP_CHAN_RGB, B_NODE_EXEC+node->nr, "RGB",
1999                                          butr->xmin, butr->ymin, (butr->xmax-butr->xmin)/2, 20, 
2000                                          &node->custom1, 0, 0, 0, 0, "");
2001                 uiDefButBitS(block, TOG, CMP_CHAN_A, B_NODE_EXEC+node->nr, "A",
2002                                          butr->xmin+(butr->xmax-butr->xmin)/2, butr->ymin, (butr->xmax-butr->xmin)/2, 20, 
2003                                          &node->custom1, 0, 0, 0, 0, "");
2004                 uiBlockEndAlign(block);
2005         }
2006         return 20;      
2007 }
2008
2009 static int node_composit_buts_premulkey(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
2010 {
2011         if(block) {
2012                 uiBut *bt;
2013                 
2014                 /* blend type */
2015                 bt=uiDefButS(block, MENU, B_NODE_EXEC+node->nr, "Key to Premul %x0|Premul to Key %x1",
2016                                          butr->xmin, butr->ymin, butr->xmax-butr->xmin, 20, 
2017                                          &node->custom1, 0, 0, 0, 0, "Conversion between premultiplied alpha and key alpha");
2018         }
2019         return 20;
2020 }
2021
2022 /* only once called */
2023 static void node_composit_set_butfunc(bNodeType *ntype)
2024 {
2025         switch(ntype->type) {
2026                 /* case NODE_GROUP:      note, typeinfo for group is generated... see "XXX ugly hack" */
2027
2028                 case CMP_NODE_IMAGE:
2029                         ntype->butfunc= node_composit_buts_image;
2030                         break;
2031                 case CMP_NODE_R_LAYERS:
2032                         ntype->butfunc= node_composit_buts_renderlayers;
2033                         break;
2034                 case CMP_NODE_NORMAL:
2035                         ntype->butfunc= node_buts_normal;
2036                         break;
2037                 case CMP_NODE_CURVE_VEC:
2038                         ntype->butfunc= node_buts_curvevec;
2039                         break;
2040                 case CMP_NODE_CURVE_RGB:
2041                         ntype->butfunc= node_buts_curvecol;
2042                         break;
2043                 case CMP_NODE_VALUE:
2044                         ntype->butfunc= node_buts_value;
2045                         break;
2046                 case CMP_NODE_RGB:
2047                         ntype->butfunc= node_buts_rgb;
2048                         break;
2049                 case CMP_NODE_FLIP:
2050                         ntype->butfunc= node_composit_buts_flip;
2051                         break;
2052                 case CMP_NODE_SPLITVIEWER:
2053                         ntype->butfunc= node_composit_buts_splitviewer;
2054                         break;
2055                 case CMP_NODE_MIX_RGB:
2056                         ntype->butfunc= node_buts_mix_rgb;
2057                         break;
2058                 case CMP_NODE_VALTORGB:
2059                         ntype->butfunc= node_buts_valtorgb;
2060                         break;
2061                 case CMP_NODE_CROP:
2062                         ntype->butfunc= node_composit_buts_crop;
2063                         break;
2064                 case CMP_NODE_BLUR:
2065                         ntype->butfunc= node_composit_buts_blur;
2066                         break;
2067                 case CMP_NODE_DBLUR:
2068                         ntype->butfunc= node_composit_buts_dblur;
2069                         break;
2070                 case CMP_NODE_BILATERALBLUR:
2071                         ntype->butfunc= node_composit_buts_bilateralblur;
2072                         break;
2073                 /* qdn: defocus node */
2074                 case CMP_NODE_DEFOCUS:
2075                         ntype->butfunc = node_composit_buts_defocus;
2076                         break;
2077                 /* qdn: glare node */
2078                 case CMP_NODE_GLARE:
2079                         ntype->butfunc = node_composit_buts_glare;
2080                         break;
2081                 /* qdn: tonemap node */
2082                 case CMP_NODE_TONEMAP:
2083                         ntype->butfunc = node_composit_buts_tonemap;
2084                         break;
2085                 /* qdn: lens distortion node */
2086                 case CMP_NODE_LENSDIST:
2087                         ntype->butfunc = node_composit_buts_lensdist;
2088                         break;
2089                 case CMP_NODE_VECBLUR:
2090                         ntype->butfunc= node_composit_buts_vecblur;
2091                         break;
2092                 case CMP_NODE_FILTER:
2093                         ntype->butfunc= node_composit_buts_filter;
2094                         break;
2095                 case CMP_NODE_MAP_VALUE:
2096                         ntype->butfunc= node_composit_buts_map_value;
2097                         break;
2098                 case CMP_NODE_TIME:
2099                         ntype->butfunc= node_buts_time;
2100                         break;
2101                 case CMP_NODE_ALPHAOVER:
2102                         ntype->butfunc= node_composit_buts_alphaover;
2103                         break;
2104                 case CMP_NODE_HUE_SAT:
2105                         ntype->butfunc= node_composit_buts_hue_sat;
2106                         break;
2107                 case CMP_NODE_TEXTURE:
2108                         ntype->butfunc= node_buts_texture;
2109                         break;
2110                 case CMP_NODE_DILATEERODE:
2111                         ntype->butfunc= node_composit_buts_dilateerode;
2112                         break;
2113                 case CMP_NODE_OUTPUT_FILE:
2114                         ntype->butfunc= node_composit_buts_file_output;
2115                         break;
2116         
2117                 case CMP_NODE_DIFF_MATTE:
2118                         ntype->butfunc=node_composit_buts_diff_matte;
2119                         break;
2120                 case CMP_NODE_COLOR_SPILL:
2121                         ntype->butfunc=node_composit_buts_color_spill;
2122                         break;
2123                 case CMP_NODE_CHROMA:
2124                         ntype->butfunc=node_composit_buts_chroma_matte;
2125                         break;
2126                 case CMP_NODE_SCALE:
2127                         ntype->butfunc= node_composit_buts_scale;
2128                         break;
2129                 case CMP_NODE_CHANNEL_MATTE:
2130                         ntype->butfunc= node_composit_buts_channel_matte;
2131                         break;
2132                 case CMP_NODE_LUMA_MATTE:
2133                         ntype->butfunc= node_composit_buts_luma_matte;
2134                         break;
2135                 case CMP_NODE_MAP_UV:
2136                         ntype->butfunc= node_composit_buts_map_uv;
2137                         break;
2138                 case CMP_NODE_ID_MASK:
2139                         ntype->butfunc= node_composit_buts_id_mask;
2140                         break;
2141                 case CMP_NODE_MATH:
2142                         ntype->butfunc= node_buts_math;
2143                         break;
2144                 case CMP_NODE_INVERT:
2145                         ntype->butfunc= node_composit_buts_invert;
2146                         break;
2147                 case CMP_NODE_PREMULKEY:
2148                         ntype->butfunc= node_composit_buts_premulkey;
2149                         break;
2150                 default:
2151                         ntype->butfunc= NULL;
2152         }
2153 }
2154
2155 /* ****************** BUTTON CALLBACKS FOR TEXTURE NODES ***************** */
2156
2157 static int node_texture_buts_bricks(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
2158 {
2159         if(block) {
2160                 short w = butr->xmax-butr->xmin;
2161                 short ofw = 32;
2162                 
2163                 uiBlockBeginAlign(block);
2164                 
2165                 /* Offset */
2166                 uiDefButF(
2167                         block, NUM, B_NODE_EXEC+node->nr, "Offset",
2168                         butr->xmin, butr->ymin+20, w-ofw, 20,
2169                         &node->custom3,
2170                         0, 1, 0.25, 2,
2171                         "Offset amount" );
2172                 uiDefButS(
2173                         block, NUM, B_NODE_EXEC+node->nr, "",
2174                         butr->xmin+w-ofw, butr->ymin+20, ofw, 20,
2175                         &node->custom1,
2176                         2, 99, 0, 0,
2177                         "Offset every N rows" );
2178                 
2179                 /* Squash */
2180                 uiDefButF(
2181                         block, NUM, B_NODE_EXEC+node->nr, "Squash",
2182                         butr->xmin, butr->ymin+0, w-ofw, 20,
2183                         &node->custom4,
2184                         0, 99, 0.25, 2,
2185                         "Stretch amount" );
2186                 uiDefButS(
2187                         block, NUM, B_NODE_EXEC+node->nr, "",
2188                         butr->xmin+w-ofw, butr->ymin+0, ofw, 20,
2189                         &node->custom2,
2190                         2, 99, 0, 0,
2191                         "Stretch every N rows" );
2192                 
2193                 uiBlockEndAlign(block);
2194         }
2195         return 40;
2196 }
2197
2198 /* Copied from buttons_shading.c -- needs unifying */
2199 static char* noisebasis_menu()
2200 {
2201         static char nbmenu[256];
2202         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);
2203         return nbmenu;
2204 }
2205
2206 static int node_texture_buts_proc(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
2207 {
2208         Tex *tex = (Tex *)node->storage;
2209         short x,y,w,h;
2210         
2211         if( block ) {
2212                 x = butr->xmin;
2213                 y = butr->ymin;
2214                 w = butr->xmax - x;
2215                 h = butr->ymax - y;
2216         }
2217         
2218         switch( tex->type ) {
2219                 case TEX_BLEND:
2220                         if( block ) {
2221                                 uiBlockBeginAlign( block );
2222                                 uiDefButS( block, MENU, B_NODE_EXEC+node->nr,
2223                                         "Linear %x0|Quad %x1|Ease %x2|Diag %x3|Sphere %x4|Halo %x5|Radial %x6",
2224                                         x, y+20, w, 20, &tex->stype, 0, 1, 0, 0, "Blend Type" );
2225                                 uiDefButBitS(block, TOG, TEX_FLIPBLEND, B_NODE_EXEC+node->nr, "Flip XY", x, y, w, 20,
2226                                         &tex->flag, 0, 0, 0, 0, "Flips the direction of the progression 90 degrees");
2227                                 uiBlockEndAlign( block );
2228                         }
2229                         return 40;
2230                         
2231                         
2232                 case TEX_MARBLE:
2233                         if( block ) {
2234                                 uiBlockBeginAlign(block);
2235                         
2236                                 uiDefButS(block, ROW, B_NODE_EXEC+node->nr, "Soft",       0*w/3+x, 40+y, w/3, 18, &tex->stype, 2.0, (float)TEX_SOFT, 0, 0, "Uses soft marble"); 
2237                                 uiDefButS(block, ROW, B_NODE_EXEC+node->nr, "Sharp",      1*w/3+x, 40+y, w/3, 18, &tex->stype, 2.0, (float)TEX_SHARP, 0, 0, "Uses more clearly defined marble"); 
2238                                 uiDefButS(block, ROW, B_NODE_EXEC+node->nr, "Sharper",    2*w/3+x, 40+y, w/3, 18, &tex->stype, 2.0, (float)TEX_SHARPER, 0, 0, "Uses very clearly defined marble"); 
2239                                 
2240                                 uiDefButS(block, ROW, B_NODE_EXEC+node->nr, "Soft noise", 0*w/2+x, 20+y, w/2, 19, &tex->noisetype, 12.0, (float)TEX_NOISESOFT, 0, 0, "Generates soft noise");
2241                                 uiDefButS(block, ROW, B_NODE_EXEC+node->nr, "Hard noise", 1*w/2+x, 20+y, w/2, 19, &tex->noisetype, 12.0, (float)TEX_NOISEPERL, 0, 0, "Generates hard noise");
2242                                 
2243                                 uiDefButS(block, ROW, B_NODE_EXEC+node->nr, "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."); 
2244                                 uiDefButS(block, ROW, B_NODE_EXEC+node->nr, "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"); 
2245                                 uiDefButS(block, ROW, B_NODE_EXEC+node->nr, "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"); 
2246             
2247                                 uiBlockEndAlign(block);
2248                         }
2249                         return 60;
2250                         
2251                 case TEX_WOOD:
2252                         if( block ) {
2253                                 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");
2254                                 
2255                                 uiBlockBeginAlign(block);
2256                                 uiDefButS(block, ROW, B_TEXPRV,             "Bands",     x,  40+y, w/2, 18, &tex->stype, 2.0, (float)TEX_BANDNOISE, 0, 0, "Uses standard noise"); 
2257                                 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"); 
2258                                 
2259                                 uiDefButS(block, ROW, B_NODE_EXEC+node->nr, "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."); 
2260                                 uiDefButS(block, ROW, B_NODE_EXEC+node->nr, "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"); 
2261                                 uiDefButS(block, ROW, B_NODE_EXEC+node->nr, "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");
2262                                 
2263                                 uiDefButS(block, ROW, B_NODE_EXEC+node->nr, "Soft noise", 0*w/2+x, 0+y, w/2, 19, &tex->noisetype, 12.0, (float)TEX_NOISESOFT, 0, 0, "Generates soft noise");
2264                                 uiDefButS(block, ROW, B_NODE_EXEC+node->nr, "Hard noise", 1*w/2+x, 0+y, w/2, 19, &tex->noisetype, 12.0, (float)TEX_NOISEPERL, 0, 0, "Generates hard noise");
2265                                 uiBlockEndAlign(block);
2266                         }
2267                         return 80; 
2268                         
2269                 case TEX_CLOUDS:
2270                         if( block ) {
2271                                 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");
2272                                 
2273                                 uiBlockBeginAlign(block);
2274                                 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"); 
2275                                 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"); 
2276                                 uiDefButS(block, ROW, B_TEXPRV, "Soft",      x, y+20, w/2, 18, &tex->noisetype, 12.0, (float)TEX_NOISESOFT, 0, 0, "Generates soft noise");
2277                                 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");
2278                                 uiBlockEndAlign(block);
2279                                 
2280                                 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");
2281                         }
2282                         return 80;
2283                         
2284                 case TEX_DISTNOISE:
2285                         if( block ) {
2286                                 uiBlockBeginAlign(block);
2287                                 uiDefButS(block, MENU, B_TEXPRV, noisebasis_menu(), x, y+18, w, 18, &tex->noisebasis2, 0,0,0,0, "Sets the noise basis to distort");
2288                                 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");
2289                                 uiBlockEndAlign(block);
2290                         }
2291                         return 36;
2292         }
2293         return 0;
2294 }
2295
2296 static int node_texture_buts_image(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
2297 {
2298         char *strp;
2299         uiBut *bt;
2300         
2301         if( block ) {
2302                 uiBlockBeginAlign(block);
2303                 uiBlockSetCol(block, TH_BUT_SETTING2);
2304                 
2305                 /* browse button */
2306                 IMAnames_to_pupstring(&strp, NULL, "LOAD NEW %x32767", &(G.main->image), NULL, NULL);
2307                 node->menunr= 0;
2308                 bt= uiDefButS(block, MENU, B_NOP, strp, 
2309                                           butr->xmin, butr->ymin, 19, 19, 
2310                                           &node->menunr, 0, 0, 0, 0, "Browses existing choices");
2311                 uiButSetFunc(bt, node_browse_image_cb, ntree, node);
2312                 if(strp) MEM_freeN(strp);
2313                 
2314                 /* Add New button */
2315                 if(node->id==NULL) {
2316                         bt= uiDefBut(block, BUT, B_NODE_LOADIMAGE, "Load New",
2317                                                  butr->xmin+19, butr->ymin, (short)(butr->xmax-butr->xmin-19.0f), 19, 
2318                                                  NULL, 0.0, 0.0, 0, 0, "Add new Image");
2319                         uiButSetFunc(bt, node_active_cb, ntree, node);
2320                         uiBlockSetCol(block, TH_AUTO);
2321                 }
2322                 else {
2323                         /* name button */
2324                         short xmin= (short)butr->xmin, xmax= (short)butr->xmax;
2325                         short width= xmax - xmin - 19;
2326                         
2327                         bt= uiDefBut(block, TEX, B_NOP, "IM:",
2328                                                  xmin+19, butr->ymin, width, 19, 
2329                                                  node->id->name+2, 0.0, 19.0, 0, 0, "Image name");
2330                         uiButSetFunc(bt, node_ID_title_cb, node, NULL);
2331                 }
2332         }
2333         return 20;
2334 }
2335
2336 static int node_texture_buts_output(uiBlock *block, bNodeTree *ntree, bNode *node, rctf *butr)
2337 {
2338         if( block ) {
2339                 uiBut *bt;
2340                 short width;
2341                 char *name = ((TexNodeOutput*)node->storage)->name;
2342                 
2343                 uiBlockBeginAlign(block);
2344                 
2345                 width = (short)(butr->xmax - butr->xmin);
2346                 
2347                 bt = uiDefBut(
2348                         block, TEX, B_NOP,
2349                         "Name:",
2350                         butr->xmin, butr->ymin,
2351                         width, 19, 
2352                         name, 0, 31,
2353                         0, 0, 
2354                         "Name this output"
2355                 );
2356                 
2357                 uiBlockEndAlign(block);
2358         }
2359         return 19;
2360 }
2361
2362 /* only once called */
2363 static void node_texture_set_butfunc(bNodeType *ntype)
2364 {
2365         if( ntype->type >= TEX_NODE_PROC && ntype->type < TEX_NODE_PROC_MAX ) {
2366                 ntype->butfunc = node_texture_buts_proc;
2367         }
2368         else switch(ntype->type) {
2369                 
2370                 case TEX_NODE_MATH:
2371                         ntype->butfunc = node_buts_math;
2372                         break;
2373                 
2374                 case TEX_NODE_MIX_RGB:
2375                         ntype->butfunc = node_buts_mix_rgb;
2376                         break;
2377                         
2378                 case TEX_NODE_VALTORGB:
2379                         ntype->butfunc = node_buts_valtorgb;
2380                         break;
2381                         
2382                 case TEX_NODE_CURVE_RGB:
2383                         ntype->butfunc= node_buts_curvecol;
2384                         break;
2385                         
2386                 case TEX_NODE_CURVE_TIME:
2387                         ntype->butfunc = node_buts_time;
2388                         break;
2389                         
2390                 case TEX_NODE_TEXTURE:
2391                         ntype->butfunc = node_buts_texture;
2392                         break;
2393                         
2394                 case TEX_NODE_BRICKS:
2395                         ntype->butfunc = node_texture_buts_bricks;
2396                         break;
2397                         
2398                 case TEX_NODE_IMAGE:
2399                         ntype->butfunc = node_texture_buts_image;
2400                         break;
2401                         
2402                 case TEX_NODE_OUTPUT:
2403                         ntype->butfunc = node_texture_buts_output;
2404                         break;
2405                         
2406                 default:
2407                         ntype->butfunc= NULL;
2408         }
2409 }
2410
2411 /* ******* init draw callbacks for all tree types, only called in usiblender.c, once ************* */
2412
2413 void init_node_butfuncs(void)
2414 {
2415         bNodeType *ntype;
2416         
2417         /* shader nodes */
2418         ntype= node_all_shaders.first;
2419         while(ntype) {
2420                 node_shader_set_butfunc(ntype);
2421                 ntype= ntype->next;
2422         }
2423         /* composit nodes */
2424         ntype= node_all_composit.first;
2425         while(ntype) {
2426                 node_composit_set_butfunc(ntype);
2427                 ntype= ntype->next;
2428         }
2429         ntype = node_all_textures.first;
2430         while(ntype) {
2431                 node_texture_set_butfunc(ntype);
2432                 ntype= ntype->next;
2433         }
2434 }
2435
2436 /* ************** Generic drawing ************** */
2437
2438 void node_rename_but(char *s)
2439 {
2440         uiBlock *block;
2441         ListBase listb={0, 0};
2442         int dy, x1, y1, sizex=80, sizey=30;
2443         short pivot[2], mval[2], ret=0;
2444         
2445         getmouseco_sc(mval);
2446
2447         pivot[0]= CLAMPIS(mval[0], (sizex+10), G.curscreen->sizex-30);
2448         pivot[1]= CLAMPIS(mval[1], (sizey/2)+10, G.curscreen->sizey-(sizey/2)-10);
2449         
2450         if (pivot[0]!=mval[0] || pivot[1]!=mval[1])
2451                 warp_pointer(pivot[0], pivot[1]);
2452
2453         mywinset(G.curscreen->mainwin);
2454         
2455         x1= pivot[0]-sizex+10;
2456         y1= pivot[1]-sizey/2;
2457         dy= sizey/2;
2458         
2459         block= uiNewBlock(&listb, "button", UI_EMBOSS, UI_HELV, G.curscreen->mainwin);
2460         uiBlockSetFlag(block, UI_BLOCK_LOOP|UI_BLOCK_REDRAW|UI_BLOCK_NUMSELECT|UI_BLOCK_ENTER_OK);
2461         
2462         /* buttons have 0 as return event, to prevent menu to close on hotkeys */
2463         uiBlockBeginAlign(block);
2464         
2465         uiDefBut(block, TEX, B_NOP, "Name: ", (short)(x1),(short)(y1+dy), 150, 19, s, 0.0, 19.0, 0, 0, "Node user name");
2466         
2467         uiBlockEndAlign(block);
2468
2469         uiDefBut(block, BUT, 32767, "OK", (short)(x1+150), (short)(y1+dy), 29, 19, NULL, 0, 0, 0, 0, "");
2470
2471         uiBoundsBlock(block, 2);
2472
2473         ret= uiDoBlocks(&listb, 0, 0);
2474 }
2475
2476
2477 static void draw_nodespace_grid(SpaceNode *snode)
2478 {
2479         float start, step= 25.0f;
2480
2481         UI_ThemeColorShade(TH_BACK, -10);
2482         
2483         start= snode->v2d.cur.xmin -fmod(snode->v2d.cur.xmin, step);
2484         
2485         glBegin(GL_LINES);
2486         for(; start<snode->v2d.cur.xmax; start+=step) {
2487                 glVertex2f(start, snode->v2d.cur.ymin);
2488                 glVertex2f(start, snode->v2d.cur.ymax);
2489         }
2490
2491         start= snode->v2d.cur.ymin -fmod(snode->v2d.cur.ymin, step);
2492         for(; start<snode->v2d.cur.ymax; start+=step) {
2493                 glVertex2f(snode->v2d.cur.xmin, start);
2494                 glVertex2f(snode->v2d.cur.xmax, start);
2495         }
2496         
2497         /* X and Y axis */
2498         UI_ThemeColorShade(TH_BACK, -18);
2499         glVertex2f(0.0f, snode->v2d.cur.ymin);
2500         glVertex2f(0.0f, snode->v2d.cur.ymax);
2501         glVertex2f(snode->v2d.cur.xmin, 0.0f);
2502         glVertex2f(snode->v2d.cur.xmax, 0.0f);
2503         
2504         glEnd();
2505 }
2506
2507 static void draw_nodespace_back_pix(ScrArea *sa, SpaceNode *snode)
2508 {
2509         
2510         draw_nodespace_grid(snode);
2511         
2512         if((snode->flag & SNODE_BACKDRAW) && snode->treetype==NTREE_COMPOSIT) {
2513                 Image *ima= BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
2514                 ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL);
2515                 if(ibuf) {
2516                         int x, y; 
2517                         /* somehow the offset has to be calculated inverse */
2518                         
2519                         glaDefine2DArea(&sa->winrct);
2520                         /* ortho at pixel level curarea */
2521                         myortho2(-0.375, sa->winx-0.375, -0.375, sa->winy-0.375);
2522                         
2523                         x = (sa->winx-ibuf->x)/2 + snode->xof;
2524                         y = (sa->winy-ibuf->y)/2 + snode->yof;
2525                         
2526                         if(ibuf->rect)
2527                                 glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_UNSIGNED_BYTE, ibuf->rect);
2528                         else if(ibuf->channels==4)
2529                                 glaDrawPixelsSafe(x, y, ibuf->x, ibuf->y, ibuf->x, GL_RGBA, GL_FLOAT, ibuf->rect_float);
2530                         
2531                         /* sort this out, this should not be needed */
2532                         myortho2(snode->v2d.cur.xmin, snode->v2d.cur.xmax, snode->v2d.cur.ymin, snode->v2d.cur.ymax);
2533                         bwin_clear_viewmat(sa->win);    /* clear buttons view */
2534                         glLoadIdentity();
2535                 }
2536         }
2537 }
2538
2539 #if 0
2540 /* note: needs to be userpref or opengl profile option */
2541 static void draw_nodespace_back_tex(ScrArea *sa, SpaceNode *snode)
2542 {
2543
2544         draw_nodespace_grid(snode);
2545         
2546         if(snode->flag & SNODE_BACKDRAW) {
2547                 Image *ima= BKE_image_verify_viewer(IMA_TYPE_COMPOSITE, "Viewer Node");
2548                 ImBuf *ibuf= BKE_image_get_ibuf(ima, NULL);
2549                 if(ibuf) {
2550                         int x, y;
2551                         float zoom = 1.0;
2552
2553                         glMatrixMode(GL_PROJECTION);
2554                         glPushMatrix();
2555                         glMatrixMode(GL_MODELVIEW);
2556                         glPushMatrix();
2557                         
2558                         glaDefine2DArea(&sa->winrct);
2559
2560                         if(ibuf->x > sa->winx || ibuf->y > sa->winy) {
2561                                 float zoomx, zoomy;
2562                                 zoomx= (float)sa->winx/ibuf->x;
2563                                 zoomy= (float)sa->winy/ibuf->y;
2564                                 zoom = MIN2(zoomx, zoomy);
2565                         }
2566                         
2567                         x = (sa->winx-zoom*ibuf->x)/2 + snode->xof;
2568                         y = (sa->winy-zoom*ibuf->y)/2 + snode->yof;
2569
2570                         glPixelZoom(zoom, zoom);
2571
2572                         glColor4f(1.0, 1.0, 1.0, 1.0);
2573                         if(ibuf->rect)
2574                                 glaDrawPixelsTex(x, y, ibuf->x, ibuf->y, GL_UNSIGNED_BYTE, ibuf->rect);
2575                         else if(ibuf->channels==4)
2576                                 glaDrawPixelsTex(x, y, ibuf->x, ibuf->y, GL_FLOAT, ibuf->rect_float);
2577
2578                         glPixelZoom(1.0, 1.0);
2579
2580                         glMatrixMode(GL_PROJECTION);
2581                         glPopMatrix();
2582                         glMatrixMode(GL_MODELVIEW);
2583                         glPopMatrix();
2584                 }
2585         }
2586 }
2587 #endif
2588
2589
2590 #endif
2591
2592 void node_draw_link_bezier(View2D *v2d, float vec[4][3], int th_col1, int th_col2, int do_shaded)
2593 {
2594         float dist;
2595         
2596         dist= 0.5f*ABS(vec[0][0] - vec[3][0]);
2597         
2598         
2599         /* check direction later, for top sockets */
2600         vec[1][0]= vec[0][0]+dist;
2601         vec[1][1]= vec[0][1];
2602         
2603         vec[2][0]= vec[3][0]-dist;
2604         vec[2][1]= vec[3][1];
2605         // printf("-> %f   %f   %f   %f   %f\n", dist, vec[0][0], vec[3][0], vec[1][0], vec[2][0]);
2606         
2607         if( MIN4(vec[0][0], vec[1][0], vec[2][0], vec[3][0]) > v2d->cur.xmax); /* clipped */    
2608         else if ( MAX4(vec[0][0], vec[1][0], vec[2][0], vec[3][0]) < v2d->cur.xmin); /* clipped */
2609         else {
2610                 float curve_res = 24, spline_step = 0.0f;
2611                 
2612                 /* we can reuse the dist variable here to increment the GL curve eval amount*/
2613                 dist = 1.0f/curve_res;
2614                 
2615                 glMap1f(GL_MAP1_VERTEX_3, 0.0, 1.0, 3, 4, vec[0]);
2616                 glBegin(GL_LINE_STRIP);
2617                 while (spline_step < 1.000001f) {
2618                         if(do_shaded)
2619                                 UI_ThemeColorBlend(th_col1, th_col2, spline_step);
2620                         glEvalCoord1f(spline_step);
2621                         spline_step += dist;
2622                 }
2623                 glEnd();
2624         }
2625         
2626 }
2627
2628 /* note; this is used for fake links in groups too */
2629 void node_draw_link(View2D *v2d, SpaceNode *snode, bNodeLink *link)
2630 {
2631         float vec[4][3];
2632         float mx=0.0f, my=0.0f;
2633         int do_shaded= 1, th_col1= TH_WIRE, th_col2= TH_WIRE;
2634         
2635         if(link->fromnode==NULL && link->tonode==NULL)
2636                 return;
2637         
2638         /* XXX fix -> notifier thingymajiggle this is dragging link */
2639         if(link->fromnode==NULL || link->tonode==NULL) {
2640                 // short mval[2];
2641                 // XXX getmouseco_areawin(mval);
2642                 // XXX areamouseco_to_ipoco(v2d, mval, &mx, &my);
2643                 UI_ThemeColor(TH_WIRE);
2644                 do_shaded= 0;
2645         }
2646         else {
2647                 /* going to give issues once... */
2648                 if(link->tosock->flag & SOCK_UNAVAIL)
2649                         return;
2650                 if(link->fromsock->flag & SOCK_UNAVAIL)
2651                         return;
2652                 
2653                 /* a bit ugly... but thats how we detect the internal group links */
2654                 if(link->fromnode==link->tonode) {
2655                         UI_ThemeColorBlend(TH_BACK, TH_WIRE, 0.25f);
2656                         do_shaded= 0;
2657                 }
2658                 else {
2659                         /* check cyclic */
2660                         if(link->fromnode->level >= link->tonode->level && link->tonode->level!=0xFFF) {
2661                                 if(link->fromnode->flag & SELECT)
2662                                         th_col1= TH_EDGE_SELECT;
2663                                 if(link->tonode->flag & SELECT)
2664                                         th_col2= TH_EDGE_SELECT;
2665                         }                               
2666                         else {
2667                                 UI_ThemeColor(TH_REDALERT);
2668                                 do_shaded= 0;
2669                         }
2670                 }
2671         }
2672         
2673         vec[0][2]= vec[1][2]= vec[2][2]= vec[3][2]= 0.0; /* only 2d spline, set the Z to 0*/
2674         
2675         /* in v0 and v3 we put begin/end points */
2676         if(link->fromnode) {
2677                 vec[0][0]= link->fromsock->locx;
2678                 vec[0][1]= link->fromsock->locy;
2679         }
2680         else {
2681                 vec[0][0]= mx;
2682                 vec[0][1]= my;
2683         }
2684         if(link->tonode) {
2685                 vec[3][0]= link->tosock->locx;
2686                 vec[3][1]= link->tosock->locy;
2687         }
2688         else {
2689                 vec[3][0]= mx;
2690                 vec[3][1]= my;
2691         }
2692         
2693         node_draw_link_bezier(v2d, vec, th_col1, th_col2, do_shaded);
2694         // fdrawbezier(vec);
2695 }
2696
2697 #if 0
2698
2699 static void nodes_panel_gpencil(short cntrl)    // NODES_HANDLER_GREASEPENCIL
2700 {
2701         uiBlock *block;
2702         SpaceNode *snode;
2703         
2704         snode= curarea->spacedata.first;
2705
2706         block= uiNewBlock(&curarea->uiblocks, "nodes_panel_gpencil", UI_EMBOSS, UI_HELV, curarea->win);
2707         uiPanelControl(UI_PNL_SOLID | UI_PNL_CLOSE  | cntrl);
2708         uiSetPanelHandler(NODES_HANDLER_GREASEPENCIL);  // for close and esc
2709         if (uiNewPanel(curarea, block, "Grease Pencil", "SpaceNode", 100, 30, 318, 204)==0) return;
2710         
2711         /* we can only really draw stuff if there are nodes (otherwise no events are handled */
2712         if (snode->nodetree == NULL)
2713                 return;
2714         
2715         /* allocate memory for gpd if drawing enabled (this must be done first or else we crash) */
2716         if (snode->flag & SNODE_DISPGP) {
2717                 if (snode->gpd == NULL)
2718                         gpencil_data_setactive(curarea, gpencil_data_addnew());
2719         }
2720         
2721         if (snode->flag & SNODE_DISPGP) {
2722                 bGPdata *gpd= snode->gpd;
2723                 short newheight;
2724                 
2725                 /* this is a variable height panel, newpanel doesnt force new size on existing panels */
2726                 /* so first we make it default height */
2727                 uiNewPanelHeight(block, 204);
2728                 
2729                 /* draw button for showing gpencil settings and drawings */
2730                 uiDefButBitS(block, TOG, SNODE_DISPGP, B_REDR, "Use Grease Pencil", 10, 225, 150, 20, &snode->flag, 0, 0, 0, 0, "Display freehand annotations overlay over this Node Editor (draw using Shift-LMB)");
2731                 
2732                 /* extend the panel if the contents won't fit */
2733                 newheight= draw_gpencil_panel(block, gpd, curarea); 
2734                 uiNewPanelHeight(block, newheight);
2735         }
2736         else {
2737                 uiDefButBitS(block, TOG, SNODE_DISPGP, B_REDR, "Use Grease Pencil", 10, 225, 150, 20, &snode->flag, 0, 0, 0, 0, "Display freehand annotations overlay over this Node Editor");
2738                 uiDefBut(block, LABEL, 1, " ",  160, 180, 150, 20, NULL, 0.0, 0.0, 0, 0, "");
2739         }
2740 }
2741
2742 static void nodes_blockhandlers(ScrArea *sa)
2743 {
2744         SpaceNode *snode= sa->spacedata.first;
2745         short a;
2746         
2747         for(a=0; a<SPACE_MAXHANDLER; a+=2) {
2748                 switch(snode->blockhandler[a]) {
2749                         case NODES_HANDLER_GREASEPENCIL:
2750                                 nodes_panel_gpencil(snode->blockhandler[a+1]);
2751                                 break;
2752                 }
2753                 
2754                 /* clear action value for event */
2755                 snode->blockhandler[a+1]= 0;
2756         }
2757         uiDrawBlocksPanels(sa, 0);
2758 }
2759 #endif