Skip to content

Instantly share code, notes, and snippets.

Created September 27, 2016 19:24
Show Gist options
  • Save anonymous/48527afe13f4bdf5e5cdb9243c5712c5 to your computer and use it in GitHub Desktop.
Save anonymous/48527afe13f4bdf5e5cdb9243c5712c5 to your computer and use it in GitHub Desktop.
Shared via Rust Playground
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