- Steal `asset_loading` from `bevy_new_2d` - Rename `BlockResources` to `BlockAssets` - Remove `common::blocks::*` re-exports - Turn `Args` into a resource and insert it - Add `Screen` state to see when loading finishes - Run gameplay systems only in `Gameplay` state - Start server / connect when loading finishesmain
parent
058ed952fc
commit
765882b8b6
8 changed files with 226 additions and 82 deletions
@ -1,31 +0,0 @@ |
|||||||
use bevy::prelude::*; |
|
||||||
|
|
||||||
pub use common::block::*; |
|
||||||
|
|
||||||
#[derive(Resource)] |
|
||||||
pub struct BlockResources { |
|
||||||
mesh: Handle<Mesh>, |
|
||||||
material: Handle<StandardMaterial>, |
|
||||||
} |
|
||||||
|
|
||||||
pub fn setup_blocks( |
|
||||||
mut commands: Commands, |
|
||||||
mut meshes: ResMut<Assets<Mesh>>, |
|
||||||
mut materials: ResMut<Assets<StandardMaterial>>, |
|
||||||
) { |
|
||||||
commands.insert_resource(BlockResources { |
|
||||||
mesh: meshes.add(Cuboid::new(1.0, 1.0, 1.0)), |
|
||||||
material: materials.add(Color::srgb_u8(124, 144, 255)), |
|
||||||
}); |
|
||||||
} |
|
||||||
|
|
||||||
pub fn add_block_visuals( |
|
||||||
add: On<Add, Block>, |
|
||||||
mut commands: Commands, |
|
||||||
resources: Res<BlockResources>, |
|
||||||
) { |
|
||||||
commands.entity(add.entity).insert(( |
|
||||||
Mesh3d(resources.mesh.clone()), |
|
||||||
MeshMaterial3d(resources.material.clone()), |
|
||||||
)); |
|
||||||
} |
|
||||||
@ -0,0 +1,41 @@ |
|||||||
|
use bevy::prelude::*; |
||||||
|
|
||||||
|
use common::asset_loading::LoadResource; |
||||||
|
use common::block::Block; |
||||||
|
|
||||||
|
pub fn plugin(app: &mut App) { |
||||||
|
app.add_observer(insert_block_visuals); |
||||||
|
app.load_resource::<BlockAssets>(); |
||||||
|
} |
||||||
|
|
||||||
|
#[derive(Resource, Asset, Reflect, Clone)] |
||||||
|
#[reflect(Resource)] |
||||||
|
pub struct BlockAssets { |
||||||
|
#[dependency] |
||||||
|
mesh: Handle<Mesh>, |
||||||
|
#[dependency] |
||||||
|
material: Handle<StandardMaterial>, |
||||||
|
} |
||||||
|
|
||||||
|
impl FromWorld for BlockAssets { |
||||||
|
fn from_world(world: &mut World) -> Self { |
||||||
|
let assets = world.resource::<AssetServer>(); |
||||||
|
Self { |
||||||
|
mesh: assets.add(Cuboid::new(1.0, 1.0, 1.0).into()), |
||||||
|
material: assets.add(Color::srgb_u8(124, 144, 255).into()), |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// Observer which automatically inserts block visuals (mesh and
|
||||||
|
/// material) when an entity has the `Block` component added to it.
|
||||||
|
fn insert_block_visuals( |
||||||
|
add: On<Add, Block>, |
||||||
|
mut commands: Commands, |
||||||
|
block_assets: Res<BlockAssets>, |
||||||
|
) { |
||||||
|
commands.entity(add.entity).insert(( |
||||||
|
Mesh3d(block_assets.mesh.clone()), |
||||||
|
MeshMaterial3d(block_assets.material.clone()), |
||||||
|
)); |
||||||
|
} |
||||||
@ -0,0 +1,20 @@ |
|||||||
|
use bevy::prelude::*; |
||||||
|
|
||||||
|
use common::asset_loading::ResourceHandles; |
||||||
|
|
||||||
|
use crate::Screen; |
||||||
|
|
||||||
|
pub fn plugin(app: &mut App) { |
||||||
|
app.add_systems( |
||||||
|
Update, |
||||||
|
enter_gameplay_screen.run_if(in_state(Screen::Loading).and(all_assets_loaded)), |
||||||
|
); |
||||||
|
} |
||||||
|
|
||||||
|
fn enter_gameplay_screen(mut next_screen: ResMut<NextState<Screen>>) { |
||||||
|
next_screen.set(Screen::Gameplay); |
||||||
|
} |
||||||
|
|
||||||
|
fn all_assets_loaded(resource_handles: Res<ResourceHandles>) -> bool { |
||||||
|
resource_handles.is_all_done() |
||||||
|
} |
||||||
@ -0,0 +1,72 @@ |
|||||||
|
//! A high-level way to load collections of asset handles as resources.
|
||||||
|
// Taken from: https://github.com/TheBevyFlock/bevy_new_2d/blob/main/src/asset_tracking.rs
|
||||||
|
|
||||||
|
use std::collections::VecDeque; |
||||||
|
|
||||||
|
use bevy::prelude::*; |
||||||
|
|
||||||
|
pub fn plugin(app: &mut App) { |
||||||
|
app.init_resource::<ResourceHandles>(); |
||||||
|
app.add_systems(PreUpdate, load_resource_assets); |
||||||
|
} |
||||||
|
|
||||||
|
pub trait LoadResource { |
||||||
|
/// This will load the [`Resource`] as an [`Asset`]. When all of its asset dependencies
|
||||||
|
/// have been loaded, it will be inserted as a resource. This ensures that the resource only
|
||||||
|
/// exists when the assets are ready.
|
||||||
|
fn load_resource<T: Resource + Asset + Clone + FromWorld>(&mut self) -> &mut Self; |
||||||
|
} |
||||||
|
|
||||||
|
impl LoadResource for App { |
||||||
|
fn load_resource<T: Resource + Asset + Clone + FromWorld>(&mut self) -> &mut Self { |
||||||
|
self.init_asset::<T>(); |
||||||
|
let world = self.world_mut(); |
||||||
|
let value = T::from_world(world); |
||||||
|
let assets = world.resource::<AssetServer>(); |
||||||
|
let handle = assets.add(value); |
||||||
|
let mut handles = world.resource_mut::<ResourceHandles>(); |
||||||
|
handles |
||||||
|
.waiting |
||||||
|
.push_back((handle.untyped(), |world, handle| { |
||||||
|
let assets = world.resource::<Assets<T>>(); |
||||||
|
if let Some(value) = assets.get(handle.id().typed::<T>()) { |
||||||
|
world.insert_resource(value.clone()); |
||||||
|
} |
||||||
|
})); |
||||||
|
self |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/// A function that inserts a loaded resource.
|
||||||
|
type InsertLoadedResource = fn(&mut World, &UntypedHandle); |
||||||
|
|
||||||
|
#[derive(Resource, Default)] |
||||||
|
pub struct ResourceHandles { |
||||||
|
// Use a queue for waiting assets so they can be cycled through and moved to
|
||||||
|
// `finished` one at a time.
|
||||||
|
waiting: VecDeque<(UntypedHandle, InsertLoadedResource)>, |
||||||
|
finished: Vec<UntypedHandle>, |
||||||
|
} |
||||||
|
|
||||||
|
impl ResourceHandles { |
||||||
|
/// Returns true if all requested [`Asset`]s have finished loading and are available as [`Resource`]s.
|
||||||
|
pub fn is_all_done(&self) -> bool { |
||||||
|
self.waiting.is_empty() |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
fn load_resource_assets(world: &mut World) { |
||||||
|
world.resource_scope(|world, mut resource_handles: Mut<ResourceHandles>| { |
||||||
|
world.resource_scope(|world, assets: Mut<AssetServer>| { |
||||||
|
for _ in 0..resource_handles.waiting.len() { |
||||||
|
let (handle, insert_fn) = resource_handles.waiting.pop_front().unwrap(); |
||||||
|
if assets.is_loaded_with_dependencies(&handle) { |
||||||
|
insert_fn(world, &handle); |
||||||
|
resource_handles.finished.push(handle); |
||||||
|
} else { |
||||||
|
resource_handles.waiting.push_back((handle, insert_fn)); |
||||||
|
} |
||||||
|
} |
||||||
|
}); |
||||||
|
}); |
||||||
|
} |
||||||
@ -1,2 +1,3 @@ |
|||||||
|
pub mod asset_loading; |
||||||
pub mod block; |
pub mod block; |
||||||
pub mod network; |
pub mod network; |
||||||
|
|||||||
Loading…
Reference in new issue