game: create sync window system, handle more window events in the winit plugin
This commit is contained in:
parent
393b4206d3
commit
33ddf689be
|
@ -42,7 +42,7 @@ pub fn delta_time_system(world: &mut World) -> anyhow::Result<()> {
|
||||||
pub struct DeltaTimePlugin;
|
pub struct DeltaTimePlugin;
|
||||||
|
|
||||||
impl Plugin for DeltaTimePlugin {
|
impl Plugin for DeltaTimePlugin {
|
||||||
fn setup(&self, app: &mut crate::game::App) {
|
fn setup(&mut self, app: &mut crate::game::App) {
|
||||||
app.world.add_resource(DeltaTime(0.0, None));
|
app.world.add_resource(DeltaTime(0.0, None));
|
||||||
app.add_system_to_stage(GameStages::First, "delta_time", delta_time_system, &[]);
|
app.add_system_to_stage(GameStages::First, "delta_time", delta_time_system, &[]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -196,7 +196,7 @@ impl<E: Event> Iterator for EventReader<E> {
|
||||||
pub struct EventsPlugin;
|
pub struct EventsPlugin;
|
||||||
|
|
||||||
impl Plugin for EventsPlugin {
|
impl Plugin for EventsPlugin {
|
||||||
fn setup(&self, app: &mut crate::game::App) {
|
fn setup(&mut self, app: &mut crate::game::App) {
|
||||||
app.world.add_resource(EventQueue::new());
|
app.world.add_resource(EventQueue::new());
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -182,12 +182,12 @@ impl App {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a plugin to the game. These are executed as they are added.
|
/// Add a plugin to the game. These are executed as they are added.
|
||||||
pub fn with_plugin<P>(&mut self, plugin: P) -> &mut Self
|
pub fn with_plugin<P>(&mut self, mut plugin: P) -> &mut Self
|
||||||
where
|
where
|
||||||
P: Plugin + 'static
|
P: Plugin + 'static
|
||||||
{
|
{
|
||||||
|
plugin.setup(self);
|
||||||
let plugin = Box::new(plugin);
|
let plugin = Box::new(plugin);
|
||||||
plugin.as_ref().setup(self);
|
|
||||||
self.plugins.push_back(plugin);
|
self.plugins.push_back(plugin);
|
||||||
|
|
||||||
self
|
self
|
||||||
|
|
|
@ -597,7 +597,7 @@ fn actions_system(world: &mut World) -> anyhow::Result<()> {
|
||||||
pub struct InputActionPlugin;
|
pub struct InputActionPlugin;
|
||||||
|
|
||||||
impl Plugin for InputActionPlugin {
|
impl Plugin for InputActionPlugin {
|
||||||
fn setup(&self, app: &mut crate::game::App) {
|
fn setup(&mut self, app: &mut crate::game::App) {
|
||||||
app.add_system_to_stage(GameStages::PreUpdate, "input_actions", actions_system, &[]);
|
app.add_system_to_stage(GameStages::PreUpdate, "input_actions", actions_system, &[]);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -135,7 +135,7 @@ impl IntoSystem<()> for InputSystem {
|
||||||
pub struct InputPlugin;
|
pub struct InputPlugin;
|
||||||
|
|
||||||
impl Plugin for InputPlugin {
|
impl Plugin for InputPlugin {
|
||||||
fn setup(&self, app: &mut crate::game::App) {
|
fn setup(&mut self, app: &mut crate::game::App) {
|
||||||
app.add_system_to_stage(GameStages::PreUpdate, "input", InputSystem, &[]);
|
app.add_system_to_stage(GameStages::PreUpdate, "input", InputSystem, &[]);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -11,7 +11,7 @@ use crate::render::window::WindowPlugin;
|
||||||
/// A Plugin is something you can add to a `Game` that can be used to define systems, or spawn initial entities.
|
/// A Plugin is something you can add to a `Game` that can be used to define systems, or spawn initial entities.
|
||||||
pub trait Plugin {
|
pub trait Plugin {
|
||||||
/// Setup this plugin. This runs before the app has started
|
/// Setup this plugin. This runs before the app has started
|
||||||
fn setup(&self, app: &mut App);
|
fn setup(&mut self, app: &mut App);
|
||||||
|
|
||||||
fn is_ready(&self, app: &mut App) -> bool {
|
fn is_ready(&self, app: &mut App) -> bool {
|
||||||
let _ = app;
|
let _ = app;
|
||||||
|
@ -30,7 +30,7 @@ pub trait Plugin {
|
||||||
impl<P> Plugin for P
|
impl<P> Plugin for P
|
||||||
where P: Fn(&mut App)
|
where P: Fn(&mut App)
|
||||||
{
|
{
|
||||||
fn setup(&self, app: &mut App) {
|
fn setup(&mut self, app: &mut App) {
|
||||||
self(app);
|
self(app);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -58,8 +58,8 @@ impl PluginSet {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Plugin for PluginSet {
|
impl Plugin for PluginSet {
|
||||||
fn setup(&self, app: &mut App) {
|
fn setup(&mut self, app: &mut App) {
|
||||||
for plugin in self.plugins.iter() {
|
for plugin in self.plugins.iter_mut() {
|
||||||
plugin.setup(app);
|
plugin.setup(app);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -100,7 +100,7 @@ impl_tuple_plugin_set! { (C0, 0) (C1, 1) (C2, 2) (C3, 3) (C4, 4) (C5, 5) (C6, 6)
|
||||||
pub struct ResourceManagerPlugin;
|
pub struct ResourceManagerPlugin;
|
||||||
|
|
||||||
impl Plugin for ResourceManagerPlugin {
|
impl Plugin for ResourceManagerPlugin {
|
||||||
fn setup(&self, app: &mut App) {
|
fn setup(&mut self, app: &mut App) {
|
||||||
app.world.add_resource(ResourceManager::new());
|
app.world.add_resource(ResourceManager::new());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -110,8 +110,8 @@ impl Plugin for ResourceManagerPlugin {
|
||||||
pub struct DefaultPlugins;
|
pub struct DefaultPlugins;
|
||||||
|
|
||||||
impl Plugin for DefaultPlugins {
|
impl Plugin for DefaultPlugins {
|
||||||
fn setup(&self, app: &mut App) {
|
fn setup(&mut self, app: &mut App) {
|
||||||
WinitPlugin.setup(app);
|
WinitPlugin::default().setup(app);
|
||||||
CommandQueuePlugin.setup(app);
|
CommandQueuePlugin.setup(app);
|
||||||
EventsPlugin.setup(app);
|
EventsPlugin.setup(app);
|
||||||
InputPlugin.setup(app);
|
InputPlugin.setup(app);
|
||||||
|
@ -127,7 +127,7 @@ impl Plugin for DefaultPlugins {
|
||||||
pub struct CommandQueuePlugin;
|
pub struct CommandQueuePlugin;
|
||||||
|
|
||||||
impl Plugin for CommandQueuePlugin {
|
impl Plugin for CommandQueuePlugin {
|
||||||
fn setup(&self, app: &mut App) {
|
fn setup(&mut self, app: &mut App) {
|
||||||
app.world.add_resource(CommandQueue::default());
|
app.world.add_resource(CommandQueue::default());
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,23 +1,21 @@
|
||||||
use std::sync::Arc;
|
use std::ops::{Deref, DerefMut};
|
||||||
|
|
||||||
use glam::{IVec2, Vec2};
|
use lyra_ecs::{query::{filter::Changed, Entities, ResMut}, Component, World};
|
||||||
use lyra_ecs::{query::{filter::Changed, Entities, ResMut, TickOf}, Component, World};
|
use lyra_resource::Image;
|
||||||
use tracing::{error, warn};
|
use tracing::error;
|
||||||
use winit::{
|
use winit::window::{CustomCursor, Fullscreen, Window};
|
||||||
dpi::{LogicalPosition, LogicalSize, PhysicalPosition}, error::ExternalError, monitor::VideoModeHandle, window::{CustomCursor, Fullscreen, Window, WindowAttributes}
|
|
||||||
};
|
|
||||||
|
|
||||||
pub use winit::window::{CursorGrabMode, CursorIcon, Icon, Theme, WindowButtons, WindowLevel};
|
pub use winit::window::{CursorGrabMode, CursorIcon, Icon, Theme, WindowButtons, WindowLevel};
|
||||||
|
|
||||||
use crate::{change_tracker::Ct, input::InputEvent, plugin::Plugin, winit::WinitWindows, EventQueue};
|
use crate::{change_tracker::Ct, plugin::Plugin, winit::WinitWindows};
|
||||||
|
|
||||||
#[derive(Default, Clone, Copy)]
|
#[derive(Default, Clone, Copy, PartialEq)]
|
||||||
pub struct Area {
|
pub struct Area {
|
||||||
position: Position,
|
position: Position,
|
||||||
size: Size,
|
size: Size,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy, PartialEq)]
|
||||||
pub enum Size {
|
pub enum Size {
|
||||||
Physical { x: u32, y: u32 },
|
Physical { x: u32, y: u32 },
|
||||||
Logical { x: f64, y: f64 },
|
Logical { x: f64, y: f64 },
|
||||||
|
@ -58,7 +56,7 @@ impl Size {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy, PartialEq)]
|
||||||
pub enum Position {
|
pub enum Position {
|
||||||
Physical { x: i32, y: i32 },
|
Physical { x: i32, y: i32 },
|
||||||
Logical { x: f64, y: f64 },
|
Logical { x: f64, y: f64 },
|
||||||
|
@ -102,7 +100,7 @@ impl Position {
|
||||||
#[derive(Clone, Component)]
|
#[derive(Clone, Component)]
|
||||||
pub struct PrimaryWindow;
|
pub struct PrimaryWindow;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone, PartialEq, Eq)]
|
||||||
pub enum CursorAppearance {
|
pub enum CursorAppearance {
|
||||||
Icon(CursorIcon),
|
Icon(CursorIcon),
|
||||||
Custom(CustomCursor)
|
Custom(CustomCursor)
|
||||||
|
@ -151,13 +149,13 @@ pub struct WindowOptions {
|
||||||
/// Platform-specific
|
/// Platform-specific
|
||||||
/// * **Wayland / X11 / Orbital:** Not implemented. Always set to [`WindowButtons::all`].
|
/// * **Wayland / X11 / Orbital:** Not implemented. Always set to [`WindowButtons::all`].
|
||||||
/// * **Web / iOS / Android:** Unsupported. Always set to [`WindowButtons::all`].
|
/// * **Web / iOS / Android:** Unsupported. Always set to [`WindowButtons::all`].
|
||||||
enabled_buttons: WindowButtons,
|
pub enabled_buttons: WindowButtons,
|
||||||
|
|
||||||
/// Gets or sets if the window is in focus.
|
/// Gets or sets if the window is in focus.
|
||||||
///
|
///
|
||||||
/// Platform-specific
|
/// Platform-specific
|
||||||
/// * **iOS / Android / Wayland / Orbital:** Unsupported.
|
/// * **iOS / Android / Wayland / Orbital:** Unsupported.
|
||||||
focused: bool,
|
pub focused: bool,
|
||||||
|
|
||||||
/// Gets or sets the fullscreen setting.
|
/// Gets or sets the fullscreen setting.
|
||||||
///
|
///
|
||||||
|
@ -168,9 +166,9 @@ pub struct WindowOptions {
|
||||||
/// * **Android / Orbital:** Will always return None.
|
/// * **Android / Orbital:** Will always return None.
|
||||||
/// * **Wayland:** Can return Borderless(None) when there are no monitors.
|
/// * **Wayland:** Can return Borderless(None) when there are no monitors.
|
||||||
/// * **Web:** Can only return None or Borderless(None).
|
/// * **Web:** Can only return None or Borderless(None).
|
||||||
fullscreen: Option<Fullscreen>,
|
pub fullscreen: Option<Fullscreen>,
|
||||||
|
|
||||||
/// Gets/sets the position of the top-left hand corner of the window’s client area relative to
|
/// Gets the position of the top-left hand corner of the window’s client area relative to
|
||||||
/// the top-left hand corner of the desktop.
|
/// the top-left hand corner of the desktop.
|
||||||
///
|
///
|
||||||
/// Note that the top-left hand corner of the desktop is not necessarily the same
|
/// Note that the top-left hand corner of the desktop is not necessarily the same
|
||||||
|
@ -187,7 +185,7 @@ pub struct WindowOptions {
|
||||||
/// * **Web:** Value is the top-left coordinates relative to the viewport. Note: this will be
|
/// * **Web:** Value is the top-left coordinates relative to the viewport. Note: this will be
|
||||||
/// the same value as [`WindowOptions::outer_position`].
|
/// the same value as [`WindowOptions::outer_position`].
|
||||||
/// * **Android / Wayland:** Unsupported.
|
/// * **Android / Wayland:** Unsupported.
|
||||||
inner_position: Option<Position>,
|
pub inner_position: Option<Position>,
|
||||||
|
|
||||||
/// Gets/sets the size of the view in the window.
|
/// Gets/sets the size of the view in the window.
|
||||||
///
|
///
|
||||||
|
@ -195,19 +193,19 @@ pub struct WindowOptions {
|
||||||
///
|
///
|
||||||
/// Platform-specific
|
/// Platform-specific
|
||||||
/// * **Web:** The size of the canvas element. Doesn’t account for CSS `transform`.
|
/// * **Web:** The size of the canvas element. Doesn’t account for CSS `transform`.
|
||||||
size: Option<Size>,
|
pub size: Size,
|
||||||
|
|
||||||
/// Gets/sets if the window has decorations.
|
/// Gets/sets if the window has decorations.
|
||||||
///
|
///
|
||||||
/// Platform-specific
|
/// Platform-specific
|
||||||
/// * **iOS / Android / Web:** Always set to `true`.
|
/// * **iOS / Android / Web:** Always set to `true`.
|
||||||
decorated: bool,
|
pub decorated: bool,
|
||||||
|
|
||||||
/// Gets/sets the window's current maximized state
|
/// Gets/sets the window's current maximized state
|
||||||
///
|
///
|
||||||
/// Platform-specific
|
/// Platform-specific
|
||||||
/// * **iOS / Android / Web:** Unsupported.
|
/// * **iOS / Android / Web:** Unsupported.
|
||||||
maximized: bool,
|
pub maximized: bool,
|
||||||
|
|
||||||
/// Gets/sets the window's current minimized state.
|
/// Gets/sets the window's current minimized state.
|
||||||
///
|
///
|
||||||
|
@ -216,7 +214,7 @@ pub struct WindowOptions {
|
||||||
/// Platform-specific
|
/// Platform-specific
|
||||||
/// * **Wayland:** always `None`, un-minimize is unsupported.
|
/// * **Wayland:** always `None`, un-minimize is unsupported.
|
||||||
/// * **iOS / Android / Web / Orbital:** Unsupported.
|
/// * **iOS / Android / Web / Orbital:** Unsupported.
|
||||||
minimized: Option<bool>,
|
pub minimized: Option<bool>,
|
||||||
|
|
||||||
/// Gets/sets the window's current resizable state
|
/// Gets/sets the window's current resizable state
|
||||||
///
|
///
|
||||||
|
@ -227,7 +225,7 @@ pub struct WindowOptions {
|
||||||
///
|
///
|
||||||
/// * **X11:** Due to a bug in XFCE, setting this has no effect..
|
/// * **X11:** Due to a bug in XFCE, setting this has no effect..
|
||||||
/// * **iOS / Android / Web:** Unsupported.
|
/// * **iOS / Android / Web:** Unsupported.
|
||||||
resizable: bool,
|
pub resizable: bool,
|
||||||
|
|
||||||
/// Gets/sets the window's current visibility state.
|
/// Gets/sets the window's current visibility state.
|
||||||
///
|
///
|
||||||
|
@ -237,7 +235,7 @@ pub struct WindowOptions {
|
||||||
/// * **X11:** Not implemented.
|
/// * **X11:** Not implemented.
|
||||||
/// * **Wayland / Android / Web:** Unsupported.
|
/// * **Wayland / Android / Web:** Unsupported.
|
||||||
/// * **iOS:** Setting is not implemented, getting is unsupported.
|
/// * **iOS:** Setting is not implemented, getting is unsupported.
|
||||||
visible: Option<bool>,
|
pub visible: Option<bool>,
|
||||||
|
|
||||||
/// Gets/sets the position of the top-left hand corner of the window relative to
|
/// Gets/sets the position of the top-left hand corner of the window relative to
|
||||||
/// the top-left hand corner of the desktop.
|
/// the top-left hand corner of the desktop.
|
||||||
|
@ -255,7 +253,7 @@ pub struct WindowOptions {
|
||||||
/// space coordinate system.
|
/// space coordinate system.
|
||||||
/// * **Web:** Value is the top-left coordinates relative to the viewport.
|
/// * **Web:** Value is the top-left coordinates relative to the viewport.
|
||||||
/// * **Android / Wayland:** Unsupported.
|
/// * **Android / Wayland:** Unsupported.
|
||||||
outer_position: Option<Position>,
|
pub outer_position: Option<Position>,
|
||||||
|
|
||||||
/// Gets/sets the window resize increments.
|
/// Gets/sets the window resize increments.
|
||||||
///
|
///
|
||||||
|
@ -266,21 +264,21 @@ pub struct WindowOptions {
|
||||||
/// * **macOS:** Increments are converted to logical size and then macOS rounds them to whole numbers.
|
/// * **macOS:** Increments are converted to logical size and then macOS rounds them to whole numbers.
|
||||||
/// * **Wayland:** Not implemented, always `None`.
|
/// * **Wayland:** Not implemented, always `None`.
|
||||||
/// * **iOS / Android / Web / Orbital:** Unsupported.
|
/// * **iOS / Android / Web / Orbital:** Unsupported.
|
||||||
resize_increments: Option<Size>,
|
pub resize_increments: Option<Size>,
|
||||||
|
|
||||||
/// Gets/sets the scale factor.
|
/// Gets the scale factor.
|
||||||
///
|
///
|
||||||
/// The scale factor is the ratio of physical pixels to logical pixels.
|
/// The scale factor is the ratio of physical pixels to logical pixels.
|
||||||
/// See [winit docs](https://docs.rs/winit/latest/winit/window/struct.Window.html#method.scale_factor)
|
/// See [winit docs](https://docs.rs/winit/latest/winit/window/struct.Window.html#method.scale_factor)
|
||||||
/// for more information.
|
/// for more information.
|
||||||
scale_factor: f64,
|
pub scale_factor: f64,
|
||||||
|
|
||||||
/// Gets/sets the window's blur state.
|
/// Gets/sets the window's blur state.
|
||||||
///
|
///
|
||||||
/// Platform-specific
|
/// Platform-specific
|
||||||
/// * **Android / iOS / X11 / Web / Windows:** Unsupported.
|
/// * **Android / iOS / X11 / Web / Windows:** Unsupported.
|
||||||
/// * **Wayland:** Only works with org_kde_kwin_blur_manager protocol.
|
/// * **Wayland:** Only works with org_kde_kwin_blur_manager protocol.
|
||||||
blur: bool,
|
pub blur: bool,
|
||||||
|
|
||||||
/// Prevents the window contents from being captured by other apps.
|
/// Prevents the window contents from being captured by other apps.
|
||||||
///
|
///
|
||||||
|
@ -289,9 +287,9 @@ pub struct WindowOptions {
|
||||||
/// is used but doesn’t completely prevent all apps from reading the window content,
|
/// is used but doesn’t completely prevent all apps from reading the window content,
|
||||||
/// for instance, QuickTime.
|
/// for instance, QuickTime.
|
||||||
/// * **iOS / Android / x11 / Wayland / Web / Orbital:** Unsupported.
|
/// * **iOS / Android / x11 / Wayland / Web / Orbital:** Unsupported.
|
||||||
content_protected: bool,
|
pub content_protected: bool,
|
||||||
|
|
||||||
cursor: Cursor,
|
pub cursor: Cursor,
|
||||||
|
|
||||||
/// Sets whether the window should get IME events
|
/// Sets whether the window should get IME events
|
||||||
///
|
///
|
||||||
|
@ -308,26 +306,26 @@ pub struct WindowOptions {
|
||||||
/// * **macOS:** IME must be enabled to receive text-input where dead-key sequences are combined.
|
/// * **macOS:** IME must be enabled to receive text-input where dead-key sequences are combined.
|
||||||
/// * **iOS / Android / Web / Orbital:** Unsupported.
|
/// * **iOS / Android / Web / Orbital:** Unsupported.
|
||||||
/// * **X11:** Enabling IME will disable dead keys reporting during compose.
|
/// * **X11:** Enabling IME will disable dead keys reporting during compose.
|
||||||
ime_allowed: bool,
|
pub ime_allowed: bool,
|
||||||
|
|
||||||
/// Sets area of IME candidate box in window client area coordinates relative to the top left.
|
/// Sets area of IME candidate box in window client area coordinates relative to the top left.
|
||||||
///
|
///
|
||||||
/// Platform-specific
|
/// Platform-specific
|
||||||
/// * **X11:** - area is not supported, only position.
|
/// * **X11:** - area is not supported, only position.
|
||||||
/// * **iOS / Android / Web / Orbital:** Unsupported.
|
/// * **iOS / Android / Web / Orbital:** Unsupported.
|
||||||
ime_cursor_area: Option<Area>,
|
pub ime_cursor_area: Option<Area>,
|
||||||
|
|
||||||
/// Gets/sets the minimum size of the window.
|
/// Gets/sets the minimum size of the window.
|
||||||
///
|
///
|
||||||
/// Platform-specific
|
/// Platform-specific
|
||||||
/// * **iOS / Android / Orbital:** Unsupported.
|
/// * **iOS / Android / Orbital:** Unsupported.
|
||||||
min_size: Option<Size>,
|
pub min_size: Option<Size>,
|
||||||
|
|
||||||
/// Gets/sets the maximum size of the window.
|
/// Gets/sets the maximum size of the window.
|
||||||
///
|
///
|
||||||
/// Platform-specific
|
/// Platform-specific
|
||||||
/// * **iOS / Android / Orbital:** Unsupported.
|
/// * **iOS / Android / Orbital:** Unsupported.
|
||||||
max_size: Option<Size>,
|
pub max_size: Option<Size>,
|
||||||
|
|
||||||
/// Gets/sets the current window theme.
|
/// Gets/sets the current window theme.
|
||||||
///
|
///
|
||||||
|
@ -340,14 +338,14 @@ pub struct WindowOptions {
|
||||||
/// * **X11:** Sets `_GTK_THEME_VARIANT` hint to `dark` or `light` and if `None` is used,
|
/// * **X11:** Sets `_GTK_THEME_VARIANT` hint to `dark` or `light` and if `None` is used,
|
||||||
/// it will default to [`Theme::Dark`](winit::window::Theme::Dark).
|
/// it will default to [`Theme::Dark`](winit::window::Theme::Dark).
|
||||||
/// * **iOS / Android / Web / Orbital:** Unsupported.
|
/// * **iOS / Android / Web / Orbital:** Unsupported.
|
||||||
theme: Option<Theme>,
|
pub theme: Option<Theme>,
|
||||||
|
|
||||||
/// Gets/sets the title of the window.
|
/// Gets/sets the title of the window.
|
||||||
///
|
///
|
||||||
/// Platform-specific
|
/// Platform-specific
|
||||||
/// * **iOS / Android:** Unsupported.
|
/// * **iOS / Android:** Unsupported.
|
||||||
/// * **X11 / Wayland / Web:** Cannot get, will always be an empty string.
|
/// * **X11 / Wayland / Web:** Cannot get, will always be an empty string.
|
||||||
title: String,
|
pub title: String,
|
||||||
|
|
||||||
/// Gets/sets the window's transparency state.
|
/// Gets/sets the window's transparency state.
|
||||||
///
|
///
|
||||||
|
@ -359,7 +357,7 @@ pub struct WindowOptions {
|
||||||
/// * **macOS:** This will reset the window’s background color.
|
/// * **macOS:** This will reset the window’s background color.
|
||||||
/// * **Web / iOS / Android:** Unsupported.
|
/// * **Web / iOS / Android:** Unsupported.
|
||||||
/// * **X11:** Can only be set while building the window.
|
/// * **X11:** Can only be set while building the window.
|
||||||
transparent: bool,
|
pub transparent: bool,
|
||||||
|
|
||||||
/// Sets the window's icon.
|
/// Sets the window's icon.
|
||||||
///
|
///
|
||||||
|
@ -372,14 +370,14 @@ pub struct WindowOptions {
|
||||||
/// recommended to account for screen scaling and pick a multiple of that, i.e. 32x32.
|
/// recommended to account for screen scaling and pick a multiple of that, i.e. 32x32.
|
||||||
/// * **X11:** Has no universal guidelines for icon sizes, so you’re at the whims of
|
/// * **X11:** Has no universal guidelines for icon sizes, so you’re at the whims of
|
||||||
/// the WM. That said, it’s usually in the same ballpark as on Windows.
|
/// the WM. That said, it’s usually in the same ballpark as on Windows.
|
||||||
window_icon: Option<Icon>,
|
pub window_icon: Option<lyra_resource::ResHandle<Image>>,
|
||||||
|
|
||||||
/// Change the window level.
|
/// Change the window level.
|
||||||
///
|
///
|
||||||
/// This is just a hint to the OS, and the system could ignore it.
|
/// This is just a hint to the OS, and the system could ignore it.
|
||||||
///
|
///
|
||||||
/// See [`WindowLevel`] for details.
|
/// See [`WindowLevel`] for details.
|
||||||
window_level: WindowLevel,
|
pub window_level: WindowLevel,
|
||||||
|
|
||||||
/// Show [window menu](https://en.wikipedia.org/wiki/Common_menus_in_Microsoft_Windows#System_menu)
|
/// Show [window menu](https://en.wikipedia.org/wiki/Common_menus_in_Microsoft_Windows#System_menu)
|
||||||
/// at a specified position.
|
/// at a specified position.
|
||||||
|
@ -387,7 +385,21 @@ pub struct WindowOptions {
|
||||||
/// This is the context menu that is normally shown when interacting with the title bar. This is useful when implementing custom decorations.
|
/// This is the context menu that is normally shown when interacting with the title bar. This is useful when implementing custom decorations.
|
||||||
/// Platform-specific
|
/// Platform-specific
|
||||||
/// * **Android / iOS / macOS / Orbital / Wayland / Web / X11:** Unsupported.
|
/// * **Android / iOS / macOS / Orbital / Wayland / Web / X11:** Unsupported.
|
||||||
show_window_menu: Option<Position>,
|
pub show_window_menu: Option<Position>,
|
||||||
|
|
||||||
|
/// Gets the window's occluded state (completely hidden from view).
|
||||||
|
///
|
||||||
|
/// This is different to window visibility as it depends on whether the window is
|
||||||
|
/// closed, minimised, set invisible, or fully occluded by another window.
|
||||||
|
///
|
||||||
|
/// Platform-specific
|
||||||
|
/// * **iOS:** this is set to `false` in response to an applicationWillEnterForeground
|
||||||
|
/// callback which means the application should start preparing its data.
|
||||||
|
/// Its `true` in response to an applicationDidEnterBackground callback which means
|
||||||
|
/// the application should free resources (according to the iOS application lifecycle).
|
||||||
|
/// * **Web:** Doesn't take into account CSS border, padding, or transform.
|
||||||
|
/// * **Android / Wayland / Windows / Orbital:** Unsupported.
|
||||||
|
pub occluded: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<winit::window::WindowAttributes> for WindowOptions {
|
impl From<winit::window::WindowAttributes> for WindowOptions {
|
||||||
|
@ -397,7 +409,8 @@ impl From<winit::window::WindowAttributes> for WindowOptions {
|
||||||
focused: false,
|
focused: false,
|
||||||
fullscreen: value.fullscreen,
|
fullscreen: value.fullscreen,
|
||||||
inner_position: None,
|
inner_position: None,
|
||||||
size: value.inner_size.map(|s| s.into()),
|
size: value.inner_size.map(|s| s.into())
|
||||||
|
.unwrap_or(Size::new_physical(1280, 720)),
|
||||||
decorated: value.decorations,
|
decorated: value.decorations,
|
||||||
maximized: value.maximized,
|
maximized: value.maximized,
|
||||||
minimized: None,
|
minimized: None,
|
||||||
|
@ -424,9 +437,10 @@ impl From<winit::window::WindowAttributes> for WindowOptions {
|
||||||
theme: value.preferred_theme,
|
theme: value.preferred_theme,
|
||||||
title: value.title,
|
title: value.title,
|
||||||
transparent: value.transparent,
|
transparent: value.transparent,
|
||||||
window_icon: value.window_icon,
|
window_icon: None,
|
||||||
window_level: value.window_level,
|
window_level: value.window_level,
|
||||||
show_window_menu: None,
|
show_window_menu: None,
|
||||||
|
occluded: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -437,101 +451,199 @@ impl Default for WindowOptions {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl WindowOptions {
|
||||||
|
/// Create winit [`WindowAttributes`] from self.
|
||||||
|
pub(crate) fn as_attributes(&self) -> winit::window::WindowAttributes {
|
||||||
|
let mut att = winit::window::Window::default_attributes();
|
||||||
|
|
||||||
|
att.enabled_buttons = self.enabled_buttons.clone();
|
||||||
|
att.fullscreen = self.fullscreen.clone();
|
||||||
|
att.inner_size = Some(self.size.into());
|
||||||
|
att.decorations = self.decorated;
|
||||||
|
att.maximized = self.maximized;
|
||||||
|
att.resizable = self.resizable;
|
||||||
|
att.visible = self.visible.unwrap_or(true);
|
||||||
|
att.position = self.outer_position.map(|p| p.into());
|
||||||
|
att.resize_increments = self.resize_increments.map(|i| i.into());
|
||||||
|
att.blur = self.blur;
|
||||||
|
att.content_protected = self.content_protected;
|
||||||
|
att.cursor = match self.cursor.appearance.clone() {
|
||||||
|
CursorAppearance::Icon(icon) => winit::window::Cursor::Icon(icon),
|
||||||
|
CursorAppearance::Custom(custom) => winit::window::Cursor::Custom(custom),
|
||||||
|
};
|
||||||
|
att.min_inner_size = self.min_size.map(|s| s.into());
|
||||||
|
att.max_inner_size = self.max_size.map(|s| s.into());
|
||||||
|
att.preferred_theme = self.theme;
|
||||||
|
att.title = self.title.clone();
|
||||||
|
att.transparent = self.transparent;
|
||||||
|
if self.window_icon.is_some() {
|
||||||
|
todo!("cannot set window attribute icon yet");
|
||||||
|
}
|
||||||
|
att.window_level = self.window_level;
|
||||||
|
|
||||||
|
att
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Component)]
|
#[derive(Clone, Component)]
|
||||||
struct LastWindow {
|
struct LastWindow {
|
||||||
last: WindowOptions,
|
last: WindowOptions,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Deref for LastWindow {
|
||||||
|
type Target = WindowOptions;
|
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target {
|
||||||
|
&self.last
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DerefMut for LastWindow {
|
||||||
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||||
|
&mut self.last
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct WindowPlugin {
|
pub struct WindowPlugin {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
create_options: WindowOptions,
|
create_options: WindowOptions,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert an Vec2 to a LogicalPosition<f32>
|
|
||||||
fn vec2_to_logical_pos(pos: Vec2) -> LogicalPosition<f32> {
|
|
||||||
LogicalPosition { x: pos.x, y: pos.y }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Convert an IVec2 to a LogicalSize<i32>
|
|
||||||
fn ivec2_to_logical_size(size: IVec2) -> LogicalSize<i32> {
|
|
||||||
LogicalSize {
|
|
||||||
width: size.x,
|
|
||||||
height: size.y,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Convert an Option<IVec2> to an Option<LogicalSize<i32>>
|
|
||||||
fn ivec2_to_logical_size_op(size: Option<IVec2>) -> Option<LogicalSize<i32>> {
|
|
||||||
size.map(ivec2_to_logical_size)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Convert an Option<Vec2> to an Option<LogicalSize<f32>>
|
|
||||||
fn vec2_to_logical_size_op(size: Option<Vec2>) -> Option<LogicalSize<f32>> {
|
|
||||||
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(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// if the window is set to confine the cursor, the cursor is invisible,
|
|
||||||
/// and the window is focused, set the cursor position to the center of the screen.
|
|
||||||
fn center_mouse(window: &Window, options: &WindowOptions) {
|
|
||||||
if options.cursor_grab == CursorGrabMode::Confined && !options.cursor_visible && options.focused
|
|
||||||
{
|
|
||||||
let size = window.inner_size();
|
|
||||||
let middle = PhysicalPosition {
|
|
||||||
x: size.width / 2,
|
|
||||||
y: size.height / 2,
|
|
||||||
};
|
|
||||||
window.set_cursor_position(middle).unwrap();
|
|
||||||
}
|
|
||||||
} */
|
|
||||||
|
|
||||||
/// A system that syncs Winit Windows with [`WindowOptions`] components.
|
/// A system that syncs Winit Windows with [`WindowOptions`] components.
|
||||||
pub fn window_sync_system(world: &mut World) -> anyhow::Result<()> {
|
pub fn window_sync_system(world: &mut World) -> anyhow::Result<()> {
|
||||||
for (entity, mut opts, mut last_window, windows) in world.filtered_view_iter::<(Entities, &mut WindowOptions, &mut LastWindow, ResMut<WinitWindows>), Changed<WindowOptions>>() {
|
for (entity, opts, mut last, windows) in world.filtered_view_iter::<(Entities, &WindowOptions, &mut LastWindow, ResMut<WinitWindows>), Changed<WindowOptions>>() {
|
||||||
let window = windows.get_entity_window(entity)
|
let window = windows.get_entity_window(entity)
|
||||||
.expect("entity's window is missing");
|
.expect("entity's window is missing");
|
||||||
|
|
||||||
|
if opts.enabled_buttons != last.enabled_buttons {
|
||||||
|
window.set_enabled_buttons(opts.enabled_buttons);
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts.focused != last.focused && opts.focused {
|
||||||
|
window.focus_window();
|
||||||
|
}
|
||||||
|
|
||||||
todo!()
|
if opts.fullscreen != last.fullscreen {
|
||||||
|
window.set_fullscreen(opts.fullscreen.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts.size != last.size {
|
||||||
|
if window.request_inner_size(opts.size).is_some() {
|
||||||
|
error!("request to increase window size failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts.decorated != last.decorated {
|
||||||
|
window.set_decorations(opts.decorated);
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts.maximized != last.maximized {
|
||||||
|
window.set_maximized(opts.maximized);
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts.minimized != last.minimized && opts.minimized.is_some() {
|
||||||
|
window.set_minimized(opts.minimized.unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts.visible != last.visible && opts.visible.is_some() {
|
||||||
|
window.set_visible(opts.visible.unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts.outer_position != last.outer_position && opts.outer_position.is_some() {
|
||||||
|
window.set_outer_position(opts.outer_position.unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts.resize_increments != last.resize_increments {
|
||||||
|
window.set_resize_increments(opts.resize_increments);
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts.blur != last.blur {
|
||||||
|
window.set_blur(opts.blur)
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts.content_protected != last.content_protected {
|
||||||
|
window.set_content_protected(opts.content_protected);
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts.cursor.appearance != last.cursor.appearance {
|
||||||
|
match opts.cursor.appearance.clone() {
|
||||||
|
CursorAppearance::Icon(icon) => window.set_cursor(winit::window::Cursor::Icon(icon)),
|
||||||
|
CursorAppearance::Custom(custom) => window.set_cursor(winit::window::Cursor::Custom(custom)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts.cursor.grab != last.cursor.grab {
|
||||||
|
if let Err(e) = window.set_cursor_grab(opts.cursor.grab) {
|
||||||
|
error!("could not set cursor grab mode: {}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts.cursor.hittest != last.cursor.hittest {
|
||||||
|
if let Err(e) = window.set_cursor_hittest(opts.cursor.hittest) {
|
||||||
|
error!("could not set cursor hittest: {}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts.cursor.visible != last.cursor.visible {
|
||||||
|
window.set_cursor_visible(opts.cursor.visible);
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts.ime_allowed != last.ime_allowed {
|
||||||
|
window.set_ime_allowed(opts.ime_allowed);
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts.ime_cursor_area != last.ime_cursor_area && opts.ime_cursor_area.is_some() {
|
||||||
|
let area = opts.ime_cursor_area.as_ref().unwrap();
|
||||||
|
window.set_ime_cursor_area(area.position, area.size);
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts.min_size != last.min_size {
|
||||||
|
window.set_min_inner_size(opts.min_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts.max_size != last.max_size {
|
||||||
|
window.set_max_inner_size(opts.max_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts.theme != last.theme {
|
||||||
|
window.set_theme(opts.theme);
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts.title != last.title {
|
||||||
|
window.set_title(&opts.title);
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts.transparent != last.transparent {
|
||||||
|
window.set_transparent(opts.transparent);
|
||||||
|
}
|
||||||
|
|
||||||
|
// compare the resource version and uuid. These will get changed
|
||||||
|
// when the image is reloaded
|
||||||
|
let opts_icon = opts.window_icon.as_ref()
|
||||||
|
.map(|i| (i.version(), i.uuid()));
|
||||||
|
let last_icon = last.window_icon.as_ref()
|
||||||
|
.map(|i| (i.version(), i.uuid()));
|
||||||
|
if opts_icon != last_icon {
|
||||||
|
todo!("cannot set window icon yet");
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts.window_level != last.window_level {
|
||||||
|
window.set_window_level(opts.window_level);
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts.show_window_menu != last.show_window_menu && opts.show_window_menu.is_some() {
|
||||||
|
window.show_window_menu(opts.show_window_menu.unwrap());
|
||||||
|
}
|
||||||
|
|
||||||
|
last.last = opts.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Plugin for WindowPlugin {
|
impl Plugin for WindowPlugin {
|
||||||
fn setup(&self, app: &mut crate::game::App) {
|
fn setup(&mut self, app: &mut crate::game::App) {
|
||||||
let window_options = WindowOptions::default();
|
let window_options = WindowOptions::default();
|
||||||
|
|
||||||
app.world.add_resource(Ct::new(window_options));
|
app.world.add_resource(Ct::new(window_options));
|
||||||
|
|
|
@ -97,7 +97,7 @@ pub fn free_fly_camera_controller(delta_time: Res<DeltaTime>, handler: Res<Actio
|
||||||
pub struct FreeFlyCameraPlugin;
|
pub struct FreeFlyCameraPlugin;
|
||||||
|
|
||||||
impl Plugin for FreeFlyCameraPlugin {
|
impl Plugin for FreeFlyCameraPlugin {
|
||||||
fn setup(&self, app: &mut App) {
|
fn setup(&mut self, app: &mut App) {
|
||||||
app.with_system("free_fly_camera_system", free_fly_camera_controller, &[]);
|
app.with_system("free_fly_camera_system", free_fly_camera_controller, &[]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use std::sync::Arc;
|
use std::{collections::VecDeque, sync::Arc};
|
||||||
|
|
||||||
use async_std::task::block_on;
|
use async_std::task::block_on;
|
||||||
use glam::IVec2;
|
use glam::IVec2;
|
||||||
|
@ -7,15 +7,32 @@ use rustc_hash::FxHashMap;
|
||||||
use tracing::{debug, error, info, warn};
|
use tracing::{debug, error, info, warn};
|
||||||
use winit::{application::ApplicationHandler, event::WindowEvent, event_loop::{ActiveEventLoop, EventLoop}, window::{Window, WindowAttributes, WindowId}};
|
use winit::{application::ApplicationHandler, event::WindowEvent, event_loop::{ActiveEventLoop, EventLoop}, window::{Window, WindowAttributes, WindowId}};
|
||||||
|
|
||||||
use crate::{game::{App, WindowState}, input::InputEvent, plugin::Plugin, render::{renderer::BasicRenderer, window::{PrimaryWindow, WindowOptions}}, EventQueue};
|
use crate::{game::{App, WindowState}, input::InputEvent, plugin::Plugin, render::{renderer::BasicRenderer, window::{PrimaryWindow, Size, WindowOptions}}, EventQueue};
|
||||||
|
|
||||||
#[derive(Default)]
|
pub struct WinitPlugin {
|
||||||
pub struct WinitPlugin;
|
/// The primary window that will be created.
|
||||||
|
///
|
||||||
|
/// This will become `None` after the window is created. If you want to get the
|
||||||
|
/// primary world later, query for an entity with the [`PrimaryWindow`] and
|
||||||
|
/// [`WindowOptions`] components.
|
||||||
|
pub primary_window: Option<WindowOptions>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for WinitPlugin {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self { primary_window: Some(WindowOptions::default()) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Plugin for WinitPlugin {
|
impl Plugin for WinitPlugin {
|
||||||
fn setup(&self, app: &mut crate::game::App) {
|
fn setup(&mut self, app: &mut crate::game::App) {
|
||||||
app.set_run_fn(winit_app_runner);
|
app.set_run_fn(winit_app_runner);
|
||||||
app.add_resource(WinitWindows::default());
|
|
||||||
|
if let Some(prim) = self.primary_window.take() {
|
||||||
|
app.add_resource(WinitWindows::with_window(prim));
|
||||||
|
} else {
|
||||||
|
app.add_resource(WinitWindows::default());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_ready(&self, _app: &mut crate::game::App) -> bool {
|
fn is_ready(&self, _app: &mut crate::game::App) -> bool {
|
||||||
|
@ -35,15 +52,26 @@ impl Plugin for WinitPlugin {
|
||||||
pub struct WinitWindows {
|
pub struct WinitWindows {
|
||||||
pub windows: FxHashMap<WindowId, Arc<Window>>,
|
pub windows: FxHashMap<WindowId, Arc<Window>>,
|
||||||
pub entity_to_window: FxHashMap<Entity, WindowId>,
|
pub entity_to_window: FxHashMap<Entity, WindowId>,
|
||||||
|
pub window_to_entity: FxHashMap<WindowId, Entity>,
|
||||||
|
/// windows that will be created when the Winit runner first starts.
|
||||||
|
window_queue: VecDeque<WindowOptions>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WinitWindows {
|
impl WinitWindows {
|
||||||
|
pub fn with_window(window: WindowOptions) -> Self {
|
||||||
|
Self {
|
||||||
|
window_queue: vec![window].into(),
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn create_window(&mut self, event_loop: &ActiveEventLoop, entity: Entity, attr: WindowAttributes) -> Result<WindowId, winit::error::OsError> {
|
pub fn create_window(&mut self, event_loop: &ActiveEventLoop, entity: Entity, attr: WindowAttributes) -> Result<WindowId, winit::error::OsError> {
|
||||||
let win = event_loop.create_window(attr)?;
|
let win = event_loop.create_window(attr)?;
|
||||||
let id = win.id();
|
let id = win.id();
|
||||||
|
|
||||||
self.windows.insert(id, Arc::new(win));
|
self.windows.insert(id, Arc::new(win));
|
||||||
self.entity_to_window.insert(entity, id);
|
self.entity_to_window.insert(entity, id);
|
||||||
|
self.window_to_entity.insert(id, entity);
|
||||||
|
|
||||||
Ok(id)
|
Ok(id)
|
||||||
}
|
}
|
||||||
|
@ -71,8 +99,6 @@ struct WinitRunner {
|
||||||
|
|
||||||
impl ApplicationHandler for WinitRunner {
|
impl ApplicationHandler for WinitRunner {
|
||||||
fn about_to_wait(&mut self, event_loop: &winit::event_loop::ActiveEventLoop) {
|
fn about_to_wait(&mut self, event_loop: &winit::event_loop::ActiveEventLoop) {
|
||||||
debug!("update now");
|
|
||||||
|
|
||||||
self.app.update();
|
self.app.update();
|
||||||
|
|
||||||
let renderer = self.app.renderer.get_mut().expect("renderer was not initialized");
|
let renderer = self.app.renderer.get_mut().expect("renderer was not initialized");
|
||||||
|
@ -94,18 +120,29 @@ impl ApplicationHandler for WinitRunner {
|
||||||
// All other errors (Outdated, Timeout) should be resolved by the next frame
|
// All other errors (Outdated, Timeout) should be resolved by the next frame
|
||||||
Err(e) => eprintln!("{:?}", e),
|
Err(e) => eprintln!("{:?}", e),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let windows = self.app.world.get_resource::<WinitWindows>();
|
||||||
|
for window in windows.windows.values() {
|
||||||
|
window.request_redraw();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resumed(&mut self, event_loop: &winit::event_loop::ActiveEventLoop) {
|
fn resumed(&mut self, event_loop: &winit::event_loop::ActiveEventLoop) {
|
||||||
let world = &mut self.app.world;
|
let world = &mut self.app.world;
|
||||||
let en = world.spawn((WindowOptions::default(), PrimaryWindow));
|
|
||||||
|
|
||||||
let attr = Window::default_attributes();
|
|
||||||
let mut windows = world.get_resource_mut::<WinitWindows>();
|
let mut windows = world.get_resource_mut::<WinitWindows>();
|
||||||
let wid = windows.create_window(event_loop, en, attr).unwrap();
|
let to_create_window = windows.window_queue.pop_front().unwrap_or_default();
|
||||||
|
let window_attr = to_create_window.as_attributes();
|
||||||
|
drop(windows);
|
||||||
|
let en = world.spawn((to_create_window, PrimaryWindow));
|
||||||
|
|
||||||
|
let mut windows = world.get_resource_mut::<WinitWindows>();
|
||||||
|
let wid = windows.create_window(event_loop, en, window_attr).unwrap();
|
||||||
let window = windows.windows.get(&wid).unwrap().clone();
|
let window = windows.windows.get(&wid).unwrap().clone();
|
||||||
drop(windows);
|
drop(windows);
|
||||||
|
|
||||||
|
debug!("Created window after resume");
|
||||||
|
|
||||||
let renderer = block_on(BasicRenderer::create_with_window(world, window));
|
let renderer = block_on(BasicRenderer::create_with_window(world, window));
|
||||||
if self.app.renderer.set(Box::new(renderer)).is_err() {
|
if self.app.renderer.set(Box::new(renderer)).is_err() {
|
||||||
warn!("renderer was re-initialized");
|
warn!("renderer was re-initialized");
|
||||||
|
@ -139,6 +176,12 @@ impl ApplicationHandler for WinitRunner {
|
||||||
WindowEvent::ActivationTokenDone { serial, token } => todo!(),
|
WindowEvent::ActivationTokenDone { serial, token } => todo!(),
|
||||||
WindowEvent::Resized(physical_size) => {
|
WindowEvent::Resized(physical_size) => {
|
||||||
self.app.on_resize(physical_size);
|
self.app.on_resize(physical_size);
|
||||||
|
|
||||||
|
let mut window_opts = self.app.world.get_resource::<WinitWindows>()
|
||||||
|
.window_to_entity.get(&window_id)
|
||||||
|
.and_then(|e| self.app.world.view_one::<&mut WindowOptions>(*e).get())
|
||||||
|
.unwrap();
|
||||||
|
window_opts.size = Size::new_physical(physical_size.width, physical_size.height);
|
||||||
},
|
},
|
||||||
WindowEvent::Moved(physical_position) => {
|
WindowEvent::Moved(physical_position) => {
|
||||||
let mut state = self.app.world.get_resource_or_else(WindowState::new);
|
let mut state = self.app.world.get_resource_or_else(WindowState::new);
|
||||||
|
@ -153,20 +196,36 @@ impl ApplicationHandler for WinitRunner {
|
||||||
WindowEvent::HoveredFile(path_buf) => todo!(),
|
WindowEvent::HoveredFile(path_buf) => todo!(),
|
||||||
WindowEvent::HoveredFileCancelled => todo!(),
|
WindowEvent::HoveredFileCancelled => todo!(),
|
||||||
WindowEvent::Focused(focused) => {
|
WindowEvent::Focused(focused) => {
|
||||||
let mut state = self.app.world.get_resource_or_else(WindowState::new);
|
let mut window_opts = self.app.world.get_resource::<WinitWindows>()
|
||||||
state.focused = focused;
|
.window_to_entity.get(&window_id)
|
||||||
|
.and_then(|e| self.app.world.view_one::<&mut WindowOptions>(*e).get())
|
||||||
|
.unwrap();
|
||||||
|
window_opts.focused = focused;
|
||||||
},
|
},
|
||||||
WindowEvent::ModifiersChanged(modifiers) => debug!("modifiers changed: {:?}", modifiers),
|
WindowEvent::ModifiersChanged(modifiers) => debug!("modifiers changed: {:?}", modifiers),
|
||||||
WindowEvent::ScaleFactorChanged { scale_factor, inner_size_writer } => {
|
WindowEvent::ScaleFactorChanged { scale_factor, .. } => {
|
||||||
info!("changed scale to {scale_factor}");
|
let mut window_opts = self.app.world.get_resource::<WinitWindows>()
|
||||||
|
.window_to_entity.get(&window_id)
|
||||||
|
.and_then(|e| self.app.world.view_one::<&mut WindowOptions>(*e).get())
|
||||||
|
.unwrap();
|
||||||
|
window_opts.scale_factor = scale_factor;
|
||||||
|
},
|
||||||
|
WindowEvent::ThemeChanged(theme) => {
|
||||||
|
let mut window_opts = self.app.world.get_resource::<WinitWindows>()
|
||||||
|
.window_to_entity.get(&window_id)
|
||||||
|
.and_then(|e| self.app.world.view_one::<&mut WindowOptions>(*e).get())
|
||||||
|
.unwrap();
|
||||||
|
window_opts.theme = Some(theme);
|
||||||
},
|
},
|
||||||
WindowEvent::ThemeChanged(theme) => todo!(),
|
|
||||||
WindowEvent::Occluded(occ) => {
|
WindowEvent::Occluded(occ) => {
|
||||||
let mut state = self.app.world.get_resource_or_else(WindowState::new);
|
let mut window_opts = self.app.world.get_resource::<WinitWindows>()
|
||||||
state.occluded = occ;
|
.window_to_entity.get(&window_id)
|
||||||
|
.and_then(|e| self.app.world.view_one::<&mut WindowOptions>(*e).get())
|
||||||
|
.unwrap();
|
||||||
|
window_opts.occluded = occ;
|
||||||
},
|
},
|
||||||
WindowEvent::RedrawRequested => {
|
WindowEvent::RedrawRequested => {
|
||||||
debug!("should redraw");
|
//debug!("should redraw");
|
||||||
},
|
},
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -190,7 +190,7 @@ pub fn lua_script_last_stage_system(world: &mut World) -> anyhow::Result<()> {
|
||||||
pub struct LuaScriptingPlugin;
|
pub struct LuaScriptingPlugin;
|
||||||
|
|
||||||
impl Plugin for LuaScriptingPlugin {
|
impl Plugin for LuaScriptingPlugin {
|
||||||
fn setup(&self, game: &mut lyra_game::game::Game) {
|
fn setup(&mut self, game: &mut lyra_game::game::Game) {
|
||||||
let world = game.world_mut();
|
let world = game.world_mut();
|
||||||
|
|
||||||
world.add_resource_default::<TypeRegistry>();
|
world.add_resource_default::<TypeRegistry>();
|
||||||
|
|
Loading…
Reference in New Issue