|
Blender
V2.59
|
00001 /* 00002 * $Id: node_draw.c 38751 2011-07-27 06:55:20Z campbellbarton $ 00003 * 00004 * ***** BEGIN GPL LICENSE BLOCK ***** 00005 * 00006 * This program is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU General Public License 00008 * as published by the Free Software Foundation; either version 2 00009 * of the License, or (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 * GNU General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU General Public License 00017 * along with this program; if not, write to the Free Software Foundation, 00018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00019 * 00020 * The Original Code is Copyright (C) 2008 Blender Foundation. 00021 * All rights reserved. 00022 * 00023 * The Original Code is: all of this file. 00024 * Contributor(s): Nathan Letwory 00025 * 00026 * ***** END GPL LICENSE BLOCK ***** 00027 */ 00028 00034 #include <math.h> 00035 #include <stdio.h> 00036 #include <string.h> 00037 00038 #include "MEM_guardedalloc.h" 00039 00040 #include "DNA_node_types.h" 00041 #include "DNA_material_types.h" 00042 #include "DNA_object_types.h" 00043 #include "DNA_scene_types.h" 00044 #include "DNA_space_types.h" 00045 #include "DNA_screen_types.h" 00046 00047 #include "BLI_math.h" 00048 #include "BLI_blenlib.h" 00049 #include "BLI_threads.h" 00050 #include "BLI_utildefines.h" 00051 00052 #include "BKE_context.h" 00053 #include "BKE_depsgraph.h" 00054 #include "BKE_main.h" 00055 #include "BKE_node.h" 00056 00057 #include "BIF_gl.h" 00058 #include "BIF_glutil.h" 00059 00060 #include "WM_api.h" 00061 #include "WM_types.h" 00062 00063 #include "ED_node.h" 00064 #include "ED_gpencil.h" 00065 00066 #include "UI_interface.h" 00067 #include "UI_interface_icons.h" 00068 #include "UI_resources.h" 00069 #include "UI_view2d.h" 00070 00071 #include "RNA_access.h" 00072 00073 #include "CMP_node.h" 00074 #include "SHD_node.h" 00075 00076 #include "node_intern.h" 00077 00078 /* width of socket columns in group display */ 00079 #define NODE_GROUP_FRAME 120 00080 00081 // XXX interface.h 00082 extern void ui_dropshadow(rctf *rct, float radius, float aspect, int select); 00083 00084 void ED_node_changed_update(ID *id, bNode *node) 00085 { 00086 bNodeTree *nodetree, *edittree; 00087 int treetype; 00088 00089 node_tree_from_ID(id, &nodetree, &edittree, &treetype); 00090 00091 if(treetype==NTREE_SHADER) { 00092 DAG_id_tag_update(id, 0); 00093 WM_main_add_notifier(NC_MATERIAL|ND_SHADING_DRAW, id); 00094 } 00095 else if(treetype==NTREE_COMPOSIT) { 00096 NodeTagChanged(edittree, node); 00097 /* don't use NodeTagIDChanged, it gives far too many recomposites for image, scene layers, ... */ 00098 00099 node= node_tree_get_editgroup(nodetree); 00100 if(node) 00101 NodeTagIDChanged(nodetree, node->id); 00102 00103 WM_main_add_notifier(NC_SCENE|ND_NODES, id); 00104 } 00105 else if(treetype==NTREE_TEXTURE) { 00106 DAG_id_tag_update(id, 0); 00107 WM_main_add_notifier(NC_TEXTURE|ND_NODES, id); 00108 } 00109 } 00110 00111 static int has_nodetree(bNodeTree *ntree, bNodeTree *lookup) 00112 { 00113 bNode *node; 00114 00115 if(ntree == lookup) 00116 return 1; 00117 00118 for(node=ntree->nodes.first; node; node=node->next) 00119 if(node->type == NODE_GROUP && node->id) 00120 if(has_nodetree((bNodeTree*)node->id, lookup)) 00121 return 1; 00122 00123 return 0; 00124 } 00125 00126 void ED_node_generic_update(Main *bmain, bNodeTree *ntree, bNode *node) 00127 { 00128 Material *ma; 00129 Tex *tex; 00130 Scene *sce; 00131 00132 /* look through all datablocks, to support groups */ 00133 for(ma=bmain->mat.first; ma; ma=ma->id.next) 00134 if(ma->nodetree && ma->use_nodes && has_nodetree(ma->nodetree, ntree)) 00135 ED_node_changed_update(&ma->id, node); 00136 00137 for(tex=bmain->tex.first; tex; tex=tex->id.next) 00138 if(tex->nodetree && tex->use_nodes && has_nodetree(tex->nodetree, ntree)) 00139 ED_node_changed_update(&tex->id, node); 00140 00141 for(sce=bmain->scene.first; sce; sce=sce->id.next) 00142 if(sce->nodetree && sce->use_nodes && has_nodetree(sce->nodetree, ntree)) 00143 ED_node_changed_update(&sce->id, node); 00144 00145 if(ntree->type == NTREE_TEXTURE) 00146 ntreeTexCheckCyclics(ntree); 00147 } 00148 00149 static void do_node_internal_buttons(bContext *C, void *node_v, int event) 00150 { 00151 if(event==B_NODE_EXEC) { 00152 SpaceNode *snode= CTX_wm_space_node(C); 00153 if(snode && snode->id) 00154 ED_node_changed_update(snode->id, node_v); 00155 } 00156 } 00157 00158 00159 static void node_scaling_widget(int color_id, float aspect, float xmin, float ymin, float xmax, float ymax) 00160 { 00161 float dx; 00162 float dy; 00163 00164 dx= 0.5f*(xmax-xmin); 00165 dy= 0.5f*(ymax-ymin); 00166 00167 UI_ThemeColorShade(color_id, +30); 00168 fdrawline(xmin, ymin, xmax, ymax); 00169 fdrawline(xmin+dx, ymin, xmax, ymax-dy); 00170 00171 UI_ThemeColorShade(color_id, -10); 00172 fdrawline(xmin, ymin+aspect, xmax, ymax+aspect); 00173 fdrawline(xmin+dx, ymin+aspect, xmax, ymax-dy+aspect); 00174 } 00175 00176 static void node_uiblocks_init(const bContext *C, bNodeTree *ntree) 00177 { 00178 bNode *node; 00179 char str[32]; 00180 00181 /* add node uiBlocks in reverse order - prevents events going to overlapping nodes */ 00182 00183 /* process selected nodes first so they're at the start of the uiblocks list */ 00184 for(node= ntree->nodes.last; node; node= node->prev) { 00185 00186 if (node->flag & NODE_SELECT) { 00187 /* ui block */ 00188 sprintf(str, "node buttons %p", (void *)node); 00189 node->block= uiBeginBlock(C, CTX_wm_region(C), str, UI_EMBOSS); 00190 uiBlockSetHandleFunc(node->block, do_node_internal_buttons, node); 00191 } 00192 } 00193 00194 /* then the rest */ 00195 for(node= ntree->nodes.last; node; node= node->prev) { 00196 00197 if (!(node->flag & (NODE_GROUP_EDIT|NODE_SELECT))) { 00198 /* ui block */ 00199 sprintf(str, "node buttons %p", (void *)node); 00200 node->block= uiBeginBlock(C, CTX_wm_region(C), str, UI_EMBOSS); 00201 uiBlockSetHandleFunc(node->block, do_node_internal_buttons, node); 00202 } 00203 } 00204 } 00205 00206 /* based on settings in node, sets drawing rect info. each redraw! */ 00207 static void node_update(const bContext *C, bNodeTree *ntree, bNode *node) 00208 { 00209 uiLayout *layout; 00210 PointerRNA ptr; 00211 bNodeSocket *nsock; 00212 float dy= node->locy; 00213 int buty; 00214 00215 /* header */ 00216 dy-= NODE_DY; 00217 00218 /* little bit space in top */ 00219 if(node->outputs.first) 00220 dy-= NODE_DYS/2; 00221 00222 /* output sockets */ 00223 for(nsock= node->outputs.first; nsock; nsock= nsock->next) { 00224 if(!(nsock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) { 00225 nsock->locx= node->locx + node->width; 00226 nsock->locy= dy - NODE_DYS; 00227 dy-= NODE_DY; 00228 } 00229 } 00230 00231 node->prvr.xmin= node->locx + NODE_DYS; 00232 node->prvr.xmax= node->locx + node->width- NODE_DYS; 00233 00234 /* preview rect? */ 00235 if(node->flag & NODE_PREVIEW) { 00236 /* only recalculate size when there's a preview actually, otherwise we use stored result */ 00237 BLI_lock_thread(LOCK_PREVIEW); 00238 00239 if(node->preview && node->preview->rect) { 00240 float aspect= 1.0f; 00241 00242 if(node->preview && node->preview->xsize && node->preview->ysize) 00243 aspect= (float)node->preview->ysize/(float)node->preview->xsize; 00244 00245 dy-= NODE_DYS/2; 00246 node->prvr.ymax= dy; 00247 00248 if(aspect <= 1.0f) 00249 node->prvr.ymin= dy - aspect*(node->width-NODE_DY); 00250 else { 00251 float dx= (node->width - NODE_DYS) - (node->width- NODE_DYS)/aspect; /* width correction of image */ 00252 00253 node->prvr.ymin= dy - (node->width-NODE_DY); 00254 00255 node->prvr.xmin+= 0.5f*dx; 00256 node->prvr.xmax-= 0.5f*dx; 00257 } 00258 00259 dy= node->prvr.ymin - NODE_DYS/2; 00260 00261 /* make sure that maximums are bigger or equal to minimums */ 00262 if(node->prvr.xmax < node->prvr.xmin) SWAP(float, node->prvr.xmax, node->prvr.xmin); 00263 if(node->prvr.ymax < node->prvr.ymin) SWAP(float, node->prvr.ymax, node->prvr.ymin); 00264 } 00265 else { 00266 float oldh= node->prvr.ymax - node->prvr.ymin; 00267 if(oldh==0.0f) 00268 oldh= 0.6f*node->width-NODE_DY; 00269 dy-= NODE_DYS/2; 00270 node->prvr.ymax= dy; 00271 node->prvr.ymin= dy - oldh; 00272 dy= node->prvr.ymin - NODE_DYS/2; 00273 } 00274 00275 BLI_unlock_thread(LOCK_PREVIEW); 00276 } 00277 00278 /* buttons rect? */ 00279 if((node->flag & NODE_OPTIONS) && node->typeinfo->uifunc) { 00280 dy-= NODE_DYS/2; 00281 00282 /* set this for uifunc() that don't use layout engine yet */ 00283 node->butr.xmin= 0; 00284 node->butr.xmax= node->width - 2*NODE_DYS; 00285 node->butr.ymin= 0; 00286 node->butr.ymax= 0; 00287 00288 RNA_pointer_create(&ntree->id, &RNA_Node, node, &ptr); 00289 00290 layout= uiBlockLayout(node->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, 00291 node->locx+NODE_DYS, dy, node->butr.xmax, NODE_DY, U.uistyles.first); 00292 00293 node->typeinfo->uifunc(layout, (bContext *)C, &ptr); 00294 uiBlockEndAlign(node->block); 00295 uiBlockLayoutResolve(node->block, NULL, &buty); 00296 00297 dy= buty - NODE_DYS/2; 00298 } 00299 00300 /* input sockets */ 00301 for(nsock= node->inputs.first; nsock; nsock= nsock->next) { 00302 if(!(nsock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) { 00303 nsock->locx= node->locx; 00304 nsock->locy= dy - NODE_DYS; 00305 dy-= NODE_DY; 00306 } 00307 } 00308 00309 /* little bit space in end */ 00310 if(node->inputs.first || (node->flag & (NODE_OPTIONS|NODE_PREVIEW))==0 ) 00311 dy-= NODE_DYS/2; 00312 00313 node->totr.xmin= node->locx; 00314 node->totr.xmax= node->locx + node->width; 00315 node->totr.ymax= node->locy; 00316 node->totr.ymin= MIN2(dy, node->locy-2*NODE_DY); 00317 } 00318 00319 /* based on settings in node, sets drawing rect info. each redraw! */ 00320 static void node_update_hidden(bNode *node) 00321 { 00322 bNodeSocket *nsock; 00323 float rad, drad, hiddenrad= HIDDEN_RAD; 00324 int totin=0, totout=0, tot; 00325 00326 /* calculate minimal radius */ 00327 for(nsock= node->inputs.first; nsock; nsock= nsock->next) 00328 if(!(nsock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) 00329 totin++; 00330 for(nsock= node->outputs.first; nsock; nsock= nsock->next) 00331 if(!(nsock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) 00332 totout++; 00333 00334 tot= MAX2(totin, totout); 00335 if(tot>4) { 00336 hiddenrad += 5.0f*(float)(tot-4); 00337 } 00338 00339 node->totr.xmin= node->locx; 00340 node->totr.xmax= node->locx + 3*hiddenrad + node->miniwidth; 00341 node->totr.ymax= node->locy + (hiddenrad - 0.5f*NODE_DY); 00342 node->totr.ymin= node->totr.ymax - 2*hiddenrad; 00343 00344 /* output sockets */ 00345 rad=drad= (float)M_PI/(1.0f + (float)totout); 00346 00347 for(nsock= node->outputs.first; nsock; nsock= nsock->next) { 00348 if(!(nsock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) { 00349 nsock->locx= node->totr.xmax - hiddenrad + (float)sin(rad)*hiddenrad; 00350 nsock->locy= node->totr.ymin + hiddenrad + (float)cos(rad)*hiddenrad; 00351 rad+= drad; 00352 } 00353 } 00354 00355 /* input sockets */ 00356 rad=drad= - (float)M_PI/(1.0f + (float)totin); 00357 00358 for(nsock= node->inputs.first; nsock; nsock= nsock->next) { 00359 if(!(nsock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) { 00360 nsock->locx= node->totr.xmin + hiddenrad + (float)sin(rad)*hiddenrad; 00361 nsock->locy= node->totr.ymin + hiddenrad + (float)cos(rad)*hiddenrad; 00362 rad+= drad; 00363 } 00364 } 00365 } 00366 00367 static int node_get_colorid(bNode *node) 00368 { 00369 if(node->typeinfo->nclass==NODE_CLASS_INPUT) 00370 return TH_NODE_IN_OUT; 00371 if(node->typeinfo->nclass==NODE_CLASS_OUTPUT) { 00372 if(node->flag & NODE_DO_OUTPUT) 00373 return TH_NODE_IN_OUT; 00374 else 00375 return TH_NODE; 00376 } 00377 if(node->typeinfo->nclass==NODE_CLASS_CONVERTOR) 00378 return TH_NODE_CONVERTOR; 00379 if(ELEM3(node->typeinfo->nclass, NODE_CLASS_OP_COLOR, NODE_CLASS_OP_VECTOR, NODE_CLASS_OP_FILTER)) 00380 return TH_NODE_OPERATOR; 00381 if(node->typeinfo->nclass==NODE_CLASS_GROUP) 00382 return TH_NODE_GROUP; 00383 return TH_NODE; 00384 } 00385 00386 /* based on settings in node, sets drawing rect info. each redraw! */ 00387 /* note: this assumes only 1 group at a time is drawn (linked data) */ 00388 /* in node->totr the entire boundbox for the group is stored */ 00389 static void node_update_group(const bContext *C, bNodeTree *UNUSED(ntree), bNode *gnode) 00390 { 00391 bNodeTree *ngroup= (bNodeTree *)gnode->id; 00392 bNode *node; 00393 bNodeSocket *sock, *gsock; 00394 rctf *rect= &gnode->totr; 00395 float node_group_frame= U.dpi*NODE_GROUP_FRAME/72; 00396 int counter; 00397 int dy; 00398 00399 rect->xmin = rect->xmax = gnode->locx; 00400 rect->ymin = rect->ymax = gnode->locy; 00401 00402 /* center them, is a bit of abuse of locx and locy though */ 00403 for(node= ngroup->nodes.first; node; node= node->next) { 00404 node->locx+= gnode->locx; 00405 node->locy+= gnode->locy; 00406 00407 if(node->flag & NODE_HIDDEN) 00408 node_update_hidden(node); 00409 else 00410 node_update(C, ngroup, node); 00411 node->locx-= gnode->locx; 00412 node->locy-= gnode->locy; 00413 } 00414 counter= 1; 00415 for(node= ngroup->nodes.first; node; node= node->next) { 00416 if(counter) { 00417 *rect= node->totr; 00418 counter= 0; 00419 } 00420 else 00421 BLI_union_rctf(rect, &node->totr); 00422 } 00423 00424 /* add some room for links to group sockets */ 00425 rect->xmin -= 4*NODE_DY; 00426 rect->xmax += 4*NODE_DY; 00427 rect->ymin-= NODE_DY; 00428 rect->ymax+= NODE_DY; 00429 00430 /* input sockets */ 00431 dy = 0.5f*(rect->ymin+rect->ymax) + NODE_DY*(BLI_countlist(&gnode->inputs)-1); 00432 for(gsock=ngroup->inputs.first, sock=gnode->inputs.first; gsock; gsock=gsock->next, sock=sock->next) { 00433 gsock->locx = rect->xmin; 00434 sock->locx = rect->xmin - node_group_frame; 00435 sock->locy = gsock->locy = dy; 00436 00437 /* prevent long socket lists from growing out of the group box */ 00438 if (dy-3*NODE_DYS < rect->ymin) 00439 rect->ymin = dy-3*NODE_DYS; 00440 if (dy+3*NODE_DYS > rect->ymax) 00441 rect->ymax = dy+3*NODE_DYS; 00442 00443 dy -= 2*NODE_DY; 00444 } 00445 00446 /* output sockets */ 00447 dy = 0.5f*(rect->ymin+rect->ymax) + NODE_DY*(BLI_countlist(&gnode->outputs)-1); 00448 for(gsock=ngroup->outputs.first, sock=gnode->outputs.first; gsock; gsock=gsock->next, sock=sock->next) { 00449 gsock->locx = rect->xmax; 00450 sock->locx = rect->xmax + node_group_frame; 00451 sock->locy = gsock->locy = dy - NODE_DYS; 00452 00453 /* prevent long socket lists from growing out of the group box */ 00454 if (dy-3*NODE_DYS < rect->ymin) 00455 rect->ymin = dy-3*NODE_DYS; 00456 if (dy+3*NODE_DYS > rect->ymax) 00457 rect->ymax = dy+3*NODE_DYS; 00458 00459 dy -= 2*NODE_DY; 00460 } 00461 } 00462 00463 /* note: in cmp_util.c is similar code, for node_compo_pass_on() */ 00464 /* note: in node_edit.c is similar code, for untangle node */ 00465 static void node_draw_mute_line(View2D *v2d, SpaceNode *snode, bNode *node) 00466 { 00467 bNodeSocket *valsock= NULL, *colsock= NULL, *vecsock= NULL; 00468 bNodeSocket *sock; 00469 bNodeLink link= {NULL}; 00470 int a; 00471 00472 /* connect the first value buffer in with first value out */ 00473 /* connect the first RGBA buffer in with first RGBA out */ 00474 00475 /* test the inputs */ 00476 for(a=0, sock= node->inputs.first; sock; sock= sock->next, a++) { 00477 if(nodeCountSocketLinks(snode->edittree, sock)) { 00478 if(sock->type==SOCK_VALUE && valsock==NULL) valsock= sock; 00479 if(sock->type==SOCK_VECTOR && vecsock==NULL) vecsock= sock; 00480 if(sock->type==SOCK_RGBA && colsock==NULL) colsock= sock; 00481 } 00482 } 00483 00484 /* outputs, draw lines */ 00485 glEnable(GL_BLEND); 00486 glEnable( GL_LINE_SMOOTH ); 00487 00488 if(valsock || colsock || vecsock) { 00489 for(a=0, sock= node->outputs.first; sock; sock= sock->next, a++) { 00490 if(nodeCountSocketLinks(snode->edittree, sock)) { 00491 link.tosock= sock; 00492 00493 if(sock->type==SOCK_VALUE && valsock) { 00494 link.fromsock= valsock; 00495 node_draw_link_bezier(v2d, snode, &link, TH_REDALERT, 0, TH_WIRE, 0, TH_WIRE); 00496 valsock= NULL; 00497 } 00498 if(sock->type==SOCK_VECTOR && vecsock) { 00499 link.fromsock= vecsock; 00500 node_draw_link_bezier(v2d, snode, &link, TH_REDALERT, 0, TH_WIRE, 0, TH_WIRE); 00501 vecsock= NULL; 00502 } 00503 if(sock->type==SOCK_RGBA && colsock) { 00504 link.fromsock= colsock; 00505 node_draw_link_bezier(v2d, snode, &link, TH_REDALERT, 0, TH_WIRE, 0, TH_WIRE); 00506 colsock= NULL; 00507 } 00508 } 00509 } 00510 } 00511 glDisable(GL_BLEND); 00512 glDisable( GL_LINE_SMOOTH ); 00513 } 00514 00515 /* nice AA filled circle */ 00516 /* this might have some more generic use */ 00517 static void circle_draw(float x, float y, float size, int col[3]) 00518 { 00519 /* 16 values of sin function */ 00520 static float si[16] = { 00521 0.00000000f, 0.39435585f,0.72479278f,0.93775213f, 00522 0.99871650f,0.89780453f,0.65137248f,0.29936312f, 00523 -0.10116832f,-0.48530196f,-0.79077573f,-0.96807711f, 00524 -0.98846832f,-0.84864425f,-0.57126821f,-0.20129852f 00525 }; 00526 /* 16 values of cos function */ 00527 static float co[16] ={ 00528 1.00000000f,0.91895781f,0.68896691f,0.34730525f, 00529 -0.05064916f,-0.44039415f,-0.75875812f,-0.95413925f, 00530 -0.99486932f,-0.87434661f,-0.61210598f,-0.25065253f, 00531 0.15142777f,0.52896401f,0.82076344f,0.97952994f, 00532 }; 00533 int a; 00534 00535 glColor3ub(col[0], col[1], col[2]); 00536 00537 glBegin(GL_POLYGON); 00538 for(a=0; a<16; a++) 00539 glVertex2f(x+size*si[a], y+size*co[a]); 00540 glEnd(); 00541 00542 glColor4ub(0, 0, 0, 150); 00543 glEnable(GL_BLEND); 00544 glEnable( GL_LINE_SMOOTH ); 00545 glBegin(GL_LINE_LOOP); 00546 for(a=0; a<16; a++) 00547 glVertex2f(x+size*si[a], y+size*co[a]); 00548 glEnd(); 00549 glDisable( GL_LINE_SMOOTH ); 00550 glDisable(GL_BLEND); 00551 } 00552 00553 static void socket_circle_draw(bNodeSocket *sock, float size) 00554 { 00555 int col[3]; 00556 00557 if(sock->type==-1) { 00558 col[0]= 0; col[1]= 0; col[2]= 0; 00559 } 00560 else if(sock->type==SOCK_VALUE) { 00561 col[0]= 160; col[1]= 160; col[2]= 160; 00562 } 00563 else if(sock->type==SOCK_VECTOR) { 00564 col[0]= 100; col[1]= 100; col[2]= 200; 00565 } 00566 else if(sock->type==SOCK_RGBA) { 00567 col[0]= 200; col[1]= 200; col[2]= 40; 00568 } 00569 else { 00570 col[0]= 100; col[1]= 200; col[2]= 100; 00571 } 00572 00573 circle_draw(sock->locx, sock->locy, size, col); 00574 } 00575 00576 static void node_sync_cb(bContext *UNUSED(C), void *snode_v, void *node_v) 00577 { 00578 SpaceNode *snode= snode_v; 00579 00580 if(snode->treetype==NTREE_SHADER) { 00581 nodeShaderSynchronizeID(node_v, 1); 00582 // allqueue(REDRAWBUTSSHADING, 0); 00583 } 00584 } 00585 00586 /* ************** Socket callbacks *********** */ 00587 00588 /* not a callback */ 00589 static void node_draw_preview(bNodePreview *preview, rctf *prv) 00590 { 00591 float xscale= (prv->xmax-prv->xmin)/((float)preview->xsize); 00592 float yscale= (prv->ymax-prv->ymin)/((float)preview->ysize); 00593 float tile= (prv->xmax - prv->xmin) / 10.0f; 00594 float x, y; 00595 00596 /* draw checkerboard backdrop to show alpha */ 00597 glColor3ub(120, 120, 120); 00598 glRectf(prv->xmin, prv->ymin, prv->xmax, prv->ymax); 00599 glColor3ub(160, 160, 160); 00600 00601 for(y=prv->ymin; y<prv->ymax; y+=tile*2) { 00602 for(x=prv->xmin; x<prv->xmax; x+=tile*2) { 00603 float tilex= tile, tiley= tile; 00604 00605 if(x+tile > prv->xmax) 00606 tilex= prv->xmax-x; 00607 if(y+tile > prv->ymax) 00608 tiley= prv->ymax-y; 00609 00610 glRectf(x, y, x + tilex, y + tiley); 00611 } 00612 } 00613 for(y=prv->ymin+tile; y<prv->ymax; y+=tile*2) { 00614 for(x=prv->xmin+tile; x<prv->xmax; x+=tile*2) { 00615 float tilex= tile, tiley= tile; 00616 00617 if(x+tile > prv->xmax) 00618 tilex= prv->xmax-x; 00619 if(y+tile > prv->ymax) 00620 tiley= prv->ymax-y; 00621 00622 glRectf(x, y, x + tilex, y + tiley); 00623 } 00624 } 00625 00626 glPixelZoom(xscale, yscale); 00627 00628 glEnable(GL_BLEND); 00629 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); /* premul graphics */ 00630 00631 glColor4f(1.0, 1.0, 1.0, 1.0); 00632 glaDrawPixelsTex(prv->xmin, prv->ymin, preview->xsize, preview->ysize, GL_UNSIGNED_BYTE, preview->rect); 00633 00634 glDisable(GL_BLEND); 00635 glPixelZoom(1.0f, 1.0f); 00636 00637 UI_ThemeColorShadeAlpha(TH_BACK, -15, +100); 00638 fdrawbox(prv->xmin, prv->ymin, prv->xmax, prv->ymax); 00639 00640 } 00641 00642 typedef struct SocketVectorMenuArgs { 00643 PointerRNA ptr; 00644 int x, y, width; 00645 uiButHandleFunc cb; 00646 void *arg1, *arg2; 00647 } SocketVectorMenuArgs; 00648 00649 /* NOTE: this is a block-menu, needs 0 events, otherwise the menu closes */ 00650 static uiBlock *socket_vector_menu(bContext *C, ARegion *ar, void *args_v) 00651 { 00652 SocketVectorMenuArgs *args= (SocketVectorMenuArgs*)args_v; 00653 uiBlock *block; 00654 uiLayout *layout; 00655 00656 block= uiBeginBlock(C, ar, "socket menu", UI_EMBOSS); 00657 uiBlockSetFlag(block, UI_BLOCK_KEEP_OPEN); 00658 00659 layout= uiLayoutColumn(uiBlockLayout(block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, args->x, args->y+2, args->width, NODE_DY, U.uistyles.first), 0); 00660 00661 uiItemR(layout, &args->ptr, "default_value", UI_ITEM_R_EXPAND, "", ICON_NONE); 00662 00663 return block; 00664 } 00665 00666 static void node_draw_socket_button(bNodeTree *ntree, bNodeSocket *sock, const char *name, 00667 uiBlock *block, int x, int y, int width, 00668 uiButHandleFunc cb, void *arg1, void *arg2) 00669 { 00670 uiBut *bt= NULL; 00671 PointerRNA ptr; 00672 int labelw; 00673 SocketVectorMenuArgs *args; 00674 00675 RNA_pointer_create(&ntree->id, &RNA_NodeSocket, sock, &ptr); 00676 00677 switch (sock->type) { 00678 case SOCK_VALUE: 00679 bt=uiDefButR(block, NUM, B_NODE_EXEC, name, 00680 x, y+1, width, NODE_DY-2, 00681 &ptr, "default_value", 0, sock->ns.min, sock->ns.max, -1, -1, NULL); 00682 if (cb) 00683 uiButSetFunc(bt, cb, arg1, arg2); 00684 break; 00685 00686 case SOCK_VECTOR: 00687 args= MEM_callocN(sizeof(SocketVectorMenuArgs), "SocketVectorMenuArgs"); 00688 00689 args->ptr = ptr; 00690 args->x = x; 00691 args->y = y; 00692 args->width = width; 00693 args->cb = cb; 00694 args->arg1 = arg1; 00695 args->arg2 = arg2; 00696 00697 uiDefBlockButN(block, socket_vector_menu, args, name, 00698 x, y+1, width, NODE_DY-2, 00699 ""); 00700 break; 00701 00702 case SOCK_RGBA: 00703 labelw= width - 40; 00704 00705 bt=uiDefButR(block, COL, B_NODE_EXEC, "", 00706 x, y+2, (labelw>0 ? 40 : width), NODE_DY-2, 00707 &ptr, "default_value", 0, sock->ns.min, sock->ns.max, -1, -1, NULL); 00708 if (cb) 00709 uiButSetFunc(bt, cb, arg1, arg2); 00710 00711 if (name[0]!='\0' && labelw>0) 00712 uiDefBut(block, LABEL, 0, name, 00713 x + 40, y+2, labelw, NODE_DY-2, 00714 NULL, 0, 0, 0, 0, ""); 00715 break; 00716 } 00717 } 00718 00719 static void node_draw_basis(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *node) 00720 { 00721 bNodeSocket *sock; 00722 rctf *rct= &node->totr; 00723 float iconofs; 00724 float socket_size= NODE_SOCKSIZE*U.dpi/72; 00725 float iconbutw= 0.8f*UI_UNIT_X; 00726 int color_id= node_get_colorid(node); 00727 char showname[128]; /* 128 used below */ 00728 View2D *v2d = &ar->v2d; 00729 00730 /* hurmf... another candidate for callback, have to see how this works first */ 00731 if(node->id && node->block && snode->treetype==NTREE_SHADER) 00732 nodeShaderSynchronizeID(node, 0); 00733 00734 /* skip if out of view */ 00735 if (node->totr.xmax < ar->v2d.cur.xmin || node->totr.xmin > ar->v2d.cur.xmax || 00736 node->totr.ymax < ar->v2d.cur.ymin || node->totr.ymin > ar->v2d.cur.ymax) { 00737 00738 uiEndBlock(C, node->block); 00739 node->block= NULL; 00740 return; 00741 } 00742 00743 uiSetRoundBox(15-4); 00744 ui_dropshadow(rct, BASIS_RAD, snode->aspect, node->flag & SELECT); 00745 00746 /* header */ 00747 if(color_id==TH_NODE) 00748 UI_ThemeColorShade(color_id, -20); 00749 else 00750 UI_ThemeColor(color_id); 00751 00752 if(node->flag & NODE_MUTED) 00753 UI_ThemeColorBlend(color_id, TH_REDALERT, 0.5f); 00754 00755 uiSetRoundBox(3); 00756 uiRoundBox(rct->xmin, rct->ymax-NODE_DY, rct->xmax, rct->ymax, BASIS_RAD); 00757 00758 /* show/hide icons, note this sequence is copied in do_header_node() node_state.c */ 00759 iconofs= rct->xmax - 7.0f; 00760 00761 if(node->typeinfo->flag & NODE_PREVIEW) { 00762 int icon_id; 00763 00764 if(node->flag & (NODE_ACTIVE_ID|NODE_DO_OUTPUT)) 00765 icon_id= ICON_MATERIAL; 00766 else 00767 icon_id= ICON_MATERIAL_DATA; 00768 iconofs-=iconbutw; 00769 uiDefIconBut(node->block, LABEL, B_REDR, icon_id, iconofs, rct->ymax-NODE_DY, 00770 iconbutw, UI_UNIT_Y, NULL, 0.0, 0.0, 1.0, 0.5, ""); 00771 } 00772 if(node->type == NODE_GROUP) { 00773 00774 iconofs-=iconbutw; 00775 uiDefIconBut(node->block, LABEL, B_REDR, ICON_NODETREE, iconofs, rct->ymax-NODE_DY, 00776 iconbutw, UI_UNIT_Y, NULL, 0.0, 0.0, 1.0, 0.5, ""); 00777 } 00778 if(node->typeinfo->flag & NODE_OPTIONS) { 00779 iconofs-=iconbutw; 00780 uiDefIconBut(node->block, LABEL, B_REDR, ICON_BUTS, iconofs, rct->ymax-NODE_DY, 00781 iconbutw, UI_UNIT_Y, NULL, 0.0, 0.0, 1.0, 0.5, ""); 00782 } 00783 { /* always hide/reveal unused sockets */ 00784 // XXX re-enable 00785 /* int shade; 00786 if(node_has_hidden_sockets(node)) 00787 shade= -40; 00788 else 00789 shade= -90; */ 00790 00791 iconofs-=iconbutw; 00792 00793 uiDefIconBut(node->block, LABEL, B_REDR, ICON_PLUS, iconofs, rct->ymax-NODE_DY, 00794 iconbutw, UI_UNIT_Y, NULL, 0.0, 0.0, 1.0, 0.5, ""); 00795 } 00796 00797 /* title */ 00798 if(node->flag & SELECT) 00799 UI_ThemeColor(TH_TEXT_HI); 00800 else 00801 UI_ThemeColorBlendShade(TH_TEXT, color_id, 0.4f, 10); 00802 00803 /* open/close entirely? */ 00804 UI_DrawTriIcon(rct->xmin+10.0f, rct->ymax-NODE_DY/2.0f, 'v'); 00805 00806 /* this isn't doing anything for the label, so commenting out 00807 if(node->flag & SELECT) 00808 UI_ThemeColor(TH_TEXT_HI); 00809 else 00810 UI_ThemeColor(TH_TEXT); */ 00811 00812 if (node->label[0]!='\0') 00813 BLI_strncpy(showname, node->label, sizeof(showname)); 00814 else if (node->typeinfo->labelfunc) 00815 BLI_strncpy(showname, node->typeinfo->labelfunc(node), sizeof(showname)); 00816 else 00817 BLI_strncpy(showname, node->typeinfo->name, sizeof(showname)); 00818 00819 //if(node->flag & NODE_MUTED) 00820 // sprintf(showname, "[%s]", showname); 00821 00822 uiDefBut(node->block, LABEL, 0, showname, (short)(rct->xmin+15), (short)(rct->ymax-NODE_DY), 00823 (int)(iconofs - rct->xmin-18.0f), NODE_DY, NULL, 0, 0, 0, 0, ""); 00824 00825 /* body */ 00826 UI_ThemeColor4(TH_NODE); 00827 glEnable(GL_BLEND); 00828 uiSetRoundBox(8); 00829 uiRoundBox(rct->xmin, rct->ymin, rct->xmax, rct->ymax-NODE_DY, BASIS_RAD); 00830 glDisable(GL_BLEND); 00831 00832 /* scaling indicator */ 00833 node_scaling_widget(TH_NODE, snode->aspect, rct->xmax-BASIS_RAD*snode->aspect, rct->ymin, rct->xmax, rct->ymin+BASIS_RAD*snode->aspect); 00834 00835 /* outline active and selected emphasis */ 00836 if( node->flag & (NODE_ACTIVE|SELECT) ) { 00837 glEnable(GL_BLEND); 00838 glEnable( GL_LINE_SMOOTH ); 00839 /* using different shades of TH_TEXT_HI for the empasis, like triangle */ 00840 if( node->flag & NODE_ACTIVE ) 00841 UI_ThemeColorShadeAlpha(TH_TEXT_HI, 0, -40); 00842 else 00843 UI_ThemeColorShadeAlpha(TH_TEXT_HI, -20, -120); 00844 uiSetRoundBox(15-4); // round all corners except lower right 00845 uiDrawBox(GL_LINE_LOOP, rct->xmin, rct->ymin, rct->xmax, rct->ymax, BASIS_RAD); 00846 00847 glDisable( GL_LINE_SMOOTH ); 00848 glDisable(GL_BLEND); 00849 } 00850 00851 /* disable lines */ 00852 if(node->flag & NODE_MUTED) 00853 node_draw_mute_line(v2d, snode, node); 00854 00855 00856 /* socket inputs, buttons */ 00857 for(sock= node->inputs.first; sock; sock= sock->next) { 00858 if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) { 00859 socket_circle_draw(sock, socket_size); 00860 00861 if(node->block && sock->link==NULL) { 00862 node_draw_socket_button(ntree, sock, sock->name, node->block, sock->locx+NODE_DYS, sock->locy-NODE_DYS, node->width-NODE_DY, node_sync_cb, snode, node); 00863 } 00864 else { 00865 uiDefBut(node->block, LABEL, 0, sock->name, (short)(sock->locx+7), (short)(sock->locy-9.0f), 00866 (short)(node->width-NODE_DY), NODE_DY, NULL, 0, 0, 0, 0, ""); 00867 } 00868 } 00869 } 00870 00871 /* socket outputs */ 00872 for(sock= node->outputs.first; sock; sock= sock->next) { 00873 if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) { 00874 float slen; 00875 int ofs= 0; 00876 00877 socket_circle_draw(sock, socket_size); 00878 00879 UI_ThemeColor(TH_TEXT); 00880 slen= snode->aspect*UI_GetStringWidth(sock->name); 00881 while(slen > node->width) { 00882 ofs++; 00883 slen= snode->aspect*UI_GetStringWidth(sock->name+ofs); 00884 } 00885 00886 uiDefBut(node->block, LABEL, 0, sock->name+ofs, (short)(sock->locx-15.0f-slen), (short)(sock->locy-9.0f), 00887 (short)(node->width-NODE_DY), NODE_DY, NULL, 0, 0, 0, 0, ""); 00888 } 00889 } 00890 00891 /* preview */ 00892 if(node->flag & NODE_PREVIEW) { 00893 BLI_lock_thread(LOCK_PREVIEW); 00894 if(node->preview && node->preview->rect && !BLI_rctf_is_empty(&node->prvr)) 00895 node_draw_preview(node->preview, &node->prvr); 00896 BLI_unlock_thread(LOCK_PREVIEW); 00897 } 00898 00899 UI_ThemeClearColor(color_id); 00900 00901 uiEndBlock(C, node->block); 00902 uiDrawBlock(C, node->block); 00903 node->block= NULL; 00904 } 00905 00906 static void node_draw_hidden(const bContext *C, ARegion *ar, SpaceNode *snode, bNode *node) 00907 { 00908 bNodeSocket *sock; 00909 rctf *rct= &node->totr; 00910 float dx, centy= 0.5f*(rct->ymax+rct->ymin); 00911 float hiddenrad= 0.5f*(rct->ymax-rct->ymin); 00912 float socket_size= NODE_SOCKSIZE*U.dpi/72; 00913 int color_id= node_get_colorid(node); 00914 char showname[128]; /* 128 is used below */ 00915 00916 /* shadow */ 00917 uiSetRoundBox(15); 00918 ui_dropshadow(rct, hiddenrad, snode->aspect, node->flag & SELECT); 00919 00920 /* body */ 00921 UI_ThemeColor(color_id); 00922 if(node->flag & NODE_MUTED) 00923 UI_ThemeColorBlend(color_id, TH_REDALERT, 0.5f); 00924 uiRoundBox(rct->xmin, rct->ymin, rct->xmax, rct->ymax, hiddenrad); 00925 00926 /* outline active and selected emphasis */ 00927 if( node->flag & (NODE_ACTIVE|SELECT) ) { 00928 glEnable(GL_BLEND); 00929 glEnable( GL_LINE_SMOOTH ); 00930 /* using different shades of TH_TEXT_HI for the empasis, like triangle */ 00931 if( node->flag & NODE_ACTIVE ) 00932 UI_ThemeColorShadeAlpha(TH_TEXT_HI, 0, -40); 00933 else 00934 UI_ThemeColorShadeAlpha(TH_TEXT_HI, -20, -120); 00935 uiDrawBox(GL_LINE_LOOP, rct->xmin, rct->ymin, rct->xmax, rct->ymax, hiddenrad); 00936 glDisable( GL_LINE_SMOOTH ); 00937 glDisable(GL_BLEND); 00938 } 00939 00940 /* title */ 00941 if(node->flag & SELECT) 00942 UI_ThemeColor(TH_TEXT_HI); 00943 else 00944 UI_ThemeColorBlendShade(TH_TEXT, color_id, 0.4f, 10); 00945 00946 /* open entirely icon */ 00947 UI_DrawTriIcon(rct->xmin+10.0f, centy, 'h'); 00948 00949 /* disable lines */ 00950 if(node->flag & NODE_MUTED) 00951 node_draw_mute_line(&ar->v2d, snode, node); 00952 00953 if(node->flag & SELECT) 00954 UI_ThemeColor(TH_TEXT_HI); 00955 else 00956 UI_ThemeColor(TH_TEXT); 00957 00958 if(node->miniwidth>0.0f) { 00959 if (node->label[0]!='\0') 00960 BLI_strncpy(showname, node->label, sizeof(showname)); 00961 else if (node->typeinfo->labelfunc) 00962 BLI_strncpy(showname, node->typeinfo->labelfunc(node), sizeof(showname)); 00963 else 00964 BLI_strncpy(showname, node->typeinfo->name, sizeof(showname)); 00965 00966 //if(node->flag & NODE_MUTED) 00967 // sprintf(showname, "[%s]", showname); 00968 00969 uiDefBut(node->block, LABEL, 0, showname, (short)(rct->xmin+15), (short)(centy-10), 00970 (int)(rct->xmax - rct->xmin-18.0f -12.0f), NODE_DY, NULL, 0, 0, 0, 0, ""); 00971 } 00972 00973 /* scale widget thing */ 00974 UI_ThemeColorShade(color_id, -10); 00975 dx= 10.0f; 00976 fdrawline(rct->xmax-dx, centy-4.0f, rct->xmax-dx, centy+4.0f); 00977 fdrawline(rct->xmax-dx-3.0f*snode->aspect, centy-4.0f, rct->xmax-dx-3.0f*snode->aspect, centy+4.0f); 00978 00979 UI_ThemeColorShade(color_id, +30); 00980 dx-= snode->aspect; 00981 fdrawline(rct->xmax-dx, centy-4.0f, rct->xmax-dx, centy+4.0f); 00982 fdrawline(rct->xmax-dx-3.0f*snode->aspect, centy-4.0f, rct->xmax-dx-3.0f*snode->aspect, centy+4.0f); 00983 00984 /* sockets */ 00985 for(sock= node->inputs.first; sock; sock= sock->next) { 00986 if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) 00987 socket_circle_draw(sock, socket_size); 00988 } 00989 00990 for(sock= node->outputs.first; sock; sock= sock->next) { 00991 if(!(sock->flag & (SOCK_HIDDEN|SOCK_UNAVAIL))) 00992 socket_circle_draw(sock, socket_size); 00993 } 00994 00995 uiEndBlock(C, node->block); 00996 uiDrawBlock(C, node->block); 00997 node->block= NULL; 00998 } 00999 01000 static void node_draw_nodetree(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree) 01001 { 01002 bNode *node; 01003 bNodeLink *link; 01004 int a; 01005 01006 if(ntree==NULL) return; /* groups... */ 01007 01008 /* node lines */ 01009 glEnable(GL_BLEND); 01010 glEnable(GL_LINE_SMOOTH); 01011 for(link= ntree->links.first; link; link= link->next) 01012 node_draw_link(&ar->v2d, snode, link); 01013 glDisable(GL_LINE_SMOOTH); 01014 glDisable(GL_BLEND); 01015 01016 /* not selected first */ 01017 for(a=0, node= ntree->nodes.first; node; node= node->next, a++) { 01018 node->nr= a; /* index of node in list, used for exec event code */ 01019 if(!(node->flag & SELECT)) { 01020 if(node->flag & NODE_GROUP_EDIT); 01021 else if(node->flag & NODE_HIDDEN) 01022 node_draw_hidden(C, ar, snode, node); 01023 else 01024 node_draw_basis(C, ar, snode, ntree, node); 01025 } 01026 } 01027 01028 /* selected */ 01029 for(node= ntree->nodes.first; node; node= node->next) { 01030 if(node->flag & SELECT) { 01031 if(node->flag & NODE_GROUP_EDIT); 01032 else if(node->flag & NODE_HIDDEN) 01033 node_draw_hidden(C, ar, snode, node); 01034 else 01035 node_draw_basis(C, ar, snode, ntree, node); 01036 } 01037 } 01038 } 01039 01040 static void group_verify_cb(bContext *UNUSED(C), void *UNUSED(snode_v), void *ngroup_v) 01041 { 01042 bNodeTree *ngroup= (bNodeTree*)ngroup_v; 01043 01044 nodeGroupVerify(ngroup); 01045 } 01046 01047 /* groups are, on creation, centered around 0,0 */ 01048 static void node_draw_group(const bContext *C, ARegion *ar, SpaceNode *snode, bNodeTree *ntree, bNode *gnode) 01049 { 01050 bNodeTree *ngroup= (bNodeTree *)gnode->id; 01051 bNodeSocket *sock; 01052 uiLayout *layout; 01053 PointerRNA ptr; 01054 uiBut *bt; 01055 rctf rect= gnode->totr; 01056 float socket_size= NODE_SOCKSIZE*U.dpi/72; 01057 float node_group_frame= U.dpi*NODE_GROUP_FRAME/72; 01058 float group_header= 26*U.dpi/72; 01059 float arrowbutw= 0.8f*UI_UNIT_X; 01060 /* layout stuff for buttons on group left frame */ 01061 float col1= 6, colw1= 0.6f*node_group_frame; 01062 float col2= col1 + colw1+6; 01063 float col3= node_group_frame - arrowbutw - 6; 01064 /* layout stuff for buttons on group right frame */ 01065 float cor1= 6; 01066 float cor2= cor1 + arrowbutw + 6; 01067 float cor3= cor2 + arrowbutw + 6, corw3= node_group_frame - cor3-6; 01068 01069 int index; 01070 01071 /* backdrop header */ 01072 glEnable(GL_BLEND); 01073 uiSetRoundBox(3); 01074 UI_ThemeColorShadeAlpha(TH_NODE_GROUP, 0, -70); 01075 uiDrawBox(GL_POLYGON, rect.xmin-node_group_frame, rect.ymax, rect.xmax+node_group_frame, rect.ymax+group_header, BASIS_RAD); 01076 01077 /* backdrop body */ 01078 UI_ThemeColorShadeAlpha(TH_BACK, -8, -70); 01079 uiSetRoundBox(0); 01080 uiDrawBox(GL_POLYGON, rect.xmin, rect.ymin, rect.xmax, rect.ymax, BASIS_RAD); 01081 01082 /* input column */ 01083 UI_ThemeColorShadeAlpha(TH_BACK, 10, -50); 01084 uiSetRoundBox(8); 01085 uiDrawBox(GL_POLYGON, rect.xmin-node_group_frame, rect.ymin, rect.xmin, rect.ymax, BASIS_RAD); 01086 01087 /* output column */ 01088 UI_ThemeColorShadeAlpha(TH_BACK, 10, -50); 01089 uiSetRoundBox(4); 01090 uiDrawBox(GL_POLYGON, rect.xmax, rect.ymin, rect.xmax+node_group_frame, rect.ymax, BASIS_RAD); 01091 01092 /* input column separator */ 01093 glColor4ub(200, 200, 200, 140); 01094 glBegin(GL_LINES); 01095 glVertex2f(rect.xmin, rect.ymin); 01096 glVertex2f(rect.xmin, rect.ymax); 01097 glEnd(); 01098 01099 /* output column separator */ 01100 glColor4ub(200, 200, 200, 140); 01101 glBegin(GL_LINES); 01102 glVertex2f(rect.xmax, rect.ymin); 01103 glVertex2f(rect.xmax, rect.ymax); 01104 glEnd(); 01105 01106 /* group node outline */ 01107 uiSetRoundBox(15); 01108 glColor4ub(200, 200, 200, 140); 01109 glEnable( GL_LINE_SMOOTH ); 01110 uiDrawBox(GL_LINE_LOOP, rect.xmin-node_group_frame, rect.ymin, rect.xmax+node_group_frame, rect.ymax+group_header, BASIS_RAD); 01111 glDisable( GL_LINE_SMOOTH ); 01112 glDisable(GL_BLEND); 01113 01114 /* backdrop title */ 01115 UI_ThemeColor(TH_TEXT_HI); 01116 01117 layout = uiBlockLayout(gnode->block, UI_LAYOUT_VERTICAL, UI_LAYOUT_PANEL, (short)(rect.xmin+15), (short)(rect.ymax+group_header), 01118 MIN2((int)(rect.xmax - rect.xmin-18.0f), node_group_frame+20), group_header, U.uistyles.first); 01119 RNA_pointer_create(&ntree->id, &RNA_Node, gnode, &ptr); 01120 uiTemplateIDBrowse(layout, (bContext*)C, &ptr, "node_tree", NULL, NULL, NULL); 01121 uiBlockLayoutResolve(gnode->block, NULL, NULL); 01122 01123 /* draw the internal tree nodes and links */ 01124 node_draw_nodetree(C, ar, snode, ngroup); 01125 01126 /* group sockets */ 01127 for(sock=ngroup->inputs.first, index=0; sock; sock=sock->next, ++index) { 01128 float locx= sock->locx - node_group_frame; 01129 01130 socket_circle_draw(sock, socket_size); 01131 /* small hack to use socket_circle_draw function with offset */ 01132 sock->locx -= node_group_frame; 01133 socket_circle_draw(sock, socket_size); 01134 sock->locx += node_group_frame; 01135 01136 bt = uiDefBut(gnode->block, TEX, 0, "", 01137 locx+col1, sock->locy+1, colw1, NODE_DY, 01138 sock->name, 0, 31, 0, 0, ""); 01139 uiButSetFunc(bt, group_verify_cb, snode, ngroup); 01140 01141 node_draw_socket_button(ngroup, sock, "", gnode->block, 01142 locx+col1, sock->locy-NODE_DY, colw1, 01143 NULL, NULL, NULL); 01144 01145 uiBlockSetDirection(gnode->block, UI_TOP); 01146 uiBlockBeginAlign(gnode->block); 01147 bt = uiDefIconButO(gnode->block, BUT, "NODE_OT_group_socket_move_up", 0, ICON_TRIA_UP, 01148 locx+col2, sock->locy, arrowbutw, arrowbutw, ""); 01149 if (!sock->prev) 01150 uiButSetFlag(bt, UI_BUT_DISABLED); 01151 RNA_int_set(uiButGetOperatorPtrRNA(bt), "index", index); 01152 RNA_enum_set(uiButGetOperatorPtrRNA(bt), "in_out", SOCK_IN); 01153 bt = uiDefIconButO(gnode->block, BUT, "NODE_OT_group_socket_move_down", 0, ICON_TRIA_DOWN, 01154 locx+col2, sock->locy-arrowbutw, arrowbutw, arrowbutw, ""); 01155 if (!sock->next) 01156 uiButSetFlag(bt, UI_BUT_DISABLED); 01157 RNA_int_set(uiButGetOperatorPtrRNA(bt), "index", index); 01158 RNA_enum_set(uiButGetOperatorPtrRNA(bt), "in_out", SOCK_IN); 01159 uiBlockEndAlign(gnode->block); 01160 uiBlockSetDirection(gnode->block, 0); 01161 01162 uiBlockSetEmboss(gnode->block, UI_EMBOSSN); 01163 bt = uiDefIconButO(gnode->block, BUT, "NODE_OT_group_socket_remove", 0, ICON_X, 01164 locx+col3, sock->locy-0.5f*arrowbutw, arrowbutw, arrowbutw, ""); 01165 RNA_int_set(uiButGetOperatorPtrRNA(bt), "index", index); 01166 RNA_enum_set(uiButGetOperatorPtrRNA(bt), "in_out", SOCK_IN); 01167 uiBlockSetEmboss(gnode->block, UI_EMBOSS); 01168 } 01169 01170 for(sock=ngroup->outputs.first, index=0; sock; sock=sock->next, ++index) { 01171 float locx= sock->locx; 01172 01173 socket_circle_draw(sock, socket_size); 01174 /* small hack to use socket_circle_draw function with offset */ 01175 sock->locx += node_group_frame; 01176 socket_circle_draw(sock, socket_size); 01177 sock->locx -= node_group_frame; 01178 01179 uiBlockSetEmboss(gnode->block, UI_EMBOSSN); 01180 bt = uiDefIconButO(gnode->block, BUT, "NODE_OT_group_socket_remove", 0, ICON_X, 01181 locx+col1, sock->locy-0.5f*arrowbutw, arrowbutw, arrowbutw, ""); 01182 RNA_int_set(uiButGetOperatorPtrRNA(bt), "index", index); 01183 RNA_enum_set(uiButGetOperatorPtrRNA(bt), "in_out", SOCK_OUT); 01184 uiBlockSetEmboss(gnode->block, UI_EMBOSS); 01185 01186 uiBlockSetDirection(gnode->block, UI_TOP); 01187 uiBlockBeginAlign(gnode->block); 01188 bt = uiDefIconButO(gnode->block, BUT, "NODE_OT_group_socket_move_up", 0, ICON_TRIA_UP, 01189 locx+cor2, sock->locy, arrowbutw, arrowbutw, ""); 01190 if (!sock->prev) 01191 uiButSetFlag(bt, UI_BUT_DISABLED); 01192 RNA_int_set(uiButGetOperatorPtrRNA(bt), "index", index); 01193 RNA_enum_set(uiButGetOperatorPtrRNA(bt), "in_out", SOCK_OUT); 01194 bt = uiDefIconButO(gnode->block, BUT, "NODE_OT_group_socket_move_down", 0, ICON_TRIA_DOWN, 01195 locx+cor2, sock->locy-arrowbutw, arrowbutw, arrowbutw, ""); 01196 if (!sock->next) 01197 uiButSetFlag(bt, UI_BUT_DISABLED); 01198 RNA_int_set(uiButGetOperatorPtrRNA(bt), "index", index); 01199 RNA_enum_set(uiButGetOperatorPtrRNA(bt), "in_out", SOCK_OUT); 01200 uiBlockEndAlign(gnode->block); 01201 uiBlockSetDirection(gnode->block, 0); 01202 01203 if (sock->link) { 01204 bt = uiDefBut(gnode->block, TEX, 0, "", 01205 locx+cor3, sock->locy-NODE_DYS+1, corw3, NODE_DY, 01206 sock->name, 0, 31, 0, 0, ""); 01207 uiButSetFunc(bt, group_verify_cb, snode, ngroup); 01208 } 01209 else { 01210 bt = uiDefBut(gnode->block, TEX, 0, "", 01211 locx+cor3, sock->locy+1, corw3, NODE_DY, 01212 sock->name, 0, 31, 0, 0, ""); 01213 uiButSetFunc(bt, group_verify_cb, snode, ngroup); 01214 01215 node_draw_socket_button(ngroup, sock, "", gnode->block, locx+cor3, sock->locy-NODE_DY, corw3, NULL, NULL, NULL); 01216 } 01217 } 01218 01219 uiEndBlock(C, gnode->block); 01220 uiDrawBlock(C, gnode->block); 01221 gnode->block= NULL; 01222 } 01223 01224 void drawnodespace(const bContext *C, ARegion *ar, View2D *v2d) 01225 { 01226 View2DScrollers *scrollers; 01227 SpaceNode *snode= CTX_wm_space_node(C); 01228 Scene *scene= CTX_data_scene(C); 01229 int color_manage = scene->r.color_mgt_flag & R_COLOR_MANAGEMENT; 01230 bNodeLinkDrag *nldrag; 01231 01232 UI_ThemeClearColor(TH_BACK); 01233 glClear(GL_COLOR_BUFFER_BIT); 01234 01235 UI_view2d_view_ortho(v2d); 01236 01237 //uiFreeBlocksWin(&sa->uiblocks, sa->win); 01238 01239 /* only set once */ 01240 glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); 01241 glEnable(GL_MAP1_VERTEX_3); 01242 01243 /* aspect+font, set each time */ 01244 snode->aspect= (v2d->cur.xmax - v2d->cur.xmin)/((float)ar->winx); 01245 // XXX snode->curfont= uiSetCurFont_ext(snode->aspect); 01246 01247 UI_view2d_constant_grid_draw(v2d); 01248 /* backdrop */ 01249 draw_nodespace_back_pix(ar, snode, color_manage); 01250 01251 /* nodes */ 01252 snode_set_context(snode, CTX_data_scene(C)); 01253 01254 if(snode->nodetree) { 01255 bNode *node; 01256 01257 /* init ui blocks for opened node group trees first 01258 * so they're in the correct depth stack order */ 01259 for(node= snode->nodetree->nodes.first; node; node= node->next) { 01260 if(node->flag & NODE_GROUP_EDIT) 01261 node_uiblocks_init(C, (bNodeTree *)node->id); 01262 } 01263 01264 node_uiblocks_init(C, snode->nodetree); 01265 01266 01267 /* for now, we set drawing coordinates on each redraw */ 01268 for(node= snode->nodetree->nodes.first; node; node= node->next) { 01269 if(node->flag & NODE_GROUP_EDIT) 01270 node_update_group(C, snode->nodetree, node); 01271 else if(node->flag & NODE_HIDDEN) 01272 node_update_hidden(node); 01273 else 01274 node_update(C, snode->nodetree, node); 01275 } 01276 01277 node_draw_nodetree(C, ar, snode, snode->nodetree); 01278 01279 /* active group */ 01280 for(node= snode->nodetree->nodes.first; node; node= node->next) { 01281 if(node->flag & NODE_GROUP_EDIT) 01282 node_draw_group(C, ar, snode, snode->nodetree, node); 01283 } 01284 } 01285 01286 /* temporary links */ 01287 glEnable(GL_BLEND); 01288 glEnable(GL_LINE_SMOOTH); 01289 for(nldrag= snode->linkdrag.first; nldrag; nldrag= nldrag->next) 01290 node_draw_link(&ar->v2d, snode, nldrag->link); 01291 glDisable(GL_LINE_SMOOTH); 01292 glDisable(GL_BLEND); 01293 01294 /* draw grease-pencil ('canvas' strokes) */ 01295 if (/*(snode->flag & SNODE_DISPGP) &&*/ (snode->nodetree)) 01296 draw_gpencil_view2d((bContext*)C, 1); 01297 01298 /* reset view matrix */ 01299 UI_view2d_view_restore(C); 01300 01301 /* draw grease-pencil (screen strokes, and also paintbuffer) */ 01302 if (/*(snode->flag & SNODE_DISPGP) && */(snode->nodetree)) 01303 draw_gpencil_view2d((bContext*)C, 0); 01304 01305 /* scrollers */ 01306 scrollers= UI_view2d_scrollers_calc(C, v2d, 10, V2D_GRID_CLAMP, V2D_ARG_DUMMY, V2D_ARG_DUMMY); 01307 UI_view2d_scrollers_draw(C, v2d, scrollers); 01308 UI_view2d_scrollers_free(scrollers); 01309 }