Add no_std support to bevy_window (#17031)

# Objective

- Contributes to #15460

## Solution

- Added the following features:
  - `std` (default)
  - `bevy_reflect` (default)
  - `libm`

## Testing

- CI

## Notes

- `bevy_reflect` was previously always enabled, which isn't how most
other crates handle reflection. I've brought this in line with how most
crates gate `bevy_reflect`. This is where the majority of the changes
come from in this PR.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
This commit is contained in:
Zachary Harrold 2025-01-02 10:05:25 +11:00 committed by GitHub
parent 4058bfa47c
commit 10e113d641
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 305 additions and 180 deletions

View File

@ -9,24 +9,69 @@ license = "MIT OR Apache-2.0"
keywords = ["bevy"]
[features]
serialize = ["serde", "smol_str/serde", "bevy_ecs/serialize"]
default = ["std", "bevy_reflect"]
# Functionality
## Adds runtime reflection support using `bevy_reflect`.
bevy_reflect = [
"dep:bevy_reflect",
"bevy_app/bevy_reflect",
"bevy_ecs/bevy_reflect",
"bevy_input/bevy_reflect",
]
## Adds serialization support through `serde`.
serialize = [
"serde",
"smol_str/serde",
"bevy_ecs/serialize",
"bevy_input/serialize",
]
# Platform Compatibility
## Allows access to the `std` crate. Enabling this feature will prevent compilation
## on `no_std` targets, but provides access to certain additional features on
## supported platforms.
std = [
"bevy_app/std",
"bevy_ecs/std",
"bevy_input/std",
"bevy_math/std",
"bevy_reflect?/std",
"serde?/std",
"raw-window-handle/std",
]
## Uses the `libm` maths library instead of the one provided in `std` and `core`.
libm = ["bevy_math/libm"]
[dependencies]
# bevy
bevy_app = { path = "../bevy_app", version = "0.15.0-dev" }
bevy_ecs = { path = "../bevy_ecs", version = "0.15.0-dev" }
bevy_input = { path = "../bevy_input", version = "0.15.0-dev" }
bevy_math = { path = "../bevy_math", version = "0.15.0-dev" }
bevy_reflect = { path = "../bevy_reflect", version = "0.15.0-dev", features = [
bevy_app = { path = "../bevy_app", version = "0.15.0-dev", default-features = false }
bevy_ecs = { path = "../bevy_ecs", version = "0.15.0-dev", default-features = false }
bevy_input = { path = "../bevy_input", version = "0.15.0-dev", default-features = false }
bevy_math = { path = "../bevy_math", version = "0.15.0-dev", default-features = false }
bevy_reflect = { path = "../bevy_reflect", version = "0.15.0-dev", default-features = false, features = [
"glam",
"smol_str",
] }
bevy_utils = { path = "../bevy_utils", version = "0.15.0-dev" }
], optional = true }
bevy_utils = { path = "../bevy_utils", version = "0.15.0-dev", default-features = false }
# other
serde = { version = "1.0", features = ["derive"], optional = true }
raw-window-handle = "0.6"
smol_str = "0.2"
serde = { version = "1.0", features = [
"alloc",
"derive",
], default-features = false, optional = true }
raw-window-handle = { version = "0.6", features = [
"alloc",
], default-features = false }
smol_str = { version = "0.2", default-features = false }
log = { version = "0.4", default-features = false }
spin = { version = "0.9.8", default-features = false, features = [
"spin_mutex",
] }
[target.'cfg(target_os = "android")'.dependencies]
android-activity = "0.6"

View File

@ -1,5 +1,4 @@
use std::path::PathBuf;
use alloc::string::String;
use bevy_ecs::{entity::Entity, event::Event};
use bevy_input::{
gestures::*,
@ -8,6 +7,14 @@ use bevy_input::{
touch::TouchInput,
};
use bevy_math::{IVec2, Vec2};
#[cfg(feature = "std")]
use std::path::PathBuf;
#[cfg(not(feature = "std"))]
use alloc::string::String as PathBuf;
#[cfg(feature = "bevy_reflect")]
use bevy_reflect::Reflect;
#[cfg(feature = "serialize")]
@ -16,11 +23,11 @@ use bevy_reflect::{ReflectDeserialize, ReflectSerialize};
use crate::WindowTheme;
/// A window event that is sent whenever a window's logical size has changed.
#[derive(Event, Debug, Clone, PartialEq, Reflect)]
#[reflect(Debug, PartialEq)]
#[derive(Event, Debug, Clone, PartialEq)]
#[cfg_attr(feature = "bevy_reflect", derive(Reflect), reflect(Debug, PartialEq))]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(
feature = "serialize",
derive(serde::Serialize, serde::Deserialize),
all(feature = "serialize", feature = "bevy_reflect"),
reflect(Serialize, Deserialize)
)]
pub struct WindowResized {
@ -34,11 +41,11 @@ pub struct WindowResized {
/// An event that indicates all of the application's windows should be redrawn,
/// even if their control flow is set to `Wait` and there have been no window events.
#[derive(Event, Debug, Clone, PartialEq, Eq, Reflect)]
#[reflect(Debug, PartialEq)]
#[derive(Event, Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "bevy_reflect", derive(Reflect), reflect(Debug, PartialEq))]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(
feature = "serialize",
derive(serde::Serialize, serde::Deserialize),
all(feature = "serialize", feature = "bevy_reflect"),
reflect(Serialize, Deserialize)
)]
pub struct RequestRedraw;
@ -46,11 +53,11 @@ pub struct RequestRedraw;
/// An event that is sent whenever a new window is created.
///
/// To create a new window, spawn an entity with a [`crate::Window`] on it.
#[derive(Event, Debug, Clone, PartialEq, Eq, Reflect)]
#[reflect(Debug, PartialEq)]
#[derive(Event, Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "bevy_reflect", derive(Reflect), reflect(Debug, PartialEq))]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(
feature = "serialize",
derive(serde::Serialize, serde::Deserialize),
all(feature = "serialize", feature = "bevy_reflect"),
reflect(Serialize, Deserialize)
)]
pub struct WindowCreated {
@ -68,11 +75,11 @@ pub struct WindowCreated {
///
/// [`WindowPlugin`]: crate::WindowPlugin
/// [`Window`]: crate::Window
#[derive(Event, Debug, Clone, PartialEq, Eq, Reflect)]
#[reflect(Debug, PartialEq)]
#[derive(Event, Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "bevy_reflect", derive(Reflect), reflect(Debug, PartialEq))]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(
feature = "serialize",
derive(serde::Serialize, serde::Deserialize),
all(feature = "serialize", feature = "bevy_reflect"),
reflect(Serialize, Deserialize)
)]
pub struct WindowCloseRequested {
@ -82,11 +89,11 @@ pub struct WindowCloseRequested {
/// An event that is sent whenever a window is closed. This will be sent when
/// the window entity loses its [`Window`](crate::window::Window) component or is despawned.
#[derive(Event, Debug, Clone, PartialEq, Eq, Reflect)]
#[reflect(Debug, PartialEq)]
#[derive(Event, Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "bevy_reflect", derive(Reflect), reflect(Debug, PartialEq))]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(
feature = "serialize",
derive(serde::Serialize, serde::Deserialize),
all(feature = "serialize", feature = "bevy_reflect"),
reflect(Serialize, Deserialize)
)]
pub struct WindowClosed {
@ -99,11 +106,11 @@ pub struct WindowClosed {
/// An event that is sent whenever a window is closing. This will be sent when
/// after a [`WindowCloseRequested`] event is received and the window is in the process of closing.
#[derive(Event, Debug, Clone, PartialEq, Eq, Reflect)]
#[reflect(Debug, PartialEq)]
#[derive(Event, Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "bevy_reflect", derive(Reflect), reflect(Debug, PartialEq))]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(
feature = "serialize",
derive(serde::Serialize, serde::Deserialize),
all(feature = "serialize", feature = "bevy_reflect"),
reflect(Serialize, Deserialize)
)]
pub struct WindowClosing {
@ -115,11 +122,11 @@ pub struct WindowClosing {
///
/// Note that if your application only has a single window, this event may be your last chance to
/// persist state before the application terminates.
#[derive(Event, Debug, Clone, PartialEq, Eq, Reflect)]
#[reflect(Debug, PartialEq)]
#[derive(Event, Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "bevy_reflect", derive(Reflect), reflect(Debug, PartialEq))]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(
feature = "serialize",
derive(serde::Serialize, serde::Deserialize),
all(feature = "serialize", feature = "bevy_reflect"),
reflect(Serialize, Deserialize)
)]
pub struct WindowDestroyed {
@ -141,11 +148,11 @@ pub struct WindowDestroyed {
/// you should not use it for non-cursor-like behavior such as 3D camera control. Please see `MouseMotion` instead.
///
/// [`WindowEvent::CursorMoved`]: https://docs.rs/winit/latest/winit/event/enum.WindowEvent.html#variant.CursorMoved
#[derive(Event, Debug, Clone, PartialEq, Reflect)]
#[reflect(Debug, PartialEq)]
#[derive(Event, Debug, Clone, PartialEq)]
#[cfg_attr(feature = "bevy_reflect", derive(Reflect), reflect(Debug, PartialEq))]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(
feature = "serialize",
derive(serde::Serialize, serde::Deserialize),
all(feature = "serialize", feature = "bevy_reflect"),
reflect(Serialize, Deserialize)
)]
pub struct CursorMoved {
@ -162,11 +169,11 @@ pub struct CursorMoved {
}
/// An event that is sent whenever the user's cursor enters a window.
#[derive(Event, Debug, Clone, PartialEq, Eq, Reflect)]
#[reflect(Debug, PartialEq)]
#[derive(Event, Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "bevy_reflect", derive(Reflect), reflect(Debug, PartialEq))]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(
feature = "serialize",
derive(serde::Serialize, serde::Deserialize),
all(feature = "serialize", feature = "bevy_reflect"),
reflect(Serialize, Deserialize)
)]
pub struct CursorEntered {
@ -175,11 +182,11 @@ pub struct CursorEntered {
}
/// An event that is sent whenever the user's cursor leaves a window.
#[derive(Event, Debug, Clone, PartialEq, Eq, Reflect)]
#[reflect(Debug, PartialEq)]
#[derive(Event, Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "bevy_reflect", derive(Reflect), reflect(Debug, PartialEq))]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(
feature = "serialize",
derive(serde::Serialize, serde::Deserialize),
all(feature = "serialize", feature = "bevy_reflect"),
reflect(Serialize, Deserialize)
)]
pub struct CursorLeft {
@ -192,11 +199,11 @@ pub struct CursorLeft {
/// This event is the translated version of the `WindowEvent::Ime` from the `winit` crate.
///
/// It is only sent if IME was enabled on the window with [`Window::ime_enabled`](crate::window::Window::ime_enabled).
#[derive(Event, Debug, Clone, PartialEq, Eq, Reflect)]
#[reflect(Debug, PartialEq)]
#[derive(Event, Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "bevy_reflect", derive(Reflect), reflect(Debug, PartialEq))]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(
feature = "serialize",
derive(serde::Serialize, serde::Deserialize),
all(feature = "serialize", feature = "bevy_reflect"),
reflect(Serialize, Deserialize)
)]
pub enum Ime {
@ -233,11 +240,11 @@ pub enum Ime {
}
/// An event that indicates a window has received or lost focus.
#[derive(Event, Debug, Clone, PartialEq, Eq, Reflect)]
#[reflect(Debug, PartialEq)]
#[derive(Event, Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "bevy_reflect", derive(Reflect), reflect(Debug, PartialEq))]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(
feature = "serialize",
derive(serde::Serialize, serde::Deserialize),
all(feature = "serialize", feature = "bevy_reflect"),
reflect(Serialize, Deserialize)
)]
pub struct WindowFocused {
@ -256,11 +263,11 @@ pub struct WindowFocused {
/// It is the translated version of [`WindowEvent::Occluded`] from the `winit` crate.
///
/// [`WindowEvent::Occluded`]: https://docs.rs/winit/latest/winit/event/enum.WindowEvent.html#variant.Occluded
#[derive(Event, Debug, Clone, PartialEq, Eq, Reflect)]
#[reflect(Debug, PartialEq)]
#[derive(Event, Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "bevy_reflect", derive(Reflect), reflect(Debug, PartialEq))]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(
feature = "serialize",
derive(serde::Serialize, serde::Deserialize),
all(feature = "serialize", feature = "bevy_reflect"),
reflect(Serialize, Deserialize)
)]
pub struct WindowOccluded {
@ -271,11 +278,11 @@ pub struct WindowOccluded {
}
/// An event that indicates a window's scale factor has changed.
#[derive(Event, Debug, Clone, PartialEq, Reflect)]
#[reflect(Debug, PartialEq)]
#[derive(Event, Debug, Clone, PartialEq)]
#[cfg_attr(feature = "bevy_reflect", derive(Reflect), reflect(Debug, PartialEq))]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(
feature = "serialize",
derive(serde::Serialize, serde::Deserialize),
all(feature = "serialize", feature = "bevy_reflect"),
reflect(Serialize, Deserialize)
)]
pub struct WindowScaleFactorChanged {
@ -286,11 +293,11 @@ pub struct WindowScaleFactorChanged {
}
/// An event that indicates a window's OS-reported scale factor has changed.
#[derive(Event, Debug, Clone, PartialEq, Reflect)]
#[reflect(Debug, PartialEq)]
#[derive(Event, Debug, Clone, PartialEq)]
#[cfg_attr(feature = "bevy_reflect", derive(Reflect), reflect(Debug, PartialEq))]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(
feature = "serialize",
derive(serde::Serialize, serde::Deserialize),
all(feature = "serialize", feature = "bevy_reflect"),
reflect(Serialize, Deserialize)
)]
pub struct WindowBackendScaleFactorChanged {
@ -301,11 +308,11 @@ pub struct WindowBackendScaleFactorChanged {
}
/// Events related to files being dragged and dropped on a window.
#[derive(Event, Debug, Clone, PartialEq, Eq, Reflect)]
#[reflect(Debug, PartialEq)]
#[derive(Event, Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "bevy_reflect", derive(Reflect), reflect(Debug, PartialEq))]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(
feature = "serialize",
derive(serde::Serialize, serde::Deserialize),
all(feature = "serialize", feature = "bevy_reflect"),
reflect(Serialize, Deserialize)
)]
pub enum FileDragAndDrop {
@ -333,11 +340,11 @@ pub enum FileDragAndDrop {
}
/// An event that is sent when a window is repositioned in physical pixels.
#[derive(Event, Debug, Clone, PartialEq, Eq, Reflect)]
#[reflect(Debug, PartialEq)]
#[derive(Event, Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "bevy_reflect", derive(Reflect), reflect(Debug, PartialEq))]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(
feature = "serialize",
derive(serde::Serialize, serde::Deserialize),
all(feature = "serialize", feature = "bevy_reflect"),
reflect(Serialize, Deserialize)
)]
pub struct WindowMoved {
@ -351,11 +358,11 @@ pub struct WindowMoved {
///
/// This event is only sent when the window is relying on the system theme to control its appearance.
/// i.e. It is only sent when [`Window::window_theme`](crate::window::Window::window_theme) is `None` and the system theme changes.
#[derive(Event, Debug, Clone, PartialEq, Eq, Reflect)]
#[reflect(Debug, PartialEq)]
#[derive(Event, Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "bevy_reflect", derive(Reflect), reflect(Debug, PartialEq))]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(
feature = "serialize",
derive(serde::Serialize, serde::Deserialize),
all(feature = "serialize", feature = "bevy_reflect"),
reflect(Serialize, Deserialize)
)]
pub struct WindowThemeChanged {
@ -366,11 +373,11 @@ pub struct WindowThemeChanged {
}
/// Application lifetime events
#[derive(Event, Debug, Clone, Copy, PartialEq, Eq, Reflect)]
#[reflect(Debug, PartialEq)]
#[derive(Event, Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "bevy_reflect", derive(Reflect), reflect(Debug, PartialEq))]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(
feature = "serialize",
derive(serde::Serialize, serde::Deserialize),
all(feature = "serialize", feature = "bevy_reflect"),
reflect(Serialize, Deserialize)
)]
pub enum AppLifecycle {
@ -405,11 +412,11 @@ impl AppLifecycle {
/// access window events in the order they were received from the
/// operating system. Otherwise, the event types are individually
/// readable with `EventReader<E>` (e.g. `EventReader<KeyboardInput>`).
#[derive(Event, Debug, Clone, PartialEq, Reflect)]
#[reflect(Debug, PartialEq)]
#[derive(Event, Debug, Clone, PartialEq)]
#[cfg_attr(feature = "bevy_reflect", derive(Reflect), reflect(Debug, PartialEq))]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(
feature = "serialize",
derive(serde::Serialize, serde::Deserialize),
all(feature = "serialize", feature = "bevy_reflect"),
reflect(Serialize, Deserialize)
)]
#[expect(missing_docs, reason = "Not all docs are written yet, see #3492.")]

