diff --git a/src/assets/asset_events.rs b/src/assets/asset_events.rs index f09be5dbd334750c9b6cd710e77eabcde47d9920..1bc892e0ed5a36c2f4a9e9b92661858308fdf5fd 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 d581c0057ba13ce4728dc189ecd695ba4ccea299..f60fabddc3079700417b7f74d2e044cd136352d8 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 8e01210015b60678528063024174bb9f89b178c3..7b21a568caf4f3e3e6e810e499f74840fe238daf 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, + ), + ); } } }