fully implement bevy asset loader

This commit is contained in:
2024-07-31 22:54:55 -04:00
parent 601ede338f
commit 3f174d4e2f
15 changed files with 64 additions and 105 deletions

5
Cargo.lock generated
View File

@@ -236,6 +236,7 @@ name = "asset_loader"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"bevy", "bevy",
"ron",
"serde", "serde",
"serde_json", "serde_json",
] ]
@@ -1362,7 +1363,9 @@ version = "0.1.0"
dependencies = [ dependencies = [
"asset_loader", "asset_loader",
"bevy", "bevy",
"bevy_asset_loader",
"bevy_rapier3d", "bevy_rapier3d",
"ron",
"serde", "serde",
"serde_json", "serde_json",
"shared", "shared",
@@ -3441,6 +3444,7 @@ dependencies = [
"iyes_perf_ui", "iyes_perf_ui",
"noise 0.8.2", "noise 0.8.2",
"rayon", "rayon",
"ron",
"shared", "shared",
"world_generation", "world_generation",
] ]
@@ -5315,6 +5319,7 @@ dependencies = [
"bevy_asset_loader", "bevy_asset_loader",
"noise 0.9.0", "noise 0.9.0",
"rayon", "rayon",
"ron",
"serde", "serde",
"serde_json", "serde_json",
] ]

View File

@@ -9,3 +9,4 @@ edition = "2021"
serde = "1.0.204" serde = "1.0.204"
serde_json = "1.0.120" serde_json = "1.0.120"
bevy = "0.14.0" bevy = "0.14.0"
ron = "0.8.1"

View File

@@ -6,7 +6,6 @@ pub mod macros {
$plugin_name: ident, $plugin_name: ident,
$loader_name: ident, $loader_name: ident,
$asset_type: ident, $asset_type: ident,
$asset_loadstate_name: ident,
$extensions: expr, $extensions: expr,
$($string_name: ident -> $handle_name: ident)* ; $($string_name: ident -> $handle_name: ident)* ;
$($string_array_name: ident -> $handle_array_name: ident)* ? $($string_array_name: ident -> $handle_array_name: ident)* ?
@@ -18,52 +17,7 @@ pub mod macros {
impl Plugin for $plugin_name { impl Plugin for $plugin_name {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
app.init_asset::<$asset_type>() app.init_asset::<$asset_type>()
.init_asset_loader::<$loader_name>() .init_asset_loader::<$loader_name>();
.insert_resource($asset_loadstate_name::default())
.add_systems(Update, finalize);
}
}
fn finalize(
mut asset_events: EventReader<AssetEvent<$asset_type>>,
mut assets: ResMut<Assets<$asset_type>>,
mut load_state: ResMut<$asset_loadstate_name>,
asset_server: Res<AssetServer>
) {
for event in asset_events.read() {
match event {
AssetEvent::Added { id } => load_state.added += 1,
AssetEvent::LoadedWithDependencies { id } => {
let asset = assets.get_mut(id.clone()).unwrap();
$(
asset.$handle_name = asset_server.load(&asset.$string_name);
)*
$(
for i in 0..asset.$string_array_name.len(){
asset.$handle_array_name.push(asset_server.load(&asset.$string_array_name[i]));
}
)?
load_state.loaded += 1;
},
_ => (),
}
}
}
#[derive(Resource, Debug, Default)]
pub struct $asset_loadstate_name{
pub loaded: u32,
pub added: u32,
}
impl $asset_loadstate_name{
pub fn is_all_loaded(&self) -> bool{
if self.added == 0{
return false;
}
return self.loaded >= self.added;
} }
} }
@@ -81,20 +35,29 @@ pub mod macros {
&'a self, &'a self,
reader: &'a mut Reader<'_>, reader: &'a mut Reader<'_>,
_settings: &'a Self::Settings, _settings: &'a Self::Settings,
_load_context: &'a mut LoadContext<'_>, load_context: &'a mut LoadContext<'_>,
) -> Result<Self::Asset, Self::Error> { ) -> Result<Self::Asset, Self::Error> {
let mut data: String = String::new(); let mut bytes = Vec::new();
let read_result = reader.read_to_string(&mut data).await; let read_result = reader.read_to_end(&mut bytes).await;
if read_result.is_err() { if read_result.is_err() {
return Err(read_result.err().unwrap().to_string()); return Err(read_result.err().unwrap().to_string());
} }
let serialized: Result<Self::Asset, serde_json::Error> = let serialized: Result<Self::Asset, _> =
serde_json::from_str(&data); ron::de::from_bytes::<Self::Asset>(&bytes);
if serialized.is_err() { if serialized.is_err() {
return Err(serialized.err().unwrap().to_string()); return Err(serialized.err().unwrap().to_string());
} }
let r = serialized.unwrap(); let mut asset = serialized.unwrap();
return Ok(r); $(
asset.$handle_name = load_context.load(&asset.$string_name);
)*
$(
for i in 0..asset.$string_array_name.len(){
asset.$handle_array_name.push(load_context.load(&asset.$string_array_name[i]));
}
)?
return Ok(asset);
} }
fn extensions(&self) -> &[&str] { fn extensions(&self) -> &[&str] {

View File

@@ -17,6 +17,7 @@ bevy_asset_loader = { version = "0.21.0", features = [
"standard_dynamic_assets", "standard_dynamic_assets",
"3d", "3d",
] } ] }
ron = "0.8.1"
[features] [features]
tracing = ["bevy/trace_tracy"] tracing = ["bevy/trace_tracy"]

