viewport_lib/interaction/input/
query.rs1use super::binding::{ActivationMode, KeyCode, Modifiers, MouseButton, TriggerKind};
2use std::collections::HashSet;
3
4#[derive(Debug, Clone)]
9pub struct FrameInput {
10 pub keys_pressed: HashSet<KeyCode>,
12 pub keys_held: HashSet<KeyCode>,
14 pub modifiers: Modifiers,
16 pub drag_started: HashSet<MouseButton>,
18 pub dragging: HashSet<MouseButton>,
20 pub drag_delta: glam::Vec2,
22 pub scroll_delta: f32,
24 pub clicked: HashSet<MouseButton>,
26 pub pointer_delta: glam::Vec2,
29 pub hovered: bool,
31 pub ctrl_scroll_orbit_delta: glam::Vec2,
35 pub shift_scroll_pan_delta: glam::Vec2,
38}
39
40impl Default for FrameInput {
41 fn default() -> Self {
42 Self {
43 keys_pressed: Default::default(),
44 keys_held: Default::default(),
45 modifiers: Default::default(),
46 drag_started: Default::default(),
47 dragging: Default::default(),
48 drag_delta: glam::Vec2::ZERO,
49 scroll_delta: 0.0,
50 clicked: Default::default(),
51 pointer_delta: glam::Vec2::ZERO,
52 hovered: false,
53 ctrl_scroll_orbit_delta: glam::Vec2::ZERO,
54 shift_scroll_pan_delta: glam::Vec2::ZERO,
55 }
56 }
57}
58
59#[derive(Debug, Clone, Copy, PartialEq)]
61pub enum ActionState {
62 Inactive,
64 Pressed,
66 Active {
68 delta: glam::Vec2,
70 },
71}
72
73impl ActionState {
74 pub fn pressed(self) -> bool {
76 matches!(self, ActionState::Pressed)
77 }
78
79 pub fn is_active(self) -> bool {
81 !matches!(self, ActionState::Inactive)
82 }
83
84 pub fn delta(self) -> glam::Vec2 {
86 match self {
87 ActionState::Active { delta } => delta,
88 _ => glam::Vec2::ZERO,
89 }
90 }
91}
92
93pub(crate) fn modifiers_match(required: &Modifiers, current: &Modifiers, ignore: bool) -> bool {
95 if ignore {
96 return true;
97 }
98 required == current
99}
100
101pub(crate) fn evaluate_trigger(
103 kind: &TriggerKind,
104 activation: &ActivationMode,
105 required_mods: &Modifiers,
106 ignore_mods: bool,
107 input: &FrameInput,
108) -> ActionState {
109 if !modifiers_match(required_mods, &input.modifiers, ignore_mods) {
110 return ActionState::Inactive;
111 }
112
113 match (kind, activation) {
114 (TriggerKind::Key(key), ActivationMode::OnPress) => {
115 if input.keys_pressed.contains(key) {
116 ActionState::Pressed
117 } else {
118 ActionState::Inactive
119 }
120 }
121 (TriggerKind::Key(key), ActivationMode::WhileHeld) => {
122 if input.keys_held.contains(key) {
123 ActionState::Active {
124 delta: glam::Vec2::ZERO,
125 }
126 } else {
127 ActionState::Inactive
128 }
129 }
130 (TriggerKind::MouseButton(btn), ActivationMode::OnPress) => {
131 if input.clicked.contains(btn) {
132 ActionState::Pressed
133 } else {
134 ActionState::Inactive
135 }
136 }
137 (TriggerKind::MouseButton(btn), ActivationMode::OnDrag) => {
138 if input.dragging.contains(btn) {
139 ActionState::Active {
140 delta: input.drag_delta,
141 }
142 } else {
143 ActionState::Inactive
144 }
145 }
146 (TriggerKind::Scroll, ActivationMode::OnScroll) => {
147 if input.scroll_delta.abs() > 0.0 {
148 ActionState::Active {
149 delta: glam::Vec2::new(0.0, input.scroll_delta),
150 }
151 } else {
152 ActionState::Inactive
153 }
154 }
155 _ => ActionState::Inactive,
156 }
157}