void ED_preview_free_dbase(void) { if (G_pr_main) BKE_main_free(G_pr_main); if (G_pr_main_cycles) BKE_main_free(G_pr_main_cycles); }
void ED_preview_free_dbase(void) { if (G_pr_main) { BKE_main_free(G_pr_main); } if (G_pr_main_grease_pencil) { BKE_main_free(G_pr_main_grease_pencil); } }
int BKE_read_file(bContext *C, const char *filepath, ReportList *reports) { BlendFileData *bfd; int retval = BKE_READ_FILE_OK; if (strstr(filepath, BLENDER_STARTUP_FILE) == NULL) /* don't print user-pref loading */ printf("read blend: %s\n", filepath); bfd = BLO_read_from_file(filepath, reports); if (bfd) { if (bfd->user) retval = BKE_READ_FILE_OK_USERPREFS; if (0 == handle_subversion_warning(bfd->main, reports)) { BKE_main_free(bfd->main); MEM_freeN(bfd); bfd = NULL; retval = BKE_READ_FILE_FAIL; } else setup_app_data(C, bfd, filepath); // frees BFD } else BKE_reports_prependf(reports, "Loading '%s' failed: ", filepath); return (bfd ? retval : BKE_READ_FILE_FAIL); }
int BKE_blendfile_read( bContext *C, const char *filepath, const struct BlendFileReadParams *params, ReportList *reports) { BlendFileData *bfd; int retval = BKE_BLENDFILE_READ_OK; /* don't print user-pref loading */ if (strstr(filepath, BLENDER_STARTUP_FILE) == NULL) { printf("Read blend: %s\n", filepath); } bfd = BLO_read_from_file(filepath, params->skip_flags, reports); if (bfd) { if (bfd->user) { retval = BKE_BLENDFILE_READ_OK_USERPREFS; } if (0 == handle_subversion_warning(bfd->main, reports)) { BKE_main_free(bfd->main); MEM_freeN(bfd); bfd = NULL; retval = BKE_BLENDFILE_READ_FAIL; } else { setup_app_data(C, bfd, filepath, params->is_startup, reports); } } else BKE_reports_prependf(reports, "Loading '%s' failed: ", filepath); return (bfd ? retval : BKE_BLENDFILE_READ_FAIL); }
/* only to be called on exit blender */ void BKE_blender_free(void) { /* samples are in a global list..., also sets G_MAIN->sound->sample NULL */ /* Needs to run before main free as wm is still referenced for icons preview jobs. */ BKE_studiolight_free(); BKE_main_free(G_MAIN); G_MAIN = NULL; if (G.log.file != NULL) { fclose(G.log.file); } BKE_spacetypes_free(); /* after free main, it uses space callbacks */ IMB_exit(); BKE_cachefiles_exit(); BKE_images_exit(); DEG_free_node_types(); BKE_brush_system_exit(); RE_texture_rng_exit(); BLI_callback_global_finalize(); IMB_moviecache_destruct(); free_nodesystem(); }
static void clear_global(void) { // extern short winqueue_break; /* screen.c */ BKE_main_free(G.main); /* free all lib data */ // free_vertexpaint(); G.main = NULL; }
/* only read the userdef from a .blend */ UserDef *BKE_blendfile_userdef_read(const char *filepath, ReportList *reports) { BlendFileData *bfd; UserDef *userdef = NULL; bfd = BLO_read_from_file(filepath, BLO_READ_SKIP_ALL & ~BLO_READ_SKIP_USERDEF, reports); if (bfd) { if (bfd->user) { userdef = bfd->user; } BKE_main_free(bfd->main); MEM_freeN(bfd); } return userdef; }
/* only read the userdef from a .blend */ int BKE_read_file_userdef(const char *filepath, ReportList *reports) { BlendFileData *bfd; int retval = 0; bfd = BLO_read_from_file(filepath, reports); if (bfd->user) { retval = BKE_READ_FILE_OK_USERPREFS; /* only here free userdef themes... */ BKE_userdef_free(); U = *bfd->user; MEM_freeN(bfd->user); } BKE_main_free(bfd->main); MEM_freeN(bfd); return retval; }
UserDef *BKE_blendfile_userdef_read_from_memory( const void *filebuf, int filelength, ReportList *reports) { BlendFileData *bfd; UserDef *userdef = NULL; bfd = BLO_read_from_memory(filebuf, filelength, reports, BLO_READ_SKIP_ALL & ~BLO_READ_SKIP_USERDEF); if (bfd) { if (bfd->user) { userdef = bfd->user; } BKE_main_free(bfd->main); MEM_freeN(bfd); } else { BKE_reports_prepend(reports, "Loading failed: "); } return userdef; }
/* only to be called on exit blender */ void free_blender(void) { /* samples are in a global list..., also sets G.main->sound->sample NULL */ BKE_main_free(G.main); G.main = NULL; BKE_spacetypes_free(); /* after free main, it uses space callbacks */ IMB_exit(); BKE_images_exit(); DAG_exit(); BKE_brush_system_exit(); BLI_callback_global_finalize(); BKE_sequencer_cache_destruct(); IMB_moviecache_destruct(); free_nodesystem(); }
int main(int argc, char** argv) { int i; int argc_py_clamped= argc; /* use this so python args can be added after ' - ' */ bool error = false; SYS_SystemHandle syshandle = SYS_GetSystem(); bool fullScreen = false; bool fullScreenParFound = false; bool windowParFound = false; #ifdef WIN32 bool closeConsole = true; #endif RAS_IRasterizer::StereoMode stereomode = RAS_IRasterizer::RAS_STEREO_NOSTEREO; bool stereoWindow = false; bool stereoParFound = false; int stereoFlag = STEREO_NOSTEREO; int domeFov = -1; int domeTilt = -200; int domeMode = 0; char* domeWarp = NULL; Text *domeText = NULL; int windowLeft = 100; int windowTop = 100; int windowWidth = 640; int windowHeight = 480; GHOST_TUns32 fullScreenWidth = 0; GHOST_TUns32 fullScreenHeight= 0; int fullScreenBpp = 32; int fullScreenFrequency = 60; GHOST_TEmbedderWindowID parentWindow = 0; bool isBlenderPlayer = false; //true when lauching from blender or command line. false for bundled player int validArguments=0; bool samplesParFound = false; GHOST_TUns16 aasamples = 0; #ifdef __linux__ #ifdef __alpha__ signal (SIGFPE, SIG_IGN); #endif /* __alpha__ */ #endif /* __linux__ */ #ifdef WITH_SDL_DYNLOAD sdlewInit(); #endif BKE_appdir_program_path_init(argv[0]); BKE_tempdir_init(NULL); // We don't use threads directly in the BGE, but we need to call this so things like // freeing up GPU_Textures works correctly. BLI_threadapi_init(); RNA_init(); init_nodesystem(); initglobals(); U.gameflags |= USER_DISABLE_VBO; // We load our own G.main, so free the one that initglobals() gives us BKE_main_free(G.main); G.main = NULL; MEM_CacheLimiter_set_disabled(true); IMB_init(); BKE_images_init(); BKE_modifier_init(); DAG_init(); #ifdef WITH_FFMPEG IMB_ffmpeg_init(); #endif // Setup builtin font for BLF (mostly copied from creator.c, wm_init_exit.c and interface_style.c) BLF_init(11, U.dpi); BLF_lang_init(); BLF_lang_set(""); BLF_load_mem("default", (unsigned char*)datatoc_bfont_ttf, datatoc_bfont_ttf_size); if (blf_mono_font == -1) blf_mono_font = BLF_load_mem_unique("monospace", (unsigned char*)datatoc_bmonofont_ttf, datatoc_bmonofont_ttf_size); // Parse command line options #if defined(DEBUG) printf("argv[0] = '%s'\n", argv[0]); #endif #ifdef WIN32 if (scr_saver_init(argc, argv)) { switch (scr_saver_mode) { case SCREEN_SAVER_MODE_CONFIGURATION: MessageBox(scr_saver_hwnd, "This screen saver has no options that you can set", "Screen Saver", MB_OK); break; case SCREEN_SAVER_MODE_PASSWORD: /* This is W95 only, which we currently do not support. * Fall-back to normal screen saver behavior in that case... */ case SCREEN_SAVER_MODE_SAVER: fullScreen = true; fullScreenParFound = true; break; case SCREEN_SAVER_MODE_PREVIEW: /* This will actually be handled somewhere below... */ break; } } #endif // XXX add the ability to change this values to the command line parsing. U.mixbufsize = 2048; U.audiodevice = 2; U.audiorate = 44100; U.audioformat = 0x24; U.audiochannels = 2; // XXX this one too U.anisotropic_filter = 2; // enable fast mipmap generation U.use_gpu_mipmap = 1; sound_init_once(); set_free_windowmanager_cb(wm_free); /* if running blenderplayer the last argument can't be parsed since it has to be the filename. else it is bundled */ isBlenderPlayer = !BLO_is_a_runtime(argv[0]); if (isBlenderPlayer) validArguments = argc - 1; else validArguments = argc; /* Parsing command line arguments (can be set from WM_OT_blenderplayer_start) */ #if defined(DEBUG) printf("Parsing command line arguments...\n"); printf("Num of arguments is: %i\n", validArguments-1); //-1 because i starts at 1 #endif for (i = 1; (i < validArguments) && !error #ifdef WIN32 && scr_saver_mode == SCREEN_SAVER_MODE_NONE #endif ;) { #if defined(DEBUG) printf("argv[%d] = '%s'\n", i, argv[i]); #endif if (argv[i][0] == '-') { /* ignore all args after " - ", allow python to have own args */ if (argv[i][1]=='\0') { argc_py_clamped= i; break; } switch (argv[i][1]) { case 'g': //game engine options (show_framerate, fixedtime, etc) { i++; if (i <= validArguments) { char* paramname = argv[i]; // Check for single value versus assignment if (i+1 <= validArguments && (*(argv[i+1]) == '=')) { i++; if (i + 1 <= validArguments) { i++; // Assignment SYS_WriteCommandLineInt(syshandle, paramname, atoi(argv[i])); SYS_WriteCommandLineFloat(syshandle, paramname, atof(argv[i])); SYS_WriteCommandLineString(syshandle, paramname, argv[i]); #if defined(DEBUG) printf("%s = '%s'\n", paramname, argv[i]); #endif i++; } else { error = true; printf("error: argument assignment %s without value.\n", paramname); } } else { // SYS_WriteCommandLineInt(syshandle, argv[i++], 1); } } break; } case 'd': //debug on { i++; G.debug |= G_DEBUG; MEM_set_memory_debug(); #ifdef DEBUG BLI_mempool_set_memory_debug(); #endif break; } case 'f': //fullscreen mode { i++; fullScreen = true; fullScreenParFound = true; if ((i + 2) <= validArguments && argv[i][0] != '-' && argv[i+1][0] != '-') { fullScreenWidth = atoi(argv[i++]); fullScreenHeight = atoi(argv[i++]); if ((i + 1) <= validArguments && argv[i][0] != '-') { fullScreenBpp = atoi(argv[i++]); if ((i + 1) <= validArguments && argv[i][0] != '-') fullScreenFrequency = atoi(argv[i++]); } } else if ((i + 1) <= validArguments && argv[i][0] != '-' && argv[i+1][0] != '-') { error = true; printf("error: to define fullscreen width or height, both options must be used.\n"); } break; } case 'w': //display in a window { i++; fullScreen = false; windowParFound = true; // Parse window position and size options if ((i + 2) <= validArguments && argv[i][0] != '-' && argv[i+1][0] != '-') { windowWidth = atoi(argv[i++]); windowHeight = atoi(argv[i++]); if ((i + 2) <= validArguments && argv[i][0] != '-' && argv[i+1][0] != '-') { windowLeft = atoi(argv[i++]); windowTop = atoi(argv[i++]); } else if ((i + 1) <= validArguments && argv[i][0] != '-' && argv[i+1][0] != '-') { error = true; printf("error: to define the window left or right coordinates, both options must be used.\n"); } } else if ((i + 1) <= validArguments && argv[i][0] != '-' && argv[i+1][0] != '-') { error = true; printf("error: to define the window's width or height, both options must be used.\n"); } break; } case 'h': //display help { usage(argv[0], isBlenderPlayer); return 0; break; } case 'i': //parent window ID { i++; if ( (i + 1) <= validArguments ) parentWindow = atoi(argv[i++]); else { error = true; printf("error: too few options for parent window argument.\n"); } #if defined(DEBUG) printf("XWindows ID = %d\n", parentWindow); #endif // defined(DEBUG) break; } case 'm': //maximum anti-aliasing (eg. 2,4,8,16) { i++; samplesParFound = true; if ((i+1) <= validArguments ) aasamples = atoi(argv[i++]); else { error = true; printf("error: No argument supplied for -m"); } break; } case 'c': //keep console (windows only) { i++; #ifdef WIN32 closeConsole = false; #endif break; } case 's': //stereo mode { i++; if ((i + 1) <= validArguments) { stereoParFound = true; stereoFlag = STEREO_ENABLED; if (!strcmp(argv[i], "nostereo")) // may not be redundant if the file has different setting { stereomode = RAS_IRasterizer::RAS_STEREO_NOSTEREO; stereoFlag = STEREO_NOSTEREO; } // only the hardware pageflip method needs a stereo window else if (!strcmp(argv[i], "hwpageflip")) { stereomode = RAS_IRasterizer::RAS_STEREO_QUADBUFFERED; stereoWindow = true; } else if (!strcmp(argv[i], "syncdoubling")) stereomode = RAS_IRasterizer::RAS_STEREO_ABOVEBELOW; else if (!strcmp(argv[i], "3dtvtopbottom")) stereomode = RAS_IRasterizer::RAS_STEREO_3DTVTOPBOTTOM; else if (!strcmp(argv[i], "anaglyph")) stereomode = RAS_IRasterizer::RAS_STEREO_ANAGLYPH; else if (!strcmp(argv[i], "sidebyside")) stereomode = RAS_IRasterizer::RAS_STEREO_SIDEBYSIDE; else if (!strcmp(argv[i], "interlace")) stereomode = RAS_IRasterizer::RAS_STEREO_INTERLACED; else if (!strcmp(argv[i], "vinterlace")) stereomode = RAS_IRasterizer::RAS_STEREO_VINTERLACE; #if 0 // // future stuff // else if (!strcmp(argv[i], "stencil") // stereomode = RAS_STEREO_STENCIL; #endif else { error = true; printf("error: stereomode '%s' unrecognized.\n", argv[i]); } i++; } else { error = true; printf("error: too few options for stereo argument.\n"); } break; } case 'D': //dome mode { stereoFlag = STEREO_DOME; stereomode = RAS_IRasterizer::RAS_STEREO_DOME; i++; if ((i + 1) <= validArguments) { if (!strcmp(argv[i], "angle")) { i++; domeFov = atoi(argv[i++]); } if (!strcmp(argv[i], "tilt")) { i++; domeTilt = atoi(argv[i++]); } if (!strcmp(argv[i], "warpdata")) { i++; domeWarp = argv[i++]; } if (!strcmp(argv[i], "mode")) { i++; if (!strcmp(argv[i], "fisheye")) domeMode = DOME_FISHEYE; else if (!strcmp(argv[i], "truncatedfront")) domeMode = DOME_TRUNCATED_FRONT; else if (!strcmp(argv[i], "truncatedrear")) domeMode = DOME_TRUNCATED_REAR; else if (!strcmp(argv[i], "cubemap")) domeMode = DOME_ENVMAP; else if (!strcmp(argv[i], "sphericalpanoramic")) domeMode = DOME_PANORAM_SPH; else printf("error: %s is not a valid dome mode.\n", argv[i]); } i++; } break; } default: //not recognized { printf("Unknown argument: %s\n", argv[i++]); break; } } } else { i++; } } if ((windowWidth < kMinWindowWidth) || (windowHeight < kMinWindowHeight)) { error = true; printf("error: window size too small.\n"); } if (error ) { usage(argv[0], isBlenderPlayer); return 0; } #ifdef WIN32 if (scr_saver_mode != SCREEN_SAVER_MODE_CONFIGURATION) #endif { // Create the system if (GHOST_ISystem::createSystem() == GHOST_kSuccess) { GHOST_ISystem* system = GHOST_ISystem::getSystem(); assertd(system); if (!fullScreenWidth || !fullScreenHeight) system->getMainDisplayDimensions(fullScreenWidth, fullScreenHeight); // process first batch of events. If the user // drops a file on top off the blenderplayer icon, we // receive an event with the filename system->processEvents(0); // this bracket is needed for app (see below) to get out // of scope before GHOST_ISystem::disposeSystem() is called. { int exitcode = KX_EXIT_REQUEST_NO_REQUEST; STR_String exitstring = ""; GPG_Application app(system); bool firstTimeRunning = true; char filename[FILE_MAX]; char pathname[FILE_MAX]; char *titlename; get_filename(argc_py_clamped, argv, filename); if (filename[0]) BLI_path_cwd(filename); // fill the GlobalSettings with the first scene files // those may change during the game and persist after using Game Actuator GlobalSettings gs; do { // Read the Blender file BlendFileData *bfd; // if we got an exitcode 3 (KX_EXIT_REQUEST_START_OTHER_GAME) load a different file if (exitcode == KX_EXIT_REQUEST_START_OTHER_GAME) { char basedpath[FILE_MAX]; // base the actuator filename relative to the last file BLI_strncpy(basedpath, exitstring.Ptr(), sizeof(basedpath)); BLI_path_abs(basedpath, pathname); bfd = load_game_data(basedpath); if (!bfd) { // just add "//" in front of it char temppath[FILE_MAX] = "//"; BLI_strncpy(temppath + 2, basedpath, FILE_MAX - 2); BLI_path_abs(temppath, pathname); bfd = load_game_data(temppath); } } else { bfd = load_game_data(BKE_appdir_program_path(), filename[0]? filename: NULL); } #if defined(DEBUG) printf("Game data loaded from %s\n", filename); #endif if (!bfd) { usage(argv[0], isBlenderPlayer); error = true; exitcode = KX_EXIT_REQUEST_QUIT_GAME; } else { /* Setting options according to the blend file if not overriden in the command line */ #ifdef WIN32 #if !defined(DEBUG) if (closeConsole) { system->toggleConsole(0); // Close a console window } #endif // !defined(DEBUG) #endif // WIN32 Main *maggie = bfd->main; Scene *scene = bfd->curscene; G.main = maggie; if (firstTimeRunning) { G.fileflags = bfd->fileflags; gs.matmode= scene->gm.matmode; gs.glslflag= scene->gm.flag; } //Seg Fault; icon.c gIcons == 0 BKE_icons_init(1); titlename = maggie->name; // Check whether the game should be displayed full-screen if ((!fullScreenParFound) && (!windowParFound)) { // Only use file settings when command line did not override if ((scene->gm.playerflag & GAME_PLAYER_FULLSCREEN)) { //printf("fullscreen option found in Blender file\n"); fullScreen = true; fullScreenWidth= scene->gm.xplay; fullScreenHeight= scene->gm.yplay; fullScreenFrequency= scene->gm.freqplay; fullScreenBpp = scene->gm.depth; } else { fullScreen = false; windowWidth = scene->gm.xplay; windowHeight = scene->gm.yplay; } } // Check whether the game should be displayed in stereo (dome included) if (!stereoParFound) { // Only use file settings when command line did not override if (scene->gm.stereoflag == STEREO_ENABLED) { stereomode = (RAS_IRasterizer::StereoMode) scene->gm.stereomode; if (stereomode == RAS_IRasterizer::RAS_STEREO_QUADBUFFERED) stereoWindow = true; } } else { scene->gm.stereoflag = STEREO_ENABLED; } if (!samplesParFound) aasamples = scene->gm.aasamples; // Dome specific settings if (stereoFlag == STEREO_DOME) { stereomode = RAS_IRasterizer::RAS_STEREO_DOME; scene->gm.stereoflag = STEREO_DOME; if (domeFov > 89) scene->gm.dome.angle = domeFov; if (domeTilt > -180) scene->gm.dome.tilt = domeTilt; if (domeMode > 0) scene->gm.dome.mode = domeMode; if (domeWarp) { //XXX to do: convert relative to absolute path domeText= BKE_text_load(G.main, domeWarp, ""); if (!domeText) printf("error: invalid warpdata text file - %s\n", domeWarp); else scene->gm.dome.warptext = domeText; } } // GPG_Application app (system, maggie, startscenename); app.SetGameEngineData(maggie, scene, &gs, argc, argv); /* this argc cant be argc_py_clamped, since python uses it */ BLI_strncpy(pathname, maggie->name, sizeof(pathname)); if (G.main != maggie) { BLI_strncpy(G.main->name, maggie->name, sizeof(G.main->name)); } #ifdef WITH_PYTHON setGamePythonPath(G.main->name); #endif if (firstTimeRunning) { firstTimeRunning = false; if (fullScreen) { #ifdef WIN32 if (scr_saver_mode == SCREEN_SAVER_MODE_SAVER) { app.startScreenSaverFullScreen(fullScreenWidth, fullScreenHeight, fullScreenBpp, fullScreenFrequency, stereoWindow, stereomode, aasamples); } else #endif { app.startFullScreen(fullScreenWidth, fullScreenHeight, fullScreenBpp, fullScreenFrequency, stereoWindow, stereomode, aasamples, (scene->gm.playerflag & GAME_PLAYER_DESKTOP_RESOLUTION)); } } else { #ifdef __APPLE__ // on Mac's we'll show the executable name instead of the 'game.blend' name char tempname[1024], *appstring; ::strcpy(tempname, titlename); appstring = strstr(tempname, ".app/"); if (appstring) { appstring[2] = 0; titlename = &tempname[0]; } #endif // Strip the path so that we have the name of the game file STR_String path = titlename; #ifndef WIN32 vector<STR_String> parts = path.Explode('/'); #else // WIN32 vector<STR_String> parts = path.Explode('\\'); #endif // WIN32 STR_String title; if (parts.size()) { title = parts[parts.size()-1]; parts = title.Explode('.'); if (parts.size() > 1) { title = parts[0]; } } else { title = "blenderplayer"; } #ifdef WIN32 if (scr_saver_mode == SCREEN_SAVER_MODE_PREVIEW) { app.startScreenSaverPreview(scr_saver_hwnd, stereoWindow, stereomode, aasamples); } else #endif { if (parentWindow != 0) app.startEmbeddedWindow(title, parentWindow, stereoWindow, stereomode, aasamples); else app.startWindow(title, windowLeft, windowTop, windowWidth, windowHeight, stereoWindow, stereomode, aasamples); if (SYS_GetCommandLineInt(syshandle, "nomipmap", 0)) { GPU_set_mipmap(0); } GPU_set_anisotropic(U.anisotropic_filter); GPU_set_gpu_mipmapping(U.use_gpu_mipmap); } } } else { app.StartGameEngine(stereomode); exitcode = KX_EXIT_REQUEST_NO_REQUEST; } // Add the application as event consumer system->addEventConsumer(&app); // Enter main loop bool run = true; char *python_main = NULL; pynextframestate.state = NULL; pynextframestate.func = NULL; #ifdef WITH_PYTHON python_main = KX_GetPythonMain(scene); #endif // WITH_PYTHON if (python_main) { char *python_code = KX_GetPythonCode(maggie, python_main); if (python_code) { #ifdef WITH_PYTHON gpg_nextframestate.system = system; gpg_nextframestate.app = &app; gpg_nextframestate.gs = &gs; pynextframestate.state = &gpg_nextframestate; pynextframestate.func = &GPG_PyNextFrame; printf("Yielding control to Python script '%s'...\n", python_main); PyRun_SimpleString(python_code); printf("Exit Python script '%s'\n", python_main); #endif // WITH_PYTHON MEM_freeN(python_code); } else { fprintf(stderr, "ERROR: cannot yield control to Python: no Python text data block named '%s'\n", python_main); } } else { while (run) { run = GPG_NextFrame(system, &app, exitcode, exitstring, &gs); } } app.StopGameEngine(); /* 'app' is freed automatic when out of scope. * removal is needed else the system will free an already freed value */ system->removeEventConsumer(&app); BLO_blendfiledata_free(bfd); /* G.main == bfd->main, it gets referenced in free_nodesystem so we can't have a dangling pointer */ G.main = NULL; if (python_main) MEM_freeN(python_main); } } while (exitcode == KX_EXIT_REQUEST_RESTART_GAME || exitcode == KX_EXIT_REQUEST_START_OTHER_GAME); } // Seg Fault; icon.c gIcons == 0 BKE_icons_free(); // Dispose the system GHOST_ISystem::disposeSystem(); } else { error = true; printf("error: couldn't create a system.\n"); } } /* refer to WM_exit_ext() and free_blender(), * these are not called in the player but we need to match some of there behavior here, * if the order of function calls or blenders state isn't matching that of blender proper, * we may get troubles later on */ free_nodesystem(); // Cleanup RNA_exit(); BLF_exit(); #ifdef WITH_INTERNATIONAL BLF_free_unifont(); BLF_free_unifont_mono(); BLF_lang_free(); #endif IMB_exit(); BKE_images_exit(); DAG_exit(); IMB_moviecache_destruct(); SYS_DeleteSystem(syshandle); int totblock= MEM_get_memory_blocks_in_use(); if (totblock!=0) { printf("Error Totblock: %d\n",totblock); MEM_set_error_callback(mem_error_cb); MEM_printmemlist(); } BKE_tempdir_session_purge(); return error ? -1 : 0; }
void BKE_blender_globals_clear(void) { BKE_main_free(G_MAIN); /* free all lib data */ G_MAIN = NULL; }
static void render_endjob(void *rjv) { RenderJob *rj = rjv; /* this render may be used again by the sequencer without the active 'Render' where the callbacks * would be re-assigned. assign dummy callbacks to avoid referencing freed renderjobs bug [#24508] */ RE_InitRenderCB(rj->re); if (rj->main != G.main) BKE_main_free(rj->main); /* else the frame will not update for the original value */ if (rj->anim && !(rj->scene->r.scemode & R_NO_FRAME_UPDATE)) { /* possible this fails of loading new file while rendering */ if (G.main->wm.first) { ED_update_for_newframe(G.main, rj->scene, 1); } } /* XXX above function sets all tags in nodes */ ntreeCompositClearTags(rj->scene->nodetree); /* potentially set by caller */ rj->scene->r.scemode &= ~R_NO_FRAME_UPDATE; if (rj->srl) { nodeUpdateID(rj->scene->nodetree, &rj->scene->id); WM_main_add_notifier(NC_NODE | NA_EDITED, rj->scene); } if (rj->sa) { render_image_restore_layer(rj); } /* XXX render stability hack */ G.is_rendering = false; WM_main_add_notifier(NC_SCENE | ND_RENDER_RESULT, NULL); /* Partial render result will always update display buffer * for first render layer only. This is nice because you'll * see render progress during rendering, but it ends up in * wrong display buffer shown after rendering. * * The code below will mark display buffer as invalid after * rendering in case multiple layers were rendered, which * ensures display buffer matches render layer after * rendering. * * Perhaps proper way would be to toggle active render * layer in image editor and job, so we always display * layer being currently rendered. But this is not so much * trivial at this moment, especially because of external * engine API, so lets use simple and robust way for now * - sergey - */ if (rj->scene->r.layers.first != rj->scene->r.layers.last || rj->image_outdated) { void *lock; Image *ima = rj->image; ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &rj->iuser, &lock); if (ibuf) ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID; BKE_image_release_ibuf(ima, ibuf, lock); } /* Finally unlock the user interface (if it was locked). */ if (rj->interface_locked) { Scene *scene; /* Interface was locked, so window manager couldn't have been changed * and using one from Global will unlock exactly the same manager as * was locked before running the job. */ WM_set_locked_interface(G.main->wm.first, false); /* We've freed all the derived caches before rendering, which is * effectively the same as if we re-loaded the file. * * So let's not try being smart here and just reset all updated * scene layers and use generic DAG_on_visible_update. */ for (scene = G.main->scene.first; scene; scene = scene->id.next) { scene->lay_updated = 0; } DAG_on_visible_update(G.main, false); } }
/* Note m_map_*** are all ok and don't need to be freed * most are temp and NewRemoveObject frees m_map_gameobject_to_blender */ bool KX_BlenderSceneConverter::FreeBlendFile(Main *maggie) { int maggie_index = -1; int i = 0; if (maggie == NULL) return false; // If the given library is currently in loading, we do nothing. if (m_status_map.count(maggie->name)) { BLI_mutex_lock(&m_threadinfo->m_mutex); const bool finished = m_status_map[maggie->name]->IsFinished(); BLI_mutex_unlock(&m_threadinfo->m_mutex); if (!finished) { printf("Library (%s) is currently being loaded asynchronously, and cannot be freed until this process is done\n", maggie->name); return false; } } /* tag all false except the one we remove */ for (vector<Main *>::iterator it = m_DynamicMaggie.begin(); !(it == m_DynamicMaggie.end()); it++) { Main *main = *it; if (main != maggie) { BKE_main_id_tag_all(main, LIB_TAG_DOIT, false); } else { maggie_index = i; } i++; } /* should never happen but just to be safe */ if (maggie_index == -1) return false; m_DynamicMaggie.erase(m_DynamicMaggie.begin() + maggie_index); BKE_main_id_tag_all(maggie, LIB_TAG_DOIT, true); /* free all tagged objects */ KX_SceneList *scenes = m_ketsjiEngine->CurrentScenes(); int numScenes = scenes->size(); for (int scene_idx = 0; scene_idx < numScenes; scene_idx++) { KX_Scene *scene = scenes->at(scene_idx); if (IS_TAGGED(scene->GetBlenderScene())) { m_ketsjiEngine->RemoveScene(scene->GetName()); m_mat_cache.erase(scene); m_polymat_cache.erase(scene); scene_idx--; numScenes--; } else { /* in case the mesh might be refered to later */ { CTR_Map<STR_HashedString, void *> &mapStringToMeshes = scene->GetLogicManager()->GetMeshMap(); for (int i = 0; i < mapStringToMeshes.size(); i++) { RAS_MeshObject *meshobj = (RAS_MeshObject *) *mapStringToMeshes.at(i); if (meshobj && IS_TAGGED(meshobj->GetMesh())) { STR_HashedString mn = meshobj->GetName(); mapStringToMeshes.remove(mn); m_map_mesh_to_gamemesh.remove(CHashedPtr(meshobj->GetMesh())); i--; } } } /* Now unregister actions */ { CTR_Map<STR_HashedString, void *> &mapStringToActions = scene->GetLogicManager()->GetActionMap(); for (int i = 0; i < mapStringToActions.size(); i++) { ID *action = (ID*) *mapStringToActions.at(i); if (IS_TAGGED(action)) { STR_HashedString an = action->name + 2; mapStringToActions.remove(an); m_map_blender_to_gameAdtList.remove(CHashedPtr(action)); i--; } } } //scene->FreeTagged(); /* removed tagged objects and meshes*/ CListValue *obj_lists[] = {scene->GetObjectList(), scene->GetInactiveList(), NULL}; for (int ob_ls_idx = 0; obj_lists[ob_ls_idx]; ob_ls_idx++) { CListValue *obs = obj_lists[ob_ls_idx]; RAS_MeshObject *mesh; for (int ob_idx = 0; ob_idx < obs->GetCount(); ob_idx++) { KX_GameObject *gameobj = (KX_GameObject*)obs->GetValue(ob_idx); if (IS_TAGGED(gameobj->GetBlenderObject())) { int size_before = obs->GetCount(); /* Eventually calls RemoveNodeDestructObject * frees m_map_gameobject_to_blender from UnregisterGameObject */ scene->RemoveObject(gameobj); if (size_before != obs->GetCount()) ob_idx--; else { printf("ERROR COULD NOT REMOVE \"%s\"\n", gameobj->GetName().ReadPtr()); } } else { gameobj->RemoveTaggedActions(); /* free the mesh, we could be referecing a linked one! */ int mesh_index = gameobj->GetMeshCount(); while (mesh_index--) { mesh = gameobj->GetMesh(mesh_index); if (IS_TAGGED(mesh->GetMesh())) { gameobj->RemoveMeshes(); /* XXX - slack, should only remove meshes that are library items but mostly objects only have 1 mesh */ break; } else { /* also free the mesh if it's using a tagged material */ int mat_index = mesh->NumMaterials(); while (mat_index--) { if (IS_TAGGED(mesh->GetMeshMaterial(mat_index)->m_bucket->GetPolyMaterial()->GetBlenderMaterial())) { gameobj->RemoveMeshes(); /* XXX - slack, same as above */ break; } } } } /* make sure action actuators are not referencing tagged actions */ for (unsigned int act_idx = 0; act_idx < gameobj->GetActuators().size(); act_idx++) { if (gameobj->GetActuators()[act_idx]->IsType(SCA_IActuator::KX_ACT_ACTION)) { BL_ActionActuator *act = (BL_ActionActuator *)gameobj->GetActuators()[act_idx]; if (IS_TAGGED(act->GetAction())) act->SetAction(NULL); } } } } } } } int size; // delete the entities of this scene /* TODO - */ #if 0 vector<pair<KX_Scene*,KX_WorldInfo*> >::iterator worldit; size = m_worldinfos.size(); for (i=0, worldit=m_worldinfos.begin(); i<size; ) { if ((*worldit).second) { delete (*worldit).second; *worldit = m_worldinfos.back(); m_worldinfos.pop_back(); size--; } else { i++; worldit++; } } #endif /* Worlds don't reference original blender data so we need to make a set from them */ typedef std::set<KX_WorldInfo *> KX_WorldInfoSet; KX_WorldInfoSet worldset; for (int scene_idx = 0; scene_idx < numScenes; scene_idx++) { KX_Scene *scene = scenes->at(scene_idx); if (scene->GetWorldInfo()) worldset.insert(scene->GetWorldInfo()); } vector<pair<KX_Scene *, KX_WorldInfo *> >::iterator worldit; size = m_worldinfos.size(); for (i = 0, worldit = m_worldinfos.begin(); i < size;) { if (worldit->second && (worldset.count(worldit->second)) == 0) { delete worldit->second; *worldit = m_worldinfos.back(); m_worldinfos.pop_back(); size--; } else { i++; worldit++; } } worldset.clear(); /* done freeing the worlds */ vector<pair<KX_Scene *, RAS_IPolyMaterial *> >::iterator polymit; size = m_polymaterials.size(); for (i = 0, polymit = m_polymaterials.begin(); i < size; ) { RAS_IPolyMaterial *mat = polymit->second; Material *bmat = NULL; KX_BlenderMaterial *bl_mat = static_cast<KX_BlenderMaterial *>(mat); bmat = bl_mat->GetBlenderMaterial(); if (IS_TAGGED(bmat)) { /* only remove from bucket */ polymit->first->GetBucketManager()->RemoveMaterial(mat); } i++; polymit++; } for (i = 0, polymit = m_polymaterials.begin(); i < size; ) { RAS_IPolyMaterial *mat = polymit->second; Material *bmat = NULL; KX_BlenderMaterial *bl_mat = static_cast<KX_BlenderMaterial*>(mat); bmat = bl_mat->GetBlenderMaterial(); if (IS_TAGGED(bmat)) { // Remove the poly material coresponding to this Blender Material. m_polymat_cache[polymit->first].erase(bmat); delete polymit->second; *polymit = m_polymaterials.back(); m_polymaterials.pop_back(); size--; } else { i++; polymit++; } } vector<pair<KX_Scene *, BL_Material *> >::iterator matit; size = m_materials.size(); for (i = 0, matit = m_materials.begin(); i < size; ) { BL_Material *mat = matit->second; if (IS_TAGGED(mat->material)) { // Remove the bl material coresponding to this Blender Material. m_mat_cache[matit->first].erase(mat->material); delete matit->second; *matit = m_materials.back(); m_materials.pop_back(); size--; } else { i++; matit++; } } vector<pair<KX_Scene *, RAS_MeshObject *> >::iterator meshit; RAS_BucketManager::BucketList::iterator bit; list<RAS_MeshSlot>::iterator msit; RAS_BucketManager::BucketList buckets; size = m_meshobjects.size(); for (i = 0, meshit = m_meshobjects.begin(); i < size;) { RAS_MeshObject *me = meshit->second; if (IS_TAGGED(me->GetMesh())) { // Before deleting the mesh object, make sure the rasterizer is // no longer referencing it. buckets = meshit->first->GetBucketManager()->GetSolidBuckets(); for (bit = buckets.begin(); bit != buckets.end(); bit++) { msit = (*bit)->msBegin(); while (msit != (*bit)->msEnd()) { if (msit->m_mesh == meshit->second) (*bit)->RemoveMesh(&(*msit++)); else msit++; } } // And now the alpha buckets buckets = meshit->first->GetBucketManager()->GetAlphaBuckets(); for (bit = buckets.begin(); bit != buckets.end(); bit++) { msit = (*bit)->msBegin(); while (msit != (*bit)->msEnd()) { if (msit->m_mesh == meshit->second) (*bit)->RemoveMesh(&(*msit++)); else msit++; } } // Now it should be safe to delete delete meshit->second; *meshit = m_meshobjects.back(); m_meshobjects.pop_back(); size--; } else { i++; meshit++; } } #ifdef WITH_PYTHON /* make sure this maggie is removed from the import list if it's there * (this operation is safe if it isn't in the list) */ removeImportMain(maggie); #endif delete m_status_map[maggie->name]; m_status_map.erase(maggie->name); BKE_main_free(maggie); return true; }
void BKE_blender_globals_clear(void) { BKE_main_free(G.main); /* free all lib data */ G.main = NULL; }