Skip to main content

pfx_game/
config.rs

1use std::path::PathBuf;
2
3use pfx_gpu::screens::{Budget, Device, ScreenPolicy};
4use pfx_input::{Backend, LayoutSource};
5use pfx_live::flat::{Icons, SpriteImage};
6use pfx_live::renderer::Exposure;
7use pfx_live::upscale::Filter;
8use pfx_play::Settings;
9
10pub const WARM_BUDGET: f64 = 2.0;
11
12pub enum Pads {
13    None,
14    Gilrs,
15    Backend(Box<dyn Backend>),
16}
17
18pub type Crash = Box<dyn Fn(&str)>;
19
20pub struct Config {
21    pub name: String,
22    pub title: Option<String>,
23    pub crash: Option<Crash>,
24    pub version: String,
25    pub scene: Option<PathBuf>,
26    pub settings: Settings,
27    pub screen: ScreenPolicy,
28    pub device: Option<Device>,
29    pub render_scale: f32,
30    pub budget: Option<Budget>,
31    pub filter: Filter,
32    pub exposure: Exposure,
33    pub fonts: Vec<Vec<u8>>,
34    pub pads: Pads,
35    pub seed: u64,
36    pub sound: bool,
37    pub layout: Option<Box<dyn LayoutSource>>,
38    pub icons: Option<Icons>,
39    pub sprites: Option<SpriteImage>,
40    pub environment: Option<EnvironmentTexels>,
41    pub warm_budget: f64,
42}
43
44#[derive(Clone, Debug, PartialEq)]
45pub struct EnvironmentTexels {
46    pub width: u32,
47    pub height: u32,
48    pub linear: Vec<[f32; 4]>,
49    pub intensity: f32,
50}
51
52impl Config {
53    pub fn new(
54        name: impl Into<String>,
55        version: impl Into<String>,
56        scene: impl Into<PathBuf>,
57    ) -> Self {
58        Self {
59            scene: Some(scene.into()),
60            ..Self::flat(name, version)
61        }
62    }
63
64    pub fn flat(name: impl Into<String>, version: impl Into<String>) -> Self {
65        Self {
66            name: name.into(),
67            title: None,
68            crash: None,
69            version: version.into(),
70            scene: None,
71            settings: Settings::default(),
72            screen: ScreenPolicy::default(),
73            device: None,
74            render_scale: 1.0,
75            budget: None,
76            filter: Filter::Sharp,
77            exposure: Exposure::Auto { bias: 0.0 },
78            fonts: Vec::new(),
79            pads: Pads::Gilrs,
80            seed: 0,
81            sound: true,
82            layout: None,
83            icons: None,
84            sprites: None,
85            environment: None,
86            warm_budget: WARM_BUDGET,
87        }
88    }
89
90    pub fn bind_text(&self) {
91        pfx_load::scene::bind("name", &self.name);
92        pfx_load::scene::bind("version", &self.version);
93    }
94
95    pub fn warm_budget(mut self, seconds: f64) -> Self {
96        self.warm_budget = seconds;
97        self
98    }
99
100    pub fn title(mut self, title: impl Into<String>) -> Self {
101        self.title = Some(title.into());
102        self
103    }
104
105    pub fn window_title(&self) -> &str {
106        self.title.as_deref().unwrap_or(&self.name)
107    }
108
109    pub fn crash(mut self, hook: impl Fn(&str) + 'static) -> Self {
110        self.crash = Some(Box::new(hook));
111        self
112    }
113
114    pub fn settings(mut self, settings: Settings) -> Self {
115        self.settings = settings;
116        self
117    }
118
119    pub fn screen(mut self, screen: ScreenPolicy) -> Self {
120        self.screen = screen;
121        self
122    }
123
124    pub fn device(mut self, device: Device) -> Self {
125        self.device = Some(device);
126        self
127    }
128
129    pub fn render_scale(mut self, scale: f32) -> Self {
130        self.render_scale = scale;
131        self
132    }
133
134    pub fn budget(mut self, budget: Budget) -> Self {
135        self.budget = Some(budget);
136        self
137    }
138
139    pub fn exposure(mut self, exposure: Exposure) -> Self {
140        self.exposure = exposure;
141        self
142    }
143
144    pub fn filter(mut self, filter: Filter) -> Self {
145        self.filter = filter;
146        self
147    }
148
149    pub fn font(mut self, bytes: impl Into<Vec<u8>>) -> Self {
150        self.fonts.push(bytes.into());
151        self
152    }
153
154    pub fn pads(mut self, pads: Pads) -> Self {
155        self.pads = pads;
156        self
157    }
158
159    pub fn seed(mut self, seed: u64) -> Self {
160        self.seed = seed;
161        self
162    }
163
164    pub fn layout(mut self, layout: Box<dyn LayoutSource>) -> Self {
165        self.layout = Some(layout);
166        self
167    }
168
169    pub fn icons(mut self, icons: Icons) -> Self {
170        self.icons = Some(icons);
171        self
172    }
173
174    pub fn sprites(mut self, sprites: SpriteImage) -> Self {
175        self.sprites = Some(sprites);
176        self
177    }
178
179    pub fn environment(mut self, environment: EnvironmentTexels) -> Self {
180        self.environment = Some(environment);
181        self
182    }
183
184    pub fn sound(mut self, on: bool) -> Self {
185        self.sound = on;
186        self
187    }
188}
189
190pub(crate) fn report(name: &str, crash: Option<&Crash>, error: &str) {
191    eprintln!("{name}: {error}");
192    if let Some(crash) = crash {
193        crash(error);
194    }
195}