wuple/
lib.rs

1//! Simple, Performant rendering on WGPU
2//!
3//! ## Example
4//! ```
5//! use wuple::App;
6//!
7//! pub struct Example {}
8//! impl App for Example {
9//!     fn render(&mut self, painter: &mut wuple::painter::Painter, builder: &mut wuple::builder::Builder, _info: &wuple::info::Info) {
10//!         // Draw a Rectangle
11//!         painter.draw(builder.rect(
12//!             (-0.5, -0.5), (0.5, 0.5),
13//!             wuple::builder::Draw::Color(wuple::painter::color::WHITE)
14//!         ));
15//!     }
16//!
17//!     fn event(&mut self, event: &winit::event::WindowEvent) -> bool {
18//!         // Handle Event
19//!         false
20//!     }
21//!
22//!     fn update(&mut self, _info: &wuple::info::Info) {
23//!         // Do some Updates before Rendering
24//!     }
25//! }
26//!
27//! Example {}.run(true);
28//! ```
29
30mod backend;
31pub mod builder;
32pub mod draw;
33pub mod info;
34pub mod painter;
35pub mod settings;
36pub mod vertex;
37
38pub use winit;
39
40use builder::Builder;
41use info::Info;
42
43use winit::{
44    event::*,
45    event_loop::{ControlFlow, EventLoop},
46    window::WindowBuilder,
47};
48
49use self::{backend::State, painter::Painter};
50
51/// Result for the event function
52#[derive(Default)]
53pub enum EventResult {
54    #[default]
55    Unhandled,
56    Handled,
57    Exit,
58}
59
60/// Main Application trait  
61/// handles rendering, inputs and updates
62pub trait App {
63    /// Handle Initialization
64    fn init(&mut self, _builder: &mut Builder) {}
65
66    /// Handle Rendering
67    fn render(&mut self, painter: &mut Painter, builder: &mut Builder, info: &Info);
68
69    /// Handle Events  
70    /// return true if the event was handled
71    fn event(&mut self, event: &WindowEvent) -> EventResult;
72
73    /// Handle Update (called before render)
74    fn update(&mut self, builder: &mut Builder, info: &Info);
75
76    /// Runs the App  
77    ///
78    /// continuous: draw continuously or after an event
79    /// title: the title of the window
80    fn run(self, settings: settings::RunSettings)
81    where
82        Self: Sized + 'static,
83    {
84        let event_loop = EventLoop::new();
85        self.run_with_event_loop(event_loop, settings);
86    }
87
88    /// Runs the App
89    fn run_with_event_loop(mut self, event_loop: EventLoop<()>, settings: settings::RunSettings)
90    where
91        Self: Sized + 'static,
92    {
93        let window = WindowBuilder::new().build(&event_loop).unwrap();
94        window.set_title(settings.title);
95        let mut state: State = pollster::block_on(State::new(window, &mut self));
96
97        event_loop.run(move |event, _, control_flow| match event {
98            Event::RedrawRequested(window_id) if window_id == state.window().id() => {
99                state.update(&mut self);
100                match state.render(&mut self) {
101                    Ok(_) => {}
102                    Err(wgpu::SurfaceError::Lost) => state.resize(state.size),
103                    Err(wgpu::SurfaceError::OutOfMemory) => *control_flow = ControlFlow::Exit,
104                    Err(e) => eprintln!("{:?}", e),
105                }
106            }
107            Event::MainEventsCleared => {
108                if !settings.continuous {
109                    control_flow.set_wait();
110                }
111
112                state.window().request_redraw();
113            }
114            Event::WindowEvent {
115                ref event,
116                window_id,
117            } if window_id == state.window().id() => match state.event(&mut self, event) {
118                EventResult::Unhandled => match event {
119                    WindowEvent::CloseRequested => {
120                        *control_flow = ControlFlow::Exit;
121                    }
122                    WindowEvent::Resized(physical_size) => {
123                        state.resize(*physical_size);
124                    }
125                    WindowEvent::ScaleFactorChanged { new_inner_size, .. } => {
126                        state.resize(**new_inner_size);
127                    }
128                    _ => {}
129                },
130                EventResult::Handled => {}
131                EventResult::Exit => *control_flow = ControlFlow::Exit,
132            },
133            Event::Resumed => {
134                state.create_surface();
135            }
136            Event::Suspended => {}
137
138            _ => {}
139        });
140    }
141}