rework marco modules, crate-ify ui

This commit is contained in:
Carter Anderson 2020-04-06 14:20:53 -07:00
parent 016bf2152c
commit b19e3004b8
22 changed files with 211 additions and 97 deletions

View File

@ -17,6 +17,7 @@ bevy_diagnostic = { path = "bevy_diagnostic" }
bevy_input = { path = "bevy_input" } bevy_input = { path = "bevy_input" }
bevy_render = { path = "bevy_render" } bevy_render = { path = "bevy_render" }
bevy_transform = { path = "bevy_transform" } bevy_transform = { path = "bevy_transform" }
bevy_ui = { path = "bevy_ui" }
bevy_window = { path = "bevy_window" } bevy_window = { path = "bevy_window" }
bevy_wgpu = { path = "bevy_wgpu", optional = true } bevy_wgpu = { path = "bevy_wgpu", optional = true }
bevy_winit = { path = "bevy_winit", optional = true } bevy_winit = { path = "bevy_winit", optional = true }

View File

@ -1,5 +1,6 @@
mod app; mod app;
mod app_builder; mod app_builder;
mod entity_archetype;
mod event; mod event;
mod plugin; mod plugin;
pub mod schedule_plan; pub mod schedule_plan;
@ -8,5 +9,6 @@ pub mod stage;
pub use app::*; pub use app::*;
pub use app_builder::*; pub use app_builder::*;
pub use plugin::*; pub use entity_archetype::*;
pub use event::*; pub use event::*;
pub use plugin::*;

View File

@ -1,5 +1,6 @@
pub mod bytes; pub mod bytes;
pub mod time; pub mod time;
pub mod transform;
use bevy_app::{stage, AppBuilder, AppPlugin}; use bevy_app::{stage, AppBuilder, AppPlugin};
use bevy_transform::transform_system_bundle; use bevy_transform::transform_system_bundle;

View File

