1pub mod display;
2pub mod run;
3pub mod device;
4pub mod vec_buffer;
5
6use std::sync::mpsc::Sender;
7use std::sync::Arc;
8use std::sync::Mutex;
9use std::time::Duration;
10use std::time::Instant;
11
12use winit::event::MouseButton;
13use winit::event_loop::EventLoopProxy;
14use winit::window::WindowId;
15
16use std::collections::VecDeque;
17
18use sketchbook::aspects::*;
19use sketchbook::compose;
20
21use crate::double_buffer::*;
22use crate::fifo::{FiFo, FiFoPop, FiFoPush};
23
24use self::display::Frame;
25use self::display::shape::shape_to_raw;
26
27pub use winit::event::VirtualKeyCode as Key;
28use sketchbook::compose::AsPart;
29
30pub struct TypeHolder;
31
32compose! {
33 pub enum Events {
34 #[part]
35 Update(update::env_api::Events<TypeHolder>),
36 #[part]
37 Draw(draw::env_api::Events<TypeHolder>),
38 #[part]
39 Mouse(mouse::env_api::Events<TypeHolder>),
40 #[part]
41 Keyboard(keyboard::env_api::Events<TypeHolder>),
42 Close,
43 }
44}
45
46pub struct DisplayInfo {
47 width: f32,
48 height: f32,
49 bridge: Option<DisplayBridge>,
50}
51
52#[derive(Debug, Clone)]
53pub enum DisplayEvent {
54 Redraw(WindowId),
55 Close(WindowId),
56}
57
58pub struct DisplayBridge {
59 pub window_id: WindowId,
60 pub event_loop: EventLoopProxy<DisplayEvent>,
61}
62
63compose! {
64 pub struct Page {
65 event_queue: FiFoPop<Events>,
66 shapes: DoubleBufferWrite<Frame>,
67 info: Arc<Mutex<DisplayInfo>>,
68 bridge: Option<DisplayBridge>,
69
70 #[part]
71 update_data: update::env_api::PageData<TypeHolder>,
72 #[part]
73 draw_data: draw::env_api::PageData<TypeHolder>,
74 #[part]
75 mouse_data: mouse::env_api::PageData<TypeHolder>,
76 #[part]
77 keyboard_data: keyboard::env_api::PageData<TypeHolder>,
78
79 update_impl: update::UpdateUsingInstant,
80 last_draw: Option<Instant>,
81
82 did_draw_this_group: bool,
83 events_for_group: VecDeque<Events>,
84 }
85}
86
87struct CreateWindow {
88 event_queue: FiFoPush<Events>,
89 shapes: DoubleBufferRead<Frame>,
90 info: Arc<Mutex<DisplayInfo>>,
91}
92
93#[derive(Clone)]
94pub struct Mill {
95 create_windows: Sender<CreateWindow>,
96}
97
98#[derive(Default)]
99pub struct Env;
100
101impl sketchbook::Environment for Env {
102 type Mill = Mill;
103
104 fn run<F>(self, func: F)
105 where
106 F: FnMut(&mut Self::Mill) -> sketchbook::Status + 'static,
107 {
108 run::run(self, func);
109 }
110}
111
112impl sketchbook::Mill for Mill {
113 type Page = Page;
114
115 fn new_page(&mut self) -> Self::Page {
116 let (event_sender, event_receiver) = FiFo::new(1000).split();
118 let info = Arc::new(Mutex::new(DisplayInfo {
119 width: 0.,
120 height: 0.,
121 bridge: None,
122 }));
123 let buffer = DoubleBuffer::new();
124 let (read, write) = buffer.split();
125 {
126 self.create_windows
127 .send(CreateWindow {
128 event_queue: event_sender,
129 shapes: read,
130 info: info.clone(),
131 })
132 .unwrap();
133 }
134 Page {
135 did_draw_this_group: false,
136 events_for_group: VecDeque::new(),
137 bridge: None,
138 event_queue: event_receiver,
139 update_impl: update::UpdateUsingInstant::default(),
140 last_draw: None,
141 update_data: update::env_api::PageData::default(),
142 shapes: write,
143 draw_data: draw::env_api::PageData::default(),
144 mouse_data: mouse::env_api::PageData::default(),
145 keyboard_data: keyboard::env_api::PageData::default(),
146 info,
147 }
148 }
149}
150
151impl update::GetTime for Page {
152 type Time = Instant;
153 type Duration = Duration;
154
155 fn get_time(&mut self) -> Instant {
156 Instant::now()
157 }
158
159 fn zero_duration() -> Duration {
160 Duration::from_millis(0)
161 }
162
163 fn duration_between(start: &Instant, end: &Instant) -> Duration {
164 end.duration_since(*start)
165 }
166}
167
168impl keyboard::env_api::AssociatedTypes for TypeHolder {
169 type Key = Key;
170}
171
172impl keyboard::env_api::EnvAssociatedTypes for Env {
173 type AssociatedTypesHolder = TypeHolder;
174}
175
176impl update::env_api::AssociatedTypes for TypeHolder {
177 type Time = Instant;
178 type DeltaT = Duration;
179 type UpdateRate = f32;
180}
181
182impl update::UpdateDefaults for TypeHolder {
183 type DefaultUpdateRate = f32;
184
185 fn default_update_rate() -> Self::DefaultUpdateRate {
186 30.0
187 }
188}
189
190impl update::env_api::EnvAssociatedTypes for Env {
191 type AssociatedTypesHolder = TypeHolder;
192}
193
194impl update::env_api::EnvAssociatedTypes for Page {
195 type AssociatedTypesHolder = TypeHolder;
196}
197
198impl draw::env_api::AssociatedTypes for TypeHolder {
199 type Real = f32;
200 type Color = palette::Srgba<u8>;
201}
202
203impl draw::DrawDefaults for TypeHolder {
204 type DefaultReal = f32;
205 type DefaultColor = palette::Srgba<u8>;
206
207 fn default_size() -> sketchbook::Size2<Self::DefaultReal> {
208 sketchbook::Size2 { width: 1.0, height: 1.0 }
209 }
210
211 fn default_context() -> draw::Context<Self::DefaultReal, Self::DefaultColor> {
212 draw::Context {
213 fill: palette::Srgba::new(255, 255, 255, 255),
214 stroke: palette::Srgba::new(0, 0, 0, 255),
215 weight: 0.0,
216 rectangle_mode: draw::Mode::Center,
217 ellipse_mode: draw::Mode::Center,
218 rotation: 0.0,
219 }
220 }
221
222 fn default_background() -> Self::DefaultColor {
223 palette::Srgba::new(10, 10, 10, 255)
224 }
225
226 fn default_frame_rate() -> Self::DefaultReal {
227 30.0
228 }
229}
230
231impl draw::env_api::EnvAssociatedTypes for Env {
232 type AssociatedTypesHolder = TypeHolder;
233}
234
235impl draw::env_api::EnvAssociatedTypes for Page {
236 type AssociatedTypesHolder = TypeHolder;
237}
238
239impl mouse::env_api::AssociatedTypes for TypeHolder {
240 type Button = MouseButton;
241 type WheelCount = f32;
242 type Position = f32;
243}
244
245impl mouse::env_api::EnvAssociatedTypes for Env {
246 type AssociatedTypesHolder = TypeHolder;
247}
248
249impl sketchbook::Page for Page {
250 type Event = Events;
251
252 fn start_group(&mut self) {
253 let (width, height) = {
258 let mut info = self.info.lock().unwrap();
259 if let Some(bridge) = info.bridge.take() {
260 self.bridge = Some(bridge);
261 }
262 (info.width, info.height)
263 };
264 self.draw_data.set_size(sketchbook::Size2 { width, height });
265
266 for _ in 0..100 {
270 if let Some(event) = self.event_queue.pop() {
271 self.events_for_group.push_back(event);
272 } else {
273 break;
274 }
275 }
276
277 if self.update_impl.should_update(self.update_data.update_rate()) {
282 self.events_for_group.push_back(Events::Update(update::env_api::Events::Update));
283 }
284
285 if let Some(last_draw) = self.last_draw {
286 if last_draw.elapsed().as_secs_f32() >= 1.0 / self.draw_data.frame_rate() {
287 self.last_draw = Some(Instant::now());
288 self.events_for_group.push_back(Events::Draw(draw::env_api::Events::Draw));
289 }
290 } else {
291 self.last_draw = Some(Instant::now());
292 self.events_for_group.push_back(Events::Draw(draw::env_api::Events::Draw));
293 }
294
295 self.did_draw_this_group = false;
297 }
298
299 fn end_group(&mut self) {
300 if !self.events_for_group.is_empty() {
301 eprintln!("Event buffer was not completely processed. Events will roll over to next group.");
302 }
303
304 if self.did_draw_this_group {
306 let background = self.draw_data.background_color();
307 self.shapes.background = wgpu::Color {
308 r: background.red as f64 / 255.0,
309 g: background.green as f64 / 255.0,
310 b: background.blue as f64 / 255.0,
311 a: background.alpha as f64 / 255.0,
312 };
313
314 self.shapes.buffer.clear();
316
317 self.shapes.buffer.extend(self.draw_data.frame_mut().iter().map(|shape| shape_to_raw(shape)));
319
320 if self.draw_data.frame_mut().len() > 1_000_000 {
322 eprintln!("Frame buffer has {} shapes.", self.draw_data.frame_mut().len())
323 }
324
325 DoubleBufferWrite::swap(&mut self.shapes);
327
328 if let Some(bridge) = &self.bridge {
330 bridge
331 .event_loop
332 .send_event(DisplayEvent::Redraw(bridge.window_id))
333 .ok();
334 }
335 }
336 }
337
338 fn next_event_in_group(&mut self) -> Option<Self::Event> {
339 self.events_for_group.pop_front()
340 }
341
342 fn before_event(&mut self, event: &Self::Event) {
343 }
345
346 fn finish_event(&mut self, event: Self::Event) {
347 match event {
348 Events::Draw(_) => {
349 self.did_draw_this_group = true;
351 },
352 Events::Close => {
353 self.update_data.stop();
355 },
356 _ => {},
357 }
358 }
359
360 fn status(&self) -> sketchbook::Status {
361 if self.update_data.should_stop() {
362 sketchbook::Status::Stop
363 } else {
364 sketchbook::Status::Continue
365 }
366 }
367}
368
369impl Drop for Page {
370 fn drop(&mut self) {
371 if let Some(bridge) = &self.bridge {
373 bridge
374 .event_loop
375 .send_event(DisplayEvent::Close(bridge.window_id))
376 .ok();
377 }
378 }
379}