diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index fa6a7832f54..b6a2b09c80a 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -187,6 +187,7 @@ Viewport::GUI::GUI() { tooltip = NULL; tooltip_popup = NULL; tooltip_label = NULL; + subwindow_visibility_dirty = false; subwindow_order_dirty = false; } @@ -1346,6 +1347,24 @@ void Viewport::warp_mouse(const Vector2 &p_pos) { Input::get_singleton()->warp_mouse_position(gpos); } +void Viewport::_gui_prepare_subwindows() { + + if (gui.subwindow_visibility_dirty) { + + gui.subwindows.clear(); + for (List::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) @@ -1488,7 +1507,7 @@ void Viewport::_gui_call_input(Control *p_control, const Ref &p_inpu Control *Viewport::_gui_find_control(const Point2 &p_global) { - _gui_sort_subwindows(); + _gui_prepare_subwindows(); for (List::Element *E = gui.subwindows.back(); E; E = E->prev()) { @@ -2181,8 +2200,14 @@ List::Element *Viewport::_gui_add_root_control(Control *p_control) { List::Element *Viewport::_gui_add_subwindow_control(Control *p_control) { - gui.subwindow_order_dirty = true; - return gui.subwindows.push_back(p_control); + p_control->connect("visibility_changed", this, "_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() { @@ -2269,7 +2294,17 @@ void Viewport::_gui_remove_root_control(List::Element *RI) { void Viewport::_gui_remove_subwindow_control(List::Element *SI) { - gui.subwindows.erase(SI); + ERR_FAIL_COND(!SI); + + Control *control = SI->get(); + + control->disconnect("visibility_changed", this, "_subwindow_visibility_changed"); + + List::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) { @@ -2753,6 +2788,8 @@ void Viewport::_bind_methods() { ClassDB::bind_method(D_METHOD("set_shadow_atlas_quadrant_subdiv", "quadrant", "subdiv"), &Viewport::set_shadow_atlas_quadrant_subdiv); ClassDB::bind_method(D_METHOD("get_shadow_atlas_quadrant_subdiv", "quadrant"), &Viewport::get_shadow_atlas_quadrant_subdiv); + ClassDB::bind_method(D_METHOD("_subwindow_visibility_changed"), &Viewport::_subwindow_visibility_changed); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "arvr"), "set_use_arvr", "use_arvr"); ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "size"), "set_size", "get_size"); @@ -2830,6 +2867,13 @@ void Viewport::_bind_methods() { BIND_ENUM_CONSTANT(CLEAR_MODE_ONLY_NEXT_FRAME); } +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(memnew(World2D)); diff --git a/scene/main/viewport.h b/scene/main/viewport.h index c084e348b5c..74dd1ebc8c2 100644 --- a/scene/main/viewport.h +++ b/scene/main/viewport.h @@ -271,7 +271,9 @@ private: List modal_stack; Transform2D focus_inv_xform; bool subwindow_order_dirty; - List subwindows; + bool subwindow_visibility_dirty; + List subwindows; // visible subwindows + List all_known_subwindows; bool roots_order_dirty; List roots; int canvas_sort_index; //for sorting items with canvas as root @@ -282,6 +284,7 @@ private: bool disable_input; void _gui_call_input(Control *p_control, const Ref &p_input); + void _gui_prepare_subwindows(); void _gui_sort_subwindows(); void _gui_sort_roots(); void _gui_sort_modal_stack(); @@ -470,6 +473,8 @@ public: void set_snap_controls_to_pixels(bool p_enable); bool is_snap_controls_to_pixels_enabled() const; + void _subwindow_visibility_changed(); + Viewport(); ~Viewport(); };