Skip to content

Commit

Permalink
Taking events back out. Not baked enough to be worth the complexity. …
Browse files Browse the repository at this point in the history
…May revisit later.
  • Loading branch information
recatek committed Jan 14, 2025
1 parent ffbbc7d commit 54421b7
Show file tree
Hide file tree
Showing 7 changed files with 1 addition and 408 deletions.
8 changes: 1 addition & 7 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ keywords = ["ecs", "entity"]
categories = ["data-structures", "game-engines"]

[features]
default = ['events']
default = []

# Allow archetypes to have up to 32 components (default is 16). Worsens compile times.
32_components = []
Expand All @@ -20,12 +20,6 @@ default = ['events']
# creating/destroying entities, but has a (probabilistically insignificant) risk of allowing reuse of stale handles.
wrapping_version = []

# Adds event tracking for entity creation/destruction. Has the following perf consequences:
# - Adds some additional allocation overhead to the ECS system for each per-archetype queue.
# - Every entity creation or destruction pushes an event to an archetype's queue.
# - Event queues will accumulate indefinitely and must be regularly drained.
events = ['gecs_macros/events']

[dependencies]
gecs_macros = { version = "0.3.0", path = "macros", default-features = false }

Expand Down
75 changes: 0 additions & 75 deletions macros/src/generate/world.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ pub fn generate_world(world_data: &DataWorld, raw_input: &str) -> TokenStream {
.iter()
.map(|archetype| with_capacity_new(archetype))
.collect::<Vec<_>>();
let section_events = section_events_world(world_data);

// Documentation helpers
#[rustfmt::skip]
Expand Down Expand Up @@ -135,9 +134,6 @@ pub fn generate_world(world_data: &DataWorld, raw_input: &str) -> TokenStream {

type Capacities = #WorldCapacity;

// Will only appear if we have the events feature enabled.
#section_events

#[inline(always)]
fn new() -> Self {
Self {
Expand Down Expand Up @@ -611,9 +607,6 @@ fn section_archetype(archetype_data: &DataArchetype) -> TokenStream {
.map(|component| format_ident!("{}", to_snake(&component.name)))
.collect::<Vec<_>>();

// Generated subsections
let section_events = section_events_archetype();

// Documentation helpers
let archetype_doc_component_types = archetype_data
.components
Expand Down Expand Up @@ -652,9 +645,6 @@ fn section_archetype(archetype_data: &DataArchetype) -> TokenStream {
type IterArgs<'a> = #IterArgs;
type IterMutArgs<'a> = #IterMutArgs;

// Will only appear if we have the events feature enabled.
#section_events

#[inline(always)]
fn new() -> Self {
Self { data: #StorageN::new() }
Expand Down Expand Up @@ -1067,68 +1057,3 @@ fn with_capacity_new(archetype_data: &DataArchetype) -> TokenStream {
let archetype = format_ident!("{}", to_snake(&archetype_data.name));
quote!(with_capacity(capacity.#archetype))
}

#[allow(non_snake_case)]
fn section_events_world(world_data: &DataWorld) -> TokenStream {
if cfg!(feature = "events") {
let archetype_fields = world_data
.archetypes
.iter()
.rev() // Reverse the list because we'll chain inside-out
.map(|archetype| format_ident!("{}", to_snake(&archetype.name)))
.collect::<Vec<_>>();

// We throw a compile error if we don't have any archetypes, so we must have at least one.
let archetype = &archetype_fields[0];
let mut iter_body = quote!(self.#archetype.iter_events());
let mut drain_body = quote!(self.#archetype.drain_events());

// Keep nesting the chain operations
for archetype in archetype_fields[1..].iter() {
iter_body = quote!(self.#archetype.iter_events().chain(#iter_body));
drain_body = quote!(self.#archetype.drain_events().chain(#drain_body));
}

quote!(
#[inline(always)]
fn iter_events(&self) -> impl Iterator<Item = &EcsEvent> {
#iter_body
}

#[inline(always)]
fn drain_events(&mut self) -> impl Iterator<Item = EcsEvent> {
#drain_body
}

#[inline(always)]
fn clear_events(&mut self) {
#(self.#archetype_fields.clear_events();)*
}
)
} else {
quote!()
}
}

fn section_events_archetype() -> TokenStream {
if cfg!(feature = "events") {
quote!(
#[inline(always)]
fn iter_events(&self) -> impl Iterator<Item = &EcsEvent> {
self.data.iter_events()
}

#[inline(always)]
fn drain_events(&mut self) -> impl Iterator<Item = EcsEvent> {
self.data.drain_events()
}

#[inline(always)]
fn clear_events(&mut self) {
self.data.clear_events()
}
)
} else {
quote!()
}
}
41 changes: 0 additions & 41 deletions src/archetype/storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,6 @@ use crate::traits::{Archetype, EntityKey, StorageCanResolve};
use crate::util::{debug_checked_assume, num_assert_leq};
use crate::version::ArchetypeVersion;

#[cfg(feature = "events")]
use crate::event::EcsEvent;

macro_rules! declare_storage_dynamic_n {
(
$name:ident,
Expand All @@ -40,9 +37,6 @@ macro_rules! declare_storage_dynamic_n {
// No RefCell here since we never grant mutable access externally
entities: DataPtr<Entity<A>>,
#(d~I: RefCell<DataPtr<T~I>>,)*

#[cfg(feature = "events")]
events: Vec<EcsEvent>, // Optional queue tracking create/destroy events
}

impl<A: Archetype, #(T~I,)*> $name<A, #(T~I,)*>
Expand Down Expand Up @@ -74,9 +68,6 @@ macro_rules! declare_storage_dynamic_n {
slots,
entities: DataPtr::with_capacity(capacity),
#(d~I: RefCell::new(DataPtr::with_capacity(capacity)),)*

#[cfg(feature = "events")]
events: Vec::new(),
}
}

Expand Down Expand Up @@ -312,27 +303,6 @@ macro_rules! declare_storage_dynamic_n {
}
)*

/// Iterates over all of the entity create/destroy events for this storage.
#[cfg(feature = "events")]
#[inline(always)]
pub fn iter_events(&self) -> impl Iterator<Item = &EcsEvent> + '_ {
self.events.iter()
}

/// Drains the active event queue of its entity create/destroy events.
#[cfg(feature = "events")]
#[inline(always)]
pub fn drain_events(&mut self) -> impl Iterator<Item = EcsEvent> + '_ {
self.events.drain(..)
}

/// Clears the current event queue of all entity create/destroy events.
#[cfg(feature = "events")]
#[inline(always)]
pub fn clear_events(&mut self) {
self.events.clear()
}

/// Resolves the slot index and data index for a given entity.
/// Both indices are guaranteed to point to valid corresponding cells.
#[inline(always)]
Expand Down Expand Up @@ -519,11 +489,6 @@ macro_rules! declare_storage_dynamic_n {
self.entities.write(index, entity);
#(self.d~I.get_mut().write(index, data.I);)*

#[cfg(feature = "events")]
{
self.events.push(EcsEvent::Created(entity.into()));
}

entity
}
}
Expand Down Expand Up @@ -558,12 +523,6 @@ macro_rules! declare_storage_dynamic_n {
entities[dense_index_usize].version(),
self.slots.slice(self.capacity())[slot_index_usize].version());

#[cfg(feature = "events")]
{
let entity = *entities.get_unchecked(dense_index_usize);
self.events.push(EcsEvent::Destroyed(entity.into()));
}

// SAFETY: We know self.len > 0 because we got Some from resolve_slot.
let last_dense_index = self.len - 1;
// SAFETY: We know the entity slice has a length of self.len.
Expand Down
14 changes: 0 additions & 14 deletions src/event.rs

This file was deleted.

10 changes: 0 additions & 10 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,6 @@ pub mod version;
/// Enums for controlling iteration stepping.
pub mod iter;

/// Events for reporting entity creation and destruction.
#[cfg(feature = "events")]
pub mod event;

mod macros {
/// Macro for declaring a new ECS world struct with archetype storage.
///
Expand Down Expand Up @@ -870,9 +866,6 @@ pub mod prelude {
pub use traits::{Archetype, ArchetypeHas};
pub use traits::{View, ViewHas};
pub use traits::{Borrow, BorrowHas};

#[cfg(feature = "events")]
pub use event::EcsEvent;
}

#[doc(hidden)]
Expand Down Expand Up @@ -908,7 +901,4 @@ pub mod __internal {
pub use traits::{Archetype, ArchetypeHas};
pub use traits::{View, ViewHas};
pub use traits::{Borrow, BorrowHas};

#[cfg(feature = "events")]
pub use event::EcsEvent;
}
Loading

0 comments on commit 54421b7

Please sign in to comment.