2.5 / Nodes
[blender-staging.git] / source / blender / editors / space_node / node_draw.c
1 /**
2  * $Id: drawnode.c 17439 2008-11-13 09:57:11Z kakbarnf $
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) 2008 Blender Foundation.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  * Contributor(s): Nathan Letwory
25  *
26  * ***** END GPL LICENSE BLOCK *****
27  */
28
29 #include <math.h>
30 #include <stdio.h>
31 #include <string.h>
32
33 #include "DNA_ID.h"
34 #include "DNA_node_types.h"
35 #include "DNA_image_types.h"
36 #include "DNA_material_types.h"
37 #include "DNA_mesh_types.h"
38 #include "DNA_action_types.h"
39 #include "DNA_color_types.h"
40 #include "DNA_customdata_types.h"
41 #include "DNA_gpencil_types.h"
42 #include "DNA_ipo_types.h"
43 #include "DNA_object_types.h"
44 #include "DNA_scene_types.h"
45 #include "DNA_space_types.h"
46 #include "DNA_screen_types.h"
47 #include "DNA_texture_types.h"
48 #include "DNA_text_types.h"
49 #include "DNA_userdef_types.h"
50
51 #include "BLI_blenlib.h"
52 #include "BLI_arithb.h"
53 #include "MEM_guardedalloc.h"
54
55 #include "BKE_context.h"
56 #include "BKE_global.h"
57 #include "BKE_image.h"
58 #include "BKE_library.h"
59 #include "BKE_main.h"
60 #include "BKE_material.h"
61 #include "BKE_node.h"
62 #include "BKE_object.h"
63 #include "BKE_texture.h"
64 #include "BKE_text.h"
65 #include "BKE_utildefines.h"
66
67 /* #include "BDR_gpencil.h" XXX */
68
69 #include "BIF_gl.h"
70 #include "BIF_glutil.h"
71 #include "BMF_Api.h"
72
73 #include "WM_api.h"
74
75 #include "ED_screen.h"
76 #include "ED_util.h"
77 #include "ED_types.h"
78
79 #include "UI_text.h"
80 #include "UI_interface.h"
81 #include "UI_interface_icons.h"
82 #include "UI_resources.h"
83 #include "UI_view2d.h"
84
85 #include "CMP_node.h"
86 #include "SHD_node.h"
87
88 #include "node_intern.h"
89
90 // XXX from BSE_node.h
91 #define HIDDEN_RAD              15.0f
92 #define BASIS_RAD               8.0f
93 #define NODE_DYS                10
94 #define NODE_DY                 20
95 #define NODE_SOCKSIZE   5
96
97 // XXX interface.h
98 extern void ui_dropshadow(rctf *rct, float radius, float aspect, int select);
99 extern void ui_rasterpos_safe(float x, float y, float aspect);
100 extern void gl_round_box(int mode, float minx, float miny, float maxx, float maxy, float rad);
101 extern void ui_draw_tria_icon(float x, float y, float aspect, char dir);
102
103 // XXX butspace.h
104 #define B_NODE_EXEC                     3610
105
106 #if 0 // XXX
107 static void snode_drawstring(void *curfont, SpaceNode *snode, char *str, int okwidth)
108 {
109         char drawstr[NODE_MAXSTR];
110         int width;
111         
112         if(str[0]==0 || okwidth<4) return;
113         
114         BLI_strncpy(drawstr, str, NODE_MAXSTR);
115         width= snode->aspect*UI_GetStringWidth(curfont, drawstr, 0);
116
117         if(width > okwidth) {
118                 int len= strlen(drawstr)-1;
119                 
120                 while(width > okwidth && len>=0) {
121                         drawstr[len]= 0;
122                         
123                         width= snode->aspect*UI_GetStringWidth(curfont, drawstr, 0);
124                         len--;
125                 }
126                 if(len==0) return;
127         }
128         UI_DrawString(curfont, drawstr, 0);
129 }
130 #endif
131
132 static void node_scaling_widget(int color_id, float aspect, float xmin, float ymin, float xmax, float ymax)
133 {
134         float dx;
135         float dy;
136         
137         dx= 0.5f*(xmax-xmin);
138         dy= 0.5f*(ymax-ymin);
139         
140         UI_ThemeColorShade(color_id, +30);      
141         fdrawline(xmin, ymin, xmax, ymax);
142         fdrawline(xmin+dx, ymin, xmax, ymax-dy);
143         
144         UI_ThemeColorShade(color_id, -10);
145         fdrawline(xmin, ymin+aspect, xmax, ymax+aspect);
146         fdrawline(xmin+dx, ymin+aspect, xmax, ymax-dy+aspect);
147 }
148
149 /* based on settings in node, sets drawing rect info. each redraw! */
150 static void node_update(bNode *node)
151 {
152         bNodeSocket *nsock;
153         float dy= node->locy;
154         
155         /* header */
156         dy-= NODE_DY;
157         
158         /* little bit space in top */
159         if(node->outputs.first)
160                 dy-= NODE_DYS/2;
161         
162         /* output sockets */
163         for(nsock= node->outputs.first; nsock; nsock= nsock->next) {
164                 if(!(nsock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) {
165                         nsock->locx= node->locx + node->width;
166                         nsock->locy= dy - NODE_DYS;
167                         dy-= NODE_DY;
168                 }
169         }
170         
171         node->prvr.xmin= node->butr.xmin= node->locx + NODE_DYS;
172         node->prvr.xmax= node->butr.xmax= node->locx + node->width- NODE_DYS;
173         
174         /* preview rect? */
175         if(node->flag & NODE_PREVIEW) {
176                 /* only recalculate size when there's a preview actually, otherwise we use stored result */
177                 if(node->preview && node->preview->rect) {
178                         float aspect= 1.0f;
179                         
180                         if(node->preview && node->preview->xsize && node->preview->ysize) 
181                                 aspect= (float)node->preview->ysize/(float)node->preview->xsize;
182                         
183                         dy-= NODE_DYS/2;
184                         node->prvr.ymax= dy;
185                         
186                         if(aspect <= 1.0f)
187                                 node->prvr.ymin= dy - aspect*(node->width-NODE_DY);
188                         else {
189                                 float dx= (node->width - NODE_DYS) - (node->width- NODE_DYS)/aspect;    /* width correction of image */
190                                 
191                                 node->prvr.ymin= dy - (node->width-NODE_DY);
192                                 
193                                 node->prvr.xmin+= 0.5f*dx;
194                                 node->prvr.xmax-= 0.5f*dx;
195                         }
196
197                         dy= node->prvr.ymin - NODE_DYS/2;
198
199                         /* make sure that maximums are bigger or equal to minimums */
200                         if(node->prvr.xmax < node->prvr.xmin) SWAP(float, node->prvr.xmax, node->prvr.xmin);
201                         if(node->prvr.ymax < node->prvr.ymin) SWAP(float, node->prvr.ymax, node->prvr.ymin);
202                 }
203                 else {
204                         float oldh= node->prvr.ymax - node->prvr.ymin;
205                         if(oldh==0.0f)
206                                 oldh= 0.6f*node->width-NODE_DY;
207                         dy-= NODE_DYS/2;
208                         node->prvr.ymax= dy;
209                         node->prvr.ymin= dy - oldh;
210                         dy= node->prvr.ymin - NODE_DYS/2;
211                 }
212         }
213
214         /* XXX ugly hack, typeinfo for group is generated */
215         if(node->type == NODE_GROUP)
216                 ; // XXX node->typeinfo->butfunc= node_buts_group;
217         
218         /* buttons rect? */
219         if((node->flag & NODE_OPTIONS) && node->typeinfo->butfunc) {
220                 dy-= NODE_DYS/2;
221                 node->butr.ymax= dy;
222                 node->butr.ymin= dy - (float)node->typeinfo->butfunc(NULL, NULL, node, NULL);
223                 dy= node->butr.ymin - NODE_DYS/2;
224         }
225         
226         /* input sockets */
227         for(nsock= node->inputs.first; nsock; nsock= nsock->next) {
228                 if(!(nsock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) {
229                         nsock->locx= node->locx;
230                         nsock->locy= dy - NODE_DYS;
231                         dy-= NODE_DY;
232                 }
233         }
234         
235         /* little bit space in end */
236         if(node->inputs.first || (node->flag & (NODE_OPTIONS|NODE_PREVIEW))==0 )
237                 dy-= NODE_DYS/2;
238         
239         node->totr.xmin= node->locx;
240         node->totr.xmax= node->locx + node->width;
241         node->totr.ymax= node->locy;
242         node->totr.ymin= dy;
243 }
244
245 /* based on settings in node, sets drawing rect info. each redraw! */
246 static void node_update_hidden(bNode *node)
247 {
248         bNodeSocket *nsock;
249         float rad, drad, hiddenrad= HIDDEN_RAD;
250         int totin=0, totout=0, tot;
251         
252         /* calculate minimal radius */
253         for(nsock= node->inputs.first; nsock; nsock= nsock->next)
254                 if(!(nsock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL)))
255                         totin++;
256         for(nsock= node->outputs.first; nsock; nsock= nsock->next)
257                 if(!(nsock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL)))
258                         totout++;
259         
260         tot= MAX2(totin, totout);
261         if(tot>4) {
262                 hiddenrad += 5.0f*(float)(tot-4);
263         }
264         
265         node->totr.xmin= node->locx;
266         node->totr.xmax= node->locx + 3*hiddenrad + node->miniwidth;
267         node->totr.ymax= node->locy + (hiddenrad - 0.5f*NODE_DY);
268         node->totr.ymin= node->totr.ymax - 2*hiddenrad;
269         
270         /* output sockets */
271         rad=drad= (float)M_PI/(1.0f + (float)totout);
272         
273         for(nsock= node->outputs.first; nsock; nsock= nsock->next) {
274                 if(!(nsock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) {
275                         nsock->locx= node->totr.xmax - hiddenrad + (float)sin(rad)*hiddenrad;
276                         nsock->locy= node->totr.ymin + hiddenrad + (float)cos(rad)*hiddenrad;
277                         rad+= drad;
278                 }
279         }
280         
281         /* input sockets */
282         rad=drad= - (float)M_PI/(1.0f + (float)totin);
283         
284         for(nsock= node->inputs.first; nsock; nsock= nsock->next) {
285                 if(!(nsock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) {
286                         nsock->locx= node->totr.xmin + hiddenrad + (float)sin(rad)*hiddenrad;
287                         nsock->locy= node->totr.ymin + hiddenrad + (float)cos(rad)*hiddenrad;
288                         rad+= drad;
289                 }
290         }
291 }
292
293 static int node_get_colorid(bNode *node)
294 {
295         if(node->typeinfo->nclass==NODE_CLASS_INPUT)
296                 return TH_NODE_IN_OUT;
297         if(node->typeinfo->nclass==NODE_CLASS_OUTPUT) {
298                 if(node->flag & NODE_DO_OUTPUT)
299                         return TH_NODE_IN_OUT;
300                 else
301                         return TH_NODE;
302         }
303         if(node->typeinfo->nclass==NODE_CLASS_CONVERTOR)
304                 return TH_NODE_CONVERTOR;
305         if(ELEM3(node->typeinfo->nclass, NODE_CLASS_OP_COLOR, NODE_CLASS_OP_VECTOR, NODE_CLASS_OP_FILTER))
306                 return TH_NODE_OPERATOR;
307         if(node->typeinfo->nclass==NODE_CLASS_GROUP)
308                 return TH_NODE_GROUP;
309         return TH_NODE;
310 }
311
312 /* based on settings in node, sets drawing rect info. each redraw! */
313 /* note: this assumes only 1 group at a time is drawn (linked data) */
314 /* in node->totr the entire boundbox for the group is stored */
315 static void node_update_group(bNode *gnode)
316 {
317         bNodeTree *ngroup= (bNodeTree *)gnode->id;
318         bNode *node;
319         bNodeSocket *nsock;
320         rctf *rect= &gnode->totr;
321         int counter;
322         
323         /* center them, is a bit of abuse of locx and locy though */
324         for(node= ngroup->nodes.first; node; node= node->next) {
325                 node->locx+= gnode->locx;
326                 node->locy+= gnode->locy;
327                 if(node->flag & NODE_HIDDEN)
328                         node_update_hidden(node);
329                 else
330                         node_update(node);
331                 node->locx-= gnode->locx;
332                 node->locy-= gnode->locy;
333         }
334         counter= 1;
335         for(node= ngroup->nodes.first; node; node= node->next) {
336                 if(counter) {
337                         *rect= node->totr;
338                         counter= 0;
339                 }
340                 else
341                         BLI_union_rctf(rect, &node->totr);
342         }
343         if(counter==1) return;  /* should be prevented? */
344         
345         rect->xmin-= NODE_DY;
346         rect->ymin-= NODE_DY;
347         rect->xmax+= NODE_DY;
348         rect->ymax+= NODE_DY;
349         
350         /* output sockets */
351         for(nsock= gnode->outputs.first; nsock; nsock= nsock->next) {
352                 nsock->locx= rect->xmax;
353                 nsock->locy= nsock->tosock->locy;
354         }
355         
356         /* input sockets */
357         for(nsock= gnode->inputs.first; nsock; nsock= nsock->next) {
358                 nsock->locx= rect->xmin;
359                 nsock->locy= nsock->tosock->locy;
360         }
361 }
362
363 /* note: in cmp_util.c is similar code, for node_compo_pass_on() */
364 static void node_draw_mute_line(View2D *v2d, SpaceNode *snode, bNode *node)
365 {
366         bNodeSocket *valsock= NULL, *colsock= NULL, *vecsock= NULL;
367         bNodeSocket *sock;
368         float vec[4][3];
369         int a;
370         
371         vec[0][2]= vec[1][2]= vec[2][2]= vec[3][2]= 0.0; /* only 2d spline, set the Z to 0*/
372         
373         /* connect the first value buffer in with first value out */
374         /* connect the first RGBA buffer in with first RGBA out */
375         
376         /* test the inputs */
377         for(a=0, sock= node->inputs.first; sock; sock= sock->next, a++) {
378                 if(nodeCountSocketLinks(snode->edittree, sock)) {
379                         if(sock->type==SOCK_VALUE && valsock==NULL) valsock= sock;
380                         if(sock->type==SOCK_VECTOR && vecsock==NULL) vecsock= sock;
381                         if(sock->type==SOCK_RGBA && colsock==NULL) colsock= sock;
382                 }
383         }
384         
385         /* outputs, draw lines */
386         UI_ThemeColor(TH_REDALERT);
387         glEnable(GL_BLEND);
388         glEnable( GL_LINE_SMOOTH );
389         
390         if(valsock || colsock || vecsock) {
391                 for(a=0, sock= node->outputs.first; sock; sock= sock->next, a++) {
392                         if(nodeCountSocketLinks(snode->edittree, sock)) {
393                                 vec[3][0]= sock->locx;
394                                 vec[3][1]= sock->locy;
395                                 
396                                 if(sock->type==SOCK_VALUE && valsock) {
397                                         vec[0][0]= valsock->locx;
398                                         vec[0][1]= valsock->locy;
399                                         node_draw_link_bezier(v2d, vec, TH_WIRE, TH_WIRE, 0);
400                                         valsock= NULL;
401                                 }
402                                 if(sock->type==SOCK_VECTOR && vecsock) {
403                                         vec[0][0]= vecsock->locx;
404                                         vec[0][1]= vecsock->locy;
405                                         node_draw_link_bezier(v2d, vec, TH_WIRE, TH_WIRE, 0);
406                                         vecsock= NULL;
407                                 }
408                                 if(sock->type==SOCK_RGBA && colsock) {
409                                         vec[0][0]= colsock->locx;
410                                         vec[0][1]= colsock->locy;
411                                         node_draw_link_bezier(v2d, vec, TH_WIRE, TH_WIRE, 0);
412                                         colsock= NULL;
413                                 }
414                         }
415                 }
416         }
417         glDisable(GL_BLEND);
418         glDisable( GL_LINE_SMOOTH );
419 }
420
421 /* nice AA filled circle */
422 /* this might have some more generic use */
423 static void circle_draw(float x, float y, float size, int type, int col[3])
424 {
425         /* 16 values of sin function */
426         static float si[16] = {
427                 0.00000000f, 0.39435585f,0.72479278f,0.93775213f,
428                 0.99871650f,0.89780453f,0.65137248f,0.29936312f,
429                 -0.10116832f,-0.48530196f,-0.79077573f,-0.96807711f,
430                 -0.98846832f,-0.84864425f,-0.57126821f,-0.20129852f
431         };
432         /* 16 values of cos function */
433         static float co[16] ={
434                 1.00000000f,0.91895781f,0.68896691f,0.34730525f,
435                 -0.05064916f,-0.44039415f,-0.75875812f,-0.95413925f,
436                 -0.99486932f,-0.87434661f,-0.61210598f,-0.25065253f,
437                 0.15142777f,0.52896401f,0.82076344f,0.97952994f,
438         };
439         int a;
440         
441         glColor3ub(col[0], col[1], col[2]);
442         
443         glBegin(GL_POLYGON);
444         for(a=0; a<16; a++)
445                 glVertex2f(x+size*si[a], y+size*co[a]);
446         glEnd();
447         
448         glColor4ub(0, 0, 0, 150);
449         glEnable(GL_BLEND);
450         glEnable( GL_LINE_SMOOTH );
451         glBegin(GL_LINE_LOOP);
452         for(a=0; a<16; a++)
453                 glVertex2f(x+size*si[a], y+size*co[a]);
454         glEnd();
455         glDisable( GL_LINE_SMOOTH );
456         glDisable(GL_BLEND);
457 }
458
459 static void socket_circle_draw(bNodeSocket *sock, float size)
460 {
461         int col[3];
462         
463         /* choose color based on sock flags */
464         if(sock->flag & SELECT) {
465                 if(sock->flag & SOCK_SEL) {
466                         col[0]= 240; col[1]= 200; col[2]= 40;}
467                 else if(sock->type==SOCK_VALUE) {
468                         col[0]= 200; col[1]= 200; col[2]= 200;}
469                 else if(sock->type==SOCK_VECTOR) {
470                         col[0]= 140; col[1]= 140; col[2]= 240;}
471                 else if(sock->type==SOCK_RGBA) {
472                         col[0]= 240; col[1]= 240; col[2]= 100;}
473                 else {
474                         col[0]= 140; col[1]= 240; col[2]= 140;}
475         }
476         else if(sock->flag & SOCK_SEL) {
477                 col[0]= 200; col[1]= 160; col[2]= 0;}
478         else {
479                 if(sock->type==-1) {
480                         col[0]= 0; col[1]= 0; col[2]= 0;}
481                 else if(sock->type==SOCK_VALUE) {
482                         col[0]= 160; col[1]= 160; col[2]= 160;}
483                 else if(sock->type==SOCK_VECTOR) {
484                         col[0]= 100; col[1]= 100; col[2]= 200;}
485                 else if(sock->type==SOCK_RGBA) {
486                         col[0]= 200; col[1]= 200; col[2]= 40;}
487                 else { 
488                         col[0]= 100; col[1]= 200; col[2]= 100;}
489         }
490         
491         circle_draw(sock->locx, sock->locy, size, sock->type, col);
492 }
493
494 static void node_sync_cb(bContext *C, void *snode_v, void *node_v)
495 {
496         SpaceNode *snode= snode_v;
497         
498         if(snode->treetype==NTREE_SHADER) {
499                 nodeShaderSynchronizeID(node_v, 1);
500                 // allqueue(REDRAWBUTSSHADING, 0);
501         }
502 }
503
504 /* **************  Socket callbacks *********** */
505
506 static void socket_vector_menu_cb(bContext *C, void *node_v, void *ntree_v)
507 {
508         if(node_v && ntree_v) {
509                 NodeTagChanged(ntree_v, node_v); 
510                 // addqueue(curarea->win, UI_BUT_EVENT, B_NODE_EXEC+((bNode *)node_v)->nr); XXX
511         }
512 }
513
514 /* NOTE: this is a block-menu, needs 0 events, otherwise the menu closes */
515 static uiBlock *socket_vector_menu(bContext *C, uiMenuBlockHandle *handle, void *socket_v)
516 {
517         SpaceNode *snode= (SpaceNode *)CTX_wm_space_data(C);
518         ScrArea *curarea= CTX_wm_area(C);
519         bNode *node;
520         bNodeSocket *sock= socket_v;
521         bNodeStack *ns= &sock->ns;
522         uiBlock *block;
523         uiBut *bt;
524         
525         /* a bit ugly... retrieve the node the socket comes from */
526         for(node= snode->nodetree->nodes.first; node; node= node->next) {
527                 bNodeSocket *sockt;
528                 for(sockt= node->inputs.first; sockt; sockt= sockt->next)
529                         if(sockt==sock)
530                                 break;
531                 if(sockt)
532                         break;
533         }
534         
535         block= uiBeginBlock(C, handle->region, "socket menu", UI_EMBOSS, UI_HELV);
536
537         /* use this for a fake extra empy space around the buttons */
538         uiDefBut(block, LABEL, 0, "",                   -4, -4, 188, 68, NULL, 0, 0, 0, 0, "");
539         
540         uiBlockBeginAlign(block);
541         bt= uiDefButF(block, NUMSLI, 0, "X ",    0,40,180,20, ns->vec, ns->min, ns->max, 10, 0, "");
542         uiButSetFunc(bt, socket_vector_menu_cb, node, snode->nodetree);
543         bt= uiDefButF(block, NUMSLI, 0, "Y ",    0,20,180,20, ns->vec+1, ns->min, ns->max, 10, 0, "");
544         uiButSetFunc(bt, socket_vector_menu_cb, node, snode->nodetree);
545         bt= uiDefButF(block, NUMSLI, 0, "Z ",    0,0,180,20, ns->vec+2, ns->min, ns->max, 10, 0, "");
546         uiButSetFunc(bt, socket_vector_menu_cb, node, snode->nodetree);
547         
548         uiBlockSetDirection(block, UI_TOP);
549         uiEndBlock(C, block);
550         
551         ED_area_tag_redraw(curarea);
552         
553         return block;
554 }
555
556 /* not a callback */
557 static void node_draw_preview(bNodePreview *preview, rctf *prv)
558 {
559         float xscale= (prv->xmax-prv->xmin)/((float)preview->xsize);
560         float yscale= (prv->ymax-prv->ymin)/((float)preview->ysize);
561         float tile= (prv->xmax - prv->xmin) / 10.0f;
562         float x, y;
563         
564         /* draw checkerboard backdrop to show alpha */
565         glColor3ub(120, 120, 120);
566         glRectf(prv->xmin, prv->ymin, prv->xmax, prv->ymax);
567         glColor3ub(160, 160, 160);
568         
569         for(y=prv->ymin; y<prv->ymax; y+=tile*2) {
570                 for(x=prv->xmin; x<prv->xmax; x+=tile*2) {
571                         float tilex= tile, tiley= tile;
572
573                         if(x+tile > prv->xmax)
574                                 tilex= prv->xmax-x;
575                         if(y+tile > prv->ymax)
576                                 tiley= prv->ymax-y;
577
578                         glRectf(x, y, x + tilex, y + tiley);
579                 }
580         }
581         for(y=prv->ymin+tile; y<prv->ymax; y+=tile*2) {
582                 for(x=prv->xmin+tile; x<prv->xmax; x+=tile*2) {
583                         float tilex= tile, tiley= tile;
584
585                         if(x+tile > prv->xmax)
586                                 tilex= prv->xmax-x;
587                         if(y+tile > prv->ymax)
588                                 tiley= prv->ymax-y;
589
590                         glRectf(x, y, x + tilex, y + tiley);
591                 }
592         }
593         
594 #ifdef __APPLE__
595 //      if(is_a_really_crappy_nvidia_card()) {  XXX
596 //              float zoomx= curarea->winx/(float)(G.v2d->cur.xmax-G.v2d->cur.xmin);
597 //              float zoomy= curarea->winy/(float)(G.v2d->cur.ymax-G.v2d->cur.ymin);
598 //              glPixelZoom(zoomx*xscale, zoomy*yscale);
599 //      }
600 //      else
601 #endif
602                 glPixelZoom(xscale, yscale);
603
604         glEnable(GL_BLEND);
605         glBlendFunc( GL_ONE, GL_ONE_MINUS_SRC_ALPHA );  /* premul graphics */
606         
607         glColor4f(1.0, 1.0, 1.0, 1.0);
608         glaDrawPixelsTex(prv->xmin, prv->ymin, preview->xsize, preview->ysize, GL_FLOAT, preview->rect);
609         
610         glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
611         glDisable(GL_BLEND);
612         glPixelZoom(1.0f, 1.0f);
613
614         UI_ThemeColorShadeAlpha(TH_BACK, -15, +100);
615         fdrawbox(prv->xmin, prv->ymin, prv->xmax, prv->ymax);
616         
617 }
618
619 static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bNode *node)
620 {
621         bNodeSocket *sock;
622         uiBlock *block= NULL;
623         uiBut *bt;
624         rctf *rct= &node->totr;
625         float /*slen,*/ iconofs;
626         int /*ofs,*/ color_id= node_get_colorid(node);
627         char showname[128]; /* 128 used below */
628         View2D *v2d = &ar->v2d;
629         
630         uiSetRoundBox(15-4);
631         ui_dropshadow(rct, BASIS_RAD, snode->aspect, node->flag & SELECT);
632         
633         /* header */
634         if(color_id==TH_NODE)
635                 UI_ThemeColorShade(color_id, -20);
636         else
637                 UI_ThemeColor(color_id);
638                 
639         uiSetRoundBox(3);
640         uiRoundBox(rct->xmin, rct->ymax-NODE_DY, rct->xmax, rct->ymax, BASIS_RAD);
641         
642         /* show/hide icons, note this sequence is copied in editnode.c */
643         iconofs= rct->xmax;
644         
645         if(node->typeinfo->flag & NODE_PREVIEW) {
646                 int icon_id;
647                 
648                 if(node->flag & (NODE_ACTIVE_ID|NODE_DO_OUTPUT))
649                         icon_id= ICON_MATERIAL;
650                 else
651                         icon_id= ICON_MATERIAL_DEHLT;
652                 iconofs-= 18.0f;
653                 glEnable(GL_BLEND);
654                 UI_icon_draw_aspect_blended(iconofs, rct->ymax-NODE_DY+2, icon_id, snode->aspect, -60);
655                 glDisable(GL_BLEND);
656         }
657         if(node->type == NODE_GROUP) {
658                 
659                 iconofs-= 18.0f;
660                 glEnable(GL_BLEND);
661                 if(node->id->lib) {
662                         glPixelTransferf(GL_GREEN_SCALE, 0.7f);
663                         glPixelTransferf(GL_BLUE_SCALE, 0.3f);
664                         UI_icon_draw_aspect(iconofs, rct->ymax-NODE_DY+2, ICON_NODE, snode->aspect);
665                         glPixelTransferf(GL_GREEN_SCALE, 1.0f);
666                         glPixelTransferf(GL_BLUE_SCALE, 1.0f);
667                 }
668                 else {
669                         UI_icon_draw_aspect_blended(iconofs, rct->ymax-NODE_DY+2, ICON_NODE, snode->aspect, -60);
670                 }
671                 glDisable(GL_BLEND);
672         }
673         if(node->typeinfo->flag & NODE_OPTIONS) {
674                 iconofs-= 18.0f;
675                 glEnable(GL_BLEND);
676                 UI_icon_draw_aspect_blended(iconofs, rct->ymax-NODE_DY+2, ICON_BUTS, snode->aspect, -60);
677                 glDisable(GL_BLEND);
678         }
679         {       /* always hide/reveil unused sockets */ 
680                 int shade;
681
682                 iconofs-= 18.0f;
683                 // XXX re-enable
684                 /*if(node_has_hidden_sockets(node))
685                         shade= -40;
686                 else*/
687                         shade= -90;
688                 glEnable(GL_BLEND);
689                 UI_icon_draw_aspect_blended(iconofs, rct->ymax-NODE_DY+2, ICON_PLUS, snode->aspect, shade);
690                 glDisable(GL_BLEND);
691         }
692         
693         /* title */
694         if(node->flag & SELECT) 
695                 UI_ThemeColor(TH_TEXT_HI);
696         else
697                 UI_ThemeColorBlendShade(TH_TEXT, color_id, 0.4f, 10);
698         
699         /* open/close entirely? */
700         ui_draw_tria_icon(rct->xmin+8.0f, rct->ymax-NODE_DY+4.0f, snode->aspect, 'v');
701         
702         if(node->flag & SELECT) 
703                 UI_ThemeColor(TH_TEXT_HI);
704         else
705                 UI_ThemeColor(TH_TEXT);
706         
707         // ui_rasterpos_safe(rct->xmin+19.0f, rct->ymax-NODE_DY+5.0f, snode->aspect);
708         
709         if(node->flag & NODE_MUTED)
710                 sprintf(showname, "[%s]", node->name);
711         else if(node->username[0])
712                 sprintf(showname, "(%s) %s", node->username, node->name);
713         else
714                 BLI_strncpy(showname, node->name, 128);
715         
716         block= uiBeginBlock(C, ar, "snode_drawstring_hack", UI_EMBOSSN, UI_HELV);
717         // snode_drawstring(block->curfont, snode, showname, (int)(iconofs - rct->xmin-18.0f));
718         bt= uiDefBut(block, LABEL, 0, showname, (int)rct->xmin+19, (int)rct->ymax-NODE_DY+5, 100, 20, NULL, 0, 0, 0, 0, "");
719         uiEndBlock(C, block);
720         block= NULL;
721
722         /* body */
723         UI_ThemeColor4(TH_NODE);
724         glEnable(GL_BLEND);
725         uiSetRoundBox(8);
726         uiRoundBox(rct->xmin, rct->ymin, rct->xmax, rct->ymax-NODE_DY, BASIS_RAD);
727         glDisable(GL_BLEND);
728
729         /* scaling indicator */
730         node_scaling_widget(TH_NODE, snode->aspect, rct->xmax-BASIS_RAD*snode->aspect, rct->ymin, rct->xmax, rct->ymin+BASIS_RAD*snode->aspect);
731
732         /* outline active emphasis */
733         if(node->flag & NODE_ACTIVE) {
734                 glEnable(GL_BLEND);
735                 glColor4ub(200, 200, 200, 140);
736                 uiSetRoundBox(15-4);
737                 gl_round_box(GL_LINE_LOOP, rct->xmin, rct->ymin, rct->xmax, rct->ymax, BASIS_RAD);
738                 glDisable(GL_BLEND);
739         }
740         
741         /* disable lines */
742         if(node->flag & NODE_MUTED)
743                 node_draw_mute_line(v2d, snode, node);
744
745         /* we make buttons for input sockets, if... */
746         if(node->flag & NODE_OPTIONS) {
747                 if(node->inputs.first || node->typeinfo->butfunc) {
748                         char str[32];
749                         
750                         /* make unique block name, also used for handling blocks in editnode.c */
751                         sprintf(str, "node buttons %p", node);
752                         
753                         //block= uiNewBlock(&sa->uiblocks, str, UI_EMBOSS, UI_HELV, sa->win);
754                         block= uiBeginBlock(C, ar, str, UI_EMBOSS, UI_HELV);
755                         uiBlockSetFlag(block, UI_BLOCK_NO_HILITE);
756                         // XXX if(snode->id)
757                         // XXX  uiSetButLock(snode->id->lib!=NULL, ERROR_LIBDATA_MESSAGE);
758                 }
759         }
760         
761         /* hurmf... another candidate for callback, have to see how this works first */
762         if(node->id && block && snode->treetype==NTREE_SHADER)
763                 nodeShaderSynchronizeID(node, 0);
764         
765         /* socket inputs, buttons */
766         for(sock= node->inputs.first; sock; sock= sock->next) {
767                 if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) {
768                         socket_circle_draw(sock, NODE_SOCKSIZE);
769                         
770                         if(block && sock->link==NULL) {
771                                 float *butpoin= sock->ns.vec;
772                                 
773                                 if(sock->type==SOCK_VALUE) {
774                                         bt= uiDefButF(block, NUM, B_NODE_EXEC+node->nr, sock->name, 
775                                                   (short)sock->locx+NODE_DYS, (short)(sock->locy)-9, (short)node->width-NODE_DY, 17, 
776                                                   butpoin, sock->ns.min, sock->ns.max, 10, 2, "");
777                                         uiButSetFunc(bt, node_sync_cb, snode, node);
778                                 }
779                                 else if(sock->type==SOCK_VECTOR) {
780                                         uiDefBlockBut(block, socket_vector_menu, sock, sock->name, 
781                                                   (short)sock->locx+NODE_DYS, (short)sock->locy-9, (short)node->width-NODE_DY, 17, 
782                                                   "");
783                                 }
784                                 else if(block && sock->type==SOCK_RGBA) {
785                                         short labelw= (short)node->width-NODE_DY-40, width;
786                                         
787                                         if(labelw>0) width= 40; else width= (short)node->width-NODE_DY;
788                                         
789                                         bt= uiDefButF(block, COL, B_NODE_EXEC+node->nr, "", 
790                                                 (short)(sock->locx+NODE_DYS), (short)sock->locy-8, width, 15, 
791                                                    butpoin, 0, 0, 0, 0, "");
792                                         uiButSetFunc(bt, node_sync_cb, snode, node);
793                                         
794                                         if(labelw>0) uiDefBut(block, LABEL, 0, sock->name, 
795                                                                                    (short)(sock->locx+NODE_DYS) + 40, (short)sock->locy-8, labelw, 15, 
796                                                                                    NULL, 0, 0, 0, 0, "");
797                                 }
798                         }
799                         else {
800                                 /* XXX fix
801                                 UI_ThemeColor(TH_TEXT);
802                                 ui_rasterpos_safe(sock->locx+8.0f, sock->locy-5.0f, snode->aspect);
803                                 UI_DrawString(snode->curfont, sock->name, 0);
804                                 */
805                         }
806                 }
807         }
808         
809         /* socket outputs */
810         for(sock= node->outputs.first; sock; sock= sock->next) {
811                 if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) {
812                         socket_circle_draw(sock, NODE_SOCKSIZE);
813                         
814                         /* XXX fix
815                         UI_ThemeColor(TH_TEXT);
816                         ofs= 0;
817                         slen= snode->aspect*UI_GetStringWidth(snode->curfont, sock->name, 0);
818                         while(slen > node->width) {
819                                 ofs++;
820                                 slen= snode->aspect*UI_GetStringWidth(snode->curfont, sock->name+ofs, 0);
821                         }
822                         ui_rasterpos_safe(sock->locx-8.0f-slen, sock->locy-5.0f, snode->aspect);
823                         UI_DrawString(snode->curfont, sock->name+ofs, 0);
824                         */
825                 }
826         }
827         
828         /* preview */
829         if(node->flag & NODE_PREVIEW)
830                 if(node->preview && node->preview->rect)
831                         node_draw_preview(node->preview, &node->prvr);
832                 
833         /* buttons */
834         if(node->flag & NODE_OPTIONS) {
835                 if(block) {
836                         if(node->typeinfo->butfunc) {
837                                 node->typeinfo->butfunc(block, snode->nodetree, node, &node->butr);
838                         }
839                         uiDrawBlock(C, block);
840                 }
841         }
842         
843         if(block)
844                 uiEndBlock(C, block);
845 }
846
847 static void node_draw_hidden(View2D *v2d, SpaceNode *snode, bNode *node)
848 {
849 //      uiBlock *block; // XXX HACK
850         bNodeSocket *sock;
851         rctf *rct= &node->totr;
852         float dx, centy= 0.5f*(rct->ymax+rct->ymin);
853         float hiddenrad= 0.5f*(rct->ymax-rct->ymin);
854         int color_id= node_get_colorid(node);
855         char showname[128];     /* 128 is used below */
856         
857         /* shadow */
858         uiSetRoundBox(15);
859         ui_dropshadow(rct, hiddenrad, snode->aspect, node->flag & SELECT);
860
861         /* body */
862         UI_ThemeColor(color_id);        
863         uiRoundBox(rct->xmin, rct->ymin, rct->xmax, rct->ymax, hiddenrad);
864         
865         /* outline active emphasis */
866         if(node->flag & NODE_ACTIVE) {
867                 glEnable(GL_BLEND);
868                 glColor4ub(200, 200, 200, 140);
869                 gl_round_box(GL_LINE_LOOP, rct->xmin, rct->ymin, rct->xmax, rct->ymax, hiddenrad);
870                 glDisable(GL_BLEND);
871         }
872         
873         /* title */
874         if(node->flag & SELECT) 
875                 UI_ThemeColor(TH_TEXT_HI);
876         else
877                 UI_ThemeColorBlendShade(TH_TEXT, color_id, 0.4f, 10);
878         
879         /* open entirely icon */
880         ui_draw_tria_icon(rct->xmin+9.0f, centy-6.0f, snode->aspect, 'h');      
881         
882         /* disable lines */
883         if(node->flag & NODE_MUTED)
884                 node_draw_mute_line(v2d, snode, node);  
885         
886         if(node->flag & SELECT) 
887                 UI_ThemeColor(TH_TEXT_HI);
888         else
889                 UI_ThemeColor(TH_TEXT);
890         
891         if(node->miniwidth>0.0f) {
892                 ui_rasterpos_safe(rct->xmin+21.0f, centy-4.0f, snode->aspect);
893
894                 if(node->flag & NODE_MUTED)
895                         sprintf(showname, "[%s]", node->name);
896                 else if(node->username[0])
897                         sprintf(showname, "(%s)%s", node->username, node->name);
898                 else
899                         BLI_strncpy(showname, node->name, 128);
900
901                 /* XXX 
902                 block= uiBeginBlock(C, ar, "snode_drawstring_hack", UI_EMBOSSN, UI_HELV);
903                 // snode_drawstring(block->curfont, snode, showname, (int)(iconofs - rct->xmin-18.0f));
904                 bt= uiDefBut(block, LABEL, 0, showname, rct->xmin+21, centy-4, 100, 20, NULL, 0, 0, 0, 0, "");
905                 uiEndBlock(C, block);
906                 */
907                 
908         }       
909
910         /* scale widget thing */
911         UI_ThemeColorShade(color_id, -10);      
912         dx= 10.0f;
913         fdrawline(rct->xmax-dx, centy-4.0f, rct->xmax-dx, centy+4.0f);
914         fdrawline(rct->xmax-dx-3.0f*snode->aspect, centy-4.0f, rct->xmax-dx-3.0f*snode->aspect, centy+4.0f);
915         
916         UI_ThemeColorShade(color_id, +30);
917         dx-= snode->aspect;
918         fdrawline(rct->xmax-dx, centy-4.0f, rct->xmax-dx, centy+4.0f);
919         fdrawline(rct->xmax-dx-3.0f*snode->aspect, centy-4.0f, rct->xmax-dx-3.0f*snode->aspect, centy+4.0f);
920         
921         /* sockets */
922         for(sock= node->inputs.first; sock; sock= sock->next) {
923                 if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL)))
924                         socket_circle_draw(sock, NODE_SOCKSIZE);
925         }
926         
927         for(sock= node->outputs.first; sock; sock= sock->next) {
928                 if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL)))
929                         socket_circle_draw(sock, NODE_SOCKSIZE);
930         }
931 }
932
933 static void node_draw_nodetree(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree)
934 {
935         bNode *node;
936         bNodeLink *link;
937         int a;
938         
939         if(ntree==NULL) return;         /* groups... */
940         
941         /* node lines */
942         glEnable(GL_BLEND);
943         glEnable(GL_LINE_SMOOTH);
944         for(link= ntree->links.first; link; link= link->next)
945                 node_draw_link(&ar->v2d, snode, link);
946         glDisable(GL_LINE_SMOOTH);
947         glDisable(GL_BLEND);
948         
949         /* not selected first */
950         for(a=0, node= ntree->nodes.first; node; node= node->next, a++) {
951                 node->nr= a;            /* index of node in list, used for exec event code */
952                 if(!(node->flag & SELECT)) {
953                         if(node->flag & NODE_GROUP_EDIT);
954                         else if(node->flag & NODE_HIDDEN)
955                                 node_draw_hidden(&ar->v2d, snode, node);
956                         else
957                                 node_draw_basis(C, ar, snode, node);
958                 }
959         }
960         
961         /* selected */
962         for(node= ntree->nodes.first; node; node= node->next) {
963                 if(node->flag & SELECT) {
964                         if(node->flag & NODE_GROUP_EDIT);
965                         else if(node->flag & NODE_HIDDEN)
966                                 node_draw_hidden(&ar->v2d, snode, node);
967                         else
968                                 node_draw_basis(C, ar, snode, node);
969                 }
970         }       
971 }
972
973 /* fake links from groupnode to internal nodes */
974 static void node_draw_group_links(View2D *v2d, SpaceNode *snode, bNode *gnode)
975 {
976         bNodeLink fakelink;
977         bNodeSocket *sock;
978         
979         glEnable(GL_BLEND);
980         glEnable(GL_LINE_SMOOTH);
981         
982         fakelink.tonode= fakelink.fromnode= gnode;
983         
984         for(sock= gnode->inputs.first; sock; sock= sock->next) {
985                 if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) {
986                         if(sock->tosock) {
987                                 fakelink.fromsock= sock;
988                                 fakelink.tosock= sock->tosock;
989                                 node_draw_link(v2d, snode, &fakelink);
990                         }
991                 }
992         }
993         
994         for(sock= gnode->outputs.first; sock; sock= sock->next) {
995                 if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) {
996                         if(sock->tosock) {
997                                 fakelink.tosock= sock;
998                                 fakelink.fromsock= sock->tosock;
999                                 node_draw_link(v2d, snode, &fakelink);
1000                         }
1001                 }
1002         }
1003         
1004         glDisable(GL_BLEND);
1005         glDisable(GL_LINE_SMOOTH);
1006 }
1007
1008 /* groups are, on creation, centered around 0,0 */
1009 static void node_draw_group(const bContext *C, ARegion *ar, SpaceNode *snode, bNode *gnode)
1010 {
1011         bNodeTree *ngroup= (bNodeTree *)gnode->id;
1012         bNodeSocket *sock;
1013         rctf rect= gnode->totr;
1014         char showname[128];
1015         
1016         /* backdrop header */
1017         glEnable(GL_BLEND);
1018         uiSetRoundBox(3);
1019         UI_ThemeColorShadeAlpha(TH_NODE_GROUP, 0, -70);
1020         gl_round_box(GL_POLYGON, rect.xmin, rect.ymax, rect.xmax, rect.ymax+NODE_DY, BASIS_RAD);
1021         
1022         /* backdrop body */
1023         UI_ThemeColorShadeAlpha(TH_BACK, -8, -70);
1024         uiSetRoundBox(12);
1025         gl_round_box(GL_POLYGON, rect.xmin, rect.ymin, rect.xmax, rect.ymax, BASIS_RAD);
1026         
1027         /* selection outline */
1028         uiSetRoundBox(15);
1029         glColor4ub(200, 200, 200, 140);
1030         glEnable( GL_LINE_SMOOTH );
1031         gl_round_box(GL_LINE_LOOP, rect.xmin, rect.ymin, rect.xmax, rect.ymax+NODE_DY, BASIS_RAD);
1032         glDisable( GL_LINE_SMOOTH );
1033         glDisable(GL_BLEND);
1034         
1035         /* backdrop title */
1036         UI_ThemeColor(TH_TEXT_HI);
1037         ui_rasterpos_safe(rect.xmin+8.0f, rect.ymax+5.0f, snode->aspect);
1038
1039         if(gnode->username[0]) {
1040                 strcpy(showname,"(");
1041                 strcat(showname, gnode->username);
1042                 strcat(showname,") ");
1043                 strcat(showname, ngroup->id.name+2);
1044         }
1045         else
1046                 strcpy(showname, ngroup->id.name+2);
1047
1048         UI_DrawString(snode->curfont, showname, 0);
1049         
1050         /* links from groupsockets to the internal nodes */
1051         node_draw_group_links(&ar->v2d, snode, gnode);
1052         
1053         /* group sockets */
1054         for(sock= gnode->inputs.first; sock; sock= sock->next)
1055                 if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL)))
1056                         socket_circle_draw(sock, NODE_SOCKSIZE);
1057         for(sock= gnode->outputs.first; sock; sock= sock->next)
1058                 if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL)))
1059                         socket_circle_draw(sock, NODE_SOCKSIZE);
1060
1061         /* and finally the whole tree */
1062         node_draw_nodetree(C, ar, snode, ngroup);
1063 }
1064
1065 void drawnodespace(const bContext *C, ARegion *ar, View2D *v2d)
1066 {
1067         float col[3];
1068         View2DScrollers *scrollers;
1069         SpaceNode *snode= (SpaceNode*)CTX_wm_space_data(C);
1070         ScrArea *sa= CTX_wm_area(C);
1071         int argus;
1072         
1073         argus= 1.1f+ 2.3f;
1074         
1075         UI_GetThemeColor3fv(TH_BACK, col);
1076         glClearColor(col[0], col[1], col[2], 0.0);
1077         glClear(GL_COLOR_BUFFER_BIT);
1078
1079         UI_view2d_view_ortho(C, v2d);
1080         
1081         //bwin_clear_viewmat(sa->win);  /* clear buttons view */
1082         //glLoadIdentity();
1083         
1084         /* always free, blocks here have no unique identifier (1 block per node) */
1085         //uiFreeBlocksWin(&sa->uiblocks, sa->win);
1086
1087         /* only set once */
1088         glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
1089         glEnable(GL_MAP1_VERTEX_3);
1090
1091         /* aspect+font, set each time */
1092         snode->aspect= (v2d->cur.xmax - v2d->cur.xmin)/((float)sa->winx);
1093         //snode->curfont= uiSetCurFont_ext(snode->aspect);
1094
1095         UI_view2d_constant_grid_draw(C, v2d);
1096         /* backdrop */
1097         draw_nodespace_back_pix(CTX_wm_area(C), snode);
1098         
1099         /* nodes */
1100         snode_set_context(snode, CTX_data_scene(C));
1101         
1102         if(snode->nodetree) {
1103                 bNode *node;
1104                 
1105                 /* for now, we set drawing coordinates on each redraw */
1106                 for(node= snode->nodetree->nodes.first; node; node= node->next) {
1107                         if(node->flag & NODE_GROUP_EDIT)
1108                                 node_update_group(node);
1109                         else if(node->flag & NODE_HIDDEN)
1110                                 node_update_hidden(node);
1111                         else
1112                                 node_update(node);
1113                 }
1114
1115                 node_draw_nodetree(C, ar, snode, snode->nodetree);
1116                         
1117                 /* active group */
1118                 for(node= snode->nodetree->nodes.first; node; node= node->next) {
1119                         if(node->flag & NODE_GROUP_EDIT)
1120                                 node_draw_group(C, ar, snode, node);
1121                 }
1122         }
1123         
1124         /* draw grease-pencil ('canvas' strokes) */
1125         /*if ((snode->flag & SNODE_DISPGP) && (snode->nodetree))
1126                 draw_gpencil_2dview(sa, 1);*/
1127         
1128         /* restore viewport (not needed yet) */
1129         /*mywinset(sa->win);*/
1130
1131         /* ortho at pixel level curarea */
1132         /*myortho2(-0.375, sa->winx-0.375, -0.375, sa->winy-0.375);*/
1133         
1134         /* draw grease-pencil (screen strokes) */
1135         /*if ((snode->flag & SNODE_DISPGP) && (snode->nodetree))
1136                 draw_gpencil_2dview(sa, 0);*/
1137
1138         //draw_area_emboss(sa);
1139         
1140         /* it is important to end a view in a transform compatible with buttons */
1141         /*bwin_scalematrix(sa->win, snode->blockscale, snode->blockscale, snode->blockscale);
1142         nodes_blockhandlers(sa);*/
1143         
1144         //curarea->win_swap= WIN_BACK_OK;
1145         
1146         /* in the end, this is a delayed previewrender test, to allow buttons to be first */
1147         /*if(snode->flag & SNODE_DO_PREVIEW) {
1148                 addafterqueue(sa->win, RENDERPREVIEW, 1);
1149                 snode->flag &= ~SNODE_DO_PREVIEW;
1150         }*/
1151         
1152         /* reset view matrix */
1153         UI_view2d_view_restore(C);
1154         
1155         /* scrollers */
1156         scrollers= UI_view2d_scrollers_calc(C, v2d, 10/*unit*/, V2D_GRID_CLAMP, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
1157         UI_view2d_scrollers_draw(C, v2d, scrollers);
1158         UI_view2d_scrollers_free(scrollers);
1159 }