diff options
author | Juan Linietsky <juan@godotengine.org> | 2020-03-04 13:36:09 -0300 |
---|---|---|
committer | Juan Linietsky <reduzio@gmail.com> | 2020-03-26 15:49:39 +0100 |
commit | 8e6960a69e0202cb1e6f3b3dc9f9bb34e1c1d889 (patch) | |
tree | 67b81f61ea79e83d7877c77a302592b9c849991e /scene/main | |
parent | 9e08742de81b062c30b7984900a55d5150a4bd17 (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.cpp | 3 | ||||
-rw-r--r-- | scene/main/node.h | 15 | ||||
-rw-r--r-- | scene/main/scene_tree.cpp | 193 | ||||
-rw-r--r-- | scene/main/scene_tree.h | 14 | ||||
-rw-r--r-- | scene/main/viewport.cpp | 178 | ||||
-rw-r--r-- | scene/main/viewport.h | 8 | ||||
-rw-r--r-- | scene/main/window.cpp | 90 | ||||
-rw-r--r-- | scene/main/window.h | 10 |
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); |