From a1e9304dc31980703446bdb33246e314bafd3b15 Mon Sep 17 00:00:00 2001 From: Silas Bartha Date: Tue, 24 Dec 2024 00:54:31 -0500 Subject: Switched to bevy_mod_scripting, bevy 0.15 update --- src/preload/events.rs | 12 +++++++ src/preload/mod.rs | 82 ++++++++++++++++++++++++++++++++++++++++++++++++ src/preload/resources.rs | 7 +++++ src/preload/systems.rs | 41 ++++++++++++++++++++++++ 4 files changed, 142 insertions(+) create mode 100644 src/preload/events.rs create mode 100644 src/preload/mod.rs create mode 100644 src/preload/resources.rs create mode 100644 src/preload/systems.rs (limited to 'src/preload') diff --git a/src/preload/events.rs b/src/preload/events.rs new file mode 100644 index 0000000..7167d73 --- /dev/null +++ b/src/preload/events.rs @@ -0,0 +1,12 @@ +use bevy::prelude::*; + +/// Event used to trigger preload callbacks after the asset file has been pre-processed to extract +/// the payload +#[derive(Debug, Event, Clone)] +pub struct DirworldPreload { + /// Entity with the `[DirworldEntity]` component corresponding to the entity being preloaded + pub entity: Entity, + /// The data portion of the file after being pre-processed + pub data: Option>, +} + diff --git a/src/preload/mod.rs b/src/preload/mod.rs new file mode 100644 index 0000000..b90db38 --- /dev/null +++ b/src/preload/mod.rs @@ -0,0 +1,82 @@ +use crate::cache::DirworldCache; +use crate::{ + components::DirworldEntity, + resources::{DirworldCodecs, DirworldObservers, EntryType}, + utils::extract_entity_payload, + Extensions, +}; +use bevy::prelude::*; +use std::{collections::HashMap, path::PathBuf}; + +mod systems; + +mod resources; +pub use resources::*; + +mod events; +pub use events::DirworldPreload; + +pub(crate) struct DirworldPreloadPlugin; + +impl Plugin for DirworldPreloadPlugin { + fn build(&self, app: &mut App) { + app.add_systems( + PostUpdate, + systems::handle_preload.run_if(in_state(PreloadState::Loading)), + ) + .add_systems(OnEnter(PreloadState::Done), systems::handle_spawn) + .init_resource::() + .init_state::(); + } +} + +/// State of asset preloading +#[derive(States, Debug, Clone, PartialEq, Eq, Hash, Default)] +pub enum PreloadState { + /// Indicates assets are in the process of loading + #[default] + Loading, + /// Indicates all room assets are finished loading, i.e. all assets are loaded with + /// dependencies + Done, +} + +/// Initiates loading of an asset +// TODO: Make into a command extension +pub fn load_entity( + entry: &PathBuf, + cache: &mut DirworldCache, + codecs: &DirworldCodecs, + observers: &DirworldObservers, + commands: &mut Commands, + preload_state: &mut NextState, + room_assets: &mut RoomAssets, +) { + let (mut payload, data) = extract_entity_payload(&entry, &codecs); + payload = payload.map(|p| cache.get_entity_cache(&entry).unwrap_or(p)); + let entry_type = if entry.is_dir() { + EntryType::Folder + } else { + EntryType::File(entry.extensions()) + }; + let transform = payload + .as_ref() + .map(|payload| payload.transform.clone()) + .unwrap_or_default(); + let entity = commands + .spawn(( + *transform, + Visibility::Inherited, + DirworldEntity { + path: entry.clone(), + payload, + }, + )) + .id(); + if let Some(observer) = observers.get(&entry_type) { + preload_state.set(PreloadState::Loading); + room_assets.insert(entry.clone(), HashMap::default()); + commands.trigger_targets(DirworldPreload { entity, data }, observer.clone()); + info!("Triggered preload for {entry:?}"); + } +} diff --git a/src/preload/resources.rs b/src/preload/resources.rs new file mode 100644 index 0000000..4060c10 --- /dev/null +++ b/src/preload/resources.rs @@ -0,0 +1,7 @@ +use std::{collections::HashMap, path::PathBuf}; + +use bevy::prelude::*; + +/// A map of asset handles required by each entry in a room, indexed by their paths +#[derive(Resource, Default, Debug, Deref, DerefMut)] +pub struct RoomAssets(pub HashMap>); diff --git a/src/preload/systems.rs b/src/preload/systems.rs new file mode 100644 index 0000000..ec867ae --- /dev/null +++ b/src/preload/systems.rs @@ -0,0 +1,41 @@ +use bevy::prelude::*; + +use crate::{components::DirworldEntity, events::DirworldSpawn, resources::{DirworldObservers, EntryType}, Extensions}; + +use super::{PreloadState, RoomAssets}; + +pub fn handle_preload( + asset_server: Res, + room_assets: Res, + mut next_state: ResMut>, +) { + if room_assets.is_empty() + || room_assets + .values() + .flat_map(|v| v.values()) + .all(|a| asset_server.is_loaded_with_dependencies(a)) + { + info!("Preload Done."); + next_state.set(PreloadState::Done); + } +} + +pub fn handle_spawn( + dirworld_entity_query: Query<(Entity, &DirworldEntity)>, + mut commands: Commands, + observers: Res, +) { + info!("Spawning"); + for (entity, DirworldEntity { path, .. }) in dirworld_entity_query.iter() { + let entry_type = if path.is_dir() { + EntryType::Folder + } else { + EntryType::File(path.extensions()) + }; + if let Some(observer) = observers.get(&entry_type) { + info!("Found observer {observer:?} for {entry_type:?}"); + commands.trigger_targets(DirworldSpawn(entity), observer.clone()); + } + } +} + -- cgit v1.2.3