Files
test2/source/blender/blenkernel/intern/blendfile.cc

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

2145 lines
75 KiB
C++
Raw Normal View History

/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: GPL-2.0-or-later */
/** \file
* \ingroup bke
*
* High level `.blend` file read/write,
* and functions for writing *partial* files (only selected data-blocks).
*/
#include <cstdlib>
#include <cstring>
#include "CLG_log.h"
#include "MEM_guardedalloc.h"
#include "DNA_scene_types.h"
#include "DNA_screen_types.h"
#include "DNA_space_types.h"
Main Workspace Integration This commit does the main integration of workspaces, which is a design we agreed on during the 2.8 UI workshop (see https://wiki.blender.org/index.php/Dev:2.8/UI/Workshop_Writeup) Workspaces should generally be stable, I'm not aware of any remaining bugs (or I've forgotten them :) ). If you find any, let me know! (Exception: mode switching button might get out of sync with actual mode in some cases, would consider that a limitation/ToDo. Needs to be resolved at some point.) == Main Changes/Features * Introduces the new Workspaces as data-blocks. * Allow storing a number of custom workspaces as part of the user configuration. Needs further work to allow adding and deleting individual workspaces. * Bundle a default workspace configuration with Blender (current screen-layouts converted to workspaces). * Pressing button to add a workspace spawns a menu to select between "Duplicate Current" and the workspaces from the user configuration. If no workspaces are stored in the user configuration, the default workspaces are listed instead. * Store screen-layouts (`bScreen`) per workspace. * Store an active screen-layout per workspace. Changing the workspace will enable this layout. * Store active mode in workspace. Changing the workspace will also enter the mode of the new workspace. (Note that we still store the active mode in the object, moving this completely to workspaces is a separate project.) * Store an active render layer per workspace. * Moved mode switch from 3D View header to Info Editor header. * Store active scene in window (not directly workspace related, but overlaps quite a bit). * Removed 'Use Global Scene' User Preference option. * Compatibility with old files - a new workspace is created for every screen-layout of old files. Old Blender versions should be able to read files saved with workspace support as well. * Default .blend only contains one workspace ("General"). * Support appending workspaces. Opening files without UI and commandline rendering should work fine. Note that the UI is temporary! We plan to introduce a new global topbar that contains the workspace options and tabs for switching workspaces. == Technical Notes * Workspaces are data-blocks. * Adding and removing `bScreen`s should be done through `ED_workspace_layout` API now. * A workspace can be active in multiple windows at the same time. * The mode menu (which is now in the Info Editor header) doesn't display "Grease Pencil Edit" mode anymore since its availability depends on the active editor. Will be fixed by making Grease Pencil an own object type (as planned). * The button to change the active workspace object mode may get out of sync with the mode of the active object. Will either be resolved by moving mode out of object data, or we'll disable workspace modes again (there's a `#define USE_WORKSPACE_MODE` for that). * Screen-layouts (`bScreen`) are IDs and thus stored in a main list-base. Had to add a wrapper `WorkSpaceLayout` so we can store them in a list-base within workspaces, too. On the long run we could completely replace `bScreen` by workspace structs. * `WorkSpace` types use some special compiler trickery to allow marking structs and struct members as private. BKE_workspace API should be used for accessing those. * Added scene operators `SCENE_OT_`. Was previously done through screen operators. == BPY API Changes * Removed `Screen.scene`, added `Window.scene` * Removed `UserPreferencesView.use_global_scene` * Added `Context.workspace`, `Window.workspace` and `BlendData.workspaces` * Added `bpy.types.WorkSpace` containing `screens`, `object_mode` and `render_layer` * Added Screen.layout_name for the layout name that'll be displayed in the UI (may differ from internal name) == What's left? * There are a few open design questions (T50521). We should find the needed answers and implement them. * Allow adding and removing individual workspaces from workspace configuration (needs UI design). * Get the override system ready and support overrides per workspace. * Support custom UI setups as part of workspaces (hidden panels, hidden buttons, customizable toolbars, etc). * Allow enabling add-ons per workspace. * Support custom workspace keymaps. * Remove special exception for workspaces in linking code (so they're always appended, never linked). Depends on a few things, so best to solve later. * Get the topbar done. * Workspaces need a proper icon, current one is just a placeholder :) Reviewed By: campbellbarton, mont29 Tags: #user_interface, #bf_blender_2.8 Maniphest Tasks: T50521 Differential Revision: https://developer.blender.org/D2451
2017-06-01 19:56:58 +02:00
#include "DNA_workspace_types.h"
#include "BLI_fileops.h"
#include "BLI_function_ref.hh"
#include "BLI_listbase.h"
#include "BLI_path_utils.hh"
#include "BLI_string.h"
#include "BLI_system.h"
#include "BLI_time.h"
#include "BLI_utildefines.h"
#include "BLI_vector_set.hh"
#include "BLT_translation.hh"
2024-01-18 22:50:23 +02:00
#include "IMB_colormanagement.hh"
#include "BKE_addon.h"
#include "BKE_appdir.hh"
#include "BKE_blender.hh"
#include "BKE_blender_version.h"
#include "BKE_blendfile.hh"
#include "BKE_bpath.hh"
#include "BKE_colorband.hh"
#include "BKE_context.hh"
#include "BKE_global.hh"
#include "BKE_idtype.hh"
2024-01-23 15:18:09 -05:00
#include "BKE_layer.hh"
2024-01-15 12:44:04 -05:00
#include "BKE_lib_id.hh"
#include "BKE_lib_override.hh"
#include "BKE_lib_query.hh"
#include "BKE_lib_remap.hh"
#include "BKE_main.hh"
#include "BKE_main_idmap.hh"
#include "BKE_main_namemap.hh"
#include "BKE_preferences.h"
#include "BKE_report.hh"
#include "BKE_scene.hh"
#include "BKE_screen.hh"
#include "BKE_studiolight.h"
2024-01-15 12:26:09 -05:00
#include "BKE_undo_system.hh"
2024-04-12 17:03:18 -04:00
#include "BKE_workspace.hh"
#include "BLO_read_write.hh"
#include "BLO_readfile.hh"
#include "BLO_userdef_default.h"
#include "BLO_writefile.hh"
#include "RE_pipeline.h"
#ifdef WITH_PYTHON
# include "BPY_extern.hh"
#endif
using namespace blender::bke;
/* -------------------------------------------------------------------- */
/** \name Blend/Library Paths
* \{ */
bool BKE_blendfile_extension_check(const char *str)
{
const char *ext_test[4] = {".blend", ".ble", ".blend.gz", nullptr};
return BLI_path_extension_check_array(str, ext_test);
}
bool BKE_blendfile_library_path_explode(const char *path,
char *r_dir,
char **r_group,
char **r_name)
{
/* We might get some data names with slashes,
* so we have to go up in path until we find blend file itself,
* then we know next path item is group, and everything else is data name. */
char *slash = nullptr, *prev_slash = nullptr, c = '\0';
r_dir[0] = '\0';
if (r_group) {
*r_group = nullptr;
}
if (r_name) {
*r_name = nullptr;
}
/* if path leads to an existing directory, we can be sure we're not (in) a library */
if (BLI_is_dir(path)) {
return false;
}
BLI_strncpy(r_dir, path, FILE_MAX_LIBEXTRA);
while ((slash = (char *)BLI_path_slash_rfind(r_dir))) {
char tc = *slash;
*slash = '\0';
if (BKE_blendfile_extension_check(r_dir) && BLI_is_file(r_dir)) {
break;
}
if (STREQ(r_dir, BLO_EMBEDDED_STARTUP_BLEND)) {
break;
}
if (prev_slash) {
*prev_slash = c;
}
prev_slash = slash;
c = tc;
}
if (!slash) {
return false;
}
if (slash[1] != '\0') {
BLI_assert(strlen(slash + 1) < BLO_GROUP_MAX);
if (r_group) {
*r_group = slash + 1;
}
}
if (prev_slash && (prev_slash[1] != '\0')) {
BLI_assert(strlen(prev_slash + 1) < MAX_ID_NAME - 2);
if (r_name) {
*r_name = prev_slash + 1;
}
}
return true;
}
bool BKE_blendfile_is_readable(const char *path, ReportList *reports)
{
BlendFileReadReport readfile_reports;
readfile_reports.reports = reports;
BlendHandle *bh = BLO_blendhandle_from_file(path, &readfile_reports);
if (bh != nullptr) {
BLO_blendhandle_close(bh);
return true;
}
return false;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Blend File IO (High Level)
* \{ */
static bool foreach_path_clean_cb(BPathForeachPathData * /*bpath_data*/,
char *path_dst,
size_t path_dst_maxncpy,
const char *path_src)
{
BLI_strncpy(path_dst, path_src, path_dst_maxncpy);
BLI_path_slash_native(path_dst);
return !STREQ(path_dst, path_src);
}
/* make sure path names are correct for OS */
static void clean_paths(Main *bmain)
{
BPathForeachPathData foreach_path_data{};
foreach_path_data.bmain = bmain;
foreach_path_data.callback_function = foreach_path_clean_cb;
foreach_path_data.flag = BKE_BPATH_FOREACH_PATH_SKIP_MULTIFILE;
foreach_path_data.user_data = nullptr;
BKE_bpath_foreach_path_main(&foreach_path_data);
LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
BLI_path_slash_native(scene->r.pic);
}
}
static bool wm_scene_is_visible(wmWindowManager *wm, Scene *scene)
{
LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
Main Workspace Integration This commit does the main integration of workspaces, which is a design we agreed on during the 2.8 UI workshop (see https://wiki.blender.org/index.php/Dev:2.8/UI/Workshop_Writeup) Workspaces should generally be stable, I'm not aware of any remaining bugs (or I've forgotten them :) ). If you find any, let me know! (Exception: mode switching button might get out of sync with actual mode in some cases, would consider that a limitation/ToDo. Needs to be resolved at some point.) == Main Changes/Features * Introduces the new Workspaces as data-blocks. * Allow storing a number of custom workspaces as part of the user configuration. Needs further work to allow adding and deleting individual workspaces. * Bundle a default workspace configuration with Blender (current screen-layouts converted to workspaces). * Pressing button to add a workspace spawns a menu to select between "Duplicate Current" and the workspaces from the user configuration. If no workspaces are stored in the user configuration, the default workspaces are listed instead. * Store screen-layouts (`bScreen`) per workspace. * Store an active screen-layout per workspace. Changing the workspace will enable this layout. * Store active mode in workspace. Changing the workspace will also enter the mode of the new workspace. (Note that we still store the active mode in the object, moving this completely to workspaces is a separate project.) * Store an active render layer per workspace. * Moved mode switch from 3D View header to Info Editor header. * Store active scene in window (not directly workspace related, but overlaps quite a bit). * Removed 'Use Global Scene' User Preference option. * Compatibility with old files - a new workspace is created for every screen-layout of old files. Old Blender versions should be able to read files saved with workspace support as well. * Default .blend only contains one workspace ("General"). * Support appending workspaces. Opening files without UI and commandline rendering should work fine. Note that the UI is temporary! We plan to introduce a new global topbar that contains the workspace options and tabs for switching workspaces. == Technical Notes * Workspaces are data-blocks. * Adding and removing `bScreen`s should be done through `ED_workspace_layout` API now. * A workspace can be active in multiple windows at the same time. * The mode menu (which is now in the Info Editor header) doesn't display "Grease Pencil Edit" mode anymore since its availability depends on the active editor. Will be fixed by making Grease Pencil an own object type (as planned). * The button to change the active workspace object mode may get out of sync with the mode of the active object. Will either be resolved by moving mode out of object data, or we'll disable workspace modes again (there's a `#define USE_WORKSPACE_MODE` for that). * Screen-layouts (`bScreen`) are IDs and thus stored in a main list-base. Had to add a wrapper `WorkSpaceLayout` so we can store them in a list-base within workspaces, too. On the long run we could completely replace `bScreen` by workspace structs. * `WorkSpace` types use some special compiler trickery to allow marking structs and struct members as private. BKE_workspace API should be used for accessing those. * Added scene operators `SCENE_OT_`. Was previously done through screen operators. == BPY API Changes * Removed `Screen.scene`, added `Window.scene` * Removed `UserPreferencesView.use_global_scene` * Added `Context.workspace`, `Window.workspace` and `BlendData.workspaces` * Added `bpy.types.WorkSpace` containing `screens`, `object_mode` and `render_layer` * Added Screen.layout_name for the layout name that'll be displayed in the UI (may differ from internal name) == What's left? * There are a few open design questions (T50521). We should find the needed answers and implement them. * Allow adding and removing individual workspaces from workspace configuration (needs UI design). * Get the override system ready and support overrides per workspace. * Support custom UI setups as part of workspaces (hidden panels, hidden buttons, customizable toolbars, etc). * Allow enabling add-ons per workspace. * Support custom workspace keymaps. * Remove special exception for workspaces in linking code (so they're always appended, never linked). Depends on a few things, so best to solve later. * Get the topbar done. * Workspaces need a proper icon, current one is just a placeholder :) Reviewed By: campbellbarton, mont29 Tags: #user_interface, #bf_blender_2.8 Maniphest Tasks: T50521 Differential Revision: https://developer.blender.org/D2451
2017-06-01 19:56:58 +02:00
if (win->scene == scene) {
return true;
}
}
return false;
}
static void setup_app_userdef(BlendFileData *bfd)
{
if (bfd->user) {
/* only here free userdef themes... */
BKE_blender_userdef_data_set_and_free(bfd->user);
bfd->user = nullptr;
/* Security issue: any blend file could include a #BLO_CODE_USER block.
*
* Preferences are loaded from #BLENDER_STARTUP_FILE and later on load #BLENDER_USERPREF_FILE,
* to load the preferences defined in the users home directory.
*
* This means we will never accidentally (or maliciously)
* enable scripts auto-execution by loading a `.blend` file. */
U.flag |= USER_SCRIPT_AUTOEXEC_DISABLE;
}
}
2023-06-21 11:28:58 +10:00
/**
* Helper struct to manage IDs that are re-used across blend-file loading (i.e. moved from the old
* Main the new one).
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
*
2023-06-21 11:28:58 +10:00
* NOTE: this is only used when actually loading a real `.blend` file,
* loading of memfile undo steps does not need it.
*/
struct ReuseOldBMainData {
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
Main *new_bmain;
Main *old_bmain;
/** Data generated and used by calling WM code to handle keeping WM and UI IDs as best as
* possible across file reading.
*
* \note May be null in undo (memfile) case. */
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
BlendFileReadWMSetupData *wm_setup_data;
/** Storage for all remapping rules (old_id -> new_id) required by the preservation of old IDs
* into the new Main. */
id::IDRemapper *remapper;
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
bool is_libraries_remapped;
/** Used to find matching IDs by name/lib in new main, to remap ID usages of data ported over
* from old main. */
IDNameLib_Map *id_map;
};
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
2023-07-04 12:27:38 +10:00
/**
* Search for all libraries in `old_bmain` that are also in `new_bmain` (i.e. different Library
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
* IDs having the same absolute filepath), and create a remapping rule for these.
*
* NOTE: The case where the `old_bmain` would be a library in the newly read one is not handled
* here, as it does not create explicit issues. The local data from `old_bmain` is either
* discarded, or added to the `new_bmain` as local data as well. Worst case, there will be a
2023-06-07 21:45:48 +10:00
* double of a linked data as a local one, without any known relationships between them. In
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
* practice, this latter case is not expected to commonly happen.
*/
static id::IDRemapper &reuse_bmain_data_remapper_ensure(ReuseOldBMainData *reuse_data)
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
{
if (reuse_data->is_libraries_remapped) {
return *reuse_data->remapper;
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
}
if (reuse_data->remapper == nullptr) {
reuse_data->remapper = MEM_new<id::IDRemapper>(__func__);
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
}
Main *new_bmain = reuse_data->new_bmain;
Main *old_bmain = reuse_data->old_bmain;
id::IDRemapper &remapper = *reuse_data->remapper;
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
LISTBASE_FOREACH (Library *, old_lib_iter, &old_bmain->libraries) {
/* In case newly opened `new_bmain` is a library of the `old_bmain`, remap it to null, since a
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
* file should never ever have linked data from itself. */
if (STREQ(old_lib_iter->runtime.filepath_abs, new_bmain->filepath)) {
remapper.add(&old_lib_iter->id, nullptr);
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
continue;
}
/* NOTE: Although this is quadratic complexity, it is not expected to be an issue in practice:
* - Files using more than a few tens of libraries are extremely rare.
* - This code is only executed once for every file reading (not on undos).
*/
LISTBASE_FOREACH (Library *, new_lib_iter, &new_bmain->libraries) {
if (!STREQ(old_lib_iter->runtime.filepath_abs, new_lib_iter->runtime.filepath_abs)) {
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
continue;
}
remapper.add(&old_lib_iter->id, &new_lib_iter->id);
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
break;
}
}
reuse_data->is_libraries_remapped = true;
return *reuse_data->remapper;
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
}
static bool reuse_bmain_data_remapper_is_id_remapped(id::IDRemapper &remapper, ID *id)
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
{
IDRemapperApplyResult result = remapper.get_mapping_result(id, ID_REMAP_APPLY_DEFAULT, nullptr);
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
if (ELEM(result, ID_REMAP_RESULT_SOURCE_REMAPPED, ID_REMAP_RESULT_SOURCE_UNASSIGNED)) {
/* ID is already remapped to its matching ID in the new main, or explicitly remapped to null,
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
* nothing else to do here. */
return true;
}
BLI_assert_msg(result != ID_REMAP_RESULT_SOURCE_NOT_MAPPABLE,
"There should never be a non-mappable (i.e. null) input here.");
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
BLI_assert(result == ID_REMAP_RESULT_SOURCE_UNAVAILABLE);
return false;
}
static bool reuse_bmain_move_id(ReuseOldBMainData *reuse_data,
ID *id,
Library *lib,
const bool reuse_existing)
{
id::IDRemapper &remapper = reuse_bmain_data_remapper_ensure(reuse_data);
Main *new_bmain = reuse_data->new_bmain;
Main *old_bmain = reuse_data->old_bmain;
ListBase *new_lb = which_libbase(new_bmain, GS(id->name));
ListBase *old_lb = which_libbase(old_bmain, GS(id->name));
if (reuse_existing) {
/* A 'new' version of the same data may already exist in new_bmain, in the rare case
* that the same asset blend file was linked explicitly into the blend file we are loading.
* Don't move the old linked ID, but remap its usages to the new one instead. */
LISTBASE_FOREACH_BACKWARD (ID *, id_iter, new_lb) {
if (!ELEM(id_iter->lib, id->lib, lib)) {
continue;
}
if (!STREQ(id_iter->name + 2, id->name + 2)) {
continue;
}
remapper.add(id, id_iter);
return false;
}
}
/* If ID is already in the new_bmain, this should not have been called. */
BLI_assert(BLI_findindex(new_lb, id) < 0);
BLI_assert(BLI_findindex(old_lb, id) >= 0);
/* Move from one list to another, and ensure name is valid. */
BLI_remlink_safe(old_lb, id);
BKE_main_namemap_remove_name(old_bmain, id, id->name + 2);
id->lib = lib;
BLI_addtail(new_lb, id);
BKE_id_new_name_validate(
*new_bmain, *new_lb, *id, nullptr, IDNewNameMode::RenameExistingNever, true);
BKE_lib_libblock_session_uid_renew(id);
/* Remap to itself, to avoid re-processing this ID again. */
remapper.add(id, id);
return true;
}
static Library *reuse_bmain_data_dependencies_new_library_get(ReuseOldBMainData *reuse_data,
Library *old_lib)
{
const id::IDRemapper &remapper = reuse_bmain_data_remapper_ensure(reuse_data);
Library *new_lib = old_lib;
IDRemapperApplyResult result = remapper.apply(reinterpret_cast<ID **>(&new_lib),
ID_REMAP_APPLY_DEFAULT);
switch (result) {
case ID_REMAP_RESULT_SOURCE_UNAVAILABLE: {
/* Move library to new bmain.
* There should be no filepath conflicts, as #reuse_bmain_data_remapper_ensure has
* already remapped existing libraries with matching filepath. */
reuse_bmain_move_id(reuse_data, &old_lib->id, nullptr, false);
return old_lib;
}
case ID_REMAP_RESULT_SOURCE_NOT_MAPPABLE: {
BLI_assert_unreachable();
return nullptr;
}
case ID_REMAP_RESULT_SOURCE_REMAPPED: {
/* Already in new bmain, only transfer flags. */
new_lib->runtime.tag |= old_lib->runtime.tag &
(LIBRARY_ASSET_EDITABLE | LIBRARY_ASSET_FILE_WRITABLE);
return new_lib;
}
case ID_REMAP_RESULT_SOURCE_UNASSIGNED: {
/* Happens when the library is the newly opened blend file. */
return nullptr;
}
}
BLI_assert_unreachable();
return nullptr;
}
static int reuse_editable_asset_bmain_data_dependencies_process_cb(
LibraryIDLinkCallbackData *cb_data)
{
ID *id = *cb_data->id_pointer;
if (id == nullptr) {
return IDWALK_RET_NOP;
}
2024-05-23 16:11:19 +02:00
if (GS(id->name) == ID_LI) {
/* Libraries are handled separately. */
return IDWALK_RET_STOP_RECURSION;
}
ReuseOldBMainData *reuse_data = static_cast<ReuseOldBMainData *>(cb_data->user_data);
/* First check if it has already been remapped. */
id::IDRemapper &remapper = reuse_bmain_data_remapper_ensure(reuse_data);
if (reuse_bmain_data_remapper_is_id_remapped(remapper, id)) {
return IDWALK_RET_STOP_RECURSION;
}
if (id->lib == nullptr) {
/* There should be no links to local datablocks from linked editable data. */
remapper.add(id, nullptr);
BLI_assert_unreachable();
return IDWALK_RET_STOP_RECURSION;
}
/* Only preserve specific datablock types. */
if (!ID_TYPE_SUPPORTS_ASSET_EDITABLE(GS(id->name))) {
remapper.add(id, nullptr);
return IDWALK_RET_STOP_RECURSION;
}
/* There may be a new library pointer in new_bmain, matching a library in old_bmain, even
* though pointer values are not the same. So we need to check new linked IDs in new_bmain
* against both potential library pointers. */
Library *old_id_new_lib = reuse_bmain_data_dependencies_new_library_get(reuse_data, id->lib);
/* Happens when the library is the newly opened blend file. */
if (old_id_new_lib == nullptr) {
remapper.add(id, nullptr);
return IDWALK_RET_STOP_RECURSION;
}
/* Move to new main database. */
return reuse_bmain_move_id(reuse_data, id, old_id_new_lib, true) ? IDWALK_RET_STOP_RECURSION :
IDWALK_RET_NOP;
}
static bool reuse_editable_asset_needed(ReuseOldBMainData *reuse_data)
{
Main *old_bmain = reuse_data->old_bmain;
LISTBASE_FOREACH (Library *, lib, &old_bmain->libraries) {
if (lib->runtime.tag & LIBRARY_ASSET_EDITABLE) {
return true;
}
}
return false;
}
/**
* Selectively 'import' data from old Main into new Main, provided it does not conflict with data
* already present in the new Main (name-wise and library-wise).
*
* Dependencies from moved over old data are also imported into the new Main, (unless, in case of
* linked data, a matching linked ID is already available in new Main).
*
* When a conflict is found, usages of the conflicted ID by the old data are stored in the
* `remapper` of `ReuseOldBMainData` to be remapped to the matching data in the new Main later.
*
* NOTE: This function will never remove any original new data from the new Main, it only moves
* (some of) the old data to the new Main.
*/
static void reuse_editable_asset_bmain_data_for_blendfile(ReuseOldBMainData *reuse_data,
const short idcode)
{
Main *new_bmain = reuse_data->new_bmain;
Main *old_bmain = reuse_data->old_bmain;
id::IDRemapper &remapper = reuse_bmain_data_remapper_ensure(reuse_data);
ListBase *old_lb = which_libbase(old_bmain, idcode);
ID *old_id_iter;
FOREACH_MAIN_LISTBASE_ID_BEGIN (old_lb, old_id_iter) {
/* Keep any datablocks from libraries marked as LIBRARY_ASSET_EDITABLE. */
if (!(ID_IS_LINKED(old_id_iter) && old_id_iter->lib->runtime.tag & LIBRARY_ASSET_EDITABLE)) {
continue;
}
Library *old_id_new_lib = reuse_bmain_data_dependencies_new_library_get(reuse_data,
old_id_iter->lib);
/* Happens when the library is the newly opened blend file. */
if (old_id_new_lib == nullptr) {
remapper.add(old_id_iter, nullptr);
continue;
}
if (reuse_bmain_move_id(reuse_data, old_id_iter, old_id_new_lib, true)) {
/* Port over dependencies of re-used ID, unless matching already existing ones in
* new_bmain can be found.
*
* NOTE : No pointers are remapped here, this code only moves dependencies from old_bmain
* to new_bmain if needed, and add necessary remapping rules to the reuse_data.remapper. */
BKE_library_foreach_ID_link(new_bmain,
old_id_iter,
reuse_editable_asset_bmain_data_dependencies_process_cb,
reuse_data,
IDWALK_RECURSE | IDWALK_DO_LIBRARY_POINTER);
}
}
FOREACH_MAIN_LISTBASE_ID_END;
}
/**
* Does a complete replacement of data in `new_bmain` by data from `old_bmain. Original new data
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
* are moved to the `old_bmain`, and will be freed together with it.
*
* WARNING: Currently only expects to work on local data, won't work properly if some of the IDs of
* given type are linked.
*
* NOTE: Unlike with #reuse_editable_asset_bmain_data_for_blendfile, there is no support at all for
* potential dependencies of the IDs moved around. This is not expected to be necessary for the
* current use cases (UI-related IDs).
*/
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
static void swap_old_bmain_data_for_blendfile(ReuseOldBMainData *reuse_data, const short id_code)
{
Main *new_bmain = reuse_data->new_bmain;
Main *old_bmain = reuse_data->old_bmain;
ListBase *new_lb = which_libbase(new_bmain, id_code);
ListBase *old_lb = which_libbase(old_bmain, id_code);
id::IDRemapper &remapper = reuse_bmain_data_remapper_ensure(reuse_data);
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
/* NOTE: Full swapping is only supported for ID types that are assumed to be only local
* data-blocks (like UI-like ones). Otherwise, the swapping could fail in many funny ways. */
BLI_assert(BLI_listbase_is_empty(old_lb) || !ID_IS_LINKED(old_lb->last));
BLI_assert(BLI_listbase_is_empty(new_lb) || !ID_IS_LINKED(new_lb->last));
std::swap(*new_lb, *old_lb);
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
2024-02-22 22:38:55 +11:00
/* TODO: Could add per-IDType control over name-maps clearing, if this becomes a performances
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
* concern. */
BKE_main_namemap_clear(old_bmain);
BKE_main_namemap_clear(new_bmain);
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
/* Original 'new' IDs have been moved into the old listbase and will be discarded (deleted).
* Original 'old' IDs have been moved into the new listbase and are being reused (kept).
* The discarded ones need to be remapped to a matching reused one, based on their names, if
* possible.
*
* Since both lists are ordered, and they are all local, we can do a smart parallel processing of
* both lists here instead of doing complete full list searches. */
ID *discarded_id_iter = static_cast<ID *>(old_lb->first);
ID *reused_id_iter = static_cast<ID *>(new_lb->first);
while (!ELEM(nullptr, discarded_id_iter, reused_id_iter)) {
const int strcmp_result = strcmp(discarded_id_iter->name + 2, reused_id_iter->name + 2);
if (strcmp_result == 0) {
/* Matching IDs, we can remap the discarded 'new' one to the re-used 'old' one. */
remapper.add(discarded_id_iter, reused_id_iter);
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
discarded_id_iter = static_cast<ID *>(discarded_id_iter->next);
reused_id_iter = static_cast<ID *>(reused_id_iter->next);
}
else if (strcmp_result < 0) {
/* No matching reused 'old' ID for this discarded 'new' one. */
remapper.add(discarded_id_iter, nullptr);
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
discarded_id_iter = static_cast<ID *>(discarded_id_iter->next);
}
else {
reused_id_iter = static_cast<ID *>(reused_id_iter->next);
}
}
/* Also remap all remaining non-compared discarded 'new' IDs to null. */
for (; discarded_id_iter != nullptr;
discarded_id_iter = static_cast<ID *>(discarded_id_iter->next))
{
remapper.add(discarded_id_iter, nullptr);
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
}
FOREACH_MAIN_LISTBASE_ID_BEGIN (new_lb, reused_id_iter) {
/* Necessary as all `session_uid` are renewed on blendfile loading. */
BKE_lib_libblock_session_uid_renew(reused_id_iter);
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
/* Ensure that the reused ID is remapped to itself, since it is known to be in the `new_bmain`.
*/
remapper.add_overwrite(reused_id_iter, reused_id_iter);
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
}
FOREACH_MAIN_LISTBASE_ID_END;
}
/**
* Similar to #swap_old_bmain_data_for_blendfile, but with special handling for WM ID. Tightly
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
* related to further WM post-processing from calling WM code (see #WM_file_read and
* #wm_homefile_read_ex).
*/
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
static void swap_wm_data_for_blendfile(ReuseOldBMainData *reuse_data, const bool load_ui)
{
Main *old_bmain = reuse_data->old_bmain;
Main *new_bmain = reuse_data->new_bmain;
ListBase *old_wm_list = &old_bmain->wm;
ListBase *new_wm_list = &new_bmain->wm;
/* Currently there should never be more than one WM in a main. */
BLI_assert(BLI_listbase_count_at_most(new_wm_list, 2) <= 1);
BLI_assert(BLI_listbase_count_at_most(old_wm_list, 2) <= 1);
wmWindowManager *old_wm = static_cast<wmWindowManager *>(old_wm_list->first);
wmWindowManager *new_wm = static_cast<wmWindowManager *>(new_wm_list->first);
if (old_wm == nullptr) {
/* No current (old) WM. Either (new) WM from file is used, or if none, WM code is responsible
* to add a new default WM. Nothing to do here. */
return;
}
/* Current (old) WM, and (new) WM in file, and loading UI: use WM from file, keep old WM around
* for further processing in WM code. */
if (load_ui && new_wm != nullptr) {
/* Support window-manager ID references being held between file load operations by keeping
2023-06-13 14:51:49 -04:00
* #Main.wm.first memory address in-place, while swapping all of its contents.
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
*
* This is needed so items such as key-maps can be held by an add-on,
* without it pointing to invalid memory, see: #86431. */
BLI_remlink(old_wm_list, old_wm);
BLI_remlink(new_wm_list, new_wm);
BKE_lib_id_swap_full(nullptr,
&old_wm->id,
&new_wm->id,
true,
(ID_REMAP_SKIP_NEVER_NULL_USAGE | ID_REMAP_SKIP_UPDATE_TAGGING |
ID_REMAP_SKIP_USER_REFCOUNT | ID_REMAP_FORCE_UI_POINTERS));
/* Not strictly necessary, but helps for readability. */
std::swap<wmWindowManager *>(old_wm, new_wm);
BLI_addhead(new_wm_list, new_wm);
/* Do not add old WM back to `old_bmain`, so that it does not get freed when `old_bmain` is
* freed. Calling WM code will need this old WM to restore some windows etc. data into the
* new WM, and is responsible to free it properly. */
reuse_data->wm_setup_data->old_wm = old_wm;
id::IDRemapper &remapper = reuse_bmain_data_remapper_ensure(reuse_data);
remapper.add(&old_wm->id, &new_wm->id);
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
}
/* Current (old) WM, but no (new) one in file (should only happen when reading pre 2.5 files, no
* WM back then), or not loading UI: Keep current WM. */
else {
swap_old_bmain_data_for_blendfile(reuse_data, ID_WM);
old_wm->init_flag &= ~WM_INIT_FLAG_WINDOW;
reuse_data->wm_setup_data->old_wm = old_wm;
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
}
}
static int swap_old_bmain_data_for_blendfile_dependencies_process_cb(
LibraryIDLinkCallbackData *cb_data)
{
ID *id = *cb_data->id_pointer;
if (id == nullptr) {
return IDWALK_RET_NOP;
}
ReuseOldBMainData *reuse_data = static_cast<ReuseOldBMainData *>(cb_data->user_data);
/* First check if it has already been remapped. */
id::IDRemapper &remapper = reuse_bmain_data_remapper_ensure(reuse_data);
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
if (reuse_bmain_data_remapper_is_id_remapped(remapper, id)) {
return IDWALK_RET_NOP;
}
IDNameLib_Map *id_map = reuse_data->id_map;
BLI_assert(id_map != nullptr);
ID *id_new = BKE_main_idmap_lookup_id(id_map, id);
remapper.add(id, id_new);
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
return IDWALK_RET_NOP;
}
static void swap_old_bmain_data_dependencies_process(ReuseOldBMainData *reuse_data,
const short id_code)
{
Main *new_bmain = reuse_data->new_bmain;
ListBase *new_lb = which_libbase(new_bmain, id_code);
BLI_assert(reuse_data->id_map != nullptr);
ID *new_id_iter;
FOREACH_MAIN_LISTBASE_ID_BEGIN (new_lb, new_id_iter) {
/* Check all ID usages and find a matching new ID to remap them to in `new_bmain` if possible
* (matching by names and libraries).
*
* Note that this call does not do any effective remapping, it only adds required remapping
* operations to the remapper. */
BKE_library_foreach_ID_link(new_bmain,
new_id_iter,
swap_old_bmain_data_for_blendfile_dependencies_process_cb,
reuse_data,
IDWALK_READONLY | IDWALK_INCLUDE_UI | IDWALK_DO_LIBRARY_POINTER);
}
FOREACH_MAIN_LISTBASE_ID_END;
}
static int reuse_bmain_data_invalid_local_usages_fix_cb(LibraryIDLinkCallbackData *cb_data)
{
ID *id = *cb_data->id_pointer;
if (id == nullptr) {
return IDWALK_RET_NOP;
}
/* Embedded data cannot (yet) be fully trusted to have the same lib pointer as their owner ID, so
* for now ignore them. This code should never have anything to fix for them anyway, otherwise
* there is something extremely wrong going on. */
if ((cb_data->cb_flag & (IDWALK_CB_EMBEDDED | IDWALK_CB_EMBEDDED_NOT_OWNING)) != 0) {
return IDWALK_RET_NOP;
}
if (!ID_IS_LINKED(id)) {
ID *owner_id = cb_data->owner_id;
/* Do not allow linked data to use local data. */
if (ID_IS_LINKED(owner_id)) {
if (cb_data->cb_flag & IDWALK_CB_USER) {
id_us_min(id);
}
*cb_data->id_pointer = nullptr;
}
/* Do not allow local liboverride data to use local data as reference. */
else if (ID_IS_OVERRIDE_LIBRARY_REAL(owner_id) &&
&owner_id->override_library->reference == cb_data->id_pointer)
{
if (cb_data->cb_flag & IDWALK_CB_USER) {
id_us_min(id);
}
*cb_data->id_pointer = nullptr;
}
}
return IDWALK_RET_NOP;
}
/**
* Detect and fix invalid usages of locale IDs by linked ones (or as reference of liboverrides).
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
*/
static void reuse_bmain_data_invalid_local_usages_fix(ReuseOldBMainData *reuse_data)
{
Main *new_bmain = reuse_data->new_bmain;
ID *id_iter;
FOREACH_MAIN_ID_BEGIN (new_bmain, id_iter) {
if (!ID_IS_LINKED(id_iter) && !ID_IS_OVERRIDE_LIBRARY_REAL(id_iter)) {
continue;
}
ID *liboverride_reference = ID_IS_OVERRIDE_LIBRARY_REAL(id_iter) ?
id_iter->override_library->reference :
nullptr;
BKE_library_foreach_ID_link(
new_bmain, id_iter, reuse_bmain_data_invalid_local_usages_fix_cb, reuse_data, 0);
/* Liboverrides who lost their reference should not be liboverrides anymore, but regular IDs.
*/
if (ID_IS_OVERRIDE_LIBRARY_REAL(id_iter) &&
id_iter->override_library->reference != liboverride_reference)
{
BKE_lib_override_library_free(&id_iter->override_library, true);
}
}
FOREACH_MAIN_ID_END;
}
/* Post-remapping helpers to ensure validity of the UI data. */
static void view3d_data_consistency_ensure(wmWindow *win, Scene *scene, ViewLayer *view_layer)
{
bScreen *screen = BKE_workspace_active_screen_get(win->workspace_hook);
LISTBASE_FOREACH (ScrArea *, area, &screen->areabase) {
LISTBASE_FOREACH (SpaceLink *, sl, &area->spacedata) {
if (sl->spacetype != SPACE_VIEW3D) {
continue;
}
View3D *v3d = reinterpret_cast<View3D *>(sl);
if (v3d->camera == nullptr || v3d->scenelock) {
v3d->camera = scene->camera;
}
if (v3d->localvd == nullptr) {
continue;
}
if (v3d->localvd->camera == nullptr || v3d->scenelock) {
v3d->localvd->camera = v3d->camera;
}
/* Local-view can become invalid during undo/redo steps, exit it when no valid object could
* be found. */
Base *base;
for (base = static_cast<Base *>(view_layer->object_bases.first); base; base = base->next) {
if (base->local_view_bits & v3d->local_view_uid) {
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
break;
}
}
if (base != nullptr) {
/* The local view3D still has a valid object, nothing else to do. */
continue;
}
/* No valid object found for the local view3D, it has to be cleared off. */
MEM_freeN(v3d->localvd);
v3d->localvd = nullptr;
v3d->local_view_uid = 0;
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
/* Region-base storage is different depending on whether the space is active or not. */
ListBase *regionbase = (sl == area->spacedata.first) ? &area->regionbase : &sl->regionbase;
LISTBASE_FOREACH (ARegion *, region, regionbase) {
if (region->regiontype != RGN_TYPE_WINDOW) {
continue;
}
RegionView3D *rv3d = static_cast<RegionView3D *>(region->regiondata);
MEM_SAFE_FREE(rv3d->localvd);
}
}
}
}
static void wm_data_consistency_ensure(wmWindowManager *curwm,
Scene *cur_scene,
ViewLayer *cur_view_layer)
{
/* There may not be any available WM (e.g. when reading `userpref.blend`). */
if (curwm == nullptr) {
return;
}
LISTBASE_FOREACH (wmWindow *, win, &curwm->windows) {
if (win->scene == nullptr) {
win->scene = cur_scene;
}
if (BKE_view_layer_find(win->scene, win->view_layer_name) == nullptr) {
STRNCPY(win->view_layer_name, cur_view_layer->name);
}
view3d_data_consistency_ensure(win, win->scene, cur_view_layer);
}
}
/**
* This function runs after loading blend-file data and is responsible
* for setting up the context (the active view-layer, scene & work-space).
*
* When loading a blend-file without it's UI (#G_FILE_NO_UI),
* the existing screen-data needs to point to the newly loaded blend-file data.
*
* \note this is called on undo so any slow conversion functions here
* should be avoided or check `mode != LOAD_UNDO`.
*
* \param bfd: Blend file data, freed by this function on exit.
*/
static void setup_app_data(bContext *C,
BlendFileData *bfd,
const BlendFileReadParams *params,
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
BlendFileReadWMSetupData *wm_setup_data,
BlendFileReadReport *reports)
{
Main *bmain = G_MAIN;
const bool recover = (G.fileflags & G_FILE_RECOVER_READ) != 0;
enum {
LOAD_UI = 1,
LOAD_UI_OFF,
LOAD_UNDO,
} mode;
if (params->undo_direction != STEP_INVALID) {
BLI_assert(bfd->curscene != nullptr);
mode = LOAD_UNDO;
}
else if (bfd->fileflags & G_FILE_ASSET_EDIT_FILE) {
BKE_report(reports->reports,
RPT_WARNING,
"This file is managed by the asset system, you cannot overwrite it (using \"Save "
"As\" is possible)");
/* From now on the file in memory is a normal file, further saving it will contain a
* window-manager, scene, ... and potentially user created data. Use #Main.is_asset_edit_file
* to detect if saving this file needs extra protections. */
bfd->fileflags &= ~G_FILE_ASSET_EDIT_FILE;
BLI_assert(bfd->main->is_asset_edit_file);
mode = LOAD_UI_OFF;
}
/* May happen with library files, loading undo-data should never have a null `curscene`
* (but may have a null `curscreen`). */
else if (ELEM(nullptr, bfd->curscreen, bfd->curscene)) {
BKE_report(reports->reports, RPT_WARNING, "Library file, loading empty scene");
mode = LOAD_UI_OFF;
}
else if (G.fileflags & G_FILE_NO_UI) {
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 file-paths compatible when loading for real (not undo). */
if (mode != LOAD_UNDO) {
clean_paths(bfd->main);
}
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
BLI_assert(BKE_main_namemap_validate(bfd->main));
/* Temporary data to handle swapping around IDs between old and new mains,
* and accumulate the required remapping accordingly. */
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
ReuseOldBMainData reuse_data = {nullptr};
reuse_data.new_bmain = bfd->main;
reuse_data.old_bmain = bmain;
reuse_data.wm_setup_data = wm_setup_data;
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
if (mode != LOAD_UNDO) {
const short ui_id_codes[]{ID_WS, ID_SCR};
/* WM needs special complex handling, regardless of whether UI is kept or loaded from file. */
swap_wm_data_for_blendfile(&reuse_data, mode == LOAD_UI);
if (mode != LOAD_UI) {
/* Re-use UI data from `old_bmain` if keeping existing UI. */
for (auto id_code : ui_id_codes) {
swap_old_bmain_data_for_blendfile(&reuse_data, id_code);
}
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
}
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
/* Needs to happen after all data from `old_bmain` has been moved into new one. */
BLI_assert(reuse_data.id_map == nullptr);
reuse_data.id_map = BKE_main_idmap_create(
reuse_data.new_bmain, true, reuse_data.old_bmain, MAIN_IDMAP_TYPE_NAME);
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
swap_old_bmain_data_dependencies_process(&reuse_data, ID_WM);
if (mode != LOAD_UI) {
for (auto id_code : ui_id_codes) {
swap_old_bmain_data_dependencies_process(&reuse_data, id_code);
}
}
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
BKE_main_idmap_destroy(reuse_data.id_map);
if (!params->is_factory_settings && reuse_editable_asset_needed(&reuse_data)) {
/* Keep linked brush asset data, similar to UI data. Only does a known
* subset know. Could do everything, but that risks dragging along more
* scene data than we want. */
for (short idtype_index = 0; idtype_index < INDEX_ID_MAX; idtype_index++) {
const IDTypeInfo *idtype_info = BKE_idtype_get_info_from_idtype_index(idtype_index);
if (ID_TYPE_SUPPORTS_ASSET_EDITABLE(idtype_info->id_code)) {
reuse_editable_asset_bmain_data_for_blendfile(&reuse_data, idtype_info->id_code);
}
}
}
if (mode != LOAD_UI) {
LISTBASE_FOREACH (bScreen *, screen, &bfd->main->screens) {
BKE_screen_runtime_refresh_for_blendfile(screen);
}
}
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
}
/* 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.
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
*
* This means that users can have 2 or more 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: #43424. */
bool track_undo_scene = false;
/* Always use the Scene and ViewLayer pointers from new file, if possible. */
ViewLayer *cur_view_layer = bfd->cur_view_layer;
Scene *curscene = bfd->curscene;
wmWindow *win = nullptr;
bScreen *curscreen = nullptr;
2023-06-07 21:45:48 +10:00
/* Ensure that there is a valid scene and view-layer. */
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
if (curscene == nullptr) {
curscene = static_cast<Scene *>(bfd->main->scenes.first);
}
/* Empty file, add a scene to make Blender work. */
if (curscene == nullptr) {
curscene = BKE_scene_add(bfd->main, "Empty");
}
if (cur_view_layer == nullptr) {
/* Fallback to the active scene view layer. */
cur_view_layer = BKE_view_layer_default_view(curscene);
}
/* If UI is not loaded when opening actual `.blend` file,
* and always in case of undo MEMFILE reading. */
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
if (mode != LOAD_UI) {
/* Re-use current window and screen. */
Main Workspace Integration This commit does the main integration of workspaces, which is a design we agreed on during the 2.8 UI workshop (see https://wiki.blender.org/index.php/Dev:2.8/UI/Workshop_Writeup) Workspaces should generally be stable, I'm not aware of any remaining bugs (or I've forgotten them :) ). If you find any, let me know! (Exception: mode switching button might get out of sync with actual mode in some cases, would consider that a limitation/ToDo. Needs to be resolved at some point.) == Main Changes/Features * Introduces the new Workspaces as data-blocks. * Allow storing a number of custom workspaces as part of the user configuration. Needs further work to allow adding and deleting individual workspaces. * Bundle a default workspace configuration with Blender (current screen-layouts converted to workspaces). * Pressing button to add a workspace spawns a menu to select between "Duplicate Current" and the workspaces from the user configuration. If no workspaces are stored in the user configuration, the default workspaces are listed instead. * Store screen-layouts (`bScreen`) per workspace. * Store an active screen-layout per workspace. Changing the workspace will enable this layout. * Store active mode in workspace. Changing the workspace will also enter the mode of the new workspace. (Note that we still store the active mode in the object, moving this completely to workspaces is a separate project.) * Store an active render layer per workspace. * Moved mode switch from 3D View header to Info Editor header. * Store active scene in window (not directly workspace related, but overlaps quite a bit). * Removed 'Use Global Scene' User Preference option. * Compatibility with old files - a new workspace is created for every screen-layout of old files. Old Blender versions should be able to read files saved with workspace support as well. * Default .blend only contains one workspace ("General"). * Support appending workspaces. Opening files without UI and commandline rendering should work fine. Note that the UI is temporary! We plan to introduce a new global topbar that contains the workspace options and tabs for switching workspaces. == Technical Notes * Workspaces are data-blocks. * Adding and removing `bScreen`s should be done through `ED_workspace_layout` API now. * A workspace can be active in multiple windows at the same time. * The mode menu (which is now in the Info Editor header) doesn't display "Grease Pencil Edit" mode anymore since its availability depends on the active editor. Will be fixed by making Grease Pencil an own object type (as planned). * The button to change the active workspace object mode may get out of sync with the mode of the active object. Will either be resolved by moving mode out of object data, or we'll disable workspace modes again (there's a `#define USE_WORKSPACE_MODE` for that). * Screen-layouts (`bScreen`) are IDs and thus stored in a main list-base. Had to add a wrapper `WorkSpaceLayout` so we can store them in a list-base within workspaces, too. On the long run we could completely replace `bScreen` by workspace structs. * `WorkSpace` types use some special compiler trickery to allow marking structs and struct members as private. BKE_workspace API should be used for accessing those. * Added scene operators `SCENE_OT_`. Was previously done through screen operators. == BPY API Changes * Removed `Screen.scene`, added `Window.scene` * Removed `UserPreferencesView.use_global_scene` * Added `Context.workspace`, `Window.workspace` and `BlendData.workspaces` * Added `bpy.types.WorkSpace` containing `screens`, `object_mode` and `render_layer` * Added Screen.layout_name for the layout name that'll be displayed in the UI (may differ from internal name) == What's left? * There are a few open design questions (T50521). We should find the needed answers and implement them. * Allow adding and removing individual workspaces from workspace configuration (needs UI design). * Get the override system ready and support overrides per workspace. * Support custom UI setups as part of workspaces (hidden panels, hidden buttons, customizable toolbars, etc). * Allow enabling add-ons per workspace. * Support custom workspace keymaps. * Remove special exception for workspaces in linking code (so they're always appended, never linked). Depends on a few things, so best to solve later. * Get the topbar done. * Workspaces need a proper icon, current one is just a placeholder :) Reviewed By: campbellbarton, mont29 Tags: #user_interface, #bf_blender_2.8 Maniphest Tasks: T50521 Differential Revision: https://developer.blender.org/D2451
2017-06-01 19:56:58 +02:00
win = CTX_wm_window(C);
curscreen = CTX_wm_screen(C);
track_undo_scene = (mode == LOAD_UNDO && curscreen && curscene && bfd->main->wm.first);
if (track_undo_scene) {
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
/* Keep the old (to-be-freed) scene, remapping below will ensure it's remapped to the
* matching new scene if available, or null otherwise, in which case
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
* #wm_data_consistency_ensure will define `curscene` as the active one. */
}
/* Enforce `curscene` to be in current screen. */
else if (win) { /* The window may be null in background-mode. */
Main Workspace Integration This commit does the main integration of workspaces, which is a design we agreed on during the 2.8 UI workshop (see https://wiki.blender.org/index.php/Dev:2.8/UI/Workshop_Writeup) Workspaces should generally be stable, I'm not aware of any remaining bugs (or I've forgotten them :) ). If you find any, let me know! (Exception: mode switching button might get out of sync with actual mode in some cases, would consider that a limitation/ToDo. Needs to be resolved at some point.) == Main Changes/Features * Introduces the new Workspaces as data-blocks. * Allow storing a number of custom workspaces as part of the user configuration. Needs further work to allow adding and deleting individual workspaces. * Bundle a default workspace configuration with Blender (current screen-layouts converted to workspaces). * Pressing button to add a workspace spawns a menu to select between "Duplicate Current" and the workspaces from the user configuration. If no workspaces are stored in the user configuration, the default workspaces are listed instead. * Store screen-layouts (`bScreen`) per workspace. * Store an active screen-layout per workspace. Changing the workspace will enable this layout. * Store active mode in workspace. Changing the workspace will also enter the mode of the new workspace. (Note that we still store the active mode in the object, moving this completely to workspaces is a separate project.) * Store an active render layer per workspace. * Moved mode switch from 3D View header to Info Editor header. * Store active scene in window (not directly workspace related, but overlaps quite a bit). * Removed 'Use Global Scene' User Preference option. * Compatibility with old files - a new workspace is created for every screen-layout of old files. Old Blender versions should be able to read files saved with workspace support as well. * Default .blend only contains one workspace ("General"). * Support appending workspaces. Opening files without UI and commandline rendering should work fine. Note that the UI is temporary! We plan to introduce a new global topbar that contains the workspace options and tabs for switching workspaces. == Technical Notes * Workspaces are data-blocks. * Adding and removing `bScreen`s should be done through `ED_workspace_layout` API now. * A workspace can be active in multiple windows at the same time. * The mode menu (which is now in the Info Editor header) doesn't display "Grease Pencil Edit" mode anymore since its availability depends on the active editor. Will be fixed by making Grease Pencil an own object type (as planned). * The button to change the active workspace object mode may get out of sync with the mode of the active object. Will either be resolved by moving mode out of object data, or we'll disable workspace modes again (there's a `#define USE_WORKSPACE_MODE` for that). * Screen-layouts (`bScreen`) are IDs and thus stored in a main list-base. Had to add a wrapper `WorkSpaceLayout` so we can store them in a list-base within workspaces, too. On the long run we could completely replace `bScreen` by workspace structs. * `WorkSpace` types use some special compiler trickery to allow marking structs and struct members as private. BKE_workspace API should be used for accessing those. * Added scene operators `SCENE_OT_`. Was previously done through screen operators. == BPY API Changes * Removed `Screen.scene`, added `Window.scene` * Removed `UserPreferencesView.use_global_scene` * Added `Context.workspace`, `Window.workspace` and `BlendData.workspaces` * Added `bpy.types.WorkSpace` containing `screens`, `object_mode` and `render_layer` * Added Screen.layout_name for the layout name that'll be displayed in the UI (may differ from internal name) == What's left? * There are a few open design questions (T50521). We should find the needed answers and implement them. * Allow adding and removing individual workspaces from workspace configuration (needs UI design). * Get the override system ready and support overrides per workspace. * Support custom UI setups as part of workspaces (hidden panels, hidden buttons, customizable toolbars, etc). * Allow enabling add-ons per workspace. * Support custom workspace keymaps. * Remove special exception for workspaces in linking code (so they're always appended, never linked). Depends on a few things, so best to solve later. * Get the topbar done. * Workspaces need a proper icon, current one is just a placeholder :) Reviewed By: campbellbarton, mont29 Tags: #user_interface, #bf_blender_2.8 Maniphest Tasks: T50521 Differential Revision: https://developer.blender.org/D2451
2017-06-01 19:56:58 +02:00
win->scene = curscene;
}
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
}
BLI_assert(BKE_main_namemap_validate(bfd->main));
/* Apply remapping of ID pointers caused by re-using part of the data from the 'old' main into
* the new one. */
if (reuse_data.remapper != nullptr) {
/* In undo case all "keeping old data" and remapping logic is now handled
* in file reading code itself, so there should never be any remapping to do here. */
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
BLI_assert(mode != LOAD_UNDO);
/* Handle all pending remapping from swapping old and new IDs around. */
BKE_libblock_remap_multiple_raw(bfd->main,
*reuse_data.remapper,
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
(ID_REMAP_FORCE_UI_POINTERS | ID_REMAP_SKIP_USER_REFCOUNT |
ID_REMAP_SKIP_UPDATE_TAGGING | ID_REMAP_SKIP_USER_CLEAR));
/* Fix potential invalid usages of now-locale-data created by remapping above. Should never
* be needed in undo case, this is to address cases like:
* "opening a blend-file that was a library of the previous opened blend-file". */
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
reuse_bmain_data_invalid_local_usages_fix(&reuse_data);
MEM_delete(reuse_data.remapper);
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
reuse_data.remapper = nullptr;
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
wm_data_consistency_ensure(CTX_wm_manager(C), curscene, cur_view_layer);
}
if (mode == LOAD_UNDO) {
/* It's possible to undo into a time before the scene existed, in this case the window's scene
* will be null. Since it doesn't make sense to remove the window, set it to the current scene.
*
* NOTE: Redo will restore the active scene to the window so a reasonably consistent state
* is maintained. We could do better by keeping a window/scene map for each undo step.
*
* Another source of potential inconsistency is undoing into a step where the active camera
* object does not exist (see e.g. #125636).
*/
wm_data_consistency_ensure(CTX_wm_manager(C), curscene, cur_view_layer);
}
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
BLI_assert(BKE_main_namemap_validate(bfd->main));
if (mode != LOAD_UI) {
Main Workspace Integration This commit does the main integration of workspaces, which is a design we agreed on during the 2.8 UI workshop (see https://wiki.blender.org/index.php/Dev:2.8/UI/Workshop_Writeup) Workspaces should generally be stable, I'm not aware of any remaining bugs (or I've forgotten them :) ). If you find any, let me know! (Exception: mode switching button might get out of sync with actual mode in some cases, would consider that a limitation/ToDo. Needs to be resolved at some point.) == Main Changes/Features * Introduces the new Workspaces as data-blocks. * Allow storing a number of custom workspaces as part of the user configuration. Needs further work to allow adding and deleting individual workspaces. * Bundle a default workspace configuration with Blender (current screen-layouts converted to workspaces). * Pressing button to add a workspace spawns a menu to select between "Duplicate Current" and the workspaces from the user configuration. If no workspaces are stored in the user configuration, the default workspaces are listed instead. * Store screen-layouts (`bScreen`) per workspace. * Store an active screen-layout per workspace. Changing the workspace will enable this layout. * Store active mode in workspace. Changing the workspace will also enter the mode of the new workspace. (Note that we still store the active mode in the object, moving this completely to workspaces is a separate project.) * Store an active render layer per workspace. * Moved mode switch from 3D View header to Info Editor header. * Store active scene in window (not directly workspace related, but overlaps quite a bit). * Removed 'Use Global Scene' User Preference option. * Compatibility with old files - a new workspace is created for every screen-layout of old files. Old Blender versions should be able to read files saved with workspace support as well. * Default .blend only contains one workspace ("General"). * Support appending workspaces. Opening files without UI and commandline rendering should work fine. Note that the UI is temporary! We plan to introduce a new global topbar that contains the workspace options and tabs for switching workspaces. == Technical Notes * Workspaces are data-blocks. * Adding and removing `bScreen`s should be done through `ED_workspace_layout` API now. * A workspace can be active in multiple windows at the same time. * The mode menu (which is now in the Info Editor header) doesn't display "Grease Pencil Edit" mode anymore since its availability depends on the active editor. Will be fixed by making Grease Pencil an own object type (as planned). * The button to change the active workspace object mode may get out of sync with the mode of the active object. Will either be resolved by moving mode out of object data, or we'll disable workspace modes again (there's a `#define USE_WORKSPACE_MODE` for that). * Screen-layouts (`bScreen`) are IDs and thus stored in a main list-base. Had to add a wrapper `WorkSpaceLayout` so we can store them in a list-base within workspaces, too. On the long run we could completely replace `bScreen` by workspace structs. * `WorkSpace` types use some special compiler trickery to allow marking structs and struct members as private. BKE_workspace API should be used for accessing those. * Added scene operators `SCENE_OT_`. Was previously done through screen operators. == BPY API Changes * Removed `Screen.scene`, added `Window.scene` * Removed `UserPreferencesView.use_global_scene` * Added `Context.workspace`, `Window.workspace` and `BlendData.workspaces` * Added `bpy.types.WorkSpace` containing `screens`, `object_mode` and `render_layer` * Added Screen.layout_name for the layout name that'll be displayed in the UI (may differ from internal name) == What's left? * There are a few open design questions (T50521). We should find the needed answers and implement them. * Allow adding and removing individual workspaces from workspace configuration (needs UI design). * Get the override system ready and support overrides per workspace. * Support custom UI setups as part of workspaces (hidden panels, hidden buttons, customizable toolbars, etc). * Allow enabling add-ons per workspace. * Support custom workspace keymaps. * Remove special exception for workspaces in linking code (so they're always appended, never linked). Depends on a few things, so best to solve later. * Get the topbar done. * Workspaces need a proper icon, current one is just a placeholder :) Reviewed By: campbellbarton, mont29 Tags: #user_interface, #bf_blender_2.8 Maniphest Tasks: T50521 Differential Revision: https://developer.blender.org/D2451
2017-06-01 19:56:58 +02:00
if (win) {
curscene = win->scene;
}
if (track_undo_scene) {
wmWindowManager *wm = static_cast<wmWindowManager *>(bfd->main->wm.first);
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
if (!wm_scene_is_visible(wm, bfd->curscene)) {
curscene = bfd->curscene;
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
if (win) {
win->scene = curscene;
}
Main Workspace Integration This commit does the main integration of workspaces, which is a design we agreed on during the 2.8 UI workshop (see https://wiki.blender.org/index.php/Dev:2.8/UI/Workshop_Writeup) Workspaces should generally be stable, I'm not aware of any remaining bugs (or I've forgotten them :) ). If you find any, let me know! (Exception: mode switching button might get out of sync with actual mode in some cases, would consider that a limitation/ToDo. Needs to be resolved at some point.) == Main Changes/Features * Introduces the new Workspaces as data-blocks. * Allow storing a number of custom workspaces as part of the user configuration. Needs further work to allow adding and deleting individual workspaces. * Bundle a default workspace configuration with Blender (current screen-layouts converted to workspaces). * Pressing button to add a workspace spawns a menu to select between "Duplicate Current" and the workspaces from the user configuration. If no workspaces are stored in the user configuration, the default workspaces are listed instead. * Store screen-layouts (`bScreen`) per workspace. * Store an active screen-layout per workspace. Changing the workspace will enable this layout. * Store active mode in workspace. Changing the workspace will also enter the mode of the new workspace. (Note that we still store the active mode in the object, moving this completely to workspaces is a separate project.) * Store an active render layer per workspace. * Moved mode switch from 3D View header to Info Editor header. * Store active scene in window (not directly workspace related, but overlaps quite a bit). * Removed 'Use Global Scene' User Preference option. * Compatibility with old files - a new workspace is created for every screen-layout of old files. Old Blender versions should be able to read files saved with workspace support as well. * Default .blend only contains one workspace ("General"). * Support appending workspaces. Opening files without UI and commandline rendering should work fine. Note that the UI is temporary! We plan to introduce a new global topbar that contains the workspace options and tabs for switching workspaces. == Technical Notes * Workspaces are data-blocks. * Adding and removing `bScreen`s should be done through `ED_workspace_layout` API now. * A workspace can be active in multiple windows at the same time. * The mode menu (which is now in the Info Editor header) doesn't display "Grease Pencil Edit" mode anymore since its availability depends on the active editor. Will be fixed by making Grease Pencil an own object type (as planned). * The button to change the active workspace object mode may get out of sync with the mode of the active object. Will either be resolved by moving mode out of object data, or we'll disable workspace modes again (there's a `#define USE_WORKSPACE_MODE` for that). * Screen-layouts (`bScreen`) are IDs and thus stored in a main list-base. Had to add a wrapper `WorkSpaceLayout` so we can store them in a list-base within workspaces, too. On the long run we could completely replace `bScreen` by workspace structs. * `WorkSpace` types use some special compiler trickery to allow marking structs and struct members as private. BKE_workspace API should be used for accessing those. * Added scene operators `SCENE_OT_`. Was previously done through screen operators. == BPY API Changes * Removed `Screen.scene`, added `Window.scene` * Removed `UserPreferencesView.use_global_scene` * Added `Context.workspace`, `Window.workspace` and `BlendData.workspaces` * Added `bpy.types.WorkSpace` containing `screens`, `object_mode` and `render_layer` * Added Screen.layout_name for the layout name that'll be displayed in the UI (may differ from internal name) == What's left? * There are a few open design questions (T50521). We should find the needed answers and implement them. * Allow adding and removing individual workspaces from workspace configuration (needs UI design). * Get the override system ready and support overrides per workspace. * Support custom UI setups as part of workspaces (hidden panels, hidden buttons, customizable toolbars, etc). * Allow enabling add-ons per workspace. * Support custom workspace keymaps. * Remove special exception for workspaces in linking code (so they're always appended, never linked). Depends on a few things, so best to solve later. * Get the topbar done. * Workspaces need a proper icon, current one is just a placeholder :) Reviewed By: campbellbarton, mont29 Tags: #user_interface, #bf_blender_2.8 Maniphest Tasks: T50521 Differential Revision: https://developer.blender.org/D2451
2017-06-01 19:56:58 +02:00
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 won't have to handle
* events from multiple screens at once. */
if (curscreen) {
BKE_screen_gizmo_tag_refresh(curscreen);
}
}
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
CTX_data_scene_set(C, curscene);
BLI_assert(BKE_main_namemap_validate(bfd->main));
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
/* This frees the `old_bmain`. */
BKE_blender_globals_main_replace(bfd->main);
bmain = G_MAIN;
bfd->main = nullptr;
CTX_data_main_set(C, bmain);
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
BLI_assert(BKE_main_namemap_validate(bmain));
/* These context data should remain valid if old UI is being re-used. */
if (mode == LOAD_UI) {
/* Setting a window-manger clears all other windowing members (window, screen, area, etc).
* So only do it when effectively loading a new #wmWindowManager
* otherwise just assert that the WM from context is still the same as in `new_bmain`. */
CTX_wm_manager_set(C, static_cast<wmWindowManager *>(bmain->wm.first));
CTX_wm_screen_set(C, bfd->curscreen);
CTX_wm_area_set(C, nullptr);
CTX_wm_region_set(C, nullptr);
CTX_wm_region_popup_set(C, nullptr);
}
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
BLI_assert(CTX_wm_manager(C) == static_cast<wmWindowManager *>(bmain->wm.first));
/* Keep state from preferences. */
const int fileflags_keep = G_FILE_FLAG_ALL_RUNTIME;
G.fileflags = (G.fileflags & fileflags_keep) | (bfd->fileflags & ~fileflags_keep);
/* Special cases, override any #G_FLAG_ALL_READFILE flags from the blend-file. */
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 */
if (CTX_py_init_get(C)) {
BPY_context_update(C);
}
#endif
if (mode != LOAD_UNDO) {
/* Perform complex versioning that involves adding or removing IDs,
* and/or needs to operate over the whole Main data-base
* (versioning done in file reading code only operates on a per-library basis). */
BLO_read_do_version_after_setup(bmain, nullptr, reports);
}
bmain->recovered = false;
/* `startup.blend` or recovered startup. */
if (params->is_startup) {
bmain->filepath[0] = '\0';
}
else if (recover) {
/* In case of auto-save or `quit.blend`, use original file-path instead
* (see also #read_global in `readfile.cc`). */
bmain->recovered = true;
STRNCPY(bmain->filepath, bfd->filepath);
}
/* Base-flags, groups, make depsgraph, etc. */
/* first handle case if other windows have different scenes visible. */
if (mode == LOAD_UI) {
wmWindowManager *wm = static_cast<wmWindowManager *>(bmain->wm.first);
if (wm) {
LISTBASE_FOREACH (wmWindow *, win, &wm->windows) {
Main Workspace Integration This commit does the main integration of workspaces, which is a design we agreed on during the 2.8 UI workshop (see https://wiki.blender.org/index.php/Dev:2.8/UI/Workshop_Writeup) Workspaces should generally be stable, I'm not aware of any remaining bugs (or I've forgotten them :) ). If you find any, let me know! (Exception: mode switching button might get out of sync with actual mode in some cases, would consider that a limitation/ToDo. Needs to be resolved at some point.) == Main Changes/Features * Introduces the new Workspaces as data-blocks. * Allow storing a number of custom workspaces as part of the user configuration. Needs further work to allow adding and deleting individual workspaces. * Bundle a default workspace configuration with Blender (current screen-layouts converted to workspaces). * Pressing button to add a workspace spawns a menu to select between "Duplicate Current" and the workspaces from the user configuration. If no workspaces are stored in the user configuration, the default workspaces are listed instead. * Store screen-layouts (`bScreen`) per workspace. * Store an active screen-layout per workspace. Changing the workspace will enable this layout. * Store active mode in workspace. Changing the workspace will also enter the mode of the new workspace. (Note that we still store the active mode in the object, moving this completely to workspaces is a separate project.) * Store an active render layer per workspace. * Moved mode switch from 3D View header to Info Editor header. * Store active scene in window (not directly workspace related, but overlaps quite a bit). * Removed 'Use Global Scene' User Preference option. * Compatibility with old files - a new workspace is created for every screen-layout of old files. Old Blender versions should be able to read files saved with workspace support as well. * Default .blend only contains one workspace ("General"). * Support appending workspaces. Opening files without UI and commandline rendering should work fine. Note that the UI is temporary! We plan to introduce a new global topbar that contains the workspace options and tabs for switching workspaces. == Technical Notes * Workspaces are data-blocks. * Adding and removing `bScreen`s should be done through `ED_workspace_layout` API now. * A workspace can be active in multiple windows at the same time. * The mode menu (which is now in the Info Editor header) doesn't display "Grease Pencil Edit" mode anymore since its availability depends on the active editor. Will be fixed by making Grease Pencil an own object type (as planned). * The button to change the active workspace object mode may get out of sync with the mode of the active object. Will either be resolved by moving mode out of object data, or we'll disable workspace modes again (there's a `#define USE_WORKSPACE_MODE` for that). * Screen-layouts (`bScreen`) are IDs and thus stored in a main list-base. Had to add a wrapper `WorkSpaceLayout` so we can store them in a list-base within workspaces, too. On the long run we could completely replace `bScreen` by workspace structs. * `WorkSpace` types use some special compiler trickery to allow marking structs and struct members as private. BKE_workspace API should be used for accessing those. * Added scene operators `SCENE_OT_`. Was previously done through screen operators. == BPY API Changes * Removed `Screen.scene`, added `Window.scene` * Removed `UserPreferencesView.use_global_scene` * Added `Context.workspace`, `Window.workspace` and `BlendData.workspaces` * Added `bpy.types.WorkSpace` containing `screens`, `object_mode` and `render_layer` * Added Screen.layout_name for the layout name that'll be displayed in the UI (may differ from internal name) == What's left? * There are a few open design questions (T50521). We should find the needed answers and implement them. * Allow adding and removing individual workspaces from workspace configuration (needs UI design). * Get the override system ready and support overrides per workspace. * Support custom UI setups as part of workspaces (hidden panels, hidden buttons, customizable toolbars, etc). * Allow enabling add-ons per workspace. * Support custom workspace keymaps. * Remove special exception for workspaces in linking code (so they're always appended, never linked). Depends on a few things, so best to solve later. * Get the topbar done. * Workspaces need a proper icon, current one is just a placeholder :) Reviewed By: campbellbarton, mont29 Tags: #user_interface, #bf_blender_2.8 Maniphest Tasks: T50521 Differential Revision: https://developer.blender.org/D2451
2017-06-01 19:56:58 +02:00
if (win->scene && win->scene != curscene) {
BKE_scene_set_background(bmain, win->scene);
}
}
}
}
/* Setting scene might require having a dependency graph, with copy-on-eval
* 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();
}
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
/* Both undo and regular file loading can perform some fairly complex ID manipulation, simpler
* and safer to fully redo reference-counting. This is a relatively cheap process anyway. */
BKE_main_id_refcount_recompute(bmain, false);
BLI_assert(BKE_main_namemap_validate(bmain));
if (mode != LOAD_UNDO && !USER_EXPERIMENTAL_TEST(&U, no_override_auto_resync)) {
reports->duration.lib_overrides_resync = BLI_time_now_seconds();
BKE_lib_override_library_main_resync(
bmain,
curscene,
bfd->cur_view_layer ? bfd->cur_view_layer : BKE_view_layer_default_view(curscene),
reports);
reports->duration.lib_overrides_resync = BLI_time_now_seconds() -
reports->duration.lib_overrides_resync;
/* We need to rebuild some of the deleted override rules (for UI feedback purpose). */
BKE_lib_override_library_main_operations_create(bmain, true, nullptr);
}
/* Now that liboverrides have been resynced and 'irrelevant' missing linked IDs has been removed,
* report actual missing linked data. */
if (mode != LOAD_UNDO) {
ID *id_iter;
int missing_linked_ids_num = 0;
FOREACH_MAIN_ID_BEGIN (bmain, id_iter) {
if (ID_IS_LINKED(id_iter) && (id_iter->tag & ID_TAG_MISSING)) {
missing_linked_ids_num++;
BLO_reportf_wrap(reports,
RPT_INFO,
RPT_("LIB: %s: '%s' missing from '%s', parent '%s'"),
BKE_idtype_idcode_to_name(GS(id_iter->name)),
id_iter->name + 2,
id_iter->lib->runtime.filepath_abs,
id_iter->lib->runtime.parent ?
id_iter->lib->runtime.parent->runtime.filepath_abs :
"<direct>");
}
}
FOREACH_MAIN_ID_END;
reports->count.missing_linked_id = missing_linked_ids_num;
}
}
static void setup_app_blend_file_data(bContext *C,
BlendFileData *bfd,
const BlendFileReadParams *params,
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
BlendFileReadWMSetupData *wm_setup_data,
BlendFileReadReport *reports)
{
if ((params->skip_flags & BLO_READ_SKIP_USERDEF) == 0) {
setup_app_userdef(bfd);
}
if ((params->skip_flags & BLO_READ_SKIP_DATA) == 0) {
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
setup_app_data(C, bfd, params, wm_setup_data, reports);
}
}
static void handle_subversion_warning(Main *main, BlendFileReadReport *reports)
{
if (main->versionfile > BLENDER_FILE_VERSION || (main->versionfile == BLENDER_FILE_VERSION &&
main->subversionfile > BLENDER_FILE_SUBVERSION))
{
BKE_reportf(reports->reports,
RPT_WARNING,
"File written by newer Blender binary (%d.%d), expect loss of data!",
main->versionfile,
main->subversionfile);
}
}
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
void BKE_blendfile_read_setup_readfile(bContext *C,
BlendFileData *bfd,
const BlendFileReadParams *params,
BlendFileReadWMSetupData *wm_setup_data,
BlendFileReadReport *reports,
/* Extra args. */
const bool startup_update_defaults,
const char *startup_app_template)
{
if (bfd->main->is_read_invalid) {
BKE_reports_prepend(reports->reports,
"File could not be read, critical data corruption detected");
BLO_blendfiledata_free(bfd);
return;
}
if (startup_update_defaults) {
if ((params->skip_flags & BLO_READ_SKIP_DATA) == 0) {
BLO_update_defaults_startup_blend(bfd->main, startup_app_template);
}
}
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
setup_app_blend_file_data(C, bfd, params, wm_setup_data, reports);
BLO_blendfiledata_free(bfd);
}
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
void BKE_blendfile_read_setup_undo(bContext *C,
BlendFileData *bfd,
const BlendFileReadParams *params,
BlendFileReadReport *reports)
{
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
BKE_blendfile_read_setup_readfile(C, bfd, params, nullptr, reports, false, nullptr);
}
BlendFileData *BKE_blendfile_read(const char *filepath,
const BlendFileReadParams *params,
BlendFileReadReport *reports)
{
/* Don't print startup file loading. */
if (params->is_startup == false) {
if (!G.quiet) {
printf("Read blend: \"%s\"\n", filepath);
}
}
BlendFileData *bfd = BLO_read_from_file(filepath, eBLOReadSkip(params->skip_flags), reports);
if (bfd && bfd->main->is_read_invalid) {
BLO_blendfiledata_free(bfd);
bfd = nullptr;
}
if (bfd) {
handle_subversion_warning(bfd->main, reports);
}
else {
BKE_reports_prependf(reports->reports, "Loading \"%s\" failed: ", filepath);
}
return bfd;
}
BlendFileData *BKE_blendfile_read_from_memory(const void *file_buf,
int file_buf_size,
const BlendFileReadParams *params,
ReportList *reports)
{
BlendFileData *bfd = BLO_read_from_memory(
file_buf, file_buf_size, eBLOReadSkip(params->skip_flags), reports);
if (bfd && bfd->main->is_read_invalid) {
BLO_blendfiledata_free(bfd);
bfd = nullptr;
}
if (bfd) {
/* Pass. */
}
else {
BKE_reports_prepend(reports, "Loading failed: ");
}
return bfd;
}
BlendFileData *BKE_blendfile_read_from_memfile(Main *bmain,
MemFile *memfile,
const BlendFileReadParams *params,
ReportList *reports)
{
BlendFileData *bfd = BLO_read_from_memfile(
bmain, BKE_main_blendfile_path(bmain), memfile, params, reports);
if (bfd && bfd->main->is_read_invalid) {
BLO_blendfiledata_free(bfd);
bfd = nullptr;
}
Readfile: Refactor several parts of the process This commit affects: * Reading undo steps from memfile (aka 'Global Undo'); * Handling of UI IDs (WindowManager, Workspaces and Screens) when opening a .blend file. While no major changes are expected from a user PoV, there may be some unexpected changes in rare edge-cases. None has been identified so far. Undo step loading should be marginally faster (`setup_app_data` itself is 2-3 times faster, as it does not do remapping anymore, which makes the whole 'read undo step' process about 20% faster - but the most time-consuming step on undo is the depsgraph processing, which remains unchanged here). This commit also solves some bugs (crashes) in some relatively uncommon cases, like e.g. if the WM had an IDProperty pointing at an object and UI is not loaded when opening a new .blend file with the 'Load UI' option enabled (as in previous code on file opening WM ID would never be remapped). From a more technical side, this commit aims mainly at cleaning things up, in preparation for the introduction of new 'no undo, no readfile' type of handling (as part of the Brush Assets project): - Prevent WM code from doing (too much) horrible ID 'management' on its WM when opening a new file. It used to remove current WM from the Main database, store it in a temporary own list, and then free it itself... - Trying to make the complex logic behind WM handling on file reading a bit more easy to follow, at least way more documented in code. - Keep the handling of 'IDs being re-used from old Main' in a single place, as much as possible: -- Readfile code itself in undo case (because it's more efficient, and undo case is in a way simpler than actual .blend file reading case). The whole `blo_lib_link_restore` block of code is also removed. -- (Mostly) setup_app_data code in actual file reading case. - Sanitize the usage of the 'libmap' in readfile code in undo case (waaaaay too many pointers were added there, which was hiding some other issues in the related code, and potentially causing (in rare cases) memory addresses collisions. Pull Request: https://projects.blender.org/blender/blender/pulls/108016
2023-06-05 13:54:49 +02:00
if (bfd == nullptr) {
BKE_reports_prepend(reports, "Loading failed: ");
}
return bfd;
}
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;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Blend File IO (Preferences)
*
* Application Templates
* =====================
*
* When using app-templates, both regular & app-template preferences are used.
* Note that "regular" preferences refers to the preferences used with no app-template is active.
*
* - Reading preferences is performed for both the app-template & regular preferences.
*
* The preferences are merged by using some from the app-template and other settings from the
* regular preferences (add-ons from the app-template for example are used),
* undo-memory uses the regular preferences (for e.g.).
*
* - Writing preferences is performed for both the app-template & regular preferences.
*
* Writing unmodified preference (#U) into the regular preferences
* would loose any settings the app-template overrides.
* To keep default settings the regular preferences is read, add-ons etc temporarily swapped
* into #U for writing, then swapped back out so as not to change the run-time preferences.
*
* \note The function #BKE_blender_userdef_app_template_data_swap determines which settings
* the app-template overrides.
* \{ */
UserDef *BKE_blendfile_userdef_read(const char *filepath, ReportList *reports)
{
BlendFileData *bfd;
UserDef *userdef = nullptr;
BlendFileReadReport blend_file_read_reports{};
blend_file_read_reports.reports = reports;
bfd = BLO_read_from_file(
filepath, BLO_READ_SKIP_ALL & ~BLO_READ_SKIP_USERDEF, &blend_file_read_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 *file_buf,
int file_buf_size,
ReportList *reports)
{
BlendFileData *bfd;
UserDef *userdef = nullptr;
bfd = BLO_read_from_memory(
file_buf, file_buf_size, 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;
}
UserDef *BKE_blendfile_userdef_from_defaults()
{
2023-01-23 02:16:35 +01:00
UserDef *userdef = static_cast<UserDef *>(MEM_callocN(sizeof(UserDef), __func__));
2023-01-23 00:55:15 +01:00
*userdef = blender::dna::shallow_copy(U_default);
/* Add-ons. */
{
const char *addons[] = {
"io_anim_bvh",
"io_curve_svg",
"io_mesh_uv_layout",
"io_scene_fbx",
"io_scene_gltf2",
"cycles",
"pose_library",
"bl_pkg",
};
for (int i = 0; i < ARRAY_SIZE(addons); i++) {
bAddon *addon = BKE_addon_new();
STRNCPY(addon->module, addons[i]);
BLI_addtail(&userdef->addons, addon);
}
}
/* Theme. */
{
bTheme *btheme = static_cast<bTheme *>(MEM_mallocN(sizeof(*btheme), __func__));
memcpy(btheme, &U_theme_default, sizeof(*btheme));
BLI_addtail(&userdef->themes, btheme);
}
#ifdef WITH_PYTHON_SECURITY
/* use alternative setting for security nuts
* otherwise we'd need to patch the binary blob - startup.blend.c */
userdef->flag |= USER_SCRIPT_AUTOEXEC_DISABLE;
#else
userdef->flag &= ~USER_SCRIPT_AUTOEXEC_DISABLE;
#endif
/* System-specific fonts directory.
* NOTE: when not found, leaves as-is (`//` for the blend-file directory). */
if (BKE_appdir_font_folder_default(userdef->fontdir, sizeof(userdef->fontdir))) {
/* Not actually needed, just a convention that directory selection
* adds a trailing slash. */
BLI_path_slash_ensure(userdef->fontdir, sizeof(userdef->fontdir));
}
userdef->memcachelimit = min_ii(BLI_system_memory_max_in_megabytes_int() / 2,
userdef->memcachelimit);
/* Init weight paint range. */
BKE_colorband_init(&userdef->coba_weight, true);
/* Default studio light. */
BKE_studiolight_default(userdef->light_param, userdef->light_ambient);
BKE_preferences_asset_library_default_add(userdef);
BKE_preferences_extension_repo_add_defaults_all(userdef);
{
BKE_preferences_asset_shelf_settings_ensure_catalog_path_enabled(
userdef, "VIEW3D_AST_brush_sculpt", "Brushes/Mesh Sculpt/Cloth");
BKE_preferences_asset_shelf_settings_ensure_catalog_path_enabled(
userdef, "VIEW3D_AST_brush_sculpt", "Brushes/Mesh Sculpt/General");
BKE_preferences_asset_shelf_settings_ensure_catalog_path_enabled(
userdef, "VIEW3D_AST_brush_sculpt", "Brushes/Mesh Sculpt/Paint");
}
return userdef;
}
bool BKE_blendfile_userdef_write(const char *filepath, ReportList *reports)
{
Main *mainb = MEM_cnew<Main>("empty main");
bool ok = false;
BlendFileWriteParams params{};
params.use_userdef = true;
if (BLO_write_file(mainb, filepath, 0, &params, reports)) {
ok = true;
}
MEM_freeN(mainb);
return ok;
}
bool BKE_blendfile_userdef_write_app_template(const char *filepath, ReportList *reports)
{
/* Checking that `filepath` exists is not essential, it just avoids printing a warning that
* the file can't be found. In this case it's not an error - as the file is used if it exists,
* falling back to the defaults.
* If the preferences exists but file reading fails - the file can be assumed corrupt
* so overwriting the file is OK. */
UserDef *userdef_default = BLI_exists(filepath) ? BKE_blendfile_userdef_read(filepath, nullptr) :
nullptr;
if (userdef_default == nullptr) {
userdef_default = BKE_blendfile_userdef_from_defaults();
}
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;
}
bool BKE_blendfile_userdef_write_all(ReportList *reports)
{
char filepath[FILE_MAX];
std::optional<std::string> cfgdir;
bool ok = true;
const bool use_template_userpref = BKE_appdir_app_template_has_userpref(U.app_template);
if ((cfgdir = BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, nullptr))) {
bool ok_write;
BLI_path_join(filepath, sizeof(filepath), cfgdir->c_str(), BLENDER_USERPREF_FILE);
if (!G.quiet) {
printf("Writing userprefs: \"%s\" ", filepath);
}
if (use_template_userpref) {
ok_write = BKE_blendfile_userdef_write_app_template(filepath, reports);
}
else {
ok_write = BKE_blendfile_userdef_write(filepath, reports);
}
if (ok_write) {
if (!G.quiet) {
printf("ok\n");
}
BKE_report(reports, RPT_INFO, "Preferences saved");
}
else {
if (!G.quiet) {
printf("fail\n");
}
ok = false;
BKE_report(reports, RPT_ERROR, "Saving preferences failed");
}
}
else {
BKE_report(reports, RPT_ERROR, "Unable to create userpref path");
}
if (use_template_userpref) {
if ((cfgdir = BKE_appdir_folder_id_create(BLENDER_USER_CONFIG, U.app_template))) {
2023-07-15 15:45:06 +10:00
/* Also save app-template preferences. */
BLI_path_join(filepath, sizeof(filepath), cfgdir->c_str(), BLENDER_USERPREF_FILE);
if (!G.quiet) {
printf("Writing userprefs app-template: \"%s\" ", filepath);
}
if (BKE_blendfile_userdef_write(filepath, reports) != 0) {
if (!G.quiet) {
printf("ok\n");
}
}
else {
if (!G.quiet) {
printf("fail\n");
}
ok = false;
}
}
else {
BKE_report(reports, RPT_ERROR, "Unable to create app-template userpref path");
ok = false;
}
}
if (ok) {
U.runtime.is_dirty = false;
}
return ok;
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Blend File IO (WorkSpace)
* \{ */
WorkspaceConfigFileData *BKE_blendfile_workspace_config_read(const char *filepath,
const void *file_buf,
int file_buf_size,
ReportList *reports)
Main Workspace Integration This commit does the main integration of workspaces, which is a design we agreed on during the 2.8 UI workshop (see https://wiki.blender.org/index.php/Dev:2.8/UI/Workshop_Writeup) Workspaces should generally be stable, I'm not aware of any remaining bugs (or I've forgotten them :) ). If you find any, let me know! (Exception: mode switching button might get out of sync with actual mode in some cases, would consider that a limitation/ToDo. Needs to be resolved at some point.) == Main Changes/Features * Introduces the new Workspaces as data-blocks. * Allow storing a number of custom workspaces as part of the user configuration. Needs further work to allow adding and deleting individual workspaces. * Bundle a default workspace configuration with Blender (current screen-layouts converted to workspaces). * Pressing button to add a workspace spawns a menu to select between "Duplicate Current" and the workspaces from the user configuration. If no workspaces are stored in the user configuration, the default workspaces are listed instead. * Store screen-layouts (`bScreen`) per workspace. * Store an active screen-layout per workspace. Changing the workspace will enable this layout. * Store active mode in workspace. Changing the workspace will also enter the mode of the new workspace. (Note that we still store the active mode in the object, moving this completely to workspaces is a separate project.) * Store an active render layer per workspace. * Moved mode switch from 3D View header to Info Editor header. * Store active scene in window (not directly workspace related, but overlaps quite a bit). * Removed 'Use Global Scene' User Preference option. * Compatibility with old files - a new workspace is created for every screen-layout of old files. Old Blender versions should be able to read files saved with workspace support as well. * Default .blend only contains one workspace ("General"). * Support appending workspaces. Opening files without UI and commandline rendering should work fine. Note that the UI is temporary! We plan to introduce a new global topbar that contains the workspace options and tabs for switching workspaces. == Technical Notes * Workspaces are data-blocks. * Adding and removing `bScreen`s should be done through `ED_workspace_layout` API now. * A workspace can be active in multiple windows at the same time. * The mode menu (which is now in the Info Editor header) doesn't display "Grease Pencil Edit" mode anymore since its availability depends on the active editor. Will be fixed by making Grease Pencil an own object type (as planned). * The button to change the active workspace object mode may get out of sync with the mode of the active object. Will either be resolved by moving mode out of object data, or we'll disable workspace modes again (there's a `#define USE_WORKSPACE_MODE` for that). * Screen-layouts (`bScreen`) are IDs and thus stored in a main list-base. Had to add a wrapper `WorkSpaceLayout` so we can store them in a list-base within workspaces, too. On the long run we could completely replace `bScreen` by workspace structs. * `WorkSpace` types use some special compiler trickery to allow marking structs and struct members as private. BKE_workspace API should be used for accessing those. * Added scene operators `SCENE_OT_`. Was previously done through screen operators. == BPY API Changes * Removed `Screen.scene`, added `Window.scene` * Removed `UserPreferencesView.use_global_scene` * Added `Context.workspace`, `Window.workspace` and `BlendData.workspaces` * Added `bpy.types.WorkSpace` containing `screens`, `object_mode` and `render_layer` * Added Screen.layout_name for the layout name that'll be displayed in the UI (may differ from internal name) == What's left? * There are a few open design questions (T50521). We should find the needed answers and implement them. * Allow adding and removing individual workspaces from workspace configuration (needs UI design). * Get the override system ready and support overrides per workspace. * Support custom UI setups as part of workspaces (hidden panels, hidden buttons, customizable toolbars, etc). * Allow enabling add-ons per workspace. * Support custom workspace keymaps. * Remove special exception for workspaces in linking code (so they're always appended, never linked). Depends on a few things, so best to solve later. * Get the topbar done. * Workspaces need a proper icon, current one is just a placeholder :) Reviewed By: campbellbarton, mont29 Tags: #user_interface, #bf_blender_2.8 Maniphest Tasks: T50521 Differential Revision: https://developer.blender.org/D2451
2017-06-01 19:56:58 +02:00
{
BlendFileData *bfd;
WorkspaceConfigFileData *workspace_config = nullptr;
Main Workspace Integration This commit does the main integration of workspaces, which is a design we agreed on during the 2.8 UI workshop (see https://wiki.blender.org/index.php/Dev:2.8/UI/Workshop_Writeup) Workspaces should generally be stable, I'm not aware of any remaining bugs (or I've forgotten them :) ). If you find any, let me know! (Exception: mode switching button might get out of sync with actual mode in some cases, would consider that a limitation/ToDo. Needs to be resolved at some point.) == Main Changes/Features * Introduces the new Workspaces as data-blocks. * Allow storing a number of custom workspaces as part of the user configuration. Needs further work to allow adding and deleting individual workspaces. * Bundle a default workspace configuration with Blender (current screen-layouts converted to workspaces). * Pressing button to add a workspace spawns a menu to select between "Duplicate Current" and the workspaces from the user configuration. If no workspaces are stored in the user configuration, the default workspaces are listed instead. * Store screen-layouts (`bScreen`) per workspace. * Store an active screen-layout per workspace. Changing the workspace will enable this layout. * Store active mode in workspace. Changing the workspace will also enter the mode of the new workspace. (Note that we still store the active mode in the object, moving this completely to workspaces is a separate project.) * Store an active render layer per workspace. * Moved mode switch from 3D View header to Info Editor header. * Store active scene in window (not directly workspace related, but overlaps quite a bit). * Removed 'Use Global Scene' User Preference option. * Compatibility with old files - a new workspace is created for every screen-layout of old files. Old Blender versions should be able to read files saved with workspace support as well. * Default .blend only contains one workspace ("General"). * Support appending workspaces. Opening files without UI and commandline rendering should work fine. Note that the UI is temporary! We plan to introduce a new global topbar that contains the workspace options and tabs for switching workspaces. == Technical Notes * Workspaces are data-blocks. * Adding and removing `bScreen`s should be done through `ED_workspace_layout` API now. * A workspace can be active in multiple windows at the same time. * The mode menu (which is now in the Info Editor header) doesn't display "Grease Pencil Edit" mode anymore since its availability depends on the active editor. Will be fixed by making Grease Pencil an own object type (as planned). * The button to change the active workspace object mode may get out of sync with the mode of the active object. Will either be resolved by moving mode out of object data, or we'll disable workspace modes again (there's a `#define USE_WORKSPACE_MODE` for that). * Screen-layouts (`bScreen`) are IDs and thus stored in a main list-base. Had to add a wrapper `WorkSpaceLayout` so we can store them in a list-base within workspaces, too. On the long run we could completely replace `bScreen` by workspace structs. * `WorkSpace` types use some special compiler trickery to allow marking structs and struct members as private. BKE_workspace API should be used for accessing those. * Added scene operators `SCENE_OT_`. Was previously done through screen operators. == BPY API Changes * Removed `Screen.scene`, added `Window.scene` * Removed `UserPreferencesView.use_global_scene` * Added `Context.workspace`, `Window.workspace` and `BlendData.workspaces` * Added `bpy.types.WorkSpace` containing `screens`, `object_mode` and `render_layer` * Added Screen.layout_name for the layout name that'll be displayed in the UI (may differ from internal name) == What's left? * There are a few open design questions (T50521). We should find the needed answers and implement them. * Allow adding and removing individual workspaces from workspace configuration (needs UI design). * Get the override system ready and support overrides per workspace. * Support custom UI setups as part of workspaces (hidden panels, hidden buttons, customizable toolbars, etc). * Allow enabling add-ons per workspace. * Support custom workspace keymaps. * Remove special exception for workspaces in linking code (so they're always appended, never linked). Depends on a few things, so best to solve later. * Get the topbar done. * Workspaces need a proper icon, current one is just a placeholder :) Reviewed By: campbellbarton, mont29 Tags: #user_interface, #bf_blender_2.8 Maniphest Tasks: T50521 Differential Revision: https://developer.blender.org/D2451
2017-06-01 19:56:58 +02:00
if (filepath) {
BlendFileReadReport blend_file_read_reports{};
blend_file_read_reports.reports = reports;
bfd = BLO_read_from_file(filepath, BLO_READ_SKIP_USERDEF, &blend_file_read_reports);
}
else {
bfd = BLO_read_from_memory(file_buf, file_buf_size, BLO_READ_SKIP_USERDEF, reports);
}
Main Workspace Integration This commit does the main integration of workspaces, which is a design we agreed on during the 2.8 UI workshop (see https://wiki.blender.org/index.php/Dev:2.8/UI/Workshop_Writeup) Workspaces should generally be stable, I'm not aware of any remaining bugs (or I've forgotten them :) ). If you find any, let me know! (Exception: mode switching button might get out of sync with actual mode in some cases, would consider that a limitation/ToDo. Needs to be resolved at some point.) == Main Changes/Features * Introduces the new Workspaces as data-blocks. * Allow storing a number of custom workspaces as part of the user configuration. Needs further work to allow adding and deleting individual workspaces. * Bundle a default workspace configuration with Blender (current screen-layouts converted to workspaces). * Pressing button to add a workspace spawns a menu to select between "Duplicate Current" and the workspaces from the user configuration. If no workspaces are stored in the user configuration, the default workspaces are listed instead. * Store screen-layouts (`bScreen`) per workspace. * Store an active screen-layout per workspace. Changing the workspace will enable this layout. * Store active mode in workspace. Changing the workspace will also enter the mode of the new workspace. (Note that we still store the active mode in the object, moving this completely to workspaces is a separate project.) * Store an active render layer per workspace. * Moved mode switch from 3D View header to Info Editor header. * Store active scene in window (not directly workspace related, but overlaps quite a bit). * Removed 'Use Global Scene' User Preference option. * Compatibility with old files - a new workspace is created for every screen-layout of old files. Old Blender versions should be able to read files saved with workspace support as well. * Default .blend only contains one workspace ("General"). * Support appending workspaces. Opening files without UI and commandline rendering should work fine. Note that the UI is temporary! We plan to introduce a new global topbar that contains the workspace options and tabs for switching workspaces. == Technical Notes * Workspaces are data-blocks. * Adding and removing `bScreen`s should be done through `ED_workspace_layout` API now. * A workspace can be active in multiple windows at the same time. * The mode menu (which is now in the Info Editor header) doesn't display "Grease Pencil Edit" mode anymore since its availability depends on the active editor. Will be fixed by making Grease Pencil an own object type (as planned). * The button to change the active workspace object mode may get out of sync with the mode of the active object. Will either be resolved by moving mode out of object data, or we'll disable workspace modes again (there's a `#define USE_WORKSPACE_MODE` for that). * Screen-layouts (`bScreen`) are IDs and thus stored in a main list-base. Had to add a wrapper `WorkSpaceLayout` so we can store them in a list-base within workspaces, too. On the long run we could completely replace `bScreen` by workspace structs. * `WorkSpace` types use some special compiler trickery to allow marking structs and struct members as private. BKE_workspace API should be used for accessing those. * Added scene operators `SCENE_OT_`. Was previously done through screen operators. == BPY API Changes * Removed `Screen.scene`, added `Window.scene` * Removed `UserPreferencesView.use_global_scene` * Added `Context.workspace`, `Window.workspace` and `BlendData.workspaces` * Added `bpy.types.WorkSpace` containing `screens`, `object_mode` and `render_layer` * Added Screen.layout_name for the layout name that'll be displayed in the UI (may differ from internal name) == What's left? * There are a few open design questions (T50521). We should find the needed answers and implement them. * Allow adding and removing individual workspaces from workspace configuration (needs UI design). * Get the override system ready and support overrides per workspace. * Support custom UI setups as part of workspaces (hidden panels, hidden buttons, customizable toolbars, etc). * Allow enabling add-ons per workspace. * Support custom workspace keymaps. * Remove special exception for workspaces in linking code (so they're always appended, never linked). Depends on a few things, so best to solve later. * Get the topbar done. * Workspaces need a proper icon, current one is just a placeholder :) Reviewed By: campbellbarton, mont29 Tags: #user_interface, #bf_blender_2.8 Maniphest Tasks: T50521 Differential Revision: https://developer.blender.org/D2451
2017-06-01 19:56:58 +02:00
if (bfd) {
workspace_config = MEM_cnew<WorkspaceConfigFileData>(__func__);
Main Workspace Integration This commit does the main integration of workspaces, which is a design we agreed on during the 2.8 UI workshop (see https://wiki.blender.org/index.php/Dev:2.8/UI/Workshop_Writeup) Workspaces should generally be stable, I'm not aware of any remaining bugs (or I've forgotten them :) ). If you find any, let me know! (Exception: mode switching button might get out of sync with actual mode in some cases, would consider that a limitation/ToDo. Needs to be resolved at some point.) == Main Changes/Features * Introduces the new Workspaces as data-blocks. * Allow storing a number of custom workspaces as part of the user configuration. Needs further work to allow adding and deleting individual workspaces. * Bundle a default workspace configuration with Blender (current screen-layouts converted to workspaces). * Pressing button to add a workspace spawns a menu to select between "Duplicate Current" and the workspaces from the user configuration. If no workspaces are stored in the user configuration, the default workspaces are listed instead. * Store screen-layouts (`bScreen`) per workspace. * Store an active screen-layout per workspace. Changing the workspace will enable this layout. * Store active mode in workspace. Changing the workspace will also enter the mode of the new workspace. (Note that we still store the active mode in the object, moving this completely to workspaces is a separate project.) * Store an active render layer per workspace. * Moved mode switch from 3D View header to Info Editor header. * Store active scene in window (not directly workspace related, but overlaps quite a bit). * Removed 'Use Global Scene' User Preference option. * Compatibility with old files - a new workspace is created for every screen-layout of old files. Old Blender versions should be able to read files saved with workspace support as well. * Default .blend only contains one workspace ("General"). * Support appending workspaces. Opening files without UI and commandline rendering should work fine. Note that the UI is temporary! We plan to introduce a new global topbar that contains the workspace options and tabs for switching workspaces. == Technical Notes * Workspaces are data-blocks. * Adding and removing `bScreen`s should be done through `ED_workspace_layout` API now. * A workspace can be active in multiple windows at the same time. * The mode menu (which is now in the Info Editor header) doesn't display "Grease Pencil Edit" mode anymore since its availability depends on the active editor. Will be fixed by making Grease Pencil an own object type (as planned). * The button to change the active workspace object mode may get out of sync with the mode of the active object. Will either be resolved by moving mode out of object data, or we'll disable workspace modes again (there's a `#define USE_WORKSPACE_MODE` for that). * Screen-layouts (`bScreen`) are IDs and thus stored in a main list-base. Had to add a wrapper `WorkSpaceLayout` so we can store them in a list-base within workspaces, too. On the long run we could completely replace `bScreen` by workspace structs. * `WorkSpace` types use some special compiler trickery to allow marking structs and struct members as private. BKE_workspace API should be used for accessing those. * Added scene operators `SCENE_OT_`. Was previously done through screen operators. == BPY API Changes * Removed `Screen.scene`, added `Window.scene` * Removed `UserPreferencesView.use_global_scene` * Added `Context.workspace`, `Window.workspace` and `BlendData.workspaces` * Added `bpy.types.WorkSpace` containing `screens`, `object_mode` and `render_layer` * Added Screen.layout_name for the layout name that'll be displayed in the UI (may differ from internal name) == What's left? * There are a few open design questions (T50521). We should find the needed answers and implement them. * Allow adding and removing individual workspaces from workspace configuration (needs UI design). * Get the override system ready and support overrides per workspace. * Support custom UI setups as part of workspaces (hidden panels, hidden buttons, customizable toolbars, etc). * Allow enabling add-ons per workspace. * Support custom workspace keymaps. * Remove special exception for workspaces in linking code (so they're always appended, never linked). Depends on a few things, so best to solve later. * Get the topbar done. * Workspaces need a proper icon, current one is just a placeholder :) Reviewed By: campbellbarton, mont29 Tags: #user_interface, #bf_blender_2.8 Maniphest Tasks: T50521 Differential Revision: https://developer.blender.org/D2451
2017-06-01 19:56:58 +02:00
workspace_config->main = bfd->main;
/* Only 2.80+ files have actual workspaces, don't try to use screens
* from older versions. */
if (bfd->main->versionfile >= 280) {
workspace_config->workspaces = bfd->main->workspaces;
}
Main Workspace Integration This commit does the main integration of workspaces, which is a design we agreed on during the 2.8 UI workshop (see https://wiki.blender.org/index.php/Dev:2.8/UI/Workshop_Writeup) Workspaces should generally be stable, I'm not aware of any remaining bugs (or I've forgotten them :) ). If you find any, let me know! (Exception: mode switching button might get out of sync with actual mode in some cases, would consider that a limitation/ToDo. Needs to be resolved at some point.) == Main Changes/Features * Introduces the new Workspaces as data-blocks. * Allow storing a number of custom workspaces as part of the user configuration. Needs further work to allow adding and deleting individual workspaces. * Bundle a default workspace configuration with Blender (current screen-layouts converted to workspaces). * Pressing button to add a workspace spawns a menu to select between "Duplicate Current" and the workspaces from the user configuration. If no workspaces are stored in the user configuration, the default workspaces are listed instead. * Store screen-layouts (`bScreen`) per workspace. * Store an active screen-layout per workspace. Changing the workspace will enable this layout. * Store active mode in workspace. Changing the workspace will also enter the mode of the new workspace. (Note that we still store the active mode in the object, moving this completely to workspaces is a separate project.) * Store an active render layer per workspace. * Moved mode switch from 3D View header to Info Editor header. * Store active scene in window (not directly workspace related, but overlaps quite a bit). * Removed 'Use Global Scene' User Preference option. * Compatibility with old files - a new workspace is created for every screen-layout of old files. Old Blender versions should be able to read files saved with workspace support as well. * Default .blend only contains one workspace ("General"). * Support appending workspaces. Opening files without UI and commandline rendering should work fine. Note that the UI is temporary! We plan to introduce a new global topbar that contains the workspace options and tabs for switching workspaces. == Technical Notes * Workspaces are data-blocks. * Adding and removing `bScreen`s should be done through `ED_workspace_layout` API now. * A workspace can be active in multiple windows at the same time. * The mode menu (which is now in the Info Editor header) doesn't display "Grease Pencil Edit" mode anymore since its availability depends on the active editor. Will be fixed by making Grease Pencil an own object type (as planned). * The button to change the active workspace object mode may get out of sync with the mode of the active object. Will either be resolved by moving mode out of object data, or we'll disable workspace modes again (there's a `#define USE_WORKSPACE_MODE` for that). * Screen-layouts (`bScreen`) are IDs and thus stored in a main list-base. Had to add a wrapper `WorkSpaceLayout` so we can store them in a list-base within workspaces, too. On the long run we could completely replace `bScreen` by workspace structs. * `WorkSpace` types use some special compiler trickery to allow marking structs and struct members as private. BKE_workspace API should be used for accessing those. * Added scene operators `SCENE_OT_`. Was previously done through screen operators. == BPY API Changes * Removed `Screen.scene`, added `Window.scene` * Removed `UserPreferencesView.use_global_scene` * Added `Context.workspace`, `Window.workspace` and `BlendData.workspaces` * Added `bpy.types.WorkSpace` containing `screens`, `object_mode` and `render_layer` * Added Screen.layout_name for the layout name that'll be displayed in the UI (may differ from internal name) == What's left? * There are a few open design questions (T50521). We should find the needed answers and implement them. * Allow adding and removing individual workspaces from workspace configuration (needs UI design). * Get the override system ready and support overrides per workspace. * Support custom UI setups as part of workspaces (hidden panels, hidden buttons, customizable toolbars, etc). * Allow enabling add-ons per workspace. * Support custom workspace keymaps. * Remove special exception for workspaces in linking code (so they're always appended, never linked). Depends on a few things, so best to solve later. * Get the topbar done. * Workspaces need a proper icon, current one is just a placeholder :) Reviewed By: campbellbarton, mont29 Tags: #user_interface, #bf_blender_2.8 Maniphest Tasks: T50521 Differential Revision: https://developer.blender.org/D2451
2017-06-01 19:56:58 +02:00
MEM_freeN(bfd);
}
return workspace_config;
}
void BKE_blendfile_workspace_config_data_free(WorkspaceConfigFileData *workspace_config)
{
BKE_main_free(workspace_config->main);
MEM_freeN(workspace_config);
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Blend File Write (Partial)
* \{ */
static CLG_LogRef LOG_PARTIALWRITE = {"bke.blendfile.partial_write"};
namespace blender::bke::blendfile {
PartialWriteContext::PartialWriteContext(StringRefNull reference_root_filepath)
: reference_root_filepath_(reference_root_filepath)
{
BKE_main_init(this->bmain);
if (!reference_root_filepath_.empty()) {
STRNCPY(this->bmain.filepath, reference_root_filepath_.c_str());
}
/* Only for IDs matching existing data in current G_MAIN. */
matching_uid_map_ = BKE_main_idmap_create(&this->bmain, false, nullptr, MAIN_IDMAP_TYPE_UID);
/* For all IDs existing in the context. */
this->bmain.id_map = BKE_main_idmap_create(
&this->bmain, false, nullptr, MAIN_IDMAP_TYPE_UID | MAIN_IDMAP_TYPE_NAME);
};
PartialWriteContext::~PartialWriteContext()
{
BKE_main_idmap_destroy(matching_uid_map_);
BLI_assert(this->bmain.next == nullptr);
BKE_main_destroy(this->bmain);
};
void PartialWriteContext::preempt_session_uid(ID *ctx_id, uint session_uid)
{
/* If there is already an existing ID in the 'matching' set with that UID, it should be the same
* as the given ctx_id. */
ID *matching_ctx_id = BKE_main_idmap_lookup_uid(matching_uid_map_, session_uid);
if (matching_ctx_id == ctx_id) {
/* That ID has already been added to the context, nothing to do. */
BLI_assert(matching_ctx_id->session_uid == session_uid);
return;
}
if (matching_ctx_id != nullptr) {
/* Another ID in the context, who has a matching ID in current G_MAIN, is sharing the same
* session UID. This marks a critical corruption somewhere! */
CLOG_FATAL(
&LOG_PARTIALWRITE,
"Different matching IDs sharing the same session UID in the partial write context.");
return;
}
/* No ID with this session UID in the context, who's matching a current ID in G_MAIN. Check if a
* non-matching context ID is already using that UID, if yes, regenerate a new one for it, such
* that given `ctx_id` can use the desired UID. */
/* NOTE: In theory, there should never be any session uid collision currently, since these are
* generated session-wide, regardless of the type/source of the IDs. */
matching_ctx_id = BKE_main_idmap_lookup_uid(this->bmain.id_map, session_uid);
BLI_assert(matching_ctx_id != ctx_id);
if (matching_ctx_id) {
CLOG_INFO(&LOG_PARTIALWRITE,
3,
"Non-matching IDs sharing the same session UID in the partial write context.");
BKE_main_idmap_remove_id(this->bmain.id_map, matching_ctx_id);
/* FIXME: Allow #BKE_lib_libblock_session_uid_renew to work with temp IDs? */
matching_ctx_id->tag &= ~ID_TAG_TEMP_MAIN;
BKE_lib_libblock_session_uid_renew(matching_ctx_id);
matching_ctx_id->tag |= ID_TAG_TEMP_MAIN;
BKE_main_idmap_insert_id(this->bmain.id_map, matching_ctx_id);
BLI_assert(BKE_main_idmap_lookup_uid(this->bmain.id_map, session_uid) == nullptr);
}
ctx_id->session_uid = session_uid;
}
void PartialWriteContext::process_added_id(ID *ctx_id,
const PartialWriteContext::IDAddOperations operations)
{
const bool set_fake_user = (operations & SET_FAKE_USER) != 0;
const bool set_clipboard_mark = (operations & SET_CLIPBOARD_MARK) != 0;
if (set_fake_user) {
id_fake_user_set(ctx_id);
}
else {
/* NOTE: Using this tag will ensure that this ID is written on disk in current state (current
* context session). However, reloading the blendfile will clear this tag. */
id_us_ensure_real(ctx_id);
}
if (set_clipboard_mark) {
ctx_id->flag |= ID_FLAG_CLIPBOARD_MARK;
}
}
ID *PartialWriteContext::id_add_copy(const ID *id, const bool regenerate_session_uid)
{
ID *ctx_root_id = nullptr;
BLI_assert(BKE_main_idmap_lookup_uid(matching_uid_map_, id->session_uid) == nullptr);
ctx_root_id = BKE_id_copy_in_lib(nullptr,
id->lib,
id,
nullptr,
nullptr,
(LIB_ID_CREATE_NO_MAIN | LIB_ID_CREATE_NO_USER_REFCOUNT));
ctx_root_id->tag |= ID_TAG_TEMP_MAIN;
if (regenerate_session_uid) {
/* Calling #BKE_lib_libblock_session_uid_renew is not needed here, copying already generated a
* new one. */
BLI_assert(BKE_main_idmap_lookup_uid(matching_uid_map_, id->session_uid) == nullptr);
}
else {
this->preempt_session_uid(ctx_root_id, id->session_uid);
BKE_main_idmap_insert_id(matching_uid_map_, ctx_root_id);
}
BKE_main_idmap_insert_id(this->bmain.id_map, ctx_root_id);
BKE_libblock_management_main_add(&this->bmain, ctx_root_id);
/* Note: remapping of external file relative paths is done as part of the 'write' process. */
return ctx_root_id;
}
void PartialWriteContext::make_local(ID *ctx_id, const int make_local_flags)
{
/* Making an ID local typically resets its session UID, here we want to keep the same value. */
const uint ctx_id_session_uid = ctx_id->session_uid;
BKE_main_idmap_remove_id(this->bmain.id_map, ctx_id);
BKE_main_idmap_remove_id(matching_uid_map_, ctx_id);
BKE_lib_id_make_local(&this->bmain, ctx_id, make_local_flags);
this->preempt_session_uid(ctx_id, ctx_id_session_uid);
BKE_main_idmap_insert_id(this->bmain.id_map, ctx_id);
BKE_main_idmap_insert_id(matching_uid_map_, ctx_id);
}
Library *PartialWriteContext::ensure_library(ID *ctx_id)
{
if (!ID_IS_LINKED(ctx_id)) {
return nullptr;
}
blender::StringRefNull lib_path = ctx_id->lib->runtime.filepath_abs;
Library *ctx_lib = this->libraries_map_.lookup_default(lib_path, nullptr);
if (!ctx_lib) {
ctx_lib = reinterpret_cast<Library *>(id_add_copy(&ctx_id->lib->id, true));
this->libraries_map_.add(lib_path, ctx_lib);
}
ctx_id->lib = ctx_lib;
return ctx_lib;
}
Library *PartialWriteContext::ensure_library(blender::StringRefNull library_absolute_path)
{
Library *ctx_lib = this->libraries_map_.lookup_default(library_absolute_path, nullptr);
if (!ctx_lib) {
const char *library_name = BLI_path_basename(library_absolute_path.c_str());
ctx_lib = static_cast<Library *>(
BKE_id_new_in_lib(&this->bmain, nullptr, ID_LI, library_name));
ctx_lib->id.tag |= ID_TAG_TEMP_MAIN;
id_us_min(&ctx_lib->id);
this->libraries_map_.add(library_absolute_path, ctx_lib);
}
return ctx_lib;
}
ID *PartialWriteContext::id_add(
const ID *id,
PartialWriteContext::IDAddOptions options,
blender::FunctionRef<PartialWriteContext::IDAddOperations(
LibraryIDLinkCallbackData *cb_data, PartialWriteContext::IDAddOptions options)>
dependencies_filter_cb)
{
constexpr int make_local_flags = (LIB_ID_MAKELOCAL_INDIRECT | LIB_ID_MAKELOCAL_FORCE_LOCAL |
LIB_ID_MAKELOCAL_LIBOVERRIDE_CLEAR);
const bool add_dependencies = (options.operations & ADD_DEPENDENCIES) != 0;
const bool clear_dependencies = (options.operations & CLEAR_DEPENDENCIES) != 0;
const bool duplicate_dependencies = (options.operations & DUPLICATE_DEPENDENCIES) != 0;
BLI_assert(clear_dependencies || add_dependencies || dependencies_filter_cb);
BLI_assert(!clear_dependencies || !(add_dependencies || duplicate_dependencies));
UNUSED_VARS_NDEBUG(add_dependencies, clear_dependencies, duplicate_dependencies);
/* Do not directly add an embedded ID. Add its owner instead. */
if (id->flag & ID_FLAG_EMBEDDED_DATA) {
id = BKE_id_owner_get(const_cast<ID *>(id), true);
}
2024-07-07 00:28:53 +10:00
/* The given ID may have already been added (either explicitly or as a dependency) before. */
ID *ctx_root_id = BKE_main_idmap_lookup_uid(matching_uid_map_, id->session_uid);
if (ctx_root_id) {
/* If the root orig ID is already in the context, assume all of its dependencies are as well.
*/
BLI_assert(ctx_root_id->session_uid == id->session_uid);
this->process_added_id(ctx_root_id, options.operations);
return ctx_root_id;
}
/* Local mapping, such that even in case dependencies are duplicated for this specific added ID,
* once a dependency has been duplicated, it can be re-used for other ID usages within the
* dependencies of the added ID. */
blender::Map<const ID *, ID *> local_ctx_id_map;
/* A list of IDs to post-process. Only contains IDs that were actually added to the context (not
* the ones that were already there and were re-used). The #IDAddOperations item of the pair
* stores the returned value from the given #dependencies_filter_cb (or given global #options
* parameter otherwise). */
blender::Vector<std::pair<ID *, PartialWriteContext::IDAddOperations>> post_process_ids_todo;
ctx_root_id = id_add_copy(id, false);
BLI_assert(ctx_root_id->session_uid == id->session_uid);
local_ctx_id_map.add(id, ctx_root_id);
post_process_ids_todo.append({ctx_root_id, options.operations});
this->process_added_id(ctx_root_id, options.operations);
blender::VectorSet<ID *> ids_to_process{ctx_root_id};
auto dependencies_cb = [this,
options,
&local_ctx_id_map,
&ids_to_process,
&post_process_ids_todo,
dependencies_filter_cb](LibraryIDLinkCallbackData *cb_data) -> int {
ID **id_ptr = cb_data->id_pointer;
const ID *orig_deps_id = *id_ptr;
if (cb_data->cb_flag & (IDWALK_CB_EMBEDDED | IDWALK_CB_EMBEDDED_NOT_OWNING)) {
return IDWALK_RET_NOP;
}
if (!orig_deps_id) {
return IDWALK_RET_NOP;
}
if (cb_data->cb_flag & IDWALK_CB_INTERNAL) {
/* Cleanup internal ID pointers. */
*id_ptr = nullptr;
return IDWALK_RET_NOP;
}
PartialWriteContext::IDAddOperations operations_final = PartialWriteContext::IDAddOperations(
options.operations & MASK_INHERITED);
if (dependencies_filter_cb) {
const PartialWriteContext::IDAddOperations operations_per_id = dependencies_filter_cb(
cb_data, options);
operations_final = PartialWriteContext::IDAddOperations(
(operations_per_id & MASK_PER_ID_USAGE) | (operations_final & ~MASK_PER_ID_USAGE));
}
const bool add_dependencies = (operations_final & ADD_DEPENDENCIES) != 0;
const bool clear_dependencies = (operations_final & CLEAR_DEPENDENCIES) != 0;
const bool duplicate_dependencies = (operations_final & DUPLICATE_DEPENDENCIES) != 0;
BLI_assert(clear_dependencies || add_dependencies);
BLI_assert(!clear_dependencies || !(add_dependencies || duplicate_dependencies));
UNUSED_VARS_NDEBUG(add_dependencies);
if (clear_dependencies) {
if (cb_data->cb_flag & IDWALK_CB_NEVER_NULL) {
CLOG_WARN(&LOG_PARTIALWRITE,
"Clearing a 'never null' ID usage of '%s' by '%s', this is likely not a "
"desired action",
(*id_ptr)->name,
cb_data->owner_id->name);
}
/* Owner ID should be a 'context-main' duplicate of a real Main ID, as such there should be
* no need to decrease ID usages refcount here. */
*id_ptr = nullptr;
return IDWALK_RET_NOP;
}
/* else if (add_dependencies) */
2024-07-07 00:28:53 +10:00
/* The given ID may have already been added (either explicitly or as a dependency) before. */
ID *ctx_deps_id = nullptr;
if (duplicate_dependencies) {
ctx_deps_id = local_ctx_id_map.lookup(orig_deps_id);
}
else {
ctx_deps_id = BKE_main_idmap_lookup_uid(matching_uid_map_, orig_deps_id->session_uid);
}
if (!ctx_deps_id) {
if (cb_data->cb_flag & IDWALK_CB_LOOPBACK) {
/* Do not follow 'loop back' pointers. */
/* NOTE: Not sure whether this should be considered an error or not. Typically hitting such
* a case is bad practice. On the other hand, some of these pointers are present in
* 'normal' IDs, like e.g. the parent collections ones. This implies that currently, all
* attempt to adding a collection to a partial write context should make usage of a custom
2024-07-07 00:28:53 +10:00
* `dependencies_filter_cb` function to explicitly clear these pointers. */
CLOG_ERROR(&LOG_PARTIALWRITE,
"First dependency to ID '%s' found through a 'loopback' usage from ID '%s', "
"this should never happen",
(*id_ptr)->name,
cb_data->owner_id->name);
*id_ptr = nullptr;
return IDWALK_RET_NOP;
}
ctx_deps_id = this->id_add_copy(orig_deps_id, duplicate_dependencies);
local_ctx_id_map.add(orig_deps_id, ctx_deps_id);
ids_to_process.add(ctx_deps_id);
post_process_ids_todo.append({ctx_deps_id, operations_final});
}
if (duplicate_dependencies) {
BLI_assert(ctx_deps_id->session_uid != orig_deps_id->session_uid);
}
else {
BLI_assert(ctx_deps_id->session_uid == orig_deps_id->session_uid);
}
this->process_added_id(ctx_deps_id, operations_final);
/* In-place remapping. */
*id_ptr = ctx_deps_id;
return IDWALK_RET_NOP;
};
while (!ids_to_process.is_empty()) {
ID *ctx_id = ids_to_process.pop();
BKE_library_foreach_ID_link(
&this->bmain, ctx_id, dependencies_cb, &options, IDWALK_DO_INTERNAL_RUNTIME_POINTERS);
}
/* Post process all newly added IDs in the context:
* - Make them local or ensure that their library reference is also in the context.
*/
for (auto [ctx_id, options_final] : post_process_ids_todo) {
const bool do_make_local = (options_final & MAKE_LOCAL) != 0;
if (do_make_local) {
this->make_local(ctx_id, make_local_flags);
}
else {
this->ensure_library(ctx_id);
}
}
return ctx_root_id;
}
ID *PartialWriteContext::id_create(const short id_type,
const blender::StringRefNull id_name,
Library *library,
PartialWriteContext::IDAddOptions options)
{
Library *ctx_library = nullptr;
if (library) {
ctx_library = this->ensure_library(library->runtime.filepath_abs);
}
ID *ctx_id = static_cast<ID *>(
BKE_id_new_in_lib(&this->bmain, ctx_library, id_type, id_name.c_str()));
ctx_id->tag |= ID_TAG_TEMP_MAIN;
id_us_min(ctx_id);
this->process_added_id(ctx_id, options.operations);
/* See function doc about why handling of #matching_uid_map_ can be skipped here. */
BKE_main_idmap_insert_id(this->bmain.id_map, ctx_id);
return ctx_id;
}
void PartialWriteContext::id_delete(const ID *id)
{
if (ID *ctx_id = BKE_main_idmap_lookup_uid(matching_uid_map_, id->session_uid)) {
BKE_main_idmap_remove_id(matching_uid_map_, ctx_id);
BKE_id_delete(&this->bmain, ctx_id);
}
}
void PartialWriteContext::remove_unused(const bool clear_extra_user)
{
LibQueryUnusedIDsData parameters;
parameters.do_local_ids = true;
parameters.do_linked_ids = true;
parameters.do_recursive = true;
if (clear_extra_user) {
ID *id_iter;
FOREACH_MAIN_ID_BEGIN (&this->bmain, id_iter) {
id_us_clear_real(id_iter);
}
FOREACH_MAIN_ID_END;
}
BKE_lib_query_unused_ids_tag(&this->bmain, ID_TAG_DOIT, parameters);
CLOG_INFO(&LOG_PARTIALWRITE,
3,
"Removing %d unused IDs from current partial write context",
parameters.num_total[INDEX_ID_NULL]);
ID *id_iter;
FOREACH_MAIN_ID_BEGIN (&this->bmain, id_iter) {
if ((id_iter->tag & ID_TAG_DOIT) != 0) {
BKE_main_idmap_remove_id(matching_uid_map_, id_iter);
}
}
FOREACH_MAIN_ID_END;
BKE_id_multi_tagged_delete(&this->bmain);
}
void PartialWriteContext::clear()
{
BKE_main_idmap_clear(*matching_uid_map_);
BKE_main_clear(this->bmain);
}
bool PartialWriteContext::is_valid()
{
blender::Set<ID *> ids_in_context;
blender::Set<uint> session_uids_in_context;
bool is_valid = true;
ID *id_iter;
/* Fill `ids_in_context`, check uniqueness of session_uid's. */
FOREACH_MAIN_ID_BEGIN (&this->bmain, id_iter) {
ids_in_context.add(id_iter);
if (session_uids_in_context.contains(id_iter->session_uid)) {
CLOG_ERROR(&LOG_PARTIALWRITE, "ID %s does not have a unique session_uid", id_iter->name);
is_valid = false;
}
else {
session_uids_in_context.add(id_iter->session_uid);
}
}
FOREACH_MAIN_ID_END;
/* Check that no ID uses IDs from outside this context. */
auto id_validate_dependencies_cb = [&ids_in_context,
&is_valid](LibraryIDLinkCallbackData *cb_data) -> int {
ID **id_p = cb_data->id_pointer;
ID *owner_id = cb_data->owner_id;
ID *self_id = cb_data->self_id;
/* By definition, embedded IDs are not in Main, so they are not listed in this context either.
*/
if (cb_data->cb_flag & (IDWALK_CB_EMBEDDED | IDWALK_CB_EMBEDDED_NOT_OWNING)) {
return IDWALK_RET_NOP;
}
if (*id_p && !ids_in_context.contains(*id_p)) {
if (owner_id != self_id) {
CLOG_ERROR(
&LOG_PARTIALWRITE,
"ID %s (used by ID '%s', embedded ID '%s') is not in current partial write context",
(*id_p)->name,
owner_id->name,
self_id->name);
}
else {
CLOG_ERROR(&LOG_PARTIALWRITE,
"ID %s (used by ID '%s') is not in current partial write context",
(*id_p)->name,
owner_id->name);
}
is_valid = false;
}
return IDWALK_RET_NOP;
};
FOREACH_MAIN_ID_BEGIN (&this->bmain, id_iter) {
BKE_library_foreach_ID_link(
&this->bmain, id_iter, id_validate_dependencies_cb, nullptr, IDWALK_READONLY);
}
FOREACH_MAIN_ID_END;
return is_valid;
}
bool PartialWriteContext::write(const char *write_filepath,
const int write_flags,
const int remap_mode,
ReportList &reports)
{
BLI_assert_msg(write_filepath != reference_root_filepath_,
"A library blendfile should not overwrite currently edited blendfile");
/* In case the write path is the same as one of the libraries used by this context, make this
* library local, and delete it (and all of its potentially remaining linked data). */
Library *make_local_lib = nullptr;
LISTBASE_FOREACH (Library *, library, &this->bmain.libraries) {
if (STREQ(write_filepath, library->runtime.filepath_abs)) {
make_local_lib = library;
}
}
if (make_local_lib) {
BKE_library_make_local(&this->bmain, make_local_lib, nullptr, false, false, false);
BKE_id_delete(&this->bmain, make_local_lib);
make_local_lib = nullptr;
}
BLI_assert(this->is_valid());
BlendFileWriteParams blend_file_write_params{};
blend_file_write_params.remap_mode = eBLO_WritePathRemap(remap_mode);
return BLO_write_file(
&this->bmain, write_filepath, write_flags, &blend_file_write_params, &reports);
}
bool PartialWriteContext::write(const char *write_filepath, ReportList &reports)
{
return this->write(write_filepath, 0, BLO_WRITE_PATH_REMAP_RELATIVE, reports);
}
} // namespace blender::bke::blendfile
/** \} */