Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'source/blender/blenkernel/intern/blendfile.c')
-rw-r--r--source/blender/blenkernel/intern/blendfile.c1057
1 files changed, 529 insertions, 528 deletions
diff --git a/source/blender/blenkernel/intern/blendfile.c b/source/blender/blenkernel/intern/blendfile.c
index cd17911d65d..723c8bb48bf 100644
--- a/source/blender/blenkernel/intern/blendfile.c
+++ b/source/blender/blenkernel/intern/blendfile.c
@@ -70,32 +70,32 @@
static bool clean_paths_visit_cb(void *UNUSED(userdata), char *path_dst, const char *path_src)
{
- strcpy(path_dst, path_src);
- BLI_path_native_slash(path_dst);
- return !STREQ(path_dst, path_src);
+ strcpy(path_dst, path_src);
+ BLI_path_native_slash(path_dst);
+ return !STREQ(path_dst, path_src);
}
/* make sure path names are correct for OS */
static void clean_paths(Main *main)
{
- Scene *scene;
+ Scene *scene;
- BKE_bpath_traverse_main(main, clean_paths_visit_cb, BKE_BPATH_TRAVERSE_SKIP_MULTIFILE, NULL);
+ BKE_bpath_traverse_main(main, clean_paths_visit_cb, BKE_BPATH_TRAVERSE_SKIP_MULTIFILE, NULL);
- for (scene = main->scenes.first; scene; scene = scene->id.next) {
- BLI_path_native_slash(scene->r.pic);
- }
+ for (scene = main->scenes.first; scene; scene = scene->id.next) {
+ BLI_path_native_slash(scene->r.pic);
+ }
}
static bool wm_scene_is_visible(wmWindowManager *wm, Scene *scene)
{
- wmWindow *win;
- for (win = wm->windows.first; win; win = win->next) {
- if (win->scene == scene) {
- return true;
- }
- }
- return false;
+ wmWindow *win;
+ for (win = wm->windows.first; win; win = win->next) {
+ if (win->scene == scene) {
+ return true;
+ }
+ }
+ return false;
}
/**
@@ -107,350 +107,351 @@ static bool wm_scene_is_visible(wmWindowManager *wm, Scene *scene)
* \param bfd: Blend file data, freed by this function on exit.
* \param filepath: File path or identifier.
*/
-static void setup_app_data(
- bContext *C, BlendFileData *bfd,
- const char *filepath,
- const bool is_startup,
- ReportList *reports)
+static void setup_app_data(bContext *C,
+ BlendFileData *bfd,
+ const char *filepath,
+ const bool is_startup,
+ ReportList *reports)
{
- Main *bmain = G_MAIN;
- Scene *curscene = NULL;
- const bool recover = (G.fileflags & G_FILE_RECOVER) != 0;
- enum {
- LOAD_UI = 1,
- LOAD_UI_OFF,
- LOAD_UNDO,
- } mode;
-
- /* may happen with library files - UNDO file should never have NULL cursccene... */
- if (ELEM(NULL, bfd->curscreen, bfd->curscene)) {
- BKE_report(reports, RPT_WARNING, "Library file, loading empty scene");
- mode = LOAD_UI_OFF;
- }
- else if (BLI_listbase_is_empty(&bfd->main->screens)) {
- mode = LOAD_UNDO;
- }
- else if ((G.fileflags & G_FILE_NO_UI) && (is_startup == false)) {
- mode = LOAD_UI_OFF;
- }
- else {
- mode = LOAD_UI;
- }
-
- /* Free all render results, without this stale data gets displayed after loading files */
- if (mode != LOAD_UNDO) {
- RE_FreeAllRenderResults();
- }
-
- /* Only make filepaths compatible when loading for real (not undo) */
- if (mode != LOAD_UNDO) {
- clean_paths(bfd->main);
- }
-
- /* XXX here the complex windowmanager matching */
-
- /* no load screens? */
- if (mode != LOAD_UI) {
- /* Logic for 'track_undo_scene' is to keep using the scene which the active screen has,
- * as long as the scene associated with the undo operation is visible in one of the open windows.
- *
- * - 'curscreen->scene' - scene the user is currently looking at.
- * - 'bfd->curscene' - scene undo-step was created in.
- *
- * This means users can have 2+ windows open and undo in both without screens switching.
- * But if they close one of the screens,
- * undo will ensure that the scene being operated on will be activated
- * (otherwise we'd be undoing on an off-screen scene which isn't acceptable).
- * see: T43424
- */
- wmWindow *win;
- bScreen *curscreen = NULL;
- ViewLayer *cur_view_layer;
- bool track_undo_scene;
-
- /* comes from readfile.c */
- SWAP(ListBase, bmain->wm, bfd->main->wm);
- SWAP(ListBase, bmain->workspaces, bfd->main->workspaces);
- SWAP(ListBase, bmain->screens, bfd->main->screens);
-
- /* we re-use current window and screen */
- win = CTX_wm_window(C);
- curscreen = CTX_wm_screen(C);
- /* but use Scene pointer from new file */
- curscene = bfd->curscene;
- cur_view_layer = bfd->cur_view_layer;
-
- track_undo_scene = (mode == LOAD_UNDO && curscreen && curscene && bfd->main->wm.first);
-
- if (curscene == NULL) {
- curscene = bfd->main->scenes.first;
- }
- /* empty file, we add a scene to make Blender work */
- if (curscene == NULL) {
- curscene = BKE_scene_add(bfd->main, "Empty");
- }
- if (cur_view_layer == NULL) {
- /* fallback to scene layer */
- cur_view_layer = BKE_view_layer_default_view(curscene);
- }
-
- if (track_undo_scene) {
- /* keep the old (free'd) scene, let 'blo_lib_link_screen_restore'
- * replace it with 'curscene' if its needed */
- }
- /* and we enforce curscene to be in current screen */
- else if (win) { /* can run in bgmode */
- win->scene = curscene;
- }
-
- /* BKE_blender_globals_clear will free G_MAIN, here we can still restore pointers */
- blo_lib_link_restore(bmain, bfd->main, CTX_wm_manager(C), curscene, cur_view_layer);
- if (win) {
- curscene = win->scene;
- }
-
- if (track_undo_scene) {
- wmWindowManager *wm = bfd->main->wm.first;
- if (wm_scene_is_visible(wm, bfd->curscene) == false) {
- curscene = bfd->curscene;
- win->scene = curscene;
- BKE_screen_view3d_scene_sync(curscreen, curscene);
- }
- }
-
- /* We need to tag this here because events may be handled immediately after.
- * only the current screen is important because we wont have to handle
- * events from multiple screens at once.*/
- if (curscreen) {
- BKE_screen_gizmo_tag_refresh(curscreen);
- }
- }
-
- /* free G_MAIN Main database */
-// CTX_wm_manager_set(C, NULL);
- BKE_blender_globals_clear();
-
- /* clear old property update cache, in case some old references are left dangling */
- RNA_property_update_cache_free();
-
- bmain = G_MAIN = bfd->main;
-
- CTX_data_main_set(C, bmain);
-
- if (bfd->user) {
-
- /* only here free userdef themes... */
- BKE_blender_userdef_data_set_and_free(bfd->user);
- bfd->user = NULL;
-
- /* Security issue: any blend file could include a USER block.
- *
- * Currently we load prefs from BLENDER_STARTUP_FILE and later on load BLENDER_USERPREF_FILE,
- * to load the preferences defined in the users home dir.
- *
- * This means we will never accidentally (or maliciously)
- * enable scripts auto-execution by loading a '.blend' file.
- */
- U.flag |= USER_SCRIPT_AUTOEXEC_DISABLE;
- }
-
- /* case G_FILE_NO_UI or no screens in file */
- if (mode != LOAD_UI) {
- /* leave entire context further unaltered? */
- CTX_data_scene_set(C, curscene);
- }
- else {
- CTX_wm_manager_set(C, bmain->wm.first);
- CTX_wm_screen_set(C, bfd->curscreen);
- CTX_data_scene_set(C, bfd->curscene);
- CTX_wm_area_set(C, NULL);
- CTX_wm_region_set(C, NULL);
- CTX_wm_menu_set(C, NULL);
- curscene = bfd->curscene;
- }
-
- /* Keep state from preferences. */
- const int fileflags_keep = G_FILE_FLAG_ALL_RUNTIME;
- G.fileflags = (G.fileflags & fileflags_keep) | (bfd->fileflags & ~fileflags_keep);
-
- /* this can happen when active scene was lib-linked, and doesn't exist anymore */
- if (CTX_data_scene(C) == NULL) {
- wmWindow *win = CTX_wm_window(C);
-
- /* in case we don't even have a local scene, add one */
- if (!bmain->scenes.first)
- BKE_scene_add(bmain, "Empty");
-
- CTX_data_scene_set(C, bmain->scenes.first);
- win->scene = CTX_data_scene(C);
- curscene = CTX_data_scene(C);
- }
-
- BLI_assert(curscene == CTX_data_scene(C));
-
-
- /* special cases, override loaded flags: */
- if (G.f != bfd->globalf) {
- const int flags_keep = G_FLAG_ALL_RUNTIME;
- bfd->globalf &= G_FLAG_ALL_READFILE;
- bfd->globalf = (bfd->globalf & ~flags_keep) | (G.f & flags_keep);
- }
-
-
- G.f = bfd->globalf;
+ Main *bmain = G_MAIN;
+ Scene *curscene = NULL;
+ const bool recover = (G.fileflags & G_FILE_RECOVER) != 0;
+ enum {
+ LOAD_UI = 1,
+ LOAD_UI_OFF,
+ LOAD_UNDO,
+ } mode;
+
+ /* may happen with library files - UNDO file should never have NULL cursccene... */
+ if (ELEM(NULL, bfd->curscreen, bfd->curscene)) {
+ BKE_report(reports, RPT_WARNING, "Library file, loading empty scene");
+ mode = LOAD_UI_OFF;
+ }
+ else if (BLI_listbase_is_empty(&bfd->main->screens)) {
+ mode = LOAD_UNDO;
+ }
+ else if ((G.fileflags & G_FILE_NO_UI) && (is_startup == false)) {
+ mode = LOAD_UI_OFF;
+ }
+ else {
+ mode = LOAD_UI;
+ }
+
+ /* Free all render results, without this stale data gets displayed after loading files */
+ if (mode != LOAD_UNDO) {
+ RE_FreeAllRenderResults();
+ }
+
+ /* Only make filepaths compatible when loading for real (not undo) */
+ if (mode != LOAD_UNDO) {
+ clean_paths(bfd->main);
+ }
+
+ /* XXX here the complex windowmanager matching */
+
+ /* no load screens? */
+ if (mode != LOAD_UI) {
+ /* Logic for 'track_undo_scene' is to keep using the scene which the active screen has,
+ * as long as the scene associated with the undo operation is visible in one of the open windows.
+ *
+ * - 'curscreen->scene' - scene the user is currently looking at.
+ * - 'bfd->curscene' - scene undo-step was created in.
+ *
+ * This means users can have 2+ windows open and undo in both without screens switching.
+ * But if they close one of the screens,
+ * undo will ensure that the scene being operated on will be activated
+ * (otherwise we'd be undoing on an off-screen scene which isn't acceptable).
+ * see: T43424
+ */
+ wmWindow *win;
+ bScreen *curscreen = NULL;
+ ViewLayer *cur_view_layer;
+ bool track_undo_scene;
+
+ /* comes from readfile.c */
+ SWAP(ListBase, bmain->wm, bfd->main->wm);
+ SWAP(ListBase, bmain->workspaces, bfd->main->workspaces);
+ SWAP(ListBase, bmain->screens, bfd->main->screens);
+
+ /* we re-use current window and screen */
+ win = CTX_wm_window(C);
+ curscreen = CTX_wm_screen(C);
+ /* but use Scene pointer from new file */
+ curscene = bfd->curscene;
+ cur_view_layer = bfd->cur_view_layer;
+
+ track_undo_scene = (mode == LOAD_UNDO && curscreen && curscene && bfd->main->wm.first);
+
+ if (curscene == NULL) {
+ curscene = bfd->main->scenes.first;
+ }
+ /* empty file, we add a scene to make Blender work */
+ if (curscene == NULL) {
+ curscene = BKE_scene_add(bfd->main, "Empty");
+ }
+ if (cur_view_layer == NULL) {
+ /* fallback to scene layer */
+ cur_view_layer = BKE_view_layer_default_view(curscene);
+ }
+
+ if (track_undo_scene) {
+ /* keep the old (free'd) scene, let 'blo_lib_link_screen_restore'
+ * replace it with 'curscene' if its needed */
+ }
+ /* and we enforce curscene to be in current screen */
+ else if (win) { /* can run in bgmode */
+ win->scene = curscene;
+ }
+
+ /* BKE_blender_globals_clear will free G_MAIN, here we can still restore pointers */
+ blo_lib_link_restore(bmain, bfd->main, CTX_wm_manager(C), curscene, cur_view_layer);
+ if (win) {
+ curscene = win->scene;
+ }
+
+ if (track_undo_scene) {
+ wmWindowManager *wm = bfd->main->wm.first;
+ if (wm_scene_is_visible(wm, bfd->curscene) == false) {
+ curscene = bfd->curscene;
+ win->scene = curscene;
+ BKE_screen_view3d_scene_sync(curscreen, curscene);
+ }
+ }
+
+ /* We need to tag this here because events may be handled immediately after.
+ * only the current screen is important because we wont have to handle
+ * events from multiple screens at once.*/
+ if (curscreen) {
+ BKE_screen_gizmo_tag_refresh(curscreen);
+ }
+ }
+
+ /* free G_MAIN Main database */
+ // CTX_wm_manager_set(C, NULL);
+ BKE_blender_globals_clear();
+
+ /* clear old property update cache, in case some old references are left dangling */
+ RNA_property_update_cache_free();
+
+ bmain = G_MAIN = bfd->main;
+
+ CTX_data_main_set(C, bmain);
+
+ if (bfd->user) {
+
+ /* only here free userdef themes... */
+ BKE_blender_userdef_data_set_and_free(bfd->user);
+ bfd->user = NULL;
+
+ /* Security issue: any blend file could include a USER block.
+ *
+ * Currently we load prefs from BLENDER_STARTUP_FILE and later on load BLENDER_USERPREF_FILE,
+ * to load the preferences defined in the users home dir.
+ *
+ * This means we will never accidentally (or maliciously)
+ * enable scripts auto-execution by loading a '.blend' file.
+ */
+ U.flag |= USER_SCRIPT_AUTOEXEC_DISABLE;
+ }
+
+ /* case G_FILE_NO_UI or no screens in file */
+ if (mode != LOAD_UI) {
+ /* leave entire context further unaltered? */
+ CTX_data_scene_set(C, curscene);
+ }
+ else {
+ CTX_wm_manager_set(C, bmain->wm.first);
+ CTX_wm_screen_set(C, bfd->curscreen);
+ CTX_data_scene_set(C, bfd->curscene);
+ CTX_wm_area_set(C, NULL);
+ CTX_wm_region_set(C, NULL);
+ CTX_wm_menu_set(C, NULL);
+ curscene = bfd->curscene;
+ }
+
+ /* Keep state from preferences. */
+ const int fileflags_keep = G_FILE_FLAG_ALL_RUNTIME;
+ G.fileflags = (G.fileflags & fileflags_keep) | (bfd->fileflags & ~fileflags_keep);
+
+ /* this can happen when active scene was lib-linked, and doesn't exist anymore */
+ if (CTX_data_scene(C) == NULL) {
+ wmWindow *win = CTX_wm_window(C);
+
+ /* in case we don't even have a local scene, add one */
+ if (!bmain->scenes.first)
+ BKE_scene_add(bmain, "Empty");
+
+ CTX_data_scene_set(C, bmain->scenes.first);
+ win->scene = CTX_data_scene(C);
+ curscene = CTX_data_scene(C);
+ }
+
+ BLI_assert(curscene == CTX_data_scene(C));
+
+ /* special cases, override loaded flags: */
+ if (G.f != bfd->globalf) {
+ const int flags_keep = G_FLAG_ALL_RUNTIME;
+ bfd->globalf &= G_FLAG_ALL_READFILE;
+ bfd->globalf = (bfd->globalf & ~flags_keep) | (G.f & flags_keep);
+ }
+
+ G.f = bfd->globalf;
#ifdef WITH_PYTHON
- /* let python know about new main */
- BPY_context_update(C);
+ /* let python know about new main */
+ BPY_context_update(C);
#endif
- /* FIXME: this version patching should really be part of the file-reading code,
- * but we still get too many unrelated data-corruption crashes otherwise... */
- if (bmain->versionfile < 250)
- do_versions_ipos_to_animato(bmain);
-
- bmain->recovered = 0;
-
- /* startup.blend or recovered startup */
- if (is_startup) {
- bmain->name[0] = '\0';
- }
- else if (recover && G.relbase_valid) {
- /* in case of autosave or quit.blend, use original filename instead
- * use relbase_valid to make sure the file is saved, else we get <memory2> in the filename */
- filepath = bfd->filename;
- bmain->recovered = 1;
-
- /* these are the same at times, should never copy to the same location */
- if (bmain->name != filepath)
- BLI_strncpy(bmain->name, filepath, FILE_MAX);
- }
-
- /* baseflags, groups, make depsgraph, etc */
- /* first handle case if other windows have different scenes visible */
- if (mode == LOAD_UI) {
- wmWindowManager *wm = bmain->wm.first;
-
- if (wm) {
- for (wmWindow *win = wm->windows.first; win; win = win->next) {
- if (win->scene && win->scene != curscene) {
- BKE_scene_set_background(bmain, win->scene);
- }
- }
- }
- }
-
- /* Setting scene might require having a dependency graph, with copy on write
- * we need to make sure we ensure scene has correct color management before
- * constructing dependency graph.
- */
- if (mode != LOAD_UNDO) {
- IMB_colormanagement_check_file_config(bmain);
- }
-
- BKE_scene_set_background(bmain, curscene);
-
- if (mode != LOAD_UNDO) {
- /* TODO(sergey): Can this be also move above? */
- RE_FreeAllPersistentData();
- }
-
- MEM_freeN(bfd);
-
+ /* FIXME: this version patching should really be part of the file-reading code,
+ * but we still get too many unrelated data-corruption crashes otherwise... */
+ if (bmain->versionfile < 250)
+ do_versions_ipos_to_animato(bmain);
+
+ bmain->recovered = 0;
+
+ /* startup.blend or recovered startup */
+ if (is_startup) {
+ bmain->name[0] = '\0';
+ }
+ else if (recover && G.relbase_valid) {
+ /* in case of autosave or quit.blend, use original filename instead
+ * use relbase_valid to make sure the file is saved, else we get <memory2> in the filename */
+ filepath = bfd->filename;
+ bmain->recovered = 1;
+
+ /* these are the same at times, should never copy to the same location */
+ if (bmain->name != filepath)
+ BLI_strncpy(bmain->name, filepath, FILE_MAX);
+ }
+
+ /* baseflags, groups, make depsgraph, etc */
+ /* first handle case if other windows have different scenes visible */
+ if (mode == LOAD_UI) {
+ wmWindowManager *wm = bmain->wm.first;
+
+ if (wm) {
+ for (wmWindow *win = wm->windows.first; win; win = win->next) {
+ if (win->scene && win->scene != curscene) {
+ BKE_scene_set_background(bmain, win->scene);
+ }
+ }
+ }
+ }
+
+ /* Setting scene might require having a dependency graph, with copy on write
+ * we need to make sure we ensure scene has correct color management before
+ * constructing dependency graph.
+ */
+ if (mode != LOAD_UNDO) {
+ IMB_colormanagement_check_file_config(bmain);
+ }
+
+ BKE_scene_set_background(bmain, curscene);
+
+ if (mode != LOAD_UNDO) {
+ /* TODO(sergey): Can this be also move above? */
+ RE_FreeAllPersistentData();
+ }
+
+ MEM_freeN(bfd);
}
static int handle_subversion_warning(Main *main, ReportList *reports)
{
- if (main->minversionfile > BLENDER_VERSION ||
- (main->minversionfile == BLENDER_VERSION &&
- main->minsubversionfile > BLENDER_SUBVERSION))
- {
- BKE_reportf(reports, RPT_ERROR, "File written by newer Blender binary (%d.%d), expect loss of data!",
- main->minversionfile, main->minsubversionfile);
- }
-
- return 1;
+ if (main->minversionfile > BLENDER_VERSION ||
+ (main->minversionfile == BLENDER_VERSION && main->minsubversionfile > BLENDER_SUBVERSION)) {
+ BKE_reportf(reports,
+ RPT_ERROR,
+ "File written by newer Blender binary (%d.%d), expect loss of data!",
+ main->minversionfile,
+ main->minsubversionfile);
+ }
+
+ return 1;
}
-int BKE_blendfile_read(
- bContext *C, const char *filepath,
- const struct BlendFileReadParams *params,
- ReportList *reports)
+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);
+ 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);
}
-bool BKE_blendfile_read_from_memory(
- bContext *C, const void *filebuf, int filelength, bool update_defaults,
- const struct BlendFileReadParams *params,
- ReportList *reports)
+bool BKE_blendfile_read_from_memory(bContext *C,
+ const void *filebuf,
+ int filelength,
+ bool update_defaults,
+ const struct BlendFileReadParams *params,
+ ReportList *reports)
{
- BlendFileData *bfd;
-
- bfd = BLO_read_from_memory(filebuf, filelength, params->skip_flags, reports);
- if (bfd) {
- if (update_defaults)
- BLO_update_defaults_startup_blend(bfd->main, NULL);
- setup_app_data(C, bfd, "<memory2>", params->is_startup, reports);
- }
- else {
- BKE_reports_prepend(reports, "Loading failed: ");
- }
-
- return (bfd != NULL);
+ BlendFileData *bfd;
+
+ bfd = BLO_read_from_memory(filebuf, filelength, params->skip_flags, reports);
+ if (bfd) {
+ if (update_defaults)
+ BLO_update_defaults_startup_blend(bfd->main, NULL);
+ setup_app_data(C, bfd, "<memory2>", params->is_startup, reports);
+ }
+ else {
+ BKE_reports_prepend(reports, "Loading failed: ");
+ }
+
+ return (bfd != NULL);
}
/* memfile is the undo buffer */
-bool BKE_blendfile_read_from_memfile(
- bContext *C, struct MemFile *memfile,
- const struct BlendFileReadParams *params,
- ReportList *reports)
+bool BKE_blendfile_read_from_memfile(bContext *C,
+ struct MemFile *memfile,
+ const struct BlendFileReadParams *params,
+ ReportList *reports)
{
- Main *bmain = CTX_data_main(C);
- BlendFileData *bfd;
-
- bfd = BLO_read_from_memfile(bmain, BKE_main_blendfile_path(bmain), memfile, params->skip_flags, reports);
- if (bfd) {
- /* remove the unused screens and wm */
- while (bfd->main->wm.first)
- BKE_id_free(bfd->main, bfd->main->wm.first);
- while (bfd->main->screens.first)
- BKE_id_free(bfd->main, bfd->main->screens.first);
-
- setup_app_data(C, bfd, "<memory1>", params->is_startup, reports);
- }
- else {
- BKE_reports_prepend(reports, "Loading failed: ");
- }
-
- return (bfd != NULL);
+ Main *bmain = CTX_data_main(C);
+ BlendFileData *bfd;
+
+ bfd = BLO_read_from_memfile(
+ bmain, BKE_main_blendfile_path(bmain), memfile, params->skip_flags, reports);
+ if (bfd) {
+ /* remove the unused screens and wm */
+ while (bfd->main->wm.first)
+ BKE_id_free(bfd->main, bfd->main->wm.first);
+ while (bfd->main->screens.first)
+ BKE_id_free(bfd->main, bfd->main->screens.first);
+
+ setup_app_data(C, bfd, "<memory1>", params->is_startup, reports);
+ }
+ else {
+ BKE_reports_prepend(reports, "Loading failed: ");
+ }
+
+ return (bfd != NULL);
}
/**
@@ -459,85 +460,81 @@ bool BKE_blendfile_read_from_memfile(
*/
void BKE_blendfile_read_make_empty(bContext *C)
{
- Main *bmain = CTX_data_main(C);
- ListBase *lb;
- ID *id;
-
- FOREACH_MAIN_LISTBASE_BEGIN(bmain, lb)
- {
- FOREACH_MAIN_LISTBASE_ID_BEGIN(lb, id)
- {
- if (ELEM(GS(id->name), ID_SCE, ID_SCR, ID_WM, ID_WS)) {
- break;
- }
- BKE_id_delete(bmain, id);
- }
- FOREACH_MAIN_LISTBASE_ID_END;
- }
- FOREACH_MAIN_LISTBASE_END;
+ Main *bmain = CTX_data_main(C);
+ ListBase *lb;
+ ID *id;
+
+ FOREACH_MAIN_LISTBASE_BEGIN(bmain, lb)
+ {
+ FOREACH_MAIN_LISTBASE_ID_BEGIN(lb, id)
+ {
+ if (ELEM(GS(id->name), ID_SCE, ID_SCR, ID_WM, ID_WS)) {
+ break;
+ }
+ BKE_id_delete(bmain, id);
+ }
+ FOREACH_MAIN_LISTBASE_ID_END;
+ }
+ FOREACH_MAIN_LISTBASE_END;
}
/* 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;
+ 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;
}
-
-UserDef *BKE_blendfile_userdef_read_from_memory(
- const void *filebuf, int filelength,
- ReportList *reports)
+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,
- 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);
- }
- else {
- BKE_reports_prepend(reports, "Loading failed: ");
- }
-
- return userdef;
+ BlendFileData *bfd;
+ UserDef *userdef = NULL;
+
+ bfd = BLO_read_from_memory(
+ filebuf, filelength, 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);
+ }
+ else {
+ BKE_reports_prepend(reports, "Loading failed: ");
+ }
+
+ return userdef;
}
-
/**
* Only write the userdef in a .blend
* \return success
*/
bool BKE_blendfile_userdef_write(const char *filepath, ReportList *reports)
{
- Main *mainb = MEM_callocN(sizeof(Main), "empty main");
- bool ok = false;
+ Main *mainb = MEM_callocN(sizeof(Main), "empty main");
+ bool ok = false;
- if (BLO_write_file(mainb, filepath, G_FILE_USERPREFS, reports, NULL)) {
- ok = true;
- }
+ if (BLO_write_file(mainb, filepath, G_FILE_USERPREFS, reports, NULL)) {
+ ok = true;
+ }
- MEM_freeN(mainb);
+ MEM_freeN(mainb);
- return ok;
+ return ok;
}
/**
@@ -549,182 +546,186 @@ bool BKE_blendfile_userdef_write(const char *filepath, ReportList *reports)
*/
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;
+ /* 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;
}
-WorkspaceConfigFileData *BKE_blendfile_workspace_config_read(const char *filepath, const void *filebuf, int filelength, ReportList *reports)
+WorkspaceConfigFileData *BKE_blendfile_workspace_config_read(const char *filepath,
+ const void *filebuf,
+ int filelength,
+ ReportList *reports)
{
- BlendFileData *bfd;
- WorkspaceConfigFileData *workspace_config = NULL;
+ BlendFileData *bfd;
+ WorkspaceConfigFileData *workspace_config = NULL;
- if (filepath) {
- bfd = BLO_read_from_file(filepath, BLO_READ_SKIP_USERDEF, reports);
- }
- else {
- bfd = BLO_read_from_memory(filebuf, filelength, BLO_READ_SKIP_USERDEF, reports);
- }
+ if (filepath) {
+ bfd = BLO_read_from_file(filepath, BLO_READ_SKIP_USERDEF, reports);
+ }
+ else {
+ bfd = BLO_read_from_memory(filebuf, filelength, BLO_READ_SKIP_USERDEF, reports);
+ }
- if (bfd) {
- workspace_config = MEM_mallocN(sizeof(*workspace_config), __func__);
- workspace_config->main = bfd->main;
- workspace_config->workspaces = bfd->main->workspaces;
+ if (bfd) {
+ workspace_config = MEM_mallocN(sizeof(*workspace_config), __func__);
+ workspace_config->main = bfd->main;
+ workspace_config->workspaces = bfd->main->workspaces;
- MEM_freeN(bfd);
- }
+ MEM_freeN(bfd);
+ }
- return workspace_config;
+ return workspace_config;
}
bool BKE_blendfile_workspace_config_write(Main *bmain, const char *filepath, ReportList *reports)
{
- int fileflags = G.fileflags & ~(G_FILE_NO_UI | G_FILE_HISTORY);
- bool retval = false;
+ int fileflags = G.fileflags & ~(G_FILE_NO_UI | G_FILE_HISTORY);
+ bool retval = false;
- BKE_blendfile_write_partial_begin(bmain);
+ BKE_blendfile_write_partial_begin(bmain);
- for (WorkSpace *workspace = bmain->workspaces.first; workspace; workspace = workspace->id.next) {
- BKE_blendfile_write_partial_tag_ID(&workspace->id, true);
- }
+ for (WorkSpace *workspace = bmain->workspaces.first; workspace; workspace = workspace->id.next) {
+ BKE_blendfile_write_partial_tag_ID(&workspace->id, true);
+ }
- if (BKE_blendfile_write_partial(bmain, filepath, fileflags, reports)) {
- retval = true;
- }
+ if (BKE_blendfile_write_partial(bmain, filepath, fileflags, reports)) {
+ retval = true;
+ }
- BKE_blendfile_write_partial_end(bmain);
+ BKE_blendfile_write_partial_end(bmain);
- return retval;
+ return retval;
}
void BKE_blendfile_workspace_config_data_free(WorkspaceConfigFileData *workspace_config)
{
- BKE_main_free(workspace_config->main);
- MEM_freeN(workspace_config);
+ BKE_main_free(workspace_config->main);
+ MEM_freeN(workspace_config);
}
/** \} */
-
/* -------------------------------------------------------------------- */
/** \name Partial `.blend` file save.
* \{ */
void BKE_blendfile_write_partial_begin(Main *bmain_src)
{
- BKE_main_id_tag_all(bmain_src, LIB_TAG_NEED_EXPAND | LIB_TAG_DOIT, false);
+ BKE_main_id_tag_all(bmain_src, LIB_TAG_NEED_EXPAND | LIB_TAG_DOIT, false);
}
void BKE_blendfile_write_partial_tag_ID(ID *id, bool set)
{
- if (set) {
- id->tag |= LIB_TAG_NEED_EXPAND | LIB_TAG_DOIT;
- }
- else {
- id->tag &= ~(LIB_TAG_NEED_EXPAND | LIB_TAG_DOIT);
- }
+ if (set) {
+ id->tag |= LIB_TAG_NEED_EXPAND | LIB_TAG_DOIT;
+ }
+ else {
+ id->tag &= ~(LIB_TAG_NEED_EXPAND | LIB_TAG_DOIT);
+ }
}
static void blendfile_write_partial_cb(void *UNUSED(handle), Main *UNUSED(bmain), void *vid)
{
- if (vid) {
- ID *id = vid;
- /* only tag for need-expand if not done, prevents eternal loops */
- if ((id->tag & LIB_TAG_DOIT) == 0)
- id->tag |= LIB_TAG_NEED_EXPAND | LIB_TAG_DOIT;
-
- if (id->lib && (id->lib->id.tag & LIB_TAG_DOIT) == 0)
- id->lib->id.tag |= LIB_TAG_DOIT;
- }
+ if (vid) {
+ ID *id = vid;
+ /* only tag for need-expand if not done, prevents eternal loops */
+ if ((id->tag & LIB_TAG_DOIT) == 0)
+ id->tag |= LIB_TAG_NEED_EXPAND | LIB_TAG_DOIT;
+
+ if (id->lib && (id->lib->id.tag & LIB_TAG_DOIT) == 0)
+ id->lib->id.tag |= LIB_TAG_DOIT;
+ }
}
/**
* \return Success.
*/
-bool BKE_blendfile_write_partial(
- Main *bmain_src, const char *filepath, const int write_flags, ReportList *reports)
+bool BKE_blendfile_write_partial(Main *bmain_src,
+ const char *filepath,
+ const int write_flags,
+ ReportList *reports)
{
- Main *bmain_dst = MEM_callocN(sizeof(Main), "copybuffer");
- ListBase *lbarray_dst[MAX_LIBARRAY], *lbarray_src[MAX_LIBARRAY];
- int a, retval;
-
- void *path_list_backup = NULL;
- const int path_list_flag = (BKE_BPATH_TRAVERSE_SKIP_LIBRARY | BKE_BPATH_TRAVERSE_SKIP_MULTIFILE);
-
- /* This is needed to be able to load that file as a real one later
- * (otherwise main->name will not be set at read time). */
- BLI_strncpy(bmain_dst->name, bmain_src->name, sizeof(bmain_dst->name));
-
- BLO_main_expander(blendfile_write_partial_cb);
- BLO_expand_main(NULL, bmain_src);
-
- /* move over all tagged blocks */
- set_listbasepointers(bmain_src, lbarray_src);
- a = set_listbasepointers(bmain_dst, lbarray_dst);
- while (a--) {
- ID *id, *nextid;
- ListBase *lb_dst = lbarray_dst[a], *lb_src = lbarray_src[a];
-
- for (id = lb_src->first; id; id = nextid) {
- nextid = id->next;
- if (id->tag & LIB_TAG_DOIT) {
- BLI_remlink(lb_src, id);
- BLI_addtail(lb_dst, id);
- }
- }
- }
-
- /* Backup paths because remap relative will overwrite them.
- *
- * NOTE: we do this only on the list of datablocks that we are writing
- * because the restored full list is not guaranteed to be in the same
- * order as before, as expected by BKE_bpath_list_restore.
- *
- * This happens because id_sort_by_name does not take into account
- * string case or the library name, so the order is not strictly
- * defined for two linked datablocks with the same name! */
- if (write_flags & G_FILE_RELATIVE_REMAP) {
- path_list_backup = BKE_bpath_list_backup(bmain_dst, path_list_flag);
- }
-
- /* save the buffer */
- retval = BLO_write_file(bmain_dst, filepath, write_flags, reports, NULL);
-
- if (path_list_backup) {
- BKE_bpath_list_restore(bmain_dst, path_list_flag, path_list_backup);
- BKE_bpath_list_free(path_list_backup);
- }
-
- /* move back the main, now sorted again */
- set_listbasepointers(bmain_src, lbarray_dst);
- a = set_listbasepointers(bmain_dst, lbarray_src);
- while (a--) {
- ID *id;
- ListBase *lb_dst = lbarray_dst[a], *lb_src = lbarray_src[a];
-
- while ((id = BLI_pophead(lb_src))) {
- BLI_addtail(lb_dst, id);
- id_sort_by_name(lb_dst, id);
- }
- }
-
- MEM_freeN(bmain_dst);
-
- return retval;
+ Main *bmain_dst = MEM_callocN(sizeof(Main), "copybuffer");
+ ListBase *lbarray_dst[MAX_LIBARRAY], *lbarray_src[MAX_LIBARRAY];
+ int a, retval;
+
+ void *path_list_backup = NULL;
+ const int path_list_flag = (BKE_BPATH_TRAVERSE_SKIP_LIBRARY | BKE_BPATH_TRAVERSE_SKIP_MULTIFILE);
+
+ /* This is needed to be able to load that file as a real one later
+ * (otherwise main->name will not be set at read time). */
+ BLI_strncpy(bmain_dst->name, bmain_src->name, sizeof(bmain_dst->name));
+
+ BLO_main_expander(blendfile_write_partial_cb);
+ BLO_expand_main(NULL, bmain_src);
+
+ /* move over all tagged blocks */
+ set_listbasepointers(bmain_src, lbarray_src);
+ a = set_listbasepointers(bmain_dst, lbarray_dst);
+ while (a--) {
+ ID *id, *nextid;
+ ListBase *lb_dst = lbarray_dst[a], *lb_src = lbarray_src[a];
+
+ for (id = lb_src->first; id; id = nextid) {
+ nextid = id->next;
+ if (id->tag & LIB_TAG_DOIT) {
+ BLI_remlink(lb_src, id);
+ BLI_addtail(lb_dst, id);
+ }
+ }
+ }
+
+ /* Backup paths because remap relative will overwrite them.
+ *
+ * NOTE: we do this only on the list of datablocks that we are writing
+ * because the restored full list is not guaranteed to be in the same
+ * order as before, as expected by BKE_bpath_list_restore.
+ *
+ * This happens because id_sort_by_name does not take into account
+ * string case or the library name, so the order is not strictly
+ * defined for two linked datablocks with the same name! */
+ if (write_flags & G_FILE_RELATIVE_REMAP) {
+ path_list_backup = BKE_bpath_list_backup(bmain_dst, path_list_flag);
+ }
+
+ /* save the buffer */
+ retval = BLO_write_file(bmain_dst, filepath, write_flags, reports, NULL);
+
+ if (path_list_backup) {
+ BKE_bpath_list_restore(bmain_dst, path_list_flag, path_list_backup);
+ BKE_bpath_list_free(path_list_backup);
+ }
+
+ /* move back the main, now sorted again */
+ set_listbasepointers(bmain_src, lbarray_dst);
+ a = set_listbasepointers(bmain_dst, lbarray_src);
+ while (a--) {
+ ID *id;
+ ListBase *lb_dst = lbarray_dst[a], *lb_src = lbarray_src[a];
+
+ while ((id = BLI_pophead(lb_src))) {
+ BLI_addtail(lb_dst, id);
+ id_sort_by_name(lb_dst, id);
+ }
+ }
+
+ MEM_freeN(bmain_dst);
+
+ return retval;
}
void BKE_blendfile_write_partial_end(Main *bmain_src)
{
- BKE_main_id_tag_all(bmain_src, LIB_TAG_NEED_EXPAND | LIB_TAG_DOIT, false);
+ BKE_main_id_tag_all(bmain_src, LIB_TAG_NEED_EXPAND | LIB_TAG_DOIT, false);
}
/** \} */