summaryrefslogtreecommitdiff
path: root/ecs/src
diff options
context:
space:
mode:
Diffstat (limited to 'ecs/src')
-rw-r--r--ecs/src/actions.rs8
-rw-r--r--ecs/src/component.rs8
-rw-r--r--ecs/src/component/storage.rs53
-rw-r--r--ecs/src/component/storage/archetype.rs23
-rw-r--r--ecs/src/entity.rs20
-rw-r--r--ecs/src/lib.rs169
-rw-r--r--ecs/src/pair.rs29
-rw-r--r--ecs/src/query.rs11
-rw-r--r--ecs/src/query/flexible.rs31
-rw-r--r--ecs/src/uid.rs13
-rw-r--r--ecs/src/util.rs2
-rw-r--r--ecs/src/util/array_vec.rs24
12 files changed, 185 insertions, 206 deletions
diff --git a/ecs/src/actions.rs b/ecs/src/actions.rs
index f366b4c..e0efeda 100644
--- a/ecs/src/actions.rs
+++ b/ecs/src/actions.rs
@@ -1,5 +1,5 @@
use std::marker::PhantomData;
-use std::sync::{Arc, Weak};
+use std::rc::{Rc, Weak};
use crate::component::{Parts as ComponentParts, Sequence as ComponentSequence};
use crate::system::{Param as SystemParam, System};
@@ -87,11 +87,11 @@ impl<'world> Actions<'world>
}
}
- fn new(action_queue: &'world Arc<ActionQueue>) -> Self
+ fn new(action_queue: &'world Rc<ActionQueue>) -> Self
{
Self {
action_queue,
- action_queue_weak: Arc::downgrade(action_queue),
+ action_queue_weak: Rc::downgrade(action_queue),
}
}
}
@@ -142,7 +142,7 @@ impl WeakRef
#[derive(Debug, Clone)]
pub struct Ref<'weak_ref>
{
- action_queue: Arc<ActionQueue>,
+ action_queue: Rc<ActionQueue>,
_pd: PhantomData<&'weak_ref ()>,
}
diff --git a/ecs/src/component.rs b/ecs/src/component.rs
index de4384b..a0ed752 100644
--- a/ecs/src/component.rs
+++ b/ecs/src/component.rs
@@ -99,6 +99,9 @@ pub trait HandleFromEntityComponentRef<'comp>: Sized
type Error: Error;
/// Creates a new handle instance from a [`EntityComponentRef`].
+ ///
+ /// # Errors
+ /// See the implementation's [`Self::Error`] type.
fn from_entity_component_ref(
entity_component_ref: Option<EntityComponentRef<'comp>>,
world: &'comp World,
@@ -306,16 +309,19 @@ pub struct Parts
impl Parts
{
+ #[must_use]
pub fn id(&self) -> Uid
{
self.id
}
+ #[must_use]
pub fn name(&self) -> &'static str
{
self.name
}
+ #[must_use]
pub fn builder() -> PartsBuilder
{
PartsBuilder::default()
@@ -335,12 +341,14 @@ pub struct PartsBuilder
impl PartsBuilder
{
+ #[must_use]
pub fn name(mut self, name: &'static str) -> Self
{
self.name = name;
self
}
+ #[must_use]
pub fn build<Data: 'static>(self, id: Uid, data: Data) -> Parts
{
Parts {
diff --git a/ecs/src/component/storage.rs b/ecs/src/component/storage.rs
index 14f3ea4..f5cce57 100644
--- a/ecs/src/component/storage.rs
+++ b/ecs/src/component/storage.rs
@@ -216,38 +216,35 @@ impl Storage
});
}
- let add_edge_archetype_id = match archetype_node
+ let add_edge_archetype_id = if let Some(add_edge_id) = archetype_node
.get_or_insert_edges(component_id, ArchetypeEdges::default)
.add
{
- Some(add_edge_id) => {
- if !self.graph.contains_archetype(add_edge_id) {
- let (_, add_edge_comp_ids) = self
- .graph
- .get_node_by_id(archetype_id)
- .expect("Archetype should exist")
- .make_add_edge(component_id);
-
- self.graph.create_node(add_edge_id, &add_edge_comp_ids);
- }
-
- add_edge_id
- }
- None => {
- let archetype_node = self
+ if !self.graph.contains_archetype(add_edge_id) {
+ let (_, add_edge_comp_ids) = self
.graph
.get_node_by_id(archetype_id)
- .expect("Archetype should exist");
+ .expect("Archetype should exist")
+ .make_add_edge(component_id);
- let (add_edge_id, add_edge_comp_ids) =
- archetype_node.make_add_edge(component_id);
+ self.graph.create_node(add_edge_id, &add_edge_comp_ids);
+ }
- if !self.graph.contains_archetype(add_edge_id) {
- self.graph.create_node(add_edge_id, &add_edge_comp_ids);
- }
+ add_edge_id
+ } else {
+ let archetype_node = self
+ .graph
+ .get_node_by_id(archetype_id)
+ .expect("Archetype should exist");
- add_edge_id
+ let (add_edge_id, add_edge_comp_ids) =
+ archetype_node.make_add_edge(component_id);
+
+ if !self.graph.contains_archetype(add_edge_id) {
+ self.graph.create_node(add_edge_id, &add_edge_comp_ids);
}
+
+ add_edge_id
};
let archetype_node = self
@@ -592,8 +589,7 @@ pub struct ArchetypeRefIter<'storage, 'search_terms>
search_terms: ArchetypeSearchTerms<'search_terms>,
}
-impl<'component_storage, 'search_terms> Iterator
- for ArchetypeRefIter<'component_storage, 'search_terms>
+impl<'component_storage> Iterator for ArchetypeRefIter<'component_storage, '_>
{
type Item = &'component_storage Archetype;
@@ -646,10 +642,7 @@ impl<'component_storage, 'search_terms> Iterator
self.storage.imaginary_archetypes.borrow_mut().push(
ImaginaryArchetype {
id: add_edge_archetype_id,
- component_ids: add_edge_archetype_comps
- .iter()
- .map(|comp_id| *comp_id)
- .collect::<Vec<_>>(),
+ component_ids: add_edge_archetype_comps.clone(),
},
);
@@ -663,8 +656,6 @@ impl<'component_storage, 'search_terms> Iterator
)),
found.into_iter(),
));
-
- continue;
}
_ => {
unreachable!();
diff --git a/ecs/src/component/storage/archetype.rs b/ecs/src/component/storage/archetype.rs
index f8c204b..56dd5ae 100644
--- a/ecs/src/component/storage/archetype.rs
+++ b/ecs/src/component/storage/archetype.rs
@@ -155,7 +155,7 @@ impl Archetype
inner: Either::B(
[component_id]
.into_iter()
- .zip(self.get_index_for_component(component_id).into_iter()),
+ .zip(self.get_index_for_component(component_id)),
),
}
}
@@ -219,19 +219,20 @@ type MatchingComponentIterFilterFn = fn(&((usize, &Uid), Uid)) -> bool;
type MatchingComponentIterMapFn = fn(((usize, &Uid), Uid)) -> (Uid, usize);
+type InnerMatchingComponentIterA<'archetype> = Map<
+ Filter<
+ Zip<Enumerate<SliceIter<'archetype, Uid>>, RepeatN<Uid>>,
+ MatchingComponentIterFilterFn,
+ >,
+ MatchingComponentIterMapFn,
+>;
+
+type InnerMatchingComponentIterB = Zip<ArrayIntoIter<Uid, 1>, OptionIntoIter<usize>>;
+
#[derive(Debug)]
pub struct MatchingComponentIter<'archetype>
{
- inner: Either<
- Map<
- Filter<
- Zip<Enumerate<SliceIter<'archetype, Uid>>, RepeatN<Uid>>,
- MatchingComponentIterFilterFn,
- >,
- MatchingComponentIterMapFn,
- >,
- Zip<ArrayIntoIter<Uid, 1>, OptionIntoIter<usize>>,
- >,
+ inner: Either<InnerMatchingComponentIterA<'archetype>, InnerMatchingComponentIterB>,
}
impl Iterator for MatchingComponentIter<'_>
diff --git a/ecs/src/entity.rs b/ecs/src/entity.rs
index 3f5a3d3..562f7ea 100644
--- a/ecs/src/entity.rs
+++ b/ecs/src/entity.rs
@@ -35,6 +35,14 @@ impl<'a> Handle<'a>
self.entity.uid()
}
+ /// Returns a reference to the specified component in this entity. `None` is
+ /// returned if the component isn't found in the entity.
+ ///
+ /// # Panics
+ /// Will panic if:
+ /// - The component's ID is not a component ID
+ /// - The component is mutably borrowed elsewhere
+ #[must_use]
pub fn get<ComponentT: Component>(&self) -> Option<ComponentHandle<'_, ComponentT>>
{
assert_eq!(ComponentT::id().kind(), UidKind::Component);
@@ -52,6 +60,14 @@ impl<'a> Handle<'a>
)
}
+ /// Returns a mutable reference to the specified component in this entity. `None` is
+ /// returned if the component isn't found in the entity.
+ ///
+ /// # Panics
+ /// Will panic if:
+ /// - The component's ID is not a component ID
+ /// - The component is borrowed elsewhere
+ #[must_use]
pub fn get_mut<ComponentT: Component>(
&self,
) -> Option<ComponentHandleMut<'_, ComponentT>>
@@ -131,7 +147,7 @@ macro_rules! static_entity {
$crate::entity::CREATE_STATIC_ENTITIES
)]
#[linkme(crate=$crate::private::linkme)]
- static CREATE_STATIC_ENTITY: fn(&$crate::World) = |world| {
+ static CREATE_STATIC_ENTITY: fn(&mut $crate::World) = |world| {
world.create_entity_with_uid($components, *$ident);
};
}
@@ -141,4 +157,4 @@ macro_rules! static_entity {
#[distributed_slice]
#[doc(hidden)]
-pub static CREATE_STATIC_ENTITIES: [fn(&World)];
+pub static CREATE_STATIC_ENTITIES: [fn(&mut World)];
diff --git a/ecs/src/lib.rs b/ecs/src/lib.rs
index dd43e0b..c953290 100644
--- a/ecs/src/lib.rs
+++ b/ecs/src/lib.rs
@@ -4,6 +4,7 @@ use std::any::{type_name, Any, TypeId};
use std::cell::RefCell;
use std::fmt::Debug;
use std::mem::ManuallyDrop;
+use std::rc::Rc;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
@@ -23,7 +24,7 @@ use crate::event::component::{
Removed as ComponentRemovedEvent,
};
use crate::extension::{Collector as ExtensionCollector, Extension};
-use crate::lock::{Lock, WriteGuard};
+use crate::lock::Lock;
use crate::pair::{ChildOf, DependsOn, Pair};
use crate::phase::{Phase, START as START_PHASE};
use crate::query::flexible::Query as FlexibleQuery;
@@ -86,7 +87,7 @@ impl World
world.add_sole(Stats::default()).ok();
for create_static_entity in CREATE_STATIC_ENTITIES {
- create_static_entity(&world);
+ create_static_entity(&mut world);
}
world
@@ -109,29 +110,23 @@ impl World
#[tracing::instrument(skip_all)]
#[doc(hidden)]
- pub fn create_entity_with_uid<Comps>(&self, components: Comps, entity_uid: Uid)
+ pub fn create_entity_with_uid<Comps>(&mut self, components: Comps, entity_uid: Uid)
where
Comps: ComponentSequence,
{
debug_assert_eq!(entity_uid.kind(), UidKind::Entity);
- let added_component_ids;
-
- {
- let mut component_storage_lock = self.lock_component_storage_rw();
-
- if let Err(err) = component_storage_lock.create_entity(entity_uid) {
- tracing::warn!("Failed to create entity: {err}");
- return;
- };
-
- added_component_ids = Self::add_entity_components(
- entity_uid,
- components.into_parts_array(),
- &mut component_storage_lock,
- );
+ if let Err(err) = self.data.component_storage.create_entity(entity_uid) {
+ tracing::warn!("Failed to create entity: {err}");
+ return;
}
+ let added_component_ids = Self::add_entity_components(
+ entity_uid,
+ components.into_parts_array(),
+ &mut self.data.component_storage,
+ );
+
for comp_id in added_component_ids {
self.emit_event_by_id::<ComponentAddedEvent>(comp_id);
}
@@ -203,7 +198,7 @@ impl World
///
/// # Panics
/// Will panic if a internal lock cannot be acquired.
- pub fn step(&self) -> StepResult
+ pub fn step(&mut self) -> StepResult
{
if self.stop.load(Ordering::Relaxed) {
return StepResult::Stop;
@@ -219,8 +214,7 @@ impl World
self.perform_phases();
- self.lock_component_storage_rw()
- .create_imaginary_archetypes();
+ self.data.component_storage.create_imaginary_archetypes();
self.perform_queued_actions();
@@ -249,7 +243,7 @@ impl World
///
/// # Panics
/// Will panic if a internal lock cannot be acquired.
- pub fn start_loop(&self)
+ pub fn start_loop(&mut self)
{
while let StepResult::Continue = self.step() {}
}
@@ -267,13 +261,7 @@ impl World
VizoxideArchetypeGraphParams,
};
- let component_storage_lock = self
- .data
- .component_storage
- .read_nonblock()
- .expect("Failed to acquire read-only component storage lock");
-
- component_storage_lock.create_vizoxide_archetype_graph(
+ self.data.component_storage.create_vizoxide_archetype_graph(
name,
VizoxideArchetypeGraphParams {
create_node_name: |archetype, _| {
@@ -339,7 +327,7 @@ impl World
.build(),
);
- for child_phase_entity in phase_query.iter() {
+ for child_phase_entity in &phase_query {
self.query_and_run_systems(child_phase_entity.uid());
self.perform_child_phases(child_phase_entity.uid());
}
@@ -360,7 +348,7 @@ impl World
}
#[tracing::instrument(skip_all)]
- fn perform_queued_actions(&self)
+ fn perform_queued_actions(&mut self)
{
let mut active_action_queue = match *self.data.action_queue.active_queue.borrow()
{
@@ -380,27 +368,21 @@ impl World
for action in active_action_queue.drain(..) {
match action {
Action::Spawn(components) => {
- let added_component_ids;
+ let new_entity_uid = Uid::new_unique(UidKind::Entity);
+ if let Err(err) =
+ self.data.component_storage.create_entity(new_entity_uid)
{
- let mut component_storage_lock = self.lock_component_storage_rw();
-
- let new_entity_uid = Uid::new_unique(UidKind::Entity);
-
- if let Err(err) =
- component_storage_lock.create_entity(new_entity_uid)
- {
- tracing::warn!("Failed to create entity: {err}");
- continue;
- };
-
- added_component_ids = Self::add_entity_components(
- new_entity_uid,
- components,
- &mut component_storage_lock,
- );
+ tracing::warn!("Failed to create entity: {err}");
+ continue;
}
+ let added_component_ids = Self::add_entity_components(
+ new_entity_uid,
+ components,
+ &mut self.data.component_storage,
+ );
+
if !has_swapped_active_queue {
self.swap_event_queue(&mut has_swapped_active_queue);
}
@@ -410,20 +392,31 @@ impl World
}
}
Action::Despawn(entity_uid) => {
- self.despawn_entity(entity_uid, &mut has_swapped_active_queue);
- }
- Action::AddComponents(entity_uid, components) => {
- let added_component_ids;
+ let removed_entity =
+ match self.data.component_storage.remove_entity(entity_uid) {
+ Ok(components) => components,
+ Err(err) => {
+ tracing::error!("Failed to despawn entity: {err}");
+ return;
+ }
+ };
- {
- let mut component_storage_lock = self.lock_component_storage_rw();
+ if !has_swapped_active_queue {
+ self.swap_event_queue(&mut has_swapped_active_queue);
+ }
- added_component_ids = Self::add_entity_components(
- entity_uid,
- components,
- &mut component_storage_lock,
+ for removed_ent_comp in removed_entity.components() {
+ self.emit_event_by_id::<ComponentRemovedEvent>(
+ removed_ent_comp.id(),
);
}
+ }
+ Action::AddComponents(entity_uid, components) => {
+ let added_component_ids = Self::add_entity_components(
+ entity_uid,
+ components,
+ &mut self.data.component_storage,
+ );
if !has_swapped_active_queue {
self.swap_event_queue(&mut has_swapped_active_queue);
@@ -434,17 +427,11 @@ impl World
}
}
Action::RemoveComponents(entity_uid, component_ids) => {
- let removed_component_ids;
-
- {
- let mut component_storage_lock = self.lock_component_storage_rw();
-
- removed_component_ids = Self::remove_entity_components(
- entity_uid,
- component_ids,
- &mut component_storage_lock,
- );
- }
+ let removed_component_ids = Self::remove_entity_components(
+ entity_uid,
+ component_ids,
+ &mut self.data.component_storage,
+ );
if !has_swapped_active_queue {
self.swap_event_queue(&mut has_swapped_active_queue);
@@ -461,30 +448,6 @@ impl World
}
}
- #[tracing::instrument(skip_all)]
- fn despawn_entity(&self, entity_uid: Uid, has_swapped_active_queue: &mut bool)
- {
- let mut component_storage_lock = self.lock_component_storage_rw();
-
- let removed_entity = match component_storage_lock.remove_entity(entity_uid) {
- Ok(components) => components,
- Err(err) => {
- tracing::error!("Failed to despawn entity: {err}");
- return;
- }
- };
-
- drop(component_storage_lock);
-
- if !*has_swapped_active_queue {
- self.swap_event_queue(has_swapped_active_queue);
- }
-
- for removed_ent_comp in removed_entity.components() {
- self.emit_event_by_id::<ComponentRemovedEvent>(removed_ent_comp.id());
- }
- }
-
fn add_entity_components(
entity_uid: Uid,
components: impl IntoIterator<Item = ComponentParts>,
@@ -568,14 +531,6 @@ impl World
*has_swapped_active_queue = true;
}
-
- fn lock_component_storage_rw(&self) -> WriteGuard<'_, ComponentStorage>
- {
- self.data
- .component_storage
- .write_nonblock()
- .expect("Failed to acquire read-write component storage lock")
- }
}
impl Default for World
@@ -599,9 +554,9 @@ pub enum StepResult
#[derive(Debug)]
pub struct WorldData
{
- component_storage: Arc<Lock<ComponentStorage>>,
+ component_storage: ComponentStorage,
sole_storage: SoleStorage,
- action_queue: Arc<ActionQueue>,
+ action_queue: Rc<ActionQueue>,
}
impl Default for WorldData
@@ -609,12 +564,9 @@ impl Default for WorldData
fn default() -> Self
{
Self {
- component_storage: Arc::new(Lock::new(
- ComponentStorage::default(),
- type_name::<ComponentStorage>(),
- )),
+ component_storage: ComponentStorage::default(),
sole_storage: SoleStorage::default(),
- action_queue: Arc::new(ActionQueue::default()),
+ action_queue: Rc::new(ActionQueue::default()),
}
}
}
@@ -633,6 +585,7 @@ impl<'a> EntityComponentRef<'a>
self.component.component()
}
+ #[must_use]
pub fn id(&self) -> Uid
{
self.component_id
diff --git a/ecs/src/pair.rs b/ecs/src/pair.rs
index 27e535e..2055d5e 100644
--- a/ecs/src/pair.rs
+++ b/ecs/src/pair.rs
@@ -1,12 +1,10 @@
use std::convert::Infallible;
-use crate::component::storage::Storage as ComponentStorage;
use crate::component::{IntoParts as IntoComponentParts, Parts as ComponentParts};
use crate::entity::{
Handle as EntityHandle,
MatchingComponentIter as EntityMatchingComponentIter,
};
-use crate::lock::ReadGuard;
use crate::query::{
TermWithField as QueryTermWithField,
TermsBuilder as QueryTermsBuilder,
@@ -24,14 +22,16 @@ pub struct Pair<RelationElem: Element, TargetElem: Element>
impl Pair<Uid, Uid>
{
+ #[must_use]
pub fn new<Relation: WithUid>(target: Uid) -> Self
{
Self { relation: Relation::uid(), target }
}
+ #[must_use]
pub fn id(&self) -> Uid
{
- Uid::new_pair(UidPairParams {
+ Uid::new_pair(&UidPairParams {
relation: self.relation,
target: self.target,
})
@@ -72,7 +72,6 @@ where
Handle {
world,
- component_storage_lock: world.data.component_storage.read_nonblock().unwrap(),
pair_uid: first_matching_comp.id(),
}
}
@@ -85,7 +84,7 @@ where
{
fn uid() -> Uid
{
- Uid::new_pair(UidPairParams {
+ Uid::new_pair(&UidPairParams {
relation: Relation::uid(),
target: Target::uid(),
})
@@ -121,21 +120,25 @@ where
pub struct Handle<'world>
{
world: &'world World,
- component_storage_lock: ReadGuard<'world, ComponentStorage>,
pair_uid: Uid,
}
impl Handle<'_>
{
+ #[must_use]
pub fn get_target_entity(&self) -> Option<EntityHandle<'_>>
{
let archetype = self
- .component_storage_lock
+ .world
+ .data
+ .component_storage
.get_entity_archetype(self.pair_uid.target_entity())?;
- let archetype_entity = archetype
- .get_entity_by_id(self.pair_uid.target_entity())
- .expect("Not possible");
+ let Some(archetype_entity) =
+ archetype.get_entity_by_id(self.pair_uid.target_entity())
+ else {
+ unreachable!();
+ };
Some(EntityHandle::new(self.world, archetype, archetype_entity))
}
@@ -157,12 +160,6 @@ impl<'a> Iterator for HandleIter<'a>
Some(Handle {
world: self.world,
- component_storage_lock: self
- .world
- .data
- .component_storage
- .read_nonblock()
- .unwrap(),
pair_uid: matching_comp.id(),
})
}
diff --git a/ecs/src/query.rs b/ecs/src/query.rs
index 1947c18..7e10c5b 100644
--- a/ecs/src/query.rs
+++ b/ecs/src/query.rs
@@ -168,12 +168,14 @@ impl<const MAX_TERM_CNT: usize> Terms<MAX_TERM_CNT>
}
#[derive(Debug, Default)]
+#[must_use]
pub struct TermsBuilder<const MAX_TERM_CNT: usize>
{
required_components: ArrayVec<Uid, MAX_TERM_CNT>,
excluded_components: ArrayVec<Uid, MAX_TERM_CNT>,
}
+#[allow(clippy::return_self_not_must_use)]
pub trait TermsBuilderInterface
{
fn with<WithUidT: WithUid>(self) -> Self;
@@ -233,7 +235,7 @@ impl_terms_builder! {
ids.as_mut().sort();
}
- if self.required_components.len() == 0 {
+ if self.required_components.is_empty() {
self.required_components.extend(ids);
return self;
}
@@ -265,7 +267,7 @@ impl_terms_builder! {
ids.as_mut().sort();
}
- if self.excluded_components.len() == 0 {
+ if self.excluded_components.is_empty() {
self.excluded_components.extend(ids);
return self;
}
@@ -293,10 +295,11 @@ impl_terms_builder! {
impl<const MAX_TERM_CNT: usize> TermsBuilder<MAX_TERM_CNT>
{
+ #[must_use]
pub fn build(self) -> Terms<MAX_TERM_CNT>
{
- assert!(self.required_components.is_sorted());
- assert!(self.excluded_components.is_sorted());
+ debug_assert!(self.required_components.is_sorted());
+ debug_assert!(self.excluded_components.is_sorted());
Terms {
required_components: self.required_components,
diff --git a/ecs/src/query/flexible.rs b/ecs/src/query/flexible.rs
index 3e72b34..6d65ee0 100644
--- a/ecs/src/query/flexible.rs
+++ b/ecs/src/query/flexible.rs
@@ -2,13 +2,8 @@
use std::iter::{repeat_n, FlatMap, RepeatN, Zip};
use crate::component::storage::archetype::{Archetype, EntityIter};
-use crate::component::storage::{
- ArchetypeRefIter,
- ArchetypeSearchTerms,
- Storage as ComponentStorage,
-};
+use crate::component::storage::{ArchetypeRefIter, ArchetypeSearchTerms};
use crate::entity::Handle as EntityHandle;
-use crate::lock::ReadGuard;
use crate::query::Terms;
use crate::World;
@@ -17,7 +12,6 @@ use crate::World;
pub struct Query<'world, const MAX_TERM_CNT: usize>
{
world: &'world World,
- component_storage: ReadGuard<'world, ComponentStorage>,
terms: Terms<MAX_TERM_CNT>,
}
@@ -30,6 +24,8 @@ impl<'world, const MAX_TERM_CNT: usize> Query<'world, MAX_TERM_CNT>
Iter {
world: self.world,
iter: self
+ .world
+ .data
.component_storage
.search_archetypes(ArchetypeSearchTerms {
required_components: &self.terms.required_components,
@@ -46,15 +42,18 @@ impl<'world, const MAX_TERM_CNT: usize> Query<'world, MAX_TERM_CNT>
pub(crate) fn new(world: &'world World, terms: Terms<MAX_TERM_CNT>) -> Self
{
- Self {
- world,
- component_storage: world
- .data
- .component_storage
- .read_nonblock()
- .expect("Failed to acquire read-only component storage lock"),
- terms,
- }
+ Self { world, terms }
+ }
+}
+
+impl<'query, const MAX_TERM_CNT: usize> IntoIterator for &'query Query<'_, MAX_TERM_CNT>
+{
+ type IntoIter = Iter<'query>;
+ type Item = EntityHandle<'query>;
+
+ fn into_iter(self) -> Self::IntoIter
+ {
+ self.iter()
}
}
diff --git a/ecs/src/uid.rs b/ecs/src/uid.rs
index 6c97649..feed62c 100644
--- a/ecs/src/uid.rs
+++ b/ecs/src/uid.rs
@@ -54,8 +54,12 @@ impl Uid
}
}
+ /// Returns a new pair UID.
+ ///
+ /// # Panics
+ /// Will panic if either the given relation or target is a pair UID.
#[must_use]
- pub fn new_pair(params: PairParams) -> Self
+ pub fn new_pair(params: &PairParams) -> Self
{
assert_ne!(
params.relation.kind(),
@@ -102,6 +106,7 @@ impl Uid
///
/// # Panics
/// Will panic if this `Uid` is not a pair.
+ #[must_use]
pub fn relation_component(&self) -> Self
{
assert_eq!(self.kind(), Kind::Pair, "Uid is not a pair");
@@ -112,6 +117,7 @@ impl Uid
}
}
+ #[must_use]
pub fn has_same_relation_as(&self, other: Self) -> bool
{
self.relation() == other.relation()
@@ -121,6 +127,7 @@ impl Uid
///
/// # Panics
/// Will panic if this `Uid` is not a pair.
+ #[must_use]
pub fn relation_entity(&self) -> Self
{
assert_eq!(self.kind(), Kind::Pair, "Uid is not a pair");
@@ -135,6 +142,7 @@ impl Uid
///
/// # Panics
/// Will panic if this `Uid` is not a pair.
+ #[must_use]
pub fn target_component(&self) -> Self
{
assert_eq!(self.kind(), Kind::Pair, "Uid is not a pair");
@@ -149,6 +157,7 @@ impl Uid
///
/// # Panics
/// Will panic if this `Uid` is not a pair.
+ #[must_use]
pub fn target_entity(&self) -> Self
{
assert_eq!(self.kind(), Kind::Pair, "Uid is not a pair");
@@ -159,7 +168,7 @@ impl Uid
}
}
- fn relation(&self) -> u32
+ fn relation(self) -> u32
{
let Ok(relation) = u32::try_from(self.inner.field_get(RELATION_BITS)) else {
unreachable!("Uid relation does not fit in u32");
diff --git a/ecs/src/util.rs b/ecs/src/util.rs
index eb06ab4..9ab4dc6 100644
--- a/ecs/src/util.rs
+++ b/ecs/src/util.rs
@@ -4,7 +4,7 @@ use std::ops::{BitAnd, Deref};
use hashbrown::HashMap;
-pub mod array_vec;
+pub(crate) mod array_vec;
pub trait VecExt<Item>
{
diff --git a/ecs/src/util/array_vec.rs b/ecs/src/util/array_vec.rs
index 648c976..13a0349 100644
--- a/ecs/src/util/array_vec.rs
+++ b/ecs/src/util/array_vec.rs
@@ -1,4 +1,4 @@
-use std::mem::{transmute, MaybeUninit};
+use std::mem::MaybeUninit;
use std::ops::{Deref, DerefMut};
#[derive(Debug)]
@@ -10,16 +10,18 @@ pub struct ArrayVec<Item, const CAPACITY: usize>
impl<Item, const CAPACITY: usize> ArrayVec<Item, CAPACITY>
{
- pub fn new() -> Self
+ #[inline]
+ #[must_use]
+ pub fn len(&self) -> usize
{
- Self::default()
+ self.len
}
#[inline]
#[must_use]
- pub fn len(&self) -> usize
+ pub fn is_empty(&self) -> bool
{
- self.len
+ self.len == 0
}
pub fn push(&mut self, item: Item)
@@ -69,7 +71,9 @@ impl<Item, const CAPACITY: usize> AsRef<[Item]> for ArrayVec<Item, CAPACITY>
{
fn as_ref(&self) -> &[Item]
{
- unsafe { transmute::<&[MaybeUninit<Item>], &[Item]>(&self.items[..self.len]) }
+ let ptr = &raw const self.items[..self.len];
+
+ unsafe { &*(ptr as *const [Item]) }
}
}
@@ -77,11 +81,9 @@ impl<Item, const CAPACITY: usize> AsMut<[Item]> for ArrayVec<Item, CAPACITY>
{
fn as_mut(&mut self) -> &mut [Item]
{
- unsafe {
- transmute::<&mut [MaybeUninit<Item>], &mut [Item]>(
- &mut self.items[..self.len],
- )
- }
+ let ptr = &raw mut self.items[..self.len];
+
+ unsafe { &mut *(ptr as *mut [Item]) }
}
}