summaryrefslogtreecommitdiff
path: root/engine-ecs/src
diff options
context:
space:
mode:
authorHampusM <hampus@hampusmat.com>2026-06-07 00:41:15 +0200
committerHampusM <hampus@hampusmat.com>2026-06-07 01:20:04 +0200
commit3f099cddf16f2e7e002cc24217ed3cc5da422156 (patch)
treee6ed78738b3b9fff8f4502d4ed909380b9bebf75 /engine-ecs/src
parent582128a649abc2f460ca00f45571deaf28dd526e (diff)
feat(engine-ecs): add component reflection supportHEADmaster
Diffstat (limited to 'engine-ecs/src')
-rw-r--r--engine-ecs/src/component.rs60
-rw-r--r--engine-ecs/src/lib.rs52
2 files changed, 86 insertions, 26 deletions
diff --git a/engine-ecs/src/component.rs b/engine-ecs/src/component.rs
index 17b279b..f881128 100644
--- a/engine-ecs/src/component.rs
+++ b/engine-ecs/src/component.rs
@@ -2,6 +2,7 @@ use std::any::{type_name, Any};
use std::fmt::Debug;
use std::ops::{Deref, DerefMut};
+use engine_ecs_macros::Component;
use seq_macro::seq;
use crate::event::component::Changed;
@@ -30,6 +31,10 @@ pub trait Component: SystemInput + Any
where
Self: Sized;
+ fn type_reflection() -> Option<&'static crate::reflection::Type>
+ where
+ Self: Sized;
+
/// Returns the name of this component.
fn name(&self) -> &'static str;
}
@@ -243,6 +248,7 @@ where
{
Parts::builder()
.name(type_name::<Self>())
+ .type_reflection(Self::type_reflection())
.build(Self::id(), self)
}
}
@@ -252,41 +258,26 @@ where
#[non_exhaustive]
pub struct Parts
{
- id: Uid,
- name: &'static str,
- data: Box<dyn Any>,
+ pub id: Uid,
+ pub name: &'static str,
+ pub type_reflection: Option<&'static crate::reflection::Type>,
+ pub data: Box<dyn Any>,
}
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()
}
-
- pub(crate) fn into_data(self) -> Box<dyn Any>
- {
- self.data
- }
}
#[derive(Debug)]
pub struct PartsBuilder
{
name: &'static str,
+ type_reflection: Option<&'static crate::reflection::Type>,
}
impl PartsBuilder
@@ -299,11 +290,22 @@ impl PartsBuilder
}
#[must_use]
+ pub fn type_reflection(
+ mut self,
+ type_reflection: Option<&'static crate::reflection::Type>,
+ ) -> Self
+ {
+ self.type_reflection = type_reflection;
+ self
+ }
+
+ #[must_use]
pub fn build<Data: 'static>(self, id: Uid, data: Data) -> Parts
{
Parts {
id,
name: self.name,
+ type_reflection: self.type_reflection,
data: Box::new(data),
}
}
@@ -311,7 +313,12 @@ impl PartsBuilder
#[must_use]
pub fn build_with_any_data(self, id: Uid, data: Box<dyn Any>) -> Parts
{
- Parts { id, name: self.name, data }
+ Parts {
+ id,
+ name: self.name,
+ type_reflection: self.type_reflection,
+ data,
+ }
}
}
@@ -319,6 +326,15 @@ impl Default for PartsBuilder
{
fn default() -> Self
{
- Self { name: "(unspecified)" }
+ Self {
+ name: "(unspecified)",
+ type_reflection: None,
+ }
}
}
+
+#[derive(Debug, Clone, Component)]
+pub struct Type
+{
+ pub type_reflection: &'static crate::reflection::Type,
+}
diff --git a/engine-ecs/src/lib.rs b/engine-ecs/src/lib.rs
index 6880a24..2e30bb8 100644
--- a/engine-ecs/src/lib.rs
+++ b/engine-ecs/src/lib.rs
@@ -18,6 +18,7 @@ use crate::component::{
IntoParts as IntoComponentParts,
Parts as ComponentParts,
Sequence as ComponentSequence,
+ Type as ComponentType,
};
use crate::entity::{Declaration as EntityDeclaration, Handle as EntityHandle};
use crate::error::{
@@ -47,6 +48,7 @@ use crate::query::{
TermsBuilderInterface,
MAX_TERM_CNT as QUERY_MAX_TERM_CNT,
};
+use crate::reflection::Type as TypeReflection;
use crate::sole::{Single, Sole};
use crate::stats::Stats;
use crate::system::observer::Observer;
@@ -81,6 +83,8 @@ pub use engine_ecs_macros::{Component, Sole};
pub use crate::query::Query;
+pub extern crate engine_reflection as reflection;
+
#[derive(Debug)]
pub struct World
{
@@ -546,13 +550,12 @@ impl World
let component_iter = components.into_iter();
for component_parts in component_iter {
- let comp_id = component_parts.id();
-
- let comp_name = component_parts.name();
+ let comp_id = component_parts.id;
+ let comp_name = component_parts.name;
if let Err(err) = component_storage.add_entity_component(
entity_uid,
- (comp_id, comp_name, component_parts.into_data()),
+ (comp_id, comp_name, component_parts.data),
) {
tracing::error!("Failed to add component {comp_name} to entity: {err}");
continue;
@@ -562,6 +565,14 @@ impl World
continue;
}
+ if let Some(type_reflection) = component_parts.type_reflection {
+ Self::create_component_type_entity(
+ comp_id,
+ type_reflection,
+ component_storage,
+ );
+ }
+
event_submitter.submit_event(
&Pair::builder()
.relation::<Added>()
@@ -572,6 +583,39 @@ impl World
}
}
+ fn create_component_type_entity(
+ comp_id: Uid,
+ type_reflection: &'static TypeReflection,
+ component_storage: &mut ComponentStorage,
+ )
+ {
+ if let Some(comp_ent_archetype) = component_storage.get_entity_archetype(comp_id)
+ {
+ if comp_ent_archetype.contains_component_with_exact_id(ComponentType::id()) {
+ return;
+ }
+ } else {
+ if let Err(EntityAlreadyExistsError) =
+ component_storage.create_entity(comp_id)
+ {
+ unreachable!();
+ }
+ }
+
+ let ComponentParts {
+ id: comp_type_id,
+ name: comp_type_name,
+ type_reflection: _,
+ data: comp_type_data,
+ } = ComponentType { type_reflection }.into_parts();
+
+ if let Err(err) = component_storage
+ .add_entity_component(comp_id, (comp_type_id, comp_type_name, comp_type_data))
+ {
+ tracing::error!("Failed to add component {comp_type_name} to entity: {err}");
+ }
+ }
+
fn remove_entity_components(
entity_uid: Uid,
component_ids: impl IntoIterator<Item = Uid>,