summaryrefslogtreecommitdiff
path: root/scene
diff options
context:
space:
mode:
Diffstat (limited to 'scene')
-rw-r--r--scene/2d/audio_stream_player_2d.cpp2
-rw-r--r--scene/2d/camera_2d.h2
-rw-r--r--scene/2d/canvas_item.cpp58
-rw-r--r--scene/2d/canvas_item.h4
-rw-r--r--scene/2d/node_2d.cpp2
-rw-r--r--scene/2d/particles_2d.cpp2
-rw-r--r--scene/2d/sprite.cpp2
-rw-r--r--scene/2d/touch_screen_button.cpp19
-rw-r--r--scene/2d/visibility_notifier_2d.cpp2
-rw-r--r--scene/3d/arvr_nodes.cpp8
-rw-r--r--scene/3d/audio_stream_player_3d.cpp2
-rw-r--r--scene/3d/camera.h2
-rw-r--r--scene/3d/gi_probe.cpp2
-rw-r--r--scene/3d/listener.h2
-rw-r--r--scene/3d/particles.cpp2
-rw-r--r--scene/3d/spatial.cpp2
-rw-r--r--scene/3d/world_environment.cpp2
-rw-r--r--scene/debugger/scene_debugger.cpp2
-rw-r--r--scene/gui/base_button.cpp5
-rw-r--r--scene/gui/box_container.cpp6
-rw-r--r--scene/gui/button.cpp86
-rw-r--r--scene/gui/check_box.cpp20
-rw-r--r--scene/gui/check_button.cpp16
-rw-r--r--scene/gui/color_picker.cpp80
-rw-r--r--scene/gui/control.cpp863
-rw-r--r--scene/gui/control.h98
-rw-r--r--scene/gui/dialogs.cpp439
-rw-r--r--scene/gui/dialogs.h83
-rw-r--r--scene/gui/file_dialog.cpp147
-rw-r--r--scene/gui/file_dialog.h23
-rw-r--r--scene/gui/gradient_edit.cpp6
-rw-r--r--scene/gui/graph_edit.cpp54
-rw-r--r--scene/gui/graph_node.cpp56
-rw-r--r--scene/gui/grid_container.cpp8
-rw-r--r--scene/gui/item_list.cpp30
-rw-r--r--scene/gui/label.cpp34
-rw-r--r--scene/gui/line_edit.cpp125
-rw-r--r--scene/gui/link_button.cpp20
-rw-r--r--scene/gui/margin_container.cpp16
-rw-r--r--scene/gui/menu_button.cpp34
-rw-r--r--scene/gui/option_button.cpp39
-rw-r--r--scene/gui/panel.cpp16
-rw-r--r--scene/gui/panel.h14
-rw-r--r--scene/gui/panel_container.cpp20
-rw-r--r--scene/gui/popup.cpp280
-rw-r--r--scene/gui/popup.h39
-rw-r--r--scene/gui/popup_menu.cpp567
-rw-r--r--scene/gui/popup_menu.h13
-rw-r--r--scene/gui/progress_bar.cpp14
-rw-r--r--scene/gui/rich_text_label.cpp93
-rw-r--r--scene/gui/scroll_bar.cpp54
-rw-r--r--scene/gui/scroll_container.cpp14
-rw-r--r--scene/gui/separator.cpp6
-rw-r--r--scene/gui/shortcut.h2
-rw-r--r--scene/gui/slider.cpp16
-rw-r--r--scene/gui/spin_box.cpp13
-rw-r--r--scene/gui/split_container.cpp26
-rw-r--r--scene/gui/tab_container.cpp98
-rw-r--r--scene/gui/tabs.cpp104
-rw-r--r--scene/gui/text_edit.cpp160
-rw-r--r--scene/gui/tree.cpp164
-rw-r--r--scene/gui/tree.h8
-rw-r--r--scene/gui/viewport_container.cpp18
-rw-r--r--scene/main/node.cpp4
-rw-r--r--scene/main/node.h17
-rw-r--r--scene/main/scene_tree.cpp383
-rw-r--r--scene/main/scene_tree.h56
-rw-r--r--scene/main/viewport.cpp1615
-rw-r--r--scene/main/viewport.h213
-rw-r--r--scene/main/window.cpp1406
-rw-r--r--scene/main/window.h266
-rw-r--r--scene/register_scene_types.cpp9
-rw-r--r--scene/resources/default_theme/default_theme.cpp21
-rw-r--r--scene/resources/world_2d.cpp2
-rw-r--r--scene/scene_string_names.cpp6
-rw-r--r--scene/scene_string_names.h7
76 files changed, 4779 insertions, 3370 deletions
diff --git a/scene/2d/audio_stream_player_2d.cpp b/scene/2d/audio_stream_player_2d.cpp
index 3ef4dfe5f1..df0b17800f 100644
--- a/scene/2d/audio_stream_player_2d.cpp
+++ b/scene/2d/audio_stream_player_2d.cpp
@@ -32,7 +32,7 @@
#include "core/engine.h"
#include "scene/2d/area_2d.h"
-#include "scene/main/viewport.h"
+#include "scene/main/window.h"
void AudioStreamPlayer2D::_mix_audio() {
diff --git a/scene/2d/camera_2d.h b/scene/2d/camera_2d.h
index 04b5260444..7a106ef79a 100644
--- a/scene/2d/camera_2d.h
+++ b/scene/2d/camera_2d.h
@@ -32,7 +32,7 @@
#define CAMERA_2D_H
#include "scene/2d/node_2d.h"
-#include "scene/main/viewport.h"
+#include "scene/main/window.h"
class Camera2D : public Node2D {
diff --git a/scene/2d/canvas_item.cpp b/scene/2d/canvas_item.cpp
index ef7aa9ba01..7a0fc3352b 100644
--- a/scene/2d/canvas_item.cpp
+++ b/scene/2d/canvas_item.cpp
@@ -29,11 +29,13 @@
/*************************************************************************/
#include "canvas_item.h"
+
+#include "core/input/input_filter.h"
#include "core/message_queue.h"
#include "core/method_bind_ext.gen.inc"
-#include "core/os/input.h"
#include "scene/main/canvas_layer.h"
#include "scene/main/viewport.h"
+#include "scene/main/window.h"
#include "scene/resources/font.h"
#include "scene/resources/style_box.h"
#include "scene/resources/texture.h"
@@ -347,6 +349,9 @@ bool CanvasItem::is_visible_in_tree() const {
while (p) {
if (!p->visible)
return false;
+ if (p->window && !p->window->is_visible()) {
+ return false;
+ }
p = p->get_parent_item();
}
@@ -450,6 +455,21 @@ Transform2D CanvasItem::get_global_transform_with_canvas() const {
return get_global_transform();
}
+Transform2D CanvasItem::get_screen_transform() const {
+ ERR_FAIL_COND_V(!is_inside_tree(), Transform2D());
+ Transform2D xform = get_global_transform_with_canvas();
+
+ Window *w = Object::cast_to<Window>(get_viewport());
+ if (w && !w->is_embedding_subwindows()) {
+ Transform2D s;
+ s.set_origin(w->get_position());
+
+ xform = s * xform;
+ }
+
+ return xform;
+}
+
Transform2D CanvasItem::get_global_transform() const {
#ifdef DEBUG_ENABLED
ERR_FAIL_COND_V(!is_inside_tree(), get_transform());
@@ -548,10 +568,30 @@ void CanvasItem::_notification(int p_what) {
_update_texture_repeat_changed(false);
first_draw = true;
- if (get_parent()) {
- CanvasItem *ci = Object::cast_to<CanvasItem>(get_parent());
+ Node *parent = get_parent();
+ if (parent) {
+ CanvasItem *ci = Object::cast_to<CanvasItem>(parent);
if (ci)
C = ci->children_items.push_back(this);
+ if (!ci) {
+ //look for a window
+ Viewport *viewport = nullptr;
+
+ while (parent) {
+ viewport = Object::cast_to<Viewport>(parent);
+ if (viewport) {
+ break;
+ }
+ parent = parent->get_parent();
+ }
+
+ ERR_FAIL_COND(!viewport);
+
+ window = Object::cast_to<Window>(viewport);
+ if (window) {
+ window->connect(SceneStringNames::get_singleton()->visibility_changed, callable_mp(this, &CanvasItem::_window_visibility_changed));
+ }
+ }
}
_enter_canvas();
if (!block_transform_notify && !xform_change.in_list()) {
@@ -580,6 +620,9 @@ void CanvasItem::_notification(int p_what) {
Object::cast_to<CanvasItem>(get_parent())->children_items.erase(C);
C = NULL;
}
+ if (window) {
+ window->disconnect(SceneStringNames::get_singleton()->visibility_changed, callable_mp(this, &CanvasItem::_window_visibility_changed));
+ }
global_invalid = true;
} break;
case NOTIFICATION_DRAW:
@@ -600,6 +643,14 @@ void CanvasItem::set_visible(bool p_visible) {
else
hide();
}
+
+void CanvasItem::_window_visibility_changed() {
+
+ if (visible) {
+ _propagate_visibility_changed(window->is_visible());
+ }
+}
+
bool CanvasItem::is_visible() const {
return visible;
@@ -1408,6 +1459,7 @@ CanvasItem::TextureRepeat CanvasItem::get_texture_repeat() const {
CanvasItem::CanvasItem() :
xform_change(this) {
+ window = nullptr;
canvas_item = VisualServer::get_singleton()->canvas_item_create();
visible = true;
pending_update = false;
diff --git a/scene/2d/canvas_item.h b/scene/2d/canvas_item.h
index c7f9500ea1..3f176e5f60 100644
--- a/scene/2d/canvas_item.h
+++ b/scene/2d/canvas_item.h
@@ -201,6 +201,7 @@ private:
int light_mask;
+ Window *window;
bool first_draw;
bool visible;
bool pending_update;
@@ -232,6 +233,8 @@ private:
void _enter_canvas();
void _exit_canvas();
+ void _window_visibility_changed();
+
void _notify_transform(CanvasItem *p_node);
void _set_on_top(bool p_on_top) { set_draw_behind_parent(!p_on_top); }
@@ -364,6 +367,7 @@ public:
virtual Transform2D get_global_transform() const;
virtual Transform2D get_global_transform_with_canvas() const;
+ virtual Transform2D get_screen_transform() const;
CanvasItem *get_toplevel() const;
_FORCE_INLINE_ RID get_canvas_item() const {
diff --git a/scene/2d/node_2d.cpp b/scene/2d/node_2d.cpp
index df21538609..0b0b9820d3 100644
--- a/scene/2d/node_2d.cpp
+++ b/scene/2d/node_2d.cpp
@@ -32,7 +32,7 @@
#include "core/message_queue.h"
#include "scene/gui/control.h"
-#include "scene/main/viewport.h"
+#include "scene/main/window.h"
#include "servers/visual_server.h"
#ifdef TOOLS_ENABLED
diff --git a/scene/2d/particles_2d.cpp b/scene/2d/particles_2d.cpp
index 2ba2fd8f79..e5c17fe9a4 100644
--- a/scene/2d/particles_2d.cpp
+++ b/scene/2d/particles_2d.cpp
@@ -228,7 +228,7 @@ bool Particles2D::get_fractional_delta() const {
String Particles2D::get_configuration_warning() const {
- if (OS::get_singleton()->get_current_video_driver() == OS::VIDEO_DRIVER_GLES2) {
+ if (VisualServer::get_singleton()->is_low_end()) {
return TTR("GPU-based particles are not supported by the GLES2 video driver.\nUse the CPUParticles2D node instead. You can use the \"Convert to CPUParticles\" option for this purpose.");
}
diff --git a/scene/2d/sprite.cpp b/scene/2d/sprite.cpp
index 7eaafe5348..a6fb6f7435 100644
--- a/scene/2d/sprite.cpp
+++ b/scene/2d/sprite.cpp
@@ -32,7 +32,7 @@
#include "core/core_string_names.h"
#include "core/os/os.h"
-#include "scene/main/viewport.h"
+#include "scene/main/window.h"
#include "scene/scene_string_names.h"
#ifdef TOOLS_ENABLED
diff --git a/scene/2d/touch_screen_button.cpp b/scene/2d/touch_screen_button.cpp
index 1cca45b422..2cb979a0e0 100644
--- a/scene/2d/touch_screen_button.cpp
+++ b/scene/2d/touch_screen_button.cpp
@@ -30,10 +30,11 @@
#include "touch_screen_button.h"
-#include "core/input_map.h"
-#include "core/os/input.h"
+#include "core/input/input_filter.h"
+#include "core/input/input_map.h"
#include "core/os/os.h"
-
+#include "scene/main/window.h"
+#
void TouchScreenButton::set_texture(const Ref<Texture2D> &p_texture) {
texture = p_texture;
@@ -114,7 +115,7 @@ void TouchScreenButton::_notification(int p_what) {
if (!is_inside_tree())
return;
- if (!Engine::get_singleton()->is_editor_hint() && !OS::get_singleton()->has_touchscreen_ui_hint() && visibility == VISIBILITY_TOUCHSCREEN_ONLY)
+ if (!Engine::get_singleton()->is_editor_hint() && !!DisplayServer::get_singleton()->screen_is_touchscreen(DisplayServer::get_singleton()->window_get_current_screen(get_viewport()->get_window_id())) && visibility == VISIBILITY_TOUCHSCREEN_ONLY)
return;
if (finger_pressed != -1) {
@@ -145,7 +146,7 @@ void TouchScreenButton::_notification(int p_what) {
} break;
case NOTIFICATION_ENTER_TREE: {
- if (!Engine::get_singleton()->is_editor_hint() && !OS::get_singleton()->has_touchscreen_ui_hint() && visibility == VISIBILITY_TOUCHSCREEN_ONLY)
+ if (!Engine::get_singleton()->is_editor_hint() && !!DisplayServer::get_singleton()->screen_is_touchscreen(DisplayServer::get_singleton()->window_get_current_screen(get_viewport()->get_window_id())) && visibility == VISIBILITY_TOUCHSCREEN_ONLY)
return;
update();
@@ -289,12 +290,12 @@ void TouchScreenButton::_press(int p_finger_pressed) {
if (action != StringName()) {
- Input::get_singleton()->action_press(action);
+ InputFilter::get_singleton()->action_press(action);
Ref<InputEventAction> iea;
iea.instance();
iea->set_action(action);
iea->set_pressed(true);
- get_tree()->input_event(iea);
+ get_viewport()->input(iea, true);
}
emit_signal("pressed");
@@ -307,14 +308,14 @@ void TouchScreenButton::_release(bool p_exiting_tree) {
if (action != StringName()) {
- Input::get_singleton()->action_release(action);
+ InputFilter::get_singleton()->action_release(action);
if (!p_exiting_tree) {
Ref<InputEventAction> iea;
iea.instance();
iea->set_action(action);
iea->set_pressed(false);
- get_tree()->input_event(iea);
+ get_viewport()->input(iea, true);
}
}
diff --git a/scene/2d/visibility_notifier_2d.cpp b/scene/2d/visibility_notifier_2d.cpp
index 54511bbe1b..65dabb92b1 100644
--- a/scene/2d/visibility_notifier_2d.cpp
+++ b/scene/2d/visibility_notifier_2d.cpp
@@ -35,7 +35,7 @@
#include "scene/2d/animated_sprite.h"
#include "scene/2d/physics_body_2d.h"
#include "scene/animation/animation_player.h"
-#include "scene/main/viewport.h"
+#include "scene/main/window.h"
#include "scene/scene_string_names.h"
#ifdef TOOLS_ENABLED
diff --git a/scene/3d/arvr_nodes.cpp b/scene/3d/arvr_nodes.cpp
index d23e5ffa08..bea717b354 100644
--- a/scene/3d/arvr_nodes.cpp
+++ b/scene/3d/arvr_nodes.cpp
@@ -29,7 +29,7 @@
/*************************************************************************/
#include "arvr_nodes.h"
-#include "core/os/input.h"
+#include "core/input/input_filter.h"
#include "servers/arvr/arvr_interface.h"
#include "servers/arvr_server.h"
@@ -206,7 +206,7 @@ void ARVRController::_notification(int p_what) {
// check button states
for (int i = 0; i < 16; i++) {
bool was_pressed = (button_states & mask) == mask;
- bool is_pressed = Input::get_singleton()->is_joy_button_pressed(joy_id, i);
+ bool is_pressed = InputFilter::get_singleton()->is_joy_button_pressed(joy_id, i);
if (!was_pressed && is_pressed) {
emit_signal("button_pressed", i);
@@ -306,7 +306,7 @@ bool ARVRController::is_button_pressed(int p_button) const {
return false;
};
- return Input::get_singleton()->is_joy_button_pressed(joy_id, p_button);
+ return InputFilter::get_singleton()->is_joy_button_pressed(joy_id, p_button);
};
float ARVRController::get_joystick_axis(int p_axis) const {
@@ -315,7 +315,7 @@ float ARVRController::get_joystick_axis(int p_axis) const {
return 0.0;
};
- return Input::get_singleton()->get_joy_axis(joy_id, p_axis);
+ return InputFilter::get_singleton()->get_joy_axis(joy_id, p_axis);
};
real_t ARVRController::get_rumble() const {
diff --git a/scene/3d/audio_stream_player_3d.cpp b/scene/3d/audio_stream_player_3d.cpp
index f0a61a905c..f3020d4044 100644
--- a/scene/3d/audio_stream_player_3d.cpp
+++ b/scene/3d/audio_stream_player_3d.cpp
@@ -33,7 +33,7 @@
#include "scene/3d/area.h"
#include "scene/3d/camera.h"
#include "scene/3d/listener.h"
-#include "scene/main/viewport.h"
+#include "scene/main/window.h"
// Based on "A Novel Multichannel Panning Method for Standard and Arbitrary Loudspeaker Configurations" by Ramy Sadek and Chris Kyriakakis (2004)
// Speaker-Placement Correction Amplitude Panning (SPCAP)
diff --git a/scene/3d/camera.h b/scene/3d/camera.h
index 6ac3ece798..feb7b39b1e 100644
--- a/scene/3d/camera.h
+++ b/scene/3d/camera.h
@@ -33,7 +33,7 @@
#include "scene/3d/spatial.h"
#include "scene/3d/spatial_velocity_tracker.h"
-#include "scene/main/viewport.h"
+#include "scene/main/window.h"
#include "scene/resources/environment.h"
class Camera : public Spatial {
diff --git a/scene/3d/gi_probe.cpp b/scene/3d/gi_probe.cpp
index c3f039ae85..76549f7e51 100644
--- a/scene/3d/gi_probe.cpp
+++ b/scene/3d/gi_probe.cpp
@@ -526,7 +526,7 @@ Vector<Face3> GIProbe::get_faces(uint32_t p_usage_flags) const {
String GIProbe::get_configuration_warning() const {
- if (OS::get_singleton()->get_current_video_driver() == OS::VIDEO_DRIVER_GLES2) {
+ if (VisualServer::get_singleton()->is_low_end()) {
return TTR("GIProbes are not supported by the GLES2 video driver.\nUse a BakedLightmap instead.");
}
return String();
diff --git a/scene/3d/listener.h b/scene/3d/listener.h
index 287e67f31e..17ff1d9397 100644
--- a/scene/3d/listener.h
+++ b/scene/3d/listener.h
@@ -32,7 +32,7 @@
#define LISTENER_H
#include "scene/3d/spatial.h"
-#include "scene/main/viewport.h"
+#include "scene/main/window.h"
class Listener : public Spatial {
diff --git a/scene/3d/particles.cpp b/scene/3d/particles.cpp
index e502b0c037..7a1eeb105a 100644
--- a/scene/3d/particles.cpp
+++ b/scene/3d/particles.cpp
@@ -240,7 +240,7 @@ bool Particles::get_fractional_delta() const {
String Particles::get_configuration_warning() const {
- if (OS::get_singleton()->get_current_video_driver() == OS::VIDEO_DRIVER_GLES2) {
+ if (VisualServer::get_singleton()->is_low_end()) {
return TTR("GPU-based particles are not supported by the GLES2 video driver.\nUse the CPUParticles node instead. You can use the \"Convert to CPUParticles\" option for this purpose.");
}
diff --git a/scene/3d/spatial.cpp b/scene/3d/spatial.cpp
index f1911348ce..c6225dd291 100644
--- a/scene/3d/spatial.cpp
+++ b/scene/3d/spatial.cpp
@@ -33,7 +33,7 @@
#include "core/engine.h"
#include "core/message_queue.h"
#include "scene/main/scene_tree.h"
-#include "scene/main/viewport.h"
+#include "scene/main/window.h"
#include "scene/scene_string_names.h"
/*
diff --git a/scene/3d/world_environment.cpp b/scene/3d/world_environment.cpp
index 83a7243906..9276432ba9 100644
--- a/scene/3d/world_environment.cpp
+++ b/scene/3d/world_environment.cpp
@@ -29,7 +29,7 @@
/*************************************************************************/
#include "world_environment.h"
-#include "scene/main/viewport.h"
+#include "scene/main/window.h"
void WorldEnvironment::_notification(int p_what) {
diff --git a/scene/debugger/scene_debugger.cpp b/scene/debugger/scene_debugger.cpp
index 7a184adc55..359f936793 100644
--- a/scene/debugger/scene_debugger.cpp
+++ b/scene/debugger/scene_debugger.cpp
@@ -34,7 +34,7 @@
#include "core/io/marshalls.h"
#include "core/script_language.h"
#include "scene/main/scene_tree.h"
-#include "scene/main/viewport.h"
+#include "scene/main/window.h"
#include "scene/resources/packed_scene.h"
void SceneDebugger::initialize() {
diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp
index b2020d44e8..a05ac08e9d 100644
--- a/scene/gui/base_button.cpp
+++ b/scene/gui/base_button.cpp
@@ -31,7 +31,7 @@
#include "base_button.h"
#include "core/os/keyboard.h"
-#include "scene/main/viewport.h"
+#include "scene/main/window.h"
#include "scene/scene_string_names.h"
void BaseButton::_unpress_group() {
@@ -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);
}
}
diff --git a/scene/gui/box_container.cpp b/scene/gui/box_container.cpp
index e0bfeac9f7..0da6e0fdfa 100644
--- a/scene/gui/box_container.cpp
+++ b/scene/gui/box_container.cpp
@@ -45,7 +45,7 @@ void BoxContainer::_resort() {
Size2i new_size = get_size();
- int sep = get_constant("separation"); //,vertical?"VBoxContainer":"HBoxContainer");
+ int sep = get_theme_constant("separation"); //,vertical?"VBoxContainer":"HBoxContainer");
bool first = true;
int children_count = 0;
@@ -206,7 +206,7 @@ Size2 BoxContainer::get_minimum_size() const {
/* Calculate MINIMUM SIZE */
Size2i minimum;
- int sep = get_constant("separation"); //,vertical?"VBoxContainer":"HBoxContainer");
+ int sep = get_theme_constant("separation"); //,vertical?"VBoxContainer":"HBoxContainer");
bool first = true;
@@ -310,7 +310,7 @@ MarginContainer *VBoxContainer::add_margin_child(const String &p_label, Control
l->set_text(p_label);
add_child(l);
MarginContainer *mc = memnew(MarginContainer);
- mc->add_constant_override("margin_left", 0);
+ mc->add_theme_constant_override("margin_left", 0);
mc->add_child(p_control);
add_child(mc);
if (p_expand)
diff --git a/scene/gui/button.cpp b/scene/gui/button.cpp
index 784d298bff..f71d322412 100644
--- a/scene/gui/button.cpp
+++ b/scene/gui/button.cpp
@@ -35,14 +35,14 @@
Size2 Button::get_minimum_size() const {
- Size2 minsize = get_font("font")->get_string_size(xl_text);
+ Size2 minsize = get_theme_font("font")->get_string_size(xl_text);
if (clip_text)
minsize.width = 0;
if (!expand_icon) {
Ref<Texture2D> _icon;
- if (icon.is_null() && has_icon("icon"))
- _icon = Control::get_icon("icon");
+ if (icon.is_null() && has_theme_icon("icon"))
+ _icon = Control::get_theme_icon("icon");
else
_icon = icon;
@@ -51,11 +51,11 @@ Size2 Button::get_minimum_size() const {
minsize.height = MAX(minsize.height, _icon->get_height());
minsize.width += _icon->get_width();
if (xl_text != "")
- minsize.width += get_constant("hseparation");
+ minsize.width += get_theme_constant("hseparation");
}
}
- return get_stylebox("normal")->get_minimum_size() + minsize;
+ return get_theme_stylebox("normal")->get_minimum_size() + minsize;
}
void Button::_set_internal_margin(Margin p_margin, float p_value) {
@@ -79,30 +79,30 @@ void Button::_notification(int p_what) {
Color color;
Color color_icon(1, 1, 1, 1);
- Ref<StyleBox> style = get_stylebox("normal");
+ Ref<StyleBox> style = get_theme_stylebox("normal");
switch (get_draw_mode()) {
case DRAW_NORMAL: {
- style = get_stylebox("normal");
+ style = get_theme_stylebox("normal");
if (!flat)
style->draw(ci, Rect2(Point2(0, 0), size));
- color = get_color("font_color");
- if (has_color("icon_color_normal"))
- color_icon = get_color("icon_color_normal");
+ color = get_theme_color("font_color");
+ if (has_theme_color("icon_color_normal"))
+ color_icon = get_theme_color("icon_color_normal");
} break;
case DRAW_HOVER_PRESSED: {
- if (has_stylebox("hover_pressed") && has_stylebox_override("hover_pressed")) {
- style = get_stylebox("hover_pressed");
+ if (has_theme_stylebox("hover_pressed") && has_theme_stylebox_override("hover_pressed")) {
+ style = get_theme_stylebox("hover_pressed");
if (!flat)
style->draw(ci, Rect2(Point2(0, 0), size));
- if (has_color("font_color_hover_pressed"))
- color = get_color("font_color_hover_pressed");
+ if (has_theme_color("font_color_hover_pressed"))
+ color = get_theme_color("font_color_hover_pressed");
else
- color = get_color("font_color");
- if (has_color("icon_color_hover_pressed"))
- color_icon = get_color("icon_color_hover_pressed");
+ color = get_theme_color("font_color");
+ if (has_theme_color("icon_color_hover_pressed"))
+ color_icon = get_theme_color("icon_color_hover_pressed");
break;
}
@@ -110,49 +110,49 @@ void Button::_notification(int p_what) {
}
case DRAW_PRESSED: {
- style = get_stylebox("pressed");
+ style = get_theme_stylebox("pressed");
if (!flat)
style->draw(ci, Rect2(Point2(0, 0), size));
- if (has_color("font_color_pressed"))
- color = get_color("font_color_pressed");
+ if (has_theme_color("font_color_pressed"))
+ color = get_theme_color("font_color_pressed");
else
- color = get_color("font_color");
- if (has_color("icon_color_pressed"))
- color_icon = get_color("icon_color_pressed");
+ color = get_theme_color("font_color");
+ if (has_theme_color("icon_color_pressed"))
+ color_icon = get_theme_color("icon_color_pressed");
} break;
case DRAW_HOVER: {
- style = get_stylebox("hover");
+ style = get_theme_stylebox("hover");
if (!flat)
style->draw(ci, Rect2(Point2(0, 0), size));
- color = get_color("font_color_hover");
- if (has_color("icon_color_hover"))
- color_icon = get_color("icon_color_hover");
+ color = get_theme_color("font_color_hover");
+ if (has_theme_color("icon_color_hover"))
+ color_icon = get_theme_color("icon_color_hover");
} break;
case DRAW_DISABLED: {
- style = get_stylebox("disabled");
+ style = get_theme_stylebox("disabled");
if (!flat)
style->draw(ci, Rect2(Point2(0, 0), size));
- color = get_color("font_color_disabled");
- if (has_color("icon_color_disabled"))
- color_icon = get_color("icon_color_disabled");
+ color = get_theme_color("font_color_disabled");
+ if (has_theme_color("icon_color_disabled"))
+ color_icon = get_theme_color("icon_color_disabled");
} break;
}
if (has_focus()) {
- Ref<StyleBox> style2 = get_stylebox("focus");
+ Ref<StyleBox> style2 = get_theme_stylebox("focus");
style2->draw(ci, Rect2(Point2(), size));
}
- Ref<Font> font = get_font("font");
+ Ref<Font> font = get_theme_font("font");
Ref<Texture2D> _icon;
- if (icon.is_null() && has_icon("icon"))
- _icon = Control::get_icon("icon");
+ if (icon.is_null() && has_theme_icon("icon"))
+ _icon = Control::get_theme_icon("icon");
else
_icon = icon;
@@ -166,14 +166,14 @@ void Button::_notification(int p_what) {
float icon_ofs_region = 0;
if (_internal_margin[MARGIN_LEFT] > 0) {
- icon_ofs_region = _internal_margin[MARGIN_LEFT] + get_constant("hseparation");
+ icon_ofs_region = _internal_margin[MARGIN_LEFT] + get_theme_constant("hseparation");
}
if (expand_icon) {
Size2 _size = get_size() - style->get_offset() * 2;
- _size.width -= get_constant("hseparation") + icon_ofs_region;
+ _size.width -= get_theme_constant("hseparation") + icon_ofs_region;
if (!clip_text)
- _size.width -= get_font("font")->get_string_size(xl_text).width;
+ _size.width -= get_theme_font("font")->get_string_size(xl_text).width;
float icon_width = _icon->get_width() * _size.height / _icon->get_height();
float icon_height = _size.height;
@@ -188,13 +188,13 @@ void Button::_notification(int p_what) {
}
}
- Point2 icon_ofs = !_icon.is_null() ? Point2(icon_region.size.width + get_constant("hseparation"), 0) : Point2();
+ Point2 icon_ofs = !_icon.is_null() ? Point2(icon_region.size.width + get_theme_constant("hseparation"), 0) : Point2();
int text_clip = size.width - style->get_minimum_size().width - icon_ofs.width;
if (_internal_margin[MARGIN_LEFT] > 0) {
- text_clip -= _internal_margin[MARGIN_LEFT] + get_constant("hseparation");
+ text_clip -= _internal_margin[MARGIN_LEFT] + get_theme_constant("hseparation");
}
if (_internal_margin[MARGIN_RIGHT] > 0) {
- text_clip -= _internal_margin[MARGIN_RIGHT] + get_constant("hseparation");
+ text_clip -= _internal_margin[MARGIN_RIGHT] + get_theme_constant("hseparation");
}
Point2 text_ofs = (size - style->get_minimum_size() - icon_ofs - font->get_string_size(xl_text) - Point2(_internal_margin[MARGIN_RIGHT] - _internal_margin[MARGIN_LEFT], 0)) / 2.0;
@@ -202,7 +202,7 @@ void Button::_notification(int p_what) {
switch (align) {
case ALIGN_LEFT: {
if (_internal_margin[MARGIN_LEFT] > 0) {
- text_ofs.x = style->get_margin(MARGIN_LEFT) + icon_ofs.x + _internal_margin[MARGIN_LEFT] + get_constant("hseparation");
+ text_ofs.x = style->get_margin(MARGIN_LEFT) + icon_ofs.x + _internal_margin[MARGIN_LEFT] + get_theme_constant("hseparation");
} else {
text_ofs.x = style->get_margin(MARGIN_LEFT) + icon_ofs.x;
}
@@ -216,7 +216,7 @@ void Button::_notification(int p_what) {
} break;
case ALIGN_RIGHT: {
if (_internal_margin[MARGIN_RIGHT] > 0) {
- text_ofs.x = size.x - style->get_margin(MARGIN_RIGHT) - font->get_string_size(xl_text).x - _internal_margin[MARGIN_RIGHT] - get_constant("hseparation");
+ text_ofs.x = size.x - style->get_margin(MARGIN_RIGHT) - font->get_string_size(xl_text).x - _internal_margin[MARGIN_RIGHT] - get_theme_constant("hseparation");
} else {
text_ofs.x = size.x - style->get_margin(MARGIN_RIGHT) - font->get_string_size(xl_text).x;
}
diff --git a/scene/gui/check_box.cpp b/scene/gui/check_box.cpp
index 89bd8ab0dd..d68bd4fe4e 100644
--- a/scene/gui/check_box.cpp
+++ b/scene/gui/check_box.cpp
@@ -33,10 +33,10 @@
#include "servers/visual_server.h"
Size2 CheckBox::get_icon_size() const {
- Ref<Texture2D> checked = Control::get_icon("checked");
- Ref<Texture2D> unchecked = Control::get_icon("unchecked");
- Ref<Texture2D> radio_checked = Control::get_icon("radio_checked");
- Ref<Texture2D> radio_unchecked = Control::get_icon("radio_unchecked");
+ Ref<Texture2D> checked = Control::get_theme_icon("checked");
+ Ref<Texture2D> unchecked = Control::get_theme_icon("unchecked");
+ Ref<Texture2D> radio_checked = Control::get_theme_icon("radio_checked");
+ Ref<Texture2D> radio_unchecked = Control::get_theme_icon("radio_unchecked");
Size2 tex_size = Size2(0, 0);
if (!checked.is_null())
@@ -56,9 +56,9 @@ Size2 CheckBox::get_minimum_size() const {
Size2 tex_size = get_icon_size();
minsize.width += tex_size.width;
if (get_text().length() > 0) {
- minsize.width += get_constant("hseparation");
+ minsize.width += get_theme_constant("hseparation");
}
- Ref<StyleBox> sb = get_stylebox("normal");
+ Ref<StyleBox> sb = get_theme_stylebox("normal");
minsize.height = MAX(minsize.height, tex_size.height + sb->get_margin(MARGIN_TOP) + sb->get_margin(MARGIN_BOTTOM));
return minsize;
@@ -73,13 +73,13 @@ void CheckBox::_notification(int p_what) {
RID ci = get_canvas_item();
- Ref<Texture2D> on = Control::get_icon(is_radio() ? "radio_checked" : "checked");
- Ref<Texture2D> off = Control::get_icon(is_radio() ? "radio_unchecked" : "unchecked");
- Ref<StyleBox> sb = get_stylebox("normal");
+ Ref<Texture2D> on = Control::get_theme_icon(is_radio() ? "radio_checked" : "checked");
+ Ref<Texture2D> off = Control::get_theme_icon(is_radio() ? "radio_unchecked" : "unchecked");
+ Ref<StyleBox> sb = get_theme_stylebox("normal");
Vector2 ofs;
ofs.x = sb->get_margin(MARGIN_LEFT);
- ofs.y = int((get_size().height - get_icon_size().height) / 2) + get_constant("check_vadjust");
+ ofs.y = int((get_size().height - get_icon_size().height) / 2) + get_theme_constant("check_vadjust");
if (is_pressed())
on->draw(ci, ofs);
diff --git a/scene/gui/check_button.cpp b/scene/gui/check_button.cpp
index 0b093ce850..ac967a128c 100644
--- a/scene/gui/check_button.cpp
+++ b/scene/gui/check_button.cpp
@@ -35,8 +35,8 @@
Size2 CheckButton::get_icon_size() const {
- Ref<Texture2D> on = Control::get_icon(is_disabled() ? "on_disabled" : "on");
- Ref<Texture2D> off = Control::get_icon(is_disabled() ? "off_disabled" : "off");
+ Ref<Texture2D> on = Control::get_theme_icon(is_disabled() ? "on_disabled" : "on");
+ Ref<Texture2D> off = Control::get_theme_icon(is_disabled() ? "off_disabled" : "off");
Size2 tex_size = Size2(0, 0);
if (!on.is_null())
tex_size = Size2(on->get_width(), on->get_height());
@@ -52,8 +52,8 @@ Size2 CheckButton::get_minimum_size() const {
Size2 tex_size = get_icon_size();
minsize.width += tex_size.width;
if (get_text().length() > 0)
- minsize.width += get_constant("hseparation");
- Ref<StyleBox> sb = get_stylebox("normal");
+ minsize.width += get_theme_constant("hseparation");
+ Ref<StyleBox> sb = get_theme_stylebox("normal");
minsize.height = MAX(minsize.height, tex_size.height + sb->get_margin(MARGIN_TOP) + sb->get_margin(MARGIN_BOTTOM));
return minsize;
@@ -68,15 +68,15 @@ void CheckButton::_notification(int p_what) {
RID ci = get_canvas_item();
- Ref<Texture2D> on = Control::get_icon(is_disabled() ? "on_disabled" : "on");
- Ref<Texture2D> off = Control::get_icon(is_disabled() ? "off_disabled" : "off");
+ Ref<Texture2D> on = Control::get_theme_icon(is_disabled() ? "on_disabled" : "on");
+ Ref<Texture2D> off = Control::get_theme_icon(is_disabled() ? "off_disabled" : "off");
- Ref<StyleBox> sb = get_stylebox("normal");
+ Ref<StyleBox> sb = get_theme_stylebox("normal");
Vector2 ofs;
Size2 tex_size = get_icon_size();
ofs.x = get_size().width - (tex_size.width + sb->get_margin(MARGIN_RIGHT));
- ofs.y = (get_size().height - tex_size.height) / 2 + get_constant("check_vadjust");
+ ofs.y = (get_size().height - tex_size.height) / 2 + get_theme_constant("check_vadjust");
if (is_pressed())
on->draw(ci, ofs);
diff --git a/scene/gui/color_picker.cpp b/scene/gui/color_picker.cpp
index a8b5ac6909..2ec9bb2292 100644
--- a/scene/gui/color_picker.cpp
+++ b/scene/gui/color_picker.cpp
@@ -30,7 +30,7 @@
#include "color_picker.h"
-#include "core/os/input.h"
+#include "core/input/input_filter.h"
#include "core/os/keyboard.h"
#include "core/os/os.h"
@@ -38,22 +38,22 @@
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#endif
-#include "scene/main/viewport.h"
+#include "scene/main/window.h"
void ColorPicker::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_THEME_CHANGED: {
- btn_pick->set_icon(get_icon("screen_picker", "ColorPicker"));
- bt_add_preset->set_icon(get_icon("add_preset"));
+ btn_pick->set_icon(get_theme_icon("screen_picker", "ColorPicker"));
+ bt_add_preset->set_icon(get_theme_icon("add_preset"));
_update_controls();
} break;
case NOTIFICATION_ENTER_TREE: {
- btn_pick->set_icon(get_icon("screen_picker", "ColorPicker"));
- bt_add_preset->set_icon(get_icon("add_preset"));
+ btn_pick->set_icon(get_theme_icon("screen_picker", "ColorPicker"));
+ bt_add_preset->set_icon(get_theme_icon("add_preset"));
_update_color();
@@ -70,15 +70,15 @@ void ColorPicker::_notification(int p_what) {
case NOTIFICATION_PARENTED: {
for (int i = 0; i < 4; i++)
- set_margin((Margin)i, get_constant("margin"));
+ set_margin((Margin)i, get_theme_constant("margin"));
} break;
case NOTIFICATION_VISIBILITY_CHANGED: {
Popup *p = Object::cast_to<Popup>(get_parent());
if (p)
- p->set_size(Size2(get_combined_minimum_size().width + get_constant("margin") * 2, get_combined_minimum_size().height + get_constant("margin") * 2));
+ p->set_size(Size2(get_combined_minimum_size().width + get_theme_constant("margin") * 2, get_combined_minimum_size().height + get_theme_constant("margin") * 2));
} break;
- case MainLoop::NOTIFICATION_WM_QUIT_REQUEST: {
+ case NOTIFICATION_WM_CLOSE_REQUEST: {
if (screen != NULL && screen->is_visible())
screen->hide();
@@ -247,6 +247,9 @@ void ColorPicker::_update_color(bool p_update_sliders) {
}
void ColorPicker::_update_presets() {
+ return;
+ //presets should be shown using buttons or something else, this method is not a good idea
+
presets_per_row = 10;
Size2 size = bt_add_preset->get_size();
Size2 preset_size = Size2(MIN(size.width * presets.size(), presets_per_row * size.width), size.height * (Math::ceil((float)presets.size() / presets_per_row)));
@@ -267,7 +270,7 @@ void ColorPicker::_text_type_toggled() {
text_is_constructor = !text_is_constructor;
if (text_is_constructor) {
text_type->set_text("");
- text_type->set_icon(get_icon("Script", "EditorIcons"));
+ text_type->set_icon(get_theme_icon("Script", "EditorIcons"));
c_text->set_editable(false);
} else {
@@ -399,14 +402,14 @@ void ColorPicker::_sample_draw() {
const Rect2 r = Rect2(Point2(), Size2(uv_edit->get_size().width, sample->get_size().height * 0.95));
if (color.a < 1.0) {
- sample->draw_texture_rect(get_icon("preset_bg", "ColorPicker"), r, true);
+ sample->draw_texture_rect(get_theme_icon("preset_bg", "ColorPicker"), r, true);
}
sample->draw_rect(r, color);
if (color.r > 1 || color.g > 1 || color.b > 1) {
// Draw an indicator to denote that the color is "overbright" and can't be displayed accurately in the preview
- sample->draw_texture(get_icon("overbright_indicator", "ColorPicker"), Point2());
+ sample->draw_texture(get_theme_icon("overbright_indicator", "ColorPicker"), Point2());
}
}
@@ -445,7 +448,7 @@ void ColorPicker::_hsv_draw(int p_which, Control *c) {
c->draw_line(Point2(0, y), Point2(c->get_size().x, y), col.inverted());
c->draw_line(Point2(x, y), Point2(x, y), Color(1, 1, 1), 2);
} else if (p_which == 1) {
- Ref<Texture2D> hue = get_icon("color_hue", "ColorPicker");
+ Ref<Texture2D> hue = get_theme_icon("color_hue", "ColorPicker");
c->draw_texture_rect(hue, Rect2(Point2(), c->get_size()));
int y = c->get_size().y - c->get_size().y * (1.0 - h);
Color col = Color();
@@ -620,7 +623,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() {
@@ -738,12 +744,12 @@ ColorPicker::ColorPicker() :
uv_edit->set_mouse_filter(MOUSE_FILTER_PASS);
uv_edit->set_h_size_flags(SIZE_EXPAND_FILL);
uv_edit->set_v_size_flags(SIZE_EXPAND_FILL);
- uv_edit->set_custom_minimum_size(Size2(get_constant("sv_width"), get_constant("sv_height")));
+ uv_edit->set_custom_minimum_size(Size2(get_theme_constant("sv_width"), get_theme_constant("sv_height")));
uv_edit->connect("draw", callable_mp(this, &ColorPicker::_hsv_draw), make_binds(0, uv_edit));
w_edit = memnew(Control);
hb_edit->add_child(w_edit);
- w_edit->set_custom_minimum_size(Size2(get_constant("h_width"), 0));
+ w_edit->set_custom_minimum_size(Size2(get_theme_constant("h_width"), 0));
w_edit->set_h_size_flags(SIZE_FILL);
w_edit->set_v_size_flags(SIZE_EXPAND_FILL);
w_edit->connect("gui_input", callable_mp(this, &ColorPicker::_w_input));
@@ -777,7 +783,7 @@ ColorPicker::ColorPicker() :
HBoxContainer *hbc = memnew(HBoxContainer);
labels[i] = memnew(Label());
- labels[i]->set_custom_minimum_size(Size2(get_constant("label_width"), 0));
+ labels[i]->set_custom_minimum_size(Size2(get_theme_constant("label_width"), 0));
labels[i]->set_v_size_flags(SIZE_SHRINK_CENTER);
hbc->add_child(labels[i]);
@@ -881,8 +887,32 @@ void ColorPickerButton::_modal_closed() {
void ColorPickerButton::pressed() {
_update_picker();
- popup->set_position(get_global_position() - picker->get_combined_minimum_size() * get_global_transform().get_scale());
- popup->set_scale(get_global_transform().get_scale());
+
+ popup->set_as_minsize();
+
+ Rect2i usable_rect = popup->get_usable_parent_rect();
+ //let's try different positions to see which one we can use
+
+ Rect2i cp_rect(Point2i(), popup->get_size());
+ for (int i = 0; i < 4; i++) {
+ if (i > 1) {
+ cp_rect.position.y = get_screen_position().y - cp_rect.size.y;
+ } else {
+ cp_rect.position.y = get_screen_position().y + get_size().height;
+ }
+
+ if (i & 1) {
+ cp_rect.position.x = get_screen_position().x;
+ } else {
+
+ cp_rect.position.x = get_screen_position().x - MAX(0, (cp_rect.size.x - get_size().x));
+ }
+
+ if (usable_rect.encloses(cp_rect)) {
+ break;
+ }
+ }
+ popup->set_position(cp_rect.position);
popup->popup();
picker->set_focus_on_line_edit();
}
@@ -892,17 +922,17 @@ void ColorPickerButton::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_DRAW: {
- const Ref<StyleBox> normal = get_stylebox("normal");
+ const Ref<StyleBox> normal = get_theme_stylebox("normal");
const Rect2 r = Rect2(normal->get_offset(), get_size() - normal->get_minimum_size());
- draw_texture_rect(Control::get_icon("bg", "ColorPickerButton"), r, true);
+ draw_texture_rect(Control::get_theme_icon("bg", "ColorPickerButton"), r, true);
draw_rect(r, color);
if (color.r > 1 || color.g > 1 || color.b > 1) {
// Draw an indicator to denote that the color is "overbright" and can't be displayed accurately in the preview
- draw_texture(Control::get_icon("overbright_indicator", "ColorPicker"), normal->get_offset());
+ draw_texture(Control::get_theme_icon("overbright_indicator", "ColorPicker"), normal->get_offset());
}
} break;
- case MainLoop::NOTIFICATION_WM_QUIT_REQUEST: {
+ case NOTIFICATION_WM_CLOSE_REQUEST: {
if (popup)
popup->hide();
@@ -958,12 +988,14 @@ PopupPanel *ColorPickerButton::get_popup() {
void ColorPickerButton::_update_picker() {
if (!picker) {
popup = memnew(PopupPanel);
+ popup->set_wrap_controls(true);
picker = memnew(ColorPicker);
+ picker->set_anchors_and_margins_preset(PRESET_WIDE);
popup->add_child(picker);
add_child(popup);
picker->connect("color_changed", callable_mp(this, &ColorPickerButton::_color_changed));
popup->connect("modal_closed", callable_mp(this, &ColorPickerButton::_modal_closed));
- popup->connect("about_to_show", callable_mp((BaseButton *)this, &BaseButton::set_pressed), varray(true));
+ popup->connect("about_to_popup", callable_mp((BaseButton *)this, &BaseButton::set_pressed), varray(true));
popup->connect("popup_hide", callable_mp((BaseButton *)this, &BaseButton::set_pressed), varray(false));
picker->set_pick_color(color);
picker->set_edit_alpha(edit_alpha);
diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp
index 1a231e368b..14bca0e2c8 100644
--- a/scene/gui/control.cpp
+++ b/scene/gui/control.cpp
@@ -38,7 +38,7 @@
#include "scene/gui/label.h"
#include "scene/gui/panel.h"
#include "scene/main/canvas_layer.h"
-#include "scene/main/viewport.h"
+#include "scene/main/window.h"
#include "scene/scene_string_names.h"
#include "servers/visual_server.h"
@@ -260,22 +260,22 @@ bool Control::_set(const StringName &p_name, const Variant &p_value) {
} else {
if (name.begins_with("custom_icons/")) {
String dname = name.get_slicec('/', 1);
- add_icon_override(dname, p_value);
+ add_theme_icon_override(dname, p_value);
} else if (name.begins_with("custom_shaders/")) {
String dname = name.get_slicec('/', 1);
- add_shader_override(dname, p_value);
+ add_theme_shader_override(dname, p_value);
} else if (name.begins_with("custom_styles/")) {
String dname = name.get_slicec('/', 1);
- add_style_override(dname, p_value);
+ add_theme_style_override(dname, p_value);
} else if (name.begins_with("custom_fonts/")) {
String dname = name.get_slicec('/', 1);
- add_font_override(dname, p_value);
+ add_theme_font_override(dname, p_value);
} else if (name.begins_with("custom_colors/")) {
String dname = name.get_slicec('/', 1);
- add_color_override(dname, p_value);
+ add_theme_color_override(dname, p_value);
} else if (name.begins_with("custom_constants/")) {
String dname = name.get_slicec('/', 1);
- add_constant_override(dname, p_value);
+ add_theme_constant_override(dname, p_value);
} else
return false;
}
@@ -438,22 +438,30 @@ void Control::_resize(const Size2 &p_size) {
void Control::add_child_notify(Node *p_child) {
Control *child_c = Object::cast_to<Control>(p_child);
- if (!child_c)
- return;
- if (child_c->data.theme.is_null() && data.theme_owner) {
- _propagate_theme_changed(child_c, data.theme_owner); //need to propagate here, since many controls may require setting up stuff
+ if (child_c && child_c->data.theme.is_null() && (data.theme_owner || data.theme_owner_window)) {
+ _propagate_theme_changed(child_c, data.theme_owner, data.theme_owner_window); //need to propagate here, since many controls may require setting up stuff
+ }
+
+ Window *child_w = Object::cast_to<Window>(p_child);
+
+ if (child_w && child_w->theme.is_null() && (data.theme_owner || data.theme_owner_window)) {
+ _propagate_theme_changed(child_w, data.theme_owner, data.theme_owner_window); //need to propagate here, since many controls may require setting up stuff
}
}
void Control::remove_child_notify(Node *p_child) {
Control *child_c = Object::cast_to<Control>(p_child);
- if (!child_c)
- return;
- if (child_c->data.theme_owner && child_c->data.theme.is_null()) {
- _propagate_theme_changed(child_c, NULL);
+ if (child_c && (child_c->data.theme_owner || child_c->data.theme_owner_window) && child_c->data.theme.is_null()) {
+ _propagate_theme_changed(child_c, NULL, NULL);
+ }
+
+ Window *child_w = Object::cast_to<Window>(p_child);
+
+ if (child_w && (child_w->theme_owner || child_w->theme_owner_window) && child_w->theme.is_null()) {
+ _propagate_theme_changed(child_w, NULL, NULL);
}
}
@@ -486,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);
-
- if (data.theme.is_null() && data.parent && data.parent->data.theme_owner) {
- data.theme_owner = data.parent->data.theme_owner;
- notification(NOTIFICATION_THEME_CHANGED);
- }
-
- } else {
-
- Node *parent = this; //meh
- Control *parent_control = NULL;
- bool subwindow = false;
+ 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;
- }
+ while (parent) {
- parent_control = Object::cast_to<Control>(parent);
+ parent = parent->get_parent();
- if (parent_control) {
- break;
- } else if (ci) {
+ if (!parent)
+ break;
- } else {
- break;
- }
+ CanvasItem *ci = Object::cast_to<CanvasItem>(parent);
+ if (ci && ci->is_set_as_toplevel()) {
+ subwindow = true;
+ break;
}
- 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);
- } else {
- //is a regular root control
- data.RI = get_viewport()->_gui_add_root_control(this);
- }
+ parent_control = Object::cast_to<Control>(parent);
- data.parent_canvas_item = get_parent_item();
-
- if (data.parent_canvas_item) {
+ if (parent_control) {
+ break;
+ } else if (ci) {
- 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: {
@@ -568,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;
@@ -600,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();
}
@@ -644,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()) {
@@ -655,23 +624,14 @@ 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 {
data.minimum_size_valid = false;
_size_changed();
}
} break;
- case SceneTree::NOTIFICATION_WM_UNFOCUS_REQUEST: {
-
- get_viewport()->_gui_unfocus_control(this);
-
- } break;
}
}
@@ -787,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();
@@ -813,50 +760,130 @@ Size2 Control::get_minimum_size() const {
return Size2();
}
-Ref<Texture2D> Control::get_icon(const StringName &p_name, const StringName &p_type) const {
+template <class T>
+bool Control::_find_theme_item(Control *p_theme_owner, Window *p_theme_owner_window, T &r_ret, T (Theme::*get_func)(const StringName &, const StringName &) const, bool (Theme::*has_func)(const StringName &, const StringName &) const, const StringName &p_name, const StringName &p_type) {
- if (p_type == StringName() || p_type == get_class_name()) {
+ // try with custom themes
+ Control *theme_owner = p_theme_owner;
+ Window *theme_owner_window = p_theme_owner_window;
- const Ref<Texture2D> *tex = data.icon_override.getptr(p_name);
- if (tex)
- return *tex;
+ while (theme_owner || theme_owner_window) {
+
+ StringName class_name = p_type;
+
+ while (class_name != StringName()) {
+ if (theme_owner && (theme_owner->data.theme.operator->()->*has_func)(p_name, class_name)) {
+ r_ret = (theme_owner->data.theme.operator->()->*get_func)(p_name, class_name);
+ return true;
+ }
+
+ if (theme_owner_window && (theme_owner_window->theme.operator->()->*has_func)(p_name, class_name)) {
+ r_ret = (theme_owner_window->theme.operator->()->*get_func)(p_name, class_name);
+ return true;
+ }
+
+ class_name = ClassDB::get_parent_class_nocheck(class_name);
+ }
+
+ Node *parent = theme_owner ? theme_owner->get_parent() : theme_owner_window->get_parent();
+
+ Control *parent_c = Object::cast_to<Control>(parent);
+
+ if (parent_c) {
+ theme_owner = parent_c->data.theme_owner;
+ theme_owner_window = parent_c->data.theme_owner_window;
+ } else {
+ Window *parent_w = Object::cast_to<Window>(parent);
+ if (parent_w) {
+ theme_owner = parent_w->theme_owner;
+ theme_owner_window = parent_w->theme_owner_window;
+ } else {
+
+ theme_owner = NULL;
+ theme_owner_window = NULL;
+ }
+ }
}
+ return false;
+}
- StringName type = p_type ? p_type : get_class_name();
+bool Control::_has_theme_item(Control *p_theme_owner, Window *p_theme_owner_window, bool (Theme::*has_func)(const StringName &, const StringName &) const, const StringName &p_name, const StringName &p_type) {
// try with custom themes
- Control *theme_owner = data.theme_owner;
+ Control *theme_owner = p_theme_owner;
+ Window *theme_owner_window = p_theme_owner_window;
- while (theme_owner) {
+ while (theme_owner || theme_owner_window) {
- StringName class_name = type;
+ StringName class_name = p_type;
while (class_name != StringName()) {
- if (theme_owner->data.theme->has_icon(p_name, class_name)) {
- return theme_owner->data.theme->get_icon(p_name, class_name);
+ if (theme_owner && (theme_owner->data.theme.operator->()->*has_func)(p_name, class_name)) {
+ return true;
+ }
+
+ if (theme_owner_window && (theme_owner_window->theme.operator->()->*has_func)(p_name, class_name)) {
+ return true;
}
class_name = ClassDB::get_parent_class_nocheck(class_name);
}
- Control *parent = Object::cast_to<Control>(theme_owner->get_parent());
+ Node *parent = theme_owner ? theme_owner->get_parent() : theme_owner_window->get_parent();
+
+ Control *parent_c = Object::cast_to<Control>(parent);
+
+ if (parent_c) {
+ theme_owner = parent_c->data.theme_owner;
+ theme_owner_window = parent_c->data.theme_owner_window;
+ } else {
+ Window *parent_w = Object::cast_to<Window>(parent);
+ if (parent_w) {
+ theme_owner = parent_w->theme_owner;
+ theme_owner_window = parent_w->theme_owner_window;
+ } else {
+
+ theme_owner = NULL;
+ theme_owner_window = NULL;
+ }
+ }
+ }
+ return false;
+}
+
+Ref<Texture2D> Control::get_theme_icon(const StringName &p_name, const StringName &p_type) const {
+
+ if (p_type == StringName() || p_type == get_class_name()) {
+
+ const Ref<Texture2D> *tex = data.icon_override.getptr(p_name);
+ if (tex)
+ return *tex;
+ }
+
+ StringName type = p_type ? p_type : get_class_name();
- if (parent)
- theme_owner = parent->data.theme_owner;
- else
- theme_owner = NULL;
+ return get_icons(data.theme_owner, data.theme_owner_window, p_name, type);
+}
+
+Ref<Texture2D> Control::get_icons(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_type) {
+
+ Ref<Texture2D> icon;
+
+ if (_find_theme_item(p_theme_owner, p_theme_owner_window, icon, &Theme::get_icon, &Theme::has_icon, p_name, p_type)) {
+ return icon;
}
if (Theme::get_project_default().is_valid()) {
- if (Theme::get_project_default()->has_icon(p_name, type)) {
- return Theme::get_project_default()->get_icon(p_name, type);
+ if (Theme::get_project_default()->has_icon(p_name, p_type)) {
+ return Theme::get_project_default()->get_icon(p_name, p_type);
}
}
- return Theme::get_default()->get_icon(p_name, type);
+ return Theme::get_default()->get_icon(p_name, p_type);
}
-Ref<Shader> Control::get_shader(const StringName &p_name, const StringName &p_type) const {
+Ref<Shader> Control::get_theme_shader(const StringName &p_name, const StringName &p_type) const {
+
if (p_type == StringName() || p_type == get_class_name()) {
const Ref<Shader> *sdr = data.shader_override.getptr(p_name);
@@ -866,39 +893,27 @@ Ref<Shader> Control::get_shader(const StringName &p_name, const StringName &p_ty
StringName type = p_type ? p_type : get_class_name();
- // try with custom themes
- Control *theme_owner = data.theme_owner;
-
- while (theme_owner) {
-
- StringName class_name = type;
-
- while (class_name != StringName()) {
- if (theme_owner->data.theme->has_shader(p_name, class_name)) {
- return theme_owner->data.theme->get_shader(p_name, class_name);
- }
+ return get_shaders(data.theme_owner, data.theme_owner_window, p_name, type);
+}
- class_name = ClassDB::get_parent_class_nocheck(class_name);
- }
+Ref<Shader> Control::get_shaders(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_type) {
- Control *parent = Object::cast_to<Control>(theme_owner->get_parent());
+ Ref<Shader> shader;
- if (parent)
- theme_owner = parent->data.theme_owner;
- else
- theme_owner = NULL;
+ if (_find_theme_item(p_theme_owner, p_theme_owner_window, shader, &Theme::get_shader, &Theme::has_shader, p_name, p_type)) {
+ return shader;
}
if (Theme::get_project_default().is_valid()) {
- if (Theme::get_project_default()->has_shader(p_name, type)) {
- return Theme::get_project_default()->get_shader(p_name, type);
+ if (Theme::get_project_default()->has_shader(p_name, p_type)) {
+ return Theme::get_project_default()->get_shader(p_name, p_type);
}
}
- return Theme::get_default()->get_shader(p_name, type);
+ return Theme::get_default()->get_shader(p_name, p_type);
}
-Ref<StyleBox> Control::get_stylebox(const StringName &p_name, const StringName &p_type) const {
+Ref<StyleBox> Control::get_theme_stylebox(const StringName &p_name, const StringName &p_type) const {
if (p_type == StringName() || p_type == get_class_name()) {
const Ref<StyleBox> *style = data.style_override.getptr(p_name);
@@ -908,43 +923,27 @@ Ref<StyleBox> Control::get_stylebox(const StringName &p_name, const StringName &
StringName type = p_type ? p_type : get_class_name();
- // try with custom themes
- Control *theme_owner = data.theme_owner;
+ return get_styleboxs(data.theme_owner, data.theme_owner_window, p_name, type);
+}
- StringName class_name = type;
+Ref<StyleBox> Control::get_styleboxs(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_type) {
- while (theme_owner) {
+ Ref<StyleBox> stylebox;
- while (class_name != StringName()) {
- if (theme_owner->data.theme->has_stylebox(p_name, class_name)) {
- return theme_owner->data.theme->get_stylebox(p_name, class_name);
- }
+ if (_find_theme_item(p_theme_owner, p_theme_owner_window, stylebox, &Theme::get_stylebox, &Theme::has_stylebox, p_name, p_type)) {
+ return stylebox;
+ }
- class_name = ClassDB::get_parent_class_nocheck(class_name);
+ if (Theme::get_project_default().is_valid()) {
+ if (Theme::get_project_default()->has_stylebox(p_name, p_type)) {
+ return Theme::get_project_default()->get_stylebox(p_name, p_type);
}
-
- class_name = type;
-
- Control *parent = Object::cast_to<Control>(theme_owner->get_parent());
-
- if (parent)
- theme_owner = parent->data.theme_owner;
- else
- theme_owner = NULL;
}
- while (class_name != StringName()) {
- if (Theme::get_project_default().is_valid() && Theme::get_project_default()->has_stylebox(p_name, type))
- return Theme::get_project_default()->get_stylebox(p_name, type);
-
- if (Theme::get_default()->has_stylebox(p_name, class_name))
- return Theme::get_default()->get_stylebox(p_name, class_name);
-
- class_name = ClassDB::get_parent_class_nocheck(class_name);
- }
- return Theme::get_default()->get_stylebox(p_name, type);
+ return Theme::get_default()->get_stylebox(p_name, p_type);
}
-Ref<Font> Control::get_font(const StringName &p_name, const StringName &p_type) const {
+
+Ref<Font> Control::get_theme_font(const StringName &p_name, const StringName &p_type) const {
if (p_type == StringName() || p_type == get_class_name()) {
const Ref<Font> *font = data.font_override.getptr(p_name);
@@ -954,34 +953,27 @@ Ref<Font> Control::get_font(const StringName &p_name, const StringName &p_type)
StringName type = p_type ? p_type : get_class_name();
- // try with custom themes
- Control *theme_owner = data.theme_owner;
+ return get_fonts(data.theme_owner, data.theme_owner_window, p_name, type);
+}
- while (theme_owner) {
+Ref<Font> Control::get_fonts(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_type) {
- StringName class_name = type;
+ Ref<Font> font;
- while (class_name != StringName()) {
- if (theme_owner->data.theme->has_font(p_name, class_name)) {
- return theme_owner->data.theme->get_font(p_name, class_name);
- }
+ if (_find_theme_item(p_theme_owner, p_theme_owner_window, font, &Theme::get_font, &Theme::has_font, p_name, p_type)) {
+ return font;
+ }
- class_name = ClassDB::get_parent_class_nocheck(class_name);
+ if (Theme::get_project_default().is_valid()) {
+ if (Theme::get_project_default()->has_font(p_name, p_type)) {
+ return Theme::get_project_default()->get_font(p_name, p_type);
}
-
- if (theme_owner->data.theme->get_default_theme_font().is_valid())
- return theme_owner->data.theme->get_default_theme_font();
- Control *parent = Object::cast_to<Control>(theme_owner->get_parent());
-
- if (parent)
- theme_owner = parent->data.theme_owner;
- else
- theme_owner = NULL;
}
- return Theme::get_default()->get_font(p_name, type);
+ return Theme::get_default()->get_font(p_name, p_type);
}
-Color Control::get_color(const StringName &p_name, const StringName &p_type) const {
+
+Color Control::get_theme_color(const StringName &p_name, const StringName &p_type) const {
if (p_type == StringName() || p_type == get_class_name()) {
const Color *color = data.color_override.getptr(p_name);
@@ -990,38 +982,27 @@ Color Control::get_color(const StringName &p_name, const StringName &p_type) con
}
StringName type = p_type ? p_type : get_class_name();
- // try with custom themes
- Control *theme_owner = data.theme_owner;
-
- while (theme_owner) {
- StringName class_name = type;
+ return get_colors(data.theme_owner, data.theme_owner_window, p_name, type);
+}
- while (class_name != StringName()) {
- if (theme_owner->data.theme->has_color(p_name, class_name)) {
- return theme_owner->data.theme->get_color(p_name, class_name);
- }
+Color Control::get_colors(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_type) {
- class_name = ClassDB::get_parent_class_nocheck(class_name);
- }
+ Color color;
- Control *parent = Object::cast_to<Control>(theme_owner->get_parent());
-
- if (parent)
- theme_owner = parent->data.theme_owner;
- else
- theme_owner = NULL;
+ if (_find_theme_item(p_theme_owner, p_theme_owner_window, color, &Theme::get_color, &Theme::has_color, p_name, p_type)) {
+ return color;
}
if (Theme::get_project_default().is_valid()) {
- if (Theme::get_project_default()->has_color(p_name, type)) {
- return Theme::get_project_default()->get_color(p_name, type);
+ if (Theme::get_project_default()->has_color(p_name, p_type)) {
+ return Theme::get_project_default()->get_color(p_name, p_type);
}
}
- return Theme::get_default()->get_color(p_name, type);
+ return Theme::get_default()->get_color(p_name, p_type);
}
-int Control::get_constant(const StringName &p_name, const StringName &p_type) const {
+int Control::get_theme_constant(const StringName &p_name, const StringName &p_type) const {
if (p_type == StringName() || p_type == get_class_name()) {
const int *constant = data.constant_override.getptr(p_name);
@@ -1030,303 +1011,213 @@ int Control::get_constant(const StringName &p_name, const StringName &p_type) co
}
StringName type = p_type ? p_type : get_class_name();
- // try with custom themes
- Control *theme_owner = data.theme_owner;
-
- while (theme_owner) {
-
- StringName class_name = type;
- while (class_name != StringName()) {
- if (theme_owner->data.theme->has_constant(p_name, class_name)) {
- return theme_owner->data.theme->get_constant(p_name, class_name);
- }
+ return get_constants(data.theme_owner, data.theme_owner_window, p_name, type);
+}
- class_name = ClassDB::get_parent_class_nocheck(class_name);
- }
+int Control::get_constants(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_type) {
- Control *parent = Object::cast_to<Control>(theme_owner->get_parent());
+ int constant;
- if (parent)
- theme_owner = parent->data.theme_owner;
- else
- theme_owner = NULL;
+ if (_find_theme_item(p_theme_owner, p_theme_owner_window, constant, &Theme::get_constant, &Theme::has_constant, p_name, p_type)) {
+ return constant;
}
if (Theme::get_project_default().is_valid()) {
- if (Theme::get_project_default()->has_constant(p_name, type)) {
- return Theme::get_project_default()->get_constant(p_name, type);
+ if (Theme::get_project_default()->has_constant(p_name, p_type)) {
+ return Theme::get_project_default()->get_constant(p_name, p_type);
}
}
- return Theme::get_default()->get_constant(p_name, type);
+ return Theme::get_default()->get_constant(p_name, p_type);
}
-bool Control::has_icon_override(const StringName &p_name) const {
+bool Control::has_theme_icon_override(const StringName &p_name) const {
const Ref<Texture2D> *tex = data.icon_override.getptr(p_name);
return tex != NULL;
}
-bool Control::has_shader_override(const StringName &p_name) const {
+bool Control::has_theme_shader_override(const StringName &p_name) const {
const Ref<Shader> *sdr = data.shader_override.getptr(p_name);
return sdr != NULL;
}
-bool Control::has_stylebox_override(const StringName &p_name) const {
+bool Control::has_theme_stylebox_override(const StringName &p_name) const {
const Ref<StyleBox> *style = data.style_override.getptr(p_name);
return style != NULL;
}
-bool Control::has_font_override(const StringName &p_name) const {
+bool Control::has_theme_font_override(const StringName &p_name) const {
const Ref<Font> *font = data.font_override.getptr(p_name);
return font != NULL;
}
-bool Control::has_color_override(const StringName &p_name) const {
+bool Control::has_theme_color_override(const StringName &p_name) const {
const Color *color = data.color_override.getptr(p_name);
return color != NULL;
}
-bool Control::has_constant_override(const StringName &p_name) const {
+bool Control::has_theme_constant_override(const StringName &p_name) const {
const int *constant = data.constant_override.getptr(p_name);
return constant != NULL;
}
-bool Control::has_icon(const StringName &p_name, const StringName &p_type) const {
+bool Control::has_theme_icon(const StringName &p_name, const StringName &p_type) const {
if (p_type == StringName() || p_type == get_class_name()) {
- if (has_icon_override(p_name))
+ if (has_theme_icon_override(p_name))
return true;
}
StringName type = p_type ? p_type : get_class_name();
- // try with custom themes
- Control *theme_owner = data.theme_owner;
-
- while (theme_owner) {
-
- StringName class_name = type;
-
- while (class_name != StringName()) {
- if (theme_owner->data.theme->has_icon(p_name, class_name)) {
- return true;
- }
- class_name = ClassDB::get_parent_class_nocheck(class_name);
- }
+ return has_icons(data.theme_owner, data.theme_owner_window, p_name, type);
+}
- Control *parent = Object::cast_to<Control>(theme_owner->get_parent());
+bool Control::has_icons(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_type) {
- if (parent)
- theme_owner = parent->data.theme_owner;
- else
- theme_owner = NULL;
+ if (_has_theme_item(p_theme_owner, p_theme_owner_window, &Theme::has_icon, p_name, p_type)) {
+ return true;
}
if (Theme::get_project_default().is_valid()) {
- if (Theme::get_project_default()->has_color(p_name, type)) {
+ if (Theme::get_project_default()->has_color(p_name, p_type)) {
return true;
}
}
- return Theme::get_default()->has_icon(p_name, type);
+ return Theme::get_default()->has_icon(p_name, p_type);
}
-bool Control::has_shader(const StringName &p_name, const StringName &p_type) const {
+bool Control::has_theme_shader(const StringName &p_name, const StringName &p_type) const {
if (p_type == StringName() || p_type == get_class_name()) {
- if (has_shader_override(p_name))
+ if (has_theme_shader_override(p_name))
return true;
}
StringName type = p_type ? p_type : get_class_name();
- // try with custom themes
- Control *theme_owner = data.theme_owner;
-
- while (theme_owner) {
-
- StringName class_name = type;
-
- while (class_name != StringName()) {
- if (theme_owner->data.theme->has_shader(p_name, class_name)) {
- return true;
- }
- class_name = ClassDB::get_parent_class_nocheck(class_name);
- }
-
- Control *parent = Object::cast_to<Control>(theme_owner->get_parent());
+ return has_shaders(data.theme_owner, data.theme_owner_window, p_name, type);
+}
+bool Control::has_shaders(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_type) {
- if (parent)
- theme_owner = parent->data.theme_owner;
- else
- theme_owner = NULL;
+ if (_has_theme_item(p_theme_owner, p_theme_owner_window, &Theme::has_shader, p_name, p_type)) {
+ return true;
}
if (Theme::get_project_default().is_valid()) {
- if (Theme::get_project_default()->has_shader(p_name, type)) {
+ if (Theme::get_project_default()->has_shader(p_name, p_type)) {
return true;
}
}
- return Theme::get_default()->has_shader(p_name, type);
+ return Theme::get_default()->has_shader(p_name, p_type);
}
-bool Control::has_stylebox(const StringName &p_name, const StringName &p_type) const {
+
+bool Control::has_theme_stylebox(const StringName &p_name, const StringName &p_type) const {
if (p_type == StringName() || p_type == get_class_name()) {
- if (has_stylebox_override(p_name))
+ if (has_theme_stylebox_override(p_name))
return true;
}
StringName type = p_type ? p_type : get_class_name();
- // try with custom themes
- Control *theme_owner = data.theme_owner;
-
- while (theme_owner) {
-
- StringName class_name = type;
-
- while (class_name != StringName()) {
- if (theme_owner->data.theme->has_stylebox(p_name, class_name)) {
- return true;
- }
- class_name = ClassDB::get_parent_class_nocheck(class_name);
- }
+ return has_styleboxs(data.theme_owner, data.theme_owner_window, p_name, type);
+}
- Control *parent = Object::cast_to<Control>(theme_owner->get_parent());
+bool Control::has_styleboxs(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_type) {
- if (parent)
- theme_owner = parent->data.theme_owner;
- else
- theme_owner = NULL;
+ if (_has_theme_item(p_theme_owner, p_theme_owner_window, &Theme::has_stylebox, p_name, p_type)) {
+ return true;
}
if (Theme::get_project_default().is_valid()) {
- if (Theme::get_project_default()->has_stylebox(p_name, type)) {
+ if (Theme::get_project_default()->has_stylebox(p_name, p_type)) {
return true;
}
}
- return Theme::get_default()->has_stylebox(p_name, type);
+ return Theme::get_default()->has_stylebox(p_name, p_type);
}
-bool Control::has_font(const StringName &p_name, const StringName &p_type) const {
+
+bool Control::has_theme_font(const StringName &p_name, const StringName &p_type) const {
if (p_type == StringName() || p_type == get_class_name()) {
- if (has_font_override(p_name))
+ if (has_theme_font_override(p_name))
return true;
}
StringName type = p_type ? p_type : get_class_name();
- // try with custom themes
- Control *theme_owner = data.theme_owner;
-
- while (theme_owner) {
-
- StringName class_name = type;
-
- while (class_name != StringName()) {
- if (theme_owner->data.theme->has_font(p_name, class_name)) {
- return true;
- }
- class_name = ClassDB::get_parent_class_nocheck(class_name);
- }
-
- Control *parent = Object::cast_to<Control>(theme_owner->get_parent());
+ return has_fonts(data.theme_owner, data.theme_owner_window, p_name, type);
+}
+bool Control::has_fonts(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_type) {
- if (parent)
- theme_owner = parent->data.theme_owner;
- else
- theme_owner = NULL;
+ if (_has_theme_item(p_theme_owner, p_theme_owner_window, &Theme::has_font, p_name, p_type)) {
+ return true;
}
if (Theme::get_project_default().is_valid()) {
- if (Theme::get_project_default()->has_font(p_name, type)) {
+ if (Theme::get_project_default()->has_font(p_name, p_type)) {
return true;
}
}
- return Theme::get_default()->has_font(p_name, type);
+ return Theme::get_default()->has_font(p_name, p_type);
}
-bool Control::has_color(const StringName &p_name, const StringName &p_type) const {
+bool Control::has_theme_color(const StringName &p_name, const StringName &p_type) const {
if (p_type == StringName() || p_type == get_class_name()) {
- if (has_color_override(p_name))
+ if (has_theme_color_override(p_name))
return true;
}
StringName type = p_type ? p_type : get_class_name();
- // try with custom themes
- Control *theme_owner = data.theme_owner;
-
- while (theme_owner) {
-
- StringName class_name = type;
-
- while (class_name != StringName()) {
- if (theme_owner->data.theme->has_color(p_name, class_name)) {
- return true;
- }
- class_name = ClassDB::get_parent_class_nocheck(class_name);
- }
-
- Control *parent = Object::cast_to<Control>(theme_owner->get_parent());
+ return has_colors(data.theme_owner, data.theme_owner_window, p_name, type);
+}
+bool Control::has_colors(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_type) {
- if (parent)
- theme_owner = parent->data.theme_owner;
- else
- theme_owner = NULL;
+ if (_has_theme_item(p_theme_owner, p_theme_owner_window, &Theme::has_color, p_name, p_type)) {
+ return true;
}
if (Theme::get_project_default().is_valid()) {
- if (Theme::get_project_default()->has_color(p_name, type)) {
+ if (Theme::get_project_default()->has_color(p_name, p_type)) {
return true;
}
}
- return Theme::get_default()->has_color(p_name, type);
+ return Theme::get_default()->has_color(p_name, p_type);
}
-bool Control::has_constant(const StringName &p_name, const StringName &p_type) const {
+bool Control::has_theme_constant(const StringName &p_name, const StringName &p_type) const {
if (p_type == StringName() || p_type == get_class_name()) {
- if (has_constant_override(p_name))
+ if (has_theme_constant_override(p_name))
return true;
}
StringName type = p_type ? p_type : get_class_name();
- // try with custom themes
- Control *theme_owner = data.theme_owner;
-
- while (theme_owner) {
-
- StringName class_name = type;
-
- while (class_name != StringName()) {
- if (theme_owner->data.theme->has_constant(p_name, class_name)) {
- return true;
- }
- class_name = ClassDB::get_parent_class_nocheck(class_name);
- }
+ return has_constants(data.theme_owner, data.theme_owner_window, p_name, p_type);
+}
- Control *parent = Object::cast_to<Control>(theme_owner->get_parent());
+bool Control::has_constants(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_type) {
- if (parent)
- theme_owner = parent->data.theme_owner;
- else
- theme_owner = NULL;
+ if (_has_theme_item(p_theme_owner, p_theme_owner_window, &Theme::has_constant, p_name, p_type)) {
+ return true;
}
if (Theme::get_project_default().is_valid()) {
- if (Theme::get_project_default()->has_constant(p_name, type)) {
+ if (Theme::get_project_default()->has_constant(p_name, p_type)) {
return true;
}
}
- return Theme::get_default()->has_constant(p_name, type);
+ return Theme::get_default()->has_constant(p_name, p_type);
}
Rect2 Control::get_parent_anchorable_rect() const {
@@ -1769,6 +1660,17 @@ Point2 Control::get_global_position() const {
return get_global_transform().get_origin();
}
+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 && !w->is_embedding_subwindows()) {
+ global_pos += w->get_position();
+ }
+
+ return global_pos;
+}
+
void Control::_set_global_position(const Point2 &p_point) {
set_global_position(p_point);
}
@@ -1863,6 +1765,20 @@ Rect2 Control::get_global_rect() const {
return Rect2(get_global_position(), get_size());
}
+Rect2 Control::get_screen_rect() const {
+
+ ERR_FAIL_COND_V(!is_inside_tree(), Rect2());
+
+ Rect2 r(get_global_position(), get_size());
+
+ Window *w = Object::cast_to<Window>(get_viewport());
+ if (w && !w->is_embedding_subwindows()) {
+ r.position += w->get_position();
+ }
+
+ return r;
+}
+
Rect2 Control::get_window_rect() const {
ERR_FAIL_COND_V(!is_inside_tree(), Rect2());
Rect2 gr = get_global_rect();
@@ -1880,7 +1796,7 @@ Rect2 Control::get_anchorable_rect() const {
return Rect2(Point2(), get_size());
}
-void Control::add_icon_override(const StringName &p_name, const Ref<Texture2D> &p_icon) {
+void Control::add_theme_icon_override(const StringName &p_name, const Ref<Texture2D> &p_icon) {
if (data.icon_override.has(p_name)) {
data.icon_override[p_name]->disconnect("changed", callable_mp(this, &Control::_override_changed));
@@ -1898,7 +1814,7 @@ void Control::add_icon_override(const StringName &p_name, const Ref<Texture2D> &
notification(NOTIFICATION_THEME_CHANGED);
}
-void Control::add_shader_override(const StringName &p_name, const Ref<Shader> &p_shader) {
+void Control::add_theme_shader_override(const StringName &p_name, const Ref<Shader> &p_shader) {
if (data.shader_override.has(p_name)) {
data.shader_override[p_name]->disconnect("changed", callable_mp(this, &Control::_override_changed));
@@ -1915,7 +1831,7 @@ void Control::add_shader_override(const StringName &p_name, const Ref<Shader> &p
}
notification(NOTIFICATION_THEME_CHANGED);
}
-void Control::add_style_override(const StringName &p_name, const Ref<StyleBox> &p_style) {
+void Control::add_theme_style_override(const StringName &p_name, const Ref<StyleBox> &p_style) {
if (data.style_override.has(p_name)) {
data.style_override[p_name]->disconnect("changed", callable_mp(this, &Control::_override_changed));
@@ -1933,7 +1849,7 @@ void Control::add_style_override(const StringName &p_name, const Ref<StyleBox> &
notification(NOTIFICATION_THEME_CHANGED);
}
-void Control::add_font_override(const StringName &p_name, const Ref<Font> &p_font) {
+void Control::add_theme_font_override(const StringName &p_name, const Ref<Font> &p_font) {
if (data.font_override.has(p_name)) {
data.font_override[p_name]->disconnect("changed", callable_mp(this, &Control::_override_changed));
@@ -1950,12 +1866,12 @@ void Control::add_font_override(const StringName &p_name, const Ref<Font> &p_fon
}
notification(NOTIFICATION_THEME_CHANGED);
}
-void Control::add_color_override(const StringName &p_name, const Color &p_color) {
+void Control::add_theme_color_override(const StringName &p_name, const Color &p_color) {
data.color_override[p_name] = p_color;
notification(NOTIFICATION_THEME_CHANGED);
}
-void Control::add_constant_override(const StringName &p_name, int p_constant) {
+void Control::add_theme_constant_override(const StringName &p_name, int p_constant) {
data.constant_override[p_name] = p_constant;
notification(NOTIFICATION_THEME_CHANGED);
@@ -2049,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();
}
@@ -2192,53 +2108,29 @@ 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::_propagate_theme_changed(Node *p_at, Control *p_owner, Window *p_owner_window, bool p_assign) {
-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());
+ Control *c = Object::cast_to<Control>(p_at);
- if (!data.MI)
+ if (c && c != p_owner && c->data.theme.is_valid()) // has a theme, this can't be propagated
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();
-}
+ Window *w = c == nullptr ? Object::cast_to<Window>(p_at) : nullptr;
-void Control::_propagate_theme_changed(CanvasItem *p_at, Control *p_owner, bool p_assign) {
-
- Control *c = Object::cast_to<Control>(p_at);
-
- if (c && c != p_owner && c->data.theme.is_valid()) // has a theme, this can't be propagated
+ if (w && w != p_owner_window && w->theme.is_valid()) // has a theme, this can't be propagated
return;
for (int i = 0; i < p_at->get_child_count(); i++) {
CanvasItem *child = Object::cast_to<CanvasItem>(p_at->get_child(i));
if (child) {
- _propagate_theme_changed(child, p_owner, p_assign);
+ _propagate_theme_changed(child, p_owner, p_owner_window, p_assign);
+ } else {
+
+ Window *window = Object::cast_to<Window>(p_at->get_child(i));
+ if (window) {
+ _propagate_theme_changed(window, p_owner, p_owner_window, p_assign);
+ }
}
}
@@ -2246,14 +2138,26 @@ void Control::_propagate_theme_changed(CanvasItem *p_at, Control *p_owner, bool
if (p_assign) {
c->data.theme_owner = p_owner;
+ c->data.theme_owner_window = p_owner_window;
+ }
+ c->notification(Control::NOTIFICATION_THEME_CHANGED);
+ c->emit_signal(SceneStringNames::get_singleton()->theme_changed);
+ }
+
+ if (w) {
+
+ if (p_assign) {
+ w->theme_owner = p_owner;
+ w->theme_owner_window = p_owner_window;
}
- c->notification(NOTIFICATION_THEME_CHANGED);
+ w->notification(Window::NOTIFICATION_THEME_CHANGED);
+ w->emit_signal(SceneStringNames::get_singleton()->theme_changed);
}
}
void Control::_theme_changed() {
- _propagate_theme_changed(this, this, false);
+ _propagate_theme_changed(this, this, nullptr, false);
}
void Control::set_theme(const Ref<Theme> &p_theme) {
@@ -2269,15 +2173,21 @@ void Control::set_theme(const Ref<Theme> &p_theme) {
if (!p_theme.is_null()) {
data.theme_owner = this;
- _propagate_theme_changed(this, this);
+ data.theme_owner_window = nullptr;
+ _propagate_theme_changed(this, this, nullptr);
} else {
- Control *parent = cast_to<Control>(get_parent());
- if (parent && parent->data.theme_owner) {
- _propagate_theme_changed(this, parent->data.theme_owner);
- } else {
+ Control *parent_c = Object::cast_to<Control>(get_parent());
- _propagate_theme_changed(this, NULL);
+ if (parent_c && (parent_c->data.theme_owner || parent_c->data.theme_owner_window)) {
+ Control::_propagate_theme_changed(this, parent_c->data.theme_owner, parent_c->data.theme_owner_window);
+ } else {
+ Window *parent_w = cast_to<Window>(get_parent());
+ if (parent_w && (parent_w->theme_owner || parent_w->theme_owner_window)) {
+ Control::_propagate_theme_changed(this, parent_w->theme_owner, parent_w->theme_owner_window);
+ } else {
+ Control::_propagate_theme_changed(this, nullptr, nullptr);
+ }
}
}
@@ -2440,8 +2350,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;
}
@@ -2511,7 +2419,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);
}
@@ -2569,6 +2477,12 @@ void Control::minimum_size_changed() {
invalidate->data.minimum_size_valid = false;
if (invalidate->is_set_as_toplevel())
break; // do not go further up
+ if (!invalidate->data.parent && get_parent()) {
+ Window *parent_window = Object::cast_to<Window>(get_parent());
+ if (parent_window && parent_window->is_wrapping_controls()) {
+ parent_window->child_controls_changed();
+ }
+ }
invalidate = invalidate->data.parent;
}
@@ -2599,16 +2513,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);
@@ -2658,6 +2562,7 @@ float Control::get_rotation_degrees() const {
void Control::_override_changed() {
notification(NOTIFICATION_THEME_CHANGED);
+ emit_signal(SceneStringNames::get_singleton()->theme_changed);
minimum_size_changed(); // overrides are likely to affect minimum size
}
@@ -2701,7 +2606,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;
}
@@ -2853,7 +2758,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);
@@ -2873,31 +2777,31 @@ void Control::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_theme", "theme"), &Control::set_theme);
ClassDB::bind_method(D_METHOD("get_theme"), &Control::get_theme);
- ClassDB::bind_method(D_METHOD("add_icon_override", "name", "texture"), &Control::add_icon_override);
- ClassDB::bind_method(D_METHOD("add_shader_override", "name", "shader"), &Control::add_shader_override);
- ClassDB::bind_method(D_METHOD("add_stylebox_override", "name", "stylebox"), &Control::add_style_override);
- ClassDB::bind_method(D_METHOD("add_font_override", "name", "font"), &Control::add_font_override);
- ClassDB::bind_method(D_METHOD("add_color_override", "name", "color"), &Control::add_color_override);
- ClassDB::bind_method(D_METHOD("add_constant_override", "name", "constant"), &Control::add_constant_override);
-
- ClassDB::bind_method(D_METHOD("get_icon", "name", "type"), &Control::get_icon, DEFVAL(""));
- ClassDB::bind_method(D_METHOD("get_stylebox", "name", "type"), &Control::get_stylebox, DEFVAL(""));
- ClassDB::bind_method(D_METHOD("get_font", "name", "type"), &Control::get_font, DEFVAL(""));
- ClassDB::bind_method(D_METHOD("get_color", "name", "type"), &Control::get_color, DEFVAL(""));
- ClassDB::bind_method(D_METHOD("get_constant", "name", "type"), &Control::get_constant, DEFVAL(""));
-
- ClassDB::bind_method(D_METHOD("has_icon_override", "name"), &Control::has_icon_override);
- ClassDB::bind_method(D_METHOD("has_shader_override", "name"), &Control::has_shader_override);
- ClassDB::bind_method(D_METHOD("has_stylebox_override", "name"), &Control::has_stylebox_override);
- ClassDB::bind_method(D_METHOD("has_font_override", "name"), &Control::has_font_override);
- ClassDB::bind_method(D_METHOD("has_color_override", "name"), &Control::has_color_override);
- ClassDB::bind_method(D_METHOD("has_constant_override", "name"), &Control::has_constant_override);
-
- ClassDB::bind_method(D_METHOD("has_icon", "name", "type"), &Control::has_icon, DEFVAL(""));
- ClassDB::bind_method(D_METHOD("has_stylebox", "name", "type"), &Control::has_stylebox, DEFVAL(""));
- ClassDB::bind_method(D_METHOD("has_font", "name", "type"), &Control::has_font, DEFVAL(""));
- ClassDB::bind_method(D_METHOD("has_color", "name", "type"), &Control::has_color, DEFVAL(""));
- ClassDB::bind_method(D_METHOD("has_constant", "name", "type"), &Control::has_constant, DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("add_theme_icon_override", "name", "texture"), &Control::add_theme_icon_override);
+ ClassDB::bind_method(D_METHOD("add_theme_shader_override", "name", "shader"), &Control::add_theme_shader_override);
+ ClassDB::bind_method(D_METHOD("add_theme_stylebox_override", "name", "stylebox"), &Control::add_theme_style_override);
+ ClassDB::bind_method(D_METHOD("add_theme_font_override", "name", "font"), &Control::add_theme_font_override);
+ ClassDB::bind_method(D_METHOD("add_theme_color_override", "name", "color"), &Control::add_theme_color_override);
+ ClassDB::bind_method(D_METHOD("add_theme_constant_override", "name", "constant"), &Control::add_theme_constant_override);
+
+ ClassDB::bind_method(D_METHOD("get_theme_icon", "name", "type"), &Control::get_theme_icon, DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("get_theme_stylebox", "name", "type"), &Control::get_theme_stylebox, DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("get_theme_font", "name", "type"), &Control::get_theme_font, DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("get_theme_color", "name", "type"), &Control::get_theme_color, DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("get_theme_constant", "name", "type"), &Control::get_theme_constant, DEFVAL(""));
+
+ ClassDB::bind_method(D_METHOD("has_theme_icon_override", "name"), &Control::has_theme_icon_override);
+ ClassDB::bind_method(D_METHOD("has_theme_shader_override", "name"), &Control::has_theme_shader_override);
+ ClassDB::bind_method(D_METHOD("has_theme_stylebox_override", "name"), &Control::has_theme_stylebox_override);
+ ClassDB::bind_method(D_METHOD("has_theme_font_override", "name"), &Control::has_theme_font_override);
+ ClassDB::bind_method(D_METHOD("has_theme_color_override", "name"), &Control::has_theme_color_override);
+ ClassDB::bind_method(D_METHOD("has_theme_constant_override", "name"), &Control::has_theme_constant_override);
+
+ ClassDB::bind_method(D_METHOD("has_theme_icon", "name", "type"), &Control::has_theme_icon, DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("has_theme_stylebox", "name", "type"), &Control::has_theme_stylebox, DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("has_theme_font", "name", "type"), &Control::has_theme_font, DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("has_theme_color", "name", "type"), &Control::has_theme_color, DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("has_theme_constant", "name", "type"), &Control::has_theme_constant, DEFVAL(""));
ClassDB::bind_method(D_METHOD("get_parent_control"), &Control::get_parent_control);
@@ -3013,7 +2917,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);
@@ -3082,7 +2985,7 @@ 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")));
}
@@ -3091,13 +2994,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.modal_exclusive = false;
+ data.theme_owner_window = NULL;
data.default_cursor = CURSOR_ARROW;
data.h_size_flags = SIZE_FILL;
data.v_size_flags = SIZE_FILL;
@@ -3106,7 +3006,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;
diff --git a/scene/gui/control.h b/scene/gui/control.h
index 15a32b8f67..c52e80fa70 100644
--- a/scene/gui/control.h
+++ b/scene/gui/control.h
@@ -168,8 +168,6 @@ private:
float expand;
Point2 custom_minimum_size;
- bool pass_on_modal_close_click;
-
MouseFilter mouse_filter;
bool clip_contents;
@@ -179,21 +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;
@@ -218,7 +211,6 @@ private:
void _set_global_position(const Point2 &p_point);
void _set_size(const Size2 &p_size);
- void _propagate_theme_changed(CanvasItem *p_at, Control *p_owner, bool p_assign = true);
void _theme_changed();
void _change_notify_margins();
@@ -240,10 +232,29 @@ 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;
+ static void _propagate_theme_changed(Node *p_at, Control *p_owner, Window *p_owner_window, bool p_assign = true);
+
+ template <class T>
+ _FORCE_INLINE_ static bool _find_theme_item(Control *p_theme_owner, Window *p_theme_owner_window, T &, T (Theme::*get_func)(const StringName &, const StringName &) const, bool (Theme::*has_func)(const StringName &, const StringName &) const, const StringName &p_name, const StringName &p_type);
+
+ _FORCE_INLINE_ static bool _has_theme_item(Control *p_theme_owner, Window *p_theme_owner_window, bool (Theme::*has_func)(const StringName &, const StringName &) const, const StringName &p_name, const StringName &p_type);
+
+ static Ref<Texture2D> get_icons(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_type = StringName());
+ static Ref<Shader> get_shaders(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_type = StringName());
+ static Ref<StyleBox> get_styleboxs(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_type = StringName());
+ static Ref<Font> get_fonts(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_type = StringName());
+ static Color get_colors(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_type = StringName());
+ static int get_constants(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_type = StringName());
+
+ static bool has_icons(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_type = StringName());
+ static bool has_shaders(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_type = StringName());
+ static bool has_styleboxs(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_type = StringName());
+ static bool has_fonts(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_type = StringName());
+ static bool has_colors(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_type = StringName());
+ static bool has_constants(Control *p_theme_owner, Window *p_theme_owner_window, const StringName &p_name, const StringName &p_type = StringName());
protected:
virtual void add_child_notify(Node *p_child);
@@ -272,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,
@@ -320,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 */
@@ -349,12 +356,14 @@ public:
void set_global_position(const Point2 &p_point, bool p_keep_margins = false);
Point2 get_position() const;
Point2 get_global_position() const;
+ Point2 get_screen_position() const;
void set_size(const Size2 &p_size, bool p_keep_margins = false);
Size2 get_size() const;
Rect2 get_rect() const;
Rect2 get_global_rect() const;
+ Rect2 get_screen_rect() const;
Rect2 get_window_rect() const; ///< use with care, as it blocks waiting for the visual server
Rect2 get_anchorable_rect() const;
@@ -375,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;
@@ -415,38 +422,35 @@ 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_icon_override(const StringName &p_name, const Ref<Texture2D> &p_icon);
- void add_shader_override(const StringName &p_name, const Ref<Shader> &p_shader);
- void add_style_override(const StringName &p_name, const Ref<StyleBox> &p_style);
- void add_font_override(const StringName &p_name, const Ref<Font> &p_font);
- void add_color_override(const StringName &p_name, const Color &p_color);
- void add_constant_override(const StringName &p_name, int p_constant);
-
- Ref<Texture2D> get_icon(const StringName &p_name, const StringName &p_type = StringName()) const;
- Ref<Shader> get_shader(const StringName &p_name, const StringName &p_type = StringName()) const;
- Ref<StyleBox> get_stylebox(const StringName &p_name, const StringName &p_type = StringName()) const;
- Ref<Font> get_font(const StringName &p_name, const StringName &p_type = StringName()) const;
- Color get_color(const StringName &p_name, const StringName &p_type = StringName()) const;
- int get_constant(const StringName &p_name, const StringName &p_type = StringName()) const;
-
- bool has_icon_override(const StringName &p_name) const;
- bool has_shader_override(const StringName &p_name) const;
- bool has_stylebox_override(const StringName &p_name) const;
- bool has_font_override(const StringName &p_name) const;
- bool has_color_override(const StringName &p_name) const;
- bool has_constant_override(const StringName &p_name) const;
-
- bool has_icon(const StringName &p_name, const StringName &p_type = StringName()) const;
- bool has_shader(const StringName &p_name, const StringName &p_type = StringName()) const;
- bool has_stylebox(const StringName &p_name, const StringName &p_type = StringName()) const;
- bool has_font(const StringName &p_name, const StringName &p_type = StringName()) const;
- bool has_color(const StringName &p_name, const StringName &p_type = StringName()) const;
- bool has_constant(const StringName &p_name, const StringName &p_type = StringName()) const;
+ void add_theme_icon_override(const StringName &p_name, const Ref<Texture2D> &p_icon);
+ void add_theme_shader_override(const StringName &p_name, const Ref<Shader> &p_shader);
+ void add_theme_style_override(const StringName &p_name, const Ref<StyleBox> &p_style);
+ void add_theme_font_override(const StringName &p_name, const Ref<Font> &p_font);
+ void add_theme_color_override(const StringName &p_name, const Color &p_color);
+ void add_theme_constant_override(const StringName &p_name, int p_constant);
+
+ Ref<Texture2D> get_theme_icon(const StringName &p_name, const StringName &p_type = StringName()) const;
+ Ref<Shader> get_theme_shader(const StringName &p_name, const StringName &p_type = StringName()) const;
+ Ref<StyleBox> get_theme_stylebox(const StringName &p_name, const StringName &p_type = StringName()) const;
+ Ref<Font> get_theme_font(const StringName &p_name, const StringName &p_type = StringName()) const;
+ Color get_theme_color(const StringName &p_name, const StringName &p_type = StringName()) const;
+ int get_theme_constant(const StringName &p_name, const StringName &p_type = StringName()) const;
+
+ bool has_theme_icon_override(const StringName &p_name) const;
+ bool has_theme_shader_override(const StringName &p_name) const;
+ bool has_theme_stylebox_override(const StringName &p_name) const;
+ bool has_theme_font_override(const StringName &p_name) const;
+ bool has_theme_color_override(const StringName &p_name) const;
+ bool has_theme_constant_override(const StringName &p_name) const;
+
+ bool has_theme_icon(const StringName &p_name, const StringName &p_type = StringName()) const;
+ bool has_theme_shader(const StringName &p_name, const StringName &p_type = StringName()) const;
+ bool has_theme_stylebox(const StringName &p_name, const StringName &p_type = StringName()) const;
+ bool has_theme_font(const StringName &p_name, const StringName &p_type = StringName()) const;
+ 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;
/* TOOLTIP */
diff --git a/scene/gui/dialogs.cpp b/scene/gui/dialogs.cpp
index 6cadd0a63e..2e87a92969 100644
--- a/scene/gui/dialogs.cpp
+++ b/scene/gui/dialogs.cpp
@@ -29,6 +29,8 @@
/*************************************************************************/
#include "dialogs.h"
+
+#include "core/os/keyboard.h"
#include "core/print_string.h"
#include "core/translation.h"
#include "line_edit.h"
@@ -36,362 +38,61 @@
#ifdef TOOLS_ENABLED
#include "editor/editor_node.h"
#include "editor/editor_scale.h"
-#include "scene/main/viewport.h" // Only used to check for more modals when dimming the editor.
+#include "scene/main/window.h" // Only used to check for more modals when dimming the editor.
#endif
-// WindowDialog
-
-void WindowDialog::_post_popup() {
-
- drag_type = DRAG_NONE; // just in case
-}
-
-void WindowDialog::_fix_size() {
-
- // Perhaps this should be called when the viewport resizes as well or windows go out of bounds...
-
- // Ensure the whole window is visible.
- Point2i pos = get_global_position();
- Size2i size = get_size();
- Size2i viewport_size = get_viewport_rect().size;
-
- // Windows require additional padding to keep the window chrome visible.
- Ref<StyleBox> panel = get_stylebox("panel", "WindowDialog");
- float top = 0;
- float left = 0;
- float bottom = 0;
- float right = 0;
- // Check validity, because the theme could contain a different type of StyleBox.
- if (panel->get_class() == "StyleBoxTexture") {
- Ref<StyleBoxTexture> panel_texture = Object::cast_to<StyleBoxTexture>(*panel);
- top = panel_texture->get_expand_margin_size(MARGIN_TOP);
- left = panel_texture->get_expand_margin_size(MARGIN_LEFT);
- bottom = panel_texture->get_expand_margin_size(MARGIN_BOTTOM);
- right = panel_texture->get_expand_margin_size(MARGIN_RIGHT);
- } else if (panel->get_class() == "StyleBoxFlat") {
- Ref<StyleBoxFlat> panel_flat = Object::cast_to<StyleBoxFlat>(*panel);
- top = panel_flat->get_expand_margin_size(MARGIN_TOP);
- left = panel_flat->get_expand_margin_size(MARGIN_LEFT);
- bottom = panel_flat->get_expand_margin_size(MARGIN_BOTTOM);
- right = panel_flat->get_expand_margin_size(MARGIN_RIGHT);
- }
-
- pos.x = MAX(left, MIN(pos.x, viewport_size.x - size.x - right));
- pos.y = MAX(top, MIN(pos.y, viewport_size.y - size.y - bottom));
- set_global_position(pos);
+// AcceptDialog
- if (resizable) {
- size.x = MIN(size.x, viewport_size.x - left - right);
- size.y = MIN(size.y, viewport_size.y - top - bottom);
- set_size(size);
+void AcceptDialog::_input_from_window(const Ref<InputEvent> &p_event) {
+ Ref<InputEventKey> key = p_event;
+ if (key.is_valid() && key->is_pressed() && key->get_keycode() == KEY_ESCAPE) {
+ _cancel_pressed();
}
}
-bool WindowDialog::has_point(const Point2 &p_point) const {
-
- Rect2 r(Point2(), get_size());
-
- // Enlarge upwards for title bar.
- int title_height = get_constant("title_height", "WindowDialog");
- r.position.y -= title_height;
- r.size.y += title_height;
-
- // Inflate by the resizable border thickness.
- if (resizable) {
- int scaleborder_size = get_constant("scaleborder_size", "WindowDialog");
- r.position.x -= scaleborder_size;
- r.size.width += scaleborder_size * 2;
- r.position.y -= scaleborder_size;
- r.size.height += scaleborder_size * 2;
- }
-
- return r.has_point(p_point);
+void AcceptDialog::_parent_focused() {
+ _cancel_pressed();
}
-void WindowDialog::_gui_input(const Ref<InputEvent> &p_event) {
-
- Ref<InputEventMouseButton> mb = p_event;
-
- if (mb.is_valid() && mb->get_button_index() == BUTTON_LEFT) {
-
- if (mb->is_pressed()) {
- // Begin a possible dragging operation.
- drag_type = _drag_hit_test(Point2(mb->get_position().x, mb->get_position().y));
- if (drag_type != DRAG_NONE)
- drag_offset = get_global_mouse_position() - get_position();
- drag_offset_far = get_position() + get_size() - get_global_mouse_position();
- } else if (drag_type != DRAG_NONE && !mb->is_pressed()) {
- // End a dragging operation.
- drag_type = DRAG_NONE;
- }
- }
+void AcceptDialog::_notification(int p_what) {
- Ref<InputEventMouseMotion> mm = p_event;
-
- if (mm.is_valid()) {
-
- if (drag_type == DRAG_NONE) {
- // Update the cursor while moving along the borders.
- CursorShape cursor = CURSOR_ARROW;
- if (resizable) {
- int preview_drag_type = _drag_hit_test(Point2(mm->get_position().x, mm->get_position().y));
- switch (preview_drag_type) {
- case DRAG_RESIZE_TOP:
- case DRAG_RESIZE_BOTTOM:
- cursor = CURSOR_VSIZE;
- break;
- case DRAG_RESIZE_LEFT:
- case DRAG_RESIZE_RIGHT:
- cursor = CURSOR_HSIZE;
- break;
- case DRAG_RESIZE_TOP + DRAG_RESIZE_LEFT:
- case DRAG_RESIZE_BOTTOM + DRAG_RESIZE_RIGHT:
- cursor = CURSOR_FDIAGSIZE;
- break;
- case DRAG_RESIZE_TOP + DRAG_RESIZE_RIGHT:
- case DRAG_RESIZE_BOTTOM + DRAG_RESIZE_LEFT:
- cursor = CURSOR_BDIAGSIZE;
- break;
+ switch (p_what) {
+ case NOTIFICATION_VISIBILITY_CHANGED: {
+ if (is_visible()) {
+
+ get_ok()->grab_focus();
+ _update_child_rects();
+ parent_visible = get_parent_visible_window();
+ if (parent_visible) {
+ parent_visible->connect("focus_entered", callable_mp(this, &AcceptDialog::_parent_focused));
}
- }
- if (get_cursor_shape() != cursor)
- set_default_cursor_shape(cursor);
- } else {
- // Update while in a dragging operation.
- Point2 global_pos = get_global_mouse_position();
- global_pos.y = MAX(global_pos.y, 0); // Ensure title bar stays visible.
-
- Rect2 rect = get_rect();
- Size2 min_size = get_combined_minimum_size();
-
- if (drag_type == DRAG_MOVE) {
- rect.position = global_pos - drag_offset;
} else {
- if (drag_type & DRAG_RESIZE_TOP) {
- int bottom = rect.position.y + rect.size.height;
- int max_y = bottom - min_size.height;
- rect.position.y = MIN(global_pos.y - drag_offset.y, max_y);
- rect.size.height = bottom - rect.position.y;
- } else if (drag_type & DRAG_RESIZE_BOTTOM) {
- rect.size.height = global_pos.y - rect.position.y + drag_offset_far.y;
- }
- if (drag_type & DRAG_RESIZE_LEFT) {
- int right = rect.position.x + rect.size.width;
- int max_x = right - min_size.width;
- rect.position.x = MIN(global_pos.x - drag_offset.x, max_x);
- rect.size.width = right - rect.position.x;
- } else if (drag_type & DRAG_RESIZE_RIGHT) {
- rect.size.width = global_pos.x - rect.position.x + drag_offset_far.x;
+ if (parent_visible) {
+ parent_visible->disconnect("focus_entered", callable_mp(this, &AcceptDialog::_parent_focused));
+ parent_visible = nullptr;
}
}
- set_size(rect.size);
- set_position(rect.position);
- }
- }
-}
-
-void WindowDialog::_notification(int p_what) {
-
- switch (p_what) {
- case NOTIFICATION_DRAW: {
- RID canvas = get_canvas_item();
-
- // Draw the background.
- Ref<StyleBox> panel = get_stylebox("panel");
- Size2 size = get_size();
- panel->draw(canvas, Rect2(0, 0, size.x, size.y));
-
- // Draw the title bar text.
- Ref<Font> title_font = get_font("title_font", "WindowDialog");
- Color title_color = get_color("title_color", "WindowDialog");
- int title_height = get_constant("title_height", "WindowDialog");
- int font_height = title_font->get_height() - title_font->get_descent() * 2;
- int x = (size.x - title_font->get_string_size(xl_title).x) / 2;
- int y = (-title_height + font_height) / 2;
- title_font->draw(canvas, Point2(x, y), xl_title, title_color, size.x - panel->get_minimum_size().x);
} break;
- case NOTIFICATION_THEME_CHANGED:
- case NOTIFICATION_ENTER_TREE: {
- close_button->set_normal_texture(get_icon("close", "WindowDialog"));
- close_button->set_pressed_texture(get_icon("close", "WindowDialog"));
- close_button->set_hover_texture(get_icon("close_highlight", "WindowDialog"));
- close_button->set_anchor(MARGIN_LEFT, ANCHOR_END);
- close_button->set_begin(Point2(-get_constant("close_h_ofs", "WindowDialog"), -get_constant("close_v_ofs", "WindowDialog")));
- } break;
-
- case NOTIFICATION_TRANSLATION_CHANGED: {
- String new_title = tr(title);
- if (new_title != xl_title) {
- xl_title = new_title;
- minimum_size_changed();
- update();
- }
+ case NOTIFICATION_THEME_CHANGED: {
+ bg->add_theme_style_override("panel", bg->get_theme_stylebox("panel", "AcceptDialog"));
} break;
- case NOTIFICATION_MOUSE_EXIT: {
- // Reset the mouse cursor when leaving the resizable window border.
- if (resizable && !drag_type) {
- if (get_default_cursor_shape() != CURSOR_ARROW)
- set_default_cursor_shape(CURSOR_ARROW);
+ case NOTIFICATION_EXIT_TREE: {
+ if (parent_visible) {
+ parent_visible->disconnect("focus_entered", callable_mp(this, &AcceptDialog::_parent_focused));
+ parent_visible = nullptr;
}
} break;
-
-#ifdef TOOLS_ENABLED
- case NOTIFICATION_POST_POPUP: {
- if (get_tree() && Engine::get_singleton()->is_editor_hint() && EditorNode::get_singleton()) {
- was_editor_dimmed = EditorNode::get_singleton()->is_editor_dimmed();
- EditorNode::get_singleton()->dim_editor(true);
- }
- } break;
-
- case NOTIFICATION_POPUP_HIDE: {
- if (get_tree() && Engine::get_singleton()->is_editor_hint() && EditorNode::get_singleton() && !was_editor_dimmed) {
- EditorNode::get_singleton()->dim_editor(false);
- set_pass_on_modal_close_click(false);
+ case NOTIFICATION_READY:
+ case NOTIFICATION_WM_SIZE_CHANGED: {
+ if (is_visible()) {
+ _update_child_rects();
}
} break;
-#endif
- }
-}
-
-void WindowDialog::_closed() {
-
- _close_pressed();
- hide();
-}
-
-int WindowDialog::_drag_hit_test(const Point2 &pos) const {
- int drag_type = DRAG_NONE;
-
- if (resizable) {
- int title_height = get_constant("title_height", "WindowDialog");
- int scaleborder_size = get_constant("scaleborder_size", "WindowDialog");
-
- Rect2 rect = get_rect();
-
- if (pos.y < (-title_height + scaleborder_size))
- drag_type = DRAG_RESIZE_TOP;
- else if (pos.y >= (rect.size.height - scaleborder_size))
- drag_type = DRAG_RESIZE_BOTTOM;
- if (pos.x < scaleborder_size)
- drag_type |= DRAG_RESIZE_LEFT;
- else if (pos.x >= (rect.size.width - scaleborder_size))
- drag_type |= DRAG_RESIZE_RIGHT;
- }
-
- if (drag_type == DRAG_NONE && pos.y < 0)
- drag_type = DRAG_MOVE;
-
- return drag_type;
-}
-
-void WindowDialog::set_title(const String &p_title) {
-
- if (title != p_title) {
- title = p_title;
- xl_title = tr(p_title);
- minimum_size_changed();
- update();
- }
-}
-String WindowDialog::get_title() const {
-
- return title;
-}
-
-void WindowDialog::set_resizable(bool p_resizable) {
- resizable = p_resizable;
-}
-bool WindowDialog::get_resizable() const {
- return resizable;
-}
-
-Size2 WindowDialog::get_minimum_size() const {
-
- Ref<Font> font = get_font("title_font", "WindowDialog");
-
- const int button_width = close_button->get_combined_minimum_size().x;
- const int title_width = font->get_string_size(xl_title).x;
- const int padding = button_width / 2;
- const int button_area = button_width + padding;
-
- // As the title gets centered, title_width + close_button_width is not enough.
- // We want a width w, such that w / 2 - title_width / 2 >= button_area, i.e.
- // w >= 2 * button_area + title_width
-
- return Size2(2 * button_area + title_width, 1);
-}
-
-TextureButton *WindowDialog::get_close_button() {
-
- return close_button;
-}
-
-void WindowDialog::_bind_methods() {
-
- ClassDB::bind_method(D_METHOD("_gui_input"), &WindowDialog::_gui_input);
- ClassDB::bind_method(D_METHOD("set_title", "title"), &WindowDialog::set_title);
- ClassDB::bind_method(D_METHOD("get_title"), &WindowDialog::get_title);
- ClassDB::bind_method(D_METHOD("set_resizable", "resizable"), &WindowDialog::set_resizable);
- ClassDB::bind_method(D_METHOD("get_resizable"), &WindowDialog::get_resizable);
- ClassDB::bind_method(D_METHOD("get_close_button"), &WindowDialog::get_close_button);
-
- ADD_PROPERTY(PropertyInfo(Variant::STRING, "window_title", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT_INTL), "set_title", "get_title");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "resizable", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_DEFAULT_INTL), "set_resizable", "get_resizable");
-}
-
-WindowDialog::WindowDialog() {
-
- drag_type = DRAG_NONE;
- resizable = false;
- close_button = memnew(TextureButton);
- add_child(close_button);
- close_button->connect("pressed", callable_mp(this, &WindowDialog::_closed));
-
-#ifdef TOOLS_ENABLED
- was_editor_dimmed = false;
-#endif
-}
-
-WindowDialog::~WindowDialog() {
-}
-
-// PopupDialog
-
-void PopupDialog::_notification(int p_what) {
-
- if (p_what == NOTIFICATION_DRAW) {
- RID ci = get_canvas_item();
- get_stylebox("panel")->draw(ci, Rect2(Point2(), get_size()));
- }
-}
-
-PopupDialog::PopupDialog() {
-}
-
-PopupDialog::~PopupDialog() {
-}
-
-// AcceptDialog
-
-void AcceptDialog::_post_popup() {
-
- WindowDialog::_post_popup();
- get_ok()->grab_focus();
-}
-
-void AcceptDialog::_notification(int p_what) {
-
- switch (p_what) {
- case NOTIFICATION_MODAL_CLOSE: {
- cancel_pressed();
- } break;
-
- case NOTIFICATION_READY:
- case NOTIFICATION_RESIZED: {
- _update_child_rects();
+ case NOTIFICATION_WM_CLOSE_REQUEST: {
+ _cancel_pressed();
} break;
}
}
@@ -404,20 +105,28 @@ void AcceptDialog::_text_entered(const String &p_text) {
void AcceptDialog::_ok_pressed() {
if (hide_on_ok)
- hide();
+ set_visible(false);
ok_pressed();
emit_signal("confirmed");
}
-void AcceptDialog::_close_pressed() {
+void AcceptDialog::_cancel_pressed() {
+
+ Window *parent_window = parent_visible;
+ if (parent_visible) {
+ parent_visible->disconnect("focus_entered", callable_mp(this, &AcceptDialog::_parent_focused));
+ parent_visible = nullptr;
+ }
+
+ call_deferred("hide");
+
+ emit_signal("cancelled");
cancel_pressed();
-}
-// FIXME: This is redundant with _closed_pressed, but there's a slight behavior
-// change (WindowDialog's _closed() also calls hide()) which should be assessed.
-void AcceptDialog::_on_close_pressed() {
- _closed(); // From WindowDialog.
+ if (parent_window) {
+ //parent_window->grab_focus();
+ }
}
String AcceptDialog::get_text() const {
@@ -427,8 +136,10 @@ String AcceptDialog::get_text() const {
void AcceptDialog::set_text(String p_text) {
label->set_text(p_text);
- minimum_size_changed();
- _update_child_rects();
+ child_controls_changed();
+ if (is_visible()) {
+ _update_child_rects();
+ }
}
void AcceptDialog::set_hide_on_ok(bool p_hide) {
@@ -463,7 +174,7 @@ void AcceptDialog::_update_child_rects() {
if (label->get_text().empty()) {
label_size.height = 0;
}
- int margin = get_constant("margin", "Dialogs");
+ int margin = hbc->get_theme_constant("margin", "Dialogs");
Size2 size = get_size();
Size2 hminsize = hbc->get_combined_minimum_size();
@@ -475,7 +186,7 @@ void AcceptDialog::_update_child_rects() {
if (!c)
continue;
- if (c == hbc || c == label || c == get_close_button() || c->is_set_as_toplevel())
+ if (c == hbc || c == label || c == bg || c->is_set_as_toplevel())
continue;
c->set_position(cpos);
@@ -487,11 +198,14 @@ void AcceptDialog::_update_child_rects() {
hbc->set_position(cpos);
hbc->set_size(csize);
+
+ bg->set_position(Point2());
+ bg->set_size(size);
}
-Size2 AcceptDialog::get_minimum_size() const {
+Size2 AcceptDialog::_get_contents_minimum_size() const {
- int margin = get_constant("margin", "Dialogs");
+ int margin = hbc->get_theme_constant("margin", "Dialogs");
Size2 minsize = label->get_combined_minimum_size();
for (int i = 0; i < get_child_count(); i++) {
@@ -499,7 +213,7 @@ Size2 AcceptDialog::get_minimum_size() const {
if (!c)
continue;
- if (c == hbc || c == label || c == const_cast<AcceptDialog *>(this)->get_close_button() || c->is_set_as_toplevel())
+ if (c == hbc || c == label || c->is_set_as_toplevel())
continue;
Size2 cminsize = c->get_combined_minimum_size();
@@ -513,7 +227,7 @@ Size2 AcceptDialog::get_minimum_size() const {
minsize.x += margin * 2;
minsize.y += margin * 3; //one as separation between hbc and child
- Size2 wmsize = WindowDialog::get_minimum_size();
+ Size2 wmsize = get_min_size();
minsize.x = MAX(wmsize.x, minsize.x);
return minsize;
}
@@ -551,7 +265,7 @@ Button *AcceptDialog::add_cancel(const String &p_cancel) {
if (p_cancel == "")
c = RTR("Cancel");
Button *b = swap_ok_cancel ? add_button(c, true) : add_button(c);
- b->connect("pressed", callable_mp(this, &AcceptDialog::_on_close_pressed));
+ b->connect("pressed", callable_mp(this, &AcceptDialog::_cancel_pressed));
return b;
}
@@ -570,6 +284,7 @@ void AcceptDialog::_bind_methods() {
ClassDB::bind_method(D_METHOD("has_autowrap"), &AcceptDialog::has_autowrap);
ADD_SIGNAL(MethodInfo("confirmed"));
+ ADD_SIGNAL(MethodInfo("cancelled"));
ADD_SIGNAL(MethodInfo("custom_action", PropertyInfo(Variant::STRING_NAME, "action")));
ADD_GROUP("Dialog", "dialog");
@@ -586,12 +301,23 @@ void AcceptDialog::set_swap_ok_cancel(bool p_swap) {
AcceptDialog::AcceptDialog() {
- int margin = get_constant("margin", "Dialogs");
- int button_margin = get_constant("button_margin", "Dialogs");
+ parent_visible = nullptr;
+
+ set_wrap_controls(true);
+ set_visible(false);
+ set_transient(true);
+
+ bg = memnew(Panel);
+ add_child(bg);
+
+ hbc = memnew(HBoxContainer);
+
+ int margin = hbc->get_theme_constant("margin", "Dialogs");
+ int button_margin = hbc->get_theme_constant("button_margin", "Dialogs");
label = memnew(Label);
- label->set_anchor(MARGIN_RIGHT, ANCHOR_END);
- label->set_anchor(MARGIN_BOTTOM, ANCHOR_END);
+ label->set_anchor(MARGIN_RIGHT, Control::ANCHOR_END);
+ label->set_anchor(MARGIN_BOTTOM, Control::ANCHOR_END);
label->set_begin(Point2(margin, margin));
label->set_end(Point2(-margin, -button_margin - 10));
add_child(label);
@@ -606,10 +332,11 @@ AcceptDialog::AcceptDialog() {
hbc->add_spacer();
ok->connect("pressed", callable_mp(this, &AcceptDialog::_ok_pressed));
- set_as_toplevel(true);
hide_on_ok = true;
set_title(RTR("Alert!"));
+
+ connect("window_input", callable_mp(this, &AcceptDialog::_input_from_window));
}
AcceptDialog::~AcceptDialog() {
@@ -631,7 +358,7 @@ ConfirmationDialog::ConfirmationDialog() {
set_title(RTR("Please Confirm..."));
#ifdef TOOLS_ENABLED
- set_custom_minimum_size(Size2(200, 70) * EDSCALE);
+ set_min_size(Size2(200, 70) * EDSCALE);
#endif
cancel = add_cancel();
}
diff --git a/scene/gui/dialogs.h b/scene/gui/dialogs.h
index c474f7849d..b68b4297d7 100644
--- a/scene/gui/dialogs.h
+++ b/scene/gui/dialogs.h
@@ -37,91 +37,32 @@
#include "scene/gui/panel.h"
#include "scene/gui/popup.h"
#include "scene/gui/texture_button.h"
-
-class WindowDialog : public Popup {
-
- GDCLASS(WindowDialog, Popup);
-
- enum DRAG_TYPE {
- DRAG_NONE = 0,
- DRAG_MOVE = 1,
- DRAG_RESIZE_TOP = 1 << 1,
- DRAG_RESIZE_RIGHT = 1 << 2,
- DRAG_RESIZE_BOTTOM = 1 << 3,
- DRAG_RESIZE_LEFT = 1 << 4
- };
-
- TextureButton *close_button;
- String title;
- String xl_title;
- int drag_type;
- Point2 drag_offset;
- Point2 drag_offset_far;
- bool resizable;
-
-#ifdef TOOLS_ENABLED
- bool was_editor_dimmed;
-#endif
-
- void _gui_input(const Ref<InputEvent> &p_event);
- int _drag_hit_test(const Point2 &pos) const;
-
-protected:
- virtual void _post_popup();
- virtual void _fix_size();
- virtual void _close_pressed() {}
- virtual bool has_point(const Point2 &p_point) const;
- void _notification(int p_what);
- static void _bind_methods();
-
- // Not private since used by derived classes signal.
- void _closed();
-
-public:
- TextureButton *get_close_button();
-
- void set_title(const String &p_title);
- String get_title() const;
- void set_resizable(bool p_resizable);
- bool get_resizable() const;
-
- Size2 get_minimum_size() const;
-
- WindowDialog();
- ~WindowDialog();
-};
-
-class PopupDialog : public Popup {
-
- GDCLASS(PopupDialog, Popup);
-
-protected:
- void _notification(int p_what);
-
-public:
- PopupDialog();
- ~PopupDialog();
-};
+#include "scene/main/window.h"
class LineEdit;
-class AcceptDialog : public WindowDialog {
+class AcceptDialog : public Window {
- GDCLASS(AcceptDialog, WindowDialog);
+ GDCLASS(AcceptDialog, Window);
+ Window *parent_visible;
+ Panel *bg;
HBoxContainer *hbc;
Label *label;
Button *ok;
bool hide_on_ok;
void _custom_action(const String &p_action);
- void _close_pressed();
void _update_child_rects();
static bool swap_ok_cancel;
+ void _input_from_window(const Ref<InputEvent> &p_event);
+ void _parent_focused();
+
protected:
- virtual void _post_popup();
+ virtual Size2 _get_contents_minimum_size() const;
+
void _notification(int p_what);
static void _bind_methods();
virtual void ok_pressed() {}
@@ -131,11 +72,9 @@ protected:
// Not private since used by derived classes signal.
void _text_entered(const String &p_text);
void _ok_pressed();
- void _on_close_pressed();
+ void _cancel_pressed();
public:
- Size2 get_minimum_size() const;
-
Label *get_label() { return label; }
static void set_swap_ok_cancel(bool p_swap);
diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp
index 3be77ff4b3..a4f0338f00 100644
--- a/scene/gui/file_dialog.cpp
+++ b/scene/gui/file_dialog.cpp
@@ -44,42 +44,46 @@ VBoxContainer *FileDialog::get_vbox() {
return vbox;
}
-void FileDialog::_notification(int p_what) {
+void FileDialog::_theme_changed() {
- if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) {
+ Color font_color = vbc->get_theme_color("font_color", "ToolButton");
+ Color font_color_hover = vbc->get_theme_color("font_color_hover", "ToolButton");
+ Color font_color_pressed = vbc->get_theme_color("font_color_pressed", "ToolButton");
- if (p_what == NOTIFICATION_ENTER_TREE) {
- dir_up->set_icon(get_icon("parent_folder"));
- refresh->set_icon(get_icon("reload"));
- show_hidden->set_icon(get_icon("toggle_hidden"));
- }
+ dir_up->add_theme_color_override("icon_color_normal", font_color);
+ dir_up->add_theme_color_override("icon_color_hover", font_color_hover);
+ dir_up->add_theme_color_override("icon_color_pressed", font_color_pressed);
- Color font_color = get_color("font_color", "ToolButton");
- Color font_color_hover = get_color("font_color_hover", "ToolButton");
- Color font_color_pressed = get_color("font_color_pressed", "ToolButton");
+ refresh->add_theme_color_override("icon_color_normal", font_color);
+ refresh->add_theme_color_override("icon_color_hover", font_color_hover);
+ refresh->add_theme_color_override("icon_color_pressed", font_color_pressed);
- dir_up->add_color_override("icon_color_normal", font_color);
- dir_up->add_color_override("icon_color_hover", font_color_hover);
- dir_up->add_color_override("icon_color_pressed", font_color_pressed);
+ show_hidden->add_theme_color_override("icon_color_normal", font_color);
+ show_hidden->add_theme_color_override("icon_color_hover", font_color_hover);
+ show_hidden->add_theme_color_override("icon_color_pressed", font_color_pressed);
+}
- refresh->add_color_override("icon_color_normal", font_color);
- refresh->add_color_override("icon_color_hover", font_color_hover);
- refresh->add_color_override("icon_color_pressed", font_color_pressed);
+void FileDialog::_notification(int p_what) {
- show_hidden->add_color_override("icon_color_normal", font_color);
- show_hidden->add_color_override("icon_color_hover", font_color_hover);
- show_hidden->add_color_override("icon_color_pressed", font_color_pressed);
+ if (p_what == NOTIFICATION_VISIBILITY_CHANGED) {
+ if (!is_visible()) {
- } else if (p_what == NOTIFICATION_POPUP_HIDE) {
+ set_process_unhandled_input(false);
+ }
+ }
+ if (p_what == NOTIFICATION_ENTER_TREE) {
- set_process_unhandled_input(false);
+ dir_up->set_icon(vbc->get_theme_icon("parent_folder"));
+ refresh->set_icon(vbc->get_theme_icon("reload"));
+ show_hidden->set_icon(vbc->get_theme_icon("toggle_hidden"));
+ _theme_changed();
}
}
void FileDialog::_unhandled_input(const Ref<InputEvent> &p_event) {
Ref<InputEventKey> k = p_event;
- if (k.is_valid() && is_window_modal_on_top()) {
+ if (k.is_valid() && has_focus()) {
if (k->is_pressed()) {
@@ -110,7 +114,7 @@ void FileDialog::_unhandled_input(const Ref<InputEvent> &p_event) {
}
if (handled)
- accept_event();
+ set_input_as_handled();
}
}
}
@@ -171,7 +175,7 @@ void FileDialog::_post_popup() {
update_file_list();
invalidated = false;
}
- if (mode == MODE_SAVE_FILE)
+ if (mode == FILE_MODE_SAVE_FILE)
file->grab_focus();
else
tree->grab_focus();
@@ -179,7 +183,7 @@ void FileDialog::_post_popup() {
set_process_unhandled_input(true);
// For open dir mode, deselect all items on file dialog open.
- if (mode == MODE_OPEN_DIR) {
+ if (mode == FILE_MODE_OPEN_DIR) {
deselect_items();
file_box->set_visible(false);
} else {
@@ -189,7 +193,7 @@ void FileDialog::_post_popup() {
void FileDialog::_action_pressed() {
- if (mode == MODE_OPEN_FILES) {
+ if (mode == FILE_MODE_OPEN_FILES) {
TreeItem *ti = tree->get_next_selected(NULL);
String fbase = dir_access->get_current_dir();
@@ -211,10 +215,10 @@ void FileDialog::_action_pressed() {
String f = dir_access->get_current_dir().plus_file(file->get_text());
- if ((mode == MODE_OPEN_ANY || mode == MODE_OPEN_FILE) && dir_access->file_exists(f)) {
+ if ((mode == FILE_MODE_OPEN_ANY || mode == FILE_MODE_OPEN_FILE) && dir_access->file_exists(f)) {
emit_signal("file_selected", f);
hide();
- } else if (mode == MODE_OPEN_ANY || mode == MODE_OPEN_DIR) {
+ } else if (mode == FILE_MODE_OPEN_ANY || mode == FILE_MODE_OPEN_DIR) {
String path = dir_access->get_current_dir();
@@ -231,7 +235,7 @@ void FileDialog::_action_pressed() {
hide();
}
- if (mode == MODE_SAVE_FILE) {
+ if (mode == FILE_MODE_SAVE_FILE) {
bool valid = false;
@@ -283,7 +287,7 @@ void FileDialog::_action_pressed() {
if (!valid) {
- exterr->popup_centered_minsize(Size2(250, 80));
+ exterr->popup_centered(Size2(250, 80));
return;
}
@@ -307,7 +311,7 @@ void FileDialog::_cancel_pressed() {
bool FileDialog::_is_open_should_be_disabled() {
- if (mode == MODE_OPEN_ANY || mode == MODE_SAVE_FILE)
+ if (mode == FILE_MODE_OPEN_ANY || mode == FILE_MODE_SAVE_FILE)
return false;
TreeItem *ti = tree->get_next_selected(tree->get_root());
@@ -319,13 +323,13 @@ bool FileDialog::_is_open_should_be_disabled() {
}
// We have something that we can't select?
if (!ti)
- return mode != MODE_OPEN_DIR; // In "Open folder" mode, having nothing selected picks the current folder.
+ return mode != FILE_MODE_OPEN_DIR; // In "Open folder" mode, having nothing selected picks the current folder.
Dictionary d = ti->get_metadata(0);
// Opening a file, but selected a folder? Forbidden.
- return ((mode == MODE_OPEN_FILE || mode == MODE_OPEN_FILES) && d["dir"]) || // Flipped case, also forbidden.
- (mode == MODE_OPEN_DIR && !d["dir"]);
+ return ((mode == FILE_MODE_OPEN_FILE || mode == FILE_MODE_OPEN_FILES) && d["dir"]) || // Flipped case, also forbidden.
+ (mode == FILE_MODE_OPEN_DIR && !d["dir"]);
}
void FileDialog::_go_up() {
@@ -346,15 +350,15 @@ void FileDialog::deselect_items() {
switch (mode) {
- case MODE_OPEN_FILE:
- case MODE_OPEN_FILES:
+ case FILE_MODE_OPEN_FILE:
+ case FILE_MODE_OPEN_FILES:
get_ok()->set_text(RTR("Open"));
break;
- case MODE_OPEN_DIR:
+ case FILE_MODE_OPEN_DIR:
get_ok()->set_text(RTR("Select Current Folder"));
break;
- case MODE_OPEN_ANY:
- case MODE_SAVE_FILE:
+ case FILE_MODE_OPEN_ANY:
+ case FILE_MODE_SAVE_FILE:
// FIXME: Implement, or refactor to avoid duplication with set_mode
break;
}
@@ -375,7 +379,7 @@ void FileDialog::_tree_selected() {
if (!d["dir"]) {
file->set_text(d["name"]);
- } else if (mode == MODE_OPEN_DIR) {
+ } else if (mode == FILE_MODE_OPEN_DIR) {
get_ok()->set_text(RTR("Select This Folder"));
}
@@ -393,7 +397,7 @@ void FileDialog::_tree_item_activated() {
if (d["dir"]) {
dir_access->change_dir(d["name"]);
- if (mode == MODE_OPEN_FILE || mode == MODE_OPEN_FILES || mode == MODE_OPEN_DIR || mode == MODE_OPEN_ANY)
+ if (mode == FILE_MODE_OPEN_FILE || mode == FILE_MODE_OPEN_FILES || mode == FILE_MODE_OPEN_DIR || mode == FILE_MODE_OPEN_ANY)
file->set_text("");
call_deferred("_update_file_list");
call_deferred("_update_dir");
@@ -425,8 +429,8 @@ void FileDialog::update_file_list() {
dir_access->list_dir_begin();
TreeItem *root = tree->create_item();
- Ref<Texture2D> folder = get_icon("folder");
- const Color folder_color = get_color("folder_icon_modulate");
+ Ref<Texture2D> folder = vbc->get_theme_icon("folder");
+ const Color folder_color = vbc->get_theme_color("folder_icon_modulate");
List<String> files;
List<String> dirs;
@@ -523,8 +527,8 @@ void FileDialog::update_file_list() {
ti->set_icon(0, icon);
}
- if (mode == MODE_OPEN_DIR) {
- ti->set_custom_color(0, get_color("files_disabled"));
+ if (mode == FILE_MODE_OPEN_DIR) {
+ ti->set_custom_color(0, vbc->get_theme_color("files_disabled"));
ti->set_selectable(0, false);
}
Dictionary d;
@@ -661,38 +665,38 @@ bool FileDialog::is_mode_overriding_title() const {
return mode_overrides_title;
}
-void FileDialog::set_mode(Mode p_mode) {
+void FileDialog::set_file_mode(FileMode p_mode) {
ERR_FAIL_INDEX((int)p_mode, 5);
mode = p_mode;
switch (mode) {
- case MODE_OPEN_FILE:
+ case FILE_MODE_OPEN_FILE:
get_ok()->set_text(RTR("Open"));
if (mode_overrides_title)
set_title(RTR("Open a File"));
makedir->hide();
break;
- case MODE_OPEN_FILES:
+ case FILE_MODE_OPEN_FILES:
get_ok()->set_text(RTR("Open"));
if (mode_overrides_title)
set_title(RTR("Open File(s)"));
makedir->hide();
break;
- case MODE_OPEN_DIR:
+ case FILE_MODE_OPEN_DIR:
get_ok()->set_text(RTR("Select Current Folder"));
if (mode_overrides_title)
set_title(RTR("Open a Directory"));
makedir->show();
break;
- case MODE_OPEN_ANY:
+ case FILE_MODE_OPEN_ANY:
get_ok()->set_text(RTR("Open"));
if (mode_overrides_title)
set_title(RTR("Open a File or Directory"));
makedir->show();
break;
- case MODE_SAVE_FILE:
+ case FILE_MODE_SAVE_FILE:
get_ok()->set_text(RTR("Save"));
if (mode_overrides_title)
set_title(RTR("Save a File"));
@@ -700,14 +704,14 @@ void FileDialog::set_mode(Mode p_mode) {
break;
}
- if (mode == MODE_OPEN_FILES) {
+ if (mode == FILE_MODE_OPEN_FILES) {
tree->set_select_mode(Tree::SELECT_MULTI);
} else {
tree->set_select_mode(Tree::SELECT_SINGLE);
}
}
-FileDialog::Mode FileDialog::get_mode() const {
+FileDialog::FileMode FileDialog::get_file_mode() const {
return mode;
}
@@ -741,7 +745,7 @@ void FileDialog::set_access(Access p_access) {
void FileDialog::invalidate() {
- if (is_visible_in_tree()) {
+ if (is_visible()) {
update_file_list();
invalidated = false;
} else {
@@ -763,14 +767,14 @@ void FileDialog::_make_dir_confirm() {
update_filters();
update_dir();
} else {
- mkdirerr->popup_centered_minsize(Size2(250, 50));
+ mkdirerr->popup_centered(Size2(250, 50));
}
makedirname->set_text(""); // reset label
}
void FileDialog::_make_dir() {
- makedialog->popup_centered_minsize(Size2(250, 80));
+ makedialog->popup_centered(Size2(250, 80));
makedirname->grab_focus();
}
@@ -826,8 +830,8 @@ void FileDialog::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_current_path", "path"), &FileDialog::set_current_path);
ClassDB::bind_method(D_METHOD("set_mode_overrides_title", "override"), &FileDialog::set_mode_overrides_title);
ClassDB::bind_method(D_METHOD("is_mode_overriding_title"), &FileDialog::is_mode_overriding_title);
- ClassDB::bind_method(D_METHOD("set_mode", "mode"), &FileDialog::set_mode);
- ClassDB::bind_method(D_METHOD("get_mode"), &FileDialog::get_mode);
+ ClassDB::bind_method(D_METHOD("set_file_mode", "mode"), &FileDialog::set_file_mode);
+ ClassDB::bind_method(D_METHOD("get_file_mode"), &FileDialog::get_file_mode);
ClassDB::bind_method(D_METHOD("get_vbox"), &FileDialog::get_vbox);
ClassDB::bind_method(D_METHOD("get_line_edit"), &FileDialog::get_line_edit);
ClassDB::bind_method(D_METHOD("set_access", "access"), &FileDialog::set_access);
@@ -842,7 +846,7 @@ void FileDialog::_bind_methods() {
ClassDB::bind_method(D_METHOD("invalidate"), &FileDialog::invalidate);
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "mode_overrides_title"), "set_mode_overrides_title", "is_mode_overriding_title");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Open File,Open Files,Open Folder,Open Any,Save"), "set_mode", "get_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "file_mode", PROPERTY_HINT_ENUM, "Open File,Open Files,Open Folder,Open Any,Save"), "set_file_mode", "get_file_mode");
ADD_PROPERTY(PropertyInfo(Variant::INT, "access", PROPERTY_HINT_ENUM, "Resources,User data,File system"), "set_access", "get_access");
ADD_PROPERTY(PropertyInfo(Variant::PACKED_STRING_ARRAY, "filters"), "set_filters", "get_filters");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "show_hidden_files"), "set_show_hidden_files", "is_showing_hidden_files");
@@ -854,11 +858,11 @@ void FileDialog::_bind_methods() {
ADD_SIGNAL(MethodInfo("files_selected", PropertyInfo(Variant::PACKED_STRING_ARRAY, "paths")));
ADD_SIGNAL(MethodInfo("dir_selected", PropertyInfo(Variant::STRING, "dir")));
- BIND_ENUM_CONSTANT(MODE_OPEN_FILE);
- BIND_ENUM_CONSTANT(MODE_OPEN_FILES);
- BIND_ENUM_CONSTANT(MODE_OPEN_DIR);
- BIND_ENUM_CONSTANT(MODE_OPEN_ANY);
- BIND_ENUM_CONSTANT(MODE_SAVE_FILE);
+ BIND_ENUM_CONSTANT(FILE_MODE_OPEN_FILE);
+ BIND_ENUM_CONSTANT(FILE_MODE_OPEN_FILES);
+ BIND_ENUM_CONSTANT(FILE_MODE_OPEN_DIR);
+ BIND_ENUM_CONSTANT(FILE_MODE_OPEN_ANY);
+ BIND_ENUM_CONSTANT(FILE_MODE_SAVE_FILE);
BIND_ENUM_CONSTANT(ACCESS_RESOURCES);
BIND_ENUM_CONSTANT(ACCESS_USERDATA);
@@ -884,10 +888,11 @@ FileDialog::FileDialog() {
mode_overrides_title = true;
- VBoxContainer *vbc = memnew(VBoxContainer);
+ vbc = memnew(VBoxContainer);
add_child(vbc);
+ vbc->connect("theme_changed", callable_mp(this, &FileDialog::_theme_changed));
- mode = MODE_SAVE_FILE;
+ mode = FILE_MODE_SAVE_FILE;
set_title(RTR("Save a File"));
HBoxContainer *hbc = memnew(HBoxContainer);
@@ -907,7 +912,7 @@ FileDialog::FileDialog() {
dir = memnew(LineEdit);
hbc->add_child(dir);
- dir->set_h_size_flags(SIZE_EXPAND_FILL);
+ dir->set_h_size_flags(Control::SIZE_EXPAND_FILL);
refresh = memnew(ToolButton);
refresh->set_tooltip(RTR("Refresh files."));
@@ -938,11 +943,11 @@ FileDialog::FileDialog() {
file_box->add_child(memnew(Label(RTR("File:"))));
file = memnew(LineEdit);
file->set_stretch_ratio(4);
- file->set_h_size_flags(SIZE_EXPAND_FILL);
+ file->set_h_size_flags(Control::SIZE_EXPAND_FILL);
file_box->add_child(file);
filter = memnew(OptionButton);
filter->set_stretch_ratio(3);
- filter->set_h_size_flags(SIZE_EXPAND_FILL);
+ filter->set_h_size_flags(Control::SIZE_EXPAND_FILL);
filter->set_clip_text(true); // too many extensions overflows it
file_box->add_child(filter);
vbc->add_child(file_box);
@@ -961,7 +966,7 @@ FileDialog::FileDialog() {
filter->connect("item_selected", callable_mp(this, &FileDialog::_filter_selected));
confirm_save = memnew(ConfirmationDialog);
- confirm_save->set_as_toplevel(true);
+ // confirm_save->set_as_toplevel(true);
add_child(confirm_save);
confirm_save->connect("confirmed", callable_mp(this, &FileDialog::_save_confirm_pressed));
@@ -1024,7 +1029,7 @@ LineEditFileChooser::LineEditFileChooser() {
line_edit = memnew(LineEdit);
add_child(line_edit);
- line_edit->set_h_size_flags(SIZE_EXPAND_FILL);
+ line_edit->set_h_size_flags(Control::SIZE_EXPAND_FILL);
button = memnew(Button);
button->set_text(" .. ");
add_child(button);
diff --git a/scene/gui/file_dialog.h b/scene/gui/file_dialog.h
index a7dc101d12..295ae023d1 100644
--- a/scene/gui/file_dialog.h
+++ b/scene/gui/file_dialog.h
@@ -50,12 +50,12 @@ public:
ACCESS_FILESYSTEM
};
- enum Mode {
- MODE_OPEN_FILE,
- MODE_OPEN_FILES,
- MODE_OPEN_DIR,
- MODE_OPEN_ANY,
- MODE_SAVE_FILE
+ enum FileMode {
+ FILE_MODE_OPEN_FILE,
+ FILE_MODE_OPEN_FILES,
+ FILE_MODE_OPEN_DIR,
+ FILE_MODE_OPEN_ANY,
+ FILE_MODE_SAVE_FILE
};
typedef Ref<Texture2D> (*GetIconFunc)(const String &);
@@ -70,11 +70,12 @@ private:
ConfirmationDialog *makedialog;
LineEdit *makedirname;
+ VBoxContainer *vbc;
Button *makedir;
Access access;
//Button *action;
VBoxContainer *vbox;
- Mode mode;
+ FileMode mode;
LineEdit *dir;
HBoxContainer *drives_container;
HBoxContainer *shortcuts_container;
@@ -131,6 +132,8 @@ private:
virtual void _post_popup();
protected:
+ void _theme_changed();
+
void _notification(int p_what);
static void _bind_methods();
//bind helpers
@@ -153,8 +156,8 @@ public:
void set_mode_overrides_title(bool p_override);
bool is_mode_overriding_title() const;
- void set_mode(Mode p_mode);
- Mode get_mode() const;
+ void set_file_mode(FileMode p_mode);
+ FileMode get_file_mode() const;
VBoxContainer *get_vbox();
LineEdit *get_line_edit() { return file; }
@@ -196,7 +199,7 @@ public:
LineEditFileChooser();
};
-VARIANT_ENUM_CAST(FileDialog::Mode);
+VARIANT_ENUM_CAST(FileDialog::FileMode);
VARIANT_ENUM_CAST(FileDialog::Access);
#endif
diff --git a/scene/gui/gradient_edit.cpp b/scene/gui/gradient_edit.cpp
index 6345bfe562..88107f754c 100644
--- a/scene/gui/gradient_edit.cpp
+++ b/scene/gui/gradient_edit.cpp
@@ -76,15 +76,15 @@ void GradientEdit::_show_color_picker() {
if (grabbed == -1)
return;
picker->set_pick_color(points[grabbed].color);
- Size2 minsize = popup->get_combined_minimum_size();
+ Size2 minsize = popup->get_contents_minimum_size();
bool show_above = false;
if (get_global_position().y + get_size().y + minsize.y > get_viewport_rect().size.y) {
show_above = true;
}
if (show_above) {
- popup->set_position(get_global_position() - Vector2(0, minsize.y));
+ popup->set_position(get_screen_position() - Vector2(0, minsize.y));
} else {
- popup->set_position(get_global_position() + Vector2(0, get_size().y));
+ popup->set_position(get_screen_position() + Vector2(0, get_size().y));
}
popup->popup();
}
diff --git a/scene/gui/graph_edit.cpp b/scene/gui/graph_edit.cpp
index 4bc33b220e..fd7935b376 100644
--- a/scene/gui/graph_edit.cpp
+++ b/scene/gui/graph_edit.cpp
@@ -30,7 +30,7 @@
#include "graph_edit.h"
-#include "core/os/input.h"
+#include "core/input/input_filter.h"
#include "core/os/keyboard.h"
#include "scene/gui/box_container.h"
@@ -281,13 +281,13 @@ void GraphEdit::remove_child_notify(Node *p_child) {
void GraphEdit::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE || p_what == NOTIFICATION_THEME_CHANGED) {
- port_grab_distance_horizontal = get_constant("port_grab_distance_horizontal");
- port_grab_distance_vertical = get_constant("port_grab_distance_vertical");
+ port_grab_distance_horizontal = get_theme_constant("port_grab_distance_horizontal");
+ port_grab_distance_vertical = get_theme_constant("port_grab_distance_vertical");
- zoom_minus->set_icon(get_icon("minus"));
- zoom_reset->set_icon(get_icon("reset"));
- zoom_plus->set_icon(get_icon("more"));
- snap_button->set_icon(get_icon("snap"));
+ zoom_minus->set_icon(get_theme_icon("minus"));
+ zoom_reset->set_icon(get_theme_icon("reset"));
+ zoom_plus->set_icon(get_theme_icon("more"));
+ snap_button->set_icon(get_theme_icon("snap"));
}
if (p_what == NOTIFICATION_READY) {
Size2 hmin = h_scroll->get_combined_minimum_size();
@@ -305,7 +305,7 @@ void GraphEdit::_notification(int p_what) {
}
if (p_what == NOTIFICATION_DRAW) {
- draw_style_box(get_stylebox("bg"), Rect2(Point2(), get_size()));
+ draw_style_box(get_theme_stylebox("bg"), Rect2(Point2(), get_size()));
if (is_using_snap()) {
//draw grid
@@ -318,8 +318,8 @@ void GraphEdit::_notification(int p_what) {
Point2i from = (offset / float(snap)).floor();
Point2i len = (size / float(snap)).floor() + Vector2(1, 1);
- Color grid_minor = get_color("grid_minor");
- Color grid_major = get_color("grid_major");
+ Color grid_minor = get_theme_color("grid_minor");
+ Color grid_major = get_theme_color("grid_major");
for (int i = from.x; i < from.x + len.x; i++) {
@@ -357,7 +357,7 @@ void GraphEdit::_notification(int p_what) {
bool GraphEdit::_filter_input(const Point2 &p_point) {
- Ref<Texture2D> port = get_icon("port", "GraphNode");
+ Ref<Texture2D> port = get_theme_icon("port", "GraphNode");
for (int i = get_child_count() - 1; i >= 0; i--) {
@@ -389,7 +389,7 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) {
Ref<InputEventMouseButton> mb = p_ev;
if (mb.is_valid() && mb->get_button_index() == BUTTON_LEFT && mb->is_pressed()) {
- Ref<Texture2D> port = get_icon("port", "GraphNode");
+ Ref<Texture2D> port = get_theme_icon("port", "GraphNode");
Vector2 mpos(mb->get_position().x, mb->get_position().y);
for (int i = get_child_count() - 1; i >= 0; i--) {
@@ -501,7 +501,7 @@ void GraphEdit::_top_layer_input(const Ref<InputEvent> &p_ev) {
connecting_target = false;
top_layer->update();
- Ref<Texture2D> port = get_icon("port", "GraphNode");
+ Ref<Texture2D> port = get_theme_icon("port", "GraphNode");
Vector2 mpos = mm->get_position();
for (int i = get_child_count() - 1; i >= 0; i--) {
@@ -666,8 +666,8 @@ void GraphEdit::_draw_cos_line(CanvasItem *p_where, const Vector2 &p_from, const
//cubic bezier code
float diff = p_to.x - p_from.x;
float cp_offset;
- int cp_len = get_constant("bezier_len_pos");
- int cp_neg_len = get_constant("bezier_len_neg");
+ int cp_len = get_theme_constant("bezier_len_pos");
+ int cp_neg_len = get_theme_constant("bezier_len_neg");
if (diff > 0) {
cp_offset = MIN(cp_len, diff * 0.5);
@@ -697,7 +697,7 @@ void GraphEdit::_draw_cos_line(CanvasItem *p_where, const Vector2 &p_from, const
void GraphEdit::_connections_layer_draw() {
- Color activity_color = get_color("activity");
+ Color activity_color = get_theme_color("activity");
//draw connections
List<List<Connection>::Element *> to_erase;
for (List<Connection>::Element *E = connections.front(); E; E = E->next()) {
@@ -784,8 +784,8 @@ void GraphEdit::_top_layer_draw() {
}
if (box_selecting) {
- top_layer->draw_rect(box_selecting_rect, get_color("selection_fill"));
- top_layer->draw_rect(box_selecting_rect, get_color("selection_stroke"), false);
+ top_layer->draw_rect(box_selecting_rect, get_theme_color("selection_fill"));
+ top_layer->draw_rect(box_selecting_rect, get_theme_color("selection_stroke"), false);
}
}
@@ -804,7 +804,7 @@ void GraphEdit::set_selected(Node *p_child) {
void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) {
Ref<InputEventMouseMotion> mm = p_ev;
- if (mm.is_valid() && (mm->get_button_mask() & BUTTON_MASK_MIDDLE || (mm->get_button_mask() & BUTTON_MASK_LEFT && Input::get_singleton()->is_key_pressed(KEY_SPACE)))) {
+ if (mm.is_valid() && (mm->get_button_mask() & BUTTON_MASK_MIDDLE || (mm->get_button_mask() & BUTTON_MASK_LEFT && InputFilter::get_singleton()->is_key_pressed(KEY_SPACE)))) {
h_scroll->set_value(h_scroll->get_value() - mm->get_relative().x);
v_scroll->set_value(v_scroll->get_value() - mm->get_relative().y);
}
@@ -823,7 +823,7 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) {
// Snapping can be toggled temporarily by holding down Ctrl.
// This is done here as to not toggle the grid when holding down Ctrl.
- if (is_using_snap() ^ Input::get_singleton()->is_key_pressed(KEY_CONTROL)) {
+ if (is_using_snap() ^ InputFilter::get_singleton()->is_key_pressed(KEY_CONTROL)) {
const int snap = get_snap();
pos = pos.snapped(Vector2(snap, snap));
}
@@ -886,7 +886,7 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) {
}
if (b->get_button_index() == BUTTON_LEFT && !b->is_pressed() && dragging) {
- if (!just_selected && drag_accum == Vector2() && Input::get_singleton()->is_key_pressed(KEY_CONTROL)) {
+ if (!just_selected && drag_accum == Vector2() && InputFilter::get_singleton()->is_key_pressed(KEY_CONTROL)) {
//deselect current node
for (int i = get_child_count() - 1; i >= 0; i--) {
GraphNode *gn = Object::cast_to<GraphNode>(get_child(i));
@@ -948,7 +948,7 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) {
drag_accum = Vector2();
drag_origin = get_local_mouse_position();
just_selected = !gn->is_selected();
- if (!gn->is_selected() && !Input::get_singleton()->is_key_pressed(KEY_CONTROL)) {
+ if (!gn->is_selected() && !InputFilter::get_singleton()->is_key_pressed(KEY_CONTROL)) {
for (int i = 0; i < get_child_count(); i++) {
GraphNode *o_gn = Object::cast_to<GraphNode>(get_child(i));
if (o_gn)
@@ -968,7 +968,7 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) {
} else {
if (_filter_input(b->get_position()))
return;
- if (Input::get_singleton()->is_key_pressed(KEY_SPACE))
+ if (InputFilter::get_singleton()->is_key_pressed(KEY_SPACE))
return;
box_selecting = true;
@@ -1025,16 +1025,16 @@ void GraphEdit::_gui_input(const Ref<InputEvent> &p_ev) {
//too difficult to get right
//set_zoom(zoom/ZOOM_SCALE);
}
- if (b->get_button_index() == BUTTON_WHEEL_UP && !Input::get_singleton()->is_key_pressed(KEY_SHIFT)) {
+ if (b->get_button_index() == BUTTON_WHEEL_UP && !InputFilter::get_singleton()->is_key_pressed(KEY_SHIFT)) {
v_scroll->set_value(v_scroll->get_value() - v_scroll->get_page() * b->get_factor() / 8);
}
- if (b->get_button_index() == BUTTON_WHEEL_DOWN && !Input::get_singleton()->is_key_pressed(KEY_SHIFT)) {
+ if (b->get_button_index() == BUTTON_WHEEL_DOWN && !InputFilter::get_singleton()->is_key_pressed(KEY_SHIFT)) {
v_scroll->set_value(v_scroll->get_value() + v_scroll->get_page() * b->get_factor() / 8);
}
- if (b->get_button_index() == BUTTON_WHEEL_RIGHT || (b->get_button_index() == BUTTON_WHEEL_DOWN && Input::get_singleton()->is_key_pressed(KEY_SHIFT))) {
+ if (b->get_button_index() == BUTTON_WHEEL_RIGHT || (b->get_button_index() == BUTTON_WHEEL_DOWN && InputFilter::get_singleton()->is_key_pressed(KEY_SHIFT))) {
h_scroll->set_value(h_scroll->get_value() + h_scroll->get_page() * b->get_factor() / 8);
}
- if (b->get_button_index() == BUTTON_WHEEL_LEFT || (b->get_button_index() == BUTTON_WHEEL_UP && Input::get_singleton()->is_key_pressed(KEY_SHIFT))) {
+ if (b->get_button_index() == BUTTON_WHEEL_LEFT || (b->get_button_index() == BUTTON_WHEEL_UP && InputFilter::get_singleton()->is_key_pressed(KEY_SHIFT))) {
h_scroll->set_value(h_scroll->get_value() - h_scroll->get_page() * b->get_factor() / 8);
}
}
diff --git a/scene/gui/graph_node.cpp b/scene/gui/graph_node.cpp
index 82e890395a..c28a60ff87 100644
--- a/scene/gui/graph_node.cpp
+++ b/scene/gui/graph_node.cpp
@@ -117,8 +117,8 @@ void GraphNode::_get_property_list(List<PropertyInfo> *p_list) const {
void GraphNode::_resort() {
- int sep = get_constant("separation");
- Ref<StyleBox> sb = get_stylebox("frame");
+ int sep = get_theme_constant("separation");
+ Ref<StyleBox> sb = get_theme_stylebox("frame");
bool first = true;
Size2 minsize;
@@ -169,8 +169,8 @@ void GraphNode::_resort() {
bool GraphNode::has_point(const Point2 &p_point) const {
if (comment) {
- Ref<StyleBox> comment = get_stylebox("comment");
- Ref<Texture2D> resizer = get_icon("resizer");
+ Ref<StyleBox> comment = get_theme_stylebox("comment");
+ Ref<Texture2D> resizer = get_theme_icon("resizer");
if (Rect2(get_size() - resizer->get_size(), resizer->get_size()).has_point(p_point)) {
return true;
@@ -195,28 +195,28 @@ void GraphNode::_notification(int p_what) {
Ref<StyleBox> sb;
if (comment) {
- sb = get_stylebox(selected ? "commentfocus" : "comment");
+ sb = get_theme_stylebox(selected ? "commentfocus" : "comment");
} else {
- sb = get_stylebox(selected ? "selectedframe" : "frame");
+ sb = get_theme_stylebox(selected ? "selectedframe" : "frame");
}
//sb=sb->duplicate();
//sb->call("set_modulate",modulate);
- Ref<Texture2D> port = get_icon("port");
- Ref<Texture2D> close = get_icon("close");
- Ref<Texture2D> resizer = get_icon("resizer");
- int close_offset = get_constant("close_offset");
- int close_h_offset = get_constant("close_h_offset");
- Color close_color = get_color("close_color");
- Color resizer_color = get_color("resizer_color");
- Ref<Font> title_font = get_font("title_font");
- int title_offset = get_constant("title_offset");
- int title_h_offset = get_constant("title_h_offset");
- Color title_color = get_color("title_color");
+ Ref<Texture2D> port = get_theme_icon("port");
+ Ref<Texture2D> close = get_theme_icon("close");
+ Ref<Texture2D> resizer = get_theme_icon("resizer");
+ int close_offset = get_theme_constant("close_offset");
+ int close_h_offset = get_theme_constant("close_h_offset");
+ Color close_color = get_theme_color("close_color");
+ Color resizer_color = get_theme_color("resizer_color");
+ Ref<Font> title_font = get_theme_font("title_font");
+ int title_offset = get_theme_constant("title_offset");
+ int title_h_offset = get_theme_constant("title_h_offset");
+ Color title_color = get_theme_color("title_color");
Point2i icofs = -port->get_size() * 0.5;
- int edgeofs = get_constant("port_offset");
+ int edgeofs = get_theme_constant("port_offset");
icofs.y += sb->get_margin(MARGIN_TOP);
draw_style_box(sb, Rect2(Point2(), get_size()));
@@ -227,10 +227,10 @@ void GraphNode::_notification(int p_what) {
} break;
case OVERLAY_BREAKPOINT: {
- draw_style_box(get_stylebox("breakpoint"), Rect2(Point2(), get_size()));
+ draw_style_box(get_theme_stylebox("breakpoint"), Rect2(Point2(), get_size()));
} break;
case OVERLAY_POSITION: {
- draw_style_box(get_stylebox("position"), Rect2(Point2(), get_size()));
+ draw_style_box(get_theme_stylebox("position"), Rect2(Point2(), get_size()));
} break;
}
@@ -370,16 +370,16 @@ Color GraphNode::get_slot_color_right(int p_idx) const {
Size2 GraphNode::get_minimum_size() const {
- Ref<Font> title_font = get_font("title_font");
+ Ref<Font> title_font = get_theme_font("title_font");
- int sep = get_constant("separation");
- Ref<StyleBox> sb = get_stylebox("frame");
+ int sep = get_theme_constant("separation");
+ Ref<StyleBox> sb = get_theme_stylebox("frame");
bool first = true;
Size2 minsize;
minsize.x = title_font->get_string_size(title).x;
if (show_close) {
- Ref<Texture2D> close = get_icon("close");
+ Ref<Texture2D> close = get_theme_icon("close");
minsize.x += sep + close->get_width();
}
@@ -464,10 +464,10 @@ bool GraphNode::is_close_button_visible() const {
void GraphNode::_connpos_update() {
- int edgeofs = get_constant("port_offset");
- int sep = get_constant("separation");
+ int edgeofs = get_theme_constant("port_offset");
+ int sep = get_theme_constant("separation");
- Ref<StyleBox> sb = get_stylebox("frame");
+ Ref<StyleBox> sb = get_theme_stylebox("frame");
conn_input_cache.clear();
conn_output_cache.clear();
int vofs = 0;
@@ -606,7 +606,7 @@ void GraphNode::_gui_input(const Ref<InputEvent> &p_ev) {
return;
}
- Ref<Texture2D> resizer = get_icon("resizer");
+ Ref<Texture2D> resizer = get_theme_icon("resizer");
if (resizable && mpos.x > get_size().x - resizer->get_width() && mpos.y > get_size().y - resizer->get_height()) {
diff --git a/scene/gui/grid_container.cpp b/scene/gui/grid_container.cpp
index 0028093a95..16f6fd0111 100644
--- a/scene/gui/grid_container.cpp
+++ b/scene/gui/grid_container.cpp
@@ -41,8 +41,8 @@ void GridContainer::_notification(int p_what) {
Set<int> col_expanded; // Columns which have the SIZE_EXPAND flag set.
Set<int> row_expanded; // Rows which have the SIZE_EXPAND flag set.
- int hsep = get_constant("hseparation");
- int vsep = get_constant("vseparation");
+ int hsep = get_theme_constant("hseparation");
+ int vsep = get_theme_constant("vseparation");
int max_col = MIN(get_child_count(), columns);
int max_row = ceil((float)get_child_count() / (float)columns);
@@ -200,8 +200,8 @@ Size2 GridContainer::get_minimum_size() const {
Map<int, int> col_minw;
Map<int, int> row_minh;
- int hsep = get_constant("hseparation");
- int vsep = get_constant("vseparation");
+ int hsep = get_theme_constant("hseparation");
+ int vsep = get_theme_constant("vseparation");
int max_row = 0;
int max_col = 0;
diff --git a/scene/gui/item_list.cpp b/scene/gui/item_list.cpp
index 5e662b8df0..2db44d0b66 100644
--- a/scene/gui/item_list.cpp
+++ b/scene/gui/item_list.cpp
@@ -495,7 +495,7 @@ void ItemList::_gui_input(const Ref<InputEvent> &p_event) {
search_string = ""; //any mousepress cancels
Vector2 pos = mb->get_position();
- Ref<StyleBox> bg = get_stylebox("bg");
+ Ref<StyleBox> bg = get_theme_stylebox("bg");
pos -= bg->get_offset();
pos.y += scroll_bar->get_value();
@@ -820,7 +820,7 @@ void ItemList::_notification(int p_what) {
if (p_what == NOTIFICATION_DRAW) {
- Ref<StyleBox> bg = get_stylebox("bg");
+ Ref<StyleBox> bg = get_theme_stylebox("bg");
int mw = scroll_bar->get_minimum_size().x;
scroll_bar->set_anchor_and_margin(MARGIN_LEFT, ANCHOR_END, -mw);
@@ -837,18 +837,18 @@ void ItemList::_notification(int p_what) {
draw_style_box(bg, Rect2(Point2(), size));
- int hseparation = get_constant("hseparation");
- int vseparation = get_constant("vseparation");
- int icon_margin = get_constant("icon_margin");
- int line_separation = get_constant("line_separation");
+ int hseparation = get_theme_constant("hseparation");
+ int vseparation = get_theme_constant("vseparation");
+ int icon_margin = get_theme_constant("icon_margin");
+ int line_separation = get_theme_constant("line_separation");
- Ref<StyleBox> sbsel = has_focus() ? get_stylebox("selected_focus") : get_stylebox("selected");
- Ref<StyleBox> cursor = has_focus() ? get_stylebox("cursor") : get_stylebox("cursor_unfocused");
+ Ref<StyleBox> sbsel = has_focus() ? get_theme_stylebox("selected_focus") : get_theme_stylebox("selected");
+ Ref<StyleBox> cursor = has_focus() ? get_theme_stylebox("cursor") : get_theme_stylebox("cursor_unfocused");
- Ref<Font> font = get_font("font");
- Color guide_color = get_color("guide_color");
- Color font_color = get_color("font_color");
- Color font_color_selected = get_color("font_color_selected");
+ Ref<Font> font = get_theme_font("font");
+ Color guide_color = get_theme_color("guide_color");
+ Color font_color = get_theme_color("font_color");
+ Color font_color_selected = get_theme_color("font_color_selected");
int font_height = font->get_height();
Vector<int> line_size_cache;
Vector<int> line_limit_cache;
@@ -860,7 +860,7 @@ void ItemList::_notification(int p_what) {
if (has_focus()) {
VisualServer::get_singleton()->canvas_item_add_clip_ignore(get_canvas_item(), true);
- draw_style_box(get_stylebox("bg_focus"), Rect2(Point2(), size));
+ draw_style_box(get_theme_stylebox("bg_focus"), Rect2(Point2(), size));
VisualServer::get_singleton()->canvas_item_add_clip_ignore(get_canvas_item(), false);
}
@@ -1251,7 +1251,7 @@ void ItemList::_scroll_changed(double) {
int ItemList::get_item_at_position(const Point2 &p_pos, bool p_exact) const {
Vector2 pos = p_pos;
- Ref<StyleBox> bg = get_stylebox("bg");
+ Ref<StyleBox> bg = get_theme_stylebox("bg");
pos -= bg->get_offset();
pos.y += scroll_bar->get_value();
@@ -1286,7 +1286,7 @@ bool ItemList::is_pos_at_end_of_items(const Point2 &p_pos) const {
return true;
Vector2 pos = p_pos;
- Ref<StyleBox> bg = get_stylebox("bg");
+ Ref<StyleBox> bg = get_theme_stylebox("bg");
pos -= bg->get_offset();
pos.y += scroll_bar->get_value();
diff --git a/scene/gui/label.cpp b/scene/gui/label.cpp
index c900b35d65..ef1bb958f6 100644
--- a/scene/gui/label.cpp
+++ b/scene/gui/label.cpp
@@ -65,7 +65,7 @@ bool Label::is_uppercase() const {
int Label::get_line_height() const {
- return get_font("font")->get_height();
+ return get_theme_font("font")->get_height();
}
void Label::_notification(int p_what) {
@@ -94,14 +94,14 @@ void Label::_notification(int p_what) {
Size2 string_size;
Size2 size = get_size();
- Ref<StyleBox> style = get_stylebox("normal");
- Ref<Font> font = get_font("font");
- Color font_color = get_color("font_color");
- Color font_color_shadow = get_color("font_color_shadow");
- bool use_outline = get_constant("shadow_as_outline");
- Point2 shadow_ofs(get_constant("shadow_offset_x"), get_constant("shadow_offset_y"));
- int line_spacing = get_constant("line_spacing");
- Color font_outline_modulate = get_color("font_outline_modulate");
+ Ref<StyleBox> style = get_theme_stylebox("normal");
+ Ref<Font> font = get_theme_font("font");
+ Color font_color = get_theme_color("font_color");
+ Color font_color_shadow = get_theme_color("font_color_shadow");
+ bool use_outline = get_theme_constant("shadow_as_outline");
+ Point2 shadow_ofs(get_theme_constant("shadow_offset_x"), get_theme_constant("shadow_offset_y"));
+ int line_spacing = get_theme_constant("line_spacing");
+ Color font_outline_modulate = get_theme_color("font_outline_modulate");
style->draw(ci, Rect2(Point2(0, 0), get_size()));
@@ -300,7 +300,7 @@ void Label::_notification(int p_what) {
Size2 Label::get_minimum_size() const {
- Size2 min_style = get_stylebox("normal")->get_minimum_size();
+ Size2 min_style = get_theme_stylebox("normal")->get_minimum_size();
// don't want to mutable everything
if (word_cache_dirty) {
@@ -319,7 +319,7 @@ Size2 Label::get_minimum_size() const {
int Label::get_longest_line_width() const {
- Ref<Font> font = get_font("font");
+ Ref<Font> font = get_theme_font("font");
real_t max_line_width = 0;
real_t line_width = 0;
@@ -363,9 +363,9 @@ int Label::get_line_count() const {
int Label::get_visible_line_count() const {
- int line_spacing = get_constant("line_spacing");
- int font_h = get_font("font")->get_height() + line_spacing;
- int lines_visible = (get_size().height - get_stylebox("normal")->get_minimum_size().height + line_spacing) / font_h;
+ int line_spacing = get_theme_constant("line_spacing");
+ int font_h = get_theme_font("font")->get_height() + line_spacing;
+ int lines_visible = (get_size().height - get_theme_stylebox("normal")->get_minimum_size().height + line_spacing) / font_h;
if (lines_visible > line_count)
lines_visible = line_count;
@@ -387,20 +387,20 @@ void Label::regenerate_word_cache() {
int width;
if (autowrap) {
- Ref<StyleBox> style = get_stylebox("normal");
+ Ref<StyleBox> style = get_theme_stylebox("normal");
width = MAX(get_size().width, get_custom_minimum_size().width) - style->get_minimum_size().width;
} else {
width = get_longest_line_width();
}
- Ref<Font> font = get_font("font");
+ Ref<Font> font = get_theme_font("font");
real_t current_word_size = 0;
int word_pos = 0;
real_t line_width = 0;
int space_count = 0;
real_t space_width = font->get_char_size(' ').width;
- int line_spacing = get_constant("line_spacing");
+ int line_spacing = get_theme_constant("line_spacing");
line_count = 1;
total_char_cache = 0;
diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp
index 7ee4dab3c9..734e27b1b6 100644
--- a/scene/gui/line_edit.cpp
+++ b/scene/gui/line_edit.cpp
@@ -36,12 +36,12 @@
#include "core/print_string.h"
#include "core/translation.h"
#include "label.h"
-
+#include "servers/display_server.h"
#ifdef TOOLS_ENABLED
#include "editor/editor_scale.h"
#include "editor/editor_settings.h"
#endif
-
+#include "scene/main/window.h"
static bool _is_text_char(CharType c) {
return !is_symbol(c);
@@ -56,7 +56,7 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
if (b->is_pressed() && b->get_button_index() == BUTTON_RIGHT && context_menu_enabled) {
menu->set_position(get_global_transform().xform(get_local_mouse_position()));
menu->set_size(Vector2(1, 1));
- menu->set_scale(get_global_transform().get_scale());
+ //menu->set_scale(get_global_transform().get_scale());
menu->popup();
grab_focus();
accept_event();
@@ -127,8 +127,8 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
selection.creating = false;
selection.doubleclick = false;
- if (OS::get_singleton()->has_virtual_keyboard())
- OS::get_singleton()->show_virtual_keyboard(text, get_global_rect(), max_length);
+ if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_VIRTUAL_KEYBOARD))
+ DisplayServer::get_singleton()->virtual_keyboard_show(text, get_global_rect(), max_length);
}
update();
@@ -304,8 +304,8 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
case KEY_ENTER: {
emit_signal("text_entered", text);
- if (OS::get_singleton()->has_virtual_keyboard())
- OS::get_singleton()->hide_virtual_keyboard();
+ if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_VIRTUAL_KEYBOARD))
+ DisplayServer::get_singleton()->virtual_keyboard_hide();
} break;
@@ -552,10 +552,10 @@ void LineEdit::_gui_input(Ref<InputEvent> p_event) {
} break;
case KEY_MENU: {
if (context_menu_enabled) {
- Point2 pos = Point2(get_cursor_pixel_pos(), (get_size().y + get_font("font")->get_height()) / 2);
+ Point2 pos = Point2(get_cursor_pixel_pos(), (get_size().y + get_theme_font("font")->get_height()) / 2);
menu->set_position(get_global_transform().xform(pos));
menu->set_size(Vector2(1, 1));
- menu->set_scale(get_global_transform().get_scale());
+ // menu->set_scale(get_global_transform().get_scale());
menu->popup();
menu->grab_focus();
}
@@ -629,7 +629,7 @@ void LineEdit::drop_data(const Point2 &p_point, const Variant &p_data) {
set_cursor_at_pixel_pos(p_point.x);
int selected = selection.end - selection.begin;
- Ref<Font> font = get_font("font");
+ Ref<Font> font = get_theme_font("font");
if (font != NULL) {
for (int i = selection.begin; i < selection.end; i++)
cached_width -= font->get_char_size(pass ? secret_character[0] : text[i]).width;
@@ -654,8 +654,8 @@ bool LineEdit::_is_over_clear_button(const Point2 &p_pos) const {
if (!clear_button_enabled || !has_point(p_pos)) {
return false;
}
- Ref<Texture2D> icon = Control::get_icon("clear");
- int x_ofs = get_stylebox("normal")->get_offset().x;
+ Ref<Texture2D> icon = Control::get_theme_icon("clear");
+ int x_ofs = get_theme_stylebox("normal")->get_offset().x;
return p_pos.x > get_size().width - icon->get_width() - x_ofs;
}
@@ -685,12 +685,12 @@ void LineEdit::_notification(int p_what) {
update_placeholder_width();
update();
} break;
- case MainLoop::NOTIFICATION_WM_FOCUS_IN: {
+ case NOTIFICATION_WM_FOCUS_IN: {
window_has_focus = true;
draw_caret = true;
update();
} break;
- case MainLoop::NOTIFICATION_WM_FOCUS_OUT: {
+ case NOTIFICATION_WM_FOCUS_OUT: {
window_has_focus = false;
draw_caret = false;
update();
@@ -709,19 +709,19 @@ void LineEdit::_notification(int p_what) {
RID ci = get_canvas_item();
- Ref<StyleBox> style = get_stylebox("normal");
+ Ref<StyleBox> style = get_theme_stylebox("normal");
if (!is_editable()) {
- style = get_stylebox("read_only");
+ style = get_theme_stylebox("read_only");
draw_caret = false;
}
- Ref<Font> font = get_font("font");
+ Ref<Font> font = get_theme_font("font");
style->draw(ci, Rect2(Point2(), size));
if (has_focus()) {
- get_stylebox("focus")->draw(ci, Rect2(Point2(), size));
+ get_theme_stylebox("focus")->draw(ci, Rect2(Point2(), size));
}
int x_ofs = 0;
@@ -756,10 +756,10 @@ void LineEdit::_notification(int p_what) {
int font_ascent = font->get_ascent();
- Color selection_color = get_color("selection_color");
- Color font_color = is_editable() ? get_color("font_color") : get_color("font_color_uneditable");
- Color font_color_selected = get_color("font_color_selected");
- Color cursor_color = get_color("cursor_color");
+ Color selection_color = get_theme_color("selection_color");
+ Color font_color = is_editable() ? get_theme_color("font_color") : get_theme_color("font_color_uneditable");
+ Color font_color_selected = get_theme_color("font_color_selected");
+ Color cursor_color = get_theme_color("cursor_color");
const String &t = using_placeholder ? placeholder_translated : text;
// Draw placeholder color.
@@ -768,13 +768,13 @@ void LineEdit::_notification(int p_what) {
bool display_clear_icon = !using_placeholder && is_editable() && clear_button_enabled;
if (right_icon.is_valid() || display_clear_icon) {
- Ref<Texture2D> r_icon = display_clear_icon ? Control::get_icon("clear") : right_icon;
+ Ref<Texture2D> r_icon = display_clear_icon ? Control::get_theme_icon("clear") : right_icon;
Color color_icon(1, 1, 1, !is_editable() ? .5 * .9 : .9);
if (display_clear_icon) {
if (clear_button_status.press_attempt && clear_button_status.pressing_inside) {
- color_icon = get_color("clear_button_color_pressed");
+ color_icon = get_theme_color("clear_button_color_pressed");
} else {
- color_icon = get_color("clear_button_color");
+ color_icon = get_theme_color("clear_button_color");
}
}
@@ -913,9 +913,10 @@ void LineEdit::_notification(int p_what) {
}
if (has_focus()) {
-
- OS::get_singleton()->set_ime_active(true);
- OS::get_singleton()->set_ime_position(get_global_position() + Point2(using_placeholder ? 0 : x_ofs, y_ofs + caret_height));
+ if (get_viewport()->get_window_id() != DisplayServer::INVALID_WINDOW_ID) {
+ DisplayServer::get_singleton()->window_set_ime_active(true, get_viewport()->get_window_id());
+ DisplayServer::get_singleton()->window_set_ime_position(get_global_position() + Point2(using_placeholder ? 0 : x_ofs, y_ofs + caret_height), get_viewport()->get_window_id());
+ }
}
} break;
case NOTIFICATION_FOCUS_ENTER: {
@@ -926,12 +927,14 @@ void LineEdit::_notification(int p_what) {
draw_caret = true;
}
- OS::get_singleton()->set_ime_active(true);
- Point2 cursor_pos = Point2(get_cursor_position(), 1) * get_minimum_size().height;
- OS::get_singleton()->set_ime_position(get_global_position() + cursor_pos);
+ if (get_viewport()->get_window_id() != DisplayServer::INVALID_WINDOW_ID) {
+ DisplayServer::get_singleton()->window_set_ime_active(true, get_viewport()->get_window_id());
+ Point2 cursor_pos = Point2(get_cursor_position(), 1) * get_minimum_size().height;
+ DisplayServer::get_singleton()->window_set_ime_position(get_global_position() + cursor_pos, get_viewport()->get_window_id());
+ }
- if (OS::get_singleton()->has_virtual_keyboard())
- OS::get_singleton()->show_virtual_keyboard(text, get_global_rect(), max_length);
+ if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_VIRTUAL_KEYBOARD))
+ DisplayServer::get_singleton()->virtual_keyboard_show(text, get_global_rect(), max_length);
} break;
case NOTIFICATION_FOCUS_EXIT: {
@@ -940,20 +943,22 @@ void LineEdit::_notification(int p_what) {
caret_blink_timer->stop();
}
- OS::get_singleton()->set_ime_position(Point2());
- OS::get_singleton()->set_ime_active(false);
+ if (get_viewport()->get_window_id() != DisplayServer::INVALID_WINDOW_ID) {
+ DisplayServer::get_singleton()->window_set_ime_position(Point2(), get_viewport()->get_window_id());
+ DisplayServer::get_singleton()->window_set_ime_active(false, get_viewport()->get_window_id());
+ }
ime_text = "";
ime_selection = Point2();
- if (OS::get_singleton()->has_virtual_keyboard())
- OS::get_singleton()->hide_virtual_keyboard();
+ if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_VIRTUAL_KEYBOARD))
+ DisplayServer::get_singleton()->virtual_keyboard_hide();
} break;
case MainLoop::NOTIFICATION_OS_IME_UPDATE: {
if (has_focus()) {
- ime_text = OS::get_singleton()->get_ime_text();
- ime_selection = OS::get_singleton()->get_ime_selection();
+ ime_text = DisplayServer::get_singleton()->ime_get_text();
+ ime_selection = DisplayServer::get_singleton()->ime_get_selection();
update();
}
} break;
@@ -963,14 +968,14 @@ void LineEdit::_notification(int p_what) {
void LineEdit::copy_text() {
if (selection.enabled && !pass) {
- OS::get_singleton()->set_clipboard(text.substr(selection.begin, selection.end - selection.begin));
+ DisplayServer::get_singleton()->clipboard_set(text.substr(selection.begin, selection.end - selection.begin));
}
}
void LineEdit::cut_text() {
if (selection.enabled && !pass) {
- OS::get_singleton()->set_clipboard(text.substr(selection.begin, selection.end - selection.begin));
+ DisplayServer::get_singleton()->clipboard_set(text.substr(selection.begin, selection.end - selection.begin));
selection_delete();
}
}
@@ -978,7 +983,7 @@ void LineEdit::cut_text() {
void LineEdit::paste_text() {
// Strip escape characters like \n and \t as they can't be displayed on LineEdit.
- String paste_buffer = OS::get_singleton()->get_clipboard().strip_escapes();
+ String paste_buffer = DisplayServer::get_singleton()->clipboard_get().strip_escapes();
if (paste_buffer != "") {
@@ -1054,13 +1059,13 @@ void LineEdit::shift_selection_check_post(bool p_shift) {
void LineEdit::set_cursor_at_pixel_pos(int p_x) {
- Ref<Font> font = get_font("font");
+ Ref<Font> font = get_theme_font("font");
int ofs = window_pos;
- Ref<StyleBox> style = get_stylebox("normal");
+ Ref<StyleBox> style = get_theme_stylebox("normal");
int pixel_ofs = 0;
Size2 size = get_size();
bool display_clear_icon = !text.empty() && is_editable() && clear_button_enabled;
- int r_icon_width = Control::get_icon("clear")->get_width();
+ int r_icon_width = Control::get_theme_icon("clear")->get_width();
switch (align) {
@@ -1108,13 +1113,13 @@ void LineEdit::set_cursor_at_pixel_pos(int p_x) {
int LineEdit::get_cursor_pixel_pos() {
- Ref<Font> font = get_font("font");
+ Ref<Font> font = get_theme_font("font");
int ofs = window_pos;
- Ref<StyleBox> style = get_stylebox("normal");
+ Ref<StyleBox> style = get_theme_stylebox("normal");
int pixel_ofs = 0;
Size2 size = get_size();
bool display_clear_icon = !text.empty() && is_editable() && clear_button_enabled;
- int r_icon_width = Control::get_icon("clear")->get_width();
+ int r_icon_width = Control::get_theme_icon("clear")->get_width();
switch (align) {
@@ -1201,7 +1206,7 @@ void LineEdit::delete_char() {
if ((text.length() <= 0) || (cursor_pos == 0)) return;
- Ref<Font> font = get_font("font");
+ Ref<Font> font = get_theme_font("font");
if (font != NULL) {
cached_width -= font->get_char_size(pass ? secret_character[0] : text[cursor_pos - 1]).width;
}
@@ -1220,7 +1225,7 @@ void LineEdit::delete_char() {
void LineEdit::delete_text(int p_from_column, int p_to_column) {
if (text.size() > 0) {
- Ref<Font> font = get_font("font");
+ Ref<Font> font = get_theme_font("font");
if (font != NULL) {
for (int i = p_from_column; i < p_to_column; i++)
cached_width -= font->get_char_size(pass ? secret_character[0] : text[i]).width;
@@ -1318,8 +1323,8 @@ void LineEdit::set_cursor_position(int p_pos) {
return;
}
- Ref<StyleBox> style = get_stylebox("normal");
- Ref<Font> font = get_font("font");
+ Ref<StyleBox> style = get_theme_stylebox("normal");
+ Ref<Font> font = get_theme_font("font");
if (cursor_pos <= window_pos) {
// Adjust window if cursor goes too much to the left.
@@ -1329,7 +1334,7 @@ void LineEdit::set_cursor_position(int p_pos) {
int window_width = get_size().width - style->get_minimum_size().width;
bool display_clear_icon = !text.empty() && is_editable() && clear_button_enabled;
if (right_icon.is_valid() || display_clear_icon) {
- Ref<Texture2D> r_icon = display_clear_icon ? Control::get_icon("clear") : right_icon;
+ Ref<Texture2D> r_icon = display_clear_icon ? Control::get_theme_icon("clear") : right_icon;
window_width -= r_icon->get_width();
}
@@ -1404,14 +1409,14 @@ void LineEdit::clear_internal() {
Size2 LineEdit::get_minimum_size() const {
- Ref<StyleBox> style = get_stylebox("normal");
- Ref<Font> font = get_font("font");
+ Ref<StyleBox> style = get_theme_stylebox("normal");
+ Ref<Font> font = get_theme_font("font");
Size2 min_size;
// Minimum size of text.
int space_size = font->get_char_size(' ').x;
- min_size.width = get_constant("minimum_spaces") * space_size;
+ min_size.width = get_theme_constant("minimum_spaces") * space_size;
if (expand_to_text_length) {
// Add a space because some fonts are too exact, and because cursor needs a bit more when at the end.
@@ -1422,8 +1427,8 @@ Size2 LineEdit::get_minimum_size() const {
// Take icons into account.
if (!text.empty() && is_editable() && clear_button_enabled) {
- min_size.width = MAX(min_size.width, Control::get_icon("clear")->get_width());
- min_size.height = MAX(min_size.height, Control::get_icon("clear")->get_height());
+ min_size.width = MAX(min_size.width, Control::get_theme_icon("clear")->get_width());
+ min_size.height = MAX(min_size.height, Control::get_theme_icon("clear")->get_height());
}
if (right_icon.is_valid()) {
min_size.width = MAX(min_size.width, right_icon->get_width());
@@ -1702,7 +1707,7 @@ void LineEdit::_emit_text_change() {
}
void LineEdit::update_cached_width() {
- Ref<Font> font = get_font("font");
+ Ref<Font> font = get_theme_font("font");
cached_width = 0;
if (font != NULL) {
String text = get_text();
@@ -1713,7 +1718,7 @@ void LineEdit::update_cached_width() {
}
void LineEdit::update_placeholder_width() {
- Ref<Font> font = get_font("font");
+ Ref<Font> font = get_theme_font("font");
cached_placeholder_width = 0;
if (font != NULL) {
for (int i = 0; i < placeholder_translated.length(); i++) {
diff --git a/scene/gui/link_button.cpp b/scene/gui/link_button.cpp
index 4b8054bac6..3dffa06b49 100644
--- a/scene/gui/link_button.cpp
+++ b/scene/gui/link_button.cpp
@@ -54,7 +54,7 @@ LinkButton::UnderlineMode LinkButton::get_underline_mode() const {
Size2 LinkButton::get_minimum_size() const {
- return get_font("font")->get_string_size(text);
+ return get_theme_font("font")->get_string_size(text);
}
void LinkButton::_notification(int p_what) {
@@ -72,29 +72,29 @@ void LinkButton::_notification(int p_what) {
case DRAW_NORMAL: {
- color = get_color("font_color");
+ color = get_theme_color("font_color");
do_underline = underline_mode == UNDERLINE_MODE_ALWAYS;
} break;
case DRAW_HOVER_PRESSED:
case DRAW_PRESSED: {
- if (has_color("font_color_pressed"))
- color = get_color("font_color_pressed");
+ if (has_theme_color("font_color_pressed"))
+ color = get_theme_color("font_color_pressed");
else
- color = get_color("font_color");
+ color = get_theme_color("font_color");
do_underline = underline_mode != UNDERLINE_MODE_NEVER;
} break;
case DRAW_HOVER: {
- color = get_color("font_color_hover");
+ color = get_theme_color("font_color_hover");
do_underline = underline_mode != UNDERLINE_MODE_NEVER;
} break;
case DRAW_DISABLED: {
- color = get_color("font_color_disabled");
+ color = get_theme_color("font_color_disabled");
do_underline = underline_mode == UNDERLINE_MODE_ALWAYS;
} break;
@@ -102,16 +102,16 @@ void LinkButton::_notification(int p_what) {
if (has_focus()) {
- Ref<StyleBox> style = get_stylebox("focus");
+ Ref<StyleBox> style = get_theme_stylebox("focus");
style->draw(ci, Rect2(Point2(), size));
}
- Ref<Font> font = get_font("font");
+ Ref<Font> font = get_theme_font("font");
draw_string(font, Vector2(0, font->get_ascent()), text, color);
if (do_underline) {
- int underline_spacing = get_constant("underline_spacing");
+ int underline_spacing = get_theme_constant("underline_spacing");
int width = font->get_string_size(text).width;
int y = font->get_ascent() + underline_spacing;
diff --git a/scene/gui/margin_container.cpp b/scene/gui/margin_container.cpp
index 53373fc297..1cd4ff4ff8 100644
--- a/scene/gui/margin_container.cpp
+++ b/scene/gui/margin_container.cpp
@@ -32,10 +32,10 @@
Size2 MarginContainer::get_minimum_size() const {
- int margin_left = get_constant("margin_left");
- int margin_top = get_constant("margin_top");
- int margin_right = get_constant("margin_right");
- int margin_bottom = get_constant("margin_bottom");
+ int margin_left = get_theme_constant("margin_left");
+ int margin_top = get_theme_constant("margin_top");
+ int margin_right = get_theme_constant("margin_right");
+ int margin_bottom = get_theme_constant("margin_bottom");
Size2 max;
@@ -67,10 +67,10 @@ void MarginContainer::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_SORT_CHILDREN: {
- int margin_left = get_constant("margin_left");
- int margin_top = get_constant("margin_top");
- int margin_right = get_constant("margin_right");
- int margin_bottom = get_constant("margin_bottom");
+ int margin_left = get_theme_constant("margin_left");
+ int margin_top = get_theme_constant("margin_top");
+ int margin_right = get_theme_constant("margin_right");
+ int margin_bottom = get_theme_constant("margin_bottom");
Size2 s = get_size();
diff --git a/scene/gui/menu_button.cpp b/scene/gui/menu_button.cpp
index 2b163187c5..a7d1f64e93 100644
--- a/scene/gui/menu_button.cpp
+++ b/scene/gui/menu_button.cpp
@@ -31,7 +31,7 @@
#include "menu_button.h"
#include "core/os/keyboard.h"
-#include "scene/main/viewport.h"
+#include "scene/main/window.h"
void MenuButton::_unhandled_key_input(Ref<InputEvent> p_event) {
@@ -43,23 +43,34 @@ 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_show");
+ {
+ Window *w = Object::cast_to<Window>(get_viewport());
+ if (w && !w->is_embedding_subwindows()) {
+ print_line("windowpos: " + w->get_position());
+ }
+ }
Size2 size = get_size();
- Point2 gp = get_global_position();
- popup->set_global_position(gp + Size2(0, size.height * get_global_transform().get_scale().y));
+ Point2 gp = get_screen_position();
+
+ print_line("screenpos: " + gp);
+ gp.y += get_size().y;
+
+ popup->set_position(gp);
+
popup->set_size(Size2(size.width, 0));
- popup->set_scale(get_global_transform().get_scale());
- popup->set_parent_rect(Rect2(Point2(gp - popup->get_global_position()), get_size()));
+ popup->set_parent_rect(Rect2(Point2(gp - popup->get_position()), get_size()));
+ popup->take_mouse_focus();
popup->popup();
}
@@ -116,7 +127,7 @@ void MenuButton::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::ARRAY, "items", PROPERTY_HINT_NONE, "", PROPERTY_USAGE_NOEDITOR | PROPERTY_USAGE_INTERNAL), "_set_items", "_get_items");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "switch_on_hover"), "set_switch_on_hover", "is_switch_on_hover");
- ADD_SIGNAL(MethodInfo("about_to_show"));
+ ADD_SIGNAL(MethodInfo("about_to_popup"));
}
void MenuButton::set_disable_shortcuts(bool p_disabled) {
@@ -137,8 +148,7 @@ MenuButton::MenuButton() {
popup = memnew(PopupMenu);
popup->hide();
add_child(popup);
- popup->set_pass_on_modal_close_click(false);
- popup->connect("about_to_show", callable_mp((BaseButton *)this, &BaseButton::set_pressed), varray(true)); // For when switching from another MenuButton.
+ popup->connect("about_to_popup", callable_mp((BaseButton *)this, &BaseButton::set_pressed), varray(true)); // For when switching from another MenuButton.
popup->connect("popup_hide", callable_mp((BaseButton *)this, &BaseButton::set_pressed), varray(false));
}
diff --git a/scene/gui/option_button.cpp b/scene/gui/option_button.cpp
index c185761beb..30ecd651b1 100644
--- a/scene/gui/option_button.cpp
+++ b/scene/gui/option_button.cpp
@@ -36,12 +36,12 @@ Size2 OptionButton::get_minimum_size() const {
Size2 minsize = Button::get_minimum_size();
- if (has_icon("arrow")) {
- const Size2 padding = get_stylebox("normal")->get_minimum_size();
- const Size2 arrow_size = Control::get_icon("arrow")->get_size();
+ if (has_theme_icon("arrow")) {
+ const Size2 padding = get_theme_stylebox("normal")->get_minimum_size();
+ const Size2 arrow_size = Control::get_theme_icon("arrow")->get_size();
Size2 content_size = minsize - padding;
- content_size.width += arrow_size.width + get_constant("hseparation");
+ content_size.width += arrow_size.width + get_theme_constant("hseparation");
content_size.height = MAX(content_size.height, arrow_size.height);
minsize = content_size + padding;
@@ -55,37 +55,37 @@ void OptionButton::_notification(int p_what) {
switch (p_what) {
case NOTIFICATION_DRAW: {
- if (!has_icon("arrow"))
+ if (!has_theme_icon("arrow"))
return;
RID ci = get_canvas_item();
- Ref<Texture2D> arrow = Control::get_icon("arrow");
+ Ref<Texture2D> arrow = Control::get_theme_icon("arrow");
Color clr = Color(1, 1, 1);
- if (get_constant("modulate_arrow")) {
+ if (get_theme_constant("modulate_arrow")) {
switch (get_draw_mode()) {
case DRAW_PRESSED:
- clr = get_color("font_color_pressed");
+ clr = get_theme_color("font_color_pressed");
break;
case DRAW_HOVER:
- clr = get_color("font_color_hover");
+ clr = get_theme_color("font_color_hover");
break;
case DRAW_DISABLED:
- clr = get_color("font_color_disabled");
+ clr = get_theme_color("font_color_disabled");
break;
default:
- clr = get_color("font_color");
+ clr = get_theme_color("font_color");
}
}
Size2 size = get_size();
- Point2 ofs(size.width - arrow->get_width() - get_constant("arrow_margin"), int(Math::abs((size.height - arrow->get_height()) / 2)));
+ Point2 ofs(size.width - arrow->get_width() - get_theme_constant("arrow_margin"), int(Math::abs((size.height - arrow->get_height()) / 2)));
arrow->draw(ci, ofs, clr);
} break;
case NOTIFICATION_THEME_CHANGED: {
- if (has_icon("arrow")) {
- _set_internal_margin(MARGIN_RIGHT, Control::get_icon("arrow")->get_width());
+ if (has_theme_icon("arrow")) {
+ _set_internal_margin(MARGIN_RIGHT, Control::get_theme_icon("arrow")->get_width());
}
} break;
case NOTIFICATION_VISIBILITY_CHANGED: {
@@ -109,9 +109,8 @@ void OptionButton::_selected(int p_which) {
void OptionButton::pressed() {
Size2 size = get_size();
- popup->set_global_position(get_global_position() + Size2(0, size.height * get_global_transform().get_scale().y));
+ popup->set_position(get_screen_position() + Size2(0, size.height * get_global_transform().get_scale().y));
popup->set_size(Size2(size.width, 0));
- popup->set_scale(get_global_transform().get_scale());
popup->popup();
}
@@ -351,15 +350,15 @@ OptionButton::OptionButton() {
set_toggle_mode(true);
set_text_align(ALIGN_LEFT);
set_action_mode(ACTION_MODE_BUTTON_PRESS);
- if (has_icon("arrow")) {
- _set_internal_margin(MARGIN_RIGHT, Control::get_icon("arrow")->get_width());
+ if (has_theme_icon("arrow")) {
+ _set_internal_margin(MARGIN_RIGHT, Control::get_theme_icon("arrow")->get_width());
}
popup = memnew(PopupMenu);
popup->hide();
add_child(popup);
- popup->set_pass_on_modal_close_click(false);
- popup->set_notify_transform(true);
+ // popup->set_pass_on_modal_close_click(false);
+ // popup->set_notify_transform(true);
popup->set_allow_search(true);
popup->connect("index_pressed", callable_mp(this, &OptionButton::_selected));
popup->connect("id_focused", callable_mp(this, &OptionButton::_focused));
diff --git a/scene/gui/panel.cpp b/scene/gui/panel.cpp
index 0356607071..ae51463a15 100644
--- a/scene/gui/panel.cpp
+++ b/scene/gui/panel.cpp
@@ -36,11 +36,25 @@ void Panel::_notification(int p_what) {
if (p_what == NOTIFICATION_DRAW) {
RID ci = get_canvas_item();
- Ref<StyleBox> style = get_stylebox("panel");
+ Ref<StyleBox> style = mode == MODE_BACKGROUND ? get_theme_stylebox("panel") : get_theme_stylebox("panel_fg");
style->draw(ci, Rect2(Point2(), get_size()));
}
}
+void Panel::set_mode(Mode p_mode) {
+ mode = p_mode;
+ update();
+}
+Panel::Mode Panel::get_mode() const {
+ return mode;
+}
+
+void Panel::_bind_methods() {
+ ClassDB::bind_method(D_METHOD("set_mode", "mode"), &Panel::set_mode);
+ ClassDB::bind_method(D_METHOD("get_mode"), &Panel::get_mode);
+
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Background,Foreground"), "set_mode", "get_mode");
+}
Panel::Panel() {
// Has visible stylebox, so stop by default.
set_mouse_filter(MOUSE_FILTER_STOP);
diff --git a/scene/gui/panel.h b/scene/gui/panel.h
index 3538126d22..739c64c0a6 100644
--- a/scene/gui/panel.h
+++ b/scene/gui/panel.h
@@ -37,12 +37,26 @@ class Panel : public Control {
GDCLASS(Panel, Control);
+public:
+ enum Mode {
+ MODE_BACKGROUND,
+ MODE_FOREGROUND
+ };
+
+private:
+ Mode mode = MODE_BACKGROUND;
+
protected:
void _notification(int p_what);
+ static void _bind_methods();
public:
+ void set_mode(Mode p_mode);
+ Mode get_mode() const;
+
Panel();
~Panel();
};
+VARIANT_ENUM_CAST(Panel::Mode)
#endif
diff --git a/scene/gui/panel_container.cpp b/scene/gui/panel_container.cpp
index 6cf23b8a32..62b9296409 100644
--- a/scene/gui/panel_container.cpp
+++ b/scene/gui/panel_container.cpp
@@ -34,16 +34,16 @@ Size2 PanelContainer::get_minimum_size() const {
Ref<StyleBox> style;
- if (has_stylebox("panel"))
- style = get_stylebox("panel");
+ if (has_theme_stylebox("panel"))
+ style = get_theme_stylebox("panel");
else
- style = get_stylebox("panel", "PanelContainer");
+ style = get_theme_stylebox("panel", "PanelContainer");
Size2 ms;
for (int i = 0; i < get_child_count(); i++) {
Control *c = Object::cast_to<Control>(get_child(i));
- if (!c || !c->is_visible_in_tree())
+ if (!c || !c->is_visible())
continue;
if (c->is_set_as_toplevel())
continue;
@@ -65,10 +65,10 @@ void PanelContainer::_notification(int p_what) {
RID ci = get_canvas_item();
Ref<StyleBox> style;
- if (has_stylebox("panel"))
- style = get_stylebox("panel");
+ if (has_theme_stylebox("panel"))
+ style = get_theme_stylebox("panel");
else
- style = get_stylebox("panel", "PanelContainer");
+ style = get_theme_stylebox("panel", "PanelContainer");
style->draw(ci, Rect2(Point2(), get_size()));
}
@@ -77,10 +77,10 @@ void PanelContainer::_notification(int p_what) {
Ref<StyleBox> style;
- if (has_stylebox("panel"))
- style = get_stylebox("panel");
+ if (has_theme_stylebox("panel"))
+ style = get_theme_stylebox("panel");
else
- style = get_stylebox("panel", "PanelContainer");
+ style = get_theme_stylebox("panel", "PanelContainer");
Size2 size = get_size();
Point2 ofs;
diff --git a/scene/gui/popup.cpp b/scene/gui/popup.cpp
index 64ef4a01f6..6edafc65a0 100644
--- a/scene/gui/popup.cpp
+++ b/scene/gui/popup.cpp
@@ -32,227 +32,131 @@
#include "core/engine.h"
#include "core/os/keyboard.h"
+#include "scene/gui/panel.h"
-void Popup::_gui_input(Ref<InputEvent> p_event) {
-}
-
-void Popup::_notification(int p_what) {
-
- if (p_what == NOTIFICATION_VISIBILITY_CHANGED) {
- if (popped_up && !is_visible_in_tree()) {
- popped_up = false;
- notification(NOTIFICATION_POPUP_HIDE);
- emit_signal("popup_hide");
- }
-
- update_configuration_warning();
- }
-
- if (p_what == NOTIFICATION_EXIT_TREE) {
- if (popped_up) {
- popped_up = false;
- notification(NOTIFICATION_POPUP_HIDE);
- emit_signal("popup_hide");
- }
- }
-
- if (p_what == NOTIFICATION_ENTER_TREE) {
-//small helper to make editing of these easier in editor
-#ifdef TOOLS_ENABLED
- if (Engine::get_singleton()->is_editor_hint() && get_tree()->get_edited_scene_root() && get_tree()->get_edited_scene_root()->is_a_parent_of(this)) {
- //edited on editor
- set_as_toplevel(false);
- } else
-#endif
- if (is_visible()) {
- hide();
- }
+void Popup::_input_from_window(const Ref<InputEvent> &p_event) {
+ Ref<InputEventKey> key = p_event;
+ if (key.is_valid() && key->is_pressed() && key->get_keycode() == KEY_ESCAPE) {
+ _close_pressed();
}
}
-void Popup::_fix_size() {
-
- Point2 pos = get_global_position();
- Size2 size = get_size() * get_scale();
- Point2 window_size = get_viewport_rect().size - get_viewport_transform().get_origin();
-
- if (pos.x + size.width > window_size.width)
- pos.x = window_size.width - size.width;
- if (pos.x < 0)
- pos.x = 0;
+void Popup::_parent_focused() {
- if (pos.y + size.height > window_size.height)
- pos.y = window_size.height - size.height;
- if (pos.y < 0)
- pos.y = 0;
- if (pos != get_position())
- set_global_position(pos);
+ _close_pressed();
}
+void Popup::_notification(int p_what) {
-void Popup::set_as_minsize() {
-
- Size2 total_minsize;
-
- for (int i = 0; i < get_child_count(); i++) {
-
- Control *c = Object::cast_to<Control>(get_child(i));
- if (!c)
- continue;
- if (!c->is_visible())
- continue;
-
- Size2 minsize = c->get_combined_minimum_size();
-
- for (int j = 0; j < 2; j++) {
-
- Margin m_beg = Margin(0 + j);
- Margin m_end = Margin(2 + j);
-
- float margin_begin = c->get_margin(m_beg);
- float margin_end = c->get_margin(m_end);
- float anchor_begin = c->get_anchor(m_beg);
- float anchor_end = c->get_anchor(m_end);
-
- minsize[j] += margin_begin * (ANCHOR_END - anchor_begin) + margin_end * anchor_end;
- }
-
- total_minsize.width = MAX(total_minsize.width, minsize.width);
- total_minsize.height = MAX(total_minsize.height, minsize.height);
+ switch (p_what) {
+ case NOTIFICATION_VISIBILITY_CHANGED: {
+ if (is_visible()) {
+
+ parent_visible = get_parent_visible_window();
+ if (parent_visible) {
+ parent_visible->connect("focus_entered", callable_mp(this, &Popup::_parent_focused));
+ }
+ } else {
+ if (parent_visible) {
+ parent_visible->disconnect("focus_entered", callable_mp(this, &Popup::_parent_focused));
+ parent_visible = nullptr;
+ }
+
+ emit_signal("popup_hide");
+ }
+
+ } break;
+ case NOTIFICATION_EXIT_TREE: {
+ if (parent_visible) {
+ parent_visible->disconnect("focus_entered", callable_mp(this, &Popup::_parent_focused));
+ parent_visible = nullptr;
+ }
+ } break;
+ case NOTIFICATION_WM_CLOSE_REQUEST: {
+ _close_pressed();
+
+ } break;
}
-
- set_size(total_minsize);
}
-void Popup::popup_centered_clamped(const Size2 &p_size, float p_fallback_ratio) {
-
- Size2 popup_size = p_size;
- Size2 window_size = get_viewport_rect().size;
-
- // clamp popup size in each dimension if window size is too small (using fallback ratio)
- popup_size.x = MIN(window_size.x * p_fallback_ratio, popup_size.x);
- popup_size.y = MIN(window_size.y * p_fallback_ratio, popup_size.y);
-
- popup_centered(popup_size);
-}
+void Popup::_close_pressed() {
-void Popup::popup_centered_minsize(const Size2 &p_minsize) {
-
- set_custom_minimum_size(p_minsize);
- _fix_size();
- popup_centered();
-}
+ Window *parent_window = parent_visible;
+ if (parent_visible) {
+ parent_visible->disconnect("focus_entered", callable_mp(this, &Popup::_parent_focused));
+ parent_visible = nullptr;
+ }
-void Popup::popup_centered(const Size2 &p_size) {
+ call_deferred("hide");
- Rect2 rect;
- Size2 window_size = get_viewport_rect().size;
- rect.size = p_size == Size2() ? get_size() : p_size;
- rect.position = ((window_size - rect.size) / 2.0).floor();
+ emit_signal("cancelled");
- _popup(rect, true);
+ if (parent_window) {
+ //parent_window->grab_focus();
+ }
}
-void Popup::popup_centered_ratio(float p_screen_ratio) {
-
- Rect2 rect;
- Size2 window_size = get_viewport_rect().size;
- rect.size = (window_size * p_screen_ratio).floor();
- rect.position = ((window_size - rect.size) / 2.0).floor();
-
- _popup(rect, true);
+void Popup::set_as_minsize() {
+ set_size(get_contents_minimum_size());
}
+void Popup::_bind_methods() {
-void Popup::popup(const Rect2 &p_bounds) {
-
- _popup(p_bounds);
+ ADD_SIGNAL(MethodInfo("popup_hide"));
}
-void Popup::_popup(const Rect2 &p_bounds, const bool p_centered) {
-
- emit_signal("about_to_show");
- show_modal(exclusive);
-
- // Fit the popup into the optionally provided bounds.
- if (!p_bounds.has_no_area()) {
- set_size(p_bounds.size);
+Rect2i Popup::_popup_adjust_rect() const {
+ ERR_FAIL_COND_V(!is_inside_tree(), Rect2());
+ Rect2i parent = get_usable_parent_rect();
- // check if p_bounds.size was using an outdated cached values
- if (p_centered && p_bounds.size != get_size()) {
- set_position(p_bounds.position - ((get_size() - p_bounds.size) / 2.0).floor());
- } else {
- set_position(p_bounds.position);
- }
+ if (parent == Rect2i()) {
+ return Rect2i();
}
- _fix_size();
-
- Control *focusable = find_next_valid_focus();
-
- if (focusable)
- focusable->grab_focus();
-
- _post_popup();
- notification(NOTIFICATION_POST_POPUP);
- popped_up = true;
-}
-void Popup::set_exclusive(bool p_exclusive) {
+ Rect2i current(get_position(), get_size());
- exclusive = p_exclusive;
-}
-
-bool Popup::is_exclusive() const {
+ if (current.position.x + current.size.x > parent.position.x + parent.size.x) {
+ current.position.x = parent.position.x + parent.size.x - current.size.x;
+ }
- return exclusive;
-}
+ if (current.position.x < parent.position.x) {
+ current.position.x = parent.position.x;
+ }
-void Popup::_bind_methods() {
+ if (current.position.y + current.size.y > parent.position.y + parent.size.y) {
+ current.position.y = parent.position.y + parent.size.y - current.size.y;
+ }
- ClassDB::bind_method(D_METHOD("set_as_minsize"), &Popup::set_as_minsize);
- ClassDB::bind_method(D_METHOD("popup_centered", "size"), &Popup::popup_centered, DEFVAL(Size2()));
- ClassDB::bind_method(D_METHOD("popup_centered_ratio", "ratio"), &Popup::popup_centered_ratio, DEFVAL(0.75));
- ClassDB::bind_method(D_METHOD("popup_centered_minsize", "minsize"), &Popup::popup_centered_minsize, DEFVAL(Size2()));
- ClassDB::bind_method(D_METHOD("popup_centered_clamped", "size", "fallback_ratio"), &Popup::popup_centered_clamped, DEFVAL(Size2()), DEFVAL(0.75));
- ClassDB::bind_method(D_METHOD("popup", "bounds"), &Popup::popup, DEFVAL(Rect2()));
- ClassDB::bind_method(D_METHOD("set_exclusive", "enable"), &Popup::set_exclusive);
- ClassDB::bind_method(D_METHOD("is_exclusive"), &Popup::is_exclusive);
- ADD_SIGNAL(MethodInfo("about_to_show"));
- ADD_SIGNAL(MethodInfo("popup_hide"));
- ADD_GROUP("Popup", "popup_");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "popup_exclusive"), "set_exclusive", "is_exclusive");
+ if (current.position.y < parent.position.y) {
+ current.position.y = parent.position.y;
+ }
- BIND_CONSTANT(NOTIFICATION_POST_POPUP);
- BIND_CONSTANT(NOTIFICATION_POPUP_HIDE);
+ return current;
}
Popup::Popup() {
- set_as_toplevel(true);
- exclusive = false;
- popped_up = false;
- hide();
-}
-
-String Popup::get_configuration_warning() const {
+ parent_visible = nullptr;
- if (is_visible_in_tree()) {
- return TTR("Popups will hide by default unless you call popup() or any of the popup*() functions. Making them visible for editing is fine, but they will hide upon running.");
- }
+ set_wrap_controls(true);
+ set_visible(false);
+ set_transient(true);
+ set_flag(FLAG_BORDERLESS, true);
+ set_flag(FLAG_RESIZE_DISABLED, true);
- return String();
+ connect("window_input", callable_mp(this, &Popup::_input_from_window));
}
Popup::~Popup() {
}
-Size2 PopupPanel::get_minimum_size() const {
+Size2 PopupPanel::_get_contents_minimum_size() const {
- Ref<StyleBox> p = get_stylebox("panel");
+ Ref<StyleBox> p = get_theme_stylebox("panel", get_class_name());
Size2 ms;
for (int i = 0; i < get_child_count(); i++) {
Control *c = Object::cast_to<Control>(get_child(i));
- if (!c)
+ if (!c || c == panel)
continue;
if (c->is_set_as_toplevel())
@@ -268,7 +172,7 @@ Size2 PopupPanel::get_minimum_size() const {
void PopupPanel::_update_child_rects() {
- Ref<StyleBox> p = get_stylebox("panel");
+ Ref<StyleBox> p = get_theme_stylebox("panel", get_class_name());
Vector2 cpos(p->get_offset());
Vector2 csize(get_size() - p->get_minimum_size());
@@ -281,24 +185,32 @@ void PopupPanel::_update_child_rects() {
if (c->is_set_as_toplevel())
continue;
- c->set_position(cpos);
- c->set_size(csize);
+ if (c == panel) {
+ c->set_position(Vector2());
+ c->set_size(get_size());
+ } else {
+ c->set_position(cpos);
+ c->set_size(csize);
+ }
}
}
void PopupPanel::_notification(int p_what) {
- if (p_what == NOTIFICATION_DRAW) {
-
- get_stylebox("panel")->draw(get_canvas_item(), Rect2(Point2(), get_size()));
- } else if (p_what == NOTIFICATION_READY) {
+ if (p_what == NOTIFICATION_THEME_CHANGED) {
+ panel->add_theme_style_override("panel", get_theme_stylebox("panel", get_class_name()));
+ } else if (p_what == NOTIFICATION_READY || p_what == NOTIFICATION_ENTER_TREE) {
+ panel->add_theme_style_override("panel", get_theme_stylebox("panel", get_class_name()));
_update_child_rects();
- } else if (p_what == NOTIFICATION_RESIZED) {
+ } else if (p_what == NOTIFICATION_WM_SIZE_CHANGED) {
_update_child_rects();
}
}
PopupPanel::PopupPanel() {
+
+ panel = memnew(Panel);
+ add_child(panel);
}
diff --git a/scene/gui/popup.h b/scene/gui/popup.h
index ff472170b3..6cd2b4028f 100644
--- a/scene/gui/popup.h
+++ b/scene/gui/popup.h
@@ -31,44 +31,26 @@
#ifndef POPUP_H
#define POPUP_H
-#include "scene/gui/control.h"
+#include "scene/main/window.h"
-class Popup : public Control {
+class Popup : public Window {
- GDCLASS(Popup, Control);
+ GDCLASS(Popup, Window);
- bool exclusive;
- bool popped_up;
+ Window *parent_visible;
-private:
- void _popup(const Rect2 &p_bounds = Rect2(), const bool p_centered = false);
+ void _input_from_window(const Ref<InputEvent> &p_event);
+ void _parent_focused();
protected:
- virtual void _post_popup() {}
+ void _close_pressed();
+ virtual Rect2i _popup_adjust_rect() const;
- void _gui_input(Ref<InputEvent> p_event);
void _notification(int p_what);
- virtual void _fix_size();
static void _bind_methods();
public:
- enum {
- NOTIFICATION_POST_POPUP = 80,
- NOTIFICATION_POPUP_HIDE = 81
- };
-
- void set_exclusive(bool p_exclusive);
- bool is_exclusive() const;
-
- void popup_centered_ratio(float p_screen_ratio = 0.75);
- void popup_centered(const Size2 &p_size = Size2());
- void popup_centered_minsize(const Size2 &p_minsize = Size2());
void set_as_minsize();
- void popup_centered_clamped(const Size2 &p_size = Size2(), float p_fallback_ratio = 0.75);
- virtual void popup(const Rect2 &p_bounds = Rect2());
-
- virtual String get_configuration_warning() const;
-
Popup();
~Popup();
};
@@ -77,13 +59,16 @@ class PopupPanel : public Popup {
GDCLASS(PopupPanel, Popup);
+ Panel *panel;
+
protected:
void _update_child_rects();
void _notification(int p_what);
+ virtual Size2 _get_contents_minimum_size() const;
+
public:
void set_child_rect(Control *p_child);
- virtual Size2 get_minimum_size() const;
PopupPanel();
};
diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp
index e75dadd5e0..c096dc94cb 100644
--- a/scene/gui/popup_menu.cpp
+++ b/scene/gui/popup_menu.cpp
@@ -30,11 +30,12 @@
#include "popup_menu.h"
-#include "core/os/input.h"
+#include "core/input/input_filter.h"
#include "core/os/keyboard.h"
#include "core/os/os.h"
#include "core/print_string.h"
#include "core/translation.h"
+#include "scene/gui/control.h"
String PopupMenu::_get_accel_text(int p_item) const {
@@ -47,18 +48,18 @@ String PopupMenu::_get_accel_text(int p_item) const {
return String();
}
-Size2 PopupMenu::get_minimum_size() const {
+Size2 PopupMenu::_get_contents_minimum_size() const {
- int vseparation = get_constant("vseparation");
- int hseparation = get_constant("hseparation");
+ int vseparation = get_theme_constant("vseparation");
+ int hseparation = get_theme_constant("hseparation");
- Size2 minsize = get_stylebox("panel")->get_minimum_size();
- Ref<Font> font = get_font("font");
+ Size2 minsize = get_theme_stylebox("panel")->get_minimum_size();
+ Ref<Font> font = get_theme_font("font");
float max_w = 0;
float icon_w = 0;
int font_h = font->get_height();
- int check_w = MAX(get_icon("checked")->get_width(), get_icon("radio_checked")->get_width()) + hseparation;
+ int check_w = MAX(get_theme_icon("checked")->get_width(), get_theme_icon("radio_checked")->get_width()) + hseparation;
int accel_max_w = 0;
bool has_check = false;
@@ -93,7 +94,7 @@ Size2 PopupMenu::get_minimum_size() const {
}
if (items[i].submenu != "")
- size.width += get_icon("submenu")->get_width();
+ size.width += get_theme_icon("submenu")->get_width();
max_w = MAX(max_w, size.width);
@@ -112,15 +113,15 @@ int PopupMenu::_get_mouse_over(const Point2 &p_over) const {
if (p_over.x < 0 || p_over.x >= get_size().width)
return -1;
- Ref<StyleBox> style = get_stylebox("panel");
+ Ref<StyleBox> style = get_theme_stylebox("panel");
Point2 ofs = style->get_offset();
if (ofs.y > p_over.y)
return -1;
- Ref<Font> font = get_font("font");
- int vseparation = get_constant("vseparation");
+ Ref<Font> font = get_theme_font("font");
+ int vseparation = get_theme_constant("vseparation");
float font_h = font->get_height();
for (int i = 0; i < items.size(); i++) {
@@ -152,27 +153,27 @@ void PopupMenu::_activate_submenu(int over) {
ERR_FAIL_COND_MSG(!n, "Item subnode does not exist: " + items[over].submenu + ".");
Popup *pm = Object::cast_to<Popup>(n);
ERR_FAIL_COND_MSG(!pm, "Item subnode is not a Popup: " + items[over].submenu + ".");
- if (pm->is_visible_in_tree())
+ if (pm->is_visible())
return; //already visible!
- Point2 p = get_global_position();
+ Point2 p = get_position();
Rect2 pr(p, get_size());
- Ref<StyleBox> style = get_stylebox("panel");
+ Ref<StyleBox> style = get_theme_stylebox("panel");
- Point2 pos = p + Point2(get_size().width, items[over]._ofs_cache - style->get_offset().y) * get_global_transform().get_scale();
+ 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_viewport_rect().size.width)
+ if (pos.x + size.width > get_parent_rect().size.width)
pos.x = p.x - size.width;
pm->set_position(pos);
- pm->set_scale(get_global_transform().get_scale());
+ // pm->set_scale(get_global_transform().get_scale());
pm->popup();
PopupMenu *pum = Object::cast_to<PopupMenu>(pm);
if (pum) {
- pr.position -= pum->get_global_position();
+ pr.position -= pum->get_position();
pum->clear_autohide_areas();
pum->add_autohide_area(Rect2(pr.position.x, pr.position.y, pr.size.x, items[over]._ofs_cache));
if (over < items.size() - 1) {
@@ -184,6 +185,9 @@ void PopupMenu::_activate_submenu(int over) {
void PopupMenu::_submenu_timeout() {
+ //if (!has_focus()) {
+ // return; //do not activate if not has focus
+ //}
if (mouse_over == submenu_over)
_activate_submenu(mouse_over);
@@ -192,20 +196,27 @@ void PopupMenu::_submenu_timeout() {
void PopupMenu::_scroll(float p_factor, const Point2 &p_over) {
- int vseparation = get_constant("vseparation");
- Ref<Font> font = get_font("font");
+ int vseparation = get_theme_constant("vseparation");
+ Ref<Font> font = get_theme_font("font");
- float dy = (vseparation + font->get_height()) * 3 * p_factor * get_global_transform().get_scale().y;
+ Rect2 visible_rect = get_usable_parent_rect();
+
+ int dy = (vseparation + font->get_height()) * 3 * p_factor;
if (dy > 0) {
- const float global_top = get_global_position().y;
- const float limit = global_top < 0 ? -global_top : 0;
+ const float global_top = get_position().y;
+ const float limit = global_top < visible_rect.position.y ? visible_rect.position.y - global_top : 0;
dy = MIN(dy, limit);
} else if (dy < 0) {
- const float global_bottom = get_global_position().y + get_size().y * get_global_transform().get_scale().y;
- const float viewport_height = get_viewport_rect().size.y;
+ const float global_bottom = get_position().y + get_size().y;
+ const float viewport_height = visible_rect.position.y + visible_rect.size.y;
const float limit = global_bottom > viewport_height ? global_bottom - viewport_height : 0;
dy = -MIN(-dy, limit);
}
+
+ if (dy == 0) {
+ return;
+ }
+
set_position(get_position() + Vector2(0, dy));
Ref<InputEventMouseMotion> ie;
@@ -231,8 +242,8 @@ void PopupMenu::_gui_input(const Ref<InputEvent> &p_event) {
mouse_over = i;
emit_signal("id_focused", i);
- update();
- accept_event();
+ control->update();
+ set_input_as_handled();
break;
}
}
@@ -251,8 +262,8 @@ void PopupMenu::_gui_input(const Ref<InputEvent> &p_event) {
mouse_over = i;
emit_signal("id_focused", i);
- update();
- accept_event();
+ control->update();
+ set_input_as_handled();
break;
}
}
@@ -261,13 +272,13 @@ void PopupMenu::_gui_input(const Ref<InputEvent> &p_event) {
Node *n = get_parent();
if (n && Object::cast_to<PopupMenu>(n)) {
hide();
- accept_event();
+ set_input_as_handled();
}
} else if (p_event->is_action("ui_right") && p_event->is_pressed()) {
if (mouse_over >= 0 && mouse_over < items.size() && !items[mouse_over].separator && items[mouse_over].submenu != "" && submenu_over != mouse_over) {
_activate_submenu(mouse_over);
- accept_event();
+ set_input_as_handled();
}
} else if (p_event->is_action("ui_accept") && p_event->is_pressed()) {
@@ -278,7 +289,7 @@ void PopupMenu::_gui_input(const Ref<InputEvent> &p_event) {
} else {
activate_item(mouse_over);
}
- accept_event();
+ set_input_as_handled();
}
}
@@ -294,15 +305,11 @@ void PopupMenu::_gui_input(const Ref<InputEvent> &p_event) {
case BUTTON_WHEEL_DOWN: {
- if (get_global_position().y + get_size().y * get_global_transform().get_scale().y > get_viewport_rect().size.y) {
- _scroll(-b->get_factor(), b->get_position());
- }
+ _scroll(-b->get_factor(), b->get_position());
} break;
case BUTTON_WHEEL_UP: {
- if (get_global_position().y < 0) {
- _scroll(b->get_factor(), b->get_position());
- }
+ _scroll(b->get_factor(), b->get_position());
} break;
default: {
// Allow activating item by releasing the LMB or any that was down when the popup appeared
@@ -338,7 +345,7 @@ void PopupMenu::_gui_input(const Ref<InputEvent> &p_event) {
}
}
- //update();
+ //control->update();
}
Ref<InputEventMouseMotion> m = p_event;
@@ -354,7 +361,8 @@ void PopupMenu::_gui_input(const Ref<InputEvent> &p_event) {
for (List<Rect2>::Element *E = autohide_areas.front(); E; E = E->next()) {
if (!Rect2(Point2(), get_size()).has_point(m->get_position()) && E->get().has_point(m->get_position())) {
- call_deferred("hide");
+
+ _close_pressed();
return;
}
}
@@ -364,7 +372,7 @@ void PopupMenu::_gui_input(const Ref<InputEvent> &p_event) {
if (id < 0) {
mouse_over = -1;
- update();
+ control->update();
return;
}
@@ -375,15 +383,13 @@ void PopupMenu::_gui_input(const Ref<InputEvent> &p_event) {
if (over != mouse_over) {
mouse_over = over;
- update();
+ control->update();
}
}
Ref<InputEventPanGesture> pan_gesture = p_event;
if (pan_gesture.is_valid()) {
- if (get_global_position().y + get_size().y > get_viewport_rect().size.y || get_global_position().y < 0) {
- _scroll(-pan_gesture->get_delta().y, pan_gesture->get_position());
- }
+ _scroll(-pan_gesture->get_delta().y, pan_gesture->get_position());
}
Ref<InputEventKey> k = p_event;
@@ -416,218 +422,227 @@ void PopupMenu::_gui_input(const Ref<InputEvent> &p_event) {
if (items[i].text.findn(search_string) == 0) {
mouse_over = i;
emit_signal("id_focused", i);
- update();
- accept_event();
+ control->update();
+ set_input_as_handled();
break;
}
}
}
}
-bool PopupMenu::has_point(const Point2 &p_point) const {
+void PopupMenu::_draw() {
- if (parent_rect.has_point(p_point))
- return true;
- for (const List<Rect2>::Element *E = autohide_areas.front(); E; E = E->next()) {
+ RID ci = control->get_canvas_item();
+ Size2 size = get_size();
- if (E->get().has_point(p_point))
- return true;
- }
+ Ref<StyleBox> style = get_theme_stylebox("panel");
+ Ref<StyleBox> hover = get_theme_stylebox("hover");
+ Ref<Font> font = get_theme_font("font");
+ // In Item::checkable_type enum order (less the non-checkable member)
+ Ref<Texture2D> check[] = { get_theme_icon("checked"), get_theme_icon("radio_checked") };
+ Ref<Texture2D> uncheck[] = { get_theme_icon("unchecked"), get_theme_icon("radio_unchecked") };
+ Ref<Texture2D> submenu = get_theme_icon("submenu");
+ Ref<StyleBox> separator = get_theme_stylebox("separator");
+ Ref<StyleBox> labeled_separator_left = get_theme_stylebox("labeled_separator_left");
+ Ref<StyleBox> labeled_separator_right = get_theme_stylebox("labeled_separator_right");
- return Control::has_point(p_point);
-}
-
-void PopupMenu::_notification(int p_what) {
+ style->draw(ci, Rect2(Point2(), get_size()));
+ Point2 ofs = style->get_offset();
+ int vseparation = get_theme_constant("vseparation");
+ int hseparation = get_theme_constant("hseparation");
+ Color font_color = get_theme_color("font_color");
+ Color font_color_disabled = get_theme_color("font_color_disabled");
+ Color font_color_accel = get_theme_color("font_color_accel");
+ Color font_color_hover = get_theme_color("font_color_hover");
+ float font_h = font->get_height();
- switch (p_what) {
+ // Add the check and the wider icon to the offset of all items.
+ float icon_ofs = 0.0;
+ bool has_check = false;
+ for (int i = 0; i < items.size(); i++) {
- case NOTIFICATION_ENTER_TREE: {
+ if (!items[i].icon.is_null())
+ icon_ofs = MAX(items[i].icon->get_size().width, icon_ofs);
- PopupMenu *pm = Object::cast_to<PopupMenu>(get_parent());
- if (pm) {
- // Inherit submenu's popup delay time from parent menu
- float pm_delay = pm->get_submenu_popup_delay();
- set_submenu_popup_delay(pm_delay);
- }
- } break;
- case NOTIFICATION_TRANSLATION_CHANGED: {
+ if (items[i].checkable_type)
+ has_check = true;
+ }
+ if (icon_ofs > 0.0)
+ icon_ofs += hseparation;
- for (int i = 0; i < items.size(); i++) {
- items.write[i].xl_text = tr(items[i].text);
- }
+ float check_ofs = 0.0;
+ if (has_check)
+ check_ofs = MAX(get_theme_icon("checked")->get_width(), get_theme_icon("radio_checked")->get_width()) + hseparation;
- minimum_size_changed();
- update();
- } break;
- case NOTIFICATION_DRAW: {
-
- RID ci = get_canvas_item();
- Size2 size = get_size();
-
- Ref<StyleBox> style = get_stylebox("panel");
- Ref<StyleBox> hover = get_stylebox("hover");
- Ref<Font> font = get_font("font");
- // In Item::checkable_type enum order (less the non-checkable member)
- Ref<Texture2D> check[] = { get_icon("checked"), get_icon("radio_checked") };
- Ref<Texture2D> uncheck[] = { get_icon("unchecked"), get_icon("radio_unchecked") };
- Ref<Texture2D> submenu = get_icon("submenu");
- Ref<StyleBox> separator = get_stylebox("separator");
- Ref<StyleBox> labeled_separator_left = get_stylebox("labeled_separator_left");
- Ref<StyleBox> labeled_separator_right = get_stylebox("labeled_separator_right");
-
- style->draw(ci, Rect2(Point2(), get_size()));
- Point2 ofs = style->get_offset();
- int vseparation = get_constant("vseparation");
- int hseparation = get_constant("hseparation");
- Color font_color = get_color("font_color");
- Color font_color_disabled = get_color("font_color_disabled");
- Color font_color_accel = get_color("font_color_accel");
- Color font_color_hover = get_color("font_color_hover");
- float font_h = font->get_height();
-
- // Add the check and the wider icon to the offset of all items.
- float icon_ofs = 0.0;
- bool has_check = false;
- for (int i = 0; i < items.size(); i++) {
+ for (int i = 0; i < items.size(); i++) {
- if (!items[i].icon.is_null())
- icon_ofs = MAX(items[i].icon->get_size().width, icon_ofs);
+ if (i > 0)
+ ofs.y += vseparation;
+ Point2 item_ofs = ofs;
+ Size2 icon_size;
+ float h;
- if (items[i].checkable_type)
- has_check = true;
- }
- if (icon_ofs > 0.0)
- icon_ofs += hseparation;
+ if (!items[i].icon.is_null()) {
- float check_ofs = 0.0;
- if (has_check)
- check_ofs = MAX(get_icon("checked")->get_width(), get_icon("radio_checked")->get_width()) + hseparation;
+ icon_size = items[i].icon->get_size();
+ h = MAX(icon_size.height, font_h);
+ } else {
- for (int i = 0; i < items.size(); i++) {
+ h = font_h;
+ }
- if (i > 0)
- ofs.y += vseparation;
- Point2 item_ofs = ofs;
- Size2 icon_size;
- float h;
+ if (i == mouse_over) {
- if (!items[i].icon.is_null()) {
+ hover->draw(ci, Rect2(item_ofs + Point2(-hseparation, -vseparation / 2), Size2(get_size().width - style->get_minimum_size().width + hseparation * 2, h + vseparation)));
+ }
- icon_size = items[i].icon->get_size();
- h = MAX(icon_size.height, font_h);
- } else {
+ String text = items[i].xl_text;
- h = font_h;
+ item_ofs.x += items[i].h_ofs;
+ if (items[i].separator) {
+
+ int sep_h = separator->get_center_size().height + separator->get_minimum_size().height;
+ if (text != String()) {
+ int ss = font->get_string_size(text).width;
+ int center = (get_size().width) / 2;
+ int l = center - ss / 2;
+ int r = center + ss / 2;
+ if (l > item_ofs.x) {
+ labeled_separator_left->draw(ci, Rect2(item_ofs + Point2(0, Math::floor((h - sep_h) / 2.0)), Size2(MAX(0, l - item_ofs.x), sep_h)));
}
-
- if (i == mouse_over) {
-
- hover->draw(ci, Rect2(item_ofs + Point2(-hseparation, -vseparation / 2), Size2(get_size().width - style->get_minimum_size().width + hseparation * 2, h + vseparation)));
+ if (r < get_size().width - style->get_margin(MARGIN_RIGHT)) {
+ labeled_separator_right->draw(ci, Rect2(Point2(r, item_ofs.y + Math::floor((h - sep_h) / 2.0)), Size2(MAX(0, get_size().width - style->get_margin(MARGIN_RIGHT) - r), sep_h)));
}
+ } else {
+ separator->draw(ci, Rect2(item_ofs + Point2(0, Math::floor((h - sep_h) / 2.0)), Size2(get_size().width - style->get_minimum_size().width, sep_h)));
+ }
+ }
- String text = items[i].xl_text;
+ Color icon_color(1, 1, 1, items[i].disabled ? 0.5 : 1);
- item_ofs.x += items[i].h_ofs;
- if (items[i].separator) {
+ if (items[i].checkable_type) {
+ Texture2D *icon = (items[i].checked ? check[items[i].checkable_type - 1] : uncheck[items[i].checkable_type - 1]).ptr();
+ icon->draw(ci, item_ofs + Point2(0, Math::floor((h - icon->get_height()) / 2.0)), icon_color);
+ }
- int sep_h = separator->get_center_size().height + separator->get_minimum_size().height;
- if (text != String()) {
- int ss = font->get_string_size(text).width;
- int center = (get_size().width) / 2;
- int l = center - ss / 2;
- int r = center + ss / 2;
- if (l > item_ofs.x) {
- labeled_separator_left->draw(ci, Rect2(item_ofs + Point2(0, Math::floor((h - sep_h) / 2.0)), Size2(MAX(0, l - item_ofs.x), sep_h)));
- }
- if (r < get_size().width - style->get_margin(MARGIN_RIGHT)) {
- labeled_separator_right->draw(ci, Rect2(Point2(r, item_ofs.y + Math::floor((h - sep_h) / 2.0)), Size2(MAX(0, get_size().width - style->get_margin(MARGIN_RIGHT) - r), sep_h)));
- }
- } else {
- separator->draw(ci, Rect2(item_ofs + Point2(0, Math::floor((h - sep_h) / 2.0)), Size2(get_size().width - style->get_minimum_size().width, sep_h)));
- }
- }
+ if (!items[i].icon.is_null()) {
+ items[i].icon->draw(ci, item_ofs + Size2(check_ofs, 0) + Point2(0, Math::floor((h - icon_size.height) / 2.0)), icon_color);
+ }
- Color icon_color(1, 1, 1, items[i].disabled ? 0.5 : 1);
+ if (items[i].submenu != "") {
+ submenu->draw(ci, Point2(size.width - style->get_margin(MARGIN_RIGHT) - submenu->get_width(), item_ofs.y + Math::floor(h - submenu->get_height()) / 2), icon_color);
+ }
- if (items[i].checkable_type) {
- Texture2D *icon = (items[i].checked ? check[items[i].checkable_type - 1] : uncheck[items[i].checkable_type - 1]).ptr();
- icon->draw(ci, item_ofs + Point2(0, Math::floor((h - icon->get_height()) / 2.0)), icon_color);
- }
+ item_ofs.y += font->get_ascent();
+ if (items[i].separator) {
- if (!items[i].icon.is_null()) {
- items[i].icon->draw(ci, item_ofs + Size2(check_ofs, 0) + Point2(0, Math::floor((h - icon_size.height) / 2.0)), icon_color);
- }
+ if (text != String()) {
+ int center = (get_size().width - font->get_string_size(text).width) / 2;
+ font->draw(ci, Point2(center, item_ofs.y + Math::floor((h - font_h) / 2.0)), text, font_color_disabled);
+ }
+ } else {
- if (items[i].submenu != "") {
- submenu->draw(ci, Point2(size.width - style->get_margin(MARGIN_RIGHT) - submenu->get_width(), item_ofs.y + Math::floor(h - submenu->get_height()) / 2), icon_color);
- }
+ item_ofs.x += icon_ofs + check_ofs;
+ font->draw(ci, item_ofs + Point2(0, Math::floor((h - font_h) / 2.0)), text, items[i].disabled ? font_color_disabled : (i == mouse_over ? font_color_hover : font_color));
+ }
- item_ofs.y += font->get_ascent();
- if (items[i].separator) {
+ if (items[i].accel || (items[i].shortcut.is_valid() && items[i].shortcut->is_valid())) {
+ //accelerator
+ String text2 = _get_accel_text(i);
+ item_ofs.x = size.width - style->get_margin(MARGIN_RIGHT) - font->get_string_size(text2).width;
+ font->draw(ci, item_ofs + Point2(0, Math::floor((h - font_h) / 2.0)), text2, i == mouse_over ? font_color_hover : font_color_accel);
+ }
- if (text != String()) {
- int center = (get_size().width - font->get_string_size(text).width) / 2;
- font->draw(ci, Point2(center, item_ofs.y + Math::floor((h - font_h) / 2.0)), text, font_color_disabled);
- }
- } else {
+ items.write[i]._ofs_cache = ofs.y;
- item_ofs.x += icon_ofs + check_ofs;
- font->draw(ci, item_ofs + Point2(0, Math::floor((h - font_h) / 2.0)), text, items[i].disabled ? font_color_disabled : (i == mouse_over ? font_color_hover : font_color));
- }
+ ofs.y += h;
+ }
+}
- if (items[i].accel || (items[i].shortcut.is_valid() && items[i].shortcut->is_valid())) {
- //accelerator
- String text2 = _get_accel_text(i);
- item_ofs.x = size.width - style->get_margin(MARGIN_RIGHT) - font->get_string_size(text2).width;
- font->draw(ci, item_ofs + Point2(0, Math::floor((h - font_h) / 2.0)), text2, i == mouse_over ? font_color_hover : font_color_accel);
- }
+void PopupMenu::_notification(int p_what) {
+
+ switch (p_what) {
- items.write[i]._ofs_cache = ofs.y;
+ case NOTIFICATION_ENTER_TREE: {
- ofs.y += h;
+ PopupMenu *pm = Object::cast_to<PopupMenu>(get_parent());
+ if (pm) {
+ // Inherit submenu's popup delay time from parent menu
+ float pm_delay = pm->get_submenu_popup_delay();
+ set_submenu_popup_delay(pm_delay);
}
} break;
- case MainLoop::NOTIFICATION_WM_FOCUS_OUT: {
+ case NOTIFICATION_TRANSLATION_CHANGED: {
- if (hide_on_window_lose_focus)
- hide();
+ for (int i = 0; i < items.size(); i++) {
+ items.write[i].xl_text = tr(items[i].text);
+ }
+
+ child_controls_changed();
+ control->update();
} break;
- case NOTIFICATION_MOUSE_ENTER: {
+ case NOTIFICATION_WM_MOUSE_ENTER: {
- grab_focus();
+ //grab_focus();
} break;
- case NOTIFICATION_MOUSE_EXIT: {
+ case NOTIFICATION_WM_MOUSE_EXIT: {
if (mouse_over >= 0 && (items[mouse_over].submenu == "" || submenu_over != -1)) {
mouse_over = -1;
- update();
+ control->update();
}
} break;
case NOTIFICATION_POST_POPUP: {
- initial_button_mask = Input::get_singleton()->get_mouse_button_mask();
+ initial_button_mask = InputFilter::get_singleton()->get_mouse_button_mask();
during_grabbed_click = (bool)initial_button_mask;
} break;
- case NOTIFICATION_POPUP_HIDE: {
+ case NOTIFICATION_WM_SIZE_CHANGED: {
- if (mouse_over >= 0) {
- mouse_over = -1;
- update();
+ } break;
+ case NOTIFICATION_INTERNAL_PROCESS: {
+ //only used when using operating system windows
+ if (get_window_id() != DisplayServer::INVALID_WINDOW_ID && autohide_areas.size()) {
+ Point2 mouse_pos = DisplayServer::get_singleton()->mouse_get_position();
+ mouse_pos -= get_position();
+
+ for (List<Rect2>::Element *E = autohide_areas.front(); E; E = E->next()) {
+
+ if (!Rect2(Point2(), get_size()).has_point(mouse_pos) && E->get().has_point(mouse_pos)) {
+ _close_pressed();
+ return;
+ }
+ }
}
+ } break;
+ case NOTIFICATION_VISIBILITY_CHANGED: {
- for (int i = 0; i < items.size(); i++) {
- if (items[i].submenu == "")
- continue;
+ if (!is_visible()) {
+ if (mouse_over >= 0) {
+ mouse_over = -1;
+ control->update();
+ }
+
+ for (int i = 0; i < items.size(); i++) {
+ if (items[i].submenu == "")
+ continue;
- Node *n = get_node(items[i].submenu);
- if (!n)
- continue;
+ Node *n = get_node(items[i].submenu);
+ if (!n)
+ continue;
- PopupMenu *pm = Object::cast_to<PopupMenu>(n);
- if (!pm || !pm->is_visible())
- continue;
+ PopupMenu *pm = Object::cast_to<PopupMenu>(n);
+ if (!pm || !pm->is_visible())
+ continue;
- pm->hide();
+ pm->hide();
+ }
+
+ set_process_internal(false);
+ } else {
+ if (get_window_id() != DisplayServer::INVALID_WINDOW_ID) {
+ set_process_internal(true);
+ }
}
} break;
}
@@ -648,8 +663,8 @@ void PopupMenu::add_item(const String &p_label, int p_id, uint32_t p_accel) {
Item item;
ITEM_SETUP_WITH_ACCEL(p_label, p_id, p_accel);
items.push_back(item);
- update();
- minimum_size_changed();
+ control->update();
+ child_controls_changed();
}
void PopupMenu::add_icon_item(const Ref<Texture2D> &p_icon, const String &p_label, int p_id, uint32_t p_accel) {
@@ -658,8 +673,8 @@ void PopupMenu::add_icon_item(const Ref<Texture2D> &p_icon, const String &p_labe
ITEM_SETUP_WITH_ACCEL(p_label, p_id, p_accel);
item.icon = p_icon;
items.push_back(item);
- update();
- minimum_size_changed();
+ control->update();
+ child_controls_changed();
}
void PopupMenu::add_check_item(const String &p_label, int p_id, uint32_t p_accel) {
@@ -668,8 +683,8 @@ void PopupMenu::add_check_item(const String &p_label, int p_id, uint32_t p_accel
ITEM_SETUP_WITH_ACCEL(p_label, p_id, p_accel);
item.checkable_type = Item::CHECKABLE_TYPE_CHECK_BOX;
items.push_back(item);
- update();
- minimum_size_changed();
+ control->update();
+ child_controls_changed();
}
void PopupMenu::add_icon_check_item(const Ref<Texture2D> &p_icon, const String &p_label, int p_id, uint32_t p_accel) {
@@ -679,8 +694,8 @@ void PopupMenu::add_icon_check_item(const Ref<Texture2D> &p_icon, const String &
item.icon = p_icon;
item.checkable_type = Item::CHECKABLE_TYPE_CHECK_BOX;
items.push_back(item);
- update();
- minimum_size_changed();
+ control->update();
+ child_controls_changed();
}
void PopupMenu::add_radio_check_item(const String &p_label, int p_id, uint32_t p_accel) {
@@ -689,8 +704,8 @@ void PopupMenu::add_radio_check_item(const String &p_label, int p_id, uint32_t p
ITEM_SETUP_WITH_ACCEL(p_label, p_id, p_accel);
item.checkable_type = Item::CHECKABLE_TYPE_RADIO_BUTTON;
items.push_back(item);
- update();
- minimum_size_changed();
+ control->update();
+ child_controls_changed();
}
void PopupMenu::add_icon_radio_check_item(const Ref<Texture2D> &p_icon, const String &p_label, int p_id, uint32_t p_accel) {
@@ -700,8 +715,8 @@ void PopupMenu::add_icon_radio_check_item(const Ref<Texture2D> &p_icon, const St
item.icon = p_icon;
item.checkable_type = Item::CHECKABLE_TYPE_RADIO_BUTTON;
items.push_back(item);
- update();
- minimum_size_changed();
+ control->update();
+ child_controls_changed();
}
void PopupMenu::add_multistate_item(const String &p_label, int p_max_states, int p_default_state, int p_id, uint32_t p_accel) {
@@ -711,8 +726,8 @@ void PopupMenu::add_multistate_item(const String &p_label, int p_max_states, int
item.max_states = p_max_states;
item.state = p_default_state;
items.push_back(item);
- update();
- minimum_size_changed();
+ control->update();
+ child_controls_changed();
}
#define ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global) \
@@ -729,8 +744,8 @@ void PopupMenu::add_shortcut(const Ref<ShortCut> &p_shortcut, int p_id, bool p_g
Item item;
ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global);
items.push_back(item);
- update();
- minimum_size_changed();
+ control->update();
+ child_controls_changed();
}
void PopupMenu::add_icon_shortcut(const Ref<Texture2D> &p_icon, const Ref<ShortCut> &p_shortcut, int p_id, bool p_global) {
@@ -739,8 +754,8 @@ void PopupMenu::add_icon_shortcut(const Ref<Texture2D> &p_icon, const Ref<ShortC
ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global);
item.icon = p_icon;
items.push_back(item);
- update();
- minimum_size_changed();
+ control->update();
+ child_controls_changed();
}
void PopupMenu::add_check_shortcut(const Ref<ShortCut> &p_shortcut, int p_id, bool p_global) {
@@ -749,8 +764,8 @@ void PopupMenu::add_check_shortcut(const Ref<ShortCut> &p_shortcut, int p_id, bo
ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global);
item.checkable_type = Item::CHECKABLE_TYPE_CHECK_BOX;
items.push_back(item);
- update();
- minimum_size_changed();
+ control->update();
+ child_controls_changed();
}
void PopupMenu::add_icon_check_shortcut(const Ref<Texture2D> &p_icon, const Ref<ShortCut> &p_shortcut, int p_id, bool p_global) {
@@ -760,8 +775,8 @@ void PopupMenu::add_icon_check_shortcut(const Ref<Texture2D> &p_icon, const Ref<
item.icon = p_icon;
item.checkable_type = Item::CHECKABLE_TYPE_CHECK_BOX;
items.push_back(item);
- update();
- minimum_size_changed();
+ control->update();
+ child_controls_changed();
}
void PopupMenu::add_radio_check_shortcut(const Ref<ShortCut> &p_shortcut, int p_id, bool p_global) {
@@ -770,8 +785,8 @@ void PopupMenu::add_radio_check_shortcut(const Ref<ShortCut> &p_shortcut, int p_
ITEM_SETUP_WITH_SHORTCUT(p_shortcut, p_id, p_global);
item.checkable_type = Item::CHECKABLE_TYPE_RADIO_BUTTON;
items.push_back(item);
- update();
- minimum_size_changed();
+ control->update();
+ child_controls_changed();
}
void PopupMenu::add_icon_radio_check_shortcut(const Ref<Texture2D> &p_icon, const Ref<ShortCut> &p_shortcut, int p_id, bool p_global) {
@@ -781,8 +796,8 @@ void PopupMenu::add_icon_radio_check_shortcut(const Ref<Texture2D> &p_icon, cons
item.icon = p_icon;
item.checkable_type = Item::CHECKABLE_TYPE_RADIO_BUTTON;
items.push_back(item);
- update();
- minimum_size_changed();
+ control->update();
+ child_controls_changed();
}
void PopupMenu::add_submenu_item(const String &p_label, const String &p_submenu, int p_id) {
@@ -793,8 +808,8 @@ void PopupMenu::add_submenu_item(const String &p_label, const String &p_submenu,
item.id = p_id == -1 ? items.size() : p_id;
item.submenu = p_submenu;
items.push_back(item);
- update();
- minimum_size_changed();
+ control->update();
+ child_controls_changed();
}
#undef ITEM_SETUP_WITH_ACCEL
@@ -808,16 +823,16 @@ void PopupMenu::set_item_text(int p_idx, const String &p_text) {
items.write[p_idx].text = p_text;
items.write[p_idx].xl_text = tr(p_text);
- update();
- minimum_size_changed();
+ control->update();
+ child_controls_changed();
}
void PopupMenu::set_item_icon(int p_idx, const Ref<Texture2D> &p_icon) {
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].icon = p_icon;
- update();
- minimum_size_changed();
+ control->update();
+ child_controls_changed();
}
void PopupMenu::set_item_checked(int p_idx, bool p_checked) {
@@ -825,16 +840,16 @@ void PopupMenu::set_item_checked(int p_idx, bool p_checked) {
items.write[p_idx].checked = p_checked;
- update();
- minimum_size_changed();
+ control->update();
+ child_controls_changed();
}
void PopupMenu::set_item_id(int p_idx, int p_id) {
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].id = p_id;
- update();
- minimum_size_changed();
+ control->update();
+ child_controls_changed();
}
void PopupMenu::set_item_accelerator(int p_idx, uint32_t p_accel) {
@@ -842,40 +857,40 @@ void PopupMenu::set_item_accelerator(int p_idx, uint32_t p_accel) {
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].accel = p_accel;
- update();
- minimum_size_changed();
+ control->update();
+ child_controls_changed();
}
void PopupMenu::set_item_metadata(int p_idx, const Variant &p_meta) {
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].metadata = p_meta;
- update();
- minimum_size_changed();
+ control->update();
+ child_controls_changed();
}
void PopupMenu::set_item_disabled(int p_idx, bool p_disabled) {
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].disabled = p_disabled;
- update();
- minimum_size_changed();
+ control->update();
+ child_controls_changed();
}
void PopupMenu::set_item_submenu(int p_idx, const String &p_submenu) {
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].submenu = p_submenu;
- update();
- minimum_size_changed();
+ control->update();
+ child_controls_changed();
}
void PopupMenu::toggle_item_checked(int p_idx) {
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].checked = !items[p_idx].checked;
- update();
- minimum_size_changed();
+ control->update();
+ child_controls_changed();
}
String PopupMenu::get_item_text(int p_idx) const {
@@ -968,7 +983,7 @@ void PopupMenu::set_item_as_separator(int p_idx, bool p_separator) {
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].separator = p_separator;
- update();
+ control->update();
}
bool PopupMenu::is_item_separator(int p_idx) const {
@@ -980,21 +995,21 @@ void PopupMenu::set_item_as_checkable(int p_idx, bool p_checkable) {
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].checkable_type = p_checkable ? Item::CHECKABLE_TYPE_CHECK_BOX : Item::CHECKABLE_TYPE_NONE;
- update();
+ control->update();
}
void PopupMenu::set_item_as_radio_checkable(int p_idx, bool p_radio_checkable) {
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].checkable_type = p_radio_checkable ? Item::CHECKABLE_TYPE_RADIO_BUTTON : Item::CHECKABLE_TYPE_NONE;
- update();
+ control->update();
}
void PopupMenu::set_item_tooltip(int p_idx, const String &p_tooltip) {
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].tooltip = p_tooltip;
- update();
+ control->update();
}
void PopupMenu::set_item_shortcut(int p_idx, const Ref<ShortCut> &p_shortcut, bool p_global) {
@@ -1009,29 +1024,29 @@ void PopupMenu::set_item_shortcut(int p_idx, const Ref<ShortCut> &p_shortcut, bo
_ref_shortcut(items[p_idx].shortcut);
}
- update();
+ control->update();
}
void PopupMenu::set_item_h_offset(int p_idx, int p_offset) {
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].h_ofs = p_offset;
- update();
- minimum_size_changed();
+ control->update();
+ child_controls_changed();
}
void PopupMenu::set_item_multistate(int p_idx, int p_state) {
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].state = p_state;
- update();
+ control->update();
}
void PopupMenu::set_item_shortcut_disabled(int p_idx, bool p_disabled) {
ERR_FAIL_INDEX(p_idx, items.size());
items.write[p_idx].shortcut_is_disabled = p_disabled;
- update();
+ control->update();
}
void PopupMenu::toggle_item_multistate(int p_idx) {
@@ -1045,7 +1060,7 @@ void PopupMenu::toggle_item_multistate(int p_idx) {
if (items.write[p_idx].max_states <= items[p_idx].state)
items.write[p_idx].state = 0;
- update();
+ control->update();
}
bool PopupMenu::is_item_checkable(int p_idx) const {
@@ -1177,8 +1192,8 @@ void PopupMenu::remove_item(int p_idx) {
}
items.remove(p_idx);
- update();
- minimum_size_changed();
+ control->update();
+ child_controls_changed();
}
void PopupMenu::add_separator(const String &p_text) {
@@ -1191,7 +1206,7 @@ void PopupMenu::add_separator(const String &p_text) {
sep.xl_text = tr(p_text);
}
items.push_back(sep);
- update();
+ control->update();
}
void PopupMenu::clear() {
@@ -1203,8 +1218,8 @@ void PopupMenu::clear() {
}
items.clear();
mouse_over = -1;
- update();
- minimum_size_changed();
+ control->update();
+ child_controls_changed();
}
Array PopupMenu::_get_items() const {
@@ -1345,16 +1360,6 @@ bool PopupMenu::get_allow_search() const {
return allow_search;
}
-void PopupMenu::set_hide_on_window_lose_focus(bool p_enabled) {
-
- hide_on_window_lose_focus = p_enabled;
-}
-
-bool PopupMenu::is_hide_on_window_lose_focus() const {
-
- return hide_on_window_lose_focus;
-}
-
String PopupMenu::get_tooltip(const Point2 &p_pos) const {
int over = _get_mouse_over(p_pos);
@@ -1387,6 +1392,14 @@ void PopupMenu::clear_autohide_areas() {
autohide_areas.clear();
}
+void PopupMenu::take_mouse_focus() {
+ ERR_FAIL_COND(!is_inside_tree());
+
+ if (get_parent()) {
+ get_parent()->get_viewport()->pass_mouse_focus_to(this, control);
+ }
+}
+
void PopupMenu::_bind_methods() {
ClassDB::bind_method(D_METHOD("_gui_input"), &PopupMenu::_gui_input);
@@ -1466,9 +1479,6 @@ void PopupMenu::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_submenu_popup_delay", "seconds"), &PopupMenu::set_submenu_popup_delay);
ClassDB::bind_method(D_METHOD("get_submenu_popup_delay"), &PopupMenu::get_submenu_popup_delay);
- ClassDB::bind_method(D_METHOD("set_hide_on_window_lose_focus", "enable"), &PopupMenu::set_hide_on_window_lose_focus);
- ClassDB::bind_method(D_METHOD("is_hide_on_window_lose_focus"), &PopupMenu::is_hide_on_window_lose_focus);
-
ClassDB::bind_method(D_METHOD("set_allow_search", "allow"), &PopupMenu::set_allow_search);
ClassDB::bind_method(D_METHOD("get_allow_search"), &PopupMenu::get_allow_search);
@@ -1486,7 +1496,6 @@ void PopupMenu::_bind_methods() {
void PopupMenu::popup(const Rect2 &p_bounds) {
- grab_click_focus();
moved = Vector2();
invalidated_click = true;
Popup::popup(p_bounds);
@@ -1494,6 +1503,13 @@ void PopupMenu::popup(const Rect2 &p_bounds) {
PopupMenu::PopupMenu() {
+ control = memnew(Control);
+ add_child(control);
+
+ control->set_anchors_and_margins_preset(Control::PRESET_WIDE);
+ connect("window_input", callable_mp(this, &PopupMenu::_gui_input));
+ control->connect("draw", callable_mp(this, &PopupMenu::_draw));
+
mouse_over = -1;
submenu_over = -1;
initial_button_mask = 0;
@@ -1503,12 +1519,9 @@ PopupMenu::PopupMenu() {
search_time_msec = 0;
search_string = "";
- set_focus_mode(FOCUS_ALL);
- set_as_toplevel(true);
set_hide_on_item_selection(true);
set_hide_on_checkable_item_selection(true);
set_hide_on_multistate_item_selection(false);
- set_hide_on_window_lose_focus(true);
submenu_timer = memnew(Timer);
submenu_timer->set_wait_time(0.3);
diff --git a/scene/gui/popup_menu.h b/scene/gui/popup_menu.h
index a3a858cfde..2eef1f009d 100644
--- a/scene/gui/popup_menu.h
+++ b/scene/gui/popup_menu.h
@@ -32,6 +32,7 @@
#define POPUP_MENU_H
#include "scene/gui/popup.h"
+#include "scene/gui/shortcut.h"
class PopupMenu : public Popup {
@@ -87,7 +88,7 @@ class PopupMenu : public Popup {
Rect2 parent_rect;
String _get_accel_text(int p_item) const;
int _get_mouse_over(const Point2 &p_over) const;
- virtual Size2 get_minimum_size() const;
+ virtual Size2 _get_contents_minimum_size() const;
void _scroll(float p_factor, const Point2 &p_over);
void _gui_input(const Ref<InputEvent> &p_event);
void _activate_submenu(int over);
@@ -97,7 +98,6 @@ class PopupMenu : public Popup {
bool hide_on_item_selection;
bool hide_on_checkable_item_selection;
bool hide_on_multistate_item_selection;
- bool hide_on_window_lose_focus;
Vector2 moved;
Array _get_items() const;
@@ -112,9 +112,11 @@ class PopupMenu : public Popup {
uint64_t search_time_msec;
String search_string;
-protected:
- virtual bool has_point(const Point2 &p_point) const;
+ Control *control;
+
+ void _draw();
+protected:
friend class MenuButton;
void _notification(int p_what);
static void _bind_methods();
@@ -213,8 +215,7 @@ public:
virtual void popup(const Rect2 &p_bounds = Rect2());
- void set_hide_on_window_lose_focus(bool p_enabled);
- bool is_hide_on_window_lose_focus() const;
+ void take_mouse_focus();
PopupMenu();
~PopupMenu();
diff --git a/scene/gui/progress_bar.cpp b/scene/gui/progress_bar.cpp
index e11295d7e7..362c45453d 100644
--- a/scene/gui/progress_bar.cpp
+++ b/scene/gui/progress_bar.cpp
@@ -32,9 +32,9 @@
Size2 ProgressBar::get_minimum_size() const {
- Ref<StyleBox> bg = get_stylebox("bg");
- Ref<StyleBox> fg = get_stylebox("fg");
- Ref<Font> font = get_font("font");
+ Ref<StyleBox> bg = get_theme_stylebox("bg");
+ Ref<StyleBox> fg = get_theme_stylebox("fg");
+ Ref<Font> font = get_theme_font("font");
Size2 minimum_size = bg->get_minimum_size();
minimum_size.height = MAX(minimum_size.height, fg->get_minimum_size().height);
@@ -52,10 +52,10 @@ void ProgressBar::_notification(int p_what) {
if (p_what == NOTIFICATION_DRAW) {
- Ref<StyleBox> bg = get_stylebox("bg");
- Ref<StyleBox> fg = get_stylebox("fg");
- Ref<Font> font = get_font("font");
- Color font_color = get_color("font_color");
+ Ref<StyleBox> bg = get_theme_stylebox("bg");
+ Ref<StyleBox> fg = get_theme_stylebox("fg");
+ Ref<Font> font = get_theme_font("font");
+ Color font_color = get_theme_color("font_color");
draw_style_box(bg, Rect2(Point2(), get_size()));
float r = get_as_ratio();
diff --git a/scene/gui/rich_text_label.cpp b/scene/gui/rich_text_label.cpp
index e4651ef473..df28a4c12f 100644
--- a/scene/gui/rich_text_label.cpp
+++ b/scene/gui/rich_text_label.cpp
@@ -34,6 +34,7 @@
#include "core/os/keyboard.h"
#include "core/os/os.h"
#include "scene/scene_string_names.h"
+#include "servers/display_server.h"
#include "modules/modules_enabled.gen.h"
#ifdef MODULE_REGEX_ENABLED
@@ -142,7 +143,7 @@ RichTextLabel::Item *RichTextLabel::_get_prev_item(Item *p_item, bool p_free) {
}
Rect2 RichTextLabel::_get_text_rect() {
- Ref<StyleBox> style = get_stylebox("normal");
+ Ref<StyleBox> style = get_theme_stylebox("normal");
return Rect2(style->get_offset(), get_size() - style->get_minimum_size());
}
@@ -240,7 +241,7 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int &
l.space_caches.push_back(spaces); \
} \
line_wrapped = false; \
- y += line_height + get_constant(SceneStringNames::get_singleton()->line_separation); \
+ y += line_height + get_theme_constant(SceneStringNames::get_singleton()->line_separation); \
line_height = 0; \
line_ascent = 0; \
line_descent = 0; \
@@ -305,8 +306,8 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int &
Color selection_bg;
if (p_mode == PROCESS_DRAW) {
- selection_fg = get_color("font_color_selected");
- selection_bg = get_color("selection_color");
+ selection_fg = get_theme_color("font_color_selected");
+ selection_bg = get_theme_color("selection_color");
}
int rchar = 0;
@@ -667,13 +668,13 @@ int RichTextLabel::_process_line(ItemFrame *p_frame, const Vector2 &p_ofs, int &
lh = 0;
ItemTable *table = static_cast<ItemTable *>(it);
- int hseparation = get_constant("table_hseparation");
- int vseparation = get_constant("table_vseparation");
+ int hseparation = get_theme_constant("table_hseparation");
+ int vseparation = get_theme_constant("table_vseparation");
Color ccolor = _find_color(table, p_base_color);
Vector2 draw_ofs = Point2(wofs, y);
- Color font_color_shadow = get_color("font_color_shadow");
- bool use_outline = get_constant("shadow_as_outline");
- Point2 shadow_ofs2(get_constant("shadow_offset_x"), get_constant("shadow_offset_y"));
+ Color font_color_shadow = get_theme_color("font_color_shadow");
+ bool use_outline = get_theme_constant("shadow_as_outline");
+ Point2 shadow_ofs2(get_theme_constant("shadow_offset_x"), get_theme_constant("shadow_offset_y"));
if (p_mode == PROCESS_CACHE) {
@@ -987,11 +988,11 @@ void RichTextLabel::_notification(int p_what) {
Size2 size = get_size();
Rect2 text_rect = _get_text_rect();
- draw_style_box(get_stylebox("normal"), Rect2(Point2(), size));
+ draw_style_box(get_theme_stylebox("normal"), Rect2(Point2(), size));
if (has_focus()) {
VisualServer::get_singleton()->canvas_item_add_clip_ignore(ci, true);
- draw_style_box(get_stylebox("focus"), Rect2(Point2(), size));
+ draw_style_box(get_theme_stylebox("focus"), Rect2(Point2(), size));
VisualServer::get_singleton()->canvas_item_add_clip_ignore(ci, false);
}
@@ -1012,11 +1013,11 @@ void RichTextLabel::_notification(int p_what) {
if (from_line >= main->lines.size())
break; //nothing to draw
int y = (main->lines[from_line].height_accum_cache - main->lines[from_line].height_cache) - ofs;
- Ref<Font> base_font = get_font("normal_font");
- Color base_color = get_color("default_color");
- Color font_color_shadow = get_color("font_color_shadow");
- bool use_outline = get_constant("shadow_as_outline");
- Point2 shadow_ofs(get_constant("shadow_offset_x"), get_constant("shadow_offset_y"));
+ Ref<Font> base_font = get_theme_font("normal_font");
+ Color base_color = get_theme_color("default_color");
+ Color font_color_shadow = get_theme_color("font_color_shadow");
+ bool use_outline = get_theme_constant("shadow_as_outline");
+ Point2 shadow_ofs(get_theme_constant("shadow_offset_x"), get_theme_constant("shadow_offset_y"));
visible_line_count = 0;
while (y < size.height && from_line < main->lines.size()) {
@@ -1043,9 +1044,9 @@ void RichTextLabel::_find_click(ItemFrame *p_frame, const Point2i &p_click, Item
Rect2 text_rect = _get_text_rect();
int ofs = vscroll->get_value();
- Color font_color_shadow = get_color("font_color_shadow");
- bool use_outline = get_constant("shadow_as_outline");
- Point2 shadow_ofs(get_constant("shadow_offset_x"), get_constant("shadow_offset_y"));
+ Color font_color_shadow = get_theme_color("font_color_shadow");
+ bool use_outline = get_theme_constant("shadow_as_outline");
+ Point2 shadow_ofs(get_theme_constant("shadow_offset_x"), get_theme_constant("shadow_offset_y"));
//todo, change to binary search
int from_line = 0;
@@ -1061,8 +1062,8 @@ void RichTextLabel::_find_click(ItemFrame *p_frame, const Point2i &p_click, Item
return;
int y = (p_frame->lines[from_line].height_accum_cache - p_frame->lines[from_line].height_cache) - ofs;
- Ref<Font> base_font = get_font("normal_font");
- Color base_color = get_color("default_color");
+ Ref<Font> base_font = get_theme_font("normal_font");
+ Color base_color = get_theme_color("default_color");
while (y < text_rect.get_size().height && from_line < p_frame->lines.size()) {
@@ -1227,14 +1228,14 @@ void RichTextLabel::_gui_input(Ref<InputEvent> p_event) {
case KEY_UP: {
if (vscroll->is_visible_in_tree()) {
- vscroll->set_value(vscroll->get_value() - get_font("normal_font")->get_height());
+ vscroll->set_value(vscroll->get_value() - get_theme_font("normal_font")->get_height());
handled = true;
}
} break;
case KEY_DOWN: {
if (vscroll->is_visible_in_tree()) {
- vscroll->set_value(vscroll->get_value() + get_font("normal_font")->get_height());
+ vscroll->set_value(vscroll->get_value() + get_theme_font("normal_font")->get_height());
handled = true;
}
} break;
@@ -1525,11 +1526,11 @@ void RichTextLabel::_validate_line_caches(ItemFrame *p_frame) {
size.width = fixed_width;
}
Rect2 text_rect = _get_text_rect();
- Color font_color_shadow = get_color("font_color_shadow");
- bool use_outline = get_constant("shadow_as_outline");
- Point2 shadow_ofs(get_constant("shadow_offset_x"), get_constant("shadow_offset_y"));
+ Color font_color_shadow = get_theme_color("font_color_shadow");
+ bool use_outline = get_theme_constant("shadow_as_outline");
+ Point2 shadow_ofs(get_theme_constant("shadow_offset_x"), get_theme_constant("shadow_offset_y"));
- Ref<Font> base_font = get_font("normal_font");
+ Ref<Font> base_font = get_theme_font("normal_font");
for (int i = p_frame->first_invalid_line; i < p_frame->lines.size(); i++) {
@@ -1544,7 +1545,7 @@ void RichTextLabel::_validate_line_caches(ItemFrame *p_frame) {
int total_height = 0;
if (p_frame->lines.size())
- total_height = p_frame->lines[p_frame->lines.size() - 1].height_accum_cache + get_stylebox("normal")->get_minimum_size().height;
+ total_height = p_frame->lines[p_frame->lines.size() - 1].height_accum_cache + get_theme_stylebox("normal")->get_minimum_size().height;
main->first_invalid_line = p_frame->lines.size();
@@ -1646,6 +1647,10 @@ void RichTextLabel::_add_item(Item *p_item, bool p_enter, bool p_ensure_newline)
p_item->line = current_frame->lines.size() - 1;
_invalidate_current_line(current_frame);
+
+ if (fixed_width != -1) {
+ minimum_size_changed();
+ }
}
void RichTextLabel::_remove_item(Item *p_item, const int p_line, const int p_subitem_line) {
@@ -1758,35 +1763,35 @@ void RichTextLabel::push_font(const Ref<Font> &p_font) {
}
void RichTextLabel::push_normal() {
- Ref<Font> normal_font = get_font("normal_font");
+ Ref<Font> normal_font = get_theme_font("normal_font");
ERR_FAIL_COND(normal_font.is_null());
push_font(normal_font);
}
void RichTextLabel::push_bold() {
- Ref<Font> bold_font = get_font("bold_font");
+ Ref<Font> bold_font = get_theme_font("bold_font");
ERR_FAIL_COND(bold_font.is_null());
push_font(bold_font);
}
void RichTextLabel::push_bold_italics() {
- Ref<Font> bold_italics_font = get_font("bold_italics_font");
+ Ref<Font> bold_italics_font = get_theme_font("bold_italics_font");
ERR_FAIL_COND(bold_italics_font.is_null());
push_font(bold_italics_font);
}
void RichTextLabel::push_italics() {
- Ref<Font> italics_font = get_font("italics_font");
+ Ref<Font> italics_font = get_theme_font("italics_font");
ERR_FAIL_COND(italics_font.is_null());
push_font(italics_font);
}
void RichTextLabel::push_mono() {
- Ref<Font> mono_font = get_font("mono_font");
+ Ref<Font> mono_font = get_theme_font("mono_font");
ERR_FAIL_COND(mono_font.is_null());
push_font(mono_font);
@@ -1967,6 +1972,10 @@ void RichTextLabel::clear() {
selection.click = NULL;
selection.active = false;
current_idx = 1;
+
+ if (fixed_width != -1) {
+ minimum_size_changed();
+ }
}
void RichTextLabel::set_tab_size(int p_spaces) {
@@ -2044,13 +2053,13 @@ Error RichTextLabel::append_bbcode(const String &p_bbcode) {
int pos = 0;
List<String> tag_stack;
- Ref<Font> normal_font = get_font("normal_font");
- Ref<Font> bold_font = get_font("bold_font");
- Ref<Font> italics_font = get_font("italics_font");
- Ref<Font> bold_italics_font = get_font("bold_italics_font");
- Ref<Font> mono_font = get_font("mono_font");
+ Ref<Font> normal_font = get_theme_font("normal_font");
+ Ref<Font> bold_font = get_theme_font("bold_font");
+ Ref<Font> italics_font = get_theme_font("italics_font");
+ Ref<Font> bold_italics_font = get_theme_font("bold_italics_font");
+ Ref<Font> mono_font = get_theme_font("mono_font");
- Color base_color = get_color("default_color");
+ Color base_color = get_theme_color("default_color");
int indent_level = 0;
@@ -2518,7 +2527,7 @@ bool RichTextLabel::search(const String &p_string, bool p_from_selection, bool p
_validate_line_caches(main);
- int fh = _find_font(t).is_valid() ? _find_font(t)->get_height() : get_font("normal_font")->get_height();
+ int fh = _find_font(t).is_valid() ? _find_font(t)->get_height() : get_theme_font("normal_font")->get_height();
float offset = 0;
@@ -2584,7 +2593,7 @@ void RichTextLabel::selection_copy() {
}
if (text != "") {
- OS::get_singleton()->set_clipboard(text);
+ DisplayServer::get_singleton()->clipboard_set(text);
}
}
@@ -2692,7 +2701,7 @@ void RichTextLabel::install_effect(const Variant effect) {
int RichTextLabel::get_content_height() {
int total_height = 0;
if (main->lines.size())
- total_height = main->lines[main->lines.size() - 1].height_accum_cache + get_stylebox("normal")->get_minimum_size().height;
+ total_height = main->lines[main->lines.size() - 1].height_accum_cache + get_theme_stylebox("normal")->get_minimum_size().height;
return total_height;
}
diff --git a/scene/gui/scroll_bar.cpp b/scene/gui/scroll_bar.cpp
index fef5e00984..5e9541730e 100644
--- a/scene/gui/scroll_bar.cpp
+++ b/scene/gui/scroll_bar.cpp
@@ -33,6 +33,7 @@
#include "core/os/keyboard.h"
#include "core/os/os.h"
#include "core/print_string.h"
+#include "scene/main/window.h"
bool ScrollBar::focus_by_default = false;
@@ -71,8 +72,8 @@ void ScrollBar::_gui_input(Ref<InputEvent> p_event) {
if (b->is_pressed()) {
double ofs = orientation == VERTICAL ? b->get_position().y : b->get_position().x;
- Ref<Texture2D> decr = get_icon("decrement");
- Ref<Texture2D> incr = get_icon("increment");
+ Ref<Texture2D> decr = get_theme_icon("decrement");
+ Ref<Texture2D> incr = get_theme_icon("increment");
double decr_size = orientation == VERTICAL ? decr->get_height() : decr->get_width();
double incr_size = orientation == VERTICAL ? incr->get_height() : incr->get_width();
@@ -148,7 +149,7 @@ void ScrollBar::_gui_input(Ref<InputEvent> p_event) {
if (drag.active) {
double ofs = orientation == VERTICAL ? m->get_position().y : m->get_position().x;
- Ref<Texture2D> decr = get_icon("decrement");
+ Ref<Texture2D> decr = get_theme_icon("decrement");
double decr_size = orientation == VERTICAL ? decr->get_height() : decr->get_width();
ofs -= decr_size;
@@ -159,8 +160,8 @@ void ScrollBar::_gui_input(Ref<InputEvent> p_event) {
} else {
double ofs = orientation == VERTICAL ? m->get_position().y : m->get_position().x;
- Ref<Texture2D> decr = get_icon("decrement");
- Ref<Texture2D> incr = get_icon("increment");
+ Ref<Texture2D> decr = get_theme_icon("decrement");
+ Ref<Texture2D> incr = get_theme_icon("increment");
double decr_size = orientation == VERTICAL ? decr->get_height() : decr->get_width();
double incr_size = orientation == VERTICAL ? incr->get_height() : incr->get_width();
@@ -233,17 +234,17 @@ void ScrollBar::_notification(int p_what) {
RID ci = get_canvas_item();
- Ref<Texture2D> decr = highlight == HIGHLIGHT_DECR ? get_icon("decrement_highlight") : get_icon("decrement");
- Ref<Texture2D> incr = highlight == HIGHLIGHT_INCR ? get_icon("increment_highlight") : get_icon("increment");
- Ref<StyleBox> bg = has_focus() ? get_stylebox("scroll_focus") : get_stylebox("scroll");
+ Ref<Texture2D> decr = highlight == HIGHLIGHT_DECR ? get_theme_icon("decrement_highlight") : get_theme_icon("decrement");
+ Ref<Texture2D> incr = highlight == HIGHLIGHT_INCR ? get_theme_icon("increment_highlight") : get_theme_icon("increment");
+ Ref<StyleBox> bg = has_focus() ? get_theme_stylebox("scroll_focus") : get_theme_stylebox("scroll");
Ref<StyleBox> grabber;
if (drag.active)
- grabber = get_stylebox("grabber_pressed");
+ grabber = get_theme_stylebox("grabber_pressed");
else if (highlight == HIGHLIGHT_RANGE)
- grabber = get_stylebox("grabber_highlight");
+ grabber = get_theme_stylebox("grabber_highlight");
else
- grabber = get_stylebox("grabber");
+ grabber = get_theme_stylebox("grabber");
Point2 ofs;
@@ -416,7 +417,7 @@ void ScrollBar::_notification(int p_what) {
double ScrollBar::get_grabber_min_size() const {
- Ref<StyleBox> grabber = get_stylebox("grabber");
+ Ref<StyleBox> grabber = get_theme_stylebox("grabber");
Size2 gminsize = grabber->get_minimum_size() + grabber->get_center_size();
return (orientation == VERTICAL) ? gminsize.height : gminsize.width;
}
@@ -442,17 +443,17 @@ double ScrollBar::get_area_size() const {
switch (orientation) {
case VERTICAL: {
double area = get_size().height;
- area -= get_stylebox("scroll")->get_minimum_size().height;
- area -= get_icon("increment")->get_height();
- area -= get_icon("decrement")->get_height();
+ area -= get_theme_stylebox("scroll")->get_minimum_size().height;
+ area -= get_theme_icon("increment")->get_height();
+ area -= get_theme_icon("decrement")->get_height();
area -= get_grabber_min_size();
return area;
} break;
case HORIZONTAL: {
double area = get_size().width;
- area -= get_stylebox("scroll")->get_minimum_size().width;
- area -= get_icon("increment")->get_width();
- area -= get_icon("decrement")->get_width();
+ area -= get_theme_stylebox("scroll")->get_minimum_size().width;
+ area -= get_theme_icon("increment")->get_width();
+ area -= get_theme_icon("decrement")->get_width();
area -= get_grabber_min_size();
return area;
} break;
@@ -468,14 +469,14 @@ double ScrollBar::get_area_offset() const {
if (orientation == VERTICAL) {
- ofs += get_stylebox("hscroll")->get_margin(MARGIN_TOP);
- ofs += get_icon("decrement")->get_height();
+ ofs += get_theme_stylebox("hscroll")->get_margin(MARGIN_TOP);
+ ofs += get_theme_icon("decrement")->get_height();
}
if (orientation == HORIZONTAL) {
- ofs += get_stylebox("hscroll")->get_margin(MARGIN_LEFT);
- ofs += get_icon("decrement")->get_width();
+ ofs += get_theme_stylebox("hscroll")->get_margin(MARGIN_LEFT);
+ ofs += get_theme_icon("decrement")->get_width();
}
return ofs;
@@ -500,9 +501,9 @@ double ScrollBar::get_grabber_offset() const {
Size2 ScrollBar::get_minimum_size() const {
- Ref<Texture2D> incr = get_icon("increment");
- Ref<Texture2D> decr = get_icon("decrement");
- Ref<StyleBox> bg = get_stylebox("scroll");
+ Ref<Texture2D> incr = get_theme_icon("increment");
+ Ref<Texture2D> decr = get_theme_icon("decrement");
+ Ref<StyleBox> bg = get_theme_stylebox("scroll");
Size2 minsize;
if (orientation == VERTICAL) {
@@ -559,8 +560,7 @@ void ScrollBar::_drag_node_input(const Ref<InputEvent> &p_input) {
drag_node_accum = Vector2();
last_drag_node_accum = Vector2();
drag_node_from = Vector2(orientation == HORIZONTAL ? get_value() : 0, orientation == VERTICAL ? get_value() : 0);
-
- drag_node_touching = OS::get_singleton()->has_touchscreen_ui_hint();
+ drag_node_touching = !DisplayServer::get_singleton()->screen_is_touchscreen(DisplayServer::get_singleton()->window_get_current_screen(get_viewport()->get_window_id()));
drag_node_touching_deaccel = false;
time_since_motion = 0;
diff --git a/scene/gui/scroll_container.cpp b/scene/gui/scroll_container.cpp
index c25a6d5a0c..fb17adf96e 100644
--- a/scene/gui/scroll_container.cpp
+++ b/scene/gui/scroll_container.cpp
@@ -30,7 +30,7 @@
#include "scroll_container.h"
#include "core/os/os.h"
-#include "scene/main/viewport.h"
+#include "scene/main/window.h"
bool ScrollContainer::clips_input() const {
@@ -39,7 +39,7 @@ bool ScrollContainer::clips_input() const {
Size2 ScrollContainer::get_minimum_size() const {
- Ref<StyleBox> sb = get_stylebox("bg");
+ Ref<StyleBox> sb = get_theme_stylebox("bg");
Size2 min_size;
for (int i = 0; i < get_child_count(); i++) {
@@ -129,7 +129,7 @@ void ScrollContainer::_gui_input(const Ref<InputEvent> &p_gui_input) {
if (v_scroll->get_value() != prev_v_scroll || h_scroll->get_value() != prev_h_scroll)
accept_event(); //accept event if scroll changed
- if (!OS::get_singleton()->has_touchscreen_ui_hint())
+ if (!DisplayServer::get_singleton()->screen_is_touchscreen(DisplayServer::get_singleton()->window_get_current_screen(get_viewport()->get_window_id())))
return;
if (mb->get_button_index() != BUTTON_LEFT)
@@ -145,7 +145,7 @@ void ScrollContainer::_gui_input(const Ref<InputEvent> &p_gui_input) {
drag_accum = Vector2();
last_drag_accum = Vector2();
drag_from = Vector2(h_scroll->get_value(), v_scroll->get_value());
- drag_touching = OS::get_singleton()->has_touchscreen_ui_hint();
+ drag_touching = !DisplayServer::get_singleton()->screen_is_touchscreen(DisplayServer::get_singleton()->window_get_current_screen(get_viewport()->get_window_id()));
drag_touching_deaccel = false;
beyond_deadzone = false;
time_since_motion = 0;
@@ -276,7 +276,7 @@ void ScrollContainer::_notification(int p_what) {
Size2 size = get_size();
Point2 ofs;
- Ref<StyleBox> sb = get_stylebox("bg");
+ Ref<StyleBox> sb = get_theme_stylebox("bg");
size -= sb->get_minimum_size();
ofs += sb->get_offset();
@@ -323,7 +323,7 @@ void ScrollContainer::_notification(int p_what) {
if (p_what == NOTIFICATION_DRAW) {
- Ref<StyleBox> sb = get_stylebox("bg");
+ Ref<StyleBox> sb = get_theme_stylebox("bg");
draw_style_box(sb, Rect2(Vector2(), get_size()));
update_scrollbars();
@@ -404,7 +404,7 @@ void ScrollContainer::_notification(int p_what) {
void ScrollContainer::update_scrollbars() {
Size2 size = get_size();
- Ref<StyleBox> sb = get_stylebox("bg");
+ Ref<StyleBox> sb = get_theme_stylebox("bg");
size -= sb->get_minimum_size();
Size2 hmin;
diff --git a/scene/gui/separator.cpp b/scene/gui/separator.cpp
index 4635efb233..75c4b7cce9 100644
--- a/scene/gui/separator.cpp
+++ b/scene/gui/separator.cpp
@@ -34,9 +34,9 @@ Size2 Separator::get_minimum_size() const {
Size2 ms(3, 3);
if (orientation == VERTICAL) {
- ms.x = get_constant("separation");
+ ms.x = get_theme_constant("separation");
} else { // HORIZONTAL
- ms.y = get_constant("separation");
+ ms.y = get_theme_constant("separation");
}
return ms;
}
@@ -48,7 +48,7 @@ void Separator::_notification(int p_what) {
case NOTIFICATION_DRAW: {
Size2i size = get_size();
- Ref<StyleBox> style = get_stylebox("separator");
+ Ref<StyleBox> style = get_theme_stylebox("separator");
Size2i ssize = style->get_minimum_size() + style->get_center_size();
if (orientation == VERTICAL) {
diff --git a/scene/gui/shortcut.h b/scene/gui/shortcut.h
index 59d3245db5..b22c3441c5 100644
--- a/scene/gui/shortcut.h
+++ b/scene/gui/shortcut.h
@@ -31,7 +31,7 @@
#ifndef SHORTCUT_H
#define SHORTCUT_H
-#include "core/os/input_event.h"
+#include "core/input/input_event.h"
#include "core/resource.h"
class ShortCut : public Resource {
diff --git a/scene/gui/slider.cpp b/scene/gui/slider.cpp
index 85887ef7b1..e47e2b869d 100644
--- a/scene/gui/slider.cpp
+++ b/scene/gui/slider.cpp
@@ -33,10 +33,10 @@
Size2 Slider::get_minimum_size() const {
- Ref<StyleBox> style = get_stylebox("slider");
+ Ref<StyleBox> style = get_theme_stylebox("slider");
Size2i ss = style->get_minimum_size() + style->get_center_size();
- Ref<Texture2D> grabber = get_icon("grabber");
+ Ref<Texture2D> grabber = get_theme_icon("grabber");
Size2i rs = grabber->get_size();
if (orientation == HORIZONTAL)
@@ -57,7 +57,7 @@ void Slider::_gui_input(Ref<InputEvent> p_event) {
if (mb->get_button_index() == BUTTON_LEFT) {
if (mb->is_pressed()) {
- Ref<Texture2D> grabber = get_icon(mouse_inside || has_focus() ? "grabber_highlight" : "grabber");
+ Ref<Texture2D> grabber = get_theme_icon(mouse_inside || has_focus() ? "grabber_highlight" : "grabber");
grab.pos = orientation == VERTICAL ? mb->get_position().y : mb->get_position().x;
double grab_width = (double)grabber->get_size().width;
@@ -87,7 +87,7 @@ void Slider::_gui_input(Ref<InputEvent> p_event) {
if (grab.active) {
Size2i size = get_size();
- Ref<Texture2D> grabber = get_icon("grabber");
+ Ref<Texture2D> grabber = get_theme_icon("grabber");
float motion = (orientation == VERTICAL ? mm->get_position().y : mm->get_position().x) - grab.pos;
if (orientation == VERTICAL)
motion = -motion;
@@ -165,10 +165,10 @@ void Slider::_notification(int p_what) {
case NOTIFICATION_DRAW: {
RID ci = get_canvas_item();
Size2i size = get_size();
- Ref<StyleBox> style = get_stylebox("slider");
- Ref<StyleBox> grabber_area = get_stylebox("grabber_area");
- Ref<Texture2D> grabber = get_icon(editable ? ((mouse_inside || has_focus()) ? "grabber_highlight" : "grabber") : "grabber_disabled");
- Ref<Texture2D> tick = get_icon("tick");
+ Ref<StyleBox> style = get_theme_stylebox("slider");
+ Ref<StyleBox> grabber_area = get_theme_stylebox("grabber_area");
+ Ref<Texture2D> grabber = get_theme_icon(editable ? ((mouse_inside || has_focus()) ? "grabber_highlight" : "grabber") : "grabber_disabled");
+ Ref<Texture2D> tick = get_theme_icon("tick");
double ratio = Math::is_nan(get_as_ratio()) ? 0 : get_as_ratio();
if (orientation == VERTICAL) {
diff --git a/scene/gui/spin_box.cpp b/scene/gui/spin_box.cpp
index 576de98a4f..ccfa8ebf63 100644
--- a/scene/gui/spin_box.cpp
+++ b/scene/gui/spin_box.cpp
@@ -29,8 +29,9 @@
/*************************************************************************/
#include "spin_box.h"
+
+#include "core/input/input_filter.h"
#include "core/math/expression.h"
-#include "core/os/input.h"
Size2 SpinBox::get_minimum_size() const {
@@ -76,7 +77,7 @@ void SpinBox::_line_edit_input(const Ref<InputEvent> &p_event) {
void SpinBox::_range_click_timeout() {
- if (!drag.enabled && Input::get_singleton()->is_mouse_button_pressed(BUTTON_LEFT)) {
+ if (!drag.enabled && InputFilter::get_singleton()->is_mouse_button_pressed(BUTTON_LEFT)) {
bool up = get_local_mouse_position().y < (get_size().height / 2);
set_value(get_value() + (up ? get_step() : -get_step()));
@@ -148,7 +149,7 @@ void SpinBox::_gui_input(const Ref<InputEvent> &p_event) {
if (drag.enabled) {
drag.enabled = false;
- Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE);
+ InputFilter::get_singleton()->set_mouse_mode(InputFilter::MOUSE_MODE_VISIBLE);
warp_mouse(drag.capture_pos);
}
drag.allowed = false;
@@ -165,7 +166,7 @@ void SpinBox::_gui_input(const Ref<InputEvent> &p_event) {
set_value(CLAMP(drag.base_val + get_step() * diff_y, get_min(), get_max()));
} else if (drag.allowed && drag.capture_pos.distance_to(mm->get_position()) > 2) {
- Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_CAPTURED);
+ InputFilter::get_singleton()->set_mouse_mode(InputFilter::MOUSE_MODE_CAPTURED);
drag.enabled = true;
drag.base_val = get_value();
drag.diff_y = 0;
@@ -195,7 +196,7 @@ void SpinBox::_notification(int p_what) {
if (p_what == NOTIFICATION_DRAW) {
- Ref<Texture2D> updown = get_icon("updown");
+ Ref<Texture2D> updown = get_theme_icon("updown");
_adjust_width_for_icon(updown);
@@ -209,7 +210,7 @@ void SpinBox::_notification(int p_what) {
//_value_changed(0);
} else if (p_what == NOTIFICATION_ENTER_TREE) {
- _adjust_width_for_icon(get_icon("updown"));
+ _adjust_width_for_icon(get_theme_icon("updown"));
_value_changed(0);
} else if (p_what == NOTIFICATION_THEME_CHANGED) {
diff --git a/scene/gui/split_container.cpp b/scene/gui/split_container.cpp
index 255278be2b..4eb614a9ac 100644
--- a/scene/gui/split_container.cpp
+++ b/scene/gui/split_container.cpp
@@ -74,8 +74,8 @@ void SplitContainer::_resort() {
bool second_expanded = (vertical ? second->get_v_size_flags() : second->get_h_size_flags()) & SIZE_EXPAND;
// Determine the separation between items
- Ref<Texture2D> g = get_icon("grabber");
- int sep = get_constant("separation");
+ Ref<Texture2D> g = get_theme_icon("grabber");
+ int sep = get_theme_constant("separation");
sep = (dragger_visibility != DRAGGER_HIDDEN_COLLAPSED) ? MAX(sep, vertical ? g->get_height() : g->get_width()) : 0;
// Compute the minimum size
@@ -123,8 +123,8 @@ Size2 SplitContainer::get_minimum_size() const {
/* Calculate MINIMUM SIZE */
Size2i minimum;
- Ref<Texture2D> g = get_icon("grabber");
- int sep = get_constant("separation");
+ Ref<Texture2D> g = get_theme_icon("grabber");
+ int sep = get_theme_constant("separation");
sep = (dragger_visibility != DRAGGER_HIDDEN_COLLAPSED) ? MAX(sep, vertical ? g->get_height() : g->get_width()) : 0;
for (int i = 0; i < 2; i++) {
@@ -167,7 +167,7 @@ void SplitContainer::_notification(int p_what) {
case NOTIFICATION_MOUSE_EXIT: {
mouse_inside = false;
- if (get_constant("autohide"))
+ if (get_theme_constant("autohide"))
update();
} break;
case NOTIFICATION_DRAW: {
@@ -175,14 +175,14 @@ void SplitContainer::_notification(int p_what) {
if (!_getch(0) || !_getch(1))
return;
- if (collapsed || (!dragging && !mouse_inside && get_constant("autohide")))
+ if (collapsed || (!dragging && !mouse_inside && get_theme_constant("autohide")))
return;
if (dragger_visibility != DRAGGER_VISIBLE)
return;
- int sep = dragger_visibility != DRAGGER_HIDDEN_COLLAPSED ? get_constant("separation") : 0;
- Ref<Texture2D> tex = get_icon("grabber");
+ int sep = dragger_visibility != DRAGGER_HIDDEN_COLLAPSED ? get_theme_constant("separation") : 0;
+ Ref<Texture2D> tex = get_theme_icon("grabber");
Size2 size = get_size();
if (vertical)
@@ -210,7 +210,7 @@ void SplitContainer::_gui_input(const Ref<InputEvent> &p_event) {
if (mb->is_pressed()) {
- int sep = get_constant("separation");
+ int sep = get_theme_constant("separation");
if (vertical) {
@@ -242,14 +242,14 @@ void SplitContainer::_gui_input(const Ref<InputEvent> &p_event) {
bool mouse_inside_state = false;
if (vertical)
- mouse_inside_state = mm->get_position().y > middle_sep && mm->get_position().y < middle_sep + get_constant("separation");
+ mouse_inside_state = mm->get_position().y > middle_sep && mm->get_position().y < middle_sep + get_theme_constant("separation");
else
- mouse_inside_state = mm->get_position().x > middle_sep && mm->get_position().x < middle_sep + get_constant("separation");
+ mouse_inside_state = mm->get_position().x > middle_sep && mm->get_position().x < middle_sep + get_theme_constant("separation");
if (mouse_inside != mouse_inside_state) {
mouse_inside = mouse_inside_state;
- if (get_constant("autohide"))
+ if (get_theme_constant("autohide"))
update();
}
@@ -270,7 +270,7 @@ Control::CursorShape SplitContainer::get_cursor_shape(const Point2 &p_pos) const
if (!collapsed && _getch(0) && _getch(1) && dragger_visibility == DRAGGER_VISIBLE) {
- int sep = get_constant("separation");
+ int sep = get_theme_constant("separation");
if (vertical) {
diff --git a/scene/gui/tab_container.cpp b/scene/gui/tab_container.cpp
index 6290d364fc..7cecbf7fa2 100644
--- a/scene/gui/tab_container.cpp
+++ b/scene/gui/tab_container.cpp
@@ -41,14 +41,14 @@ int TabContainer::_get_top_margin() const {
return 0;
// Respect the minimum tab height.
- Ref<StyleBox> tab_bg = get_stylebox("tab_bg");
- Ref<StyleBox> tab_fg = get_stylebox("tab_fg");
- Ref<StyleBox> tab_disabled = get_stylebox("tab_disabled");
+ Ref<StyleBox> tab_bg = get_theme_stylebox("tab_bg");
+ Ref<StyleBox> tab_fg = get_theme_stylebox("tab_fg");
+ Ref<StyleBox> tab_disabled = get_theme_stylebox("tab_disabled");
int tab_height = MAX(MAX(tab_bg->get_minimum_size().height, tab_fg->get_minimum_size().height), tab_disabled->get_minimum_size().height);
// Font height or higher icon wins.
- Ref<Font> font = get_font("font");
+ Ref<Font> font = get_theme_font("font");
int content_height = font->get_height();
Vector<Control *> tabs = _get_tabs();
@@ -81,15 +81,15 @@ void TabContainer::_gui_input(const Ref<InputEvent> &p_event) {
return;
// Handle menu button.
- Ref<Texture2D> menu = get_icon("menu");
+ Ref<Texture2D> menu = get_theme_icon("menu");
if (popup && pos.x > size.width - menu->get_width()) {
emit_signal("pre_popup_pressed");
- Vector2 popup_pos = get_global_position();
- popup_pos.x += size.width * get_global_transform().get_scale().x - popup->get_size().width * popup->get_global_transform().get_scale().x;
- popup_pos.y += menu->get_height() * get_global_transform().get_scale().y;
+ Vector2 popup_pos = get_screen_position();
+ popup_pos.x += size.width - popup->get_size().width;
+ popup_pos.y += menu->get_height();
- popup->set_global_position(popup_pos);
+ popup->set_position(popup_pos);
popup->popup();
return;
}
@@ -107,8 +107,8 @@ void TabContainer::_gui_input(const Ref<InputEvent> &p_event) {
popup_ofs = menu->get_width();
}
- Ref<Texture2D> increment = get_icon("increment");
- Ref<Texture2D> decrement = get_icon("decrement");
+ Ref<Texture2D> increment = get_theme_icon("increment");
+ Ref<Texture2D> decrement = get_theme_icon("decrement");
if (pos.x > size.width - increment->get_width() - popup_ofs) {
if (last_tab_cache < tabs.size() - 1) {
first_tab_cache += 1;
@@ -159,7 +159,7 @@ void TabContainer::_gui_input(const Ref<InputEvent> &p_event) {
return;
}
- Ref<Texture2D> menu = get_icon("menu");
+ Ref<Texture2D> menu = get_theme_icon("menu");
if (popup) {
if (pos.x >= size.width - menu->get_width()) {
@@ -191,8 +191,8 @@ void TabContainer::_gui_input(const Ref<InputEvent> &p_event) {
popup_ofs = menu->get_width();
}
- Ref<Texture2D> increment = get_icon("increment");
- Ref<Texture2D> decrement = get_icon("decrement");
+ Ref<Texture2D> increment = get_theme_icon("increment");
+ Ref<Texture2D> decrement = get_theme_icon("decrement");
if (pos.x >= size.width - increment->get_width() - popup_ofs) {
if (highlight_arrow != 1) {
@@ -224,10 +224,10 @@ void TabContainer::_notification(int p_what) {
case NOTIFICATION_RESIZED: {
Vector<Control *> tabs = _get_tabs();
- int side_margin = get_constant("side_margin");
- Ref<Texture2D> menu = get_icon("menu");
- Ref<Texture2D> increment = get_icon("increment");
- Ref<Texture2D> decrement = get_icon("decrement");
+ int side_margin = get_theme_constant("side_margin");
+ Ref<Texture2D> menu = get_theme_icon("menu");
+ Ref<Texture2D> increment = get_theme_icon("increment");
+ Ref<Texture2D> decrement = get_theme_icon("decrement");
int header_width = get_size().width - side_margin * 2;
// Find the width of the header area.
@@ -262,28 +262,28 @@ void TabContainer::_notification(int p_what) {
Size2 size = get_size();
// Draw only the tab area if the header is hidden.
- Ref<StyleBox> panel = get_stylebox("panel");
+ Ref<StyleBox> panel = get_theme_stylebox("panel");
if (!tabs_visible) {
panel->draw(canvas, Rect2(0, 0, size.width, size.height));
return;
}
Vector<Control *> tabs = _get_tabs();
- Ref<StyleBox> tab_bg = get_stylebox("tab_bg");
- Ref<StyleBox> tab_fg = get_stylebox("tab_fg");
- Ref<StyleBox> tab_disabled = get_stylebox("tab_disabled");
- Ref<Texture2D> increment = get_icon("increment");
- Ref<Texture2D> increment_hl = get_icon("increment_highlight");
- Ref<Texture2D> decrement = get_icon("decrement");
- Ref<Texture2D> decrement_hl = get_icon("decrement_highlight");
- Ref<Texture2D> menu = get_icon("menu");
- Ref<Texture2D> menu_hl = get_icon("menu_highlight");
- Ref<Font> font = get_font("font");
- Color font_color_fg = get_color("font_color_fg");
- Color font_color_bg = get_color("font_color_bg");
- Color font_color_disabled = get_color("font_color_disabled");
- int side_margin = get_constant("side_margin");
- int icon_text_distance = get_constant("hseparation");
+ Ref<StyleBox> tab_bg = get_theme_stylebox("tab_bg");
+ Ref<StyleBox> tab_fg = get_theme_stylebox("tab_fg");
+ Ref<StyleBox> tab_disabled = get_theme_stylebox("tab_disabled");
+ Ref<Texture2D> increment = get_theme_icon("increment");
+ Ref<Texture2D> increment_hl = get_theme_icon("increment_highlight");
+ Ref<Texture2D> decrement = get_theme_icon("decrement");
+ Ref<Texture2D> decrement_hl = get_theme_icon("decrement_highlight");
+ Ref<Texture2D> menu = get_theme_icon("menu");
+ Ref<Texture2D> menu_hl = get_theme_icon("menu_highlight");
+ Ref<Font> font = get_theme_font("font");
+ Color font_color_fg = get_theme_color("font_color_fg");
+ Color font_color_bg = get_theme_color("font_color_bg");
+ Color font_color_disabled = get_theme_color("font_color_disabled");
+ int side_margin = get_theme_constant("side_margin");
+ int icon_text_distance = get_theme_constant("hseparation");
// Find out start and width of the header area.
int header_x = side_margin;
@@ -458,7 +458,7 @@ int TabContainer::_get_tab_width(int p_index) const {
return 0;
// Get the width of the text displayed on the tab.
- Ref<Font> font = get_font("font");
+ Ref<Font> font = get_theme_font("font");
String text = control->has_meta("_tab_name") ? String(tr(String(control->get_meta("_tab_name")))) : String(control->get_name());
int width = font->get_string_size(text).width;
@@ -468,14 +468,14 @@ int TabContainer::_get_tab_width(int p_index) const {
if (icon.is_valid()) {
width += icon->get_width();
if (text != "")
- width += get_constant("hseparation");
+ width += get_theme_constant("hseparation");
}
}
// Respect a minimum size.
- Ref<StyleBox> tab_bg = get_stylebox("tab_bg");
- Ref<StyleBox> tab_fg = get_stylebox("tab_fg");
- Ref<StyleBox> tab_disabled = get_stylebox("tab_disabled");
+ Ref<StyleBox> tab_bg = get_theme_stylebox("tab_bg");
+ Ref<StyleBox> tab_fg = get_theme_stylebox("tab_fg");
+ Ref<StyleBox> tab_disabled = get_theme_stylebox("tab_disabled");
if (get_tab_disabled(p_index)) {
width += tab_disabled->get_minimum_size().width;
} else if (p_index == current) {
@@ -530,7 +530,7 @@ void TabContainer::add_child_notify(Node *p_child) {
c->set_anchors_and_margins_preset(Control::PRESET_WIDE);
if (tabs_visible)
c->set_margin(MARGIN_TOP, _get_top_margin());
- Ref<StyleBox> sb = get_stylebox("panel");
+ Ref<StyleBox> sb = get_theme_stylebox("panel");
c->set_margin(Margin(MARGIN_TOP), c->get_margin(Margin(MARGIN_TOP)) + sb->get_margin(Margin(MARGIN_TOP)));
c->set_margin(Margin(MARGIN_LEFT), c->get_margin(Margin(MARGIN_LEFT)) + sb->get_margin(Margin(MARGIN_LEFT)));
c->set_margin(Margin(MARGIN_RIGHT), c->get_margin(Margin(MARGIN_RIGHT)) - sb->get_margin(Margin(MARGIN_RIGHT)));
@@ -554,7 +554,7 @@ void TabContainer::set_current_tab(int p_current) {
int pending_previous = current;
current = p_current;
- Ref<StyleBox> sb = get_stylebox("panel");
+ Ref<StyleBox> sb = get_theme_stylebox("panel");
Vector<Control *> tabs = _get_tabs();
for (int i = 0; i < tabs.size(); i++) {
@@ -745,12 +745,12 @@ int TabContainer::get_tab_idx_at_point(const Point2 &p_point) const {
int right_ofs = 0;
if (popup) {
- Ref<Texture2D> menu = get_icon("menu");
+ Ref<Texture2D> menu = get_theme_icon("menu");
right_ofs += menu->get_width();
}
if (buttons_visible_cache) {
- Ref<Texture2D> increment = get_icon("increment");
- Ref<Texture2D> decrement = get_icon("decrement");
+ Ref<Texture2D> increment = get_theme_icon("increment");
+ Ref<Texture2D> decrement = get_theme_icon("decrement");
right_ofs += increment->get_width() + decrement->get_width();
}
if (p_point.x > size.width - right_ofs) {
@@ -933,17 +933,17 @@ Size2 TabContainer::get_minimum_size() const {
ms.y = MAX(ms.y, cms.y);
}
- Ref<StyleBox> tab_bg = get_stylebox("tab_bg");
- Ref<StyleBox> tab_fg = get_stylebox("tab_fg");
- Ref<StyleBox> tab_disabled = get_stylebox("tab_disabled");
- Ref<Font> font = get_font("font");
+ Ref<StyleBox> tab_bg = get_theme_stylebox("tab_bg");
+ Ref<StyleBox> tab_fg = get_theme_stylebox("tab_fg");
+ Ref<StyleBox> tab_disabled = get_theme_stylebox("tab_disabled");
+ Ref<Font> font = get_theme_font("font");
if (tabs_visible) {
ms.y += MAX(MAX(tab_bg->get_minimum_size().y, tab_fg->get_minimum_size().y), tab_disabled->get_minimum_size().y);
ms.y += font->get_height();
}
- Ref<StyleBox> sb = get_stylebox("panel");
+ Ref<StyleBox> sb = get_theme_stylebox("panel");
ms += sb->get_minimum_size();
return ms;
diff --git a/scene/gui/tabs.cpp b/scene/gui/tabs.cpp
index 901408919a..ea6d44e3a7 100644
--- a/scene/gui/tabs.cpp
+++ b/scene/gui/tabs.cpp
@@ -37,10 +37,10 @@
Size2 Tabs::get_minimum_size() const {
- Ref<StyleBox> tab_bg = get_stylebox("tab_bg");
- Ref<StyleBox> tab_fg = get_stylebox("tab_fg");
- Ref<StyleBox> tab_disabled = get_stylebox("tab_disabled");
- Ref<Font> font = get_font("font");
+ Ref<StyleBox> tab_bg = get_theme_stylebox("tab_bg");
+ Ref<StyleBox> tab_fg = get_theme_stylebox("tab_fg");
+ Ref<StyleBox> tab_disabled = get_theme_stylebox("tab_disabled");
+ Ref<Font> font = get_theme_font("font");
Size2 ms(0, MAX(MAX(tab_bg->get_minimum_size().height, tab_fg->get_minimum_size().height), tab_disabled->get_minimum_size().height) + font->get_height());
@@ -50,7 +50,7 @@ Size2 Tabs::get_minimum_size() const {
if (tex.is_valid()) {
ms.height = MAX(ms.height, tex->get_size().height);
if (tabs[i].text != "")
- ms.width += get_constant("hseparation");
+ ms.width += get_theme_constant("hseparation");
}
ms.width += Math::ceil(font->get_string_size(tabs[i].xl_text).width);
@@ -65,15 +65,15 @@ Size2 Tabs::get_minimum_size() const {
if (tabs[i].right_button.is_valid()) {
Ref<Texture2D> rb = tabs[i].right_button;
Size2 bms = rb->get_size();
- bms.width += get_constant("hseparation");
+ bms.width += get_theme_constant("hseparation");
ms.width += bms.width;
ms.height = MAX(bms.height + tab_bg->get_minimum_size().height, ms.height);
}
if (cb_displaypolicy == CLOSE_BUTTON_SHOW_ALWAYS || (cb_displaypolicy == CLOSE_BUTTON_SHOW_ACTIVE_ONLY && i == current)) {
- Ref<Texture2D> cb = get_icon("close");
+ Ref<Texture2D> cb = get_theme_icon("close");
Size2 bms = cb->get_size();
- bms.width += get_constant("hseparation");
+ bms.width += get_theme_constant("hseparation");
ms.width += bms.width;
ms.height = MAX(bms.height + tab_bg->get_minimum_size().height, ms.height);
}
@@ -94,8 +94,8 @@ void Tabs::_gui_input(const Ref<InputEvent> &p_event) {
highlight_arrow = -1;
if (buttons_visible) {
- Ref<Texture2D> incr = get_icon("increment");
- Ref<Texture2D> decr = get_icon("decrement");
+ Ref<Texture2D> incr = get_theme_icon("increment");
+ Ref<Texture2D> decr = get_theme_icon("decrement");
int limit = get_size().width - incr->get_width() - decr->get_width();
@@ -163,8 +163,8 @@ void Tabs::_gui_input(const Ref<InputEvent> &p_event) {
if (buttons_visible) {
- Ref<Texture2D> incr = get_icon("increment");
- Ref<Texture2D> decr = get_icon("decrement");
+ Ref<Texture2D> incr = get_theme_icon("increment");
+ Ref<Texture2D> decr = get_theme_icon("decrement");
int limit = get_size().width - incr->get_width() - decr->get_width();
@@ -238,14 +238,14 @@ void Tabs::_notification(int p_what) {
_update_cache();
RID ci = get_canvas_item();
- Ref<StyleBox> tab_bg = get_stylebox("tab_bg");
- Ref<StyleBox> tab_fg = get_stylebox("tab_fg");
- Ref<StyleBox> tab_disabled = get_stylebox("tab_disabled");
- Ref<Font> font = get_font("font");
- Color color_fg = get_color("font_color_fg");
- Color color_bg = get_color("font_color_bg");
- Color color_disabled = get_color("font_color_disabled");
- Ref<Texture2D> close = get_icon("close");
+ Ref<StyleBox> tab_bg = get_theme_stylebox("tab_bg");
+ Ref<StyleBox> tab_fg = get_theme_stylebox("tab_fg");
+ Ref<StyleBox> tab_disabled = get_theme_stylebox("tab_disabled");
+ Ref<Font> font = get_theme_font("font");
+ Color color_fg = get_theme_color("font_color_fg");
+ Color color_bg = get_theme_color("font_color_bg");
+ Color color_disabled = get_theme_color("font_color_disabled");
+ Ref<Texture2D> close = get_theme_icon("close");
int h = get_size().height;
int w = 0;
@@ -267,10 +267,10 @@ void Tabs::_notification(int p_what) {
w = 0;
}
- Ref<Texture2D> incr = get_icon("increment");
- Ref<Texture2D> decr = get_icon("decrement");
- Ref<Texture2D> incr_hl = get_icon("increment_highlight");
- Ref<Texture2D> decr_hl = get_icon("decrement_highlight");
+ Ref<Texture2D> incr = get_theme_icon("increment");
+ Ref<Texture2D> decr = get_theme_icon("decrement");
+ Ref<Texture2D> incr_hl = get_theme_icon("increment_highlight");
+ Ref<Texture2D> decr_hl = get_theme_icon("decrement_highlight");
int limit = get_size().width - incr->get_size().width - decr->get_size().width;
@@ -318,7 +318,7 @@ void Tabs::_notification(int p_what) {
icon->draw(ci, Point2i(w, sb->get_margin(MARGIN_TOP) + ((sb_rect.size.y - sb_ms.y) - icon->get_height()) / 2));
if (tabs[i].text != "")
- w += icon->get_width() + get_constant("hseparation");
+ w += icon->get_width() + get_theme_constant("hseparation");
}
font->draw(ci, Point2i(w, sb->get_margin(MARGIN_TOP) + ((sb_rect.size.y - sb_ms.y) - font->get_height()) / 2 + font->get_ascent()), tabs[i].xl_text, col, tabs[i].size_text);
@@ -327,10 +327,10 @@ void Tabs::_notification(int p_what) {
if (tabs[i].right_button.is_valid()) {
- Ref<StyleBox> style = get_stylebox("button");
+ Ref<StyleBox> style = get_theme_stylebox("button");
Ref<Texture2D> rb = tabs[i].right_button;
- w += get_constant("hseparation");
+ w += get_theme_constant("hseparation");
Rect2 rb_rect;
rb_rect.size = style->get_minimum_size() + rb->get_size();
@@ -339,7 +339,7 @@ void Tabs::_notification(int p_what) {
if (rb_hover == i) {
if (rb_pressing)
- get_stylebox("button_pressed")->draw(ci, rb_rect);
+ get_theme_stylebox("button_pressed")->draw(ci, rb_rect);
else
style->draw(ci, rb_rect);
}
@@ -351,10 +351,10 @@ void Tabs::_notification(int p_what) {
if (cb_displaypolicy == CLOSE_BUTTON_SHOW_ALWAYS || (cb_displaypolicy == CLOSE_BUTTON_SHOW_ACTIVE_ONLY && i == current)) {
- Ref<StyleBox> style = get_stylebox("button");
+ Ref<StyleBox> style = get_theme_stylebox("button");
Ref<Texture2D> cb = close;
- w += get_constant("hseparation");
+ w += get_theme_constant("hseparation");
Rect2 cb_rect;
cb_rect.size = style->get_minimum_size() + cb->get_size();
@@ -363,7 +363,7 @@ void Tabs::_notification(int p_what) {
if (!tabs[i].disabled && cb_hover == i) {
if (cb_pressing)
- get_stylebox("button_pressed")->draw(ci, cb_rect);
+ get_theme_stylebox("button_pressed")->draw(ci, cb_rect);
else
style->draw(ci, cb_rect);
}
@@ -532,12 +532,12 @@ void Tabs::_update_hover() {
}
void Tabs::_update_cache() {
- Ref<StyleBox> tab_disabled = get_stylebox("tab_disabled");
- Ref<StyleBox> tab_bg = get_stylebox("tab_bg");
- Ref<StyleBox> tab_fg = get_stylebox("tab_fg");
- Ref<Font> font = get_font("font");
- Ref<Texture2D> incr = get_icon("increment");
- Ref<Texture2D> decr = get_icon("decrement");
+ Ref<StyleBox> tab_disabled = get_theme_stylebox("tab_disabled");
+ Ref<StyleBox> tab_bg = get_theme_stylebox("tab_bg");
+ Ref<StyleBox> tab_fg = get_theme_stylebox("tab_fg");
+ Ref<Font> font = get_theme_font("font");
+ Ref<Texture2D> incr = get_theme_icon("increment");
+ Ref<Texture2D> decr = get_theme_icon("decrement");
int limit = get_size().width - incr->get_width() - decr->get_width();
int w = 0;
@@ -577,12 +577,12 @@ void Tabs::_update_cache() {
slen = m_width - (sb->get_margin(MARGIN_LEFT) + sb->get_margin(MARGIN_RIGHT));
if (tabs[i].icon.is_valid()) {
slen -= tabs[i].icon->get_width();
- slen -= get_constant("hseparation");
+ slen -= get_theme_constant("hseparation");
}
if (cb_displaypolicy == CLOSE_BUTTON_SHOW_ALWAYS || (cb_displaypolicy == CLOSE_BUTTON_SHOW_ACTIVE_ONLY && i == current)) {
- Ref<Texture2D> cb = get_icon("close");
+ Ref<Texture2D> cb = get_theme_icon("close");
slen -= cb->get_width();
- slen -= get_constant("hseparation");
+ slen -= get_theme_constant("hseparation");
}
slen = MAX(slen, 1);
lsize = m_width;
@@ -799,10 +799,10 @@ int Tabs::get_tab_width(int p_idx) const {
ERR_FAIL_INDEX_V(p_idx, tabs.size(), 0);
- Ref<StyleBox> tab_bg = get_stylebox("tab_bg");
- Ref<StyleBox> tab_fg = get_stylebox("tab_fg");
- Ref<StyleBox> tab_disabled = get_stylebox("tab_disabled");
- Ref<Font> font = get_font("font");
+ Ref<StyleBox> tab_bg = get_theme_stylebox("tab_bg");
+ Ref<StyleBox> tab_fg = get_theme_stylebox("tab_fg");
+ Ref<StyleBox> tab_disabled = get_theme_stylebox("tab_disabled");
+ Ref<Font> font = get_theme_font("font");
int x = 0;
@@ -810,7 +810,7 @@ int Tabs::get_tab_width(int p_idx) const {
if (tex.is_valid()) {
x += tex->get_width();
if (tabs[p_idx].text != "")
- x += get_constant("hseparation");
+ x += get_theme_constant("hseparation");
}
x += Math::ceil(font->get_string_size(tabs[p_idx].xl_text).width);
@@ -825,13 +825,13 @@ int Tabs::get_tab_width(int p_idx) const {
if (tabs[p_idx].right_button.is_valid()) {
Ref<Texture2D> rb = tabs[p_idx].right_button;
x += rb->get_width();
- x += get_constant("hseparation");
+ x += get_theme_constant("hseparation");
}
if (cb_displaypolicy == CLOSE_BUTTON_SHOW_ALWAYS || (cb_displaypolicy == CLOSE_BUTTON_SHOW_ACTIVE_ONLY && p_idx == current)) {
- Ref<Texture2D> cb = get_icon("close");
+ Ref<Texture2D> cb = get_theme_icon("close");
x += cb->get_width();
- x += get_constant("hseparation");
+ x += get_theme_constant("hseparation");
}
return x;
@@ -842,8 +842,8 @@ void Tabs::_ensure_no_over_offset() {
if (!is_inside_tree())
return;
- Ref<Texture2D> incr = get_icon("increment");
- Ref<Texture2D> decr = get_icon("decrement");
+ Ref<Texture2D> incr = get_theme_icon("increment");
+ Ref<Texture2D> decr = get_theme_icon("decrement");
int limit = get_size().width - incr->get_width() - decr->get_width();
@@ -885,8 +885,8 @@ void Tabs::ensure_tab_visible(int p_idx) {
}
int prev_offset = offset;
- Ref<Texture2D> incr = get_icon("increment");
- Ref<Texture2D> decr = get_icon("decrement");
+ Ref<Texture2D> incr = get_theme_icon("increment");
+ Ref<Texture2D> decr = get_theme_icon("decrement");
int limit = get_size().width - incr->get_width() - decr->get_width();
for (int i = offset; i <= p_idx; i++) {
if (tabs[i].ofs_cache + tabs[i].size_cache > limit) {
diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp
index cdc2430eb5..fb477ee3b4 100644
--- a/scene/gui/text_edit.cpp
+++ b/scene/gui/text_edit.cpp
@@ -30,13 +30,13 @@
#include "text_edit.h"
+#include "core/input/input_filter.h"
#include "core/message_queue.h"
-#include "core/os/input.h"
#include "core/os/keyboard.h"
#include "core/os/os.h"
#include "core/project_settings.h"
#include "core/script_language.h"
-#include "scene/main/viewport.h"
+#include "scene/main/window.h"
#ifdef TOOLS_ENABLED
#include "editor/editor_scale.h"
@@ -446,7 +446,7 @@ void TextEdit::_click_selection_held() {
// Warning: is_mouse_button_pressed(BUTTON_LEFT) returns false for double+ clicks, so this doesn't work for MODE_WORD
// and MODE_LINE. However, moving the mouse triggers _gui_input, which calls these functions too, so that's not a huge problem.
// I'm unsure if there's an actual fix that doesn't have a ton of side effects.
- if (Input::get_singleton()->is_mouse_button_pressed(BUTTON_LEFT) && selection.selecting_mode != Selection::MODE_NONE) {
+ if (InputFilter::get_singleton()->is_mouse_button_pressed(BUTTON_LEFT) && selection.selecting_mode != Selection::MODE_NONE) {
switch (selection.selecting_mode) {
case Selection::MODE_POINTER: {
_update_selection_mode_pointer();
@@ -639,12 +639,12 @@ void TextEdit::_notification(int p_what) {
_update_wrap_at();
syntax_highlighting_cache.clear();
} break;
- case MainLoop::NOTIFICATION_WM_FOCUS_IN: {
+ case NOTIFICATION_WM_FOCUS_IN: {
window_has_focus = true;
draw_caret = true;
update();
} break;
- case MainLoop::NOTIFICATION_WM_FOCUS_OUT: {
+ case NOTIFICATION_WM_FOCUS_OUT: {
window_has_focus = false;
draw_caret = false;
update();
@@ -1584,11 +1584,11 @@ void TextEdit::_notification(int p_what) {
bool completion_below = false;
if (completion_active && completion_options.size() > 0) {
// Code completion box.
- Ref<StyleBox> csb = get_stylebox("completion");
- int maxlines = get_constant("completion_lines");
- int cmax_width = get_constant("completion_max_width") * cache.font->get_char_size('x').x;
- int scrollw = get_constant("completion_scroll_width");
- Color scrollc = get_color("completion_scroll_color");
+ Ref<StyleBox> csb = get_theme_stylebox("completion");
+ int maxlines = get_theme_constant("completion_lines");
+ int cmax_width = get_theme_constant("completion_max_width") * cache.font->get_char_size('x').x;
+ int scrollw = get_theme_constant("completion_scroll_width");
+ Color scrollc = get_theme_color("completion_scroll_color");
const int completion_options_size = completion_options.size();
int lines = MIN(completion_options_size, maxlines);
@@ -1607,7 +1607,7 @@ void TextEdit::_notification(int p_what) {
}
// Add space for completion icons.
- const int icon_hsep = get_constant("hseparation", "ItemList");
+ const int icon_hsep = get_theme_constant("hseparation", "ItemList");
Size2 icon_area_size(get_row_height(), get_row_height());
w += icon_area_size.width + icon_hsep;
@@ -1694,9 +1694,9 @@ void TextEdit::_notification(int p_what) {
if (show_hint) {
- Ref<StyleBox> sb = get_stylebox("panel", "TooltipPanel");
+ Ref<StyleBox> sb = get_theme_stylebox("panel", "TooltipPanel");
Ref<Font> font = cache.font;
- Color font_color = get_color("font_color", "TooltipLabel");
+ Color font_color = get_theme_color("font_color", "TooltipLabel");
int max_w = 0;
int sc = completion_hint.get_slice_count("\n");
@@ -1754,8 +1754,10 @@ void TextEdit::_notification(int p_what) {
}
if (has_focus()) {
- OS::get_singleton()->set_ime_active(true);
- OS::get_singleton()->set_ime_position(get_global_position() + cursor_pos + Point2(0, get_row_height()));
+ if (get_viewport()->get_window_id() != DisplayServer::INVALID_WINDOW_ID) {
+ DisplayServer::get_singleton()->window_set_ime_active(true, get_viewport()->get_window_id());
+ DisplayServer::get_singleton()->window_set_ime_position(get_global_position() + cursor_pos + Point2(0, get_row_height()), get_viewport()->get_window_id());
+ }
}
} break;
case NOTIFICATION_FOCUS_ENTER: {
@@ -1766,12 +1768,14 @@ void TextEdit::_notification(int p_what) {
draw_caret = true;
}
- OS::get_singleton()->set_ime_active(true);
- Point2 cursor_pos = Point2(cursor_get_column(), cursor_get_line()) * get_row_height();
- OS::get_singleton()->set_ime_position(get_global_position() + cursor_pos);
+ if (get_viewport()->get_window_id() != DisplayServer::INVALID_WINDOW_ID) {
+ DisplayServer::get_singleton()->window_set_ime_active(true, get_viewport()->get_window_id());
+ Point2 cursor_pos = Point2(cursor_get_column(), cursor_get_line()) * get_row_height();
+ DisplayServer::get_singleton()->window_set_ime_position(get_global_position() + cursor_pos, get_viewport()->get_window_id());
+ }
- if (OS::get_singleton()->has_virtual_keyboard())
- OS::get_singleton()->show_virtual_keyboard(get_text(), get_global_rect());
+ if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_VIRTUAL_KEYBOARD))
+ DisplayServer::get_singleton()->virtual_keyboard_show(get_text(), get_global_rect());
} break;
case NOTIFICATION_FOCUS_EXIT: {
@@ -1779,19 +1783,21 @@ void TextEdit::_notification(int p_what) {
caret_blink_timer->stop();
}
- OS::get_singleton()->set_ime_position(Point2());
- OS::get_singleton()->set_ime_active(false);
+ if (get_viewport()->get_window_id() != DisplayServer::INVALID_WINDOW_ID) {
+ DisplayServer::get_singleton()->window_set_ime_position(Point2(), get_viewport()->get_window_id());
+ DisplayServer::get_singleton()->window_set_ime_active(false, get_viewport()->get_window_id());
+ }
ime_text = "";
ime_selection = Point2();
- if (OS::get_singleton()->has_virtual_keyboard())
- OS::get_singleton()->hide_virtual_keyboard();
+ if (DisplayServer::get_singleton()->has_feature(DisplayServer::FEATURE_VIRTUAL_KEYBOARD))
+ DisplayServer::get_singleton()->virtual_keyboard_hide();
} break;
case MainLoop::NOTIFICATION_OS_IME_UPDATE: {
if (has_focus()) {
- ime_text = OS::get_singleton()->get_ime_text();
- ime_selection = OS::get_singleton()->get_ime_selection();
+ ime_text = DisplayServer::get_singleton()->ime_get_text();
+ ime_selection = DisplayServer::get_singleton()->ime_get_selection();
update();
}
} break;
@@ -2477,9 +2483,9 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
}
}
- menu->set_position(get_global_transform().xform(get_local_mouse_position()));
+ menu->set_position(get_screen_transform().xform(get_local_mouse_position()));
menu->set_size(Vector2(1, 1));
- menu->set_scale(get_global_transform().get_scale());
+ // menu->set_scale(get_global_transform().get_scale());
menu->popup();
grab_focus();
}
@@ -2634,7 +2640,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
if (k->get_keycode() == KEY_PAGEUP) {
- completion_index -= get_constant("completion_lines");
+ completion_index -= get_theme_constant("completion_lines");
if (completion_index < 0)
completion_index = 0;
completion_current = completion_options[completion_index];
@@ -2645,7 +2651,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
if (k->get_keycode() == KEY_PAGEDOWN) {
- completion_index += get_constant("completion_lines");
+ completion_index += get_theme_constant("completion_lines");
if (completion_index >= completion_options.size())
completion_index = completion_options.size() - 1;
completion_current = completion_options[completion_index];
@@ -3735,7 +3741,7 @@ void TextEdit::_gui_input(const Ref<InputEvent> &p_gui_input) {
if (context_menu_enabled) {
menu->set_position(get_global_transform().xform(_get_cursor_pixel_pos()));
menu->set_size(Vector2(1, 1));
- menu->set_scale(get_global_transform().get_scale());
+ // menu->set_scale(get_global_transform().get_scale());
menu->popup();
menu->grab_focus();
}
@@ -5026,51 +5032,51 @@ void TextEdit::_toggle_draw_caret() {
void TextEdit::_update_caches() {
- cache.style_normal = get_stylebox("normal");
- cache.style_focus = get_stylebox("focus");
- cache.style_readonly = get_stylebox("read_only");
- cache.completion_background_color = get_color("completion_background_color");
- cache.completion_selected_color = get_color("completion_selected_color");
- cache.completion_existing_color = get_color("completion_existing_color");
- cache.completion_font_color = get_color("completion_font_color");
- cache.font = get_font("font");
- cache.caret_color = get_color("caret_color");
- cache.caret_background_color = get_color("caret_background_color");
- cache.line_number_color = get_color("line_number_color");
- cache.safe_line_number_color = get_color("safe_line_number_color");
- cache.font_color = get_color("font_color");
- cache.font_color_selected = get_color("font_color_selected");
- cache.font_color_readonly = get_color("font_color_readonly");
- cache.keyword_color = get_color("keyword_color");
- cache.function_color = get_color("function_color");
- cache.member_variable_color = get_color("member_variable_color");
- cache.number_color = get_color("number_color");
- cache.selection_color = get_color("selection_color");
- cache.mark_color = get_color("mark_color");
- cache.current_line_color = get_color("current_line_color");
- cache.line_length_guideline_color = get_color("line_length_guideline_color");
- cache.bookmark_color = get_color("bookmark_color");
- cache.breakpoint_color = get_color("breakpoint_color");
- cache.executing_line_color = get_color("executing_line_color");
- cache.code_folding_color = get_color("code_folding_color");
- cache.brace_mismatch_color = get_color("brace_mismatch_color");
- cache.word_highlighted_color = get_color("word_highlighted_color");
- cache.search_result_color = get_color("search_result_color");
- cache.search_result_border_color = get_color("search_result_border_color");
- cache.symbol_color = get_color("symbol_color");
- cache.background_color = get_color("background_color");
+ cache.style_normal = get_theme_stylebox("normal");
+ cache.style_focus = get_theme_stylebox("focus");
+ cache.style_readonly = get_theme_stylebox("read_only");
+ cache.completion_background_color = get_theme_color("completion_background_color");
+ cache.completion_selected_color = get_theme_color("completion_selected_color");
+ cache.completion_existing_color = get_theme_color("completion_existing_color");
+ cache.completion_font_color = get_theme_color("completion_font_color");
+ cache.font = get_theme_font("font");
+ cache.caret_color = get_theme_color("caret_color");
+ cache.caret_background_color = get_theme_color("caret_background_color");
+ cache.line_number_color = get_theme_color("line_number_color");
+ cache.safe_line_number_color = get_theme_color("safe_line_number_color");
+ cache.font_color = get_theme_color("font_color");
+ cache.font_color_selected = get_theme_color("font_color_selected");
+ cache.font_color_readonly = get_theme_color("font_color_readonly");
+ cache.keyword_color = get_theme_color("keyword_color");
+ cache.function_color = get_theme_color("function_color");
+ cache.member_variable_color = get_theme_color("member_variable_color");
+ cache.number_color = get_theme_color("number_color");
+ cache.selection_color = get_theme_color("selection_color");
+ cache.mark_color = get_theme_color("mark_color");
+ cache.current_line_color = get_theme_color("current_line_color");
+ cache.line_length_guideline_color = get_theme_color("line_length_guideline_color");
+ cache.bookmark_color = get_theme_color("bookmark_color");
+ cache.breakpoint_color = get_theme_color("breakpoint_color");
+ cache.executing_line_color = get_theme_color("executing_line_color");
+ cache.code_folding_color = get_theme_color("code_folding_color");
+ cache.brace_mismatch_color = get_theme_color("brace_mismatch_color");
+ cache.word_highlighted_color = get_theme_color("word_highlighted_color");
+ cache.search_result_color = get_theme_color("search_result_color");
+ cache.search_result_border_color = get_theme_color("search_result_border_color");
+ cache.symbol_color = get_theme_color("symbol_color");
+ cache.background_color = get_theme_color("background_color");
#ifdef TOOLS_ENABLED
- cache.line_spacing = get_constant("line_spacing") * EDSCALE;
+ cache.line_spacing = get_theme_constant("line_spacing") * EDSCALE;
#else
- cache.line_spacing = get_constant("line_spacing");
+ cache.line_spacing = get_theme_constant("line_spacing");
#endif
cache.row_height = cache.font->get_height() + cache.line_spacing;
- cache.tab_icon = get_icon("tab");
- cache.space_icon = get_icon("space");
- cache.folded_icon = get_icon("folded");
- cache.can_fold_icon = get_icon("fold");
- cache.folded_eol_icon = get_icon("GuiEllipsis", "EditorIcons");
- cache.executing_icon = get_icon("MainPlay", "EditorIcons");
+ cache.tab_icon = get_theme_icon("tab");
+ cache.space_icon = get_theme_icon("space");
+ cache.folded_icon = get_theme_icon("folded");
+ cache.can_fold_icon = get_theme_icon("fold");
+ cache.folded_eol_icon = get_theme_icon("GuiEllipsis", "EditorIcons");
+ cache.executing_icon = get_theme_icon("MainPlay", "EditorIcons");
text.set_font(cache.font);
if (syntax_highlighter) {
@@ -5226,7 +5232,7 @@ void TextEdit::cut() {
if (!selection.active) {
String clipboard = text[cursor.line];
- OS::get_singleton()->set_clipboard(clipboard);
+ DisplayServer::get_singleton()->clipboard_set(clipboard);
cursor_set_line(cursor.line);
cursor_set_column(0);
@@ -5244,7 +5250,7 @@ void TextEdit::cut() {
} else {
String clipboard = _base_get_text(selection.from_line, selection.from_column, selection.to_line, selection.to_column);
- OS::get_singleton()->set_clipboard(clipboard);
+ DisplayServer::get_singleton()->clipboard_set(clipboard);
_remove_text(selection.from_line, selection.from_column, selection.to_line, selection.to_column);
cursor_set_line(selection.from_line); // Set afterwards else it causes the view to be offset.
@@ -5264,19 +5270,19 @@ void TextEdit::copy() {
if (text[cursor.line].length() != 0) {
String clipboard = _base_get_text(cursor.line, 0, cursor.line, text[cursor.line].length());
- OS::get_singleton()->set_clipboard(clipboard);
+ DisplayServer::get_singleton()->clipboard_set(clipboard);
cut_copy_line = clipboard;
}
} else {
String clipboard = _base_get_text(selection.from_line, selection.from_column, selection.to_line, selection.to_column);
- OS::get_singleton()->set_clipboard(clipboard);
+ DisplayServer::get_singleton()->clipboard_set(clipboard);
cut_copy_line = "";
}
}
void TextEdit::paste() {
- String clipboard = OS::get_singleton()->get_clipboard();
+ String clipboard = DisplayServer::get_singleton()->clipboard_get();
begin_complex_operation();
if (selection.active) {
diff --git a/scene/gui/tree.cpp b/scene/gui/tree.cpp
index 12b3d56938..653ac74164 100644
--- a/scene/gui/tree.cpp
+++ b/scene/gui/tree.cpp
@@ -30,13 +30,15 @@
#include "tree.h"
+#include "core/input/input_filter.h"
#include "core/math/math_funcs.h"
-#include "core/os/input.h"
#include "core/os/keyboard.h"
#include "core/os/os.h"
#include "core/print_string.h"
#include "core/project_settings.h"
-#include "scene/main/viewport.h"
+#include "scene/main/window.h"
+
+#include "box_container.h"
#ifdef TOOLS_ENABLED
#include "editor/editor_scale.h"
@@ -952,45 +954,45 @@ TreeItem::~TreeItem() {
void Tree::update_cache() {
- cache.font = get_font("font");
- cache.tb_font = get_font("title_button_font");
- cache.bg = get_stylebox("bg");
- cache.selected = get_stylebox("selected");
- cache.selected_focus = get_stylebox("selected_focus");
- cache.cursor = get_stylebox("cursor");
- cache.cursor_unfocus = get_stylebox("cursor_unfocused");
- cache.button_pressed = get_stylebox("button_pressed");
-
- cache.checked = get_icon("checked");
- cache.unchecked = get_icon("unchecked");
- cache.arrow_collapsed = get_icon("arrow_collapsed");
- cache.arrow = get_icon("arrow");
- cache.select_arrow = get_icon("select_arrow");
- cache.updown = get_icon("updown");
-
- cache.custom_button = get_stylebox("custom_button");
- cache.custom_button_hover = get_stylebox("custom_button_hover");
- cache.custom_button_pressed = get_stylebox("custom_button_pressed");
- cache.custom_button_font_highlight = get_color("custom_button_font_highlight");
-
- cache.font_color = get_color("font_color");
- cache.font_color_selected = get_color("font_color_selected");
- cache.guide_color = get_color("guide_color");
- cache.drop_position_color = get_color("drop_position_color");
- cache.hseparation = get_constant("hseparation");
- cache.vseparation = get_constant("vseparation");
- cache.item_margin = get_constant("item_margin");
- cache.button_margin = get_constant("button_margin");
- cache.draw_guides = get_constant("draw_guides");
- cache.draw_relationship_lines = get_constant("draw_relationship_lines");
- cache.relationship_line_color = get_color("relationship_line_color");
- cache.scroll_border = get_constant("scroll_border");
- cache.scroll_speed = get_constant("scroll_speed");
-
- cache.title_button = get_stylebox("title_button_normal");
- cache.title_button_pressed = get_stylebox("title_button_pressed");
- cache.title_button_hover = get_stylebox("title_button_hover");
- cache.title_button_color = get_color("title_button_color");
+ cache.font = get_theme_font("font");
+ cache.tb_font = get_theme_font("title_button_font");
+ cache.bg = get_theme_stylebox("bg");
+ cache.selected = get_theme_stylebox("selected");
+ cache.selected_focus = get_theme_stylebox("selected_focus");
+ cache.cursor = get_theme_stylebox("cursor");
+ cache.cursor_unfocus = get_theme_stylebox("cursor_unfocused");
+ cache.button_pressed = get_theme_stylebox("button_pressed");
+
+ cache.checked = get_theme_icon("checked");
+ cache.unchecked = get_theme_icon("unchecked");
+ cache.arrow_collapsed = get_theme_icon("arrow_collapsed");
+ cache.arrow = get_theme_icon("arrow");
+ cache.select_arrow = get_theme_icon("select_arrow");
+ cache.updown = get_theme_icon("updown");
+
+ cache.custom_button = get_theme_stylebox("custom_button");
+ cache.custom_button_hover = get_theme_stylebox("custom_button_hover");
+ cache.custom_button_pressed = get_theme_stylebox("custom_button_pressed");
+ cache.custom_button_font_highlight = get_theme_color("custom_button_font_highlight");
+
+ cache.font_color = get_theme_color("font_color");
+ cache.font_color_selected = get_theme_color("font_color_selected");
+ cache.guide_color = get_theme_color("guide_color");
+ cache.drop_position_color = get_theme_color("drop_position_color");
+ cache.hseparation = get_theme_constant("hseparation");
+ cache.vseparation = get_theme_constant("vseparation");
+ cache.item_margin = get_theme_constant("item_margin");
+ cache.button_margin = get_theme_constant("button_margin");
+ cache.draw_guides = get_theme_constant("draw_guides");
+ cache.draw_relationship_lines = get_theme_constant("draw_relationship_lines");
+ cache.relationship_line_color = get_theme_color("relationship_line_color");
+ cache.scroll_border = get_theme_constant("scroll_border");
+ cache.scroll_speed = get_theme_constant("scroll_speed");
+
+ cache.title_button = get_theme_stylebox("title_button_normal");
+ cache.title_button_pressed = get_theme_stylebox("title_button_pressed");
+ cache.title_button_hover = get_theme_stylebox("title_button_hover");
+ cache.title_button_color = get_theme_color("title_button_color");
v_scroll->set_custom_step(cache.font->get_height());
}
@@ -1291,7 +1293,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
}
}
- Color col = p_item->cells[i].custom_color ? p_item->cells[i].color : get_color(p_item->cells[i].selected ? "font_color_selected" : "font_color");
+ Color col = p_item->cells[i].custom_color ? p_item->cells[i].color : get_theme_color(p_item->cells[i].selected ? "font_color_selected" : "font_color");
Color icon_col = p_item->cells[i].icon_color;
Point2i text_pos = item_rect.position;
@@ -1423,7 +1425,7 @@ int Tree::draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2
if (p_item->cells[i].custom_button) {
if (cache.hover_item == p_item && cache.hover_cell == i) {
- if (Input::get_singleton()->is_mouse_button_pressed(BUTTON_LEFT)) {
+ if (InputFilter::get_singleton()->is_mouse_button_pressed(BUTTON_LEFT)) {
draw_style_box(cache.custom_button_pressed, ir);
} else {
draw_style_box(cache.custom_button_hover, ir);
@@ -1659,7 +1661,7 @@ Rect2 Tree::search_item_rect(TreeItem *p_from, TreeItem *p_item) {
void Tree::_range_click_timeout() {
- if (range_item_last && !range_drag_enabled && Input::get_singleton()->is_mouse_button_pressed(BUTTON_LEFT)) {
+ if (range_item_last && !range_drag_enabled && InputFilter::get_singleton()->is_mouse_button_pressed(BUTTON_LEFT)) {
Point2 pos = get_local_mouse_position() - cache.bg->get_offset();
if (show_column_titles) {
@@ -2046,9 +2048,9 @@ int Tree::propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool
void Tree::_text_editor_modal_close() {
- if (Input::get_singleton()->is_key_pressed(KEY_ESCAPE) ||
- Input::get_singleton()->is_key_pressed(KEY_KP_ENTER) ||
- Input::get_singleton()->is_key_pressed(KEY_ENTER)) {
+ if (InputFilter::get_singleton()->is_key_pressed(KEY_ESCAPE) ||
+ InputFilter::get_singleton()->is_key_pressed(KEY_KP_ENTER) ||
+ InputFilter::get_singleton()->is_key_pressed(KEY_ENTER)) {
return;
}
@@ -2056,13 +2058,12 @@ void Tree::_text_editor_modal_close() {
if (value_editor->has_point(value_editor->get_local_mouse_position()))
return;
- text_editor_enter(text_editor->get_text());
+ _text_editor_enter(text_editor->get_text());
}
-void Tree::text_editor_enter(String p_text) {
+void Tree::_text_editor_enter(String p_text) {
- text_editor->hide();
- value_editor->hide();
+ popup_editor->hide();
if (!popup_edited_item)
return;
@@ -2531,7 +2532,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) {
range_drag_enabled = true;
range_drag_capture_pos = cpos;
range_drag_base = popup_edited_item->get_range(popup_edited_item_col);
- Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_CAPTURED);
+ InputFilter::get_singleton()->set_mouse_mode(InputFilter::MOUSE_MODE_CAPTURED);
}
} else {
@@ -2593,7 +2594,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) {
if (range_drag_enabled) {
range_drag_enabled = false;
- Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE);
+ InputFilter::get_singleton()->set_mouse_mode(InputFilter::MOUSE_MODE_VISIBLE);
warp_mouse(range_drag_capture_pos);
} else {
Rect2 rect = get_selected()->get_meta("__focus_rect");
@@ -2703,7 +2704,7 @@ void Tree::_gui_input(Ref<InputEvent> p_event) {
drag_accum = 0;
//last_drag_accum=0;
drag_from = v_scroll->get_value();
- drag_touching = OS::get_singleton()->has_touchscreen_ui_hint();
+ drag_touching = !DisplayServer::get_singleton()->screen_is_touchscreen(DisplayServer::get_singleton()->window_get_current_screen(get_viewport()->get_window_id()));
drag_touching_deaccel = false;
if (drag_touching) {
set_physics_process_internal(true);
@@ -2806,20 +2807,23 @@ bool Tree::edit_selected() {
} else if (c.mode == TreeItem::CELL_MODE_STRING || c.mode == TreeItem::CELL_MODE_RANGE) {
+ Rect2 popup_rect;
+
Vector2 ofs(0, (text_editor->get_size().height - rect.size.height) / 2);
- Point2i textedpos = get_global_position() + rect.position - ofs;
+
+ Point2i textedpos = get_screen_position() + rect.position - ofs;
cache.text_editor_position = textedpos;
- text_editor->set_position(textedpos);
- text_editor->set_size(rect.size);
+ popup_rect.position = textedpos;
+ popup_rect.size = rect.size;
text_editor->clear();
text_editor->set_text(c.mode == TreeItem::CELL_MODE_STRING ? c.text : String::num(c.val, Math::range_step_decimals(c.step)));
text_editor->select_all();
if (c.mode == TreeItem::CELL_MODE_RANGE) {
- 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();
+ popup_rect.size.y += value_editor->get_minimum_size().height;
+
+ value_editor->show();
updating_value_editor = true;
value_editor->set_min(c.min);
value_editor->set_max(c.max);
@@ -2827,10 +2831,17 @@ bool Tree::edit_selected() {
value_editor->set_value(c.val);
value_editor->set_exp_ratio(c.expr);
updating_value_editor = false;
+ } else {
+ value_editor->hide();
}
- text_editor->show_modal();
+ popup_editor->set_position(popup_rect.position);
+ popup_editor->set_size(popup_rect.size);
+ popup_editor->popup();
+ popup_editor->child_controls_changed();
+
text_editor->grab_focus();
+
return true;
}
@@ -3011,7 +3022,7 @@ void Tree::_notification(int p_what) {
RID ci = get_canvas_item();
Ref<StyleBox> bg = cache.bg;
- Ref<StyleBox> bg_focus = get_stylebox("bg_focus");
+ Ref<StyleBox> bg_focus = get_theme_stylebox("bg_focus");
Point2 draw_ofs;
draw_ofs += bg->get_offset();
@@ -3234,7 +3245,7 @@ void Tree::clear() {
if (pressing_for_editor) {
if (range_drag_enabled) {
range_drag_enabled = false;
- Input::get_singleton()->set_mouse_mode(Input::MOUSE_MODE_VISIBLE);
+ InputFilter::get_singleton()->set_mouse_mode(InputFilter::MOUSE_MODE_VISIBLE);
warp_mouse(range_drag_capture_pos);
}
pressing_for_editor = false;
@@ -4020,14 +4031,23 @@ Tree::Tree() {
popup_menu = memnew(PopupMenu);
popup_menu->hide();
add_child(popup_menu);
- popup_menu->set_as_toplevel(true);
+ // popup_menu->set_as_toplevel(true);
+
+ popup_editor = memnew(PopupPanel);
+ popup_editor->set_wrap_controls(true);
+ add_child(popup_editor);
+ popup_editor_vb = memnew(VBoxContainer);
+ popup_editor->add_child(popup_editor_vb);
+ popup_editor_vb->add_theme_constant_override("separation", 0);
+ popup_editor_vb->set_anchors_and_margins_preset(PRESET_WIDE);
text_editor = memnew(LineEdit);
- add_child(text_editor);
- text_editor->set_as_toplevel(true);
- text_editor->hide();
+ popup_editor_vb->add_child(text_editor);
+ text_editor->set_v_size_flags(SIZE_EXPAND_FILL);
+ text_editor->set_h_size_flags(SIZE_EXPAND_FILL);
value_editor = memnew(HSlider);
- add_child(value_editor);
- value_editor->set_as_toplevel(true);
+ value_editor->set_v_size_flags(SIZE_EXPAND_FILL);
+ value_editor->set_h_size_flags(SIZE_EXPAND_FILL);
+ popup_editor_vb->add_child(value_editor);
value_editor->hide();
h_scroll = memnew(HScrollBar);
@@ -4042,13 +4062,11 @@ Tree::Tree() {
h_scroll->connect("value_changed", callable_mp(this, &Tree::_scroll_moved));
v_scroll->connect("value_changed", callable_mp(this, &Tree::_scroll_moved));
- text_editor->connect("text_entered", callable_mp(this, &Tree::text_editor_enter));
- text_editor->connect("modal_closed", callable_mp(this, &Tree::_text_editor_modal_close));
+ text_editor->connect("text_entered", callable_mp(this, &Tree::_text_editor_enter));
+ popup_editor->connect("popup_hide", callable_mp(this, &Tree::_text_editor_modal_close));
popup_menu->connect("id_pressed", callable_mp(this, &Tree::popup_select));
value_editor->connect("value_changed", callable_mp(this, &Tree::value_editor_changed));
- value_editor->set_as_toplevel(true);
- text_editor->set_as_toplevel(true);
set_notify_transform(true);
updating_value_editor = false;
diff --git a/scene/gui/tree.h b/scene/gui/tree.h
index b179c5bcba..becbe76598 100644
--- a/scene/gui/tree.h
+++ b/scene/gui/tree.h
@@ -290,6 +290,8 @@ public:
VARIANT_ENUM_CAST(TreeItem::TreeCellMode);
VARIANT_ENUM_CAST(TreeItem::TextAlign);
+class VBoxContainer;
+
class Tree : public Control {
GDCLASS(Tree, Control);
@@ -359,6 +361,10 @@ private:
};
bool show_column_titles;
+
+ VBoxContainer *popup_editor_vb;
+
+ PopupPanel *popup_editor;
LineEdit *text_editor;
HSlider *value_editor;
bool updating_value_editor;
@@ -379,7 +385,7 @@ private:
int draw_item(const Point2i &p_pos, const Point2 &p_draw_ofs, const Size2 &p_draw_size, TreeItem *p_item);
void select_single_item(TreeItem *p_selected, TreeItem *p_current, int p_col, TreeItem *p_prev = NULL, bool *r_in_range = NULL, bool p_force_deselect = false);
int propagate_mouse_event(const Point2i &p_pos, int x_ofs, int y_ofs, bool p_doubleclick, TreeItem *p_item, int p_button, const Ref<InputEventWithModifiers> &p_mod);
- void text_editor_enter(String p_text);
+ void _text_editor_enter(String p_text);
void _text_editor_modal_close();
void value_editor_changed(double p_value);
diff --git a/scene/gui/viewport_container.cpp b/scene/gui/viewport_container.cpp
index a76f2924d3..7ce1d9e551 100644
--- a/scene/gui/viewport_container.cpp
+++ b/scene/gui/viewport_container.cpp
@@ -40,7 +40,7 @@ Size2 ViewportContainer::get_minimum_size() const {
Size2 ms;
for (int i = 0; i < get_child_count(); i++) {
- Viewport *c = Object::cast_to<Viewport>(get_child(i));
+ SubViewport *c = Object::cast_to<SubViewport>(get_child(i));
if (!c)
continue;
@@ -77,7 +77,7 @@ void ViewportContainer::set_stretch_shrink(int p_shrink) {
for (int i = 0; i < get_child_count(); i++) {
- Viewport *c = Object::cast_to<Viewport>(get_child(i));
+ SubViewport *c = Object::cast_to<SubViewport>(get_child(i));
if (!c)
continue;
@@ -101,7 +101,7 @@ void ViewportContainer::_notification(int p_what) {
for (int i = 0; i < get_child_count(); i++) {
- Viewport *c = Object::cast_to<Viewport>(get_child(i));
+ SubViewport *c = Object::cast_to<SubViewport>(get_child(i));
if (!c)
continue;
@@ -113,14 +113,14 @@ void ViewportContainer::_notification(int p_what) {
for (int i = 0; i < get_child_count(); i++) {
- Viewport *c = Object::cast_to<Viewport>(get_child(i));
+ SubViewport *c = Object::cast_to<SubViewport>(get_child(i));
if (!c)
continue;
if (is_visible_in_tree())
- c->set_update_mode(Viewport::UPDATE_ALWAYS);
+ c->set_update_mode(SubViewport::UPDATE_ALWAYS);
else
- c->set_update_mode(Viewport::UPDATE_DISABLED);
+ c->set_update_mode(SubViewport::UPDATE_DISABLED);
c->set_handle_input_locally(false); //do not handle input locally here
}
@@ -130,7 +130,7 @@ void ViewportContainer::_notification(int p_what) {
for (int i = 0; i < get_child_count(); i++) {
- Viewport *c = Object::cast_to<Viewport>(get_child(i));
+ SubViewport *c = Object::cast_to<SubViewport>(get_child(i));
if (!c)
continue;
@@ -159,7 +159,7 @@ void ViewportContainer::_input(const Ref<InputEvent> &p_event) {
for (int i = 0; i < get_child_count(); i++) {
- Viewport *c = Object::cast_to<Viewport>(get_child(i));
+ SubViewport *c = Object::cast_to<SubViewport>(get_child(i));
if (!c || c->is_input_disabled())
continue;
@@ -184,7 +184,7 @@ void ViewportContainer::_unhandled_input(const Ref<InputEvent> &p_event) {
for (int i = 0; i < get_child_count(); i++) {
- Viewport *c = Object::cast_to<Viewport>(get_child(i));
+ SubViewport *c = Object::cast_to<SubViewport>(get_child(i));
if (!c || c->is_input_disabled())
continue;
diff --git a/scene/main/node.cpp b/scene/main/node.cpp
index 973dff07d2..b882b9ead6 100644
--- a/scene/main/node.cpp
+++ b/scene/main/node.cpp
@@ -2950,9 +2950,9 @@ void Node::_bind_methods() {
BIND_CONSTANT(NOTIFICATION_WM_MOUSE_EXIT);
BIND_CONSTANT(NOTIFICATION_WM_FOCUS_IN);
BIND_CONSTANT(NOTIFICATION_WM_FOCUS_OUT);
- BIND_CONSTANT(NOTIFICATION_WM_QUIT_REQUEST);
+ BIND_CONSTANT(NOTIFICATION_WM_CLOSE_REQUEST);
BIND_CONSTANT(NOTIFICATION_WM_GO_BACK_REQUEST);
- BIND_CONSTANT(NOTIFICATION_WM_UNFOCUS_REQUEST);
+ BIND_CONSTANT(NOTIFICATION_WM_SIZE_CHANGED);
BIND_CONSTANT(NOTIFICATION_OS_MEMORY_WARNING);
BIND_CONSTANT(NOTIFICATION_TRANSLATION_CHANGED);
BIND_CONSTANT(NOTIFICATION_WM_ABOUT);
diff --git a/scene/main/node.h b/scene/main/node.h
index d1f75b71ec..cf25a92be6 100644
--- a/scene/main/node.h
+++ b/scene/main/node.h
@@ -244,13 +244,16 @@ public:
NOTIFICATION_INTERNAL_PHYSICS_PROCESS = 26,
NOTIFICATION_POST_ENTER_TREE = 27,
//keep these linked to node
- NOTIFICATION_WM_MOUSE_ENTER = MainLoop::NOTIFICATION_WM_MOUSE_ENTER,
- NOTIFICATION_WM_MOUSE_EXIT = MainLoop::NOTIFICATION_WM_MOUSE_EXIT,
- NOTIFICATION_WM_FOCUS_IN = MainLoop::NOTIFICATION_WM_FOCUS_IN,
- NOTIFICATION_WM_FOCUS_OUT = MainLoop::NOTIFICATION_WM_FOCUS_OUT,
- NOTIFICATION_WM_QUIT_REQUEST = MainLoop::NOTIFICATION_WM_QUIT_REQUEST,
- NOTIFICATION_WM_GO_BACK_REQUEST = MainLoop::NOTIFICATION_WM_GO_BACK_REQUEST,
- NOTIFICATION_WM_UNFOCUS_REQUEST = MainLoop::NOTIFICATION_WM_UNFOCUS_REQUEST,
+
+ NOTIFICATION_WM_MOUSE_ENTER = 1002,
+ NOTIFICATION_WM_MOUSE_EXIT = 1003,
+ NOTIFICATION_WM_FOCUS_IN = 1004,
+ NOTIFICATION_WM_FOCUS_OUT = 1005,
+ NOTIFICATION_WM_CLOSE_REQUEST = 1006,
+ NOTIFICATION_WM_GO_BACK_REQUEST = 1007,
+ NOTIFICATION_WM_SIZE_CHANGED = 1008,
+ NOTIFICATION_WM_DPI_CHANGE = 1009,
+
NOTIFICATION_OS_MEMORY_WARNING = MainLoop::NOTIFICATION_OS_MEMORY_WARNING,
NOTIFICATION_TRANSLATION_CHANGED = MainLoop::NOTIFICATION_TRANSLATION_CHANGED,
NOTIFICATION_WM_ABOUT = MainLoop::NOTIFICATION_WM_ABOUT,
diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp
index f472de220b..fad10524b9 100644
--- a/scene/main/scene_tree.cpp
+++ b/scene/main/scene_tree.cpp
@@ -31,6 +31,7 @@
#include "scene_tree.h"
#include "core/debugger/engine_debugger.h"
+#include "core/input/input_filter.h"
#include "core/io/marshalls.h"
#include "core/io/resource_loader.h"
#include "core/message_queue.h"
@@ -39,7 +40,6 @@
#include "core/os/os.h"
#include "core/print_string.h"
#include "core/project_settings.h"
-#include "main/input_default.h"
#include "node.h"
#include "scene/debugger/scene_debugger.h"
#include "scene/resources/dynamic_font.h"
@@ -47,10 +47,11 @@
#include "scene/resources/mesh.h"
#include "scene/resources/packed_scene.h"
#include "scene/scene_string_names.h"
+#include "servers/display_server.h"
#include "servers/navigation_server.h"
#include "servers/physics_2d_server.h"
#include "servers/physics_server.h"
-#include "viewport.h"
+#include "window.h"
#include <stdio.h>
@@ -397,69 +398,6 @@ void SceneTree::set_group(const StringName &p_group, const String &p_name, const
set_group_flags(0, p_group, p_name, p_value);
}
-void SceneTree::set_input_as_handled() {
-
- input_handled = true;
-}
-
-void SceneTree::input_text(const String &p_text) {
-
- root_lock++;
-
- call_group_flags(GROUP_CALL_REALTIME, "_viewports", "_vp_input_text", p_text); //special one for GUI, as controls use their own process check
-
- root_lock--;
-}
-
-bool SceneTree::is_input_handled() {
- return input_handled;
-}
-
-void SceneTree::input_event(const Ref<InputEvent> &p_event) {
-
- if (Engine::get_singleton()->is_editor_hint() && (Object::cast_to<InputEventJoypadButton>(p_event.ptr()) || Object::cast_to<InputEventJoypadMotion>(*p_event)))
- return; //avoid joy input on editor
-
- current_event++;
- root_lock++;
-
- input_handled = false;
-
- // Don't make const ref unless you can find and fix what caused GH-34691.
- Ref<InputEvent> ev = p_event;
-
- MainLoop::input_event(ev);
-
- call_group_flags(GROUP_CALL_REALTIME, "_viewports", "_vp_input", ev); //special one for GUI, as controls use their own process check
-
- if (EngineDebugger::is_active()) {
- //quit from game window using F8
- Ref<InputEventKey> k = ev;
- if (k.is_valid() && k->is_pressed() && !k->is_echo() && k->get_keycode() == KEY_F8) {
- EngineDebugger::get_singleton()->send_message("request_quit", Array());
- }
- }
-
- _flush_ugc();
- root_lock--;
- //MessageQueue::get_singleton()->flush(); //flushing here causes UI and other places slowness
-
- root_lock++;
-
- if (!input_handled) {
- call_group_flags(GROUP_CALL_REALTIME, "_viewports", "_vp_unhandled_input", ev); //special one for GUI, as controls use their own process check
- _flush_ugc();
- // input_handled = true; - no reason to set this as handled
- root_lock--;
- //MessageQueue::get_singleton()->flush(); //flushing here causes UI and other places slowness
- } else {
- // input_handled = true; - no reason to set this as handled
- root_lock--;
- }
-
- _call_idle_callbacks();
-}
-
void SceneTree::init() {
initialized = true;
root->_set_tree(this);
@@ -493,14 +431,6 @@ bool SceneTree::iteration(float p_time) {
return _quit;
}
-void SceneTree::_update_font_oversampling(float p_ratio) {
-
- if (use_font_oversampling) {
- DynamicFontAtSize::font_oversampling = p_ratio;
- DynamicFont::update_oversampling();
- }
-}
-
bool SceneTree::idle(float p_time) {
//print_line("ram: "+itos(OS::get_singleton()->get_static_memory_usage())+" sram: "+itos(OS::get_singleton()->get_dynamic_memory_usage()));
@@ -526,15 +456,6 @@ bool SceneTree::idle(float p_time) {
_notify_group_pause("idle_process_internal", Node::NOTIFICATION_INTERNAL_PROCESS);
_notify_group_pause("idle_process", Node::NOTIFICATION_PROCESS);
- Size2 win_size = Size2(OS::get_singleton()->get_window_size().width, OS::get_singleton()->get_window_size().height);
-
- if (win_size != last_screen_size) {
-
- last_screen_size = win_size;
- _update_root_rect();
- emit_signal("screen_resized");
- }
-
_flush_ugc();
MessageQueue::get_singleton()->flush(); //small little hack
flush_transform_notifications(); //transforms after world update, to avoid unnecessary enter/exit notifications
@@ -642,59 +563,36 @@ void SceneTree::quit(int p_exit_code) {
_quit = true;
}
-void SceneTree::_notification(int p_notification) {
-
- switch (p_notification) {
-
- case NOTIFICATION_WM_QUIT_REQUEST: {
-
- get_root()->propagate_notification(p_notification);
-
- if (accept_quit) {
- _quit = true;
- break;
- }
- } break;
-
- case NOTIFICATION_WM_GO_BACK_REQUEST: {
-
- get_root()->propagate_notification(p_notification);
+void SceneTree::_main_window_close() {
- if (quit_on_go_back) {
- _quit = true;
- break;
- }
- } break;
+ if (accept_quit) {
+ _quit = true;
+ }
+}
+void SceneTree::_main_window_go_back() {
+ if (quit_on_go_back) {
+ _quit = true;
+ }
+}
- case NOTIFICATION_WM_FOCUS_IN: {
+void SceneTree::_main_window_focus_in() {
+ InputFilter *id = InputFilter::get_singleton();
+ if (id) {
+ id->ensure_touch_mouse_raised();
+ }
+}
- InputDefault *id = Object::cast_to<InputDefault>(Input::get_singleton());
- if (id) {
- id->ensure_touch_mouse_raised();
- }
+void SceneTree::_notification(int p_notification) {
- get_root()->propagate_notification(p_notification);
- } break;
+ switch (p_notification) {
case NOTIFICATION_TRANSLATION_CHANGED: {
if (!Engine::get_singleton()->is_editor_hint()) {
get_root()->propagate_notification(p_notification);
}
} break;
-
- case NOTIFICATION_WM_UNFOCUS_REQUEST: {
-
- notify_group_flags(GROUP_CALL_REALTIME | GROUP_CALL_MULTILEVEL, "input", NOTIFICATION_WM_UNFOCUS_REQUEST);
-
- get_root()->propagate_notification(p_notification);
-
- } break;
-
case NOTIFICATION_OS_MEMORY_WARNING:
case NOTIFICATION_OS_IME_UPDATE:
- case NOTIFICATION_WM_MOUSE_ENTER:
- case NOTIFICATION_WM_MOUSE_EXIT:
- case NOTIFICATION_WM_FOCUS_OUT:
case NOTIFICATION_WM_ABOUT:
case NOTIFICATION_CRASH:
case NOTIFICATION_APP_RESUMED:
@@ -910,7 +808,7 @@ bool SceneTree::is_paused() const {
return pause;
}
-void SceneTree::_call_input_pause(const StringName &p_group, const StringName &p_method, const Ref<InputEvent> &p_input) {
+void SceneTree::_notify_group_pause(const StringName &p_group, int p_notification) {
Map<StringName, Group>::Element *E = group_map.find(p_group);
if (!E)
@@ -919,7 +817,7 @@ void SceneTree::_call_input_pause(const StringName &p_group, const StringName &p
if (g.nodes.empty())
return;
- _update_group_order(g);
+ _update_group_order(g, p_notification == Node::NOTIFICATION_PROCESS || p_notification == Node::NOTIFICATION_INTERNAL_PROCESS || p_notification == Node::NOTIFICATION_PHYSICS_PROCESS || p_notification == Node::NOTIFICATION_INTERNAL_PHYSICS_PROCESS);
//copy, so copy on write happens in case something is removed from process while being called
//performance is not lost because only if something is added/removed the vector is copied.
@@ -928,15 +826,9 @@ void SceneTree::_call_input_pause(const StringName &p_group, const StringName &p
int node_count = nodes_copy.size();
Node **nodes = nodes_copy.ptrw();
- Variant arg = p_input;
- const Variant *v[1] = { &arg };
-
call_lock++;
- for (int i = node_count - 1; i >= 0; i--) {
-
- if (input_handled)
- break;
+ for (int i = 0; i < node_count; i++) {
Node *n = nodes[i];
if (call_lock && call_skip.has(n))
@@ -944,8 +836,10 @@ void SceneTree::_call_input_pause(const StringName &p_group, const StringName &p
if (!n->can_process())
continue;
+ if (!n->can_process_notification(p_notification))
+ continue;
- n->call_multilevel(p_method, (const Variant **)v, 1);
+ n->notification(p_notification);
//ERR_FAIL_COND(node_count != g.nodes.size());
}
@@ -954,7 +848,18 @@ void SceneTree::_call_input_pause(const StringName &p_group, const StringName &p
call_skip.clear();
}
-void SceneTree::_notify_group_pause(const StringName &p_group, int p_notification) {
+/*
+void SceneMainLoop::_update_listener_2d() {
+
+ if (listener_2d.is_valid()) {
+
+ SpatialSound2DServer::get_singleton()->listener_set_space( listener_2d, world_2d->get_sound_space() );
+ }
+
+}
+*/
+
+void SceneTree::_call_input_pause(const StringName &p_group, const StringName &p_method, const Ref<InputEvent> &p_input, Viewport *p_viewport) {
Map<StringName, Group>::Element *E = group_map.find(p_group);
if (!E)
@@ -963,7 +868,7 @@ void SceneTree::_notify_group_pause(const StringName &p_group, int p_notificatio
if (g.nodes.empty())
return;
- _update_group_order(g, p_notification == Node::NOTIFICATION_PROCESS || p_notification == Node::NOTIFICATION_INTERNAL_PROCESS || p_notification == Node::NOTIFICATION_PHYSICS_PROCESS || p_notification == Node::NOTIFICATION_INTERNAL_PHYSICS_PROCESS);
+ _update_group_order(g);
//copy, so copy on write happens in case something is removed from process while being called
//performance is not lost because only if something is added/removed the vector is copied.
@@ -972,9 +877,15 @@ void SceneTree::_notify_group_pause(const StringName &p_group, int p_notificatio
int node_count = nodes_copy.size();
Node **nodes = nodes_copy.ptrw();
+ Variant arg = p_input;
+ const Variant *v[1] = { &arg };
+
call_lock++;
- for (int i = 0; i < node_count; i++) {
+ for (int i = node_count - 1; i >= 0; i--) {
+
+ if (p_viewport->is_input_handled())
+ break;
Node *n = nodes[i];
if (call_lock && call_skip.has(n))
@@ -982,10 +893,8 @@ void SceneTree::_notify_group_pause(const StringName &p_group, int p_notificatio
if (!n->can_process())
continue;
- if (!n->can_process_notification(p_notification))
- continue;
- n->notification(p_notification);
+ n->call_multilevel(p_method, (const Variant **)v, 1);
//ERR_FAIL_COND(node_count != g.nodes.size());
}
@@ -993,18 +902,6 @@ void SceneTree::_notify_group_pause(const StringName &p_group, int p_notificatio
if (call_lock == 0)
call_skip.clear();
}
-
-/*
-void SceneMainLoop::_update_listener_2d() {
-
- if (listener_2d.is_valid()) {
-
- SpatialSound2DServer::get_singleton()->listener_set_space( listener_2d, world_2d->get_sound_space() );
- }
-
-}
-*/
-
Variant SceneTree::_call_group_flags(const Variant **p_args, int p_argcount, Callable::CallError &r_error) {
r_error.error = Callable::CallError::CALL_OK;
@@ -1129,129 +1026,6 @@ int SceneTree::get_node_count() const {
return node_count;
}
-void SceneTree::_update_root_rect() {
-
- if (stretch_mode == STRETCH_MODE_DISABLED) {
-
- _update_font_oversampling(1.0);
- root->set_size((last_screen_size / stretch_shrink).floor());
- root->set_attach_to_screen_rect(Rect2(Point2(), last_screen_size));
- root->set_size_override_stretch(false);
- root->set_size_override(false, Size2());
- root->update_canvas_items();
- return; //user will take care
- }
-
- //actual screen video mode
- Size2 video_mode = Size2(OS::get_singleton()->get_window_size().width, OS::get_singleton()->get_window_size().height);
- Size2 desired_res = stretch_min;
-
- Size2 viewport_size;
- Size2 screen_size;
-
- float viewport_aspect = desired_res.aspect();
- float video_mode_aspect = video_mode.aspect();
-
- if (use_font_oversampling && stretch_aspect == STRETCH_ASPECT_IGNORE) {
- WARN_PRINT("Font oversampling only works with the resize modes 'Keep Width', 'Keep Height', and 'Expand'.");
- }
-
- if (stretch_aspect == STRETCH_ASPECT_IGNORE || Math::is_equal_approx(viewport_aspect, video_mode_aspect)) {
- //same aspect or ignore aspect
- viewport_size = desired_res;
- screen_size = video_mode;
- } else if (viewport_aspect < video_mode_aspect) {
- // screen ratio is smaller vertically
-
- if (stretch_aspect == STRETCH_ASPECT_KEEP_HEIGHT || stretch_aspect == STRETCH_ASPECT_EXPAND) {
-
- //will stretch horizontally
- viewport_size.x = desired_res.y * video_mode_aspect;
- viewport_size.y = desired_res.y;
- screen_size = video_mode;
-
- } else {
- //will need black bars
- viewport_size = desired_res;
- screen_size.x = video_mode.y * viewport_aspect;
- screen_size.y = video_mode.y;
- }
- } else {
- //screen ratio is smaller horizontally
- if (stretch_aspect == STRETCH_ASPECT_KEEP_WIDTH || stretch_aspect == STRETCH_ASPECT_EXPAND) {
-
- //will stretch horizontally
- viewport_size.x = desired_res.x;
- viewport_size.y = desired_res.x / video_mode_aspect;
- screen_size = video_mode;
-
- } else {
- //will need black bars
- viewport_size = desired_res;
- screen_size.x = video_mode.x;
- screen_size.y = video_mode.x / viewport_aspect;
- }
- }
-
- screen_size = screen_size.floor();
- viewport_size = viewport_size.floor();
-
- Size2 margin;
- Size2 offset;
- //black bars and margin
- if (stretch_aspect != STRETCH_ASPECT_EXPAND && screen_size.x < video_mode.x) {
- margin.x = Math::round((video_mode.x - screen_size.x) / 2.0);
- VisualServer::get_singleton()->black_bars_set_margins(margin.x, 0, margin.x, 0);
- offset.x = Math::round(margin.x * viewport_size.y / screen_size.y);
- } else if (stretch_aspect != STRETCH_ASPECT_EXPAND && screen_size.y < video_mode.y) {
- margin.y = Math::round((video_mode.y - screen_size.y) / 2.0);
- VisualServer::get_singleton()->black_bars_set_margins(0, margin.y, 0, margin.y);
- offset.y = Math::round(margin.y * viewport_size.x / screen_size.x);
- } else {
- VisualServer::get_singleton()->black_bars_set_margins(0, 0, 0, 0);
- }
-
- switch (stretch_mode) {
- case STRETCH_MODE_DISABLED: {
- // Already handled above
- _update_font_oversampling(1.0);
- } break;
- case STRETCH_MODE_2D: {
-
- _update_font_oversampling(screen_size.x / viewport_size.x); //screen / viewport radio drives oversampling
- root->set_size((screen_size / stretch_shrink).floor());
- root->set_attach_to_screen_rect(Rect2(margin, screen_size));
- root->set_size_override_stretch(true);
- root->set_size_override(true, (viewport_size / stretch_shrink).floor());
- root->update_canvas_items(); //force them to update just in case
-
- } break;
- case STRETCH_MODE_VIEWPORT: {
-
- _update_font_oversampling(1.0);
- root->set_size((viewport_size / stretch_shrink).floor());
- root->set_attach_to_screen_rect(Rect2(margin, screen_size));
- root->set_size_override_stretch(false);
- root->set_size_override(false, Size2());
- root->update_canvas_items(); //force them to update just in case
-
- if (use_font_oversampling) {
- WARN_PRINT("Font oversampling does not work in 'Viewport' stretch mode, only '2D'.");
- }
-
- } break;
- }
-}
-
-void SceneTree::set_screen_stretch(StretchMode p_mode, StretchAspect p_aspect, const Size2 &p_minsize, real_t p_shrink) {
-
- stretch_mode = p_mode;
- stretch_aspect = p_aspect;
- stretch_min = p_minsize;
- stretch_shrink = p_shrink;
- _update_root_rect();
-}
-
void SceneTree::set_edited_scene_root(Node *p_node) {
#ifdef TOOLS_ENABLED
edited_scene_root = p_node;
@@ -1330,18 +1104,6 @@ void SceneTree::add_current_scene(Node *p_current) {
root->add_child(p_current);
}
-void SceneTree::drop_files(const Vector<String> &p_files, int p_from_screen) {
-
- emit_signal("files_dropped", p_files, p_from_screen);
- MainLoop::drop_files(p_files, p_from_screen);
-}
-
-void SceneTree::global_menu_action(const Variant &p_id, const Variant &p_meta) {
-
- emit_signal("global_menu_action", p_id, p_meta);
- MainLoop::global_menu_action(p_id, p_meta);
-}
-
Ref<SceneTreeTimer> SceneTree::create_timer(float p_delay_sec, bool p_process_pause) {
Ref<SceneTreeTimer> stt;
@@ -1469,8 +1231,6 @@ void SceneTree::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_pause", "enable"), &SceneTree::set_pause);
ClassDB::bind_method(D_METHOD("is_paused"), &SceneTree::is_paused);
- ClassDB::bind_method(D_METHOD("set_input_as_handled"), &SceneTree::set_input_as_handled);
- ClassDB::bind_method(D_METHOD("is_input_handled"), &SceneTree::is_input_handled);
ClassDB::bind_method(D_METHOD("create_timer", "time_sec", "pause_mode_process"), &SceneTree::create_timer, DEFVAL(true));
@@ -1478,8 +1238,6 @@ void SceneTree::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_frame"), &SceneTree::get_frame);
ClassDB::bind_method(D_METHOD("quit", "exit_code"), &SceneTree::quit, DEFVAL(-1));
- ClassDB::bind_method(D_METHOD("set_screen_stretch", "mode", "aspect", "minsize", "shrink"), &SceneTree::set_screen_stretch, DEFVAL(1));
-
ClassDB::bind_method(D_METHOD("queue_delete", "obj"), &SceneTree::queue_delete);
MethodInfo mi;
@@ -1529,15 +1287,11 @@ void SceneTree::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_refuse_new_network_connections", "refuse"), &SceneTree::set_refuse_new_network_connections);
ClassDB::bind_method(D_METHOD("is_refusing_new_network_connections"), &SceneTree::is_refusing_new_network_connections);
- ClassDB::bind_method(D_METHOD("set_use_font_oversampling", "enable"), &SceneTree::set_use_font_oversampling);
- ClassDB::bind_method(D_METHOD("is_using_font_oversampling"), &SceneTree::is_using_font_oversampling);
-
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "debug_collisions_hint"), "set_debug_collisions_hint", "is_debugging_collisions_hint");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "debug_navigation_hint"), "set_debug_navigation_hint", "is_debugging_navigation_hint");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "paused"), "set_pause", "is_paused");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "refuse_new_network_connections"), "set_refuse_new_network_connections", "is_refusing_new_network_connections");
ADD_PROPERTY_DEFAULT("refuse_new_network_connections", false);
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "use_font_oversampling"), "set_use_font_oversampling", "is_using_font_oversampling");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "edited_scene_root", PROPERTY_HINT_RESOURCE_TYPE, "Node", 0), "set_edited_scene_root", "get_edited_scene_root");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "current_scene", PROPERTY_HINT_RESOURCE_TYPE, "Node", 0), "set_current_scene", "get_current_scene");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "network_peer", PROPERTY_HINT_RESOURCE_TYPE, "NetworkedMultiplayerPeer", 0), "set_network_peer", "get_network_peer");
@@ -1549,14 +1303,12 @@ void SceneTree::_bind_methods() {
ADD_SIGNAL(MethodInfo("node_added", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
ADD_SIGNAL(MethodInfo("node_removed", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
ADD_SIGNAL(MethodInfo("node_renamed", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
- ADD_SIGNAL(MethodInfo("screen_resized"));
ADD_SIGNAL(MethodInfo("node_configuration_warning_changed", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Node")));
ADD_SIGNAL(MethodInfo("idle_frame"));
ADD_SIGNAL(MethodInfo("physics_frame"));
ADD_SIGNAL(MethodInfo("files_dropped", PropertyInfo(Variant::PACKED_STRING_ARRAY, "files"), PropertyInfo(Variant::INT, "screen")));
- ADD_SIGNAL(MethodInfo("global_menu_action", PropertyInfo(Variant::NIL, "id"), PropertyInfo(Variant::NIL, "meta")));
ADD_SIGNAL(MethodInfo("network_peer_connected", PropertyInfo(Variant::INT, "id")));
ADD_SIGNAL(MethodInfo("network_peer_disconnected", PropertyInfo(Variant::INT, "id")));
ADD_SIGNAL(MethodInfo("connected_to_server"));
@@ -1567,16 +1319,6 @@ void SceneTree::_bind_methods() {
BIND_ENUM_CONSTANT(GROUP_CALL_REVERSE);
BIND_ENUM_CONSTANT(GROUP_CALL_REALTIME);
BIND_ENUM_CONSTANT(GROUP_CALL_UNIQUE);
-
- BIND_ENUM_CONSTANT(STRETCH_MODE_DISABLED);
- BIND_ENUM_CONSTANT(STRETCH_MODE_2D);
- BIND_ENUM_CONSTANT(STRETCH_MODE_VIEWPORT);
-
- BIND_ENUM_CONSTANT(STRETCH_ASPECT_IGNORE);
- BIND_ENUM_CONSTANT(STRETCH_ASPECT_KEEP);
- BIND_ENUM_CONSTANT(STRETCH_ASPECT_KEEP_WIDTH);
- BIND_ENUM_CONSTANT(STRETCH_ASPECT_KEEP_HEIGHT);
- BIND_ENUM_CONSTANT(STRETCH_ASPECT_EXPAND);
}
SceneTree *SceneTree::singleton = NULL;
@@ -1596,19 +1338,6 @@ void SceneTree::add_idle_callback(IdleCallback p_callback) {
idle_callbacks[idle_callback_count++] = p_callback;
}
-void SceneTree::set_use_font_oversampling(bool p_oversampling) {
-
- if (use_font_oversampling == p_oversampling)
- return;
-
- use_font_oversampling = p_oversampling;
- _update_root_rect();
-}
-
-bool SceneTree::is_using_font_oversampling() const {
- return use_font_oversampling;
-}
-
void SceneTree::get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const {
if (p_function == "change_scene") {
@@ -1648,7 +1377,6 @@ SceneTree::SceneTree() {
accept_quit = true;
quit_on_go_back = true;
initialized = false;
- use_font_oversampling = false;
#ifdef DEBUG_ENABLED
debug_collisions_hint = false;
debug_navigation_hint = false;
@@ -1665,7 +1393,6 @@ SceneTree::SceneTree() {
idle_process_time = 1;
root = NULL;
- input_handled = false;
pause = false;
current_frame = 0;
current_event = 0;
@@ -1680,9 +1407,8 @@ SceneTree::SceneTree() {
//create with mainloop
- root = memnew(Viewport);
+ root = memnew(Window);
root->set_name("root");
- root->set_handle_input_locally(false);
if (!root->get_world().is_valid())
root->set_world(Ref<World>(memnew(World)));
@@ -1730,15 +1456,12 @@ SceneTree::SceneTree() {
}
}
- stretch_mode = STRETCH_MODE_DISABLED;
- stretch_aspect = STRETCH_ASPECT_IGNORE;
- stretch_shrink = 1;
-
- last_screen_size = Size2(OS::get_singleton()->get_window_size().width, OS::get_singleton()->get_window_size().height);
- _update_root_rect();
-
root->set_physics_object_picking(GLOBAL_DEF("physics/common/enable_object_picking", true));
+ root->connect("close_requested", callable_mp(this, &SceneTree::_main_window_close));
+ root->connect("go_back_requested", callable_mp(this, &SceneTree::_main_window_go_back));
+ root->connect("focus_entered", callable_mp(this, &SceneTree::_main_window_focus_in));
+
#ifdef TOOLS_ENABLED
edited_scene_root = NULL;
#endif
diff --git a/scene/main/scene_tree.h b/scene/main/scene_tree.h
index 2f805d074f..e6b2575f98 100644
--- a/scene/main/scene_tree.h
+++ b/scene/main/scene_tree.h
@@ -39,9 +39,11 @@
#include "scene/resources/world.h"
#include "scene/resources/world_2d.h"
+#undef Window
+
class PackedScene;
class Node;
-class Viewport;
+class Window;
class Material;
class Mesh;
class SceneDebugger;
@@ -76,22 +78,6 @@ class SceneTree : public MainLoop {
public:
typedef void (*IdleCallback)();
- enum StretchMode {
-
- STRETCH_MODE_DISABLED,
- STRETCH_MODE_2D,
- STRETCH_MODE_VIEWPORT,
- };
-
- enum StretchAspect {
-
- STRETCH_ASPECT_IGNORE,
- STRETCH_ASPECT_KEEP,
- STRETCH_ASPECT_KEEP_WIDTH,
- STRETCH_ASPECT_KEEP_HEIGHT,
- STRETCH_ASPECT_EXPAND,
- };
-
private:
struct Group {
@@ -101,7 +87,7 @@ private:
Group() { changed = false; };
};
- Viewport *root;
+ Window *root;
uint64_t tree_version;
float physics_process_time;
@@ -119,15 +105,12 @@ private:
Map<StringName, Group> group_map;
bool _quit;
bool initialized;
- bool input_handled;
- Size2 last_screen_size;
StringName tree_changed_name;
StringName node_added_name;
StringName node_removed_name;
StringName node_renamed_name;
- bool use_font_oversampling;
int64_t current_frame;
int64_t current_event;
int node_count;
@@ -147,14 +130,6 @@ private:
int call_lock;
Set<Node *> call_skip; //skip erased nodes
- StretchMode stretch_mode;
- StretchAspect stretch_aspect;
- Size2i stretch_min;
- real_t stretch_shrink;
-
- void _update_font_oversampling(float p_ratio);
- void _update_root_rect();
-
List<ObjectID> delete_queue;
Map<UGCall, Vector<Variant>> unique_group_calls;
@@ -208,7 +183,6 @@ private:
void make_group_changed(const StringName &p_group);
void _notify_group_pause(const StringName &p_group, int p_notification);
- void _call_input_pause(const StringName &p_group, const StringName &p_method, const Ref<InputEvent> &p_input);
Variant _call_group_flags(const Variant **p_args, int p_argcount, Callable::CallError &r_error);
Variant _call_group(const Variant **p_args, int p_argcount, Callable::CallError &r_error);
@@ -232,6 +206,13 @@ private:
static int idle_callback_count;
void _call_idle_callbacks();
+ void _main_window_focus_in();
+ void _main_window_close();
+ void _main_window_go_back();
+
+ //used by viewport
+ void _call_input_pause(const StringName &p_group, const StringName &p_method, const Ref<InputEvent> &p_input, Viewport *p_viewport);
+
protected:
void _notification(int p_notification);
static void _bind_methods();
@@ -249,7 +230,7 @@ public:
GROUP_CALL_MULTILEVEL = 8,
};
- _FORCE_INLINE_ Viewport *get_root() const { return root; }
+ _FORCE_INLINE_ Window *get_root() const { return root; }
void call_group_flags(uint32_t p_call_flags, const StringName &p_group, const StringName &p_function, VARIANT_ARG_LIST);
void notify_group_flags(uint32_t p_call_flags, const StringName &p_group, int p_notification);
@@ -261,8 +242,6 @@ public:
void flush_transform_notifications();
- virtual void input_text(const String &p_text);
- virtual void input_event(const Ref<InputEvent> &p_event);
virtual void init();
virtual bool iteration(float p_time);
@@ -275,8 +254,6 @@ public:
void quit(int p_exit_code = -1);
- void set_input_as_handled();
- bool is_input_handled();
_FORCE_INLINE_ float get_physics_process_time() const { return physics_process_time; }
_FORCE_INLINE_ float get_idle_process_time() const { return idle_process_time; }
@@ -335,11 +312,6 @@ public:
void get_nodes_in_group(const StringName &p_group, List<Node *> *p_list);
bool has_group(const StringName &p_identifier) const;
- void set_screen_stretch(StretchMode p_mode, StretchAspect p_aspect, const Size2 &p_minsize, real_t p_shrink = 1);
-
- void set_use_font_oversampling(bool p_oversampling);
- bool is_using_font_oversampling() const;
-
//void change_scene(const String& p_path);
//Node *get_loaded_scene();
@@ -359,8 +331,6 @@ public:
static SceneTree *get_singleton() { return singleton; }
- void drop_files(const Vector<String> &p_files, int p_from_screen = 0);
- void global_menu_action(const Variant &p_id, const Variant &p_meta);
void get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const;
//network API
@@ -388,8 +358,6 @@ public:
~SceneTree();
};
-VARIANT_ENUM_CAST(SceneTree::StretchMode);
-VARIANT_ENUM_CAST(SceneTree::StretchAspect);
VARIANT_ENUM_CAST(SceneTree::GroupCallFlags);
#endif
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index 8ef3bdd04e..e49674663a 100644
--- a/scene/main/viewport.cpp
+++ b/scene/main/viewport.cpp
@@ -32,7 +32,7 @@
#include "core/core_string_names.h"
#include "core/debugger/engine_debugger.h"
-#include "core/os/input.h"
+#include "core/input/input_filter.h"
#include "core/os/os.h"
#include "core/project_settings.h"
#include "scene/2d/collision_object_2d.h"
@@ -49,8 +49,10 @@
#include "scene/gui/popup_menu.h"
#include "scene/main/canvas_layer.h"
#include "scene/main/timer.h"
+#include "scene/main/window.h"
#include "scene/resources/mesh.h"
#include "scene/scene_string_names.h"
+#include "servers/display_server.h"
#include "servers/physics_2d_server.h"
void ViewportTexture::setup_local_to_scene() {
@@ -141,7 +143,7 @@ void ViewportTexture::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_viewport_path_in_scene", "path"), &ViewportTexture::set_viewport_path_in_scene);
ClassDB::bind_method(D_METHOD("get_viewport_path_in_scene"), &ViewportTexture::get_viewport_path_in_scene);
- ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "viewport_path", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "Viewport", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NODE_PATH_FROM_SCENE_ROOT), "set_viewport_path_in_scene", "get_viewport_path_in_scene");
+ ADD_PROPERTY(PropertyInfo(Variant::NODE_PATH, "viewport_path", PROPERTY_HINT_NODE_PATH_VALID_TYPES, "SubViewport", PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_NODE_PATH_FROM_SCENE_ROOT), "set_viewport_path_in_scene", "get_viewport_path_in_scene");
}
ViewportTexture::ViewportTexture() {
@@ -166,9 +168,9 @@ ViewportTexture::~ViewportTexture() {
/////////////////////////////////////
-class TooltipPanel : public PanelContainer {
+class TooltipPanel : public PopupPanel {
- GDCLASS(TooltipPanel, PanelContainer);
+ GDCLASS(TooltipPanel, PopupPanel);
public:
TooltipPanel(){};
@@ -184,39 +186,25 @@ public:
Viewport::GUI::GUI() {
+ embed_subwindows_hint = false;
+ embedding_subwindows = false;
+
dragging = false;
mouse_focus = NULL;
+ forced_mouse_focus = false;
mouse_click_grabber = NULL;
mouse_focus_mask = 0;
key_focus = NULL;
mouse_over = NULL;
+ drag_mouse_over = NULL;
tooltip = NULL;
tooltip_popup = NULL;
tooltip_label = NULL;
- subwindow_visibility_dirty = false;
- subwindow_order_dirty = false;
}
/////////////////////////////////////
-void Viewport::_update_stretch_transform() {
-
- if (size_override_stretch && size_override) {
-
- stretch_transform = Transform2D();
- Size2 scale = size / (size_override_size + size_override_margin * 2);
- stretch_transform.scale(scale);
- stretch_transform.elements[2] = size_override_margin * scale;
-
- } else {
-
- stretch_transform = Transform2D();
- }
-
- _update_global_transform();
-}
-
void Viewport::update_worlds() {
if (!is_inside_tree())
@@ -249,6 +237,191 @@ 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 (p_window->get_flag(Window::FLAG_NO_FOCUS)) {
+ //can only move to foreground, but no focus granted
+ 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();
+ return; //i guess not...
+ }
+
+ 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());
@@ -276,6 +449,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());
@@ -310,7 +485,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
@@ -371,6 +545,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: {
@@ -408,7 +583,7 @@ void Viewport::_notification(int p_what) {
VS::get_singleton()->multimesh_set_visible_instances(contact_3d_debug_multimesh, point_count);
}
- if (physics_object_picking && (to_screen_rect == Rect2() || Input::get_singleton()->get_mouse_mode() != Input::MOUSE_MODE_CAPTURED)) {
+ if (physics_object_picking && (to_screen_rect == Rect2i() || InputFilter::get_singleton()->get_mouse_mode() != InputFilter::MOUSE_MODE_CAPTURED)) {
#ifndef _3D_DISABLED
Vector2 last_pos(1e20, 1e20);
@@ -433,6 +608,7 @@ void Viewport::_notification(int p_what) {
if (!has_mouse_event) {
Ref<InputEventMouseMotion> mm;
mm.instance();
+
mm->set_device(InputEvent::DEVICE_ID_INTERNAL);
mm->set_global_position(physics_last_mousepos);
mm->set_position(physics_last_mousepos);
@@ -680,13 +856,12 @@ void Viewport::_notification(int p_what) {
}
} break;
- case SceneTree::NOTIFICATION_WM_MOUSE_EXIT:
- case SceneTree::NOTIFICATION_WM_FOCUS_OUT: {
+ case NOTIFICATION_WM_MOUSE_EXIT:
+ case NOTIFICATION_WM_FOCUS_OUT: {
_drop_physics_mouseover();
- if (gui.mouse_focus) {
- //if mouse is being pressed, send a release event
+ if (gui.mouse_focus && !gui.forced_mouse_focus) {
_drop_mouse_focus();
}
} break;
@@ -698,16 +873,6 @@ RID Viewport::get_viewport_rid() const {
return viewport;
}
-void Viewport::set_use_arvr(bool p_use_arvr) {
- arvr = p_use_arvr;
-
- VS::get_singleton()->viewport_set_use_arvr(viewport, arvr);
-}
-
-bool Viewport::use_arvr() {
- return arvr;
-}
-
void Viewport::update_canvas_items() {
if (!is_inside_tree())
return;
@@ -715,40 +880,52 @@ void Viewport::update_canvas_items() {
_update_canvas_items(this);
}
-void Viewport::set_size(const Size2 &p_size) {
+void Viewport::_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) {
- if (size == p_size.floor())
+ if (size == p_size && size_allocated == p_allocated && stretch_transform == p_stretch_transform && p_size_override == size_override && to_screen_rect != p_to_screen_rect)
return;
- size = p_size.floor();
- VS::get_singleton()->viewport_set_size(viewport, size.width, size.height);
+ size = p_size;
+ size_allocated = p_allocated;
+ size_override = p_size_override;
+ stretch_transform = p_stretch_transform;
+ to_screen_rect = p_to_screen_rect;
+
+ if (p_allocated) {
+ VS::get_singleton()->viewport_set_size(viewport, size.width, size.height);
+ } else {
+ VS::get_singleton()->viewport_set_size(viewport, 0, 0);
+ }
+ _update_global_transform();
- _update_stretch_transform();
+ update_canvas_items();
emit_signal("size_changed");
}
+Size2i Viewport::_get_size() const {
+ return size;
+}
+bool Viewport::_is_size_allocated() const {
+ return size_allocated;
+}
+
Rect2 Viewport::get_visible_rect() const {
Rect2 r;
if (size == Size2()) {
- r = Rect2(Point2(), OS::get_singleton()->get_window_size());
+ r = Rect2(Point2(), DisplayServer::get_singleton()->window_get_size());
} else {
r = Rect2(Point2(), size);
}
- if (size_override) {
- r.size = size_override_size;
+ if (size_override != Size2i()) {
+ r.size = size_override;
}
return r;
}
-Size2 Viewport::get_size() const {
-
- return size;
-}
-
void Viewport::_update_listener() {
/*
if (is_inside_tree() && audio_listener && (camera || listener) && (!get_parent() || (Object::cast_to<Control>(get_parent()) && Object::cast_to<Control>(get_parent())->is_visible_in_tree()))) {
@@ -943,7 +1120,9 @@ void Viewport::_camera_set(Camera *p_camera) {
if (camera) {
camera->notification(Camera::NOTIFICATION_LOST_CURRENT);
}
+
camera = p_camera;
+
if (!camera_override) {
if (camera)
VisualServer::get_singleton()->viewport_attach_camera(viewport, camera->get_camera());
@@ -1278,70 +1457,11 @@ void Viewport::_update_canvas_items(Node *p_node) {
}
}
-void Viewport::set_size_override(bool p_enable, const Size2 &p_size, const Vector2 &p_margin) {
-
- if (size_override == p_enable && p_size == size_override_size)
- return;
-
- size_override = p_enable;
- if (p_size.x >= 0 || p_size.y >= 0) {
- size_override_size = p_size;
- }
- size_override_margin = p_margin;
-
- _update_stretch_transform();
- emit_signal("size_changed");
-}
-
-Size2 Viewport::get_size_override() const {
-
- return size_override_size;
-}
-bool Viewport::is_size_override_enabled() const {
-
- return size_override;
-}
-void Viewport::set_size_override_stretch(bool p_enable) {
-
- if (p_enable == size_override_stretch)
- return;
-
- size_override_stretch = p_enable;
-
- _update_stretch_transform();
-}
-
-bool Viewport::is_size_override_stretch_enabled() const {
-
- return size_override_stretch;
-}
-
-void Viewport::set_update_mode(UpdateMode p_mode) {
-
- update_mode = p_mode;
- VS::get_singleton()->viewport_set_update_mode(viewport, VS::ViewportUpdateMode(p_mode));
-}
-Viewport::UpdateMode Viewport::get_update_mode() const {
-
- return update_mode;
-}
-
Ref<ViewportTexture> Viewport::get_texture() const {
return default_texture;
}
-void Viewport::set_clear_mode(ClearMode p_mode) {
-
- clear_mode = p_mode;
- VS::get_singleton()->viewport_set_clear_mode(viewport, VS::ViewportClearMode(p_mode));
-}
-
-Viewport::ClearMode Viewport::get_clear_mode() const {
-
- return clear_mode;
-}
-
void Viewport::set_shadow_atlas_size(int p_size) {
if (shadow_atlas_size == p_size)
@@ -1379,7 +1499,7 @@ Transform2D Viewport::_get_input_pre_xform() const {
Transform2D pre_xf;
- if (to_screen_rect != Rect2()) {
+ if (to_screen_rect.size.x != 0 && to_screen_rect.size.y != 0) {
pre_xf.elements[2] = -to_screen_rect.position;
pre_xf.scale(size / to_screen_rect.size);
@@ -1388,118 +1508,22 @@ 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);
-}
-
-void Viewport::_vp_input_text(const String &p_text) {
-
- if (gui.key_focus) {
- gui.key_focus->call("set_text", p_text);
- }
-}
-
-void Viewport::_vp_input(const Ref<InputEvent> &p_ev) {
-
- if (disable_input)
- return;
-
-#ifdef TOOLS_ENABLED
- if (Engine::get_singleton()->is_editor_hint() && get_tree()->get_edited_scene_root() && get_tree()->get_edited_scene_root()->is_a_parent_of(this)) {
- return;
- }
-#endif
-
- if (to_screen_rect == Rect2())
- return; //if render target, can't get input events
-
- //this one handles system input, p_ev are in system coordinates
- //they are converted to viewport coordinates
-
- Ref<InputEvent> ev = _make_input_local(p_ev);
- input(ev);
-}
-
-void Viewport::_vp_unhandled_input(const Ref<InputEvent> &p_ev) {
-
- if (disable_input)
- return;
-#ifdef TOOLS_ENABLED
- if (Engine::get_singleton()->is_editor_hint() && get_tree()->get_edited_scene_root() && get_tree()->get_edited_scene_root()->is_a_parent_of(this)) {
- return;
- }
-#endif
-
- /*
- if (parent_control && !parent_control->is_visible_in_tree())
- return;
- */
-
- if (to_screen_rect == Rect2())
- return; //if render target, can't get input events
-
- //this one handles system input, p_ev are in system coordinates
- //they are converted to viewport coordinates
-
- Ref<InputEvent> ev = _make_input_local(p_ev);
- unhandled_input(ev);
+ return ev->xformed_by(ai);
}
Vector2 Viewport::get_mouse_position() const {
- return (get_final_transform().affine_inverse() * _get_input_pre_xform()).xform(Input::get_singleton()->get_mouse_position() - _get_window_offset());
+ return gui.last_mouse_pos;
}
void Viewport::warp_mouse(const Vector2 &p_pos) {
Vector2 gpos = (get_final_transform().affine_inverse() * _get_input_pre_xform()).affine_inverse().xform(p_pos);
- Input::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>();
+ InputFilter::get_singleton()->warp_mouse_position(gpos);
}
void Viewport::_gui_sort_roots() {
@@ -1575,47 +1599,49 @@ void Viewport::_gui_show_tooltip() {
Control *rp = which;
- gui.tooltip_popup = which->make_custom_tooltip(tooltip);
-
- if (!gui.tooltip_popup) {
- gui.tooltip_popup = memnew(TooltipPanel);
+ Control *base_tooltip = which->make_custom_tooltip(tooltip);
+ if (!base_tooltip) {
gui.tooltip_label = memnew(TooltipLabel);
- gui.tooltip_popup->add_child(gui.tooltip_label);
-
- Ref<StyleBox> ttp = gui.tooltip_label->get_stylebox("panel", "TooltipPanel");
-
- gui.tooltip_label->set_anchor_and_margin(MARGIN_LEFT, Control::ANCHOR_BEGIN, ttp->get_margin(MARGIN_LEFT));
- gui.tooltip_label->set_anchor_and_margin(MARGIN_TOP, Control::ANCHOR_BEGIN, ttp->get_margin(MARGIN_TOP));
- gui.tooltip_label->set_anchor_and_margin(MARGIN_RIGHT, Control::ANCHOR_END, -ttp->get_margin(MARGIN_RIGHT));
- gui.tooltip_label->set_anchor_and_margin(MARGIN_BOTTOM, Control::ANCHOR_END, -ttp->get_margin(MARGIN_BOTTOM));
gui.tooltip_label->set_text(tooltip);
+ base_tooltip = gui.tooltip_label;
}
+ base_tooltip->set_anchors_and_margins_preset(Control::PRESET_WIDE);
+
+ TooltipPanel *panel = memnew(TooltipPanel);
+ panel->set_transient(false);
+ panel->set_flag(Window::FLAG_NO_FOCUS, true);
+ panel->set_wrap_controls(true);
+ panel->add_child(base_tooltip);
+
+ gui.tooltip_popup = panel;
+
rp->add_child(gui.tooltip_popup);
- gui.tooltip_popup->force_parent_owned();
- gui.tooltip_popup->set_as_toplevel(true);
- if (gui.tooltip) // Avoids crash when rapidly switching controls.
- gui.tooltip_popup->set_scale(gui.tooltip->get_global_transform().get_scale());
+
+ //if (gui.tooltip) // Avoids crash when rapidly switching controls.
+ // gui.tooltip_popup->set_scale(gui.tooltip->get_global_transform().get_scale());
Point2 tooltip_offset = ProjectSettings::get_singleton()->get("display/mouse_cursor/tooltip_position_offset");
- Rect2 r(gui.tooltip_pos + tooltip_offset, gui.tooltip_popup->get_minimum_size());
- Rect2 vr = gui.tooltip_popup->get_viewport_rect();
- if (r.size.x * gui.tooltip_popup->get_scale().x + r.position.x > vr.size.x)
- r.position.x = vr.size.x - r.size.x * gui.tooltip_popup->get_scale().x;
- else if (r.position.x < 0)
- r.position.x = 0;
-
- if (r.size.y * gui.tooltip_popup->get_scale().y + r.position.y > vr.size.y)
- r.position.y = vr.size.y - r.size.y * gui.tooltip_popup->get_scale().y;
- else if (r.position.y < 0)
- r.position.y = 0;
-
- gui.tooltip_popup->set_global_position(r.position);
+ Rect2 r(gui.tooltip_pos + tooltip_offset, gui.tooltip_popup->get_contents_minimum_size());
+
+ Rect2i vr = gui.tooltip_popup->get_parent_visible_window()->get_usable_parent_rect();
+
+ if (r.size.x + r.position.x > vr.size.x + vr.position.x)
+ r.position.x = vr.position.x + vr.size.x - r.size.x;
+ else if (r.position.x < vr.position.x)
+ r.position.x = vr.position.x;
+
+ if (r.size.y + r.position.y > vr.size.y + vr.position.y)
+ r.position.y = vr.position.y + vr.size.y - r.size.y;
+ else if (r.position.y < vr.position.y)
+ r.position.y = vr.position.y;
+
+ gui.tooltip_popup->set_position(r.position);
gui.tooltip_popup->set_size(r.size);
- gui.tooltip_popup->raise();
gui.tooltip_popup->show();
+ gui.tooltip_popup->child_controls_changed();
}
void Viewport::_gui_call_input(Control *p_control, const Ref<InputEvent> &p_input) {
@@ -1704,26 +1730,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()) {
@@ -1752,8 +1759,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
@@ -1770,9 +1775,6 @@ Control *Viewport::_gui_find_control_at_pos(CanvasItem *p_node, const Point2 &p_
for (int i = p_node->get_child_count() - 1; i >= 0; i--) {
- if (p_node == gui.tooltip_popup)
- continue;
-
CanvasItem *ci = Object::cast_to<CanvasItem>(p_node->get_child(i));
if (!ci || ci->is_set_as_toplevel())
continue;
@@ -1858,39 +1860,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;
@@ -1992,11 +1961,8 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
if (gui.drag_data.get_type() != Variant::NIL && mb->get_button_index() == BUTTON_LEFT) {
- if (gui.mouse_over) {
- Size2 pos = mpos;
- pos = gui.focus_inv_xform.xform(pos);
-
- _gui_drop(gui.mouse_over, pos, false);
+ if (gui.drag_mouse_over) {
+ _gui_drop(gui.drag_mouse_over, gui.drag_mouse_over_pos, false);
}
if (gui.drag_preview && mb->get_button_index() == BUTTON_LEFT) {
@@ -2006,6 +1972,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
gui.drag_data = Variant();
gui.dragging = false;
+ gui.drag_mouse_over = nullptr;
_propagate_viewport_notification(this, NOTIFICATION_DRAG_END);
//change mouse accordingly
}
@@ -2029,6 +1996,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
//disable mouse focus if needed before calling input, this makes popups on mouse press event work better, as the release will never be received otherwise
if (gui.mouse_focus_mask == 0) {
gui.mouse_focus = NULL;
+ gui.forced_mouse_focus = false;
}
if (mouse_focus && mouse_focus->can_process()) {
@@ -2074,6 +2042,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
if (gui.drag_data.get_type() != Variant::NIL) {
gui.mouse_focus = NULL;
+ gui.forced_mouse_focus = false;
gui.mouse_focus_mask = 0;
break;
} else {
@@ -2113,45 +2082,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)) {
-
- PopupMenu *popup_menu = Object::cast_to<PopupMenu>(top);
- MenuButton *popup_menu_parent = NULL;
- MenuButton *menu_button = Object::cast_to<MenuButton>(over);
-
- if (popup_menu) {
- popup_menu_parent = Object::cast_to<MenuButton>(popup_menu->get_parent());
- if (!popup_menu_parent) {
- // Go through the parents to see if there's a MenuButton at the end.
- while (Object::cast_to<PopupMenu>(popup_menu->get_parent())) {
- popup_menu = Object::cast_to<PopupMenu>(popup_menu->get_parent());
- }
- popup_menu_parent = Object::cast_to<MenuButton>(popup_menu->get_parent());
- }
- }
-
- // If the mouse is over a menu button, this menu will open automatically
- // if there is already a pop-up menu open at the same hierarchical level.
- if (popup_menu_parent && menu_button && popup_menu_parent->is_switch_on_hover() &&
- !menu_button->is_disabled() && menu_button->is_switch_on_hover() &&
- (popup_menu_parent->get_parent()->is_a_parent_of(menu_button) ||
- menu_button->get_parent()->is_a_parent_of(popup_menu))) {
-
- popup_menu->notification(Control::NOTIFICATION_MODAL_CLOSE);
- popup_menu->_modal_stack_remove();
- popup_menu->hide();
-
- menu_button->pressed();
- } else {
- over = NULL; //nothing can be found outside the modal stack
- }
- }
- }
-
if (over != gui.mouse_over) {
if (gui.mouse_over) {
@@ -2167,103 +2097,195 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
gui.mouse_over = over;
- if (gui.drag_preview) {
- gui.drag_preview->set_position(mpos);
- }
+ DisplayServer::CursorShape ds_cursor_shape = (DisplayServer::CursorShape)InputFilter::get_singleton()->get_default_cursor_shape();
- if (!over) {
- OS::get_singleton()->set_cursor_shape((OS::CursorShape)Input::get_singleton()->get_default_cursor_shape());
- return;
- }
+ if (over) {
- Transform2D localizer = over->get_global_transform_with_canvas().affine_inverse();
- Size2 pos = localizer.xform(mpos);
- Vector2 speed = localizer.basis_xform(mm->get_speed());
- Vector2 rel = localizer.basis_xform(mm->get_relative());
+ Transform2D localizer = over->get_global_transform_with_canvas().affine_inverse();
+ Size2 pos = localizer.xform(mpos);
+ Vector2 speed = localizer.basis_xform(mm->get_speed());
+ Vector2 rel = localizer.basis_xform(mm->get_relative());
- mm = mm->xformed_by(Transform2D()); //make a copy
+ mm = mm->xformed_by(Transform2D()); //make a copy
- mm->set_global_position(mpos);
- mm->set_speed(speed);
- mm->set_relative(rel);
+ mm->set_global_position(mpos);
+ mm->set_speed(speed);
+ mm->set_relative(rel);
- if (mm->get_button_mask() == 0) {
- //nothing pressed
+ if (mm->get_button_mask() == 0) {
+ //nothing pressed
- bool can_tooltip = true;
+ 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) {
+ if (can_tooltip && gui.tooltip) {
+ String tooltip = _gui_get_tooltip(over, gui.tooltip->get_global_transform().xform_inv(mpos));
- bool is_tooltip_shown = false;
+ if (tooltip.length() == 0)
+ _gui_cancel_tooltip();
+ else if (gui.tooltip_label) {
+ if (tooltip == gui.tooltip_label->get_text()) {
+ is_tooltip_shown = true;
+ }
+ } else {
- if (gui.tooltip_popup) {
- if (can_tooltip && gui.tooltip) {
- String tooltip = _gui_get_tooltip(over, gui.tooltip->get_global_transform().xform_inv(mpos));
+ Variant t = gui.tooltip_popup->call("get_tooltip_text");
- if (tooltip.length() == 0)
- _gui_cancel_tooltip();
- else if (gui.tooltip_label) {
- if (tooltip == gui.tooltip_label->get_text()) {
- is_tooltip_shown = true;
+ if (t.get_type() == Variant::STRING) {
+ if (tooltip == String(t)) {
+ is_tooltip_shown = true;
+ }
+ } else {
+ is_tooltip_shown = true; //well, nothing to compare against, likely using custom control, so if it changes there is nothing we can do
+ }
}
- } else if (tooltip == String(gui.tooltip_popup->call("get_tooltip_text"))) {
- is_tooltip_shown = true;
- }
- } else
- _gui_cancel_tooltip();
+ } else
+ _gui_cancel_tooltip();
+ }
+
+ if (can_tooltip && !is_tooltip_shown) {
+
+ gui.tooltip = over;
+ gui.tooltip_pos = over->get_screen_transform().xform(pos); //(parent_xform * get_transform()).affine_inverse().xform(pos);
+ gui.tooltip_timer = gui.tooltip_delay;
+ }
}
- if (can_tooltip && !is_tooltip_shown) {
+ //pos = gui.focus_inv_xform.xform(pos);
- gui.tooltip = over;
- gui.tooltip_pos = mpos; //(parent_xform * get_transform()).affine_inverse().xform(pos);
- gui.tooltip_timer = gui.tooltip_delay;
+ mm->set_position(pos);
+
+ Control::CursorShape cursor_shape = Control::CURSOR_ARROW;
+ {
+ Control *c = over;
+ Vector2 cpos = pos;
+ while (c) {
+ cursor_shape = c->get_cursor_shape(cpos);
+ cpos = c->get_transform().xform(cpos);
+ if (cursor_shape != Control::CURSOR_ARROW)
+ break;
+ if (c->data.mouse_filter == Control::MOUSE_FILTER_STOP)
+ break;
+ if (c->is_set_as_toplevel())
+ break;
+ c = c->get_parent_control();
+ }
}
+
+ ds_cursor_shape = (DisplayServer::CursorShape)cursor_shape;
+
+ if (over && over->can_process()) {
+ _gui_call_input(over, mm);
+ }
+
+ set_input_as_handled();
}
- //pos = gui.focus_inv_xform.xform(pos);
+ if (gui.drag_data.get_type() != Variant::NIL) {
+ //handle dragandrop
- mm->set_position(pos);
+ if (gui.drag_preview) {
+ gui.drag_preview->set_position(mpos);
+ }
- Control::CursorShape cursor_shape = Control::CURSOR_ARROW;
- {
- Control *c = over;
- Vector2 cpos = pos;
- while (c) {
- cursor_shape = c->get_cursor_shape(cpos);
- cpos = c->get_transform().xform(cpos);
- if (cursor_shape != Control::CURSOR_ARROW)
- break;
- if (c->data.mouse_filter == Control::MOUSE_FILTER_STOP)
- break;
- if (c->is_set_as_toplevel())
- break;
- c = c->get_parent_control();
+ gui.drag_mouse_over = over;
+ gui.drag_mouse_over_pos = Vector2();
+
+ //find the window this is above of
+
+ //see if there is an embedder
+ Viewport *embedder = nullptr;
+ Vector2 viewport_pos;
+
+ if (is_embedding_subwindows()) {
+ embedder = this;
+ viewport_pos = mpos;
+ } else {
+ //not an embeder, but may be a subwindow of an embedder
+ Window *w = Object::cast_to<Window>(this);
+ if (w) {
+ if (w->is_embedded()) {
+ embedder = w->_get_embedder();
+
+ Transform2D ai = (get_final_transform().affine_inverse() * _get_input_pre_xform()).affine_inverse();
+
+ viewport_pos = ai.xform(mpos) + w->get_position(); //to parent coords
+ }
+ }
}
- }
- OS::get_singleton()->set_cursor_shape((OS::CursorShape)cursor_shape);
+ Viewport *viewport_under = nullptr;
- if (over && over->can_process()) {
- _gui_call_input(over, mm);
- }
+ if (embedder) {
+ //use embedder logic
- set_input_as_handled();
+ for (int i = embedder->gui.sub_windows.size() - 1; i >= 0; i--) {
+ Window *sw = embedder->gui.sub_windows[i].window;
+ Rect2 swrect = Rect2i(sw->get_position(), sw->get_size());
+ if (!sw->get_flag(Window::FLAG_BORDERLESS)) {
+ int title_height = sw->get_theme_constant("title_height");
+ swrect.position.y -= title_height;
+ swrect.size.y += title_height;
+ }
- if (gui.drag_data.get_type() != Variant::NIL && mm->get_button_mask() & BUTTON_MASK_LEFT) {
+ if (swrect.has_point(viewport_pos)) {
+ viewport_under = sw;
+ viewport_pos -= sw->get_position();
+ }
+ }
- bool can_drop = _gui_drop(over, pos, true);
+ if (!viewport_under) {
+ //not in a subwindow, likely in embedder
+ viewport_under = embedder;
+ }
+ } else {
+ //use displayserver logic
+ Vector2i screen_mouse_pos = DisplayServer::get_singleton()->mouse_get_position();
+
+ DisplayServer::WindowID window_id = DisplayServer::get_singleton()->get_window_at_screen_position(screen_mouse_pos);
+
+ if (window_id != DisplayServer::INVALID_WINDOW_ID) {
+ ObjectID object_under = DisplayServer::get_singleton()->window_get_attached_instance_id(window_id);
+
+ if (object_under != ObjectID()) { //fetch window
+ Window *w = Object::cast_to<Window>(ObjectDB::get_instance(object_under));
+ if (w) {
+ viewport_under = w;
+ viewport_pos = screen_mouse_pos - w->get_position();
+ }
+ }
+ }
+ }
+
+ if (viewport_under) {
+ Transform2D ai = (viewport_under->get_final_transform().affine_inverse() * viewport_under->_get_input_pre_xform());
+ viewport_pos = ai.xform(viewport_pos);
+ //find control under at pos
+ gui.drag_mouse_over = viewport_under->_gui_find_control(viewport_pos);
+ if (gui.drag_mouse_over) {
+ Transform2D localizer = gui.drag_mouse_over->get_global_transform_with_canvas().affine_inverse();
+ gui.drag_mouse_over_pos = localizer.xform(viewport_pos);
+
+ if (mm->get_button_mask() & BUTTON_MASK_LEFT) {
+
+ bool can_drop = _gui_drop(gui.drag_mouse_over, gui.drag_mouse_over_pos, true);
+
+ if (!can_drop) {
+ ds_cursor_shape = DisplayServer::CURSOR_FORBIDDEN;
+ } else {
+ ds_cursor_shape = DisplayServer::CURSOR_CAN_DROP;
+ }
+ }
+ }
- if (!can_drop) {
- OS::get_singleton()->set_cursor_shape(OS::CURSOR_FORBIDDEN);
} else {
- OS::get_singleton()->set_cursor_shape(OS::CURSOR_CAN_DROP);
+ gui.drag_mouse_over = nullptr;
}
- //change mouse accordingly i guess
}
+
+ DisplayServer::get_singleton()->cursor_set_shape(ds_cursor_shape);
}
Ref<InputEventScreenTouch> touch_event = p_event;
@@ -2275,14 +2297,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
@@ -2348,14 +2362,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();
@@ -2399,21 +2405,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
@@ -2426,7 +2417,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
if (from && p_event->is_pressed()) {
Control *next = NULL;
- Input *input = Input::get_singleton();
+ InputFilter *input = InputFilter::get_singleton();
if (p_event->is_action_pressed("ui_focus_next") && input->is_action_just_pressed("ui_focus_next")) {
@@ -2472,61 +2463,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.");
@@ -2563,21 +2503,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) {
@@ -2605,6 +2530,8 @@ void Viewport::_gui_hid_control(Control *p_control) {
_gui_remove_focus();
if (gui.mouse_over == p_control)
gui.mouse_over = NULL;
+ if (gui.drag_mouse_over == p_control)
+ gui.drag_mouse_over = NULL;
if (gui.tooltip == p_control)
_gui_cancel_tooltip();
}
@@ -2613,6 +2540,7 @@ void Viewport::_gui_remove_control(Control *p_control) {
if (gui.mouse_focus == p_control) {
gui.mouse_focus = NULL;
+ gui.forced_mouse_focus = false;
gui.mouse_focus_mask = 0;
}
if (gui.last_mouse_focus == p_control) {
@@ -2622,11 +2550,10 @@ void Viewport::_gui_remove_control(Control *p_control) {
gui.key_focus = NULL;
if (gui.mouse_over == p_control)
gui.mouse_over = NULL;
+ if (gui.drag_mouse_over == p_control)
+ gui.drag_mouse_over = NULL;
if (gui.tooltip == p_control)
gui.tooltip = NULL;
- if (gui.tooltip_popup == p_control) {
- _gui_cancel_tooltip();
- }
}
void Viewport::_gui_remove_focus() {
@@ -2638,11 +2565,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;
@@ -2672,6 +2594,7 @@ void Viewport::_drop_mouse_focus() {
Control *c = gui.mouse_focus;
int mask = gui.mouse_focus_mask;
gui.mouse_focus = NULL;
+ gui.forced_mouse_focus = false;
gui.mouse_focus_mask = 0;
for (int i = 0; i < 3; i++) {
@@ -2714,22 +2637,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;
@@ -2798,44 +2705,390 @@ void Viewport::_post_gui_grab_click_focus() {
///////////////////////////////
-void Viewport::input(const Ref<InputEvent> &p_event) {
+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(sw.window, 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());
+ if (disable_input)
+ return;
+
+ if (Engine::get_singleton()->is_editor_hint() && get_tree()->get_edited_scene_root() && get_tree()->get_edited_scene_root()->is_a_parent_of(this)) {
+ return;
+ }
+
local_input_handled = false;
+ Ref<InputEvent> ev;
+ if (!p_local_coords) {
+ ev = _make_input_local(p_event);
+ } else {
+ 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", p_event); //not a bug, must happen before GUI, order is _input -> gui input -> _unhandled input
+ get_tree()->_call_input_pause(input_group, "_input", ev, this); //not a bug, must happen before GUI, order is _input -> gui input -> _unhandled input
}
if (!is_input_handled()) {
- _gui_input_event(p_event);
+ _gui_input_event(ev);
}
- //get_tree()->call_group(SceneTree::GROUP_CALL_REVERSE|SceneTree::GROUP_CALL_REALTIME|SceneTree::GROUP_CALL_MULIILEVEL,gui_input_group,"_gui_input",p_event); //special one for GUI, as controls use their own process check
+ //get_tree()->call_group(SceneTree::GROUP_CALL_REVERSE|SceneTree::GROUP_CALL_REALTIME|SceneTree::GROUP_CALL_MULIILEVEL,gui_input_group,"_gui_input",ev); //special one for GUI, as controls use their own process check
}
-void Viewport::unhandled_input(const Ref<InputEvent> &p_event) {
+void Viewport::unhandled_input(const Ref<InputEvent> &p_event, bool p_local_coords) {
ERR_FAIL_COND(!is_inside_tree());
- get_tree()->_call_input_pause(unhandled_input_group, "_unhandled_input", p_event);
+ if (disable_input)
+ return;
+
+ if (Engine::get_singleton()->is_editor_hint() && get_tree()->get_edited_scene_root() && get_tree()->get_edited_scene_root()->is_a_parent_of(this)) {
+ return;
+ }
+
+ Ref<InputEvent> ev;
+ if (!p_local_coords) {
+ ev = _make_input_local(p_event);
+ } else {
+ ev = p_event;
+ }
+
+ get_tree()->_call_input_pause(unhandled_input_group, "_unhandled_input", ev, this);
//call_group(GROUP_CALL_REVERSE|GROUP_CALL_REALTIME|GROUP_CALL_MULIILEVEL,"unhandled_input","_unhandled_input",ev);
- if (!get_tree()->input_handled && Object::cast_to<InputEventKey>(*p_event) != NULL) {
- get_tree()->_call_input_pause(unhandled_key_input_group, "_unhandled_key_input", p_event);
+ if (!is_input_handled() && Object::cast_to<InputEventKey>(*ev) != NULL) {
+ get_tree()->_call_input_pause(unhandled_key_input_group, "_unhandled_key_input", ev, this);
//call_group(GROUP_CALL_REVERSE|GROUP_CALL_REALTIME|GROUP_CALL_MULIILEVEL,"unhandled_key_input","_unhandled_key_input",ev);
}
- if (physics_object_picking && !get_tree()->input_handled) {
+ if (physics_object_picking && !is_input_handled()) {
- if (Input::get_singleton()->get_mouse_mode() != Input::MOUSE_MODE_CAPTURED &&
- (Object::cast_to<InputEventMouseButton>(*p_event) ||
- Object::cast_to<InputEventMouseMotion>(*p_event) ||
- Object::cast_to<InputEventScreenDrag>(*p_event) ||
- Object::cast_to<InputEventScreenTouch>(*p_event) ||
- Object::cast_to<InputEventKey>(*p_event) //to remember state
+ if (InputFilter::get_singleton()->get_mouse_mode() != InputFilter::MOUSE_MODE_CAPTURED &&
+ (Object::cast_to<InputEventMouseButton>(*ev) ||
+ Object::cast_to<InputEventMouseMotion>(*ev) ||
+ Object::cast_to<InputEventScreenDrag>(*ev) ||
+ Object::cast_to<InputEventScreenTouch>(*ev) ||
+ Object::cast_to<InputEventKey>(*ev) //to remember state
)) {
- physics_picking_events.push_back(p_event);
+ physics_picking_events.push_back(ev);
}
}
}
@@ -2877,30 +3130,6 @@ bool Viewport::is_using_own_world() const {
return own_world.is_valid();
}
-void Viewport::set_attach_to_screen_rect(const Rect2 &p_rect) {
-
- VS::get_singleton()->viewport_attach_to_screen(viewport, p_rect);
- to_screen_rect = p_rect;
-}
-
-Rect2 Viewport::get_attach_to_screen_rect() const {
-
- return to_screen_rect;
-}
-
-void Viewport::set_use_render_direct_to_screen(bool p_render_direct_to_screen) {
-
- if (p_render_direct_to_screen == render_direct_to_screen)
- return;
-
- render_direct_to_screen = p_render_direct_to_screen;
- VS::get_singleton()->viewport_set_render_direct_to_screen(viewport, p_render_direct_to_screen);
-}
-
-bool Viewport::is_using_render_direct_to_screen() const {
- return render_direct_to_screen;
-}
-
void Viewport::set_physics_object_picking(bool p_enable) {
physics_object_picking = p_enable;
@@ -2925,11 +3154,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;
}
@@ -2943,10 +3167,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) {
@@ -3017,7 +3237,17 @@ void Viewport::set_input_as_handled() {
local_input_handled = true;
} else {
ERR_FAIL_COND(!is_inside_tree());
- get_tree()->set_input_as_handled();
+ Viewport *vp = this;
+ while (true) {
+ if (Object::cast_to<Window>(vp)) {
+ break;
+ }
+ if (!vp->get_parent()) {
+ break;
+ }
+ vp = vp->get_parent()->get_viewport();
+ }
+ vp->set_input_as_handled();
}
}
@@ -3025,8 +3255,17 @@ bool Viewport::is_input_handled() const {
if (handle_input_locally) {
return local_input_handled;
} else {
- ERR_FAIL_COND_V(!is_inside_tree(), false);
- return get_tree()->is_input_handled();
+ const Viewport *vp = this;
+ while (true) {
+ if (Object::cast_to<Window>(vp)) {
+ break;
+ }
+ if (!vp->get_parent()) {
+ break;
+ }
+ vp = vp->get_parent()->get_viewport();
+ }
+ return vp->is_input_handled();
}
}
@@ -3086,13 +3325,47 @@ void Viewport::_propagate_update_default_repeat(Node *p_node) {
}
}
-void Viewport::_bind_methods() {
+DisplayServer::WindowID Viewport::get_window_id() const {
+ return DisplayServer::MAIN_WINDOW_ID;
+}
- ClassDB::bind_method(D_METHOD("set_use_arvr", "use"), &Viewport::set_use_arvr);
- ClassDB::bind_method(D_METHOD("use_arvr"), &Viewport::use_arvr);
+Viewport *Viewport::get_parent_viewport() const {
+ ERR_FAIL_COND_V(!is_inside_tree(), nullptr);
+ if (!get_parent()) {
+ return nullptr; //root viewport
+ }
+
+ return get_parent()->get_viewport();
+}
+
+void Viewport::set_embed_subwindows_hint(bool p_embed) {
+ gui.embed_subwindows_hint = p_embed;
+}
+bool Viewport::get_embed_subwindows_hint() const {
+ return gui.embed_subwindows_hint;
+}
+bool Viewport::is_embedding_subwindows() const {
+ return gui.embed_subwindows_hint;
+}
+
+void Viewport::pass_mouse_focus_to(Viewport *p_viewport, Control *p_control) {
+ ERR_FAIL_NULL(p_viewport);
+ ERR_FAIL_NULL(p_control);
+
+ if (gui.mouse_focus) {
+ p_viewport->gui.mouse_focus = p_control;
+ p_viewport->gui.mouse_focus_mask = gui.mouse_focus_mask;
+ p_viewport->gui.key_focus = p_control;
+ p_viewport->gui.forced_mouse_focus = true;
+
+ gui.mouse_focus = nullptr;
+ gui.forced_mouse_focus = false;
+ gui.mouse_focus_mask = 0;
+ }
+}
+
+void Viewport::_bind_methods() {
- ClassDB::bind_method(D_METHOD("set_size", "size"), &Viewport::set_size);
- ClassDB::bind_method(D_METHOD("get_size"), &Viewport::get_size);
ClassDB::bind_method(D_METHOD("set_world_2d", "world_2d"), &Viewport::set_world_2d);
ClassDB::bind_method(D_METHOD("get_world_2d"), &Viewport::get_world_2d);
ClassDB::bind_method(D_METHOD("find_world_2d"), &Viewport::find_world_2d);
@@ -3111,22 +3384,6 @@ void Viewport::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_transparent_background", "enable"), &Viewport::set_transparent_background);
ClassDB::bind_method(D_METHOD("has_transparent_background"), &Viewport::has_transparent_background);
- ClassDB::bind_method(D_METHOD("_vp_input"), &Viewport::_vp_input);
- ClassDB::bind_method(D_METHOD("_vp_input_text", "text"), &Viewport::_vp_input_text);
- ClassDB::bind_method(D_METHOD("_vp_unhandled_input"), &Viewport::_vp_unhandled_input);
-
- ClassDB::bind_method(D_METHOD("set_size_override", "enable", "size", "margin"), &Viewport::set_size_override, DEFVAL(Size2(-1, -1)), DEFVAL(Size2(0, 0)));
- ClassDB::bind_method(D_METHOD("get_size_override"), &Viewport::get_size_override);
- ClassDB::bind_method(D_METHOD("is_size_override_enabled"), &Viewport::is_size_override_enabled);
- ClassDB::bind_method(D_METHOD("set_size_override_stretch", "enabled"), &Viewport::set_size_override_stretch);
- ClassDB::bind_method(D_METHOD("is_size_override_stretch_enabled"), &Viewport::is_size_override_stretch_enabled);
-
- ClassDB::bind_method(D_METHOD("set_clear_mode", "mode"), &Viewport::set_clear_mode);
- ClassDB::bind_method(D_METHOD("get_clear_mode"), &Viewport::get_clear_mode);
-
- ClassDB::bind_method(D_METHOD("set_update_mode", "mode"), &Viewport::set_update_mode);
- ClassDB::bind_method(D_METHOD("get_update_mode"), &Viewport::get_update_mode);
-
ClassDB::bind_method(D_METHOD("set_msaa", "msaa"), &Viewport::set_msaa);
ClassDB::bind_method(D_METHOD("get_msaa"), &Viewport::get_msaa);
@@ -3141,8 +3398,9 @@ void Viewport::_bind_methods() {
ClassDB::bind_method(D_METHOD("get_physics_object_picking"), &Viewport::get_physics_object_picking);
ClassDB::bind_method(D_METHOD("get_viewport_rid"), &Viewport::get_viewport_rid);
- ClassDB::bind_method(D_METHOD("input", "local_event"), &Viewport::input);
- ClassDB::bind_method(D_METHOD("unhandled_input", "local_event"), &Viewport::unhandled_input);
+ ClassDB::bind_method(D_METHOD("input_text", "text"), &Viewport::input_text);
+ ClassDB::bind_method(D_METHOD("input", "event", "in_local_coords"), &Viewport::input, DEFVAL(false));
+ ClassDB::bind_method(D_METHOD("unhandled_input", "event", "in_local_coords"), &Viewport::unhandled_input, DEFVAL(false));
ClassDB::bind_method(D_METHOD("update_worlds"), &Viewport::update_worlds);
@@ -3156,19 +3414,13 @@ void Viewport::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_as_audio_listener_2d", "enable"), &Viewport::set_as_audio_listener_2d);
ClassDB::bind_method(D_METHOD("is_audio_listener_2d"), &Viewport::is_audio_listener_2d);
- ClassDB::bind_method(D_METHOD("set_attach_to_screen_rect", "rect"), &Viewport::set_attach_to_screen_rect);
- ClassDB::bind_method(D_METHOD("set_use_render_direct_to_screen", "enable"), &Viewport::set_use_render_direct_to_screen);
- ClassDB::bind_method(D_METHOD("is_using_render_direct_to_screen"), &Viewport::is_using_render_direct_to_screen);
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);
@@ -3194,13 +3446,13 @@ void Viewport::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_default_canvas_item_texture_filter", "mode"), &Viewport::set_default_canvas_item_texture_filter);
ClassDB::bind_method(D_METHOD("get_default_canvas_item_texture_filter"), &Viewport::get_default_canvas_item_texture_filter);
+ ClassDB::bind_method(D_METHOD("set_embed_subwindows_hint", "enable"), &Viewport::set_embed_subwindows_hint);
+ ClassDB::bind_method(D_METHOD("get_embed_subwindows_hint"), &Viewport::get_embed_subwindows_hint);
+ ClassDB::bind_method(D_METHOD("is_embedding_subwindows"), &Viewport::is_embedding_subwindows);
+
ClassDB::bind_method(D_METHOD("set_default_canvas_item_texture_repeat", "mode"), &Viewport::set_default_canvas_item_texture_repeat);
ClassDB::bind_method(D_METHOD("get_default_canvas_item_texture_repeat"), &Viewport::get_default_canvas_item_texture_repeat);
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "arvr"), "set_use_arvr", "use_arvr");
-
- ADD_PROPERTY(PropertyInfo(Variant::VECTOR2, "size"), "set_size", "get_size");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "size_override_stretch"), "set_size_override_stretch", "is_size_override_stretch_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "own_world"), "set_use_own_world", "is_using_own_world");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "world", PROPERTY_HINT_RESOURCE_TYPE, "World"), "set_world", "get_world");
ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "world_2d", PROPERTY_HINT_RESOURCE_TYPE, "World2D", 0), "set_world_2d", "get_world_2d");
@@ -3208,11 +3460,7 @@ void Viewport::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "handle_input_locally"), "set_handle_input_locally", "is_handling_input_locally");
ADD_GROUP("Rendering", "");
ADD_PROPERTY(PropertyInfo(Variant::INT, "msaa", PROPERTY_HINT_ENUM, "Disabled,2x,4x,8x,16x,AndroidVR 2x,AndroidVR 4x"), "set_msaa", "get_msaa");
- ADD_PROPERTY(PropertyInfo(Variant::BOOL, "render_direct_to_screen"), "set_use_render_direct_to_screen", "is_using_render_direct_to_screen");
ADD_PROPERTY(PropertyInfo(Variant::INT, "debug_draw", PROPERTY_HINT_ENUM, "Disabled,Unshaded,Overdraw,Wireframe"), "set_debug_draw", "get_debug_draw");
- ADD_GROUP("Render Target", "render_target_");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "render_target_clear_mode", PROPERTY_HINT_ENUM, "Always,Never,Next Frame"), "set_clear_mode", "get_clear_mode");
- ADD_PROPERTY(PropertyInfo(Variant::INT, "render_target_update_mode", PROPERTY_HINT_ENUM, "Disabled,Once,When Visible,Always"), "set_update_mode", "get_update_mode");
ADD_GROUP("Canvas Items", "canvas_item_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "canvas_item_default_texture_filter", PROPERTY_HINT_ENUM, "Nearest,Linear,MipmapLinear,MipmapNearest"), "set_default_canvas_item_texture_filter", "get_default_canvas_item_texture_filter");
ADD_PROPERTY(PropertyInfo(Variant::INT, "canvas_item_default_texture_repeat", PROPERTY_HINT_ENUM, "Disabled,Enabled,Mirror"), "set_default_canvas_item_texture_repeat", "get_default_canvas_item_texture_repeat");
@@ -3224,6 +3472,7 @@ void Viewport::_bind_methods() {
ADD_GROUP("GUI", "gui_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gui_disable_input"), "set_disable_input", "is_input_disabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gui_snap_controls_to_pixels"), "set_snap_controls_to_pixels", "is_snap_controls_to_pixels_enabled");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "gui_embed_subwindows"), "set_embed_subwindows_hint", "get_embed_subwindows_hint");
ADD_GROUP("Shadow Atlas", "shadow_atlas_");
ADD_PROPERTY(PropertyInfo(Variant::INT, "shadow_atlas_size"), "set_shadow_atlas_size", "get_shadow_atlas_size");
ADD_PROPERTYI(PropertyInfo(Variant::INT, "shadow_atlas_quad_0", PROPERTY_HINT_ENUM, "Disabled,1 Shadow,4 Shadows,16 Shadows,64 Shadows,256 Shadows,1024 Shadows"), "set_shadow_atlas_quadrant_subdiv", "get_shadow_atlas_quadrant_subdiv", 0);
@@ -3236,11 +3485,6 @@ void Viewport::_bind_methods() {
ADD_SIGNAL(MethodInfo("size_changed"));
ADD_SIGNAL(MethodInfo("gui_focus_changed", PropertyInfo(Variant::OBJECT, "node", PROPERTY_HINT_RESOURCE_TYPE, "Control")));
- BIND_ENUM_CONSTANT(UPDATE_DISABLED);
- BIND_ENUM_CONSTANT(UPDATE_ONCE);
- BIND_ENUM_CONSTANT(UPDATE_WHEN_VISIBLE);
- BIND_ENUM_CONSTANT(UPDATE_ALWAYS);
-
BIND_ENUM_CONSTANT(SHADOW_ATLAS_QUADRANT_SUBDIV_DISABLED);
BIND_ENUM_CONSTANT(SHADOW_ATLAS_QUADRANT_SUBDIV_1);
BIND_ENUM_CONSTANT(SHADOW_ATLAS_QUADRANT_SUBDIV_4);
@@ -3277,10 +3521,6 @@ void Viewport::_bind_methods() {
BIND_ENUM_CONSTANT(MSAA_8X);
BIND_ENUM_CONSTANT(MSAA_16X);
- BIND_ENUM_CONSTANT(CLEAR_MODE_ALWAYS);
- BIND_ENUM_CONSTANT(CLEAR_MODE_NEVER);
- BIND_ENUM_CONSTANT(CLEAR_MODE_ONLY_NEXT_FRAME);
-
BIND_ENUM_CONSTANT(DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_NEAREST);
BIND_ENUM_CONSTANT(DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_LINEAR);
BIND_ENUM_CONSTANT(DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS);
@@ -3293,13 +3533,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));
@@ -3307,8 +3540,6 @@ Viewport::Viewport() {
viewport = VisualServer::get_singleton()->viewport_create();
texture_rid = VisualServer::get_singleton()->viewport_get_texture(viewport);
- render_direct_to_screen = false;
-
default_texture.instance();
default_texture->vp = const_cast<Viewport *>(this);
viewport_textures.insert(default_texture.ptr());
@@ -3324,14 +3555,10 @@ Viewport::Viewport() {
camera = NULL;
override_canvas_transform = false;
canvas_layers.insert(NULL); // This eases picking code (interpreted as the canvas of the Viewport)
- arvr = false;
- size_override = false;
- size_override_stretch = false;
- size_override_size = Size2(1, 1);
+
gen_mipmaps = false;
//clear=true;
- update_mode = UPDATE_WHEN_VISIBLE;
physics_object_picking = false;
physics_has_last_mousepos = false;
@@ -3368,12 +3595,14 @@ Viewport::Viewport() {
gui.canvas_sort_index = 0;
gui.roots_order_dirty = false;
gui.mouse_focus = NULL;
+ gui.forced_mouse_focus = false;
gui.last_mouse_focus = NULL;
+ gui.subwindow_focused = nullptr;
+ gui.subwindow_drag = SUB_WINDOW_DRAG_DISABLED;
msaa = MSAA_DISABLED;
debug_draw = DEBUG_DRAW_DISABLED;
- clear_mode = CLEAR_MODE_ALWAYS;
snap_controls_to_pixels = true;
physics_last_mouse_state.alt = false;
@@ -3384,6 +3613,8 @@ Viewport::Viewport() {
local_input_handled = false;
handle_input_locally = true;
+ size_allocated = false;
+
default_canvas_item_texture_filter = DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_LINEAR;
default_canvas_item_texture_repeat = DEFAULT_CANVAS_ITEM_TEXTURE_REPEAT_DISABLED;
}
@@ -3398,3 +3629,95 @@ Viewport::~Viewport() {
//SpatialSoundServer::get_singleton()->free(internal_listener);
//SpatialSound2DServer::get_singleton()->free(internal_listener_2d);
}
+
+/////////////////////////////////
+
+void SubViewport::set_use_arvr(bool p_use_arvr) {
+ arvr = p_use_arvr;
+
+ VS::get_singleton()->viewport_set_use_arvr(get_viewport_rid(), arvr);
+}
+
+bool SubViewport::is_using_arvr() {
+ return arvr;
+}
+
+void SubViewport::set_size(const Size2i &p_size) {
+ _set_size(p_size, Size2i(), Rect2i(), Transform2D(), true);
+}
+Size2i SubViewport::get_size() const {
+ return _get_size();
+}
+
+void SubViewport::set_update_mode(UpdateMode p_mode) {
+
+ update_mode = p_mode;
+ VS::get_singleton()->viewport_set_update_mode(get_viewport_rid(), VS::ViewportUpdateMode(p_mode));
+}
+SubViewport::UpdateMode SubViewport::get_update_mode() const {
+
+ return update_mode;
+}
+
+void SubViewport::set_clear_mode(ClearMode p_mode) {
+
+ clear_mode = p_mode;
+ VS::get_singleton()->viewport_set_clear_mode(get_viewport_rid(), VS::ViewportClearMode(p_mode));
+}
+
+SubViewport::ClearMode SubViewport::get_clear_mode() const {
+
+ return clear_mode;
+}
+
+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);
+
+ ClassDB::bind_method(D_METHOD("set_size", "size"), &SubViewport::set_size);
+ ClassDB::bind_method(D_METHOD("get_size"), &SubViewport::get_size);
+
+ ClassDB::bind_method(D_METHOD("set_update_mode", "mode"), &SubViewport::set_update_mode);
+ ClassDB::bind_method(D_METHOD("get_update_mode"), &SubViewport::get_update_mode);
+
+ ClassDB::bind_method(D_METHOD("set_clear_mode", "mode"), &SubViewport::set_clear_mode);
+ ClassDB::bind_method(D_METHOD("get_clear_mode"), &SubViewport::get_clear_mode);
+
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "arvr"), "set_use_arvr", "is_using_arvr");
+ ADD_GROUP("Render Target", "render_target_");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "render_target_clear_mode", PROPERTY_HINT_ENUM, "Always,Never,Next Frame"), "set_clear_mode", "get_clear_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "render_target_update_mode", PROPERTY_HINT_ENUM, "Disabled,Once,When Visible,Always"), "set_update_mode", "get_update_mode");
+
+ 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);
+ BIND_ENUM_CONSTANT(CLEAR_MODE_NEVER);
+ BIND_ENUM_CONSTANT(CLEAR_MODE_ONLY_NEXT_FRAME);
+}
+
+SubViewport::SubViewport() {
+ arvr = false;
+ update_mode = UPDATE_WHEN_VISIBLE;
+ clear_mode = CLEAR_MODE_ALWAYS;
+}
+
+SubViewport::~SubViewport() {
+}
diff --git a/scene/main/viewport.h b/scene/main/viewport.h
index e511ce1b17..6b68bc0c94 100644
--- a/scene/main/viewport.h
+++ b/scene/main/viewport.h
@@ -35,6 +35,7 @@
#include "scene/main/node.h"
#include "scene/resources/texture.h"
#include "scene/resources/world_2d.h"
+#include "servers/display_server.h"
#include "servers/visual_server.h"
class Camera;
@@ -88,13 +89,6 @@ class Viewport : public Node {
GDCLASS(Viewport, Node);
public:
- enum UpdateMode {
- UPDATE_DISABLED,
- UPDATE_ONCE, //then goes to disabled
- UPDATE_WHEN_VISIBLE, // default
- UPDATE_ALWAYS
- };
-
enum ShadowAtlasQuadrantSubdiv {
SHADOW_ATLAS_QUADRANT_SUBDIV_DISABLED,
SHADOW_ATLAS_QUADRANT_SUBDIV_1,
@@ -142,13 +136,6 @@ public:
DEBUG_DRAW_ROUGHNESS_LIMITER
};
- enum ClearMode {
-
- CLEAR_MODE_ALWAYS,
- CLEAR_MODE_NEVER,
- CLEAR_MODE_ONLY_NEXT_FRAME
- };
-
enum DefaultCanvasItemTextureFilter {
DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_NEAREST,
DEFAULT_CANVAS_ITEM_TEXTURE_FILTER_LINEAR,
@@ -164,6 +151,10 @@ public:
DEFAULT_CANVAS_ITEM_TEXTURE_REPEAT_MAX,
};
+ enum {
+ SUBWINDOW_CANVAS_LAYER = 1024
+ };
+
private:
friend class ViewportTexture;
@@ -172,8 +163,6 @@ private:
Listener *listener;
Set<Listener *> listeners;
- bool arvr;
-
struct CameraOverrideData {
Transform transform;
enum Projection {
@@ -198,6 +187,7 @@ private:
RID viewport;
RID current_canvas;
+ RID subwindow_canvas;
bool audio_listener;
RID internal_listener;
@@ -212,23 +202,17 @@ private:
Transform2D global_canvas_transform;
Transform2D stretch_transform;
- Size2 size;
- Rect2 to_screen_rect;
- bool render_direct_to_screen;
+ Size2i size;
+ Size2i size_override;
+ bool size_allocated;
RID contact_2d_debug;
RID contact_3d_debug_multimesh;
RID contact_3d_debug_instance;
- bool size_override;
- bool size_override_stretch;
- Size2 size_override_size;
- Size2 size_override_margin;
-
Rect2 last_vp_rect;
bool transparent_bg;
- ClearMode clear_mode;
bool filter;
bool gen_mipmaps;
@@ -264,6 +248,7 @@ private:
Ref<World> world;
Ref<World> own_world;
+ Rect2i to_screen_rect;
StringName input_group;
StringName gui_input_group;
StringName unhandled_input_group;
@@ -276,10 +261,8 @@ private:
void _propagate_exit_world(Node *p_node);
void _propagate_viewport_notification(Node *p_node, int p_what);
- void _update_stretch_transform();
void _update_global_transform();
- UpdateMode update_mode;
RID texture_rid;
DebugDraw debug_draw;
@@ -291,9 +274,35 @@ 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
+ bool forced_mouse_focus; //used for menu buttons
bool key_event_accepted;
Control *mouse_focus;
Control *last_mouse_focus;
@@ -301,8 +310,10 @@ private:
int mouse_focus_mask;
Control *key_focus;
Control *mouse_over;
+ Control *drag_mouse_over;
+ Vector2 drag_mouse_over_pos;
Control *tooltip;
- Control *tooltip_popup;
+ Window *tooltip_popup;
Label *tooltip_label;
Point2 tooltip_pos;
Point2 last_mouse_pos;
@@ -312,16 +323,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;
@@ -337,10 +356,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);
@@ -350,23 +366,13 @@ private:
_FORCE_INLINE_ Transform2D _get_input_pre_xform() const;
- void _vp_input(const Ref<InputEvent> &p_ev);
- void _vp_input_text(const String &p_text);
- void _vp_unhandled_input(const Ref<InputEvent> &p_ev);
Ref<InputEvent> _make_input_local(const Ref<InputEvent> &ev);
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();
@@ -378,9 +384,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);
@@ -391,8 +394,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;
@@ -418,9 +419,26 @@ 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);
+
+ Size2i _get_size() const;
+ bool _is_size_allocated() const;
+
void _notification(int p_what);
static void _bind_methods();
virtual void _validate_property(PropertyInfo &property) const;
@@ -438,19 +456,14 @@ public:
void set_camera_override_perspective(float p_fovy_degrees, float p_z_near, float p_z_far);
void set_camera_override_orthogonal(float p_size, float p_z_near, float p_z_far);
- void set_use_arvr(bool p_use_arvr);
- bool use_arvr();
-
void set_as_audio_listener(bool p_enable);
bool is_audio_listener() const;
void set_as_audio_listener_2d(bool p_enable);
bool is_audio_listener_2d() const;
- void set_size(const Size2 &p_size);
void update_canvas_items();
- Size2 get_size() const;
Rect2 get_visible_rect() const;
RID get_viewport_rid() const;
@@ -479,18 +492,6 @@ public:
void set_transparent_background(bool p_enable);
bool has_transparent_background() const;
- void set_size_override(bool p_enable, const Size2 &p_size = Size2(-1, -1), const Vector2 &p_margin = Vector2());
- Size2 get_size_override() const;
-
- bool is_size_override_enabled() const;
- void set_size_override_stretch(bool p_enable);
- bool is_size_override_stretch_enabled() const;
-
- void set_clear_mode(ClearMode p_mode);
- ClearMode get_clear_mode() const;
-
- void set_update_mode(UpdateMode p_mode);
- UpdateMode get_update_mode() const;
Ref<ViewportTexture> get_texture() const;
void set_shadow_atlas_size(int p_size);
@@ -508,28 +509,20 @@ public:
void set_use_own_world(bool p_world);
bool is_using_own_world() const;
- void input(const Ref<InputEvent> &p_event);
- void unhandled_input(const Ref<InputEvent> &p_event);
+ void input_text(const String &p_text);
+ void input(const Ref<InputEvent> &p_event, bool p_local_coords = false);
+ void unhandled_input(const Ref<InputEvent> &p_event, bool p_local_coords = false);
void set_disable_input(bool p_disable);
bool is_input_disabled() const;
- void set_attach_to_screen_rect(const Rect2 &p_rect);
- Rect2 get_attach_to_screen_rect() const;
-
- void set_use_render_direct_to_screen(bool p_render_direct_to_screen);
- bool is_using_render_direct_to_screen() const;
-
Vector2 get_mouse_position() const;
void warp_mouse(const Vector2 &p_pos);
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();
@@ -544,8 +537,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;
@@ -560,15 +551,71 @@ public:
void set_default_canvas_item_texture_repeat(DefaultCanvasItemTextureRepeat p_repeat);
DefaultCanvasItemTextureRepeat get_default_canvas_item_texture_repeat() const;
+ virtual DisplayServer::WindowID get_window_id() const = 0;
+
+ void set_embed_subwindows_hint(bool p_embed);
+ bool get_embed_subwindows_hint() const;
+ bool is_embedding_subwindows() const;
+
+ Viewport *get_parent_viewport() const;
+
+ void pass_mouse_focus_to(Viewport *p_viewport, Control *p_control);
+
Viewport();
~Viewport();
};
-VARIANT_ENUM_CAST(Viewport::UpdateMode);
+class SubViewport : public Viewport {
+
+ GDCLASS(SubViewport, Viewport);
+
+public:
+ enum ClearMode {
+
+ CLEAR_MODE_ALWAYS,
+ CLEAR_MODE_NEVER,
+ CLEAR_MODE_ONLY_NEXT_FRAME
+ };
+
+ enum UpdateMode {
+ UPDATE_DISABLED,
+ UPDATE_ONCE, //then goes to disabled
+ UPDATE_WHEN_VISIBLE, // default
+ UPDATE_WHEN_PARENT_VISIBLE,
+ UPDATE_ALWAYS
+ };
+
+private:
+ UpdateMode update_mode;
+ ClearMode clear_mode;
+ bool arvr;
+
+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);
+ Size2i get_size() const;
+
+ void set_use_arvr(bool p_use_arvr);
+ bool is_using_arvr();
+
+ void set_update_mode(UpdateMode p_mode);
+ UpdateMode get_update_mode() const;
+
+ void set_clear_mode(ClearMode p_mode);
+ ClearMode get_clear_mode() const;
+
+ SubViewport();
+ ~SubViewport();
+};
+VARIANT_ENUM_CAST(SubViewport::UpdateMode);
VARIANT_ENUM_CAST(Viewport::ShadowAtlasQuadrantSubdiv);
VARIANT_ENUM_CAST(Viewport::MSAA);
VARIANT_ENUM_CAST(Viewport::DebugDraw);
-VARIANT_ENUM_CAST(Viewport::ClearMode);
+VARIANT_ENUM_CAST(SubViewport::ClearMode);
VARIANT_ENUM_CAST(Viewport::RenderInfo);
VARIANT_ENUM_CAST(Viewport::DefaultCanvasItemTextureFilter);
VARIANT_ENUM_CAST(Viewport::DefaultCanvasItemTextureRepeat);
diff --git a/scene/main/window.cpp b/scene/main/window.cpp
new file mode 100644
index 0000000000..a2a49aea75
--- /dev/null
+++ b/scene/main/window.cpp
@@ -0,0 +1,1406 @@
+/*************************************************************************/
+/* window.cpp */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#include "window.h"
+
+#include "core/debugger/engine_debugger.h"
+#include "core/os/keyboard.h"
+#include "scene/gui/control.h"
+#include "scene/resources/dynamic_font.h"
+#include "scene/scene_string_names.h"
+
+void Window::set_title(const String &p_title) {
+ title = p_title;
+
+ 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;
+}
+
+void Window::set_current_screen(int p_screen) {
+ current_screen = p_screen;
+ if (window_id == DisplayServer::INVALID_WINDOW_ID)
+ return;
+ DisplayServer::get_singleton()->window_set_current_screen(p_screen, window_id);
+}
+int Window::get_current_screen() const {
+ if (window_id != DisplayServer::INVALID_WINDOW_ID) {
+ current_screen = DisplayServer::get_singleton()->window_get_current_screen(window_id);
+ }
+ return current_screen;
+}
+
+void Window::set_position(const Point2i &p_position) {
+
+ position = p_position;
+
+ 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 {
+ return position;
+}
+
+void Window::set_size(const Size2i &p_size) {
+ size = p_size;
+ _update_window_size();
+}
+Size2i Window::get_size() const {
+
+ return size;
+}
+
+Size2i Window::get_real_size() const {
+
+ if (window_id != DisplayServer::INVALID_WINDOW_ID) {
+ return DisplayServer::get_singleton()->window_get_real_size(window_id);
+ }
+ return size;
+}
+
+void Window::set_max_size(const Size2i &p_max_size) {
+ max_size = p_max_size;
+ if (window_id != DisplayServer::INVALID_WINDOW_ID) {
+ DisplayServer::get_singleton()->window_set_max_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;
+}
+
+void Window::set_min_size(const Size2i &p_min_size) {
+ min_size = p_min_size;
+ if (window_id != DisplayServer::INVALID_WINDOW_ID) {
+ DisplayServer::get_singleton()->window_set_min_size(min_size, window_id);
+ }
+ _update_window_size();
+}
+
+Size2i Window::get_min_size() const {
+ if (window_id != DisplayServer::INVALID_WINDOW_ID) {
+ min_size = DisplayServer::get_singleton()->window_get_min_size(window_id);
+ }
+ return min_size;
+}
+
+void Window::set_mode(Mode p_mode) {
+
+ mode = p_mode;
+
+ 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 {
+
+ if (window_id != DisplayServer::INVALID_WINDOW_ID) {
+ mode = (Mode)DisplayServer::get_singleton()->window_get_mode(window_id);
+ }
+ return mode;
+}
+
+void Window::set_flag(Flags p_flag, bool p_enabled) {
+ ERR_FAIL_INDEX(p_flag, FLAG_MAX);
+ flags[p_flag] = p_enabled;
+
+ 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 {
+ ERR_FAIL_INDEX_V(p_flag, FLAG_MAX, false);
+ if (window_id != DisplayServer::INVALID_WINDOW_ID) {
+ flags[p_flag] = DisplayServer::get_singleton()->window_get_flag(DisplayServer::WindowFlags(p_flag), window_id);
+ }
+ return flags[p_flag];
+}
+
+bool Window::is_maximize_allowed() const {
+ if (window_id != DisplayServer::INVALID_WINDOW_ID) {
+ return DisplayServer::get_singleton()->window_is_maximize_allowed(window_id);
+ }
+ return true;
+}
+
+void Window::request_attention() {
+ if (window_id != DisplayServer::INVALID_WINDOW_ID) {
+ DisplayServer::get_singleton()->window_request_attention(window_id);
+ }
+}
+void Window::move_to_foreground() {
+
+ 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);
+ }
+}
+
+bool Window::can_draw() const {
+ if (!is_inside_tree()) {
+ return false;
+ }
+ if (window_id != DisplayServer::INVALID_WINDOW_ID) {
+ return DisplayServer::get_singleton()->window_can_draw(window_id);
+ }
+
+ return visible;
+}
+
+void Window::set_ime_active(bool p_active) {
+ if (window_id != DisplayServer::INVALID_WINDOW_ID) {
+ DisplayServer::get_singleton()->window_set_ime_active(p_active, window_id);
+ }
+}
+void Window::set_ime_position(const Point2i &p_pos) {
+ if (window_id != DisplayServer::INVALID_WINDOW_ID) {
+ DisplayServer::get_singleton()->window_set_ime_position(p_pos, window_id);
+ }
+}
+
+bool Window::is_embedded() const {
+ ERR_FAIL_COND_V(!is_inside_tree(), false);
+
+ return _get_embedder() != nullptr;
+}
+
+void Window::_make_window() {
+ ERR_FAIL_COND(window_id != DisplayServer::INVALID_WINDOW_ID);
+
+ uint32_t f = 0;
+ for (int i = 0; i < FLAG_MAX; i++) {
+ if (flags[i]) {
+ 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);
+ DisplayServer::get_singleton()->window_set_max_size(max_size, window_id);
+ DisplayServer::get_singleton()->window_set_min_size(min_size, window_id);
+ DisplayServer::get_singleton()->window_set_title(title, window_id);
+ DisplayServer::get_singleton()->window_attach_instance_id(get_instance_id(), window_id);
+
+ _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);
+ }
+
+ for (Set<Window *>::Element *E = transient_children.front(); E; E = E->next()) {
+ if (E->get()->window_id != DisplayServer::INVALID_WINDOW_ID) {
+ 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() {
+
+ ERR_FAIL_COND(window_id == DisplayServer::INVALID_WINDOW_ID);
+ mode = (Mode)DisplayServer::get_singleton()->window_get_mode(window_id);
+ for (int i = 0; i < FLAG_MAX; i++) {
+ flags[i] = DisplayServer::get_singleton()->window_get_flag(DisplayServer::WindowFlags(i), window_id);
+ }
+}
+
+void Window::_clear_window() {
+ ERR_FAIL_COND(window_id == DisplayServer::INVALID_WINDOW_ID);
+
+ if (transient_parent && transient_parent->window_id != DisplayServer::INVALID_WINDOW_ID) {
+ DisplayServer::get_singleton()->window_set_transient(window_id, DisplayServer::INVALID_WINDOW_ID);
+ }
+
+ for (Set<Window *>::Element *E = transient_children.front(); E; E = E->next()) {
+ if (E->get()->window_id != DisplayServer::INVALID_WINDOW_ID) {
+ DisplayServer::get_singleton()->window_set_transient(E->get()->window_id, DisplayServer::INVALID_WINDOW_ID);
+ }
+ }
+
+ _update_from_window();
+
+ DisplayServer::get_singleton()->delete_sub_window(window_id);
+ window_id = DisplayServer::INVALID_WINDOW_ID;
+
+ _update_viewport_size();
+ VS::get_singleton()->viewport_set_update_mode(get_viewport_rid(), VS::VIEWPORT_UPDATE_DISABLED);
+}
+
+void Window::_rect_changed_callback(const Rect2i &p_callback) {
+
+ //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) {
+ p_node->notification(p_notification);
+ for (int i = 0; i < p_node->get_child_count(); i++) {
+ Node *child = p_node->get_child(i);
+ Window *window = Object::cast_to<Window>(child);
+ if (window) {
+ break;
+ }
+ _propagate_window_notification(child, p_notification);
+ }
+}
+
+void Window::_event_callback(DisplayServer::WindowEvent p_event) {
+
+ switch (p_event) {
+ case DisplayServer::WINDOW_EVENT_MOUSE_ENTER: {
+ _propagate_window_notification(this, NOTIFICATION_WM_MOUSE_ENTER);
+ emit_signal("mouse_entered");
+ } break;
+ case DisplayServer::WINDOW_EVENT_MOUSE_EXIT: {
+ _propagate_window_notification(this, NOTIFICATION_WM_MOUSE_EXIT);
+ emit_signal("mouse_exited");
+ } break;
+ case DisplayServer::WINDOW_EVENT_FOCUS_IN: {
+ focused = true;
+ _propagate_window_notification(this, NOTIFICATION_WM_FOCUS_IN);
+ emit_signal("focus_entered");
+
+ } break;
+ case DisplayServer::WINDOW_EVENT_FOCUS_OUT: {
+ focused = false;
+ _propagate_window_notification(this, NOTIFICATION_WM_FOCUS_OUT);
+ emit_signal("focus_exited");
+ } break;
+ case DisplayServer::WINDOW_EVENT_CLOSE_REQUEST: {
+ if (exclusive_child != nullptr) {
+ break; //has an exclusive child, can't get events until child is closed
+ }
+ _propagate_window_notification(this, NOTIFICATION_WM_CLOSE_REQUEST);
+ emit_signal("close_requested");
+ } break;
+ case DisplayServer::WINDOW_EVENT_GO_BACK_REQUEST: {
+ _propagate_window_notification(this, NOTIFICATION_WM_GO_BACK_REQUEST);
+ emit_signal("go_back_requested");
+ } break;
+ case DisplayServer::WINDOW_EVENT_DPI_CHANGE: {
+ _propagate_window_notification(this, NOTIFICATION_WM_DPI_CHANGE);
+ emit_signal("dpi_changed");
+ } break;
+ }
+}
+
+void Window::show() {
+ set_visible(true);
+}
+void Window::hide() {
+ set_visible(false);
+}
+
+void Window::set_visible(bool p_visible) {
+
+ if (visible == p_visible) {
+ return;
+ }
+
+ visible = p_visible;
+
+ if (!is_inside_tree()) {
+ return;
+ }
+
+ if (updating_child_controls) {
+ _update_child_controls();
+ }
+
+ ERR_FAIL_COND_MSG(get_parent() == nullptr, "Can't change visibility of main window.");
+
+ Viewport *embedder_vp = _get_embedder();
+
+ if (!embedder_vp) {
+ if (!p_visible && window_id != DisplayServer::INVALID_WINDOW_ID) {
+ _clear_window();
+ }
+ if (p_visible && window_id == DisplayServer::INVALID_WINDOW_ID) {
+ _make_window();
+ _update_window_callbacks();
+ }
+ } else {
+ 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) {
+ focused = false;
+ }
+ 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() {
+ if (transient_parent) {
+ if (transient_parent->window_id != DisplayServer::INVALID_WINDOW_ID && window_id != DisplayServer::INVALID_WINDOW_ID) {
+ DisplayServer::get_singleton()->window_set_transient(window_id, DisplayServer::INVALID_WINDOW_ID);
+ }
+ transient_parent->transient_children.erase(this);
+ if (transient_parent->exclusive_child == this) {
+ transient_parent->exclusive_child = nullptr;
+ }
+ transient_parent = nullptr;
+ }
+}
+
+void Window::_make_transient() {
+ if (!get_parent()) {
+ //main window, can't be transient
+ return;
+ }
+ //find transient parent
+ Viewport *vp = get_parent()->get_viewport();
+ Window *window = nullptr;
+ while (vp) {
+ window = Object::cast_to<Window>(vp);
+ if (window) {
+ break;
+ }
+ if (!vp->get_parent()) {
+ break;
+ }
+
+ vp = vp->get_parent()->get_viewport();
+ }
+
+ if (window) {
+ transient_parent = window;
+ window->transient_children.insert(this);
+ if (is_inside_tree() && is_visible() && exclusive) {
+ if (transient_parent->exclusive_child == nullptr) {
+ transient_parent->exclusive_child = this;
+ } else if (transient_parent->exclusive_child != this) {
+ ERR_PRINT("Making child transient exclusive, but parent has another exclusive child");
+ }
+ }
+ }
+
+ //see if we can make transient
+ if (transient_parent->window_id != DisplayServer::INVALID_WINDOW_ID && window_id != DisplayServer::INVALID_WINDOW_ID) {
+ DisplayServer::get_singleton()->window_set_transient(window_id, transient_parent->window_id);
+ }
+}
+
+void Window::set_transient(bool p_transient) {
+ if (transient == p_transient) {
+ return;
+ }
+
+ transient = p_transient;
+
+ if (!is_inside_tree()) {
+ return;
+ }
+
+ if (transient) {
+ _make_transient();
+ } else {
+ _clear_transient();
+ }
+}
+bool Window::is_transient() const {
+ return transient;
+}
+
+void Window::set_exclusive(bool p_exclusive) {
+
+ if (exclusive == p_exclusive) {
+ return;
+ }
+
+ exclusive = p_exclusive;
+
+ if (transient_parent) {
+ if (p_exclusive && is_inside_tree() && is_visible()) {
+ ERR_FAIL_COND_MSG(transient_parent->exclusive_child && transient_parent->exclusive_child != this, "Transient parent has another exclusive child.");
+ transient_parent->exclusive_child = this;
+ } else {
+ if (transient_parent->exclusive_child == this) {
+ transient_parent->exclusive_child = nullptr;
+ }
+ }
+ }
+}
+
+bool Window::is_exclusive() const {
+ return exclusive;
+}
+
+bool Window::is_visible() const {
+ return visible;
+}
+
+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;
+ Rect2i attach_to_screen_rect(Point2i(), size);
+ Transform2D stretch_transform;
+ float font_oversampling = 1.0;
+
+ if (content_scale_mode == CONTENT_SCALE_MODE_DISABLED || content_scale_size.x == 0 || content_scale_size.y == 0) {
+
+ stretch_transform = Transform2D();
+ final_size = size;
+
+ } else {
+
+ //actual screen video mode
+ Size2 video_mode = size;
+ Size2 desired_res = content_scale_size;
+
+ Size2 viewport_size;
+ Size2 screen_size;
+
+ float viewport_aspect = desired_res.aspect();
+ float video_mode_aspect = video_mode.aspect();
+
+ if (content_scale_aspect == CONTENT_SCALE_ASPECT_IGNORE || Math::is_equal_approx(viewport_aspect, video_mode_aspect)) {
+ //same aspect or ignore aspect
+ viewport_size = desired_res;
+ screen_size = video_mode;
+ } else if (viewport_aspect < video_mode_aspect) {
+ // screen ratio is smaller vertically
+
+ if (content_scale_aspect == CONTENT_SCALE_ASPECT_KEEP_HEIGHT || content_scale_aspect == CONTENT_SCALE_ASPECT_EXPAND) {
+
+ //will stretch horizontally
+ viewport_size.x = desired_res.y * video_mode_aspect;
+ viewport_size.y = desired_res.y;
+ screen_size = video_mode;
+
+ } else {
+ //will need black bars
+ viewport_size = desired_res;
+ screen_size.x = video_mode.y * viewport_aspect;
+ screen_size.y = video_mode.y;
+ }
+ } else {
+ //screen ratio is smaller horizontally
+ if (content_scale_aspect == CONTENT_SCALE_ASPECT_KEEP_WIDTH || content_scale_aspect == CONTENT_SCALE_ASPECT_EXPAND) {
+
+ //will stretch horizontally
+ viewport_size.x = desired_res.x;
+ viewport_size.y = desired_res.x / video_mode_aspect;
+ screen_size = video_mode;
+
+ } else {
+ //will need black bars
+ viewport_size = desired_res;
+ screen_size.x = video_mode.x;
+ screen_size.y = video_mode.x / viewport_aspect;
+ }
+ }
+
+ screen_size = screen_size.floor();
+ viewport_size = viewport_size.floor();
+
+ Size2 margin;
+ Size2 offset;
+ //black bars and margin
+ if (content_scale_aspect != CONTENT_SCALE_ASPECT_EXPAND && screen_size.x < video_mode.x) {
+ margin.x = Math::round((video_mode.x - screen_size.x) / 2.0);
+ //VisualServer::get_singleton()->black_bars_set_margins(margin.x, 0, margin.x, 0);
+ offset.x = Math::round(margin.x * viewport_size.y / screen_size.y);
+ } else if (content_scale_aspect != CONTENT_SCALE_ASPECT_EXPAND && screen_size.y < video_mode.y) {
+ margin.y = Math::round((video_mode.y - screen_size.y) / 2.0);
+ //VisualServer::get_singleton()->black_bars_set_margins(0, margin.y, 0, margin.y);
+ offset.y = Math::round(margin.y * viewport_size.x / screen_size.x);
+ } else {
+ //VisualServer::get_singleton()->black_bars_set_margins(0, 0, 0, 0);
+ }
+
+ switch (content_scale_mode) {
+ case CONTENT_SCALE_MODE_DISABLED: {
+ // Already handled above
+ //_update_font_oversampling(1.0);
+ } break;
+ case CONTENT_SCALE_MODE_OBJECTS: {
+
+ final_size = screen_size;
+ final_size_override = viewport_size;
+ attach_to_screen_rect = Rect2(margin, screen_size);
+ font_oversampling = screen_size.x / viewport_size.x;
+ } break;
+ case CONTENT_SCALE_MODE_PIXELS: {
+
+ final_size = viewport_size;
+ attach_to_screen_rect = Rect2(margin, screen_size);
+
+ } break;
+ }
+
+ Size2 scale = size / (Vector2(final_size) + margin * 2);
+ stretch_transform.scale(scale);
+ stretch_transform.elements[2] = margin * scale;
+ }
+
+ 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);
+
+ if (window_id != DisplayServer::INVALID_WINDOW_ID) {
+ VisualServer::get_singleton()->viewport_attach_to_screen(get_viewport_rid(), attach_to_screen_rect, window_id);
+ } else {
+ VisualServer::get_singleton()->viewport_attach_to_screen(get_viewport_rid(), Rect2i(), DisplayServer::INVALID_WINDOW_ID);
+ }
+
+ if (window_id == DisplayServer::MAIN_WINDOW_ID) {
+
+ if (!use_font_oversampling) {
+ font_oversampling = 1.0;
+ }
+ if (DynamicFontAtSize::font_oversampling != font_oversampling) {
+
+ DynamicFontAtSize::font_oversampling = font_oversampling;
+ DynamicFont::update_oversampling();
+ }
+ }
+
+ notification(NOTIFICATION_WM_SIZE_CHANGED);
+
+ if (embedder) {
+ embedder->_sub_window_update(this);
+ }
+}
+
+void Window::_update_window_callbacks() {
+ 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) {
+
+ bool embedded = false;
+ {
+
+ embedder = _get_embedder();
+
+ if (embedder) {
+ embedded = true;
+
+ if (!visible) {
+ embedder = nullptr; //not yet since not visible
+ }
+ }
+ }
+
+ if (embedded) {
+ //create as embedded
+ 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;
+ DisplayServer::get_singleton()->window_attach_instance_id(get_instance_id(), window_id);
+ _update_from_window();
+ //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) {
+ _make_window();
+ _update_window_callbacks();
+ }
+ }
+ }
+
+ if (transient) {
+ _make_transient();
+ }
+ if (visible) {
+ notification(NOTIFICATION_VISIBILITY_CHANGED);
+ emit_signal(SceneStringNames::get_singleton()->visibility_changed);
+ VS::get_singleton()->viewport_set_active(get_viewport_rid(), true);
+ }
+ }
+
+ if (p_what == NOTIFICATION_READY) {
+
+ if (wrap_controls) {
+ _update_child_controls();
+ }
+ }
+
+ if (p_what == NOTIFICATION_EXIT_TREE) {
+
+ if (transient) {
+ _clear_transient();
+ }
+
+ if (!is_embedded() && window_id != DisplayServer::INVALID_WINDOW_ID) {
+
+ 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 {
+
+ 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);
+ }
+}
+
+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_viewport_size();
+}
+
+Size2i Window::get_content_scale_size() const {
+ return content_scale_size;
+}
+
+void Window::set_content_scale_mode(ContentScaleMode p_mode) {
+ content_scale_mode = p_mode;
+ _update_viewport_size();
+}
+Window::ContentScaleMode Window::get_content_scale_mode() const {
+ return content_scale_mode;
+}
+
+void Window::set_content_scale_aspect(ContentScaleAspect p_aspect) {
+ content_scale_aspect = p_aspect;
+ _update_viewport_size();
+}
+Window::ContentScaleAspect Window::get_content_scale_aspect() const {
+ return content_scale_aspect;
+}
+
+void Window::set_use_font_oversampling(bool p_oversampling) {
+ if (is_inside_tree() && window_id != DisplayServer::MAIN_WINDOW_ID) {
+ ERR_FAIL_MSG("Only the root window can set and use font oversampling.");
+ }
+ use_font_oversampling = p_oversampling;
+ _update_viewport_size();
+}
+bool Window::is_using_font_oversampling() const {
+ return use_font_oversampling;
+}
+
+DisplayServer::WindowID Window::get_window_id() const {
+ return window_id;
+}
+
+void Window::set_wrap_controls(bool p_enable) {
+ wrap_controls = p_enable;
+ if (wrap_controls) {
+ child_controls_changed();
+ }
+}
+
+bool Window::is_wrapping_controls() const {
+ return wrap_controls;
+}
+
+Size2 Window::_get_contents_minimum_size() const {
+ Size2 max;
+
+ for (int i = 0; i < get_child_count(); i++) {
+ Control *c = Object::cast_to<Control>(get_child(i));
+ if (c) {
+ Point2i pos = c->get_position();
+ Size2i min = c->get_combined_minimum_size();
+
+ max.x = MAX(pos.x + min.x, max.x);
+ max.y = MAX(pos.y + min.y, max.y);
+ }
+ }
+
+ return max;
+}
+void Window::_update_child_controls() {
+
+ if (!updating_child_controls) {
+ return;
+ }
+
+ _update_window_size();
+
+ updating_child_controls = false;
+}
+void Window::child_controls_changed() {
+
+ if (!is_inside_tree() || !visible || updating_child_controls) {
+ return;
+ }
+
+ updating_child_controls = true;
+ call_deferred("_update_child_controls");
+}
+
+void Window::_window_input(const Ref<InputEvent> &p_ev) {
+ if (Engine::get_singleton()->is_editor_hint() && (Object::cast_to<InputEventJoypadButton>(p_ev.ptr()) || Object::cast_to<InputEventJoypadMotion>(*p_ev)))
+ return; //avoid joy input on editor
+
+ if (EngineDebugger::is_active()) {
+ //quit from game window using F8
+ Ref<InputEventKey> k = p_ev;
+ if (k.is_valid() && k->is_pressed() && !k->is_echo() && k->get_keycode() == KEY_F8) {
+ EngineDebugger::get_singleton()->send_message("request_quit", Array());
+ }
+ }
+
+ if (exclusive_child != nullptr) {
+ exclusive_child->grab_focus();
+
+ return; //has an exclusive child, can't get events until child is closed
+ }
+
+ emit_signal(SceneStringNames::get_singleton()->window_input, p_ev);
+ input(p_ev);
+ if (!is_input_handled()) {
+ unhandled_input(p_ev);
+ }
+}
+void Window::_window_input_text(const String &p_text) {
+ input_text(p_text);
+}
+void Window::_window_drop_files(const Vector<String> &p_files) {
+ emit_signal("files_dropped", p_files);
+}
+
+Viewport *Window::get_parent_viewport() const {
+
+ if (get_parent()) {
+ return get_parent()->get_viewport();
+ } else {
+ return nullptr;
+ }
+}
+
+Window *Window::get_parent_visible_window() const {
+
+ Viewport *vp = get_parent_viewport();
+ Window *window = nullptr;
+ while (vp) {
+ window = Object::cast_to<Window>(vp);
+ if (window && window->visible) {
+ break;
+ }
+ if (!vp->get_parent()) {
+ break;
+ }
+
+ vp = vp->get_parent()->get_viewport();
+ }
+ return window;
+}
+
+void Window::popup_on_parent(const Rect2i &p_parent_rect) {
+
+ ERR_FAIL_COND(!is_inside_tree());
+ ERR_FAIL_COND_MSG(window_id == DisplayServer::MAIN_WINDOW_ID, "Can't popup the main window.");
+
+ if (!is_embedded()) {
+ Window *window = get_parent_visible_window();
+
+ if (!window) {
+ popup(p_parent_rect);
+ } else {
+ popup(Rect2i(window->get_position() + p_parent_rect.position, p_parent_rect.size));
+ }
+ } else {
+ popup(p_parent_rect);
+ }
+}
+
+void Window::popup_centered_clamped(const Size2i &p_size, float p_fallback_ratio) {
+
+ ERR_FAIL_COND(!is_inside_tree());
+ ERR_FAIL_COND_MSG(window_id == DisplayServer::MAIN_WINDOW_ID, "Can't popup the main window.");
+
+ Rect2 parent_rect;
+
+ if (is_embedded()) {
+ parent_rect = get_parent_viewport()->get_visible_rect();
+ } else {
+ DisplayServer::WindowID parent_id = get_parent_visible_window()->get_window_id();
+ int parent_screen = DisplayServer::get_singleton()->window_get_current_screen(parent_id);
+ parent_rect.position = DisplayServer::get_singleton()->screen_get_position(parent_screen);
+ parent_rect.size = DisplayServer::get_singleton()->screen_get_size(parent_screen);
+ }
+
+ Vector2i size_ratio = parent_rect.size * p_fallback_ratio;
+
+ Rect2i popup_rect;
+ popup_rect.size = Vector2i(MIN(size_ratio.x, p_size.x), MIN(size_ratio.y, p_size.y));
+ popup_rect.position = (parent_rect.size - popup_rect.size) / 2;
+
+ popup(popup_rect);
+}
+
+void Window::popup_centered(const Size2i &p_minsize) {
+ ERR_FAIL_COND(!is_inside_tree());
+ ERR_FAIL_COND_MSG(window_id == DisplayServer::MAIN_WINDOW_ID, "Can't popup the main window.");
+
+ Rect2 parent_rect;
+
+ if (is_embedded()) {
+ parent_rect = get_parent_viewport()->get_visible_rect();
+ } else {
+ DisplayServer::WindowID parent_id = get_parent_visible_window()->get_window_id();
+ int parent_screen = DisplayServer::get_singleton()->window_get_current_screen(parent_id);
+ parent_rect.position = DisplayServer::get_singleton()->screen_get_position(parent_screen);
+ parent_rect.size = DisplayServer::get_singleton()->screen_get_size(parent_screen);
+ }
+
+ Rect2i popup_rect;
+ if (p_minsize == Size2i()) {
+ popup_rect.size = _get_contents_minimum_size();
+ } else {
+ popup_rect.size = p_minsize;
+ }
+ popup_rect.position = (parent_rect.size - popup_rect.size) / 2;
+
+ popup(popup_rect);
+}
+
+void Window::popup_centered_ratio(float p_ratio) {
+
+ ERR_FAIL_COND(!is_inside_tree());
+ ERR_FAIL_COND_MSG(window_id == DisplayServer::MAIN_WINDOW_ID, "Can't popup the main window.");
+
+ Rect2i parent_rect;
+
+ if (is_embedded()) {
+ parent_rect = get_parent_viewport()->get_visible_rect();
+ } else {
+ DisplayServer::WindowID parent_id = get_parent_visible_window()->get_window_id();
+ int parent_screen = DisplayServer::get_singleton()->window_get_current_screen(parent_id);
+ parent_rect.position = DisplayServer::get_singleton()->screen_get_position(parent_screen);
+ parent_rect.size = DisplayServer::get_singleton()->screen_get_size(parent_screen);
+ }
+
+ Rect2i popup_rect;
+ popup_rect.size = parent_rect.size * p_ratio;
+ popup_rect.position = (parent_rect.size - popup_rect.size) / 2;
+
+ popup(popup_rect);
+}
+
+void Window::popup(const Rect2i &p_screen_rect) {
+
+ emit_signal("about_to_popup");
+
+ if (p_screen_rect != Rect2i()) {
+ set_position(p_screen_rect.position);
+ set_size(p_screen_rect.size);
+ }
+
+ Rect2i adjust = _popup_adjust_rect();
+ if (adjust != Rect2i()) {
+ set_position(adjust.position);
+ set_size(adjust.size);
+ }
+
+ set_transient(true);
+ set_visible(true);
+ _post_popup();
+ notification(NOTIFICATION_POST_POPUP);
+}
+
+Size2 Window::get_contents_minimum_size() const {
+ return _get_contents_minimum_size();
+}
+
+void Window::grab_focus() {
+ 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);
+ }
+}
+
+bool Window::has_focus() const {
+ return focused;
+}
+
+Rect2i Window::get_usable_parent_rect() const {
+ ERR_FAIL_COND_V(!is_inside_tree(), Rect2());
+ Rect2i parent;
+ if (is_embedded()) {
+ parent = _get_embedder()->get_visible_rect();
+ } else {
+
+ const Window *w = is_visible() ? this : get_parent_visible_window();
+ //find a parent that can contain us
+ ERR_FAIL_COND_V(!w, Rect2());
+
+ parent = DisplayServer::get_singleton()->screen_get_usable_rect(DisplayServer::get_singleton()->window_get_current_screen(w->get_window_id()));
+ }
+ return parent;
+}
+
+void Window::add_child_notify(Node *p_child) {
+
+ Control *child_c = Object::cast_to<Control>(p_child);
+
+ if (child_c && child_c->data.theme.is_null() && (theme_owner || theme_owner_window)) {
+ Control::_propagate_theme_changed(child_c, theme_owner, theme_owner_window); //need to propagate here, since many controls may require setting up stuff
+ }
+
+ Window *child_w = Object::cast_to<Window>(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) {
+
+ Control *child_c = Object::cast_to<Control>(p_child);
+
+ if (child_c && (child_c->data.theme_owner || child_c->data.theme_owner_window) && child_c->data.theme.is_null()) {
+ Control::_propagate_theme_changed(child_c, NULL, NULL);
+ }
+
+ Window *child_w = Object::cast_to<Window>(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) {
+
+ if (theme == p_theme)
+ return;
+
+ theme = p_theme;
+
+ if (!p_theme.is_null()) {
+
+ theme_owner = nullptr;
+ theme_owner_window = this;
+ Control::_propagate_theme_changed(this, nullptr, this);
+ } else {
+
+ Control *parent_c = cast_to<Control>(get_parent());
+ if (parent_c && (parent_c->data.theme_owner || parent_c->data.theme_owner_window)) {
+ Control::_propagate_theme_changed(this, parent_c->data.theme_owner, parent_c->data.theme_owner_window);
+ } else {
+ Window *parent_w = cast_to<Window>(get_parent());
+ if (parent_w && (parent_w->theme_owner || parent_w->theme_owner_window)) {
+ Control::_propagate_theme_changed(this, parent_w->theme_owner, parent_w->theme_owner_window);
+ } else {
+ Control::_propagate_theme_changed(this, nullptr, nullptr);
+ }
+ }
+ }
+}
+Ref<Theme> Window::get_theme() const {
+ return theme;
+}
+
+Ref<Texture2D> Window::get_theme_icon(const StringName &p_name, const StringName &p_type) const {
+ 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 {
+ 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 {
+ 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 {
+ 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 {
+ 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 {
+ 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 {
+ 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 {
+ 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 {
+ 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 {
+ 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 {
+ 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 {
+ StringName type = p_type ? p_type : get_class_name();
+ return Control::has_constants(theme_owner, theme_owner_window, p_name, type);
+}
+
+Rect2i Window::get_parent_rect() const {
+ ERR_FAIL_COND_V(!is_inside_tree(), Rect2i());
+ if (is_embedded()) {
+ //viewport
+ 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;
+ Rect2i closest_rect;
+ for (int i = 0; i < DisplayServer::get_singleton()->get_screen_count(); i++) {
+ Rect2i s(DisplayServer::get_singleton()->screen_get_position(i), DisplayServer::get_singleton()->screen_get_size(i));
+ int d;
+ if (x >= s.position.x && x < s.size.x) {
+ //contained
+ closest_rect = s;
+ break;
+ } else if (x < s.position.x) {
+ d = s.position.x - x;
+ } else {
+ d = x - (s.position.x + s.size.x);
+ }
+
+ if (d < closest_dist) {
+ closest_dist = d;
+ closest_rect = s;
+ }
+ }
+ return closest_rect;
+ }
+}
+
+void Window::_bind_methods() {
+
+ ClassDB::bind_method(D_METHOD("set_title", "title"), &Window::set_title);
+ ClassDB::bind_method(D_METHOD("get_title"), &Window::get_title);
+
+ ClassDB::bind_method(D_METHOD("set_current_screen", "index"), &Window::set_current_screen);
+ ClassDB::bind_method(D_METHOD("get_current_screen"), &Window::get_current_screen);
+
+ ClassDB::bind_method(D_METHOD("set_position", "position"), &Window::set_position);
+ ClassDB::bind_method(D_METHOD("get_position"), &Window::get_position);
+
+ ClassDB::bind_method(D_METHOD("set_size", "size"), &Window::set_size);
+ ClassDB::bind_method(D_METHOD("get_size"), &Window::get_size);
+
+ ClassDB::bind_method(D_METHOD("get_real_size"), &Window::get_real_size);
+
+ ClassDB::bind_method(D_METHOD("set_max_size", "max_size"), &Window::set_max_size);
+ ClassDB::bind_method(D_METHOD("get_max_size"), &Window::get_max_size);
+
+ ClassDB::bind_method(D_METHOD("set_min_size", "min_size"), &Window::set_min_size);
+ ClassDB::bind_method(D_METHOD("get_min_size"), &Window::get_min_size);
+
+ ClassDB::bind_method(D_METHOD("set_mode", "mode"), &Window::set_mode);
+ ClassDB::bind_method(D_METHOD("get_mode"), &Window::get_mode);
+
+ ClassDB::bind_method(D_METHOD("set_flag", "flag", "enabled"), &Window::set_flag);
+ ClassDB::bind_method(D_METHOD("get_flag", "flag"), &Window::get_flag);
+
+ ClassDB::bind_method(D_METHOD("is_maximize_allowed"), &Window::is_maximize_allowed);
+
+ ClassDB::bind_method(D_METHOD("request_attention"), &Window::request_attention);
+
+ ClassDB::bind_method(D_METHOD("move_to_foreground"), &Window::move_to_foreground);
+
+ ClassDB::bind_method(D_METHOD("set_visible", "visible"), &Window::set_visible);
+ ClassDB::bind_method(D_METHOD("is_visible"), &Window::is_visible);
+
+ ClassDB::bind_method(D_METHOD("hide"), &Window::hide);
+ ClassDB::bind_method(D_METHOD("show"), &Window::show);
+
+ ClassDB::bind_method(D_METHOD("set_transient", "transient"), &Window::set_transient);
+ ClassDB::bind_method(D_METHOD("is_transient"), &Window::is_transient);
+
+ ClassDB::bind_method(D_METHOD("set_exclusive", "exclusive"), &Window::set_exclusive);
+ ClassDB::bind_method(D_METHOD("is_exclusive"), &Window::is_exclusive);
+
+ ClassDB::bind_method(D_METHOD("can_draw"), &Window::is_transient);
+ ClassDB::bind_method(D_METHOD("has_focus"), &Window::has_focus);
+ ClassDB::bind_method(D_METHOD("grab_focus"), &Window::grab_focus);
+
+ ClassDB::bind_method(D_METHOD("set_ime_active"), &Window::set_ime_active);
+ ClassDB::bind_method(D_METHOD("set_ime_position"), &Window::set_ime_position);
+
+ ClassDB::bind_method(D_METHOD("is_embedded"), &Window::is_embedded);
+
+ ClassDB::bind_method(D_METHOD("set_content_scale_size", "size"), &Window::set_content_scale_size);
+ ClassDB::bind_method(D_METHOD("get_content_scale_size"), &Window::get_content_scale_size);
+
+ ClassDB::bind_method(D_METHOD("set_content_scale_mode", "mode"), &Window::set_content_scale_mode);
+ ClassDB::bind_method(D_METHOD("get_content_scale_mode"), &Window::get_content_scale_mode);
+
+ ClassDB::bind_method(D_METHOD("set_content_scale_aspect", "aspect"), &Window::set_content_scale_aspect);
+ ClassDB::bind_method(D_METHOD("get_content_scale_aspect"), &Window::get_content_scale_aspect);
+
+ ClassDB::bind_method(D_METHOD("set_use_font_oversampling", "enable"), &Window::set_use_font_oversampling);
+ ClassDB::bind_method(D_METHOD("is_using_font_oversampling"), &Window::is_using_font_oversampling);
+
+ ClassDB::bind_method(D_METHOD("set_wrap_controls", "enable"), &Window::set_wrap_controls);
+ ClassDB::bind_method(D_METHOD("is_wrapping_controls"), &Window::is_wrapping_controls);
+ ClassDB::bind_method(D_METHOD("child_controls_changed"), &Window::child_controls_changed);
+
+ ClassDB::bind_method(D_METHOD("_update_child_controls"), &Window::_update_child_controls);
+
+ ClassDB::bind_method(D_METHOD("set_theme", "theme"), &Window::set_theme);
+ ClassDB::bind_method(D_METHOD("get_theme"), &Window::get_theme);
+
+ ClassDB::bind_method(D_METHOD("get_theme_icon", "name", "type"), &Window::get_theme_icon, DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("get_theme_stylebox", "name", "type"), &Window::get_theme_stylebox, DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("get_theme_font", "name", "type"), &Window::get_theme_font, DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("get_theme_color", "name", "type"), &Window::get_theme_color, DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("get_theme_constant", "name", "type"), &Window::get_theme_constant, DEFVAL(""));
+
+ ClassDB::bind_method(D_METHOD("has_theme_icon", "name", "type"), &Window::has_theme_icon, DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("has_theme_stylebox", "name", "type"), &Window::has_theme_stylebox, DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("has_theme_font", "name", "type"), &Window::has_theme_font, DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("has_theme_color", "name", "type"), &Window::has_theme_color, DEFVAL(""));
+ ClassDB::bind_method(D_METHOD("has_theme_constant", "name", "type"), &Window::has_theme_constant, DEFVAL(""));
+
+ ClassDB::bind_method(D_METHOD("popup", "rect"), &Window::popup, DEFVAL(Rect2i()));
+ ClassDB::bind_method(D_METHOD("popup_on_parent", "parent_rect"), &Window::popup_on_parent);
+ ClassDB::bind_method(D_METHOD("popup_centered_ratio", "ratio"), &Window::popup_centered_ratio, DEFVAL(0.8));
+ ClassDB::bind_method(D_METHOD("popup_centered", "minsize"), &Window::popup_centered, DEFVAL(Size2i()));
+ ClassDB::bind_method(D_METHOD("popup_centered_clamped", "minsize", "fallback_ratio"), &Window::popup_centered, DEFVAL(Size2i()), DEFVAL(0.75));
+
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "title"), "set_title", "get_title");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "position"), "set_position", "get_position");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "size"), "set_size", "get_size");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "mode", PROPERTY_HINT_ENUM, "Windowed,Minimized,Maximized,FullScreen"), "set_mode", "get_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::STRING, "current_screen"), "set_current_screen", "get_current_screen");
+ ADD_GROUP("Flags", "");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "visible"), "set_visible", "is_visible");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "wrap_controls"), "set_wrap_controls", "is_wrapping_controls");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "transient"), "set_transient", "is_transient");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "exclusive"), "set_exclusive", "is_exclusive");
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "unresizable"), "set_flag", "get_flag", FLAG_RESIZE_DISABLED);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "borderless"), "set_flag", "get_flag", FLAG_BORDERLESS);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "always_on_top"), "set_flag", "get_flag", FLAG_ALWAYS_ON_TOP);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "transparent"), "set_flag", "get_flag", FLAG_TRANSPARENT);
+ ADD_PROPERTYI(PropertyInfo(Variant::BOOL, "unfocusable"), "set_flag", "get_flag", FLAG_NO_FOCUS);
+ ADD_GROUP("Limits", "");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "min_size"), "set_min_size", "get_min_size");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "max_size"), "set_max_size", "get_max_size");
+ ADD_GROUP("Content Scale", "content_scale_");
+ ADD_PROPERTY(PropertyInfo(Variant::VECTOR2I, "content_scale_size"), "set_content_scale_size", "get_content_scale_size");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "content_scale_mode", PROPERTY_HINT_ENUM, "Disabled,Object,Pixels"), "set_content_scale_mode", "get_content_scale_mode");
+ ADD_PROPERTY(PropertyInfo(Variant::INT, "content_scale_aspect", PROPERTY_HINT_ENUM, "Ignore,Keep,KeepWidth,KeepHeight,Expand"), "set_content_scale_aspect", "get_content_scale_aspect");
+ ADD_GROUP("Theme", "");
+ ADD_PROPERTY(PropertyInfo(Variant::OBJECT, "theme", PROPERTY_HINT_RESOURCE_TYPE, "Theme"), "set_theme", "get_theme");
+
+ ADD_SIGNAL(MethodInfo("window_input", PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent")));
+ ADD_SIGNAL(MethodInfo("files_dropped", PropertyInfo(Variant::PACKED_STRING_ARRAY, "files")));
+ ADD_SIGNAL(MethodInfo("mouse_entered"));
+ ADD_SIGNAL(MethodInfo("mouse_exited"));
+ ADD_SIGNAL(MethodInfo("focus_entered"));
+ ADD_SIGNAL(MethodInfo("focus_exited"));
+ ADD_SIGNAL(MethodInfo("close_requested"));
+ ADD_SIGNAL(MethodInfo("go_back_requested"));
+ ADD_SIGNAL(MethodInfo("visibility_changed"));
+ ADD_SIGNAL(MethodInfo("about_to_popup"));
+
+ BIND_CONSTANT(NOTIFICATION_VISIBILITY_CHANGED);
+
+ BIND_ENUM_CONSTANT(MODE_WINDOWED);
+ BIND_ENUM_CONSTANT(MODE_MINIMIZED);
+ BIND_ENUM_CONSTANT(MODE_MAXIMIZED);
+ BIND_ENUM_CONSTANT(MODE_FULLSCREEN);
+
+ BIND_ENUM_CONSTANT(FLAG_RESIZE_DISABLED);
+ BIND_ENUM_CONSTANT(FLAG_BORDERLESS);
+ BIND_ENUM_CONSTANT(FLAG_ALWAYS_ON_TOP);
+ BIND_ENUM_CONSTANT(FLAG_TRANSPARENT);
+ BIND_ENUM_CONSTANT(FLAG_NO_FOCUS);
+ BIND_ENUM_CONSTANT(FLAG_MAX);
+
+ BIND_ENUM_CONSTANT(CONTENT_SCALE_MODE_DISABLED);
+ BIND_ENUM_CONSTANT(CONTENT_SCALE_MODE_OBJECTS);
+ BIND_ENUM_CONSTANT(CONTENT_SCALE_MODE_PIXELS);
+
+ BIND_ENUM_CONSTANT(CONTENT_SCALE_ASPECT_IGNORE);
+ BIND_ENUM_CONSTANT(CONTENT_SCALE_ASPECT_KEEP);
+ BIND_ENUM_CONSTANT(CONTENT_SCALE_ASPECT_KEEP_WIDTH);
+ BIND_ENUM_CONSTANT(CONTENT_SCALE_ASPECT_KEEP_HEIGHT);
+ BIND_ENUM_CONSTANT(CONTENT_SCALE_ASPECT_EXPAND);
+}
+
+Window::Window() {
+ for (int i = 0; i < FLAG_MAX; i++) {
+ flags[i] = false;
+ }
+ 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() {
+}
diff --git a/scene/main/window.h b/scene/main/window.h
new file mode 100644
index 0000000000..be07762f20
--- /dev/null
+++ b/scene/main/window.h
@@ -0,0 +1,266 @@
+/*************************************************************************/
+/* window.h */
+/*************************************************************************/
+/* This file is part of: */
+/* GODOT ENGINE */
+/* https://godotengine.org */
+/*************************************************************************/
+/* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur. */
+/* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md). */
+/* */
+/* Permission is hereby granted, free of charge, to any person obtaining */
+/* a copy of this software and associated documentation files (the */
+/* "Software"), to deal in the Software without restriction, including */
+/* without limitation the rights to use, copy, modify, merge, publish, */
+/* distribute, sublicense, and/or sell copies of the Software, and to */
+/* permit persons to whom the Software is furnished to do so, subject to */
+/* the following conditions: */
+/* */
+/* The above copyright notice and this permission notice shall be */
+/* included in all copies or substantial portions of the Software. */
+/* */
+/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
+/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
+/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
+/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
+/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
+/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
+/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
+/*************************************************************************/
+
+#ifndef WINDOW_H
+#define WINDOW_H
+
+#include "scene/main/viewport.h"
+#include "scene/resources/theme.h"
+#include "servers/display_server.h"
+
+class Control;
+class Window : public Viewport {
+ GDCLASS(Window, Viewport)
+public:
+ enum Mode {
+ MODE_WINDOWED = DisplayServer::WINDOW_MODE_WINDOWED,
+ MODE_MINIMIZED = DisplayServer::WINDOW_MODE_MINIMIZED,
+ MODE_MAXIMIZED = DisplayServer::WINDOW_MODE_MAXIMIZED,
+ MODE_FULLSCREEN = DisplayServer::WINDOW_MODE_FULLSCREEN
+ };
+
+ enum Flags {
+ FLAG_RESIZE_DISABLED = DisplayServer::WINDOW_FLAG_RESIZE_DISABLED,
+ FLAG_BORDERLESS = DisplayServer::WINDOW_FLAG_BORDERLESS,
+ FLAG_ALWAYS_ON_TOP = DisplayServer::WINDOW_FLAG_ALWAYS_ON_TOP,
+ FLAG_TRANSPARENT = DisplayServer::WINDOW_FLAG_TRANSPARENT,
+ FLAG_NO_FOCUS = DisplayServer::WINDOW_FLAG_NO_FOCUS,
+ FLAG_MAX = DisplayServer::WINDOW_FLAG_MAX,
+ };
+
+ enum ContentScaleMode {
+ CONTENT_SCALE_MODE_DISABLED,
+ CONTENT_SCALE_MODE_OBJECTS,
+ CONTENT_SCALE_MODE_PIXELS,
+
+ };
+
+ enum ContentScaleAspect {
+ CONTENT_SCALE_ASPECT_IGNORE,
+ CONTENT_SCALE_ASPECT_KEEP,
+ CONTENT_SCALE_ASPECT_KEEP_WIDTH,
+ CONTENT_SCALE_ASPECT_KEEP_HEIGHT,
+ CONTENT_SCALE_ASPECT_EXPAND,
+
+ };
+ enum {
+ DEFAULT_WINDOW_SIZE = 100
+ };
+
+private:
+ DisplayServer::WindowID window_id = DisplayServer::INVALID_WINDOW_ID;
+
+ String title;
+ mutable int current_screen = 0;
+ mutable Vector2i position;
+ mutable Size2i size = Size2i(DEFAULT_WINDOW_SIZE, DEFAULT_WINDOW_SIZE);
+ mutable Size2i min_size;
+ mutable Size2i max_size;
+ mutable Mode mode = MODE_WINDOWED;
+ mutable bool flags[FLAG_MAX];
+ bool visible = true;
+ bool focused = false;
+
+ bool use_font_oversampling = false;
+ bool transient = false;
+ bool exclusive = false;
+ bool wrap_controls = false;
+ bool updating_child_controls = false;
+
+ void _update_child_controls();
+
+ Size2i content_scale_size;
+ ContentScaleMode content_scale_mode;
+ ContentScaleAspect content_scale_aspect;
+
+ void _make_window();
+ void _clear_window();
+ void _update_from_window();
+
+ void _update_viewport_size();
+ void _update_window_size();
+
+ void _propagate_window_notification(Node *p_node, int p_notification);
+
+ void _update_window_callbacks();
+
+ void _clear_transient();
+ void _make_transient();
+ Window *transient_parent = nullptr;
+ Window *exclusive_child = nullptr;
+ Set<Window *> transient_children;
+
+ friend class Control;
+ Ref<Theme> theme;
+ Control *theme_owner = nullptr;
+ Window *theme_owner_window = nullptr;
+
+ 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:
+ Viewport *_get_embedder() const;
+
+ virtual Rect2i _popup_adjust_rect() const { return Rect2i(); }
+
+ virtual void _post_popup() {}
+ virtual Size2 _get_contents_minimum_size() const;
+ static void _bind_methods();
+ void _notification(int p_what);
+
+ virtual void add_child_notify(Node *p_child);
+ virtual void remove_child_notify(Node *p_child);
+
+public:
+ enum {
+
+ NOTIFICATION_VISIBILITY_CHANGED = 30,
+ NOTIFICATION_POST_POPUP = 31,
+ NOTIFICATION_THEME_CHANGED = 32,
+ };
+
+ void set_title(const String &p_title);
+ String get_title() const;
+
+ void set_current_screen(int p_screen);
+ int get_current_screen() const;
+
+ void set_position(const Point2i &p_position);
+ Point2i get_position() const;
+
+ void set_size(const Size2i &p_size);
+ Size2i get_size() const;
+
+ Size2i get_real_size() const;
+
+ void set_max_size(const Size2i &p_max_size);
+ Size2i get_max_size() const;
+
+ void set_min_size(const Size2i &p_min_size);
+ Size2i get_min_size() const;
+
+ void set_mode(Mode p_mode);
+ Mode get_mode() const;
+
+ void set_flag(Flags p_flag, bool p_enabled);
+ bool get_flag(Flags p_flag) const;
+
+ bool is_maximize_allowed() const;
+
+ void request_attention();
+ void move_to_foreground();
+
+ void set_visible(bool p_visible);
+ bool is_visible() const;
+
+ void show();
+ void hide();
+
+ void set_transient(bool p_transient);
+ bool is_transient() const;
+
+ void set_exclusive(bool p_exclusive);
+ bool is_exclusive() const;
+
+ bool can_draw() const;
+
+ void set_ime_active(bool p_active);
+ void set_ime_position(const Point2i &p_pos);
+
+ bool is_embedded() const;
+
+ void set_content_scale_size(const Size2i &p_size);
+ Size2i get_content_scale_size() const;
+
+ void set_content_scale_mode(ContentScaleMode p_mode);
+ ContentScaleMode get_content_scale_mode() const;
+
+ void set_content_scale_aspect(ContentScaleAspect p_aspect);
+ ContentScaleAspect get_content_scale_aspect() const;
+
+ void set_use_font_oversampling(bool p_oversampling);
+ bool is_using_font_oversampling() const;
+
+ void set_wrap_controls(bool p_enable);
+ bool is_wrapping_controls() const;
+ void child_controls_changed();
+
+ Window *get_parent_visible_window() const;
+ Viewport *get_parent_viewport() const;
+ void popup(const Rect2i &p_rect = Rect2i());
+ void popup_on_parent(const Rect2i &p_parent_rect);
+ void popup_centered_ratio(float p_ratio = 0.8);
+ void popup_centered(const Size2i &p_minsize = Size2i());
+ void popup_centered_clamped(const Size2i &p_size = Size2i(), float p_fallback_ratio = 0.75);
+
+ void set_theme(const Ref<Theme> &p_theme);
+ Ref<Theme> get_theme() const;
+
+ Size2 get_contents_minimum_size() const;
+
+ void grab_focus();
+ bool has_focus() const;
+
+ Rect2i get_usable_parent_rect() const;
+
+ Ref<Texture2D> get_theme_icon(const StringName &p_name, const StringName &p_type = StringName()) const;
+ Ref<Shader> get_theme_shader(const StringName &p_name, const StringName &p_type = StringName()) const;
+ Ref<StyleBox> get_theme_stylebox(const StringName &p_name, const StringName &p_type = StringName()) const;
+ Ref<Font> get_theme_font(const StringName &p_name, const StringName &p_type = StringName()) const;
+ Color get_theme_color(const StringName &p_name, const StringName &p_type = StringName()) const;
+ int get_theme_constant(const StringName &p_name, const StringName &p_type = StringName()) const;
+
+ bool has_theme_icon(const StringName &p_name, const StringName &p_type = StringName()) const;
+ bool has_theme_shader(const StringName &p_name, const StringName &p_type = StringName()) const;
+ bool has_theme_stylebox(const StringName &p_name, const StringName &p_type = StringName()) const;
+ bool has_theme_font(const StringName &p_name, const StringName &p_type = StringName()) const;
+ 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_parent_rect() const;
+ virtual DisplayServer::WindowID get_window_id() const;
+
+ Window();
+ ~Window();
+};
+
+VARIANT_ENUM_CAST(Window::Window::Mode);
+VARIANT_ENUM_CAST(Window::Window::Flags);
+VARIANT_ENUM_CAST(Window::ContentScaleMode);
+VARIANT_ENUM_CAST(Window::ContentScaleAspect);
+
+#endif // WINDOW_H
diff --git a/scene/register_scene_types.cpp b/scene/register_scene_types.cpp
index f15911b0e2..41c43a586b 100644
--- a/scene/register_scene_types.cpp
+++ b/scene/register_scene_types.cpp
@@ -128,6 +128,7 @@
#include "scene/main/scene_tree.h"
#include "scene/main/timer.h"
#include "scene/main/viewport.h"
+#include "scene/main/window.h"
#include "scene/resources/audio_stream_sample.h"
#include "scene/resources/bit_map.h"
#include "scene/resources/box_shape.h"
@@ -267,13 +268,14 @@ void register_scene_types() {
ClassDB::register_class<Node>();
ClassDB::register_virtual_class<InstancePlaceholder>();
- ClassDB::register_class<Viewport>();
+ ClassDB::register_virtual_class<Viewport>();
ClassDB::register_class<ViewportTexture>();
ClassDB::register_class<HTTPRequest>();
ClassDB::register_class<Timer>();
ClassDB::register_class<CanvasLayer>();
ClassDB::register_class<CanvasModulate>();
ClassDB::register_class<ResourcePreloader>();
+ ClassDB::register_class<Window>();
/* REGISTER GUI */
ClassDB::register_class<ButtonGroup>();
@@ -348,8 +350,7 @@ void register_scene_types() {
ClassDB::register_class<RichTextLabel>();
ClassDB::register_class<RichTextEffect>();
ClassDB::register_class<CharFXTransform>();
- ClassDB::register_class<PopupDialog>();
- ClassDB::register_class<WindowDialog>();
+ ;
ClassDB::register_class<AcceptDialog>();
ClassDB::register_class<ConfirmationDialog>();
ClassDB::register_class<MarginContainer>();
@@ -480,7 +481,7 @@ void register_scene_types() {
#endif
ClassDB::register_class<NavigationMesh>();
- AcceptDialog::set_swap_ok_cancel(GLOBAL_DEF("gui/common/swap_ok_cancel", bool(OS::get_singleton()->get_swap_ok_cancel())));
+ AcceptDialog::set_swap_ok_cancel(GLOBAL_DEF("gui/common/swap_ok_cancel", bool(DisplayServer::get_singleton()->get_swap_ok_cancel())));
ClassDB::register_class<Shader>();
ClassDB::register_class<VisualShader>();
diff --git a/scene/resources/default_theme/default_theme.cpp b/scene/resources/default_theme/default_theme.cpp
index 9f5b49c4c3..0c45779307 100644
--- a/scene/resources/default_theme/default_theme.cpp
+++ b/scene/resources/default_theme/default_theme.cpp
@@ -188,6 +188,7 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
// Panel
theme->set_stylebox("panel", "Panel", make_stylebox(panel_bg_png, 0, 0, 0, 0));
+ theme->set_stylebox("panel_fg", "Panel", make_stylebox(panel_bg_png, 0, 0, 0, 0));
// Focus
@@ -523,17 +524,19 @@ void fill_default_theme(Ref<Theme> &theme, const Ref<Font> &default_font, const
// WindowDialog
- theme->set_stylebox("panel", "WindowDialog", sb_expand(make_stylebox(popup_window_png, 10, 26, 10, 8), 8, 24, 8, 6));
- theme->set_constant("scaleborder_size", "WindowDialog", 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", "WindowDialog", large_font);
- theme->set_color("title_color", "WindowDialog", Color(0, 0, 0));
- theme->set_constant("title_height", "WindowDialog", 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", "WindowDialog", make_icon(close_png));
- theme->set_icon("close_highlight", "WindowDialog", make_icon(close_hl_png));
- theme->set_constant("close_h_ofs", "WindowDialog", 18 * scale);
- theme->set_constant("close_v_ofs", "WindowDialog", 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
diff --git a/scene/resources/world_2d.cpp b/scene/resources/world_2d.cpp
index 6bdc4cf6f0..75bdeeac07 100644
--- a/scene/resources/world_2d.cpp
+++ b/scene/resources/world_2d.cpp
@@ -33,7 +33,7 @@
#include "core/project_settings.h"
#include "scene/2d/camera_2d.h"
#include "scene/2d/visibility_notifier_2d.h"
-#include "scene/main/viewport.h"
+#include "scene/main/window.h"
#include "servers/physics_2d_server.h"
#include "servers/visual_server.h"
diff --git a/scene/scene_string_names.cpp b/scene/scene_string_names.cpp
index d3c5a87cae..1f0365dab9 100644
--- a/scene/scene_string_names.cpp
+++ b/scene/scene_string_names.cpp
@@ -193,6 +193,12 @@ SceneStringNames::SceneStringNames() {
mesh_materials[i] = "material/" + itos(i);
}
+ _window_group = StaticCString::create("_window_group");
+ _window_input = StaticCString::create("_window_input");
+ window_input = StaticCString::create("window_input");
+ _window_unhandled_input = StaticCString::create("_window_unhandled_input");
+
+ theme_changed = StaticCString::create("theme_changed");
parameters_base_path = "parameters/";
tracks_changed = "tracks_changed";
diff --git a/scene/scene_string_names.h b/scene/scene_string_names.h
index 7976a2072c..e255ebb3cb 100644
--- a/scene/scene_string_names.h
+++ b/scene/scene_string_names.h
@@ -201,6 +201,13 @@ public:
StringName tracks_changed;
+ StringName _window_group;
+ StringName _window_input;
+ StringName _window_unhandled_input;
+ StringName window_input;
+
+ StringName theme_changed;
+
enum {
MAX_MATERIALS = 32
};