diff options
Diffstat (limited to 'engine/src')
-rw-r--r-- | engine/src/camera/fly.rs | 12 | ||||
-rw-r--r-- | engine/src/file_format/wavefront/mtl.rs | 11 | ||||
-rw-r--r-- | engine/src/input.rs | 7 | ||||
-rw-r--r-- | engine/src/opengl/mod.rs | 22 | ||||
-rw-r--r-- | engine/src/opengl/texture.rs | 6 | ||||
-rw-r--r-- | engine/src/performance.rs | 16 | ||||
-rw-r--r-- | engine/src/renderer/opengl.rs | 59 | ||||
-rw-r--r-- | engine/src/texture.rs | 5 | ||||
-rw-r--r-- | engine/src/window.rs | 474 |
9 files changed, 515 insertions, 97 deletions
diff --git a/engine/src/camera/fly.rs b/engine/src/camera/fly.rs index b6ba7aa..99739e3 100644 --- a/engine/src/camera/fly.rs +++ b/engine/src/camera/fly.rs @@ -2,12 +2,11 @@ use ecs::component::local::Local; use ecs::sole::Single; use ecs::system::{Into, System}; use ecs::{Component, Query}; -use glfw::window::{Key, KeyState}; use crate::camera::{Active as ActiveCamera, Camera}; use crate::delta_time::DeltaTime; use crate::event::Update as UpdateEvent; -use crate::input::{Cursor, CursorFlags, Keys}; +use crate::input::{Cursor, CursorFlags, Key, KeyState, Keys}; use crate::transform::Position; use crate::util::builder; use crate::vector::{Vec2, Vec3}; @@ -87,7 +86,6 @@ fn update( { for (mut camera, mut camera_pos, mut fly_camera, _) in &camera_query { if cursor.has_moved && cursor_flags.is_first_move.flag { - #[cfg(feature = "debug")] tracing::debug!("First cursor move"); cursor_state.last_pos = cursor.position; @@ -123,23 +121,23 @@ fn update( camera.global_up = cam_right.cross(&direction).normalize(); - if matches!(keys.get_key_state(Key::W), KeyState::Pressed) { + if keys.get_key_state(Key::W) == KeyState::Pressed { camera_pos.position += direction * fly_camera.speed * delta_time.as_secs_f32(); } - if matches!(keys.get_key_state(Key::S), KeyState::Pressed) { + if keys.get_key_state(Key::S) == KeyState::Pressed { camera_pos.position -= direction * fly_camera.speed * delta_time.as_secs_f32(); } - if matches!(keys.get_key_state(Key::A), KeyState::Pressed) { + if keys.get_key_state(Key::A) == KeyState::Pressed { let cam_left = -direction.cross(&Vec3::UP).normalize(); camera_pos.position += cam_left * fly_camera.speed * delta_time.as_secs_f32(); } - if matches!(keys.get_key_state(Key::D), KeyState::Pressed) { + if keys.get_key_state(Key::D) == KeyState::Pressed { let cam_right = direction.cross(&Vec3::UP).normalize(); camera_pos.position += diff --git a/engine/src/file_format/wavefront/mtl.rs b/engine/src/file_format/wavefront/mtl.rs index ef6e894..d90dbcf 100644 --- a/engine/src/file_format/wavefront/mtl.rs +++ b/engine/src/file_format/wavefront/mtl.rs @@ -44,7 +44,6 @@ pub fn parse(obj_content: &str) -> Result<Vec<NamedMaterial>, Error> .filter(|(_, statement)| matches!(statement.keyword, Keyword::Newmtl)) .count(); - #[cfg(feature = "debug")] tracing::debug!("Material count: {material_cnt}"); statements_to_materials(statements, material_cnt) @@ -93,7 +92,7 @@ pub enum Error }, } -#[cfg_attr(feature = "debug", tracing::instrument(skip_all))] +#[tracing::instrument(skip_all)] fn statements_to_materials( statements: impl IntoIterator<Item = (usize, Statement<Keyword>)>, material_cnt: usize, @@ -110,7 +109,6 @@ fn statements_to_materials( for (line_no, statement) in statements { if statement.keyword == Keyword::Newmtl { if curr_material.ready { - #[cfg(feature = "debug")] tracing::debug!("Building material"); let material = curr_material.material_builder.clone().build(); @@ -135,7 +133,6 @@ fn statements_to_materials( Keyword::Ka => { let color = get_color_from_statement(&statement, line_no)?; - #[cfg(feature = "debug")] tracing::debug!("Adding ambient color"); curr_material.material_builder = @@ -144,7 +141,6 @@ fn statements_to_materials( Keyword::Kd => { let color = get_color_from_statement(&statement, line_no)?; - #[cfg(feature = "debug")] tracing::debug!("Adding diffuse color"); curr_material.material_builder = @@ -153,7 +149,6 @@ fn statements_to_materials( Keyword::Ks => { let color = get_color_from_statement(&statement, line_no)?; - #[cfg(feature = "debug")] tracing::debug!("Adding specular color"); curr_material.material_builder = @@ -172,7 +167,6 @@ fn statements_to_materials( let texture = Texture::open(Path::new(texture_file_path))?; - #[cfg(feature = "debug")] tracing::debug!("Adding ambient map"); let texture_id = texture.id(); @@ -185,7 +179,6 @@ fn statements_to_materials( Keyword::MapKd => { let texture = get_map_from_texture(&statement, line_no)?; - #[cfg(feature = "debug")] tracing::debug!("Adding diffuse map"); let texture_id = texture.id(); @@ -198,7 +191,6 @@ fn statements_to_materials( Keyword::MapKs => { let texture = get_map_from_texture(&statement, line_no)?; - #[cfg(feature = "debug")] tracing::debug!("Adding specular map"); let texture_id = texture.id(); @@ -213,7 +205,6 @@ fn statements_to_materials( } if curr_material.ready { - #[cfg(feature = "debug")] tracing::debug!("Building last material"); let material = curr_material.material_builder.build(); diff --git a/engine/src/input.rs b/engine/src/input.rs index f4166f6..e847702 100644 --- a/engine/src/input.rs +++ b/engine/src/input.rs @@ -68,10 +68,6 @@ impl Keys pub fn set_key_state(&mut self, key: Key, new_key_state: KeyState) { - if matches!(new_key_state, KeyState::Repeat) { - return; - } - let Some(key_data) = self.map.get_mut(&key) else { unreachable!(); }; @@ -194,7 +190,6 @@ fn initialize( let cursor_flags_weak_ref = cursor_flags.to_weak_ref(); window.set_focus_callback(move |is_focused| { - #[cfg(feature = "debug")] tracing::trace!("Window is focused: {is_focused}"); let cursor_flags_ref = cursor_flags_weak_ref.access().expect("No world"); @@ -209,7 +204,6 @@ fn maybe_clear_cursor_is_first_move( ) { if cursor_flags.is_first_move.pending_clear { - #[cfg(feature = "debug")] tracing::trace!("Clearing is_first_move"); // This flag was set for the whole previous tick so it can be cleared now @@ -219,7 +213,6 @@ fn maybe_clear_cursor_is_first_move( } if cursor.has_moved && cursor_flags.is_first_move.flag { - #[cfg(feature = "debug")] tracing::trace!("Setting flag to clear is_first_move next tick"); // Make this system clear is_first_move the next time it runs diff --git a/engine/src/opengl/mod.rs b/engine/src/opengl/mod.rs index a4d3959..53e0120 100644 --- a/engine/src/opengl/mod.rs +++ b/engine/src/opengl/mod.rs @@ -1,4 +1,5 @@ use bitflags::bitflags; +use gl::types::GLint; use crate::data_types::dimens::Dimens; use crate::vector::Vec2; @@ -11,7 +12,6 @@ pub mod vertex_array; mod util; -#[cfg(feature = "debug")] pub mod debug; pub fn set_viewport(position: Vec2<u32>, size: Dimens<u32>) @@ -48,6 +48,17 @@ pub fn enable(capacity: Capability) } } +pub fn get_context_flags() -> ContextFlags +{ + let mut context_flags: GLint = 0; + + unsafe { + gl::GetIntegerv(gl::CONTEXT_FLAGS as u32, &mut context_flags); + } + + ContextFlags::from_bits_truncate(context_flags as u32) +} + bitflags! { #[derive(Debug, Clone, Copy)] pub struct BufferClearMask: u32 { @@ -106,3 +117,12 @@ impl From<crate::draw_flags::PolygonModeFace> for PolygonModeFace } } } + +bitflags! { +#[derive(Debug, Clone, Copy)] +pub struct ContextFlags: u32 { + const FORWARD_COMPATIBLE = gl::CONTEXT_FLAG_FORWARD_COMPATIBLE_BIT; + const DEBUG = gl::CONTEXT_FLAG_DEBUG_BIT; + const ROBUST_ACCESS = gl::CONTEXT_FLAG_ROBUST_ACCESS_BIT; +} +} diff --git a/engine/src/opengl/texture.rs b/engine/src/opengl/texture.rs index 074ade7..52c8554 100644 --- a/engine/src/opengl/texture.rs +++ b/engine/src/opengl/texture.rs @@ -1,5 +1,5 @@ use crate::data_types::dimens::Dimens; -use crate::texture::{Id, Properties}; +use crate::texture::Properties; #[derive(Debug)] pub struct Texture @@ -224,8 +224,8 @@ macro_rules! texture_unit_enum { } } - pub fn from_texture_id(texture_id: Id) -> Option<Self> { - match texture_id.into_inner() { + pub fn from_num(num: usize) -> Option<Self> { + match num { #( N => Some(Self::No~N), )* diff --git a/engine/src/performance.rs b/engine/src/performance.rs index ffc5c27..3ec8994 100644 --- a/engine/src/performance.rs +++ b/engine/src/performance.rs @@ -21,20 +21,6 @@ impl ecs::extension::Extension for Extension } } -#[cfg(feature = "debug")] -macro_rules! log_perf { - ($($tt: tt)*) => { - tracing::info!($($tt)*); - }; -} - -#[cfg(not(feature = "debug"))] -macro_rules! log_perf { - ($($tt: tt)*) => { - println!($($tt)*); - }; -} - fn log_perf(mut state: Local<State>) { let Some(last_time) = state.last_time else { @@ -46,7 +32,7 @@ fn log_perf(mut state: Local<State>) state.last_time = Some(time_now); - log_perf!( + tracing::info!( "Frame time: {}us", time_now.duration_since(last_time).as_micros() ); diff --git a/engine/src/renderer/opengl.rs b/engine/src/renderer/opengl.rs index deb26a8..c036cc0 100644 --- a/engine/src/renderer/opengl.rs +++ b/engine/src/renderer/opengl.rs @@ -24,8 +24,15 @@ use crate::material::{Flags as MaterialFlags, Material}; use crate::matrix::Matrix; use crate::mesh::Mesh; use crate::opengl::buffer::{Buffer, Usage as BufferUsage}; -#[cfg(feature = "debug")] -use crate::opengl::debug::{MessageSeverity, MessageSource, MessageType}; +use crate::opengl::debug::{ + enable_debug_output, + set_debug_message_callback, + set_debug_message_control, + MessageIdsAction, + MessageSeverity, + MessageSource, + MessageType, +}; use crate::opengl::glsl::{ preprocess as glsl_preprocess, PreprocessingError as GlslPreprocessingError, @@ -46,7 +53,14 @@ use crate::opengl::vertex_array::{ PrimitiveKind, VertexArray, }; -use crate::opengl::{clear_buffers, enable, BufferClearMask, Capability}; +use crate::opengl::{ + clear_buffers, + enable, + get_context_flags as get_opengl_context_flags, + BufferClearMask, + Capability, + ContextFlags, +}; use crate::projection::{new_perspective_matrix, Projection}; use crate::texture::{Id as TextureId, Texture}; use crate::transform::{Position, Scale}; @@ -101,8 +115,9 @@ fn initialize(window: Single<Window>) } }); - #[cfg(feature = "debug")] - initialize_debug(); + if get_opengl_context_flags().contains(ContextFlags::DEBUG) { + initialize_debug(); + } let window_size = window.size().expect("Failed to get window size"); @@ -129,7 +144,6 @@ fn render( ) { let Some((camera, camera_pos, _)) = camera_query.iter().next() else { - #[cfg(feature = "debug")] tracing::warn!("No current camera. Nothing will be rendered"); return; }; @@ -203,15 +217,12 @@ fn render( &camera_pos, ); - for texture in &material.textures { + for (index, texture) in material.textures.iter().enumerate() { let gl_texture = gl_textures .entry(texture.id()) .or_insert_with(|| create_gl_texture(texture)); - let texture_unit = - TextureUnit::from_texture_id(texture.id()).unwrap_or_else(|| { - panic!("Texture id {} is a invalid texture unit", texture.id()); - }); + let texture_unit = TextureUnit::from_num(index).expect("Too many textures"); set_active_texture_unit(texture_unit); @@ -252,20 +263,11 @@ fn set_viewport(position: Vec2<u32>, size: Dimens<u32>) crate::opengl::set_viewport(position, size); } -#[cfg(feature = "debug")] fn initialize_debug() { - use crate::opengl::debug::{ - enable_debug_output, - set_debug_message_callback, - set_debug_message_control, - MessageIdsAction, - }; - enable_debug_output(); set_debug_message_callback(opengl_debug_message_cb); - set_debug_message_control(None, None, None, &[], MessageIdsAction::Disable); } @@ -370,10 +372,9 @@ struct GlObjects impl GlObjects { - #[cfg_attr(feature = "debug", tracing::instrument(skip_all))] + #[tracing::instrument(skip_all)] fn new(mesh: &Mesh) -> Self { - #[cfg(feature = "debug")] tracing::trace!( "Creating vertex array, vertex buffer{}", if mesh.indices().is_some() { @@ -562,22 +563,29 @@ fn apply_light<PointLightHolder>( gl_shader_program .set_uniform_vec_3fv(c"material.specular", &material.specular.clone().into()); + let texture_map = material + .textures + .iter() + .enumerate() + .map(|(index, texture)| (texture.id(), index)) + .collect::<HashMap<_, _>>(); + #[allow(clippy::cast_possible_wrap)] gl_shader_program.set_uniform_1i( c"material.ambient_map", - material.ambient_map.into_inner() as i32, + *texture_map.get(&material.ambient_map).unwrap() as i32, ); #[allow(clippy::cast_possible_wrap)] gl_shader_program.set_uniform_1i( c"material.diffuse_map", - material.diffuse_map.into_inner() as i32, + *texture_map.get(&material.diffuse_map).unwrap() as i32, ); #[allow(clippy::cast_possible_wrap)] gl_shader_program.set_uniform_1i( c"material.specular_map", - material.specular_map.into_inner() as i32, + *texture_map.get(&material.specular_map).unwrap() as i32, ); gl_shader_program.set_uniform_1fv(c"material.shininess", material.shininess); @@ -688,7 +696,6 @@ fn create_view(camera: &Camera, camera_pos: &Position) -> Matrix<f32, 4, 4> view } -#[cfg(feature = "debug")] #[tracing::instrument(skip_all)] fn opengl_debug_message_cb( source: MessageSource, diff --git a/engine/src/texture.rs b/engine/src/texture.rs index f82b59d..16c1941 100644 --- a/engine/src/texture.rs +++ b/engine/src/texture.rs @@ -181,11 +181,6 @@ impl Id { Self { id } } - - pub(crate) fn into_inner(self) -> u32 - { - self.id - } } impl Display for Id diff --git a/engine/src/window.rs b/engine/src/window.rs index ccc1b8d..008c09b 100644 --- a/engine/src/window.rs +++ b/engine/src/window.rs @@ -1,31 +1,19 @@ use std::borrow::Cow; use std::ffi::{CStr, CString}; +use bitflags::bitflags; use ecs::actions::Actions; use ecs::extension::Collector as ExtensionCollector; use ecs::sole::Single; use ecs::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::event::{Conclude as ConcludeEvent, Start as StartEvent}; use crate::vector::Vec2; -mod reexports -{ - pub use glfw::window::{ - CursorMode, - Hint as CreationHint, - HintValue as CreationHintValue, - InputMode, - Key, - KeyModifiers, - KeyState, - }; -} - -pub use reexports::*; - #[derive(Debug, Sole)] /// Has to be dropped last since it holds the OpenGL context. #[sole(drop_last)] @@ -53,7 +41,9 @@ impl Window enabled: bool, ) -> Result<(), Error> { - Ok(self.inner.set_input_mode(input_mode, enabled)?) + Ok(self + .inner + .set_input_mode(input_mode.to_glfw_input_mode(), enabled)?) } /// Sets the cursor mode. @@ -62,7 +52,9 @@ impl Window /// If a platform error occurs. pub fn set_cursor_mode(&self, cursor_mode: CursorMode) -> Result<(), Error> { - Ok(self.inner.set_cursor_mode(cursor_mode)?) + 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 @@ -155,7 +147,19 @@ impl Window callback: impl Fn(Key, i32, KeyState, KeyModifiers) + 'static, ) { - self.inner.set_key_callback(callback); + 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. @@ -165,6 +169,24 @@ impl Window .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) { @@ -188,10 +210,26 @@ pub struct Builder impl Builder { - #[must_use] - pub fn creation_hint(mut self, hint: CreationHint, value: CreationHintValue) -> Self + /// 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(hint, value); + self.inner = self.inner.hint( + WindowCreationHint::Samples, + WindowCreationHintValue::Number(sample_count as i32), + ); self } @@ -204,8 +242,8 @@ impl Builder pub fn create(&self, size: Dimens<u32>, title: &str) -> Result<Window, Error> { let builder = self.inner.clone().hint( - CreationHint::OpenGLDebugContext, - CreationHintValue::Bool(cfg!(feature = "debug")), + WindowCreationHint::OpenGLDebugContext, + WindowCreationHintValue::Bool(true), ); let window = builder.create( @@ -220,6 +258,396 @@ impl Builder } } +#[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 { |