Struct bevy::ecs::event::EventReader
source · pub struct EventReader<'w, 's, E>where
E: Event,{ /* private fields */ }
Expand description
Reads events of type T
in order and tracks which events have already been read.
§Concurrency
Unlike EventWriter<T>
, systems with EventReader<T>
param can be executed concurrently
(but not concurrently with EventWriter<T>
systems for the same event type).
Implementations§
source§impl<'w, 's, E> EventReader<'w, 's, E>where
E: Event,
impl<'w, 's, E> EventReader<'w, 's, E>where
E: Event,
sourcepub fn read(&mut self) -> EventIterator<'_, E> ⓘ
pub fn read(&mut self) -> EventIterator<'_, E> ⓘ
Iterates over the events this EventReader
has not seen yet. This updates the
EventReader
’s event counter, which means subsequent event reads will not include events
that happened before now.
Examples found in repository?
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
fn read_and_write_different_event_types(mut a: EventWriter<A>, mut b: EventReader<B>) {
for _ in b.read() {}
a.send(A);
}
/// A dummy event type.
#[derive(Debug, Clone, Event)]
struct DebugEvent {
resend_from_param_set: bool,
resend_from_local_event_reader: bool,
times_sent: u8,
}
/// A system that sends all combinations of events.
fn send_events(mut events: EventWriter<DebugEvent>, frame_count: Res<FrameCount>) {
println!("Sending events for frame {:?}", frame_count.0);
events.send(DebugEvent {
resend_from_param_set: false,
resend_from_local_event_reader: false,
times_sent: 1,
});
events.send(DebugEvent {
resend_from_param_set: true,
resend_from_local_event_reader: false,
times_sent: 1,
});
events.send(DebugEvent {
resend_from_param_set: false,
resend_from_local_event_reader: true,
times_sent: 1,
});
events.send(DebugEvent {
resend_from_param_set: true,
resend_from_local_event_reader: true,
times_sent: 1,
});
}
/// A system that prints all events sent since the last time this system ran.
///
/// Note that some events will be printed twice, because they were sent twice.
fn debug_events(mut events: EventReader<DebugEvent>) {
for event in events.read() {
println!("{:?}", event);
}
}
/// A system that both sends and receives events using [`ParamSet`].
fn send_and_receive_param_set(
mut param_set: ParamSet<(EventReader<DebugEvent>, EventWriter<DebugEvent>)>,
frame_count: Res<FrameCount>,
) {
println!(
"Sending and receiving events for frame {} with a `ParamSet`",
frame_count.0
);
// We must collect the events to resend, because we can't access the writer while we're iterating over the reader.
let mut events_to_resend = Vec::new();
// This is p0, as the first parameter in the `ParamSet` is the reader.
for event in param_set.p0().read() {
if event.resend_from_param_set {
events_to_resend.push(event.clone());
}
}
// This is p1, as the second parameter in the `ParamSet` is the writer.
for mut event in events_to_resend {
event.times_sent += 1;
param_set.p1().send(event);
}
}
More examples
- examples/ecs/state.rs
- examples/window/window_resizing.rs
- examples/2d/pixel_grid_snap.rs
- examples/2d/texture_atlas.rs
- examples/audio/pitch.rs
- examples/async_tasks/external_source_external_thread.rs
- examples/3d/tonemapping.rs
- examples/ui/ui.rs
- examples/input/mouse_input_events.rs
- examples/input/text_input.rs
- examples/3d/split_screen.rs
- examples/input/gamepad_input_events.rs
- examples/ui/size_constraints.rs
- examples/3d/../helpers/camera_controller.rs
sourcepub fn read_with_id(&mut self) -> EventIteratorWithId<'_, E> ⓘ
pub fn read_with_id(&mut self) -> EventIteratorWithId<'_, E> ⓘ
sourcepub fn len(&self) -> usize
pub fn len(&self) -> usize
Determines the number of events available to be read from this EventReader
without consuming any.
sourcepub fn is_empty(&self) -> bool
pub fn is_empty(&self) -> bool
Returns true
if there are no events available to read.
§Example
The following example shows a useful pattern where some behavior is triggered if new events are available.
EventReader::clear()
is used so the same events don’t re-trigger the behavior the next time the system runs.
#[derive(Event)]
struct CollisionEvent;
fn play_collision_sound(mut events: EventReader<CollisionEvent>) {
if !events.is_empty() {
events.clear();
// Play a sound
}
}
Examples found in repository?
413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428
fn play_collision_sound(
mut commands: Commands,
mut collision_events: EventReader<CollisionEvent>,
sound: Res<CollisionSound>,
) {
// Play a sound once per frame if a collision occurred.
if !collision_events.is_empty() {
// This prevents events staying active on the next frame.
collision_events.clear();
commands.spawn(AudioBundle {
source: sound.0.clone(),
// auto-despawn the entity when playback finishes
settings: PlaybackSettings::DESPAWN,
});
}
}
sourcepub fn clear(&mut self)
pub fn clear(&mut self)
Consumes all available events.
This means these events will not appear in calls to EventReader::read()
or
EventReader::read_with_id()
and EventReader::is_empty()
will return true
.
For usage, see EventReader::is_empty()
.
Examples found in repository?
413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428
fn play_collision_sound(
mut commands: Commands,
mut collision_events: EventReader<CollisionEvent>,
sound: Res<CollisionSound>,
) {
// Play a sound once per frame if a collision occurred.
if !collision_events.is_empty() {
// This prevents events staying active on the next frame.
collision_events.clear();
commands.spawn(AudioBundle {
source: sound.0.clone(),
// auto-despawn the entity when playback finishes
settings: PlaybackSettings::DESPAWN,
});
}
}
More examples
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219
fn run_camera_controller(
time: Res<Time>,
mut windows: Query<&mut Window>,
mut mouse_events: EventReader<MouseMotion>,
mouse_button_input: Res<ButtonInput<MouseButton>>,
key_input: Res<ButtonInput<KeyCode>>,
mut toggle_cursor_grab: Local<bool>,
mut mouse_cursor_grab: Local<bool>,
mut query: Query<(&mut Transform, &mut CameraController), With<Camera>>,
) {
let dt = time.delta_seconds();
if let Ok((mut transform, mut controller)) = query.get_single_mut() {
if !controller.initialized {
let (yaw, pitch, _roll) = transform.rotation.to_euler(EulerRot::YXZ);
controller.yaw = yaw;
controller.pitch = pitch;
controller.initialized = true;
info!("{}", *controller);
}
if !controller.enabled {
mouse_events.clear();
return;
}
// Handle key input
let mut axis_input = Vec3::ZERO;
if key_input.pressed(controller.key_forward) {
axis_input.z += 1.0;
}
if key_input.pressed(controller.key_back) {
axis_input.z -= 1.0;
}
if key_input.pressed(controller.key_right) {
axis_input.x += 1.0;
}
if key_input.pressed(controller.key_left) {
axis_input.x -= 1.0;
}
if key_input.pressed(controller.key_up) {
axis_input.y += 1.0;
}
if key_input.pressed(controller.key_down) {
axis_input.y -= 1.0;
}
let mut cursor_grab_change = false;
if key_input.just_pressed(controller.keyboard_key_toggle_cursor_grab) {
*toggle_cursor_grab = !*toggle_cursor_grab;
cursor_grab_change = true;
}
if mouse_button_input.just_pressed(controller.mouse_key_cursor_grab) {
*mouse_cursor_grab = true;
cursor_grab_change = true;
}
if mouse_button_input.just_released(controller.mouse_key_cursor_grab) {
*mouse_cursor_grab = false;
cursor_grab_change = true;
}
let cursor_grab = *mouse_cursor_grab || *toggle_cursor_grab;
// Apply movement update
if axis_input != Vec3::ZERO {
let max_speed = if key_input.pressed(controller.key_run) {
controller.run_speed
} else {
controller.walk_speed
};
controller.velocity = axis_input.normalize() * max_speed;
} else {
let friction = controller.friction.clamp(0.0, 1.0);
controller.velocity *= 1.0 - friction;
if controller.velocity.length_squared() < 1e-6 {
controller.velocity = Vec3::ZERO;
}
}
let forward = *transform.forward();
let right = *transform.right();
transform.translation += controller.velocity.x * dt * right
+ controller.velocity.y * dt * Vec3::Y
+ controller.velocity.z * dt * forward;
// Handle cursor grab
if cursor_grab_change {
if cursor_grab {
for mut window in &mut windows {
if !window.focused {
continue;
}
window.cursor.grab_mode = CursorGrabMode::Locked;
window.cursor.visible = false;
}
} else {
for mut window in &mut windows {
window.cursor.grab_mode = CursorGrabMode::None;
window.cursor.visible = true;
}
}
}
// Handle mouse input
let mut mouse_delta = Vec2::ZERO;
if cursor_grab {
for mouse_event in mouse_events.read() {
mouse_delta += mouse_event.delta;
}
} else {
mouse_events.clear();
}
if mouse_delta != Vec2::ZERO {
// Apply look update
controller.pitch = (controller.pitch
- mouse_delta.y * RADIANS_PER_DOT * controller.sensitivity)
.clamp(-PI / 2., PI / 2.);
controller.yaw -= mouse_delta.x * RADIANS_PER_DOT * controller.sensitivity;
transform.rotation =
Quat::from_euler(EulerRot::ZYX, 0.0, controller.yaw, controller.pitch);
}
}
}
Trait Implementations§
source§impl<'w, 's, E> Debug for EventReader<'w, 's, E>
impl<'w, 's, E> Debug for EventReader<'w, 's, E>
source§impl<E> SystemParam for EventReader<'_, '_, E>where
E: Event,
impl<E> SystemParam for EventReader<'_, '_, E>where
E: Event,
§type Item<'w, 's> = EventReader<'w, 's, E>
type Item<'w, 's> = EventReader<'w, 's, E>
Self
, instantiated with new lifetimes. Read moresource§fn init_state(
world: &mut World,
system_meta: &mut SystemMeta
) -> <EventReader<'_, '_, E> as SystemParam>::State
fn init_state( world: &mut World, system_meta: &mut SystemMeta ) -> <EventReader<'_, '_, E> as SystemParam>::State
World
access used by this SystemParam
and creates a new instance of this param’s State
.source§fn new_archetype(
state: &mut <EventReader<'_, '_, E> as SystemParam>::State,
archetype: &Archetype,
system_meta: &mut SystemMeta
)
fn new_archetype( state: &mut <EventReader<'_, '_, E> as SystemParam>::State, archetype: &Archetype, system_meta: &mut SystemMeta )
Archetype
, registers the components accessed by this SystemParam
(if applicable).source§fn apply(
state: &mut <EventReader<'_, '_, E> as SystemParam>::State,
system_meta: &SystemMeta,
world: &mut World
)
fn apply( state: &mut <EventReader<'_, '_, E> as SystemParam>::State, system_meta: &SystemMeta, world: &mut World )
SystemParam
’s state.
This is used to apply Commands
during apply_deferred
.source§unsafe fn get_param<'w, 's>(
state: &'s mut <EventReader<'_, '_, E> as SystemParam>::State,
system_meta: &SystemMeta,
world: UnsafeWorldCell<'w>,
change_tick: Tick
) -> <EventReader<'_, '_, E> as SystemParam>::Item<'w, 's>
unsafe fn get_param<'w, 's>( state: &'s mut <EventReader<'_, '_, E> as SystemParam>::State, system_meta: &SystemMeta, world: UnsafeWorldCell<'w>, change_tick: Tick ) -> <EventReader<'_, '_, E> as SystemParam>::Item<'w, 's>
SystemParamFunction
. Read moreimpl<'w, 's, E> ReadOnlySystemParam for EventReader<'w, 's, E>where
E: Event,
Local<'s, ManualEventReader<E>>: ReadOnlySystemParam,
Res<'w, Events<E>>: ReadOnlySystemParam,
Auto Trait Implementations§
impl<'w, 's, E> Freeze for EventReader<'w, 's, E>
impl<'w, 's, E> RefUnwindSafe for EventReader<'w, 's, E>
impl<'w, 's, E> Send for EventReader<'w, 's, E>
impl<'w, 's, E> Sync for EventReader<'w, 's, E>
impl<'w, 's, E> Unpin for EventReader<'w, 's, E>
impl<'w, 's, E> !UnwindSafe for EventReader<'w, 's, E>
Blanket Implementations§
source§impl<T, U> AsBindGroupShaderType<U> for T
impl<T, U> AsBindGroupShaderType<U> for T
source§fn as_bind_group_shader_type(&self, _images: &RenderAssets<Image>) -> U
fn as_bind_group_shader_type(&self, _images: &RenderAssets<Image>) -> U
T
ShaderType
for self
. When used in AsBindGroup
derives, it is safe to assume that all images in self
exist.source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait>
(where Trait: Downcast
) to Box<dyn Any>
. Box<dyn Any>
can
then be further downcast
into Box<ConcreteType>
where ConcreteType
implements Trait
.source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait>
(where Trait: Downcast
) to Rc<Any>
. Rc<Any>
can then be
further downcast
into Rc<ConcreteType>
where ConcreteType
implements Trait
.source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &Any
’s vtable from &Trait
’s.source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &mut Any
’s vtable from &mut Trait
’s.