@ -1,10 +1,3 @@
pub mod default_archetypes;
mod entity_archetype;
mod world_builder;
pub use entity_archetype::*;
pub use world_builder::*;
use bevy_transform::prelude::Children; use bevy_transform::prelude::Children;
use legion::{ use legion::{
prelude::{Entity, World}, prelude::{Entity, World},

View File

@ -0,0 +1,5 @@
mod hierarchy;
mod world_builder;
pub use hierarchy::*;
pub use world_builder::*;

View File

@ -1,4 +1,4 @@
use crate::ecs::EntityArchetype; use bevy_app::EntityArchetype;
use bevy_transform::components::{LocalToParent, Parent}; use bevy_transform::components::{LocalToParent, Parent};
use legion::{ use legion::{
filter::{ChunksetFilterData, Filter}, filter::{ChunksetFilterData, Filter},
@ -26,6 +26,7 @@ pub struct WorldBuilder<'a> {
parent_entity: Option<Entity>, parent_entity: Option<Entity>,
} }
// TODO: make this a non-consuming builder
impl<'a> WorldBuilder<'a> { impl<'a> WorldBuilder<'a> {
pub fn build_entity(mut self) -> Self { pub fn build_entity(mut self) -> Self {
let entity = *self.world.insert((), vec![()]).first().unwrap(); let entity = *self.world.insert((), vec![()]).first().unwrap();

View File

@ -4,7 +4,7 @@ use darling::FromMeta;
use inflector::Inflector; use inflector::Inflector;
use proc_macro::TokenStream; use proc_macro::TokenStream;
use quote::{format_ident, quote}; use quote::{format_ident, quote};
use syn::{parse_macro_input, Data, DataStruct, DeriveInput, Field, Fields, Ident, Type, Path}; use syn::{parse_macro_input, Data, DataStruct, DeriveInput, Field, Fields, Ident, Path, Type};
#[derive(FromMeta, Debug, Default)] #[derive(FromMeta, Debug, Default)]
struct EntityArchetypeAttributeArgs { struct EntityArchetypeAttributeArgs {
@ -12,7 +12,112 @@ struct EntityArchetypeAttributeArgs {
pub tag: Option<bool>, pub tag: Option<bool>,
} }
#[proc_macro_derive(EntityArchetype, attributes(tag))] #[derive(FromMeta, Debug)]
struct ModuleAttributeArgs {
#[darling(default)]
pub bevy_render: Option<String>,
#[darling(default)]
pub bevy_asset: Option<String>,
#[darling(default)]
pub bevy_core: Option<String>,
#[darling(default)]
pub bevy_app: Option<String>,
#[darling(default)]
pub legion: Option<String>,
/// If true, it will use the meta "bevy" crate for dependencies by default (ex: bevy:app). If this is set to false, the individual bevy crates
/// will be used (ex: "bevy_app"). Defaults to "true"
#[darling(default)]
pub meta: bool,
}
struct Modules {
pub bevy_render: String,
pub bevy_asset: String,
pub bevy_core: String,
pub bevy_app: String,
pub legion: String,
}
impl Modules {
pub fn meta() -> Modules {
Modules {
bevy_asset: "bevy::asset".to_string(),
bevy_render: "bevy::render".to_string(),
bevy_core: "bevy::core".to_string(),
bevy_app: "bevy::app".to_string(),
legion: "bevy".to_string(),
}
}
pub fn external() -> Modules {
Modules {
bevy_asset: "bevy_asset".to_string(),
bevy_render: "bevy_render".to_string(),
bevy_core: "bevy_core".to_string(),
bevy_app: "bevy_app".to_string(),
legion: "legion".to_string(),
}
}
}
impl Default for ModuleAttributeArgs {
fn default() -> Self {
ModuleAttributeArgs {
bevy_asset: None,
bevy_render: None,
bevy_core: None,
bevy_app: None,
legion: None,
meta: true,
}
}
}
static MODULE_ATTRIBUTE_NAME: &'static str = "module";
fn get_modules(ast: &DeriveInput) -> Modules {
let module_attribute_args = ast.attrs
.iter()
.find(|a| a.path.get_ident().as_ref().unwrap().to_string() == MODULE_ATTRIBUTE_NAME)
.map(|a| {
ModuleAttributeArgs::from_meta(&a.parse_meta().unwrap())
.unwrap_or_else(|_err| ModuleAttributeArgs::default())
});
if let Some(module_attribute_args) = module_attribute_args {
let mut modules = if module_attribute_args.meta {
Modules::meta()
} else {
Modules::external()
};
if let Some(path) = module_attribute_args.bevy_asset {
modules.bevy_asset = path;
}
if let Some(path) = module_attribute_args.bevy_render {
modules.bevy_render = path;
}
if let Some(path) = module_attribute_args.bevy_core {
modules.bevy_core = path;
}
if let Some(path) = module_attribute_args.bevy_app {
modules.bevy_app = path;
}
modules
} else {
Modules::meta()
}
}
fn get_path(path_str: &str) -> Path {
syn::parse(path_str.parse::<TokenStream>().unwrap()).unwrap()
}
#[proc_macro_derive(EntityArchetype, attributes(tag, module))]
pub fn derive_entity_archetype(input: TokenStream) -> TokenStream { pub fn derive_entity_archetype(input: TokenStream) -> TokenStream {
let ast = parse_macro_input!(input as DeriveInput); let ast = parse_macro_input!(input as DeriveInput);
let fields = match &ast.data { let fields = match &ast.data {
@ -23,6 +128,10 @@ pub fn derive_entity_archetype(input: TokenStream) -> TokenStream {
_ => panic!("expected a struct with named fields"), _ => panic!("expected a struct with named fields"),
}; };
let modules = get_modules(&ast);
let bevy_app_path = get_path(&modules.bevy_app);
let legion_path = get_path(&modules.legion);
let tag_fields = fields let tag_fields = fields
.iter() .iter()
.filter(|f| { .filter(|f| {
@ -51,8 +160,8 @@ pub fn derive_entity_archetype(input: TokenStream) -> TokenStream {
let struct_name = &ast.ident; let struct_name = &ast.ident;
TokenStream::from(quote! { TokenStream::from(quote! {
impl #impl_generics bevy::prelude::EntityArchetype for #struct_name#ty_generics { impl #impl_generics #bevy_app_path::EntityArchetype for #struct_name#ty_generics {
fn insert(self, world: &mut bevy::prelude::World) -> Entity { fn insert(self, world: &mut #legion_path::prelude::World) -> #legion_path::prelude::Entity {
*world.insert((#(self.#tag_fields,)*), *world.insert((#(self.#tag_fields,)*),
vec![( vec![(
#(self.#component_fields,)* #(self.#component_fields,)*
@ -60,7 +169,7 @@ pub fn derive_entity_archetype(input: TokenStream) -> TokenStream {
]).first().unwrap() ]).first().unwrap()
} }
fn insert_command_buffer(self, command_buffer: &mut bevy::prelude::CommandBuffer) -> Entity { fn insert_command_buffer(self, command_buffer: &mut #legion_path::prelude::CommandBuffer) -> #legion_path::prelude::Entity {
*command_buffer.insert((#(self.#tag_fields,)*), *command_buffer.insert((#(self.#tag_fields,)*),
vec![( vec![(
#(self.#component_fields,)* #(self.#component_fields,)*
@ -90,39 +199,15 @@ struct UniformAttributeArgs {
pub bevy_core_path: Option<String>, pub bevy_core_path: Option<String>,
} }
#[proc_macro_derive(Uniforms, attributes(uniform))] static UNIFORM_ATTRIBUTE_NAME: &'static str = "uniform";
#[proc_macro_derive(Uniforms, attributes(uniform, module))]
pub fn derive_uniforms(input: TokenStream) -> TokenStream { pub fn derive_uniforms(input: TokenStream) -> TokenStream {
static UNIFORM_ATTRIBUTE_NAME: &'static str = "uniform";
let ast = parse_macro_input!(input as DeriveInput); let ast = parse_macro_input!(input as DeriveInput);
let mut bevy_render_path_name = "bevy::render".to_string(); let modules = get_modules(&ast);
let mut bevy_core_path_name = "bevy::core".to_string();
let mut bevy_asset_path_name = "bevy::asset".to_string();
let struct_attribute_args = ast
.attrs
.iter()
.find(|a| a.path.get_ident().as_ref().unwrap().to_string() == UNIFORM_ATTRIBUTE_NAME)
.map(|a| {
UniformAttributeArgs::from_meta(&a.parse_meta().unwrap())
.unwrap_or_else(|_err| UniformAttributeArgs::default())
});
if let Some(struct_attribute_args) = struct_attribute_args { let bevy_render_path: Path = get_path(&modules.bevy_render);
if let Some(value) = struct_attribute_args.bevy_render_path { let bevy_core_path: Path = get_path(&modules.bevy_core);
bevy_render_path_name = value.to_string(); let bevy_asset_path: Path = get_path(&modules.bevy_asset);
}
if let Some(value) = struct_attribute_args.bevy_core_path {
bevy_core_path_name = value.to_string();
}
if let Some(value) = struct_attribute_args.bevy_asset_path {
bevy_asset_path_name = value.to_string();
}
}
// let bevy_render_path = Ident::new(&bevy_render_path_name, Span::call_site());
// let bevy_render_path = Path::parse(&bevy_render_path_name).unwrap();
let bevy_render_path: Path = syn::parse(bevy_render_path_name.parse::<TokenStream>().unwrap()).unwrap();
let bevy_core_path: Path = syn::parse(bevy_core_path_name.parse::<TokenStream>().unwrap()).unwrap();
let bevy_asset_path: Path = syn::parse(bevy_asset_path_name.parse::<TokenStream>().unwrap()).unwrap();
let fields = match &ast.data { let fields = match &ast.data {
Data::Struct(DataStruct { Data::Struct(DataStruct {

View File

@ -1,9 +1,10 @@
use crate::{prelude::*, render::Renderable};
use crate as bevy; // for macro imports
use bevy_derive::EntityArchetype; use bevy_derive::EntityArchetype;
use bevy_asset::Handle;
use crate::{shader::uniforms::StandardMaterial, mesh::Mesh, Renderable, Light, Camera, ActiveCamera, ActiveCamera2d, CameraType};
use bevy_transform::components::{Translation, LocalToWorld, Rotation, Scale};
#[derive(EntityArchetype, Default)] #[derive(EntityArchetype, Default)]
#[module(meta = false)]
pub struct MeshEntity { pub struct MeshEntity {
// #[tag] // #[tag]
pub mesh: Handle<Mesh>, pub mesh: Handle<Mesh>,
@ -17,6 +18,7 @@ pub struct MeshEntity {
} }
#[derive(EntityArchetype, Default)] #[derive(EntityArchetype, Default)]
#[module(meta = false)]
pub struct MeshMaterialEntity<T: Default + Send + Sync + 'static> { pub struct MeshMaterialEntity<T: Default + Send + Sync + 'static> {
pub mesh: Handle<Mesh>, pub mesh: Handle<Mesh>,
pub material: Handle<T>, pub material: Handle<T>,
@ -28,6 +30,7 @@ pub struct MeshMaterialEntity<T: Default + Send + Sync + 'static> {
} }
#[derive(EntityArchetype, Default)] #[derive(EntityArchetype, Default)]
#[module(meta = false)]
pub struct LightEntity { pub struct LightEntity {
pub light: Light, pub light: Light,
pub local_to_world: LocalToWorld, pub local_to_world: LocalToWorld,
@ -36,6 +39,7 @@ pub struct LightEntity {
} }
#[derive(EntityArchetype, Default)] #[derive(EntityArchetype, Default)]
#[module(meta = false)]
pub struct CameraEntity { pub struct CameraEntity {
pub camera: Camera, pub camera: Camera,
pub active_camera: ActiveCamera, pub active_camera: ActiveCamera,
@ -43,6 +47,7 @@ pub struct CameraEntity {
} }
#[derive(EntityArchetype)] #[derive(EntityArchetype)]
#[module(meta = false)]
pub struct Camera2dEntity { pub struct Camera2dEntity {
pub camera: Camera, pub camera: Camera,
pub active_camera_2d: ActiveCamera2d, pub active_camera_2d: ActiveCamera2d,
@ -55,9 +60,4 @@ impl Default for Camera2dEntity {
active_camera_2d: ActiveCamera2d, active_camera_2d: ActiveCamera2d,
} }
} }
} }
#[derive(EntityArchetype)]
pub struct UiEntity {
pub node: Node,
}

View File

@ -3,6 +3,7 @@ mod camera;
pub mod mesh; pub mod mesh;
pub mod render_graph; pub mod render_graph;
pub mod shader; pub mod shader;
pub mod entity;
mod color; mod color;
mod light; mod light;

View File

@ -2,11 +2,11 @@ use crate::{texture::Texture, Color};
use bevy_asset::Handle; use bevy_asset::Handle;
use bevy_derive::Uniforms; use bevy_derive::Uniforms;
use bevy_core;
use bevy_asset; use bevy_asset;
use bevy_core;
#[derive(Uniforms)] #[derive(Uniforms)]
#[uniform(bevy_render_path = "crate", bevy_core_path = "bevy_core", bevy_asset_path = "bevy_asset")] #[module(meta = false, bevy_render = "crate")]
pub struct StandardMaterial { pub struct StandardMaterial {
#[uniform(instance)] #[uniform(instance)]
pub albedo: Color, pub albedo: Color,

View File

@ -7,7 +7,7 @@ use bevy_asset;
#[repr(C)] #[repr(C)]
#[derive(Clone, Copy, AsBytes, FromBytes, Uniforms)] #[derive(Clone, Copy, AsBytes, FromBytes, Uniforms)]
#[uniform(bevy_render_path = "crate", bevy_asset_path = "bevy_asset", bevy_core_path = "bevy_core")] #[module(meta = false, bevy_render = "crate")]
pub struct Vertex { pub struct Vertex {
#[uniform(vertex)] #[uniform(vertex)]
pub position: [f32; 4], pub position: [f32; 4],

19
bevy_ui/Cargo.toml Normal file
View File

@ -0,0 +1,19 @@
[package]
name = "bevy_ui"
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
[dependencies]
bevy_app = { path = "../bevy_app" }
bevy_core = { path = "../bevy_core" }
bevy_derive = { path = "../bevy_derive" }
bevy_transform = { path = "../bevy_transform" }
bevy_render = { path = "../bevy_render" }
bevy_window = { path = "../bevy_window" }
legion = { path = "../bevy_legion", features = ["serialize"] }
glam = "0.8.6"

8
bevy_ui/src/entity.rs Normal file
View File

@ -0,0 +1,8 @@
use bevy_derive::EntityArchetype;
use super::Node;
#[derive(EntityArchetype)]
#[module(meta = false)]
pub struct UiEntity {
pub node: Node,
}

View File

@ -1,4 +1,5 @@
mod anchors; mod anchors;
pub mod entity;
mod margins; mod margins;
mod node; mod node;
mod ui_update_system; mod ui_update_system;
@ -8,7 +9,7 @@ pub use margins::*;
pub use node::*; pub use node::*;
pub use ui_update_system::*; pub use ui_update_system::*;
use crate::{app::AppBuilder, prelude::AppPlugin}; use bevy_app::{AppBuilder, AppPlugin};
#[derive(Default)] #[derive(Default)]
pub struct UiPlugin; pub struct UiPlugin;

View File

@ -1,9 +1,6 @@
use crate::{ use super::{Anchors, Margins};
math, use bevy_render::Color;
math::Vec2, use glam::{self, Vec2};
prelude::Color,
ui::{Anchors, Margins},
};
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
enum GrowDirection { enum GrowDirection {
@ -67,8 +64,8 @@ impl Node {
parent_dimensions.y(), parent_dimensions.y(),
); );
self.size = math::vec2(rect_width, rect_height); self.size = glam::vec2(rect_width, rect_height);
self.global_position = math::vec2(rect_x, rect_y) + parent_position; self.global_position = glam::vec2(rect_x, rect_y) + parent_position;
} }
fn compute_dimension_properties( fn compute_dimension_properties(

View File

@ -1,17 +1,14 @@
use crate::{ use bevy_core::ecs;
ecs,
render::{
pipeline::VertexBufferDescriptors,
render_resource::{
resource_name, BufferArrayInfo, BufferInfo, BufferUsage, RenderResource,
RenderResourceAssignments, ResourceProvider,
},
renderer::Renderer,
shader::AsUniforms,
},
};
use bevy_derive::Uniforms; use bevy_derive::Uniforms;
use bevy_render::{
pipeline::VertexBufferDescriptors,
render_resource::{
resource_name, BufferArrayInfo, BufferInfo, BufferUsage, RenderResource,
RenderResourceAssignments, ResourceProvider,
},
renderer::Renderer,
shader::AsUniforms,
};
use bevy_transform::prelude::Parent; use bevy_transform::prelude::Parent;
use legion::prelude::*; use legion::prelude::*;
use zerocopy::{AsBytes, FromBytes}; use zerocopy::{AsBytes, FromBytes};

View File

@ -1,4 +1,9 @@
use crate::prelude::*; use super::Node;
use bevy_core::transform::run_on_hierarchy_subworld_mut;
use bevy_transform::prelude::{Children, Parent};
use bevy_window::Windows;
use glam::Vec2;
use legion::{prelude::*, systems::SubWorld};
pub fn ui_update_system() -> Box<dyn Schedulable> { pub fn ui_update_system() -> Box<dyn Schedulable> {
SystemBuilder::new("ui_update") SystemBuilder::new("ui_update")
@ -8,10 +13,10 @@ pub fn ui_update_system() -> Box<dyn Schedulable> {
.read_component::<Children>() .read_component::<Children>()
.build(move |_, world, windows, node_query| { .build(move |_, world, windows, node_query| {
let window = windows.get_primary().unwrap(); let window = windows.get_primary().unwrap();
let parent_size = math::vec2(window.width as f32, window.height as f32); let parent_size = glam::vec2(window.width as f32, window.height as f32);
let parent_position = math::vec2(0.0, 0.0); let parent_position = glam::vec2(0.0, 0.0);
for (entity, _) in node_query.iter_entities_mut(world) { for (entity, _) in node_query.iter_entities_mut(world) {
ecs::run_on_hierarchy_subworld_mut( run_on_hierarchy_subworld_mut(
world, world,
entity, entity,
(parent_size, parent_position), (parent_size, parent_position),

View File

@ -1,17 +1,16 @@
#![feature(specialization)] #![feature(specialization)]
pub mod ecs;
pub mod prelude; pub mod prelude;
pub mod serialization; pub mod serialization;
pub mod ui;
pub use bevy_transform as transform; pub use bevy_app as app;
pub use bevy_asset as asset;
pub use bevy_core as core; pub use bevy_core as core;
pub use bevy_diagnostic as diagnostic; pub use bevy_diagnostic as diagnostic;
pub use bevy_asset as asset;
pub use bevy_render as render;
pub use bevy_app as app;
pub use bevy_window as window;
pub use bevy_input as input; pub use bevy_input as input;
pub use bevy_render as render;
pub use bevy_transform as transform;
pub use bevy_ui as ui;
pub use bevy_window as window;
pub use glam as math; pub use glam as math;
pub use legion; pub use legion;

View File

@ -1,14 +1,13 @@
pub use crate::{ pub use crate::{
app::{AppPlugin, App, AppBuilder, EventReader, Events, GetEventReader}, app::{App, AppBuilder, AppPlugin, EntityArchetype, EventReader, Events, GetEventReader},
asset::{Asset, AssetStorage, Handle}, asset::{Asset, AssetStorage, Handle},
core::time::Time, core::{
diagnostic::DiagnosticsPlugin, time::Time,
ecs, transform::{CommandBufferBuilderSource, WorldBuilder, WorldBuilderSource},
ecs::{
default_archetypes::*, CommandBufferBuilderSource, EntityArchetype, WorldBuilder,
WorldBuilderSource,
}, },
diagnostic::DiagnosticsPlugin,
render::{ render::{
entity::*,
mesh::{Mesh, MeshType}, mesh::{Mesh, MeshType},
pipeline::PipelineDescriptor, pipeline::PipelineDescriptor,
render_graph::RenderGraph, render_graph::RenderGraph,
@ -19,7 +18,7 @@ pub use crate::{
texture::{Texture, TextureType}, texture::{Texture, TextureType},
ActiveCamera, ActiveCamera2d, Camera, CameraType, Color, ColorSource, Light, Renderable, ActiveCamera, ActiveCamera2d, Camera, CameraType, Color, ColorSource, Light, Renderable,
}, },
ui::{Anchors, Margins, Node}, ui::{entity::*, Anchors, Margins, Node},
window::{Window, WindowDescriptor, WindowPlugin, Windows}, window::{Window, WindowDescriptor, WindowPlugin, Windows},
AddDefaultPlugins, AddDefaultPlugins,
}; };