summaryrefslogtreecommitdiff
path: root/engine/src/window.rs
diff options
context:
space:
mode:
Diffstat (limited to 'engine/src/window.rs')
-rw-r--r--engine/src/window.rs755
1 files changed, 0 insertions, 755 deletions
diff --git a/engine/src/window.rs b/engine/src/window.rs
deleted file mode 100644
index f191c06..0000000
--- a/engine/src/window.rs
+++ /dev/null
@@ -1,755 +0,0 @@
-use std::borrow::Cow;
-use std::ffi::{CStr, CString};
-
-use bitflags::bitflags;
-use ecs::actions::Actions;
-use ecs::extension::Collector as ExtensionCollector;
-use ecs::pair::{ChildOf, Pair};
-use ecs::phase::{Phase, START as START_PHASE};
-use ecs::sole::Single;
-use ecs::{declare_entity, Sole};
-use glfw::window::{Hint as WindowCreationHint, HintValue as WindowCreationHintValue};
-use glfw::WindowSize;
-use util_macros::VariantArr;
-
-use crate::data_types::dimens::Dimens;
-use crate::renderer::RENDER_PHASE;
-use crate::vector::Vec2;
-
-declare_entity!(
- pub UPDATE_PHASE,
- (Phase, Pair::builder().relation::<ChildOf>().target_id(*RENDER_PHASE).build())
-);
-
-#[derive(Debug, Sole)]
-/// Has to be dropped last since it holds the OpenGL context.
-#[sole(drop_last)]
-pub struct Window
-{
- inner: glfw::Window,
-}
-
-impl Window
-{
- /// Returns a new Window builder.
- #[must_use]
- pub fn builder() -> Builder
- {
- Builder::default()
- }
-
- /// Sets the value of a input mode.
- ///
- /// # Errors
- /// Returns `Err` if the input mode is unsupported on the current system.
- pub fn set_input_mode(
- &self,
- input_mode: InputMode,
- enabled: bool,
- ) -> Result<(), Error>
- {
- Ok(self
- .inner
- .set_input_mode(input_mode.to_glfw_input_mode(), enabled)?)
- }
-
- /// Sets the cursor mode.
- ///
- /// # Errors
- /// If a platform error occurs.
- pub fn set_cursor_mode(&self, cursor_mode: CursorMode) -> Result<(), Error>
- {
- Ok(self
- .inner
- .set_cursor_mode(cursor_mode.to_glfw_cursor_mode())?)
- }
-
- /// Returns whether or not the window should close. Will return true when the user has
- /// attempted to close the window.
- #[must_use]
- pub fn should_close(&self) -> bool
- {
- self.inner.should_close()
- }
-
- /// Processes all pending events.
- ///
- /// # Errors
- /// If a platform error occurs.
- pub fn poll_events(&self) -> Result<(), Error>
- {
- Ok(self.inner.poll_events()?)
- }
-
- /// Swaps the front and back buffers of the window.
- ///
- /// # Errors
- /// Will return `Err` if a platform error occurs or if no OpenGL window context
- /// is present.
- pub fn swap_buffers(&self) -> Result<(), Error>
- {
- Ok(self.inner.swap_buffers()?)
- }
-
- /// Returns the size of the window.
- ///
- /// # Errors
- /// Will return `Err` if a platform error occurs.
- pub fn size(&self) -> Result<Dimens<u32>, Error>
- {
- let size = self.inner.size()?;
-
- Ok(Dimens {
- width: size.width,
- height: size.height,
- })
- }
-
- /// Returns the address of the specified OpenGL function, if it is supported by the
- /// current OpenGL context.
- ///
- /// # Errors
- /// Will return `Err` if a platform error occurs or if no current context has
- /// been set.
- ///
- /// # Panics
- /// Will panic if the `proc_name` argument contains a nul byte.
- pub fn get_proc_address(
- &self,
- proc_name: &str,
- ) -> Result<unsafe extern "C" fn(), Error>
- {
- let proc_name_c: Cow<CStr> = CStr::from_bytes_with_nul(proc_name.as_bytes())
- .map(Cow::Borrowed)
- .or_else(|_| CString::new(proc_name).map(Cow::Owned))
- .expect("OpenGL function name contains a nul byte");
-
- Ok(self.inner.get_proc_address(&proc_name_c)?)
- }
-
- /// Makes the OpenGL context of the window current for the calling thread.
- ///
- /// # Errors
- /// Will return `Err` if a platform error occurs or if no OpenGL context is
- /// present.
- pub fn make_context_current(&self) -> Result<(), Error>
- {
- Ok(self.inner.make_context_current()?)
- }
-
- /// Sets the window's framebuffer size callback.
- pub fn set_framebuffer_size_callback(&self, callback: impl Fn(Dimens<u32>) + 'static)
- {
- self.inner.set_framebuffer_size_callback(move |size| {
- callback(Dimens {
- width: size.width,
- height: size.height,
- });
- });
- }
-
- /// Sets the window's key size callback.
- pub fn set_key_callback(
- &self,
- callback: impl Fn(Key, i32, KeyState, KeyModifiers) + 'static,
- )
- {
- self.inner
- .set_key_callback(move |key, scancode, key_state, key_modifiers| {
- let Some(key_state) = KeyState::from_glfw_key_state(key_state) else {
- return;
- };
-
- callback(
- Key::from_glfw_key(key),
- scancode,
- key_state,
- KeyModifiers::from_bits_truncate(key_modifiers.bits()),
- )
- });
- }
-
- /// Sets the window's cursor position callback.
- pub fn set_cursor_pos_callback(&self, callback: impl Fn(Vec2<f64>) + 'static)
- {
- self.inner
- .set_cursor_pos_callback(move |pos| callback(Vec2 { x: pos.x, y: pos.y }));
- }
-
- /// Sets the window's mouse button callback. The given function is called when a mouse
- /// button enters a new state.
- pub fn set_mouse_button_callback(
- &self,
- callback: impl Fn(MouseButton, MouseButtonState, KeyModifiers) + 'static,
- )
- {
- self.inner.set_mouse_button_callback(
- move |mouse_button, mouse_button_state, key_modifiers| {
- callback(
- MouseButton::from_glfw_mouse_button(mouse_button),
- MouseButtonState::from_glfw_mouse_button_state(mouse_button_state),
- KeyModifiers::from_bits_truncate(key_modifiers.bits()),
- )
- },
- );
- }
-
- /// Sets the window's close callback.
- pub fn set_close_callback(&self, callback: impl Fn() + 'static)
- {
- self.inner.set_close_callback(callback);
- }
-
- /// Sets the window's focus callback. The callback is called when the window loses or
- /// gains input focus.
- pub fn set_focus_callback(&self, callback: impl Fn(bool) + 'static)
- {
- self.inner.set_focus_callback(callback);
- }
-}
-
-/// [`Window`] builder.
-#[derive(Debug, Clone, Default)]
-pub struct Builder
-{
- inner: glfw::WindowBuilder,
-}
-
-impl Builder
-{
- /// Sets whether the OpenGL context should be created in debug mode, which may
- /// provide additional error and diagnostic reporting functionality.
- pub fn opengl_debug_context(mut self, enabled: bool) -> Self
- {
- self.inner = self.inner.hint(
- WindowCreationHint::OpenGLDebugContext,
- WindowCreationHintValue::Bool(enabled),
- );
-
- self
- }
-
- /// Set the desired number of samples to use for multisampling. Zero disables
- /// multisampling.
- pub fn multisampling_sample_count(mut self, sample_count: u16) -> Self
- {
- self.inner = self.inner.hint(
- WindowCreationHint::Samples,
- WindowCreationHintValue::Number(sample_count as i32),
- );
-
- self
- }
-
- /// Creates a new window.
- ///
- /// # Errors
- /// Will return `Err` if the title contains a internal nul byte or if a platform error
- /// occurs.
- pub fn create(&self, size: Dimens<u32>, title: &str) -> Result<Window, Error>
- {
- let builder = self.inner.clone().hint(
- WindowCreationHint::OpenGLDebugContext,
- WindowCreationHintValue::Bool(true),
- );
-
- let window = builder.create(
- &WindowSize {
- width: size.width,
- height: size.height,
- },
- title,
- )?;
-
- Ok(Window { inner: window })
- }
-}
-
-#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, VariantArr)]
-#[variant_arr(name = KEYS)]
-pub enum Key
-{
- Space,
- Apostrophe,
- Comma,
- Minus,
- Period,
- Slash,
- Digit0,
- Digit1,
- Digit2,
- Digit3,
- Digit4,
- Digit5,
- Digit6,
- Digit7,
- Digit8,
- Digit9,
- Semicolon,
- Equal,
- A,
- B,
- C,
- D,
- E,
- F,
- G,
- H,
- I,
- J,
- K,
- L,
- M,
- N,
- O,
- P,
- Q,
- R,
- S,
- T,
- U,
- V,
- W,
- X,
- Y,
- Z,
- LeftBracket,
- Backslash,
- RightBracket,
- GraveAccent,
- World1,
- World2,
- Escape,
- Enter,
- Tab,
- Backspace,
- Insert,
- Delete,
- Right,
- Left,
- Down,
- Up,
- PageUp,
- PageDown,
- Home,
- End,
- CapsLock,
- ScrollLock,
- NumLock,
- PrintScreen,
- Pause,
- F1,
- F2,
- F3,
- F4,
- F5,
- F6,
- F7,
- F8,
- F9,
- F10,
- F11,
- F12,
- F13,
- F14,
- F15,
- F16,
- F17,
- F18,
- F19,
- F20,
- F21,
- F22,
- F23,
- F24,
- F25,
- Kp0,
- Kp1,
- Kp2,
- Kp3,
- Kp4,
- Kp5,
- Kp6,
- Kp7,
- Kp8,
- Kp9,
- KpDecimal,
- KpDivide,
- KpMultiply,
- KpSubtract,
- KpAdd,
- KpEnter,
- KpEqual,
- LeftShift,
- LeftControl,
- LeftAlt,
- LeftSuper,
- RightShift,
- RightControl,
- RightAlt,
- RightSuper,
- Menu,
-}
-
-impl Key
-{
- fn from_glfw_key(glfw_key: glfw::window::Key) -> Self
- {
- match glfw_key {
- glfw::window::Key::Space => Self::Space,
- glfw::window::Key::Apostrophe => Self::Apostrophe,
- glfw::window::Key::Comma => Self::Comma,
- glfw::window::Key::Minus => Self::Minus,
- glfw::window::Key::Period => Self::Period,
- glfw::window::Key::Slash => Self::Slash,
- glfw::window::Key::Digit0 => Self::Digit0,
- glfw::window::Key::Digit1 => Self::Digit1,
- glfw::window::Key::Digit2 => Self::Digit2,
- glfw::window::Key::Digit3 => Self::Digit3,
- glfw::window::Key::Digit4 => Self::Digit4,
- glfw::window::Key::Digit5 => Self::Digit5,
- glfw::window::Key::Digit6 => Self::Digit6,
- glfw::window::Key::Digit7 => Self::Digit7,
- glfw::window::Key::Digit8 => Self::Digit8,
- glfw::window::Key::Digit9 => Self::Digit9,
- glfw::window::Key::Semicolon => Self::Semicolon,
- glfw::window::Key::Equal => Self::Equal,
- glfw::window::Key::A => Self::A,
- glfw::window::Key::B => Self::B,
- glfw::window::Key::C => Self::C,
- glfw::window::Key::D => Self::D,
- glfw::window::Key::E => Self::E,
- glfw::window::Key::F => Self::F,
- glfw::window::Key::G => Self::G,
- glfw::window::Key::H => Self::H,
- glfw::window::Key::I => Self::I,
- glfw::window::Key::J => Self::J,
- glfw::window::Key::K => Self::K,
- glfw::window::Key::L => Self::L,
- glfw::window::Key::M => Self::M,
- glfw::window::Key::N => Self::N,
- glfw::window::Key::O => Self::O,
- glfw::window::Key::P => Self::P,
- glfw::window::Key::Q => Self::Q,
- glfw::window::Key::R => Self::R,
- glfw::window::Key::S => Self::S,
- glfw::window::Key::T => Self::T,
- glfw::window::Key::U => Self::U,
- glfw::window::Key::V => Self::V,
- glfw::window::Key::W => Self::W,
- glfw::window::Key::X => Self::X,
- glfw::window::Key::Y => Self::Y,
- glfw::window::Key::Z => Self::Z,
- glfw::window::Key::LeftBracket => Self::LeftBracket,
- glfw::window::Key::Backslash => Self::Backslash,
- glfw::window::Key::RightBracket => Self::RightBracket,
- glfw::window::Key::GraveAccent => Self::GraveAccent,
- glfw::window::Key::World1 => Self::World1,
- glfw::window::Key::World2 => Self::World2,
- glfw::window::Key::Escape => Self::Escape,
- glfw::window::Key::Enter => Self::Enter,
- glfw::window::Key::Tab => Self::Tab,
- glfw::window::Key::Backspace => Self::Backspace,
- glfw::window::Key::Insert => Self::Insert,
- glfw::window::Key::Delete => Self::Delete,
- glfw::window::Key::Right => Self::Right,
- glfw::window::Key::Left => Self::Left,
- glfw::window::Key::Down => Self::Down,
- glfw::window::Key::Up => Self::Up,
- glfw::window::Key::PageUp => Self::PageUp,
- glfw::window::Key::PageDown => Self::PageDown,
- glfw::window::Key::Home => Self::Home,
- glfw::window::Key::End => Self::End,
- glfw::window::Key::CapsLock => Self::CapsLock,
- glfw::window::Key::ScrollLock => Self::ScrollLock,
- glfw::window::Key::NumLock => Self::NumLock,
- glfw::window::Key::PrintScreen => Self::PrintScreen,
- glfw::window::Key::Pause => Self::Pause,
- glfw::window::Key::F1 => Self::F1,
- glfw::window::Key::F2 => Self::F2,
- glfw::window::Key::F3 => Self::F3,
- glfw::window::Key::F4 => Self::F4,
- glfw::window::Key::F5 => Self::F5,
- glfw::window::Key::F6 => Self::F6,
- glfw::window::Key::F7 => Self::F7,
- glfw::window::Key::F8 => Self::F8,
- glfw::window::Key::F9 => Self::F9,
- glfw::window::Key::F10 => Self::F10,
- glfw::window::Key::F11 => Self::F11,
- glfw::window::Key::F12 => Self::F12,
- glfw::window::Key::F13 => Self::F13,
- glfw::window::Key::F14 => Self::F14,
- glfw::window::Key::F15 => Self::F15,
- glfw::window::Key::F16 => Self::F16,
- glfw::window::Key::F17 => Self::F17,
- glfw::window::Key::F18 => Self::F18,
- glfw::window::Key::F19 => Self::F19,
- glfw::window::Key::F20 => Self::F20,
- glfw::window::Key::F21 => Self::F21,
- glfw::window::Key::F22 => Self::F22,
- glfw::window::Key::F23 => Self::F23,
- glfw::window::Key::F24 => Self::F24,
- glfw::window::Key::F25 => Self::F25,
- glfw::window::Key::Kp0 => Self::Kp0,
- glfw::window::Key::Kp1 => Self::Kp1,
- glfw::window::Key::Kp2 => Self::Kp2,
- glfw::window::Key::Kp3 => Self::Kp3,
- glfw::window::Key::Kp4 => Self::Kp4,
- glfw::window::Key::Kp5 => Self::Kp5,
- glfw::window::Key::Kp6 => Self::Kp6,
- glfw::window::Key::Kp7 => Self::Kp7,
- glfw::window::Key::Kp8 => Self::Kp8,
- glfw::window::Key::Kp9 => Self::Kp9,
- glfw::window::Key::KpDecimal => Self::KpDecimal,
- glfw::window::Key::KpDivide => Self::KpDivide,
- glfw::window::Key::KpMultiply => Self::KpMultiply,
- glfw::window::Key::KpSubtract => Self::KpSubtract,
- glfw::window::Key::KpAdd => Self::KpAdd,
- glfw::window::Key::KpEnter => Self::KpEnter,
- glfw::window::Key::KpEqual => Self::KpEqual,
- glfw::window::Key::LeftShift => Self::LeftShift,
- glfw::window::Key::LeftControl => Self::LeftControl,
- glfw::window::Key::LeftAlt => Self::LeftAlt,
- glfw::window::Key::LeftSuper => Self::LeftSuper,
- glfw::window::Key::RightShift => Self::RightShift,
- glfw::window::Key::RightControl => Self::RightControl,
- glfw::window::Key::RightAlt => Self::RightAlt,
- glfw::window::Key::RightSuper => Self::RightSuper,
- glfw::window::Key::Menu => Self::Menu,
- }
- }
-}
-
-#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
-pub enum KeyState
-{
- Pressed,
- Released,
-}
-
-impl KeyState
-{
- fn from_glfw_key_state(glfw_key_state: glfw::window::KeyState) -> Option<Self>
- {
- match glfw_key_state {
- glfw::window::KeyState::Pressed => Some(Self::Pressed),
- glfw::window::KeyState::Released => Some(Self::Released),
- glfw::window::KeyState::Repeat => None,
- }
- }
-}
-
-#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
-pub enum MouseButton
-{
- One,
- Two,
- Three,
- Four,
- Five,
- Six,
- Seven,
- Eight,
-}
-
-impl MouseButton
-{
- pub const LEFT: Self = Self::One;
- pub const MIDDLE: Self = Self::Three;
- pub const RIGHT: Self = Self::Two;
-
- fn from_glfw_mouse_button(mouse_button: glfw::window::MouseButton) -> Self
- {
- match mouse_button {
- glfw::window::MouseButton::One => Self::One,
- glfw::window::MouseButton::Two => Self::Two,
- glfw::window::MouseButton::Three => Self::Three,
- glfw::window::MouseButton::Four => Self::Four,
- glfw::window::MouseButton::Five => Self::Five,
- glfw::window::MouseButton::Six => Self::Six,
- glfw::window::MouseButton::Seven => Self::Seven,
- glfw::window::MouseButton::Eight => Self::Eight,
- }
- }
-}
-
-#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
-pub enum MouseButtonState
-{
- Pressed,
- Released,
-}
-
-impl MouseButtonState
-{
- fn from_glfw_mouse_button_state(
- mouse_button_state: glfw::window::MouseButtonState,
- ) -> Self
- {
- match mouse_button_state {
- glfw::window::MouseButtonState::Pressed => Self::Pressed,
- glfw::window::MouseButtonState::Released => Self::Released,
- }
- }
-}
-
-bitflags! {
- #[derive(Debug, Clone, Copy)]
- pub struct KeyModifiers: i32 {
- const SHIFT = glfw::window::KeyModifiers::SHIFT.bits();
- const CONTROL = glfw::window::KeyModifiers::CONTROL.bits();
- const ALT = glfw::window::KeyModifiers::ALT.bits();
- const SUPER = glfw::window::KeyModifiers::SUPER.bits();
- const CAPS_LOCK = glfw::window::KeyModifiers::CAPS_LOCK.bits();
- const NUM_LOCK = glfw::window::KeyModifiers::NUM_LOCK.bits();
- }
-}
-
-#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
-pub enum CursorMode
-{
- /// Hides and grabs the cursor, providing virtual and unlimited cursor movement.
- Disabled,
-
- /// Makes the cursor invisible when it is over the content area of the window but
- /// does not restrict the cursor from leaving.
- Hidden,
-
- /// Makes the cursor visible and behaving normally.
- Normal,
-}
-
-impl CursorMode
-{
- fn to_glfw_cursor_mode(self) -> glfw::window::CursorMode
- {
- match self {
- Self::Disabled => glfw::window::CursorMode::Disabled,
- Self::Hidden => glfw::window::CursorMode::Hidden,
- Self::Normal => glfw::window::CursorMode::Normal,
- }
- }
-}
-
-#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
-pub enum InputMode
-{
- /// When the cursor is disabled, raw (unscaled and unaccelerated) mouse motion can be
- /// enabled if available.
- ///
- /// Raw mouse motion is closer to the actual motion of the mouse across a surface. It
- /// is not affected by the scaling and acceleration applied to the motion of the
- /// desktop cursor. That processing is suitable for a cursor while raw motion is
- /// better for controlling for example a 3D camera. Because of this, raw mouse motion
- /// is only provided when the cursor is disabled.
- RawMouseMotion,
-}
-
-impl InputMode
-{
- fn to_glfw_input_mode(self) -> glfw::window::InputMode
- {
- match self {
- Self::RawMouseMotion => glfw::window::InputMode::RawMouseMotion,
- }
- }
-}
-
-#[derive(Debug)]
-pub struct Extension
-{
- window_builder: Builder,
- window_size: Dimens<u32>,
- window_title: String,
-}
-
-impl Extension
-{
- #[must_use]
- pub fn new(window_builder: Builder) -> Self
- {
- Self { window_builder, ..Default::default() }
- }
-
- #[must_use]
- pub fn window_size(mut self, window_size: Dimens<u32>) -> Self
- {
- self.window_size = window_size;
-
- self
- }
-
- #[must_use]
- pub fn window_title(mut self, window_title: impl Into<String>) -> Self
- {
- self.window_title = window_title.into();
-
- self
- }
-}
-
-impl ecs::extension::Extension for Extension
-{
- fn collect(self, mut collector: ExtensionCollector<'_>)
- {
- collector.add_declared_entity(&self::UPDATE_PHASE);
-
- collector.add_system(*START_PHASE, initialize);
- collector.add_system(*self::UPDATE_PHASE, update);
-
- let window = self
- .window_builder
- .create(self.window_size, &self.window_title)
- .unwrap();
-
- window.set_cursor_mode(CursorMode::Normal).unwrap();
-
- collector.add_sole(window).ok();
- }
-}
-
-impl Default for Extension
-{
- fn default() -> Self
- {
- Self {
- window_builder: Builder::default(),
- window_size: Dimens { width: 1920, height: 1080 },
- window_title: String::new(),
- }
- }
-}
-
-#[derive(Debug, thiserror::Error)]
-#[error(transparent)]
-pub struct Error(glfw::Error);
-
-impl From<glfw::Error> for Error
-{
- fn from(err: glfw::Error) -> Self
- {
- Self(err)
- }
-}
-
-fn initialize(window: Single<Window>, actions: Actions)
-{
- let actions_weak_ref = actions.to_weak_ref();
-
- window.set_close_callback(move || {
- let actions_weak_ref = actions_weak_ref.clone();
-
- let actions_ref = actions_weak_ref.access().expect("No world");
-
- actions_ref.to_actions().stop();
- });
-}
-
-fn update(window: Single<Window>)
-{
- window
- .swap_buffers()
- .expect("Failed to swap window buffers");
-
- window.poll_events().expect("Failed to poll window events");
-}