diff --git a/type-id-test-rs b/type-id-test-rs deleted file mode 160000 index 6e707fe..0000000 --- a/type-id-test-rs +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 6e707fe6a877971c9f51ea0b3d4e90d76811be33 diff --git a/type-id-test-rs/.gitignore b/type-id-test-rs/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/type-id-test-rs/.gitignore @@ -0,0 +1 @@ +/target diff --git a/type-id-test-rs/Cargo.lock b/type-id-test-rs/Cargo.lock new file mode 100644 index 0000000..70a7578 --- /dev/null +++ b/type-id-test-rs/Cargo.lock @@ -0,0 +1,53 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "component-macro" +version = "0.1.0" +dependencies = [ + "quote", + "syn", +] + +[[package]] +name = "proc-macro2" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "syn" +version = "2.0.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44cfb93f38070beee36b3fef7d4f5a16f27751d94b187b666a5cc5e9b0d30687" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "type-id-test-rs" +version = "0.1.0" +dependencies = [ + "component-macro", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" diff --git a/type-id-test-rs/Cargo.toml b/type-id-test-rs/Cargo.toml new file mode 100644 index 0000000..3a4316d --- /dev/null +++ b/type-id-test-rs/Cargo.toml @@ -0,0 +1,10 @@ +workspace = { members = ["component-macro"] } +[package] +name = "type-id-test-rs" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +component-macro = { version = "0.1.0", path = "./component-macro" } diff --git a/type-id-test-rs/component-macro/Cargo.toml b/type-id-test-rs/component-macro/Cargo.toml new file mode 100644 index 0000000..add0db6 --- /dev/null +++ b/type-id-test-rs/component-macro/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "component-macro" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[lib] +proc-macro = true + +[dependencies] +quote = "1.0.35" +syn = "2.0.58" diff --git a/type-id-test-rs/component-macro/src/lib.rs b/type-id-test-rs/component-macro/src/lib.rs new file mode 100644 index 0000000..f8ef66b --- /dev/null +++ b/type-id-test-rs/component-macro/src/lib.rs @@ -0,0 +1,26 @@ +use proc_macro::TokenStream; +use quote::quote; +use syn; + +#[proc_macro_derive(Component)] +pub fn derive_component(input: TokenStream) -> TokenStream { + let ast = syn::parse(input).unwrap(); + impl_derive_macro(&ast) +} + +fn impl_derive_macro(ast: &syn::DeriveInput) -> TokenStream { + let name = &ast.ident; + let gen = quote! { + impl Component for #name { + fn inner_type_id(&self) -> TypeId { + TypeId::of::() + } + fn as_any(&mut self) -> &mut dyn Any { + self + } + } + }; + gen.into() +} + + diff --git a/type-id-test-rs/src/component.rs b/type-id-test-rs/src/component.rs new file mode 100644 index 0000000..1bdc386 --- /dev/null +++ b/type-id-test-rs/src/component.rs @@ -0,0 +1,6 @@ +use std::any::{Any, TypeId}; + +pub trait Component { + fn inner_type_id(&self) -> TypeId; + fn as_any(&mut self) -> &mut dyn Any; +} diff --git a/type-id-test-rs/src/main.rs b/type-id-test-rs/src/main.rs new file mode 100644 index 0000000..8cbe276 --- /dev/null +++ b/type-id-test-rs/src/main.rs @@ -0,0 +1,124 @@ +#![allow(dead_code)] + +use std::any::{Any, TypeId}; + +use component::Component; +use component_macro::Component; + +mod component; + +struct Context<'a> { + entities: &'a mut Vec<(u64, Vec>)>, +} + +impl<'a> Context<'a> { + pub fn entities_with_component(&self) -> Vec { + let entity_type_id = TypeId::of::(); + self.entities + .iter() + .filter_map(|(id, components)| { + let contains_component = components.iter().any(|entity| { + let is_id = (*entity).inner_type_id() == entity_type_id; + is_id + }); + if contains_component { + Some(*id) + } else { + None + } + }) + .collect() + } + + pub fn entity_component(&mut self, entity_id: u64) -> &mut T { + let entity_type_id = TypeId::of::(); + let (_id, components) = self + .entities + .iter_mut() + .find(|(id, _)| *id == entity_id) + .unwrap(); + + let component = components + .iter_mut() + .find_map(|entity| { + let is_id = (*entity).inner_type_id() == entity_type_id; + if is_id { + Some(entity.as_any().downcast_mut::().unwrap()) + } else { + None + } + }) + .unwrap(); + component + } +} + +trait System { + fn on_update(&self, context: &mut Context); +} + +#[derive(Component)] +struct Position { + pub x: i32, + pub y: i32, +} + +#[derive(Component)] +struct NotPosition { + pub a: i32, + pub b: i32, +} + +struct Gravity; +struct NotGravity; + +impl System for Gravity { + fn on_update(&self, context: &mut Context) { + let entities_with_position = context.entities_with_component::(); + for entity_id in entities_with_position { + let position = context.entity_component::(entity_id); + position.y -= 1; + } + } +} + +impl System for NotGravity { + fn on_update(&self, context: &mut Context) { + let entities_with_position = context.entities_with_component::(); + for entity_id in entities_with_position { + let position = context.entity_component::(entity_id); + position.a -= 1; + } + } +} + +fn main() { + let mut entities: Vec<(u64, Vec>)> = Vec::new(); + let mut systems: Vec> = Vec::new(); + + systems.push(Box::new(Gravity)); + systems.push(Box::new(NotGravity)); + entities.push(( + 0, + vec![ + Box::new(Position { x: 0, y: 0 }), + Box::new(NotPosition { a: 0, b: 0 }), + ], + )); + + entities.push(( + 1, + vec![ + Box::new(Position { x: 0, y: 0 }), + Box::new(NotPosition { a: 0, b: 0 }), + ], + )); + + let mut context = Context { + entities: &mut entities, + }; + + for system in systems { + system.on_update(&mut context) + } +}