Open sub-windows as embedded if the OS does not support them
This commit is contained in:
parent
441f1a5fe9
commit
c7b4dcae2f
32 changed files with 1027 additions and 636 deletions
|
@ -2853,7 +2853,10 @@ void AnimationTrackEdit::_gui_input(const Ref<InputEvent> &p_event) {
|
|||
Vector2 theme_ofs = path->get_theme_stylebox("normal", "LineEdit")->get_offset();
|
||||
path->set_position(get_global_position() + path_rect.position - theme_ofs);
|
||||
path->set_size(path_rect.size);
|
||||
path->show_modal();
|
||||
#ifndef _MSC_VER
|
||||
#warning show modal not supported any longer, need to move this to a popup
|
||||
#endif
|
||||
path->show();
|
||||
path->grab_focus();
|
||||
path->set_cursor_position(path->get_text().length());
|
||||
clicking_on_name = false;
|
||||
|
|
|
@ -264,11 +264,8 @@ void EditorNode::_update_title() {
|
|||
|
||||
void EditorNode::_unhandled_input(const Ref<InputEvent> &p_event) {
|
||||
|
||||
if (Node::get_viewport()->get_modal_stack_top())
|
||||
return; //ignore because of modal window
|
||||
|
||||
Ref<InputEventKey> k = p_event;
|
||||
if (k.is_valid() && k->is_pressed() && !k->is_echo() && !gui_base->get_viewport()->gui_has_modal_stack()) {
|
||||
if (k.is_valid() && k->is_pressed() && !k->is_echo()) {
|
||||
|
||||
EditorPlugin *old_editor = editor_plugin_screen;
|
||||
|
||||
|
|
|
@ -911,15 +911,16 @@ Ref<Theme> create_editor_theme(const Ref<Theme> p_theme) {
|
|||
style_window->set_border_width(MARGIN_TOP, 24 * EDSCALE);
|
||||
style_window->set_expand_margin_size(MARGIN_TOP, 24 * EDSCALE);
|
||||
|
||||
theme->set_stylebox("panel", "AcceptDialog", style_default);
|
||||
theme->set_stylebox("panel_window", "AcceptDialog", style_window);
|
||||
theme->set_color("title_color", "AcceptDialog", font_color);
|
||||
theme->set_icon("close", "AcceptDialog", theme->get_icon("GuiClose", "EditorIcons"));
|
||||
theme->set_icon("close_highlight", "AcceptDialog", theme->get_icon("GuiClose", "EditorIcons"));
|
||||
theme->set_constant("close_h_ofs", "AcceptDialog", 22 * EDSCALE);
|
||||
theme->set_constant("close_v_ofs", "AcceptDialog", 20 * EDSCALE);
|
||||
theme->set_constant("title_height", "AcceptDialog", 24 * EDSCALE);
|
||||
theme->set_font("title_font", "AcceptDialog", theme->get_font("title", "EditorFonts"));
|
||||
theme->set_stylebox("panel", "Window", style_default);
|
||||
theme->set_stylebox("panel_window", "Window", style_window);
|
||||
theme->set_color("title_color", "Window", font_color);
|
||||
theme->set_icon("close", "Window", theme->get_icon("GuiClose", "EditorIcons"));
|
||||
theme->set_icon("close_highlight", "Window", theme->get_icon("GuiClose", "EditorIcons"));
|
||||
theme->set_constant("close_h_ofs", "Window", 22 * EDSCALE);
|
||||
theme->set_constant("close_v_ofs", "Window", 20 * EDSCALE);
|
||||
theme->set_constant("title_height", "Window", 24 * EDSCALE);
|
||||
theme->set_constant("resize_margin", "Window", 4 * EDSCALE);
|
||||
theme->set_font("title_font", "Window", theme->get_font("title", "EditorFonts"));
|
||||
|
||||
// complex window, for now only Editor settings and Project settings
|
||||
Ref<StyleBoxFlat> style_complex_window = style_window->duplicate();
|
||||
|
|
|
@ -2350,8 +2350,6 @@ void FileSystemDock::_file_multi_selected(int p_index, bool p_selected) {
|
|||
}
|
||||
|
||||
void FileSystemDock::_tree_gui_input(Ref<InputEvent> p_event) {
|
||||
if (get_viewport()->get_modal_stack_top())
|
||||
return; // Ignore because of modal window.
|
||||
|
||||
Ref<InputEventKey> key = p_event;
|
||||
if (key.is_valid() && key->is_pressed() && !key->is_echo()) {
|
||||
|
@ -2368,8 +2366,6 @@ void FileSystemDock::_tree_gui_input(Ref<InputEvent> p_event) {
|
|||
}
|
||||
|
||||
void FileSystemDock::_file_list_gui_input(Ref<InputEvent> p_event) {
|
||||
if (get_viewport()->get_modal_stack_top())
|
||||
return; // Ignore because of modal window.
|
||||
|
||||
Ref<InputEventKey> key = p_event;
|
||||
if (key.is_valid() && key->is_pressed() && !key->is_echo()) {
|
||||
|
|
|
@ -158,7 +158,11 @@ void AnimationNodeStateMachineEditor::_state_machine_gui_input(const Ref<InputEv
|
|||
name_edit->set_global_position(state_machine_draw->get_global_transform().xform(edit_rect.position));
|
||||
name_edit->set_size(edit_rect.size);
|
||||
name_edit->set_text(node_rects[i].node_name);
|
||||
name_edit->show_modal();
|
||||
#ifndef _MSC_VER
|
||||
#warning no more show modal, so it must replaced by a popup
|
||||
#endif
|
||||
//name_edit->show_modal();
|
||||
name_edit->show();
|
||||
name_edit->grab_focus();
|
||||
name_edit->select_all();
|
||||
|
||||
|
|
|
@ -477,7 +477,7 @@ void CanvasItemEditor::_unhandled_key_input(const Ref<InputEvent> &p_ev) {
|
|||
|
||||
Ref<InputEventKey> k = p_ev;
|
||||
|
||||
if (!is_visible_in_tree() || get_viewport()->gui_has_modal_stack())
|
||||
if (!is_visible_in_tree())
|
||||
return;
|
||||
|
||||
if (k->get_keycode() == KEY_CONTROL || k->get_keycode() == KEY_ALT || k->get_keycode() == KEY_SHIFT) {
|
||||
|
|
|
@ -5718,7 +5718,7 @@ void SpatialEditor::snap_selected_nodes_to_floor() {
|
|||
|
||||
void SpatialEditor::_unhandled_key_input(Ref<InputEvent> p_event) {
|
||||
|
||||
if (!is_visible_in_tree() || get_viewport()->gui_has_modal_stack())
|
||||
if (!is_visible_in_tree())
|
||||
return;
|
||||
|
||||
snap_key_enabled = InputFilter::get_singleton()->is_key_pressed(KEY_CONTROL);
|
||||
|
|
|
@ -75,9 +75,6 @@ void SceneTreeDock::_input(Ref<InputEvent> p_event) {
|
|||
|
||||
void SceneTreeDock::_unhandled_key_input(Ref<InputEvent> p_event) {
|
||||
|
||||
if (get_viewport()->get_modal_stack_top())
|
||||
return; //ignore because of modal window
|
||||
|
||||
if (get_focus_owner() && get_focus_owner()->is_text_field())
|
||||
return;
|
||||
|
||||
|
|
|
@ -120,6 +120,7 @@ static int audio_driver_idx = -1;
|
|||
|
||||
// Engine config/tools
|
||||
|
||||
static bool single_window = false;
|
||||
static bool editor = false;
|
||||
static bool project_manager = false;
|
||||
static String locale;
|
||||
|
@ -303,6 +304,7 @@ void Main::print_help(const char *p_binary) {
|
|||
OS::get_singleton()->print(" --no-window Disable window creation (Windows only). Useful together with --script.\n");
|
||||
OS::get_singleton()->print(" --enable-vsync-via-compositor When vsync is enabled, vsync via the OS' window compositor (Windows only).\n");
|
||||
OS::get_singleton()->print(" --disable-vsync-via-compositor Disable vsync via the OS' window compositor (Windows only).\n");
|
||||
OS::get_singleton()->print(" --single-window Use a single window (no separate subwindows).\n");
|
||||
OS::get_singleton()->print("\n");
|
||||
#endif
|
||||
|
||||
|
@ -576,6 +578,9 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
|
|||
} else if (I->get() == "--gpu-abort") { // force windowed window
|
||||
|
||||
Engine::singleton->abort_on_gpu_errors = true;
|
||||
} else if (I->get() == "--single-window") { // force single window
|
||||
|
||||
single_window = true;
|
||||
} else if (I->get() == "-t" || I->get() == "--always-on-top") { // force always-on-top window
|
||||
|
||||
init_always_on_top = true;
|
||||
|
@ -1710,6 +1715,9 @@ bool Main::start() {
|
|||
}
|
||||
#endif
|
||||
|
||||
if (single_window) {
|
||||
sml->get_root()->set_embed_subwindows_hint(true);
|
||||
}
|
||||
ResourceLoader::add_custom_loaders();
|
||||
ResourceSaver::add_custom_savers();
|
||||
|
||||
|
|
|
@ -708,13 +708,13 @@ void DisplayServerX11::window_set_title(const String &p_title, WindowID p_window
|
|||
XChangeProperty(x11_display, wd.x11_window, _net_wm_name, utf8_string, 8, PropModeReplace, (unsigned char *)p_title.utf8().get_data(), p_title.utf8().length());
|
||||
}
|
||||
|
||||
void DisplayServerX11::window_set_resize_callback(const Callable &p_callable, WindowID p_window) {
|
||||
void DisplayServerX11::window_set_rect_changed_callback(const Callable &p_callable, WindowID p_window) {
|
||||
|
||||
_THREAD_SAFE_METHOD_
|
||||
|
||||
ERR_FAIL_COND(!windows.has(p_window));
|
||||
WindowData &wd = windows[p_window];
|
||||
wd.resize_callback = p_callable;
|
||||
wd.rect_changed_callback = p_callable;
|
||||
}
|
||||
|
||||
void DisplayServerX11::window_set_window_event_callback(const Callable &p_callable, WindowID p_window) {
|
||||
|
@ -2224,12 +2224,12 @@ void DisplayServerX11::_window_changed(XEvent *event) {
|
|||
}
|
||||
#endif
|
||||
|
||||
if (!wd.resize_callback.is_null()) {
|
||||
Variant size = wd.size;
|
||||
Variant *sizep = &size;
|
||||
if (!wd.rect_changed_callback.is_null()) {
|
||||
Variant rect = Rect2i(wd.im_position, wd.size);
|
||||
Variant *rectp = ▭
|
||||
Variant ret;
|
||||
Callable::CallError ce;
|
||||
wd.resize_callback.call((const Variant **)&sizep, 1, ret, ce);
|
||||
wd.rect_changed_callback.call((const Variant **)&rectp, 1, ret, ce);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -121,7 +121,7 @@ class DisplayServerX11 : public DisplayServer {
|
|||
Size2i size;
|
||||
Size2i im_position;
|
||||
bool im_active = false;
|
||||
Callable resize_callback;
|
||||
Callable rect_changed_callback;
|
||||
Callable event_callback;
|
||||
Callable input_event_callback;
|
||||
Callable input_text_callback;
|
||||
|
@ -268,7 +268,7 @@ public:
|
|||
virtual void delete_sub_window(WindowID p_id);
|
||||
|
||||
virtual void window_set_title(const String &p_title, WindowID p_window = MAIN_WINDOW_ID);
|
||||
virtual void window_set_resize_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID);
|
||||
virtual void window_set_rect_changed_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID);
|
||||
virtual void window_set_window_event_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID);
|
||||
virtual void window_set_input_event_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID);
|
||||
virtual void window_set_input_text_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID);
|
||||
|
|
|
@ -420,6 +420,10 @@ DisplayServer::WindowID DisplayServerWindows::create_sub_window(WindowMode p_mod
|
|||
}
|
||||
}
|
||||
|
||||
ShowWindow(windows[window_id].hWnd, SW_SHOW); // Show The Window
|
||||
SetForegroundWindow(windows[window_id].hWnd); // Slightly Higher Priority
|
||||
SetFocus(windows[window_id].hWnd); // Sets Keyboard Focus To
|
||||
|
||||
return window_id;
|
||||
}
|
||||
void DisplayServerWindows::delete_sub_window(WindowID p_window) {
|
||||
|
@ -449,12 +453,12 @@ void DisplayServerWindows::delete_sub_window(WindowID p_window) {
|
|||
windows.erase(p_window);
|
||||
}
|
||||
|
||||
void DisplayServerWindows::window_set_resize_callback(const Callable &p_callable, WindowID p_window) {
|
||||
void DisplayServerWindows::window_set_rect_changed_callback(const Callable &p_callable, WindowID p_window) {
|
||||
|
||||
_THREAD_SAFE_METHOD_
|
||||
|
||||
ERR_FAIL_COND(!windows.has(p_window));
|
||||
windows[p_window].resize_callback = p_callable;
|
||||
windows[p_window].rect_changed_callback = p_callable;
|
||||
}
|
||||
|
||||
void DisplayServerWindows::window_set_window_event_callback(const Callable &p_callable, WindowID p_window) {
|
||||
|
@ -757,20 +761,32 @@ void DisplayServerWindows::_update_window_style(WindowID p_window, bool p_repain
|
|||
ERR_FAIL_COND(!windows.has(p_window));
|
||||
WindowData &wd = windows[p_window];
|
||||
|
||||
DWORD style = 0;
|
||||
DWORD style_ex = WS_EX_WINDOWEDGE;
|
||||
if (p_window == MAIN_WINDOW_ID) {
|
||||
style_ex |= WS_EX_APPWINDOW;
|
||||
}
|
||||
|
||||
if (wd.fullscreen || wd.borderless) {
|
||||
SetWindowLongPtr(wd.hWnd, GWL_STYLE, WS_SYSMENU | WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE);
|
||||
style = WS_SYSMENU | WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE;
|
||||
if (wd.borderless) {
|
||||
style_ex |= WS_EX_TOOLWINDOW;
|
||||
}
|
||||
} else {
|
||||
if (wd.resizable) {
|
||||
if (p_maximized) {
|
||||
SetWindowLongPtr(wd.hWnd, GWL_STYLE, WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_MAXIMIZE);
|
||||
style = WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_MAXIMIZE;
|
||||
} else {
|
||||
SetWindowLongPtr(wd.hWnd, GWL_STYLE, WS_OVERLAPPEDWINDOW | WS_VISIBLE);
|
||||
style = GWL_STYLE, WS_OVERLAPPEDWINDOW | WS_VISIBLE;
|
||||
}
|
||||
} else {
|
||||
SetWindowLongPtr(wd.hWnd, GWL_STYLE, WS_CAPTION | WS_MINIMIZEBOX | WS_POPUPWINDOW | WS_VISIBLE);
|
||||
style = WS_CAPTION | WS_MINIMIZEBOX | WS_POPUPWINDOW | WS_VISIBLE;
|
||||
}
|
||||
}
|
||||
|
||||
SetWindowLongPtr(wd.hWnd, GWL_STYLE, style);
|
||||
SetWindowLongPtr(wd.hWnd, GWL_EXSTYLE, style_ex);
|
||||
|
||||
SetWindowPos(wd.hWnd, wd.always_on_top ? HWND_TOPMOST : HWND_NOTOPMOST, 0, 0, 0, 0, SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE);
|
||||
|
||||
if (p_repaint) {
|
||||
|
@ -2208,6 +2224,15 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
|
|||
int x = LOWORD(lParam);
|
||||
int y = HIWORD(lParam);
|
||||
windows[window_id].last_pos = Point2(x, y);
|
||||
|
||||
if (!windows[window_id].rect_changed_callback.is_null()) {
|
||||
|
||||
Variant size = Rect2i(windows[window_id].last_pos.x, windows[window_id].last_pos.y, windows[window_id].width, windows[window_id].height);
|
||||
Variant *sizep = &size;
|
||||
Variant ret;
|
||||
Callable::CallError ce;
|
||||
windows[window_id].rect_changed_callback.call((const Variant **)&sizep, 1, ret, ce);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
|
@ -2232,13 +2257,13 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
|
|||
}
|
||||
}
|
||||
|
||||
if (!windows[window_id].resize_callback.is_null()) {
|
||||
if (!windows[window_id].rect_changed_callback.is_null()) {
|
||||
|
||||
Variant size = Size2(windows[window_id].width, windows[window_id].height);
|
||||
Variant size = Rect2i(windows[window_id].last_pos.x, windows[window_id].last_pos.y, windows[window_id].width, windows[window_id].height);
|
||||
Variant *sizep = &size;
|
||||
Variant ret;
|
||||
Callable::CallError ce;
|
||||
windows[window_id].resize_callback.call((const Variant **)&sizep, 1, ret, ce);
|
||||
windows[window_id].rect_changed_callback.call((const Variant **)&sizep, 1, ret, ce);
|
||||
}
|
||||
|
||||
if (wParam == SIZE_MAXIMIZED) {
|
||||
|
@ -2541,9 +2566,13 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode,
|
|||
DWORD dwExStyle;
|
||||
DWORD dwStyle;
|
||||
|
||||
dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
|
||||
dwExStyle = WS_EX_WINDOWEDGE;
|
||||
dwStyle = WS_OVERLAPPEDWINDOW;
|
||||
|
||||
if (window_id_counter == MAIN_WINDOW_ID) {
|
||||
dwExStyle |= WS_EX_APPWINDOW;
|
||||
}
|
||||
|
||||
RECT WindowRect;
|
||||
|
||||
WindowRect.left = p_rect.position.x;
|
||||
|
@ -2594,10 +2623,6 @@ DisplayServer::WindowID DisplayServerWindows::_create_window(WindowMode p_mode,
|
|||
|
||||
DragAcceptFiles(wd.hWnd, true);
|
||||
|
||||
ShowWindow(wd.hWnd, SW_SHOW); // Show The Window
|
||||
SetForegroundWindow(wd.hWnd); // Slightly Higher Priority
|
||||
SetFocus(wd.hWnd); // Sets Keyboard Focus To
|
||||
|
||||
// IME
|
||||
wd.im_himc = ImmGetContext(wd.hWnd);
|
||||
ImmReleaseContext(wd.hWnd, wd.im_himc);
|
||||
|
@ -2743,6 +2768,10 @@ DisplayServerWindows::DisplayServerWindows(const String &p_rendering_driver, Win
|
|||
}
|
||||
}
|
||||
|
||||
ShowWindow(windows[MAIN_WINDOW_ID].hWnd, SW_SHOW); // Show The Window
|
||||
SetForegroundWindow(windows[MAIN_WINDOW_ID].hWnd); // Slightly Higher Priority
|
||||
SetFocus(windows[MAIN_WINDOW_ID].hWnd); // Sets Keyboard Focus To
|
||||
|
||||
#if defined(VULKAN_ENABLED)
|
||||
|
||||
if (rendering_driver == "vulkan") {
|
||||
|
|
|
@ -200,7 +200,7 @@ class DisplayServerWindows : public DisplayServer {
|
|||
|
||||
bool layered_window = false;
|
||||
|
||||
Callable resize_callback;
|
||||
Callable rect_changed_callback;
|
||||
Callable event_callback;
|
||||
Callable input_event_callback;
|
||||
Callable input_text_callback;
|
||||
|
@ -293,7 +293,7 @@ public:
|
|||
virtual WindowID create_sub_window(WindowMode p_mode, uint32_t p_flags, const Rect2i &p_rect = Rect2i());
|
||||
virtual void delete_sub_window(WindowID p_window);
|
||||
|
||||
virtual void window_set_resize_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID);
|
||||
virtual void window_set_rect_changed_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID);
|
||||
|
||||
virtual void window_set_window_event_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID);
|
||||
virtual void window_set_input_event_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID);
|
||||
|
|
|
@ -460,7 +460,7 @@ Transform2D CanvasItem::get_screen_transform() const {
|
|||
Transform2D xform = get_global_transform_with_canvas();
|
||||
|
||||
Window *w = Object::cast_to<Window>(get_viewport());
|
||||
if (w) {
|
||||
if (w && !w->is_embedding_subwindows()) {
|
||||
Transform2D s;
|
||||
s.set_origin(w->get_position());
|
||||
|
||||
|
|
|
@ -357,9 +357,6 @@ void BaseButton::_unhandled_input(Ref<InputEvent> p_event) {
|
|||
|
||||
if (!is_disabled() && is_visible_in_tree() && !p_event->is_echo() && shortcut.is_valid() && shortcut->is_shortcut(p_event)) {
|
||||
|
||||
if (get_viewport()->get_modal_stack_top() && !get_viewport()->get_modal_stack_top()->is_a_parent_of(this))
|
||||
return; //ignore because of modal window
|
||||
|
||||
on_action_event(p_event);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -620,7 +620,10 @@ void ColorPicker::_screen_pick_pressed() {
|
|||
screen->call_deferred("connect", "hide", Callable(btn_pick, "set_pressed"), varray(false));
|
||||
}
|
||||
screen->raise();
|
||||
screen->show_modal();
|
||||
#ifndef _MSC_VER
|
||||
#warning show modal no longer works, needs to be converted to a popup
|
||||
#endif
|
||||
//screen->show_modal();
|
||||
}
|
||||
|
||||
void ColorPicker::_focus_enter() {
|
||||
|
|
|
@ -494,76 +494,54 @@ void Control::_notification(int p_notification) {
|
|||
|
||||
data.parent = Object::cast_to<Control>(get_parent());
|
||||
|
||||
if (is_set_as_toplevel()) {
|
||||
data.SI = get_viewport()->_gui_add_subwindow_control(this);
|
||||
Node *parent = this; //meh
|
||||
Control *parent_control = NULL;
|
||||
bool subwindow = false;
|
||||
|
||||
if (data.theme.is_null() && data.parent && data.parent->data.theme_owner) {
|
||||
data.theme_owner = data.parent->data.theme_owner;
|
||||
notification(NOTIFICATION_THEME_CHANGED);
|
||||
while (parent) {
|
||||
|
||||
parent = parent->get_parent();
|
||||
|
||||
if (!parent)
|
||||
break;
|
||||
|
||||
CanvasItem *ci = Object::cast_to<CanvasItem>(parent);
|
||||
if (ci && ci->is_set_as_toplevel()) {
|
||||
subwindow = true;
|
||||
break;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
Node *parent = this; //meh
|
||||
Control *parent_control = NULL;
|
||||
bool subwindow = false;
|
||||
|
||||
while (parent) {
|
||||
|
||||
parent = parent->get_parent();
|
||||
|
||||
if (!parent)
|
||||
break;
|
||||
|
||||
CanvasItem *ci = Object::cast_to<CanvasItem>(parent);
|
||||
if (ci && ci->is_set_as_toplevel()) {
|
||||
subwindow = true;
|
||||
break;
|
||||
}
|
||||
|
||||
parent_control = Object::cast_to<Control>(parent);
|
||||
|
||||
if (parent_control) {
|
||||
break;
|
||||
} else if (ci) {
|
||||
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
parent_control = Object::cast_to<Control>(parent);
|
||||
|
||||
if (parent_control) {
|
||||
//do nothing, has a parent control
|
||||
if (data.theme.is_null() && parent_control->data.theme_owner) {
|
||||
data.theme_owner = parent_control->data.theme_owner;
|
||||
notification(NOTIFICATION_THEME_CHANGED);
|
||||
}
|
||||
} else if (subwindow) {
|
||||
//is a subwindow (process input before other controls for that canvas)
|
||||
data.SI = get_viewport()->_gui_add_subwindow_control(this);
|
||||
break;
|
||||
} else if (ci) {
|
||||
|
||||
} else {
|
||||
//is a regular root control
|
||||
data.RI = get_viewport()->_gui_add_root_control(this);
|
||||
}
|
||||
|
||||
data.parent_canvas_item = get_parent_item();
|
||||
|
||||
if (data.parent_canvas_item) {
|
||||
|
||||
data.parent_canvas_item->connect("item_rect_changed", callable_mp(this, &Control::_size_changed));
|
||||
} else {
|
||||
//connect viewport
|
||||
get_viewport()->connect("size_changed", callable_mp(this, &Control::_size_changed));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
if (data.theme.is_null() && data.parent && data.parent->data.theme_owner) {
|
||||
data.theme_owner=data.parent->data.theme_owner;
|
||||
notification(NOTIFICATION_THEME_CHANGED);
|
||||
if (parent_control && !subwindow) {
|
||||
//do nothing, has a parent control and not toplevel
|
||||
if (data.theme.is_null() && parent_control->data.theme_owner) {
|
||||
data.theme_owner = parent_control->data.theme_owner;
|
||||
notification(NOTIFICATION_THEME_CHANGED);
|
||||
}
|
||||
} else {
|
||||
//is a regular root control or toplevel
|
||||
data.RI = get_viewport()->_gui_add_root_control(this);
|
||||
}
|
||||
*/
|
||||
|
||||
data.parent_canvas_item = get_parent_item();
|
||||
|
||||
if (data.parent_canvas_item) {
|
||||
|
||||
data.parent_canvas_item->connect("item_rect_changed", callable_mp(this, &Control::_size_changed));
|
||||
} else {
|
||||
//connect viewport
|
||||
get_viewport()->connect("size_changed", callable_mp(this, &Control::_size_changed));
|
||||
}
|
||||
} break;
|
||||
case NOTIFICATION_EXIT_CANVAS: {
|
||||
|
||||
|
@ -576,16 +554,6 @@ void Control::_notification(int p_notification) {
|
|||
get_viewport()->disconnect("size_changed", callable_mp(this, &Control::_size_changed));
|
||||
}
|
||||
|
||||
if (data.MI) {
|
||||
get_viewport()->_gui_remove_modal_control(data.MI);
|
||||
data.MI = NULL;
|
||||
}
|
||||
|
||||
if (data.SI) {
|
||||
get_viewport()->_gui_remove_subwindow_control(data.SI);
|
||||
data.SI = NULL;
|
||||
}
|
||||
|
||||
if (data.RI) {
|
||||
get_viewport()->_gui_remove_root_control(data.RI);
|
||||
data.RI = NULL;
|
||||
|
@ -608,9 +576,6 @@ void Control::_notification(int p_notification) {
|
|||
data.parent->update();
|
||||
update();
|
||||
|
||||
if (data.SI) {
|
||||
get_viewport()->_gui_set_subwindow_order_dirty();
|
||||
}
|
||||
if (data.RI) {
|
||||
get_viewport()->_gui_set_root_order_dirty();
|
||||
}
|
||||
|
@ -652,10 +617,6 @@ void Control::_notification(int p_notification) {
|
|||
minimum_size_changed();
|
||||
update();
|
||||
} break;
|
||||
case NOTIFICATION_MODAL_CLOSE: {
|
||||
|
||||
emit_signal("modal_closed");
|
||||
} break;
|
||||
case NOTIFICATION_VISIBILITY_CHANGED: {
|
||||
|
||||
if (!is_visible_in_tree()) {
|
||||
|
@ -663,10 +624,6 @@ void Control::_notification(int p_notification) {
|
|||
if (get_viewport() != NULL)
|
||||
get_viewport()->_gui_hid_control(this);
|
||||
|
||||
if (is_inside_tree()) {
|
||||
_modal_stack_remove();
|
||||
}
|
||||
|
||||
//remove key focus
|
||||
//remove modalness
|
||||
} else {
|
||||
|
@ -790,19 +747,6 @@ void Control::set_drag_preview(Control *p_control) {
|
|||
get_viewport()->_gui_set_drag_preview(this, p_control);
|
||||
}
|
||||
|
||||
bool Control::is_window_modal_on_top() const {
|
||||
|
||||
if (!is_inside_tree())
|
||||
return false;
|
||||
|
||||
return get_viewport()->_gui_is_modal_on_top(this);
|
||||
}
|
||||
|
||||
uint64_t Control::get_modal_frame() const {
|
||||
|
||||
return data.modal_frame;
|
||||
}
|
||||
|
||||
Size2 Control::get_minimum_size() const {
|
||||
|
||||
ScriptInstance *si = const_cast<Control *>(this)->get_script_instance();
|
||||
|
@ -1720,7 +1664,7 @@ Point2 Control::get_screen_position() const {
|
|||
ERR_FAIL_COND_V(!is_inside_tree(), Point2());
|
||||
Point2 global_pos = get_global_position();
|
||||
Window *w = Object::cast_to<Window>(get_viewport());
|
||||
if (w) {
|
||||
if (w && !w->is_embedding_subwindows()) {
|
||||
global_pos += w->get_position();
|
||||
}
|
||||
|
||||
|
@ -1828,7 +1772,7 @@ Rect2 Control::get_screen_rect() const {
|
|||
Rect2 r(get_global_position(), get_size());
|
||||
|
||||
Window *w = Object::cast_to<Window>(get_viewport());
|
||||
if (w) {
|
||||
if (w && !w->is_embedding_subwindows()) {
|
||||
r.position += w->get_position();
|
||||
}
|
||||
|
||||
|
@ -2021,7 +1965,7 @@ Control *Control::find_next_valid_focus() const {
|
|||
next_child = const_cast<Control *>(this);
|
||||
while (next_child) {
|
||||
|
||||
if (next_child->data.SI || next_child->data.RI)
|
||||
if (next_child->data.RI)
|
||||
break;
|
||||
next_child = next_child->get_parent_control();
|
||||
}
|
||||
|
@ -2164,41 +2108,6 @@ bool Control::is_toplevel_control() const {
|
|||
return is_inside_tree() && (!data.parent_canvas_item && !data.RI && is_set_as_toplevel());
|
||||
}
|
||||
|
||||
void Control::show_modal(bool p_exclusive) {
|
||||
|
||||
ERR_FAIL_COND(!is_inside_tree());
|
||||
ERR_FAIL_COND(!data.SI);
|
||||
|
||||
if (is_visible_in_tree())
|
||||
hide();
|
||||
|
||||
ERR_FAIL_COND(data.MI != NULL);
|
||||
show();
|
||||
raise();
|
||||
data.modal_exclusive = p_exclusive;
|
||||
data.MI = get_viewport()->_gui_show_modal(this);
|
||||
data.modal_frame = Engine::get_singleton()->get_frames_drawn();
|
||||
}
|
||||
|
||||
void Control::_modal_set_prev_focus_owner(ObjectID p_prev) {
|
||||
data.modal_prev_focus_owner = p_prev;
|
||||
}
|
||||
|
||||
void Control::_modal_stack_remove() {
|
||||
|
||||
ERR_FAIL_COND(!is_inside_tree());
|
||||
|
||||
if (!data.MI)
|
||||
return;
|
||||
|
||||
List<Control *>::Element *element = data.MI;
|
||||
data.MI = NULL;
|
||||
|
||||
get_viewport()->_gui_remove_from_modal_stack(element, data.modal_prev_focus_owner);
|
||||
|
||||
data.modal_prev_focus_owner = ObjectID();
|
||||
}
|
||||
|
||||
void Control::_propagate_theme_changed(Node *p_at, Control *p_owner, Window *p_owner_window, bool p_assign) {
|
||||
|
||||
Control *c = Object::cast_to<Control>(p_at);
|
||||
|
@ -2444,8 +2353,6 @@ Control *Control::_get_focus_neighbour(Margin p_margin, int p_count) {
|
|||
|
||||
Control *c = Object::cast_to<Control>(base);
|
||||
if (c) {
|
||||
if (c->data.SI)
|
||||
break;
|
||||
if (c->data.RI)
|
||||
break;
|
||||
}
|
||||
|
@ -2515,7 +2422,7 @@ void Control::_window_find_focus_neighbour(const Vector2 &p_dir, Node *p_at, con
|
|||
|
||||
Node *child = p_at->get_child(i);
|
||||
Control *childc = Object::cast_to<Control>(child);
|
||||
if (childc && childc->data.SI)
|
||||
if (childc && childc->data.RI)
|
||||
continue; //subwindow, ignore
|
||||
_window_find_focus_neighbour(p_dir, p_at->get_child(i), p_points, p_min, r_closest_dist, r_closest);
|
||||
}
|
||||
|
@ -2609,16 +2516,6 @@ Control::MouseFilter Control::get_mouse_filter() const {
|
|||
return data.mouse_filter;
|
||||
}
|
||||
|
||||
void Control::set_pass_on_modal_close_click(bool p_pass_on) {
|
||||
|
||||
data.pass_on_modal_close_click = p_pass_on;
|
||||
}
|
||||
|
||||
bool Control::pass_on_modal_close_click() const {
|
||||
|
||||
return data.pass_on_modal_close_click;
|
||||
}
|
||||
|
||||
Control *Control::get_focus_owner() const {
|
||||
|
||||
ERR_FAIL_COND_V(!is_inside_tree(), NULL);
|
||||
|
@ -2712,7 +2609,7 @@ Control *Control::get_root_parent_control() const {
|
|||
if (c) {
|
||||
root = c;
|
||||
|
||||
if (c->data.RI || c->data.MI || c->is_toplevel_control())
|
||||
if (c->data.RI || c->is_toplevel_control())
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -2864,7 +2761,6 @@ void Control::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("get_global_position"), &Control::get_global_position);
|
||||
ClassDB::bind_method(D_METHOD("get_rect"), &Control::get_rect);
|
||||
ClassDB::bind_method(D_METHOD("get_global_rect"), &Control::get_global_rect);
|
||||
ClassDB::bind_method(D_METHOD("show_modal", "exclusive"), &Control::show_modal, DEFVAL(false));
|
||||
ClassDB::bind_method(D_METHOD("set_focus_mode", "mode"), &Control::set_focus_mode);
|
||||
ClassDB::bind_method(D_METHOD("get_focus_mode"), &Control::get_focus_mode);
|
||||
ClassDB::bind_method(D_METHOD("has_focus"), &Control::has_focus);
|
||||
|
@ -3024,7 +2920,6 @@ void Control::_bind_methods() {
|
|||
BIND_CONSTANT(NOTIFICATION_FOCUS_ENTER);
|
||||
BIND_CONSTANT(NOTIFICATION_FOCUS_EXIT);
|
||||
BIND_CONSTANT(NOTIFICATION_THEME_CHANGED);
|
||||
BIND_CONSTANT(NOTIFICATION_MODAL_CLOSE);
|
||||
BIND_CONSTANT(NOTIFICATION_SCROLL_BEGIN);
|
||||
BIND_CONSTANT(NOTIFICATION_SCROLL_END);
|
||||
|
||||
|
@ -3093,7 +2988,6 @@ void Control::_bind_methods() {
|
|||
ADD_SIGNAL(MethodInfo("focus_exited"));
|
||||
ADD_SIGNAL(MethodInfo("size_flags_changed"));
|
||||
ADD_SIGNAL(MethodInfo("minimum_size_changed"));
|
||||
ADD_SIGNAL(MethodInfo("modal_closed"));
|
||||
ADD_SIGNAL(MethodInfo("theme_changed"));
|
||||
|
||||
BIND_VMETHOD(MethodInfo(Variant::BOOL, "has_point", PropertyInfo(Variant::VECTOR2, "point")));
|
||||
|
@ -3103,14 +2997,10 @@ Control::Control() {
|
|||
data.parent = NULL;
|
||||
|
||||
data.mouse_filter = MOUSE_FILTER_STOP;
|
||||
data.pass_on_modal_close_click = true;
|
||||
|
||||
data.SI = NULL;
|
||||
data.MI = NULL;
|
||||
data.RI = NULL;
|
||||
data.theme_owner = NULL;
|
||||
data.theme_owner_window = NULL;
|
||||
data.modal_exclusive = false;
|
||||
data.default_cursor = CURSOR_ARROW;
|
||||
data.h_size_flags = SIZE_FILL;
|
||||
data.v_size_flags = SIZE_FILL;
|
||||
|
@ -3119,7 +3009,6 @@ Control::Control() {
|
|||
data.parent_canvas_item = NULL;
|
||||
data.scale = Vector2(1, 1);
|
||||
|
||||
data.modal_frame = 0;
|
||||
data.block_minimum_size_adjust = false;
|
||||
data.disable_visibility_clip = false;
|
||||
data.h_grow = GROW_DIRECTION_END;
|
||||
|
|
|
@ -168,8 +168,6 @@ private:
|
|||
float expand;
|
||||
Point2 custom_minimum_size;
|
||||
|
||||
bool pass_on_modal_close_click;
|
||||
|
||||
MouseFilter mouse_filter;
|
||||
|
||||
bool clip_contents;
|
||||
|
@ -179,22 +177,16 @@ private:
|
|||
|
||||
Control *parent;
|
||||
ObjectID drag_owner;
|
||||
bool modal_exclusive;
|
||||
uint64_t modal_frame; //frame used to put something as modal
|
||||
Ref<Theme> theme;
|
||||
Control *theme_owner;
|
||||
Window *theme_owner_window;
|
||||
String tooltip;
|
||||
CursorShape default_cursor;
|
||||
|
||||
List<Control *>::Element *MI; //modal item
|
||||
List<Control *>::Element *SI;
|
||||
List<Control *>::Element *RI;
|
||||
|
||||
CanvasItem *parent_canvas_item;
|
||||
|
||||
ObjectID modal_prev_focus_owner;
|
||||
|
||||
NodePath focus_neighbour[4];
|
||||
NodePath focus_next;
|
||||
NodePath focus_prev;
|
||||
|
@ -240,8 +232,6 @@ private:
|
|||
Transform2D _get_internal_transform() const;
|
||||
|
||||
friend class Viewport;
|
||||
void _modal_stack_remove();
|
||||
void _modal_set_prev_focus_owner(ObjectID p_prev);
|
||||
|
||||
void _update_minimum_size_cache();
|
||||
friend class Window;
|
||||
|
@ -293,7 +283,6 @@ public:
|
|||
NOTIFICATION_FOCUS_ENTER = 43,
|
||||
NOTIFICATION_FOCUS_EXIT = 44,
|
||||
NOTIFICATION_THEME_CHANGED = 45,
|
||||
NOTIFICATION_MODAL_CLOSE = 46,
|
||||
NOTIFICATION_SCROLL_BEGIN = 47,
|
||||
NOTIFICATION_SCROLL_END = 48,
|
||||
|
||||
|
@ -341,9 +330,6 @@ public:
|
|||
void set_custom_minimum_size(const Size2 &p_custom);
|
||||
Size2 get_custom_minimum_size() const;
|
||||
|
||||
bool is_window_modal_on_top() const;
|
||||
uint64_t get_modal_frame() const; //frame in which this was made modal
|
||||
|
||||
Control *get_parent_control() const;
|
||||
|
||||
/* POSITIONING */
|
||||
|
@ -398,8 +384,6 @@ public:
|
|||
void set_scale(const Vector2 &p_scale);
|
||||
Vector2 get_scale() const;
|
||||
|
||||
void show_modal(bool p_exclusive = false);
|
||||
|
||||
void set_theme(const Ref<Theme> &p_theme);
|
||||
Ref<Theme> get_theme() const;
|
||||
|
||||
|
@ -438,9 +422,6 @@ public:
|
|||
void set_mouse_filter(MouseFilter p_filter);
|
||||
MouseFilter get_mouse_filter() const;
|
||||
|
||||
void set_pass_on_modal_close_click(bool p_pass_on);
|
||||
bool pass_on_modal_close_click() const;
|
||||
|
||||
/* SKINNING */
|
||||
|
||||
void add_theme_icon_override(const StringName &p_name, const Ref<Texture2D> &p_icon);
|
||||
|
|
|
@ -43,20 +43,24 @@ void MenuButton::_unhandled_key_input(Ref<InputEvent> p_event) {
|
|||
if (!get_parent() || !is_visible_in_tree() || is_disabled())
|
||||
return;
|
||||
|
||||
bool global_only = (get_viewport()->get_modal_stack_top() && !get_viewport()->get_modal_stack_top()->is_a_parent_of(this));
|
||||
|
||||
if (popup->activate_item_by_event(p_event, global_only))
|
||||
//bool global_only = (get_viewport()->get_modal_stack_top() && !get_viewport()->get_modal_stack_top()->is_a_parent_of(this));
|
||||
//if (popup->activate_item_by_event(p_event, global_only))
|
||||
// accept_event();
|
||||
if (popup->activate_item_by_event(p_event, false))
|
||||
accept_event();
|
||||
}
|
||||
}
|
||||
|
||||
void MenuButton::pressed() {
|
||||
|
||||
emit_signal("about_to_popup");
|
||||
Size2 size = get_size();
|
||||
|
||||
Point2 gp = get_screen_position();
|
||||
popup->set_position(gp + Size2(0, size.height * get_global_transform().get_scale().y));
|
||||
|
||||
gp.y += get_size().y;
|
||||
|
||||
popup->set_position(gp);
|
||||
|
||||
popup->set_size(Size2(size.width, 0));
|
||||
popup->set_parent_rect(Rect2(Point2(gp - popup->get_position()), get_size()));
|
||||
popup->popup();
|
||||
|
|
|
@ -163,7 +163,7 @@ void PopupMenu::_activate_submenu(int over) {
|
|||
Point2 pos = p + Point2(get_size().width, items[over]._ofs_cache - style->get_offset().y);
|
||||
Size2 size = pm->get_size();
|
||||
// fix pos
|
||||
if (pos.x + size.width > get_screen_rect().size.width)
|
||||
if (pos.x + size.width > get_parent_rect().size.width)
|
||||
pos.x = p.x - size.width;
|
||||
|
||||
pm->set_position(pos);
|
||||
|
@ -203,7 +203,7 @@ void PopupMenu::_scroll(float p_factor, const Point2 &p_over) {
|
|||
dy = MIN(dy, limit);
|
||||
} else if (dy < 0) {
|
||||
const float global_bottom = get_position().y + get_size().y;
|
||||
const float viewport_height = get_screen_rect().size.y;
|
||||
const float viewport_height = get_parent_rect().size.y;
|
||||
const float limit = global_bottom > viewport_height ? global_bottom - viewport_height : 0;
|
||||
dy = -MIN(-dy, limit);
|
||||
}
|
||||
|
@ -295,7 +295,7 @@ void PopupMenu::_gui_input(const Ref<InputEvent> &p_event) {
|
|||
|
||||
case BUTTON_WHEEL_DOWN: {
|
||||
|
||||
if (get_position().y + get_size().y > get_screen_rect().size.y) {
|
||||
if (get_position().y + get_size().y > get_parent_rect().size.y) {
|
||||
_scroll(-b->get_factor(), b->get_position());
|
||||
}
|
||||
} break;
|
||||
|
@ -382,7 +382,7 @@ void PopupMenu::_gui_input(const Ref<InputEvent> &p_event) {
|
|||
|
||||
Ref<InputEventPanGesture> pan_gesture = p_event;
|
||||
if (pan_gesture.is_valid()) {
|
||||
if (get_position().y + get_size().y > get_screen_rect().size.y || get_position().y < 0) {
|
||||
if (get_position().y + get_size().y > get_parent_rect().size.y || get_position().y < 0) {
|
||||
_scroll(-pan_gesture->get_delta().y, pan_gesture->get_position());
|
||||
}
|
||||
}
|
||||
|
@ -591,6 +591,9 @@ void PopupMenu::_notification(int p_what) {
|
|||
|
||||
initial_button_mask = InputFilter::get_singleton()->get_mouse_button_mask();
|
||||
during_grabbed_click = (bool)initial_button_mask;
|
||||
} break;
|
||||
case NOTIFICATION_WM_SIZE_CHANGED: {
|
||||
|
||||
} break;
|
||||
case NOTIFICATION_VISIBILITY_CHANGED: {
|
||||
|
||||
|
|
|
@ -2819,7 +2819,10 @@ bool Tree::edit_selected() {
|
|||
|
||||
value_editor->set_position(textedpos + Point2i(0, text_editor->get_size().height));
|
||||
value_editor->set_size(Size2(rect.size.width, 1));
|
||||
value_editor->show_modal();
|
||||
#ifndef _MSC_VER
|
||||
#warning show modal no longer works, need to replace by a popup
|
||||
#endif
|
||||
value_editor->show();
|
||||
updating_value_editor = true;
|
||||
value_editor->set_min(c.min);
|
||||
value_editor->set_max(c.max);
|
||||
|
@ -2828,8 +2831,10 @@ bool Tree::edit_selected() {
|
|||
value_editor->set_exp_ratio(c.expr);
|
||||
updating_value_editor = false;
|
||||
}
|
||||
|
||||
text_editor->show_modal();
|
||||
#ifndef _MSC_VER
|
||||
#warning show modal no longer works, need to replace by a popup
|
||||
#endif
|
||||
text_editor->show();
|
||||
text_editor->grab_focus();
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -187,6 +187,7 @@ public:
|
|||
Viewport::GUI::GUI() {
|
||||
|
||||
embed_subwindows_hint = false;
|
||||
embedding_subwindows = false;
|
||||
|
||||
dragging = false;
|
||||
mouse_focus = NULL;
|
||||
|
@ -198,8 +199,6 @@ Viewport::GUI::GUI() {
|
|||
tooltip = NULL;
|
||||
tooltip_popup = NULL;
|
||||
tooltip_label = NULL;
|
||||
subwindow_visibility_dirty = false;
|
||||
subwindow_order_dirty = false;
|
||||
}
|
||||
|
||||
/////////////////////////////////////
|
||||
|
@ -236,6 +235,180 @@ void Viewport::_collision_object_input_event(CollisionObject *p_object, Camera *
|
|||
physics_last_id = id;
|
||||
}
|
||||
|
||||
void Viewport::_sub_window_update_order() {
|
||||
|
||||
for (int i = 0; i < gui.sub_windows.size(); i++) {
|
||||
VS::get_singleton()->canvas_item_set_draw_index(gui.sub_windows[i].canvas_item, i);
|
||||
}
|
||||
}
|
||||
|
||||
void Viewport::_sub_window_register(Window *p_window) {
|
||||
|
||||
ERR_FAIL_COND(!is_inside_tree());
|
||||
for (int i = 0; i < gui.sub_windows.size(); i++) {
|
||||
ERR_FAIL_COND(gui.sub_windows[i].window == p_window);
|
||||
}
|
||||
|
||||
if (gui.sub_windows.size() == 0) {
|
||||
subwindow_canvas = VS::get_singleton()->canvas_create();
|
||||
VS::get_singleton()->viewport_attach_canvas(viewport, subwindow_canvas);
|
||||
VS::get_singleton()->viewport_set_canvas_stacking(viewport, subwindow_canvas, SUBWINDOW_CANVAS_LAYER, 0);
|
||||
}
|
||||
SubWindow sw;
|
||||
sw.canvas_item = VS::get_singleton()->canvas_item_create();
|
||||
VS::get_singleton()->canvas_item_set_parent(sw.canvas_item, subwindow_canvas);
|
||||
sw.window = p_window;
|
||||
gui.sub_windows.push_back(sw);
|
||||
|
||||
_sub_window_grab_focus(p_window);
|
||||
|
||||
VisualServer::get_singleton()->viewport_set_parent_viewport(p_window->viewport, viewport);
|
||||
}
|
||||
|
||||
void Viewport::_sub_window_update(Window *p_window) {
|
||||
|
||||
int index = -1;
|
||||
for (int i = 0; i < gui.sub_windows.size(); i++) {
|
||||
if (gui.sub_windows[i].window == p_window) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ERR_FAIL_COND(index == -1);
|
||||
|
||||
const SubWindow &sw = gui.sub_windows[index];
|
||||
|
||||
Transform2D pos;
|
||||
pos.set_origin(p_window->get_position());
|
||||
VS::get_singleton()->canvas_item_clear(sw.canvas_item);
|
||||
Rect2i r = Rect2i(p_window->get_position(), sw.window->get_size());
|
||||
|
||||
if (!p_window->get_flag(Window::FLAG_BORDERLESS)) {
|
||||
Ref<StyleBox> panel = p_window->get_theme_stylebox("panel_window");
|
||||
panel->draw(sw.canvas_item, r);
|
||||
|
||||
// Draw the title bar text.
|
||||
Ref<Font> title_font = p_window->get_theme_font("title_font");
|
||||
Color title_color = p_window->get_theme_color("title_color");
|
||||
int title_height = p_window->get_theme_constant("title_height");
|
||||
int font_height = title_font->get_height() - title_font->get_descent() * 2;
|
||||
int x = (r.size.width - title_font->get_string_size(p_window->get_title()).x) / 2;
|
||||
int y = (-title_height + font_height) / 2;
|
||||
|
||||
int close_h_ofs = p_window->get_theme_constant("close_h_ofs");
|
||||
int close_v_ofs = p_window->get_theme_constant("close_v_ofs");
|
||||
|
||||
title_font->draw(sw.canvas_item, r.position + Point2(x, y), p_window->get_title(), title_color, r.size.width - panel->get_minimum_size().x - close_h_ofs);
|
||||
|
||||
bool hl = gui.subwindow_focused == sw.window && gui.subwindow_drag == SUB_WINDOW_DRAG_CLOSE && gui.subwindow_drag_close_inside;
|
||||
|
||||
Ref<Texture2D> close_icon = p_window->get_theme_icon(hl ? "close_highlight" : "close");
|
||||
close_icon->draw(sw.canvas_item, r.position + Vector2(r.size.width - close_h_ofs, -close_v_ofs));
|
||||
}
|
||||
|
||||
VS::get_singleton()->canvas_item_add_texture_rect(sw.canvas_item, r, sw.window->get_texture()->get_rid());
|
||||
}
|
||||
|
||||
void Viewport::_sub_window_grab_focus(Window *p_window) {
|
||||
|
||||
if (p_window == nullptr) {
|
||||
//release current focus
|
||||
if (gui.subwindow_focused) {
|
||||
gui.subwindow_focused->_event_callback(DisplayServer::WINDOW_EVENT_FOCUS_OUT);
|
||||
gui.subwindow_focused = nullptr;
|
||||
gui.subwindow_drag = SUB_WINDOW_DRAG_DISABLED;
|
||||
}
|
||||
|
||||
Window *this_window = Object::cast_to<Window>(this);
|
||||
if (this_window) {
|
||||
this_window->_event_callback(DisplayServer::WINDOW_EVENT_FOCUS_IN);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
int index = -1;
|
||||
for (int i = 0; i < gui.sub_windows.size(); i++) {
|
||||
if (gui.sub_windows[i].window == p_window) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ERR_FAIL_COND(index == -1);
|
||||
|
||||
if (gui.subwindow_focused) {
|
||||
if (gui.subwindow_focused == p_window) {
|
||||
return; //nothing to do
|
||||
}
|
||||
gui.subwindow_focused->_event_callback(DisplayServer::WINDOW_EVENT_FOCUS_OUT);
|
||||
gui.subwindow_drag = SUB_WINDOW_DRAG_DISABLED;
|
||||
} else {
|
||||
Window *this_window = Object::cast_to<Window>(this);
|
||||
if (this_window) {
|
||||
this_window->_event_callback(DisplayServer::WINDOW_EVENT_FOCUS_OUT);
|
||||
}
|
||||
}
|
||||
|
||||
Window *old_focus = gui.subwindow_focused;
|
||||
|
||||
gui.subwindow_focused = p_window;
|
||||
|
||||
gui.subwindow_focused->_event_callback(DisplayServer::WINDOW_EVENT_FOCUS_IN);
|
||||
|
||||
{ //move to foreground
|
||||
SubWindow sw = gui.sub_windows[index];
|
||||
gui.sub_windows.remove(index);
|
||||
gui.sub_windows.push_back(sw);
|
||||
index = gui.sub_windows.size() - 1;
|
||||
_sub_window_update_order();
|
||||
}
|
||||
|
||||
if (old_focus) {
|
||||
_sub_window_update(old_focus);
|
||||
}
|
||||
|
||||
_sub_window_update(p_window);
|
||||
}
|
||||
|
||||
void Viewport::_sub_window_remove(Window *p_window) {
|
||||
|
||||
for (int i = 0; i < gui.sub_windows.size(); i++) {
|
||||
if (gui.sub_windows[i].window == p_window) {
|
||||
VS::get_singleton()->free(gui.sub_windows[i].canvas_item);
|
||||
gui.sub_windows.remove(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (gui.sub_windows.size() == 0) {
|
||||
VS::get_singleton()->free(subwindow_canvas);
|
||||
subwindow_canvas = RID();
|
||||
}
|
||||
|
||||
if (gui.subwindow_focused == p_window) {
|
||||
Window *parent_visible = p_window->get_parent_visible_window();
|
||||
|
||||
gui.subwindow_drag = SUB_WINDOW_DRAG_DISABLED;
|
||||
|
||||
gui.subwindow_focused->_event_callback(DisplayServer::WINDOW_EVENT_FOCUS_OUT);
|
||||
|
||||
if (parent_visible && parent_visible != this) {
|
||||
|
||||
gui.subwindow_focused = parent_visible;
|
||||
gui.subwindow_focused->_event_callback(DisplayServer::WINDOW_EVENT_FOCUS_IN);
|
||||
} else {
|
||||
gui.subwindow_focused = nullptr;
|
||||
Window *this_window = Object::cast_to<Window>(this);
|
||||
if (this_window) {
|
||||
this_window->_event_callback(DisplayServer::WINDOW_EVENT_FOCUS_IN);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VisualServer::get_singleton()->viewport_set_parent_viewport(p_window->viewport, p_window->parent ? p_window->parent->viewport : RID());
|
||||
}
|
||||
|
||||
void Viewport::_own_world_changed() {
|
||||
ERR_FAIL_COND(world.is_null());
|
||||
ERR_FAIL_COND(own_world.is_null());
|
||||
|
@ -263,6 +436,8 @@ void Viewport::_notification(int p_what) {
|
|||
|
||||
case NOTIFICATION_ENTER_TREE: {
|
||||
|
||||
gui.embedding_subwindows = gui.embed_subwindows_hint;
|
||||
|
||||
if (get_parent()) {
|
||||
parent = get_parent()->get_viewport();
|
||||
VisualServer::get_singleton()->viewport_set_parent_viewport(viewport, parent->get_viewport_rid());
|
||||
|
@ -297,7 +472,6 @@ void Viewport::_notification(int p_what) {
|
|||
//VisualServer::get_singleton()->instance_geometry_set_flag(contact_3d_debug_instance, VS::INSTANCE_FLAG_VISIBLE_IN_ALL_ROOMS, true);
|
||||
}
|
||||
|
||||
VS::get_singleton()->viewport_set_active(viewport, true);
|
||||
} break;
|
||||
case NOTIFICATION_READY: {
|
||||
#ifndef _3D_DISABLED
|
||||
|
@ -358,6 +532,7 @@ void Viewport::_notification(int p_what) {
|
|||
remove_from_group("_viewports");
|
||||
|
||||
VS::get_singleton()->viewport_set_active(viewport, false);
|
||||
VisualServer::get_singleton()->viewport_set_parent_viewport(viewport, RID());
|
||||
|
||||
} break;
|
||||
case NOTIFICATION_INTERNAL_PROCESS: {
|
||||
|
@ -1318,25 +1493,16 @@ Transform2D Viewport::_get_input_pre_xform() const {
|
|||
return pre_xf;
|
||||
}
|
||||
|
||||
Vector2 Viewport::_get_window_offset() const {
|
||||
|
||||
if (get_parent() && get_parent()->has_method("get_global_position")) {
|
||||
return get_parent()->call("get_global_position");
|
||||
}
|
||||
return Vector2();
|
||||
}
|
||||
|
||||
Ref<InputEvent> Viewport::_make_input_local(const Ref<InputEvent> &ev) {
|
||||
|
||||
Vector2 vp_ofs = _get_window_offset();
|
||||
Transform2D ai = get_final_transform().affine_inverse() * _get_input_pre_xform();
|
||||
|
||||
return ev->xformed_by(ai, -vp_ofs);
|
||||
return ev->xformed_by(ai);
|
||||
}
|
||||
|
||||
Vector2 Viewport::get_mouse_position() const {
|
||||
|
||||
return (get_final_transform().affine_inverse() * _get_input_pre_xform()).xform(InputFilter::get_singleton()->get_mouse_position() - _get_window_offset());
|
||||
return gui.last_mouse_pos;
|
||||
}
|
||||
|
||||
void Viewport::warp_mouse(const Vector2 &p_pos) {
|
||||
|
@ -1345,40 +1511,6 @@ void Viewport::warp_mouse(const Vector2 &p_pos) {
|
|||
InputFilter::get_singleton()->warp_mouse_position(gpos);
|
||||
}
|
||||
|
||||
void Viewport::_gui_prepare_subwindows() {
|
||||
|
||||
if (gui.subwindow_visibility_dirty) {
|
||||
|
||||
gui.subwindows.clear();
|
||||
for (List<Control *>::Element *E = gui.all_known_subwindows.front(); E; E = E->next()) {
|
||||
if (E->get()->is_visible_in_tree()) {
|
||||
gui.subwindows.push_back(E->get());
|
||||
}
|
||||
}
|
||||
|
||||
gui.subwindow_visibility_dirty = false;
|
||||
gui.subwindow_order_dirty = true;
|
||||
}
|
||||
|
||||
_gui_sort_subwindows();
|
||||
}
|
||||
|
||||
void Viewport::_gui_sort_subwindows() {
|
||||
|
||||
if (!gui.subwindow_order_dirty)
|
||||
return;
|
||||
|
||||
gui.modal_stack.sort_custom<Control::CComparator>();
|
||||
gui.subwindows.sort_custom<Control::CComparator>();
|
||||
|
||||
gui.subwindow_order_dirty = false;
|
||||
}
|
||||
|
||||
void Viewport::_gui_sort_modal_stack() {
|
||||
|
||||
gui.modal_stack.sort_custom<Control::CComparator>();
|
||||
}
|
||||
|
||||
void Viewport::_gui_sort_roots() {
|
||||
|
||||
if (!gui.roots_order_dirty)
|
||||
|
@ -1581,26 +1713,7 @@ void Viewport::_gui_call_notification(Control *p_control, int p_what) {
|
|||
}
|
||||
Control *Viewport::_gui_find_control(const Point2 &p_global) {
|
||||
|
||||
_gui_prepare_subwindows();
|
||||
|
||||
for (List<Control *>::Element *E = gui.subwindows.back(); E; E = E->prev()) {
|
||||
|
||||
Control *sw = E->get();
|
||||
if (!sw->is_visible_in_tree())
|
||||
continue;
|
||||
|
||||
Transform2D xform;
|
||||
CanvasItem *pci = sw->get_parent_item();
|
||||
if (pci)
|
||||
xform = pci->get_global_transform_with_canvas();
|
||||
else
|
||||
xform = sw->get_canvas_transform();
|
||||
|
||||
Control *ret = _gui_find_control_at_pos(sw, p_global, xform, gui.focus_inv_xform);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
//aca va subwindows
|
||||
_gui_sort_roots();
|
||||
|
||||
for (List<Control *>::Element *E = gui.roots.back(); E; E = E->prev()) {
|
||||
|
@ -1629,8 +1742,6 @@ Control *Viewport::_gui_find_control_at_pos(CanvasItem *p_node, const Point2 &p_
|
|||
if (Object::cast_to<Viewport>(p_node))
|
||||
return NULL;
|
||||
|
||||
//subwindows first!!
|
||||
|
||||
if (!p_node->is_visible()) {
|
||||
//return _find_next_visible_control_at_pos(p_node,p_global,r_inv_xform);
|
||||
return NULL; //canvas item hidden, discard
|
||||
|
@ -1735,39 +1846,6 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
|
|||
|
||||
bool is_handled = false;
|
||||
|
||||
_gui_sort_modal_stack();
|
||||
while (!gui.modal_stack.empty()) {
|
||||
|
||||
Control *top = gui.modal_stack.back()->get();
|
||||
Vector2 pos2 = top->get_global_transform_with_canvas().affine_inverse().xform(mpos);
|
||||
if (!top->has_point(pos2)) {
|
||||
|
||||
if (top->data.modal_exclusive || top->data.modal_frame == Engine::get_singleton()->get_frames_drawn()) {
|
||||
//cancel event, sorry, modal exclusive EATS UP ALL
|
||||
//alternative, you can't pop out a window the same frame it was made modal (fixes many issues)
|
||||
set_input_as_handled();
|
||||
|
||||
return; // no one gets the event if exclusive NO ONE
|
||||
}
|
||||
|
||||
if (mb->get_button_index() == BUTTON_WHEEL_UP || mb->get_button_index() == BUTTON_WHEEL_DOWN || mb->get_button_index() == BUTTON_WHEEL_LEFT || mb->get_button_index() == BUTTON_WHEEL_RIGHT) {
|
||||
//cancel scroll wheel events, only clicks should trigger focus changes.
|
||||
set_input_as_handled();
|
||||
return;
|
||||
}
|
||||
|
||||
top->notification(Control::NOTIFICATION_MODAL_CLOSE);
|
||||
top->_modal_stack_remove();
|
||||
top->hide();
|
||||
|
||||
if (!top->pass_on_modal_close_click()) {
|
||||
is_handled = true;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_handled) {
|
||||
set_input_as_handled();
|
||||
return;
|
||||
|
@ -1990,15 +2068,6 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
|
|||
over = _gui_find_control(mpos);
|
||||
}
|
||||
|
||||
if (gui.drag_data.get_type() == Variant::NIL && over && !gui.modal_stack.empty()) {
|
||||
|
||||
Control *top = gui.modal_stack.back()->get();
|
||||
|
||||
if (over != top && !top->is_a_parent_of(over)) {
|
||||
over = NULL; //nothing can be found outside the modal stack
|
||||
}
|
||||
}
|
||||
|
||||
if (over != gui.mouse_over) {
|
||||
|
||||
if (gui.mouse_over) {
|
||||
|
@ -2039,11 +2108,6 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
|
|||
|
||||
bool can_tooltip = true;
|
||||
|
||||
if (!gui.modal_stack.empty()) {
|
||||
if (gui.modal_stack.back()->get() != over && !gui.modal_stack.back()->get()->is_a_parent_of(over))
|
||||
can_tooltip = false;
|
||||
}
|
||||
|
||||
bool is_tooltip_shown = false;
|
||||
|
||||
if (gui.tooltip_popup) {
|
||||
|
@ -2122,14 +2186,6 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
|
|||
Control *over = _gui_find_control(pos);
|
||||
if (over) {
|
||||
|
||||
if (!gui.modal_stack.empty()) {
|
||||
|
||||
Control *top = gui.modal_stack.back()->get();
|
||||
if (over != top && !top->is_a_parent_of(over)) {
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (over->can_process()) {
|
||||
|
||||
touch_event = touch_event->xformed_by(Transform2D()); //make a copy
|
||||
|
@ -2195,14 +2251,6 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
|
|||
}
|
||||
if (over) {
|
||||
|
||||
if (!gui.modal_stack.empty()) {
|
||||
|
||||
Control *top = gui.modal_stack.back()->get();
|
||||
if (over != top && !top->is_a_parent_of(over)) {
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (over->can_process()) {
|
||||
|
||||
Transform2D localizer = over->get_global_transform_with_canvas().affine_inverse();
|
||||
|
@ -2246,21 +2294,6 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
|
|||
}
|
||||
}
|
||||
|
||||
if (p_event->is_pressed() && p_event->is_action("ui_cancel") && !gui.modal_stack.empty()) {
|
||||
|
||||
_gui_sort_modal_stack();
|
||||
Control *top = gui.modal_stack.back()->get();
|
||||
if (!top->data.modal_exclusive) {
|
||||
|
||||
top->notification(Control::NOTIFICATION_MODAL_CLOSE);
|
||||
top->_modal_stack_remove();
|
||||
top->hide();
|
||||
// Close modal, set input as handled
|
||||
set_input_as_handled();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Control *from = gui.key_focus ? gui.key_focus : NULL; //hmm
|
||||
|
||||
//keyboard focus
|
||||
|
@ -2319,61 +2352,10 @@ List<Control *>::Element *Viewport::_gui_add_root_control(Control *p_control) {
|
|||
return gui.roots.push_back(p_control);
|
||||
}
|
||||
|
||||
List<Control *>::Element *Viewport::_gui_add_subwindow_control(Control *p_control) {
|
||||
|
||||
p_control->connect("visibility_changed", callable_mp(this, &Viewport::_subwindow_visibility_changed));
|
||||
|
||||
if (p_control->is_visible_in_tree()) {
|
||||
gui.subwindow_order_dirty = true;
|
||||
gui.subwindows.push_back(p_control);
|
||||
}
|
||||
|
||||
return gui.all_known_subwindows.push_back(p_control);
|
||||
}
|
||||
|
||||
void Viewport::_gui_set_subwindow_order_dirty() {
|
||||
gui.subwindow_order_dirty = true;
|
||||
}
|
||||
|
||||
void Viewport::_gui_set_root_order_dirty() {
|
||||
gui.roots_order_dirty = true;
|
||||
}
|
||||
|
||||
void Viewport::_gui_remove_modal_control(List<Control *>::Element *MI) {
|
||||
|
||||
gui.modal_stack.erase(MI);
|
||||
}
|
||||
|
||||
void Viewport::_gui_remove_from_modal_stack(List<Control *>::Element *MI, ObjectID p_prev_focus_owner) {
|
||||
|
||||
//transfer the focus stack to the next
|
||||
|
||||
List<Control *>::Element *next = MI->next();
|
||||
|
||||
gui.modal_stack.erase(MI);
|
||||
|
||||
if (p_prev_focus_owner.is_valid()) {
|
||||
|
||||
// for previous window in stack, pass the focus so it feels more
|
||||
// natural
|
||||
|
||||
if (!next) { //top of stack
|
||||
|
||||
Object *pfo = ObjectDB::get_instance(p_prev_focus_owner);
|
||||
Control *pfoc = Object::cast_to<Control>(pfo);
|
||||
if (!pfoc)
|
||||
return;
|
||||
|
||||
if (!pfoc->is_inside_tree() || !pfoc->is_visible_in_tree())
|
||||
return;
|
||||
pfoc->grab_focus();
|
||||
} else {
|
||||
|
||||
next->get()->_modal_set_prev_focus_owner(p_prev_focus_owner);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Viewport::_gui_force_drag(Control *p_base, const Variant &p_data, Control *p_control) {
|
||||
|
||||
ERR_FAIL_COND_MSG(p_data.get_type() == Variant::NIL, "Drag data must be a value.");
|
||||
|
@ -2410,21 +2392,6 @@ void Viewport::_gui_remove_root_control(List<Control *>::Element *RI) {
|
|||
gui.roots.erase(RI);
|
||||
}
|
||||
|
||||
void Viewport::_gui_remove_subwindow_control(List<Control *>::Element *SI) {
|
||||
|
||||
ERR_FAIL_COND(!SI);
|
||||
|
||||
Control *control = SI->get();
|
||||
|
||||
control->disconnect("visibility_changed", callable_mp(this, &Viewport::_subwindow_visibility_changed));
|
||||
|
||||
List<Control *>::Element *E = gui.subwindows.find(control);
|
||||
if (E)
|
||||
gui.subwindows.erase(E);
|
||||
|
||||
gui.all_known_subwindows.erase(SI);
|
||||
}
|
||||
|
||||
void Viewport::_gui_unfocus_control(Control *p_control) {
|
||||
|
||||
if (gui.key_focus == p_control) {
|
||||
|
@ -2485,11 +2452,6 @@ void Viewport::_gui_remove_focus() {
|
|||
}
|
||||
}
|
||||
|
||||
bool Viewport::_gui_is_modal_on_top(const Control *p_control) {
|
||||
|
||||
return (gui.modal_stack.size() && gui.modal_stack.back()->get() == p_control);
|
||||
}
|
||||
|
||||
bool Viewport::_gui_control_has_focus(const Control *p_control) {
|
||||
|
||||
return gui.key_focus == p_control;
|
||||
|
@ -2561,22 +2523,6 @@ void Viewport::_drop_physics_mouseover() {
|
|||
#endif
|
||||
}
|
||||
|
||||
List<Control *>::Element *Viewport::_gui_show_modal(Control *p_control) {
|
||||
|
||||
List<Control *>::Element *node = gui.modal_stack.push_back(p_control);
|
||||
if (gui.key_focus)
|
||||
p_control->_modal_set_prev_focus_owner(gui.key_focus->get_instance_id());
|
||||
else
|
||||
p_control->_modal_set_prev_focus_owner(ObjectID());
|
||||
|
||||
if (gui.mouse_focus && !p_control->is_a_parent_of(gui.mouse_focus) && !gui.mouse_click_grabber) {
|
||||
|
||||
_drop_mouse_focus();
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
Control *Viewport::_gui_get_focus_owner() {
|
||||
|
||||
return gui.key_focus;
|
||||
|
@ -2647,10 +2593,317 @@ void Viewport::_post_gui_grab_click_focus() {
|
|||
|
||||
void Viewport::input_text(const String &p_text) {
|
||||
|
||||
if (gui.subwindow_focused) {
|
||||
gui.subwindow_focused->input_text(p_text);
|
||||
return;
|
||||
}
|
||||
|
||||
if (gui.key_focus) {
|
||||
gui.key_focus->call("set_text", p_text);
|
||||
}
|
||||
}
|
||||
Viewport::SubWindowResize Viewport::_sub_window_get_resize_margin(Window *p_subwindow, const Point2 &p_point) {
|
||||
|
||||
if (p_subwindow->get_flag(Window::FLAG_BORDERLESS)) {
|
||||
return SUB_WINDOW_RESIZE_DISABLED;
|
||||
}
|
||||
|
||||
Rect2i r = Rect2i(p_subwindow->get_position(), p_subwindow->get_size());
|
||||
|
||||
int title_height = p_subwindow->get_theme_constant("title_height");
|
||||
|
||||
r.position.y -= title_height;
|
||||
r.size.y += title_height;
|
||||
|
||||
if (r.has_point(p_point)) {
|
||||
return SUB_WINDOW_RESIZE_DISABLED; //it's inside, so no resize
|
||||
}
|
||||
|
||||
int dist_x = p_point.x < r.position.x ? (p_point.x - r.position.x) : (p_point.x > (r.position.x + r.size.x) ? (p_point.x - (r.position.x + r.size.x)) : 0);
|
||||
int dist_y = p_point.y < r.position.y ? (p_point.y - r.position.y) : (p_point.y > (r.position.y + r.size.y) ? (p_point.y - (r.position.y + r.size.y)) : 0);
|
||||
|
||||
int limit = p_subwindow->get_theme_constant("resize_margin");
|
||||
|
||||
if (ABS(dist_x) > limit) {
|
||||
return SUB_WINDOW_RESIZE_DISABLED;
|
||||
}
|
||||
|
||||
if (ABS(dist_y) > limit) {
|
||||
return SUB_WINDOW_RESIZE_DISABLED;
|
||||
}
|
||||
|
||||
if (dist_x < 0 && dist_y < 0) {
|
||||
return SUB_WINDOW_RESIZE_TOP_LEFT;
|
||||
}
|
||||
|
||||
if (dist_x == 0 && dist_y < 0) {
|
||||
return SUB_WINDOW_RESIZE_TOP;
|
||||
}
|
||||
|
||||
if (dist_x > 0 && dist_y < 0) {
|
||||
return SUB_WINDOW_RESIZE_TOP_RIGHT;
|
||||
}
|
||||
|
||||
if (dist_x < 0 && dist_y == 0) {
|
||||
return SUB_WINDOW_RESIZE_LEFT;
|
||||
}
|
||||
|
||||
if (dist_x > 0 && dist_y == 0) {
|
||||
return SUB_WINDOW_RESIZE_RIGHT;
|
||||
}
|
||||
|
||||
if (dist_x < 0 && dist_y > 0) {
|
||||
return SUB_WINDOW_RESIZE_BOTTOM_LEFT;
|
||||
}
|
||||
|
||||
if (dist_x == 0 && dist_y > 0) {
|
||||
return SUB_WINDOW_RESIZE_BOTTOM;
|
||||
}
|
||||
|
||||
if (dist_x > 0 && dist_y > 0) {
|
||||
return SUB_WINDOW_RESIZE_BOTTOM_RIGHT;
|
||||
}
|
||||
|
||||
return SUB_WINDOW_RESIZE_DISABLED;
|
||||
}
|
||||
bool Viewport::_sub_windows_forward_input(const Ref<InputEvent> &p_event) {
|
||||
|
||||
if (gui.subwindow_drag != SUB_WINDOW_DRAG_DISABLED) {
|
||||
|
||||
ERR_FAIL_COND_V(gui.subwindow_focused == nullptr, false);
|
||||
|
||||
Ref<InputEventMouseButton> mb = p_event;
|
||||
if (mb.is_valid() && !mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) {
|
||||
|
||||
if (gui.subwindow_drag == SUB_WINDOW_DRAG_CLOSE) {
|
||||
if (gui.subwindow_drag_close_rect.has_point(mb->get_position())) {
|
||||
//close window
|
||||
gui.subwindow_focused->_event_callback(DisplayServer::WINDOW_EVENT_CLOSE_REQUEST);
|
||||
}
|
||||
}
|
||||
gui.subwindow_drag = SUB_WINDOW_DRAG_DISABLED;
|
||||
if (gui.subwindow_focused != nullptr) { //may have been erased
|
||||
_sub_window_update(gui.subwindow_focused);
|
||||
}
|
||||
}
|
||||
|
||||
Ref<InputEventMouseMotion> mm = p_event;
|
||||
if (mm.is_valid()) {
|
||||
|
||||
if (gui.subwindow_drag == SUB_WINDOW_DRAG_MOVE) {
|
||||
Vector2 diff = mm->get_position() - gui.subwindow_drag_from;
|
||||
Rect2i new_rect(gui.subwindow_drag_pos + diff, gui.subwindow_focused->get_size());
|
||||
gui.subwindow_focused->_rect_changed_callback(new_rect);
|
||||
}
|
||||
if (gui.subwindow_drag == SUB_WINDOW_DRAG_CLOSE) {
|
||||
gui.subwindow_drag_close_inside = gui.subwindow_drag_close_rect.has_point(mm->get_position());
|
||||
}
|
||||
if (gui.subwindow_drag == SUB_WINDOW_DRAG_RESIZE) {
|
||||
Vector2i diff = mm->get_position() - gui.subwindow_drag_from;
|
||||
Size2i min_size = gui.subwindow_focused->get_min_size();
|
||||
if (gui.subwindow_focused->is_wrapping_controls()) {
|
||||
Size2i cms = gui.subwindow_focused->get_contents_minimum_size();
|
||||
min_size.x = MAX(cms.x, min_size.x);
|
||||
min_size.y = MAX(cms.y, min_size.y);
|
||||
}
|
||||
min_size.x = MAX(min_size.x, 1);
|
||||
min_size.y = MAX(min_size.y, 1);
|
||||
|
||||
Rect2i r = gui.subwindow_resize_from_rect;
|
||||
|
||||
Size2i limit = r.size - min_size;
|
||||
|
||||
switch (gui.subwindow_resize_mode) {
|
||||
case SUB_WINDOW_RESIZE_TOP_LEFT: {
|
||||
|
||||
diff.x = MIN(diff.x, limit.x);
|
||||
diff.y = MIN(diff.y, limit.y);
|
||||
r.position += diff;
|
||||
r.size -= diff;
|
||||
} break;
|
||||
case SUB_WINDOW_RESIZE_TOP: {
|
||||
diff.x = 0;
|
||||
diff.y = MIN(diff.y, limit.y);
|
||||
r.position += diff;
|
||||
r.size -= diff;
|
||||
} break;
|
||||
case SUB_WINDOW_RESIZE_TOP_RIGHT: {
|
||||
diff.x = MAX(diff.x, -limit.x);
|
||||
diff.y = MIN(diff.y, limit.y);
|
||||
r.position.y += diff.y;
|
||||
r.size.y -= diff.y;
|
||||
r.size.x += diff.x;
|
||||
} break;
|
||||
case SUB_WINDOW_RESIZE_LEFT: {
|
||||
diff.x = MIN(diff.x, limit.x);
|
||||
diff.y = 0;
|
||||
r.position += diff;
|
||||
r.size -= diff;
|
||||
|
||||
} break;
|
||||
case SUB_WINDOW_RESIZE_RIGHT: {
|
||||
diff.x = MAX(diff.x, -limit.x);
|
||||
r.size.x += diff.x;
|
||||
} break;
|
||||
case SUB_WINDOW_RESIZE_BOTTOM_LEFT: {
|
||||
diff.x = MIN(diff.x, limit.x);
|
||||
diff.y = MAX(diff.y, -limit.y);
|
||||
r.position.x += diff.x;
|
||||
r.size.x -= diff.x;
|
||||
r.size.y += diff.y;
|
||||
|
||||
} break;
|
||||
case SUB_WINDOW_RESIZE_BOTTOM: {
|
||||
diff.y = MAX(diff.y, -limit.y);
|
||||
r.size.y += diff.y;
|
||||
} break;
|
||||
case SUB_WINDOW_RESIZE_BOTTOM_RIGHT: {
|
||||
diff.x = MAX(diff.x, -limit.x);
|
||||
diff.y = MAX(diff.y, -limit.y);
|
||||
r.size += diff;
|
||||
|
||||
} break;
|
||||
default: {
|
||||
}
|
||||
}
|
||||
|
||||
gui.subwindow_focused->_rect_changed_callback(r);
|
||||
}
|
||||
|
||||
if (gui.subwindow_focused) { //may have been erased
|
||||
_sub_window_update(gui.subwindow_focused);
|
||||
}
|
||||
}
|
||||
|
||||
return true; //handled
|
||||
}
|
||||
Ref<InputEventMouseButton> mb = p_event;
|
||||
//if the event is a mouse button, we need to check whether another window was clicked
|
||||
|
||||
if (mb.is_valid() && mb->is_pressed() && mb->get_button_index() == BUTTON_LEFT) {
|
||||
|
||||
bool click_on_window = false;
|
||||
for (int i = gui.sub_windows.size() - 1; i >= 0; i--) {
|
||||
SubWindow &sw = gui.sub_windows.write[i];
|
||||
|
||||
//clicked inside window?
|
||||
|
||||
Rect2i r = Rect2i(sw.window->get_position(), sw.window->get_size());
|
||||
|
||||
if (!sw.window->get_flag(Window::FLAG_BORDERLESS)) {
|
||||
//check top bar
|
||||
int title_height = sw.window->get_theme_constant("title_height");
|
||||
Rect2i title_bar = r;
|
||||
title_bar.position.y -= title_height;
|
||||
title_bar.size.y = title_height;
|
||||
|
||||
if (title_bar.has_point(mb->get_position())) {
|
||||
|
||||
click_on_window = true;
|
||||
|
||||
int close_h_ofs = sw.window->get_theme_constant("close_h_ofs");
|
||||
int close_v_ofs = sw.window->get_theme_constant("close_v_ofs");
|
||||
Ref<Texture2D> close_icon = sw.window->get_theme_icon("close");
|
||||
|
||||
Rect2 close_rect;
|
||||
close_rect.position = Vector2(r.position.x + r.size.x - close_v_ofs, r.position.y - close_h_ofs);
|
||||
close_rect.size = close_icon->get_size();
|
||||
|
||||
if (gui.subwindow_focused != sw.window) {
|
||||
//refocus
|
||||
_sub_window_grab_focus(sw.window);
|
||||
}
|
||||
|
||||
if (close_rect.has_point(mb->get_position())) {
|
||||
|
||||
gui.subwindow_drag = SUB_WINDOW_DRAG_CLOSE;
|
||||
gui.subwindow_drag_close_inside = true; //starts inside
|
||||
gui.subwindow_drag_close_rect = close_rect;
|
||||
} else {
|
||||
|
||||
gui.subwindow_drag = SUB_WINDOW_DRAG_MOVE;
|
||||
}
|
||||
|
||||
gui.subwindow_drag_from = mb->get_position();
|
||||
gui.subwindow_drag_pos = sw.window->get_position();
|
||||
|
||||
_sub_window_update(sw.window);
|
||||
} else {
|
||||
gui.subwindow_resize_mode = _sub_window_get_resize_margin(gui.subwindow_focused, mb->get_position());
|
||||
if (gui.subwindow_resize_mode != SUB_WINDOW_RESIZE_DISABLED) {
|
||||
gui.subwindow_resize_from_rect = r;
|
||||
gui.subwindow_drag_from = mb->get_position();
|
||||
gui.subwindow_drag = SUB_WINDOW_DRAG_RESIZE;
|
||||
click_on_window = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!click_on_window && r.has_point(mb->get_position())) {
|
||||
//clicked, see if it needs to fetch focus
|
||||
if (gui.subwindow_focused != sw.window) {
|
||||
//refocus
|
||||
_sub_window_grab_focus(sw.window);
|
||||
}
|
||||
|
||||
click_on_window = true;
|
||||
}
|
||||
|
||||
if (click_on_window) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!click_on_window && gui.subwindow_focused) {
|
||||
//no window found and clicked, remove focus
|
||||
_sub_window_grab_focus(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
if (gui.subwindow_focused) {
|
||||
|
||||
Ref<InputEventMouseMotion> mm = p_event;
|
||||
if (mm.is_valid()) {
|
||||
|
||||
SubWindowResize resize = _sub_window_get_resize_margin(gui.subwindow_focused, mm->get_position());
|
||||
if (resize != SUB_WINDOW_RESIZE_DISABLED) {
|
||||
|
||||
DisplayServer::CursorShape shapes[SUB_WINDOW_RESIZE_MAX] = {
|
||||
DisplayServer::CURSOR_ARROW,
|
||||
DisplayServer::CURSOR_FDIAGSIZE,
|
||||
DisplayServer::CURSOR_VSIZE,
|
||||
DisplayServer::CURSOR_BDIAGSIZE,
|
||||
DisplayServer::CURSOR_HSIZE,
|
||||
DisplayServer::CURSOR_HSIZE,
|
||||
DisplayServer::CURSOR_BDIAGSIZE,
|
||||
DisplayServer::CURSOR_VSIZE,
|
||||
DisplayServer::CURSOR_FDIAGSIZE
|
||||
};
|
||||
|
||||
DisplayServer::get_singleton()->cursor_set_shape(shapes[resize]);
|
||||
|
||||
return true; //reserved for showing the resize cursor
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (gui.subwindow_drag != SUB_WINDOW_DRAG_DISABLED) {
|
||||
return true; // dragging, don't pass the event
|
||||
}
|
||||
|
||||
if (!gui.subwindow_focused) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Transform2D window_ofs;
|
||||
window_ofs.set_origin(-gui.subwindow_focused->get_position());
|
||||
|
||||
Ref<InputEvent> ev = p_event->xformed_by(window_ofs);
|
||||
|
||||
gui.subwindow_focused->_window_input(ev);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Viewport::input(const Ref<InputEvent> &p_event, bool p_local_coords) {
|
||||
|
||||
ERR_FAIL_COND(!is_inside_tree());
|
||||
|
@ -2671,6 +2924,11 @@ void Viewport::input(const Ref<InputEvent> &p_event, bool p_local_coords) {
|
|||
ev = p_event;
|
||||
}
|
||||
|
||||
if (is_embedding_subwindows() && _sub_windows_forward_input(p_event)) {
|
||||
set_input_as_handled();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!is_input_handled()) {
|
||||
get_tree()->_call_input_pause(input_group, "_input", ev, this); //not a bug, must happen before GUI, order is _input -> gui input -> _unhandled input
|
||||
}
|
||||
|
@ -2782,11 +3040,6 @@ Vector2 Viewport::get_camera_rect_size() const {
|
|||
return size;
|
||||
}
|
||||
|
||||
bool Viewport::gui_has_modal_stack() const {
|
||||
|
||||
return gui.modal_stack.size();
|
||||
}
|
||||
|
||||
void Viewport::set_disable_input(bool p_disable) {
|
||||
disable_input = p_disable;
|
||||
}
|
||||
|
@ -2800,10 +3053,6 @@ Variant Viewport::gui_get_drag_data() const {
|
|||
return gui.drag_data;
|
||||
}
|
||||
|
||||
Control *Viewport::get_modal_stack_top() const {
|
||||
return gui.modal_stack.size() ? gui.modal_stack.back()->get() : NULL;
|
||||
}
|
||||
|
||||
String Viewport::get_configuration_warning() const {
|
||||
/*if (get_parent() && !Object::cast_to<Control>(get_parent()) && !render_target) {
|
||||
|
||||
|
@ -3039,12 +3288,9 @@ void Viewport::_bind_methods() {
|
|||
ClassDB::bind_method(D_METHOD("get_mouse_position"), &Viewport::get_mouse_position);
|
||||
ClassDB::bind_method(D_METHOD("warp_mouse", "to_position"), &Viewport::warp_mouse);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("gui_has_modal_stack"), &Viewport::gui_has_modal_stack);
|
||||
ClassDB::bind_method(D_METHOD("gui_get_drag_data"), &Viewport::gui_get_drag_data);
|
||||
ClassDB::bind_method(D_METHOD("gui_is_dragging"), &Viewport::gui_is_dragging);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("get_modal_stack_top"), &Viewport::get_modal_stack_top);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("set_disable_input", "disable"), &Viewport::set_disable_input);
|
||||
ClassDB::bind_method(D_METHOD("is_input_disabled"), &Viewport::is_input_disabled);
|
||||
|
||||
|
@ -3157,13 +3403,6 @@ void Viewport::_bind_methods() {
|
|||
BIND_ENUM_CONSTANT(DEFAULT_CANVAS_ITEM_TEXTURE_REPEAT_MAX);
|
||||
}
|
||||
|
||||
void Viewport::_subwindow_visibility_changed() {
|
||||
|
||||
// unfortunately, we don't know the sender, i.e. which subwindow changed;
|
||||
// so we have to check them all.
|
||||
gui.subwindow_visibility_dirty = true;
|
||||
}
|
||||
|
||||
Viewport::Viewport() {
|
||||
|
||||
world_2d = Ref<World2D>(memnew(World2D));
|
||||
|
@ -3227,6 +3466,8 @@ Viewport::Viewport() {
|
|||
gui.roots_order_dirty = false;
|
||||
gui.mouse_focus = NULL;
|
||||
gui.last_mouse_focus = NULL;
|
||||
gui.subwindow_focused = nullptr;
|
||||
gui.subwindow_drag = SUB_WINDOW_DRAG_DISABLED;
|
||||
|
||||
msaa = MSAA_DISABLED;
|
||||
|
||||
|
@ -3302,6 +3543,16 @@ DisplayServer::WindowID SubViewport::get_window_id() const {
|
|||
return DisplayServer::INVALID_WINDOW_ID;
|
||||
}
|
||||
|
||||
void SubViewport::_notification(int p_what) {
|
||||
|
||||
if (p_what == NOTIFICATION_ENTER_TREE) {
|
||||
VS::get_singleton()->viewport_set_active(get_viewport_rid(), true);
|
||||
}
|
||||
if (p_what == NOTIFICATION_EXIT_TREE) {
|
||||
VS::get_singleton()->viewport_set_active(get_viewport_rid(), false);
|
||||
}
|
||||
}
|
||||
|
||||
void SubViewport::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("set_use_arvr", "use"), &SubViewport::set_use_arvr);
|
||||
ClassDB::bind_method(D_METHOD("is_using_arvr"), &SubViewport::is_using_arvr);
|
||||
|
@ -3323,6 +3574,7 @@ void SubViewport::_bind_methods() {
|
|||
BIND_ENUM_CONSTANT(UPDATE_DISABLED);
|
||||
BIND_ENUM_CONSTANT(UPDATE_ONCE);
|
||||
BIND_ENUM_CONSTANT(UPDATE_WHEN_VISIBLE);
|
||||
BIND_ENUM_CONSTANT(UPDATE_WHEN_PARENT_VISIBLE);
|
||||
BIND_ENUM_CONSTANT(UPDATE_ALWAYS);
|
||||
|
||||
BIND_ENUM_CONSTANT(CLEAR_MODE_ALWAYS);
|
||||
|
|
|
@ -151,6 +151,10 @@ public:
|
|||
DEFAULT_CANVAS_ITEM_TEXTURE_REPEAT_MAX,
|
||||
};
|
||||
|
||||
enum {
|
||||
SUBWINDOW_CANVAS_LAYER = 1024
|
||||
};
|
||||
|
||||
private:
|
||||
friend class ViewportTexture;
|
||||
|
||||
|
@ -183,6 +187,7 @@ private:
|
|||
|
||||
RID viewport;
|
||||
RID current_canvas;
|
||||
RID subwindow_canvas;
|
||||
|
||||
bool audio_listener;
|
||||
RID internal_listener;
|
||||
|
@ -269,6 +274,31 @@ private:
|
|||
Ref<ViewportTexture> default_texture;
|
||||
Set<ViewportTexture *> viewport_textures;
|
||||
|
||||
enum SubWindowDrag {
|
||||
SUB_WINDOW_DRAG_DISABLED,
|
||||
SUB_WINDOW_DRAG_MOVE,
|
||||
SUB_WINDOW_DRAG_CLOSE,
|
||||
SUB_WINDOW_DRAG_RESIZE,
|
||||
};
|
||||
|
||||
enum SubWindowResize {
|
||||
SUB_WINDOW_RESIZE_DISABLED,
|
||||
SUB_WINDOW_RESIZE_TOP_LEFT,
|
||||
SUB_WINDOW_RESIZE_TOP,
|
||||
SUB_WINDOW_RESIZE_TOP_RIGHT,
|
||||
SUB_WINDOW_RESIZE_LEFT,
|
||||
SUB_WINDOW_RESIZE_RIGHT,
|
||||
SUB_WINDOW_RESIZE_BOTTOM_LEFT,
|
||||
SUB_WINDOW_RESIZE_BOTTOM,
|
||||
SUB_WINDOW_RESIZE_BOTTOM_RIGHT,
|
||||
SUB_WINDOW_RESIZE_MAX
|
||||
};
|
||||
|
||||
struct SubWindow {
|
||||
Window *window;
|
||||
RID canvas_item;
|
||||
};
|
||||
|
||||
struct GUI {
|
||||
// info used when this is a window
|
||||
|
||||
|
@ -290,17 +320,24 @@ private:
|
|||
Control *drag_preview;
|
||||
float tooltip_timer;
|
||||
float tooltip_delay;
|
||||
List<Control *> modal_stack;
|
||||
Transform2D focus_inv_xform;
|
||||
bool subwindow_order_dirty;
|
||||
bool subwindow_visibility_dirty;
|
||||
List<Control *> subwindows; // visible subwindows
|
||||
List<Control *> all_known_subwindows;
|
||||
bool roots_order_dirty;
|
||||
List<Control *> roots;
|
||||
int canvas_sort_index; //for sorting items with canvas as root
|
||||
bool dragging;
|
||||
bool embed_subwindows_hint;
|
||||
bool embedding_subwindows;
|
||||
|
||||
Window *subwindow_focused;
|
||||
SubWindowDrag subwindow_drag;
|
||||
Vector2 subwindow_drag_from;
|
||||
Vector2 subwindow_drag_pos;
|
||||
Rect2i subwindow_drag_close_rect;
|
||||
bool subwindow_drag_close_inside;
|
||||
SubWindowResize subwindow_resize_mode;
|
||||
Rect2i subwindow_resize_from_rect;
|
||||
|
||||
Vector<SubWindow> sub_windows;
|
||||
|
||||
GUI();
|
||||
} gui;
|
||||
|
@ -316,10 +353,7 @@ private:
|
|||
void _gui_call_input(Control *p_control, const Ref<InputEvent> &p_input);
|
||||
void _gui_call_notification(Control *p_control, int p_what);
|
||||
|
||||
void _gui_prepare_subwindows();
|
||||
void _gui_sort_subwindows();
|
||||
void _gui_sort_roots();
|
||||
void _gui_sort_modal_stack();
|
||||
Control *_gui_find_control(const Point2 &p_global);
|
||||
Control *_gui_find_control_at_pos(CanvasItem *p_node, const Point2 &p_global, const Transform2D &p_xform, Transform2D &r_inv_xform);
|
||||
|
||||
|
@ -334,15 +368,8 @@ private:
|
|||
friend class Control;
|
||||
|
||||
List<Control *>::Element *_gui_add_root_control(Control *p_control);
|
||||
List<Control *>::Element *_gui_add_subwindow_control(Control *p_control);
|
||||
|
||||
void _gui_set_subwindow_order_dirty();
|
||||
void _gui_set_root_order_dirty();
|
||||
|
||||
void _gui_remove_modal_control(List<Control *>::Element *MI);
|
||||
void _gui_remove_from_modal_stack(List<Control *>::Element *MI, ObjectID p_prev_focus_owner);
|
||||
void _gui_remove_root_control(List<Control *>::Element *RI);
|
||||
void _gui_remove_subwindow_control(List<Control *>::Element *SI);
|
||||
|
||||
String _gui_get_tooltip(Control *p_control, const Vector2 &p_pos, Control **r_which = NULL);
|
||||
void _gui_cancel_tooltip();
|
||||
|
@ -354,9 +381,6 @@ private:
|
|||
void _gui_force_drag(Control *p_base, const Variant &p_data, Control *p_control);
|
||||
void _gui_set_drag_preview(Control *p_base, Control *p_control);
|
||||
|
||||
bool _gui_is_modal_on_top(const Control *p_control);
|
||||
List<Control *>::Element *_gui_show_modal(Control *p_control);
|
||||
|
||||
void _gui_remove_focus();
|
||||
void _gui_unfocus_control(Control *p_control);
|
||||
bool _gui_control_has_focus(const Control *p_control);
|
||||
|
@ -367,8 +391,6 @@ private:
|
|||
|
||||
Control *_gui_get_focus_owner();
|
||||
|
||||
Vector2 _get_window_offset() const;
|
||||
|
||||
bool _gui_drop(Control *p_at_control, Point2 p_at_pos, bool p_just_check);
|
||||
|
||||
friend class Listener;
|
||||
|
@ -394,8 +416,20 @@ private:
|
|||
|
||||
void _update_canvas_items(Node *p_node);
|
||||
|
||||
void _gui_set_root_order_dirty();
|
||||
|
||||
void _own_world_changed();
|
||||
|
||||
friend class Window;
|
||||
|
||||
void _sub_window_update_order();
|
||||
void _sub_window_register(Window *p_window);
|
||||
void _sub_window_update(Window *p_window);
|
||||
void _sub_window_grab_focus(Window *p_window);
|
||||
void _sub_window_remove(Window *p_window);
|
||||
bool _sub_windows_forward_input(const Ref<InputEvent> &p_event);
|
||||
SubWindowResize _sub_window_get_resize_margin(Window *p_subwindow, const Point2 &p_point);
|
||||
|
||||
protected:
|
||||
void _set_size(const Size2i &p_size, const Size2i &p_size_override, const Rect2i &p_to_screen_rect, const Transform2D &p_stretch_transform, bool p_allocated);
|
||||
|
||||
|
@ -485,10 +519,7 @@ public:
|
|||
void set_physics_object_picking(bool p_enable);
|
||||
bool get_physics_object_picking();
|
||||
|
||||
bool gui_has_modal_stack() const;
|
||||
|
||||
Variant gui_get_drag_data() const;
|
||||
Control *get_modal_stack_top() const;
|
||||
|
||||
void gui_reset_canvas_sort_index();
|
||||
int gui_get_canvas_sort_index();
|
||||
|
@ -503,8 +534,6 @@ public:
|
|||
void set_snap_controls_to_pixels(bool p_enable);
|
||||
bool is_snap_controls_to_pixels_enabled() const;
|
||||
|
||||
void _subwindow_visibility_changed();
|
||||
|
||||
void set_input_as_handled();
|
||||
bool is_input_handled() const;
|
||||
|
||||
|
@ -546,6 +575,7 @@ public:
|
|||
UPDATE_DISABLED,
|
||||
UPDATE_ONCE, //then goes to disabled
|
||||
UPDATE_WHEN_VISIBLE, // default
|
||||
UPDATE_WHEN_PARENT_VISIBLE,
|
||||
UPDATE_ALWAYS
|
||||
};
|
||||
|
||||
|
@ -557,6 +587,7 @@ private:
|
|||
protected:
|
||||
static void _bind_methods();
|
||||
virtual DisplayServer::WindowID get_window_id() const;
|
||||
void _notification(int p_what);
|
||||
|
||||
public:
|
||||
void set_size(const Size2i &p_size);
|
||||
|
|
|
@ -37,9 +37,14 @@
|
|||
#include "scene/scene_string_names.h"
|
||||
void Window::set_title(const String &p_title) {
|
||||
title = p_title;
|
||||
if (window_id == DisplayServer::INVALID_WINDOW_ID)
|
||||
return;
|
||||
DisplayServer::get_singleton()->window_set_title(p_title, window_id);
|
||||
|
||||
if (embedder) {
|
||||
embedder->_sub_window_update(this);
|
||||
|
||||
} else if (window_id != DisplayServer::INVALID_WINDOW_ID) {
|
||||
|
||||
DisplayServer::get_singleton()->window_set_title(p_title, window_id);
|
||||
}
|
||||
}
|
||||
String Window::get_title() const {
|
||||
return title;
|
||||
|
@ -61,28 +66,25 @@ int Window::get_current_screen() const {
|
|||
void Window::set_position(const Point2i &p_position) {
|
||||
|
||||
position = p_position;
|
||||
if (window_id == DisplayServer::INVALID_WINDOW_ID)
|
||||
return;
|
||||
DisplayServer::get_singleton()->window_set_position(p_position, window_id);
|
||||
|
||||
if (embedder) {
|
||||
embedder->_sub_window_update(this);
|
||||
|
||||
} else if (window_id != DisplayServer::INVALID_WINDOW_ID) {
|
||||
|
||||
DisplayServer::get_singleton()->window_set_position(p_position, window_id);
|
||||
}
|
||||
}
|
||||
Point2i Window::get_position() const {
|
||||
if (window_id != DisplayServer::INVALID_WINDOW_ID) {
|
||||
position = DisplayServer::get_singleton()->window_get_position(window_id);
|
||||
}
|
||||
return position;
|
||||
}
|
||||
|
||||
void Window::set_size(const Size2i &p_size) {
|
||||
size = p_size;
|
||||
if (window_id != DisplayServer::INVALID_WINDOW_ID) {
|
||||
DisplayServer::get_singleton()->window_set_size(p_size, window_id);
|
||||
}
|
||||
_update_size();
|
||||
_update_window_size();
|
||||
}
|
||||
Size2i Window::get_size() const {
|
||||
if (window_id != DisplayServer::INVALID_WINDOW_ID) {
|
||||
size = DisplayServer::get_singleton()->window_get_size(window_id);
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
|
@ -96,22 +98,19 @@ Size2i Window::get_real_size() const {
|
|||
|
||||
void Window::set_max_size(const Size2i &p_max_size) {
|
||||
max_size = p_max_size;
|
||||
if (window_id == DisplayServer::INVALID_WINDOW_ID)
|
||||
return;
|
||||
DisplayServer::get_singleton()->window_set_max_size(p_max_size, window_id);
|
||||
DisplayServer::get_singleton()->window_set_min_size(max_size, window_id);
|
||||
_update_window_size();
|
||||
}
|
||||
Size2i Window::get_max_size() const {
|
||||
if (window_id != DisplayServer::INVALID_WINDOW_ID) {
|
||||
max_size = DisplayServer::get_singleton()->window_get_max_size(window_id);
|
||||
}
|
||||
return max_size;
|
||||
|
||||
return min_size;
|
||||
}
|
||||
|
||||
void Window::set_min_size(const Size2i &p_min_size) {
|
||||
|
||||
min_size = p_min_size;
|
||||
if (window_id == DisplayServer::INVALID_WINDOW_ID)
|
||||
return;
|
||||
DisplayServer::get_singleton()->window_set_min_size(p_min_size, window_id);
|
||||
DisplayServer::get_singleton()->window_set_max_size(max_size, window_id);
|
||||
_update_window_size();
|
||||
}
|
||||
Size2i Window::get_min_size() const {
|
||||
if (window_id != DisplayServer::INVALID_WINDOW_ID) {
|
||||
|
@ -123,9 +122,14 @@ Size2i Window::get_min_size() const {
|
|||
void Window::set_mode(Mode p_mode) {
|
||||
|
||||
mode = p_mode;
|
||||
if (window_id == DisplayServer::INVALID_WINDOW_ID)
|
||||
return;
|
||||
DisplayServer::get_singleton()->window_set_mode(DisplayServer::WindowMode(p_mode), window_id);
|
||||
|
||||
if (embedder) {
|
||||
embedder->_sub_window_update(this);
|
||||
|
||||
} else if (window_id != DisplayServer::INVALID_WINDOW_ID) {
|
||||
|
||||
DisplayServer::get_singleton()->window_set_mode(DisplayServer::WindowMode(p_mode), window_id);
|
||||
}
|
||||
}
|
||||
|
||||
Window::Mode Window::get_mode() const {
|
||||
|
@ -139,9 +143,14 @@ Window::Mode Window::get_mode() const {
|
|||
void Window::set_flag(Flags p_flag, bool p_enabled) {
|
||||
ERR_FAIL_INDEX(p_flag, FLAG_MAX);
|
||||
flags[p_flag] = p_enabled;
|
||||
if (window_id == DisplayServer::INVALID_WINDOW_ID)
|
||||
return;
|
||||
DisplayServer::get_singleton()->window_set_flag(DisplayServer::WindowFlags(p_flag), p_enabled, window_id);
|
||||
|
||||
if (embedder) {
|
||||
embedder->_sub_window_update(this);
|
||||
|
||||
} else if (window_id != DisplayServer::INVALID_WINDOW_ID) {
|
||||
|
||||
DisplayServer::get_singleton()->window_set_flag(DisplayServer::WindowFlags(p_flag), p_enabled, window_id);
|
||||
}
|
||||
}
|
||||
|
||||
bool Window::get_flag(Flags p_flag) const {
|
||||
|
@ -165,7 +174,11 @@ void Window::request_attention() {
|
|||
}
|
||||
}
|
||||
void Window::move_to_foreground() {
|
||||
if (window_id != DisplayServer::INVALID_WINDOW_ID) {
|
||||
|
||||
if (embedder) {
|
||||
embedder->_sub_window_grab_focus(this);
|
||||
|
||||
} else if (window_id != DisplayServer::INVALID_WINDOW_ID) {
|
||||
DisplayServer::get_singleton()->window_move_to_foreground(window_id);
|
||||
}
|
||||
}
|
||||
|
@ -178,7 +191,7 @@ bool Window::can_draw() const {
|
|||
return DisplayServer::get_singleton()->window_can_draw(window_id);
|
||||
}
|
||||
|
||||
return true;
|
||||
return visible;
|
||||
}
|
||||
|
||||
void Window::set_ime_active(bool p_active) {
|
||||
|
@ -194,11 +207,8 @@ void Window::set_ime_position(const Point2i &p_pos) {
|
|||
|
||||
bool Window::is_embedded() const {
|
||||
ERR_FAIL_COND_V(!is_inside_tree(), false);
|
||||
if (get_parent_viewport()) {
|
||||
return get_parent_viewport()->is_embedding_subwindows();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
Viewport *parent_vp = get_parent_viewport();
|
||||
return parent_vp && parent_vp->is_embedding_subwindows();
|
||||
}
|
||||
|
||||
void Window::_make_window() {
|
||||
|
@ -210,6 +220,7 @@ void Window::_make_window() {
|
|||
f |= (1 << i);
|
||||
}
|
||||
}
|
||||
|
||||
window_id = DisplayServer::get_singleton()->create_sub_window(DisplayServer::WindowMode(mode), f, Rect2i(position, size));
|
||||
ERR_FAIL_COND(window_id == DisplayServer::INVALID_WINDOW_ID);
|
||||
DisplayServer::get_singleton()->window_set_current_screen(current_screen, window_id);
|
||||
|
@ -217,7 +228,7 @@ void Window::_make_window() {
|
|||
DisplayServer::get_singleton()->window_set_min_size(min_size, window_id);
|
||||
DisplayServer::get_singleton()->window_set_title(title, window_id);
|
||||
|
||||
_update_size();
|
||||
_update_window_size();
|
||||
|
||||
if (transient_parent && transient_parent->window_id != DisplayServer::INVALID_WINDOW_ID) {
|
||||
DisplayServer::get_singleton()->window_set_transient(window_id, transient_parent->window_id);
|
||||
|
@ -228,6 +239,8 @@ void Window::_make_window() {
|
|||
DisplayServer::get_singleton()->window_set_transient(E->get()->window_id, transient_parent->window_id);
|
||||
}
|
||||
}
|
||||
|
||||
VS::get_singleton()->viewport_set_update_mode(get_viewport_rid(), VS::VIEWPORT_UPDATE_WHEN_VISIBLE);
|
||||
}
|
||||
void Window::_update_from_window() {
|
||||
|
||||
|
@ -236,10 +249,6 @@ void Window::_update_from_window() {
|
|||
for (int i = 0; i < FLAG_MAX; i++) {
|
||||
flags[i] = DisplayServer::get_singleton()->window_get_flag(DisplayServer::WindowFlags(i), window_id);
|
||||
}
|
||||
position = DisplayServer::get_singleton()->window_get_position(window_id);
|
||||
size = DisplayServer::get_singleton()->window_get_size(window_id);
|
||||
max_size = DisplayServer::get_singleton()->window_get_max_size(window_id);
|
||||
min_size = DisplayServer::get_singleton()->window_get_min_size(window_id);
|
||||
}
|
||||
|
||||
void Window::_clear_window() {
|
||||
|
@ -256,16 +265,26 @@ void Window::_clear_window() {
|
|||
}
|
||||
|
||||
_update_from_window();
|
||||
print_line("deleting window bye");
|
||||
|
||||
DisplayServer::get_singleton()->delete_sub_window(window_id);
|
||||
window_id = DisplayServer::INVALID_WINDOW_ID;
|
||||
_update_size();
|
||||
_update_viewport_size();
|
||||
|
||||
VS::get_singleton()->viewport_set_update_mode(get_viewport_rid(), VS::VIEWPORT_UPDATE_DISABLED);
|
||||
}
|
||||
|
||||
void Window::_resize_callback(const Size2i &p_callback) {
|
||||
void Window::_rect_changed_callback(const Rect2i &p_callback) {
|
||||
|
||||
size = p_callback;
|
||||
_update_size();
|
||||
//we must always accept this as the truth
|
||||
if (size == p_callback.size && position == p_callback.position) {
|
||||
return;
|
||||
}
|
||||
position = p_callback.position;
|
||||
|
||||
if (size != p_callback.size) {
|
||||
size = p_callback.size;
|
||||
_update_viewport_size();
|
||||
}
|
||||
}
|
||||
|
||||
void Window::_propagate_window_notification(Node *p_node, int p_notification) {
|
||||
|
@ -335,11 +354,15 @@ void Window::set_visible(bool p_visible) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (updating_child_controls) {
|
||||
_update_child_controls();
|
||||
}
|
||||
|
||||
ERR_FAIL_COND_MSG(get_parent() == nullptr, "Can't change visibility of main window.");
|
||||
|
||||
bool subwindow = get_parent() && get_parent()->get_viewport()->is_embedding_subwindows();
|
||||
Viewport *embedder_vp = _get_embedder();
|
||||
|
||||
if (!subwindow) {
|
||||
if (!embedder_vp) {
|
||||
if (!p_visible && window_id != DisplayServer::INVALID_WINDOW_ID) {
|
||||
_clear_window();
|
||||
}
|
||||
|
@ -348,7 +371,16 @@ void Window::set_visible(bool p_visible) {
|
|||
_update_window_callbacks();
|
||||
}
|
||||
} else {
|
||||
_update_size();
|
||||
if (visible) {
|
||||
embedder = embedder_vp;
|
||||
embedder->_sub_window_register(this);
|
||||
VS::get_singleton()->viewport_set_update_mode(get_viewport_rid(), VS::VIEWPORT_UPDATE_WHEN_PARENT_VISIBLE);
|
||||
} else {
|
||||
embedder->_sub_window_remove(this);
|
||||
embedder = nullptr;
|
||||
VS::get_singleton()->viewport_set_update_mode(get_viewport_rid(), VS::VIEWPORT_UPDATE_DISABLED);
|
||||
}
|
||||
_update_window_size();
|
||||
}
|
||||
|
||||
if (!visible) {
|
||||
|
@ -356,6 +388,8 @@ void Window::set_visible(bool p_visible) {
|
|||
}
|
||||
notification(NOTIFICATION_VISIBILITY_CHANGED);
|
||||
emit_signal(SceneStringNames::get_singleton()->visibility_changed);
|
||||
|
||||
VS::get_singleton()->viewport_set_active(get_viewport_rid(), visible);
|
||||
}
|
||||
|
||||
void Window::_clear_transient() {
|
||||
|
@ -458,7 +492,38 @@ bool Window::is_visible() const {
|
|||
return visible;
|
||||
}
|
||||
|
||||
void Window::_update_size() {
|
||||
void Window::_update_window_size() {
|
||||
|
||||
Size2i size_limit;
|
||||
if (wrap_controls) {
|
||||
size_limit = get_contents_minimum_size();
|
||||
}
|
||||
|
||||
size_limit.x = MAX(size_limit.x, min_size.x);
|
||||
size_limit.y = MAX(size_limit.y, min_size.y);
|
||||
|
||||
size.x = MAX(size_limit.x, size.x);
|
||||
size.y = MAX(size_limit.y, size.y);
|
||||
|
||||
if (max_size.x > 0 && max_size.x > min_size.x && max_size.x > size.x) {
|
||||
size.x = max_size.x;
|
||||
}
|
||||
|
||||
if (max_size.y > 0 && max_size.y > min_size.y && max_size.y > size.y) {
|
||||
size.y = max_size.y;
|
||||
}
|
||||
|
||||
if (embedder) {
|
||||
embedder->_sub_window_update(this);
|
||||
} else if (window_id != DisplayServer::INVALID_WINDOW_ID) {
|
||||
DisplayServer::get_singleton()->window_set_size(size, window_id);
|
||||
}
|
||||
|
||||
//update the viewport
|
||||
_update_viewport_size();
|
||||
}
|
||||
void Window::_update_viewport_size() {
|
||||
//update the viewport part
|
||||
|
||||
Size2i final_size;
|
||||
Size2i final_size_override;
|
||||
|
@ -563,7 +628,7 @@ void Window::_update_size() {
|
|||
stretch_transform.elements[2] = margin * scale;
|
||||
}
|
||||
|
||||
bool allocate = is_inside_tree() && visible && (window_id != DisplayServer::INVALID_WINDOW_ID || (get_parent() && get_parent()->get_viewport()->is_embedding_subwindows()));
|
||||
bool allocate = is_inside_tree() && visible && (window_id != DisplayServer::INVALID_WINDOW_ID || embedder != nullptr);
|
||||
|
||||
_set_size(final_size, final_size_override, attach_to_screen_rect, stretch_transform, allocate);
|
||||
|
||||
|
@ -586,28 +651,78 @@ void Window::_update_size() {
|
|||
}
|
||||
|
||||
notification(NOTIFICATION_WM_SIZE_CHANGED);
|
||||
|
||||
if (embedder) {
|
||||
embedder->_sub_window_update(this);
|
||||
}
|
||||
}
|
||||
|
||||
void Window::_update_window_callbacks() {
|
||||
DisplayServer::get_singleton()->window_set_resize_callback(callable_mp(this, &Window::_resize_callback), window_id);
|
||||
DisplayServer::get_singleton()->window_set_rect_changed_callback(callable_mp(this, &Window::_rect_changed_callback), window_id);
|
||||
DisplayServer::get_singleton()->window_set_window_event_callback(callable_mp(this, &Window::_event_callback), window_id);
|
||||
DisplayServer::get_singleton()->window_set_input_event_callback(callable_mp(this, &Window::_window_input), window_id);
|
||||
DisplayServer::get_singleton()->window_set_input_text_callback(callable_mp(this, &Window::_window_input_text), window_id);
|
||||
DisplayServer::get_singleton()->window_set_drop_files_callback(callable_mp(this, &Window::_window_drop_files), window_id);
|
||||
}
|
||||
|
||||
Viewport *Window::_get_embedder() const {
|
||||
|
||||
Viewport *vp = get_parent_viewport();
|
||||
|
||||
while (vp) {
|
||||
|
||||
if (vp->is_embedding_subwindows()) {
|
||||
return vp;
|
||||
}
|
||||
|
||||
if (vp->get_parent()) {
|
||||
vp = vp->get_parent()->get_viewport();
|
||||
} else {
|
||||
vp = nullptr;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Window::_notification(int p_what) {
|
||||
if (p_what == NOTIFICATION_ENTER_TREE) {
|
||||
if (is_embedded()) {
|
||||
|
||||
bool embedded = false;
|
||||
{
|
||||
|
||||
embedder = _get_embedder();
|
||||
|
||||
if (embedder) {
|
||||
embedded = true;
|
||||
|
||||
if (!visible) {
|
||||
embedder = nullptr; //not yet since not visible
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (embedded) {
|
||||
//create as embedded
|
||||
_update_size();
|
||||
if (embedder) {
|
||||
embedder->_sub_window_register(this);
|
||||
VS::get_singleton()->viewport_set_update_mode(get_viewport_rid(), VS::VIEWPORT_UPDATE_WHEN_PARENT_VISIBLE);
|
||||
_update_window_size();
|
||||
}
|
||||
|
||||
} else {
|
||||
if (get_parent() == nullptr) {
|
||||
//it's the root window!
|
||||
visible = true; //always visible
|
||||
window_id = DisplayServer::MAIN_WINDOW_ID;
|
||||
_update_from_window();
|
||||
_update_size();
|
||||
//since this window already exists (created on start), we must update pos and size from it
|
||||
{
|
||||
position = DisplayServer::get_singleton()->window_get_position(window_id);
|
||||
size = DisplayServer::get_singleton()->window_get_size(window_id);
|
||||
}
|
||||
_update_viewport_size(); //then feed back to the viewport
|
||||
_update_window_callbacks();
|
||||
VS::get_singleton()->viewport_set_update_mode(get_viewport_rid(), VS::VIEWPORT_UPDATE_WHEN_VISIBLE);
|
||||
} else {
|
||||
//create
|
||||
if (visible) {
|
||||
|
@ -623,6 +738,7 @@ void Window::_notification(int p_what) {
|
|||
if (visible) {
|
||||
notification(NOTIFICATION_VISIBILITY_CHANGED);
|
||||
emit_signal(SceneStringNames::get_singleton()->visibility_changed);
|
||||
VS::get_singleton()->viewport_set_active(get_viewport_rid(), true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -643,13 +759,22 @@ void Window::_notification(int p_what) {
|
|||
|
||||
if (window_id == DisplayServer::MAIN_WINDOW_ID) {
|
||||
|
||||
VS::get_singleton()->viewport_set_update_mode(get_viewport_rid(), VS::VIEWPORT_UPDATE_DISABLED);
|
||||
_update_window_callbacks();
|
||||
} else {
|
||||
_clear_window();
|
||||
}
|
||||
} else {
|
||||
_update_size(); //called by clear and make, which does not happen here
|
||||
|
||||
if (embedder) {
|
||||
embedder->_sub_window_remove(this);
|
||||
embedder = nullptr;
|
||||
VS::get_singleton()->viewport_set_update_mode(get_viewport_rid(), VS::VIEWPORT_UPDATE_DISABLED);
|
||||
}
|
||||
_update_viewport_size(); //called by clear and make, which does not happen here
|
||||
}
|
||||
|
||||
VS::get_singleton()->viewport_set_active(get_viewport_rid(), false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -657,7 +782,7 @@ void Window::set_content_scale_size(const Size2i &p_size) {
|
|||
ERR_FAIL_COND(p_size.x < 0);
|
||||
ERR_FAIL_COND(p_size.y < 0);
|
||||
content_scale_size = p_size;
|
||||
_update_size();
|
||||
_update_viewport_size();
|
||||
}
|
||||
|
||||
Size2i Window::get_content_scale_size() const {
|
||||
|
@ -666,7 +791,7 @@ Size2i Window::get_content_scale_size() const {
|
|||
|
||||
void Window::set_content_scale_mode(ContentScaleMode p_mode) {
|
||||
content_scale_mode = p_mode;
|
||||
_update_size();
|
||||
_update_viewport_size();
|
||||
}
|
||||
Window::ContentScaleMode Window::get_content_scale_mode() const {
|
||||
return content_scale_mode;
|
||||
|
@ -674,7 +799,7 @@ Window::ContentScaleMode Window::get_content_scale_mode() const {
|
|||
|
||||
void Window::set_content_scale_aspect(ContentScaleAspect p_aspect) {
|
||||
content_scale_aspect = p_aspect;
|
||||
_update_size();
|
||||
_update_viewport_size();
|
||||
}
|
||||
Window::ContentScaleAspect Window::get_content_scale_aspect() const {
|
||||
return content_scale_aspect;
|
||||
|
@ -685,7 +810,7 @@ void Window::set_use_font_oversampling(bool p_oversampling) {
|
|||
ERR_FAIL_MSG("Only the root window can set and use font oversampling.");
|
||||
}
|
||||
use_font_oversampling = p_oversampling;
|
||||
_update_size();
|
||||
_update_viewport_size();
|
||||
}
|
||||
bool Window::is_using_font_oversampling() const {
|
||||
return use_font_oversampling;
|
||||
|
@ -724,22 +849,17 @@ Size2 Window::_get_contents_minimum_size() const {
|
|||
}
|
||||
void Window::_update_child_controls() {
|
||||
|
||||
Size2 max = _get_contents_minimum_size();
|
||||
|
||||
Size2 new_size(MAX(max.x, size.x), MAX(max.y, size.y));
|
||||
|
||||
if (new_size != size) {
|
||||
set_size(new_size);
|
||||
}
|
||||
set_min_size(max);
|
||||
updating_child_controls = false;
|
||||
}
|
||||
void Window::child_controls_changed() {
|
||||
if (!is_inside_tree()) {
|
||||
if (!updating_child_controls) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (updating_child_controls) {
|
||||
_update_window_size();
|
||||
|
||||
updating_child_controls = false;
|
||||
}
|
||||
void Window::child_controls_changed() {
|
||||
|
||||
if (!is_inside_tree() || !visible || updating_child_controls) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -762,7 +882,7 @@ void Window::_window_input(const Ref<InputEvent> &p_ev) {
|
|||
|
||||
if (exclusive_child != nullptr) {
|
||||
exclusive_child->grab_focus();
|
||||
print_line("drop because of exclusive");
|
||||
|
||||
return; //has an exclusive child, can't get events until child is closed
|
||||
}
|
||||
|
||||
|
@ -901,6 +1021,7 @@ void Window::popup_centered_ratio(float p_ratio) {
|
|||
void Window::popup(const Rect2 &p_screen_rect) {
|
||||
|
||||
emit_signal("about_to_popup");
|
||||
|
||||
if (p_screen_rect != Rect2()) {
|
||||
set_position(p_screen_rect.position);
|
||||
set_size(p_screen_rect.size);
|
||||
|
@ -917,7 +1038,9 @@ Size2 Window::get_contents_minimum_size() const {
|
|||
}
|
||||
|
||||
void Window::grab_focus() {
|
||||
if (window_id != DisplayServer::INVALID_WINDOW_ID) {
|
||||
if (embedder) {
|
||||
embedder->_sub_window_grab_focus(this);
|
||||
} else if (window_id != DisplayServer::INVALID_WINDOW_ID) {
|
||||
DisplayServer::get_singleton()->window_move_to_foreground(window_id);
|
||||
}
|
||||
}
|
||||
|
@ -939,6 +1062,10 @@ void Window::add_child_notify(Node *p_child) {
|
|||
if (child_w && child_w->theme.is_null() && (theme_owner || theme_owner_window)) {
|
||||
Control::_propagate_theme_changed(child_w, theme_owner, theme_owner_window); //need to propagate here, since many controls may require setting up stuff
|
||||
}
|
||||
|
||||
if (is_inside_tree() && wrap_controls) {
|
||||
child_controls_changed();
|
||||
}
|
||||
}
|
||||
|
||||
void Window::remove_child_notify(Node *p_child) {
|
||||
|
@ -954,6 +1081,10 @@ void Window::remove_child_notify(Node *p_child) {
|
|||
if (child_w && (child_w->theme_owner || child_w->theme_owner_window) && child_w->theme.is_null()) {
|
||||
Control::_propagate_theme_changed(child_w, NULL, NULL);
|
||||
}
|
||||
|
||||
if (is_inside_tree() && wrap_controls) {
|
||||
child_controls_changed();
|
||||
}
|
||||
}
|
||||
|
||||
void Window::set_theme(const Ref<Theme> &p_theme) {
|
||||
|
@ -988,47 +1119,65 @@ Ref<Theme> Window::get_theme() const {
|
|||
}
|
||||
|
||||
Ref<Texture2D> Window::get_theme_icon(const StringName &p_name, const StringName &p_type) const {
|
||||
return Control::get_icons(theme_owner, theme_owner_window, p_name, p_type);
|
||||
StringName type = p_type ? p_type : get_class_name();
|
||||
return Control::get_icons(theme_owner, theme_owner_window, p_name, type);
|
||||
}
|
||||
Ref<Shader> Window::get_theme_shader(const StringName &p_name, const StringName &p_type) const {
|
||||
return Control::get_shaders(theme_owner, theme_owner_window, p_name, p_type);
|
||||
StringName type = p_type ? p_type : get_class_name();
|
||||
return Control::get_shaders(theme_owner, theme_owner_window, p_name, type);
|
||||
}
|
||||
Ref<StyleBox> Window::get_theme_stylebox(const StringName &p_name, const StringName &p_type) const {
|
||||
return Control::get_styleboxs(theme_owner, theme_owner_window, p_name, p_type);
|
||||
StringName type = p_type ? p_type : get_class_name();
|
||||
return Control::get_styleboxs(theme_owner, theme_owner_window, p_name, type);
|
||||
}
|
||||
Ref<Font> Window::get_theme_font(const StringName &p_name, const StringName &p_type) const {
|
||||
return Control::get_fonts(theme_owner, theme_owner_window, p_name, p_type);
|
||||
StringName type = p_type ? p_type : get_class_name();
|
||||
return Control::get_fonts(theme_owner, theme_owner_window, p_name, type);
|
||||
}
|
||||
Color Window::get_theme_color(const StringName &p_name, const StringName &p_type) const {
|
||||
return Control::get_colors(theme_owner, theme_owner_window, p_name, p_type);
|
||||
StringName type = p_type ? p_type : get_class_name();
|
||||
return Control::get_colors(theme_owner, theme_owner_window, p_name, type);
|
||||
}
|
||||
int Window::get_theme_constant(const StringName &p_name, const StringName &p_type) const {
|
||||
return Control::get_constants(theme_owner, theme_owner_window, p_name, p_type);
|
||||
StringName type = p_type ? p_type : get_class_name();
|
||||
return Control::get_constants(theme_owner, theme_owner_window, p_name, type);
|
||||
}
|
||||
|
||||
bool Window::has_theme_icon(const StringName &p_name, const StringName &p_type) const {
|
||||
return Control::has_icons(theme_owner, theme_owner_window, p_name, p_type);
|
||||
StringName type = p_type ? p_type : get_class_name();
|
||||
return Control::has_icons(theme_owner, theme_owner_window, p_name, type);
|
||||
}
|
||||
bool Window::has_theme_shader(const StringName &p_name, const StringName &p_type) const {
|
||||
return Control::has_shaders(theme_owner, theme_owner_window, p_name, p_type);
|
||||
StringName type = p_type ? p_type : get_class_name();
|
||||
return Control::has_shaders(theme_owner, theme_owner_window, p_name, type);
|
||||
}
|
||||
bool Window::has_theme_stylebox(const StringName &p_name, const StringName &p_type) const {
|
||||
return Control::has_styleboxs(theme_owner, theme_owner_window, p_name, p_type);
|
||||
StringName type = p_type ? p_type : get_class_name();
|
||||
return Control::has_styleboxs(theme_owner, theme_owner_window, p_name, type);
|
||||
}
|
||||
bool Window::has_theme_font(const StringName &p_name, const StringName &p_type) const {
|
||||
return Control::has_fonts(theme_owner, theme_owner_window, p_name, p_type);
|
||||
StringName type = p_type ? p_type : get_class_name();
|
||||
return Control::has_fonts(theme_owner, theme_owner_window, p_name, type);
|
||||
}
|
||||
bool Window::has_theme_color(const StringName &p_name, const StringName &p_type) const {
|
||||
return Control::has_colors(theme_owner, theme_owner_window, p_name, p_type);
|
||||
StringName type = p_type ? p_type : get_class_name();
|
||||
return Control::has_colors(theme_owner, theme_owner_window, p_name, type);
|
||||
}
|
||||
bool Window::has_theme_constant(const StringName &p_name, const StringName &p_type) const {
|
||||
return Control::has_constants(theme_owner, theme_owner_window, p_name, p_type);
|
||||
StringName type = p_type ? p_type : get_class_name();
|
||||
return Control::has_constants(theme_owner, theme_owner_window, p_name, type);
|
||||
}
|
||||
|
||||
Rect2i Window::get_screen_rect() const {
|
||||
Rect2i Window::get_parent_rect() const {
|
||||
ERR_FAIL_COND_V(!is_inside_tree(), Rect2i());
|
||||
if (is_embedded()) {
|
||||
//viewport
|
||||
return Rect2i();
|
||||
Node *n = get_parent();
|
||||
ERR_FAIL_COND_V(!n, Rect2i());
|
||||
Viewport *p = n->get_viewport();
|
||||
ERR_FAIL_COND_V(!p, Rect2i());
|
||||
|
||||
return p->get_visible_rect();
|
||||
} else {
|
||||
int x = get_position().x;
|
||||
int closest_dist = 0x7FFFFFFF;
|
||||
|
@ -1188,6 +1337,7 @@ Window::Window() {
|
|||
}
|
||||
content_scale_mode = CONTENT_SCALE_MODE_DISABLED;
|
||||
content_scale_aspect = CONTENT_SCALE_ASPECT_IGNORE;
|
||||
VS::get_singleton()->viewport_set_update_mode(get_viewport_rid(), VS::VIEWPORT_UPDATE_DISABLED);
|
||||
}
|
||||
Window::~Window() {
|
||||
}
|
||||
|
|
|
@ -103,20 +103,13 @@ private:
|
|||
void _clear_window();
|
||||
void _update_from_window();
|
||||
|
||||
void _resize_callback(const Size2i &p_callback);
|
||||
void _event_callback(DisplayServer::WindowEvent p_event);
|
||||
|
||||
void _update_size();
|
||||
void _update_viewport_size();
|
||||
void _update_window_size();
|
||||
|
||||
void _propagate_window_notification(Node *p_node, int p_notification);
|
||||
|
||||
virtual DisplayServer::WindowID get_window_id() const;
|
||||
|
||||
void _window_input(const Ref<InputEvent> &p_ev);
|
||||
void _window_input_text(const String &p_text);
|
||||
void _window_drop_files(const Vector<String> &p_files);
|
||||
|
||||
void _window_unhandled_input(const Ref<InputEvent> &p_ev);
|
||||
void _update_window_callbacks();
|
||||
|
||||
void _clear_transient();
|
||||
|
@ -130,6 +123,18 @@ private:
|
|||
Control *theme_owner = nullptr;
|
||||
Window *theme_owner_window = nullptr;
|
||||
|
||||
Viewport *_get_embedder() const;
|
||||
|
||||
Viewport *embedder = nullptr;
|
||||
|
||||
friend class Viewport; //friend back, can call the methods below
|
||||
|
||||
void _window_input(const Ref<InputEvent> &p_ev);
|
||||
void _window_input_text(const String &p_text);
|
||||
void _window_drop_files(const Vector<String> &p_files);
|
||||
void _rect_changed_callback(const Rect2i &p_callback);
|
||||
void _event_callback(DisplayServer::WindowEvent p_event);
|
||||
|
||||
protected:
|
||||
virtual void _post_popup() {}
|
||||
virtual Size2 _get_contents_minimum_size() const;
|
||||
|
@ -243,7 +248,7 @@ public:
|
|||
bool has_theme_color(const StringName &p_name, const StringName &p_type = StringName()) const;
|
||||
bool has_theme_constant(const StringName &p_name, const StringName &p_type = StringName()) const;
|
||||
|
||||
Rect2i get_screen_rect() const;
|
||||
Rect2i get_parent_rect() const;
|
||||
|
||||
Window();
|
||||
~Window();
|
||||
|
|
|
@ -524,18 +524,19 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
|
|||
|
||||
// WindowDialog
|
||||
|
||||
theme->set_stylebox("panel", "AcceptDialog", default_style);
|
||||
theme->set_stylebox("window_panel", "AcceptDialog", sb_expand(make_stylebox(popup_window_png, 10, 26, 10, 8), 8, 24, 8, 6));
|
||||
theme->set_constant("scaleborder_size", "AcceptDialog", 4 * scale);
|
||||
theme->set_stylebox("panel", "Window", default_style);
|
||||
theme->set_stylebox("window_panel", "Window", sb_expand(make_stylebox(popup_window_png, 10, 26, 10, 8), 8, 24, 8, 6));
|
||||
theme->set_constant("scaleborder_size", "Window", 4 * scale);
|
||||
|
||||
theme->set_font("title_font", "AcceptDialog", large_font);
|
||||
theme->set_color("title_color", "AcceptDialog", Color(0, 0, 0));
|
||||
theme->set_constant("title_height", "AcceptDialog", 20 * scale);
|
||||
theme->set_font("title_font", "Window", large_font);
|
||||
theme->set_color("title_color", "Window", Color(0, 0, 0));
|
||||
theme->set_constant("title_height", "Window", 20 * scale);
|
||||
theme->set_constant("resize_margin", "Window", 4 * scale);
|
||||
|
||||
theme->set_icon("close", "AcceptDialog", make_icon(close_png));
|
||||
theme->set_icon("close_highlight", "AcceptDialog", make_icon(close_hl_png));
|
||||
theme->set_constant("close_h_ofs", "AcceptDialog", 18 * scale);
|
||||
theme->set_constant("close_v_ofs", "AcceptDialog", 18 * scale);
|
||||
theme->set_icon("close", "Window", make_icon(close_png));
|
||||
theme->set_icon("close_highlight", "Window", make_icon(close_hl_png));
|
||||
theme->set_constant("close_h_ofs", "Window", 18 * scale);
|
||||
theme->set_constant("close_v_ofs", "Window", 18 * scale);
|
||||
|
||||
// File Dialog
|
||||
|
||||
|
|
|
@ -276,7 +276,7 @@ void DisplayServer::_bind_methods() {
|
|||
|
||||
ClassDB::bind_method(D_METHOD("window_get_size", "window_id"), &DisplayServer::window_get_size, DEFVAL(MAIN_WINDOW_ID));
|
||||
ClassDB::bind_method(D_METHOD("window_set_size", "size", "window_id"), &DisplayServer::window_set_size, DEFVAL(MAIN_WINDOW_ID));
|
||||
ClassDB::bind_method(D_METHOD("window_set_resize_callback", "callback", "window_id"), &DisplayServer::window_set_resize_callback, DEFVAL(MAIN_WINDOW_ID));
|
||||
ClassDB::bind_method(D_METHOD("window_set_rect_changed_callback", "callback", "window_id"), &DisplayServer::window_set_rect_changed_callback, DEFVAL(MAIN_WINDOW_ID));
|
||||
ClassDB::bind_method(D_METHOD("window_set_window_event_callback", "callback", "window_id"), &DisplayServer::window_set_window_event_callback, DEFVAL(MAIN_WINDOW_ID));
|
||||
ClassDB::bind_method(D_METHOD("window_set_input_event_callback", "callback", "window_id"), &DisplayServer::window_set_input_event_callback, DEFVAL(MAIN_WINDOW_ID));
|
||||
ClassDB::bind_method(D_METHOD("window_set_input_text_callback", "callback", "window_id"), &DisplayServer::window_set_input_text_callback, DEFVAL(MAIN_WINDOW_ID));
|
||||
|
|
|
@ -182,7 +182,7 @@ public:
|
|||
virtual WindowID create_sub_window(WindowMode p_mode, uint32_t p_flags, const Rect2i & = Rect2i());
|
||||
virtual void delete_sub_window(WindowID p_id);
|
||||
|
||||
virtual void window_set_resize_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) = 0;
|
||||
virtual void window_set_rect_changed_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) = 0;
|
||||
|
||||
enum WindowEvent {
|
||||
WINDOW_EVENT_MOUSE_ENTER,
|
||||
|
|
|
@ -316,7 +316,10 @@ void VisualServerViewport::draw_viewports() {
|
|||
//draw viewports
|
||||
RENDER_TIMESTAMP(">Render Viewports");
|
||||
|
||||
for (int i = 0; i < active_viewports.size(); i++) {
|
||||
//determine what is visible
|
||||
draw_viewports_pass++;
|
||||
|
||||
for (int i = active_viewports.size() - 1; i >= 0; i--) { //to compute parent dependency, must go in reverse draw order
|
||||
|
||||
Viewport *vp = active_viewports[i];
|
||||
|
||||
|
@ -328,11 +331,37 @@ void VisualServerViewport::draw_viewports() {
|
|||
}
|
||||
//ERR_CONTINUE(!vp->render_target.is_valid());
|
||||
|
||||
bool visible = vp->viewport_to_screen_rect != Rect2() || vp->update_mode == VS::VIEWPORT_UPDATE_ALWAYS || vp->update_mode == VS::VIEWPORT_UPDATE_ONCE || (vp->update_mode == VS::VIEWPORT_UPDATE_WHEN_VISIBLE && VSG::storage->render_target_was_used(vp->render_target));
|
||||
bool visible = vp->viewport_to_screen_rect != Rect2();
|
||||
|
||||
if (vp->update_mode == VS::VIEWPORT_UPDATE_ALWAYS || vp->update_mode == VS::VIEWPORT_UPDATE_ONCE) {
|
||||
visible = true;
|
||||
}
|
||||
|
||||
if (vp->update_mode == VS::VIEWPORT_UPDATE_WHEN_VISIBLE && VSG::storage->render_target_was_used(vp->render_target)) {
|
||||
visible = true;
|
||||
}
|
||||
|
||||
if (vp->update_mode == VS::VIEWPORT_UPDATE_WHEN_PARENT_VISIBLE) {
|
||||
Viewport *parent = viewport_owner.getornull(vp->parent);
|
||||
if (parent && parent->last_pass == draw_viewports_pass) {
|
||||
visible = true;
|
||||
}
|
||||
}
|
||||
|
||||
visible = visible && vp->size.x > 1 && vp->size.y > 1;
|
||||
|
||||
if (!visible)
|
||||
continue;
|
||||
if (visible) {
|
||||
vp->last_pass = draw_viewports_pass;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < active_viewports.size(); i++) {
|
||||
|
||||
Viewport *vp = active_viewports[i];
|
||||
|
||||
if (vp->last_pass != draw_viewports_pass) {
|
||||
continue; //should not draw
|
||||
}
|
||||
|
||||
RENDER_TIMESTAMP(">Rendering Viewport " + itos(i));
|
||||
|
||||
|
|
|
@ -73,6 +73,8 @@ public:
|
|||
RID shadow_atlas;
|
||||
int shadow_atlas_size;
|
||||
|
||||
uint64_t last_pass = 0;
|
||||
|
||||
int render_info[VS::VIEWPORT_RENDER_INFO_MAX];
|
||||
VS::ViewportDebugDraw debug_draw;
|
||||
|
||||
|
@ -129,6 +131,8 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
uint64_t draw_viewports_pass = 0;
|
||||
|
||||
mutable RID_PtrOwner<Viewport> viewport_owner;
|
||||
|
||||
struct ViewportSort {
|
||||
|
@ -139,9 +143,9 @@ public:
|
|||
|
||||
if (left_to_screen == right_to_screen) {
|
||||
|
||||
return p_left->parent == p_right->self;
|
||||
return p_right->parent == p_left->self;
|
||||
}
|
||||
return right_to_screen;
|
||||
return (right_to_screen ? 0 : 1) < (left_to_screen ? 0 : 1);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -2060,6 +2060,7 @@ void VisualServer::_bind_methods() {
|
|||
BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_DISABLED);
|
||||
BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_ONCE);
|
||||
BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_WHEN_VISIBLE);
|
||||
BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_WHEN_PARENT_VISIBLE);
|
||||
BIND_ENUM_CONSTANT(VIEWPORT_UPDATE_ALWAYS);
|
||||
|
||||
BIND_ENUM_CONSTANT(VIEWPORT_CLEAR_ALWAYS);
|
||||
|
|
|
@ -592,6 +592,7 @@ public:
|
|||
VIEWPORT_UPDATE_DISABLED,
|
||||
VIEWPORT_UPDATE_ONCE, //then goes to disabled, must be manually updated
|
||||
VIEWPORT_UPDATE_WHEN_VISIBLE, // default
|
||||
VIEWPORT_UPDATE_WHEN_PARENT_VISIBLE,
|
||||
VIEWPORT_UPDATE_ALWAYS
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue