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)>;
}