wuple 0.4.0

Simple, Performant rendering on WGPU
Documentation
//! Simple, Performant rendering on WGPU
//!
//! ## Example
//! ```
//! use wuple::App;
//!
//! pub struct Example {}
//! impl App for Example {
//!     fn render(&mut self, painter: &mut wuple::painter::Painter, builder: &mut wuple::builder::Builder, _info: &wuple::info::Info) {
//!         // Draw a Rectangle
//!         painter.draw(builder.rect(
//!             (-0.5, -0.5), (0.5, 0.5),
//!             wuple::builder::Draw::Color(wuple::painter::color::WHITE)
//!         ));
//!     }
//!
//!     fn event(&mut self, event: &winit::event::WindowEvent) -> bool {
//!         // Handle Event
//!         false
//!     }
//!
//!     fn update(&mut self, _info: &wuple::info::Info) {
//!         // Do some Updates before Rendering
//!     }
//! }
//!
//! Example {}.run(true);
//! ```

mod backend;
pub mod builder;
pub mod draw;
pub mod info;
pub mod painter;
pub mod settings;
pub mod vertex;

pub use winit;

use builder::Builder;
use info::Info;

use winit::{
    event::*,
    event_loop::{ControlFlow, EventLoop},
    window::WindowBuilder,
};

use self::{backend::State, painter::Painter};

/// Result for the event function
#[derive(Default)]
pub enum EventResult {
    #[default]
    Unhandled,
    Handled,
    Exit,
}

/// Main Application trait  
/// handles rendering, inputs and updates
pub trait App {
    /// Handle Initialization
    fn init(&mut self, _builder: &mut Builder) {}

    /// Handle Rendering
    fn render(&mut self, painter: &mut Painter, builder: &mut Builder, info: &Info);

    /// Handle Events  
    /// return true if the event was handled
    fn event(&mut self, event: &WindowEvent) -> EventResult;

    /// Handle Update (called before render)
    fn update(&mut self, builder: &mut Builder, info: &Info);

    /// Runs the App  
    ///
    /// continuous: draw continuously or after an event
    /// title: the title of the window
    fn run(self, settings: settings::RunSettings)
    where
        Self: Sized + 'static,
    {
        let event_loop = EventLoop::new();
        self.run_with_event_loop(event_loop, settings);
    }

    /// Runs the App
    fn run_with_event_loop(mut self, event_loop: EventLoop<()>, settings: settings::RunSettings)
    where
        Self: Sized + 'static,
    {
        let window = WindowBuilder::new().build(&event_loop).unwrap();
        window.set_title(settings.title);
        let mut state: State = pollster::block_on(State::new(window, &mut self));

        event_loop.run(move |event, _, control_flow| match event {
            Event::RedrawRequested(window_id) if window_id == state.window().id() => {
                state.update(&mut self);
                match state.render(&mut self) {
                    Ok(_) => {}
                    Err(wgpu::SurfaceError::Lost) => state.resize(state.size),
                    Err(wgpu::SurfaceError::OutOfMemory) => *control_flow = ControlFlow::Exit,
                    Err(e) => eprintln!("{:?}", e),
                }
            }
            Event::MainEventsCleared => {
                if !settings.continuous {
                    control_flow.set_wait();
                }

                state.window().request_redraw();
            }
            Event::WindowEvent {
                ref event,
                window_id,
            } if window_id == state.window().id() => match state.event(&mut self, event) {
                EventResult::Unhandled => match event {
                    WindowEvent::CloseRequested => {
                        *control_flow = ControlFlow::Exit;
                    }
                    WindowEvent::Resized(physical_size) => {
                        state.resize(*physical_size);
                    }
                    WindowEvent::ScaleFactorChanged { new_inner_size, .. } => {
                        state.resize(**new_inner_size);
                    }
                    _ => {}
                },
                EventResult::Handled => {}
                EventResult::Exit => *control_flow = ControlFlow::Exit,
            },
            Event::Resumed => {
                state.create_surface();
            }
            Event::Suspended => {}

            _ => {}
        });
    }
}