devotee/app/
setup.rs

1use std::marker::PhantomData;
2use std::time::Duration;
3
4use super::config::Config;
5use super::context::Context;
6use super::Constructor;
7
8/// Builder for `Setup`.
9#[derive(Default)]
10pub struct Builder<Cfg> {
11    _phantom: PhantomData<Cfg>,
12}
13
14impl<Cfg> Builder<Cfg>
15where
16    Cfg: Config,
17{
18    /// Create new builder.
19    pub fn new() -> Builder<Cfg> {
20        Self {
21            _phantom: PhantomData,
22        }
23    }
24
25    /// Add render target to setup.
26    pub fn with_render_target(self, render_target: Cfg::RenderTarget) -> StepRenderTarget<Cfg> {
27        StepRenderTarget { render_target }
28    }
29}
30
31/// Temporary container of setup properties.
32pub struct StepRenderTarget<Cfg>
33where
34    Cfg: Config,
35{
36    render_target: Cfg::RenderTarget,
37}
38
39impl<Cfg> StepRenderTarget<Cfg>
40where
41    Cfg: Config,
42{
43    /// Add input system to setup.
44    pub fn with_input(self, input: Cfg::Input) -> StepInput<Cfg> {
45        StepInput {
46            render_target: self.render_target,
47            input,
48        }
49    }
50}
51
52/// Temporary container of setup properties.
53pub struct StepInput<Cfg>
54where
55    Cfg: Config,
56{
57    render_target: Cfg::RenderTarget,
58    input: Cfg::Input,
59}
60
61impl<Cfg> StepInput<Cfg>
62where
63    Cfg: Config,
64{
65    /// Add root constructor to setup.
66    pub fn with_root_constructor<F>(self, constructor: F) -> Setup<Cfg>
67    where
68        F: 'static + FnOnce(&mut Context<Cfg>) -> Cfg::Root,
69    {
70        Setup::new(self.render_target, self.input, constructor)
71    }
72}
73
74/// Application setup structure.
75/// Describes root node, title, pause behavior, etc.
76pub struct Setup<Cfg>
77where
78    Cfg: Config,
79{
80    pub(super) title: String,
81    pub(super) update_delay: Duration,
82    pub(super) fullscreen: bool,
83    pub(super) scale: u32,
84    pub(super) render_target: Cfg::RenderTarget,
85    pub(super) constructor: Constructor<Cfg::Root, Cfg>,
86    #[cfg(target_arch = "wasm32")]
87    pub(super) element_id: Option<&'static str>,
88    pub(super) pause_on_focus_lost: bool,
89    pub(super) input: Cfg::Input,
90}
91
92impl<Cfg> Setup<Cfg>
93where
94    Cfg: Config,
95{
96    fn new<F>(render_target: Cfg::RenderTarget, input: Cfg::Input, constructor: F) -> Self
97    where
98        F: 'static + FnOnce(&mut Context<Cfg>) -> Cfg::Root,
99    {
100        let title = String::new();
101        let update_delay = Duration::from_secs_f64(1.0 / 30.0);
102        let fullscreen = false;
103        let scale = 1;
104        let constructor = Box::new(constructor);
105        Self {
106            title,
107            update_delay,
108            fullscreen,
109            scale,
110            render_target,
111            constructor,
112            #[cfg(target_arch = "wasm32")]
113            element_id: None,
114            pause_on_focus_lost: true,
115            input,
116        }
117    }
118
119    /// Set application title.
120    pub fn with_title<T: Into<String>>(self, title: T) -> Self {
121        Self {
122            title: title.into(),
123            ..self
124        }
125    }
126
127    /// Set display scale.
128    pub fn with_scale(self, scale: u32) -> Self {
129        Self { scale, ..self }
130    }
131
132    /// Set fullscreen option.
133    pub fn with_fullscreen(self, fullscreen: bool) -> Self {
134        Self { fullscreen, ..self }
135    }
136
137    /// Set update delay.
138    pub fn with_update_delay(self, update_delay: Duration) -> Self {
139        Self {
140            update_delay,
141            ..self
142        }
143    }
144
145    #[cfg(target_arch = "wasm32")]
146    /// Set target element id for canvas holding on wasm32 target.
147    pub fn with_element_id(self, element_id: &'static str) -> Self {
148        let element_id = Some(element_id);
149        Self { element_id, ..self }
150    }
151
152    /// Set whether to apply pause on focus being lost.
153    pub fn with_pause_on_focus_lost(self, pause_on_focus_lost: bool) -> Self {
154        Self {
155            pause_on_focus_lost,
156            ..self
157        }
158    }
159}