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