View File

@@ -26,8 +26,7 @@ create_asset_loader!(
BiomeAssetPlugin, BiomeAssetPlugin,
BiomeAssetLoader, BiomeAssetLoader,
BiomeAsset, BiomeAsset,
BiomeAssetLoadState, &["biome", "biome.ron"],
&["bimoe.json"],
tile_mapper_path -> tile_mapper tile_mapper_path -> tile_mapper
; ;
? ?

View File

@@ -33,4 +33,4 @@ pub struct TileAsset {
pub side_texture: String, pub side_texture: String,
} }
create_asset_loader!(TileAssetPlugin, TileAssetLoader, TileAsset, TileAssetLoadState, &["tile.json"],;?); create_asset_loader!(TileAssetPlugin, TileAssetLoader, TileAsset, &["tile", "tile.ron"],;?);

View File

@@ -31,8 +31,7 @@ create_asset_loader!(
TileMapperAssetPlugin, TileMapperAssetPlugin,
TileMapperAssetLoader, TileMapperAssetLoader,
TileMapperAsset, TileMapperAsset,
TileMapperLoadState, &["mapper", "mapper.ron"],;
&["mapper.json"],;
tiles_path -> tiles tiles_path -> tiles
? ?
); );

View File

@@ -13,7 +13,11 @@ bevy_rapier3d = "0.27.0"
serde = { version = "1.0.204", features = ["derive"] } serde = { version = "1.0.204", features = ["derive"] }
asset_loader = { path = "../../engine/asset_loader" } asset_loader = { path = "../../engine/asset_loader" }
serde_json = "1.0.120" serde_json = "1.0.120"
ron = "0.8.1"
bevy_asset_loader = { version = "0.21.0", features = [
"standard_dynamic_assets",
"3d",
] }
[features] [features]
tracing = [] tracing = []

View File

@@ -23,8 +23,7 @@ create_asset_loader!(
BuildingAssetPlugin, BuildingAssetPlugin,
BuildingAssetLoader, BuildingAssetLoader,
BuildingAsset, BuildingAsset,
BuildingAssetLoadState, &["building", "building.ron"],
&["building.json"],
prefab_path -> prefab prefab_path -> prefab
;? ;?
); );

View File

