EntityArchetype proc macro

This commit is contained in:
Carter Anderson 2020-01-19 02:02:12 -08:00
parent 48cf0190ad
commit ec4ca5559f
34 changed files with 94 additions and 82 deletions

View file

@ -6,7 +6,6 @@ edition = "2018"
[dependencies] [dependencies]
legion = { git = "https://github.com/TomGillen/legion.git", rev = "940ef3bfcb77e5d074ee3184b776ff1600da228d", features = ["serde-1"] } legion = { git = "https://github.com/TomGillen/legion.git", rev = "940ef3bfcb77e5d074ee3184b776ff1600da228d", features = ["serde-1"] }
legion_transform = { path = "src/transform" }
wgpu = { git = "https://github.com/gfx-rs/wgpu-rs.git", rev = "4a0da16fe6764c4e1dc918a31cbd7467d404df51"} wgpu = { git = "https://github.com/gfx-rs/wgpu-rs.git", rev = "4a0da16fe6764c4e1dc918a31cbd7467d404df51"}
glam = "0.8.4" glam = "0.8.4"
winit = "0.20.0-alpha6" winit = "0.20.0-alpha6"
@ -21,6 +20,8 @@ uuid = { version = "0.8", features = ["v4"] }
erased-serde = "0.3" erased-serde = "0.3"
type-uuid = "0.1" type-uuid = "0.1"
shaderc = "0.6" shaderc = "0.6"
bevy_derive = { path = "bevy_derive" }
bevy_transform = { path = "bevy_transform" }
[profile.release] [profile.release]
debug = true debug = true

16
bevy_derive/Cargo.toml Normal file
View file

@ -0,0 +1,16 @@
[package]
name = "bevy_derive"
version = "0.1.0"
authors = ["Carter Anderson <mcanders1@gmail.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[lib]
proc-macro = true
[dependencies]
syn = "1.0"
quote = "1.0"
[dev-dependencies]

25
bevy_derive/src/lib.rs Normal file
View file

@ -0,0 +1,25 @@
use proc_macro::TokenStream;
use syn::{parse_macro_input, DeriveInput, Data, DataStruct, Fields};
use quote::quote;
#[proc_macro_derive(EntityArchetype)]
pub fn derive_entity_archetype(input: TokenStream) -> TokenStream {
let ast = parse_macro_input!(input as DeriveInput);
let fields = match &ast.data {
Data::Struct(DataStruct { fields: Fields::Named(fields), .. }) => &fields.named,
_ => panic!("expected a struct with named fields"),
};
let struct_name = &ast.ident;
let field_name = fields.iter().map(|field| &field.ident);
TokenStream::from(quote! {
impl EntityArchetype for #struct_name {
fn insert(self, world: &mut World) -> Entity {
*world.insert((), vec![(
#(self.#field_name),*
)]).first().unwrap()
}
}
})
}

View file

@ -1,5 +1,5 @@
[package] [package]
name = "legion_transform" name = "bevy_transform"
version = "0.3.0" version = "0.3.0"
authors = ["Alec Thilenius <alec@thilenius.com>"] authors = ["Alec Thilenius <alec@thilenius.com>"]
edition = "2018" edition = "2018"
@ -8,7 +8,6 @@ license = "MIT"
[dependencies] [dependencies]
legion = { git = "https://github.com/TomGillen/legion.git", rev = "940ef3bfcb77e5d074ee3184b776ff1600da228d" } legion = { git = "https://github.com/TomGillen/legion.git", rev = "940ef3bfcb77e5d074ee3184b776ff1600da228d" }
#legion = { path = "../legion" }
glam = "0.8.3" glam = "0.8.3"
log = "0.4" log = "0.4"
rayon = "1.2" rayon = "1.2"

View file

