diff options
Diffstat (limited to 'editor/editor_node.cpp')
-rw-r--r-- | editor/editor_node.cpp | 487 |
1 files changed, 350 insertions, 137 deletions
diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 864d45230a..6f763d59f4 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -67,6 +67,7 @@ #include "editor/audio_stream_preview.h" #include "editor/debugger/editor_debugger_node.h" +#include "editor/debugger/script_editor_debugger.h" #include "editor/dependency_editor.h" #include "editor/editor_about.h" #include "editor/editor_audio_buses.h" @@ -147,6 +148,7 @@ #include "editor/project_settings_editor.h" #include "editor/register_exporters.h" #include "editor/scene_tree_dock.h" +#include "editor/window_wrapper.h" #include <stdio.h> #include <stdlib.h> @@ -156,6 +158,8 @@ EditorNode *EditorNode::singleton = nullptr; // The metadata key used to store and retrieve the version text to copy to the clipboard. static const String META_TEXT_TO_COPY = "text_to_copy"; +static const String EDITOR_NODE_CONFIG_SECTION = "EditorNode"; + class AcceptDialogAutoReparent : public AcceptDialog { GDCLASS(AcceptDialogAutoReparent, AcceptDialog); @@ -636,6 +640,8 @@ void EditorNode::_notification(int p_what) { } break; case NOTIFICATION_ENTER_TREE: { + get_tree()->set_disable_node_threading(true); // No node threading while running editor. + Engine::get_singleton()->set_editor_hint(true); Window *window = get_window(); @@ -1091,7 +1097,7 @@ void EditorNode::_sources_changed(bool p_exist) { EditorResourcePreview::get_singleton()->start(); } - _load_docks(); + _load_editor_layout(); if (!defer_load_scene.is_empty()) { Engine::get_singleton()->startup_benchmark_begin_measure("editor_load_scene"); @@ -1460,39 +1466,28 @@ void EditorNode::_dialog_display_load_error(String p_file, Error p_error) { } } -void EditorNode::_get_scene_metadata(const String &p_file) { +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; } - String path = EditorPaths::get_singleton()->get_project_settings_dir().path_join(p_file.get_file() + "-editstate-" + p_file.md5_text() + ".cfg"); - - Ref<ConfigFile> cf; - cf.instantiate(); - - Error err = cf->load(path); - if (err != OK || !cf->has_section("editor_states")) { - // Must not exist. - return; - } - List<String> esl; - cf->get_section_keys("editor_states", &esl); + p_config_file->get_section_keys("editor_states", &esl); Dictionary md; for (const String &E : esl) { - Variant st = cf->get_value("editor_states", E); + Variant st = p_config_file->get_value("editor_states", E); if (st.get_type() != Variant::NIL) { md[E] = st; } } - editor_data.set_editor_states(md); + editor_data.set_editor_plugin_states(md); } -void EditorNode::_set_scene_metadata(const String &p_file, int p_idx) { +void EditorNode::_save_editor_states(const String &p_file, int p_idx) { Node *scene = editor_data.get_edited_scene_root(p_idx); if (!scene) { @@ -1505,20 +1500,27 @@ void EditorNode::_set_scene_metadata(const String &p_file, int p_idx) { cf.instantiate(); Dictionary md; - if (p_idx < 0 || editor_data.get_edited_scene() == p_idx) { - md = editor_data.get_editor_states(); + md = editor_data.get_editor_plugin_states(); } else { md = editor_data.get_scene_editor_states(p_idx); } List<Variant> keys; md.get_key_list(&keys); - for (const Variant &E : keys) { cf->set_value("editor_states", E, md[E]); } + // 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 + "'."); } @@ -1810,7 +1812,7 @@ void EditorNode::_save_scene(String p_file, int idx) { _reset_animation_players(scene, &anim_backups); save_default_environment(); - _set_scene_metadata(p_file, idx); + _save_editor_states(p_file, idx); Ref<PackedScene> sdata; @@ -2022,7 +2024,7 @@ void EditorNode::_dialog_action(String p_file) { save_default_environment(); _save_scene_with_preview(p_file, scene_idx); _add_to_recent_scenes(p_file); - save_layout(); + save_editor_layout_delayed(); if (scene_idx != -1) { _discard_changes(); @@ -2602,7 +2604,7 @@ void EditorNode::_menu_option_confirm(int p_option, bool p_confirmed) { if (scene_idx != -1) { _discard_changes(); } - save_layout(); + save_editor_layout_delayed(); } else { show_save_accept(vformat(TTR("%s no longer exists! Please specify a new save location."), scene->get_scene_file_path().get_base_dir()), TTR("OK")); } @@ -3081,7 +3083,7 @@ int EditorNode::_next_unsaved_scene(bool p_valid_filename, int p_start) { void EditorNode::_exit_editor(int p_exit_code) { exiting = true; resource_preview->stop(); // Stop early to avoid crashes. - _save_docks(); + _save_editor_layout(); // Dim the editor window while it's quitting to make it clearer that it's busy. dim_editor(true); @@ -3750,7 +3752,14 @@ 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); - _get_scene_metadata(p_scene); + + String config_file_path = EditorPaths::get_singleton()->get_project_settings_dir().path_join(p_scene.get_file() + "-editstate-" + p_scene.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); + } _update_title(); _update_scene_tabs(); @@ -3771,8 +3780,20 @@ Error EditorNode::load_scene(const String &p_scene, bool p_ignore_broken_deps, b push_item(new_scene); + // 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_layout(); + save_editor_layout_delayed(); } return OK; @@ -4470,67 +4491,66 @@ void EditorNode::_copy_warning(const String &p_str) { DisplayServer::get_singleton()->clipboard_set(warning->get_text()); } -void EditorNode::_dock_floating_close_request(Control *p_control) { - // Through the MarginContainer to the Window. - Window *window = static_cast<Window *>(p_control->get_parent()->get_parent()); - int window_slot = window->get_meta("dock_slot"); +void EditorNode::_dock_floating_close_request(WindowWrapper *p_wrapper) { + int dock_slot_num = p_wrapper->get_meta("dock_slot"); + int dock_slot_index = p_wrapper->get_meta("dock_index"); - p_control->get_parent()->remove_child(p_control); - dock_slot[window_slot]->add_child(p_control); - dock_slot[window_slot]->move_child(p_control, MIN((int)window->get_meta("dock_index"), dock_slot[window_slot]->get_tab_count() - 1)); - dock_slot[window_slot]->set_current_tab(dock_slot[window_slot]->get_tab_idx_from_control(p_control)); - dock_slot[window_slot]->set_tab_title(dock_slot[window_slot]->get_tab_idx_from_control(p_control), TTRGET(p_control->get_name())); + // Give back the dock to the original owner. + Control *dock = p_wrapper->release_wrapped_control(); - window->queue_free(); + dock_slot[dock_slot_num]->add_child(dock); + dock_slot[dock_slot_num]->move_child(dock, MIN(dock_slot_index, dock_slot[dock_slot_num]->get_tab_count())); + dock_slot[dock_slot_num]->set_current_tab(dock_slot_index); - _update_dock_containers(); + floating_docks.erase(p_wrapper); + p_wrapper->queue_free(); - floating_docks.erase(p_control); + _update_dock_containers(); _edit_current(); } -void EditorNode::_dock_make_float() { +void EditorNode::_dock_make_selected_float() { Control *dock = dock_slot[dock_popup_selected_idx]->get_current_tab_control(); - ERR_FAIL_COND(!dock); + _dock_make_float(dock, dock_popup_selected_idx); + + dock_select_popup->hide(); + _edit_current(); +} + +void EditorNode::_dock_make_float(Control *p_dock, int p_slot_index, bool p_show_window) { + ERR_FAIL_COND(!p_dock); Size2 borders = Size2(4, 4) * EDSCALE; // Remember size and position before removing it from the main window. - Size2 dock_size = dock->get_size() + borders * 2; - Point2 dock_screen_pos = dock->get_global_position() + get_tree()->get_root()->get_position() - borders; - - int dock_index = dock->get_index(false); - dock_slot[dock_popup_selected_idx]->remove_child(dock); - - Window *window = memnew(Window); - window->set_title(TTRGET(dock->get_name())); - Panel *p = memnew(Panel); - p->add_theme_style_override("panel", gui_base->get_theme_stylebox(SNAME("PanelForeground"), SNAME("EditorStyles"))); - p->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); - window->add_child(p); - MarginContainer *margin = memnew(MarginContainer); - margin->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); - margin->add_theme_constant_override("margin_right", borders.width); - margin->add_theme_constant_override("margin_top", borders.height); - margin->add_theme_constant_override("margin_left", borders.width); - margin->add_theme_constant_override("margin_bottom", borders.height); - window->add_child(margin); - dock->set_anchors_and_offsets_preset(Control::PRESET_FULL_RECT); - margin->add_child(dock); - window->set_wrap_controls(true); - window->set_size(dock_size); - window->set_position(dock_screen_pos); - window->set_transient(true); - window->connect("close_requested", callable_mp(this, &EditorNode::_dock_floating_close_request).bind(dock)); - window->set_meta("dock_slot", dock_popup_selected_idx); - window->set_meta("dock_index", dock_index); - gui_base->add_child(window); + Size2 dock_size = p_dock->get_size() + borders * 2; + Point2 dock_screen_pos = p_dock->get_screen_position(); + + int dock_index = p_dock->get_index() - 1; + dock_slot[p_slot_index]->remove_child(p_dock); + + WindowWrapper *wrapper = memnew(WindowWrapper); + wrapper->set_window_title(vformat(TTR("%s - Godot Engine"), p_dock->get_name())); + wrapper->set_margins_enabled(true); + + gui_base->add_child(wrapper); + + wrapper->set_wrapped_control(p_dock); + wrapper->set_meta("dock_slot", p_slot_index); + wrapper->set_meta("dock_index", dock_index); + wrapper->set_meta("dock_name", p_dock->get_name().operator String()); + + wrapper->connect("window_close_requested", callable_mp(this, &EditorNode::_dock_floating_close_request).bind(wrapper)); dock_select_popup->hide(); + if (p_show_window) { + wrapper->restore_window(Rect2i(dock_screen_pos, dock_size), get_window()->get_current_screen()); + } + _update_dock_containers(); - floating_docks.push_back(dock); + floating_docks.push_back(wrapper); _edit_current(); } @@ -4607,7 +4627,7 @@ void EditorNode::_dock_select_input(const Ref<InputEvent> &p_input) { _update_dock_containers(); _edit_current(); - _save_docks(); + _save_editor_layout(); } } } @@ -4633,7 +4653,7 @@ void EditorNode::_dock_move_left() { dock_slot[dock_popup_selected_idx]->move_child(current_ctl, prev_ctl->get_index(false)); dock_select->queue_redraw(); _edit_current(); - _save_docks(); + _save_editor_layout(); } void EditorNode::_dock_move_right() { @@ -4645,7 +4665,7 @@ void EditorNode::_dock_move_right() { dock_slot[dock_popup_selected_idx]->move_child(next_ctl, current_ctl->get_index(false)); dock_select->queue_redraw(); _edit_current(); - _save_docks(); + _save_editor_layout(); } void EditorNode::_dock_select_draw() { @@ -4734,7 +4754,7 @@ void EditorNode::_dock_select_draw() { } } -void EditorNode::_save_docks() { +void EditorNode::_save_editor_layout() { if (waiting_for_first_scan) { return; // Scanning, do not touch docks. } @@ -4744,7 +4764,8 @@ void EditorNode::_save_docks() { config->load(EditorPaths::get_singleton()->get_project_settings_dir().path_join("editor_layout.cfg")); _save_docks_to_config(config, "docks"); - _save_open_scenes_to_config(config, "EditorNode"); + _save_open_scenes_to_config(config); + _save_central_editor_layout_to_config(config); editor_data.get_plugin_window_layout(config); config->save(EditorPaths::get_singleton()->get_project_settings_dir().path_join("editor_layout.cfg")); @@ -4770,12 +4791,41 @@ void EditorNode::_save_docks_to_config(Ref<ConfigFile> p_layout, const String &p if (!names.is_empty()) { p_layout->set_value(p_section, config_key, names); } + + int selected_tab_idx = dock_slot[i]->get_current_tab(); + if (selected_tab_idx >= 0) { + p_layout->set_value(p_section, "dock_" + itos(i + 1) + "_selected_tab_idx", selected_tab_idx); + } } - p_layout->set_value(p_section, "dock_filesystem_split", FileSystemDock::get_singleton()->get_split_offset()); - p_layout->set_value(p_section, "dock_filesystem_display_mode", FileSystemDock::get_singleton()->get_display_mode()); - p_layout->set_value(p_section, "dock_filesystem_file_sort", FileSystemDock::get_singleton()->get_file_sort()); - p_layout->set_value(p_section, "dock_filesystem_file_list_display_mode", FileSystemDock::get_singleton()->get_file_list_display_mode()); + Dictionary floating_docks_dump; + + for (WindowWrapper *wrapper : floating_docks) { + Control *dock = wrapper->get_wrapped_control(); + + Dictionary dock_dump; + dock_dump["window_rect"] = wrapper->get_window_rect(); + + int screen = wrapper->get_window_screen(); + dock_dump["window_screen"] = wrapper->get_window_screen(); + dock_dump["window_screen_rect"] = DisplayServer::get_singleton()->screen_get_usable_rect(screen); + + String name = dock->get_name(); + floating_docks_dump[name] = dock_dump; + + int dock_slot_id = wrapper->get_meta("dock_slot"); + String config_key = "dock_" + itos(dock_slot_id + 1); + + String names = p_layout->get_value(p_section, config_key, ""); + if (names.is_empty()) { + names = name; + } else { + names += "," + name; + } + p_layout->set_value(p_section, config_key, names); + } + + p_layout->set_value(p_section, "dock_floating", floating_docks_dump); for (int i = 0; i < vsplits.size(); i++) { if (vsplits[i]->is_visible_in_tree()) { @@ -4786,10 +4836,21 @@ void EditorNode::_save_docks_to_config(Ref<ConfigFile> p_layout, const String &p for (int i = 0; i < hsplits.size(); i++) { p_layout->set_value(p_section, "dock_hsplit_" + itos(i + 1), hsplits[i]->get_split_offset()); } + + // Save FileSystemDock state. + + p_layout->set_value(p_section, "dock_filesystem_split", FileSystemDock::get_singleton()->get_split_offset()); + p_layout->set_value(p_section, "dock_filesystem_display_mode", FileSystemDock::get_singleton()->get_display_mode()); + p_layout->set_value(p_section, "dock_filesystem_file_sort", FileSystemDock::get_singleton()->get_file_sort()); + p_layout->set_value(p_section, "dock_filesystem_file_list_display_mode", FileSystemDock::get_singleton()->get_file_list_display_mode()); + PackedStringArray selected_files = FileSystemDock::get_singleton()->get_selected_paths(); + p_layout->set_value(p_section, "dock_filesystem_selected_paths", selected_files); + Vector<String> uncollapsed_paths = FileSystemDock::get_singleton()->get_uncollapsed_paths(); + p_layout->set_value(p_section, "dock_filesystem_uncollapsed_paths", uncollapsed_paths); } -void EditorNode::_save_open_scenes_to_config(Ref<ConfigFile> p_layout, const String &p_section) { - Array scenes; +void EditorNode::_save_open_scenes_to_config(Ref<ConfigFile> p_layout) { + PackedStringArray scenes; for (int i = 0; i < editor_data.get_edited_scene_count(); i++) { String path = editor_data.get_scene_path(i); if (path.is_empty()) { @@ -4797,18 +4858,21 @@ void EditorNode::_save_open_scenes_to_config(Ref<ConfigFile> p_layout, const Str } scenes.push_back(path); } - p_layout->set_value(p_section, "open_scenes", scenes); + p_layout->set_value(EDITOR_NODE_CONFIG_SECTION, "open_scenes", scenes); + + String currently_edited_scene_path = editor_data.get_scene_path(editor_data.get_edited_scene()); + p_layout->set_value(EDITOR_NODE_CONFIG_SECTION, "current_scene", currently_edited_scene_path); } -void EditorNode::save_layout() { - dock_drag_timer->start(); +void EditorNode::save_editor_layout_delayed() { + editor_layout_save_delay_timer->start(); } void EditorNode::_dock_split_dragged(int ofs) { - dock_drag_timer->start(); + editor_layout_save_delay_timer->start(); } -void EditorNode::_load_docks() { +void EditorNode::_load_editor_layout() { Ref<ConfigFile> config; config.instantiate(); Error err = config->load(EditorPaths::get_singleton()->get_project_settings_dir().path_join("editor_layout.cfg")); @@ -4821,7 +4885,8 @@ void EditorNode::_load_docks() { } _load_docks_from_config(config, "docks"); - _load_open_scenes_from_config(config, "EditorNode"); + _load_open_scenes_from_config(config); + _load_central_editor_layout_from_config(config); editor_data.set_plugin_window_layout(config); } @@ -4918,7 +4983,24 @@ void EditorNode::_dock_tab_changed(int p_tab) { } } +void EditorNode::_restore_floating_dock(const Dictionary &p_dock_dump, Control *p_dock, int p_slot_index) { + WindowWrapper *wrapper = Object::cast_to<WindowWrapper>(p_dock); + if (!wrapper) { + _dock_make_float(p_dock, p_slot_index, false); + wrapper = floating_docks[floating_docks.size() - 1]; + } + + wrapper->restore_window_from_saved_position( + p_dock_dump.get("window_rect", Rect2i()), + p_dock_dump.get("window_screen", -1), + p_dock_dump.get("window_screen_rect", Rect2i())); +} + void EditorNode::_load_docks_from_config(Ref<ConfigFile> p_layout, const String &p_section) { + Dictionary floating_docks_dump = p_layout->get_value(p_section, "dock_floating", Dictionary()); + + bool restore_window_on_load = EDITOR_GET("interface/multi_window/restore_windows_on_load"); + for (int i = 0; i < DOCK_SLOT_MAX; i++) { if (!p_layout->has_section_key(p_section, "dock_" + itos(i + 1))) { continue; @@ -4928,6 +5010,7 @@ void EditorNode::_load_docks_from_config(Ref<ConfigFile> p_layout, const String for (int j = names.size() - 1; j >= 0; j--) { String name = names[j]; + // FIXME: Find it, in a horribly inefficient way. int atidx = -1; Control *node = nullptr; @@ -4942,45 +5025,55 @@ void EditorNode::_load_docks_from_config(Ref<ConfigFile> p_layout, const String atidx = k; break; } - if (atidx == -1) { // Well, it's not anywhere. + + if (atidx == -1) { + // Try floating docks. + for (WindowWrapper *wrapper : floating_docks) { + if (wrapper->get_meta("dock_name") == name) { + if (restore_window_on_load && floating_docks_dump.has(name)) { + _restore_floating_dock(floating_docks_dump[name], wrapper, i); + return; + } else { + _dock_floating_close_request(wrapper); + atidx = wrapper->get_meta("dock_index"); + } + } + } + + // Well, it's not anywhere. continue; } if (atidx == i) { dock_slot[i]->move_child(node, 0); - continue; - } + } else if (atidx != -1) { + dock_slot[atidx]->remove_child(node); - dock_slot[atidx]->remove_child(node); + if (dock_slot[atidx]->get_tab_count() == 0) { + dock_slot[atidx]->hide(); + } + dock_slot[i]->add_child(node); + dock_slot[i]->move_child(node, 0); + dock_slot[i]->set_tab_title(0, TTRGET(node->get_name())); + dock_slot[i]->show(); + } - if (dock_slot[atidx]->get_tab_count() == 0) { - dock_slot[atidx]->hide(); + WindowWrapper *wrapper = Object::cast_to<WindowWrapper>(node); + if (restore_window_on_load && floating_docks_dump.has(name)) { + _restore_floating_dock(floating_docks_dump[name], node, i); + } else if (wrapper) { + _dock_floating_close_request(wrapper); } - dock_slot[i]->add_child(node); - dock_slot[i]->move_child(node, 0); - dock_slot[i]->set_tab_title(0, TTRGET(node->get_name())); - dock_slot[i]->show(); } - } - - if (p_layout->has_section_key(p_section, "dock_filesystem_split")) { - int fs_split_ofs = p_layout->get_value(p_section, "dock_filesystem_split"); - FileSystemDock::get_singleton()->set_split_offset(fs_split_ofs); - } - if (p_layout->has_section_key(p_section, "dock_filesystem_display_mode")) { - FileSystemDock::DisplayMode dock_filesystem_display_mode = FileSystemDock::DisplayMode(int(p_layout->get_value(p_section, "dock_filesystem_display_mode"))); - FileSystemDock::get_singleton()->set_display_mode(dock_filesystem_display_mode); - } - - if (p_layout->has_section_key(p_section, "dock_filesystem_file_sort")) { - FileSystemDock::FileSortOption dock_filesystem_file_sort = FileSystemDock::FileSortOption(int(p_layout->get_value(p_section, "dock_filesystem_file_sort"))); - FileSystemDock::get_singleton()->set_file_sort(dock_filesystem_file_sort); - } + if (!p_layout->has_section_key(p_section, "dock_" + itos(i + 1) + "_selected_tab_idx")) { + continue; + } - if (p_layout->has_section_key(p_section, "dock_filesystem_file_list_display_mode")) { - FileSystemDock::FileListDisplayMode dock_filesystem_file_list_display_mode = FileSystemDock::FileListDisplayMode(int(p_layout->get_value(p_section, "dock_filesystem_file_list_display_mode"))); - FileSystemDock::get_singleton()->set_file_list_display_mode(dock_filesystem_file_list_display_mode); + int selected_tab_idx = p_layout->get_value(p_section, "dock_" + itos(i + 1) + "_selected_tab_idx"); + if (selected_tab_idx >= 0 && selected_tab_idx < dock_slot[i]->get_tab_count()) { + dock_slot[i]->call_deferred("set_current_tab", selected_tab_idx); + } } for (int i = 0; i < vsplits.size(); i++) { @@ -5020,24 +5113,141 @@ void EditorNode::_load_docks_from_config(Ref<ConfigFile> p_layout, const String dock_slot[i]->set_current_tab(0); } } + + // FileSystemDock. + + if (p_layout->has_section_key(p_section, "dock_filesystem_split")) { + int fs_split_ofs = p_layout->get_value(p_section, "dock_filesystem_split"); + FileSystemDock::get_singleton()->set_split_offset(fs_split_ofs); + } + + if (p_layout->has_section_key(p_section, "dock_filesystem_display_mode")) { + FileSystemDock::DisplayMode dock_filesystem_display_mode = FileSystemDock::DisplayMode(int(p_layout->get_value(p_section, "dock_filesystem_display_mode"))); + FileSystemDock::get_singleton()->set_display_mode(dock_filesystem_display_mode); + } + + if (p_layout->has_section_key(p_section, "dock_filesystem_file_sort")) { + FileSystemDock::FileSortOption dock_filesystem_file_sort = FileSystemDock::FileSortOption(int(p_layout->get_value(p_section, "dock_filesystem_file_sort"))); + FileSystemDock::get_singleton()->set_file_sort(dock_filesystem_file_sort); + } + + if (p_layout->has_section_key(p_section, "dock_filesystem_file_list_display_mode")) { + FileSystemDock::FileListDisplayMode dock_filesystem_file_list_display_mode = FileSystemDock::FileListDisplayMode(int(p_layout->get_value(p_section, "dock_filesystem_file_list_display_mode"))); + FileSystemDock::get_singleton()->set_file_list_display_mode(dock_filesystem_file_list_display_mode); + } + + if (p_layout->has_section_key(p_section, "dock_filesystem_selected_paths")) { + PackedStringArray dock_filesystem_selected_paths = p_layout->get_value(p_section, "dock_filesystem_selected_paths"); + for (int i = 0; i < dock_filesystem_selected_paths.size(); i++) { + FileSystemDock::get_singleton()->select_file(dock_filesystem_selected_paths[i]); + } + } + + // Restore collapsed state of FileSystemDock. + if (p_layout->has_section_key(p_section, "dock_filesystem_uncollapsed_paths")) { + PackedStringArray uncollapsed_tis = p_layout->get_value(p_section, "dock_filesystem_uncollapsed_paths"); + for (int i = 0; i < uncollapsed_tis.size(); i++) { + TreeItem *uncollapsed_ti = FileSystemDock::get_singleton()->get_tree_control()->get_item_with_metadata(uncollapsed_tis[i], 0); + if (uncollapsed_ti) { + uncollapsed_ti->set_collapsed(false); + } + } + FileSystemDock::get_singleton()->get_tree_control()->queue_redraw(); + } } -void EditorNode::_load_open_scenes_from_config(Ref<ConfigFile> p_layout, const String &p_section) { +void EditorNode::_save_central_editor_layout_to_config(Ref<ConfigFile> p_config_file) { + // Bottom panel. + + int center_split_offset = center_split->get_split_offset(); + p_config_file->set_value(EDITOR_NODE_CONFIG_SECTION, "center_split_offset", center_split_offset); + + int selected_bottom_panel_item_idx = -1; + for (int i = 0; i < bottom_panel_items.size(); i++) { + if (bottom_panel_items[i].button->is_pressed()) { + selected_bottom_panel_item_idx = i; + break; + } + } + if (selected_bottom_panel_item_idx != -1) { + p_config_file->set_value(EDITOR_NODE_CONFIG_SECTION, "selected_bottom_panel_item", selected_bottom_panel_item_idx); + } + + // Debugger tab. + + int selected_default_debugger_tab_idx = EditorDebuggerNode::get_singleton()->get_default_debugger()->get_current_debugger_tab(); + p_config_file->set_value(EDITOR_NODE_CONFIG_SECTION, "selected_default_debugger_tab_idx", selected_default_debugger_tab_idx); + + // Main editor (plugin). + + int selected_main_editor_idx = -1; + for (int i = 0; i < main_editor_buttons.size(); i++) { + if (main_editor_buttons[i]->is_pressed()) { + selected_main_editor_idx = i; + break; + } + } + if (selected_main_editor_idx != -1) { + p_config_file->set_value(EDITOR_NODE_CONFIG_SECTION, "selected_main_editor_idx", selected_main_editor_idx); + } +} + +void EditorNode::_load_central_editor_layout_from_config(Ref<ConfigFile> p_config_file) { + // Bottom panel. + + if (p_config_file->has_section_key(EDITOR_NODE_CONFIG_SECTION, "center_split_offset")) { + int center_split_offset = p_config_file->get_value(EDITOR_NODE_CONFIG_SECTION, "center_split_offset"); + center_split->set_split_offset(center_split_offset); + } + + if (p_config_file->has_section_key(EDITOR_NODE_CONFIG_SECTION, "selected_bottom_panel_item")) { + int selected_bottom_panel_item_idx = p_config_file->get_value(EDITOR_NODE_CONFIG_SECTION, "selected_bottom_panel_item"); + if (selected_bottom_panel_item_idx >= 0 && selected_bottom_panel_item_idx < bottom_panel_items.size()) { + _bottom_panel_switch(true, selected_bottom_panel_item_idx); + } + } + + // Debugger tab. + + if (p_config_file->has_section_key(EDITOR_NODE_CONFIG_SECTION, "selected_default_debugger_tab_idx")) { + int selected_default_debugger_tab_idx = p_config_file->get_value(EDITOR_NODE_CONFIG_SECTION, "selected_default_debugger_tab_idx"); + EditorDebuggerNode::get_singleton()->get_default_debugger()->switch_to_debugger(selected_default_debugger_tab_idx); + } + + // Main editor (plugin). + + if (p_config_file->has_section_key(EDITOR_NODE_CONFIG_SECTION, "selected_main_editor_idx")) { + int selected_main_editor_idx = p_config_file->get_value(EDITOR_NODE_CONFIG_SECTION, "selected_main_editor_idx"); + if (selected_main_editor_idx >= 0 && selected_main_editor_idx < main_editor_buttons.size()) { + callable_mp(this, &EditorNode::editor_select).call_deferred(selected_main_editor_idx); + } + } +} + +void EditorNode::_load_open_scenes_from_config(Ref<ConfigFile> p_layout) { if (!bool(EDITOR_GET("interface/scene_tabs/restore_scenes_on_load"))) { return; } - if (!p_layout->has_section(p_section) || !p_layout->has_section_key(p_section, "open_scenes")) { + if (!p_layout->has_section(EDITOR_NODE_CONFIG_SECTION) || + !p_layout->has_section_key(EDITOR_NODE_CONFIG_SECTION, "open_scenes")) { return; } restoring_scenes = true; - Array scenes = p_layout->get_value(p_section, "open_scenes"); + PackedStringArray scenes = p_layout->get_value(EDITOR_NODE_CONFIG_SECTION, "open_scenes"); for (int i = 0; i < scenes.size(); i++) { load_scene(scenes[i]); } - save_layout(); + + 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"); + int current_scene_idx = scenes.find(current_scene); + set_current_scene(current_scene_idx); + } + + save_editor_layout_delayed(); restoring_scenes = false; } @@ -5052,10 +5262,10 @@ bool EditorNode::has_scenes_in_session() { if (err != OK) { return false; } - if (!config->has_section("EditorNode") || !config->has_section_key("EditorNode", "open_scenes")) { + if (!config->has_section(EDITOR_NODE_CONFIG_SECTION) || !config->has_section_key(EDITOR_NODE_CONFIG_SECTION, "open_scenes")) { return false; } - Array scenes = config->get_value("EditorNode", "open_scenes"); + Array scenes = config->get_value(EDITOR_NODE_CONFIG_SECTION, "open_scenes"); return !scenes.is_empty(); } @@ -5181,7 +5391,7 @@ void EditorNode::_layout_menu_option(int p_id) { } break; case SETTINGS_LAYOUT_DEFAULT: { _load_docks_from_config(default_layout, "docks"); - _save_docks(); + _save_editor_layout(); } break; default: { Ref<ConfigFile> config; @@ -5192,7 +5402,7 @@ void EditorNode::_layout_menu_option(int p_id) { } _load_docks_from_config(config, editor_layouts->get_item_text(p_id)); - _save_docks(); + _save_editor_layout(); } } } @@ -5264,7 +5474,7 @@ void EditorNode::_scene_tab_closed(int p_tab, int p_option) { _discard_changes(); } - save_layout(); + save_editor_layout_delayed(); _update_scene_tabs(); } @@ -5765,7 +5975,7 @@ void EditorNode::reload_scene(const String &p_path) { if (current_tab == scene_idx) { editor_data.apply_changes_in_editors(); - _set_scene_metadata(p_path); + _save_editor_states(p_path); } // Reload scene. @@ -6824,13 +7034,16 @@ EditorNode::EditorNode() { dock_select->set_v_size_flags(Control::SIZE_EXPAND_FILL); dock_vb->add_child(dock_select); - dock_float = memnew(Button); - dock_float->set_text(TTR("Make Floating")); - dock_float->set_focus_mode(Control::FOCUS_NONE); - dock_float->set_h_size_flags(Control::SIZE_SHRINK_CENTER); - dock_float->connect("pressed", callable_mp(this, &EditorNode::_dock_make_float)); + if (!SceneTree::get_singleton()->get_root()->is_embedding_subwindows() && EDITOR_GET("interface/multi_window/enable")) { + dock_float = memnew(Button); + dock_float->set_icon(theme->get_icon("MakeFloating", "EditorIcons")); + dock_float->set_text(TTR("Make Floating")); + dock_float->set_focus_mode(Control::FOCUS_NONE); + dock_float->set_h_size_flags(Control::SIZE_SHRINK_CENTER); + dock_float->connect("pressed", callable_mp(this, &EditorNode::_dock_make_selected_float)); - dock_vb->add_child(dock_float); + dock_vb->add_child(dock_float); + } dock_select_popup->reset_size(); @@ -6845,11 +7058,11 @@ EditorNode::EditorNode() { dock_slot[i]->set_use_hidden_tabs_for_min_size(true); } - dock_drag_timer = memnew(Timer); - add_child(dock_drag_timer); - dock_drag_timer->set_wait_time(0.5); - dock_drag_timer->set_one_shot(true); - dock_drag_timer->connect("timeout", callable_mp(this, &EditorNode::_save_docks)); + editor_layout_save_delay_timer = memnew(Timer); + add_child(editor_layout_save_delay_timer); + editor_layout_save_delay_timer->set_wait_time(0.5); + editor_layout_save_delay_timer->set_one_shot(true); + editor_layout_save_delay_timer->connect("timeout", callable_mp(this, &EditorNode::_save_editor_layout)); top_split = memnew(VSplitContainer); center_split->add_child(top_split); @@ -7330,7 +7543,7 @@ EditorNode::EditorNode() { FileSystemDock *filesystem_dock = memnew(FileSystemDock); filesystem_dock->connect("inherit", callable_mp(this, &EditorNode::_inherit_request)); filesystem_dock->connect("instantiate", callable_mp(this, &EditorNode::_instantiate_request)); - filesystem_dock->connect("display_mode_changed", callable_mp(this, &EditorNode::_save_docks)); + filesystem_dock->connect("display_mode_changed", callable_mp(this, &EditorNode::_save_editor_layout)); get_project_settings()->connect_filesystem_dock_signals(filesystem_dock); history_dock = memnew(HistoryDock); |