@@ -1,28 +1,11 @@
use asset_loader::create_asset_loader; use bevy::{asset::Handle, prelude::Resource};
use bevy::prelude::Resource;
use serde::{Deserialize, Serialize};
use super::building_asset::BuildingAsset; use super::building_asset::BuildingAsset;
use bevy::prelude::*;
use bevy_asset_loader::prelude::*;
#[derive(Resource)] #[derive(Resource, AssetCollection)]
pub struct BuildingDatabase{ pub struct BuildingDatabase {
pub handle: Handle<BuildingDatabaseAsset> #[asset(key = "buildings", collection(typed))]
}
#[derive(Serialize, Deserialize, Debug, TypePath, Asset)]
pub struct BuildingDatabaseAsset {
pub hq: u32,
pub buildings_paths: Vec<String>,
#[serde(skip)]
pub buildings: Vec<Handle<BuildingAsset>>, pub buildings: Vec<Handle<BuildingAsset>>,
} }
create_asset_loader!(
BuildingDatabasePlugin,
BuildingDatabaseLoader,
BuildingDatabaseAsset,
BuildingDatabaseState,
&["buildings.db.json"],;
buildings_paths -> buildings
?
);

View File

@@ -1,4 +1,8 @@
use bevy::{prelude::*, window::PrimaryWindow}; use bevy::{prelude::*, window::PrimaryWindow};
use bevy_asset_loader::loading_state::{
config::{ConfigureLoadingState, LoadingStateConfig},
LoadingStateAppExt,
};
use bevy_rapier3d::{pipeline::QueryFilter, plugin::RapierContext}; use bevy_rapier3d::{pipeline::QueryFilter, plugin::RapierContext};
use shared::{ use shared::{
despawn::Despawn, despawn::Despawn,
@@ -8,10 +12,7 @@ use shared::{
use world_generation::{hex_utils::HexCoord, map::map::Map}; use world_generation::{hex_utils::HexCoord, map::map::Map};
use crate::{ use crate::{
assets::{ assets::{building_asset::BuildingAssetPlugin, building_database::BuildingDatabase},
building_asset::BuildingAssetPlugin,
building_database::{BuildingDatabase, BuildingDatabasePlugin},
},
build_queue::{BuildQueue, QueueEntry}, build_queue::{BuildQueue, QueueEntry},
}; };
@@ -20,7 +21,11 @@ pub struct BuildingPugin;
impl Plugin for BuildingPugin { impl Plugin for BuildingPugin {
fn build(&self, app: &mut App) { fn build(&self, app: &mut App) {
app.insert_resource(BuildQueue::default()); app.insert_resource(BuildQueue::default());
app.add_plugins(BuildingAssetPlugin).add_plugins(BuildingDatabasePlugin); app.add_plugins(BuildingAssetPlugin);
app.configure_loading_state(
LoadingStateConfig::new(AssetLoadState::Loading).load_collection::<BuildingDatabase>(),
);
app.add_systems(Startup, init.run_if(in_state(AssetLoadState::Loading))); app.add_systems(Startup, init.run_if(in_state(AssetLoadState::Loading)));
app.add_systems(Update, hq_placement.run_if(in_state(GameplayState::PlaceHQ))); app.add_systems(Update, hq_placement.run_if(in_state(GameplayState::PlaceHQ)));
@@ -32,19 +37,11 @@ impl Plugin for BuildingPugin {
#[derive(Resource)] #[derive(Resource)]
struct IndicatorCube(Handle<Mesh>, Handle<StandardMaterial>); struct IndicatorCube(Handle<Mesh>, Handle<StandardMaterial>);
fn init( fn init(mut commands: Commands, mut meshes: ResMut<Assets<Mesh>>, mut materials: ResMut<Assets<StandardMaterial>>) {
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
asset_server: Res<AssetServer>,
) {
let cube = Cuboid::from_size(Vec3::splat(1.)); let cube = Cuboid::from_size(Vec3::splat(1.));
let mesh_handle = meshes.add(cube); let mesh_handle = meshes.add(cube);
let mat_handle = materials.add(Color::WHITE); let mat_handle = materials.add(Color::WHITE);
commands.insert_resource(IndicatorCube(mesh_handle, mat_handle)); commands.insert_resource(IndicatorCube(mesh_handle, mat_handle));
let db = asset_server.load("buildings/buildings.db.json");
commands.insert_resource(BuildingDatabase { handle: db });
} }
fn hq_placement( fn hq_placement(
@@ -56,7 +53,7 @@ fn hq_placement(
map: Res<Map>, map: Res<Map>,
indicator: Res<IndicatorCube>, indicator: Res<IndicatorCube>,
mut build_queue: ResMut<BuildQueue>, mut build_queue: ResMut<BuildQueue>,
next_state: ResMut<NextState<GameplayState>>, mut next_state: ResMut<NextState<GameplayState>>,
) { ) {
let win = window.single(); let win = window.single();
let (cam_transform, camera) = cam_query.single(); let (cam_transform, camera) = cam_query.single();
@@ -87,6 +84,8 @@ fn hq_placement(
building: 0.into(), building: 0.into(),
pos: contact_coord, pos: contact_coord,
}); });
next_state.set(GameplayState::Playing);
} }
} }
} }

View File

@@ -16,7 +16,11 @@ bevy_rapier3d = { version = "0.27.0", features = ["simd-stable", "parallel"] }
rayon = "1.10.0" rayon = "1.10.0"
buildings = { path = "../buildings" } buildings = { path = "../buildings" }
shared = { path = "../shared" } shared = { path = "../shared" }
bevy_asset_loader = {version ="0.21.0", features = ["standard_dynamic_assets", "3d"]} bevy_asset_loader = { version = "0.21.0", features = [
"standard_dynamic_assets",
"3d",
] }
ron = "0.8.1"
[features] [features]
tracing = ["bevy/trace_tracy", "world_generation/tracing", "buildings/tracing"] tracing = ["bevy/trace_tracy", "world_generation/tracing", "buildings/tracing"]

View File

@@ -199,6 +199,9 @@ fn rts_camera_system(
cam_targets.anim_time = cam_targets.anim_time.min(1.); cam_targets.anim_time = cam_targets.anim_time.min(1.);
} }
cam_pos.y = f32::lerp(cam_pos.y, desired_height, cam_targets.anim_time); cam_pos.y = f32::lerp(cam_pos.y, desired_height, cam_targets.anim_time);
if cam_pos.y < min_height {
cam_pos.y = min_height;
}
let t = cam_pos.y.remap(cam_cfg.min_height, cam_cfg.max_height, 0., 1.); let t = cam_pos.y.remap(cam_cfg.min_height, cam_cfg.max_height, 0., 1.);
if cam_targets.rotate_time < 1. { if cam_targets.rotate_time < 1. {

View File

@@ -1,7 +1,6 @@
#[cfg(feature = "tracing")] #[cfg(feature = "tracing")]
use bevy::log::*; use bevy::log::*;
use bevy::{ use bevy::{
asset::LoadState,
pbr::{ExtendedMaterial, NotShadowCaster}, pbr::{ExtendedMaterial, NotShadowCaster},
prelude::*, prelude::*,
}; };
@@ -11,7 +10,7 @@ use bevy_inspector_egui::quick::ResourceInspectorPlugin;
use rayon::iter::{IntoParallelRefIterator, ParallelIterator}; use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
use shared::states::{AssetLoadState, GameplayState, MenuState}; use shared::states::{AssetLoadState, GameplayState, MenuState};
use world_generation::{ use world_generation::{
biome_asset::{BiomeAsset, BiomeAssetLoadState, BiomeAssetPlugin}, biome_asset::{BiomeAsset, BiomeAssetPlugin},
biome_painter::*, biome_painter::*,
heightmap::generate_heightmap, heightmap::generate_heightmap,
hex_utils::{offset_to_index, SHORT_DIAGONAL}, hex_utils::{offset_to_index, SHORT_DIAGONAL},
@@ -65,7 +64,7 @@ impl Plugin for MapInitPlugin {
LoadingStateConfig::new(AssetLoadState::Loading) LoadingStateConfig::new(AssetLoadState::Loading)
.with_dynamic_assets_file::<StandardDynamicAssetCollection>("phos.assets.ron") .with_dynamic_assets_file::<StandardDynamicAssetCollection>("phos.assets.ron")
.load_collection::<PhosAssets>() .load_collection::<PhosAssets>()
.load_collection::<BiomePainterAsset>() .load_collection::<BiomePainterAsset>(),
); );
app.add_systems(Startup, load_textures.run_if(in_state(AssetLoadState::FinalizeAssets))); app.add_systems(Startup, load_textures.run_if(in_state(AssetLoadState::FinalizeAssets)));