Skip to content

Instantly share code, notes, and snippets.

@krdln
Last active August 29, 2015 14:11
Show Gist options
  • Save krdln/79d22bd633ab5ec52480 to your computer and use it in GitHub Desktop.
Save krdln/79d22bd633ab5ec52480 to your computer and use it in GitHub Desktop.
Macro for entity manager (only main.rs is updated)
fn main() {
{
let em = entity_manager;
em.entities().filter_map(|entity|
Some(entity)
.and_then(|tuple|
entity_manager
.get_component::<X>(&tuple.0)
.map(|obj|tuple.tup_append(obj))
)
.and_then(|tuple|
match *entity_manager.get_component::<Y>(&tuple.0) {
Some(_) => None,
_ => Some(tuple)
}
)
.map(|tuple|
tuple.tup_append(*entity_manager.get_component::<Z>(&tuple.0))
)
)
}
}
#![feature(macro_rules)]
trait TupAppend<T, Result> {
fn tup_append(self, x: T) -> Result;
}
impl<A, B> TupAppend<B, (A,B)> for (A,) {
fn tup_append(self, x: B) -> (A, B) {
(self.0, x)
}
}
impl<A, B, C> TupAppend<C, (A,B,C)> for (A, B) {
fn tup_append(self, x: C) -> (A, B, C) {
(self.0, self.1, x)
}
}
macro_rules! inner(
( $em:ident, $already:expr : ) => ( $already );
( $em:ident, $already:expr : with $ty:path $( $kinds:ident $types:path )* ) => (
inner!( em, $already.and_then(|tuple|
entity_manager
.get_component::<$ty>(&tuple.0)
.map(|obj| tuple.tup_append(obj))
) : $( $kinds $types )* )
);
( $em:ident, $already:expr : without $ty:path $( $kinds:ident $types:path )* ) => (
inner!( em, $already.and_then(|tuple|
if let Some(_) = *entity_manager.get_component::<$ty>(&tuple.0) {
None
} else {
Some(tuple)
}
) : $( $kinds $types )* )
);
( $em:ident, $already:expr : option $ty:path $( $kinds:ident $types:path )* ) => (
inner!( em, $already.map(|tuple|
tuple.tup_append( *entity_manager.get_component::<$ty>(&tuple.0) )
) : $( $kinds $types )* )
);
)
macro_rules! outer(
( $entity_manager:expr : $( $kinds:ident $types:path )* ) => ({
let em = $entity_manager;
em.entities().filter_map(|entity|
inner!(em, Some(entity): $( $kinds $types )* )
)
});
)
fn main() {
outer!(entity_manager: with X without Y option Z);
}
#![feature(macro_rules)]
extern crate ecs;
use std::rc::Rc;
use std::cell::RefCell;
use std::iter::{ IteratorExt };
use ecs::{
// Entity,
EntityManager,
System,
SystemManager,
};
trait TupAppend<T, Result> {
fn tup_append(self, x: T) -> Result;
}
impl<A, B> TupAppend<B, (A,B)> for (A,) {
fn tup_append(self, x: B) -> (A, B) {
(self.0, x)
}
}
impl<A, B, C> TupAppend<C, (A,B,C)> for (A, B) {
fn tup_append(self, x: C) -> (A, B, C) {
(self.0, self.1, x)
}
}
macro_rules! inner(
( $em:ident, $already:expr : ) => ( $already );
( $em:ident, $already:expr : with $ty:path $( $kinds:ident $types:path )* ) => (
inner!( $em, $already.and_then(|tuple| {
let comp = $em.get_component::<$ty>(&tuple.0);
match *comp {
Some(ref obj) => Some( tuple.tup_append(obj) ),
None => None
}
} ) : $( $kinds $types )* )
);
( $em:ident, $already:expr : without $ty:path $( $kinds:ident $types:path )* ) => (
inner!( $em, $already.and_then(|tuple|
if let &Some(_) = $em.get_component::<$ty>(&tuple.0) {
None
} else {
Some(tuple)
}
) : $( $kinds $types )* )
);
( $em:ident, $already:expr : option $ty:path $( $kinds:ident $types:path )* ) => (
inner!( $em, $already.map(|tuple| {
let comp = $em.get_component::<$ty>(&tuple.0).as_ref();
tuple.tup_append( comp )
} ) : $( $kinds $types )* )
);
)
macro_rules! outer(
( $em:ident : $( $kinds:ident $types:path )* ) => (
$em.entities().filter_map(|entity|
inner!($em, Some((entity,)): $( $kinds $types )* )
)
);
)
fn main() {
let mut system_manager = SystemManager::new();
system_manager.register(TestSystem::new());
let rc_entity_manager = EntityManager::new();
{ // Scope for rc_entity_manager borrow
let mut entity_manager = rc_entity_manager.borrow_mut();
entity_manager.register_component::<Renderable>();
entity_manager.register_component::<Loud>();
let test_entity1 = entity_manager.create_entity();
entity_manager.assign_component(&test_entity1, Renderable);
entity_manager.assign_component(&test_entity1, Loud);
let test_entity2 = entity_manager.create_entity();
entity_manager.assign_component(&test_entity2, Renderable);
let test_entity3 = entity_manager.create_entity();
entity_manager.assign_component(&test_entity3, Loud);
entity_manager.destroy_entity(test_entity1);
let test_entity4 = entity_manager.create_entity();
entity_manager.assign_component(&test_entity4, Renderable);
// entity_manager.assign_component(&test_entity4, Loud);
}
system_manager.update::<UpdateArgs, TestSystem>(rc_entity_manager.clone(), &UpdateArgs);
}
#[deriving(Show)]
struct Renderable;
#[deriving(Show)]
struct Loud;
struct TestSystem;
impl TestSystem {
pub fn new() -> TestSystem {
TestSystem
}
}
#[deriving(Show)]
struct UpdateArgs;
impl System<UpdateArgs> for TestSystem {
fn update(&self, entity_manager: Rc<RefCell<EntityManager>>, args: &UpdateArgs) {
println!("1 {}", args);
let entity_manager = entity_manager.borrow();
// include components
for entity in entity_manager.entities() {
if let (
&Some(ref renderable),
&Some(ref loud)
) = (
entity_manager.get_component::<Renderable>(&entity),
entity_manager.get_component::<Loud>(&entity)
) {
println!("1 {}, {}, {}", entity.id(), renderable, loud);
}
}
// exclude components
for entity in entity_manager.entities() {
if let (
&Some(ref renderable),
&None
) = (
entity_manager.get_component::<Renderable>(&entity),
entity_manager.get_component::<Loud>(&entity)
) {
println!("2 {}, {}", entity.id(), renderable);
}
}
// nested get
for entity in entity_manager.entities() {
if let &Some(ref renderable) = entity_manager.get_component::<Renderable>(&entity) {
if let &Some(ref loud) = entity_manager.get_component::<Loud>(&entity) {
println!("3 {}, {}, {}", entity.id(), renderable, loud);
} else {
println!("3 {}, {}", entity.id(), renderable);
}
}
}
// optional component
for entity in entity_manager.entities() {
if let (
&Some(ref renderable),
&ref option_loud
) = (
entity_manager.get_component::<Renderable>(&entity),
entity_manager.get_component::<Loud>(&entity)
) {
println!("4 {}, {}, {}", entity.id(), renderable, option_loud);
}
}
for (entity, renderable, option_loud) in outer!(entity_manager: with Renderable option Loud) {
println!("{}, {}, {}", entity.id(), renderable, option_loud);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment