Skip to content

Commit

Permalink
Derive Reflect + FromReflect for window event types (#6235)
Browse files Browse the repository at this point in the history
# Objective

The window event types currently don't support reflection. This PR adds support to them (as requested [here](#6223 (comment))).

## Solution

Implement `Reflect` + `FromReflect` for window event types. Relevant traits are also being reflected with `#[reflect(...)]` attributes.

Additionally, this PR derives `Reflect` + `FromReflect` for `WindowDescriptor` and the types it depends on so that `CreateWindow` events can be fully manipulated through reflection.

Finally, this PR adds `FromReflect` for `PathBuf` as a value type, which is needed for `FileDragAndDrop`.

This adds the "glam" feature to the `bevy_reflect` dependency for package `bevy_window`. Since `bevy_window` transitively depends on `glam` already, all this brings in are the reflection `impl`s.

## Open questions

Should `app.register_type::<PathBuf>();` be moved to `CorePlugin`? I added it to `WindowPlugin` because that's where it's used and `CorePlugin` doesn't seem to register all the missing std types, but it would also make sense in `CorePlugin` I believe since it's a commonly used type.

---

## Changelog

Added:
- Implemented `Reflect` + `FromReflect` for window events and related types. These types are automatically registered when adding the `WindowPlugin`.
  • Loading branch information
TehPers committed Dec 9, 2022
1 parent b58ca87 commit a5d70b8
Show file tree
Hide file tree
Showing 4 changed files with 213 additions and 51 deletions.
4 changes: 3 additions & 1 deletion crates/bevy_window/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ serialize = ["serde"]
bevy_app = { path = "../bevy_app", version = "0.9.0" }
bevy_ecs = { path = "../bevy_ecs", version = "0.9.0" }
bevy_math = { path = "../bevy_math", version = "0.9.0" }
bevy_reflect = { path = "../bevy_reflect", version = "0.9.0" }
bevy_reflect = { path = "../bevy_reflect", version = "0.9.0", features = [
"glam",
] }
bevy_utils = { path = "../bevy_utils", version = "0.9.0" }
# Used for close_on_esc
bevy_input = { path = "../bevy_input", version = "0.9.0" }
Expand Down
143 changes: 113 additions & 30 deletions crates/bevy_window/src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,19 @@ use std::path::PathBuf;

use super::{WindowDescriptor, WindowId};
use bevy_math::{IVec2, Vec2};
use bevy_reflect::{FromReflect, Reflect};

#[cfg(feature = "serialize")]
use bevy_reflect::{ReflectDeserialize, ReflectSerialize};

/// A window event that is sent whenever a window's logical size has changed.
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq, Reflect, FromReflect)]
#[reflect(Debug, PartialEq)]
#[cfg_attr(
feature = "serialize",
derive(serde::Serialize, serde::Deserialize),
reflect(Serialize, Deserialize)
)]
pub struct WindowResized {
pub id: WindowId,
/// The new logical width of the window.
Expand All @@ -15,25 +24,40 @@ pub struct WindowResized {
}

/// An event that indicates that a new window should be created.
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq, Reflect, FromReflect)]
#[reflect(Debug, PartialEq)]
#[cfg_attr(
feature = "serialize",
derive(serde::Serialize, serde::Deserialize),
reflect(Serialize, Deserialize)
)]
pub struct CreateWindow {
pub id: WindowId,
pub descriptor: WindowDescriptor,
}

/// An event that indicates the window should redraw, even if its control flow is set to `Wait` and
/// there have been no window events.
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq, Reflect, FromReflect)]
#[reflect(Debug, PartialEq)]
#[cfg_attr(
feature = "serialize",
derive(serde::Serialize, serde::Deserialize),
reflect(Serialize, Deserialize)
)]
pub struct RequestRedraw;

/// An event that is sent whenever a new window is created.
///
/// To create a new window, send a [`CreateWindow`] event - this
/// event will be sent in the handler for that event.
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq, Reflect, FromReflect)]
#[reflect(Debug, PartialEq)]
#[cfg_attr(
feature = "serialize",
derive(serde::Serialize, serde::Deserialize),
reflect(Serialize, Deserialize)
)]
pub struct WindowCreated {
pub id: WindowId,
}
Expand All @@ -49,8 +73,13 @@ pub struct WindowCreated {
/// [`WindowPlugin`]: crate::WindowPlugin
/// [`Window`]: crate::Window
/// [closing]: crate::Window::close
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq, Reflect, FromReflect)]
#[reflect(Debug, PartialEq)]
#[cfg_attr(
feature = "serialize",
derive(serde::Serialize, serde::Deserialize),
reflect(Serialize, Deserialize)
)]
pub struct WindowCloseRequested {
pub id: WindowId,
}
Expand All @@ -59,11 +88,17 @@ pub struct WindowCloseRequested {
/// handler for [`Window::close`].
///
/// [`Window::close`]: crate::Window::close
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq, Reflect, FromReflect)]
#[reflect(Debug, PartialEq)]
#[cfg_attr(
feature = "serialize",
derive(serde::Serialize, serde::Deserialize),
reflect(Serialize, Deserialize)
)]
pub struct WindowClosed {
pub id: WindowId,
}

