1#[cfg(all(not(feature = "pixels"), not(feature = "softbuffer"),))]
34compile_error!("You must pick one windowing feature either pixels or softbuffer");
35
36pub mod dialogs;
37mod integration;
38#[cfg(feature = "scenes")]
39pub mod scenes;
40pub mod ui;
41pub mod utilities;
42#[cfg(feature = "window_prefs")]
43pub mod window_prefs;
44
45use crate::prelude::{winit, Coord, ALL_KEYS};
46use crate::ui::styles::UiStyle;
47#[cfg(feature = "window_prefs")]
48use crate::window_prefs::WindowPreferences;
49pub use buffer_graphics_lib;
50use buffer_graphics_lib::Graphics;
51use rustc_hash::FxHashMap;
52#[cfg(feature = "serde")]
53use serde::{Deserialize, Serialize};
54use simple_game_utils::prelude::*;
55use thiserror::Error;
56use winit::event::MouseButton;
57#[cfg(feature = "softbuffer")]
58pub use winit::event_loop::ControlFlow;
59use winit::keyboard::KeyCode;
60use winit::window::Window;
61
62pub mod prelude {
63 pub use crate::dialogs::*;
64 #[cfg(feature = "pixels")]
65 pub use crate::integration::pixels_winit::run;
66 #[cfg(feature = "softbuffer")]
67 pub use crate::integration::softbuffer_winit::run;
68 #[cfg(feature = "scenes")]
69 pub use crate::scenes::*;
70 pub use crate::utilities::virtual_key_codes::*;
71 #[cfg(feature = "window_prefs")]
72 pub use crate::window_prefs::*;
73 pub use crate::GraphicsError;
74 pub use crate::MouseData;
75 pub use crate::Options;
76 pub use crate::System;
77 pub use crate::WindowScaling;
78 pub use buffer_graphics_lib::prelude::*;
79 pub use rustc_hash::FxHashSet;
80 pub use simple_game_utils::prelude::*;
81 pub use winit::event::MouseButton;
82 pub use winit::keyboard::KeyCode;
83 pub use winit::window::Window;
84 #[cfg(feature = "pixels")]
85 pub use winit_29 as winit;
86 #[cfg(feature = "softbuffer")]
87 pub use winit_30 as winit;
88}
89
90#[derive(Error, Debug)]
91pub enum GraphicsError {
92 #[error("Creating a window: {0}")]
93 WindowInit(String),
94 #[cfg(feature = "pixels")]
95 #[error("Initialising Pixels: {0}")]
96 PixelsInit(#[source] pixels::Error),
97 #[error("Saving window pref: {0}")]
98 SavingWindowPref(String),
99 #[cfg(feature = "window_prefs")]
100 #[error("Loading window pref: {0}")]
101 LoadingWindowPref(String),
102 #[error("Invalid pixel array length, expected: {0}, found: {1}")]
103 ImageInitSize(usize, usize),
104 #[error("Both images must be the same size, expected: {0}x{1}, found: {2}x{3}")]
105 ImageBlendSize(usize, usize, usize, usize),
106 #[cfg(feature = "controller")]
107 #[error("Unable to init controller: {0}")]
108 ControllerInit(String),
109 #[cfg(any(feature = "pixels", feature = "softbuffer"))]
110 #[error("Initialing Winit: {0}")]
111 WinitInit(#[source] winit::error::EventLoopError),
112}
113
114#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
115#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
116pub enum WindowScaling {
117 Native,
119 Double,
121 Quad,
123}
124
125#[allow(unused_variables)]
126pub trait System {
127 fn keys_used(&self) -> &[KeyCode] {
129 &ALL_KEYS
130 }
131 #[cfg(feature = "window_prefs")]
132 fn window_prefs(&mut self) -> Option<WindowPreferences> {
133 None
134 }
135 fn update(&mut self, timing: &Timing, window: &Window);
136 fn render(&mut self, graphics: &mut Graphics);
137 fn on_mouse_move(&mut self, mouse: &MouseData) {}
138 fn on_mouse_down(&mut self, mouse: &MouseData, button: MouseButton) {}
139 fn on_mouse_up(&mut self, mouse: &MouseData, button: MouseButton) {}
140 fn on_scroll(&mut self, mouse: &MouseData, x_diff: isize, y_diff: isize) {}
141 fn on_key_down(&mut self, keys: Vec<KeyCode>) {}
142 fn on_key_up(&mut self, keys: Vec<KeyCode>) {}
143 fn on_window_closed(&mut self) {}
144 fn on_visibility_changed(&mut self, visible: bool) {}
145 fn on_focus_changed(&mut self, focused: bool) {}
146 fn should_exit(&mut self) -> bool {
147 false
148 }
149}
150
151#[cfg_attr(feature = "pixels_serde", derive(Serialize, Deserialize))]
153#[cfg_attr(feature = "softbuffer_serde", derive(Serialize, Deserialize))]
154#[derive(Debug, PartialEq)]
155pub struct Options {
156 pub ups: usize,
159 pub scaling: WindowScaling,
162 pub vsync: bool,
165 pub hide_cursor: bool,
169 pub confine_cursor: bool,
172 pub style: UiStyle,
174 #[cfg(feature = "softbuffer")]
176 pub control_flow: ControlFlow,
177}
178
179impl Options {
180 pub fn new(
181 ups: usize,
182 scaling: WindowScaling,
183 vsync: bool,
184 hide_cursor: bool,
185 confine_cursor: bool,
186 style: UiStyle,
187 #[cfg(feature = "softbuffer")] control_flow: ControlFlow,
188 ) -> Self {
189 Self {
190 ups,
191 scaling,
192 vsync,
193 hide_cursor,
194 confine_cursor,
195 style,
196 #[cfg(feature = "softbuffer")]
197 control_flow,
198 }
199 }
200}
201
202impl Default for Options {
203 fn default() -> Self {
204 Self {
205 ups: 240,
206 scaling: WindowScaling::Double,
207 vsync: true,
208 hide_cursor: false,
209 confine_cursor: false,
210 style: UiStyle::default(),
211 #[cfg(feature = "softbuffer")]
212 control_flow: ControlFlow::Poll,
213 }
214 }
215}
216
217#[cfg_attr(feature = "pixels_serde", derive(Serialize, Deserialize))]
218#[cfg_attr(feature = "softbuffer_serde", derive(Serialize, Deserialize))]
219#[derive(Debug, Clone, Eq, PartialEq, Default)]
220pub struct MouseData {
221 pub xy: Coord,
222 buttons: FxHashMap<MouseButton, Coord>,
223}
224
225impl MouseData {
226 pub fn any_held(&self) -> bool {
227 !self.buttons.is_empty()
228 }
229
230 pub fn is_down(&self, button: MouseButton) -> Option<Coord> {
232 self.buttons.get(&button).cloned()
233 }
234
235 pub(crate) fn add_up(&mut self, button: MouseButton) {
236 self.buttons.remove(&button);
237 }
238
239 pub(crate) fn add_down(&mut self, xy: Coord, button: MouseButton) {
240 self.buttons.insert(button, xy);
241 }
242}