aboutsummaryrefslogtreecommitdiff
path: root/src/preload/mod.rs
blob: 266cb37c336d12aca9072e4b0f8cbb0ab12043eb (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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
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::*;

pub mod events;
pub use events::*;

pub(crate) struct DirworldPreloadPlugin;

impl Plugin for DirworldPreloadPlugin {
    fn build(&self, app: &mut App) {
        app.add_systems(
            PostUpdate,
            (
                systems::cache_preload_paths,
                systems::handle_preload.run_if(in_state(PreloadState::Loading)),
            ),
        )
        .add_systems(OnEnter(PreloadState::Done), systems::handle_spawn)
        .add_event::<DirworldPreloadBegin>()
        .insert_resource(PreloadPaths {
            src: PathBuf::new(),
            dst: PathBuf::new(),
        })
        .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,
) {
    info!("Entity: {entry:?}");
    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 = if entry.file_name().is_none() {
        payload
            .as_ref()
            .map(|payload| {
                payload
                    .door_destination
                    .as_ref()
                    .expect("Door destination missing from payload!")
                    .0
            })
            .unwrap_or_default()
    } else {
        payload
            .as_ref()
            .map(|payload| payload.transform.0)
            .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:?}");
    }
}