Skip to content

Commit

Permalink
integrated window, winit
Browse files Browse the repository at this point in the history
  • Loading branch information
R3DP1XL committed Dec 17, 2021
1 parent 29b93cf commit e51dd20
Show file tree
Hide file tree
Showing 8 changed files with 195 additions and 77 deletions.
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions plugin/window/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ lgn-utils = { path = "../../lib/utils", version = "0.1.0" }

# other
log = "0.4"
raw-window-handle = "0.4.2"

[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
uuid = { version = "0.8", features = ["v4", "serde"] }
Expand Down
7 changes: 4 additions & 3 deletions plugin/window/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,12 @@
#![allow()]

mod event;
mod raw_window_handle;
mod system;
mod window;
mod windows;

pub use crate::raw_window_handle::*;
pub use event::*;
pub use system::*;
pub use window::*;
Expand Down Expand Up @@ -113,9 +115,8 @@ impl Plugin for WindowPlugin {
let window_descriptor = app
.world
.get_resource::<WindowDescriptor>()
.map_or_else(WindowDescriptor::default, |descriptor| {
(*descriptor).clone()
});
.map(|descriptor| (*descriptor).clone())
.unwrap_or_default();
let mut create_window_event = app
.world
.get_resource_mut::<Events<CreateWindow>>()
Expand Down
39 changes: 39 additions & 0 deletions plugin/window/src/raw_window_handle.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#![allow(unsafe_code)]

use raw_window_handle::{HasRawWindowHandle, RawWindowHandle};

/// This wrapper exist to enable safely passing a [`RawWindowHandle`] across threads. Extracting the handle
/// is still an unsafe operation, so the caller must still validate that using the raw handle is safe for a given context.
#[derive(Debug, Clone)]
pub struct RawWindowHandleWrapper(RawWindowHandle);

impl RawWindowHandleWrapper {
pub(crate) fn new(handle: RawWindowHandle) -> Self {
Self(handle)
}

/// # Safety
/// This returns a [`HasRawWindowHandle`] impl, which exposes [`RawWindowHandle`]. Some platforms
/// have constraints on where/how this handle can be used. For example, some platforms don't support doing window
/// operations off of the main thread. The caller must ensure the [`RawWindowHandle`] is only used in valid contexts.
pub unsafe fn get_handle(&self) -> HasRawWindowHandleWrapper {
HasRawWindowHandleWrapper(self.0)
}
}

// SAFE: RawWindowHandle is just a normal "raw pointer", which doesn't impl Send/Sync. However the pointer is only
// exposed via an unsafe method that forces the user to make a call for a given platform. (ex: some platforms don't
// support doing window operations off of the main thread).
// A recommendation for this pattern (and more context) is available here:
// https://github.com/rust-windowing/raw-window-handle/issues/59
unsafe impl Send for RawWindowHandleWrapper {}
unsafe impl Sync for RawWindowHandleWrapper {}

pub struct HasRawWindowHandleWrapper(RawWindowHandle);

// SAFE: the caller has validated that this is a valid context to get RawWindowHandle
unsafe impl HasRawWindowHandle for HasRawWindowHandleWrapper {
fn raw_window_handle(&self) -> RawWindowHandle {
self.0
}
}
53 changes: 42 additions & 11 deletions plugin/window/src/window.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use lgn_math::{IVec2, Vec2};
use lgn_math::{DVec2, IVec2, Vec2};
use log::warn;
use raw_window_handle::RawWindowHandle;
use uuid::Uuid;

#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
Expand All @@ -21,6 +22,8 @@ impl WindowId {

use std::fmt;

use crate::raw_window_handle::RawWindowHandleWrapper;

impl fmt::Display for WindowId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.to_simple().fmt(f)
Expand Down Expand Up @@ -124,7 +127,8 @@ pub struct Window {
decorations: bool,
cursor_visible: bool,
cursor_locked: bool,
cursor_position: Option<Vec2>,
physical_cursor_position: Option<DVec2>,
raw_window_handle: RawWindowHandleWrapper,
focused: bool,
mode: WindowMode,
#[cfg(target_arch = "wasm32")]
Expand Down Expand Up @@ -181,15 +185,17 @@ pub enum WindowCommand {
}

/// Defines the way a window is displayed
/// The `use_size` option that is used in the Fullscreen variant
/// defines whether a videomode is chosen that best fits the width and height
/// in the Window structure, or if these are ignored.
/// E.g. when `use_size` is set to false the best video mode possible is chosen.
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum WindowMode {
/// Creates a window that uses the given size
Windowed,
/// Creates a borderless window that uses the full size of the screen
BorderlessFullscreen,
Fullscreen { use_size: bool },
/// Creates a fullscreen window that will render at desktop resolution. The app will use the closest supported size
/// from the given size and scale it to fit the screen.
SizedFullscreen,
/// Creates a fullscreen window that uses the maximum supported size
Fullscreen,
}

impl Window {
Expand All @@ -200,6 +206,7 @@ impl Window {
physical_height: u32,
scale_factor: f64,
position: Option<IVec2>,
raw_window_handle: RawWindowHandle,
) -> Self {
Self {
id,
Expand All @@ -217,7 +224,8 @@ impl Window {
decorations: window_descriptor.decorations,
cursor_visible: window_descriptor.cursor_visible,
cursor_locked: window_descriptor.cursor_locked,
cursor_position: None,
physical_cursor_position: None,
raw_window_handle: RawWindowHandleWrapper::new(raw_window_handle),
focused: true,
mode: window_descriptor.mode,
#[cfg(target_arch = "wasm32")]
Expand Down Expand Up @@ -468,10 +476,18 @@ impl Window {
});
}

/// The current mouse position, in physical pixels.
#[inline]
pub fn physical_cursor_position(&self) -> Option<DVec2> {
self.physical_cursor_position
}

/// The current mouse position, in logical pixels, taking into account the screen scale factor.
#[inline]
#[doc(alias = "mouse position")]
pub fn cursor_position(&self) -> Option<Vec2> {
self.cursor_position
self.physical_cursor_position
.map(|p| (p / self.scale_factor()).as_vec2())
}

pub fn set_cursor_position(&mut self, position: Vec2) {
Expand All @@ -487,8 +503,8 @@ impl Window {

#[allow(missing_docs)]
#[inline]
pub fn update_cursor_position_from_backend(&mut self, cursor_position: Option<Vec2>) {
self.cursor_position = cursor_position;
pub fn update_cursor_physical_position_from_backend(&mut self, cursor_position: Option<DVec2>) {
self.physical_cursor_position = cursor_position;
}

#[inline]
Expand All @@ -513,13 +529,18 @@ impl Window {
pub fn is_focused(&self) -> bool {
self.focused
}

pub fn raw_window_handle(&self) -> RawWindowHandleWrapper {
self.raw_window_handle.clone()
}
}

#[derive(Debug, Clone)]
#[allow(clippy::struct_excessive_bools)]
pub struct WindowDescriptor {
pub width: f32,
pub height: f32,
pub position: Option<Vec2>,
pub resize_constraints: WindowResizeConstraints,
pub scale_factor_override: Option<f64>,
pub title: String,
Expand All @@ -529,6 +550,14 @@ pub struct WindowDescriptor {
pub cursor_visible: bool,
pub cursor_locked: bool,
pub mode: WindowMode,
/// Sets whether the background of the window should be transparent.
/// # Platform-specific
/// - iOS / Android / Web: Unsupported.
/// - macOS X: Not working as expected.
/// - Windows 11: Not working as expected
/// macOS X transparent works with winit out of the box, so this issue might be related to: https://github.com/gfx-rs/wgpu/issues/687
/// Windows 11 is related to https://github.com/rust-windowing/winit/issues/2082
pub transparent: bool,
#[cfg(target_arch = "wasm32")]
pub canvas: Option<String>,
}
Expand All @@ -539,6 +568,7 @@ impl Default for WindowDescriptor {
title: "legion".to_string(),
width: 1280.,
height: 720.,
position: None,
resize_constraints: WindowResizeConstraints::default(),
scale_factor_override: None,
vsync: true,
Expand All @@ -547,6 +577,7 @@ impl Default for WindowDescriptor {
cursor_locked: false,
cursor_visible: true,
mode: WindowMode::Windowed,
transparent: false,
#[cfg(target_arch = "wasm32")]
canvas: None,
}
Expand Down
5 changes: 3 additions & 2 deletions plugin/winit/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,14 @@ lgn-app = { path = "../../lib/app", version = "0.1.0" }
lgn-ecs = { path = "../../lib/ecs", version = "0.1.0" }
lgn-input = { path = "../input", version = "0.1.0" }
lgn-math = { path = "../../lib/math", version = "0.1.0" }
lgn-window = { path = "../window", version = "0.1.0" }
lgn-utils = { path = "../../lib/utils", version = "0.1.0" }
lgn-window = { path = "../window", version = "0.1.0" }

# other
approx = { version = "0.5.0", default-features = false }
log = "0.4"
raw-window-handle = "0.4.2"
winit = { version = "0.26.0", default-features = false }
approx = { version = "0.5.0", default-features = false }

[target.'cfg(target_arch = "wasm32")'.dependencies]
winit = { version = "0.26.0", default-features = false }
Expand Down
Loading

0 comments on commit e51dd20

Please sign in to comment.