Skip to main content

ustreamer_input/
lib.rs

1//! Browser input event bridge.
2//!
3//! Decodes compact binary input events from the browser and maps them
4//! to abstract application actions. Consumers define their own action types
5//! and mapping logic; this crate provides the raw event decode and a
6//! default mapper with common 3D/2D interaction patterns.
7
8use ustreamer_proto::input::InputEvent;
9
10/// Abstract application action produced by the input mapper.
11/// These cover common interaction patterns for 3D/2D applications.
12/// Consumers can extend or replace these with domain-specific actions.
13#[derive(Debug, Clone)]
14pub enum AppAction {
15    /// Camera orbit / rotation (e.g., left-drag in a 3D viewport).
16    Rotate { dx: f32, dy: f32 },
17    /// Camera zoom (e.g., scroll or middle-drag).
18    Zoom { delta: f32 },
19    /// Camera pan / translate.
20    Pan { dx: f32, dy: f32 },
21    /// Discrete scroll through items (e.g., layers, frames, slices).
22    ScrollStep { delta: i32 },
23    /// Two-axis parameter adjustment via drag (e.g., brightness/contrast).
24    DragAdjust { dx: f32, dy: f32 },
25    /// Raw pointer position update (for cursor overlay rendering).
26    PointerUpdate { x: f32, y: f32 },
27}
28
29/// Maps raw browser input events to application actions based on the current interaction mode.
30pub struct InputMapper {
31    mode: InteractionMode,
32    last_x: f32,
33    last_y: f32,
34    buttons: u8,
35}
36
37/// Interaction modes that determine how pointer drags are interpreted.
38#[derive(Debug, Clone, Copy, PartialEq, Eq)]
39pub enum InteractionMode {
40    Rotate,
41    Pan,
42    Zoom,
43    Scroll,
44    /// Two-axis parameter adjustment via drag.
45    DragAdjust,
46}
47
48impl Default for InputMapper {
49    fn default() -> Self {
50        Self {
51            mode: InteractionMode::Rotate,
52            last_x: 0.0,
53            last_y: 0.0,
54            buttons: 0,
55        }
56    }
57}
58
59impl InputMapper {
60    pub fn set_mode(&mut self, mode: InteractionMode) {
61        self.mode = mode;
62    }
63
64    /// Process a raw input event and return zero or more application actions.
65    pub fn process(&mut self, event: &InputEvent) -> Vec<AppAction> {
66        match event {
67            InputEvent::PointerMove { x, y, buttons, .. } => {
68                let dx = x - self.last_x;
69                let dy = y - self.last_y;
70                self.last_x = *x;
71                self.last_y = *y;
72                self.buttons = *buttons;
73
74                let mut actions = vec![AppAction::PointerUpdate { x: *x, y: *y }];
75
76                // Left button drag → mode-dependent action
77                if *buttons & 1 != 0 {
78                    match self.mode {
79                        InteractionMode::Rotate => {
80                            actions.push(AppAction::Rotate { dx, dy });
81                        }
82                        InteractionMode::Pan => {
83                            actions.push(AppAction::Pan { dx, dy });
84                        }
85                        InteractionMode::Zoom => {
86                            actions.push(AppAction::Zoom { delta: dy });
87                        }
88                        InteractionMode::DragAdjust => {
89                            actions.push(AppAction::DragAdjust { dx, dy });
90                        }
91                        InteractionMode::Scroll => {}
92                    }
93                }
94
95                actions
96            }
97            InputEvent::Scroll { delta_y, .. } => {
98                vec![AppAction::ScrollStep {
99                    delta: if *delta_y > 0.0 { 1 } else { -1 },
100                }]
101            }
102            InputEvent::PointerDown { x, y, .. } => {
103                self.last_x = *x;
104                self.last_y = *y;
105                vec![]
106            }
107            _ => vec![],
108        }
109    }
110}