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_render = { path = "bevy_render" }
bevy_transform = { path = "bevy_transform" }
bevy_ui = { path = "bevy_ui" }
bevy_window = { path = "bevy_window" }
bevy_wgpu = { path = "bevy_wgpu", optional = true }
bevy_winit = { path = "bevy_winit", optional = true }

View file

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

View file

@ -1,5 +1,6 @@
pub mod bytes;
pub mod time;
pub mod transform;
use bevy_app::{stage, AppBuilder, AppPlugin};
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 legion::{
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 legion::{
filter::{ChunksetFilterData, Filter},
@ -26,6 +26,7 @@ pub struct WorldBuilder<'a> {
parent_entity: Option<Entity>,
}
// TODO: make this a non-consuming builder
impl<'a> WorldBuilder<'a> {
pub fn build_entity(mut self) -> Self {
let entity = *self.world.insert((), vec![()]).first().unwrap();

View file

@ -4,7 +4,7 @@ use darling::FromMeta;
use inflector::Inflector;
use proc_macro::TokenStream;
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)]
struct EntityArchetypeAttributeArgs {
@ -12,7 +12,112 @@ struct EntityArchetypeAttributeArgs {
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 {
let ast = parse_macro_input!(input as DeriveInput);
let fields = match &ast.data {
@ -23,6 +128,10 @@ pub fn derive_entity_archetype(input: TokenStream) -> TokenStream {
_ => 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
.iter()
.filter(|f| {
@ -51,8 +160,8 @@ pub fn derive_entity_archetype(input: TokenStream) -> TokenStream {
let struct_name = &ast.ident;
TokenStream::from(quote! {
impl #impl_generics bevy::prelude::EntityArchetype for #struct_name#ty_generics {
fn insert(self, world: &mut bevy::prelude::World) -> Entity {
impl #impl_generics #bevy_app_path::EntityArchetype for #struct_name#ty_generics {
fn insert(self, world: &mut #legion_path::prelude::World) -> #legion_path::prelude::Entity {
*world.insert((#(self.#tag_fields,)*),
vec![(
#(self.#component_fields,)*
@ -60,7 +169,7 @@ pub fn derive_entity_archetype(input: TokenStream) -> TokenStream {
]).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,)*),
vec![(
#(self.#component_fields,)*
@ -90,39 +199,15 @@ struct UniformAttributeArgs {
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 {
static UNIFORM_ATTRIBUTE_NAME: &'static str = "uniform";
let ast = parse_macro_input!(input as DeriveInput);
let mut bevy_render_path_name = "bevy::render".to_string();
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())
});
let modules = get_modules(&ast);
if let Some(struct_attribute_args) = struct_attribute_args {
if let Some(value) = struct_attribute_args.bevy_render_path {
bevy_render_path_name = value.to_string();
}
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 bevy_render_path: Path = get_path(&modules.bevy_render);
let bevy_core_path: Path = get_path(&modules.bevy_core);
let bevy_asset_path: Path = get_path(&modules.bevy_asset);
let fields = match &ast.data {
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_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)]
#[module(meta = false)]
pub struct MeshEntity {
// #[tag]
pub mesh: Handle<Mesh>,
@ -17,6 +18,7 @@ pub struct MeshEntity {
}
#[derive(EntityArchetype, Default)]
#[module(meta = false)]
pub struct MeshMaterialEntity<T: Default + Send + Sync + 'static> {
pub mesh: Handle<Mesh>,
pub material: Handle<T>,
@ -28,6 +30,7 @@ pub struct MeshMaterialEntity<T: Default + Send + Sync + 'static> {
}
#[derive(EntityArchetype, Default)]
#[module(meta = false)]
pub struct LightEntity {
pub light: Light,
pub local_to_world: LocalToWorld,
@ -36,6 +39,7 @@ pub struct LightEntity {
}
#[derive(EntityArchetype, Default)]
#[module(meta = false)]
pub struct CameraEntity {
pub camera: Camera,
pub active_camera: ActiveCamera,
@ -43,6 +47,7 @@ pub struct CameraEntity {
}
#[derive(EntityArchetype)]
#[module(meta = false)]
pub struct Camera2dEntity {
pub camera: Camera,
pub active_camera_2d: ActiveCamera2d,
@ -55,9 +60,4 @@ impl Default for Camera2dEntity {
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 render_graph;
pub mod shader;
pub mod entity;
mod color;
mod light;

View file

@ -2,11 +2,11 @@ use crate::{texture::Texture, Color};
use bevy_asset::Handle;
use bevy_derive::Uniforms;
use bevy_core;
use bevy_asset;
use bevy_core;
#[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 {
#[uniform(instance)]
pub albedo: Color,

View file

@ -7,7 +7,7 @@ use bevy_asset;
#[repr(C)]
#[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 {
#[uniform(vertex)]
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;
pub mod entity;
mod margins;
mod node;
mod ui_update_system;
@ -8,7 +9,7 @@ pub use margins::*;
pub use node::*;
pub use ui_update_system::*;
use crate::{app::AppBuilder, prelude::AppPlugin};
use bevy_app::{AppBuilder, AppPlugin};
#[derive(Default)]
pub struct UiPlugin;

View file

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

View file

@ -1,17 +1,14 @@
use crate::{
ecs,
render::{
pipeline::VertexBufferDescriptors,
render_resource::{
resource_name, BufferArrayInfo, BufferInfo, BufferUsage, RenderResource,
RenderResourceAssignments, ResourceProvider,
},
renderer::Renderer,
shader::AsUniforms,
},
};
use bevy_core::ecs;
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 legion::prelude::*;
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> {
SystemBuilder::new("ui_update")
@ -8,10 +13,10 @@ pub fn ui_update_system() -> Box<dyn Schedulable> {
.read_component::<Children>()
.build(move |_, world, windows, node_query| {
let window = windows.get_primary().unwrap();
let parent_size = math::vec2(window.width as f32, window.height as f32);
let parent_position = math::vec2(0.0, 0.0);
let parent_size = glam::vec2(window.width as f32, window.height as f32);
let parent_position = glam::vec2(0.0, 0.0);
for (entity, _) in node_query.iter_entities_mut(world) {
ecs::run_on_hierarchy_subworld_mut(
run_on_hierarchy_subworld_mut(
world,
entity,
(parent_size, parent_position),

View file

@ -1,17 +1,16 @@
#![feature(specialization)]
pub mod ecs;
pub mod prelude;
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_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_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 legion;

View file

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