Skip to content

Commit

Permalink
Add multi window code and shader editors
Browse files Browse the repository at this point in the history
  • Loading branch information
trollodel committed May 10, 2023
1 parent 769d8a7 commit b4d6b47
Show file tree
Hide file tree
Showing 14 changed files with 952 additions and 97 deletions.
11 changes: 11 additions & 0 deletions doc/classes/EditorSettings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -580,6 +580,17 @@
<member name="interface/inspector/show_low_level_opentype_features" type="bool" setter="" getter="">
If [code]true[/code], display OpenType features marked as [code]hidden[/code] by the font file in the [Font] editor.
</member>
<member name="interface/multi_window/enable" type="bool" setter="" getter="">
If [code]true[/code], the multi window support in editor is enabled. The following panels can become dedicated windows (made floating): Docks, Script editor, and Shader editor.
[b]Note:[/b] When [member interface/editor/single_window_mode] is [code]true[/code], the multi window support is always disabled.
</member>
<member name="interface/multi_window/maximize_window" type="bool" setter="" getter="">
If [code]true[/code], when panels are made floating they will be maximized.
If [code]false[/code], when panels are made floating their position and size will match the ones when they are attached (excluding window border) to the editor window.
</member>
<member name="interface/multi_window/restore_windows_on_load" type="bool" setter="" getter="">
If [code]true[/code], the floating panel position, size, and screen will be saved on editor exit. On next launch the panels that were floating will be made floating in the saved positions, sizes and screens, if possible.
</member>
<member name="interface/scene_tabs/display_close_button" type="int" setter="" getter="">
Controls when the Close (X) button is displayed on scene tabs at the top of the editor.
</member>
Expand Down
5 changes: 4 additions & 1 deletion editor/editor_help_search.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,11 @@ void EditorHelpSearch::_notification(int p_what) {
_update_icons();
} break;

case NOTIFICATION_ENTER_TREE: {
case NOTIFICATION_READY: {
connect("confirmed", callable_mp(this, &EditorHelpSearch::_confirmed));
} break;

case NOTIFICATION_THEME_CHANGED: {
_update_icons();
} break;

Expand Down
191 changes: 131 additions & 60 deletions editor/editor_node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,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>
Expand Down Expand Up @@ -4470,67 +4471,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();
}
Expand Down Expand Up @@ -4772,6 +4772,35 @@ void EditorNode::_save_docks_to_config(Ref<ConfigFile> p_layout, const String &p
}
}

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);

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());
Expand Down Expand Up @@ -4918,7 +4947,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;
Expand All @@ -4928,6 +4974,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;
Expand All @@ -4942,24 +4989,45 @@ 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();
}
}

Expand Down Expand Up @@ -6824,13 +6892,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();

Expand Down
9 changes: 6 additions & 3 deletions editor/editor_node.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ class ProjectSettingsEditor;
class RunSettingsDialog;
class SceneImportSettings;
class ScriptCreateDialog;
class WindowWrapper;

class EditorNode : public Node {
GDCLASS(EditorNode, Node);
Expand Down Expand Up @@ -420,7 +421,7 @@ class EditorNode : public Node {
Button *new_inherited_button = nullptr;
String open_import_request;

Vector<Control *> floating_docks;
Vector<WindowWrapper *> floating_docks;

Button *dock_float = nullptr;
Button *dock_tab_move_left = nullptr;
Expand Down Expand Up @@ -628,8 +629,9 @@ class EditorNode : public Node {
void _dock_pre_popup(int p_which);
void _dock_split_dragged(int ofs);
void _dock_popup_exit();
void _dock_floating_close_request(Control *p_control);
void _dock_make_float();
void _dock_floating_close_request(WindowWrapper *p_wrapper);
void _dock_make_selected_float();
void _dock_make_float(Control *p_control, int p_slot_index, bool p_show_window = true);
void _scene_tab_changed(int p_tab);
void _proceed_closing_scene_tabs();
bool _is_closing_editor() const;
Expand All @@ -649,6 +651,7 @@ class EditorNode : public Node {
void _save_docks();
void _load_docks();
void _save_docks_to_config(Ref<ConfigFile> p_layout, const String &p_section);
void _restore_floating_dock(const Dictionary &p_dock_dump, Control *p_wrapper, int p_slot_index);
void _load_docks_from_config(Ref<ConfigFile> p_layout, const String &p_section);
void _update_dock_slots_visibility(bool p_keep_selected_tabs = false);
void _dock_tab_changed(int p_tab);
Expand Down
6 changes: 6 additions & 0 deletions editor/editor_settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,12 @@ void EditorSettings::_load_defaults(Ref<ConfigFile> p_extra_config) {
EDITOR_SETTING_USAGE(Variant::INT, PROPERTY_HINT_RANGE, "interface/scene_tabs/maximum_width", 350, "0,9999,1", PROPERTY_USAGE_DEFAULT)
_initial_set("interface/scene_tabs/show_script_button", false);

// Multi Window
EDITOR_SETTING(Variant::BOOL, PROPERTY_HINT_NONE, "interface/multi_window/enable", true, "");
EDITOR_SETTING(Variant::BOOL, PROPERTY_HINT_NONE, "interface/multi_window/restore_windows_on_load", true, "");
EDITOR_SETTING(Variant::BOOL, PROPERTY_HINT_NONE, "interface/multi_window/maximize_window", false, "");
set_restart_if_changed("interface/multi_window/enable", true);

/* Filesystem */

// External Programs
Expand Down
2 changes: 2 additions & 0 deletions editor/editor_themes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -833,6 +833,8 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {

// Script Editor
theme->set_stylebox("ScriptEditorPanel", "EditorStyles", make_empty_stylebox(default_margin_size, 0, default_margin_size, default_margin_size));
theme->set_stylebox("ScriptEditorPanelFloating", "EditorStyles", make_empty_stylebox(0, 0, 0, 0));

theme->set_stylebox("ScriptEditor", "EditorStyles", make_empty_stylebox(0, 0, 0, 0));

// Launch Pad and Play buttons
Expand Down
1 change: 1 addition & 0 deletions editor/icons/MakeFloating.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit b4d6b47

Please sign in to comment.