Browse Source

Fix Keyboard Input Hangs when using modifiers

Main input parsing loop only update actions for keyboard if the state has changed.
`InputMap::event_is_action` now ignores keyboard modifiers if the event is not pressed.
Clarify difference between `InputMap::action_has_event` and `InputMap::event_is_action` in docs.

Fixes #6388.
Fabio Alessandrelli 8 years ago
parent
commit
17d7e6a142
4 changed files with 12 additions and 12 deletions
  1. 3 3
      core/input_map.cpp
  2. 1 1
      core/input_map.h
  3. 1 1
      doc/base/classes.xml
  4. 7 7
      main/input_default.cpp

+ 3 - 3
core/input_map.cpp

@@ -106,7 +106,7 @@ List<StringName> InputMap::get_actions() const {
 	return actions;
 	return actions;
 }
 }
 
 
-List<InputEvent>::Element *InputMap::_find_event(List<InputEvent> &p_list,const InputEvent& p_event) const {
+List<InputEvent>::Element *InputMap::_find_event(List<InputEvent> &p_list,const InputEvent& p_event, bool p_mod_ignore=false) const {
 
 
 	for (List<InputEvent>::Element *E=p_list.front();E;E=E->next()) {
 	for (List<InputEvent>::Element *E=p_list.front();E;E=E->next()) {
 
 
@@ -122,7 +122,7 @@ List<InputEvent>::Element *InputMap::_find_event(List<InputEvent> &p_list,const
 
 
 			case InputEvent::KEY: {
 			case InputEvent::KEY: {
 
 
-				same=(e.key.scancode==p_event.key.scancode && e.key.mod == p_event.key.mod);
+				same=(e.key.scancode==p_event.key.scancode && (p_mod_ignore || e.key.mod == p_event.key.mod));
 
 
 			} break;
 			} break;
 			case InputEvent::JOYSTICK_BUTTON: {
 			case InputEvent::JOYSTICK_BUTTON: {
@@ -229,7 +229,7 @@ bool InputMap::event_is_action(const InputEvent& p_event, const StringName& p_ac
 		return p_event.action.action==E->get().id;
 		return p_event.action.action==E->get().id;
 	}
 	}
 
 
-	return _find_event(E->get().inputs,p_event)!=NULL;
+	return _find_event(E->get().inputs,p_event,!p_event.is_pressed())!=NULL;
 }
 }
 
 
 const Map<StringName, InputMap::Action>& InputMap::get_action_map() const {
 const Map<StringName, InputMap::Action>& InputMap::get_action_map() const {

+ 1 - 1
core/input_map.h

@@ -46,7 +46,7 @@ private:
 	mutable Map<StringName, Action> input_map;
 	mutable Map<StringName, Action> input_map;
 	mutable Map<int,StringName> input_id_map;
 	mutable Map<int,StringName> input_id_map;
 
 
-	List<InputEvent>::Element *_find_event(List<InputEvent> &p_list,const InputEvent& p_event) const;
+	List<InputEvent>::Element *_find_event(List<InputEvent> &p_list,const InputEvent& p_event, bool p_mod_ignore) const;
 
 
 	Array _get_action_list(const StringName& p_action);
 	Array _get_action_list(const StringName& p_action);
 	Array _get_actions();
 	Array _get_actions();

+ 1 - 1
doc/base/classes.xml

@@ -18019,7 +18019,7 @@
 			<argument index="1" name="action" type="String">
 			<argument index="1" name="action" type="String">
 			</argument>
 			</argument>
 			<description>
 			<description>
-				Return whether the given event is part of an existing action.
+				Return whether the given event is part of an existing action. This method ignores keyboard modifiers if the given [InputEvent] is not pressed (for proper release detection). See [method action_has_event] if you don't want this behavior.
 			</description>
 			</description>
 		</method>
 		</method>
 		<method name="get_action_from_id" qualifiers="const">
 		<method name="get_action_from_id" qualifiers="const">

+ 7 - 7
main/input_default.cpp

@@ -377,13 +377,13 @@ void InputDefault::parse_input_event(const InputEvent& p_event) {
 
 
 			if (InputMap::get_singleton()->event_is_action(p_event,E->key())) {
 			if (InputMap::get_singleton()->event_is_action(p_event,E->key())) {
 
 
-				Action action;
-				action.fixed_frame=OS::get_singleton()->get_fixed_frames();
-				action.idle_frame=OS::get_singleton()->get_idle_frames();
-				action.pressed=p_event.is_pressed();
-
-				action_state[E->key()]=action;
-
+				if(is_action_pressed(E->key()) != p_event.is_pressed()) {
+					Action action;
+					action.fixed_frame=OS::get_singleton()->get_fixed_frames();
+					action.idle_frame=OS::get_singleton()->get_idle_frames();
+					action.pressed=p_event.is_pressed();
+					action_state[E->key()]=action;
+				}
 			}
 			}
 		}
 		}
 	}
 	}