mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 07:04:33 +00:00
rework marco modules, crate-ify ui
This commit is contained in:
parent
016bf2152c
commit
b19e3004b8
22 changed files with 211 additions and 97 deletions
|
@ -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 }
|
||||
|
|
|
@ -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::*;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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},
|
5
bevy_core/src/transform/mod.rs
Normal file
5
bevy_core/src/transform/mod.rs
Normal file
|
@ -0,0 +1,5 @@
|
|||
mod hierarchy;
|
||||
mod world_builder;
|
||||
|
||||
pub use hierarchy::*;
|
||||
pub use world_builder::*;
|
|
@ -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();
|
|
@ -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 {
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@ mod camera;
|
|||
pub mod mesh;
|
||||
pub mod render_graph;
|
||||
pub mod shader;
|
||||
pub mod entity;
|
||||
|
||||
mod color;
|
||||
mod light;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
19
bevy_ui/Cargo.toml
Normal 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
8
bevy_ui/src/entity.rs
Normal file
|
@ -0,0 +1,8 @@
|
|||
use bevy_derive::EntityArchetype;
|
||||
use super::Node;
|
||||
|
||||
#[derive(EntityArchetype)]
|
||||
#[module(meta = false)]
|
||||
pub struct UiEntity {
|
||||
pub node: Node,
|
||||
}
|
|
@ -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;
|
|
@ -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(
|
|
@ -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};
|
|
@ -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),
|
13
src/lib.rs
13
src/lib.rs
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue