unity_mirror_rs/unity_engine/
world.rs1use crate::commons::action::SelfMutAction;
2use crate::commons::RevelArc;
3use crate::commons::RevelWeak;
4use crate::metadata_settings::Metadata;
5use crate::unity_engine::game_object::GameObject;
6use once_cell::sync::Lazy;
7use std::collections::HashMap;
8use std::ops::{Deref, DerefMut};
9use std::sync::atomic::AtomicIsize;
10use std::sync::atomic::Ordering::SeqCst;
11
12static mut WORLDS: Lazy<Vec<RevelArc<World>>> = Lazy::new(|| Vec::new());
13static mut ACTIVE_WORLD_INDEX: AtomicIsize = AtomicIsize::new(-1);
14static mut DONT_DESTROY_OBJECT: Lazy<HashMap<u64, RevelArc<GameObject>>> =
15 Lazy::new(|| HashMap::default());
16
17#[derive(Default)]
18pub struct World {
19 #[allow(unused)]
20 scene_name: String,
21 scene_path: String,
22 game_objects: HashMap<u64, RevelArc<GameObject>>,
23}
24
25static mut SCENE_LOADED_ACTION: Lazy<SelfMutAction<(String, LoadSceneMode), ()>> =
26 Lazy::new(|| SelfMutAction::default());
27
28impl World {
29 fn new(scene_path: &str) -> Self {
30 match Metadata::get_scene(scene_path) {
31 None => {
32 panic!(
33 "Failed to load scene '{}'. Please check if the scene exists in the metadata.",
34 scene_path
35 )
36 }
37 Some(scene_metadata) => {
38 let mut world = World {
39 scene_name: scene_path.to_string(),
40 scene_path: scene_path.to_string(),
41 game_objects: Default::default(),
42 };
43 for (_, metadata_prefab) in scene_metadata.iter() {
44 let arc_game_object = GameObject::instance(metadata_prefab);
45 world
46 .game_objects
47 .insert(arc_game_object.id, arc_game_object);
48 }
49 world
50 }
51 }
52 }
53
54 fn destroy_all_game_object(&mut self) {
55 for (_id, arc_game_object) in self.game_objects.iter_mut() {
56 arc_game_object.on_disable();
57 }
58 for (_id, arc_game_object) in self.game_objects.iter_mut() {
59 arc_game_object.on_destroy();
60 }
61 }
62
63 fn destroy_game_object_with_id(&mut self, id: &u64) {
64 if let Some(mut removed_arc_game_object) = self.game_objects.remove(id) {
65 removed_arc_game_object.on_disable();
66 removed_arc_game_object.on_destroy();
67 }
68 }
69
70 pub fn add_game_object(&mut self, arc_game_object: RevelArc<GameObject>) {
71 self.game_objects
72 .insert(arc_game_object.id, arc_game_object);
73 }
74
75 pub fn get_scene_path(&self) -> String {
76 return self.scene_path.clone();
77 }
78}
79
80pub enum LoadSceneMode {
81 Single,
82 Additive,
83}
84
85pub struct WorldManagerStatic {
86 loading: bool,
87}
88
89impl WorldManagerStatic {
90 #[allow(unused)]
91 pub(crate) fn loading(&self) -> bool {
92 self.loading
93 }
94 pub(crate) fn set_loading(&mut self, loading: bool) {
95 self.loading = loading;
96 }
97}
98
99static mut WORLD_MANAGER_STATIC: Lazy<WorldManagerStatic> =
100 Lazy::new(|| WorldManagerStatic { loading: false });
101
102pub struct WorldManager;
103
104impl Deref for WorldManager {
105 type Target = WorldManagerStatic;
106
107 fn deref(&self) -> &Self::Target {
108 #[allow(static_mut_refs)]
109 unsafe {
110 &*WORLD_MANAGER_STATIC
111 }
112 }
113}
114
115impl DerefMut for WorldManager {
116 fn deref_mut(&mut self) -> &mut Self::Target {
117 #[allow(static_mut_refs)]
118 unsafe {
119 &mut *WORLD_MANAGER_STATIC
120 }
121 }
122}
123
124impl WorldManager {
125 pub fn load_scene(scene_path: &str, mode: LoadSceneMode) -> usize {
126 #[allow(static_mut_refs)]
127 unsafe {
128 Self.loading = true;
129 let world = World::new(scene_path);
130 let i = match mode {
131 LoadSceneMode::Single => {
132 WORLDS
133 .iter_mut()
134 .for_each(|world| world.destroy_all_game_object());
135 WORLDS.clear();
136 WORLDS.push(RevelArc::new(world));
137 Self::set_active_scene(0)
138 }
139 LoadSceneMode::Additive => {
140 WORLDS.push(RevelArc::new(world));
141 WORLDS.len() - 1
142 }
143 };
144 SCENE_LOADED_ACTION.call((scene_path.to_string(), mode));
145 Self.loading = false;
146 i
147 }
148 }
149
150 pub fn set_scene_loaded(f: SelfMutAction<(String, LoadSceneMode), ()>) {
151 #[allow(static_mut_refs)]
152 unsafe {
153 *SCENE_LOADED_ACTION = f;
154 }
155 }
156
157 pub fn set_active_scene(index: usize) -> usize {
158 #[allow(static_mut_refs)]
159 unsafe {
160 if index > WORLDS.len() {
161 panic!("Invalid world index: {}", index);
162 }
163 ACTIVE_WORLD_INDEX.store(index as isize, SeqCst);
164 }
165 index
166 }
167
168 pub fn active_world() -> RevelWeak<World> {
169 #[allow(static_mut_refs)]
170 unsafe {
171 let index = ACTIVE_WORLD_INDEX.load(SeqCst);
172 if index >= 0 {
173 if let Some(world) = WORLDS.get(index as usize) {
174 return world.downgrade();
175 }
176 }
177 RevelWeak::default()
178 }
179 }
180
181 pub fn dont_destroy_object(arc_game_object: RevelArc<GameObject>) -> RevelWeak<GameObject> {
182 #[allow(static_mut_refs)]
183 unsafe {
184 let id = arc_game_object.id;
185
186 let index = ACTIVE_WORLD_INDEX.load(std::sync::atomic::Ordering::SeqCst);
187
188 if let Some(world) = WORLDS.get_mut(index as usize) {
189 if world.game_objects.contains_key(&id) {
190 world.game_objects.remove(&id);
191 }
192 }
193
194 if DONT_DESTROY_OBJECT.contains_key(&id) {
195 panic!(
196 "GameObject with ID {} already exists in the dont_destroy_object world.",
197 id
198 );
199 }
200 let weak_game_object = arc_game_object.downgrade();
201 DONT_DESTROY_OBJECT.insert(id, arc_game_object);
202 weak_game_object
203 }
204 }
205
206 pub fn destroy(id: &u64) {
207 #[allow(static_mut_refs)]
208 unsafe {
209 if let Some(mut arc_game_object) = DONT_DESTROY_OBJECT.remove(id) {
210 arc_game_object.on_disable();
211 arc_game_object.on_destroy();
212 } else {
213 let index = ACTIVE_WORLD_INDEX.load(std::sync::atomic::Ordering::SeqCst);
214 if let Some(world) = WORLDS.get_mut(index as usize) {
215 world.destroy_game_object_with_id(id);
216 }
217 }
218 }
219 }
220
221 pub fn root_game_objects() -> Vec<RevelWeak<GameObject>> {
222 #[allow(static_mut_refs)]
223 unsafe {
224 let mut root_game_objects = vec![];
225
226 let index = ACTIVE_WORLD_INDEX.load(SeqCst);
227 if index >= 0 {
228 if let Some(world) = WORLDS.get(index as usize) {
229 let world_root_game_objects = world
230 .game_objects
231 .values()
232 .map(|arc_game_object| arc_game_object.downgrade())
233 .collect::<Vec<_>>();
234 root_game_objects.extend(world_root_game_objects);
235 }
236 }
237
238 let dont_destroy_objects = DONT_DESTROY_OBJECT
239 .values()
240 .filter(|arc_game_object| {
241 arc_game_object.parent.upgradable()
242 })
248 .map(|arc_game_object| arc_game_object.downgrade())
249 .collect::<Vec<_>>();
250 root_game_objects.extend(dont_destroy_objects);
251 root_game_objects
252 }
253 }
254}
255
256impl WorldManager {
257 pub(super) fn fixed_update() {
258 #[allow(static_mut_refs)]
259 unsafe {
260 for (_, game_object) in DONT_DESTROY_OBJECT.iter_mut() {
261 game_object.fixed_update();
262 }
263 for world in WORLDS.iter_mut() {
264 for (_, game_object) in world.game_objects.iter_mut() {
265 game_object.fixed_update();
266 }
267 }
268 }
269 }
270
271 pub(super) fn update() {
272 #[allow(static_mut_refs)]
273 unsafe {
274 for (_, game_object) in DONT_DESTROY_OBJECT.iter_mut() {
275 game_object.update();
276 }
277 for world in WORLDS.iter_mut() {
278 for (_, game_object) in world.game_objects.iter_mut() {
279 game_object.update();
280 }
281 }
282 }
283 }
284
285 pub(super) fn late_update() {
286 #[allow(static_mut_refs)]
287 unsafe {
288 for (_, game_object) in DONT_DESTROY_OBJECT.iter_mut() {
289 game_object.late_update();
290 }
291 for world in WORLDS.iter_mut() {
292 for (_, game_object) in world.game_objects.iter_mut() {
293 game_object.late_update();
294 }
295 }
296 }
297 }
298}
299
300#[cfg(test)]
301mod tests {
302 use super::*;
303
304 #[test]
305 fn test_change_scene() {
306 WorldManager::load_scene("Assets/Scenes/RoomScene.unity", LoadSceneMode::Single);
308 }
338}