[3.x] Allow getting Input axis/vector values from multiple actions

For get_vector, use raw values and handle deadzones appropriately
This commit is contained in:
Aaron Franke
2021-07-22 21:02:18 -04:00
parent afa89c9eea
commit 69fb14256b
4 changed files with 82 additions and 2 deletions

View File

@ -61,6 +61,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_raw_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);
@ -125,10 +128,13 @@ void Input::_bind_methods() {
void Input::get_argument_options(const StringName &p_function, int p_idx, List<String> *r_options) const {
#ifdef TOOLS_ENABLED
const String quote_style = EDITOR_DEF("text_editor/completion/use_single_quotes", 0) ? "'" : "\"";
const String quote_style = EDITOR_DEF("text_editor/completion/use_single_quotes", false) ? "'" : "\"";
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_action_raw_strength" ||
pf == "get_axis" || pf == "get_vector")) {
List<PropertyInfo> pinfo;
ProjectSettings::get_singleton()->get_property_list(&pinfo);

View File

@ -87,6 +87,9 @@ public:
virtual float get_action_strength(const StringName &p_action) const = 0;
virtual float get_action_raw_strength(const StringName &p_action) const = 0;
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;
virtual float get_joy_axis(int p_device, int p_axis) const = 0;
virtual String get_joy_name(int p_idx) = 0;
virtual Array get_connected_joypads() = 0;

View File

@ -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]. On Android the unit of measurement for each axis is m/s² while on iOS and UWP it's a multiple of the Earth's gravitational acceleration [code]g[/code] (~9.81 m/s²).
</description>
</method>
<method name="get_action_raw_strength" qualifiers="const">
<return type="float">
</return>
<argument index="0" name="action" type="String">
</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="String">
</argument>
<argument index="1" name="positive_action" type="String">
</argument>
<description>
Get axis input by specifying two actions, one negative and one positive.
This is a shorthand 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="String">
</argument>
<argument index="1" name="positive_x" type="String">
</argument>
<argument index="2" name="negative_y" type="String">
</argument>
<argument index="3" name="positive_y" type="String">
</argument>
<argument index="4" name="deadzone" type="float" default="-1.0">
</argument>
<description>
Gets an input vector by specifying four actions for the positive and negative X and Y axes.
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>

View File

@ -158,6 +158,37 @@ float InputDefault::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 InputDefault::get_joy_axis(int p_device, int p_axis) const {
_THREAD_SAFE_METHOD_
int c = _combine_device(p_axis, p_device);