euv_engine/input/fn.rs
1use super::*;
2
3/// Applies the analog deadzone to a single raw axis reading.
4///
5/// A reading at or inside the deadzone band reports `0.0`; a reading
6/// beyond it is rescaled so the usable range still reaches `1.0` at
7/// full deflection. Sign is preserved, so a stick pushed left stays
8/// negative.
9///
10/// # Arguments
11///
12/// - `f64` - The raw axis reading as reported by the browser.
13///
14/// # Returns
15///
16/// - `f64` - The deadzone-corrected reading, centered inside the band.
17pub fn apply_axis_deadzone(value: f64) -> f64 {
18 let magnitude: f64 = value.abs();
19 if magnitude <= INPUT_GAMEPAD_AXIS_DEADZONE {
20 return 0.0;
21 }
22 // Phase 1: rescale the post-deadzone span back onto the full range.
23 let span: f64 = 1.0 - INPUT_GAMEPAD_AXIS_DEADZONE;
24 let normalized: f64 = (magnitude - INPUT_GAMEPAD_AXIS_DEADZONE) / span;
25 value.signum() * normalized.min(1.0)
26}
27
28/// Folds one frame of raw gamepad readings into the per-pad edge sets.
29///
30/// This is the DOM-free half of a poll: it takes the previous frame's
31/// held set and this frame's raw button pressures, and recomputes
32/// pressed / held / released exactly the way [`InputState::press_key`]
33/// and [`InputState::release_key`] do for keys. A button counts as
34/// down when its pressure is at least half, which makes digital
35/// buttons (`0.0` / `1.0`) and analog triggers agree.
36///
37/// # Arguments
38///
39/// - `&GamepadButtonSet` - The previous frame's held button indices.
40/// - `&[f64]` - This frame's raw button pressure per button index.
41///
42/// # Returns
43///
44/// - `GamepadButtonSet` - The buttons newly pressed on this frame.
45pub fn compute_pressed_buttons(
46 previous_held: &GamepadButtonSet,
47 values: &[f64],
48) -> GamepadButtonSet {
49 let mut pressed: GamepadButtonSet = GamepadButtonSet::new();
50 for (index, value) in values.iter().enumerate() {
51 let button: u32 = index as u32;
52 if is_button_down(*value) && !previous_held.contains(&button) {
53 pressed.insert(button);
54 }
55 }
56 pressed
57}
58
59/// Folds one frame of raw gamepad readings into the per-pad edge sets.
60///
61/// The held set this frame is every button at or above half pressure;
62/// the released set is every button that was held last frame and is
63/// no longer down, which is what a caller polls with to fire a
64/// one-shot action on button-up.
65///
66/// # Arguments
67///
68/// - `&GamepadButtonSet` - The previous frame's held button indices.
69/// - `&[f64]` - This frame's raw button pressure per button index.
70///
71/// # Returns
72///
73/// - `GamepadButtonSet` - The buttons that came up on this frame.
74pub fn compute_released_buttons(
75 previous_held: &GamepadButtonSet,
76 values: &[f64],
77) -> GamepadButtonSet {
78 let mut released: GamepadButtonSet = GamepadButtonSet::new();
79 for button in previous_held.iter() {
80 let slot: usize = *button as usize;
81 let value: f64 = values.get(slot).copied().unwrap_or(0.0);
82 if !is_button_down(value) {
83 released.insert(*button);
84 }
85 }
86 released
87}
88
89/// Folds one frame of raw gamepad readings into the per-pad edge sets.
90///
91/// # Arguments
92///
93/// - `&[f64]` - This frame's raw button pressure per button index.
94///
95/// # Returns
96///
97/// - `GamepadButtonSet` - Every button currently down this frame.
98pub fn compute_held_buttons(values: &[f64]) -> GamepadButtonSet {
99 let mut held: GamepadButtonSet = GamepadButtonSet::new();
100 for (index, value) in values.iter().enumerate() {
101 if is_button_down(*value) {
102 held.insert(index as u32);
103 }
104 }
105 held
106}
107
108/// Tests whether one raw button pressure counts as the button being down.
109///
110/// The threshold is one half so that a digital button reporting
111/// `1.0` and an analog trigger crossing its midpoint agree.
112///
113/// # Arguments
114///
115/// - `f64` - The raw button pressure as reported by the browser.
116///
117/// # Returns
118///
119/// - `bool` - True when the pressure reaches the press threshold.
120pub fn is_button_down(value: f64) -> bool {
121 value >= GAMEPAD_BUTTON_PRESS_THRESHOLD
122}
123
124/// Reads the nth analog axis out of a raw axis reading list.
125///
126/// # Arguments
127///
128/// - `&[f64]` - The raw axis readings as reported by the browser.
129/// - `u32` - The axis index to read.
130///
131/// # Returns
132///
133/// - `f64` - The raw reading, or `0.0` when the pad has no such axis.
134pub fn read_raw_axis(axes: &[f64], axis: u32) -> f64 {
135 axes.get(axis as usize).copied().unwrap_or(0.0)
136}