Merge pull request #116905 from KoBeWi/slashtableflip

Overhaul scene loading and edit state management
This commit is contained in:
Thaddeus Crews
2026-05-07 11:13:25 -05:00
18 changed files with 242 additions and 247 deletions
+1 -1
View File
@@ -450,7 +450,7 @@
<return type="void" />
<param index="0" name="scene_filepath" type="String" />
<description>
Reloads the scene at the given path.
Reloads the scene at the given path. Fails if the scene is not open.
</description>
</method>
<method name="restart_editor">
+1 -1
View File
@@ -167,7 +167,7 @@ void EditorDebuggerNode::_stack_frame_selected(int p_debugger) {
void EditorDebuggerNode::_error_selected(const String &p_file, int p_line, int p_debugger) {
if (!p_file.is_resource_file() && !ResourceCache::has(p_file)) {
// If it's a built-in script, make sure the scene is opened first.
EditorNode::get_singleton()->load_scene(p_file.get_slice("::", 0));
EditorNode::get_singleton()->open_scene(p_file.get_slice("::", 0));
}
Ref<Script> s = ResourceLoader::load(p_file);
emit_signal(SNAME("goto_script_line"), s, p_line - 1);
+1 -1
View File
@@ -1676,7 +1676,7 @@ void FileSystemDock::_update_dependencies_after_move(const HashMap<String, Strin
print_verbose("Remapping dependencies for: " + file);
const Error err = ResourceLoader::rename_dependencies(file, p_renames);
if (err == OK) {
if (ResourceLoader::get_resource_type(file) == "PackedScene") {
if (ResourceLoader::get_resource_type(file) == "PackedScene" && EditorNode::get_editor_data().get_edited_scene_from_path(file) != -1) {
if (file == edited_scene_path) {
scenes_to_reload.push_front(file);
} else {
+1 -1
View File
@@ -1910,7 +1910,7 @@ void SceneTreeDock::_node_strip_signal_inheritance(Node *p_node) {
}
void SceneTreeDock::_load_request(const String &p_path) {
EditorNode::get_singleton()->load_scene(p_path);
EditorNode::get_singleton()->open_scene(p_path);
_local_tree_selected();
}
+76 -24
View File
@@ -328,8 +328,23 @@ Dictionary EditorData::get_editor_plugin_states() const {
Dictionary EditorData::get_scene_editor_states(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx, edited_scene.size(), Dictionary());
EditedScene es = edited_scene[p_idx];
return es.editor_states;
return edited_scene[p_idx].editor_states;
}
Dictionary EditorData::get_scene_editor_states_with_selection(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx, edited_scene.size(), Dictionary());
const EditedScene &es = edited_scene[p_idx];
Dictionary states = es.editor_states;
TypedArray<NodePath> selected_paths;
Node *root = es.root;
if (root) {
for (Node *node : es.selection) {
selected_paths.push_back(root->get_path_to(node));
}
states["selected_nodes"] = selected_paths;
}
return states;
}
void EditorData::set_editor_plugin_states(const Dictionary &p_states) {
@@ -376,6 +391,36 @@ void EditorData::notify_scene_saved(const String &p_path) {
}
}
void EditorData::load_editor_plugin_states_from_config(const Ref<ConfigFile> &p_config_file, int p_idx) {
ERR_FAIL_INDEX(p_idx, edited_scene.size());
EditedScene &es = edited_scene.write[p_idx];
const Vector<String> esl = p_config_file->get_section_keys("editor_states");
Dictionary states;
for (const String &E : esl) {
const Variant state = p_config_file->get_value("editor_states", E);
if (state.get_type() != Variant::NIL) {
states[E] = state;
}
}
es.editor_states = states;
const Node *root = es.root;
if (root && p_config_file->has_section_key("editor_states", "selected_nodes")) {
TypedArray<NodePath> node_paths = p_config_file->get_value("editor_states", "selected_nodes");
List<Node *> nodes;
for (const Variant &np : node_paths) {
Node *node = root->get_node_or_null(np);
if (node) {
nodes.push_back(node);
}
}
es.selection = nodes;
}
}
void EditorData::clear_editor_states() {
for (int i = 0; i < editor_plugins.size(); i++) {
editor_plugins[i]->clear();
@@ -635,12 +680,6 @@ int EditorData::add_edited_scene(int p_at_pos) {
return p_at_pos;
}
void EditorData::move_edited_scene_index(int p_idx, int p_to_idx) {
ERR_FAIL_INDEX(p_idx, edited_scene.size());
ERR_FAIL_INDEX(p_to_idx, edited_scene.size());
SWAP(edited_scene.write[p_idx], edited_scene.write[p_to_idx]);
}
void EditorData::remove_scene(int p_idx) {
ERR_FAIL_INDEX(p_idx, edited_scene.size());
if (edited_scene[p_idx].root) {
@@ -671,6 +710,24 @@ void EditorData::remove_scene(int p_idx) {
edited_scene.remove_at(p_idx);
}
void EditorData::set_scene_root(int p_idx, Node *p_root) {
ERR_FAIL_INDEX(p_idx, edited_scene.size());
EditedScene &scene_info = edited_scene.write[p_idx];
scene_info.root = p_root;
if (p_root) {
if (p_root->is_instance()) {
scene_info.path = p_root->get_scene_file_path();
} else {
p_root->set_scene_file_path(scene_info.path);
}
}
if (!scene_info.path.is_empty()) {
scene_info.file_modified_time = FileAccess::get_modified_time(scene_info.path);
}
}
bool EditorData::_find_updated_instances(Node *p_root, Node *p_node, HashSet<String> &checked_paths) {
Ref<SceneState> ss;
@@ -762,6 +819,15 @@ bool EditorData::reload_scene_from_memory(int p_idx, bool p_mark_unsaved) {
return true;
}
void EditorData::move_scene_to_index(int p_idx, int p_to_idx) {
ERR_FAIL_INDEX(p_idx, edited_scene.size());
ERR_FAIL_INDEX(p_to_idx, edited_scene.size());
EditedScene es = edited_scene[p_idx];
edited_scene.remove_at(p_idx);
edited_scene.insert(p_to_idx, es);
}
int EditorData::get_edited_scene() const {
return current_edited_scene;
}
@@ -792,19 +858,7 @@ Node *EditorData::get_edited_scene_root(int p_idx) {
}
void EditorData::set_edited_scene_root(Node *p_root) {
ERR_FAIL_INDEX(current_edited_scene, edited_scene.size());
edited_scene.write[current_edited_scene].root = p_root;
if (p_root) {
if (p_root->is_instance()) {
edited_scene.write[current_edited_scene].path = p_root->get_scene_file_path();
} else {
p_root->set_scene_file_path(edited_scene[current_edited_scene].path);
}
}
if (!edited_scene[current_edited_scene].path.is_empty()) {
edited_scene.write[current_edited_scene].file_modified_time = FileAccess::get_modified_time(edited_scene[current_edited_scene].path);
}
set_scene_root(current_edited_scene, p_root);
}
int EditorData::get_edited_scene_count() const {
@@ -852,9 +906,7 @@ void EditorData::move_edited_scene_to_index(int p_idx) {
ERR_FAIL_INDEX(current_edited_scene, edited_scene.size());
ERR_FAIL_INDEX(p_idx, edited_scene.size());
EditedScene es = edited_scene[current_edited_scene];
edited_scene.remove_at(current_edited_scene);
edited_scene.insert(p_idx, es);
move_scene_to_index(current_edited_scene, p_idx);
current_edited_scene = p_idx;
}
+4 -3
View File
@@ -162,6 +162,7 @@ public:
Dictionary get_editor_plugin_states() const;
Dictionary get_scene_editor_states(int p_idx) const;
Dictionary get_scene_editor_states_with_selection(int p_idx) const;
void set_editor_plugin_states(const Dictionary &p_states);
void get_editor_breakpoints(List<String> *p_breakpoints);
void clear_editor_states();
@@ -187,8 +188,6 @@ public:
void remove_move_array_element_function(const StringName &p_class);
Callable get_move_array_element_function(const StringName &p_class) const;
void save_editor_global_states();
void add_custom_type(const String &p_type, const String &p_inherits, const Ref<Script> &p_script, const Ref<Texture2D> &p_icon);
Variant instantiate_custom_type(const String &p_type, const String &p_inherits);
void remove_custom_type(const String &p_type);
@@ -200,8 +199,8 @@ public:
void instantiate_object_properties(Object *p_object);
int add_edited_scene(int p_at_pos);
void move_edited_scene_index(int p_idx, int p_to_idx);
void remove_scene(int p_idx);
void set_scene_root(int p_idx, Node *p_root);
void set_edited_scene(int p_idx);
void set_edited_scene_root(Node *p_root);
int get_edited_scene() const;
@@ -223,6 +222,7 @@ public:
NodePath get_edited_scene_live_edit_root();
bool check_and_update_scene(int p_idx);
bool reload_scene_from_memory(int p_idx, bool p_mark_unsaved);
void move_scene_to_index(int p_idx, int p_to_idx);
void move_edited_scene_to_index(int p_idx);
bool call_build();
@@ -242,6 +242,7 @@ public:
void notify_edited_scene_changed();
void notify_resource_saved(const Ref<Resource> &p_resource);
void notify_scene_saved(const String &p_path);
void load_editor_plugin_states_from_config(const Ref<ConfigFile> &p_config_file, int p_idx);
bool script_class_is_parent(const String &p_class, const String &p_inherits);
Variant script_class_instance(const String &p_class);
+1 -1
View File
@@ -700,7 +700,7 @@ void EditorInterface::open_scene_from_path(const String &scene_path, bool p_set_
if (EditorNode::get_singleton()->is_changing_scene()) {
return;
}
EditorNode::get_singleton()->load_scene(scene_path, false, p_set_inherited);
EditorNode::get_singleton()->open_scene(scene_path, false, p_set_inherited);
}
void EditorInterface::reload_scene_from_path(const String &scene_path) {
+141 -199
View File
@@ -1482,7 +1482,9 @@ void EditorNode::_resources_reimported(const Vector<String> &p_resources) {
if (!should_refresh_current_scene_tab && E == current_scene_tab) {
should_refresh_current_scene_tab = true;
}
reload_scene(E);
if (editor_data.get_edited_scene_from_path(E) != -1) {
reload_scene(E);
}
}
reload_instances_with_path_in_edited_scenes();
@@ -1511,7 +1513,7 @@ void EditorNode::_sources_changed(bool p_exist) {
if (!defer_load_scene.is_empty()) {
OS::get_singleton()->benchmark_begin_measure("Editor", "Load Scene");
load_scene(defer_load_scene);
open_scene(defer_load_scene);
defer_load_scene = "";
OS::get_singleton()->benchmark_end_measure("Editor", "Load Scene");
@@ -1615,7 +1617,7 @@ void EditorNode::_reload_modified_scenes() {
editor_data.set_edited_scene(i);
_remove_edited_scene(false);
Error err = load_scene(filename, false, false, false, true);
Error err = open_scene(filename);
if (err != OK) {
ERR_PRINT(vformat("Failed to load scene: %s", filename));
}
@@ -1717,7 +1719,7 @@ Error EditorNode::load_scene_or_resource(const String &p_path, bool p_ignore_bro
if (!p_change_scene_tab_if_already_open && EditorNode::get_singleton()->is_scene_open(p_path)) {
return OK;
}
return EditorNode::get_singleton()->load_scene(p_path, p_ignore_broken_deps);
return EditorNode::get_singleton()->open_scene(p_path, p_ignore_broken_deps);
}
return EditorNode::get_singleton()->load_resource(p_path, p_ignore_broken_deps);
}
@@ -2112,30 +2114,10 @@ void EditorNode::_dialog_display_load_error(String p_file, Error p_error) {
}
}
void EditorNode::_load_editor_plugin_states_from_config(const Ref<ConfigFile> &p_config_file) {
Node *scene = editor_data.get_edited_scene_root();
if (!scene) {
return;
}
Vector<String> esl = p_config_file->get_section_keys("editor_states");
Dictionary md;
for (const String &E : esl) {
Variant st = p_config_file->get_value("editor_states", E);
if (st.get_type() != Variant::NIL) {
md[E] = st;
}
}
editor_data.set_editor_plugin_states(md);
}
void EditorNode::_save_editor_states(const String &p_file, int p_idx) {
Node *scene = editor_data.get_edited_scene_root(p_idx);
if (!scene) {
bool saving_current_scene = p_idx < 0 || editor_data.get_edited_scene() == p_idx;
if (saving_current_scene && !scene) {
return;
}
@@ -2145,25 +2127,25 @@ void EditorNode::_save_editor_states(const String &p_file, int p_idx) {
cf.instantiate();
Dictionary md;
if (p_idx < 0 || editor_data.get_edited_scene() == p_idx) {
if (saving_current_scene) {
md = editor_data.get_editor_plugin_states();
// Save the currently selected nodes.
List<Node *> selection = editor_selection->get_full_selected_node_list();
TypedArray<NodePath> selection_paths;
for (Node *selected_node : selection) {
selection_paths.push_back(scene->get_path_to(selected_node));
}
cf->set_value("editor_states", "selected_nodes", selection_paths);
} else {
md = editor_data.get_scene_editor_states(p_idx);
md = editor_data.get_scene_editor_states_with_selection(p_idx);
}
for (const KeyValue<Variant, Variant> &kv : md) {
cf->set_value("editor_states", kv.key, kv.value);
}
// Save the currently selected nodes.
List<Node *> selection = editor_selection->get_full_selected_node_list();
TypedArray<NodePath> selection_paths;
for (Node *selected_node : selection) {
selection_paths.push_back(selected_node->get_path());
}
cf->set_value("editor_states", "selected_nodes", selection_paths);
Error err = cf->save(path);
ERR_FAIL_COND_MSG(err != OK, "Cannot save config file to '" + path + "'.");
}
@@ -2702,10 +2684,10 @@ void EditorNode::_dialog_action(String p_file) {
_menu_option_confirm(SCENE_CLOSE, true);
}
load_scene(p_file, false, true);
open_scene(p_file, false, true);
} break;
case SCENE_OPEN_SCENE: {
load_scene(p_file);
open_scene(p_file);
} break;
case SETTINGS_PICK_MAIN_SCENE: {
ProjectSettings::get_singleton()->set("application/run/main_scene", ResourceUID::path_to_uid(p_file));
@@ -3427,7 +3409,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) {
} break;
case SCENE_OPEN_PREV: {
if (!prev_closed_scenes.is_empty()) {
load_scene(prev_closed_scenes.back()->get());
open_scene(prev_closed_scenes.back()->get());
}
} break;
case EditorSceneTabs::SCENE_CLOSE_OTHERS: {
@@ -4249,18 +4231,7 @@ void EditorNode::_discard_changes(const String &p_str) {
} break;
case SCENE_RELOAD_SAVED_SCENE: {
int cur_idx = editor_data.get_edited_scene();
const String scene_filename = editor_data.get_scene_path(cur_idx);
_remove_edited_scene();
Error err = load_scene(scene_filename);
if (err != OK) {
ERR_PRINT("Failed to load scene");
}
editor_data.move_edited_scene_to_index(cur_idx);
EditorUndoRedoManager::get_singleton()->clear_history(editor_data.get_current_edited_scene_history_id(), false);
scene_tabs->set_current_tab(cur_idx);
reload_scene(editor_data.get_scene_path(cur_idx));
confirmation->hide();
} break;
case SCENE_QUIT: {
@@ -4597,18 +4568,19 @@ void EditorNode::_remove_edited_scene(bool p_change_tab) {
scene_tabs->update_scene_tabs();
}
void EditorNode::_remove_scene(int index, bool p_change_tab) {
void EditorNode::_remove_scene(int p_idx, bool p_change_tab) {
// Clear icon cache in case some scripts are no longer needed or class icons are outdated.
// FIXME: Ideally the cache should never be cleared and only updated on per-script basis, when an icon changes.
editor_data.clear_script_icon_cache();
class_icon_cache.clear();
if (editor_data.get_edited_scene() == index) {
_save_editor_states(editor_data.get_scene_path(p_idx), p_idx);
if (editor_data.get_edited_scene() == p_idx) {
// Scene to remove is current scene.
_remove_edited_scene(p_change_tab);
} else {
// Scene to remove is not active scene.
editor_data.remove_scene(index);
editor_data.remove_scene(p_idx);
}
}
@@ -4675,13 +4647,7 @@ Dictionary EditorNode::_get_main_scene_state() {
return state;
}
void EditorNode::_set_main_scene_state(Dictionary p_state, Node *p_for_scene) {
if (get_edited_scene() != p_for_scene && p_for_scene != nullptr) {
return; // Not for this scene.
}
changing_scene = false;
void EditorNode::_set_main_scene_state(const Dictionary &p_state) {
if (get_edited_scene()) {
if (editor_main_screen->can_auto_switch_screens()) {
// Switch between 2D and 3D if currently in 2D or 3D.
@@ -4718,6 +4684,15 @@ void EditorNode::_set_main_scene_state(Dictionary p_state, Node *p_for_scene) {
RenderingServer::get_singleton()->sdfgi_reset();
}
Ref<ConfigFile> EditorNode::_load_scene_config(const String &p_scene_path) {
const String config_file_path = EditorPaths::get_singleton()->get_project_settings_dir().path_join(p_scene_path.get_file() + "-editstate-" + p_scene_path.md5_text() + ".cfg");
Ref<ConfigFile> editor_state_cf;
editor_state_cf.instantiate();
editor_state_cf->load(config_file_path);
return editor_state_cf;
}
bool EditorNode::is_changing_scene() const {
return changing_scene;
}
@@ -4730,14 +4705,17 @@ void EditorNode::_set_current_scene(int p_idx) {
_set_current_scene_nocheck(p_idx);
}
void EditorNode::_set_current_scene_nocheck(int p_idx) {
void EditorNode::_set_current_scene_nocheck(int p_idx, bool p_ignore_state) {
// Save the folding in case the scene gets reloaded.
if (editor_data.get_scene_path(p_idx) != "" && editor_data.get_edited_scene_root(p_idx)) {
const String scene_path = editor_data.get_scene_path(p_idx);
if (scene_path.is_empty() && editor_data.get_edited_scene_root(p_idx)) {
editor_folding.save_scene_folding(editor_data.get_edited_scene_root(p_idx), editor_data.get_scene_path(p_idx));
}
changing_scene = true;
editor_data.save_edited_scene_state(editor_selection, &editor_history, _get_main_scene_state());
if (!p_ignore_state) {
editor_data.save_edited_scene_state(editor_selection, &editor_history, _get_main_scene_state());
}
Node *old_scene = get_editor_data().get_edited_scene_root();
@@ -4762,43 +4740,30 @@ void EditorNode::_set_current_scene_nocheck(int p_idx) {
get_tree()->set_edited_scene_root(new_scene);
}
if (new_scene) {
if (new_scene->get_parent() != scene_root) {
scene_root->add_child(new_scene, true);
}
if (new_scene && new_scene->get_parent() != scene_root) {
scene_root->add_child(new_scene, true);
}
if (editor_data.check_and_update_scene(p_idx)) {
if (!editor_data.get_scene_path(p_idx).is_empty()) {
editor_folding.load_scene_folding(editor_data.get_edited_scene_root(p_idx), editor_data.get_scene_path(p_idx));
editor_folding.load_scene_folding(editor_data.get_edited_scene_root(p_idx), scene_path);
}
EditorUndoRedoManager::get_singleton()->clear_history(editor_data.get_scene_history_id(p_idx), false);
}
Dictionary state = editor_data.restore_edited_scene_state(editor_selection, &editor_history);
_edit_current(true);
SceneTreeDock::get_singleton()->get_tree_editor()->update_tree();
_update_title();
callable_mp(scene_tabs, &EditorSceneTabs::update_scene_tabs).call_deferred();
if (tabs_to_close.is_empty() && !restoring_scenes) {
callable_mp(this, &EditorNode::_set_main_scene_state).call_deferred(state, get_edited_scene()); // Do after everything else is done setting up.
}
if (!select_current_scene_file_requested && EDITOR_GET("interface/scene_tabs/auto_select_current_scene_file")) {
select_current_scene_file_requested = true;
callable_mp(this, &EditorNode::_nav_to_selected_scene).call_deferred();
}
const Dictionary state = editor_data.restore_edited_scene_state(editor_selection, &editor_history);
_set_main_scene_state(state);
_update_undo_redo_allowed();
_update_unsaved_cache();
}
void EditorNode::_nav_to_selected_scene() {
select_current_scene_file_requested = false;
const String scene_path = editor_data.get_scene_path(scene_tabs->get_current_tab());
if (!scene_path.is_empty()) {
changing_scene = false;
_edit_current(true);
if (EDITOR_GET("interface/scene_tabs/auto_select_current_scene_file")) {
FileSystemDock::get_singleton()->navigate_to_path(scene_path);
}
}
@@ -4860,19 +4825,14 @@ int EditorNode::new_scene() {
return idx;
}
Error EditorNode::load_scene(const String &p_scene, bool p_ignore_broken_deps, bool p_set_inherited, bool p_force_open_imported, bool p_silent_change_tab) {
if (!is_inside_tree()) {
defer_load_scene = p_scene;
return OK;
}
String lpath = ProjectSettings::get_singleton()->localize_path(ResourceUID::ensure_path(p_scene));
Error EditorNode::load_scene(const String &p_scene, bool p_ignore_broken_deps, bool p_set_inherited, bool p_force_open_imported, bool p_update_tabs) {
const String lpath = ProjectSettings::get_singleton()->localize_path(ResourceUID::ensure_path(p_scene));
_update_prev_closed_scenes(lpath, false);
if (!p_set_inherited) {
for (int i = 0; i < editor_data.get_edited_scene_count(); i++) {
if (editor_data.get_scene_path(i) == lpath) {
_set_current_scene(i);
// Already loaded, do nothing.
return OK;
}
}
@@ -4891,24 +4851,6 @@ Error EditorNode::load_scene(const String &p_scene, bool p_ignore_broken_deps, b
return ERR_FILE_NOT_FOUND;
}
int prev = editor_data.get_edited_scene();
int idx = prev;
if (prev == -1 || editor_data.get_edited_scene_root() || !editor_data.get_scene_path(prev).is_empty()) {
idx = editor_data.add_edited_scene(-1);
if (p_silent_change_tab) {
_set_current_scene_nocheck(idx);
} else {
_set_current_scene(idx);
}
} else {
EditorUndoRedoManager::get_singleton()->clear_history(editor_data.get_current_edited_scene_history_id(), false);
Dictionary state = editor_data.restore_edited_scene_state(editor_selection, &editor_history);
callable_mp(this, &EditorNode::_set_main_scene_state).call_deferred(state, get_edited_scene()); // Do after everything else is done setting up.
}
dependency_errors.clear();
Error err;
@@ -4918,21 +4860,11 @@ Error EditorNode::load_scene(const String &p_scene, bool p_ignore_broken_deps, b
current_menu_option = -1;
dependency_error->show(lpath, dependency_errors);
dependency_errors.clear();
if (prev != -1 && prev != idx) {
_set_current_scene(prev);
editor_data.remove_scene(idx);
}
return ERR_FILE_MISSING_DEPENDENCIES;
}
if (sdata.is_null()) {
_dialog_display_load_error(lpath, err);
if (prev != -1 && prev != idx) {
_set_current_scene(prev);
editor_data.remove_scene(idx);
}
return ERR_FILE_NOT_FOUND;
}
@@ -4954,7 +4886,6 @@ Error EditorNode::load_scene(const String &p_scene, bool p_ignore_broken_deps, b
ps->set_last_modified_time(sdata->get_last_modified_time());
sdata = ps;
}
} else {
sdata->set_path(lpath, true); // Take over path.
}
@@ -4963,10 +4894,6 @@ Error EditorNode::load_scene(const String &p_scene, bool p_ignore_broken_deps, b
if (!new_scene) {
sdata.unref();
_dialog_display_load_error(lpath, ERR_FILE_CORRUPT);
if (prev != -1 && prev != idx) {
_set_current_scene(prev);
editor_data.remove_scene(idx);
}
return ERR_FILE_CORRUPT;
}
@@ -4979,16 +4906,20 @@ Error EditorNode::load_scene(const String &p_scene, bool p_ignore_broken_deps, b
new_scene->set_scene_instance_state(Ref<SceneState>());
set_edited_scene(new_scene);
// When editor plugins load in, they might use node transforms during their own setup, so make sure they're up to date.
get_tree()->flush_transform_notifications();
if (!restoring_scenes) {
save_editor_layout_delayed();
_add_to_recent_scenes(lpath);
}
String config_file_path = EditorPaths::get_singleton()->get_project_settings_dir().path_join(lpath.get_file() + "-editstate-" + lpath.md5_text() + ".cfg");
Ref<ConfigFile> editor_state_cf;
editor_state_cf.instantiate();
Error editor_state_cf_err = editor_state_cf->load(config_file_path);
if (editor_state_cf_err == OK || editor_state_cf->has_section("editor_states")) {
_load_editor_plugin_states_from_config(editor_state_cf);
int idx = editor_data.get_edited_scene();
if (idx == -1 || editor_data.get_edited_scene_root() || !editor_data.get_scene_path(idx).is_empty()) {
idx = editor_data.add_edited_scene(-1);
}
editor_data.set_scene_root(idx, new_scene);
const Ref<ConfigFile> editor_state_cf = _load_scene_config(lpath);
if (editor_state_cf->has_section("editor_states")) {
editor_data.load_editor_plugin_states_from_config(editor_state_cf, idx);
}
if (editor_folding.has_folding_data(lpath)) {
@@ -4998,6 +4929,43 @@ Error EditorNode::load_scene(const String &p_scene, bool p_ignore_broken_deps, b
editor_folding.save_scene_folding(new_scene, lpath);
}
if (p_update_tabs) {
scene_tabs->update_scene_tabs();
}
return OK;
}
Error EditorNode::open_scene(const String &p_scene, bool p_ignore_broken_deps, bool p_set_inherited, bool p_force_open_imported) {
if (!is_inside_tree()) {
defer_load_scene = p_scene;
return OK;
}
const String lpath = ProjectSettings::get_singleton()->localize_path(ResourceUID::ensure_path(p_scene));
if (!p_set_inherited) {
for (int i = 0; i < editor_data.get_edited_scene_count(); i++) {
if (editor_data.get_scene_path(i) == lpath) {
_set_current_scene(i);
scene_tabs->update_scene_tabs();
return OK;
}
}
}
Error err = load_scene(p_scene, p_ignore_broken_deps, p_set_inherited, p_force_open_imported);
if (err != OK) {
return err;
}
int current_scene_idx = editor_data.get_edited_scene_count() - 1;
Node *new_scene = editor_data.get_edited_scene_root(current_scene_idx);
ERR_FAIL_NULL_V(new_scene, ERR_BUG);
_set_current_scene_nocheck(current_scene_idx);
// When editor plugins load in, they might use node transforms during their own setup, so make sure they're up to date.
get_tree()->flush_transform_notifications();
EditorDebuggerNode::get_singleton()->update_live_edit_root();
if (restoring_scenes) {
@@ -5008,32 +4976,11 @@ Error EditorNode::load_scene(const String &p_scene, bool p_ignore_broken_deps, b
}
}
// Load the selected nodes.
if (editor_state_cf->has_section_key("editor_states", "selected_nodes")) {
TypedArray<NodePath> selected_node_list = editor_state_cf->get_value("editor_states", "selected_nodes", TypedArray<String>());
for (int i = 0; i < selected_node_list.size(); i++) {
Node *selected_node = new_scene->get_node_or_null(selected_node_list[i]);
if (selected_node) {
editor_selection->add_node(selected_node);
}
}
}
if (!restoring_scenes) {
save_editor_layout_delayed();
}
if (p_set_inherited) {
EditorUndoRedoManager::get_singleton()->set_history_as_unsaved(editor_data.get_current_edited_scene_history_id());
}
_update_title();
scene_tabs->update_scene_tabs();
if (!restoring_scenes) {
_add_to_recent_scenes(lpath);
}
return OK;
}
@@ -5383,7 +5330,7 @@ bool EditorNode::has_previous_closed_scenes() const {
}
void EditorNode::edit_foreign_resource(Ref<Resource> p_resource) {
load_scene(p_resource->get_path().get_slice("::", 0));
open_scene(p_resource->get_path().get_slice("::", 0));
callable_mp(InspectorDock::get_singleton(), &InspectorDock::edit_resource).call_deferred(p_resource);
}
@@ -5493,7 +5440,7 @@ void EditorNode::_open_recent_scene(int p_idx) {
Array rc = EditorSettings::get_singleton()->get_project_metadata("recent_files", "scenes", Array());
ERR_FAIL_INDEX(p_idx, rc.size());
if (load_scene(rc[p_idx]) != OK) {
if (open_scene(rc[p_idx]) != OK) {
rc.remove_at(p_idx);
EditorSettings::get_singleton()->set_project_metadata("recent_files", "scenes", rc);
_update_recent_scenes();
@@ -6468,29 +6415,31 @@ void EditorNode::_load_open_scenes_from_config(Ref<ConfigFile> p_layout) {
return;
}
if (!p_layout->has_section(EDITOR_NODE_CONFIG_SECTION) ||
!p_layout->has_section_key(EDITOR_NODE_CONFIG_SECTION, "open_scenes")) {
if (!p_layout->has_section_key(EDITOR_NODE_CONFIG_SECTION, "open_scenes")) {
return;
}
restoring_scenes = true;
PackedStringArray scenes = p_layout->get_value(EDITOR_NODE_CONFIG_SECTION, "open_scenes");
for (int i = 0; i < scenes.size(); i++) {
if (FileAccess::exists(scenes[i])) {
load_scene(scenes[i]);
const PackedStringArray scenes = p_layout->get_value(EDITOR_NODE_CONFIG_SECTION, "open_scenes");
for (const String &scene_path : scenes) {
if (FileAccess::exists(scene_path)) {
load_scene(scene_path);
}
}
if (p_layout->has_section_key(EDITOR_NODE_CONFIG_SECTION, "current_scene")) {
String current_scene = p_layout->get_value(EDITOR_NODE_CONFIG_SECTION, "current_scene");
for (int i = 0; i < editor_data.get_edited_scene_count(); i++) {
if (editor_data.get_scene_path(i) == current_scene) {
_set_current_scene(i);
break;
}
bool current_scene_found = false;
const String current_scene = p_layout->get_value(EDITOR_NODE_CONFIG_SECTION, "current_scene", String());
for (int i = 0; i < editor_data.get_edited_scene_count(); i++) {
if (editor_data.get_scene_path(i) == current_scene) {
_set_current_scene_nocheck(i);
current_scene_found = true;
break;
}
}
if (!current_scene_found && editor_data.get_edited_scene_count() > 0) {
_set_current_scene_nocheck(0);
}
save_editor_layout_delayed();
@@ -7152,46 +7101,39 @@ void EditorNode::_notify_nodes_scene_reimported(Node *p_node, Array p_reimported
void EditorNode::reload_scene(const String &p_path) {
int scene_idx = -1;
String lpath = ProjectSettings::get_singleton()->localize_path(p_path);
const String lpath = ProjectSettings::get_singleton()->localize_path(p_path);
for (int i = 0; i < editor_data.get_edited_scene_count(); i++) {
if (editor_data.get_scene_path(i) == lpath) {
scene_idx = i;
break;
}
}
ERR_FAIL_COND_MSG(scene_idx == -1, vformat("Can't reload scene %s, as it's not opened.", p_path));
int current_tab = editor_data.get_edited_scene();
if (scene_idx == -1) {
if (get_edited_scene()) {
int current_history_id = editor_data.get_current_edited_scene_history_id();
bool is_unsaved = EditorUndoRedoManager::get_singleton()->is_history_unsaved(current_history_id);
// Scene is not open, so at it might be instantiated. We'll refresh the whole scene later.
EditorUndoRedoManager::get_singleton()->clear_history(current_history_id, false);
if (is_unsaved) {
EditorUndoRedoManager::get_singleton()->set_history_as_unsaved(current_history_id);
}
}
return;
}
if (current_tab == scene_idx) {
bool is_current_scene = current_tab == scene_idx;
if (is_current_scene) {
editor_data.apply_changes_in_editors();
_save_editor_states(p_path);
}
// Reload scene.
_remove_scene(scene_idx, false);
load_scene(p_path, true, false, true);
Error err = load_scene(p_path, true, false, false, false);
if (err != OK) {
return;
}
// Adjust index so tab is back a the previous position.
editor_data.move_edited_scene_to_index(scene_idx);
editor_data.move_scene_to_index(editor_data.get_edited_scene_count() - 1, scene_idx);
EditorUndoRedoManager::get_singleton()->clear_history(editor_data.get_scene_history_id(scene_idx), false);
// Recover the tab.
scene_tabs->set_current_tab(current_tab);
// Recover the current tab.
if (is_current_scene) {
_set_current_scene_nocheck(current_tab, true);
} else {
editor_data.set_edited_scene(current_tab);
scene_tabs->update_scene_tabs();
}
}
void EditorNode::find_all_instances_inheriting_path_in_node(Node *p_root, Node *p_node, const String &p_instance_path, HashSet<Node *> &p_instance_list) {
@@ -7726,11 +7668,11 @@ void EditorNode::call_run_scene(const String &p_scene, Vector<String> &r_args) {
void EditorNode::_inherit_imported(const String &p_action) {
open_imported->hide();
load_scene(open_import_request, true, true);
open_scene(open_import_request, true, true);
}
void EditorNode::_open_imported() {
load_scene(open_import_request, true, false, true);
open_scene(open_import_request, true, false, true);
}
void EditorNode::dim_editor(bool p_dimming) {
+6 -6
View File
@@ -452,8 +452,6 @@ private:
bool waiting_for_first_scan = true;
bool load_editor_layout_done = false;
bool select_current_scene_file_requested = false;
HashSet<Ref<Translation>> tracked_translations;
bool pending_translation_notification = false;
@@ -587,7 +585,7 @@ private:
void _save_scene_silently();
void _set_current_scene(int p_idx);
void _set_current_scene_nocheck(int p_idx);
void _set_current_scene_nocheck(int p_idx, bool p_ignore_state = false);
void _nav_to_selected_scene();
bool _validate_scene_recursive(const String &p_filename, Node *p_node);
void _save_scene(String p_file, int idx = -1);
@@ -637,7 +635,7 @@ private:
virtual void shortcut_input(const Ref<InputEvent> &p_event) override;
void _remove_edited_scene(bool p_change_tab = true);
void _remove_scene(int index, bool p_change_tab = true);
void _remove_scene(int p_idx, bool p_change_tab = true);
bool _find_and_save_resource(Ref<Resource> p_res, HashMap<Ref<Resource>, bool> &processed, int32_t flags);
bool _find_and_save_edited_subresources(Object *obj, HashMap<Ref<Resource>, bool> &processed, int32_t flags);
void _save_edited_subresources(Node *scene, HashMap<Ref<Resource>, bool> &processed, int32_t flags);
@@ -655,7 +653,8 @@ private:
void _restart_editor(bool p_goto_project_manager = false);
Dictionary _get_main_scene_state();
void _set_main_scene_state(Dictionary p_state, Node *p_for_scene);
void _set_main_scene_state(const Dictionary &p_state);
Ref<ConfigFile> _load_scene_config(const String &p_scene_path);
void _save_editor_layout();
void _load_editor_layout();
@@ -867,7 +866,8 @@ public:
void set_preview_locale(const String &p_locale);
int new_scene();
Error load_scene(const String &p_scene, bool p_ignore_broken_deps = false, bool p_set_inherited = false, bool p_force_open_imported = false, bool p_silent_change_tab = false);
Error load_scene(const String &p_scene, bool p_ignore_broken_deps = false, bool p_set_inherited = false, bool p_force_open_imported = false, bool p_update_tabs = true);
Error open_scene(const String &p_scene, bool p_ignore_broken_deps = false, bool p_set_inherited = false, bool p_force_open_imported = false);
Error load_resource(const String &p_resource, bool p_ignore_broken_deps = false);
Error load_scene_or_resource(const String &p_file, bool p_ignore_broken_deps = false, bool p_change_scene_tab_if_already_open = true);
@@ -123,7 +123,7 @@ void ProjectUpgradeTool::finish_upgrade() {
int step = 0;
for (const String &file_path : paths) {
ep.step(TTR("Re-saving scene:") + " " + file_path, step++);
EditorNode::get_singleton()->load_scene(file_path);
EditorNode::get_singleton()->open_scene(file_path);
EditorNode::get_singleton()->trigger_menu_option(EditorNode::SCENE_SAVE_SCENE, true);
EditorNode::get_singleton()->trigger_menu_option(EditorNode::SCENE_CLOSE, true);
}
@@ -233,7 +233,7 @@ void TileSetScenesCollectionSourceEditor::_scene_thumbnail_done(const String &p_
void TileSetScenesCollectionSourceEditor::_scenes_list_item_activated(int p_index) {
Ref<PackedScene> packed_scene = tile_set_scenes_collection_source->get_scene_tile_scene(scene_tiles_list->get_item_metadata(p_index));
if (packed_scene.is_valid()) {
EditorNode::get_singleton()->load_scene(packed_scene->get_path());
EditorNode::get_singleton()->open_scene(packed_scene->get_path());
}
}
+2 -2
View File
@@ -1663,7 +1663,7 @@ bool CanvasItemEditor::_gui_input_open_scene_on_double_click(const Ref<InputEven
if (selection.size() == 1) {
CanvasItem *ci = selection.front()->get();
if (ci->is_instance() && ci != EditorNode::get_singleton()->get_edited_scene()) {
EditorNode::get_singleton()->load_scene(ci->get_scene_file_path());
EditorNode::get_singleton()->open_scene(ci->get_scene_file_path());
return true;
}
}
@@ -6462,7 +6462,7 @@ void CanvasItemEditorViewport::_perform_drop_data() {
Ref<PackedScene> scene = res;
if (scene.is_valid()) {
// Without root node act the same as "Load Inherited Scene".
Error err = EditorNode::get_singleton()->load_scene(path, false, true);
Error err = EditorNode::get_singleton()->open_scene(path, false, true);
if (err != OK) {
accept->set_text(vformat(TTR("Error instantiating scene from %s."), path.get_file()));
accept->popup_centered();
+1 -1
View File
@@ -36,7 +36,7 @@
void PackedSceneEditor::_on_open_scene_pressed() {
// Using deferred call because changing scene updates the Inspector and thus destroys this plugin.
callable_mp(EditorNode::get_singleton(), &EditorNode::load_scene).call_deferred(packed_scene->get_path(), false, false, false, false);
callable_mp(EditorNode::get_singleton(), &EditorNode::open_scene).call_deferred(packed_scene->get_path(), false, false, false);
}
PackedSceneEditor::PackedSceneEditor(Ref<PackedScene> &p_packed_scene) {
+1 -1
View File
@@ -1133,7 +1133,7 @@ bool SceneTreeEditor::_update_filter_helper(TreeItem *p_parent, bool p_scroll_to
if (n && editor_selection->is_selected(n)) {
if (p_scroll_to_selected) {
// Needs to be deferred to account for possible root visibility change.
callable_mp(tree, &Tree::scroll_to_item).call_deferred(p_parent, false);
callable_mp(tree, &Tree::scroll_to_item).call_deferred(Variant(p_parent), false);
} else {
r_last_selected = p_parent;
}
+1 -1
View File
@@ -3695,7 +3695,7 @@ void ScriptEditor::_on_find_in_files_result_selected(const String &fpath, int li
scan_line--;
}
EditorNode::get_singleton()->load_scene(fpath);
EditorNode::get_singleton()->open_scene(fpath);
if (!script_id.is_empty()) {
Ref<Script> scr = ResourceLoader::load(fpath + "::" + script_id, "Script");
if (scr.is_valid()) {
+1 -1
View File
@@ -1293,7 +1293,7 @@ void ScriptTextEditor::_lookup_symbol(const String &p_symbol, int p_row, int p_c
// Check for Autoload scenes.
const ProjectSettings::AutoloadInfo &info = ProjectSettings::get_singleton()->get_autoload(p_symbol);
if (info.is_singleton) {
EditorNode::get_singleton()->load_scene(info.path);
EditorNode::get_singleton()->open_scene(info.path);
}
} else if (p_symbol.is_relative_path()) {
// Every symbol other than absolute path is relative path so keep this condition at last.
@@ -612,7 +612,7 @@ void VersionControlEditorPlugin::_cell_button_pressed(Object *p_item, int p_colu
file_path = "res://" + file_path;
if (ResourceLoader::get_resource_type(file_path) == "PackedScene") {
EditorNode::get_singleton()->load_scene(file_path);
EditorNode::get_singleton()->open_scene(file_path);
} else if (file_path.ends_with(".gd")) {
EditorNode::get_singleton()->load_resource(file_path);
ScriptEditor::get_singleton()->reload_scripts();
+1 -1
View File
@@ -4712,7 +4712,7 @@ int Main::start() {
#ifdef TOOLS_ENABLED
if (editor) {
if (!recovery_mode && (game_path != ResourceUID::ensure_path(String(GLOBAL_GET("application/run/main_scene"))) || !editor_node->has_scenes_in_session())) {
Error serr = editor_node->load_scene(local_game_path);
Error serr = editor_node->open_scene(local_game_path);
if (serr != OK) {
ERR_PRINT("Failed to load scene");
}