Skip to main content

lotus_shared/
axis.rs

1//! Logische Controller-Achsen und Force Feedback, getrennt von Tastenaktionen.
2//!
3//! Logical controller axes and force feedback, separate from button actions.
4
5use serde::{Deserialize, Serialize};
6
7/// Achsenwert ohne Belegung und Ruhelage eines zentrierten Gebers.
8///
9/// Axis value without a binding, and the rest position of a centered control.
10pub const AXIS_CENTER: f32 = 0.5;
11
12/// Beschreibt eine Achse, die bei der Engine registriert werden kann.
13///
14/// Describes an axis that can be registered with the engine.
15#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
16pub struct RegisterAxis {
17    /// Eindeutige Achsen-ID für Scripts und die Belegung.
18    ///
19    /// Unique axis identifier used by scripts and bindings.
20    pub id: String,
21}
22
23impl RegisterAxis {
24    /// Erstellt einen neuen Registrierungseintrag für eine Achse.
25    ///
26    /// Creates a new axis registration entry.
27    pub fn new(id: impl Into<String>) -> Self {
28        Self { id: id.into() }
29    }
30}
31
32/// Rückstellkraft einer Achse.
33///
34/// Restoring force of an axis.
35///
36/// `coefficient`, `saturation` und `offset` liegen in `0..=1`.
37/// `offset` 0 lässt die Federmitte unverändert.
38#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
39pub struct SpringForce {
40    /// Steifigkeit der Feder.
41    ///
42    /// Spring stiffness.
43    pub coefficient: f32,
44    /// Obere Grenze der Kraft.
45    ///
46    /// Upper bound of the force.
47    pub saturation: f32,
48    /// Verschiebung der Federmitte.
49    ///
50    /// Shift of the spring center.
51    pub offset: f32,
52}
53
54/// Schwingung entlang einer Achse.
55///
56/// Oscillation along an axis.
57#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
58pub struct AxisVibration {
59    /// Stärke, `0` schaltet die Schwingung aus.
60    ///
61    /// Strength; `0` turns the oscillation off.
62    pub magnitude: f32,
63    /// Frequenz in Hertz.
64    ///
65    /// Frequency in hertz.
66    pub frequency_hz: f32,
67}
68
69/// Zuletzt gewünschtes Force Feedback einer logischen Achse.
70///
71/// Latest requested force feedback for one logical axis.
72#[derive(Debug, Clone, Copy, PartialEq, Default, Serialize, Deserialize)]
73pub struct AxisForceFeedback {
74    /// Feder. `None`, solange das Script noch keine gesetzt hat.
75    ///
76    /// Spring. `None` until the script sets one.
77    pub spring: Option<SpringForce>,
78    /// Reibung, `0` heißt aus.
79    ///
80    /// Friction; `0` means off.
81    pub friction: f32,
82    /// Schwingung. `None` heißt aus.
83    ///
84    /// Oscillation. `None` means off.
85    pub vibration: Option<AxisVibration>,
86}
87
88/// Begrenzt einen endlichen Wert auf `0..=1`. Nicht endliche Werte werden 0.
89///
90/// Clamps a finite value to `0..=1`. Non-finite values become 0.
91pub fn clamp_unit(value: f32) -> f32 {
92    if value.is_finite() {
93        value.clamp(0.0, 1.0)
94    } else {
95        0.0
96    }
97}
98
99/// Begrenzt eine Frequenz auf `>= 0`. Nicht endliche Werte werden 0.
100///
101/// Clamps a frequency to `>= 0`. Non-finite values become 0.
102pub fn clamp_frequency_hz(value: f32) -> f32 {
103    if value.is_finite() {
104        value.max(0.0)
105    } else {
106        0.0
107    }
108}