diff --git a/rootfs/usr/share/inputplumber/schema/capability_map_v2.json b/rootfs/usr/share/inputplumber/schema/capability_map_v2.json index 17b32032..38d21393 100644 --- a/rootfs/usr/share/inputplumber/schema/capability_map_v2.json +++ b/rootfs/usr/share/inputplumber/schema/capability_map_v2.json @@ -67,6 +67,7 @@ "type": "object", "properties": { "deadzone": { + "description": "A value from 0.0-1.0 of how far an axis should be pressed in a particular direction\nin order for it to be considered \"pressed\"", "type": [ "number", "null" @@ -74,13 +75,28 @@ "format": "double" }, "direction": { + "description": "Direction of the axis to translate. Can be one of [\"vertical\", \"horizontal\", \"left\",\n\"right\", \"up\", \"down\"].", "type": [ "string", "null" ] }, + "invert": { + "description": "Invert all values of this axis with the matching direction", + "type": [ + "boolean", + "null" + ] + }, "name": { "type": "string" + }, + "quadratic_scaling": { + "description": "Use quadratic scaling for more precise control with small stick movements", + "type": [ + "boolean", + "null" + ] } }, "required": [ @@ -1430,4 +1446,4 @@ ] } } -} \ No newline at end of file +} diff --git a/src/config/capability_map.rs b/src/config/capability_map.rs index 5835aef8..e54a988e 100644 --- a/src/config/capability_map.rs +++ b/src/config/capability_map.rs @@ -222,12 +222,20 @@ pub struct GamepadCapability { #[serde(rename_all = "snake_case")] pub struct AxisCapability { pub name: String, + /// Direction of the axis to translate. Can be one of ["vertical", "horizontal", "left", + /// "right", "up", "down"]. #[serde(skip_serializing_if = "Option::is_none")] pub direction: Option, + /// A value from 0.0-1.0 of how far an axis should be pressed in a particular direction + /// in order for it to be considered "pressed" #[serde(skip_serializing_if = "Option::is_none")] pub deadzone: Option, + /// Use quadratic scaling for more precise control with small stick movements #[serde(skip_serializing_if = "Option::is_none")] pub quadratic_scaling: Option, + /// Invert all values of this axis with the matching direction + #[serde(skip_serializing_if = "Option::is_none")] + pub invert: Option, } #[derive(Debug, Deserialize, Serialize, Clone, JsonSchema, PartialEq)] diff --git a/src/input/event/value.rs b/src/input/event/value.rs index 1685f66f..be091606 100644 --- a/src/input/event/value.rs +++ b/src/input/event/value.rs @@ -253,19 +253,32 @@ impl InputValue { .and_then(|gamepad| gamepad.axis.as_ref()) .and_then(|axis| axis.quadratic_scaling) .unwrap_or(false); + let use_inverse_value = target_config + .gamepad + .as_ref() + .and_then(|gamepad| gamepad.axis.as_ref()) + .and_then(|axis| axis.invert) + .unwrap_or(false); - match use_scaling { - false => Ok(self.clone()), - true => match self { - InputValue::Vector2 { x, y } => { - let scaled_x = x.map(|v| v * v.abs()); - let scaled_y = y.map(|v| v * v.abs()); - Ok(InputValue::Vector2 { x: scaled_x, y: scaled_y }) - }, - _ => Ok(self.clone()), - }, + match self { + InputValue::Vector2 { x, y } => { + let (mut value_x, mut value_y) = (*x, *y); + if use_inverse_value { + value_x = value_x.map(|v| -v); + value_y = value_y.map(|v| -v); + } + if use_scaling { + value_x = value_x.map(|v| v * v.abs()); + value_y = value_y.map(|v| v * v.abs()); + } + Ok(InputValue::Vector2 { + x: value_x, + y: value_y, + }) + } + _ => Ok(self.clone()), } - }, + } // Axis -> Trigger Gamepad::Trigger(_) => Err(TranslationError::NotImplemented), // Axis -> Accelerometer