Forráskód Böngészése

Merge pull request #64424 from RandomShaper/safe_input_synth_3.x

[3.x] Warn users about unsafe usage of `InputEvent`
Rémi Verschelde 2 éve
szülő
commit
617f5c5580
2 módosított fájl, 30 hozzáadás és 0 törlés
  1. 25 0
      main/input_default.cpp
  2. 5 0
      main/input_default.h

+ 25 - 0
main/input_default.cpp

@@ -708,6 +708,31 @@ void InputDefault::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_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);

+ 5 - 0
main/input_default.h

@@ -204,6 +204,11 @@ private:
 	bool use_input_buffering;
 	bool use_accumulated_input;
 
+#ifdef DEBUG_ENABLED
+	Set<Ref<InputEvent>> frame_parsed_events;
+	uint64_t last_parsed_frame = UINT64_MAX;
+#endif
+
 protected:
 	struct VibrationInfo {
 		float weak_magnitude;