spitfire_gui/
interactions.rs1use raui_core::prelude::*;
2use spitfire_input::{ArrayInputCombinator, InputActionRef, InputCharactersRef};
3
4const ZERO_THRESHOLD: f32 = 1.0e-6;
5
6#[derive(Default)]
7pub struct GuiInteractionsInputs {
8 pub trigger: InputActionRef,
9 pub context: InputActionRef,
10 pub cancel: InputActionRef,
11 pub left: InputActionRef,
12 pub right: InputActionRef,
13 pub up: InputActionRef,
14 pub down: InputActionRef,
15 pub prev: InputActionRef,
16 pub next: InputActionRef,
17 pub text: InputCharactersRef,
18 pub text_start: InputActionRef,
19 pub text_end: InputActionRef,
20 pub text_delete_left: InputActionRef,
21 pub text_delete_right: InputActionRef,
22 pub pointer_position: ArrayInputCombinator<2>,
23 pub pointer_trigger: InputActionRef,
24 pub pointer_context: InputActionRef,
25 pub scroll: ArrayInputCombinator<2>,
26}
27
28#[derive(Default)]
29pub struct GuiInteractionsEngine {
30 pub inputs: GuiInteractionsInputs,
31 pub engine: DefaultInteractionsEngine,
32 cached_pointer_position: Vec2,
33}
34
35impl GuiInteractionsEngine {
36 pub fn maintain(&mut self, mapping: &CoordsMapping) {
37 if self.engine.focused_text_input().is_some() {
38 if let Some(mut text) = self.inputs.text.write() {
39 for character in text.take().chars() {
40 self.engine
41 .interact(Interaction::Navigate(NavSignal::TextChange(
42 NavTextChange::InsertCharacter(character),
43 )));
44 }
45 }
46 if self.inputs.left.get().is_pressed() {
47 self.engine
48 .interact(Interaction::Navigate(NavSignal::TextChange(
49 NavTextChange::MoveCursorLeft,
50 )));
51 }
52 if self.inputs.right.get().is_pressed() {
53 self.engine
54 .interact(Interaction::Navigate(NavSignal::TextChange(
55 NavTextChange::MoveCursorRight,
56 )));
57 }
58 if self.inputs.text_start.get().is_pressed() {
59 self.engine
60 .interact(Interaction::Navigate(NavSignal::TextChange(
61 NavTextChange::MoveCursorStart,
62 )));
63 }
64 if self.inputs.text_end.get().is_pressed() {
65 self.engine
66 .interact(Interaction::Navigate(NavSignal::TextChange(
67 NavTextChange::MoveCursorEnd,
68 )));
69 }
70 if self.inputs.text_delete_left.get().is_pressed() {
71 self.engine
72 .interact(Interaction::Navigate(NavSignal::TextChange(
73 NavTextChange::DeleteLeft,
74 )));
75 }
76 if self.inputs.text_delete_right.get().is_pressed() {
77 self.engine
78 .interact(Interaction::Navigate(NavSignal::TextChange(
79 NavTextChange::DeleteRight,
80 )));
81 }
82 if self.inputs.trigger.get().is_pressed() {
83 self.engine
84 .interact(Interaction::Navigate(NavSignal::TextChange(
85 NavTextChange::NewLine,
86 )));
87 }
88 } else {
89 if self.inputs.up.get().is_pressed() {
90 self.engine.interact(Interaction::Navigate(NavSignal::Up));
91 }
92 if self.inputs.down.get().is_pressed() {
93 self.engine.interact(Interaction::Navigate(NavSignal::Down));
94 }
95 if self.inputs.left.get().is_pressed() {
96 self.engine.interact(Interaction::Navigate(NavSignal::Left));
97 }
98 if self.inputs.right.get().is_pressed() {
99 self.engine
100 .interact(Interaction::Navigate(NavSignal::Right));
101 }
102 if self.inputs.prev.get().is_pressed() {
103 self.engine.interact(Interaction::Navigate(NavSignal::Prev));
104 }
105 if self.inputs.next.get().is_pressed() {
106 self.engine.interact(Interaction::Navigate(NavSignal::Next));
107 }
108 if self.inputs.trigger.get().is_pressed() {
109 self.engine
110 .interact(Interaction::Navigate(NavSignal::Accept(true)));
111 }
112 if self.inputs.context.get().is_pressed() {
113 self.engine
114 .interact(Interaction::Navigate(NavSignal::Context(true)));
115 }
116 if self.inputs.cancel.get().is_pressed() {
117 self.engine
118 .interact(Interaction::Navigate(NavSignal::Cancel(true)));
119 }
120 }
121 let pointer_position = {
122 let [x, y] = self.inputs.pointer_position.get();
123 let position = mapping.real_to_virtual_vec2(Vec2 { x, y }, false);
124 if (position.x - self.cached_pointer_position.x).abs() > ZERO_THRESHOLD
125 || (position.y - self.cached_pointer_position.y).abs() > ZERO_THRESHOLD
126 {
127 self.cached_pointer_position = position;
128 self.engine.interact(Interaction::PointerMove(position));
129 }
130 position
131 };
132 let pointer_trigger = self.inputs.pointer_trigger.get();
133 let pointer_context = self.inputs.pointer_context.get();
134 if pointer_trigger.is_pressed() {
135 self.engine.interact(Interaction::PointerDown(
136 PointerButton::Trigger,
137 pointer_position,
138 ));
139 }
140 if pointer_trigger.is_released() {
141 self.engine.interact(Interaction::PointerUp(
142 PointerButton::Trigger,
143 pointer_position,
144 ));
145 }
146 if pointer_context.is_pressed() {
147 self.engine.interact(Interaction::PointerDown(
148 PointerButton::Context,
149 pointer_position,
150 ));
151 }
152 if pointer_context.is_released() {
153 self.engine.interact(Interaction::PointerUp(
154 PointerButton::Context,
155 pointer_position,
156 ));
157 }
158 {
159 let [x, y] = self.inputs.scroll.get();
160 if x.abs() > ZERO_THRESHOLD || y.abs() > ZERO_THRESHOLD {
161 self.engine
162 .interact(Interaction::Navigate(NavSignal::Jump(NavJump::Scroll(
163 NavScroll::Units(Vec2 { x: -x, y: -y }, true),
164 ))));
165 }
166 }
167 }
168}
169
170impl InteractionsEngine<DefaultInteractionsEngineResult, ()> for GuiInteractionsEngine {
171 fn perform_interactions(
172 &mut self,
173 app: &mut Application,
174 ) -> Result<DefaultInteractionsEngineResult, ()> {
175 self.engine.perform_interactions(app)
176 }
177}