tirbofish/dropbear
main / crates / eucalyptus-core / src / scene / loading.rs · 4546 bytes
crates/eucalyptus-core/src/scene/loading.rs
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
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
//! Types and functions that deal with loading scenes for scripting modules through the SceneManager API.
use std::collections::HashMap;
use std::sync::LazyLock;
use hecs::{Entity, World};
use parking_lot::Mutex;
use dropbear_engine::future::FutureHandle;
use crate::states::WorldLoadingStatus;
use crate::utils::Progress;
pub static SCENE_LOADER: LazyLock<Mutex<SceneLoader>> =
LazyLock::new(|| Mutex::new(SceneLoader::new()));
pub struct SceneLoader {
scenes_to_load: HashMap<u64, SceneLoadEntry>,
pub next_id: u64,
}
pub struct LoadedScene {
pub scene_name: String,
pub world: World,
pub active_camera: Entity,
}
pub struct SceneLoadEntry {
pub scene_name: String,
pub result: SceneLoadResult,
pub progress: Progress,
pub status: Option<crossbeam_channel::Receiver<WorldLoadingStatus>>,
pub loaded: Option<crossbeam_channel::Receiver<anyhow::Result<(World, Entity)>>>,
pub loaded_scene: Option<(World, Entity)>,
pub thread_handle: Option<FutureHandle>,
}
impl SceneLoader {
pub fn new() -> Self {
Self {
scenes_to_load: HashMap::new(),
next_id: 0,
}
}
pub fn register_load(&mut self, scene_name: String) -> u64 {
for (id, entry) in &self.scenes_to_load {
if entry.scene_name == scene_name {
if let SceneLoadResult::Pending = entry.result {
return *id;
}
}
}
self.next_id += 1;
let id = self.next_id;
self.scenes_to_load.insert(
id,
SceneLoadEntry {
scene_name,
result: SceneLoadResult::Pending,
progress: Progress {
current: 0,
total: 1,
message: "Idle".to_string(),
},
status: None,
loaded: None,
loaded_scene: None,
thread_handle: None,
},
);
id
}
pub fn find_pending_id_by_name(&self, scene_name: &str) -> Option<u64> {
self.scenes_to_load.iter().find_map(|(id, entry)| {
if entry.scene_name == scene_name {
if let SceneLoadResult::Pending = entry.result {
return Some(*id);
}
}
None
})
}
pub fn get_entry(&self, id: u64) -> Option<&SceneLoadEntry> {
self.scenes_to_load.get(&id)
}
pub fn get_entry_mut(&mut self, id: u64) -> Option<&mut SceneLoadEntry> {
self.scenes_to_load.get_mut(&id)
}
}
/// The result of loading a scene asynchronously.
#[derive(Clone, Debug)]
pub enum SceneLoadResult {
/// The scene is currently in the process of loading
Pending,
/// The scene has successfully loaded
Success,
/// The scene has failed and provided an error message.
Error(String),
}
/// A handle that references the progress of a scene in the form of a handle.
#[derive(Clone, Debug)]
pub struct SceneLoadHandle {
/// The unique number that identifies the scene load.
pub id: u64,
/// The name of the planned scene.
pub scene_name: String,
}
#[derive(Clone)]
pub struct IsSceneLoaded {
pub requested_scene: String,
pub id: Option<u64>,
pub is_first_scene: bool,
pub scene_handle_requested: bool,
pub world_loaded: bool,
pub camera_received: bool,
}
impl IsSceneLoaded {
pub fn new(requested_scene: String) -> Self {
Self {
requested_scene,
id: None,
is_first_scene: false,
scene_handle_requested: false,
world_loaded: false,
camera_received: false,
}
}
pub fn new_with_id(requested_scene: String, id: u64) -> Self {
Self {
requested_scene,
id: Some(id),
is_first_scene: false,
scene_handle_requested: false,
world_loaded: false,
camera_received: false,
}
}
pub fn new_first_time(requested_scene: String) -> Self {
Self {
requested_scene,
id: None,
is_first_scene: true,
scene_handle_requested: false,
world_loaded: false,
camera_received: false,
}
}
pub fn is_everything_loaded(&self) -> bool {
self.scene_handle_requested && self.world_loaded && self.camera_received
}
pub fn is_first_scene(&self) -> bool {
self.is_first_scene
}
}