From 287bc6f41e3d1c1c2064c75982d65a2e7111f651 Mon Sep 17 00:00:00 2001 From: lawnjelly Date: Sat, 28 Sep 2024 08:48:06 +0100 Subject: [PATCH] Add warning when calling `is_action_just_pressed()` from `_input()` Calling `is_action_just_pressed()` and `is_action_just_released()` from `_input()` is liable to cause duplicate detection bugs in user code. --- main/input_default.cpp | 16 ++++++++++++++++ main/input_default.h | 14 ++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/main/input_default.cpp b/main/input_default.cpp index 24505577c03b..f632bf45fcd8 100644 --- a/main/input_default.cpp +++ b/main/input_default.cpp @@ -111,6 +111,12 @@ bool InputDefault::is_action_pressed(const StringName &p_action, bool p_exact) c } bool InputDefault::is_action_just_pressed(const StringName &p_action, bool p_exact) const { +#ifdef TOOLS_ENABLED + if (_currently_parsing_input) { + WARN_PRINT_ONCE("Prefer InputEvent.is_action_pressed() within input event callbacks to prevent detecting duplicates."); + } +#endif + ERR_FAIL_COND_V_MSG(!InputMap::get_singleton()->has_action(p_action), false, InputMap::get_singleton()->suggest_actions(p_action)); const Map::Element *E = action_state.find(p_action); if (!E) { @@ -132,6 +138,12 @@ bool InputDefault::is_action_just_pressed(const StringName &p_action, bool p_exa } bool InputDefault::is_action_just_released(const StringName &p_action, bool p_exact) const { +#ifdef TOOLS_ENABLED + if (_currently_parsing_input) { + WARN_PRINT_ONCE("Prefer InputEvent.is_action_released() within input event callbacks to prevent detecting duplicates."); + } +#endif + ERR_FAIL_COND_V_MSG(!InputMap::get_singleton()->has_action(p_action), false, InputMap::get_singleton()->suggest_actions(p_action)); const Map::Element *E = action_state.find(p_action); if (!E) { @@ -327,6 +339,10 @@ void InputDefault::_parse_input_event_impl(const Ref &p_event, bool // Regardless where the event came from originally, this has to happen on the main thread. DEV_ASSERT(Thread::get_caller_id() == Thread::get_main_id()); +#ifdef TOOLS_ENABLED + InputGuard guard(_currently_parsing_input); +#endif + // Notes on mouse-touch emulation: // - Emulated mouse events are parsed, that is, re-routed to this method, so they make the same effects // as true mouse events. The only difference is the situation is flagged as emulated so they are not diff --git a/main/input_default.h b/main/input_default.h index 6c0192e0d6fd..19206db8558b 100644 --- a/main/input_default.h +++ b/main/input_default.h @@ -114,6 +114,20 @@ class InputDefault : public Input { CursorShape default_shape; +#ifdef TOOLS_ENABLED + // Simple single-threaded detection of whether + // inside `_parse_input_event_impl()`. + bool _currently_parsing_input = false; + class InputGuard { + bool &_currently_parsing; + + public: + InputGuard(bool &r_currently_parsing) : + _currently_parsing(r_currently_parsing) { _currently_parsing = true; } + ~InputGuard() { _currently_parsing = false; } + }; +#endif + public: enum HatMask { HAT_MASK_CENTER = 0,