Skip to content

Commit

Permalink
Add send_event and friends to WorldCell (bevyengine#6515)
Browse files Browse the repository at this point in the history
# Objective

Copy `send_event` and friends from `World` to `WorldCell`.

Clean up `bevy_winit` using `WorldCell::send_event`.

## Changelog

Added `send_event`, `send_event_default`, and `send_event_batch` to `WorldCell`.

Co-authored-by: devil-ira <justthecooldude@gmail.com>
  • Loading branch information
2 people authored and ItsDoot committed Feb 1, 2023
1 parent cc42ddc commit e84dbda
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 69 deletions.
27 changes: 27 additions & 0 deletions crates/bevy_ecs/src/world/world_cell.rs
@@ -1,5 +1,8 @@
use bevy_utils::tracing::error;

use crate::{
archetype::ArchetypeComponentId,
event::{Event, Events},
storage::SparseSet,
system::Resource,
world::{Mut, World},
Expand Down Expand Up @@ -317,6 +320,30 @@ impl<'w> WorldCell<'w> {
),
}
}

/// Sends an [`Event`](crate::event::Event).
#[inline]
pub fn send_event<E: Event>(&self, event: E) {
self.send_event_batch(std::iter::once(event));
}

/// Sends the default value of the [`Event`](crate::event::Event) of type `E`.
#[inline]
pub fn send_event_default<E: Event + Default>(&self) {
self.send_event_batch(std::iter::once(E::default()));
}

/// Sends a batch of [`Event`](crate::event::Event)s from an iterator.
#[inline]
pub fn send_event_batch<E: Event>(&self, events: impl Iterator<Item = E>) {
match self.get_resource_mut::<Events<E>>() {
Some(mut events_resource) => events_resource.extend(events),
None => error!(
"Unable to send event `{}`\n\tEvent must be added to the app with `add_event()`\n\thttps://docs.rs/bevy/*/bevy/app/struct.App.html#method.add_event ",
std::any::type_name::<E>()
),
}
}
}

#[cfg(test)]
Expand Down
8 changes: 2 additions & 6 deletions crates/bevy_window/src/lib.rs
Expand Up @@ -23,10 +23,7 @@ pub mod prelude {
}

use bevy_app::prelude::*;
use bevy_ecs::{
event::Events,
schedule::{IntoSystemDescriptor, SystemLabel},
};
use bevy_ecs::schedule::{IntoSystemDescriptor, SystemLabel};

