From 58556d2b4a9b9886bd45d187ed4c65a12b474717 Mon Sep 17 00:00:00 2001 From: Louis Capitanchik <contact@louiscap.co> Date: Sun, 19 Nov 2023 02:37:08 +0000 Subject: [PATCH] Use Intermediary Asset To Load External Levels --- src/assets/asset_events.rs | 30 +++++++++++++++++++--- src/ldtk/mod.rs | 51 ++++++++++++++++++++++++-------------- src/lib.rs | 11 ++++++-- 3 files changed, 68 insertions(+), 24 deletions(-) diff --git a/src/assets/asset_events.rs b/src/assets/asset_events.rs index f09be5d..1bc892e 100644 --- a/src/assets/asset_events.rs +++ b/src/assets/asset_events.rs @@ -3,7 +3,7 @@ use std::collections::HashMap; use bevy::prelude::*; use crate::assets::{LevelIndex, TileMetadata, TilesetIndex}; -use crate::ldtk::{Level, Project}; +use crate::ldtk::{Level, LevelSet, Project}; use crate::{LdtkLevel, LevelDataUpdated}; pub fn handle_ldtk_project_events( @@ -15,7 +15,7 @@ pub fn handle_ldtk_project_events( ) { for event in events.read() { match event { - AssetEvent::Added { id } | AssetEvent::Modified { id } => { + AssetEvent::LoadedWithDependencies { id } | AssetEvent::Modified { id } => { let handle = Handle::Weak(*id); if let Some(project) = assets.get(handle) { for level in project.get_all_levels() { @@ -43,6 +43,30 @@ pub fn handle_ldtk_project_events( } } +pub(crate) fn handle_ldtk_level_set_events( + mut events: EventReader<AssetEvent<LevelSet>>, + level_sets: Res<Assets<LevelSet>>, + assets: Res<Assets<Level>>, + mut level_index: ResMut<LevelIndex>, + mut update_events: EventWriter<LevelDataUpdated>, +) { + for event in events.read() { + match event { + AssetEvent::LoadedWithDependencies { id } | AssetEvent::Modified { id } => { + let handle = Handle::Weak(*id); + if let Some(level) = level_sets.get(handle) { + for level in level.0.iter().flat_map(|hd| assets.get(hd)) { + level_index + .insert(level.identifier.clone(), LdtkLevel::from(level.clone())); + update_events.send(LevelDataUpdated(level.identifier.clone())); + } + } + } + _ => {} + } + } +} + pub fn handle_ldtk_level_events( mut events: EventReader<AssetEvent<Level>>, assets: Res<Assets<Level>>, @@ -51,7 +75,7 @@ pub fn handle_ldtk_level_events( ) { for event in events.read() { match event { - AssetEvent::Added { id } | AssetEvent::Modified { id } => { + AssetEvent::LoadedWithDependencies { id } | AssetEvent::Modified { id } => { let handle = Handle::Weak(*id); if let Some(level) = assets.get(handle) { level_index.insert(level.identifier.clone(), LdtkLevel::from(level.clone())); diff --git a/src/ldtk/mod.rs b/src/ldtk/mod.rs index d581c00..f60fabd 100644 --- a/src/ldtk/mod.rs +++ b/src/ldtk/mod.rs @@ -21,7 +21,7 @@ use bevy::asset::io::Reader; use bevy::asset::{ AssetLoader, AsyncReadExt, BoxedFuture, LoadContext, UntypedAssetId, VisitAssetDependencies, }; -use bevy::prelude::Asset; +use bevy::prelude::{Asset, Handle}; use bevy::reflect::{TypePath, TypeUuid, Uuid}; use crate::ldtk; @@ -178,6 +178,10 @@ pub enum LdtkLoadError { pub type LdtkProject = Project; +#[derive(Asset, TypePath, TypeUuid)] +#[uuid = "905609d0-8687-11ee-9e30-4705d421a1e2"] +pub(crate) struct LevelSet(pub Vec<Handle<Level>>); + #[derive(Default)] pub struct LdtkLoader; impl AssetLoader for LdtkLoader { @@ -196,29 +200,38 @@ impl AssetLoader for LdtkLoader { reader.read_to_end(&mut bytes).await?; let project = Project::from_bytes(bytes.as_slice())?; - let levels = project.levels.iter().flat_map(|level| { - log::debug!( - "Checking if level is external: {} [{}]", - level.identifier, - level.external_rel_path.is_some() - ); - - level - .external_rel_path - .as_ref() - .map(|path| (level.identifier.clone(), path)) - }); + let levels = project + .levels + .iter() + .flat_map(|level| { + log::debug!( + "Checking if level is external: {} [{}]", + level.identifier, + level.external_rel_path.is_some() + ); + + level + .external_rel_path + .as_ref() + .map(|path| (level.identifier.clone(), path)) + }) + .collect::<Vec<(String, &String)>>(); let parent_path = load_context.path().parent().map(|pp| pp.to_path_buf()); - for (id, path) in levels { - load_context.labeled_asset_scope(id, |lc| { - match &parent_path { - Some(parent) => lc.load::<Level>(parent.join(path)), - None => lc.load::<Level>(path), - }; + let mut level_set = Vec::with_capacity(levels.len()); + + for (_, path) in levels { + level_set.push(match &parent_path { + Some(parent) => load_context.load::<Level>(parent.join(path)), + None => load_context.load::<Level>(path), }); } + load_context.add_labeled_asset( + format!("{}ExternalLevels", project.iid), + LevelSet(level_set), + ); + Ok(project) }) } diff --git a/src/lib.rs b/src/lib.rs index 8e01210..7b21a56 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -82,12 +82,19 @@ mod __plugin { app.add_event::<super::system::LevelDataUpdated>() .init_asset::<super::ldtk::Project>() .init_asset::<super::ldtk::Level>() + .init_asset::<super::ldtk::LevelSet>() .init_asset_loader::<super::ldtk::LdtkLoader>() .init_asset_loader::<super::ldtk::LdtkLevelLoader>() .init_resource::<super::assets::TilesetIndex>() .init_resource::<super::assets::LevelIndex>() - .add_systems(Update, super::assets::handle_ldtk_project_events) - .add_systems(Update, super::assets::handle_ldtk_level_events); + .add_systems( + Update, + ( + super::assets::handle_ldtk_project_events, + super::assets::handle_ldtk_level_events, + super::assets::handle_ldtk_level_set_events, + ), + ); } } } -- GitLab