You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-21 14:57:09 +00:00
Merge pull request #64423 from RandomShaper/safe_input_synth
Warn users about unsafe usage of `InputEvent`
This commit is contained in:
@@ -891,6 +891,31 @@ void Input::parse_input_event(const Ref<InputEvent> &p_event) {
|
|||||||
|
|
||||||
ERR_FAIL_COND(p_event.is_null());
|
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 (use_accumulated_input) {
|
||||||
if (buffered_events.is_empty() || !buffered_events.back()->get()->accumulate(p_event)) {
|
if (buffered_events.is_empty() || !buffered_events.back()->get()->accumulate(p_event)) {
|
||||||
buffered_events.push_back(p_event);
|
buffered_events.push_back(p_event);
|
||||||
|
|||||||
@@ -223,6 +223,10 @@ private:
|
|||||||
void _parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_emulated);
|
void _parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_emulated);
|
||||||
|
|
||||||
List<Ref<InputEvent>> buffered_events;
|
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;
|
friend class DisplayServer;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user