aboutsummaryrefslogtreecommitdiff
path: root/src/preload/mod.rs
blob: b90db3834961d4686e1ed20f75221ecd7e6e6370 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
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::<RoomAssets>()
        .init_state::<PreloadState>();
    }
}

/// 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<PreloadState>,
    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:?}");
    }
}