View File

@ -3,6 +3,7 @@
html_logo_url = "https://bevyengine.org/assets/icon.png",
html_favicon_url = "https://bevyengine.org/assets/icon.png"
)]
#![cfg_attr(not(feature = "std"), no_std)]
//! `bevy_window` provides a platform-agnostic interface for windowing in Bevy.
//!
@ -14,8 +15,13 @@
extern crate alloc;
use alloc::sync::Arc;
#[cfg(feature = "std")]
use std::sync::Mutex;
#[cfg(not(feature = "std"))]
use spin::mutex::Mutex;
mod event;
mod monitor;
mod raw_handle;
@ -138,6 +144,7 @@ impl Plugin for WindowPlugin {
}
// Register event types
#[cfg(feature = "bevy_reflect")]
app.register_type::<WindowEvent>()
.register_type::<WindowResized>()
.register_type::<RequestRedraw>()
@ -159,6 +166,7 @@ impl Plugin for WindowPlugin {
.register_type::<Monitor>();
// Register window descriptor and related types
#[cfg(feature = "bevy_reflect")]
app.register_type::<Window>()
.register_type::<PrimaryWindow>();
}

View File

@ -1,8 +1,11 @@
use bevy_ecs::{component::Component, prelude::ReflectComponent};
use alloc::{string::String, vec::Vec};
use bevy_ecs::component::Component;
use bevy_math::{IVec2, UVec2};
use bevy_reflect::Reflect;
#[cfg(feature = "serialize")]
#[cfg(feature = "bevy_reflect")]
use {bevy_ecs::prelude::ReflectComponent, bevy_reflect::Reflect};
#[cfg(all(feature = "serialize", feature = "bevy_reflect"))]
use bevy_reflect::{ReflectDeserialize, ReflectSerialize};
/// Represents an available monitor as reported by the user's operating system, which can be used
@ -15,13 +18,13 @@ use bevy_reflect::{ReflectDeserialize, ReflectSerialize};
///
/// This component is synchronized with `winit` through `bevy_winit`, but is effectively
/// read-only as `winit` does not support changing monitor properties.
#[derive(Component, Debug, Clone, Reflect)]
#[derive(Component, Debug, Clone)]
#[cfg_attr(feature = "bevy_reflect", derive(Reflect), reflect(Component, Debug))]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(
feature = "serialize",
derive(serde::Serialize, serde::Deserialize),
all(feature = "serialize", feature = "bevy_reflect"),
reflect(Serialize, Deserialize)
)]
#[reflect(Component, Debug)]
pub struct Monitor {
/// The name of the monitor
pub name: Option<String>,
@ -40,8 +43,8 @@ pub struct Monitor {
}
/// A marker component for the primary monitor
#[derive(Component, Debug, Clone, Reflect)]
#[reflect(Component, Debug)]
#[derive(Component, Debug, Clone)]
#[cfg_attr(feature = "bevy_reflect", derive(Reflect), reflect(Component, Debug))]
pub struct PrimaryMonitor;
impl Monitor {
@ -52,10 +55,11 @@ impl Monitor {
}
/// Represents a video mode that a monitor supports
#[derive(Debug, Clone, Reflect)]
#[derive(Debug, Clone)]
#[cfg_attr(feature = "bevy_reflect", derive(Reflect), reflect(Debug))]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(
feature = "serialize",
derive(serde::Serialize, serde::Deserialize),
all(feature = "serialize", feature = "bevy_reflect"),
reflect(Serialize, Deserialize)
)]
pub struct VideoMode {

View File

@ -7,8 +7,13 @@ use raw_window_handle::{
DisplayHandle, HandleError, HasDisplayHandle, HasWindowHandle, RawDisplayHandle,
RawWindowHandle, WindowHandle,
};
#[cfg(feature = "std")]
use std::sync::Mutex;
#[cfg(not(feature = "std"))]
use spin::mutex::Mutex;
/// A wrapper over a window.
///
/// This allows us to extend the lifetime of the window, so it doesn't get eagerly dropped while a

View File

@ -12,7 +12,7 @@ use bevy_ecs::prelude::*;
/// [`WindowPlugin`]: crate::WindowPlugin
pub fn exit_on_all_closed(mut app_exit_events: EventWriter<AppExit>, windows: Query<&Window>) {
if windows.is_empty() {
bevy_utils::tracing::info!("No windows are open, exiting");
log::info!("No windows are open, exiting");
app_exit_events.send(AppExit::Success);
}
}
@ -27,7 +27,7 @@ pub fn exit_on_primary_closed(
windows: Query<(), (With<Window>, With<PrimaryWindow>)>,
) {
if windows.is_empty() {
bevy_utils::tracing::info!("Primary window was closed, exiting");
log::info!("Primary window was closed, exiting");
app_exit_events.send(AppExit::Success);
}
}

View File

@ -68,6 +68,7 @@
// --------- END OF W3C SHORT NOTICE
// --------------------------------------------------------------
#[cfg(feature = "bevy_reflect")]
use bevy_reflect::{prelude::ReflectDefault, Reflect};
#[cfg(feature = "serialize")]
@ -82,13 +83,17 @@ use bevy_reflect::{ReflectDeserialize, ReflectSerialize};
/// See the [`window_settings`] example for usage.
///
/// [`window_settings`]: https://github.com/bevyengine/bevy/blob/latest/examples/window/window_settings.rs
#[derive(Default, Debug, Hash, PartialEq, Eq, Clone, Copy, Reflect)]
#[derive(Default, Debug, Hash, PartialEq, Eq, Clone, Copy)]
#[cfg_attr(
feature = "serialize",
derive(serde::Serialize, serde::Deserialize),
feature = "bevy_reflect",
derive(Reflect),
reflect(Debug, PartialEq, Default)
)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(
all(feature = "serialize", feature = "bevy_reflect"),
reflect(Serialize, Deserialize)
)]
#[reflect(Debug, PartialEq, Default)]
pub enum SystemCursorIcon {
/// The platform-dependent default cursor. Often rendered as arrow.
#[default]

View File

@ -1,17 +1,22 @@
use alloc::{borrow::ToOwned, string::String};
use core::num::NonZero;
use bevy_ecs::{
entity::{Entity, EntityBorrow, VisitEntities, VisitEntitiesMut},
prelude::{Component, ReflectComponent},
prelude::Component,
};
use bevy_math::{CompassOctant, DVec2, IVec2, UVec2, Vec2};
use bevy_reflect::{std_traits::ReflectDefault, Reflect};
use log::warn;
#[cfg(feature = "serialize")]
#[cfg(feature = "bevy_reflect")]
use {
bevy_ecs::prelude::ReflectComponent,
bevy_reflect::{std_traits::ReflectDefault, Reflect},
};
#[cfg(all(feature = "serialize", feature = "bevy_reflect"))]
use bevy_reflect::{ReflectDeserialize, ReflectSerialize};
use bevy_utils::tracing::warn;
/// Marker [`Component`] for the window considered the primary window.
///
/// Currently this is assumed to only exist on 1 entity at a time.
@ -19,17 +24,22 @@ use bevy_utils::tracing::warn;
/// [`WindowPlugin`](crate::WindowPlugin) will spawn a [`Window`] entity
/// with this component if [`primary_window`](crate::WindowPlugin::primary_window)
/// is `Some`.
#[derive(Default, Debug, Component, PartialEq, Eq, PartialOrd, Ord, Copy, Clone, Reflect)]
#[reflect(Component, Debug, Default, PartialEq)]
#[derive(Default, Debug, Component, PartialEq, Eq, PartialOrd, Ord, Copy, Clone)]
#[cfg_attr(
feature = "bevy_reflect",
derive(Reflect),
reflect(Component, Debug, Default, PartialEq)
)]
pub struct PrimaryWindow;
/// Reference to a [`Window`], whether it be a direct link to a specific entity or
/// a more vague defaulting choice.
#[repr(C)]
#[derive(Default, Copy, Clone, Debug, Reflect)]
#[derive(Default, Copy, Clone, Debug)]
#[cfg_attr(feature = "bevy_reflect", derive(Reflect), reflect(Debug, Default))]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(
feature = "serialize",
derive(serde::Serialize, serde::Deserialize),
all(feature = "serialize", feature = "bevy_reflect"),
reflect(Serialize, Deserialize)
)]
pub enum WindowRef {
@ -80,10 +90,11 @@ impl VisitEntitiesMut for WindowRef {
///
/// For most purposes you probably want to use the unnormalized version [`WindowRef`].
#[repr(C)]
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Reflect)]
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "bevy_reflect", derive(Reflect), reflect(Debug, PartialEq))]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(
feature = "serialize",
derive(serde::Serialize, serde::Deserialize),
all(feature = "serialize", feature = "bevy_reflect"),
reflect(Serialize, Deserialize)
)]
pub struct NormalizedWindowRef(Entity);
@ -124,13 +135,17 @@ impl EntityBorrow for NormalizedWindowRef {
/// }
/// }
/// ```
#[derive(Component, Debug, Clone, Reflect)]
#[derive(Component, Debug, Clone)]
#[cfg_attr(
feature = "serialize",
derive(serde::Serialize, serde::Deserialize),
feature = "bevy_reflect",
derive(Reflect),
reflect(Component, Default, Debug)
)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(
all(feature = "serialize", feature = "bevy_reflect"),
reflect(Serialize, Deserialize)
)]
#[reflect(Component, Default, Debug)]
pub struct Window {
/// The cursor options of this window. Cursor icons are set with the `Cursor` component on the
/// window entity.
@ -588,13 +603,17 @@ impl Window {
/// Please note that if the window is resizable, then when the window is
/// maximized it may have a size outside of these limits. The functionality
/// required to disable maximizing is not yet exposed by winit.
#[derive(Debug, Clone, Copy, PartialEq, Reflect)]
#[derive(Debug, Clone, Copy, PartialEq)]
#[cfg_attr(
feature = "serialize",
derive(serde::Serialize, serde::Deserialize),
feature = "bevy_reflect",
derive(Reflect),
reflect(Debug, PartialEq, Default)
)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(
all(feature = "serialize", feature = "bevy_reflect"),
reflect(Serialize, Deserialize)
)]
#[reflect(Debug, PartialEq, Default)]
pub struct WindowResizeConstraints {
/// The minimum width the window can have.
pub min_width: f32,
@ -655,13 +674,13 @@ impl WindowResizeConstraints {
}
/// Cursor data for a [`Window`].
#[derive(Debug, Clone, Reflect)]
#[derive(Debug, Clone)]
#[cfg_attr(feature = "bevy_reflect", derive(Reflect), reflect(Debug, Default))]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(
feature = "serialize",
derive(serde::Serialize, serde::Deserialize),
all(feature = "serialize", feature = "bevy_reflect"),
reflect(Serialize, Deserialize)
)]
#[reflect(Debug, Default)]
pub struct CursorOptions {
/// Whether the cursor is visible or not.
///
@ -703,13 +722,13 @@ impl Default for CursorOptions {
}
/// Defines where a [`Window`] should be placed on the screen.
#[derive(Default, Debug, Clone, Copy, PartialEq, Reflect)]
#[derive(Default, Debug, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "bevy_reflect", derive(Reflect), reflect(Debug, PartialEq))]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(
feature = "serialize",
derive(serde::Serialize, serde::Deserialize),
all(feature = "serialize", feature = "bevy_reflect"),
reflect(Serialize, Deserialize)
)]
#[reflect(Debug, PartialEq)]
pub enum WindowPosition {
/// Position will be set by the window manager.
/// Bevy will delegate this decision to the window manager and no guarantees can be made about where the window will be placed.
@ -792,13 +811,17 @@ impl WindowPosition {
/// and then setting a scale factor that makes the previous requested size within
/// the limits of the screen will not get back that previous requested size.
#[derive(Debug, Clone, PartialEq, Reflect)]
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(
feature = "serialize",
derive(serde::Serialize, serde::Deserialize),
feature = "bevy_reflect",
derive(Reflect),
reflect(Debug, PartialEq, Default)
)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(
all(feature = "serialize", feature = "bevy_reflect"),
reflect(Serialize, Deserialize)
)]
#[reflect(Debug, PartialEq, Default)]
pub struct WindowResolution {
/// Width of the window in physical pixels.
physical_width: u32,
@ -987,13 +1010,17 @@ impl From<DVec2> for WindowResolution {
/// - **`iOS/Android`** don't have cursors.
///
/// Since `Windows` and `macOS` have different [`CursorGrabMode`] support, we first try to set the grab mode that was asked for. If it doesn't work then use the alternate grab mode.
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, Reflect)]
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(
feature = "serialize",
derive(serde::Serialize, serde::Deserialize),
feature = "bevy_reflect",
derive(Reflect),
reflect(Debug, PartialEq, Default)
)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(
all(feature = "serialize", feature = "bevy_reflect"),
reflect(Serialize, Deserialize)
)]
#[reflect(Debug, PartialEq, Default)]
pub enum CursorGrabMode {
/// The cursor can freely leave the window.
#[default]
@ -1005,13 +1032,17 @@ pub enum CursorGrabMode {
}
/// Stores internal [`Window`] state that isn't directly accessible.
#[derive(Default, Debug, Copy, Clone, PartialEq, Reflect)]
#[derive(Default, Debug, Copy, Clone, PartialEq)]
#[cfg_attr(
feature = "serialize",
derive(serde::Serialize, serde::Deserialize),
feature = "bevy_reflect",
derive(Reflect),
reflect(Debug, PartialEq, Default)
)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(
all(feature = "serialize", feature = "bevy_reflect"),
reflect(Serialize, Deserialize)
)]
#[reflect(Debug, PartialEq, Default)]
pub struct InternalWindowState {
/// If this is true then next frame we will ask to minimize the window.
minimize_request: Option<bool>,
@ -1050,13 +1081,13 @@ impl InternalWindowState {
/// References a screen monitor.
///
/// Used when centering a [`Window`] on a monitor.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Reflect)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "bevy_reflect", derive(Reflect), reflect(Debug, PartialEq))]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(
feature = "serialize",
derive(serde::Serialize, serde::Deserialize),
all(feature = "serialize", feature = "bevy_reflect"),
reflect(Serialize, Deserialize)
)]
#[reflect(Debug, PartialEq)]
pub enum MonitorSelection {
/// Uses the current monitor of the window.
///
@ -1091,13 +1122,17 @@ pub enum MonitorSelection {
/// [`AutoVsync`]: PresentMode::AutoVsync
/// [`AutoNoVsync`]: PresentMode::AutoNoVsync
#[repr(C)]
#[derive(Default, Copy, Clone, Debug, PartialEq, Eq, Hash, Reflect)]
#[derive(Default, Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(
feature = "serialize",
derive(serde::Serialize, serde::Deserialize),
feature = "bevy_reflect",
derive(Reflect),
reflect(Debug, PartialEq, Hash)
)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(
all(feature = "serialize", feature = "bevy_reflect"),
reflect(Serialize, Deserialize)
)]
#[reflect(Debug, PartialEq, Hash)]
#[doc(alias = "vsync")]
pub enum PresentMode {
/// Chooses [`FifoRelaxed`](Self::FifoRelaxed) -> [`Fifo`](Self::Fifo) based on availability.
@ -1168,13 +1203,17 @@ pub enum PresentMode {
/// Specifies how the alpha channel of the textures should be handled during compositing, for a [`Window`].
#[repr(C)]
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, Hash, Reflect)]
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[cfg_attr(
feature = "serialize",
derive(serde::Serialize, serde::Deserialize),
feature = "bevy_reflect",
derive(Reflect),
reflect(Debug, PartialEq, Hash)
)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(
all(feature = "serialize", feature = "bevy_reflect"),
reflect(Serialize, Deserialize)
)]
#[reflect(Debug, PartialEq, Hash)]
pub enum CompositeAlphaMode {
/// Chooses either [`Opaque`](CompositeAlphaMode::Opaque) or [`Inherit`](CompositeAlphaMode::Inherit)
/// automatically, depending on the `alpha_mode` that the current surface can support.
@ -1203,13 +1242,13 @@ pub enum CompositeAlphaMode {
}
/// Defines the way a [`Window`] is displayed.
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, Reflect)]
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "bevy_reflect", derive(Reflect), reflect(Debug, PartialEq))]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(
feature = "serialize",
derive(serde::Serialize, serde::Deserialize),
all(feature = "serialize", feature = "bevy_reflect"),
reflect(Serialize, Deserialize)
)]
#[reflect(Debug, PartialEq)]
pub enum WindowMode {
/// The window should take a portion of the screen, using the window resolution size.
#[default]
@ -1260,13 +1299,13 @@ pub enum WindowMode {
/// ## Platform-specific
///
/// - **iOS / Android / Web / Wayland:** Unsupported.
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, Reflect)]
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "bevy_reflect", derive(Reflect), reflect(Debug, PartialEq))]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(
feature = "serialize",
derive(serde::Serialize, serde::Deserialize),
all(feature = "serialize", feature = "bevy_reflect"),
reflect(Serialize, Deserialize)
)]
#[reflect(Debug, PartialEq)]
pub enum WindowLevel {
/// The window will always be below [`WindowLevel::Normal`] and [`WindowLevel::AlwaysOnTop`] windows.
///
@ -1280,13 +1319,13 @@ pub enum WindowLevel {
}
/// The [`Window`] theme variant to use.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Reflect)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "bevy_reflect", derive(Reflect), reflect(Debug, PartialEq))]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(
feature = "serialize",
derive(serde::Serialize, serde::Deserialize),
all(feature = "serialize", feature = "bevy_reflect"),
reflect(Serialize, Deserialize)
)]
#[reflect(Debug, PartialEq)]
pub enum WindowTheme {
/// Use the light variant.
Light,
@ -1302,13 +1341,17 @@ pub enum WindowTheme {
/// **`iOS`**, **`Android`**, and the **`Web`** do not have window control buttons.
///
/// On some **`Linux`** environments these values have no effect.
#[derive(Debug, Copy, Clone, PartialEq, Reflect)]
#[derive(Debug, Copy, Clone, PartialEq)]
#[cfg_attr(
feature = "serialize",
derive(serde::Serialize, serde::Deserialize),
feature = "bevy_reflect",
derive(Reflect),
reflect(Debug, PartialEq, Default)
)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(
all(feature = "serialize", feature = "bevy_reflect"),
reflect(Serialize, Deserialize)
)]
#[reflect(Debug, PartialEq, Default)]
pub struct EnabledButtons {
/// Enables the functionality of the minimize button.
pub minimize: bool,

View File

@ -134,6 +134,14 @@ impl Prepare for CompileCheckNoStdCommand {
"Please fix compiler errors in output above for bevy_state no_std compatibility.",
));
commands.push(PreparedCommand::new::<Self>(
cmd!(
sh,
"cargo check -p bevy_window --no-default-features --features libm,bevy_reflect,serialize --target {target}"
),
"Please fix compiler errors in output above for bevy_state no_std compatibility.",
));
commands.push(PreparedCommand::new::<Self>(
cmd!(
sh,