Skip to content

Commit 161876a

Browse files
Nearly-working impl of EventWriter<T> components
Had to change EventWriter and Reader to take vanilla refs, rather than Res smart pointers to accommodate mixed resource and component usage. Lifetimes are still sad.
1 parent 52dd58e commit 161876a

File tree

2 files changed

+100
-26
lines changed

2 files changed

+100
-26
lines changed

crates/bevy_ecs/src/event.rs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
use crate as bevy_ecs;
21
use crate::{
32
component::Component,
4-
system::{Local, Query, Res, ResMut, SystemParam},
3+
system::{Local, Query, ResMut, ResMutState, ResState, SystemParam},
54
};
65
use bevy_utils::tracing::trace;
76
use std::{
@@ -150,16 +149,22 @@ fn map_instance_event<T>(event_instance: &EventInstance<T>) -> &T {
150149
}
151150

152151
/// Reads events of type `T` in order and tracks which events have already been read.
153-
#[derive(SystemParam)]
154152
pub struct EventReader<'a, T: Component> {
155153
last_event_count: Local<'a, (usize, PhantomData<T>)>,
156-
events: Res<'a, Events<T>>,
154+
events: &'a Events<T>,
155+
}
156+
157+
impl<'a, T: Component> SystemParam for EventReader<'a, T> {
158+
type Fetch = ResState<Events<T>>;
157159
}
158160

159161
/// Sends events of type `T`.
160-
#[derive(SystemParam)]
161162
pub struct EventWriter<'a, T: Component> {
162-
events: ResMut<'a, Events<T>>,
163+
events: &'a mut Events<T>,
164+
}
165+
166+
impl<'a, T: Component> SystemParam for EventWriter<'a, T> {
167+
type Fetch = ResMutState<Events<T>>;
163168
}
164169

