From 9cd84224bde6e3cdfa717a189e924b510bebd426 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pedro=20J=2E=20Est=C3=A9banez?= Date: Thu, 19 Jan 2023 13:22:58 +0100 Subject: [PATCH] Warn users about unsafe usage of InputEvent --- main/input_default.cpp | 25 +++++++++++++++++++++++++ main/input_default.h | 5 +++++ 2 files changed, 30 insertions(+) diff --git a/main/input_default.cpp b/main/input_default.cpp index 8ef50527017..1d9d1a10a32 100644 --- a/main/input_default.cpp +++ b/main/input_default.cpp @@ -708,6 +708,31 @@ void InputDefault::parse_input_event(const Ref &p_event) { ERR_FAIL_COND(p_event.is_null()); +#ifdef DEBUG_ENABLED + uint64_t curr_frame = Engine::get_singleton()->get_idle_frames(); + if (curr_frame != last_parsed_frame) { + frame_parsed_events.clear(); + last_parsed_frame = curr_frame; + frame_parsed_events.insert(p_event); + } else if (frame_parsed_events.has(p_event)) { + // It would be technically safe to send the same event in cases such as: + // - After an explicit flush. + // - In platforms using buffering when agile flushing is enabled, after one of the mid-frame flushes. + // - If platform doesn't use buffering and event accumulation is disabled. + // - If platform doesn't use buffering and the event type is not accumulable. + // However, it wouldn't be reasonable to ask users to remember the full ruleset and be aware at all times + // of the possibilites of the target platform, project settings and engine internals, which may change + // without prior notice. + // Therefore, the guideline is, "don't send the same event object more than once per frame". + WARN_PRINT_ONCE( + "An input event object is being parsed more than once in the same frame, which is unsafe.\n" + "If you are generating events in a script, you have to instantiate a new event instead of sending the same one more than once, unless the original one was sent on an earlier frame.\n" + "You can call duplicate() on the event to get a new instance with identical values."); + } else { + frame_parsed_events.insert(p_event); + } +#endif + if (use_accumulated_input) { if (buffered_events.empty() || !buffered_events.back()->get()->accumulate(p_event)) { buffered_events.push_back(p_event); diff --git a/main/input_default.h b/main/input_default.h index ab6cb3cd1fb..18238da2ae4 100644 --- a/main/input_default.h +++ b/main/input_default.h @@ -204,6 +204,11 @@ private: bool use_input_buffering; bool use_accumulated_input; +#ifdef DEBUG_ENABLED + Set> frame_parsed_events; + uint64_t last_parsed_frame = UINT64_MAX; +#endif + protected: struct VibrationInfo { float weak_magnitude;