/// An event reporting that the mouse cursor has moved on a window.
///
/// The event is sent only if the cursor is over one of the application's windows.
Expand All @@ -73,62 +108,105 @@ pub struct WindowClosed {
///
/// [`WindowEvent::CursorMoved`]: https://docs.rs/winit/latest/winit/event/enum.WindowEvent.html#variant.CursorMoved
/// [`MouseMotion`]: bevy_input::mouse::MouseMotion
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq, Reflect, FromReflect)]
#[reflect(Debug, PartialEq)]
#[cfg_attr(
feature = "serialize",
derive(serde::Serialize, serde::Deserialize),
reflect(Serialize, Deserialize)
)]
pub struct CursorMoved {
/// The identifier of the window the cursor has moved on.
pub id: WindowId,

/// The position of the cursor, in window coordinates.
pub position: Vec2,
}

/// An event that is sent whenever the user's cursor enters a window.
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq, Reflect, FromReflect)]
#[reflect(Debug, PartialEq)]
#[cfg_attr(
feature = "serialize",
derive(serde::Serialize, serde::Deserialize),
reflect(Serialize, Deserialize)
)]
pub struct CursorEntered {
pub id: WindowId,
}

/// An event that is sent whenever the user's cursor leaves a window.
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq, Reflect, FromReflect)]
#[reflect(Debug, PartialEq)]
#[cfg_attr(
feature = "serialize",
derive(serde::Serialize, serde::Deserialize),
reflect(Serialize, Deserialize)
)]
pub struct CursorLeft {
pub id: WindowId,
}

/// An event that is sent whenever a window receives a character from the OS or underlying system.
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq, Reflect, FromReflect)]
#[reflect(Debug, PartialEq)]
#[cfg_attr(
feature = "serialize",
derive(serde::Serialize, serde::Deserialize),
reflect(Serialize, Deserialize)
)]
pub struct ReceivedCharacter {
pub id: WindowId,
pub char: char,
}

/// An event that indicates a window has received or lost focus.
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq, Reflect, FromReflect)]
#[reflect(Debug, PartialEq)]
#[cfg_attr(
feature = "serialize",
derive(serde::Serialize, serde::Deserialize),
reflect(Serialize, Deserialize)
)]
pub struct WindowFocused {
pub id: WindowId,
pub focused: bool,
}

/// An event that indicates a window's scale factor has changed.
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq, Reflect, FromReflect)]
#[reflect(Debug, PartialEq)]
#[cfg_attr(
feature = "serialize",
derive(serde::Serialize, serde::Deserialize),
reflect(Serialize, Deserialize)
)]
pub struct WindowScaleFactorChanged {
pub id: WindowId,
pub scale_factor: f64,
}

/// An event that indicates a window's OS-reported scale factor has changed.
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq, Reflect, FromReflect)]
#[reflect(Debug, PartialEq)]
#[cfg_attr(
feature = "serialize",
derive(serde::Serialize, serde::Deserialize),
reflect(Serialize, Deserialize)
)]
pub struct WindowBackendScaleFactorChanged {
pub id: WindowId,
pub scale_factor: f64,
}

/// Events related to files being dragged and dropped on a window.
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq, Reflect, FromReflect)]
#[reflect(Debug, PartialEq)]
#[cfg_attr(
feature = "serialize",
derive(serde::Serialize, serde::Deserialize),
reflect(Serialize, Deserialize)
)]
pub enum FileDragAndDrop {
DroppedFile { id: WindowId, path_buf: PathBuf },

Expand All @@ -138,8 +216,13 @@ pub enum FileDragAndDrop {
}

/// An event that is sent when a window is repositioned in physical pixels.
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq, Reflect, FromReflect)]
#[reflect(Debug, PartialEq)]
#[cfg_attr(
feature = "serialize",
derive(serde::Serialize, serde::Deserialize),
reflect(Serialize, Deserialize)
)]
pub struct WindowMoved {
pub id: WindowId,
pub position: IVec2,
Expand Down
30 changes: 30 additions & 0 deletions crates/bevy_window/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ pub mod prelude {

use bevy_app::prelude::*;
use bevy_ecs::schedule::{IntoSystemDescriptor, SystemLabel};
use std::path::PathBuf;

impl Default for WindowPlugin {
fn default() -> Self {
Expand Down Expand Up @@ -97,6 +98,35 @@ impl Plugin for WindowPlugin {
if self.close_when_requested {
app.add_system(close_when_requested);
}

// Register event types
app.register_type::<WindowResized>()
.register_type::<CreateWindow>()
.register_type::<RequestRedraw>()
.register_type::<WindowCreated>()
.register_type::<WindowCloseRequested>()
.register_type::<WindowClosed>()
.register_type::<CursorMoved>()
.register_type::<CursorEntered>()
.register_type::<CursorLeft>()
.register_type::<ReceivedCharacter>()
.register_type::<WindowFocused>()
.register_type::<WindowScaleFactorChanged>()
.register_type::<WindowBackendScaleFactorChanged>()
.register_type::<FileDragAndDrop>()
.register_type::<WindowMoved>();

// Register window descriptor and related types
app.register_type::<WindowId>()
.register_type::<PresentMode>()
.register_type::<WindowResizeConstraints>()
.register_type::<WindowMode>()
.register_type::<WindowPosition>()
.register_type::<MonitorSelection>()
.register_type::<WindowDescriptor>();

// Register `PathBuf` as it's used by `FileDragAndDrop`
app.register_type::<PathBuf>();
}
}

Expand Down
Loading

0 comments on commit a5d70b8

Please sign in to comment.