165170
impl<'a, T: Component> EventWriter<'a, T> {

crates/bevy_ecs/src/query/event.rs

Lines changed: 89 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,71 +1,140 @@
11
use super::{
2-
super::event::{EventReader, EventWriter, Events, ManualEventReader},
3-
Access, Fetch, FetchState, FilteredAccess, WorldQuery,
2+
super::event::{EventWriter, Events},
3+
Access, Fetch, FetchState, FilteredAccess, WorldQuery, WriteFetch, WriteState,
44
};
55
use crate::{
66
archetype::{Archetype, ArchetypeComponentId},
7-
component::{Component, ComponentId},
7+
component::{Component, ComponentId, StorageType},
88
prelude::World,
99
storage::{Table, Tables},
1010
};
11-
use std::marker::PhantomData;
11+
use std::any::TypeId;
1212

1313
impl<'a, T: Component> WorldQuery for EventWriter<'a, T> {
14-
type Fetch = EventWriterFetch<T>;
14+
type Fetch = EventWriterFetch<'a, T>;
1515
type State = EventWriterState<T>;
1616
}
1717

18-
struct EventWriterFetch<T> {
19-
marker: PhantomData<T>,
18+
struct EventWriterFetch<'s, T> {
19+
/// EventWriter query parameters require write access to &mut Events<T>
20+
write_fetch: WriteFetch<Events<T>>,
21+
state: &'s EventWriterState<T>,
2022
}
2123

22-
impl<'a, T: Component> Fetch<'a> for EventWriterFetch<T> {
23-
// EventWriter queries return an EventWriter<T> in each item
24+
impl<'a, T: Component> Fetch<'a> for EventWriterFetch<'a, T> {
25+
/// EventWriter queries return an EventWriter<T> in each item
2426
type Item = EventWriter<'a, T>;
25-
// This is the corresponding S: FetchState type
27+
/// This is the corresponding S: FetchState type
2628
type State = EventWriterState<T>;
2729

30+
/// Checks the storage type of the corresponding Events<T> component
31+
fn is_dense(&self) -> bool {
32+
match self.state.event_storage_type {
33+
StorageType::SparseSet => false,
34+
StorageType::Table => true,
35+
}
36+
}
37+
2838
unsafe fn init(
2939
world: &World,
3040
state: &Self::State,
3141
last_change_tick: u32,
3242
change_tick: u32,
3343
) -> Self {
44+
EventWriterFetch {
45+
write_fetch: WriteFetch::<Events<T>>::init(
46+
world,
47+
&state.write_state,
48+
last_change_tick,
49+
change_tick,
50+
),
51+
state,
52+
}
3453
}
3554

36-
fn is_dense(&self) -> bool {}
37-
3855
unsafe fn set_archetype(
3956
&mut self,
4057
state: &Self::State,
4158
archetype: &Archetype,
4259
tables: &Tables,
4360
) {
61+
self.write_fetch
62+
.set_archetype(&state.write_state, archetype, tables);
4463
}
4564

46-
unsafe fn set_table(&mut self, state: &Self::State, table: &Table) {}
65+
unsafe fn set_table(&mut self, state: &Self::State, table: &Table) {
66+
self.write_fetch.set_table(&state.write_state, table);
67+
}
4768

48-
unsafe fn archetype_fetch(&mut self, archetype_index: usize) -> Self::Item {}
69+
/// Returns the EventWriter<T> of the next entity when the storage type of the query is sparse
70+
unsafe fn archetype_fetch(&mut self, archetype_index: usize) -> Self::Item {
71+
let events = *self.write_fetch.archetype_fetch(archetype_index);
72+
EventWriter {
73+
events: &mut events,
74+
}
75+
}
4976

50-
unsafe fn table_fetch(&mut self, table_row: usize) -> Self::Item {}
77+
/// Returns the EventWriter<T> of the next entity when the storage type of the query is dense
78+
unsafe fn table_fetch(&mut self, table_row: usize) -> Self::Item {
79+
let events = *self.write_fetch.archetype_fetch(table_row);
80+
EventWriter {
81+
events: &mut events,
82+
}
83+
}
5184
}
5285
struct EventWriterState<T> {
53-
marker: PhantomData<T>,
86+
event_component_id: ComponentId,
87+
event_storage_type: StorageType,
88+
/// EventWriter query parameters require write access to &mut Events<T>
89+
write_state: WriteState<Events<T>>,
5490
}
5591

5692
unsafe impl<T: Component> FetchState for EventWriterState<T> {
57-
fn init(world: &mut World) -> Self {}
93+
fn init(world: &mut World) -> Self {
94+
let event_component_id = world.components.get_id(TypeId::of::<Events<T>>()).unwrap();
95+
EventWriterState {
96+
event_component_id,
97+
event_storage_type: world
98+
.components
99+
.get_info(event_component_id)
100+
.unwrap()
101+
.storage_type(),
102+
write_state: WriteState::<Events<T>>::init(world),
103+
}
104+
}
58105

59-
fn update_component_access(&self, access: &mut FilteredAccess<ComponentId>) {}
106+
/// Access is based on &Events<T>
107+
fn update_component_access(&self, access: &mut FilteredAccess<ComponentId>) {
108+
if access.access().has_write(self.event_component_id) {
109+
panic!("&{} conflicts with a previous access in this query. Shared access cannot coincide with exclusive access.",
110+
std::any::type_name::<Events<T>>());
111+
}
112+
access.add_read(self.event_component_id)
113+
}
60114

115+
/// Access is based on &Events<T>
61116
fn update_archetype_component_access(
62117
&self,
63118
archetype: &Archetype,
64119
access: &mut Access<ArchetypeComponentId>,
65120
) {
121+
if let Some(archetype_component_id) =
122+
archetype.get_archetype_component_id(self.event_component_id)
123+
{
124+
access.add_read(archetype_component_id);
125+
}
66126
}
67127

68-
fn matches_archetype(&self, archetype: &Archetype) -> bool {}
128+
/// Matches based on &Events<T>
129+
fn matches_archetype(&self, archetype: &Archetype) -> bool {
130+
archetype.contains(self.event_component_id)
131+
}
69132

70-
fn matches_table(&self, table: &Table) -> bool {}
133+
/// Matches based on &Events<T>
134+
fn matches_table(&self, table: &Table) -> bool {
135+
table.has_column(self.event_component_id)
136+
}
71137
}
138+
139+
// TODO: add tests
140+
mod tests {}

0 commit comments

Comments
 (0)