1pub use egui;
2
3use geng::prelude::*;
4
5mod painter;
6
7use painter::*;
8
9pub struct EguiGeng {
11 geng: Geng,
12 egui_ctx: egui::CtxRef,
13 egui_input: egui::RawInput,
14 painter: Painter,
15 shapes: Option<Vec<egui::epaint::ClippedShape>>,
16 screen_height: f32,
17}
18
19impl EguiGeng {
20 pub fn new(geng: &Geng) -> Self {
21 Self {
22 geng: geng.clone(),
23 egui_ctx: egui::CtxRef::default(),
24 egui_input: egui::RawInput::default(),
25 painter: Painter::new(geng),
26 shapes: None,
27 screen_height: 1.0,
28 }
29 }
30
31 pub fn get_context(&self) -> &egui::CtxRef {
33 &self.egui_ctx
34 }
35
36 pub fn begin_frame(&mut self) {
39 self.gather_input();
40 self.egui_ctx.begin_frame(self.egui_input.take());
41 }
42
43 pub fn end_frame(&mut self) {
46 let (_output, shapes) = self.egui_ctx.end_frame();
47 if self.shapes.is_some() {
48 error!("Egui contents have not been drawn. Ensure to call `draw` after `end_frame`");
49 }
50 self.shapes = Some(shapes);
51
52 }
54
55 pub fn draw(&mut self, framebuffer: &mut ugli::Framebuffer) {
57 let framebuffer_size = framebuffer.size().map(|x| x as f32);
59 self.screen_height = framebuffer_size.y;
60 self.egui_input.screen_rect = Some(egui::Rect::from_min_size(
61 egui::Pos2::ZERO,
62 egui::Vec2::new(framebuffer_size.x, framebuffer_size.y),
63 ));
64
65 if let Some(shapes) = self.shapes.take() {
67 let paint_jobs = self.egui_ctx.tessellate(shapes);
68 self.painter
69 .paint(framebuffer, paint_jobs, &self.egui_ctx.texture());
70 } else {
71 error!("Failed to draw egui. Ensure to call `draw` after `end_frame`");
72 }
73 }
74
75 pub fn handle_event(&mut self, event: geng::Event) {
77 match event {
78 geng::Event::Wheel { delta } => {
79 if self.geng.window().is_key_pressed(geng::Key::LShift) {
80 self.egui_input.scroll_delta = egui::Vec2::new(delta as f32, 0.0);
81 } else {
82 self.egui_input.scroll_delta = egui::Vec2::new(0.0, delta as f32);
83 }
84 }
85 geng::Event::KeyDown { key } => {
86 if let Some(key) = egui_key(key) {
87 let modifiers = self.get_modifiers();
88 self.egui_input.events.push(egui::Event::Key {
89 key,
90 modifiers,
91 pressed: true,
92 });
93 if let Some(mut symbol) = key_char(key) {
94 if modifiers.shift {
95 symbol = symbol.to_uppercase().next().unwrap();
96 }
97 self.egui_input
98 .events
99 .push(egui::Event::Text(symbol.to_string()));
100 }
101 }
102 }
103 geng::Event::KeyUp { key } => {
104 if let Some(key) = egui_key(key) {
105 self.egui_input.events.push(egui::Event::Key {
106 key,
107 modifiers: self.get_modifiers(),
108 pressed: false,
109 });
110 }
111 }
112 geng::Event::MouseDown { position, button } => {
113 let button = egui_button(button);
114 self.egui_input.events.push(egui::Event::PointerButton {
115 pos: self.mouse_to_pos(position),
116 button,
117 pressed: true,
118 modifiers: self.get_modifiers(),
119 });
120 }
121 geng::Event::MouseMove { position, .. } => {
122 self.egui_input
123 .events
124 .push(egui::Event::PointerMoved(self.mouse_to_pos(position)));
125 }
126 geng::Event::MouseUp { position, button } => {
127 let button = egui_button(button);
128 self.egui_input.events.push(egui::Event::PointerButton {
129 pos: self.mouse_to_pos(position),
130 button,
131 pressed: false,
132 modifiers: self.get_modifiers(),
133 });
134 }
135 _ => (),
136 }
137 }
138
139 fn gather_input(&mut self) {
140 self.egui_input.modifiers = self.get_modifiers();
141 }
142
143 fn get_modifiers(&self) -> egui::Modifiers {
144 let window = self.geng.window();
145 egui::Modifiers {
146 alt: window.is_key_pressed(geng::Key::LAlt),
147 ctrl: window.is_key_pressed(geng::Key::LCtrl),
148 shift: window.is_key_pressed(geng::Key::LShift),
149 ..default()
150 }
151 }
152
153 fn mouse_to_pos(&self, mouse: Vec2<f64>) -> egui::Pos2 {
154 egui::Pos2::new(mouse.x as f32, self.screen_height - mouse.y as f32)
155 }
156}
157
158fn pos_to_vec(pos: egui::Pos2, height: f32) -> Vec2<f32> {
160 vec2(pos.x, height - pos.y)
161}
162
163fn egui_button(geng_button: geng::MouseButton) -> egui::PointerButton {
164 match geng_button {
165 geng::MouseButton::Left => egui::PointerButton::Primary,
166 geng::MouseButton::Middle => egui::PointerButton::Middle,
167 geng::MouseButton::Right => egui::PointerButton::Secondary,
168 }
169}
170
171fn egui_key(geng_key: geng::Key) -> Option<egui::Key> {
172 use egui::Key::*;
173 match geng_key {
174 geng::Key::Num0 => Some(Num0),
175 geng::Key::Num1 => Some(Num1),
176 geng::Key::Num2 => Some(Num2),
177 geng::Key::Num3 => Some(Num3),
178 geng::Key::Num4 => Some(Num4),
179 geng::Key::Num5 => Some(Num5),
180 geng::Key::Num6 => Some(Num6),
181 geng::Key::Num7 => Some(Num7),
182 geng::Key::Num8 => Some(Num8),
183 geng::Key::Num9 => Some(Num9),
184 geng::Key::A => Some(A),
185 geng::Key::B => Some(B),
186 geng::Key::C => Some(C),
187 geng::Key::D => Some(D),
188 geng::Key::E => Some(E),
189 geng::Key::F => Some(F),
190 geng::Key::G => Some(G),
191 geng::Key::H => Some(H),
192 geng::Key::I => Some(I),
193 geng::Key::J => Some(J),
194 geng::Key::K => Some(K),
195 geng::Key::L => Some(L),
196 geng::Key::M => Some(M),
197 geng::Key::N => Some(N),
198 geng::Key::O => Some(O),
199 geng::Key::P => Some(P),
200 geng::Key::Q => Some(Q),
201 geng::Key::R => Some(R),
202 geng::Key::S => Some(S),
203 geng::Key::T => Some(T),
204 geng::Key::U => Some(U),
205 geng::Key::V => Some(V),
206 geng::Key::W => Some(W),
207 geng::Key::X => Some(X),
208 geng::Key::Y => Some(Y),
209 geng::Key::Z => Some(Z),
210 geng::Key::Escape => Some(Escape),
211 geng::Key::Space => Some(Space),
212 geng::Key::Enter => Some(Enter),
213 geng::Key::Backspace => Some(Backspace),
214 geng::Key::Left => Some(ArrowLeft),
215 geng::Key::Right => Some(ArrowRight),
216 geng::Key::Up => Some(ArrowUp),
217 geng::Key::Down => Some(ArrowDown),
218 geng::Key::PageUp => Some(PageUp),
219 geng::Key::PageDown => Some(PageDown),
220 _ => None,
221 }
222}
223
224fn key_char(key: egui::Key) -> Option<char> {
225 match key {
226 egui::Key::A => Some('a'),
227 egui::Key::B => Some('b'),
228 egui::Key::C => Some('c'),
229 egui::Key::D => Some('d'),
230 egui::Key::E => Some('e'),
231 egui::Key::F => Some('f'),
232 egui::Key::G => Some('g'),
233 egui::Key::H => Some('h'),
234 egui::Key::I => Some('i'),
235 egui::Key::J => Some('j'),
236 egui::Key::K => Some('k'),
237 egui::Key::L => Some('l'),
238 egui::Key::M => Some('m'),
239 egui::Key::N => Some('n'),
240 egui::Key::O => Some('o'),
241 egui::Key::P => Some('p'),
242 egui::Key::Q => Some('q'),
243 egui::Key::R => Some('r'),
244 egui::Key::S => Some('s'),
245 egui::Key::T => Some('t'),
246 egui::Key::U => Some('u'),
247 egui::Key::V => Some('v'),
248 egui::Key::W => Some('w'),
249 egui::Key::X => Some('x'),
250 egui::Key::Y => Some('y'),
251 egui::Key::Z => Some('z'),
252 egui::Key::Num0 => Some('0'),
253 egui::Key::Num1 => Some('1'),
254 egui::Key::Num2 => Some('2'),
255 egui::Key::Num3 => Some('3'),
256 egui::Key::Num4 => Some('4'),
257 egui::Key::Num5 => Some('5'),
258 egui::Key::Num6 => Some('6'),
259 egui::Key::Num7 => Some('7'),
260 egui::Key::Num8 => Some('8'),
261 egui::Key::Num9 => Some('9'),
262 _ => None,
263 }
264}