summaryrefslogtreecommitdiff
path: root/scene/main
diff options
context:
space:
mode:
authorJuan Linietsky <juan@godotengine.org>2020-03-04 13:36:09 -0300
committerJuan Linietsky <reduzio@gmail.com>2020-03-26 15:49:39 +0100
commit8e6960a69e0202cb1e6f3b3dc9f9bb34e1c1d889 (patch)
tree67b81f61ea79e83d7877c77a302592b9c849991e /scene/main
parent9e08742de81b062c30b7984900a55d5150a4bd17 (diff)
Refactored input, goes all via windows now.
Also renamed Input to InputFilter because all it does is filter events.
Diffstat (limited to 'scene/main')
-rw-r--r--scene/main/node.cpp3
-rw-r--r--scene/main/node.h15
-rw-r--r--scene/main/scene_tree.cpp193
-rw-r--r--scene/main/scene_tree.h14
-rw-r--r--scene/main/viewport.cpp178
-rw-r--r--scene/main/viewport.h8
-rw-r--r--scene/main/window.cpp90
-rw-r--r--scene/main/window.h10
8 files changed, 250 insertions, 261 deletions
diff --git a/scene/main/node.cpp b/scene/main/node.cpp
index 973dff07d2..578645a676 100644
--- a/scene/main/node.cpp
+++ b/scene/main/node.cpp
@@ -2950,9 +2950,8 @@ 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_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..1b61da9fb1 100644
--- a/scene/main/node.h
+++ b/scene/main/node.h
@@ -244,13 +244,14 @@ 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_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 77eb445afa..33cb067db1 100644
--- a/scene/main/scene_tree.cpp
+++ b/scene/main/scene_tree.cpp
@@ -31,7 +31,7 @@
#include "scene_tree.h"
#include "core/debugger/engine_debugger.h"
-#include "core/input/input.h"
+#include "core/input/input_filter.h"
#include "core/io/marshalls.h"
#include "core/io/resource_loader.h"
#include "core/message_queue.h"
@@ -398,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);
@@ -626,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();
+ }
+}
- Input *id = 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:
@@ -894,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)
@@ -903,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.
@@ -912,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))
@@ -928,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());
}
@@ -938,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)
@@ -947,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.
@@ -956,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))
@@ -966,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());
}
@@ -977,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;
@@ -1191,12 +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);
@@ -1330,8 +1237,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));
@@ -1495,7 +1400,6 @@ SceneTree::SceneTree() {
idle_process_time = 1;
root = NULL;
- input_handled = false;
pause = false;
current_frame = 0;
current_event = 0;
@@ -1512,7 +1416,6 @@ SceneTree::SceneTree() {
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)));
@@ -1562,6 +1465,10 @@ SceneTree::SceneTree() {
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 c51214b676..4fb19a57d5 100644
--- a/scene/main/scene_tree.h
+++ b/scene/main/scene_tree.h
@@ -105,7 +105,6 @@ private:
Map<StringName, Group> group_map;
bool _quit;
bool initialized;
- bool input_handled;
StringName tree_changed_name;
StringName node_added_name;
@@ -184,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);
@@ -208,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();
@@ -237,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);
@@ -251,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; }
@@ -330,7 +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;
diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp
index 66faaf51b3..4fbb1cb870 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/input/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,6 +49,7 @@
#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"
@@ -394,7 +395,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 == Rect2i() || 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);
@@ -666,8 +667,8 @@ 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();
@@ -1333,76 +1334,15 @@ Ref<InputEvent> Viewport::_make_input_local(const Ref<InputEvent> &ev) {
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
-
- Ref<InputEventFromWindow> window_event = p_ev;
- if (window_event.is_valid()) {
- if (window_event->get_window_id() != get_window_id()) {
- return;
- }
- }
-
- //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;
- */
-
- Ref<InputEventFromWindow> window_event = p_ev;
- if (window_event.is_valid()) {
- if (window_event->get_window_id() != get_window_id()) {
- return;
- }
- }
-
- //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);
-}
-
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 (get_final_transform().affine_inverse() * _get_input_pre_xform()).xform(InputFilter::get_singleton()->get_mouse_position() - _get_window_offset());
}
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);
+ InputFilter::get_singleton()->warp_mouse_position(gpos);
}
void Viewport::_gui_prepare_subwindows() {
@@ -2109,7 +2049,7 @@ void Viewport::_gui_input_event(Ref<InputEvent> p_event) {
}
if (!over) {
- DisplayServer::get_singleton()->cursor_set_shape((DisplayServer::CursorShape)Input::get_singleton()->get_default_cursor_shape());
+ DisplayServer::get_singleton()->cursor_set_shape((DisplayServer::CursorShape)InputFilter::get_singleton()->get_default_cursor_shape());
return;
}
@@ -2363,7 +2303,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")) {
@@ -2735,44 +2675,78 @@ 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.key_focus) {
+ gui.key_focus->call("set_text", p_text);
+ }
+}
+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_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);
}
}
}
@@ -2930,7 +2904,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();
}
}
@@ -2938,8 +2922,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();
}
}
@@ -3042,10 +3035,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_msaa", "msaa"), &Viewport::set_msaa);
ClassDB::bind_method(D_METHOD("get_msaa"), &Viewport::get_msaa);
@@ -3060,8 +3049,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);
diff --git a/scene/main/viewport.h b/scene/main/viewport.h
index 1fa08e6cd0..3d90eaf3b3 100644
--- a/scene/main/viewport.h
+++ b/scene/main/viewport.h
@@ -329,9 +329,6 @@ 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;
@@ -475,8 +472,9 @@ 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;
diff --git a/scene/main/window.cpp b/scene/main/window.cpp
index 21e7450b9f..cfc3fa87c4 100644
--- a/scene/main/window.cpp
+++ b/scene/main/window.cpp
@@ -30,6 +30,8 @@
#include "window.h"
+#include "core/debugger/engine_debugger.h"
+#include "core/os/keyboard.h"
#include "scene/resources/dynamic_font.h"
void Window::set_title(const String &p_title) {
@@ -242,6 +244,48 @@ void Window::_resize_callback(const Size2i &p_callback) {
_update_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: {
+ _propagate_window_notification(this, NOTIFICATION_WM_FOCUS_IN);
+ emit_signal("focus_entered");
+ } break;
+ case DisplayServer::WINDOW_EVENT_FOCUS_OUT: {
+ _propagate_window_notification(this, NOTIFICATION_WM_FOCUS_OUT);
+ emit_signal("focus_exited");
+ } break;
+ case DisplayServer::WINDOW_EVENT_CLOSE_REQUEST: {
+ _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;
+ }
+}
+
void Window::set_visible(bool p_visible) {
if (visible == p_visible) {
return;
@@ -398,6 +442,13 @@ void Window::_update_size() {
}
}
+void Window::_update_window_callbacks() {
+ DisplayServer::get_singleton()->window_set_resize_callback(callable_mp(this, &Window::_resize_callback), window_id);
+ DisplayServer::get_singleton()->window_set_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);
+}
void Window::_notification(int p_what) {
if (p_what == NOTIFICATION_ENTER_TREE) {
if (is_embedded()) {
@@ -409,11 +460,11 @@ void Window::_notification(int p_what) {
window_id = DisplayServer::MAIN_WINDOW_ID;
_update_from_window();
_update_size();
- DisplayServer::get_singleton()->window_set_resize_callback(callable_mp(this, &Window::_resize_callback), window_id);
+ _update_window_callbacks();
} else {
//create
_make_window();
- DisplayServer::get_singleton()->window_set_resize_callback(callable_mp(this, &Window::_resize_callback), window_id);
+ _update_window_callbacks();
}
}
}
@@ -423,7 +474,7 @@ void Window::_notification(int p_what) {
if (window_id == DisplayServer::MAIN_WINDOW_ID) {
- DisplayServer::get_singleton()->window_set_resize_callback(Callable(), window_id);
+ _update_window_callbacks();
} else {
_clear_window();
}
@@ -475,7 +526,40 @@ DisplayServer::WindowID Window::get_window_id() const {
return window_id;
}
+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());
+ }
+ }
+
+ 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);
+}
+
void Window::_bind_methods() {
+
+ ADD_SIGNAL(MethodInfo("files_dropped"));
+ 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"));
}
Window::Window() {
diff --git a/scene/main/window.h b/scene/main/window.h
index 2fd6d993a9..0c689a001f 100644
--- a/scene/main/window.h
+++ b/scene/main/window.h
@@ -95,11 +95,21 @@ private:
void _update_from_window();
void _resize_callback(const Size2i &p_callback);
+ void _event_callback(DisplayServer::WindowEvent p_event);
void _update_size();
+ void _propagate_window_notification(Node *p_node, int p_notification);
+
virtual DisplayServer::WindowID get_window_id() const;
+ void _window_input(const Ref<InputEvent> &p_ev);
+ void _window_input_text(const String &p_text);
+ void _window_drop_files(const Vector<String> &p_files);
+
+ void _window_unhandled_input(const Ref<InputEvent> &p_ev);
+ void _update_window_callbacks();
+
protected:
static void _bind_methods();
void _notification(int p_what);