This commit is contained in:
SimonFJ20 2024-04-05 10:20:54 +02:00
parent 383accdb7c
commit 13c6b2e2e0
8 changed files with 233 additions and 1 deletions

@ -1 +0,0 @@
Subproject commit 6e707fe6a877971c9f51ea0b3d4e90d76811be33

1
type-id-test-rs/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/target

53
type-id-test-rs/Cargo.lock generated Normal file
View File

@ -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"

View File

@ -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" }

View File

@ -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"

View File

@ -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::<Self>()
}
fn as_any(&mut self) -> &mut dyn Any {
self
}
}
};
gen.into()
}

View File

@ -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;
}

124
type-id-test-rs/src/main.rs Normal file
View File

@ -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<Box<dyn Component>>)>,
}
impl<'a> Context<'a> {
pub fn entities_with_component<T: 'static>(&self) -> Vec<u64> {
let entity_type_id = TypeId::of::<T>();
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<T: 'static>(&mut self, entity_id: u64) -> &mut T {
let entity_type_id = TypeId::of::<T>();
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::<T>().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::<Position>();
for entity_id in entities_with_position {
let position = context.entity_component::<Position>(entity_id);
position.y -= 1;
}
}
}
impl System for NotGravity {
fn on_update(&self, context: &mut Context) {
let entities_with_position = context.entities_with_component::<NotPosition>();
for entity_id in entities_with_position {
let position = context.entity_component::<NotPosition>(entity_id);
position.a -= 1;
}
}
}
fn main() {
let mut entities: Vec<(u64, Vec<Box<dyn Component>>)> = Vec::new();
let mut systems: Vec<Box<dyn System>> = 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)
}
}