Browse Source

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.
lawnjelly 10 months ago
parent
commit
287bc6f41e
2 changed files with 30 additions and 0 deletions
  1. 16 0
      main/input_default.cpp
  2. 14 0
      main/input_default.h

+ 16 - 0
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<StringName, Action>::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<StringName, Action>::Element *E = action_state.find(p_action);
 	if (!E) {
@@ -327,6 +339,10 @@ void InputDefault::_parse_input_event_impl(const Ref<InputEvent> &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

+ 14 - 0
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,