diff options
author | Pedro J. Estébanez <pedrojrulez@gmail.com> | 2023-06-07 13:44:37 +0200 |
---|---|---|
committer | Pedro J. Estébanez <pedrojrulez@gmail.com> | 2023-06-13 11:05:57 +0200 |
commit | 96c469a1388a430456465b602ea49bf69ef782c3 (patch) | |
tree | ca9d2818e09aa465246dc4a99d737cb64b57216b | |
parent | 828ec2c5d005b6499c7c4c88beaf81767d05614b (diff) | |
download | redot-engine-96c469a1388a430456465b602ea49bf69ef782c3.tar.gz |
Let editor workaround a case of inconsistency in compound scenes
-rw-r--r-- | doc/classes/EditorInterface.xml | 6 | ||||
-rw-r--r-- | editor/editor_interface.cpp | 7 | ||||
-rw-r--r-- | editor/editor_interface.h | 1 | ||||
-rw-r--r-- | editor/editor_node.cpp | 12 | ||||
-rw-r--r-- | editor/editor_node.h | 1 | ||||
-rw-r--r-- | scene/resources/packed_scene.cpp | 32 | ||||
-rw-r--r-- | scene/resources/packed_scene.h | 12 |
7 files changed, 70 insertions, 1 deletions
diff --git a/doc/classes/EditorInterface.xml b/doc/classes/EditorInterface.xml index 418548a95f..effce40b12 100644 --- a/doc/classes/EditorInterface.xml +++ b/doc/classes/EditorInterface.xml @@ -179,6 +179,12 @@ Returns mesh previews rendered at the given size as an [Array] of [Texture2D]s. </description> </method> + <method name="mark_scene_as_unsaved"> + <return type="void" /> + <description> + Marks the current scene tab as unsaved. + </description> + </method> <method name="open_scene_from_path"> <return type="void" /> <param index="0" name="scene_filepath" type="String" /> diff --git a/editor/editor_interface.cpp b/editor/editor_interface.cpp index 50833c3a09..d9d9dc01c0 100644 --- a/editor/editor_interface.cpp +++ b/editor/editor_interface.cpp @@ -36,6 +36,7 @@ #include "editor/editor_resource_preview.h" #include "editor/editor_scale.h" #include "editor/editor_settings.h" +#include "editor/editor_undo_redo_manager.h" #include "editor/filesystem_dock.h" #include "editor/gui/editor_run_bar.h" #include "editor/inspector_dock.h" @@ -332,6 +333,10 @@ void EditorInterface::save_scene_as(const String &p_scene, bool p_with_preview) EditorNode::get_singleton()->save_scene_to_path(p_scene, p_with_preview); } +void EditorInterface::mark_scene_as_unsaved() { + EditorUndoRedoManager::get_singleton()->set_history_as_unsaved(EditorNode::get_editor_data().get_current_edited_scene_history_id()); +} + // Scene playback. void EditorInterface::play_main_scene() { @@ -430,6 +435,8 @@ void EditorInterface::_bind_methods() { ClassDB::bind_method(D_METHOD("save_scene"), &EditorInterface::save_scene); ClassDB::bind_method(D_METHOD("save_scene_as", "path", "with_preview"), &EditorInterface::save_scene_as, DEFVAL(true)); + ClassDB::bind_method(D_METHOD("mark_scene_as_unsaved"), &EditorInterface::mark_scene_as_unsaved); + // Scene playback. ClassDB::bind_method(D_METHOD("play_main_scene"), &EditorInterface::play_main_scene); diff --git a/editor/editor_interface.h b/editor/editor_interface.h index 95fa0dd64f..f7e8cf8d4c 100644 --- a/editor/editor_interface.h +++ b/editor/editor_interface.h @@ -129,6 +129,7 @@ public: Error save_scene(); void save_scene_as(const String &p_scene, bool p_with_preview = true); + void mark_scene_as_unsaved(); // Scene playback. diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index bc61661a83..4795fca03d 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -4103,6 +4103,13 @@ void EditorNode::add_io_error(const String &p_error) { EditorInterface::get_singleton()->popup_dialog_centered_ratio(singleton->load_error_dialog, 0.5); } +void EditorNode::add_io_warning(const String &p_warning) { + DEV_ASSERT(Thread::get_caller_id() == Thread::get_main_id()); + singleton->load_errors->add_image(singleton->gui_base->get_theme_icon(SNAME("Warning"), SNAME("EditorIcons"))); + singleton->load_errors->add_text(p_warning + "\n"); + EditorInterface::get_singleton()->popup_dialog_centered_ratio(singleton->load_error_dialog, 0.5); +} + bool EditorNode::_find_scene_in_use(Node *p_node, const String &p_path) const { if (p_node->get_scene_file_path() == p_path) { return true; @@ -6806,6 +6813,11 @@ EditorNode::EditorNode() { ResourceLoader::set_error_notify_func(&EditorNode::add_io_error); ResourceLoader::set_dependency_error_notify_func(&EditorNode::_dependency_error_report); + SceneState::set_instantiation_warning_notify_func([](const String &p_warning) { + add_io_warning(p_warning); + callable_mp(EditorInterface::get_singleton(), &EditorInterface::mark_scene_as_unsaved).call_deferred(); + }); + { // Register importers at the beginning, so dialogs are created with the right extensions. Ref<ResourceImporterTexture> import_texture; diff --git a/editor/editor_node.h b/editor/editor_node.h index edcad7e4d1..65f85a76c9 100644 --- a/editor/editor_node.h +++ b/editor/editor_node.h @@ -731,6 +731,7 @@ public: static bool has_unsaved_changes() { return singleton->unsaved_cache; } static void disambiguate_filenames(const Vector<String> p_full_paths, Vector<String> &r_filenames); static void add_io_error(const String &p_error); + static void add_io_warning(const String &p_warning); static void progress_add_task(const String &p_task, const String &p_label, int p_steps, bool p_can_cancel = false); static bool progress_task_step(const String &p_task, const String &p_state, int p_step = -1, bool p_force_refresh = true); diff --git a/scene/resources/packed_scene.cpp b/scene/resources/packed_scene.cpp index 4d690bd3b1..6708c78177 100644 --- a/scene/resources/packed_scene.cpp +++ b/scene/resources/packed_scene.cpp @@ -45,6 +45,10 @@ #define PACKED_SCENE_VERSION 3 +#ifdef TOOLS_ENABLED +SceneState::InstantiationWarningNotify SceneState::instantiation_warn_notify = nullptr; +#endif + bool SceneState::can_instantiate() const { return nodes.size() > 0; } @@ -380,7 +384,33 @@ Node *SceneState::instantiate(GenEditState p_edit_state) const { //if node was not part of instance, must set its name, parenthood and ownership if (i > 0) { if (parent) { - parent->_add_child_nocheck(node, snames[n.name]); + bool pending_add = true; +#ifdef TOOLS_ENABLED + if (Engine::get_singleton()->is_editor_hint()) { + Node *existing = parent->_get_child_by_name(snames[n.name]); + if (existing) { + // There's already a node in the same parent with the same name. + // This means that somehow the node was added both to the scene being + // loaded and another one instantiated in the former, maybe because of + // manual editing, or a bug in scene saving, or a loophole in the workflow + // (with any of the bugs possibly already fixed). + // Bring consistency back by letting it be assigned a non-clashing name. + // This simple workaround at least avoids leaks and helps the user realize + // something awkward has happened. + if (instantiation_warn_notify) { + instantiation_warn_notify(vformat( + TTR("An incoming node's name clashes with %s already in the scene (presumably, from a more nested instance).\nThe less nested node will be renamed. Please fix and re-save the scene."), + ret_nodes[0]->get_path_to(existing))); + } + node->set_name(snames[n.name]); + parent->add_child(node, true); + pending_add = false; + } + } +#endif + if (pending_add) { + parent->_add_child_nocheck(node, snames[n.name]); + } if (n.index >= 0 && n.index < parent->get_child_count() - 1) { parent->move_child(node, n.index); } diff --git a/scene/resources/packed_scene.h b/scene/resources/packed_scene.h index 5c53ffdb45..29df382c1f 100644 --- a/scene/resources/packed_scene.h +++ b/scene/resources/packed_scene.h @@ -102,6 +102,14 @@ class SceneState : public RefCounted { int _find_base_scene_node_remap_key(int p_idx) const; +#ifdef TOOLS_ENABLED +public: + typedef void (*InstantiationWarningNotify)(const String &p_warning); + +private: + static InstantiationWarningNotify instantiation_warn_notify; +#endif + protected: static void _bind_methods(); @@ -201,6 +209,10 @@ public: // Used when saving pointers (saves a path property instead). static String get_meta_pointer_property(const String &p_property); +#ifdef TOOLS_ENABLED + static void set_instantiation_warning_notify_func(InstantiationWarningNotify p_warn_notify) { instantiation_warn_notify = p_warn_notify; } +#endif + SceneState(); }; |