/** * Only write the userdef in a .blend, merging with the existing blend file. * \return success * * \note In the future we should re-evaluate user preferences, * possibly splitting out system/hardware specific prefs. */ bool BKE_blendfile_userdef_write_app_template(const char *filepath, ReportList *reports) { /* if it fails, overwrite is OK. */ UserDef *userdef_default = BKE_blendfile_userdef_read(filepath, NULL); if (userdef_default == NULL) { return BKE_blendfile_userdef_write(filepath, reports); } BKE_blender_userdef_app_template_data_swap(&U, userdef_default); bool ok = BKE_blendfile_userdef_write(filepath, reports); BKE_blender_userdef_app_template_data_swap(&U, userdef_default); BKE_blender_userdef_data_free(userdef_default, false); MEM_freeN(userdef_default); return ok; }
/** * \note doesn't run exit() call #WM_exit() for that. */ void WM_exit_ext(bContext *C, const bool do_python) { wmWindowManager *wm = C ? CTX_wm_manager(C) : NULL; /* first wrap up running stuff, we assume only the active WM is running */ /* modal handlers are on window level freed, others too? */ /* note; same code copied in wm_files.c */ if (C && wm) { wmWindow *win; if (!G.background) { struct MemFile *undo_memfile = wm->undo_stack ? ED_undosys_stack_memfile_get_active(wm->undo_stack) : NULL; if ((U.uiflag2 & USER_KEEP_SESSION) || (undo_memfile != NULL)) { /* save the undo state as quit.blend */ char filename[FILE_MAX]; bool has_edited; int fileflags = G.fileflags & ~(G_FILE_COMPRESS | G_FILE_AUTOPLAY | G_FILE_HISTORY); BLI_make_file_string("/", filename, BKE_tempdir_base(), BLENDER_QUIT_FILE); has_edited = ED_editors_flush_edits(C, false); if ((has_edited && BLO_write_file(CTX_data_main(C), filename, fileflags, NULL, NULL)) || (undo_memfile && BLO_memfile_write_file(undo_memfile, filename))) { printf("Saved session recovery to '%s'\n", filename); } } } WM_jobs_kill_all(wm); for (win = wm->windows.first; win; win = win->next) { CTX_wm_window_set(C, win); /* needed by operator close callbacks */ WM_event_remove_handlers(C, &win->handlers); WM_event_remove_handlers(C, &win->modalhandlers); ED_screen_exit(C, win, win->screen); } } BKE_addon_pref_type_free(); wm_operatortype_free(); wm_dropbox_free(); WM_menutype_free(); WM_uilisttype_free(); /* all non-screen and non-space stuff editors did, like editmode */ if (C) ED_editors_exit(C); ED_undosys_type_free(); // XXX // BIF_GlobalReebFree(); // BIF_freeRetarget(); BIF_freeTemplates(C); free_openrecent(); BKE_mball_cubeTable_free(); /* render code might still access databases */ RE_FreeAllRender(); RE_engines_exit(); ED_preview_free_dbase(); /* frees a Main dbase, before BKE_blender_free! */ if (C && wm) wm_free_reports(C); /* before BKE_blender_free! - since the ListBases get freed there */ BKE_sequencer_free_clipboard(); /* sequencer.c */ BKE_tracking_clipboard_free(); BKE_mask_clipboard_free(); BKE_vfont_clipboard_free(); #ifdef WITH_COMPOSITOR COM_deinitialize(); #endif BKE_blender_free(); /* blender.c, does entire library and spacetypes */ // free_matcopybuf(); ANIM_fcurves_copybuf_free(); ANIM_drivers_copybuf_free(); ANIM_driver_vars_copybuf_free(); ANIM_fmodifiers_copybuf_free(); ED_gpencil_anim_copybuf_free(); ED_gpencil_strokes_copybuf_free(); BKE_node_clipboard_clear(); BLF_exit(); #ifdef WITH_INTERNATIONAL BLF_free_unifont(); BLF_free_unifont_mono(); BLT_lang_free(); #endif ANIM_keyingset_infos_exit(); // free_txt_data(); #ifdef WITH_PYTHON /* option not to close python so we can use 'atexit' */ if (do_python && ((C == NULL) || CTX_py_init_get(C))) { /* XXX - old note */ /* before BKE_blender_free so py's gc happens while library still exists */ /* needed at least for a rare sigsegv that can happen in pydrivers */ /* Update for blender 2.5, move after BKE_blender_free because blender now holds references to PyObject's * so decref'ing them after python ends causes bad problems every time * the pyDriver bug can be fixed if it happens again we can deal with it then */ BPY_python_end(); } #else (void)do_python; #endif if (!G.background) { #ifdef WITH_OPENSUBDIV BKE_subsurf_osd_cleanup(); #endif GPU_global_buffer_pool_free(); GPU_free_unused_buffers(G_MAIN); GPU_exit(); } ED_file_exit(); /* for fsmenu */ UI_exit(); BKE_blender_userdef_data_free(&U, false); RNA_exit(); /* should be after BPY_python_end so struct python slots are cleared */ wm_ghost_exit(); CTX_free(C); #ifdef WITH_GAMEENGINE SYS_DeleteSystem(SYS_GetSystem()); #endif GHOST_DisposeSystemPaths(); DNA_sdna_current_free(); BLI_threadapi_exit(); /* No need to call this early, rather do it late so that other pieces of Blender using sound may exit cleanly, * see also T50676. */ BKE_sound_exit(); CLG_exit(); BKE_blender_atexit(); if (MEM_get_memory_blocks_in_use() != 0) { size_t mem_in_use = MEM_get_memory_in_use() + MEM_get_memory_in_use(); printf("Error: Not freed memory blocks: %u, total unfreed memory %f MB\n", MEM_get_memory_blocks_in_use(), (double)mem_in_use / 1024 / 1024); MEM_printmemlist(); } wm_autosave_delete(); BKE_tempdir_session_purge(); }
void BKE_blender_userdef_app_template_data_set(UserDef *userdef) { BKE_blender_userdef_app_template_data_swap(&U, userdef); BKE_blender_userdef_data_free(userdef, true); }