From cbb8f55b965c8d4845a01cd9bd9e504feaa22a91 Mon Sep 17 00:00:00 2001 From: Hugo Locurcio Date: Mon, 11 Oct 2021 17:54:44 +0200 Subject: [PATCH] Show a warning toast when saving a large text-based scene Text-based scenes that contain large amounts of binary data are slower to save and load. Their binary resources should be moved to separate files, or the binary `.scn` format should be used instead. --- doc/classes/EditorSettings.xml | 4 ++++ editor/editor_node.cpp | 26 ++++++++++++++++++++++++++ editor/settings/editor_settings.cpp | 1 + 3 files changed, 31 insertions(+) diff --git a/doc/classes/EditorSettings.xml b/doc/classes/EditorSettings.xml index 14b2327ada7..eb9b0d8516b 100644 --- a/doc/classes/EditorSettings.xml +++ b/doc/classes/EditorSettings.xml @@ -853,6 +853,10 @@ If [code]true[/code], when saving a file, the editor will rename the old file to a different name, save a new file, then only remove the old file once the new file has been saved. This makes loss of data less likely to happen if the editor or operating system exits unexpectedly while saving (e.g. due to a crash or power outage). [b]Note:[/b] On Windows, this feature can interact negatively with certain antivirus programs. In this case, you may have to set this to [code]false[/code] to prevent file locking issues. + + If [code]true[/code], displays a warning toast message when saving a text-based scene or resource that is larger than 500 KiB on disk. This is typically caused by binary subresources being embedded as text, which results in slow and inefficient conversion to text. This in turn impacts scene saving and loading times. + This should usually be resolved by moving the embedded binary subresource to its own binary resource file ([code].res[/code] extension instead of [code].tres[/code]). This is the preferred approach. Alternatively, the entire scene can be saved with the binary [code].scn[/code] format as opposed to [code].tscn[/code], but this will make it less friendly to version control systems. + If set to [code]Adaptive[/code], the dialog opens in list view or grid view depending on the requested type. If set to [code]Last Used[/code], the display mode will always open the way you last used it. diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index bb7b1dddde4..3bfe1ea3afc 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -206,6 +206,8 @@ static const String EDITOR_NODE_CONFIG_SECTION = "EditorNode"; static const String REMOVE_ANDROID_BUILD_TEMPLATE_MESSAGE = TTRC("The Android build template is already installed in this project and it won't be overwritten.\nRemove the \"%s\" directory manually before attempting this operation again."); static const String INSTALL_ANDROID_BUILD_TEMPLATE_MESSAGE = TTRC("This will set up your project for gradle Android builds by installing the source template to \"%s\".\nNote that in order to make gradle builds instead of using pre-built APKs, the \"Use Gradle Build\" option should be enabled in the Android export preset."); +constexpr int LARGE_RESOURCE_WARNING_SIZE_THRESHOLD = 512'000; // 500 KB + bool EditorProgress::step(const String &p_state, int p_step, bool p_force_refresh) { if (!force_background && Thread::is_main_thread()) { return EditorNode::progress_task_step(task, p_state, p_step, p_force_refresh); @@ -1657,6 +1659,18 @@ void EditorNode::save_resource_in_path(const Ref &p_resource, const St clear_node_reference(p_resource); // // Check if Resource is saved to disk to potentially remove it from resource_count emit_signal(SNAME("resource_saved"), p_resource); editor_data.notify_resource_saved(p_resource); + + if (EDITOR_GET("filesystem/on_save/warn_on_saving_large_text_resources")) { + if (p_path.ends_with(".tres")) { + const int64_t file_size = FileAccess::get_size(p_path); + if (file_size >= LARGE_RESOURCE_WARNING_SIZE_THRESHOLD) { + // File is larger than 500 KiB, likely because it contains binary data serialized as Base64. + // This is slow to save and load, so warn the user. + EditorToaster::get_singleton()->popup_str( + vformat(TTR("The text-based resource at path \"%s\" is large on disk (%s), likely because it has embedded binary data.\nThis slows down resource saving and loading.\nConsider saving its binary subresource(s) to a binary `.res` file or saving the resource as a binary `.res` file.\nThis warning can be disabled in the Editor Settings (FileSystem > On Save > Warn on Saving Large Text Resources)."), p_path, String::humanize_size(file_size)), EditorToaster::SEVERITY_WARNING); + } + } + } } void EditorNode::save_resource(const Ref &p_resource) { @@ -2404,6 +2418,18 @@ void EditorNode::_save_scene(String p_file, int idx) { editor_data.set_scene_as_saved(idx); editor_data.set_scene_modified_time(idx, FileAccess::get_modified_time(p_file)); + if (EDITOR_GET("filesystem/on_save/warn_on_saving_large_text_resources")) { + if (p_file.ends_with(".tscn") || p_file.ends_with(".tres")) { + const int64_t file_size = FileAccess::get_size(p_file); + if (file_size >= LARGE_RESOURCE_WARNING_SIZE_THRESHOLD) { + // File is larger than 500 KiB, likely because it contains binary data serialized as Base64. + // This is slow to save and load, so warn the user. + EditorToaster::get_singleton()->popup_str( + vformat(TTR("The text-based scene at path \"%s\" is large on disk (%s), likely because it has embedded binary data.\nThis slows down scene saving and loading.\nConsider saving its binary subresource(s) to a binary `.res` file or saving the scene as a binary `.scn` file.\nThis warning can be disabled in the Editor Settings (FileSystem > On Save > Warn on Saving Large Text Resources)."), p_file, String::humanize_size(file_size)), EditorToaster::SEVERITY_WARNING); + } + } + } + editor_folding.save_scene_folding(scene, p_file); _update_title(); diff --git a/editor/settings/editor_settings.cpp b/editor/settings/editor_settings.cpp index 72e9993cf8e..3ba0ab482ad 100644 --- a/editor/settings/editor_settings.cpp +++ b/editor/settings/editor_settings.cpp @@ -653,6 +653,7 @@ void EditorSettings::_load_defaults(Ref p_extra_config) { // On save _initial_set("filesystem/on_save/compress_binary_resources", true); _initial_set("filesystem/on_save/safe_save_on_backup_then_rename", true); + _initial_set("filesystem/on_save/warn_on_saving_large_text_resources", true); // EditorFileServer _initial_set("filesystem/file_server/port", 6010);