diff --git a/src/render/window.rs b/src/render/window.rs index bdd4dd3..39f8f72 100644 --- a/src/render/window.rs +++ b/src/render/window.rs @@ -1,7 +1,7 @@ use std::sync::Arc; -use glam::Vec2; -use tracing::{warn, error}; +use glam::{Vec2, IVec2}; +use tracing::{warn, error, debug}; use winit::{window::{Window, Fullscreen}, dpi::{LogicalPosition, LogicalSize}, error::ExternalError}; pub use winit::window::{CursorGrabMode, CursorIcon, Icon, Theme, WindowButtons, WindowLevel}; @@ -99,19 +99,19 @@ pub struct WindowOptions { /// Platform-specific: /// * iOS / Android: Unsupported. /// * Web: Sets the size of the canvas element. - pub inner_size: Vec2, + pub inner_size: IVec2, /// Sets a maximum dimension size for the window. /// /// Platform-specific: /// * iOS / Android / Web / Orbital: Unsupported. - pub max_inner_size: Option, + pub max_inner_size: Option, /// Sets a minimum dimension size for the window. /// /// Platform-specific: /// * iOS / Android / Web / Orbital: Unsupported. - pub min_inner_size: Option, + pub min_inner_size: Option, /// Sets the window to maximized or back. /// @@ -188,7 +188,7 @@ impl Default for WindowOptions { mode: WindowMode::Windowed, ime_allowed: false, ime_position: Default::default(), - inner_size: Default::default(), + inner_size: glam::i32::IVec2::new(800, 600), max_inner_size: None, min_inner_size: None, maximized: false, @@ -209,20 +209,48 @@ pub struct WindowPlugin { create_options: WindowOptions, } +/// Convert an Vec2 to a LogicalPosition fn vec2_to_logical_pos(pos: Vec2) -> LogicalPosition { LogicalPosition { x: pos.x, y: pos.y } } -fn vec2_to_logical_size(size: Vec2) -> LogicalSize { +/// Convert an IVec2 to a LogicalSize +fn ivec2_to_logical_size(size: IVec2) -> LogicalSize { LogicalSize { width: size.x, height: size.y } } -fn vec2_to_logical_pos_op(pos: Option) -> Option> { - pos.map(|pos| vec2_to_logical_pos(pos)) +/// Convert an Option to an Option> +fn ivec2_to_logical_size_op(size: Option) -> Option> { + size.map(|size| ivec2_to_logical_size(size)) } +/// Convert an Option to an Option> fn vec2_to_logical_size_op(size: Option) -> Option> { - size.map(|size| vec2_to_logical_size(size)) + size.map(|size| LogicalSize { width: size.x, height: size.y } ) +} + +/// Set the cursor grab of a window depending on the platform. +/// This will also modify the parameter `grab` to ensure it matches what the platform can support +fn set_cursor_grab(window: &Window, grab: &mut CursorGrabMode) -> anyhow::Result<()> { + if *grab != CursorGrabMode::None { + if cfg!(unix) { + *grab = CursorGrabMode::Confined; + // TODO: Find a way to see if winit is using x11 or wayland. wayland supports Locked + } else if cfg!(wasm) { + *grab = CursorGrabMode::Locked; + } else if cfg!(windows) { + *grab = CursorGrabMode::Confined; // NOTE: May support Locked later + } else if cfg!(target_os = "macos") { + *grab = CursorGrabMode::Locked; // NOTE: May support Confined later + } else if cfg!(any(target_os = "android", target_os = "ios", target_os = "orbital")) { + warn!("CursorGrabMode is not supported on Android, IOS, or Oribital, skipping"); + return Ok(()) + } + } + + window.set_cursor_grab(*grab)?; + + Ok(()) } fn window_updater_system(world: &mut edict::World) -> anyhow::Result<()> { @@ -230,36 +258,10 @@ fn window_updater_system(world: &mut edict::World) -> anyhow::Result<()> { // if the options changed, update the window if opts.changed() { window.set_content_protected(opts.content_protected); - match opts.cursor_grab { - CursorGrabMode::Confined => { - match window.set_cursor_grab(opts.cursor_grab) - .or_else(|_e| window.set_cursor_grab(CursorGrabMode::Locked)) { - Ok(()) => {}, - Err(ExternalError::NotSupported(_)) => { - warn!("Setting CursorGrab is not supported on this platform"); - }, - Err(e) => { - error!("OS error when setting CursorGrab: {:?}", e); - } - } - }, - _ => { - match window.set_cursor_grab(opts.cursor_grab) { - Ok(()) => {}, - Err(ExternalError::NotSupported(_)) => { - warn!("Setting CursorGrab is not supported on this platform"); - }, - Err(e) => { - error!("OS error when setting CursorGrab: {:?}", e); - } - } - } - } + set_cursor_grab(&window, &mut opts.cursor_grab)?; match window.set_cursor_hittest(opts.cursor_hittest) { Ok(()) => {}, - Err(ExternalError::NotSupported(_)) => { - warn!("Setting cursor hittest is not supported on this platform"); - }, + Err(ExternalError::NotSupported(_)) => { /* ignore */ }, Err(e) => { error!("OS error when setting cursor hittest: {:?}", e); } @@ -284,12 +286,12 @@ fn window_updater_system(world: &mut edict::World) -> anyhow::Result<()> { window.set_ime_allowed(opts.ime_allowed); window.set_ime_position(vec2_to_logical_pos(opts.ime_position)); - //window.set_inner_size(vec2_to_logical_size(opts.inner_size)); // TODO + window.set_inner_size(ivec2_to_logical_size(opts.inner_size)); if opts.max_inner_size.is_some() { - window.set_max_inner_size(vec2_to_logical_size_op(opts.max_inner_size)); + window.set_max_inner_size(ivec2_to_logical_size_op(opts.max_inner_size)); } if opts.min_inner_size.is_some() { - window.set_min_inner_size(vec2_to_logical_size_op(opts.min_inner_size)); + window.set_min_inner_size(ivec2_to_logical_size_op(opts.min_inner_size)); } //window.set_maximized(opts.maximized); // TODO //window.set_minimized(opts.minimized); // TODO