summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ecs-macros/src/lib.rs34
-rw-r--r--ecs/examples/optional_component.rs2
-rw-r--r--ecs/src/component.rs243
-rw-r--r--ecs/src/component/storage.rs68
-rw-r--r--ecs/src/component/storage/archetype.rs22
-rw-r--r--ecs/src/component/storage/graph.rs17
-rw-r--r--ecs/src/lib.rs100
-rw-r--r--ecs/src/lock.rs95
-rw-r--r--ecs/src/query.rs143
-rw-r--r--ecs/src/query/flexible.rs8
-rw-r--r--ecs/src/query/term.rs50
-rw-r--r--ecs/src/relationship.rs76
-rw-r--r--ecs/src/sole.rs11
-rw-r--r--ecs/src/system/stateful.rs9
-rw-r--r--ecs/src/type_name.rs15
-rw-r--r--ecs/src/util.rs2
-rw-r--r--ecs/src/util/array_vec.rs115
-rw-r--r--ecs/tests/query.rs4
-rw-r--r--engine/src/renderer/opengl.rs10
19 files changed, 475 insertions, 549 deletions
diff --git a/ecs-macros/src/lib.rs b/ecs-macros/src/lib.rs
index 5af10b9..a5acc2b 100644
--- a/ecs-macros/src/lib.rs
+++ b/ecs-macros/src/lib.rs
@@ -120,7 +120,6 @@ pub fn component_derive(input: TokenStream) -> TokenStream
};
use #ecs_path::uid::{Uid, Kind as UidKind};
use #ecs_path::system::Input as SystemInput;
- use #ecs_path::type_name::TypeName;
use super::*;
@@ -139,6 +138,11 @@ pub fn component_derive(input: TokenStream) -> TokenStream
#get_id
}
+ fn name(&self) -> &'static str
+ {
+ std::any::type_name::<Self>()
+ }
+
fn get_event_uid(&self, event_kind: ComponentEventKind) -> Uid
{
match event_kind {
@@ -150,31 +154,12 @@ pub fn component_derive(input: TokenStream) -> TokenStream
}
}
}
-
- fn as_any_mut(&mut self) -> &mut dyn Any
- {
- self
- }
-
- fn as_any(&self) -> &dyn Any
- {
- self
- }
}
impl #impl_generics SystemInput for #item_ident #type_generics
#where_clause
{
}
-
- impl #impl_generics TypeName for #item_ident #type_generics
- #where_clause
- {
- fn type_name(&self) -> &'static str
- {
- std::any::type_name::<Self>()
- }
- }
}
}
.into()
@@ -214,15 +199,6 @@ pub fn sole_derive(input: TokenStream) -> TokenStream
self
}
}
-
- impl #impl_generics #ecs_path::type_name::TypeName for #item_ident #type_generics
- #where_clause
- {
- fn type_name(&self) -> &'static str
- {
- std::any::type_name::<Self>()
- }
- }
}
.into()
}
diff --git a/ecs/examples/optional_component.rs b/ecs/examples/optional_component.rs
index 488dad2..ebc9115 100644
--- a/ecs/examples/optional_component.rs
+++ b/ecs/examples/optional_component.rs
@@ -21,7 +21,7 @@ pub struct CatName
name: String,
}
-fn pet_cats(query: Query<(&CatName, &mut PettingCapacity, &Option<Aggressivity>)>)
+fn pet_cats(query: Query<(&CatName, &mut PettingCapacity, Option<&Aggressivity>)>)
{
for (cat_name, mut petting_capacity, aggressivity) in &query {
let Some(aggressivity) = aggressivity else {
diff --git a/ecs/src/component.rs b/ecs/src/component.rs
index 46fbf8a..49265b3 100644
--- a/ecs/src/component.rs
+++ b/ecs/src/component.rs
@@ -1,4 +1,5 @@
use std::any::{type_name, Any};
+use std::error::Error;
use std::fmt::Debug;
use std::ops::{Deref, DerefMut};
@@ -11,34 +12,32 @@ use crate::event::component::{
};
use crate::lock::{
Error as LockError,
- Lock,
MappedReadGuard,
MappedWriteGuard,
ReadGuard,
WriteGuard,
};
use crate::system::Input as SystemInput;
-use crate::type_name::TypeName;
use crate::uid::Uid;
use crate::util::Array;
-use crate::World;
+use crate::{EntityComponentRef, World};
pub mod local;
pub(crate) mod storage;
-pub trait Component: SystemInput + Any + TypeName
+pub trait Component: SystemInput + Any
{
/// The component type in question. Will usually be `Self`
type Component: Component
where
Self: Sized;
- type HandleMut<'component>: FromLockedOptional<'component>
+ type HandleMut<'component>: HandleFromEntityComponentRef<'component>
where
Self: Sized;
- type Handle<'component>: FromLockedOptional<'component>
+ type Handle<'component>: HandleFromEntityComponentRef<'component>
where
Self: Sized;
@@ -47,46 +46,28 @@ pub trait Component: SystemInput + Any + TypeName
where
Self: Sized;
+ /// Returns the name of this component.
+ fn name(&self) -> &'static str;
+
/// Returns the component UID of a component event for this component.
fn get_event_uid(&self, event_kind: ComponentEventKind) -> Uid;
-
- #[doc(hidden)]
- fn as_any_mut(&mut self) -> &mut dyn Any;
-
- #[doc(hidden)]
- fn as_any(&self) -> &dyn Any;
-
- /// Returns whether the component `self` is optional.
- fn self_is_optional(&self) -> bool
- {
- false
- }
-
- /// Returns whether this component is optional.
- #[must_use]
- fn is_optional() -> bool
- where
- Self: Sized,
- {
- false
- }
}
impl dyn Component
{
pub fn downcast_mut<Real: 'static>(&mut self) -> Option<&mut Real>
{
- self.as_any_mut().downcast_mut()
+ (self as &mut dyn Any).downcast_mut()
}
pub fn downcast_ref<Real: 'static>(&self) -> Option<&Real>
{
- self.as_any().downcast_ref()
+ (self as &dyn Any).downcast_ref()
}
pub fn is<Other: 'static>(&self) -> bool
{
- self.as_any().is::<Other>()
+ (self as &dyn Any).is::<Other>()
}
}
@@ -98,69 +79,6 @@ impl Debug for dyn Component
}
}
-impl TypeName for Box<dyn Component>
-{
- fn type_name(&self) -> &'static str
- {
- self.as_ref().type_name()
- }
-}
-
-impl<ComponentT> Component for Option<ComponentT>
-where
- ComponentT: Component,
- for<'a> Option<ComponentT::Handle<'a>>: FromLockedOptional<'a>,
- for<'a> Option<ComponentT::HandleMut<'a>>: FromLockedOptional<'a>,
-{
- type Component = ComponentT;
- type Handle<'component> = Option<ComponentT::Handle<'component>>;
- type HandleMut<'component> = Option<ComponentT::HandleMut<'component>>;
-
- fn id() -> Uid
- {
- ComponentT::id()
- }
-
- fn get_event_uid(&self, event_kind: ComponentEventKind) -> Uid
- {
- match event_kind {
- ComponentEventKind::Removed => ComponentRemovedEvent::<Self>::id(),
- }
- }
-
- fn as_any_mut(&mut self) -> &mut dyn Any
- {
- self
- }
-
- fn as_any(&self) -> &dyn Any
- {
- self
- }
-
- fn self_is_optional(&self) -> bool
- {
- true
- }
-
- fn is_optional() -> bool
- {
- true
- }
-}
-
-impl<ComponentT> TypeName for Option<ComponentT>
-where
- ComponentT: Component,
-{
- fn type_name(&self) -> &'static str
- {
- type_name::<Self>()
- }
-}
-
-impl<ComponentT> SystemInput for Option<ComponentT> where ComponentT: Component {}
-
/// A sequence of components.
pub trait Sequence
{
@@ -182,7 +100,7 @@ pub trait Sequence
pub trait Ref
{
type Component: Component;
- type Handle<'component>: FromLockedOptional<'component>;
+ type Handle<'component>: HandleFromEntityComponentRef<'component>;
}
impl<ComponentT> Ref for &ComponentT
@@ -207,37 +125,26 @@ where
pub struct Metadata
{
pub id: Uid,
- pub is_optional: bool,
}
impl Metadata
{
#[must_use]
- pub fn new_non_optional(id: Uid) -> Self
- {
- Self { id, is_optional: false }
- }
-
- #[must_use]
pub fn of<ComponentT: Component>() -> Self
{
- Self {
- id: ComponentT::id(),
- is_optional: ComponentT::is_optional(),
- }
+ Self { id: ComponentT::id() }
}
}
-pub trait FromLockedOptional<'comp>: Sized
+pub trait HandleFromEntityComponentRef<'comp>: Sized
{
- /// Converts a reference to a optional locked boxed component to a instance of `Self`.
- ///
- /// # Errors
- /// Returns `Err` if taking the lock (in a non-blocking way) fails.
- fn from_locked_optional_component(
- optional_component: Option<&'comp Lock<Box<dyn Component>>>,
+ type Error: Error;
+
+ /// Creates a new handle instance from a [`EntityComponentRef`].
+ fn from_entity_component_ref(
+ entity_component_ref: Option<EntityComponentRef<'comp>>,
world: &'comp World,
- ) -> Result<Self, LockError>;
+ ) -> Result<Self, Self::Error>;
}
#[derive(Debug)]
@@ -248,14 +155,13 @@ pub struct Handle<'a, ComponentT: Component>
impl<'a, ComponentT: Component> Handle<'a, ComponentT>
{
- pub(crate) fn new(inner: ReadGuard<'a, Box<dyn Component>>) -> Self
+ pub(crate) fn new(inner: ReadGuard<'a, Box<dyn Any>>) -> Self
{
Self {
inner: inner.map(|component| {
component.downcast_ref::<ComponentT>().unwrap_or_else(|| {
panic!(
- "Cannot downcast component {} to type {}",
- component.type_name(),
+ "Failed to downcast component to type {}",
type_name::<ComponentT>()
);
})
@@ -264,37 +170,25 @@ impl<'a, ComponentT: Component> Handle<'a, ComponentT>
}
}
-impl<'component, ComponentT: Component> FromLockedOptional<'component>
- for Handle<'component, ComponentT>
+impl<'comp, ComponentT: Component> HandleFromEntityComponentRef<'comp>
+ for Handle<'comp, ComponentT>
{
- fn from_locked_optional_component(
- optional_component: Option<&'component crate::lock::Lock<Box<dyn Component>>>,
- _world: &'component World,
- ) -> Result<Self, LockError>
- {
- let component = optional_component.unwrap_or_else(|| {
- panic!(
- "Component {} was not found in entity",
- type_name::<ComponentT>()
- );
- });
+ type Error = HandleError;
- Ok(Self::new(component.read_nonblock()?))
- }
-}
-
-impl<'comp, ComponentT> FromLockedOptional<'comp> for Option<Handle<'comp, ComponentT>>
-where
- ComponentT: Component,
-{
- fn from_locked_optional_component(
- optional_component: Option<&'comp Lock<Box<dyn Component>>>,
+ fn from_entity_component_ref(
+ entity_component_ref: Option<EntityComponentRef<'comp>>,
_world: &'comp World,
- ) -> Result<Self, LockError>
+ ) -> Result<Self, Self::Error>
{
- optional_component
- .map(|lock| Ok(Handle::new(lock.read_nonblock()?)))
- .transpose()
+ let entity_comp =
+ entity_component_ref.ok_or(HandleError::ComponentDoesNotExist)?;
+
+ Ok(Self::new(
+ entity_comp
+ .component()
+ .read_nonblock()
+ .map_err(AcquireComponentLockFailed)?,
+ ))
}
}
@@ -316,15 +210,13 @@ pub struct HandleMut<'a, ComponentT: Component>
impl<'a, ComponentT: Component> HandleMut<'a, ComponentT>
{
- pub(crate) fn new(inner: WriteGuard<'a, Box<dyn Component>>) -> Self
+ pub(crate) fn new(inner: WriteGuard<'a, Box<dyn Any>>) -> Self
{
Self {
inner: inner.map(|component| {
- let component_type_name = component.type_name();
-
component.downcast_mut::<ComponentT>().unwrap_or_else(|| {
panic!(
- "Cannot downcast component {component_type_name} to type {}",
+ "Failed to downcast component to type {}",
type_name::<ComponentT>()
);
})
@@ -333,37 +225,25 @@ impl<'a, ComponentT: Component> HandleMut<'a, ComponentT>
}
}
-impl<'component, ComponentT: Component> FromLockedOptional<'component>
- for HandleMut<'component, ComponentT>
+impl<'comp, ComponentT: Component> HandleFromEntityComponentRef<'comp>
+ for HandleMut<'comp, ComponentT>
{
- fn from_locked_optional_component(
- optional_component: Option<&'component Lock<Box<dyn Component>>>,
- _world: &'component World,
- ) -> Result<Self, LockError>
- {
- let component = optional_component.unwrap_or_else(|| {
- panic!(
- "Component {} was not found in entity",
- type_name::<ComponentT>()
- );
- });
+ type Error = HandleError;
- Ok(Self::new(component.write_nonblock()?))
- }
-}
-
-impl<'comp, ComponentT> FromLockedOptional<'comp> for Option<HandleMut<'comp, ComponentT>>
-where
- ComponentT: Component,
-{
- fn from_locked_optional_component(
- optional_component: Option<&'comp Lock<Box<dyn Component>>>,
+ fn from_entity_component_ref(
+ entity_component_ref: Option<EntityComponentRef<'comp>>,
_world: &'comp World,
- ) -> Result<Self, LockError>
+ ) -> Result<Self, Self::Error>
{
- optional_component
- .map(|lock| Ok(HandleMut::new(lock.write_nonblock()?)))
- .transpose()
+ let entity_comp =
+ entity_component_ref.ok_or(HandleError::ComponentDoesNotExist)?;
+
+ Ok(Self::new(
+ entity_comp
+ .component()
+ .write_nonblock()
+ .map_err(AcquireComponentLockFailed)?,
+ ))
}
}
@@ -385,6 +265,20 @@ impl<ComponentT: Component> DerefMut for HandleMut<'_, ComponentT>
}
}
+#[derive(Debug, thiserror::Error)]
+pub enum HandleError
+{
+ #[error(transparent)]
+ AcquireComponentLockFailed(#[from] AcquireComponentLockFailed),
+
+ #[error("Component does not exist")]
+ ComponentDoesNotExist,
+}
+
+#[derive(Debug, thiserror::Error)]
+#[error(transparent)]
+pub struct AcquireComponentLockFailed(LockError);
+
macro_rules! inner {
($c: tt) => {
seq!(I in 0..=$c {
@@ -413,7 +307,6 @@ macro_rules! inner {
#(
Metadata {
id: IntoComp~I::Component::id(),
- is_optional: IntoComp~I::Component::is_optional(),
},
)*
]
diff --git a/ecs/src/component/storage.rs b/ecs/src/component/storage.rs
index 4a00510..53f51f2 100644
--- a/ecs/src/component/storage.rs
+++ b/ecs/src/component/storage.rs
@@ -1,4 +1,4 @@
-use std::any::type_name;
+use std::any::Any;
use std::array::IntoIter as ArrayIter;
use std::cell::RefCell;
use std::vec::IntoIter as VecIntoIter;
@@ -17,8 +17,6 @@ use crate::component::storage::graph::{
ArchetypeEdges,
Graph,
};
-use crate::component::Component;
-use crate::type_name::TypeName;
use crate::uid::{Kind as UidKind, Uid};
use crate::util::{BorrowedOrOwned, Either, StreamingIterator, VecExt};
@@ -161,16 +159,9 @@ impl Storage
pub fn add_entity_component(
&mut self,
entity_uid: Uid,
- component: (Uid, Box<dyn Component>),
+ (component_id, component_name, component): (Uid, &'static str, Box<dyn Any>),
) -> Result<(), Error>
{
- let (component_id, component) = component;
-
- debug_assert!(
- !component.self_is_optional(),
- "Adding a optional component to a entity is not supported"
- );
-
let Some(archetype_id) = self.entity_archetype_lookup.get(&entity_uid) else {
return Err(Error::EntityDoesNotExist(entity_uid));
};
@@ -192,41 +183,39 @@ impl Storage
});
}
- let add_edge_archetype_id = archetype_node
+ let add_edge_archetype_id = match archetype_node
.get_or_insert_edges(component_id, ArchetypeEdges::default)
.add
- .unwrap_or_else(|| {
+ {
+ 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
.graph
- .get_node_by_id_mut(archetype_id)
+ .get_node_by_id(archetype_id)
.expect("Archetype should exist");
let (add_edge_id, add_edge_comp_ids) =
archetype_node.make_add_edge(component_id);
- archetype_node
- .get_edges_mut(component_id)
- .expect("Edges for component in archetype should exist")
- .add = Some(add_edge_id);
-
if !self.graph.contains_archetype(add_edge_id) {
self.graph.create_node(add_edge_id, &add_edge_comp_ids);
}
add_edge_id
- });
-
- {
- let add_edge_archetype_node = self
- .graph
- .get_node_by_id_mut(add_edge_archetype_id)
- .expect("Add edge archetype should exist");
-
- let add_edge_archetype_edges = add_edge_archetype_node
- .get_or_insert_edges(component_id, ArchetypeEdges::default);
-
- add_edge_archetype_edges.remove = Some(archetype_id);
- }
+ }
+ };
let archetype_node = self
.graph
@@ -246,7 +235,7 @@ impl Storage
entity.insert_component(
component_id,
- ArchetypeEntityComponent::new(component),
+ ArchetypeEntityComponent::new(component, component_name),
add_edge_archetype,
);
@@ -297,11 +286,6 @@ impl Storage
let (remove_edge_id, remove_edge_comp_ids) =
archetype_node.make_remove_edge(component_id);
- archetype_node
- .get_edges_mut(component_id)
- .expect("Edges for component in archetype should exist")
- .remove = Some(remove_edge_id);
-
if !self.graph.contains_archetype(remove_edge_id) {
self.graph
.create_node(remove_edge_id, &remove_edge_comp_ids);
@@ -400,14 +384,6 @@ impl Storage
}
}
-impl TypeName for Storage
-{
- fn type_name(&self) -> &'static str
- {
- type_name::<Self>()
- }
-}
-
#[cfg(feature = "vizoxide")]
impl Storage
{
diff --git a/ecs/src/component/storage/archetype.rs b/ecs/src/component/storage/archetype.rs
index 5306cf9..b8ac826 100644
--- a/ecs/src/component/storage/archetype.rs
+++ b/ecs/src/component/storage/archetype.rs
@@ -1,9 +1,10 @@
+use std::any::Any;
use std::hash::{DefaultHasher, Hash, Hasher};
use std::slice::Iter as SliceIter;
use hashbrown::HashMap;
-use crate::component::{Component, Metadata as ComponentMetadata};
+use crate::component::Metadata as ComponentMetadata;
use crate::lock::Lock;
use crate::uid::{Kind as UidKind, Uid};
use crate::util::HashMapExt;
@@ -209,26 +210,19 @@ impl Entity
#[derive(Debug)]
pub struct EntityComponent
{
- name: &'static str,
- component: Lock<Box<dyn Component>>,
+ component: Lock<Box<dyn Any>>,
}
impl EntityComponent
{
- pub fn new(component: Box<dyn Component>) -> Self
+ pub fn new(component: Box<dyn Any>, component_name: &'static str) -> Self
{
Self {
- name: component.type_name(),
- component: Lock::new(component),
+ component: Lock::new(component, component_name),
}
}
- pub fn name(&self) -> &str
- {
- self.name
- }
-
- pub fn component(&self) -> &Lock<Box<dyn Component>>
+ pub fn component(&self) -> &Lock<Box<dyn Any>>
{
&self.component
}
@@ -288,10 +282,6 @@ impl Id
prev_component_id = Some(comp_metadata.id);
- if comp_metadata.is_optional {
- continue;
- }
-
comp_metadata.id.hash(&mut hasher);
}
diff --git a/ecs/src/component/storage/graph.rs b/ecs/src/component/storage/graph.rs
index 11160e7..d38223a 100644
--- a/ecs/src/component/storage/graph.rs
+++ b/ecs/src/component/storage/graph.rs
@@ -140,7 +140,7 @@ impl Graph
}
fn create_missing_subset_node_edges(
- target_node: &ArchetypeNode,
+ target_node: &mut ArchetypeNode,
subset_node: &mut ArchetypeNode,
)
{
@@ -153,6 +153,14 @@ impl Graph
subset_node
.get_or_insert_edges(uniq_comp_id, ArchetypeEdges::default)
.add = Some(subset_node.make_add_edge(uniq_comp_id).0);
+
+ if target_node.archetype().component_cnt()
+ == subset_node.archetype().component_cnt() + 1
+ {
+ target_node
+ .get_or_insert_edges(uniq_comp_id, ArchetypeEdges::default)
+ .remove = Some(subset_node.archetype().id());
+ }
}
fn create_missing_superset_node_edges(
@@ -245,13 +253,6 @@ impl ArchetypeNode
self.edges.iter()
}
- pub fn get_edges_mut(&mut self, component_id: Uid) -> Option<&mut ArchetypeEdges>
- {
- debug_assert_eq!(component_id.kind(), UidKind::Component);
-
- self.edges.get_mut(&component_id)
- }
-
pub fn make_add_edge(&self, component_id: Uid) -> (ArchetypeId, Vec<Uid>)
{
let mut edge_comp_ids = self
diff --git a/ecs/src/lib.rs b/ecs/src/lib.rs
index 3caaa6b..2c88eef 100644
--- a/ecs/src/lib.rs
+++ b/ecs/src/lib.rs
@@ -1,6 +1,6 @@
#![deny(clippy::all, clippy::pedantic)]
-use std::any::{type_name, TypeId};
+use std::any::{type_name, Any, TypeId};
use std::cell::RefCell;
use std::fmt::Debug;
use std::mem::ManuallyDrop;
@@ -14,7 +14,6 @@ use crate::component::storage::archetype::EntityComponent as ArchetypeEntityComp
use crate::component::storage::Storage as ComponentStorage;
use crate::component::{Component, Sequence as ComponentSequence};
use crate::entity::CREATE_STATIC_ENTITIES;
-use crate::event::component::Kind as ComponentEventKind;
use crate::extension::{Collector as ExtensionCollector, Extension};
use crate::lock::{Lock, WriteGuard};
use crate::phase::{Phase, START as START_PHASE};
@@ -31,7 +30,6 @@ use crate::relationship::{ChildOf, DependsOn, Relationship};
use crate::sole::Sole;
use crate::stats::Stats;
use crate::system::{System, SystemComponent};
-use crate::type_name::TypeName;
use crate::uid::{Kind as UidKind, Uid};
pub mod actions;
@@ -39,7 +37,7 @@ pub mod component;
pub mod entity;
pub mod event;
pub mod extension;
-pub mod lock;
+mod lock;
pub mod phase;
pub mod query;
pub mod relationship;
@@ -47,7 +45,6 @@ pub mod sole;
pub mod stats;
pub mod system;
pub mod tuple;
-pub mod type_name;
pub mod uid;
pub mod util;
@@ -184,10 +181,10 @@ impl World
Query::new(self)
}
- pub fn flexible_query<'terms>(
+ pub fn flexible_query<const MAX_TERM_CNT: usize>(
&self,
- terms: QueryTerms<'terms>,
- ) -> FlexibleQuery<'_, 'terms>
+ terms: QueryTerms<MAX_TERM_CNT>,
+ ) -> FlexibleQuery<'_, MAX_TERM_CNT>
{
FlexibleQuery::new(self, terms)
}
@@ -468,7 +465,7 @@ impl World
{
let mut component_storage_lock = self.lock_component_storage_rw();
- let removed_entity = match component_storage_lock.remove_entity(entity_uid) {
+ let _removed_entity = match component_storage_lock.remove_entity(entity_uid) {
Ok(components) => components,
Err(err) => {
tracing::error!("Failed to despawn entity: {err}");
@@ -476,32 +473,17 @@ impl World
}
};
- let component_removed_event_uids = removed_entity
- .components()
- .iter()
- .map(|component| {
- component
- .component()
- .read_nonblock()
- .unwrap_or_else(|_| {
- panic!(
- "Failed to acquire read-only {} component lock",
- component.name()
- )
- })
- .get_event_uid(ComponentEventKind::Removed)
- })
- .collect::<Vec<_>>();
-
drop(component_storage_lock);
if !*has_swapped_active_queue {
self.swap_event_queue(has_swapped_active_queue);
}
- for comp_removed_event_id in component_removed_event_uids {
- self.emit_event_by_id(comp_removed_event_id);
- }
+ // TODO: Emit component removed events here
+
+ // for comp_removed_event_id in component_removed_event_uids {
+ // self.emit_event_by_id(comp_removed_event_id);
+ // }
}
fn add_entity_components(
@@ -511,9 +493,10 @@ impl World
)
{
for (component_id, component) in components {
- if let Err(err) = component_storage
- .add_entity_component(entity_uid, (component_id, component))
- {
+ if let Err(err) = component_storage.add_entity_component(
+ entity_uid,
+ (component_id, component.name(), component),
+ ) {
tracing::error!("Failed to add component to entity: {err}");
}
}
@@ -536,11 +519,9 @@ impl World
fn emit_event_by_id(&self, event_id: Uid)
{
- let mut query_required_ids = [SystemComponent::id(), event_id];
-
let query = self.flexible_query(
- QueryTerms::builder()
- .with_required_ids(&mut query_required_ids)
+ QueryTerms::<2>::builder()
+ .with_required([SystemComponent::id(), event_id])
.build(),
);
@@ -590,7 +571,7 @@ pub enum StepResult
Stop,
}
-#[derive(Debug, Default)]
+#[derive(Debug)]
pub struct WorldData
{
component_storage: Arc<Lock<ComponentStorage>>,
@@ -598,6 +579,21 @@ pub struct WorldData
action_queue: Arc<ActionQueue>,
}
+impl Default for WorldData
+{
+ fn default() -> Self
+ {
+ Self {
+ component_storage: Arc::new(Lock::new(
+ ComponentStorage::default(),
+ type_name::<ComponentStorage>(),
+ )),
+ sole_storage: SoleStorage::default(),
+ action_queue: Arc::new(ActionQueue::default()),
+ }
+ }
+}
+
#[derive(Debug)]
pub struct EntityComponentRef<'a>
{
@@ -606,7 +602,7 @@ pub struct EntityComponentRef<'a>
impl<'a> EntityComponentRef<'a>
{
- pub fn component(&self) -> &'a Lock<Box<dyn Component>>
+ fn component(&self) -> &'a Lock<Box<dyn Any>>
{
self.comp.component()
}
@@ -625,7 +621,7 @@ enum ActiveActionQueue
B,
}
-#[derive(Debug, Default)]
+#[derive(Debug)]
struct ActionQueue
{
queue_a: Lock<Vec<Action>>,
@@ -652,11 +648,15 @@ impl ActionQueue
}
}
-impl TypeName for ActionQueue
+impl Default for ActionQueue
{
- fn type_name(&self) -> &'static str
+ fn default() -> Self
{
- type_name::<Self>()
+ Self {
+ queue_a: Lock::new(Vec::new(), type_name::<Vec<Action>>()),
+ queue_b: Lock::new(Vec::new(), type_name::<Vec<Action>>()),
+ active_queue: RefCell::new(ActiveActionQueue::default()),
+ }
}
}
@@ -701,7 +701,7 @@ impl SoleStorage
self.storage.insert(
sole_type_id,
ManuallyDrop::new(StoredSole {
- sole: Arc::new(Lock::new(Box::new(sole))),
+ sole: Arc::new(Lock::new(Box::new(sole), type_name::<SoleT>())),
drop_last,
}),
);
@@ -718,18 +718,9 @@ impl Drop for SoleStorage
for sole in self.storage.values_mut() {
if sole.drop_last {
- tracing::trace!(
- "Sole {} pushed to dropping last queue",
- sole.sole.read_nonblock().unwrap().type_name()
- );
-
soles_to_drop_last.push(sole);
continue;
}
- tracing::trace!(
- "Dropping sole {}",
- sole.sole.read_nonblock().unwrap().type_name()
- );
unsafe {
ManuallyDrop::drop(sole);
@@ -737,11 +728,6 @@ impl Drop for SoleStorage
}
for sole in &mut soles_to_drop_last {
- tracing::trace!(
- "Dropping sole {} last",
- sole.sole.read_nonblock().unwrap().type_name()
- );
-
unsafe {
ManuallyDrop::drop(sole);
}
diff --git a/ecs/src/lock.rs b/ecs/src/lock.rs
index d6ed40e..0b36922 100644
--- a/ecs/src/lock.rs
+++ b/ecs/src/lock.rs
@@ -9,23 +9,21 @@ use parking_lot::{
RwLockWriteGuard,
};
-use crate::type_name::TypeName;
-
-#[derive(Debug, Default)]
+#[derive(Debug)]
pub struct Lock<Value>
-where
- Value: TypeName,
{
inner: RwLock<Value>,
+ value_type_name: &'static str,
}
impl<Value> Lock<Value>
-where
- Value: TypeName,
{
- pub fn new(value: Value) -> Self
+ pub fn new(value: Value, value_type_name: &'static str) -> Self
{
- Self { inner: RwLock::new(value) }
+ Self {
+ inner: RwLock::new(value),
+ value_type_name,
+ }
}
/// Tries to a acquire a handle to the resource with read access.
@@ -36,9 +34,12 @@ where
{
let guard = self.inner.try_read().ok_or(Error::ReadUnavailable)?;
- tracing::trace!("Acquired lock to value of type {}", guard.type_name());
+ tracing::trace!("Acquired lock to value of type {}", self.value_type_name);
- Ok(ReadGuard { inner: guard })
+ Ok(ReadGuard {
+ inner: guard,
+ value_type_name: self.value_type_name,
+ })
}
/// Tries to a acquire a handle to the resource with mutable access.
@@ -51,15 +52,13 @@ where
tracing::trace!(
"Acquired mutable lock to value of type {}",
- guard.type_name()
+ self.value_type_name
);
- Ok(WriteGuard { inner: guard })
- }
-
- pub fn into_inner(self) -> Value
- {
- self.inner.into_inner()
+ Ok(WriteGuard {
+ inner: guard,
+ value_type_name: self.value_type_name,
+ })
}
}
@@ -75,23 +74,20 @@ pub enum Error
#[derive(Debug)]
pub struct ReadGuard<'guard, Value>
-where
- Value: TypeName,
{
inner: RwLockReadGuard<'guard, Value>,
+ value_type_name: &'static str,
}
impl<'guard, Value> ReadGuard<'guard, Value>
-where
- Value: TypeName,
{
pub fn map<NewValue>(
self,
func: impl FnOnce(&Value) -> &NewValue,
) -> MappedReadGuard<'guard, NewValue>
- where
- NewValue: TypeName,
{
+ let value_type_name = self.value_type_name;
+
// The 'inner' field cannot be moved out of ReadGuard in a normal way since
// ReadGuard implements Drop
let inner = unsafe { std::ptr::read(&self.inner) };
@@ -99,13 +95,12 @@ where
MappedReadGuard {
inner: RwLockReadGuard::map(inner, func),
+ value_type_name,
}
}
}
impl<Value> Deref for ReadGuard<'_, Value>
-where
- Value: TypeName,
{
type Target = Value;
@@ -116,26 +111,21 @@ where
}
impl<Value> Drop for ReadGuard<'_, Value>
-where
- Value: TypeName,
{
fn drop(&mut self)
{
- tracing::trace!("Dropped lock to value of type {}", self.type_name());
+ tracing::trace!("Dropped lock to value of type {}", self.value_type_name);
}
}
#[derive(Debug)]
pub struct MappedReadGuard<'guard, Value>
-where
- Value: TypeName,
{
inner: MappedRwLockReadGuard<'guard, Value>,
+ value_type_name: &'static str,
}
impl<Value> Deref for MappedReadGuard<'_, Value>
-where
- Value: TypeName,
{
type Target = Value;
@@ -146,34 +136,32 @@ where
}
impl<Value> Drop for MappedReadGuard<'_, Value>
-where
- Value: TypeName,
{
fn drop(&mut self)
{
- tracing::trace!("Dropped mapped lock to value of type {}", self.type_name());
+ tracing::trace!(
+ "Dropped mapped lock to value of type {}",
+ self.value_type_name
+ );
}
}
#[derive(Debug)]
pub struct WriteGuard<'guard, Value>
-where
- Value: TypeName,
{
inner: RwLockWriteGuard<'guard, Value>,
+ value_type_name: &'static str,
}
impl<'guard, Value> WriteGuard<'guard, Value>
-where
- Value: TypeName,
{
pub fn map<NewValue>(
self,
func: impl FnOnce(&mut Value) -> &mut NewValue,
) -> MappedWriteGuard<'guard, NewValue>
- where
- NewValue: TypeName,
{
+ let value_type_name = self.value_type_name;
+
// The 'inner' field cannot be moved out of ReadGuard in a normal way since
// ReadGuard implements Drop
let inner = unsafe { std::ptr::read(&self.inner) };
@@ -181,13 +169,12 @@ where
MappedWriteGuard {
inner: RwLockWriteGuard::map(inner, func),
+ value_type_name,
}
}
}
impl<Value> Deref for WriteGuard<'_, Value>
-where
- Value: TypeName,
{
type Target = Value;
@@ -198,8 +185,6 @@ where
}
impl<Value> DerefMut for WriteGuard<'_, Value>
-where
- Value: TypeName,
{
fn deref_mut(&mut self) -> &mut Self::Target
{
@@ -208,26 +193,24 @@ where
}
impl<Value> Drop for WriteGuard<'_, Value>
-where
- Value: TypeName,
{
fn drop(&mut self)
{
- tracing::trace!("Dropped mutable lock to value of type {}", self.type_name());
+ tracing::trace!(
+ "Dropped mutable lock to value of type {}",
+ self.value_type_name
+ );
}
}
#[derive(Debug)]
pub struct MappedWriteGuard<'guard, Value>
-where
- Value: TypeName,
{
inner: MappedRwLockWriteGuard<'guard, Value>,
+ value_type_name: &'static str,
}
impl<Value> Deref for MappedWriteGuard<'_, Value>
-where
- Value: TypeName,
{
type Target = Value;
@@ -238,8 +221,6 @@ where
}
impl<Value> DerefMut for MappedWriteGuard<'_, Value>
-where
- Value: TypeName,
{
fn deref_mut(&mut self) -> &mut Self::Target
{
@@ -248,14 +229,12 @@ where
}
impl<Value> Drop for MappedWriteGuard<'_, Value>
-where
- Value: TypeName,
{
fn drop(&mut self)
{
tracing::trace!(
"Dropped mapped mutable lock to value of type {}",
- self.type_name()
+ self.value_type_name
);
}
}
diff --git a/ecs/src/query.rs b/ecs/src/query.rs
index d7d2d1c..7542f0d 100644
--- a/ecs/src/query.rs
+++ b/ecs/src/query.rs
@@ -1,15 +1,15 @@
use std::any::type_name;
-use std::borrow::Cow;
use std::marker::PhantomData;
use seq_macro::seq;
-use crate::component::{Component, FromLockedOptional, Ref as ComponentRef};
+use crate::component::{Component, HandleFromEntityComponentRef, Ref as ComponentRef};
use crate::entity::Handle as EntityHandle;
use crate::query::flexible::{Iter as FlexibleQueryIter, Query as FlexibleQuery};
use crate::system::{Param as SystemParam, System};
use crate::uid::Uid;
-use crate::util::VecExt;
+use crate::util::array_vec::ArrayVec;
+use crate::util::Array;
use crate::World;
pub mod flexible;
@@ -22,7 +22,8 @@ where
FieldlessTerms: TermWithoutFieldTuple,
{
world: &'world World,
- inner: FlexibleQuery<'world, 'static>,
+ // A term tuple type can have a maximum of 17 elements
+ inner: FlexibleQuery<'world, 17>,
_pd: PhantomData<(FieldTerms, FieldlessTerms)>,
}
@@ -147,43 +148,47 @@ where
}
#[derive(Debug)]
-pub struct Terms<'a>
+pub struct Terms<const MAX_TERM_CNT: usize>
{
- required_components: Cow<'a, [Uid]>,
- excluded_components: Cow<'a, [Uid]>,
+ required_components: ArrayVec<Uid, MAX_TERM_CNT>,
+ excluded_components: ArrayVec<Uid, MAX_TERM_CNT>,
}
-impl<'a> Terms<'a>
+impl<const MAX_TERM_CNT: usize> Terms<MAX_TERM_CNT>
{
- pub fn builder() -> TermsBuilder<'a>
+ pub fn builder() -> TermsBuilder<MAX_TERM_CNT>
{
TermsBuilder::default()
}
}
#[derive(Debug, Default)]
-pub struct TermsBuilder<'a>
+pub struct TermsBuilder<const MAX_TERM_CNT: usize>
{
- required_components: Cow<'a, [Uid]>,
- excluded_components: Cow<'a, [Uid]>,
+ required_components: ArrayVec<Uid, MAX_TERM_CNT>,
+ excluded_components: ArrayVec<Uid, MAX_TERM_CNT>,
}
-pub trait TermsBuilderInterface<'a>
+pub trait TermsBuilderInterface
{
fn with<ComponentT: Component>(self) -> Self;
fn without<ComponentT: Component>(self) -> Self;
- fn with_required_ids(self, ids: &'a mut [Uid]) -> Self;
+ fn with_required(self, ids: impl Array<Uid>) -> Self;
}
macro_rules! impl_terms_builder {
($($impl_content: tt)*) => {
- impl<'a> TermsBuilderInterface<'a> for TermsBuilder<'a> {
+ impl<const MAX_TERM_CNT: usize>
+ TermsBuilderInterface for TermsBuilder<MAX_TERM_CNT>
+ {
$($impl_content)*
}
- impl<'a> TermsBuilderInterface<'a> for &mut TermsBuilder<'a> {
+ impl<const MAX_TERM_CNT: usize>
+ TermsBuilderInterface for &mut TermsBuilder<MAX_TERM_CNT>
+ {
$($impl_content)*
}
};
@@ -193,13 +198,11 @@ impl_terms_builder! {
#[allow(unused_mut)]
fn with<ComponentT: Component>(mut self) -> Self
{
- if ComponentT::is_optional() {
- return self;
- }
+ let insert_index = self.required_components
+ .partition_point(|id| *id <= ComponentT::id());
self.required_components
- .to_mut()
- .insert_at_partition_point_by_key(ComponentT::id(), |id| *id);
+ .insert(insert_index, ComponentT::id());
self
}
@@ -207,55 +210,51 @@ impl_terms_builder! {
#[allow(unused_mut)]
fn without<ComponentT: Component>(mut self) -> Self
{
- if ComponentT::is_optional() {
- panic!(
- "{}::without cannot take optional component",
- type_name::<Self>()
- );
- }
+ let insert_index = self.excluded_components
+ .partition_point(|id| *id <= ComponentT::id());
self.excluded_components
- .to_mut()
- .insert_at_partition_point_by_key(ComponentT::id(), |id| *id);
+ .insert(insert_index, ComponentT::id());
self
}
#[allow(unused_mut)]
- fn with_required_ids(mut self, ids: &'a mut [Uid]) -> Self
+ fn with_required(mut self, mut ids: impl Array<Uid>) -> Self
{
- if ids.is_empty() {
- return self;
+ if !ids.as_ref().is_sorted() {
+ ids.as_mut().sort();
}
- if !ids.is_sorted() {
- ids.sort();
+ if self.required_components.len() == 0 {
+ self.required_components.extend(ids);
+ return self;
}
- if self.required_components.is_empty() {
- self.required_components = Cow::Borrowed(ids);
+ let mut id_iter = ids.into_iter();
- return self;
- }
+ while let Some(id) = id_iter.next() {
+ let insert_index = self.required_components
+ .partition_point(|other_id| *other_id <= id);
- let first_id_pp_index = self.required_components.partition_point(|req_comp_id| {
- req_comp_id <= ids.first().expect("Cannot happend since not empty")
- });
+ if insert_index == self.required_components.len() {
+ self.required_components.extend([id].into_iter().chain(id_iter));
- let removed = self
- .required_components
- .to_mut()
- .splice(first_id_pp_index..first_id_pp_index, ids.iter().copied());
+ return self;
+ }
+
+ self.required_components
+ .insert(insert_index, id);
- assert_eq!(removed.count(), 0);
+ }
self
}
}
-impl<'a> TermsBuilder<'a>
+impl<const MAX_TERM_CNT: usize> TermsBuilder<MAX_TERM_CNT>
{
- pub fn build(self) -> Terms<'a>
+ pub fn build(self) -> Terms<MAX_TERM_CNT>
{
assert!(self.required_components.is_sorted());
assert!(self.excluded_components.is_sorted());
@@ -269,14 +268,18 @@ impl<'a> TermsBuilder<'a>
pub trait TermWithoutField
{
- fn apply_to_terms_builder(terms_builder: &mut TermsBuilder<'_>);
+ fn apply_to_terms_builder<const MAX_TERM_CNT: usize>(
+ terms_builder: &mut TermsBuilder<MAX_TERM_CNT>,
+ );
}
pub trait TermWithField
{
type Field<'a>;
- fn apply_to_terms_builder(terms_builder: &mut TermsBuilder<'_>);
+ fn apply_to_terms_builder<const MAX_TERM_CNT: usize>(
+ terms_builder: &mut TermsBuilder<MAX_TERM_CNT>,
+ );
fn get_field<'world>(
entity_handle: &EntityHandle<'world>,
@@ -288,7 +291,9 @@ impl<ComponentRefT: ComponentRef> TermWithField for ComponentRefT
{
type Field<'a> = ComponentRefT::Handle<'a>;
- fn apply_to_terms_builder(terms_builder: &mut TermsBuilder<'_>)
+ fn apply_to_terms_builder<const MAX_TERM_CNT: usize>(
+ terms_builder: &mut TermsBuilder<MAX_TERM_CNT>,
+ )
{
terms_builder.with::<ComponentRefT::Component>();
}
@@ -298,15 +303,13 @@ impl<ComponentRefT: ComponentRef> TermWithField for ComponentRefT
world: &'world World,
) -> Self::Field<'world>
{
- Self::Field::from_locked_optional_component(
- entity_handle
- .get_component(ComponentRefT::Component::id())
- .map(|component| component.component()),
+ Self::Field::from_entity_component_ref(
+ entity_handle.get_component(ComponentRefT::Component::id()),
world,
)
.unwrap_or_else(|err| {
panic!(
- "Taking component {} lock failed: {err}",
+ "Creating handle to component {} failed: {err}",
type_name::<ComponentRefT::Component>()
);
})
@@ -315,14 +318,18 @@ impl<ComponentRefT: ComponentRef> TermWithField for ComponentRefT
pub trait TermWithoutFieldTuple
{
- fn apply_terms_to_builder(terms_builder: &mut TermsBuilder<'_>);
+ fn apply_terms_to_builder<const MAX_TERM_CNT: usize>(
+ terms_builder: &mut TermsBuilder<MAX_TERM_CNT>,
+ );
}
pub trait TermWithFieldTuple
{
type Fields<'component>;
- fn apply_terms_to_builder(terms_builder: &mut TermsBuilder<'_>);
+ fn apply_terms_to_builder<const MAX_TERM_CNT: usize>(
+ terms_builder: &mut TermsBuilder<MAX_TERM_CNT>,
+ );
fn get_fields<'component>(
entity_handle: &EntityHandle<'component>,
@@ -411,7 +418,9 @@ macro_rules! impl_term_sequence {
seq!(I in 0..=$c {
impl<#(Term~I: TermWithoutField,)*> TermWithoutFieldTuple for (#(Term~I,)*)
{
- fn apply_terms_to_builder(terms_builder: &mut TermsBuilder<'_>)
+ fn apply_terms_to_builder<const MAX_TERM_CNT: usize>(
+ terms_builder: &mut TermsBuilder<MAX_TERM_CNT>
+ )
{
#(
Term~I::apply_to_terms_builder(terms_builder);
@@ -423,7 +432,9 @@ macro_rules! impl_term_sequence {
{
type Fields<'component> = (#(Term~I::Field<'component>,)*);
- fn apply_terms_to_builder(terms_builder: &mut TermsBuilder<'_>)
+ fn apply_terms_to_builder<const MAX_TERM_CNT: usize>(
+ terms_builder: &mut TermsBuilder<MAX_TERM_CNT>
+ )
{
#(
Term~I::apply_to_terms_builder(terms_builder);
@@ -448,14 +459,22 @@ seq!(C in 0..=16 {
impl TermWithoutFieldTuple for ()
{
- fn apply_terms_to_builder(_terms_builder: &mut TermsBuilder<'_>) {}
+ fn apply_terms_to_builder<const MAX_TERM_CNT: usize>(
+ _terms_builder: &mut TermsBuilder<MAX_TERM_CNT>,
+ )
+ {
+ }
}
impl TermWithFieldTuple for ()
{
type Fields<'component> = ();
- fn apply_terms_to_builder(_terms_builder: &mut TermsBuilder<'_>) {}
+ fn apply_terms_to_builder<const MAX_TERM_CNT: usize>(
+ _terms_builder: &mut TermsBuilder<MAX_TERM_CNT>,
+ )
+ {
+ }
fn get_fields<'component>(
_entity_handle: &EntityHandle<'_>,
diff --git a/ecs/src/query/flexible.rs b/ecs/src/query/flexible.rs
index 652b96f..2f0b5e7 100644
--- a/ecs/src/query/flexible.rs
+++ b/ecs/src/query/flexible.rs
@@ -14,13 +14,13 @@ use crate::World;
/// Low-level entity query structure.
#[derive(Debug)]
-pub struct Query<'world, 'terms>
+pub struct Query<'world, const MAX_TERM_CNT: usize>
{
component_storage: ReadGuard<'world, ComponentStorage>,
- terms: Terms<'terms>,
+ terms: Terms<MAX_TERM_CNT>,
}
-impl<'world, 'terms> Query<'world, 'terms>
+impl<'world, const MAX_TERM_CNT: usize> Query<'world, MAX_TERM_CNT>
{
/// Iterates over the entities matching this query.
#[must_use]
@@ -42,7 +42,7 @@ impl<'world, 'terms> Query<'world, 'terms>
}
}
- pub(crate) fn new(world: &'world World, terms: Terms<'terms>) -> Self
+ pub(crate) fn new(world: &'world World, terms: Terms<MAX_TERM_CNT>) -> Self
{
Self {
component_storage: world
diff --git a/ecs/src/query/term.rs b/ecs/src/query/term.rs
index 7f24147..78668c5 100644
--- a/ecs/src/query/term.rs
+++ b/ecs/src/query/term.rs
@@ -1,7 +1,13 @@
+use std::any::type_name;
use std::marker::PhantomData;
-use crate::component::Component;
-use crate::query::{TermWithoutField, TermsBuilder, TermsBuilderInterface};
+use crate::component::{Component, HandleFromEntityComponentRef, Ref as ComponentRef};
+use crate::query::{
+ TermWithField,
+ TermWithoutField,
+ TermsBuilder,
+ TermsBuilderInterface,
+};
pub struct With<ComponentT>
where
@@ -14,7 +20,9 @@ impl<ComponentT> TermWithoutField for With<ComponentT>
where
ComponentT: Component,
{
- fn apply_to_terms_builder(terms_builder: &mut TermsBuilder<'_>)
+ fn apply_to_terms_builder<const MAX_TERM_CNT: usize>(
+ terms_builder: &mut TermsBuilder<MAX_TERM_CNT>,
+ )
{
terms_builder.with::<ComponentT>();
}
@@ -31,8 +39,42 @@ impl<ComponentT> TermWithoutField for Without<ComponentT>
where
ComponentT: Component,
{
- fn apply_to_terms_builder(terms_builder: &mut TermsBuilder<'_>)
+ fn apply_to_terms_builder<const MAX_TERM_CNT: usize>(
+ terms_builder: &mut TermsBuilder<MAX_TERM_CNT>,
+ )
{
terms_builder.without::<ComponentT>();
}
}
+
+impl<ComponentRefT> TermWithField for Option<ComponentRefT>
+where
+ ComponentRefT: ComponentRef,
+{
+ type Field<'a> = Option<ComponentRefT::Handle<'a>>;
+
+ fn apply_to_terms_builder<const MAX_TERM_CNT: usize>(
+ _terms_builder: &mut TermsBuilder<MAX_TERM_CNT>,
+ )
+ {
+ }
+
+ fn get_field<'world>(
+ entity_handle: &crate::entity::Handle<'world>,
+ world: &'world crate::World,
+ ) -> Self::Field<'world>
+ {
+ Some(
+ ComponentRefT::Handle::<'world>::from_entity_component_ref(
+ Some(entity_handle.get_component(ComponentRefT::Component::id())?),
+ world,
+ )
+ .unwrap_or_else(|err| {
+ panic!(
+ "Creating handle to component {} failed: {err}",
+ type_name::<ComponentRefT::Component>()
+ );
+ }),
+ )
+ }
+}
diff --git a/ecs/src/relationship.rs b/ecs/src/relationship.rs
index 45fa265..e368dd4 100644
--- a/ecs/src/relationship.rs
+++ b/ecs/src/relationship.rs
@@ -6,13 +6,14 @@ use ecs_macros::Component;
use crate::component::storage::Storage as ComponentStorage;
use crate::component::{
Component,
- FromLockedOptional as FromLockedOptionalComponent,
Handle as ComponentHandle,
+ HandleError as ComponentHandleError,
+ HandleFromEntityComponentRef,
HandleMut as ComponentHandleMut,
};
-use crate::lock::{Error as LockError, Lock, ReadGuard};
+use crate::lock::ReadGuard;
use crate::uid::{Kind as UidKind, Uid};
-use crate::World;
+use crate::{EntityComponentRef, World};
/// A relationship to one or more targets.
#[derive(Debug, Component)]
@@ -70,22 +71,24 @@ where
relationship_comp: ComponentHandleMut<'rel_comp, Relationship<Kind, ComponentT>>,
}
-impl<'rel_comp, Kind, ComponentT> FromLockedOptionalComponent<'rel_comp>
+impl<'rel_comp, Kind, ComponentT> HandleFromEntityComponentRef<'rel_comp>
for RelationMut<'rel_comp, Kind, ComponentT>
where
ComponentT: Component,
{
- fn from_locked_optional_component(
- optional_component: Option<&'rel_comp crate::lock::Lock<Box<dyn Component>>>,
+ type Error = ComponentHandleError;
+
+ fn from_entity_component_ref(
+ entity_component_ref: Option<EntityComponentRef<'rel_comp>>,
world: &'rel_comp World,
- ) -> Result<Self, LockError>
+ ) -> Result<Self, Self::Error>
{
- let relationship_comp_handle_from_locked_opt_comp = ComponentHandleMut::<
+ let relationship_comp_handle_from_ent_comp_ref = ComponentHandleMut::<
Relationship<Kind, ComponentT>,
- >::from_locked_optional_component;
+ >::from_entity_component_ref;
let relationship_comp =
- relationship_comp_handle_from_locked_opt_comp(optional_component, world)?;
+ relationship_comp_handle_from_ent_comp_ref(entity_component_ref, world)?;
let component_storage_lock = world
.data
@@ -100,24 +103,6 @@ where
}
}
-impl<'rel_comp, Kind, ComponentT> FromLockedOptionalComponent<'rel_comp>
- for Option<RelationMut<'rel_comp, Kind, ComponentT>>
-where
- ComponentT: Component,
-{
- fn from_locked_optional_component(
- optional_component: Option<&'rel_comp Lock<Box<dyn Component>>>,
- world: &'rel_comp World,
- ) -> Result<Self, crate::lock::Error>
- {
- optional_component
- .map(|component| {
- RelationMut::from_locked_optional_component(Some(component), world)
- })
- .transpose()
- }
-}
-
impl<'rel_comp, Kind, ComponentT> RelationMut<'rel_comp, Kind, ComponentT>
where
ComponentT: Component,
@@ -292,22 +277,23 @@ where
relationship_comp: ComponentHandle<'rel_comp, Relationship<Kind, ComponentT>>,
}
-impl<'rel_comp, Kind, ComponentT> FromLockedOptionalComponent<'rel_comp>
+impl<'rel_comp, Kind, ComponentT> HandleFromEntityComponentRef<'rel_comp>
for Relation<'rel_comp, Kind, ComponentT>
where
ComponentT: Component,
{
- fn from_locked_optional_component(
- optional_component: Option<&'rel_comp Lock<Box<dyn Component>>>,
+ type Error = ComponentHandleError;
+
+ fn from_entity_component_ref(
+ entity_component_ref: Option<EntityComponentRef<'rel_comp>>,
world: &'rel_comp World,
- ) -> Result<Self, LockError>
+ ) -> Result<Self, Self::Error>
{
- let relationship_comp_handle_from_locked_opt_comp = ComponentHandle::<
- Relationship<Kind, ComponentT>,
- >::from_locked_optional_component;
+ let relationship_comp_handle_from_ent_comp_ref =
+ ComponentHandle::<Relationship<Kind, ComponentT>>::from_entity_component_ref;
let relationship_comp =
- relationship_comp_handle_from_locked_opt_comp(optional_component, world)?;
+ relationship_comp_handle_from_ent_comp_ref(entity_component_ref, world)?;
let component_storage_lock = world
.data
@@ -322,24 +308,6 @@ where
}
}
-impl<'rel_comp, Kind, ComponentT> FromLockedOptionalComponent<'rel_comp>
- for Option<Relation<'rel_comp, Kind, ComponentT>>
-where
- ComponentT: Component,
-{
- fn from_locked_optional_component(
- optional_component: Option<&'rel_comp Lock<Box<dyn Component>>>,
- world: &'rel_comp World,
- ) -> Result<Self, crate::lock::Error>
- {
- optional_component
- .map(|component| {
- Relation::from_locked_optional_component(Some(component), world)
- })
- .transpose()
- }
-}
-
impl<'rel_comp, Kind, ComponentT> Relation<'rel_comp, Kind, ComponentT>
where
ComponentT: Component,
diff --git a/ecs/src/sole.rs b/ecs/src/sole.rs
index 5af5ce3..1cce419 100644
--- a/ecs/src/sole.rs
+++ b/ecs/src/sole.rs
@@ -6,11 +6,10 @@ use std::sync::{Arc, Weak};
use crate::lock::{Lock, WriteGuard};
use crate::system::{Param as SystemParam, System};
-use crate::type_name::TypeName;
use crate::World;
/// A type which has a single instance and is shared globally.
-pub trait Sole: Any + TypeName
+pub trait Sole: Any
{
fn drop_last(&self) -> bool;
@@ -40,14 +39,6 @@ impl Debug for dyn Sole
}
}
-impl TypeName for Box<dyn Sole>
-{
- fn type_name(&self) -> &'static str
- {
- self.as_ref().type_name()
- }
-}
-
/// Holds a reference to a globally shared singleton value.
#[derive(Debug)]
pub struct Single<'world, SoleT: Sole>
diff --git a/ecs/src/system/stateful.rs b/ecs/src/system/stateful.rs
index 9d911ee..54f6979 100644
--- a/ecs/src/system/stateful.rs
+++ b/ecs/src/system/stateful.rs
@@ -1,4 +1,4 @@
-use std::any::{Any, TypeId};
+use std::any::{type_name, Any, TypeId};
use std::panic::{RefUnwindSafe, UnwindSafe};
use hashbrown::HashMap;
@@ -25,7 +25,7 @@ use crate::World;
pub struct Stateful<Func>
{
func: Func,
- local_components: HashMap<Uid, Lock<Box<dyn Component>>>,
+ local_components: HashMap<Uid, Lock<Box<dyn Any>>>,
}
macro_rules! impl_system {
@@ -127,7 +127,10 @@ macro_rules! impl_system {
self.local_components
.insert(
LocalComponent::id(),
- Lock::new(Box::new(local_component))
+ Lock::new(
+ Box::new(local_component),
+ type_name::<LocalComponent>()
+ )
);
}
}
diff --git a/ecs/src/type_name.rs b/ecs/src/type_name.rs
deleted file mode 100644
index 54179be..0000000
--- a/ecs/src/type_name.rs
+++ /dev/null
@@ -1,15 +0,0 @@
-use std::any::type_name;
-
-pub trait TypeName
-{
- /// Returns the name of this type.
- fn type_name(&self) -> &'static str;
-}
-
-impl<Item> TypeName for Vec<Item>
-{
- fn type_name(&self) -> &'static str
- {
- type_name::<Self>()
- }
-}
diff --git a/ecs/src/util.rs b/ecs/src/util.rs
index 6f7aed7..eb06ab4 100644
--- a/ecs/src/util.rs
+++ b/ecs/src/util.rs
@@ -4,6 +4,8 @@ use std::ops::{BitAnd, Deref};
use hashbrown::HashMap;
+pub mod array_vec;
+
pub trait VecExt<Item>
{
fn insert_at_partition_point_by_key<Key>(
diff --git a/ecs/src/util/array_vec.rs b/ecs/src/util/array_vec.rs
new file mode 100644
index 0000000..648c976
--- /dev/null
+++ b/ecs/src/util/array_vec.rs
@@ -0,0 +1,115 @@
+use std::mem::{transmute, MaybeUninit};
+use std::ops::{Deref, DerefMut};
+
+#[derive(Debug)]
+pub struct ArrayVec<Item, const CAPACITY: usize>
+{
+ items: [MaybeUninit<Item>; CAPACITY],
+ len: usize,
+}
+
+impl<Item, const CAPACITY: usize> ArrayVec<Item, CAPACITY>
+{
+ pub fn new() -> Self
+ {
+ Self::default()
+ }
+
+ #[inline]
+ #[must_use]
+ pub fn len(&self) -> usize
+ {
+ self.len
+ }
+
+ pub fn push(&mut self, item: Item)
+ {
+ assert!(self.len < CAPACITY);
+
+ self.items[self.len].write(item);
+
+ self.len += 1;
+ }
+
+ pub fn insert(&mut self, index: usize, item: Item)
+ {
+ assert!(index <= self.len);
+ assert!(self.len < CAPACITY);
+
+ if index == self.len {
+ self.push(item);
+ return;
+ }
+
+ unsafe {
+ std::ptr::copy(
+ &self.items[index],
+ &mut self.items[index + 1],
+ self.len - index,
+ );
+ }
+
+ self.items[index].write(item);
+
+ self.len += 1;
+ }
+}
+
+impl<Item, const CAPACITY: usize> Extend<Item> for ArrayVec<Item, CAPACITY>
+{
+ fn extend<IntoIter: IntoIterator<Item = Item>>(&mut self, iter: IntoIter)
+ {
+ for item in iter {
+ self.push(item);
+ }
+ }
+}
+
+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]) }
+ }
+}
+
+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],
+ )
+ }
+ }
+}
+
+impl<Item, const CAPACITY: usize> Deref for ArrayVec<Item, CAPACITY>
+{
+ type Target = [Item];
+
+ fn deref(&self) -> &Self::Target
+ {
+ self.as_ref()
+ }
+}
+
+impl<Item, const CAPACITY: usize> DerefMut for ArrayVec<Item, CAPACITY>
+{
+ fn deref_mut(&mut self) -> &mut Self::Target
+ {
+ self.as_mut()
+ }
+}
+
+impl<Item, const CAPACITY: usize> Default for ArrayVec<Item, CAPACITY>
+{
+ fn default() -> Self
+ {
+ Self {
+ items: [const { MaybeUninit::uninit() }; CAPACITY],
+ len: 0,
+ }
+ }
+}
diff --git a/ecs/tests/query.rs b/ecs/tests/query.rs
index 0f02bd3..6e747e3 100644
--- a/ecs/tests/query.rs
+++ b/ecs/tests/query.rs
@@ -210,7 +210,7 @@ fn query_archetype_exists_with_4_comps_diff_to_next_archetype_and_opt_comp()
let ent_2_id = world.create_entity((A, B, G));
assert_query_finds_ents(
- world.query::<(&A, &Option<E>, &G), ()>(),
+ world.query::<(&A, Option<&E>, &G), ()>(),
vec![ent_1_id, ent_2_id],
);
}
@@ -249,7 +249,7 @@ fn query_archetype_nonexistant_and_opt_comp()
world.create_entity((A, B, C, G, F));
assert_query_finds_ents(
- world.query::<(&A, &E, &Option<D>), ()>(),
+ world.query::<(&A, &E, Option<&D>), ()>(),
vec![ent_2_id, ent_3_id],
);
}
diff --git a/engine/src/renderer/opengl.rs b/engine/src/renderer/opengl.rs
index 5665860..84af219 100644
--- a/engine/src/renderer/opengl.rs
+++ b/engine/src/renderer/opengl.rs
@@ -72,11 +72,11 @@ use crate::window::Window;
type RenderableEntity<'a> = (
&'a Mesh,
&'a Material,
- &'a Option<MaterialFlags>,
- &'a Option<Position>,
- &'a Option<Scale>,
- &'a Option<DrawFlags>,
- &'a Option<GlObjects>,
+ Option<&'a MaterialFlags>,
+ Option<&'a Position>,
+ Option<&'a Scale>,
+ Option<&'a DrawFlags>,
+ Option<&'a GlObjects>,
);
#[derive(Debug, Default)]