Blender V2.61 - r43446
|
00001 /* 00002 * ***** BEGIN GPL LICENSE BLOCK ***** 00003 * 00004 * This program is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU General Public License 00006 * as published by the Free Software Foundation; either version 2 00007 * of the License, or (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software Foundation, 00016 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 * 00018 * The Original Code is Copyright (C) 2008 Blender Foundation. 00019 * All rights reserved. 00020 * 00021 * 00022 * Contributor(s): Blender Foundation 00023 * 00024 * ***** END GPL LICENSE BLOCK ***** 00025 */ 00026 00032 #include <string.h> 00033 #include <stdio.h> 00034 00035 #include "DNA_lamp_types.h" 00036 #include "DNA_material_types.h" 00037 #include "DNA_node_types.h" 00038 #include "DNA_object_types.h" 00039 #include "DNA_scene_types.h" 00040 #include "DNA_world_types.h" 00041 00042 #include "MEM_guardedalloc.h" 00043 00044 #include "BLI_blenlib.h" 00045 #include "BLI_math.h" 00046 #include "BLI_rand.h" 00047 #include "BLI_utildefines.h" 00048 00049 #include "BKE_context.h" 00050 #include "BKE_screen.h" 00051 #include "BKE_node.h" 00052 00053 #include "ED_space_api.h" 00054 #include "ED_render.h" 00055 #include "ED_screen.h" 00056 00057 00058 #include "WM_api.h" 00059 #include "WM_types.h" 00060 00061 #include "UI_resources.h" 00062 #include "UI_view2d.h" 00063 00064 #include "RNA_access.h" 00065 00066 #include "node_intern.h" // own include 00067 00068 /* ******************** manage regions ********************* */ 00069 00070 ARegion *node_has_buttons_region(ScrArea *sa) 00071 { 00072 ARegion *ar, *arnew; 00073 00074 ar= BKE_area_find_region_type(sa, RGN_TYPE_UI); 00075 if(ar) return ar; 00076 00077 /* add subdiv level; after header */ 00078 ar= BKE_area_find_region_type(sa, RGN_TYPE_HEADER); 00079 00080 /* is error! */ 00081 if(ar==NULL) return NULL; 00082 00083 arnew= MEM_callocN(sizeof(ARegion), "buttons for node"); 00084 00085 BLI_insertlinkafter(&sa->regionbase, ar, arnew); 00086 arnew->regiontype= RGN_TYPE_UI; 00087 arnew->alignment= RGN_ALIGN_RIGHT; 00088 00089 arnew->flag = RGN_FLAG_HIDDEN; 00090 00091 return arnew; 00092 } 00093 00094 /* ******************** default callbacks for node space ***************** */ 00095 00096 static SpaceLink *node_new(const bContext *UNUSED(C)) 00097 { 00098 ARegion *ar; 00099 SpaceNode *snode; 00100 00101 snode= MEM_callocN(sizeof(SpaceNode), "initnode"); 00102 snode->spacetype= SPACE_NODE; 00103 00104 /* backdrop */ 00105 snode->zoom = 1.0f; 00106 00107 /* header */ 00108 ar= MEM_callocN(sizeof(ARegion), "header for node"); 00109 00110 BLI_addtail(&snode->regionbase, ar); 00111 ar->regiontype= RGN_TYPE_HEADER; 00112 ar->alignment= RGN_ALIGN_BOTTOM; 00113 00114 /* buttons/list view */ 00115 ar= MEM_callocN(sizeof(ARegion), "buttons for node"); 00116 00117 BLI_addtail(&snode->regionbase, ar); 00118 ar->regiontype= RGN_TYPE_UI; 00119 ar->alignment= RGN_ALIGN_RIGHT; 00120 ar->flag = RGN_FLAG_HIDDEN; 00121 00122 /* main area */ 00123 ar= MEM_callocN(sizeof(ARegion), "main area for node"); 00124 00125 BLI_addtail(&snode->regionbase, ar); 00126 ar->regiontype= RGN_TYPE_WINDOW; 00127 00128 ar->v2d.tot.xmin= -256.0f; 00129 ar->v2d.tot.ymin= -256.0f; 00130 ar->v2d.tot.xmax= 768.0f; 00131 ar->v2d.tot.ymax= 768.0f; 00132 00133 ar->v2d.cur.xmin= -256.0f; 00134 ar->v2d.cur.ymin= -256.0f; 00135 ar->v2d.cur.xmax= 768.0f; 00136 ar->v2d.cur.ymax= 768.0f; 00137 00138 ar->v2d.min[0]= 1.0f; 00139 ar->v2d.min[1]= 1.0f; 00140 00141 ar->v2d.max[0]= 32000.0f; 00142 ar->v2d.max[1]= 32000.0f; 00143 00144 ar->v2d.minzoom= 0.09f; 00145 ar->v2d.maxzoom= 2.31f; 00146 00147 ar->v2d.scroll= (V2D_SCROLL_RIGHT|V2D_SCROLL_BOTTOM); 00148 ar->v2d.keepzoom= V2D_LIMITZOOM|V2D_KEEPASPECT; 00149 ar->v2d.keeptot= 0; 00150 00151 return (SpaceLink *)snode; 00152 } 00153 00154 /* not spacelink itself */ 00155 static void node_free(SpaceLink *UNUSED(sl)) 00156 { 00157 00158 } 00159 00160 00161 /* spacetype; init callback */ 00162 static void node_init(struct wmWindowManager *UNUSED(wm), ScrArea *UNUSED(sa)) 00163 { 00164 00165 } 00166 00167 static void node_area_listener(ScrArea *sa, wmNotifier *wmn) 00168 { 00169 /* note, ED_area_tag_refresh will re-execute compositor */ 00170 SpaceNode *snode= sa->spacedata.first; 00171 int type= snode->treetype; 00172 00173 /* preview renders */ 00174 switch(wmn->category) { 00175 case NC_SCENE: 00176 switch (wmn->data) { 00177 case ND_NODES: 00178 case ND_FRAME: 00179 ED_area_tag_refresh(sa); 00180 break; 00181 case ND_COMPO_RESULT: 00182 ED_area_tag_redraw(sa); 00183 break; 00184 case ND_TRANSFORM_DONE: 00185 if(type==NTREE_COMPOSIT) { 00186 if(snode->flag & SNODE_AUTO_RENDER) { 00187 snode->recalc= 1; 00188 ED_area_tag_refresh(sa); 00189 } 00190 } 00191 break; 00192 } 00193 break; 00194 case NC_WM: 00195 if(wmn->data==ND_FILEREAD) 00196 ED_area_tag_refresh(sa); 00197 break; 00198 00199 /* future: add ID checks? */ 00200 case NC_MATERIAL: 00201 if(type==NTREE_SHADER) { 00202 if(wmn->data==ND_SHADING) 00203 ED_area_tag_refresh(sa); 00204 else if(wmn->data==ND_SHADING_DRAW) 00205 ED_area_tag_refresh(sa); 00206 else if(wmn->action==NA_ADDED && snode->edittree) 00207 nodeSetActiveID(snode->edittree, ID_MA, wmn->reference); 00208 00209 } 00210 break; 00211 case NC_TEXTURE: 00212 if(type==NTREE_SHADER || type==NTREE_TEXTURE) { 00213 if(wmn->data==ND_NODES) 00214 ED_area_tag_refresh(sa); 00215 } 00216 break; 00217 case NC_OBJECT: 00218 if(type==NTREE_SHADER) { 00219 if(wmn->data==ND_OB_SHADING) 00220 ED_area_tag_refresh(sa); 00221 } 00222 break; 00223 case NC_TEXT: 00224 /* pynodes */ 00225 if(wmn->data==ND_SHADING) 00226 ED_area_tag_refresh(sa); 00227 break; 00228 case NC_SPACE: 00229 if(wmn->data==ND_SPACE_NODE) 00230 ED_area_tag_refresh(sa); 00231 else if(wmn->data==ND_SPACE_NODE_VIEW) 00232 ED_area_tag_redraw(sa); 00233 break; 00234 case NC_NODE: 00235 if (wmn->action == NA_EDITED) 00236 ED_area_tag_refresh(sa); 00237 else if (wmn->action == NA_SELECTED) 00238 ED_area_tag_redraw(sa); 00239 break; 00240 case NC_SCREEN: 00241 switch(wmn->data) { 00242 case ND_ANIMPLAY: 00243 ED_area_tag_refresh(sa); 00244 break; 00245 } 00246 break; 00247 00248 case NC_IMAGE: 00249 if (wmn->action == NA_EDITED) { 00250 if(type==NTREE_COMPOSIT) { 00251 /* note that nodeUpdateID is already called by BKE_image_signal() on all 00252 * scenes so really this is just to know if the images is used in the compo else 00253 * painting on images could become very slow when the compositor is open. */ 00254 if(nodeUpdateID(snode->nodetree, wmn->reference)) 00255 ED_area_tag_refresh(sa); 00256 } 00257 } 00258 break; 00259 } 00260 } 00261 00262 static void node_area_refresh(const struct bContext *C, struct ScrArea *sa) 00263 { 00264 /* default now: refresh node is starting preview */ 00265 SpaceNode *snode= sa->spacedata.first; 00266 00267 snode_set_context(snode, CTX_data_scene(C)); 00268 00269 if(snode->nodetree) { 00270 if(snode->treetype==NTREE_SHADER) { 00271 if(GS(snode->id->name) == ID_MA) { 00272 Material *ma= (Material *)snode->id; 00273 if(ma->use_nodes) 00274 ED_preview_shader_job(C, sa, snode->id, NULL, NULL, 100, 100, PR_NODE_RENDER); 00275 } 00276 else if(GS(snode->id->name) == ID_LA) { 00277 Lamp *la= (Lamp *)snode->id; 00278 if(la->use_nodes) 00279 ED_preview_shader_job(C, sa, snode->id, NULL, NULL, 100, 100, PR_NODE_RENDER); 00280 } 00281 else if(GS(snode->id->name) == ID_WO) { 00282 World *wo= (World *)snode->id; 00283 if(wo->use_nodes) 00284 ED_preview_shader_job(C, sa, snode->id, NULL, NULL, 100, 100, PR_NODE_RENDER); 00285 } 00286 } 00287 else if(snode->treetype==NTREE_COMPOSIT) { 00288 Scene *scene= (Scene *)snode->id; 00289 if(scene->use_nodes) { 00290 /* recalc is set on 3d view changes for auto compo */ 00291 if(snode->recalc) { 00292 snode->recalc= 0; 00293 node_render_changed_exec((struct bContext*)C, NULL); 00294 } 00295 else 00296 snode_composite_job(C, sa); 00297 } 00298 } 00299 else if(snode->treetype==NTREE_TEXTURE) { 00300 Tex *tex= (Tex *)snode->id; 00301 if(tex->use_nodes) { 00302 ED_preview_shader_job(C, sa, snode->id, NULL, NULL, 100, 100, PR_NODE_RENDER); 00303 } 00304 } 00305 } 00306 } 00307 00308 static SpaceLink *node_duplicate(SpaceLink *sl) 00309 { 00310 SpaceNode *snoden= MEM_dupallocN(sl); 00311 00312 /* clear or remove stuff from old */ 00313 snoden->nodetree= NULL; 00314 snoden->linkdrag.first= snoden->linkdrag.last= NULL; 00315 00316 return (SpaceLink *)snoden; 00317 } 00318 00319 00320 /* add handlers, stuff you only do once or on area/region changes */ 00321 static void node_buttons_area_init(wmWindowManager *wm, ARegion *ar) 00322 { 00323 wmKeyMap *keymap; 00324 00325 ED_region_panels_init(wm, ar); 00326 00327 keymap= WM_keymap_find(wm->defaultconf, "Node Generic", SPACE_NODE, 0); 00328 WM_event_add_keymap_handler(&ar->handlers, keymap); 00329 } 00330 00331 static void node_buttons_area_draw(const bContext *C, ARegion *ar) 00332 { 00333 ED_region_panels(C, ar, 1, NULL, -1); 00334 } 00335 00336 /* Initialise main area, setting handlers. */ 00337 static void node_main_area_init(wmWindowManager *wm, ARegion *ar) 00338 { 00339 wmKeyMap *keymap; 00340 ListBase *lb; 00341 00342 UI_view2d_region_reinit(&ar->v2d, V2D_COMMONVIEW_CUSTOM, ar->winx, ar->winy); 00343 00344 /* own keymaps */ 00345 keymap= WM_keymap_find(wm->defaultconf, "Node Generic", SPACE_NODE, 0); 00346 WM_event_add_keymap_handler(&ar->handlers, keymap); 00347 00348 keymap= WM_keymap_find(wm->defaultconf, "Node Editor", SPACE_NODE, 0); 00349 WM_event_add_keymap_handler_bb(&ar->handlers, keymap, &ar->v2d.mask, &ar->winrct); 00350 00351 /* add drop boxes */ 00352 lb = WM_dropboxmap_find("Node Editor", SPACE_NODE, RGN_TYPE_WINDOW); 00353 00354 WM_event_add_dropbox_handler(&ar->handlers, lb); 00355 } 00356 00357 static void node_main_area_draw(const bContext *C, ARegion *ar) 00358 { 00359 View2D *v2d= &ar->v2d; 00360 00361 drawnodespace(C, ar, v2d); 00362 } 00363 00364 00365 /* ************* dropboxes ************* */ 00366 00367 static int node_drop_poll(bContext *UNUSED(C), wmDrag *drag, wmEvent *UNUSED(event)) 00368 { 00369 if(drag->type==WM_DRAG_ID) { 00370 ID *id= (ID *)drag->poin; 00371 if( GS(id->name)==ID_IM ) 00372 return 1; 00373 } 00374 else if(drag->type==WM_DRAG_PATH){ 00375 if(ELEM(drag->icon, 0, ICON_FILE_IMAGE)) /* rule might not work? */ 00376 return 1; 00377 } 00378 return 0; 00379 } 00380 00381 static void node_id_path_drop_copy(wmDrag *drag, wmDropBox *drop) 00382 { 00383 ID *id= (ID *)drag->poin; 00384 00385 if(id) { 00386 RNA_string_set(drop->ptr, "name", id->name+2); 00387 } 00388 if (drag->path[0]) { 00389 RNA_string_set(drop->ptr, "filepath", drag->path); 00390 } 00391 } 00392 00393 /* this region dropbox definition */ 00394 static void node_dropboxes(void) 00395 { 00396 ListBase *lb= WM_dropboxmap_find("Node Editor", SPACE_NODE, RGN_TYPE_WINDOW); 00397 00398 WM_dropbox_add(lb, "NODE_OT_add_file", node_drop_poll, node_id_path_drop_copy); 00399 00400 } 00401 00402 /* ************* end drop *********** */ 00403 00404 00405 /* add handlers, stuff you only do once or on area/region changes */ 00406 static void node_header_area_init(wmWindowManager *UNUSED(wm), ARegion *ar) 00407 { 00408 ED_region_header_init(ar); 00409 } 00410 00411 static void node_header_area_draw(const bContext *C, ARegion *ar) 00412 { 00413 SpaceNode *snode= CTX_wm_space_node(C); 00414 Scene *scene= CTX_data_scene(C); 00415 00416 /* find and set the context */ 00417 snode_set_context(snode, scene); 00418 00419 ED_region_header(C, ar); 00420 } 00421 00422 /* used for header + main area */ 00423 static void node_region_listener(ARegion *ar, wmNotifier *wmn) 00424 { 00425 /* context changes */ 00426 switch(wmn->category) { 00427 case NC_SPACE: 00428 if(wmn->data==ND_SPACE_NODE) 00429 ED_region_tag_redraw(ar); 00430 break; 00431 case NC_SCREEN: 00432 if(wmn->data == ND_GPENCIL) 00433 ED_region_tag_redraw(ar); 00434 break; 00435 case NC_SCENE: 00436 case NC_MATERIAL: 00437 case NC_TEXTURE: 00438 case NC_NODE: 00439 ED_region_tag_redraw(ar); 00440 break; 00441 case NC_OBJECT: 00442 if(wmn->data==ND_OB_SHADING) 00443 ED_region_tag_redraw(ar); 00444 break; 00445 case NC_ID: 00446 if(wmn->action == NA_RENAME) 00447 ED_region_tag_redraw(ar); 00448 break; 00449 } 00450 } 00451 00452 const char *node_context_dir[] = {"selected_nodes", NULL}; 00453 00454 static int node_context(const bContext *C, const char *member, bContextDataResult *result) 00455 { 00456 SpaceNode *snode= CTX_wm_space_node(C); 00457 00458 if(CTX_data_dir(member)) { 00459 CTX_data_dir_set(result, node_context_dir); 00460 return 1; 00461 } 00462 else if(CTX_data_equals(member, "selected_nodes")) { 00463 bNode *node; 00464 00465 if(snode->edittree) { 00466 for(node=snode->edittree->nodes.last; node; node=node->prev) { 00467 if(node->flag & NODE_SELECT) { 00468 CTX_data_list_add(result, &snode->edittree->id, &RNA_Node, node); 00469 } 00470 } 00471 } 00472 CTX_data_type_set(result, CTX_DATA_TYPE_COLLECTION); 00473 return 1; 00474 } 00475 else if(CTX_data_equals(member, "active_node")) { 00476 bNode *node; 00477 00478 if(snode->edittree) { 00479 for(node=snode->edittree->nodes.last; node; node=node->prev) { 00480 if(node->flag & NODE_ACTIVE) { 00481 CTX_data_pointer_set(result, &snode->edittree->id, &RNA_Node, node); 00482 break; 00483 } 00484 } 00485 } 00486 CTX_data_type_set(result, CTX_DATA_TYPE_POINTER); 00487 return 1; 00488 } 00489 00490 return 0; 00491 } 00492 00493 /* only called once, from space/spacetypes.c */ 00494 void ED_spacetype_node(void) 00495 { 00496 SpaceType *st= MEM_callocN(sizeof(SpaceType), "spacetype node"); 00497 ARegionType *art; 00498 00499 st->spaceid= SPACE_NODE; 00500 strncpy(st->name, "Node", BKE_ST_MAXNAME); 00501 00502 st->new= node_new; 00503 st->free= node_free; 00504 st->init= node_init; 00505 st->duplicate= node_duplicate; 00506 st->operatortypes= node_operatortypes; 00507 st->keymap= node_keymap; 00508 st->listener= node_area_listener; 00509 st->refresh= node_area_refresh; 00510 st->context= node_context; 00511 st->dropboxes = node_dropboxes; 00512 00513 /* regions: main window */ 00514 art= MEM_callocN(sizeof(ARegionType), "spacetype node region"); 00515 art->regionid = RGN_TYPE_WINDOW; 00516 art->init= node_main_area_init; 00517 art->draw= node_main_area_draw; 00518 art->listener= node_region_listener; 00519 art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D|ED_KEYMAP_FRAMES|ED_KEYMAP_GPENCIL; 00520 00521 BLI_addhead(&st->regiontypes, art); 00522 00523 /* regions: header */ 00524 art= MEM_callocN(sizeof(ARegionType), "spacetype node region"); 00525 art->regionid = RGN_TYPE_HEADER; 00526 art->prefsizey= HEADERY; 00527 art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_VIEW2D|ED_KEYMAP_FRAMES|ED_KEYMAP_HEADER; 00528 art->listener= node_region_listener; 00529 art->init= node_header_area_init; 00530 art->draw= node_header_area_draw; 00531 00532 BLI_addhead(&st->regiontypes, art); 00533 00534 node_menus_register(); 00535 00536 /* regions: listview/buttons */ 00537 art= MEM_callocN(sizeof(ARegionType), "spacetype node region"); 00538 art->regionid = RGN_TYPE_UI; 00539 art->prefsizex= 180; // XXX 00540 art->keymapflag= ED_KEYMAP_UI|ED_KEYMAP_FRAMES; 00541 art->listener= node_region_listener; 00542 art->init= node_buttons_area_init; 00543 art->draw= node_buttons_area_draw; 00544 BLI_addhead(&st->regiontypes, art); 00545 00546 node_buttons_register(art); 00547 00548 BKE_spacetype_register(st); 00549 } 00550