summaryrefslogtreecommitdiff
path: root/ecs/src/component.rs
diff options
context:
space:
mode:
Diffstat (limited to 'ecs/src/component.rs')
-rw-r--r--ecs/src/component.rs185
1 files changed, 105 insertions, 80 deletions
diff --git a/ecs/src/component.rs b/ecs/src/component.rs
index 525bd98..c01fd75 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,6 +46,9 @@ 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;
@@ -92,19 +94,11 @@ 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>,
+ for<'a> Option<ComponentT::Handle<'a>>: HandleFromEntityComponentRef<'a>,
+ for<'a> Option<ComponentT::HandleMut<'a>>: HandleFromEntityComponentRef<'a>,
{
type Component = ComponentT;
type Handle<'component> = Option<ComponentT::Handle<'component>>;
@@ -115,6 +109,11 @@ where
ComponentT::id()
}
+ fn name(&self) -> &'static str
+ {
+ type_name::<Self>()
+ }
+
fn get_event_uid(&self, event_kind: ComponentEventKind) -> Uid
{
match event_kind {
@@ -133,16 +132,6 @@ where
}
}
-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.
@@ -166,7 +155,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
@@ -212,16 +201,15 @@ impl Metadata
}
}
-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)]
@@ -238,8 +226,7 @@ impl<'a, ComponentT: Component> Handle<'a, ComponentT>
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>()
);
})
@@ -248,36 +235,49 @@ 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()?))
+ fn from_entity_component_ref(
+ entity_component_ref: Option<EntityComponentRef<'comp>>,
+ _world: &'comp World,
+ ) -> Result<Self, Self::Error>
+ {
+ let entity_comp =
+ entity_component_ref.ok_or(HandleError::ComponentDoesNotExist)?;
+
+ Ok(Self::new(
+ entity_comp
+ .component()
+ .read_nonblock()
+ .map_err(AcquireComponentLockFailed)?,
+ ))
}
}
-impl<'comp, ComponentT> FromLockedOptional<'comp> for Option<Handle<'comp, ComponentT>>
+impl<'comp, ComponentT> HandleFromEntityComponentRef<'comp>
+ for Option<Handle<'comp, ComponentT>>
where
ComponentT: Component,
{
- fn from_locked_optional_component(
- optional_component: Option<&'comp Lock<Box<dyn Component>>>,
+ type Error = HandleError;
+
+ 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()?)))
+ entity_component_ref
+ .map(|entity_comp| {
+ Ok(Handle::new(
+ entity_comp
+ .component()
+ .read_nonblock()
+ .map_err(AcquireComponentLockFailed)?,
+ ))
+ })
.transpose()
}
}
@@ -304,11 +304,9 @@ impl<'a, ComponentT: Component> HandleMut<'a, ComponentT>
{
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>()
);
})
@@ -317,36 +315,49 @@ 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()?))
+ fn from_entity_component_ref(
+ entity_component_ref: Option<EntityComponentRef<'comp>>,
+ _world: &'comp World,
+ ) -> Result<Self, Self::Error>
+ {
+ let entity_comp =
+ entity_component_ref.ok_or(HandleError::ComponentDoesNotExist)?;
+
+ Ok(Self::new(
+ entity_comp
+ .component()
+ .write_nonblock()
+ .map_err(AcquireComponentLockFailed)?,
+ ))
}
}
-impl<'comp, ComponentT> FromLockedOptional<'comp> for Option<HandleMut<'comp, ComponentT>>
+impl<'comp, ComponentT> HandleFromEntityComponentRef<'comp>
+ for Option<HandleMut<'comp, ComponentT>>
where
ComponentT: Component,
{
- fn from_locked_optional_component(
- optional_component: Option<&'comp Lock<Box<dyn Component>>>,
+ type Error = HandleError;
+
+ 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()?)))
+ entity_component_ref
+ .map(|entity_comp| {
+ Ok(HandleMut::new(
+ entity_comp
+ .component()
+ .write_nonblock()
+ .map_err(AcquireComponentLockFailed)?,
+ ))
+ })
.transpose()
}
}
@@ -369,6 +380,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 {