diff options
-rw-r--r-- | core/input/input.cpp | 38 | ||||
-rw-r--r-- | core/input/input.h | 4 | ||||
-rw-r--r-- | core/input/input_map.cpp | 6 | ||||
-rw-r--r-- | core/input/input_map.h | 1 | ||||
-rw-r--r-- | doc/classes/Input.xml | 40 |
5 files changed, 87 insertions, 2 deletions
diff --git a/core/input/input.cpp b/core/input/input.cpp index ef02827468..a408cd674b 100644 --- a/core/input/input.cpp +++ b/core/input/input.cpp @@ -149,6 +149,9 @@ void Input::_bind_methods() { ClassDB::bind_method(D_METHOD("is_action_just_pressed", "action"), &Input::is_action_just_pressed); ClassDB::bind_method(D_METHOD("is_action_just_released", "action"), &Input::is_action_just_released); ClassDB::bind_method(D_METHOD("get_action_strength", "action"), &Input::get_action_strength); + ClassDB::bind_method(D_METHOD("get_action_raw_strength", "action"), &Input::get_action_strength); + ClassDB::bind_method(D_METHOD("get_axis", "negative_action", "positive_action"), &Input::get_axis); + ClassDB::bind_method(D_METHOD("get_vector", "negative_x", "positive_x", "negative_y", "positive_y", "deadzone"), &Input::get_vector, DEFVAL(-1.0f)); ClassDB::bind_method(D_METHOD("add_joy_mapping", "mapping", "update_existing"), &Input::add_joy_mapping, DEFVAL(false)); ClassDB::bind_method(D_METHOD("remove_joy_mapping", "guid"), &Input::remove_joy_mapping); ClassDB::bind_method(D_METHOD("joy_connection_changed", "device", "connected", "name", "guid"), &Input::joy_connection_changed); @@ -215,7 +218,9 @@ void Input::get_argument_options(const StringName &p_function, int p_idx, List<S const String quote_style = EDITOR_DEF("text_editor/completion/use_single_quotes", 0) ? "'" : "\""; String pf = p_function; - if (p_idx == 0 && (pf == "is_action_pressed" || pf == "action_press" || pf == "action_release" || pf == "is_action_just_pressed" || pf == "is_action_just_released" || pf == "get_action_strength")) { + if (p_idx == 0 && (pf == "is_action_pressed" || pf == "action_press" || pf == "action_release" || + pf == "is_action_just_pressed" || pf == "is_action_just_released" || + pf == "get_action_strength" || pf == "get_axis" || pf == "get_vector")) { List<PropertyInfo> pinfo; ProjectSettings::get_singleton()->get_property_list(&pinfo); @@ -335,6 +340,37 @@ float Input::get_action_raw_strength(const StringName &p_action) const { return E->get().raw_strength; } +float Input::get_axis(const StringName &p_negative_action, const StringName &p_positive_action) const { + return get_action_strength(p_positive_action) - get_action_strength(p_negative_action); +} + +Vector2 Input::get_vector(const StringName &p_negative_x, const StringName &p_positive_x, const StringName &p_negative_y, const StringName &p_positive_y, float p_deadzone) const { + Vector2 vector = Vector2( + get_action_raw_strength(p_positive_x) - get_action_raw_strength(p_negative_x), + get_action_raw_strength(p_positive_y) - get_action_raw_strength(p_negative_y)); + + if (p_deadzone < 0.0f) { + // If the deadzone isn't specified, get it from the average of the actions. + p_deadzone = (InputMap::get_singleton()->action_get_deadzone(p_positive_x) + + InputMap::get_singleton()->action_get_deadzone(p_negative_x) + + InputMap::get_singleton()->action_get_deadzone(p_positive_y) + + InputMap::get_singleton()->action_get_deadzone(p_negative_y)) / + 4; + } + + // Circular length limiting and deadzone. + float length = vector.length(); + if (length <= p_deadzone) { + return Vector2(); + } else if (length > 1.0f) { + return vector / length; + } else { + // Inverse lerp length to map (p_deadzone, 1) to (0, 1). + return vector * (Math::inverse_lerp(p_deadzone, 1.0f, length) / length); + } + return vector; +} + float Input::get_joy_axis(int p_device, int p_axis) const { _THREAD_SAFE_METHOD_ int c = _combine_device(p_axis, p_device); diff --git a/core/input/input.h b/core/input/input.h index 73a7870d6c..cbb884216a 100644 --- a/core/input/input.h +++ b/core/input/input.h @@ -224,7 +224,6 @@ private: JoyAxisList _get_output_axis(String output); void _button_event(int p_device, int p_index, bool p_pressed); void _axis_event(int p_device, int p_axis, float p_value); - float _handle_deadzone(int p_device, int p_axis, float p_value); void _parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_emulated); @@ -269,6 +268,9 @@ public: float get_action_strength(const StringName &p_action) const; float get_action_raw_strength(const StringName &p_action) const; + float get_axis(const StringName &p_negative_action, const StringName &p_positive_action) const; + Vector2 get_vector(const StringName &p_negative_x, const StringName &p_positive_x, const StringName &p_negative_y, const StringName &p_positive_y, float p_deadzone = -1.0f) const; + float get_joy_axis(int p_device, int p_axis) const; String get_joy_name(int p_idx); Array get_connected_joypads(); diff --git a/core/input/input_map.cpp b/core/input/input_map.cpp index 02013c8c9c..719667e7ab 100644 --- a/core/input/input_map.cpp +++ b/core/input/input_map.cpp @@ -118,6 +118,12 @@ bool InputMap::has_action(const StringName &p_action) const { return input_map.has(p_action); } +float InputMap::action_get_deadzone(const StringName &p_action) { + ERR_FAIL_COND_V_MSG(!input_map.has(p_action), 0.0f, "Request for nonexistent InputMap action '" + String(p_action) + "'."); + + return input_map[p_action].deadzone; +} + void InputMap::action_set_deadzone(const StringName &p_action, float p_deadzone) { ERR_FAIL_COND_MSG(!input_map.has(p_action), "Request for nonexistent InputMap action '" + String(p_action) + "'."); diff --git a/core/input/input_map.h b/core/input/input_map.h index 496773a19f..019a1056fb 100644 --- a/core/input/input_map.h +++ b/core/input/input_map.h @@ -70,6 +70,7 @@ public: void add_action(const StringName &p_action, float p_deadzone = 0.5); void erase_action(const StringName &p_action); + float action_get_deadzone(const StringName &p_action); void action_set_deadzone(const StringName &p_action, float p_deadzone); void action_add_event(const StringName &p_action, const Ref<InputEvent> &p_event); bool action_has_event(const StringName &p_action, const Ref<InputEvent> &p_event); diff --git a/doc/classes/Input.xml b/doc/classes/Input.xml index fb0ed8ff62..eafae7310c 100644 --- a/doc/classes/Input.xml +++ b/doc/classes/Input.xml @@ -54,6 +54,15 @@ [b]Note:[/b] This method only works on iOS, Android, and UWP. On other platforms, it always returns [constant Vector3.ZERO]. </description> </method> + <method name="get_action_raw_strength" qualifiers="const"> + <return type="float"> + </return> + <argument index="0" name="action" type="StringName"> + </argument> + <description> + Returns a value between 0 and 1 representing the raw intensity of the given action, ignoring the action's deadzone. In most cases, you should use [method get_action_strength] instead. + </description> + </method> <method name="get_action_strength" qualifiers="const"> <return type="float"> </return> @@ -63,6 +72,18 @@ Returns a value between 0 and 1 representing the intensity of the given action. In a joypad, for example, the further away the axis (analog sticks or L2, R2 triggers) is from the dead zone, the closer the value will be to 1. If the action is mapped to a control that has no axis as the keyboard, the value returned will be 0 or 1. </description> </method> + <method name="get_axis" qualifiers="const"> + <return type="float"> + </return> + <argument index="0" name="negative_action" type="StringName"> + </argument> + <argument index="1" name="positive_action" type="StringName"> + </argument> + <description> + Get axis input by specifying two actions, one negative and one positive. + This is a horthand for writing [code]Input.get_action_strength("positive_action") - Input.get_action_strength("negative_action")[/code]. + </description> + </method> <method name="get_connected_joypads"> <return type="Array"> </return> @@ -205,6 +226,25 @@ Returns the mouse mode. See the constants for more information. </description> </method> + <method name="get_vector" qualifiers="const"> + <return type="Vector2"> + </return> + <argument index="0" name="negative_x" type="StringName"> + </argument> + <argument index="1" name="positive_x" type="StringName"> + </argument> + <argument index="2" name="negative_y" type="StringName"> + </argument> + <argument index="3" name="positive_y" type="StringName"> + </argument> + <argument index="4" name="deadzone" type="float" default="-1.0"> + </argument> + <description> + Get vector input by specifying four actions, two for the X axis and two for the Y axis, negative and positive. + This method is useful when getting vector input, such as from a joystick, directional pad, arrows, or WASD. The vector has its length limited to 1 and has a circular deadzone, which is useful for using vector input as movement. + By default, the deadzone is automatically calculated from the average of the action deadzones. However, you can override the deadzone to be whatever you want (on the range of 0 to 1). + </description> + </method> <method name="is_action_just_pressed" qualifiers="const"> <return type="bool"> </return> |