Blender V5.0
blender.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
10
11#include <cstdio>
12#include <cstdlib>
13#include <cstring>
14
16
17#include "MEM_guardedalloc.h"
18
20
21#include "BLI_listbase.h"
22#include "BLI_string.h"
23#include "BLI_string_utf8.h"
24#include "BLI_utildefines.h"
25
26#include "IMB_imbuf.hh"
27#include "IMB_moviecache.hh"
28
29#include "MOV_util.hh"
30
31#include "BKE_addon.h"
32#include "BKE_appdir.hh"
33#include "BKE_asset.hh"
34#include "BKE_blender.hh" /* own include */
35#include "BKE_blender_user_menu.hh" /* own include */
36#include "BKE_blender_version.h" /* own include */
37#include "BKE_brush.hh"
38#include "BKE_callbacks.hh"
39#include "BKE_global.hh"
40#include "BKE_idprop.hh"
41#include "BKE_main.hh"
42#include "BKE_node.hh"
43#include "BKE_screen.hh"
44#include "BKE_studiolight.h"
45
46#include "DEG_depsgraph.hh"
47
48#include "RE_texture.h"
49
50#include "BLF_api.hh"
51
52#include "SEQ_utils.hh"
53
54#include "CLG_log.h"
55
58
59/* -------------------------------------------------------------------- */
62
64{
65 /* samples are in a global list..., also sets G_MAIN->sound->sample nullptr */
66
67 /* Needs to run before main free as window-manager is still referenced for icons preview jobs. */
69
71
72 if (G.log.file != nullptr) {
73 fclose(static_cast<FILE *>(G.log.file));
74 }
75
76 BKE_spacetypes_free(); /* after free main, it uses space callbacks */
77
78 IMB_exit();
80
83
85
88 MOV_exit();
89
91}
92
94
95/* -------------------------------------------------------------------- */
98
99static char blender_version_string[48] = "";
100
101/* Only includes patch if non-zero. */
103
105{
106 const char *version_cycle = "";
107 const char *version_cycle_compact = "";
108 if (STREQ(STRINGIFY(BLENDER_VERSION_CYCLE), "alpha")) {
109 version_cycle = " Alpha";
110 version_cycle_compact = " a";
111 }
112 else if (STREQ(STRINGIFY(BLENDER_VERSION_CYCLE), "beta")) {
113 version_cycle = " Beta";
114 version_cycle_compact = " b";
115 }
116 else if (STREQ(STRINGIFY(BLENDER_VERSION_CYCLE), "rc")) {
117 version_cycle = " Release Candidate";
118 version_cycle_compact = " RC";
119 }
120 else if (STREQ(STRINGIFY(BLENDER_VERSION_CYCLE), "release")) {
121 version_cycle = "";
122 version_cycle_compact = "";
123 }
124 else {
125 BLI_assert_msg(0, "Invalid Blender version cycle");
126 }
127
128 const char *version_suffix = BKE_blender_version_is_lts() ? " LTS" : "";
129
131 "%d.%01d.%d%s%s",
132 BLENDER_VERSION / 100,
133 BLENDER_VERSION % 100,
135 version_suffix,
136 version_cycle);
137
139 "%d.%01d.%d%s",
140 BLENDER_VERSION / 100,
141 BLENDER_VERSION % 100,
143 version_cycle_compact);
144}
145
147{
149}
150
155
157 const size_t str_buff_maxncpy,
158 const short file_version,
159 const short file_subversion)
160{
161 const short file_version_major = file_version / 100;
162 const short file_version_minor = file_version % 100;
163 if (file_subversion >= 0) {
164 BLI_snprintf_utf8(str_buff,
165 str_buff_maxncpy,
166 "%d.%d (sub %d)",
167 file_version_major,
168 file_version_minor,
169 file_subversion);
170 }
171 else {
172 BLI_snprintf_utf8(str_buff, str_buff_maxncpy, "%d.%d", file_version_major, file_version_minor);
173 }
174}
175
177{
178 bool is_alpha = STREQ(STRINGIFY(BLENDER_VERSION_CYCLE), "alpha");
179 return is_alpha;
180}
181
186
188
189/* -------------------------------------------------------------------- */
192
194{
196
197 memset(&G, 0, sizeof(Global));
198
199 U.savetime = 1;
200
202
203 STRNCPY(G.filepath_last_image, "//");
204 G.filepath_last_blend[0] = '\0';
205
206#ifndef WITH_PYTHON_SECURITY /* default */
208#else
210#endif
211
212 G.log.level = CLG_LEVEL_WARN;
213
214 G.profile_gpu = false;
215}
216
218{
219 if (G_MAIN == nullptr) {
220 return;
221 }
222 BLI_assert(G_MAIN->is_global_main);
223 BKE_main_free(G_MAIN); /* free all lib data */
224
225 G_MAIN = nullptr;
226}
227
229{
230 BLI_assert(!bmain->is_global_main);
232 bmain->is_global_main = true;
233 G_MAIN = bmain;
234}
235
237{
238 Main *old_gmain = G_MAIN;
239 BLI_assert(old_gmain->is_global_main);
240 BLI_assert(!new_gmain->is_global_main);
241 new_gmain->is_global_main = true;
242 G_MAIN = new_gmain;
243 old_gmain->is_global_main = false;
244 return old_gmain;
245}
246
248{
249 /* Might be called after WM/Main exit, so needs to be careful about nullptr-checking before
250 * de-referencing. */
251
252 if (!(G_MAIN && G_MAIN->filepath[0])) {
253 BLI_path_join(filepath, FILE_MAX, BKE_tempdir_base(), "blender.crash.txt");
254 }
255 else {
257 BLI_path_extension_replace(filepath, FILE_MAX, ".crash.txt");
258 }
259}
260
262
263/* -------------------------------------------------------------------- */
266
268{
269 if (kmi->properties) {
271 }
272 if (kmi->ptr) {
273 MEM_delete(kmi->ptr);
274 }
275}
276
278{
279 blender::dna::shallow_swap(*userdef_a, *userdef_b);
280}
281
283{
285 BKE_blender_userdef_data_free(userdef, true);
286}
287
289{
291 MEM_freeN(userdef);
292}
293
294static void userdef_free_keymaps(UserDef *userdef)
295{
296 for (wmKeyMap *km = static_cast<wmKeyMap *>(userdef->user_keymaps.first), *km_next; km;
297 km = km_next)
298 {
299 km_next = km->next;
300 LISTBASE_FOREACH (wmKeyMapDiffItem *, kmdi, &km->diff_items) {
301 if (kmdi->add_item) {
302 keymap_item_free(kmdi->add_item);
303 MEM_freeN(kmdi->add_item);
304 }
305 if (kmdi->remove_item) {
306 keymap_item_free(kmdi->remove_item);
307 MEM_freeN(kmdi->remove_item);
308 }
309 }
310
311 LISTBASE_FOREACH (wmKeyMapItem *, kmi, &km->items) {
312 keymap_item_free(kmi);
313 }
314
315 BLI_freelistN(&km->diff_items);
316 BLI_freelistN(&km->items);
317
318 MEM_freeN(km);
319 }
321}
322
324{
325 for (wmKeyConfigPref *kpt = static_cast<wmKeyConfigPref *>(userdef->user_keyconfig_prefs.first),
326 *kpt_next;
327 kpt;
328 kpt = kpt_next)
329 {
330 kpt_next = kpt->next;
331 IDP_FreeProperty(kpt->prop);
332 MEM_freeN(kpt);
333 }
335}
336
337static void userdef_free_user_menus(UserDef *userdef)
338{
339 for (bUserMenu *um = static_cast<bUserMenu *>(userdef->user_menus.first), *um_next; um;
340 um = um_next)
341 {
342 um_next = um->next;
344 MEM_freeN(um);
345 }
346}
347
348static void userdef_free_addons(UserDef *userdef)
349{
350 for (bAddon *addon = static_cast<bAddon *>(userdef->addons.first), *addon_next; addon;
351 addon = addon_next)
352 {
353 addon_next = addon->next;
354 BKE_addon_free(addon);
355 }
356 BLI_listbase_clear(&userdef->addons);
357}
358
359void BKE_blender_userdef_data_free(UserDef *userdef, bool clear_fonts)
360{
361#define U BLI_STATIC_ASSERT(false, "Global 'U' not allowed, only use arguments passed in!")
362#ifdef U
363 /* Quiet warning. */
364#endif
365
366 userdef_free_keymaps(userdef);
369 userdef_free_addons(userdef);
370
371 if (clear_fonts) {
372 LISTBASE_FOREACH (uiFont *, font, &userdef->uifonts) {
373 BLF_unload_id(font->blf_id);
374 }
375 BLF_default_set(-1);
376 }
377
378 BLI_freelistN(&userdef->autoexec_paths);
381
383 MEM_SAFE_FREE(repo_ref->access_token);
384 MEM_freeN(repo_ref);
385 }
387
389 {
390 BKE_asset_catalog_path_list_free(settings->enabled_catalog_paths);
391 MEM_freeN(settings);
392 }
394
395 BLI_freelistN(&userdef->uistyles);
396 BLI_freelistN(&userdef->uifonts);
397 BLI_freelistN(&userdef->themes);
398
399#undef U
400}
401
403
404/* -------------------------------------------------------------------- */
407
409{
410 /* TODO:
411 * - various minor settings (add as needed).
412 */
413
414#define VALUE_SWAP(id) \
415 { \
416 std::swap(userdef_a->id, userdef_b->id); \
417 }
418
419#define DATA_SWAP(id) \
420 { \
421 UserDef userdef_tmp; \
422 memcpy(&(userdef_tmp.id), &(userdef_a->id), sizeof(userdef_tmp.id)); \
423 memcpy(&(userdef_a->id), &(userdef_b->id), sizeof(userdef_tmp.id)); \
424 memcpy(&(userdef_b->id), &(userdef_tmp.id), sizeof(userdef_tmp.id)); \
425 } \
426 ((void)0)
427
428#define FLAG_SWAP(id, ty, flags) \
429 { \
430 CHECK_TYPE(&(userdef_a->id), ty *); \
431 const ty f = flags; \
432 const ty a = userdef_a->id; \
433 const ty b = userdef_b->id; \
434 userdef_a->id = (userdef_a->id & ~f) | (b & f); \
435 userdef_b->id = (userdef_b->id & ~f) | (a & f); \
436 } \
437 ((void)0)
438
439 VALUE_SWAP(uistyles);
440 VALUE_SWAP(uifonts);
441 VALUE_SWAP(themes);
442 VALUE_SWAP(addons);
443 VALUE_SWAP(user_keymaps);
444 VALUE_SWAP(user_keyconfig_prefs);
445
446 DATA_SWAP(font_path_ui);
447 DATA_SWAP(font_path_ui_mono);
448 DATA_SWAP(keyconfigstr);
449
450 DATA_SWAP(gizmo_flag);
451 DATA_SWAP(app_flag);
452
453 /* We could add others. */
455
456 DATA_SWAP(ui_scale);
457
458#undef VALUE_SWAP
459#undef DATA_SWAP
460#undef FLAG_SWAP
461}
462
468
474
476
477/* -------------------------------------------------------------------- */
482
483static struct AtExitData {
485
486 void (*func)(void *user_data);
488} *g_atexit = nullptr;
489
490void BKE_blender_atexit_register(void (*func)(void *user_data), void *user_data)
491{
492 AtExitData *ae = static_cast<AtExitData *>(malloc(sizeof(*ae)));
493 ae->next = g_atexit;
494 ae->func = func;
495 ae->user_data = user_data;
496 g_atexit = ae;
497}
498
499void BKE_blender_atexit_unregister(void (*func)(void *user_data), const void *user_data)
500{
501 AtExitData *ae = g_atexit;
502 AtExitData **ae_p = &g_atexit;
503
504 while (ae) {
505 if ((ae->func == func) && (ae->user_data == user_data)) {
506 *ae_p = ae->next;
507 free(ae);
508 return;
509 }
510 ae_p = &ae->next;
511 ae = ae->next;
512 }
513}
514
516{
517 AtExitData *ae = g_atexit, *ae_next;
518 while (ae) {
519 ae_next = ae->next;
520
521 ae->func(ae->user_data);
522
523 free(ae);
524 ae = ae_next;
525 }
526 g_atexit = nullptr;
527}
528
void BKE_addon_free(struct bAddon *addon)
Definition addon.cc:68
const char * BKE_tempdir_base() ATTR_WARN_UNUSED_RESULT ATTR_RETURNS_NONNULL
Definition appdir.cc:1243
void BKE_asset_catalog_path_list_free(ListBase &catalog_path_list)
Blender util stuff.
void BKE_blender_user_menu_item_free_list(ListBase *lb)
#define BLENDER_VERSION_PATCH
#define BLENDER_VERSION_CYCLE
#define BLENDER_VERSION
#define BLENDER_VERSION_SUFFIX
void BKE_brush_system_exit()
Definition brush.cc:562
void BKE_callback_global_finalize()
Definition callbacks.cc:107
@ G_FLAG_SCRIPT_AUTOEXEC
#define G_MAIN
void IDP_FreeProperty(IDProperty *prop)
Definition idprop.cc:1251
Main * BKE_main_new()
Definition main.cc:89
void BKE_main_free(Main *bmain)
Definition main.cc:192
void BKE_spacetypes_free()
Definition screen.cc:252
void BKE_studiolight_free(void)
void BLF_default_set(int fontid)
bool BLF_unload_id(int fontid)
Definition blf.cc:280
#define BLI_assert(a)
Definition BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:53
void BLI_kdtree_nd_ free(KDTree *tree)
#define LISTBASE_FOREACH(type, var, list)
BLI_INLINE void BLI_listbase_clear(ListBase *lb)
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
void void BLI_freelistN(ListBase *listbase) ATTR_NONNULL(1)
Definition listbase.cc:497
void void void const char * BLI_path_basename(const char *path) ATTR_NONNULL(1) ATTR_WARN_UNUSED_RESULT
#define FILE_MAX
bool BLI_path_extension_replace(char *path, size_t path_maxncpy, const char *ext) ATTR_NONNULL(1
#define BLI_path_join(...)
char * STRNCPY(char(&dst)[N], const char *src)
Definition BLI_string.h:693
size_t size_t size_t BLI_snprintf_utf8(char *__restrict dst, size_t dst_maxncpy, const char *__restrict format,...) ATTR_NONNULL(1
#define SNPRINTF_UTF8(dst, format,...)
#define STRINGIFY(x)
#define STREQ(a, b)
@ CLG_LEVEL_WARN
Definition CLG_log.h:58
void DEG_free_node_types()
@ USER_SPLASH_DISABLE
@ USER_SHOW_GIZMO_NAVIGATE
@ USER_SAVE_PROMPT
void IMB_exit()
Definition module.cc:21
void IMB_moviecache_destruct()
Read Guarded memory(de)allocation.
#define MEM_SAFE_FREE(v)
static struct AtExitData * g_atexit
void BKE_blender_userdef_data_swap(UserDef *userdef_a, UserDef *userdef_b)
Definition blender.cc:277
#define VALUE_SWAP(id)
static char blender_version_string[48]
Definition blender.cc:99
static void blender_version_init()
Definition blender.cc:104
static void userdef_free_keymaps(UserDef *userdef)
Definition blender.cc:294
const char * BKE_blender_version_string_compact()
Definition blender.cc:151
bool BKE_blender_version_is_alpha()
Definition blender.cc:176
Main * BKE_blender_globals_main_swap(Main *new_gmain)
Definition blender.cc:236
void BKE_blender_userdef_data_set(UserDef *userdef)
Definition blender.cc:282
const char * BKE_blender_version_string()
Definition blender.cc:146
static void userdef_free_addons(UserDef *userdef)
Definition blender.cc:348
void BKE_blender_globals_main_replace(Main *bmain)
Definition blender.cc:228
static void userdef_free_user_menus(UserDef *userdef)
Definition blender.cc:337
void BKE_blender_userdef_app_template_data_set_and_free(UserDef *userdef)
Definition blender.cc:469
void BKE_blender_atexit_register(void(*func)(void *user_data), void *user_data)
Definition blender.cc:490
void BKE_blender_globals_crash_path_get(char filepath[FILE_MAX])
Definition blender.cc:247
#define DATA_SWAP(id)
void BKE_blender_atexit()
Definition blender.cc:515
void BKE_blender_atexit_unregister(void(*func)(void *user_data), const void *user_data)
Definition blender.cc:499
void BKE_blender_globals_init()
Definition blender.cc:193
void BKE_blender_version_blendfile_string_from_values(char *str_buff, const size_t str_buff_maxncpy, const short file_version, const short file_subversion)
Definition blender.cc:156
void BKE_blender_userdef_data_set_and_free(UserDef *userdef)
Definition blender.cc:288
void BKE_blender_globals_clear()
Definition blender.cc:217
void BKE_blender_userdef_app_template_data_set(UserDef *userdef)
Definition blender.cc:463
#define FLAG_SWAP(id, ty, flags)
void BKE_blender_userdef_app_template_data_swap(UserDef *userdef_a, UserDef *userdef_b)
Definition blender.cc:408
void BKE_blender_userdef_data_free(UserDef *userdef, bool clear_fonts)
Definition blender.cc:359
static void keymap_item_free(wmKeyMapItem *kmi)
Definition blender.cc:267
void BKE_blender_free()
Definition blender.cc:63
static char blender_version_string_compact[48]
Definition blender.cc:102
static void userdef_free_keyconfig_prefs(UserDef *userdef)
Definition blender.cc:323
bool BKE_blender_version_is_lts()
Definition blender.cc:182
#define U
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
#define G(x, y, z)
void MOV_exit()
void node_system_exit()
Definition node.cc:5431
void * user_data
Definition blender.cc:487
void(* func)(void *user_data)
Definition blender.cc:486
AtExitData * next
Definition blender.cc:484
void * first
bool is_global_main
Definition BKE_main.hh:239
struct ListBase addons
ListBase script_directories
struct ListBase uistyles
struct ListBase asset_shelves_settings
struct ListBase user_keymaps
struct ListBase themes
struct ListBase autoexec_paths
struct ListBase uifonts
struct ListBase user_keyconfig_prefs
struct ListBase extension_repos
struct ListBase user_menus
struct ListBase asset_libraries
struct PointerRNA * ptr
void RE_texture_rng_exit()