2.5: various warning fixes. There was one actual bug in a few different
[blender.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 #if 0
507 static void socket_vector_menu_cb(bContext *C, void *node_v, void *ntree_v)
508 {
509         if(node_v && ntree_v) {
510                 NodeTagChanged(ntree_v, node_v); 
511                 // addqueue(curarea->win, UI_BUT_EVENT, B_NODE_EXEC+((bNode *)node_v)->nr); XXX
512         }
513 }
514 #endif
515
516 /* NOTE: this is a block-menu, needs 0 events, otherwise the menu closes */
517 static uiBlock *socket_vector_menu(bContext *C, uiMenuBlockHandle *handle, void *socket_v)
518 {
519 #if 0 //XXX
520         SpaceNode *snode= curarea->spacedata.first;
521         bNode *node;
522         bNodeSocket *sock= socket_v;
523         bNodeStack *ns= &sock->ns;
524         uiBlock *block;
525         uiBut *bt;
526         
527         /* a bit ugly... retrieve the node the socket comes from */
528         for(node= snode->nodetree->nodes.first; node; node= node->next) {
529                 bNodeSocket *sockt;
530                 for(sockt= node->inputs.first; sockt; sockt= sockt->next)
531                         if(sockt==sock)
532                                 break;
533                 if(sockt)
534                         break;
535         }
536         
537         block= uiNewBlock(&curarea->uiblocks, "socket menu", UI_EMBOSS, UI_HELV, curarea->win);
538
539         /* use this for a fake extra empy space around the buttons */
540         uiDefBut(block, LABEL, 0, "",                   -4, -4, 188, 68, NULL, 0, 0, 0, 0, "");
541         
542         uiBlockBeginAlign(block);
543         bt= uiDefButF(block, NUMSLI, 0, "X ",    0,40,180,20, ns->vec, ns->min, ns->max, 10, 0, "");
544         uiButSetFunc(bt, socket_vector_menu_cb, node, snode->nodetree);
545         bt= uiDefButF(block, NUMSLI, 0, "Y ",    0,20,180,20, ns->vec+1, ns->min, ns->max, 10, 0, "");
546         uiButSetFunc(bt, socket_vector_menu_cb, node, snode->nodetree);
547         bt= uiDefButF(block, NUMSLI, 0, "Z ",    0,0,180,20, ns->vec+2, ns->min, ns->max, 10, 0, "");
548         uiButSetFunc(bt, socket_vector_menu_cb, node, snode->nodetree);
549         
550         uiBlockSetDirection(block, UI_TOP);
551         
552         // allqueue(REDRAWNODE, 0);
553         
554         return block;
555 #endif
556 return NULL;
557 }
558
559 /* not a callback */
560 static void node_draw_preview(bNodePreview *preview, rctf *prv)
561 {
562         float xscale= (prv->xmax-prv->xmin)/((float)preview->xsize);
563         float yscale= (prv->ymax-prv->ymin)/((float)preview->ysize);
564         float tile= (prv->xmax - prv->xmin) / 10.0f;
565         float x, y;
566         
567         /* draw checkerboard backdrop to show alpha */
568         glColor3ub(120, 120, 120);
569         glRectf(prv->xmin, prv->ymin, prv->xmax, prv->ymax);
570         glColor3ub(160, 160, 160);
571         
572         for(y=prv->ymin; y<prv->ymax; y+=tile*2) {
573                 for(x=prv->xmin; x<prv->xmax; x+=tile*2) {
574                         float tilex= tile, tiley= tile;
575
576                         if(x+tile > prv->xmax)
577                                 tilex= prv->xmax-x;
578                         if(y+tile > prv->ymax)
579                                 tiley= prv->ymax-y;
580
581                         glRectf(x, y, x + tilex, y + tiley);
582                 }
583         }
584         for(y=prv->ymin+tile; y<prv->ymax; y+=tile*2) {
585                 for(x=prv->xmin+tile; x<prv->xmax; x+=tile*2) {
586                         float tilex= tile, tiley= tile;
587
588                         if(x+tile > prv->xmax)
589                                 tilex= prv->xmax-x;
590                         if(y+tile > prv->ymax)
591                                 tiley= prv->ymax-y;
592
593                         glRectf(x, y, x + tilex, y + tiley);
594                 }
595         }
596         
597 #ifdef __APPLE__
598 //      if(is_a_really_crappy_nvidia_card()) {  XXX
599 //              float zoomx= curarea->winx/(float)(G.v2d->cur.xmax-G.v2d->cur.xmin);
600 //              float zoomy= curarea->winy/(float)(G.v2d->cur.ymax-G.v2d->cur.ymin);
601 //              glPixelZoom(zoomx*xscale, zoomy*yscale);
602 //      }
603 //      else
604 #endif
605                 glPixelZoom(xscale, yscale);
606
607         glEnable(GL_BLEND);
608         glBlendFunc( GL_ONE, GL_ONE_MINUS_SRC_ALPHA );  /* premul graphics */
609         
610         glColor4f(1.0, 1.0, 1.0, 1.0);
611         glaDrawPixelsTex(prv->xmin, prv->ymin, preview->xsize, preview->ysize, GL_FLOAT, preview->rect);
612         
613         glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
614         glDisable(GL_BLEND);
615         glPixelZoom(1.0f, 1.0f);
616
617         UI_ThemeColorShadeAlpha(TH_BACK, -15, +100);
618         fdrawbox(prv->xmin, prv->ymin, prv->xmax, prv->ymax);
619         
620 }
621
622 static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bNode *node)
623 {
624         bNodeSocket *sock;
625         uiBlock *block= NULL;
626         uiBut *bt;
627         rctf *rct= &node->totr;
628         float /*slen,*/ iconofs;
629         int /*ofs,*/ color_id= node_get_colorid(node);
630         char showname[128]; /* 128 used below */
631         View2D *v2d = &ar->v2d;
632         
633         uiSetRoundBox(15-4);
634         ui_dropshadow(rct, BASIS_RAD, snode->aspect, node->flag & SELECT);
635         
636         /* header */
637         if(color_id==TH_NODE)
638                 UI_ThemeColorShade(color_id, -20);
639         else
640                 UI_ThemeColor(color_id);
641                 
642         uiSetRoundBox(3);
643         uiRoundBox(rct->xmin, rct->ymax-NODE_DY, rct->xmax, rct->ymax, BASIS_RAD);
644         
645         /* show/hide icons, note this sequence is copied in editnode.c */
646         iconofs= rct->xmax;
647         
648         if(node->typeinfo->flag & NODE_PREVIEW) {
649                 int icon_id;
650                 
651                 if(node->flag & (NODE_ACTIVE_ID|NODE_DO_OUTPUT))
652                         icon_id= ICON_MATERIAL;
653                 else
654                         icon_id= ICON_MATERIAL_DEHLT;
655                 iconofs-= 18.0f;
656                 glEnable(GL_BLEND);
657                 UI_icon_draw_aspect_blended(iconofs, rct->ymax-NODE_DY+2, icon_id, snode->aspect, -60);
658                 glDisable(GL_BLEND);
659         }
660         if(node->type == NODE_GROUP) {
661                 
662                 iconofs-= 18.0f;
663                 glEnable(GL_BLEND);
664                 if(node->id->lib) {
665                         glPixelTransferf(GL_GREEN_SCALE, 0.7f);
666                         glPixelTransferf(GL_BLUE_SCALE, 0.3f);
667                         UI_icon_draw_aspect(iconofs, rct->ymax-NODE_DY+2, ICON_NODE, snode->aspect);
668                         glPixelTransferf(GL_GREEN_SCALE, 1.0f);
669                         glPixelTransferf(GL_BLUE_SCALE, 1.0f);
670                 }
671                 else {
672                         UI_icon_draw_aspect_blended(iconofs, rct->ymax-NODE_DY+2, ICON_NODE, snode->aspect, -60);
673                 }
674                 glDisable(GL_BLEND);
675         }
676         if(node->typeinfo->flag & NODE_OPTIONS) {
677                 iconofs-= 18.0f;
678                 glEnable(GL_BLEND);
679                 UI_icon_draw_aspect_blended(iconofs, rct->ymax-NODE_DY+2, ICON_BUTS, snode->aspect, -60);
680                 glDisable(GL_BLEND);
681         }
682         {       /* always hide/reveil unused sockets */ 
683                 int shade;
684
685                 iconofs-= 18.0f;
686                 // XXX re-enable
687                 /*if(node_has_hidden_sockets(node))
688                         shade= -40;
689                 else*/
690                         shade= -90;
691                 glEnable(GL_BLEND);
692                 UI_icon_draw_aspect_blended(iconofs, rct->ymax-NODE_DY+2, ICON_PLUS, snode->aspect, shade);
693                 glDisable(GL_BLEND);
694         }
695         
696         /* title */
697         if(node->flag & SELECT) 
698                 UI_ThemeColor(TH_TEXT_HI);
699         else
700                 UI_ThemeColorBlendShade(TH_TEXT, color_id, 0.4f, 10);
701         
702         /* open/close entirely? */
703         ui_draw_tria_icon(rct->xmin+8.0f, rct->ymax-NODE_DY+4.0f, snode->aspect, 'v');
704         
705         if(node->flag & SELECT) 
706                 UI_ThemeColor(TH_TEXT_HI);
707         else
708                 UI_ThemeColor(TH_TEXT);
709         
710         // ui_rasterpos_safe(rct->xmin+19.0f, rct->ymax-NODE_DY+5.0f, snode->aspect);
711         
712         if(node->flag & NODE_MUTED)
713                 sprintf(showname, "[%s]", node->name);
714         else if(node->username[0])
715                 sprintf(showname, "(%s) %s", node->username, node->name);
716         else
717                 BLI_strncpy(showname, node->name, 128);
718         
719         block= uiBeginBlock(C, ar, "snode_drawstring_hack", UI_EMBOSSN, UI_HELV);
720         // snode_drawstring(block->curfont, snode, showname, (int)(iconofs - rct->xmin-18.0f));
721         bt= uiDefBut(block, LABEL, 0, showname, (int)rct->xmin+19, (int)rct->ymax-NODE_DY+5, 100, 20, NULL, 0, 0, 0, 0, "");
722         uiEndBlock(C, block);
723         block= NULL;
724
725         /* body */
726         UI_ThemeColor4(TH_NODE);
727         glEnable(GL_BLEND);
728         uiSetRoundBox(8);
729         uiRoundBox(rct->xmin, rct->ymin, rct->xmax, rct->ymax-NODE_DY, BASIS_RAD);
730         glDisable(GL_BLEND);
731
732         /* scaling indicator */
733         node_scaling_widget(TH_NODE, snode->aspect, rct->xmax-BASIS_RAD*snode->aspect, rct->ymin, rct->xmax, rct->ymin+BASIS_RAD*snode->aspect);
734
735         /* outline active emphasis */
736         if(node->flag & NODE_ACTIVE) {
737                 glEnable(GL_BLEND);
738                 glColor4ub(200, 200, 200, 140);
739                 uiSetRoundBox(15-4);
740                 gl_round_box(GL_LINE_LOOP, rct->xmin, rct->ymin, rct->xmax, rct->ymax, BASIS_RAD);
741                 glDisable(GL_BLEND);
742         }
743         
744         /* disable lines */
745         if(node->flag & NODE_MUTED)
746                 node_draw_mute_line(v2d, snode, node);
747
748         /* we make buttons for input sockets, if... */
749         if(node->flag & NODE_OPTIONS) {
750                 if(node->inputs.first || node->typeinfo->butfunc) {
751                         char str[32];
752                         
753                         /* make unique block name, also used for handling blocks in editnode.c */
754                         sprintf(str, "node buttons %p", node);
755                         
756                         //block= uiNewBlock(&sa->uiblocks, str, UI_EMBOSS, UI_HELV, sa->win);
757                         block= uiBeginBlock(C, ar, str, UI_EMBOSS, UI_HELV);
758                         uiBlockSetFlag(block, UI_BLOCK_NO_HILITE);
759                         // XXX if(snode->id)
760                         // XXX  uiSetButLock(snode->id->lib!=NULL, ERROR_LIBDATA_MESSAGE);
761                 }
762         }
763         
764         /* hurmf... another candidate for callback, have to see how this works first */
765         if(node->id && block && snode->treetype==NTREE_SHADER)
766                 nodeShaderSynchronizeID(node, 0);
767         
768         /* socket inputs, buttons */
769         for(sock= node->inputs.first; sock; sock= sock->next) {
770                 if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) {
771                         socket_circle_draw(sock, NODE_SOCKSIZE);
772                         
773                         if(block && sock->link==NULL) {
774                                 float *butpoin= sock->ns.vec;
775                                 
776                                 if(sock->type==SOCK_VALUE) {
777                                         bt= uiDefButF(block, NUM, B_NODE_EXEC+node->nr, sock->name, 
778                                                   (short)sock->locx+NODE_DYS, (short)(sock->locy)-9, (short)node->width-NODE_DY, 17, 
779                                                   butpoin, sock->ns.min, sock->ns.max, 10, 2, "");
780                                         uiButSetFunc(bt, node_sync_cb, snode, node);
781                                 }
782                                 else if(sock->type==SOCK_VECTOR) {
783                                         uiDefBlockBut(block, socket_vector_menu, sock, sock->name, 
784                                                   (short)sock->locx+NODE_DYS, (short)sock->locy-9, (short)node->width-NODE_DY, 17, 
785                                                   "");
786                                 }
787                                 else if(block && sock->type==SOCK_RGBA) {
788                                         short labelw= (short)node->width-NODE_DY-40, width;
789                                         
790                                         if(labelw>0) width= 40; else width= (short)node->width-NODE_DY;
791                                         
792                                         bt= uiDefButF(block, COL, B_NODE_EXEC+node->nr, "", 
793                                                 (short)(sock->locx+NODE_DYS), (short)sock->locy-8, width, 15, 
794                                                    butpoin, 0, 0, 0, 0, "");
795                                         uiButSetFunc(bt, node_sync_cb, snode, node);
796                                         
797                                         if(labelw>0) uiDefBut(block, LABEL, 0, sock->name, 
798                                                                                    (short)(sock->locx+NODE_DYS) + 40, (short)sock->locy-8, labelw, 15, 
799                                                                                    NULL, 0, 0, 0, 0, "");
800                                 }
801                         }
802                         else {
803                                 /* XXX fix
804                                 UI_ThemeColor(TH_TEXT);
805                                 ui_rasterpos_safe(sock->locx+8.0f, sock->locy-5.0f, snode->aspect);
806                                 UI_DrawString(snode->curfont, sock->name, 0);
807                                 */
808                         }
809                 }
810         }
811         
812         /* socket outputs */
813         for(sock= node->outputs.first; sock; sock= sock->next) {
814                 if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) {
815                         socket_circle_draw(sock, NODE_SOCKSIZE);
816                         
817                         /* XXX fix
818                         UI_ThemeColor(TH_TEXT);
819                         ofs= 0;
820                         slen= snode->aspect*UI_GetStringWidth(snode->curfont, sock->name, 0);
821                         while(slen > node->width) {
822                                 ofs++;
823                                 slen= snode->aspect*UI_GetStringWidth(snode->curfont, sock->name+ofs, 0);
824                         }
825                         ui_rasterpos_safe(sock->locx-8.0f-slen, sock->locy-5.0f, snode->aspect);
826                         UI_DrawString(snode->curfont, sock->name+ofs, 0);
827                         */
828                 }
829         }
830         
831         /* preview */
832         if(node->flag & NODE_PREVIEW)
833                 if(node->preview && node->preview->rect)
834                         node_draw_preview(node->preview, &node->prvr);
835                 
836         /* buttons */
837         if(node->flag & NODE_OPTIONS) {
838                 if(block) {
839                         if(node->typeinfo->butfunc) {
840                                 node->typeinfo->butfunc(block, snode->nodetree, node, &node->butr);
841                         }
842                         uiDrawBlock(C, block);
843                 }
844         }
845         
846         if(block)
847                 uiEndBlock(C, block);
848 }
849
850 static void node_draw_hidden(View2D *v2d, SpaceNode *snode, bNode *node)
851 {
852 //      uiBlock *block; // XXX HACK
853         bNodeSocket *sock;
854         rctf *rct= &node->totr;
855         float dx, centy= 0.5f*(rct->ymax+rct->ymin);
856         float hiddenrad= 0.5f*(rct->ymax-rct->ymin);
857         int color_id= node_get_colorid(node);
858         char showname[128];     /* 128 is used below */
859         
860         /* shadow */
861         uiSetRoundBox(15);
862         ui_dropshadow(rct, hiddenrad, snode->aspect, node->flag & SELECT);
863
864         /* body */
865         UI_ThemeColor(color_id);        
866         uiRoundBox(rct->xmin, rct->ymin, rct->xmax, rct->ymax, hiddenrad);
867         
868         /* outline active emphasis */
869         if(node->flag & NODE_ACTIVE) {
870                 glEnable(GL_BLEND);
871                 glColor4ub(200, 200, 200, 140);
872                 gl_round_box(GL_LINE_LOOP, rct->xmin, rct->ymin, rct->xmax, rct->ymax, hiddenrad);
873                 glDisable(GL_BLEND);
874         }
875         
876         /* title */
877         if(node->flag & SELECT) 
878                 UI_ThemeColor(TH_TEXT_HI);
879         else
880                 UI_ThemeColorBlendShade(TH_TEXT, color_id, 0.4f, 10);
881         
882         /* open entirely icon */
883         ui_draw_tria_icon(rct->xmin+9.0f, centy-6.0f, snode->aspect, 'h');      
884         
885         /* disable lines */
886         if(node->flag & NODE_MUTED)
887                 node_draw_mute_line(v2d, snode, node);  
888         
889         if(node->flag & SELECT) 
890                 UI_ThemeColor(TH_TEXT_HI);
891         else
892                 UI_ThemeColor(TH_TEXT);
893         
894         if(node->miniwidth>0.0f) {
895                 ui_rasterpos_safe(rct->xmin+21.0f, centy-4.0f, snode->aspect);
896
897                 if(node->flag & NODE_MUTED)
898                         sprintf(showname, "[%s]", node->name);
899                 else if(node->username[0])
900                         sprintf(showname, "(%s)%s", node->username, node->name);
901                 else
902                         BLI_strncpy(showname, node->name, 128);
903
904                 /* XXX 
905                 block= uiBeginBlock(C, ar, "snode_drawstring_hack", UI_EMBOSSN, UI_HELV);
906                 // snode_drawstring(block->curfont, snode, showname, (int)(iconofs - rct->xmin-18.0f));
907                 bt= uiDefBut(block, LABEL, 0, showname, rct->xmin+21, centy-4, 100, 20, NULL, 0, 0, 0, 0, "");
908                 uiEndBlock(C, block);
909                 */
910                 
911         }       
912
913         /* scale widget thing */
914         UI_ThemeColorShade(color_id, -10);      
915         dx= 10.0f;
916         fdrawline(rct->xmax-dx, centy-4.0f, rct->xmax-dx, centy+4.0f);
917         fdrawline(rct->xmax-dx-3.0f*snode->aspect, centy-4.0f, rct->xmax-dx-3.0f*snode->aspect, centy+4.0f);
918         
919         UI_ThemeColorShade(color_id, +30);
920         dx-= snode->aspect;
921         fdrawline(rct->xmax-dx, centy-4.0f, rct->xmax-dx, centy+4.0f);
922         fdrawline(rct->xmax-dx-3.0f*snode->aspect, centy-4.0f, rct->xmax-dx-3.0f*snode->aspect, centy+4.0f);
923         
924         /* sockets */
925         for(sock= node->inputs.first; sock; sock= sock->next) {
926                 if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL)))
927                         socket_circle_draw(sock, NODE_SOCKSIZE);
928         }
929         
930         for(sock= node->outputs.first; sock; sock= sock->next) {
931                 if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL)))
932                         socket_circle_draw(sock, NODE_SOCKSIZE);
933         }
934 }
935
936 static void node_draw_nodetree(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree)
937 {
938         bNode *node;
939         bNodeLink *link;
940         int a;
941         
942         if(ntree==NULL) return;         /* groups... */
943         
944         /* node lines */
945         glEnable(GL_BLEND);
946         glEnable(GL_LINE_SMOOTH);
947         for(link= ntree->links.first; link; link= link->next)
948                 node_draw_link(&ar->v2d, snode, link);
949         glDisable(GL_LINE_SMOOTH);
950         glDisable(GL_BLEND);
951         
952         /* not selected first */
953         for(a=0, node= ntree->nodes.first; node; node= node->next, a++) {
954                 node->nr= a;            /* index of node in list, used for exec event code */
955                 if(!(node->flag & SELECT)) {
956                         if(node->flag & NODE_GROUP_EDIT);
957                         else if(node->flag & NODE_HIDDEN)
958                                 node_draw_hidden(&ar->v2d, snode, node);
959                         else
960                                 node_draw_basis(C, ar, snode, node);
961                 }
962         }
963         
964         /* selected */
965         for(node= ntree->nodes.first; node; node= node->next) {
966                 if(node->flag & SELECT) {
967                         if(node->flag & NODE_GROUP_EDIT);
968                         else if(node->flag & NODE_HIDDEN)
969                                 node_draw_hidden(&ar->v2d, snode, node);
970                         else
971                                 node_draw_basis(C, ar, snode, node);
972                 }
973         }       
974 }
975
976 /* fake links from groupnode to internal nodes */
977 static void node_draw_group_links(View2D *v2d, SpaceNode *snode, bNode *gnode)
978 {
979         bNodeLink fakelink;
980         bNodeSocket *sock;
981         
982         glEnable(GL_BLEND);
983         glEnable(GL_LINE_SMOOTH);
984         
985         fakelink.tonode= fakelink.fromnode= gnode;
986         
987         for(sock= gnode->inputs.first; sock; sock= sock->next) {
988                 if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) {
989                         if(sock->tosock) {
990                                 fakelink.fromsock= sock;
991                                 fakelink.tosock= sock->tosock;
992                                 node_draw_link(v2d, snode, &fakelink);
993                         }
994                 }
995         }
996         
997         for(sock= gnode->outputs.first; sock; sock= sock->next) {
998                 if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) {
999                         if(sock->tosock) {
1000                                 fakelink.tosock= sock;
1001                                 fakelink.fromsock= sock->tosock;
1002                                 node_draw_link(v2d, snode, &fakelink);
1003                         }
1004                 }
1005         }
1006         
1007         glDisable(GL_BLEND);
1008         glDisable(GL_LINE_SMOOTH);
1009 }
1010
1011 /* groups are, on creation, centered around 0,0 */
1012 static void node_draw_group(const bContext *C, ARegion *ar, SpaceNode *snode, bNode *gnode)
1013 {
1014         bNodeTree *ngroup= (bNodeTree *)gnode->id;
1015         bNodeSocket *sock;
1016         rctf rect= gnode->totr;
1017         char showname[128];
1018         
1019         /* backdrop header */
1020         glEnable(GL_BLEND);
1021         uiSetRoundBox(3);
1022         UI_ThemeColorShadeAlpha(TH_NODE_GROUP, 0, -70);
1023         gl_round_box(GL_POLYGON, rect.xmin, rect.ymax, rect.xmax, rect.ymax+NODE_DY, BASIS_RAD);
1024         
1025         /* backdrop body */
1026         UI_ThemeColorShadeAlpha(TH_BACK, -8, -70);
1027         uiSetRoundBox(12);
1028         gl_round_box(GL_POLYGON, rect.xmin, rect.ymin, rect.xmax, rect.ymax, BASIS_RAD);
1029         
1030         /* selection outline */
1031         uiSetRoundBox(15);
1032         glColor4ub(200, 200, 200, 140);
1033         glEnable( GL_LINE_SMOOTH );
1034         gl_round_box(GL_LINE_LOOP, rect.xmin, rect.ymin, rect.xmax, rect.ymax+NODE_DY, BASIS_RAD);
1035         glDisable( GL_LINE_SMOOTH );
1036         glDisable(GL_BLEND);
1037         
1038         /* backdrop title */
1039         UI_ThemeColor(TH_TEXT_HI);
1040         ui_rasterpos_safe(rect.xmin+8.0f, rect.ymax+5.0f, snode->aspect);
1041
1042         if(gnode->username[0]) {
1043                 strcpy(showname,"(");
1044                 strcat(showname, gnode->username);
1045                 strcat(showname,") ");
1046                 strcat(showname, ngroup->id.name+2);
1047         }
1048         else
1049                 strcpy(showname, ngroup->id.name+2);
1050
1051         UI_DrawString(snode->curfont, showname, 0);
1052         
1053         /* links from groupsockets to the internal nodes */
1054         node_draw_group_links(&ar->v2d, snode, gnode);
1055         
1056         /* group sockets */
1057         for(sock= gnode->inputs.first; sock; sock= sock->next)
1058                 if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL)))
1059                         socket_circle_draw(sock, NODE_SOCKSIZE);
1060         for(sock= gnode->outputs.first; sock; sock= sock->next)
1061                 if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL)))
1062                         socket_circle_draw(sock, NODE_SOCKSIZE);
1063
1064         /* and finally the whole tree */
1065         node_draw_nodetree(C, ar, snode, ngroup);
1066 }
1067
1068 void drawnodespace(const bContext *C, ARegion *ar, View2D *v2d)
1069 {
1070         float col[3];
1071         View2DScrollers *scrollers;
1072         SpaceNode *snode= (SpaceNode*)CTX_wm_space_data(C);
1073         
1074         UI_GetThemeColor3fv(TH_BACK, col);
1075         glClearColor(col[0], col[1], col[2], 0.0);
1076         glClear(GL_COLOR_BUFFER_BIT);
1077
1078         UI_view2d_view_ortho(C, v2d);
1079         
1080         //bwin_clear_viewmat(sa->win);  /* clear buttons view */
1081         //glLoadIdentity();
1082         
1083         /* always free, blocks here have no unique identifier (1 block per node) */
1084         //uiFreeBlocksWin(&sa->uiblocks, sa->win);
1085
1086         /* only set once */
1087         glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
1088         glEnable(GL_MAP1_VERTEX_3);
1089
1090         /* aspect+font, set each time */
1091         //snode->aspect= (snode->v2d.cur.xmax - snode->v2d.cur.xmin)/((float)sa->winx);
1092         //snode->curfont= uiSetCurFont_ext(snode->aspect);
1093
1094         UI_view2d_constant_grid_draw(C, v2d);
1095         /* backdrop */
1096         // draw_nodespace_back_pix(sa, snode);
1097         
1098         /* nodes */
1099         snode_set_context(snode, CTX_data_scene(C));
1100         
1101         if(snode->nodetree) {
1102                 bNode *node;
1103                 
1104                 /* for now, we set drawing coordinates on each redraw */
1105                 for(node= snode->nodetree->nodes.first; node; node= node->next) {
1106                         if(node->flag & NODE_GROUP_EDIT)
1107                                 node_update_group(node);
1108                         else if(node->flag & NODE_HIDDEN)
1109                                 node_update_hidden(node);
1110                         else
1111                                 node_update(node);
1112                 }
1113
1114                 node_draw_nodetree(C, ar, snode, snode->nodetree);
1115                         
1116                 /* active group */
1117                 for(node= snode->nodetree->nodes.first; node; node= node->next) {
1118                         if(node->flag & NODE_GROUP_EDIT)
1119                                 node_draw_group(C, ar, snode, node);
1120                 }
1121         }
1122         
1123         /* draw grease-pencil ('canvas' strokes) */
1124         /*if ((snode->flag & SNODE_DISPGP) && (snode->nodetree))
1125                 draw_gpencil_2dview(sa, 1);*/
1126         
1127         /* restore viewport (not needed yet) */
1128         /*mywinset(sa->win);*/
1129
1130         /* ortho at pixel level curarea */
1131         /*myortho2(-0.375, sa->winx-0.375, -0.375, sa->winy-0.375);*/
1132         
1133         /* draw grease-pencil (screen strokes) */
1134         /*if ((snode->flag & SNODE_DISPGP) && (snode->nodetree))
1135                 draw_gpencil_2dview(sa, 0);*/
1136
1137         //draw_area_emboss(sa);
1138         
1139         /* it is important to end a view in a transform compatible with buttons */
1140         /*bwin_scalematrix(sa->win, snode->blockscale, snode->blockscale, snode->blockscale);
1141         nodes_blockhandlers(sa);*/
1142         
1143         //curarea->win_swap= WIN_BACK_OK;
1144         
1145         /* in the end, this is a delayed previewrender test, to allow buttons to be first */
1146         /*if(snode->flag & SNODE_DO_PREVIEW) {
1147                 addafterqueue(sa->win, RENDERPREVIEW, 1);
1148                 snode->flag &= ~SNODE_DO_PREVIEW;
1149         }*/
1150         
1151         
1152         
1153         /* reset view matrix */
1154         UI_view2d_view_restore(C);
1155         
1156         /* scrollers */
1157         scrollers= UI_view2d_scrollers_calc(C, v2d, 10/*unit*/, V2D_GRID_CLAMP, V2D_ARG_DUMMY, V2D_ARG_DUMMY);
1158         UI_view2d_scrollers_draw(C, v2d, scrollers);
1159         UI_view2d_scrollers_free(scrollers);
1160 }