upgrade legion. refactor system and world construction

This commit is contained in:
Carter Anderson 2020-01-11 03:31:36 -08:00
parent 9f7e313dc4
commit 151675a5ef
23 changed files with 100 additions and 104 deletions

View file

@ -5,7 +5,7 @@ authors = ["Carter Anderson <mcanders1@gmail.com>"]
edition = "2018"
[dependencies]
legion = { git = "https://github.com/TomGillen/legion.git", rev = "8628b227bcbe57582fffb5e80e73c634ec4eebd9" }
legion = { git = "https://github.com/TomGillen/legion.git", rev = "940ef3bfcb77e5d074ee3184b776ff1600da228d" }
legion_transform = { path = "src/transform" }
wgpu = { git = "https://github.com/gfx-rs/wgpu-rs.git", rev = "44fa1bc2fa208fa92f80944253e0da56cb7ac1fe"}
glam = "0.8.4"

View file

@ -25,10 +25,20 @@ struct Wander {
}
fn main() {
AppBuilder::new().add_defaults().setup(&setup).run();
AppBuilder::new()
.add_defaults()
.setup_world(setup)
.setup_systems(|builder| {
builder
.add_system(build_wander_system())
.add_system(build_navigate_system())
.add_system(build_move_system())
.add_system(build_print_status_system())
})
.run();
}
fn setup(world: &mut World, scheduler: &mut SystemScheduler<AppStage>) {
fn setup(world: &mut World) {
let cube = Mesh::load(MeshType::Cube);
let cube_handle = {
let mut mesh_storage = world
@ -38,13 +48,6 @@ fn setup(world: &mut World, scheduler: &mut SystemScheduler<AppStage>) {
mesh_storage.add(cube, "cube")
};
let transform_system_bundle = transform_system_bundle::build(world);
scheduler.add_systems(AppStage::Update, transform_system_bundle);
scheduler.add_system(AppStage::Update, build_wander_system());
scheduler.add_system(AppStage::Update, build_navigate_system());
scheduler.add_system(AppStage::Update, build_move_system());
scheduler.add_system(AppStage::Update, build_print_status_system());
world.insert(
(),
vec![
@ -112,7 +115,7 @@ fn build_wander_system() -> Box<dyn Schedulable> {
Write<NavigationPoint>,
)>::query())
.build(move |_, world, time, person_query| {
for (_, translation, mut wander, mut navigation_point) in person_query.iter(world) {
for (_, translation, mut wander, mut navigation_point) in person_query.iter_mut(world) {
wander.elapsed += time.delta_seconds;
if wander.elapsed >= wander.duration {
let direction = math::vec3(
@ -141,7 +144,7 @@ fn build_navigate_system() -> Box<dyn Schedulable> {
Write<NavigationPoint>,
)>::query())
.build(move |_, world, _, person_query| {
for (_, translation, mut velocity, navigation_point) in person_query.iter(world) {
for (_, translation, mut velocity, navigation_point) in person_query.iter_mut(world) {
let distance = navigation_point.target - translation.0;
if distance.length() > 0.01 {
let direction = distance.normalize();
@ -158,7 +161,7 @@ fn build_move_system() -> Box<dyn Schedulable> {
.read_resource::<Time>()
.with_query(<(Write<Translation>, Read<Velocity>)>::query())
.build(move |_, world, time, person_query| {
for (mut translation, velocity) in person_query.iter(world) {
for (mut translation, velocity) in person_query.iter_mut(world) {
translation.0 += velocity.value * time.delta_seconds;
}
})

View file

@ -8,7 +8,11 @@ use bevy::{
struct Rotator;
fn main() {
AppBuilder::new().add_defaults().setup(&setup).run();
AppBuilder::new()
.add_defaults()
.setup_world(setup)
.setup_systems(|builder: Builder| builder.add_system(build_rotator_system()))
.run();
}
fn build_rotator_system() -> Box<dyn Schedulable> {
@ -16,13 +20,13 @@ fn build_rotator_system() -> Box<dyn Schedulable> {
.read_resource::<Time>()
.with_query(<(Write<Rotator>, Write<Rotation>)>::query())
.build(move |_, world, time, light_query| {
for (_, mut rotation) in light_query.iter(world) {
for (_, mut rotation) in light_query.iter_mut(world) {
rotation.0 = rotation.0 * Quat::from_rotation_x(3.0 * time.delta_seconds);
}
})
}
fn setup(world: &mut World, scheduler: &mut SystemScheduler<AppStage>) {
fn setup(world: &mut World) {
let cube = Mesh::load(MeshType::Cube);
let plane = Mesh::load(MeshType::Plane { size: 10.0 });
@ -37,10 +41,6 @@ fn setup(world: &mut World, scheduler: &mut SystemScheduler<AppStage>) {
)
};
let transform_system_bundle = transform_system_bundle::build(world);
scheduler.add_systems(AppStage::Update, transform_system_bundle);
scheduler.add_system(AppStage::Update, build_rotator_system());
// plane
world.insert(
(),

View file

@ -6,10 +6,10 @@ use bevy::{
};
fn main() {
AppBuilder::new().add_defaults().setup(&setup).run();
AppBuilder::new().add_defaults().setup_world(setup).run();
}
fn setup(world: &mut World, scheduler: &mut SystemScheduler<AppStage>) {
fn setup(world: &mut World) {
let cube = Mesh::load(MeshType::Cube);
let plane = Mesh::load(MeshType::Plane { size: 10.0 });
@ -24,9 +24,6 @@ fn setup(world: &mut World, scheduler: &mut SystemScheduler<AppStage>) {
)
};
let transform_system_bundle = transform_system_bundle::build(world);
scheduler.add_systems(AppStage::Update, transform_system_bundle);
// plane
world.insert(
(),

View file

@ -6,10 +6,10 @@ use bevy::{
};
fn main() {
AppBuilder::new().add_defaults().setup(&setup).run();
AppBuilder::new().add_defaults().setup_world(setup).run();
}
fn setup(world: &mut World, scheduler: &mut SystemScheduler<AppStage>) {
fn setup(world: &mut World) {
let cube = Mesh::load(MeshType::Cube);
let cube_handle = {
let mut mesh_storage = world
@ -19,9 +19,6 @@ fn setup(world: &mut World, scheduler: &mut SystemScheduler<AppStage>) {
mesh_storage.add(cube, "cube")
};
let transform_system_bundle = transform_system_bundle::build(world);
scheduler.add_systems(AppStage::Update, transform_system_bundle);
world.insert(
(),
vec![(

View file

@ -1,48 +1,58 @@
use crate::{
asset::AssetStorage,
legion::prelude::{SystemScheduler, World},
legion::{
prelude::{Schedule, World},
schedule::Builder,
},
render::{passes::*, *},
App, AppStage, Time,
transform_system_bundle, App, Time,
};
pub struct AppBuilder {
pub app: App,
pub world: World,
pub schedule_builder: Builder,
pub render_graph: RenderGraph,
}
impl AppBuilder {
pub fn new() -> Self {
let world = World::new();
let scheduler = SystemScheduler::<AppStage>::new();
AppBuilder {
app: App::new(world, scheduler),
world: World::new(),
schedule_builder: Schedule::builder(),
render_graph: RenderGraph::new(),
}
}
pub fn build(self) -> App {
self.app
App::new(self.world, self.schedule_builder.build(), self.render_graph)
}
pub fn run(self) {
self.app.run();
self.build().run();
}
pub fn with_world(mut self, world: World) -> Self {
self.app.world = world;
self.world = world;
self
}
pub fn with_scheduler(mut self, scheduler: SystemScheduler<AppStage>) -> Self {
self.app.scheduler = scheduler;
pub fn with_schedule(mut self, schedule_builder: Builder) -> Self {
self.schedule_builder = schedule_builder;
self
}
pub fn setup(mut self, setup: &dyn Fn(&mut World, &mut SystemScheduler<AppStage>)) -> Self {
setup(&mut self.app.world, &mut self.app.scheduler);
pub fn setup_world(mut self, setup: impl Fn(&mut World)) -> Self {
setup(&mut self.world);
self
}
pub fn setup_systems(mut self, setup: impl Fn(Builder) -> Builder) -> Self {
self.schedule_builder = setup(self.schedule_builder);
self
}
pub fn add_default_passes(mut self) -> Self {
let render_graph = &mut self.app.render_graph;
let render_graph = &mut self.render_graph;
render_graph
.add_render_resource_manager(Box::new(render_resources::MaterialResourceManager));
render_graph
@ -65,13 +75,22 @@ impl AppBuilder {
}
pub fn add_default_resources(mut self) -> Self {
let resources = &mut self.app.world.resources;
let resources = &mut self.world.resources;
resources.insert(Time::new());
resources.insert(AssetStorage::<Mesh, MeshType>::new());
self
}
pub fn add_default_systems(mut self) -> Self {
for transform_system in transform_system_bundle::build(&mut self.world).drain(..) {
self.schedule_builder = self.schedule_builder.add_system(transform_system);
}
self
}
pub fn add_defaults(self) -> Self {
self.add_default_resources().add_default_passes()
self.add_default_resources()
.add_default_passes()
.add_default_systems()
}
}

View file

@ -1,18 +0,0 @@
use legion::schedule::Stage;
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum AppStage {
Update,
Render,
}
impl Stage for AppStage {}
impl std::fmt::Display for AppStage {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
AppStage::Update => write!(f, "update"),
AppStage::Render => write!(f, "draw"),
}
}
}

View file

@ -1,8 +1,6 @@
mod app_builder;
mod app_stage;
pub use app_builder::AppBuilder;
pub use app_stage::AppStage;
use winit::{
event,
@ -20,15 +18,15 @@ pub struct App {
pub window: Option<Window>,
pub render_graph: RenderGraph,
pub swap_chain: Option<wgpu::SwapChain>,
pub scheduler: SystemScheduler<AppStage>,
pub scheduler: Schedule,
}
impl App {
pub fn new(world: World, scheduler: SystemScheduler<AppStage>) -> App {
pub fn new(world: World, schedule: Schedule, render_graph: RenderGraph) -> App {
App {
world: world,
scheduler: scheduler,
render_graph: RenderGraph::new(),
scheduler: schedule,
render_graph: render_graph,
swap_chain: None,
window: None,
}

View file

@ -5,12 +5,12 @@ pub mod render;
mod vertex;
pub use crate::core::*;
pub use app::{App, AppBuilder, AppStage};
pub use app::{App, AppBuilder};
pub use glam as math;
pub use legion;
pub use legion::prelude::*;
pub use legion::schedule::Schedulable;
pub use legion::schedule::{Schedulable, Builder};
pub use legion_transform;
pub use legion_transform::prelude::*;
pub use legion_transform::transform_system_bundle;

View file

@ -140,9 +140,9 @@ impl Pipeline for ForwardPipeline {
.get_mut::<AssetStorage<Mesh, MeshType>>()
.unwrap();
let mut last_mesh_id = None;
let mut mesh_query =
let mesh_query =
<(Read<Material>, Read<Handle<Mesh>>)>::query().filter(!component::<Instanced>());
for (material, mesh) in mesh_query.iter_immutable(world) {
for (material, mesh) in mesh_query.iter(world) {
let current_mesh_id = *mesh.id.read().unwrap();
let mut should_load_mesh = last_mesh_id == None;

View file

@ -27,13 +27,13 @@ impl ForwardInstancedPipeline {
}
fn create_instance_buffer_infos(device: &Device, world: &World) -> Vec<InstanceBufferInfo> {
let mut entities = <(
let entities = <(
Read<Material>,
Read<LocalToWorld>,
Read<Handle<Mesh>>,
Read<Instanced>,
)>::query();
let entities_count = entities.iter_immutable(world).count();
let entities_count = entities.iter(world).count();
if entities_count == 0 {
return Vec::new();
}
@ -50,7 +50,7 @@ impl ForwardInstancedPipeline {
let mut last_mesh_id = None;
for ((material, transform, mesh, _), slot) in entities
.iter_immutable(world)
.iter(world)
.zip(temp_buf_data.data.chunks_exact_mut(size))
{
last_mesh_id = Some(*mesh.id.read().unwrap());
@ -79,17 +79,17 @@ impl ForwardInstancedPipeline {
device: &Device,
world: &World,
) -> Vec<InstanceBufferInfo> {
let mut entities = <(
let entities = <(
Read<Material>,
Read<LocalToWorld>,
Read<Handle<Mesh>>,
Read<Instanced>,
)>::query();
let entities_count = entities.iter_immutable(world).count();
let entities_count = entities.iter(world).count();
let mut last_mesh_id = None;
let mut data = Vec::with_capacity(entities_count);
for (material, transform, mesh, _) in entities.iter_immutable(world) {
for (material, transform, mesh, _) in entities.iter(world) {
last_mesh_id = Some(*mesh.id.read().unwrap());
let (_, _, translation) = transform.0.to_scale_rotation_translation();

View file

@ -166,14 +166,14 @@ impl Pipeline for ForwardShadowPassNew {
_swap_chain_output: &SwapChainOutput,
world: &mut World,
) {
let mut mesh_query = <(Read<Material>, Read<Handle<Mesh>>)>::query();
let mesh_query = <(Read<Material>, Read<Handle<Mesh>>)>::query();
pass.set_bind_group(0, self.bind_group.as_ref().unwrap(), &[]);
let mut mesh_storage = world
.resources
.get_mut::<AssetStorage<Mesh, MeshType>>()
.unwrap();
for (material, mesh) in mesh_query.iter_immutable(world) {
for (material, mesh) in mesh_query.iter(world) {
if let Some(mesh_asset) = mesh_storage.get(*mesh.id.read().unwrap()) {
mesh_asset.setup_buffers(&render_graph.device);
pass.set_bind_group(1, material.bind_group.as_ref().unwrap(), &[]);

View file

@ -57,9 +57,9 @@ impl Pass for ShadowPass {
self.light_index = 0;
}
let mut light_query = <(Write<Light>, Read<LocalToWorld>, Read<Translation>)>::query();
let light_count = light_query.iter(world).count();
for (i, (mut light, _, _)) in light_query.iter(world).enumerate() {
let light_query = <(Write<Light>, Read<LocalToWorld>, Read<Translation>)>::query();
let light_count = light_query.iter_mut(world).count();
for (i, (mut light, _, _)) in light_query.iter_mut(world).enumerate() {
if i != self.light_index as usize {
continue;
}

View file

@ -153,7 +153,7 @@ impl Pipeline for ShadowPipeline {
_: &SwapChainOutput,
world: &mut World,
) {
let mut mesh_query =
let mesh_query =
<(Read<Material>, Read<Handle<Mesh>>)>::query().filter(!component::<Instanced>());
pass.set_bind_group(0, self.bind_group.as_ref().unwrap(), &[]);
@ -161,7 +161,7 @@ impl Pipeline for ShadowPipeline {
.resources
.get_mut::<AssetStorage<Mesh, MeshType>>()
.unwrap();
for (material, mesh) in mesh_query.iter_immutable(world) {
for (material, mesh) in mesh_query.iter(world) {
if let Some(mesh_asset) = mesh_storage.get(*mesh.id.read().unwrap()) {
mesh_asset.setup_buffers(&render_graph.device);

View file

@ -39,8 +39,8 @@ impl UiPipeline {
device: &wgpu::Device,
world: &World,
) -> Vec<InstanceBufferInfo> {
let mut rect_query = <Read<Rect>>::query();
let rect_count = rect_query.iter_immutable(world).count();
let rect_query = <Read<Rect>>::query();
let rect_count = rect_query.iter(world).count();
if rect_count == 0 {
return Vec::new();
@ -49,7 +49,7 @@ impl UiPipeline {
let mut data = Vec::with_capacity(rect_count);
// TODO: this probably isn't the best way to handle z-ordering
let mut z = 0.9999;
for rect in rect_query.iter_immutable(world) {
for rect in rect_query.iter(world) {
data.push(RectData {
position: rect.position.into(),
dimensions: rect.dimensions.into(),

View file

@ -47,7 +47,7 @@ impl RenderResourceManager for Global2dResourceManager {
encoder: &'a mut wgpu::CommandEncoder,
world: &mut World,
) {
for (mut camera, _) in <(Write<Camera>, Read<ActiveCamera2d>)>::query().iter(world) {
for (mut camera, _) in <(Write<Camera>, Read<ActiveCamera2d>)>::query().iter_mut(world) {
camera.update(
render_graph.swap_chain_descriptor.width,
render_graph.swap_chain_descriptor.height,

View file

@ -10,7 +10,7 @@ pub struct GlobalResourceManager;
impl RenderResourceManager for GlobalResourceManager {
fn initialize(&self, render_graph: &mut RenderGraphData, world: &mut World) {
let light_count = <Read<Light>>::query().iter_immutable(world).count();
let light_count = <Read<Light>>::query().iter(world).count();
let forward_uniforms = ForwardUniforms {
proj: math::Mat4::identity().to_cols_array_2d(),
num_lights: [light_count as u32, 0, 0, 0],
@ -42,7 +42,7 @@ impl RenderResourceManager for GlobalResourceManager {
world: &mut World,
) {
for (mut camera, local_to_world, _) in
<(Write<Camera>, Read<LocalToWorld>, Read<ActiveCamera>)>::query().iter(world)
<(Write<Camera>, Read<LocalToWorld>, Read<ActiveCamera>)>::query().iter_mut(world)
{
camera.update(
render_graph.swap_chain_descriptor.width,

View file

@ -44,7 +44,7 @@ impl RenderResourceManager for LightResourceManager {
world: &mut World,
) {
if self.lights_are_dirty {
let mut light_query = <(Read<Light>, Read<LocalToWorld>, Read<Translation>)>::query();
let light_query = <(Read<Light>, Read<LocalToWorld>, Read<Translation>)>::query();
let light_count = light_query.iter(world).count();
if light_count == 0 {

View file

@ -31,9 +31,9 @@ impl RenderResourceManager for MaterialResourceManager {
encoder: &'a mut wgpu::CommandEncoder,
world: &mut World,
) {
let mut entities =
let entities =
<(Write<Material>, Read<LocalToWorld>)>::query().filter(!component::<Instanced>());
let entities_count = entities.iter(world).count();
let entities_count = entities.iter_mut(world).count();
if entities_count == 0 {
return;
}
@ -44,7 +44,7 @@ impl RenderResourceManager for MaterialResourceManager {
.create_buffer_mapped(entities_count * size, wgpu::BufferUsage::COPY_SRC);
for ((material, transform), slot) in entities
.iter(world)
.iter_mut(world)
.zip(temp_buf_data.data.chunks_exact_mut(size))
{
slot.copy_from_slice(
@ -62,7 +62,7 @@ impl RenderResourceManager for MaterialResourceManager {
for mut material in <Write<Material>>::query()
.filter(!component::<Instanced>())
.iter(world)
.iter_mut(world)
{
if let None = material.bind_group {
let material_uniform_size =
@ -92,7 +92,7 @@ impl RenderResourceManager for MaterialResourceManager {
}
let temp_buf = temp_buf_data.finish();
for (i, (material, _)) in entities.iter(world).enumerate() {
for (i, (material, _)) in entities.iter_mut(world).enumerate() {
encoder.copy_buffer_to_buffer(
&temp_buf,
(i * size) as wgpu::BufferAddress,

View file

@ -7,7 +7,7 @@ edition = "2018"
license = "MIT"
[dependencies]
legion = { git = "https://github.com/TomGillen/legion.git", rev = "8628b227bcbe57582fffb5e80e73c634ec4eebd9" }
legion = { git = "https://github.com/TomGillen/legion.git", rev = "940ef3bfcb77e5d074ee3184b776ff1600da228d" }
#legion = { path = "../legion" }
glam = "0.8.3"
log = "0.4"

View file

@ -49,7 +49,7 @@ pub fn build(_: &mut World) -> Vec<Box<dyn Schedulable>> {
HashMap::<Entity, SmallVec<[Entity; 8]>>::with_capacity(16);
// Entities with a changed Parent (that also have a PreviousParent, even if None)
for (entity, (parent, mut previous_parent)) in queries.1.iter_entities(world) {
for (entity, (parent, mut previous_parent)) in queries.1.iter_entities_mut(world) {
log::trace!("Parent changed for {}", entity);
// If the `PreviousParent` is not None.

View file

@ -1,7 +1,7 @@
#![allow(dead_code)]
use crate::{
components::*,
ecs::{prelude::*, system::PreparedWorld},
ecs::{prelude::*, system::SubWorld},
};
pub fn build(_: &mut World) -> Box<dyn Schedulable> {
@ -22,7 +22,7 @@ pub fn build(_: &mut World) -> Box<dyn Schedulable> {
fn propagate_recursive(
parent_local_to_world: LocalToWorld,
world: &mut PreparedWorld,
world: &mut SubWorld,
entity: Entity,
commands: &mut CommandBuffer,
) {

View file

@ -224,7 +224,7 @@ pub fn build(_: &mut World) -> Box<dyn Schedulable> {
// Just to issue warnings: Scale + NonUniformScale
#[allow(unused_unsafe)]
unsafe {
l.iter_entities_immutable(world).for_each(
l.iter_entities(world).for_each(
|(entity, (mut _ltw, _scale, _non_uniform_scale))| {
log::warn!(
"Entity {:?} has both a Scale and NonUniformScale component.",