Created
September 29, 2024 15:11
-
-
Save matthewjberger/b4c7741cc0abea8ee755eeb75804ec56 to your computer and use it in GitHub Desktop.
more ecs ideas in rust
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use std::any::Any; | |
use std::collections::HashMap; | |
use std::marker::PhantomData; | |
// Generic handle type | |
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | |
pub struct Handle<T> { | |
id: usize, | |
_phantom: PhantomData<T>, | |
} | |
// Trait for components | |
pub trait Component: 'static {} | |
// Generic storage for components | |
pub struct ComponentStorage<T: Component> { | |
data: Vec<T>, | |
} | |
impl<T: Component> ComponentStorage<T> { | |
fn new() -> Self { | |
ComponentStorage { data: Vec::new() } | |
} | |
fn insert(&mut self, component: T) -> Handle<T> { | |
let id = self.data.len(); | |
self.data.push(component); | |
Handle { id, _phantom: PhantomData } | |
} | |
fn get(&self, handle: Handle<T>) -> Option<&T> { | |
self.data.get(handle.id) | |
} | |
fn get_mut(&mut self, handle: Handle<T>) -> Option<&mut T> { | |
self.data.get_mut(handle.id) | |
} | |
} | |
// World struct to manage all component storages | |
pub struct World { | |
storages: HashMap<std::any::TypeId, Box<dyn Any>>, | |
} | |
impl World { | |
pub fn new() -> Self { | |
World { storages: HashMap::new() } | |
} | |
pub fn register_component<T: Component>(&mut self) { | |
let type_id = std::any::TypeId::of::<T>(); | |
if !self.storages.contains_key(&type_id) { | |
self.storages.insert(type_id, Box::new(ComponentStorage::<T>::new())); | |
} | |
} | |
pub fn add_component<T: Component>(&mut self, component: T) -> Handle<T> { | |
let type_id = std::any::TypeId::of::<T>(); | |
let storage = self.storages.get_mut(&type_id) | |
.and_then(|boxed| boxed.downcast_mut::<ComponentStorage<T>>()) | |
.expect("Component type not registered"); | |
storage.insert(component) | |
} | |
pub fn get_component<T: Component>(&self, handle: Handle<T>) -> Option<&T> { | |
let type_id = std::any::TypeId::of::<T>(); | |
self.storages.get(&type_id) | |
.and_then(|boxed| boxed.downcast_ref::<ComponentStorage<T>>()) | |
.and_then(|storage| storage.get(handle)) | |
} | |
pub fn get_component_mut<T: Component>(&mut self, handle: Handle<T>) -> Option<&mut T> { | |
let type_id = std::any::TypeId::of::<T>(); | |
self.storages.get_mut(&type_id) | |
.and_then(|boxed| boxed.downcast_mut::<ComponentStorage<T>>()) | |
.and_then(|storage| storage.get_mut(handle)) | |
} | |
} | |
// Example usage | |
impl Component for Camera {} | |
impl Component for Transform {} | |
impl Component for Node {} | |
#[derive(Default, Debug)] | |
struct Camera; | |
#[derive(Default, Debug)] | |
struct Transform; | |
#[derive(Default, Debug)] | |
struct Node; | |
fn main() { | |
let mut world = World::new(); | |
world.register_component::<Camera>(); | |
world.register_component::<Transform>(); | |
world.register_component::<Node>(); | |
let camera_handle = world.add_component(Camera); | |
let transform_handle = world.add_component(Transform); | |
let node_handle = world.add_component(Node); | |
// Use the handles to access the components | |
if let Some(camera) = world.get_component(camera_handle) { | |
println!("Got camera: {:?}", camera); | |
} | |
if let Some(transform) = world.get_component_mut(transform_handle) { | |
println!("Got mutable transform: {:?}", transform); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment