add support for multiple windows
This commit is contained in:
		
							parent
							
								
									7c121563db
								
							
						
					
					
						commit
						29bbc05eae
					
				| @ -21,7 +21,7 @@ fn event_trigger_system() -> Box<dyn Schedulable> { | ||||
|         .build(move |_, _, (time, my_event), _| { | ||||
|             elapsed += time.delta_seconds; | ||||
|             if elapsed > 1.0 { | ||||
|                 my_event.raise(MyEvent { | ||||
|                 my_event.send(MyEvent { | ||||
|                     message: "Hello World".to_string(), | ||||
|                 }); | ||||
| 
 | ||||
| @ -31,8 +31,7 @@ fn event_trigger_system() -> Box<dyn Schedulable> { | ||||
| } | ||||
| 
 | ||||
| fn event_listener_system(resources: &mut Resources) -> Box<dyn Schedulable> { | ||||
|     let my_event = resources.get::<Event<MyEvent>>().unwrap(); | ||||
|     let mut my_event_handle = my_event.get_handle(); | ||||
|     let mut my_event_handle = resources.get_event_handle::<MyEvent>(); | ||||
|     SystemBuilder::new("EventListener") | ||||
|         .read_resource::<Event<MyEvent>>() | ||||
|         .build(move |_, _, my_events, _| { | ||||
|  | ||||
							
								
								
									
										18
									
								
								examples/multiple_windows.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								examples/multiple_windows.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,18 @@ | ||||
| use bevy::prelude::*; | ||||
| use bevy::core::window::CreateWindow; | ||||
| 
 | ||||
| fn main() { | ||||
|     App::build().add_defaults().setup(setup).run(); | ||||
| } | ||||
| 
 | ||||
| fn setup(_world: &mut World, resources: &mut Resources) { | ||||
|     let mut create_window_events = resources.get_mut::<Event<CreateWindow>>().unwrap(); | ||||
|     create_window_events.send(CreateWindow { | ||||
|         descriptor: WindowDescriptor { | ||||
|             width: 800, | ||||
|             height: 600, | ||||
|             vsync: false, | ||||
|             title: "another window".to_string(), | ||||
|         } | ||||
|     }); | ||||
| } | ||||
| @ -1,9 +1,18 @@ | ||||
| use super::{Time, Window, WindowResize}; | ||||
| use crate::{app::{AppBuilder, plugin::AppPlugin}}; | ||||
| use super::{CreateWindow, Time, WindowCreated, WindowResize, Windows, Event, WindowDescriptor}; | ||||
| use crate::app::{plugin::AppPlugin, AppBuilder}; | ||||
| use bevy_transform::transform_system_bundle; | ||||
| 
 | ||||
| #[derive(Default)] | ||||
| pub struct CorePlugin; | ||||
| pub struct CorePlugin { | ||||
|     pub primary_window: Option<WindowDescriptor>, | ||||
| } | ||||
| 
 | ||||
| impl Default for CorePlugin { | ||||
|     fn default() -> Self { | ||||
|         CorePlugin { | ||||
|             primary_window: Some(WindowDescriptor::default()), | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl AppPlugin for CorePlugin { | ||||
|     fn build(&self, mut app: AppBuilder) -> AppBuilder { | ||||
| @ -11,9 +20,20 @@ impl AppPlugin for CorePlugin { | ||||
|             app = app.add_system(transform_system); | ||||
|         } | ||||
| 
 | ||||
|         app.add_event::<WindowResize>() | ||||
|             .add_resource(Window::default()) | ||||
|             .add_resource(Time::new()) | ||||
|         app = app.add_event::<WindowResize>() | ||||
|             .add_event::<CreateWindow>() | ||||
|             .add_event::<WindowCreated>() | ||||
|             .add_resource(Windows::default()) | ||||
|             .add_resource(Time::new()); | ||||
| 
 | ||||
|         if let Some(ref primary_window_descriptor) = self.primary_window { | ||||
|             let mut create_window_event = app.resources.get_mut::<Event<CreateWindow>>().unwrap(); | ||||
|             create_window_event.send(CreateWindow { | ||||
|                 descriptor: primary_window_descriptor.clone(), 
 | ||||
|             }); | ||||
|         } | ||||
| 
 | ||||
|         app | ||||
|     } | ||||
| 
 | ||||
|     fn name(&self) -> &'static str { | ||||
|  | ||||
| @ -1,3 +1,4 @@ | ||||
| use crate::prelude::Resources; | ||||
| use legion::prelude::{Schedulable, SystemBuilder}; | ||||
| use std::marker::PhantomData; | ||||
| 
 | ||||
| @ -55,7 +56,7 @@ impl<T> Event<T> | ||||
| where | ||||
|     T: Send + Sync + 'static, | ||||
| { | ||||
|     pub fn raise(&mut self, event: T) { | ||||
|     pub fn send(&mut self, event: T) { | ||||
|         let event_instance = EventInstance { | ||||
|             event, | ||||
|             event_count: self.event_count, | ||||
| @ -105,7 +106,7 @@ where | ||||
| 
 | ||||
|     pub fn get_handle(&self) -> EventHandle<T> { | ||||
|         EventHandle { | ||||
|             last_event_count: self.event_count, | ||||
|             last_event_count: 0, | ||||
|             _marker: PhantomData, | ||||
|         } | ||||
|     } | ||||
| @ -131,3 +132,21 @@ where | ||||
|             .build(|_, _, event, _| event.update()) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| pub trait GetEventHandle { | ||||
|     fn get_event_handle<T>(&self) -> EventHandle<T> | ||||
|     where | ||||
|         T: Send + Sync + 'static; | ||||
| } | ||||
| 
 | ||||
| impl GetEventHandle for Resources { | ||||
|     fn get_event_handle<T>(&self) -> EventHandle<T> | ||||
|     where | ||||
|         T: Send + Sync + 'static, | ||||
|     { | ||||
|         let my_event = self | ||||
|             .get::<Event<T>>() | ||||
|             .unwrap_or_else(|| panic!("Event does not exist: {}", std::any::type_name::<T>())); | ||||
|         my_event.get_handle() | ||||
|     } | ||||
| } | ||||
|  | ||||
							
								
								
									
										18
									
								
								src/core/window/events.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								src/core/window/events.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,18 @@ | ||||
| use super::{WindowDescriptor, WindowId}; | ||||
| 
 | ||||
| #[derive(Debug, Clone)] | ||||
| pub struct WindowResize { | ||||
|     pub id: WindowId, | ||||
|     pub width: u32, | ||||
|     pub height: u32, | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug, Clone)] | ||||
| pub struct CreateWindow { | ||||
|     pub descriptor: WindowDescriptor, | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug, Clone)] | ||||
| pub struct WindowCreated { | ||||
|     pub id: WindowId, | ||||
| } | ||||
| @ -1,29 +1,47 @@ | ||||
| #[cfg(feature = "winit")] | ||||
| pub mod winit; | ||||
| mod events; | ||||
| mod windows; | ||||
| 
 | ||||
| pub use events::*; | ||||
| pub use windows::*; | ||||
| 
 | ||||
| use uuid::Uuid; | ||||
| 
 | ||||
| #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] | ||||
| pub struct WindowId(Uuid); | ||||
| 
 | ||||
| pub struct Window { | ||||
|     pub id: Uuid, | ||||
|     pub id: WindowId, | ||||
|     pub width: u32, | ||||
|     pub height: u32, | ||||
|     pub title: String, | ||||
|     pub vsync: bool, | ||||
| } | ||||
| 
 | ||||
| #[derive(Debug, Clone)] | ||||
| pub struct WindowResize { | ||||
|     pub id: Uuid, | ||||
|     pub width: u32, | ||||
|     pub height: u32, | ||||
| impl Window { | ||||
|     pub fn new(window_descriptor: &WindowDescriptor) -> Self { | ||||
|         Window { | ||||
|             id: WindowId(Uuid::new_v4()), | ||||
|             height: window_descriptor.height, | ||||
|             width: window_descriptor.width, | ||||
|             title: window_descriptor.title.clone(), | ||||
|             vsync: window_descriptor.vsync, | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| impl Default for Window { | ||||
| #[derive(Debug, Clone)] | ||||
| pub struct WindowDescriptor { | ||||
|     pub width: u32, | ||||
|     pub height: u32, | ||||
|     pub title: String, | ||||
|     pub vsync: bool, | ||||
| } | ||||
| 
 | ||||
| impl Default for WindowDescriptor { | ||||
|     fn default() -> Self { | ||||
|         Window { | ||||
|             id: Uuid::new_v4(), | ||||
|         WindowDescriptor { | ||||
|             title: "bevy".to_string(), | ||||
|             width: 1280, | ||||
|             height: 720, | ||||
|  | ||||
							
								
								
									
										35
									
								
								src/core/window/windows.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								src/core/window/windows.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,35 @@ | ||||
| use super::{Window, WindowId}; | ||||
| use std::collections::HashMap; | ||||
| 
 | ||||
| #[derive(Default)] | ||||
| pub struct Windows { | ||||
|     windows: HashMap<WindowId, Window>, | ||||
|     primary_window: Option<WindowId>, | ||||
| } | ||||
| 
 | ||||
| impl Windows { | ||||
|     pub fn add(&mut self, window: Window) { | ||||
|         if let None = self.primary_window { | ||||
|             self.primary_window = Some(window.id); | ||||
|         }; | ||||
| 
 | ||||
|         self.windows.insert(window.id, window); | ||||
|     } | ||||
| 
 | ||||
|     pub fn get(&self, id: WindowId) -> Option<&Window> { | ||||
|         self.windows.get(&id) | ||||
|     } | ||||
| 
 | ||||
|     pub fn get_mut(&mut self, id: WindowId) -> Option<&mut Window> { | ||||
|         self.windows.get_mut(&id) | ||||
|     } | ||||
| 
 | ||||
|     pub fn get_primary(&self) -> Option<&Window> { | ||||
|         self.primary_window | ||||
|             .and_then(|primary| self.windows.get(&primary)) | ||||
|     } | ||||
| 
 | ||||
|     pub fn iter(&self) -> impl Iterator<Item = &Window> { | ||||
|         self.windows.values() | ||||
|     } | ||||
| } | ||||
| @ -1,13 +1,13 @@ | ||||
| use crate::{ | ||||
|     app::{plugin::AppPlugin, App, AppBuilder}, | ||||
|     core::Event, | ||||
| }; | ||||
| mod winit_windows; | ||||
| pub use winit_windows::*; | ||||
| 
 | ||||
| use super::{Window, WindowResize}; | ||||
| use crate::prelude::*; | ||||
| 
 | ||||
| use super::{CreateWindow, Window, WindowCreated, WindowResize, Windows}; | ||||
| use winit::{ | ||||
|     event, | ||||
|     event::WindowEvent, | ||||
|     event_loop::{ControlFlow, EventLoop}, | ||||
|     event_loop::{ControlFlow, EventLoop, EventLoopWindowTarget}, | ||||
| }; | ||||
| 
 | ||||
| #[derive(Default)] | ||||
| @ -15,7 +15,9 @@ pub struct WinitPlugin; | ||||
| 
 | ||||
| impl AppPlugin for WinitPlugin { | ||||
|     fn build(&self, app: AppBuilder) -> AppBuilder { | ||||
|         app.set_runner(winit_runner) | ||||
|         app | ||||
|         .add_resource(WinitWindows::default()) | ||||
|         .set_runner(winit_runner) | ||||
|     } | ||||
| 
 | ||||
|     fn name(&self) -> &'static str { | ||||
| @ -26,18 +28,16 @@ impl AppPlugin for WinitPlugin { | ||||
| pub fn winit_runner(mut app: App) { | ||||
|     env_logger::init(); | ||||
|     let event_loop = EventLoop::new(); | ||||
|     let winit_window = { | ||||
|         let window = app.resources.get::<Window>().unwrap(); | ||||
|         let winit_window = winit::window::Window::new(&event_loop).unwrap(); | ||||
|         winit_window.set_title(&window.title); | ||||
|         winit_window.set_inner_size(winit::dpi::PhysicalSize::new(window.width, window.height)); | ||||
|         winit_window | ||||
|     }; | ||||
|     let mut create_window_event_handle = app.resources.get_event_handle::<CreateWindow>(); | ||||
| 
 | ||||
|     app.resources.insert(winit_window); | ||||
|     handle_create_window_events( | ||||
|         &mut app.resources, | ||||
|         &event_loop, | ||||
|         &mut create_window_event_handle, | ||||
|     ); | ||||
| 
 | ||||
|     log::debug!("Entering render loop"); | ||||
|     event_loop.run(move |event, _, control_flow| { | ||||
|     event_loop.run(move |event, event_loop, control_flow| { | ||||
|         *control_flow = if cfg!(feature = "metal-auto-capture") { | ||||
|             ControlFlow::Exit | ||||
|         } else { | ||||
| @ -46,15 +46,19 @@ pub fn winit_runner(mut app: App) { | ||||
|         match event { | ||||
|             event::Event::WindowEvent { | ||||
|                 event: WindowEvent::Resized(size), | ||||
|                 window_id: winit_window_id, | ||||
|                 .. | ||||
|             } => { | ||||
|                 let mut window = app.resources.get_mut::<Window>().unwrap(); | ||||
|                 let winit_windows = app.resources.get_mut::<WinitWindows>().unwrap(); | ||||
|                 let mut windows = app.resources.get_mut::<Windows>().unwrap(); | ||||
|                 let window_id = winit_windows.get_window_id(winit_window_id).unwrap(); | ||||
|                 let mut window = windows.get_mut(window_id).unwrap(); | ||||
|                 window.width = size.width; | ||||
|                 window.height = size.height; | ||||
| 
 | ||||
|                 let mut resize_event = app.resources.get_mut::<Event<WindowResize>>().unwrap(); | ||||
|                 resize_event.raise(WindowResize { | ||||
|                     id: window.id, | ||||
|                 resize_event.send(WindowResize { | ||||
|                     id: window_id, | ||||
|                     height: window.height, | ||||
|                     width: window.width, | ||||
|                 }); | ||||
| @ -75,9 +79,45 @@ pub fn winit_runner(mut app: App) { | ||||
|                 _ => {} | ||||
|             }, | ||||
|             event::Event::MainEventsCleared => { | ||||
|                 handle_create_window_events( | ||||
|                     &mut app.resources, | ||||
|                     event_loop, | ||||
|                     &mut create_window_event_handle, | ||||
|                 ); | ||||
|                 app.update(); | ||||
|             } | ||||
|             _ => (), | ||||
|         } | ||||
|     }); | ||||
| } | ||||
| 
 | ||||
| fn handle_create_window_events( | ||||
|     resources: &mut Resources, | ||||
|     event_loop: &EventLoopWindowTarget<()>, | ||||
|     create_window_event_handle: &mut EventHandle<CreateWindow>, | ||||
| ) { | ||||
|     let mut winit_windows = resources.get_mut::<WinitWindows>().unwrap(); | ||||
|     let mut windows = resources.get_mut::<Windows>().unwrap(); | ||||
|     let create_window_events = resources.get::<Event<CreateWindow>>().unwrap(); | ||||
|     let mut window_created_events = resources.get_mut::<Event<WindowCreated>>().unwrap(); | ||||
|     for create_window_event in create_window_events.iter(create_window_event_handle) { | ||||
|         let window = Window::new(&create_window_event.descriptor); | ||||
|         create_window( | ||||
|             &event_loop, | ||||
|             &mut window_created_events, | ||||
|             &mut winit_windows, | ||||
|             &window, | ||||
|         ); | ||||
|         windows.add(window); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| pub fn create_window( | ||||
|     event_loop: &EventLoopWindowTarget<()>, | ||||
|     window_created_events: &mut Event<WindowCreated>, | ||||
|     winit_windows: &mut WinitWindows, | ||||
|     window: &Window, | ||||
| ) { | ||||
|     winit_windows.create_window(event_loop, &window); | ||||
|     window_created_events.send(WindowCreated { id: window.id }); | ||||
| } | ||||
|  | ||||
							
								
								
									
										36
									
								
								src/core/window/winit/winit_windows.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								src/core/window/winit/winit_windows.rs
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,36 @@ | ||||
| use crate::{core::WindowId, prelude::*}; | ||||
| use std::collections::HashMap; | ||||
| 
 | ||||
| #[derive(Default)] | ||||
| pub struct WinitWindows { | ||||
|     pub windows: HashMap<winit::window::WindowId, winit::window::Window>, | ||||
|     pub window_id_to_winit: HashMap<WindowId, winit::window::WindowId>, | ||||
|     pub winit_to_window_id: HashMap<winit::window::WindowId, WindowId>, | ||||
| } | ||||
| 
 | ||||
| impl WinitWindows { | ||||
|     pub fn create_window( | ||||
|         &mut self, | ||||
|         event_loop: &winit::event_loop::EventLoopWindowTarget<()>, | ||||
|         window: &Window, | ||||
|     ) { | ||||
|         let winit_window = winit::window::Window::new(&event_loop).unwrap(); | ||||
|         self.window_id_to_winit.insert(window.id, winit_window.id()); | ||||
|         self.winit_to_window_id.insert(winit_window.id(), window.id); | ||||
| 
 | ||||
|         winit_window.set_title(&window.title); | ||||
|         winit_window.set_inner_size(winit::dpi::PhysicalSize::new(window.width, window.height)); | ||||
| 
 | ||||
|         self.windows.insert(winit_window.id(), winit_window); | ||||
|     } | ||||
| 
 | ||||
|     pub fn get_window(&self, id: WindowId) -> Option<&winit::window::Window> { | ||||
|         self.window_id_to_winit | ||||
|             .get(&id) | ||||
|             .and_then(|id| self.windows.get(id)) | ||||
|     } | ||||
| 
 | ||||
|     pub fn get_window_id(&self, id: winit::window::WindowId) -> Option<WindowId> { | ||||
|         self.winit_to_window_id.get(&id).cloned() | ||||
|     } | ||||
| } | ||||
| @ -1,23 +1,25 @@ | ||||
| pub use crate::{ | ||||
|     app::{App, AppBuilder, plugin::AppPlugin}, | ||||
|     app::{plugin::AppPlugin, App, AppBuilder}, | ||||
|     asset::{Asset, AssetStorage, Handle}, | ||||
|     core::{Time, Window, Event, EventHandle}, | ||||
|     core::{Event, EventHandle, GetEventHandle, Time, Window, Windows, WindowDescriptor}, | ||||
|     diagnostic::DiagnosticsPlugin, | ||||
|     ecs, | ||||
|     ecs::{ | ||||
|         default_archetypes::*, CommandBufferBuilderSource, EntityArchetype, WorldBuilder, | ||||
|         WorldBuilderSource | ||||
|         WorldBuilderSource, | ||||
|     }, | ||||
|     render::{ | ||||
|         mesh::{Mesh, MeshType}, | ||||
|         pipeline::PipelineDescriptor, | ||||
|         render_resource::{resource_name, resource_providers::UniformResourceProvider, AssetBatchers}, | ||||
|         render_graph::RenderGraph, | ||||
|         render_resource::{ | ||||
|             resource_name, resource_providers::UniformResourceProvider, AssetBatchers, | ||||
|         }, | ||||
|         shader::{uniforms::StandardMaterial, Shader, ShaderDefSuffixProvider, ShaderStage}, | ||||
|         texture::{Texture, TextureType}, | ||||
|         ActiveCamera, ActiveCamera2d, Camera, CameraType, Color, ColorSource, Light, Renderable, | ||||
|     }, | ||||
|     ui::{Anchors, Margins, Node}, | ||||
|     diagnostic::DiagnosticsPlugin, | ||||
| }; | ||||
| pub use bevy_derive::*; | ||||
| pub use bevy_transform::prelude::*; | ||||
| @ -28,12 +30,12 @@ pub use legion::{ | ||||
|     event::Event as LegionEvent, | ||||
|     filter::filter_fns::*, | ||||
|     query::{IntoQuery, Query, Read, Tagged, TryRead, TryWrite, Write}, | ||||
|     world::{Universe, World}, | ||||
|     systems::{ | ||||
|         bit_set::BitSet, | ||||
|         resource::{ResourceSet, Resources}, | ||||
|         schedule::{Executor, Runnable, Schedulable, Schedule}, | ||||
|         System, SystemBuilder, SubWorld | ||||
|         SubWorld, System, SystemBuilder, | ||||
|     }, | ||||
|     world::{Universe, World}, | ||||
| }; | ||||
| pub use math::{Mat3, Mat4, Quat, Vec2, Vec3, Vec4}; | ||||
|  | ||||
| @ -1,5 +1,5 @@ | ||||
| use crate::{ | ||||
|     core::Window, | ||||
|     core::Windows, | ||||
|     prelude::World, | ||||
|     render::{ | ||||
|         render_resource::{RenderResourceAssignments, ResourceProvider}, | ||||
| @ -23,7 +23,8 @@ impl FrameTextureResourceProvider { | ||||
|     } | ||||
| 
 | ||||
|     pub fn update(&mut self, renderer: &mut dyn Renderer, _world: &World, resources: &Resources) { | ||||
|         let window = resources.get::<Window>().unwrap(); | ||||
|         let windows = resources.get::<Windows>().unwrap(); | ||||
|         let window = windows.get_primary().unwrap(); | ||||
|         self.descriptor.size.width = window.width; | ||||
|         self.descriptor.size.height = window.height; | ||||
| 
 | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| use super::{wgpu_type_converter::OwnedWgpuVertexBufferDescriptor, WgpuRenderPass, WgpuResources}; | ||||
| use crate::{ | ||||
|     asset::{AssetStorage, Handle}, | ||||
|     core::{Event, EventHandle, Window, WindowResize}, | ||||
|     core::{Event, EventHandle, WindowResize, winit::WinitWindows, Windows}, | ||||
|     legion::prelude::*, | ||||
|     render::{ | ||||
|         pass::{ | ||||
| @ -345,8 +345,11 @@ impl WgpuRenderer { | ||||
|     pub fn create_surface(&mut self, resources: &Resources) { | ||||
|         #[cfg(feature = "winit")] | ||||
|         { | ||||
|             let window = resources.get::<winit::window::Window>().unwrap(); | ||||
|             let surface = wgpu::Surface::create(window.deref()); | ||||
|             let winit_windows = resources.get::<WinitWindows>().unwrap(); | ||||
|             let windows = resources.get::<Windows>().unwrap(); | ||||
|             let primary_window = windows.get_primary().unwrap(); | ||||
|             let primary_winit_window = winit_windows.get_window(primary_window.id).unwrap(); | ||||
|             let surface = wgpu::Surface::create(primary_winit_window.deref()); | ||||
|             self.surface = Some(surface); | ||||
|         } | ||||
|     } | ||||
| @ -361,7 +364,8 @@ impl Renderer for WgpuRenderer { | ||||
|                     .create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 }), | ||||
|             ); | ||||
|             let swap_chain_descriptor: wgpu::SwapChainDescriptor = { | ||||
|                 let window: &Window = &resources.get::<Window>().unwrap(); | ||||
|                 let windows = resources.get::<Windows>().unwrap(); | ||||
|                 let window = windows.get_primary().unwrap(); | ||||
|                 window.into() | ||||
|             }; | ||||
| 
 | ||||
|  | ||||
| @ -2,11 +2,12 @@ use crate::prelude::*; | ||||
| 
 | ||||
| pub fn ui_update_system() -> Box<dyn Schedulable> { | ||||
|     SystemBuilder::new("ui_update") | ||||
|         .read_resource::<Window>() | ||||
|         .read_resource::<Windows>() | ||||
|         .with_query(<(Write<Node>,)>::query().filter(!component::<Parent>())) | ||||
|         .write_component::<Node>() | ||||
|         .read_component::<Children>() | ||||
|         .build(move |_, world, window, node_query| { | ||||
|         .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); | ||||
|             for (entity, _) in node_query.iter_entities_mut(world) { | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Carter Anderson
						Carter Anderson