Created
September 27, 2016 19:24
-
-
Save anonymous/48527afe13f4bdf5e5cdb9243c5712c5 to your computer and use it in GitHub Desktop.
Shared via Rust Playground
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::marker::Sized; | |
macro_rules! component { | |
($i:expr, $name:ident { $( $dn:ident: $def:ty ),* } ) => ( | |
#[derive(Debug)] | |
struct $name { | |
$($dn: $def),* | |
} | |
impl Component for $name { | |
fn index() -> usize { $i } | |
fn name() -> &'static str { stringify!($name) } | |
} | |
) | |
} | |
pub trait Component: Sized { | |
fn index() -> usize; | |
fn name() -> &'static str { "<>" } | |
} | |
#[derive(Debug)] | |
pub struct ComponentVector<D: Component> { | |
vec: Vec<Option<D>> | |
} | |
#[derive(Debug)] | |
pub struct ECSMemory { | |
component_count: usize, | |
entities: Vec<Entity>, | |
hot: Vec<*mut ()> | |
} | |
#[derive(Debug)] | |
pub struct Entity { | |
component_set: Vec<bool>, | |
memory_index: usize | |
} | |
impl Entity { | |
pub fn new(compcount: usize, mem: usize) -> Self { | |
Entity { | |
component_set: vec![false; compcount], | |
memory_index: mem | |
} | |
} | |
#[inline] | |
pub fn has_component<D: Component>(&self) -> bool { | |
self.component_set[D::index()] | |
} | |
} | |
impl<D> ComponentVector<D> where D: Component { | |
pub fn new(prealloc: usize) -> Self { | |
ComponentVector { | |
vec: Vec::with_capacity(prealloc) | |
} | |
} | |
pub fn fill_to(&mut self, index: usize) { | |
for _ in self.vec.len()..index+1 { | |
self.vec.push(None); | |
} | |
} | |
} | |
impl ECSMemory { | |
pub fn new() -> Self { | |
ECSMemory { | |
component_count: 0usize, | |
entities: vec![], | |
hot: vec![] | |
} | |
} | |
pub fn register_hot<D>(&mut self) where D: Component { | |
// let i = D::index(); | |
self.hot.push(Box::into_raw(Box::new(ComponentVector::<D>::new(128))) as *mut ()); | |
self.component_count += 1; | |
} | |
pub fn create_entity(&mut self) -> usize { | |
let entid = self.entities.len(); | |
self.entities.push(Entity::new(self.component_count, entid)); | |
entid | |
} | |
pub fn add_component<D>(&mut self, ent: usize, comp: D) where D: Component { | |
let vec = { self.get_hot_vector::<D>() }; | |
let ref mut ent = self.entities[ent]; | |
vec.fill_to(ent.memory_index); | |
vec.vec[ent.memory_index] = Some(comp); | |
ent.component_set[D::index()] = true; | |
} | |
pub fn get_component<D>(&mut self, ent: usize) -> &mut D where D: Component { | |
let ref ent = self.entities[ent]; | |
let vec = self.get_hot_vector::<D>(); | |
match vec.vec[ent.memory_index] { | |
Some(ref mut x) => x, | |
None => panic!("pls.") | |
} | |
} | |
pub fn get_hot_vector<'a, 'b, D>(&'a self) -> &'b mut ComponentVector<D> where D: Component { | |
let i = D::index(); | |
let ptr = self.hot[i]; | |
unsafe { _ptr_reference_mut(ptr) } | |
} | |
} | |
#[inline] | |
unsafe fn _drop_component<D: Component>(ptr: *mut D) { | |
Box::from_raw(ptr); | |
println!("Dropped."); | |
} | |
unsafe fn _ptr_reference_mut<'a, T, U>(ptr: *mut U) -> &'a mut T { | |
&mut *(ptr as *mut T) | |
} | |
component!(0, Position { | |
x: f64, | |
y: f64 | |
}); | |
component!(1, Velocity { | |
x: f64, | |
y: f64 | |
}); | |
fn main() { | |
let mut mem = ECSMemory::new(); | |
mem.register_hot::<Position>(); | |
mem.register_hot::<Velocity>(); | |
let ent = mem.create_entity(); | |
let ent2 = mem.create_entity(); | |
mem.add_component(ent, Position { | |
x: 1.0, | |
y: 2.0 | |
}); | |
mem.add_component(ent2, Position { | |
x: 5.0, | |
y: 6.0 | |
}); | |
mem.add_component(ent2, Velocity { | |
x: 3.0, | |
y: 4.0 | |
}); | |
println!("{:?}", mem.get_hot_vector::<Position>()); | |
println!("{:?}", mem.get_hot_vector::<Velocity>()); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment