Extract editor dock manager
This commit is contained in:
parent
26b1fd0d84
commit
2323f040e9
10 changed files with 1033 additions and 782 deletions
716
editor/editor_dock_manager.cpp
Normal file
716
editor/editor_dock_manager.cpp
Normal file
|
@ -0,0 +1,716 @@
|
||||||
|
/**************************************************************************/
|
||||||
|
/* editor_dock_manager.cpp */
|
||||||
|
/**************************************************************************/
|
||||||
|
/* This file is part of: */
|
||||||
|
/* GODOT ENGINE */
|
||||||
|
/* https://godotengine.org */
|
||||||
|
/**************************************************************************/
|
||||||
|
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||||
|
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||||
|
/* */
|
||||||
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||||
|
/* a copy of this software and associated documentation files (the */
|
||||||
|
/* "Software"), to deal in the Software without restriction, including */
|
||||||
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||||
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||||
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||||
|
/* the following conditions: */
|
||||||
|
/* */
|
||||||
|
/* The above copyright notice and this permission notice shall be */
|
||||||
|
/* included in all copies or substantial portions of the Software. */
|
||||||
|
/* */
|
||||||
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||||
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||||
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||||
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||||
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||||
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||||
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
#include "editor_dock_manager.h"
|
||||||
|
|
||||||
|
#include "scene/gui/box_container.h"
|
||||||
|
#include "scene/gui/button.h"
|
||||||
|
#include "scene/gui/label.h"
|
||||||
|
#include "scene/gui/popup.h"
|
||||||
|
#include "scene/gui/split_container.h"
|
||||||
|
#include "scene/gui/tab_container.h"
|
||||||
|
#include "scene/main/window.h"
|
||||||
|
|
||||||
|
#include "editor/editor_node.h"
|
||||||
|
#include "editor/editor_scale.h"
|
||||||
|
#include "editor/editor_settings.h"
|
||||||
|
#include "editor/editor_string_names.h"
|
||||||
|
#include "editor/filesystem_dock.h"
|
||||||
|
#include "editor/window_wrapper.h"
|
||||||
|
|
||||||
|
EditorDockManager *EditorDockManager::singleton = nullptr;
|
||||||
|
|
||||||
|
void DockSplitContainer::_update_visibility() {
|
||||||
|
if (is_updating) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
is_updating = true;
|
||||||
|
bool any_visible = false;
|
||||||
|
for (int i = 0; i < 2; i++) {
|
||||||
|
Control *split = get_containable_child(i);
|
||||||
|
if (split && split->is_visible()) {
|
||||||
|
any_visible = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
set_visible(any_visible);
|
||||||
|
is_updating = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DockSplitContainer::add_child_notify(Node *p_child) {
|
||||||
|
SplitContainer::add_child_notify(p_child);
|
||||||
|
|
||||||
|
Control *child_control = nullptr;
|
||||||
|
for (int i = 0; i < 2; i++) {
|
||||||
|
Control *split = get_containable_child(i);
|
||||||
|
if (p_child == split) {
|
||||||
|
child_control = split;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!child_control) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
child_control->connect("visibility_changed", callable_mp(this, &DockSplitContainer::_update_visibility));
|
||||||
|
_update_visibility();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DockSplitContainer::remove_child_notify(Node *p_child) {
|
||||||
|
SplitContainer::remove_child_notify(p_child);
|
||||||
|
|
||||||
|
Control *child_control = nullptr;
|
||||||
|
for (int i = 0; i < 2; i++) {
|
||||||
|
Control *split = get_containable_child(i);
|
||||||
|
if (p_child == split) {
|
||||||
|
child_control = split;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!child_control) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
child_control->disconnect("visibility_changed", callable_mp(this, &DockSplitContainer::_update_visibility));
|
||||||
|
_update_visibility();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorDockManager::_dock_select_popup_theme_changed() {
|
||||||
|
if (dock_float) {
|
||||||
|
dock_float->set_icon(dock_select_popup->get_editor_theme_icon(SNAME("MakeFloating")));
|
||||||
|
}
|
||||||
|
if (dock_select_popup->is_layout_rtl()) {
|
||||||
|
dock_tab_move_left->set_icon(dock_select_popup->get_editor_theme_icon(SNAME("Forward")));
|
||||||
|
dock_tab_move_right->set_icon(dock_select_popup->get_editor_theme_icon(SNAME("Back")));
|
||||||
|
} else {
|
||||||
|
dock_tab_move_left->set_icon(dock_select_popup->get_editor_theme_icon(SNAME("Back")));
|
||||||
|
dock_tab_move_right->set_icon(dock_select_popup->get_editor_theme_icon(SNAME("Forward")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorDockManager::_dock_popup_exit() {
|
||||||
|
dock_select_rect_over_idx = -1;
|
||||||
|
dock_select->queue_redraw();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorDockManager::_dock_pre_popup(int p_dock_slot) {
|
||||||
|
dock_popup_selected_idx = p_dock_slot;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorDockManager::_dock_move_left() {
|
||||||
|
if (dock_popup_selected_idx < 0 || dock_popup_selected_idx >= DOCK_SLOT_MAX) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Control *current_ctl = dock_slot[dock_popup_selected_idx]->get_tab_control(dock_slot[dock_popup_selected_idx]->get_current_tab());
|
||||||
|
Control *prev_ctl = dock_slot[dock_popup_selected_idx]->get_tab_control(dock_slot[dock_popup_selected_idx]->get_current_tab() - 1);
|
||||||
|
if (!current_ctl || !prev_ctl) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dock_slot[dock_popup_selected_idx]->move_child(current_ctl, prev_ctl->get_index(false));
|
||||||
|
dock_select->queue_redraw();
|
||||||
|
_edit_current();
|
||||||
|
emit_signal(SNAME("layout_changed"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorDockManager::_dock_move_right() {
|
||||||
|
if (dock_popup_selected_idx < 0 || dock_popup_selected_idx >= DOCK_SLOT_MAX) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Control *current_ctl = dock_slot[dock_popup_selected_idx]->get_tab_control(dock_slot[dock_popup_selected_idx]->get_current_tab());
|
||||||
|
Control *next_ctl = dock_slot[dock_popup_selected_idx]->get_tab_control(dock_slot[dock_popup_selected_idx]->get_current_tab() + 1);
|
||||||
|
if (!current_ctl || !next_ctl) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dock_slot[dock_popup_selected_idx]->move_child(next_ctl, current_ctl->get_index(false));
|
||||||
|
dock_select->queue_redraw();
|
||||||
|
_edit_current();
|
||||||
|
emit_signal(SNAME("layout_changed"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorDockManager::_dock_select_input(const Ref<InputEvent> &p_input) {
|
||||||
|
Ref<InputEventMouse> me = p_input;
|
||||||
|
|
||||||
|
if (me.is_valid()) {
|
||||||
|
Vector2 point = me->get_position();
|
||||||
|
|
||||||
|
int nrect = -1;
|
||||||
|
for (int i = 0; i < DOCK_SLOT_MAX; i++) {
|
||||||
|
if (dock_select_rect[i].has_point(point)) {
|
||||||
|
nrect = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nrect != dock_select_rect_over_idx) {
|
||||||
|
dock_select->queue_redraw();
|
||||||
|
dock_select_rect_over_idx = nrect;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nrect == -1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ref<InputEventMouseButton> mb = me;
|
||||||
|
|
||||||
|
if (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT && mb->is_pressed() && dock_popup_selected_idx != nrect) {
|
||||||
|
dock_slot[nrect]->move_tab_from_tab_container(dock_slot[dock_popup_selected_idx], dock_slot[dock_popup_selected_idx]->get_current_tab(), dock_slot[nrect]->get_tab_count());
|
||||||
|
|
||||||
|
if (dock_slot[dock_popup_selected_idx]->get_tab_count() == 0) {
|
||||||
|
dock_slot[dock_popup_selected_idx]->hide();
|
||||||
|
} else {
|
||||||
|
dock_slot[dock_popup_selected_idx]->set_current_tab(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
dock_popup_selected_idx = nrect;
|
||||||
|
dock_slot[nrect]->show();
|
||||||
|
dock_select->queue_redraw();
|
||||||
|
|
||||||
|
update_dock_slots_visibility(true);
|
||||||
|
|
||||||
|
_edit_current();
|
||||||
|
emit_signal(SNAME("layout_changed"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorDockManager::_dock_select_draw() {
|
||||||
|
Size2 s = dock_select->get_size();
|
||||||
|
s.y /= 2.0;
|
||||||
|
s.x /= 6.0;
|
||||||
|
|
||||||
|
Color used = Color(0.6, 0.6, 0.6, 0.8);
|
||||||
|
Color used_selected = Color(0.8, 0.8, 0.8, 0.8);
|
||||||
|
Color tab_selected = dock_select->get_theme_color(SNAME("mono_color"), EditorStringName(Editor));
|
||||||
|
Color unused = used;
|
||||||
|
unused.a = 0.4;
|
||||||
|
Color unusable = unused;
|
||||||
|
unusable.a = 0.1;
|
||||||
|
|
||||||
|
Rect2 unr(s.x * 2, 0, s.x * 2, s.y * 2);
|
||||||
|
unr.position += Vector2(2, 5);
|
||||||
|
unr.size -= Vector2(4, 7);
|
||||||
|
|
||||||
|
dock_select->draw_rect(unr, unusable);
|
||||||
|
|
||||||
|
dock_tab_move_left->set_disabled(true);
|
||||||
|
dock_tab_move_right->set_disabled(true);
|
||||||
|
|
||||||
|
if (dock_popup_selected_idx != -1 && dock_slot[dock_popup_selected_idx]->get_tab_count()) {
|
||||||
|
dock_tab_move_left->set_disabled(dock_slot[dock_popup_selected_idx]->get_current_tab() == 0);
|
||||||
|
dock_tab_move_right->set_disabled(dock_slot[dock_popup_selected_idx]->get_current_tab() >= dock_slot[dock_popup_selected_idx]->get_tab_count() - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < DOCK_SLOT_MAX; i++) {
|
||||||
|
Vector2 ofs;
|
||||||
|
|
||||||
|
switch (i) {
|
||||||
|
case DOCK_SLOT_LEFT_UL: {
|
||||||
|
} break;
|
||||||
|
case DOCK_SLOT_LEFT_BL: {
|
||||||
|
ofs.y += s.y;
|
||||||
|
} break;
|
||||||
|
case DOCK_SLOT_LEFT_UR: {
|
||||||
|
ofs.x += s.x;
|
||||||
|
} break;
|
||||||
|
case DOCK_SLOT_LEFT_BR: {
|
||||||
|
ofs += s;
|
||||||
|
} break;
|
||||||
|
case DOCK_SLOT_RIGHT_UL: {
|
||||||
|
ofs.x += s.x * 4;
|
||||||
|
} break;
|
||||||
|
case DOCK_SLOT_RIGHT_BL: {
|
||||||
|
ofs.x += s.x * 4;
|
||||||
|
ofs.y += s.y;
|
||||||
|
|
||||||
|
} break;
|
||||||
|
case DOCK_SLOT_RIGHT_UR: {
|
||||||
|
ofs.x += s.x * 4;
|
||||||
|
ofs.x += s.x;
|
||||||
|
|
||||||
|
} break;
|
||||||
|
case DOCK_SLOT_RIGHT_BR: {
|
||||||
|
ofs.x += s.x * 4;
|
||||||
|
ofs += s;
|
||||||
|
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Rect2 r(ofs, s);
|
||||||
|
dock_select_rect[i] = r;
|
||||||
|
r.position += Vector2(2, 5);
|
||||||
|
r.size -= Vector2(4, 7);
|
||||||
|
|
||||||
|
if (i == dock_select_rect_over_idx) {
|
||||||
|
dock_select->draw_rect(r, used_selected);
|
||||||
|
} else if (dock_slot[i]->get_tab_count() == 0) {
|
||||||
|
dock_select->draw_rect(r, unused);
|
||||||
|
} else {
|
||||||
|
dock_select->draw_rect(r, used);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int j = 0; j < MIN(3, dock_slot[i]->get_tab_count()); j++) {
|
||||||
|
int xofs = (r.size.width / 3) * j;
|
||||||
|
Color c = used;
|
||||||
|
if (i == dock_popup_selected_idx && (dock_slot[i]->get_current_tab() > 3 || dock_slot[i]->get_current_tab() == j)) {
|
||||||
|
c = tab_selected;
|
||||||
|
}
|
||||||
|
dock_select->draw_rect(Rect2(2 + ofs.x + xofs, ofs.y, r.size.width / 3 - 1, 3), c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorDockManager::_dock_split_dragged(int p_offset) {
|
||||||
|
EditorNode::get_singleton()->save_editor_layout_delayed();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorDockManager::_dock_tab_changed(int p_tab) {
|
||||||
|
// Update visibility but don't set current tab.
|
||||||
|
update_dock_slots_visibility(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorDockManager::_edit_current() {
|
||||||
|
EditorNode::get_singleton()->edit_current();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorDockManager::_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");
|
||||||
|
|
||||||
|
// Give back the dock to the original owner.
|
||||||
|
Control *dock = p_wrapper->release_wrapped_control();
|
||||||
|
|
||||||
|
int target_index = MIN(dock_slot_index, dock_slot[dock_slot_num]->get_tab_count());
|
||||||
|
dock_slot[dock_slot_num]->add_child(dock);
|
||||||
|
dock_slot[dock_slot_num]->move_child(dock, target_index);
|
||||||
|
dock_slot[dock_slot_num]->set_current_tab(target_index);
|
||||||
|
|
||||||
|
floating_docks.erase(p_wrapper);
|
||||||
|
p_wrapper->queue_free();
|
||||||
|
|
||||||
|
update_dock_slots_visibility(true);
|
||||||
|
|
||||||
|
_edit_current();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorDockManager::_dock_make_selected_float() {
|
||||||
|
Control *dock = dock_slot[dock_popup_selected_idx]->get_current_tab_control();
|
||||||
|
_dock_make_float(dock, dock_popup_selected_idx);
|
||||||
|
|
||||||
|
dock_select_popup->hide();
|
||||||
|
_edit_current();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorDockManager::_dock_make_float(Control *p_dock, int p_slot_index, bool p_show_window) {
|
||||||
|
ERR_FAIL_NULL(p_dock);
|
||||||
|
|
||||||
|
Size2 borders = Size2(4, 4) * EDSCALE;
|
||||||
|
// Remember size and position before removing it from the main 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);
|
||||||
|
|
||||||
|
EditorNode::get_singleton()->get_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());
|
||||||
|
p_dock->show();
|
||||||
|
|
||||||
|
wrapper->connect("window_close_requested", callable_mp(this, &EditorDockManager::_dock_floating_close_request).bind(wrapper));
|
||||||
|
|
||||||
|
dock_select_popup->hide();
|
||||||
|
|
||||||
|
if (p_show_window) {
|
||||||
|
wrapper->restore_window(Rect2i(dock_screen_pos, dock_size), EditorNode::get_singleton()->get_gui_base()->get_window()->get_current_screen());
|
||||||
|
}
|
||||||
|
|
||||||
|
update_dock_slots_visibility(true);
|
||||||
|
|
||||||
|
floating_docks.push_back(wrapper);
|
||||||
|
|
||||||
|
_edit_current();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorDockManager::_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 EditorDockManager::save_docks_to_config(Ref<ConfigFile> p_layout, const String &p_section) const {
|
||||||
|
for (int i = 0; i < DOCK_SLOT_MAX; i++) {
|
||||||
|
String names;
|
||||||
|
for (int j = 0; j < dock_slot[i]->get_tab_count(); j++) {
|
||||||
|
String name = dock_slot[i]->get_tab_control(j)->get_name();
|
||||||
|
if (!names.is_empty()) {
|
||||||
|
names += ",";
|
||||||
|
}
|
||||||
|
names += name;
|
||||||
|
}
|
||||||
|
|
||||||
|
String config_key = "dock_" + itos(i + 1);
|
||||||
|
|
||||||
|
if (p_layout->has_section_key(p_section, config_key)) {
|
||||||
|
p_layout->erase_section_key(p_section, config_key);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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()) {
|
||||||
|
p_layout->set_value(p_section, "dock_split_" + itos(i + 1), vsplits[i]->get_split_offset());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < hsplits.size(); i++) {
|
||||||
|
p_layout->set_value(p_section, "dock_hsplit_" + itos(i + 1), hsplits[i]->get_split_offset());
|
||||||
|
}
|
||||||
|
|
||||||
|
FileSystemDock::get_singleton()->save_layout_to_config(p_layout, p_section);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorDockManager::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;
|
||||||
|
}
|
||||||
|
|
||||||
|
Vector<String> names = String(p_layout->get_value(p_section, "dock_" + itos(i + 1))).split(",");
|
||||||
|
|
||||||
|
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;
|
||||||
|
for (int k = 0; k < DOCK_SLOT_MAX; k++) {
|
||||||
|
if (!dock_slot[k]->has_node(name)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
node = Object::cast_to<Control>(dock_slot[k]->get_node(name));
|
||||||
|
if (!node) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
atidx = k;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
} else {
|
||||||
|
atidx = wrapper->get_meta("dock_slot");
|
||||||
|
node = wrapper->get_wrapped_control();
|
||||||
|
wrapper->set_window_enabled(false);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!node) {
|
||||||
|
// Well, it's not anywhere.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (atidx == i) {
|
||||||
|
dock_slot[i]->move_child(node, 0);
|
||||||
|
} else if (atidx != -1) {
|
||||||
|
dock_slot[i]->set_block_signals(true);
|
||||||
|
dock_slot[atidx]->set_block_signals(true);
|
||||||
|
dock_slot[i]->move_tab_from_tab_container(dock_slot[atidx], dock_slot[atidx]->get_tab_idx_from_control(node), 0);
|
||||||
|
dock_slot[i]->set_block_signals(false);
|
||||||
|
dock_slot[atidx]->set_block_signals(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
WindowWrapper *wrapper = Object::cast_to<WindowWrapper>(node);
|
||||||
|
if (restore_window_on_load && floating_docks_dump.has(name)) {
|
||||||
|
if (!dock_slot[i]->is_tab_hidden(dock_slot[i]->get_tab_idx_from_control(node))) {
|
||||||
|
_restore_floating_dock(floating_docks_dump[name], node, i);
|
||||||
|
}
|
||||||
|
} else if (wrapper) {
|
||||||
|
wrapper->set_window_enabled(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!p_layout->has_section_key(p_section, "dock_" + itos(i + 1) + "_selected_tab_idx")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
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()) {
|
||||||
|
callable_mp(dock_slot[i], &TabContainer::set_current_tab).call_deferred(selected_tab_idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < vsplits.size(); i++) {
|
||||||
|
if (!p_layout->has_section_key(p_section, "dock_split_" + itos(i + 1))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ofs = p_layout->get_value(p_section, "dock_split_" + itos(i + 1));
|
||||||
|
vsplits[i]->set_split_offset(ofs);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < hsplits.size(); i++) {
|
||||||
|
if (!p_layout->has_section_key(p_section, "dock_hsplit_" + itos(i + 1))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int ofs = p_layout->get_value(p_section, "dock_hsplit_" + itos(i + 1));
|
||||||
|
hsplits[i]->set_split_offset(ofs);
|
||||||
|
}
|
||||||
|
|
||||||
|
update_dock_slots_visibility(false);
|
||||||
|
|
||||||
|
FileSystemDock::get_singleton()->load_layout_from_config(p_layout, p_section);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorDockManager::update_dock_slots_visibility(bool p_keep_selected_tabs) {
|
||||||
|
if (!docks_visible) {
|
||||||
|
for (int i = 0; i < DOCK_SLOT_MAX; i++) {
|
||||||
|
dock_slot[i]->hide();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < DOCK_SLOT_MAX; i++) {
|
||||||
|
int first_tab_visible = -1;
|
||||||
|
for (int j = 0; j < dock_slot[i]->get_tab_count(); j++) {
|
||||||
|
if (!dock_slot[i]->is_tab_hidden(j)) {
|
||||||
|
first_tab_visible = j;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (first_tab_visible >= 0) {
|
||||||
|
dock_slot[i]->show();
|
||||||
|
if (p_keep_selected_tabs) {
|
||||||
|
int current_tab = dock_slot[i]->get_current_tab();
|
||||||
|
if (dock_slot[i]->is_tab_hidden(current_tab)) {
|
||||||
|
dock_slot[i]->set_block_signals(true);
|
||||||
|
dock_slot[i]->select_next_available();
|
||||||
|
dock_slot[i]->set_block_signals(false);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
dock_slot[i]->set_block_signals(true);
|
||||||
|
dock_slot[i]->set_current_tab(first_tab_visible);
|
||||||
|
dock_slot[i]->set_block_signals(false);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
dock_slot[i]->hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorDockManager::close_all_floating_docks() {
|
||||||
|
for (WindowWrapper *wrapper : floating_docks) {
|
||||||
|
wrapper->set_window_enabled(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorDockManager::add_control_to_dock(DockSlot p_slot, Control *p_control, const String &p_name) {
|
||||||
|
ERR_FAIL_INDEX(p_slot, DOCK_SLOT_MAX);
|
||||||
|
dock_slot[p_slot]->add_child(p_control);
|
||||||
|
if (!p_name.is_empty()) {
|
||||||
|
dock_slot[p_slot]->set_tab_title(dock_slot[p_slot]->get_tab_idx_from_control(p_control), p_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorDockManager::remove_control_from_dock(Control *p_control) {
|
||||||
|
// If the dock is floating, close it first.
|
||||||
|
for (WindowWrapper *wrapper : floating_docks) {
|
||||||
|
if (p_control == wrapper->get_wrapped_control()) {
|
||||||
|
wrapper->set_window_enabled(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Control *dock = nullptr;
|
||||||
|
for (int i = 0; i < DOCK_SLOT_MAX; i++) {
|
||||||
|
if (p_control->get_parent() == dock_slot[i]) {
|
||||||
|
dock = dock_slot[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ERR_FAIL_NULL_MSG(dock, "Control is not in a dock.");
|
||||||
|
|
||||||
|
dock->remove_child(p_control);
|
||||||
|
update_dock_slots_visibility();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorDockManager::set_docks_visible(bool p_show) {
|
||||||
|
docks_visible = p_show;
|
||||||
|
update_dock_slots_visibility(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EditorDockManager::are_docks_visible() const {
|
||||||
|
return docks_visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorDockManager::add_vsplit(DockSplitContainer *p_split) {
|
||||||
|
vsplits.push_back(p_split);
|
||||||
|
p_split->connect("dragged", callable_mp(this, &EditorDockManager::_dock_split_dragged));
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorDockManager::add_hsplit(DockSplitContainer *p_split) {
|
||||||
|
hsplits.push_back(p_split);
|
||||||
|
p_split->connect("dragged", callable_mp(this, &EditorDockManager::_dock_split_dragged));
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorDockManager::register_dock_slot(DockSlot p_dock_slot, TabContainer *p_tab_container) {
|
||||||
|
ERR_FAIL_NULL(p_tab_container);
|
||||||
|
ERR_FAIL_INDEX(p_dock_slot, DOCK_SLOT_MAX);
|
||||||
|
|
||||||
|
dock_slot[p_dock_slot] = p_tab_container;
|
||||||
|
|
||||||
|
p_tab_container->set_custom_minimum_size(Size2(170, 0) * EDSCALE);
|
||||||
|
p_tab_container->set_v_size_flags(Control::SIZE_EXPAND_FILL);
|
||||||
|
p_tab_container->set_popup(dock_select_popup);
|
||||||
|
p_tab_container->connect("pre_popup_pressed", callable_mp(this, &EditorDockManager::_dock_pre_popup).bind(p_dock_slot));
|
||||||
|
p_tab_container->set_drag_to_rearrange_enabled(true);
|
||||||
|
p_tab_container->set_tabs_rearrange_group(1);
|
||||||
|
p_tab_container->connect("tab_changed", callable_mp(this, &EditorDockManager::_dock_tab_changed));
|
||||||
|
p_tab_container->set_use_hidden_tabs_for_min_size(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
int EditorDockManager::get_vsplit_count() const {
|
||||||
|
return vsplits.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EditorDockManager::_bind_methods() {
|
||||||
|
ADD_SIGNAL(MethodInfo("layout_changed"));
|
||||||
|
}
|
||||||
|
|
||||||
|
EditorDockManager::EditorDockManager() {
|
||||||
|
singleton = this;
|
||||||
|
|
||||||
|
dock_select_popup = memnew(PopupPanel);
|
||||||
|
EditorNode::get_singleton()->get_gui_base()->add_child(dock_select_popup);
|
||||||
|
VBoxContainer *dock_vb = memnew(VBoxContainer);
|
||||||
|
dock_select_popup->add_child(dock_vb);
|
||||||
|
dock_select_popup->connect("theme_changed", callable_mp(this, &EditorDockManager::_dock_select_popup_theme_changed));
|
||||||
|
|
||||||
|
HBoxContainer *dock_hb = memnew(HBoxContainer);
|
||||||
|
dock_tab_move_left = memnew(Button);
|
||||||
|
dock_tab_move_left->set_flat(true);
|
||||||
|
dock_tab_move_left->set_focus_mode(Control::FOCUS_NONE);
|
||||||
|
dock_tab_move_left->connect("pressed", callable_mp(this, &EditorDockManager::_dock_move_left));
|
||||||
|
dock_hb->add_child(dock_tab_move_left);
|
||||||
|
|
||||||
|
Label *dock_label = memnew(Label);
|
||||||
|
dock_label->set_text(TTR("Dock Position"));
|
||||||
|
dock_label->set_h_size_flags(Control::SIZE_EXPAND_FILL);
|
||||||
|
dock_label->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER);
|
||||||
|
dock_hb->add_child(dock_label);
|
||||||
|
|
||||||
|
dock_tab_move_right = memnew(Button);
|
||||||
|
dock_tab_move_right->set_flat(true);
|
||||||
|
dock_tab_move_right->set_focus_mode(Control::FOCUS_NONE);
|
||||||
|
dock_tab_move_right->connect("pressed", callable_mp(this, &EditorDockManager::_dock_move_right));
|
||||||
|
|
||||||
|
dock_hb->add_child(dock_tab_move_right);
|
||||||
|
dock_vb->add_child(dock_hb);
|
||||||
|
|
||||||
|
dock_select = memnew(Control);
|
||||||
|
dock_select->set_custom_minimum_size(Size2(128, 64) * EDSCALE);
|
||||||
|
dock_select->connect("gui_input", callable_mp(this, &EditorDockManager::_dock_select_input));
|
||||||
|
dock_select->connect("draw", callable_mp(this, &EditorDockManager::_dock_select_draw));
|
||||||
|
dock_select->connect("mouse_exited", callable_mp(this, &EditorDockManager::_dock_popup_exit));
|
||||||
|
dock_select->set_v_size_flags(Control::SIZE_EXPAND_FILL);
|
||||||
|
dock_vb->add_child(dock_select);
|
||||||
|
|
||||||
|
if (!SceneTree::get_singleton()->get_root()->is_embedding_subwindows() && !EDITOR_GET("interface/editor/single_window_mode") && EDITOR_GET("interface/multi_window/enable")) {
|
||||||
|
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, &EditorDockManager::_dock_make_selected_float));
|
||||||
|
|
||||||
|
dock_vb->add_child(dock_float);
|
||||||
|
}
|
||||||
|
|
||||||
|
dock_select_popup->reset_size();
|
||||||
|
}
|
135
editor/editor_dock_manager.h
Normal file
135
editor/editor_dock_manager.h
Normal file
|
@ -0,0 +1,135 @@
|
||||||
|
/**************************************************************************/
|
||||||
|
/* editor_dock_manager.h */
|
||||||
|
/**************************************************************************/
|
||||||
|
/* This file is part of: */
|
||||||
|
/* GODOT ENGINE */
|
||||||
|
/* https://godotengine.org */
|
||||||
|
/**************************************************************************/
|
||||||
|
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||||
|
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||||
|
/* */
|
||||||
|
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||||
|
/* a copy of this software and associated documentation files (the */
|
||||||
|
/* "Software"), to deal in the Software without restriction, including */
|
||||||
|
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||||
|
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||||
|
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||||
|
/* the following conditions: */
|
||||||
|
/* */
|
||||||
|
/* The above copyright notice and this permission notice shall be */
|
||||||
|
/* included in all copies or substantial portions of the Software. */
|
||||||
|
/* */
|
||||||
|
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||||
|
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||||
|
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||||
|
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||||
|
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||||
|
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||||
|
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||||
|
/**************************************************************************/
|
||||||
|
|
||||||
|
#ifndef EDITOR_DOCK_MANAGER_H
|
||||||
|
#define EDITOR_DOCK_MANAGER_H
|
||||||
|
|
||||||
|
#include "scene/gui/split_container.h"
|
||||||
|
|
||||||
|
class Button;
|
||||||
|
class ConfigFile;
|
||||||
|
class Control;
|
||||||
|
class PopupPanel;
|
||||||
|
class TabContainer;
|
||||||
|
class WindowWrapper;
|
||||||
|
|
||||||
|
class DockSplitContainer : public SplitContainer {
|
||||||
|
GDCLASS(DockSplitContainer, SplitContainer);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool is_updating = false;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void _update_visibility();
|
||||||
|
|
||||||
|
virtual void add_child_notify(Node *p_child) override;
|
||||||
|
virtual void remove_child_notify(Node *p_child) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class EditorDockManager : public Object {
|
||||||
|
GDCLASS(EditorDockManager, Object);
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum DockSlot {
|
||||||
|
DOCK_SLOT_LEFT_UL,
|
||||||
|
DOCK_SLOT_LEFT_BL,
|
||||||
|
DOCK_SLOT_LEFT_UR,
|
||||||
|
DOCK_SLOT_LEFT_BR,
|
||||||
|
DOCK_SLOT_RIGHT_UL,
|
||||||
|
DOCK_SLOT_RIGHT_BL,
|
||||||
|
DOCK_SLOT_RIGHT_UR,
|
||||||
|
DOCK_SLOT_RIGHT_BR,
|
||||||
|
DOCK_SLOT_MAX
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
static EditorDockManager *singleton;
|
||||||
|
|
||||||
|
// To access splits easily by index.
|
||||||
|
Vector<DockSplitContainer *> vsplits;
|
||||||
|
Vector<DockSplitContainer *> hsplits;
|
||||||
|
|
||||||
|
Vector<WindowWrapper *> floating_docks;
|
||||||
|
TabContainer *dock_slot[DOCK_SLOT_MAX];
|
||||||
|
bool docks_visible = true;
|
||||||
|
|
||||||
|
PopupPanel *dock_select_popup = nullptr;
|
||||||
|
Button *dock_float = nullptr;
|
||||||
|
Button *dock_tab_move_left = nullptr;
|
||||||
|
Button *dock_tab_move_right = nullptr;
|
||||||
|
Control *dock_select = nullptr;
|
||||||
|
Rect2 dock_select_rect[DOCK_SLOT_MAX];
|
||||||
|
int dock_select_rect_over_idx = -1;
|
||||||
|
int dock_popup_selected_idx = -1;
|
||||||
|
|
||||||
|
void _dock_select_popup_theme_changed();
|
||||||
|
void _dock_popup_exit();
|
||||||
|
void _dock_pre_popup(int p_dock_slot);
|
||||||
|
void _dock_move_left();
|
||||||
|
void _dock_move_right();
|
||||||
|
void _dock_select_input(const Ref<InputEvent> &p_input);
|
||||||
|
void _dock_select_draw();
|
||||||
|
void _dock_split_dragged(int p_offset);
|
||||||
|
|
||||||
|
void _dock_tab_changed(int p_tab);
|
||||||
|
void _edit_current();
|
||||||
|
|
||||||
|
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 _restore_floating_dock(const Dictionary &p_dock_dump, Control *p_wrapper, int p_slot_index);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static void _bind_methods();
|
||||||
|
|
||||||
|
public:
|
||||||
|
static EditorDockManager *get_singleton() { return singleton; }
|
||||||
|
|
||||||
|
void add_vsplit(DockSplitContainer *p_split);
|
||||||
|
void add_hsplit(DockSplitContainer *p_split);
|
||||||
|
void register_dock_slot(DockSlot p_dock_slot, TabContainer *p_tab_container);
|
||||||
|
int get_vsplit_count() const;
|
||||||
|
|
||||||
|
void save_docks_to_config(Ref<ConfigFile> p_layout, const String &p_section) const;
|
||||||
|
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 close_all_floating_docks();
|
||||||
|
|
||||||
|
void set_docks_visible(bool p_show);
|
||||||
|
bool are_docks_visible() const;
|
||||||
|
|
||||||
|
void add_control_to_dock(DockSlot p_slot, Control *p_control, const String &p_name = "");
|
||||||
|
void remove_control_from_dock(Control *p_control);
|
||||||
|
|
||||||
|
EditorDockManager();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // EDITOR_DOCK_MANAGER_H
|
|
@ -79,6 +79,7 @@
|
||||||
#include "editor/editor_build_profile.h"
|
#include "editor/editor_build_profile.h"
|
||||||
#include "editor/editor_command_palette.h"
|
#include "editor/editor_command_palette.h"
|
||||||
#include "editor/editor_data.h"
|
#include "editor/editor_data.h"
|
||||||
|
#include "editor/editor_dock_manager.h"
|
||||||
#include "editor/editor_feature_profile.h"
|
#include "editor/editor_feature_profile.h"
|
||||||
#include "editor/editor_folding.h"
|
#include "editor/editor_folding.h"
|
||||||
#include "editor/editor_help.h"
|
#include "editor/editor_help.h"
|
||||||
|
@ -507,14 +508,6 @@ void EditorNode::_update_theme(bool p_skip_creation) {
|
||||||
distraction_free->set_icon(theme->get_icon(SNAME("DistractionFree"), EditorStringName(EditorIcons)));
|
distraction_free->set_icon(theme->get_icon(SNAME("DistractionFree"), EditorStringName(EditorIcons)));
|
||||||
bottom_panel_raise->set_icon(theme->get_icon(SNAME("ExpandBottomDock"), EditorStringName(EditorIcons)));
|
bottom_panel_raise->set_icon(theme->get_icon(SNAME("ExpandBottomDock"), EditorStringName(EditorIcons)));
|
||||||
|
|
||||||
if (gui_base->is_layout_rtl()) {
|
|
||||||
dock_tab_move_left->set_icon(theme->get_icon(SNAME("Forward"), EditorStringName(EditorIcons)));
|
|
||||||
dock_tab_move_right->set_icon(theme->get_icon(SNAME("Back"), EditorStringName(EditorIcons)));
|
|
||||||
} else {
|
|
||||||
dock_tab_move_left->set_icon(theme->get_icon(SNAME("Back"), EditorStringName(EditorIcons)));
|
|
||||||
dock_tab_move_right->set_icon(theme->get_icon(SNAME("Forward"), EditorStringName(EditorIcons)));
|
|
||||||
}
|
|
||||||
|
|
||||||
help_menu->set_item_icon(help_menu->get_item_index(HELP_SEARCH), theme->get_icon(SNAME("HelpSearch"), EditorStringName(EditorIcons)));
|
help_menu->set_item_icon(help_menu->get_item_index(HELP_SEARCH), theme->get_icon(SNAME("HelpSearch"), EditorStringName(EditorIcons)));
|
||||||
help_menu->set_item_icon(help_menu->get_item_index(HELP_DOCS), theme->get_icon(SNAME("ExternalLink"), EditorStringName(EditorIcons)));
|
help_menu->set_item_icon(help_menu->get_item_index(HELP_DOCS), theme->get_icon(SNAME("ExternalLink"), EditorStringName(EditorIcons)));
|
||||||
help_menu->set_item_icon(help_menu->get_item_index(HELP_QA), theme->get_icon(SNAME("ExternalLink"), EditorStringName(EditorIcons)));
|
help_menu->set_item_icon(help_menu->get_item_index(HELP_QA), theme->get_icon(SNAME("ExternalLink"), EditorStringName(EditorIcons)));
|
||||||
|
@ -2095,7 +2088,7 @@ void EditorNode::_dialog_action(String p_file) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_save_docks_to_config(config, p_file);
|
editor_dock_manager->save_docks_to_config(config, p_file);
|
||||||
|
|
||||||
config->save(EditorSettings::get_singleton()->get_editor_layouts_config());
|
config->save(EditorSettings::get_singleton()->get_editor_layouts_config());
|
||||||
|
|
||||||
|
@ -4738,240 +4731,6 @@ void EditorNode::_copy_warning(const String &p_str) {
|
||||||
DisplayServer::get_singleton()->clipboard_set(warning->get_text());
|
DisplayServer::get_singleton()->clipboard_set(warning->get_text());
|
||||||
}
|
}
|
||||||
|
|
||||||
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");
|
|
||||||
|
|
||||||
// Give back the dock to the original owner.
|
|
||||||
Control *dock = p_wrapper->release_wrapped_control();
|
|
||||||
|
|
||||||
int target_index = MIN(dock_slot_index, dock_slot[dock_slot_num]->get_tab_count());
|
|
||||||
dock_slot[dock_slot_num]->add_child(dock);
|
|
||||||
dock_slot[dock_slot_num]->move_child(dock, target_index);
|
|
||||||
dock_slot[dock_slot_num]->set_current_tab(target_index);
|
|
||||||
|
|
||||||
floating_docks.erase(p_wrapper);
|
|
||||||
p_wrapper->queue_free();
|
|
||||||
|
|
||||||
_update_dock_slots_visibility(true);
|
|
||||||
|
|
||||||
_edit_current();
|
|
||||||
}
|
|
||||||
|
|
||||||
void EditorNode::_dock_make_selected_float() {
|
|
||||||
Control *dock = dock_slot[dock_popup_selected_idx]->get_current_tab_control();
|
|
||||||
_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_NULL(p_dock);
|
|
||||||
|
|
||||||
Size2 borders = Size2(4, 4) * EDSCALE;
|
|
||||||
// Remember size and position before removing it from the main 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());
|
|
||||||
p_dock->show();
|
|
||||||
|
|
||||||
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_slots_visibility(true);
|
|
||||||
|
|
||||||
floating_docks.push_back(wrapper);
|
|
||||||
|
|
||||||
_edit_current();
|
|
||||||
}
|
|
||||||
|
|
||||||
void EditorNode::_dock_select_input(const Ref<InputEvent> &p_input) {
|
|
||||||
Ref<InputEventMouse> me = p_input;
|
|
||||||
|
|
||||||
if (me.is_valid()) {
|
|
||||||
Vector2 point = me->get_position();
|
|
||||||
|
|
||||||
int nrect = -1;
|
|
||||||
for (int i = 0; i < DOCK_SLOT_MAX; i++) {
|
|
||||||
if (dock_select_rect[i].has_point(point)) {
|
|
||||||
nrect = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nrect != dock_select_rect_over_idx) {
|
|
||||||
dock_select->queue_redraw();
|
|
||||||
dock_select_rect_over_idx = nrect;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (nrect == -1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ref<InputEventMouseButton> mb = me;
|
|
||||||
|
|
||||||
if (mb.is_valid() && mb->get_button_index() == MouseButton::LEFT && mb->is_pressed() && dock_popup_selected_idx != nrect) {
|
|
||||||
dock_slot[nrect]->move_tab_from_tab_container(dock_slot[dock_popup_selected_idx], dock_slot[dock_popup_selected_idx]->get_current_tab(), dock_slot[nrect]->get_tab_count());
|
|
||||||
|
|
||||||
if (dock_slot[dock_popup_selected_idx]->get_tab_count() == 0) {
|
|
||||||
dock_slot[dock_popup_selected_idx]->hide();
|
|
||||||
} else {
|
|
||||||
dock_slot[dock_popup_selected_idx]->set_current_tab(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
dock_popup_selected_idx = nrect;
|
|
||||||
dock_slot[nrect]->show();
|
|
||||||
dock_select->queue_redraw();
|
|
||||||
|
|
||||||
_update_dock_slots_visibility(true);
|
|
||||||
|
|
||||||
_edit_current();
|
|
||||||
_save_editor_layout();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void EditorNode::_dock_popup_exit() {
|
|
||||||
dock_select_rect_over_idx = -1;
|
|
||||||
dock_select->queue_redraw();
|
|
||||||
}
|
|
||||||
|
|
||||||
void EditorNode::_dock_pre_popup(int p_which) {
|
|
||||||
dock_popup_selected_idx = p_which;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EditorNode::_dock_move_left() {
|
|
||||||
if (dock_popup_selected_idx < 0 || dock_popup_selected_idx >= DOCK_SLOT_MAX) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Control *current_ctl = dock_slot[dock_popup_selected_idx]->get_tab_control(dock_slot[dock_popup_selected_idx]->get_current_tab());
|
|
||||||
Control *prev_ctl = dock_slot[dock_popup_selected_idx]->get_tab_control(dock_slot[dock_popup_selected_idx]->get_current_tab() - 1);
|
|
||||||
if (!current_ctl || !prev_ctl) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
dock_slot[dock_popup_selected_idx]->move_child(current_ctl, prev_ctl->get_index(false));
|
|
||||||
dock_select->queue_redraw();
|
|
||||||
_edit_current();
|
|
||||||
_save_editor_layout();
|
|
||||||
}
|
|
||||||
|
|
||||||
void EditorNode::_dock_move_right() {
|
|
||||||
Control *current_ctl = dock_slot[dock_popup_selected_idx]->get_tab_control(dock_slot[dock_popup_selected_idx]->get_current_tab());
|
|
||||||
Control *next_ctl = dock_slot[dock_popup_selected_idx]->get_tab_control(dock_slot[dock_popup_selected_idx]->get_current_tab() + 1);
|
|
||||||
if (!current_ctl || !next_ctl) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
dock_slot[dock_popup_selected_idx]->move_child(next_ctl, current_ctl->get_index(false));
|
|
||||||
dock_select->queue_redraw();
|
|
||||||
_edit_current();
|
|
||||||
_save_editor_layout();
|
|
||||||
}
|
|
||||||
|
|
||||||
void EditorNode::_dock_select_draw() {
|
|
||||||
Size2 s = dock_select->get_size();
|
|
||||||
s.y /= 2.0;
|
|
||||||
s.x /= 6.0;
|
|
||||||
|
|
||||||
Color used = Color(0.6, 0.6, 0.6, 0.8);
|
|
||||||
Color used_selected = Color(0.8, 0.8, 0.8, 0.8);
|
|
||||||
Color tab_selected = theme->get_color(SNAME("mono_color"), EditorStringName(Editor));
|
|
||||||
Color unused = used;
|
|
||||||
unused.a = 0.4;
|
|
||||||
Color unusable = unused;
|
|
||||||
unusable.a = 0.1;
|
|
||||||
|
|
||||||
Rect2 unr(s.x * 2, 0, s.x * 2, s.y * 2);
|
|
||||||
unr.position += Vector2(2, 5);
|
|
||||||
unr.size -= Vector2(4, 7);
|
|
||||||
|
|
||||||
dock_select->draw_rect(unr, unusable);
|
|
||||||
|
|
||||||
dock_tab_move_left->set_disabled(true);
|
|
||||||
dock_tab_move_right->set_disabled(true);
|
|
||||||
|
|
||||||
if (dock_popup_selected_idx != -1 && dock_slot[dock_popup_selected_idx]->get_tab_count()) {
|
|
||||||
dock_tab_move_left->set_disabled(dock_slot[dock_popup_selected_idx]->get_current_tab() == 0);
|
|
||||||
dock_tab_move_right->set_disabled(dock_slot[dock_popup_selected_idx]->get_current_tab() >= dock_slot[dock_popup_selected_idx]->get_tab_count() - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < DOCK_SLOT_MAX; i++) {
|
|
||||||
Vector2 ofs;
|
|
||||||
|
|
||||||
switch (i) {
|
|
||||||
case DOCK_SLOT_LEFT_UL: {
|
|
||||||
} break;
|
|
||||||
case DOCK_SLOT_LEFT_BL: {
|
|
||||||
ofs.y += s.y;
|
|
||||||
} break;
|
|
||||||
case DOCK_SLOT_LEFT_UR: {
|
|
||||||
ofs.x += s.x;
|
|
||||||
} break;
|
|
||||||
case DOCK_SLOT_LEFT_BR: {
|
|
||||||
ofs += s;
|
|
||||||
} break;
|
|
||||||
case DOCK_SLOT_RIGHT_UL: {
|
|
||||||
ofs.x += s.x * 4;
|
|
||||||
} break;
|
|
||||||
case DOCK_SLOT_RIGHT_BL: {
|
|
||||||
ofs.x += s.x * 4;
|
|
||||||
ofs.y += s.y;
|
|
||||||
|
|
||||||
} break;
|
|
||||||
case DOCK_SLOT_RIGHT_UR: {
|
|
||||||
ofs.x += s.x * 4;
|
|
||||||
ofs.x += s.x;
|
|
||||||
|
|
||||||
} break;
|
|
||||||
case DOCK_SLOT_RIGHT_BR: {
|
|
||||||
ofs.x += s.x * 4;
|
|
||||||
ofs += s;
|
|
||||||
|
|
||||||
} break;
|
|
||||||
}
|
|
||||||
|
|
||||||
Rect2 r(ofs, s);
|
|
||||||
dock_select_rect[i] = r;
|
|
||||||
r.position += Vector2(2, 5);
|
|
||||||
r.size -= Vector2(4, 7);
|
|
||||||
|
|
||||||
if (i == dock_select_rect_over_idx) {
|
|
||||||
dock_select->draw_rect(r, used_selected);
|
|
||||||
} else if (dock_slot[i]->get_tab_count() == 0) {
|
|
||||||
dock_select->draw_rect(r, unused);
|
|
||||||
} else {
|
|
||||||
dock_select->draw_rect(r, used);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int j = 0; j < MIN(3, dock_slot[i]->get_tab_count()); j++) {
|
|
||||||
int xofs = (r.size.width / 3) * j;
|
|
||||||
Color c = used;
|
|
||||||
if (i == dock_popup_selected_idx && (dock_slot[i]->get_current_tab() > 3 || dock_slot[i]->get_current_tab() == j)) {
|
|
||||||
c = tab_selected;
|
|
||||||
}
|
|
||||||
dock_select->draw_rect(Rect2(2 + ofs.x + xofs, ofs.y, r.size.width / 3 - 1, 3), c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void EditorNode::_save_editor_layout() {
|
void EditorNode::_save_editor_layout() {
|
||||||
if (waiting_for_first_scan) {
|
if (waiting_for_first_scan) {
|
||||||
return; // Scanning, do not touch docks.
|
return; // Scanning, do not touch docks.
|
||||||
|
@ -4981,7 +4740,7 @@ void EditorNode::_save_editor_layout() {
|
||||||
// Load and amend existing config if it exists.
|
// Load and amend existing config if it exists.
|
||||||
config->load(EditorPaths::get_singleton()->get_project_settings_dir().path_join("editor_layout.cfg"));
|
config->load(EditorPaths::get_singleton()->get_project_settings_dir().path_join("editor_layout.cfg"));
|
||||||
|
|
||||||
_save_docks_to_config(config, "docks");
|
editor_dock_manager->save_docks_to_config(config, "docks");
|
||||||
_save_open_scenes_to_config(config);
|
_save_open_scenes_to_config(config);
|
||||||
_save_central_editor_layout_to_config(config);
|
_save_central_editor_layout_to_config(config);
|
||||||
editor_data.get_plugin_window_layout(config);
|
editor_data.get_plugin_window_layout(config);
|
||||||
|
@ -4989,85 +4748,6 @@ void EditorNode::_save_editor_layout() {
|
||||||
config->save(EditorPaths::get_singleton()->get_project_settings_dir().path_join("editor_layout.cfg"));
|
config->save(EditorPaths::get_singleton()->get_project_settings_dir().path_join("editor_layout.cfg"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditorNode::_save_docks_to_config(Ref<ConfigFile> p_layout, const String &p_section) {
|
|
||||||
for (int i = 0; i < DOCK_SLOT_MAX; i++) {
|
|
||||||
String names;
|
|
||||||
for (int j = 0; j < dock_slot[i]->get_tab_count(); j++) {
|
|
||||||
String name = dock_slot[i]->get_tab_control(j)->get_name();
|
|
||||||
if (!names.is_empty()) {
|
|
||||||
names += ",";
|
|
||||||
}
|
|
||||||
names += name;
|
|
||||||
}
|
|
||||||
|
|
||||||
String config_key = "dock_" + itos(i + 1);
|
|
||||||
|
|
||||||
if (p_layout->has_section_key(p_section, config_key)) {
|
|
||||||
p_layout->erase_section_key(p_section, config_key);
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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()) {
|
|
||||||
p_layout->set_value(p_section, "dock_split_" + itos(i + 1), vsplits[i]->get_split_offset());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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_h_split_offset", FileSystemDock::get_singleton()->get_h_split_offset());
|
|
||||||
p_layout->set_value(p_section, "dock_filesystem_v_split_offset", FileSystemDock::get_singleton()->get_v_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) {
|
void EditorNode::_save_open_scenes_to_config(Ref<ConfigFile> p_layout) {
|
||||||
PackedStringArray scenes;
|
PackedStringArray scenes;
|
||||||
for (int i = 0; i < editor_data.get_edited_scene_count(); i++) {
|
for (int i = 0; i < editor_data.get_edited_scene_count(); i++) {
|
||||||
|
@ -5087,10 +4767,6 @@ void EditorNode::save_editor_layout_delayed() {
|
||||||
editor_layout_save_delay_timer->start();
|
editor_layout_save_delay_timer->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditorNode::_dock_split_dragged(int ofs) {
|
|
||||||
editor_layout_save_delay_timer->start();
|
|
||||||
}
|
|
||||||
|
|
||||||
void EditorNode::_load_editor_layout() {
|
void EditorNode::_load_editor_layout() {
|
||||||
Ref<ConfigFile> config;
|
Ref<ConfigFile> config;
|
||||||
config.instantiate();
|
config.instantiate();
|
||||||
|
@ -5113,227 +4789,13 @@ void EditorNode::_load_editor_layout() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_load_docks_from_config(config, "docks");
|
editor_dock_manager->load_docks_from_config(config, "docks");
|
||||||
_load_open_scenes_from_config(config);
|
_load_open_scenes_from_config(config);
|
||||||
_load_central_editor_layout_from_config(config);
|
_load_central_editor_layout_from_config(config);
|
||||||
|
|
||||||
editor_data.set_plugin_window_layout(config);
|
editor_data.set_plugin_window_layout(config);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditorNode::_update_dock_slots_visibility(bool p_keep_selected_tabs) {
|
|
||||||
if (!docks_visible) {
|
|
||||||
for (int i = 0; i < DOCK_SLOT_MAX; i++) {
|
|
||||||
dock_slot[i]->hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < vsplits.size(); i++) {
|
|
||||||
vsplits[i]->hide();
|
|
||||||
}
|
|
||||||
|
|
||||||
right_hsplit->hide();
|
|
||||||
} else {
|
|
||||||
for (int i = 0; i < DOCK_SLOT_MAX; i++) {
|
|
||||||
int first_tab_visible = -1;
|
|
||||||
for (int j = 0; j < dock_slot[i]->get_tab_count(); j++) {
|
|
||||||
if (!dock_slot[i]->is_tab_hidden(j)) {
|
|
||||||
first_tab_visible = j;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (first_tab_visible >= 0) {
|
|
||||||
dock_slot[i]->show();
|
|
||||||
if (p_keep_selected_tabs) {
|
|
||||||
int current_tab = dock_slot[i]->get_current_tab();
|
|
||||||
if (dock_slot[i]->is_tab_hidden(current_tab)) {
|
|
||||||
dock_slot[i]->set_block_signals(true);
|
|
||||||
dock_slot[i]->select_next_available();
|
|
||||||
dock_slot[i]->set_block_signals(false);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
dock_slot[i]->set_block_signals(true);
|
|
||||||
dock_slot[i]->set_current_tab(first_tab_visible);
|
|
||||||
dock_slot[i]->set_block_signals(false);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
dock_slot[i]->hide();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < vsplits.size(); i++) {
|
|
||||||
bool in_use = dock_slot[i * 2 + 0]->is_visible() || dock_slot[i * 2 + 1]->is_visible();
|
|
||||||
vsplits[i]->set_visible(in_use);
|
|
||||||
}
|
|
||||||
|
|
||||||
right_hsplit->set_visible(right_l_vsplit->is_visible() || right_r_vsplit->is_visible());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void EditorNode::_dock_tab_changed(int p_tab) {
|
|
||||||
// Update visibility but don't set current tab.
|
|
||||||
_update_dock_slots_visibility(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector<String> names = String(p_layout->get_value(p_section, "dock_" + itos(i + 1))).split(",");
|
|
||||||
|
|
||||||
for (int j = names.size() - 1; j >= 0; j--) {
|
|
||||||
const String &name = names[j];
|
|
||||||
|
|
||||||
// FIXME: Find it, in a horribly inefficient way.
|
|
||||||
int atidx = -1;
|
|
||||||
Control *node = nullptr;
|
|
||||||
for (int k = 0; k < DOCK_SLOT_MAX; k++) {
|
|
||||||
if (!dock_slot[k]->has_node(name)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
node = Object::cast_to<Control>(dock_slot[k]->get_node(name));
|
|
||||||
if (!node) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
atidx = k;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
} else {
|
|
||||||
atidx = wrapper->get_meta("dock_slot");
|
|
||||||
node = wrapper->get_wrapped_control();
|
|
||||||
wrapper->set_window_enabled(false);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!node) {
|
|
||||||
// Well, it's not anywhere.
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (atidx == i) {
|
|
||||||
dock_slot[i]->move_child(node, 0);
|
|
||||||
} else if (atidx != -1) {
|
|
||||||
dock_slot[i]->move_tab_from_tab_container(dock_slot[atidx], dock_slot[atidx]->get_tab_idx_from_control(node), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
WindowWrapper *wrapper = Object::cast_to<WindowWrapper>(node);
|
|
||||||
if (restore_window_on_load && floating_docks_dump.has(name)) {
|
|
||||||
if (!dock_slot[i]->is_tab_hidden(dock_slot[i]->get_tab_idx_from_control(node))) {
|
|
||||||
_restore_floating_dock(floating_docks_dump[name], node, i);
|
|
||||||
}
|
|
||||||
} else if (wrapper) {
|
|
||||||
wrapper->set_window_enabled(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!p_layout->has_section_key(p_section, "dock_" + itos(i + 1) + "_selected_tab_idx")) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
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()) {
|
|
||||||
callable_mp(dock_slot[i], &TabContainer::set_current_tab).call_deferred(selected_tab_idx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < vsplits.size(); i++) {
|
|
||||||
if (!p_layout->has_section_key(p_section, "dock_split_" + itos(i + 1))) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
int ofs = p_layout->get_value(p_section, "dock_split_" + itos(i + 1));
|
|
||||||
vsplits[i]->set_split_offset(ofs);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < hsplits.size(); i++) {
|
|
||||||
if (!p_layout->has_section_key(p_section, "dock_hsplit_" + itos(i + 1))) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
int ofs = p_layout->get_value(p_section, "dock_hsplit_" + itos(i + 1));
|
|
||||||
hsplits[i]->set_split_offset(ofs);
|
|
||||||
}
|
|
||||||
|
|
||||||
_update_dock_slots_visibility(false);
|
|
||||||
|
|
||||||
// FileSystemDock.
|
|
||||||
|
|
||||||
if (p_layout->has_section_key(p_section, "dock_filesystem_h_split_offset")) {
|
|
||||||
int fs_h_split_ofs = p_layout->get_value(p_section, "dock_filesystem_h_split_offset");
|
|
||||||
FileSystemDock::get_singleton()->set_h_split_offset(fs_h_split_ofs);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p_layout->has_section_key(p_section, "dock_filesystem_v_split_offset")) {
|
|
||||||
int fs_v_split_ofs = p_layout->get_value(p_section, "dock_filesystem_v_split_offset");
|
|
||||||
FileSystemDock::get_singleton()->set_v_split_offset(fs_v_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.
|
|
||||||
PackedStringArray uncollapsed_tis;
|
|
||||||
if (p_layout->has_section_key(p_section, "dock_filesystem_uncollapsed_paths")) {
|
|
||||||
uncollapsed_tis = p_layout->get_value(p_section, "dock_filesystem_uncollapsed_paths");
|
|
||||||
} else {
|
|
||||||
uncollapsed_tis = { "res://" };
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!uncollapsed_tis.is_empty()) {
|
|
||||||
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::_save_central_editor_layout_to_config(Ref<ConfigFile> p_config_file) {
|
void EditorNode::_save_central_editor_layout_to_config(Ref<ConfigFile> p_config_file) {
|
||||||
// Bottom panel.
|
// Bottom panel.
|
||||||
|
|
||||||
|
@ -5582,7 +5044,7 @@ void EditorNode::_layout_menu_option(int p_id) {
|
||||||
layout_dialog->popup_centered();
|
layout_dialog->popup_centered();
|
||||||
} break;
|
} break;
|
||||||
case SETTINGS_LAYOUT_DEFAULT: {
|
case SETTINGS_LAYOUT_DEFAULT: {
|
||||||
_load_docks_from_config(default_layout, "docks");
|
editor_dock_manager->load_docks_from_config(default_layout, "docks");
|
||||||
_save_editor_layout();
|
_save_editor_layout();
|
||||||
} break;
|
} break;
|
||||||
default: {
|
default: {
|
||||||
|
@ -5593,7 +5055,7 @@ void EditorNode::_layout_menu_option(int p_id) {
|
||||||
return; // No config.
|
return; // No config.
|
||||||
}
|
}
|
||||||
|
|
||||||
_load_docks_from_config(config, editor_layouts->get_item_text(p_id));
|
editor_dock_manager->load_docks_from_config(config, editor_layouts->get_item_text(p_id));
|
||||||
_save_editor_layout();
|
_save_editor_layout();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5803,15 +5265,6 @@ void EditorNode::_bottom_panel_switch(bool p_enable, int p_idx) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditorNode::set_docks_visible(bool p_show) {
|
|
||||||
docks_visible = p_show;
|
|
||||||
_update_dock_slots_visibility(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool EditorNode::get_docks_visible() const {
|
|
||||||
return docks_visible;
|
|
||||||
}
|
|
||||||
|
|
||||||
void EditorNode::_toggle_distraction_free_mode() {
|
void EditorNode::_toggle_distraction_free_mode() {
|
||||||
if (EDITOR_GET("interface/editor/separate_distraction_mode")) {
|
if (EDITOR_GET("interface/editor/separate_distraction_mode")) {
|
||||||
int screen = -1;
|
int screen = -1;
|
||||||
|
@ -5838,11 +5291,11 @@ void EditorNode::set_distraction_free_mode(bool p_enter) {
|
||||||
distraction_free->set_pressed(p_enter);
|
distraction_free->set_pressed(p_enter);
|
||||||
|
|
||||||
if (p_enter) {
|
if (p_enter) {
|
||||||
if (docks_visible) {
|
if (editor_dock_manager->are_docks_visible()) {
|
||||||
set_docks_visible(false);
|
editor_dock_manager->set_docks_visible(false);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
set_docks_visible(true);
|
editor_dock_manager->set_docks_visible(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5850,35 +5303,6 @@ bool EditorNode::is_distraction_free_mode_enabled() const {
|
||||||
return distraction_free->is_pressed();
|
return distraction_free->is_pressed();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditorNode::add_control_to_dock(DockSlot p_slot, Control *p_control) {
|
|
||||||
ERR_FAIL_INDEX(p_slot, DOCK_SLOT_MAX);
|
|
||||||
dock_slot[p_slot]->add_child(p_control);
|
|
||||||
_update_dock_slots_visibility();
|
|
||||||
}
|
|
||||||
|
|
||||||
void EditorNode::remove_control_from_dock(Control *p_control) {
|
|
||||||
// If the dock is floating, close it first.
|
|
||||||
for (WindowWrapper *wrapper : floating_docks) {
|
|
||||||
if (p_control == wrapper->get_wrapped_control()) {
|
|
||||||
wrapper->set_window_enabled(false);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Control *dock = nullptr;
|
|
||||||
for (int i = 0; i < DOCK_SLOT_MAX; i++) {
|
|
||||||
if (p_control->get_parent() == dock_slot[i]) {
|
|
||||||
dock = dock_slot[i];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ERR_FAIL_NULL_MSG(dock, "Control was not in dock.");
|
|
||||||
|
|
||||||
dock->remove_child(p_control);
|
|
||||||
_update_dock_slots_visibility();
|
|
||||||
}
|
|
||||||
|
|
||||||
Variant EditorNode::drag_resource(const Ref<Resource> &p_res, Control *p_from) {
|
Variant EditorNode::drag_resource(const Ref<Resource> &p_res, Control *p_from) {
|
||||||
Control *drag_control = memnew(Control);
|
Control *drag_control = memnew(Control);
|
||||||
TextureRect *drag_preview = memnew(TextureRect);
|
TextureRect *drag_preview = memnew(TextureRect);
|
||||||
|
@ -6632,9 +6056,7 @@ void EditorNode::_resource_loaded(Ref<Resource> p_resource, const String &p_path
|
||||||
void EditorNode::_feature_profile_changed() {
|
void EditorNode::_feature_profile_changed() {
|
||||||
Ref<EditorFeatureProfile> profile = feature_profile_manager->get_current_profile();
|
Ref<EditorFeatureProfile> profile = feature_profile_manager->get_current_profile();
|
||||||
// FIXME: Close all floating docks to avoid crash.
|
// FIXME: Close all floating docks to avoid crash.
|
||||||
for (WindowWrapper *wrapper : floating_docks) {
|
editor_dock_manager->close_all_floating_docks();
|
||||||
wrapper->set_window_enabled(false);
|
|
||||||
}
|
|
||||||
TabContainer *import_tabs = cast_to<TabContainer>(ImportDock::get_singleton()->get_parent());
|
TabContainer *import_tabs = cast_to<TabContainer>(ImportDock::get_singleton()->get_parent());
|
||||||
TabContainer *node_tabs = cast_to<TabContainer>(NodeDock::get_singleton()->get_parent());
|
TabContainer *node_tabs = cast_to<TabContainer>(NodeDock::get_singleton()->get_parent());
|
||||||
TabContainer *fs_tabs = cast_to<TabContainer>(FileSystemDock::get_singleton()->get_parent());
|
TabContainer *fs_tabs = cast_to<TabContainer>(FileSystemDock::get_singleton()->get_parent());
|
||||||
|
@ -6669,7 +6091,7 @@ void EditorNode::_feature_profile_changed() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_update_dock_slots_visibility();
|
editor_dock_manager->update_dock_slots_visibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditorNode::_bind_methods() {
|
void EditorNode::_bind_methods() {
|
||||||
|
@ -7079,127 +6501,96 @@ EditorNode::EditorNode() {
|
||||||
title_bar = memnew(EditorTitleBar);
|
title_bar = memnew(EditorTitleBar);
|
||||||
main_vbox->add_child(title_bar);
|
main_vbox->add_child(title_bar);
|
||||||
|
|
||||||
left_l_hsplit = memnew(HSplitContainer);
|
left_l_hsplit = memnew(DockSplitContainer);
|
||||||
|
left_l_hsplit->set_name("DockHSplitLeftL");
|
||||||
main_vbox->add_child(left_l_hsplit);
|
main_vbox->add_child(left_l_hsplit);
|
||||||
|
|
||||||
left_l_hsplit->set_v_size_flags(Control::SIZE_EXPAND_FILL);
|
left_l_hsplit->set_v_size_flags(Control::SIZE_EXPAND_FILL);
|
||||||
|
|
||||||
left_l_vsplit = memnew(VSplitContainer);
|
left_l_vsplit = memnew(DockSplitContainer);
|
||||||
|
left_l_vsplit->set_name("DockVSplitLeftL");
|
||||||
|
left_l_vsplit->set_vertical(true);
|
||||||
left_l_hsplit->add_child(left_l_vsplit);
|
left_l_hsplit->add_child(left_l_vsplit);
|
||||||
dock_slot[DOCK_SLOT_LEFT_UL] = memnew(TabContainer);
|
|
||||||
left_l_vsplit->add_child(dock_slot[DOCK_SLOT_LEFT_UL]);
|
|
||||||
dock_slot[DOCK_SLOT_LEFT_BL] = memnew(TabContainer);
|
|
||||||
left_l_vsplit->add_child(dock_slot[DOCK_SLOT_LEFT_BL]);
|
|
||||||
|
|
||||||
left_r_hsplit = memnew(HSplitContainer);
|
TabContainer *dock_slot[EditorDockManager::DOCK_SLOT_MAX];
|
||||||
|
dock_slot[EditorDockManager::DOCK_SLOT_LEFT_UL] = memnew(TabContainer);
|
||||||
|
dock_slot[EditorDockManager::DOCK_SLOT_LEFT_UL]->set_name("DockSlotLeftUL");
|
||||||
|
left_l_vsplit->add_child(dock_slot[EditorDockManager::DOCK_SLOT_LEFT_UL]);
|
||||||
|
dock_slot[EditorDockManager::DOCK_SLOT_LEFT_BL] = memnew(TabContainer);
|
||||||
|
dock_slot[EditorDockManager::DOCK_SLOT_LEFT_BL]->set_name("DockSlotLeftBL");
|
||||||
|
left_l_vsplit->add_child(dock_slot[EditorDockManager::DOCK_SLOT_LEFT_BL]);
|
||||||
|
|
||||||
|
left_r_hsplit = memnew(DockSplitContainer);
|
||||||
|
left_r_hsplit->set_name("DockHSplitLeftR");
|
||||||
left_l_hsplit->add_child(left_r_hsplit);
|
left_l_hsplit->add_child(left_r_hsplit);
|
||||||
left_r_vsplit = memnew(VSplitContainer);
|
left_r_vsplit = memnew(DockSplitContainer);
|
||||||
|
left_r_vsplit->set_name("DockVSplitLeftR");
|
||||||
|
left_r_vsplit->set_vertical(true);
|
||||||
left_r_hsplit->add_child(left_r_vsplit);
|
left_r_hsplit->add_child(left_r_vsplit);
|
||||||
dock_slot[DOCK_SLOT_LEFT_UR] = memnew(TabContainer);
|
dock_slot[EditorDockManager::DOCK_SLOT_LEFT_UR] = memnew(TabContainer);
|
||||||
left_r_vsplit->add_child(dock_slot[DOCK_SLOT_LEFT_UR]);
|
dock_slot[EditorDockManager::DOCK_SLOT_LEFT_UR]->set_name("DockSlotLeftUR");
|
||||||
dock_slot[DOCK_SLOT_LEFT_BR] = memnew(TabContainer);
|
left_r_vsplit->add_child(dock_slot[EditorDockManager::DOCK_SLOT_LEFT_UR]);
|
||||||
left_r_vsplit->add_child(dock_slot[DOCK_SLOT_LEFT_BR]);
|
dock_slot[EditorDockManager::DOCK_SLOT_LEFT_BR] = memnew(TabContainer);
|
||||||
|
dock_slot[EditorDockManager::DOCK_SLOT_LEFT_BR]->set_name("DockSlotLeftBR");
|
||||||
|
left_r_vsplit->add_child(dock_slot[EditorDockManager::DOCK_SLOT_LEFT_BR]);
|
||||||
|
|
||||||
main_hsplit = memnew(HSplitContainer);
|
main_hsplit = memnew(DockSplitContainer);
|
||||||
|
main_hsplit->set_name("DockHSplitMain");
|
||||||
left_r_hsplit->add_child(main_hsplit);
|
left_r_hsplit->add_child(main_hsplit);
|
||||||
VBoxContainer *center_vb = memnew(VBoxContainer);
|
VBoxContainer *center_vb = memnew(VBoxContainer);
|
||||||
main_hsplit->add_child(center_vb);
|
main_hsplit->add_child(center_vb);
|
||||||
|
|
||||||
center_vb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
|
center_vb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
|
||||||
|
|
||||||
center_split = memnew(VSplitContainer);
|
center_split = memnew(DockSplitContainer);
|
||||||
|
center_split->set_name("DockVSplitCenter");
|
||||||
|
center_split->set_vertical(true);
|
||||||
center_split->set_v_size_flags(Control::SIZE_EXPAND_FILL);
|
center_split->set_v_size_flags(Control::SIZE_EXPAND_FILL);
|
||||||
center_split->set_collapsed(false);
|
center_split->set_collapsed(false);
|
||||||
center_vb->add_child(center_split);
|
center_vb->add_child(center_split);
|
||||||
|
|
||||||
right_hsplit = memnew(HSplitContainer);
|
right_hsplit = memnew(DockSplitContainer);
|
||||||
|
right_hsplit->set_name("DockHSplitRight");
|
||||||
main_hsplit->add_child(right_hsplit);
|
main_hsplit->add_child(right_hsplit);
|
||||||
|
|
||||||
right_l_vsplit = memnew(VSplitContainer);
|
right_l_vsplit = memnew(DockSplitContainer);
|
||||||
|
right_l_vsplit->set_name("DockVSplitRightL");
|
||||||
|
right_l_vsplit->set_vertical(true);
|
||||||
right_hsplit->add_child(right_l_vsplit);
|
right_hsplit->add_child(right_l_vsplit);
|
||||||
dock_slot[DOCK_SLOT_RIGHT_UL] = memnew(TabContainer);
|
dock_slot[EditorDockManager::DOCK_SLOT_RIGHT_UL] = memnew(TabContainer);
|
||||||
right_l_vsplit->add_child(dock_slot[DOCK_SLOT_RIGHT_UL]);
|
dock_slot[EditorDockManager::DOCK_SLOT_RIGHT_UL]->set_name("DockSlotRightUL");
|
||||||
dock_slot[DOCK_SLOT_RIGHT_BL] = memnew(TabContainer);
|
right_l_vsplit->add_child(dock_slot[EditorDockManager::DOCK_SLOT_RIGHT_UL]);
|
||||||
right_l_vsplit->add_child(dock_slot[DOCK_SLOT_RIGHT_BL]);
|
dock_slot[EditorDockManager::DOCK_SLOT_RIGHT_BL] = memnew(TabContainer);
|
||||||
|
dock_slot[EditorDockManager::DOCK_SLOT_RIGHT_BL]->set_name("DockSlotRightBL");
|
||||||
|
right_l_vsplit->add_child(dock_slot[EditorDockManager::DOCK_SLOT_RIGHT_BL]);
|
||||||
|
|
||||||
right_r_vsplit = memnew(VSplitContainer);
|
right_r_vsplit = memnew(DockSplitContainer);
|
||||||
|
right_r_vsplit->set_name("DockVSplitRightR");
|
||||||
|
right_r_vsplit->set_vertical(true);
|
||||||
right_hsplit->add_child(right_r_vsplit);
|
right_hsplit->add_child(right_r_vsplit);
|
||||||
dock_slot[DOCK_SLOT_RIGHT_UR] = memnew(TabContainer);
|
dock_slot[EditorDockManager::DOCK_SLOT_RIGHT_UR] = memnew(TabContainer);
|
||||||
right_r_vsplit->add_child(dock_slot[DOCK_SLOT_RIGHT_UR]);
|
dock_slot[EditorDockManager::DOCK_SLOT_RIGHT_UR]->set_name("DockSlotRightUR");
|
||||||
dock_slot[DOCK_SLOT_RIGHT_BR] = memnew(TabContainer);
|
right_r_vsplit->add_child(dock_slot[EditorDockManager::DOCK_SLOT_RIGHT_UR]);
|
||||||
right_r_vsplit->add_child(dock_slot[DOCK_SLOT_RIGHT_BR]);
|
dock_slot[EditorDockManager::DOCK_SLOT_RIGHT_BR] = memnew(TabContainer);
|
||||||
|
dock_slot[EditorDockManager::DOCK_SLOT_RIGHT_BR]->set_name("DockSlotRightBR");
|
||||||
|
right_r_vsplit->add_child(dock_slot[EditorDockManager::DOCK_SLOT_RIGHT_BR]);
|
||||||
|
|
||||||
// Store them for easier access.
|
editor_dock_manager = memnew(EditorDockManager);
|
||||||
vsplits.push_back(left_l_vsplit);
|
editor_dock_manager->connect("layout_changed", callable_mp(this, &EditorNode::_save_editor_layout));
|
||||||
vsplits.push_back(left_r_vsplit);
|
|
||||||
vsplits.push_back(right_l_vsplit);
|
|
||||||
vsplits.push_back(right_r_vsplit);
|
|
||||||
|
|
||||||
hsplits.push_back(left_l_hsplit);
|
// Save the splits for easier access.
|
||||||
hsplits.push_back(left_r_hsplit);
|
editor_dock_manager->add_vsplit(left_l_vsplit);
|
||||||
hsplits.push_back(main_hsplit);
|
editor_dock_manager->add_vsplit(left_r_vsplit);
|
||||||
hsplits.push_back(right_hsplit);
|
editor_dock_manager->add_vsplit(right_l_vsplit);
|
||||||
|
editor_dock_manager->add_vsplit(right_r_vsplit);
|
||||||
|
|
||||||
for (int i = 0; i < vsplits.size(); i++) {
|
editor_dock_manager->add_hsplit(left_l_hsplit);
|
||||||
vsplits[i]->connect("dragged", callable_mp(this, &EditorNode::_dock_split_dragged));
|
editor_dock_manager->add_hsplit(left_r_hsplit);
|
||||||
hsplits[i]->connect("dragged", callable_mp(this, &EditorNode::_dock_split_dragged));
|
editor_dock_manager->add_hsplit(main_hsplit);
|
||||||
}
|
editor_dock_manager->add_hsplit(right_hsplit);
|
||||||
|
|
||||||
dock_select_popup = memnew(PopupPanel);
|
for (int i = 0; i < EditorDockManager::DOCK_SLOT_MAX; i++) {
|
||||||
gui_base->add_child(dock_select_popup);
|
editor_dock_manager->register_dock_slot((EditorDockManager::DockSlot)i, dock_slot[i]);
|
||||||
VBoxContainer *dock_vb = memnew(VBoxContainer);
|
|
||||||
dock_select_popup->add_child(dock_vb);
|
|
||||||
|
|
||||||
HBoxContainer *dock_hb = memnew(HBoxContainer);
|
|
||||||
dock_tab_move_left = memnew(Button);
|
|
||||||
dock_tab_move_left->set_flat(true);
|
|
||||||
dock_tab_move_left->set_focus_mode(Control::FOCUS_NONE);
|
|
||||||
dock_tab_move_left->connect("pressed", callable_mp(this, &EditorNode::_dock_move_left));
|
|
||||||
dock_hb->add_child(dock_tab_move_left);
|
|
||||||
|
|
||||||
Label *dock_label = memnew(Label);
|
|
||||||
dock_label->set_text(TTR("Dock Position"));
|
|
||||||
dock_label->set_h_size_flags(Control::SIZE_EXPAND_FILL);
|
|
||||||
dock_label->set_horizontal_alignment(HORIZONTAL_ALIGNMENT_CENTER);
|
|
||||||
dock_hb->add_child(dock_label);
|
|
||||||
|
|
||||||
dock_tab_move_right = memnew(Button);
|
|
||||||
dock_tab_move_right->set_flat(true);
|
|
||||||
dock_tab_move_right->set_focus_mode(Control::FOCUS_NONE);
|
|
||||||
dock_tab_move_right->connect("pressed", callable_mp(this, &EditorNode::_dock_move_right));
|
|
||||||
|
|
||||||
dock_hb->add_child(dock_tab_move_right);
|
|
||||||
dock_vb->add_child(dock_hb);
|
|
||||||
|
|
||||||
dock_select = memnew(Control);
|
|
||||||
dock_select->set_custom_minimum_size(Size2(128, 64) * EDSCALE);
|
|
||||||
dock_select->connect("gui_input", callable_mp(this, &EditorNode::_dock_select_input));
|
|
||||||
dock_select->connect("draw", callable_mp(this, &EditorNode::_dock_select_draw));
|
|
||||||
dock_select->connect("mouse_exited", callable_mp(this, &EditorNode::_dock_popup_exit));
|
|
||||||
dock_select->set_v_size_flags(Control::SIZE_EXPAND_FILL);
|
|
||||||
dock_vb->add_child(dock_select);
|
|
||||||
|
|
||||||
if (!SceneTree::get_singleton()->get_root()->is_embedding_subwindows() && !EDITOR_GET("interface/editor/single_window_mode") && EDITOR_GET("interface/multi_window/enable")) {
|
|
||||||
dock_float = memnew(Button);
|
|
||||||
dock_float->set_icon(theme->get_icon("MakeFloating", EditorStringName(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_select_popup->reset_size();
|
|
||||||
|
|
||||||
for (int i = 0; i < DOCK_SLOT_MAX; i++) {
|
|
||||||
dock_slot[i]->set_custom_minimum_size(Size2(170, 0) * EDSCALE);
|
|
||||||
dock_slot[i]->set_v_size_flags(Control::SIZE_EXPAND_FILL);
|
|
||||||
dock_slot[i]->set_popup(dock_select_popup);
|
|
||||||
dock_slot[i]->connect("pre_popup_pressed", callable_mp(this, &EditorNode::_dock_pre_popup).bind(i));
|
|
||||||
dock_slot[i]->set_drag_to_rearrange_enabled(true);
|
|
||||||
dock_slot[i]->set_tabs_rearrange_group(1);
|
|
||||||
dock_slot[i]->connect("tab_changed", callable_mp(this, &EditorNode::_dock_tab_changed));
|
|
||||||
dock_slot[i]->set_use_hidden_tabs_for_min_size(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
editor_layout_save_delay_timer = memnew(Timer);
|
editor_layout_save_delay_timer = memnew(Timer);
|
||||||
|
@ -7642,37 +7033,22 @@ EditorNode::EditorNode() {
|
||||||
history_dock = memnew(HistoryDock);
|
history_dock = memnew(HistoryDock);
|
||||||
|
|
||||||
// Scene: Top left.
|
// Scene: Top left.
|
||||||
dock_slot[DOCK_SLOT_LEFT_UR]->add_child(SceneTreeDock::get_singleton());
|
editor_dock_manager->add_control_to_dock(EditorDockManager::DOCK_SLOT_LEFT_UR, SceneTreeDock::get_singleton(), TTR("Scene"));
|
||||||
dock_slot[DOCK_SLOT_LEFT_UR]->set_tab_title(dock_slot[DOCK_SLOT_LEFT_UR]->get_tab_idx_from_control(SceneTreeDock::get_singleton()), TTR("Scene"));
|
|
||||||
|
|
||||||
// Import: Top left, behind Scene.
|
// Import: Top left, behind Scene.
|
||||||
dock_slot[DOCK_SLOT_LEFT_UR]->add_child(ImportDock::get_singleton());
|
editor_dock_manager->add_control_to_dock(EditorDockManager::DOCK_SLOT_LEFT_UR, ImportDock::get_singleton(), TTR("Import"));
|
||||||
dock_slot[DOCK_SLOT_LEFT_UR]->set_tab_title(dock_slot[DOCK_SLOT_LEFT_UR]->get_tab_idx_from_control(ImportDock::get_singleton()), TTR("Import"));
|
|
||||||
|
|
||||||
// FileSystem: Bottom left.
|
// FileSystem: Bottom left.
|
||||||
dock_slot[DOCK_SLOT_LEFT_BR]->add_child(FileSystemDock::get_singleton());
|
editor_dock_manager->add_control_to_dock(EditorDockManager::DOCK_SLOT_LEFT_BR, FileSystemDock::get_singleton(), TTR("FileSystem"));
|
||||||
dock_slot[DOCK_SLOT_LEFT_BR]->set_tab_title(dock_slot[DOCK_SLOT_LEFT_BR]->get_tab_idx_from_control(FileSystemDock::get_singleton()), TTR("FileSystem"));
|
|
||||||
|
|
||||||
// Inspector: Full height right.
|
// Inspector: Full height right.
|
||||||
dock_slot[DOCK_SLOT_RIGHT_UL]->add_child(InspectorDock::get_singleton());
|
editor_dock_manager->add_control_to_dock(EditorDockManager::DOCK_SLOT_RIGHT_UL, InspectorDock::get_singleton(), TTR("Inspector"));
|
||||||
dock_slot[DOCK_SLOT_RIGHT_UL]->set_tab_title(dock_slot[DOCK_SLOT_RIGHT_UL]->get_tab_idx_from_control(InspectorDock::get_singleton()), TTR("Inspector"));
|
|
||||||
|
|
||||||
// Node: Full height right, behind Inspector.
|
// Node: Full height right, behind Inspector.
|
||||||
dock_slot[DOCK_SLOT_RIGHT_UL]->add_child(NodeDock::get_singleton());
|
editor_dock_manager->add_control_to_dock(EditorDockManager::DOCK_SLOT_RIGHT_UL, NodeDock::get_singleton(), TTR("Node"));
|
||||||
dock_slot[DOCK_SLOT_RIGHT_UL]->set_tab_title(dock_slot[DOCK_SLOT_RIGHT_UL]->get_tab_idx_from_control(NodeDock::get_singleton()), TTR("Node"));
|
|
||||||
|
|
||||||
// History: Full height right, behind Node.
|
// History: Full height right, behind Node.
|
||||||
dock_slot[DOCK_SLOT_RIGHT_UL]->add_child(history_dock);
|
editor_dock_manager->add_control_to_dock(EditorDockManager::DOCK_SLOT_RIGHT_UL, history_dock, TTR("History"));
|
||||||
dock_slot[DOCK_SLOT_RIGHT_UL]->set_tab_title(dock_slot[DOCK_SLOT_RIGHT_UL]->get_tab_idx_from_control(history_dock), TTR("History"));
|
|
||||||
|
|
||||||
// Hide unused dock slots and vsplits.
|
|
||||||
dock_slot[DOCK_SLOT_LEFT_UL]->hide();
|
|
||||||
dock_slot[DOCK_SLOT_LEFT_BL]->hide();
|
|
||||||
dock_slot[DOCK_SLOT_RIGHT_BL]->hide();
|
|
||||||
dock_slot[DOCK_SLOT_RIGHT_UR]->hide();
|
|
||||||
dock_slot[DOCK_SLOT_RIGHT_BR]->hide();
|
|
||||||
left_l_vsplit->hide();
|
|
||||||
right_r_vsplit->hide();
|
|
||||||
|
|
||||||
// Add some offsets to left_r and main hsplits to make LEFT_R and RIGHT_L docks wider than minsize.
|
// Add some offsets to left_r and main hsplits to make LEFT_R and RIGHT_L docks wider than minsize.
|
||||||
left_r_hsplit->set_split_offset(270 * EDSCALE);
|
left_r_hsplit->set_split_offset(270 * EDSCALE);
|
||||||
|
@ -7687,7 +7063,8 @@ EditorNode::EditorNode() {
|
||||||
default_layout->set_value(docks_section, "dock_4", "FileSystem");
|
default_layout->set_value(docks_section, "dock_4", "FileSystem");
|
||||||
default_layout->set_value(docks_section, "dock_5", "Inspector,Node,History");
|
default_layout->set_value(docks_section, "dock_5", "Inspector,Node,History");
|
||||||
|
|
||||||
for (int i = 0; i < vsplits.size(); i++) {
|
// There are 4 vsplits and 4 hsplits.
|
||||||
|
for (int i = 0; i < editor_dock_manager->get_vsplit_count(); i++) {
|
||||||
default_layout->set_value(docks_section, "dock_split_" + itos(i + 1), 0);
|
default_layout->set_value(docks_section, "dock_split_" + itos(i + 1), 0);
|
||||||
}
|
}
|
||||||
default_layout->set_value(docks_section, "dock_hsplit_1", 0);
|
default_layout->set_value(docks_section, "dock_hsplit_1", 0);
|
||||||
|
@ -8119,6 +7496,7 @@ EditorNode::~EditorNode() {
|
||||||
memdelete(editor_plugins_force_input_forwarding);
|
memdelete(editor_plugins_force_input_forwarding);
|
||||||
memdelete(progress_hb);
|
memdelete(progress_hb);
|
||||||
memdelete(surface_upgrade_tool);
|
memdelete(surface_upgrade_tool);
|
||||||
|
memdelete(editor_dock_manager);
|
||||||
|
|
||||||
EditorSettings::destroy();
|
EditorSettings::destroy();
|
||||||
EditorColorMap::finish();
|
EditorColorMap::finish();
|
||||||
|
|
|
@ -73,10 +73,12 @@ class AudioStreamPreviewGenerator;
|
||||||
class BackgroundProgress;
|
class BackgroundProgress;
|
||||||
class DependencyEditor;
|
class DependencyEditor;
|
||||||
class DependencyErrorDialog;
|
class DependencyErrorDialog;
|
||||||
|
class DockSplitContainer;
|
||||||
class DynamicFontImportSettingsDialog;
|
class DynamicFontImportSettingsDialog;
|
||||||
class EditorAbout;
|
class EditorAbout;
|
||||||
class EditorBuildProfileManager;
|
class EditorBuildProfileManager;
|
||||||
class EditorCommandPalette;
|
class EditorCommandPalette;
|
||||||
|
class EditorDockManager;
|
||||||
class EditorExport;
|
class EditorExport;
|
||||||
class EditorExtensionManager;
|
class EditorExtensionManager;
|
||||||
class EditorFeatureProfileManager;
|
class EditorFeatureProfileManager;
|
||||||
|
@ -121,18 +123,6 @@ class EditorNode : public Node {
|
||||||
GDCLASS(EditorNode, Node);
|
GDCLASS(EditorNode, Node);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum DockSlot {
|
|
||||||
DOCK_SLOT_LEFT_UL,
|
|
||||||
DOCK_SLOT_LEFT_BL,
|
|
||||||
DOCK_SLOT_LEFT_UR,
|
|
||||||
DOCK_SLOT_LEFT_BR,
|
|
||||||
DOCK_SLOT_RIGHT_UL,
|
|
||||||
DOCK_SLOT_RIGHT_BL,
|
|
||||||
DOCK_SLOT_RIGHT_UR,
|
|
||||||
DOCK_SLOT_RIGHT_BR,
|
|
||||||
DOCK_SLOT_MAX
|
|
||||||
};
|
|
||||||
|
|
||||||
enum EditorTable {
|
enum EditorTable {
|
||||||
EDITOR_2D = 0,
|
EDITOR_2D = 0,
|
||||||
EDITOR_3D,
|
EDITOR_3D,
|
||||||
|
@ -310,18 +300,15 @@ private:
|
||||||
String renderer_request;
|
String renderer_request;
|
||||||
|
|
||||||
// Split containers.
|
// Split containers.
|
||||||
HSplitContainer *left_l_hsplit = nullptr;
|
DockSplitContainer *left_l_hsplit = nullptr;
|
||||||
VSplitContainer *left_l_vsplit = nullptr;
|
DockSplitContainer *left_l_vsplit = nullptr;
|
||||||
HSplitContainer *left_r_hsplit = nullptr;
|
DockSplitContainer *left_r_hsplit = nullptr;
|
||||||
VSplitContainer *left_r_vsplit = nullptr;
|
DockSplitContainer *left_r_vsplit = nullptr;
|
||||||
HSplitContainer *main_hsplit = nullptr;
|
DockSplitContainer *main_hsplit = nullptr;
|
||||||
HSplitContainer *right_hsplit = nullptr;
|
DockSplitContainer *right_hsplit = nullptr;
|
||||||
VSplitContainer *right_l_vsplit = nullptr;
|
DockSplitContainer *right_l_vsplit = nullptr;
|
||||||
VSplitContainer *right_r_vsplit = nullptr;
|
DockSplitContainer *right_r_vsplit = nullptr;
|
||||||
VSplitContainer *center_split = nullptr;
|
DockSplitContainer *center_split = nullptr;
|
||||||
// To access those easily by index.
|
|
||||||
Vector<VSplitContainer *> vsplits;
|
|
||||||
Vector<HSplitContainer *> hsplits;
|
|
||||||
|
|
||||||
// Main tabs.
|
// Main tabs.
|
||||||
EditorSceneTabs *scene_tabs = nullptr;
|
EditorSceneTabs *scene_tabs = nullptr;
|
||||||
|
@ -426,20 +413,8 @@ private:
|
||||||
Button *new_inherited_button = nullptr;
|
Button *new_inherited_button = nullptr;
|
||||||
String open_import_request;
|
String open_import_request;
|
||||||
|
|
||||||
Vector<WindowWrapper *> floating_docks;
|
EditorDockManager *editor_dock_manager = nullptr;
|
||||||
|
|
||||||
Button *dock_float = nullptr;
|
|
||||||
Button *dock_tab_move_left = nullptr;
|
|
||||||
Button *dock_tab_move_right = nullptr;
|
|
||||||
Control *dock_select = nullptr;
|
|
||||||
PopupPanel *dock_select_popup = nullptr;
|
|
||||||
Rect2 dock_select_rect[DOCK_SLOT_MAX];
|
|
||||||
TabContainer *dock_slot[DOCK_SLOT_MAX];
|
|
||||||
Timer *editor_layout_save_delay_timer = nullptr;
|
Timer *editor_layout_save_delay_timer = nullptr;
|
||||||
bool docks_visible = true;
|
|
||||||
int dock_popup_selected_idx = -1;
|
|
||||||
int dock_select_rect_over_idx = -1;
|
|
||||||
|
|
||||||
Button *distraction_free = nullptr;
|
Button *distraction_free = nullptr;
|
||||||
|
|
||||||
Vector<BottomPanelItem> bottom_panel_items;
|
Vector<BottomPanelItem> bottom_panel_items;
|
||||||
|
@ -634,17 +609,6 @@ private:
|
||||||
|
|
||||||
bool _find_scene_in_use(Node *p_node, const String &p_path) const;
|
bool _find_scene_in_use(Node *p_node, const String &p_path) const;
|
||||||
|
|
||||||
void _dock_select_input(const Ref<InputEvent> &p_input);
|
|
||||||
void _dock_move_left();
|
|
||||||
void _dock_move_right();
|
|
||||||
void _dock_select_draw();
|
|
||||||
void _dock_pre_popup(int p_which);
|
|
||||||
void _dock_split_dragged(int ofs);
|
|
||||||
void _dock_popup_exit();
|
|
||||||
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 _proceed_closing_scene_tabs();
|
void _proceed_closing_scene_tabs();
|
||||||
bool _is_closing_editor() const;
|
bool _is_closing_editor() const;
|
||||||
|
|
||||||
|
@ -655,11 +619,6 @@ private:
|
||||||
|
|
||||||
void _save_editor_layout();
|
void _save_editor_layout();
|
||||||
void _load_editor_layout();
|
void _load_editor_layout();
|
||||||
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);
|
|
||||||
|
|
||||||
void _save_central_editor_layout_to_config(Ref<ConfigFile> p_config_file);
|
void _save_central_editor_layout_to_config(Ref<ConfigFile> p_config_file);
|
||||||
void _load_central_editor_layout_from_config(Ref<ConfigFile> p_config_file);
|
void _load_central_editor_layout_from_config(Ref<ConfigFile> p_config_file);
|
||||||
|
@ -772,15 +731,9 @@ public:
|
||||||
|
|
||||||
void new_inherited_scene() { _menu_option_confirm(FILE_NEW_INHERITED_SCENE, false); }
|
void new_inherited_scene() { _menu_option_confirm(FILE_NEW_INHERITED_SCENE, false); }
|
||||||
|
|
||||||
void set_docks_visible(bool p_show);
|
|
||||||
bool get_docks_visible() const;
|
|
||||||
|
|
||||||
void set_distraction_free_mode(bool p_enter);
|
void set_distraction_free_mode(bool p_enter);
|
||||||
bool is_distraction_free_mode_enabled() const;
|
bool is_distraction_free_mode_enabled() const;
|
||||||
|
|
||||||
void add_control_to_dock(DockSlot p_slot, Control *p_control);
|
|
||||||
void remove_control_from_dock(Control *p_control);
|
|
||||||
|
|
||||||
void set_addon_plugin_enabled(const String &p_addon, bool p_enabled, bool p_config_changed = false);
|
void set_addon_plugin_enabled(const String &p_addon, bool p_enabled, bool p_config_changed = false);
|
||||||
bool is_addon_plugin_enabled(const String &p_addon) const;
|
bool is_addon_plugin_enabled(const String &p_addon) const;
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include "editor_plugin.h"
|
#include "editor_plugin.h"
|
||||||
|
|
||||||
#include "editor/debugger/editor_debugger_node.h"
|
#include "editor/debugger/editor_debugger_node.h"
|
||||||
|
#include "editor/editor_dock_manager.h"
|
||||||
#include "editor/editor_file_system.h"
|
#include "editor/editor_file_system.h"
|
||||||
#include "editor/editor_inspector.h"
|
#include "editor/editor_inspector.h"
|
||||||
#include "editor/editor_interface.h"
|
#include "editor/editor_interface.h"
|
||||||
|
@ -84,12 +85,12 @@ Button *EditorPlugin::add_control_to_bottom_panel(Control *p_control, const Stri
|
||||||
|
|
||||||
void EditorPlugin::add_control_to_dock(DockSlot p_slot, Control *p_control) {
|
void EditorPlugin::add_control_to_dock(DockSlot p_slot, Control *p_control) {
|
||||||
ERR_FAIL_NULL(p_control);
|
ERR_FAIL_NULL(p_control);
|
||||||
EditorNode::get_singleton()->add_control_to_dock(EditorNode::DockSlot(p_slot), p_control);
|
EditorDockManager::get_singleton()->add_control_to_dock(EditorDockManager::DockSlot(p_slot), p_control);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditorPlugin::remove_control_from_docks(Control *p_control) {
|
void EditorPlugin::remove_control_from_docks(Control *p_control) {
|
||||||
ERR_FAIL_NULL(p_control);
|
ERR_FAIL_NULL(p_control);
|
||||||
EditorNode::get_singleton()->remove_control_from_dock(p_control);
|
EditorDockManager::get_singleton()->remove_control_from_dock(p_control);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EditorPlugin::remove_control_from_bottom_panel(Control *p_control) {
|
void EditorPlugin::remove_control_from_bottom_panel(Control *p_control) {
|
||||||
|
|
|
@ -3665,6 +3665,70 @@ void FileSystemDock::_bind_methods() {
|
||||||
ADD_SIGNAL(MethodInfo("display_mode_changed"));
|
ADD_SIGNAL(MethodInfo("display_mode_changed"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FileSystemDock::save_layout_to_config(Ref<ConfigFile> p_layout, const String &p_section) const {
|
||||||
|
p_layout->set_value(p_section, "dock_filesystem_h_split_offset", get_h_split_offset());
|
||||||
|
p_layout->set_value(p_section, "dock_filesystem_v_split_offset", get_v_split_offset());
|
||||||
|
p_layout->set_value(p_section, "dock_filesystem_display_mode", get_display_mode());
|
||||||
|
p_layout->set_value(p_section, "dock_filesystem_file_sort", get_file_sort());
|
||||||
|
p_layout->set_value(p_section, "dock_filesystem_file_list_display_mode", get_file_list_display_mode());
|
||||||
|
PackedStringArray selected_files = get_selected_paths();
|
||||||
|
p_layout->set_value(p_section, "dock_filesystem_selected_paths", selected_files);
|
||||||
|
Vector<String> uncollapsed_paths = get_uncollapsed_paths();
|
||||||
|
p_layout->set_value(p_section, "dock_filesystem_uncollapsed_paths", uncollapsed_paths);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileSystemDock::load_layout_from_config(Ref<ConfigFile> p_layout, const String &p_section) {
|
||||||
|
if (p_layout->has_section_key(p_section, "dock_filesystem_h_split_offset")) {
|
||||||
|
int fs_h_split_ofs = p_layout->get_value(p_section, "dock_filesystem_h_split_offset");
|
||||||
|
set_h_split_offset(fs_h_split_ofs);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p_layout->has_section_key(p_section, "dock_filesystem_v_split_offset")) {
|
||||||
|
int fs_v_split_ofs = p_layout->get_value(p_section, "dock_filesystem_v_split_offset");
|
||||||
|
set_v_split_offset(fs_v_split_ofs);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p_layout->has_section_key(p_section, "dock_filesystem_display_mode")) {
|
||||||
|
DisplayMode dock_filesystem_display_mode = DisplayMode(int(p_layout->get_value(p_section, "dock_filesystem_display_mode")));
|
||||||
|
set_display_mode(dock_filesystem_display_mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p_layout->has_section_key(p_section, "dock_filesystem_file_sort")) {
|
||||||
|
FileSortOption dock_filesystem_file_sort = FileSortOption(int(p_layout->get_value(p_section, "dock_filesystem_file_sort")));
|
||||||
|
set_file_sort(dock_filesystem_file_sort);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p_layout->has_section_key(p_section, "dock_filesystem_file_list_display_mode")) {
|
||||||
|
FileListDisplayMode dock_filesystem_file_list_display_mode = FileListDisplayMode(int(p_layout->get_value(p_section, "dock_filesystem_file_list_display_mode")));
|
||||||
|
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++) {
|
||||||
|
select_file(dock_filesystem_selected_paths[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Restore collapsed state.
|
||||||
|
PackedStringArray uncollapsed_tis;
|
||||||
|
if (p_layout->has_section_key(p_section, "dock_filesystem_uncollapsed_paths")) {
|
||||||
|
uncollapsed_tis = p_layout->get_value(p_section, "dock_filesystem_uncollapsed_paths");
|
||||||
|
} else {
|
||||||
|
uncollapsed_tis = { "res://" };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!uncollapsed_tis.is_empty()) {
|
||||||
|
for (int i = 0; i < uncollapsed_tis.size(); i++) {
|
||||||
|
TreeItem *uncollapsed_ti = get_tree_control()->get_item_with_metadata(uncollapsed_tis[i], 0);
|
||||||
|
if (uncollapsed_ti) {
|
||||||
|
uncollapsed_ti->set_collapsed(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
get_tree_control()->queue_redraw();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
FileSystemDock::FileSystemDock() {
|
FileSystemDock::FileSystemDock() {
|
||||||
singleton = this;
|
singleton = this;
|
||||||
set_name("FileSystem");
|
set_name("FileSystem");
|
||||||
|
|
|
@ -394,13 +394,13 @@ public:
|
||||||
void select_file(const String &p_file);
|
void select_file(const String &p_file);
|
||||||
|
|
||||||
void set_display_mode(DisplayMode p_display_mode);
|
void set_display_mode(DisplayMode p_display_mode);
|
||||||
DisplayMode get_display_mode() { return display_mode; }
|
DisplayMode get_display_mode() const { return display_mode; }
|
||||||
|
|
||||||
void set_file_sort(FileSortOption p_file_sort);
|
void set_file_sort(FileSortOption p_file_sort);
|
||||||
FileSortOption get_file_sort() { return file_sort; }
|
FileSortOption get_file_sort() const { return file_sort; }
|
||||||
|
|
||||||
void set_file_list_display_mode(FileListDisplayMode p_mode);
|
void set_file_list_display_mode(FileListDisplayMode p_mode);
|
||||||
FileListDisplayMode get_file_list_display_mode() { return file_list_display_mode; };
|
FileListDisplayMode get_file_list_display_mode() const { return file_list_display_mode; };
|
||||||
|
|
||||||
Tree *get_tree_control() { return tree; }
|
Tree *get_tree_control() { return tree; }
|
||||||
|
|
||||||
|
@ -408,6 +408,9 @@ public:
|
||||||
void remove_resource_tooltip_plugin(const Ref<EditorResourceTooltipPlugin> &p_plugin);
|
void remove_resource_tooltip_plugin(const Ref<EditorResourceTooltipPlugin> &p_plugin);
|
||||||
Control *create_tooltip_for_path(const String &p_path) const;
|
Control *create_tooltip_for_path(const String &p_path) const;
|
||||||
|
|
||||||
|
void save_layout_to_config(Ref<ConfigFile> p_layout, const String &p_section) const;
|
||||||
|
void load_layout_from_config(Ref<ConfigFile> p_layout, const String &p_section);
|
||||||
|
|
||||||
FileSystemDock();
|
FileSystemDock();
|
||||||
~FileSystemDock();
|
~FileSystemDock();
|
||||||
};
|
};
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#include "core/config/project_settings.h"
|
#include "core/config/project_settings.h"
|
||||||
#include "core/os/keyboard.h"
|
#include "core/os/keyboard.h"
|
||||||
#include "core/os/time.h"
|
#include "core/os/time.h"
|
||||||
|
#include "editor/editor_dock_manager.h"
|
||||||
#include "editor/editor_file_system.h"
|
#include "editor/editor_file_system.h"
|
||||||
#include "editor/editor_interface.h"
|
#include "editor/editor_interface.h"
|
||||||
#include "editor/editor_node.h"
|
#include "editor/editor_node.h"
|
||||||
|
@ -909,7 +910,7 @@ void VersionControlEditorPlugin::fetch_available_vcs_plugin_names() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void VersionControlEditorPlugin::register_editor() {
|
void VersionControlEditorPlugin::register_editor() {
|
||||||
EditorNode::get_singleton()->add_control_to_dock(EditorNode::DOCK_SLOT_RIGHT_UL, version_commit_dock);
|
EditorDockManager::get_singleton()->add_control_to_dock(EditorDockManager::DOCK_SLOT_RIGHT_UL, version_commit_dock);
|
||||||
|
|
||||||
version_control_dock_button = EditorNode::get_singleton()->add_bottom_panel_item(TTR("Version Control"), version_control_dock);
|
version_control_dock_button = EditorNode::get_singleton()->add_bottom_panel_item(TTR("Version Control"), version_control_dock);
|
||||||
|
|
||||||
|
@ -929,7 +930,7 @@ void VersionControlEditorPlugin::shut_down() {
|
||||||
memdelete(EditorVCSInterface::get_singleton());
|
memdelete(EditorVCSInterface::get_singleton());
|
||||||
EditorVCSInterface::set_singleton(nullptr);
|
EditorVCSInterface::set_singleton(nullptr);
|
||||||
|
|
||||||
EditorNode::get_singleton()->remove_control_from_dock(version_commit_dock);
|
EditorDockManager::get_singleton()->remove_control_from_dock(version_commit_dock);
|
||||||
EditorNode::get_singleton()->remove_bottom_panel_item(version_control_dock);
|
EditorNode::get_singleton()->remove_bottom_panel_item(version_control_dock);
|
||||||
|
|
||||||
_set_vcs_ui_state(false);
|
_set_vcs_ui_state(false);
|
||||||
|
|
|
@ -39,7 +39,7 @@ void SplitContainerDragger::gui_input(const Ref<InputEvent> &p_event) {
|
||||||
|
|
||||||
SplitContainer *sc = Object::cast_to<SplitContainer>(get_parent());
|
SplitContainer *sc = Object::cast_to<SplitContainer>(get_parent());
|
||||||
|
|
||||||
if (sc->collapsed || !sc->_getch(0) || !sc->_getch(1) || sc->dragger_visibility != SplitContainer::DRAGGER_VISIBLE) {
|
if (sc->collapsed || !sc->get_containable_child(0) || !sc->get_containable_child(1) || sc->dragger_visibility != SplitContainer::DRAGGER_VISIBLE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,7 +122,7 @@ void SplitContainerDragger::_notification(int p_what) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Control *SplitContainer::_getch(int p_idx) const {
|
Control *SplitContainer::get_containable_child(int p_idx) const {
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
|
|
||||||
for (int i = 0; i < get_child_count(false); i++) {
|
for (int i = 0; i < get_child_count(false); i++) {
|
||||||
|
@ -157,8 +157,8 @@ Ref<Texture2D> SplitContainer::_get_grabber_icon() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SplitContainer::_compute_middle_sep(bool p_clamp) {
|
void SplitContainer::_compute_middle_sep(bool p_clamp) {
|
||||||
Control *first = _getch(0);
|
Control *first = get_containable_child(0);
|
||||||
Control *second = _getch(1);
|
Control *second = get_containable_child(1);
|
||||||
|
|
||||||
// Determine expanded children.
|
// Determine expanded children.
|
||||||
bool first_expanded = (vertical ? first->get_v_size_flags() : first->get_h_size_flags()) & SIZE_EXPAND;
|
bool first_expanded = (vertical ? first->get_v_size_flags() : first->get_h_size_flags()) & SIZE_EXPAND;
|
||||||
|
@ -199,8 +199,8 @@ void SplitContainer::_compute_middle_sep(bool p_clamp) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SplitContainer::_resort() {
|
void SplitContainer::_resort() {
|
||||||
Control *first = _getch(0);
|
Control *first = get_containable_child(0);
|
||||||
Control *second = _getch(1);
|
Control *second = get_containable_child(1);
|
||||||
|
|
||||||
// If we have only one element.
|
// If we have only one element.
|
||||||
if (!first || !second) {
|
if (!first || !second) {
|
||||||
|
@ -261,7 +261,7 @@ Size2 SplitContainer::get_minimum_size() const {
|
||||||
int sep = (dragger_visibility != DRAGGER_HIDDEN_COLLAPSED) ? MAX(theme_cache.separation, vertical ? g->get_height() : g->get_width()) : 0;
|
int sep = (dragger_visibility != DRAGGER_HIDDEN_COLLAPSED) ? MAX(theme_cache.separation, vertical ? g->get_height() : g->get_width()) : 0;
|
||||||
|
|
||||||
for (int i = 0; i < 2; i++) {
|
for (int i = 0; i < 2; i++) {
|
||||||
if (!_getch(i)) {
|
if (!get_containable_child(i)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -273,7 +273,7 @@ Size2 SplitContainer::get_minimum_size() const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Size2 ms = _getch(i)->get_combined_minimum_size();
|
Size2 ms = get_containable_child(i)->get_combined_minimum_size();
|
||||||
|
|
||||||
if (vertical) {
|
if (vertical) {
|
||||||
minimum.height += ms.height;
|
minimum.height += ms.height;
|
||||||
|
@ -325,7 +325,7 @@ int SplitContainer::get_split_offset() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SplitContainer::clamp_split_offset() {
|
void SplitContainer::clamp_split_offset() {
|
||||||
if (!_getch(0) || !_getch(1)) {
|
if (!get_containable_child(0) || !get_containable_child(1)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -79,8 +79,6 @@ private:
|
||||||
Ref<Texture2D> grabber_icon_v;
|
Ref<Texture2D> grabber_icon_v;
|
||||||
} theme_cache;
|
} theme_cache;
|
||||||
|
|
||||||
Control *_getch(int p_idx) const;
|
|
||||||
|
|
||||||
Ref<Texture2D> _get_grabber_icon() const;
|
Ref<Texture2D> _get_grabber_icon() const;
|
||||||
void _compute_middle_sep(bool p_clamp);
|
void _compute_middle_sep(bool p_clamp);
|
||||||
void _resort();
|
void _resort();
|
||||||
|
@ -88,6 +86,8 @@ private:
|
||||||
protected:
|
protected:
|
||||||
bool is_fixed = false;
|
bool is_fixed = false;
|
||||||
|
|
||||||
|
Control *get_containable_child(int p_idx) const;
|
||||||
|
|
||||||
void _notification(int p_what);
|
void _notification(int p_what);
|
||||||
void _validate_property(PropertyInfo &p_property) const;
|
void _validate_property(PropertyInfo &p_property) const;
|
||||||
static void _bind_methods();
|
static void _bind_methods();
|
||||||
|
|
Loading…
Reference in a new issue