Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Merged by Bors] - add len, is_empty, iter method on SparseSets, make SparseSets inspect… #7638

Closed
wants to merge 9 commits into from
6 changes: 6 additions & 0 deletions crates/bevy_ecs/src/component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,12 @@ impl ComponentInfo {
fn new(id: ComponentId, descriptor: ComponentDescriptor) -> Self {
ComponentInfo { id, descriptor }
}

/// Create a new [`ComponentInfo`] for use in tests.
#[cfg(test)]
pub(crate) fn new_for_test(id: ComponentId, descriptor: ComponentDescriptor) -> Self {
Self::new(id, descriptor)
}
}

/// A semi-opaque value which uniquely identifies the type of a [`Component`] within a
Expand Down
67 changes: 65 additions & 2 deletions crates/bevy_ecs/src/storage/sparse_set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,18 @@ pub struct SparseSets {
}

impl SparseSets {
/// Returns the number of [`SparseSet`]s this collection contains.
#[inline]
pub fn len(&self) -> usize {
self.sets.len()
}

/// Returns true if this collection contains no [`SparseSet`]s.
#[inline]
pub fn is_empty(&self) -> bool {
self.sets.is_empty()
}

pub fn get_or_insert(&mut self, component_info: &ComponentInfo) -> &mut ComponentSparseSet {
if !self.sets.contains(component_info.id()) {
self.sets.insert(
Expand All @@ -516,7 +528,8 @@ impl SparseSets {
self.sets.get_mut(component_id)
}

pub fn clear(&mut self) {
/// Clear entities stored in each [`SparseSet`]
pub fn clear_entities(&mut self) {
for set in self.sets.values_mut() {
set.clear();
}
Expand All @@ -527,11 +540,23 @@ impl SparseSets {
set.check_change_ticks(change_tick);
}
}

/// An Iterator visiting all ([`ComponentId`], [`SparseSet`]) pairs.
/// NOTE: Order is not guaranteed.
pub fn iter(&self) -> impl Iterator<Item = (ComponentId, &ComponentSparseSet)> {
self.sets.iter().map(|(id, data)| (*id, data))
}
}

#[cfg(test)]
mod tests {
use crate::{entity::Entity, storage::SparseSet};
use super::SparseSets;
use crate::{
self as bevy_ecs,
component::{Component, ComponentDescriptor, ComponentId, ComponentInfo},
entity::Entity,
storage::SparseSet,
};

#[derive(Debug, Eq, PartialEq)]
struct Foo(usize);
Expand Down Expand Up @@ -584,4 +609,42 @@ mod tests {
*set.get_mut(e1).unwrap() = Foo(11);
assert_eq!(set.get(e1), Some(&Foo(11)));
}

#[test]
fn sparse_sets() {
let mut sets = SparseSets::default();

#[derive(Component, Default, Debug)]
struct TestComponent1;

#[derive(Component, Default, Debug)]
struct TestComponent2;

assert_eq!(sets.len(), 0);
assert!(sets.is_empty());

init_component::<TestComponent1>(&mut sets, 1);
assert_eq!(sets.len(), 1);

init_component::<TestComponent2>(&mut sets, 2);
assert_eq!(sets.len(), 2);

// check its shape by iter
let mut collected_sets = sets
.iter()
.map(|(id, set)| (id, set.len()))
.collect::<Vec<_>>();
collected_sets.sort();
assert_eq!(
collected_sets,
vec![(ComponentId::new(1), 0), (ComponentId::new(2), 0),]
);

fn init_component<T: Component>(sets: &mut SparseSets, id: usize) {
let descriptor = ComponentDescriptor::new::<TestComponent1>();
let id = ComponentId::new(id);
let info = ComponentInfo::new_for_test(id, descriptor);
sets.get_or_insert(&info);
}
}
}
2 changes: 2 additions & 0 deletions crates/bevy_ecs/src/storage/table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -654,11 +654,13 @@ pub(crate) struct TableMoveResult {
}

impl Tables {
/// Returns the number of [`Table`]s this collection contains
#[inline]
pub fn len(&self) -> usize {
self.tables.len()
}

/// Returns true if this collection contains no [`Table`]s
#[inline]
pub fn is_empty(&self) -> bool {
self.tables.is_empty()
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_ecs/src/world/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1538,7 +1538,7 @@ impl World {
/// Despawns all entities in this [`World`].
pub fn clear_entities(&mut self) {
self.storages.tables.clear();
self.storages.sparse_sets.clear();
self.storages.sparse_sets.clear_entities();
self.archetypes.clear_entities();
self.entities.clear();
}
Expand Down