devotee_backend/lib.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
#![deny(missing_docs)]
//! Set of definitions for backend-y stuff of the devotee project.
//!
//! General approach is following:
//! - Specific backend works with middleware and application instances;
//! - Middleware abstract backend specifics away;
//! - Application works with Middleware abstractions;
use std::time::Duration;
/// Middleware trait.
pub trait Middleware<'a, Control> {
/// Event type to be handled;
type Event;
/// Specific context supporting the event handling.
type EventContext;
/// Surface to render to.
type Surface;
/// Initialization context to be passed to the application.
type Init;
/// Context to be passed to the application.
type Context;
/// Render target to be passed to the application.
type RenderTarget;
/// Initialize during startup.
fn init(&'a mut self, control: &'a mut Control) -> Self::Init;
/// Provide context for the application update process.
fn update(&'a mut self, control: &'a mut Control, delta: Duration) -> Self::Context;
/// Handle event generated by the backend, return it if not consumed.
fn handle_event(
&mut self,
event: Self::Event,
event_context: Self::EventContext,
control: &mut Control,
) -> Option<Self::Event>;
/// Provide render context for the application to draw on.
fn render(&'a mut self, surface: Self::Surface) -> Self::RenderTarget;
}
/// Application trait.
pub trait Application<'a, Init, Context, RenderSurface, Converter> {
/// Initialize the application.
fn init(&mut self, init: Init);
/// Handle update logic.
fn update(&mut self, context: Context);
/// Render on the surface passed by the Middleware.
fn render(&mut self, render_surface: &mut RenderSurface);
/// Provide converter to convert data on the surface into `u32` values.
fn converter(&self) -> Converter;
/// Register the pause event.
fn pause(&mut self) {}
/// Register the resume event.
fn resume(&mut self) {}
}
/// The surface for the Application to perform rendering on.
pub trait RenderSurface {
/// Pixel data to be returned to the Middleware's render target.
type Data;
/// Get the width of the render surface in pixels.
fn width(&self) -> usize;
/// Get the height of the render surface in pixels.
fn height(&self) -> usize;
/// Get specific pixel data.
///
/// # Panics
/// For values outside of safe range may panic or may return garbage value.
fn data(&self, x: usize, y: usize) -> Self::Data;
}
/// Converter from the Data value to `0xff_rr_gg_bb` format.
pub trait Converter {
/// Data to be converted from.
type Data;
/// Convert passed data into `0xff_rr_gg_bb` value.
/// `x` and `y` values represent pixel position in the surface, not in the target.
fn convert(&self, x: usize, y: usize, data: Self::Data) -> u32;
}
/// Target to render to.
pub trait RenderTarget<Converter> {
/// Stored `RenderSurface`.
type RenderSurface;
/// Error to be raised in case of a failure during presentation process.
type PresentError;
/// Get reference to the render surface.
fn render_surface(&self) -> &Self::RenderSurface;
/// Get mutable reference to the render surface.
fn render_surface_mut(&mut self) -> &mut Self::RenderSurface;
/// Present stored data.
fn present(self, converter: Converter) -> Result<(), Self::PresentError>;
}
/// Context to be passed to the Application during the update routine.
pub trait Context<'a, Input> {
/// Get stored input system.
fn input(&self) -> &Input;
/// Get simulated time passed since the previous update.
fn delta(&self) -> Duration;
/// Tell the backend to shutdown.
fn shutdown(&mut self);
}
/// Input trait consumes external events.
pub trait Input<'a, EventContext> {
/// Event to be handled.
type Event;
/// Handle event.
/// Return the event if it is ignored.
fn handle_event(
&mut self,
event: Self::Event,
event_context: &EventContext,
) -> Option<Self::Event>;
/// Handle the frame change.
fn tick(&mut self);
}
/// Context for the event handling.
#[cfg(feature = "input-context")]
pub trait EventContext {
/// Convert window position into render surface space.
/// The `Ok` result means that the position is inside the surface, `Err` otherwise.
fn position_into_render_surface_space(
&self,
position: (f32, f32),
) -> Result<(i32, i32), (i32, i32)>;
}