diff options
author | Rémi Verschelde <rverschelde@gmail.com> | 2023-01-31 15:56:43 +0100 |
---|---|---|
committer | Rémi Verschelde <rverschelde@gmail.com> | 2023-01-31 15:56:43 +0100 |
commit | 534369d2671133d1196a14af76f422105f152327 (patch) | |
tree | c84b32b2c1c01f180f67b3a013edfb448f352828 /core/input | |
parent | b8ef55a4277f0ac1dc48be40d56073942c86a99b (diff) | |
parent | a2af839a597f6662304da40faad5ded4f1506e03 (diff) |
Merge pull request #64423 from RandomShaper/safe_input_synth
Warn users about unsafe usage of `InputEvent`
Diffstat (limited to 'core/input')
-rw-r--r-- | core/input/input.cpp | 25 | ||||
-rw-r--r-- | core/input/input.h | 4 |
2 files changed, 29 insertions, 0 deletions
diff --git a/core/input/input.cpp b/core/input/input.cpp index 3cf83fd64b..aa89facdd7 100644 --- a/core/input/input.cpp +++ b/core/input/input.cpp @@ -891,6 +891,31 @@ void Input::parse_input_event(const Ref<InputEvent> &p_event) { ERR_FAIL_COND(p_event.is_null()); +#ifdef DEBUG_ENABLED + uint64_t curr_frame = Engine::get_singleton()->get_process_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.is_empty() || !buffered_events.back()->get()->accumulate(p_event)) { buffered_events.push_back(p_event); diff --git a/core/input/input.h b/core/input/input.h index f2de56b6b9..c254650ef8 100644 --- a/core/input/input.h +++ b/core/input/input.h @@ -223,6 +223,10 @@ private: void _parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_emulated); List<Ref<InputEvent>> buffered_events; +#ifdef DEBUG_ENABLED + HashSet<Ref<InputEvent>> frame_parsed_events; + uint64_t last_parsed_frame = UINT64_MAX; +#endif friend class DisplayServer; |