impl Default for WindowPlugin {
fn default() -> Self {
Expand Down Expand Up @@ -85,8 +82,7 @@ impl Plugin for WindowPlugin {
.init_resource::<Windows>();

if self.add_primary_window {
let mut create_window_event = app.world.resource_mut::<Events<CreateWindow>>();
create_window_event.send(CreateWindow {
app.world.send_event(CreateWindow {
id: WindowId::primary(),
descriptor: self.window.clone(),
});
Expand Down
87 changes: 24 additions & 63 deletions crates/bevy_winit/src/lib.rs
Expand Up @@ -14,11 +14,7 @@ use bevy_ecs::{
event::{Events, ManualEventReader},
world::World,
};
use bevy_input::{
keyboard::KeyboardInput,
mouse::{MouseButtonInput, MouseMotion, MouseScrollUnit, MouseWheel},
touch::TouchInput,
};
use bevy_input::mouse::{MouseButtonInput, MouseMotion, MouseScrollUnit, MouseWheel};
use bevy_math::{ivec2, DVec2, UVec2, Vec2};
use bevy_utils::{
tracing::{error, info, trace, warn},
Expand Down Expand Up @@ -408,76 +404,58 @@ pub fn winit_runner_with(mut app: App) {
match event {
WindowEvent::Resized(size) => {
window.update_actual_size_from_backend(size.width, size.height);
let mut resize_events = world.resource_mut::<Events<WindowResized>>();
resize_events.send(WindowResized {
world.send_event(WindowResized {
id: window_id,
width: window.width(),
height: window.height(),
});
}
WindowEvent::CloseRequested => {
let mut window_close_requested_events =
world.resource_mut::<Events<WindowCloseRequested>>();
window_close_requested_events.send(WindowCloseRequested { id: window_id });
world.send_event(WindowCloseRequested { id: window_id });
}
WindowEvent::KeyboardInput { ref input, .. } => {
let mut keyboard_input_events =
world.resource_mut::<Events<KeyboardInput>>();
keyboard_input_events.send(converters::convert_keyboard_input(input));
world.send_event(converters::convert_keyboard_input(input));
}
WindowEvent::CursorMoved { position, .. } => {
let mut cursor_moved_events = world.resource_mut::<Events<CursorMoved>>();

let physical_position = DVec2::new(position.x, position.y);
window
.update_cursor_physical_position_from_backend(Some(physical_position));

cursor_moved_events.send(CursorMoved {
world.send_event(CursorMoved {
id: window_id,
position: (physical_position / window.scale_factor()).as_vec2(),
});
}
WindowEvent::CursorEntered { .. } => {
let mut cursor_entered_events =
world.resource_mut::<Events<CursorEntered>>();
cursor_entered_events.send(CursorEntered { id: window_id });
world.send_event(CursorEntered { id: window_id });
}
WindowEvent::CursorLeft { .. } => {
let mut cursor_left_events = world.resource_mut::<Events<CursorLeft>>();
window.update_cursor_physical_position_from_backend(None);
cursor_left_events.send(CursorLeft { id: window_id });
world.send_event(CursorLeft { id: window_id });
}
WindowEvent::MouseInput { state, button, .. } => {
let mut mouse_button_input_events =
world.resource_mut::<Events<MouseButtonInput>>();
mouse_button_input_events.send(MouseButtonInput {
world.send_event(MouseButtonInput {
button: converters::convert_mouse_button(button),
state: converters::convert_element_state(state),
});
}
WindowEvent::MouseWheel { delta, .. } => match delta {
event::MouseScrollDelta::LineDelta(x, y) => {
let mut mouse_wheel_input_events =
world.resource_mut::<Events<MouseWheel>>();
mouse_wheel_input_events.send(MouseWheel {
world.send_event(MouseWheel {
unit: MouseScrollUnit::Line,
x,
y,
});
}
event::MouseScrollDelta::PixelDelta(p) => {
let mut mouse_wheel_input_events =
world.resource_mut::<Events<MouseWheel>>();
mouse_wheel_input_events.send(MouseWheel {
world.send_event(MouseWheel {
unit: MouseScrollUnit::Pixel,
x: p.x as f32,
y: p.y as f32,
});
}
},
WindowEvent::Touch(touch) => {
let mut touch_input_events = world.resource_mut::<Events<TouchInput>>();

let mut location = touch.location.to_logical(window.scale_factor());

// On a mobile window, the start is from the top while on PC/Linux/OSX from
Expand All @@ -486,13 +464,11 @@ pub fn winit_runner_with(mut app: App) {
let window_height = windows.primary().height();
location.y = window_height - location.y;
}
touch_input_events.send(converters::convert_touch_input(touch, location));

world.send_event(converters::convert_touch_input(touch, location));
}
WindowEvent::ReceivedCharacter(c) => {
let mut char_input_events =
world.resource_mut::<Events<ReceivedCharacter>>();

char_input_events.send(ReceivedCharacter {
world.send_event(ReceivedCharacter {
id: window_id,
char: c,
});
Expand All @@ -501,9 +477,7 @@ pub fn winit_runner_with(mut app: App) {
scale_factor,
new_inner_size,
} => {
let mut backend_scale_factor_change_events =
world.resource_mut::<Events<WindowBackendScaleFactorChanged>>();
backend_scale_factor_change_events.send(WindowBackendScaleFactorChanged {
world.send_event(WindowBackendScaleFactorChanged {
id: window_id,
scale_factor,
});
Expand All @@ -521,10 +495,7 @@ pub fn winit_runner_with(mut app: App) {
)
.to_physical::<u32>(forced_factor);
} else if approx::relative_ne!(new_factor, prior_factor) {
let mut scale_factor_change_events =
world.resource_mut::<Events<WindowScaleFactorChanged>>();

scale_factor_change_events.send(WindowScaleFactorChanged {
world.send_event(WindowScaleFactorChanged {
id: window_id,
scale_factor,
});
Expand All @@ -535,8 +506,7 @@ pub fn winit_runner_with(mut app: App) {
if approx::relative_ne!(window.width() as f64, new_logical_width)
|| approx::relative_ne!(window.height() as f64, new_logical_height)
{
let mut resize_events = world.resource_mut::<Events<WindowResized>>();
resize_events.send(WindowResized {
world.send_event(WindowResized {
id: window_id,
width: new_logical_width as f32,
height: new_logical_height as f32,
Expand All @@ -549,35 +519,30 @@ pub fn winit_runner_with(mut app: App) {
}
WindowEvent::Focused(focused) => {
window.update_focused_status_from_backend(focused);
let mut focused_events = world.resource_mut::<Events<WindowFocused>>();
focused_events.send(WindowFocused {
world.send_event(WindowFocused {
id: window_id,
focused,
});
}
WindowEvent::DroppedFile(path_buf) => {
let mut events = world.resource_mut::<Events<FileDragAndDrop>>();
events.send(FileDragAndDrop::DroppedFile {
world.send_event(FileDragAndDrop::DroppedFile {
id: window_id,
path_buf,
});
}
WindowEvent::HoveredFile(path_buf) => {
let mut events = world.resource_mut::<Events<FileDragAndDrop>>();
events.send(FileDragAndDrop::HoveredFile {
world.send_event(FileDragAndDrop::HoveredFile {
id: window_id,
path_buf,
});
}
WindowEvent::HoveredFileCancelled => {
let mut events = world.resource_mut::<Events<FileDragAndDrop>>();
events.send(FileDragAndDrop::HoveredFileCancelled { id: window_id });
world.send_event(FileDragAndDrop::HoveredFileCancelled { id: window_id });
}
WindowEvent::Moved(position) => {
let position = ivec2(position.x, position.y);
window.update_actual_position_from_backend(position);
let mut events = world.resource_mut::<Events<WindowMoved>>();
events.send(WindowMoved {
world.send_event(WindowMoved {
id: window_id,
position,
});
Expand All @@ -589,8 +554,7 @@ pub fn winit_runner_with(mut app: App) {
event: DeviceEvent::MouseMotion { delta: (x, y) },
..
} => {
let mut mouse_motion_events = app.world.resource_mut::<Events<MouseMotion>>();
mouse_motion_events.send(MouseMotion {
app.world.send_event(MouseMotion {
delta: DVec2 { x, y }.as_vec2(),
});
}
Expand Down Expand Up @@ -681,9 +645,6 @@ fn handle_create_window_events(
let mut winit_windows = world.non_send_resource_mut::<WinitWindows>();
let mut windows = world.resource_mut::<Windows>();
let create_window_events = world.resource::<Events<CreateWindow>>();
let mut window_created_events = world.resource_mut::<Events<WindowCreated>>();
#[cfg(not(any(target_os = "windows", target_feature = "x11")))]
let mut window_resized_events = world.resource_mut::<Events<WindowResized>>();
for create_window_event in create_window_event_reader.iter(&create_window_events) {
let window = winit_windows.create_window(
event_loop,
Expand All @@ -694,13 +655,13 @@ fn handle_create_window_events(
// TODO: we aren't yet sure about native wayland, so we might be able to exclude it,
// but sending a duplicate event isn't problematic, as windows already does this.
#[cfg(not(any(target_os = "windows", target_feature = "x11")))]
window_resized_events.send(WindowResized {
world.send_event(WindowResized {
id: create_window_event.id,
width: window.width(),
height: window.height(),
});
windows.add(window);
window_created_events.send(WindowCreated {
world.send_event(WindowCreated {
id: create_window_event.id,
});

Expand Down

0 comments on commit e84dbda

Please sign in to comment.