diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 6899a35ded84..c9d3ceea3c98 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -2073,17 +2073,23 @@ void EditorNode::restart_editor() { void EditorNode::_save_all_scenes() { bool all_saved = true; for (int i = 0; i < editor_data.get_edited_scene_count(); i++) { - Node *scene = editor_data.get_edited_scene_root(i); - if (scene) { - if (!scene->get_scene_file_path().is_empty() && DirAccess::exists(scene->get_scene_file_path().get_base_dir())) { - if (i != editor_data.get_edited_scene()) { - _save_scene(scene->get_scene_file_path(), i); - } else { - _save_scene_with_preview(scene->get_scene_file_path()); - } - } else if (!scene->get_scene_file_path().is_empty()) { - all_saved = false; - } + if (!_is_scene_unsaved(i)) { + continue; + } + + const Node *scene = editor_data.get_edited_scene_root(i); + ERR_FAIL_NULL(scene); + + const String &scene_path = scene->get_scene_file_path(); + if (!scene_path.is_empty() && !DirAccess::exists(scene_path.get_base_dir())) { + all_saved = false; + continue; + } + + if (i == editor_data.get_edited_scene()) { + _save_scene_with_preview(scene_path); + } else { + _save_scene(scene_path, i); } } @@ -2111,6 +2117,28 @@ void EditorNode::_mark_unsaved_scenes() { scene_tabs->update_scene_tabs(); } +bool EditorNode::_is_scene_unsaved(int p_idx) { + const Node *scene = editor_data.get_edited_scene_root(p_idx); + if (!scene) { + return false; + } + + if (EditorUndoRedoManager::get_singleton()->is_history_unsaved(editor_data.get_scene_history_id(p_idx))) { + return true; + } + + const String &scene_path = scene->get_scene_file_path(); + if (!scene_path.is_empty()) { + // Check if scene has unsaved changes in built-in resources. + for (int j = 0; j < editor_data.get_editor_plugin_count(); j++) { + if (!editor_data.get_editor_plugin(j)->get_unsaved_status(scene_path).is_empty()) { + return true; + } + } + } + return false; +} + void EditorNode::_dialog_action(String p_file) { switch (current_menu_option) { case FILE_NEW_INHERITED_SCENE: { @@ -3493,6 +3521,20 @@ void EditorNode::_discard_changes(const String &p_str) { } void EditorNode::_update_file_menu_opened() { + bool has_unsaved = false; + for (int i = 0; i < editor_data.get_edited_scene_count(); i++) { + if (_is_scene_unsaved(i)) { + has_unsaved = true; + break; + } + } + if (has_unsaved) { + file_menu->set_item_disabled(file_menu->get_item_index(FILE_SAVE_ALL_SCENES), false); + file_menu->set_item_tooltip(file_menu->get_item_index(FILE_SAVE_ALL_SCENES), String()); + } else { + file_menu->set_item_disabled(file_menu->get_item_index(FILE_SAVE_ALL_SCENES), true); + file_menu->set_item_tooltip(file_menu->get_item_index(FILE_SAVE_ALL_SCENES), TTR("All scenes are already saved.")); + } file_menu->set_item_disabled(file_menu->get_item_index(FILE_OPEN_PREV), previous_scenes.is_empty()); _update_undo_redo_allowed(); } diff --git a/editor/editor_node.h b/editor/editor_node.h index e9d2c285284d..5b3a218b6caf 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -636,6 +636,7 @@ class EditorNode : public Node { bool _find_and_save_edited_subresources(Object *obj, HashMap, bool> &processed, int32_t flags); void _save_edited_subresources(Node *scene, HashMap, bool> &processed, int32_t flags); void _mark_unsaved_scenes(); + bool _is_scene_unsaved(int p_idx); void _find_node_types(Node *p_node, int &count_2d, int &count_3d); void _save_scene_with_preview(String p_file, int p_idx = -1); diff --git a/editor/plugins/shader_editor_plugin.cpp b/editor/plugins/shader_editor_plugin.cpp index 597ef490047a..f48d4a28ea96 100644 --- a/editor/plugins/shader_editor_plugin.cpp +++ b/editor/plugins/shader_editor_plugin.cpp @@ -342,7 +342,7 @@ String ShaderEditorPlugin::get_unsaved_status(const String &p_for_scene) const { void ShaderEditorPlugin::save_external_data() { for (EditedShader &edited_shader : edited_shaders) { - if (edited_shader.shader_editor) { + if (edited_shader.shader_editor && edited_shader.shader_editor->is_unsaved()) { edited_shader.shader_editor->save_external_data(); } }