summaryrefslogtreecommitdiff
path: root/engine-ecs
diff options
context:
space:
mode:
Diffstat (limited to 'engine-ecs')
-rw-r--r--engine-ecs/src/component.rs51
-rw-r--r--engine-ecs/src/entity.rs36
-rw-r--r--engine-ecs/src/lock.rs70
3 files changed, 135 insertions, 22 deletions
diff --git a/engine-ecs/src/component.rs b/engine-ecs/src/component.rs
index 2734731..c163325 100644
--- a/engine-ecs/src/component.rs
+++ b/engine-ecs/src/component.rs
@@ -77,7 +77,7 @@ pub trait Sequence
}
#[derive(Debug)]
-pub struct Handle<'a, DataT: 'static>
+pub struct Handle<'a, DataT: ?Sized + 'static>
{
inner: MappedReadGuard<'a, DataT>,
}
@@ -111,7 +111,25 @@ impl<'comp, DataT: 'static> Handle<'comp, DataT>
}
}
-impl<DataT: 'static> Deref for Handle<'_, DataT>
+impl<'comp> Handle<'comp, dyn Any>
+{
+ pub fn new_any(
+ entity_component_ref: &EntityComponentRef<'comp>,
+ ) -> Result<Self, HandleError>
+ {
+ Ok(Self {
+ inner: ReadGuard::map(
+ entity_component_ref
+ .component()
+ .read_nonblock()
+ .map_err(AcquireLockError)?,
+ |component| &**component,
+ ),
+ })
+ }
+}
+
+impl<DataT: ?Sized + 'static> Deref for Handle<'_, DataT>
{
type Target = DataT;
@@ -122,7 +140,7 @@ impl<DataT: 'static> Deref for Handle<'_, DataT>
}
#[derive(Debug)]
-pub struct HandleMut<'a, DataT: 'static>
+pub struct HandleMut<'a, DataT: ?Sized + 'static>
{
entity_component_ref: EntityComponentRef<'a>,
inner: MappedWriteGuard<'a, DataT>,
@@ -154,7 +172,30 @@ impl<'comp, DataT: 'static> HandleMut<'comp, DataT>
event_submitter: world.event_submitter(),
})
}
+}
+
+impl<'comp> HandleMut<'comp, dyn Any>
+{
+ pub fn new_any(
+ entity_component_ref: &EntityComponentRef<'comp>,
+ world: &'comp World,
+ ) -> Result<Self, HandleError>
+ {
+ let inner = entity_component_ref
+ .component()
+ .write_nonblock()
+ .map_err(AcquireLockError)?;
+
+ Ok(Self {
+ entity_component_ref: entity_component_ref.clone(),
+ inner: WriteGuard::map(inner, |component| &mut **component),
+ event_submitter: world.event_submitter(),
+ })
+ }
+}
+impl<'comp, DataT: ?Sized + 'static> HandleMut<'comp, DataT>
+{
pub fn set_changed(&self)
{
self.event_submitter.submit_event(
@@ -167,7 +208,7 @@ impl<'comp, DataT: 'static> HandleMut<'comp, DataT>
}
}
-impl<DataT: 'static> Deref for HandleMut<'_, DataT>
+impl<DataT: ?Sized + 'static> Deref for HandleMut<'_, DataT>
{
type Target = DataT;
@@ -177,7 +218,7 @@ impl<DataT: 'static> Deref for HandleMut<'_, DataT>
}
}
-impl<DataT: 'static> DerefMut for HandleMut<'_, DataT>
+impl<DataT: ?Sized + 'static> DerefMut for HandleMut<'_, DataT>
{
fn deref_mut(&mut self) -> &mut Self::Target
{
diff --git a/engine-ecs/src/entity.rs b/engine-ecs/src/entity.rs
index f551de1..d7b63be 100644
--- a/engine-ecs/src/entity.rs
+++ b/engine-ecs/src/entity.rs
@@ -1,4 +1,4 @@
-use std::any::type_name;
+use std::any::{type_name, Any};
use std::ops::Deref;
use std::sync::LazyLock;
@@ -122,6 +122,40 @@ impl<'a> Handle<'a>
)
}
+ /// Returns a reference to the component with the ID `id` in this entity.
+ /// `None` is returned if the component isn't found.
+ ///
+ /// # Panics
+ /// Will panic if:
+ /// - The component is borrowed mutably elsewhere
+ #[must_use]
+ pub fn get_any_by_id(&self, id: Uid) -> Option<ComponentHandle<'a, dyn Any>>
+ {
+ let component = self.get_matching_components(id).next()?;
+
+ Some(ComponentHandle::new_any(&component).unwrap_or_else(|err| {
+ panic!("Creating handle to component with id {id} failed: {err}");
+ }))
+ }
+
+ /// Returns a reference to the component with the ID `id` in this entity.
+ /// `None` is returned if the component isn't found.
+ ///
+ /// # Panics
+ /// Will panic if:
+ /// - The component is borrowed elsewhere
+ #[must_use]
+ pub fn get_any_by_id_mut(&self, id: Uid) -> Option<ComponentHandleMut<'a, dyn Any>>
+ {
+ let component = self.get_matching_components(id).next()?;
+
+ Some(
+ ComponentHandleMut::new_any(&component, self.world).unwrap_or_else(|err| {
+ panic!("Creating handle to component with id {id} failed: {err}");
+ }),
+ )
+ }
+
/// Returns a mutable reference to the component with the ID `id` in this entity.
/// `None` is returned if the component isn't found.
///
diff --git a/engine-ecs/src/lock.rs b/engine-ecs/src/lock.rs
index fe4e08b..3db29e8 100644
--- a/engine-ecs/src/lock.rs
+++ b/engine-ecs/src/lock.rs
@@ -82,14 +82,33 @@ pub enum Error
}
#[derive(Debug)]
-pub struct ReadGuard<'guard, Value>
+pub struct ReadGuard<'guard, Value: ?Sized>
{
inner: RwLockReadGuard<'guard, Value>,
value_type_name: &'static str,
}
-impl<'guard, Value> ReadGuard<'guard, Value>
+impl<'guard, Value: ?Sized> ReadGuard<'guard, Value>
{
+ pub fn map<NewValue: ?Sized>(
+ this: Self,
+ func: impl FnOnce(&Value) -> &NewValue,
+ ) -> MappedReadGuard<'guard, NewValue>
+ {
+ let value_type_name = this.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(&raw const this.inner) };
+
+ forget(this);
+
+ MappedReadGuard {
+ inner: RwLockReadGuard::map(inner, func),
+ value_type_name: value_type_name,
+ }
+ }
+
pub fn try_map<NewValue>(
this: Self,
func: impl FnOnce(&Value) -> Option<&NewValue>,
@@ -114,7 +133,7 @@ impl<'guard, Value> ReadGuard<'guard, Value>
}
}
-impl<Value> Deref for ReadGuard<'_, Value>
+impl<Value: ?Sized> Deref for ReadGuard<'_, Value>
{
type Target = Value;
@@ -124,7 +143,7 @@ impl<Value> Deref for ReadGuard<'_, Value>
}
}
-impl<Value> Drop for ReadGuard<'_, Value>
+impl<Value: ?Sized> Drop for ReadGuard<'_, Value>
{
fn drop(&mut self)
{
@@ -133,13 +152,13 @@ impl<Value> Drop for ReadGuard<'_, Value>
}
#[derive(Debug)]
-pub struct MappedReadGuard<'guard, Value>
+pub struct MappedReadGuard<'guard, Value: ?Sized>
{
inner: MappedRwLockReadGuard<'guard, Value>,
value_type_name: &'static str,
}
-impl<Value> Deref for MappedReadGuard<'_, Value>
+impl<Value: ?Sized> Deref for MappedReadGuard<'_, Value>
{
type Target = Value;
@@ -149,7 +168,7 @@ impl<Value> Deref for MappedReadGuard<'_, Value>
}
}
-impl<Value> Drop for MappedReadGuard<'_, Value>
+impl<Value: ?Sized> Drop for MappedReadGuard<'_, Value>
{
fn drop(&mut self)
{
@@ -161,14 +180,33 @@ impl<Value> Drop for MappedReadGuard<'_, Value>
}
#[derive(Debug)]
-pub struct WriteGuard<'guard, Value>
+pub struct WriteGuard<'guard, Value: ?Sized>
{
inner: RwLockWriteGuard<'guard, Value>,
value_type_name: &'static str,
}
-impl<'guard, Value> WriteGuard<'guard, Value>
+impl<'guard, Value: ?Sized> WriteGuard<'guard, Value>
{
+ pub fn map<NewValue: ?Sized>(
+ this: Self,
+ func: impl FnOnce(&mut Value) -> &mut NewValue,
+ ) -> MappedWriteGuard<'guard, NewValue>
+ {
+ let value_type_name = this.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(&raw const this.inner) };
+
+ forget(this);
+
+ MappedWriteGuard {
+ inner: RwLockWriteGuard::map(inner, func),
+ value_type_name: value_type_name,
+ }
+ }
+
pub fn try_map<NewValue>(
this: Self,
func: impl FnOnce(&mut Value) -> Option<&mut NewValue>,
@@ -193,7 +231,7 @@ impl<'guard, Value> WriteGuard<'guard, Value>
}
}
-impl<Value> Deref for WriteGuard<'_, Value>
+impl<Value: ?Sized> Deref for WriteGuard<'_, Value>
{
type Target = Value;
@@ -203,7 +241,7 @@ impl<Value> Deref for WriteGuard<'_, Value>
}
}
-impl<Value> DerefMut for WriteGuard<'_, Value>
+impl<Value: ?Sized> DerefMut for WriteGuard<'_, Value>
{
fn deref_mut(&mut self) -> &mut Self::Target
{
@@ -211,7 +249,7 @@ impl<Value> DerefMut for WriteGuard<'_, Value>
}
}
-impl<Value> Drop for WriteGuard<'_, Value>
+impl<Value: ?Sized> Drop for WriteGuard<'_, Value>
{
fn drop(&mut self)
{
@@ -223,13 +261,13 @@ impl<Value> Drop for WriteGuard<'_, Value>
}
#[derive(Debug)]
-pub struct MappedWriteGuard<'guard, Value>
+pub struct MappedWriteGuard<'guard, Value: ?Sized>
{
inner: MappedRwLockWriteGuard<'guard, Value>,
value_type_name: &'static str,
}
-impl<Value> Deref for MappedWriteGuard<'_, Value>
+impl<Value: ?Sized> Deref for MappedWriteGuard<'_, Value>
{
type Target = Value;
@@ -239,7 +277,7 @@ impl<Value> Deref for MappedWriteGuard<'_, Value>
}
}
-impl<Value> DerefMut for MappedWriteGuard<'_, Value>
+impl<Value: ?Sized> DerefMut for MappedWriteGuard<'_, Value>
{
fn deref_mut(&mut self) -> &mut Self::Target
{
@@ -247,7 +285,7 @@ impl<Value> DerefMut for MappedWriteGuard<'_, Value>
}
}
-impl<Value> Drop for MappedWriteGuard<'_, Value>
+impl<Value: ?Sized> Drop for MappedWriteGuard<'_, Value>
{
fn drop(&mut self)
{