@ -1,5 +1,4 @@
use bevy::prelude::*; use bevy::prelude::*;
use bevy::ecs::*;
fn main() { fn main() {
AppBuilder::new().add_defaults().setup_world(setup).run(); AppBuilder::new().add_defaults().setup_world(setup).run();

View file

@ -3,11 +3,11 @@ use crate::{
asset::*, asset::*,
core::Time, core::Time,
legion::prelude::{Runnable, Schedulable, Schedule, Universe, World}, legion::prelude::{Runnable, Schedulable, Schedule, Universe, World},
legion_transform::transform_system_bundle,
render::{passes::*, *}, render::{passes::*, *},
ui, ui,
}; };
use bevy_transform::transform_system_bundle;
use std::collections::HashMap; use std::collections::HashMap;
pub const UPDATE: &str = "update"; pub const UPDATE: &str = "update";

View file

@ -1,70 +0,0 @@
use crate::prelude::*;
use legion::prelude::*;
// builder macro that makes defaults easy? Object3dBuilder { Option<Material> } impl Builder for Object3dBuilder { }
pub trait EntityArchetype {
fn insert(self, world: &mut World) -> Entity;
// this would make composing entities from multiple archetypes possible
// add_components appears to be missing from World. it will be less efficient without that
// fn add_components(self, world: &mut World);
// generate by macro. maybe a separate macro?
// fn query() -> Query
}
pub struct Object3dEntity {
pub mesh: Handle<Mesh>,
pub material: Material,
pub local_to_world: LocalToWorld,
pub translation: Translation,
}
// TODO: make this a macro
impl EntityArchetype for Object3dEntity {
fn insert(self, world: &mut World) -> Entity {
*world.insert((), vec![(
self.mesh,
self.material,
self.local_to_world,
self.translation,
)]).first().unwrap()
}
}
pub struct LightEntity {
pub light: Light,
pub local_to_world: LocalToWorld,
pub translation: Translation,
pub rotation: Rotation,
}
// TODO: make this a macro
impl EntityArchetype for LightEntity {
fn insert(self, world: &mut World) -> Entity {
*world.insert((), vec![(
self.light,
self.local_to_world,
self.translation,
self.rotation,
)]).first().unwrap()
}
}
pub struct CameraEntity {
pub camera: Camera,
pub active_camera: ActiveCamera,
pub local_to_world: LocalToWorld,
}
// TODO: make this a macro
impl EntityArchetype for CameraEntity {
fn insert(self, world: &mut World) -> Entity {
*world.insert((), vec![(
self.camera,
self.active_camera,
self.local_to_world,
)]).first().unwrap()
}
}

View file

@ -0,0 +1,25 @@
use crate::prelude::*;
use bevy_derive::EntityArchetype;
#[derive(EntityArchetype)]
pub struct Object3dEntity {
pub mesh: Handle<Mesh>,
pub material: Material,
pub local_to_world: LocalToWorld,
pub translation: Translation,
}
#[derive(EntityArchetype)]
pub struct LightEntity {
pub light: Light,
pub local_to_world: LocalToWorld,
pub translation: Translation,
pub rotation: Rotation,
}
#[derive(EntityArchetype)]
pub struct CameraEntity {
pub camera: Camera,
pub active_camera: ActiveCamera,
pub local_to_world: LocalToWorld,
}

View file

@ -0,0 +1,13 @@
use legion::prelude::*;
// builder macro that makes defaults easy? Object3dBuilder { Option<Material> } impl Builder for Object3dBuilder { }
pub trait EntityArchetype {
fn insert(self, world: &mut World) -> Entity;
// this would make composing entities from multiple archetypes possible
// add_components appears to be missing from World. it will be less efficient without that
// fn add_components(self, world: &mut World);
// generate by macro. maybe a separate macro?
// fn query() -> Query
}

View file

@ -1,10 +1,12 @@
mod entity_builder; mod entity_builder;
mod archetypes; mod entity_archetype;
pub mod default_archetypes;
pub use entity_builder::*; pub use entity_builder::*;
pub use archetypes::*; pub use entity_archetype::*;
use crate::prelude::{Children, Entity, SubWorld, World}; use legion::{prelude::{Entity, World}, system::SubWorld};
use bevy_transform::prelude::Children;
pub fn run_on_hierarchy<T>( pub fn run_on_hierarchy<T>(
world: &World, world: &World,

View file

@ -1,7 +1,7 @@
pub mod app; pub mod app;
pub mod asset; pub mod asset;
pub mod core;
pub mod ecs; pub mod ecs;
pub mod core;
pub mod prelude; pub mod prelude;
pub mod render; pub mod render;
pub mod serialization; pub mod serialization;
@ -9,5 +9,5 @@ pub mod ui;
pub use glam as math; pub use glam as math;
pub use legion; pub use legion;
pub use legion_transform; pub use bevy_transform as transform;
pub use wgpu; pub use wgpu;

View file

@ -3,6 +3,8 @@ pub use crate::{
asset::{Asset, AssetStorage, Handle, Mesh, MeshType, Texture, TextureType}, asset::{Asset, AssetStorage, Handle, Mesh, MeshType, Texture, TextureType},
core::Time, core::Time,
ecs, ecs,
ecs::{EntityArchetype, EntityBuilder, EntityBuilderSource},
ecs::default_archetypes::*,
render::{ render::{
ActiveCamera, ActiveCamera2d, Albedo, Camera, CameraType, Instanced, Light, Material, ActiveCamera, ActiveCamera2d, Albedo, Camera, CameraType, Instanced, Light, Material,
}, },
@ -15,5 +17,5 @@ pub use legion::{
system::SubWorld, system::SubWorld,
system::SystemBuilder, system::SystemBuilder,
}; };
pub use legion_transform::prelude::*; pub use bevy_transform::prelude::*;
pub use math::{Mat3, Mat4, Quat, Vec2, Vec3, Vec4}; pub use math::{Mat3, Mat4, Quat, Vec2, Vec3, Vec4};