diff --git a/core/os/input.cpp b/core/os/input.cpp index cf11ba3c6d7..caa9fb14938 100644 --- a/core/os/input.cpp +++ b/core/os/input.cpp @@ -91,6 +91,7 @@ void Input::_bind_methods() { ClassDB::bind_method(D_METHOD("set_default_cursor_shape", "shape"), &Input::set_default_cursor_shape, DEFVAL(CURSOR_ARROW)); ClassDB::bind_method(D_METHOD("set_custom_mouse_cursor", "image", "shape", "hotspot"), &Input::set_custom_mouse_cursor, DEFVAL(CURSOR_ARROW), DEFVAL(Vector2())); ClassDB::bind_method(D_METHOD("parse_input_event", "event"), &Input::parse_input_event); + ClassDB::bind_method(D_METHOD("set_use_accumulated_input", "enable"), &Input::set_use_accumulated_input); BIND_ENUM_CONSTANT(MOUSE_MODE_VISIBLE); BIND_ENUM_CONSTANT(MOUSE_MODE_HIDDEN); diff --git a/core/os/input.h b/core/os/input.h index b354acd9610..c8b80b28d07 100644 --- a/core/os/input.h +++ b/core/os/input.h @@ -132,6 +132,9 @@ public: virtual int get_joy_axis_index_from_string(String p_axis) = 0; virtual void parse_input_event(const Ref &p_event) = 0; + virtual void accumulate_input_event(const Ref &p_event) = 0; + virtual void flush_accumulated_events() = 0; + virtual void set_use_accumulated_input(bool p_enable) = 0; Input(); }; diff --git a/core/os/input_event.cpp b/core/os/input_event.cpp index 24ec8a19633..40308f4f7dd 100644 --- a/core/os/input_event.cpp +++ b/core/os/input_event.cpp @@ -122,6 +122,8 @@ void InputEvent::_bind_methods() { ClassDB::bind_method(D_METHOD("is_action_type"), &InputEvent::is_action_type); + ClassDB::bind_method(D_METHOD("accumulate", "with_event"), &InputEvent::accumulate); + ClassDB::bind_method(D_METHOD("xformed_by", "xform", "local_ofs"), &InputEvent::xformed_by, DEFVAL(Vector2())); ADD_PROPERTY(PropertyInfo(Variant::INT, "device"), "set_device", "get_device"); @@ -620,6 +622,44 @@ String InputEventMouseMotion::as_text() const { return "InputEventMouseMotion : button_mask=" + button_mask_string + ", position=(" + String(get_position()) + "), relative=(" + String(get_relative()) + "), speed=(" + String(get_speed()) + ")"; } +bool InputEventMouseMotion::accumulate(const Ref &p_event) { + + Ref motion = p_event; + if (motion.is_null()) + return false; + + if (is_pressed() != motion->is_pressed()) { + return false; + } + + if (get_button_mask() != motion->get_button_mask()) { + return false; + } + + if (get_shift() != motion->get_shift()) { + return false; + } + + if (get_control() != motion->get_control()) { + return false; + } + + if (get_alt() != motion->get_alt()) { + return false; + } + + if (get_metakey() != motion->get_metakey()) { + return false; + } + + set_position(motion->get_position()); + set_global_position(motion->get_global_position()); + set_speed(motion->get_speed()); + relative += motion->get_relative(); + + return true; +} + void InputEventMouseMotion::_bind_methods() { ClassDB::bind_method(D_METHOD("set_relative", "relative"), &InputEventMouseMotion::set_relative); diff --git a/core/os/input_event.h b/core/os/input_event.h index a6a7012298f..47f9293a7f4 100644 --- a/core/os/input_event.h +++ b/core/os/input_event.h @@ -186,6 +186,7 @@ public: virtual bool shortcut_match(const Ref &p_event) const; virtual bool is_action_type() const; + virtual bool accumulate(const Ref &p_event) { return false; } InputEvent(); }; @@ -351,6 +352,8 @@ public: virtual Ref xformed_by(const Transform2D &p_xform, const Vector2 &p_local_ofs = Vector2()) const; virtual String as_text() const; + virtual bool accumulate(const Ref &p_event); + InputEventMouseMotion(); }; diff --git a/editor/editor_node.cpp b/editor/editor_node.cpp index 07dfcaa917e..afaf90a1587 100644 --- a/editor/editor_node.cpp +++ b/editor/editor_node.cpp @@ -4850,6 +4850,7 @@ void EditorNode::_print_handler(void *p_this, const String &p_string, bool p_err EditorNode::EditorNode() { + Input::get_singleton()->set_use_accumulated_input(true); Resource::_get_local_scene_func = _resource_get_edited_scene; VisualServer::get_singleton()->textures_keep_original(true); diff --git a/main/input_default.cpp b/main/input_default.cpp index 18b4649f4db..fd76b91a0bd 100644 --- a/main/input_default.cpp +++ b/main/input_default.cpp @@ -657,8 +657,35 @@ void InputDefault::set_mouse_in_window(bool p_in_window) { */ } +void InputDefault::accumulate_input_event(const Ref &p_event) { + ERR_FAIL_COND(p_event.is_null()); + + if (!use_accumulated_input) { + parse_input_event(p_event); + return; + } + if (!accumulated_events.empty() && accumulated_events.back()->get()->accumulate(p_event)) { + return; //event was accumulated, exit + } + + accumulated_events.push_back(p_event); +} +void InputDefault::flush_accumulated_events() { + + while (accumulated_events.front()) { + parse_input_event(accumulated_events.front()->get()); + accumulated_events.pop_front(); + } +} + +void InputDefault::set_use_accumulated_input(bool p_enable) { + + use_accumulated_input = p_enable; +} + InputDefault::InputDefault() { + use_accumulated_input = false; mouse_button_mask = 0; emulate_touch_from_mouse = false; emulate_mouse_from_touch = false; diff --git a/main/input_default.h b/main/input_default.h index 75dd1e67f68..79a90cc4a45 100644 --- a/main/input_default.h +++ b/main/input_default.h @@ -183,6 +183,9 @@ private: void _parse_input_event_impl(const Ref &p_event, bool p_is_emulated); + List > accumulated_events; + bool use_accumulated_input; + public: virtual bool is_key_pressed(int p_scancode) const; virtual bool is_mouse_button_pressed(int p_button) const; @@ -264,6 +267,11 @@ public: bool is_joy_mapped(int p_device); String get_joy_guid_remapped(int p_device) const; void set_fallback_mapping(String p_guid); + + virtual void accumulate_input_event(const Ref &p_event); + virtual void flush_accumulated_events(); + virtual void set_use_accumulated_input(bool p_enable); + InputDefault(); }; diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm index 5206dc13b6d..a2f266f995f 100644 --- a/platform/osx/os_osx.mm +++ b/platform/osx/os_osx.mm @@ -2529,6 +2529,8 @@ void OS_OSX::process_events() { [autoreleasePool drain]; autoreleasePool = [[NSAutoreleasePool alloc] init]; + + input->flush_accumulated_events(); } void OS_OSX::process_key_events() { @@ -2571,13 +2573,14 @@ void OS_OSX::process_key_events() { void OS_OSX::push_input(const Ref &p_event) { Ref ev = p_event; - input->parse_input_event(ev); + input->accumulate_input_event(ev); } void OS_OSX::force_process_input() { process_events(); // get rid of pending events joypad_osx->process_joypads(); + } void OS_OSX::run() { diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp index bace65e7721..1a5e97cfb10 100644 --- a/platform/windows/os_windows.cpp +++ b/platform/windows/os_windows.cpp @@ -271,7 +271,7 @@ void OS_Windows::_touch_event(bool p_pressed, float p_x, float p_y, int idx) { event->set_position(Vector2(p_x, p_y)); if (main_loop) { - input->parse_input_event(event); + input->accumulate_input_event(event); } }; @@ -293,7 +293,7 @@ void OS_Windows::_drag_event(float p_x, float p_y, int idx) { event->set_position(Vector2(p_x, p_y)); if (main_loop) - input->parse_input_event(event); + input->accumulate_input_event(event); }; LRESULT OS_Windows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { @@ -458,7 +458,7 @@ LRESULT OS_Windows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) } if (window_has_focus && main_loop && mm->get_relative() != Vector2()) - input->parse_input_event(mm); + input->accumulate_input_event(mm); } delete[] lpb; } break; @@ -545,7 +545,7 @@ LRESULT OS_Windows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) old_x = mm->get_position().x; old_y = mm->get_position().y; if (window_has_focus && main_loop) - input->parse_input_event(mm); + input->accumulate_input_event(mm); } break; case WM_LBUTTONDOWN: @@ -718,14 +718,14 @@ LRESULT OS_Windows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) mb->set_global_position(mb->get_position()); if (main_loop) { - input->parse_input_event(mb); + input->accumulate_input_event(mb); if (mb->is_pressed() && mb->get_button_index() > 3 && mb->get_button_index() < 8) { //send release for mouse wheel Ref mbd = mb->duplicate(); last_button_state &= ~(1 << (mbd->get_button_index() - 1)); mbd->set_button_mask(last_button_state); mbd->set_pressed(false); - input->parse_input_event(mbd); + input->accumulate_input_event(mbd); } } } break; @@ -988,7 +988,7 @@ void OS_Windows::process_key_events() { if (k->get_unicode() < 32) k->set_unicode(0); - input->parse_input_event(k); + input->accumulate_input_event(k); } //do nothing @@ -1026,7 +1026,7 @@ void OS_Windows::process_key_events() { k->set_echo((ke.uMsg == WM_KEYDOWN && (ke.lParam & (1 << 30)))); - input->parse_input_event(k); + input->accumulate_input_event(k); } break; } @@ -2252,6 +2252,7 @@ void OS_Windows::process_events() { if (!drop_events) { process_key_events(); + input->flush_accumulated_events(); } } diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp index b7fbb89edfd..cc4d57ea99a 100644 --- a/platform/x11/os_x11.cpp +++ b/platform/x11/os_x11.cpp @@ -1660,7 +1660,7 @@ void OS_X11::handle_key_event(XKeyEvent *p_event, bool p_echo) { k->set_shift(true); } - input->parse_input_event(k); + input->accumulate_input_event(k); } return; } @@ -1804,7 +1804,7 @@ void OS_X11::handle_key_event(XKeyEvent *p_event, bool p_echo) { } //printf("key: %x\n",k->get_scancode()); - input->parse_input_event(k); + input->accumulate_input_event(k); } struct Property { @@ -1991,12 +1991,12 @@ void OS_X11::process_xevents() { // in a spurious mouse motion event being sent to Godot; remember it to be able to filter it out xi.mouse_pos_to_filter = pos; } - input->parse_input_event(st); + input->accumulate_input_event(st); } else { if (!xi.state.has(index)) // Defensive break; xi.state.erase(index); - input->parse_input_event(st); + input->accumulate_input_event(st); } } break; @@ -2014,7 +2014,7 @@ void OS_X11::process_xevents() { sd->set_index(index); sd->set_position(pos); sd->set_relative(pos - curr_pos_elem->value()); - input->parse_input_event(sd); + input->accumulate_input_event(sd); curr_pos_elem->value() = pos; } @@ -2102,7 +2102,7 @@ void OS_X11::process_xevents() { st.instance(); st->set_index(E->key()); st->set_position(E->get()); - input->parse_input_event(st); + input->accumulate_input_event(st); } xi.state.clear(); #endif @@ -2163,7 +2163,7 @@ void OS_X11::process_xevents() { } } - input->parse_input_event(mb); + input->accumulate_input_event(mb); } break; case MotionNotify: { @@ -2273,7 +2273,7 @@ void OS_X11::process_xevents() { // this is so that the relative motion doesn't get messed up // after we regain focus. if (window_has_focus || !mouse_mode_grab) - input->parse_input_event(mm); + input->accumulate_input_event(mm); } break; case KeyPress: @@ -2457,6 +2457,8 @@ void OS_X11::process_xevents() { printf("Win: %d,%d\n", win_x, win_y); */ } + + input->flush_accumulated_events(); } MainLoop *OS_X11::get_main_loop() const {