/* * ***** BEGIN GPL LICENSE BLOCK ***** * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. * All rights reserved. * * The Original Code is: all of this file. * * Contributor(s): none yet. * * ***** END GPL LICENSE BLOCK ***** */ /** \file blender/blenkernel/intern/blender.c * \ingroup bke * * Application level startup/shutdown functionality. */ #include #include #include #include "MEM_guardedalloc.h" #include "BLI_string.h" #include "BLI_listbase.h" #include "BLI_utildefines.h" #include "BLI_callbacks.h" #include "IMB_imbuf.h" #include "IMB_moviecache.h" #include "BKE_blender.h" /* own include */ #include "BKE_blender_version.h" /* own include */ #include "BKE_blendfile.h" #include "BKE_brush.h" #include "BKE_cachefile.h" #include "BKE_context.h" #include "BKE_depsgraph.h" #include "BKE_global.h" #include "BKE_idprop.h" #include "BKE_image.h" #include "BKE_library.h" #include "BKE_node.h" #include "BKE_report.h" #include "BKE_scene.h" #include "BKE_screen.h" #include "BKE_sequencer.h" #include "RE_pipeline.h" #include "RE_render_ext.h" #include "BLF_api.h" Global G; UserDef U; char versionstr[48] = ""; /* ********** free ********** */ /* 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 */ BKE_main_free(G.main); G.main = NULL; BKE_spacetypes_free(); /* after free main, it uses space callbacks */ IMB_exit(); BKE_cachefiles_exit(); BKE_images_exit(); DAG_exit(); BKE_brush_system_exit(); RE_texture_rng_exit(); BLI_callback_global_finalize(); BKE_sequencer_cache_destruct(); IMB_moviecache_destruct(); free_nodesystem(); } void BKE_blender_version_string(char *version_str, size_t maxncpy, short version, short subversion, bool v_prefix, bool include_subversion) { const char *prefix = v_prefix ? "v" : ""; if (include_subversion && subversion > 0) { BLI_snprintf(version_str, maxncpy, "%s%d.%02d.%d", prefix, version / 100, version % 100, subversion); } else { BLI_snprintf(version_str, maxncpy, "%s%d.%02d", prefix, version / 100, version % 100); } } void BKE_blender_globals_init(void) { memset(&G, 0, sizeof(Global)); U.savetime = 1; G.main = BKE_main_new(); strcpy(G.ima, "//"); BKE_blender_version_string(versionstr, sizeof(versionstr), BLENDER_VERSION, BLENDER_SUBVERSION, true, true); #ifndef WITH_PYTHON_SECURITY /* default */ G.f |= G_SCRIPT_AUTOEXEC; #else G.f &= ~G_SCRIPT_AUTOEXEC; #endif } void BKE_blender_globals_clear(void) { BKE_main_free(G.main); /* free all lib data */ G.main = NULL; } /***/ static void keymap_item_free(wmKeyMapItem *kmi) { if (kmi->properties) { IDP_FreeProperty(kmi->properties); MEM_freeN(kmi->properties); } if (kmi->ptr) MEM_freeN(kmi->ptr); } void BKE_blender_userdef_set_data(UserDef *userdef) { /* only here free userdef themes... */ BKE_blender_userdef_free_data(&U); U = *userdef; } static void userdef_free_keymaps(UserDef *userdef) { for (wmKeyMap *km = userdef->user_keymaps.first, *km_next; km; km = km_next) { km_next = km->next; for (wmKeyMapDiffItem *kmdi = km->diff_items.first; kmdi; kmdi = kmdi->next) { if (kmdi->add_item) { keymap_item_free(kmdi->add_item); MEM_freeN(kmdi->add_item); } if (kmdi->remove_item) { keymap_item_free(kmdi->remove_item); MEM_freeN(kmdi->remove_item); } } for (wmKeyMapItem *kmi = km->items.first; kmi; kmi = kmi->next) { keymap_item_free(kmi); } BLI_freelistN(&km->diff_items); BLI_freelistN(&km->items); MEM_freeN(km); } BLI_listbase_clear(&userdef->user_keymaps); } static void userdef_free_addons(UserDef *userdef) { for (bAddon *addon = userdef->addons.first, *addon_next; addon; addon = addon_next) { addon_next = addon->next; if (addon->prop) { IDP_FreeProperty(addon->prop); MEM_freeN(addon->prop); } MEM_freeN(addon); } BLI_listbase_clear(&userdef->addons); } /** * When loading a new userdef from file, * or when exiting Blender. */ void BKE_blender_userdef_free_data(UserDef *userdef) { #define U _invalid_access_ /* ensure no accidental global access */ #ifdef U /* quiet warning */ #endif userdef_free_keymaps(userdef); userdef_free_addons(userdef); for (uiFont *font = userdef->uifonts.first; font; font = font->next) { BLF_unload_id(font->blf_id); } BLF_default_set(-1); BLI_freelistN(&userdef->autoexec_paths); BLI_freelistN(&userdef->uistyles); BLI_freelistN(&userdef->uifonts); BLI_freelistN(&userdef->themes); #undef U } /** * Handle changes in settings that need refreshing. */ void BKE_blender_userdef_refresh(void) { /* prevent accidents */ if (U.pixelsize == 0) U.pixelsize = 1; BLF_default_dpi(U.pixelsize * U.dpi); U.widget_unit = (U.pixelsize * U.dpi * 20 + 36) / 72; } /** * Write U from userdef. * This function defines which settings a template will override for the user preferences. */ void BKE_blender_userdef_set_app_template(UserDef *userdef) { /* TODO: * - keymaps * - various minor settings (add as needed). */ #define LIST_OVERRIDE(id) { \ BLI_freelistN(&U.id); \ BLI_movelisttolist(&U.id, &userdef->id); \ } ((void)0) #define MEMCPY_OVERRIDE(id) \ memcpy(U.id, userdef->id, sizeof(U.id)); /* for some types we need custom free functions */ userdef_free_addons(&U); userdef_free_keymaps(&U); LIST_OVERRIDE(uistyles); LIST_OVERRIDE(uifonts); LIST_OVERRIDE(themes); LIST_OVERRIDE(addons); LIST_OVERRIDE(user_keymaps); MEMCPY_OVERRIDE(light); MEMCPY_OVERRIDE(font_path_ui); MEMCPY_OVERRIDE(font_path_ui_mono); #undef LIST_OVERRIDE #undef MEMCPY_OVERRIDE } /* ***************** testing for break ************* */ static void (*blender_test_break_cb)(void) = NULL; void BKE_blender_callback_test_break_set(void (*func)(void)) { blender_test_break_cb = func; } int BKE_blender_test_break(void) { if (!G.background) { if (blender_test_break_cb) blender_test_break_cb(); } return (G.is_break == true); } /** \name Blender's AtExit * * \note Don't use MEM_mallocN so functions can be registered at any time. * \{ */ static struct AtExitData { struct AtExitData *next; void (*func)(void *user_data); void *user_data; } *g_atexit = NULL; void BKE_blender_atexit_register(void (*func)(void *user_data), void *user_data) { struct AtExitData *ae = malloc(sizeof(*ae)); ae->next = g_atexit; ae->func = func; ae->user_data = user_data; g_atexit = ae; } void BKE_blender_atexit_unregister(void (*func)(void *user_data), const void *user_data) { struct AtExitData *ae = g_atexit; struct AtExitData **ae_p = &g_atexit; while (ae) { if ((ae->func == func) && (ae->user_data == user_data)) { *ae_p = ae->next; free(ae); return; } ae_p = &ae; ae = ae->next; } } void BKE_blender_atexit(void) { struct AtExitData *ae = g_atexit, *ae_next; while (ae) { ae_next = ae->next; ae->func(ae->user_data); free(ae); ae = ae_next; } g_atexit = NULL; } /** \} */