use super::commands::{SceneError, load_scene_binary_from_bytes};
use super::components::Scene;
use std::sync::{Arc, Mutex};
#[derive(Default)]
pub enum SceneLoadStatus {
#[default]
Idle,
Loading,
Ready(Box<Scene>),
Failed(String),
}
fn load_scene_from_bytes(bytes: &[u8]) -> Result<Scene, SceneError> {
if bytes.first() == Some(&b'{') {
let mut scene: Scene = serde_json::from_slice(bytes)?;
scene.rebuild_uuid_index();
Ok(scene)
} else {
load_scene_binary_from_bytes(bytes)
}
}
#[derive(Default)]
pub struct SceneLoadState {
status: Arc<Mutex<SceneLoadStatus>>,
}
impl SceneLoadState {
pub fn new() -> Self {
Self::default()
}
pub fn is_loading(&self) -> bool {
matches!(*self.status.lock().unwrap(), SceneLoadStatus::Loading)
}
pub fn take_result(&self) -> SceneLoadStatus {
std::mem::take(&mut *self.status.lock().unwrap())
}
#[cfg(target_arch = "wasm32")]
pub fn load_from_url(&self, url: &str) {
*self.status.lock().unwrap() = SceneLoadStatus::Loading;
let status = Arc::clone(&self.status);
let url = url.to_string();
ehttp::fetch(
ehttp::Request::get(&url),
move |result: ehttp::Result<ehttp::Response>| {
let mut state = status.lock().unwrap();
match result {
Ok(response) => {
if response.ok {
match load_scene_from_bytes(&response.bytes) {
Ok(scene) => *state = SceneLoadStatus::Ready(Box::new(scene)),
Err(error) => {
*state =
SceneLoadStatus::Failed(format!("Parse error: {}", error))
}
}
} else {
*state = SceneLoadStatus::Failed(format!(
"HTTP {}: {}",
response.status, response.status_text
));
}
}
Err(error) => *state = SceneLoadStatus::Failed(error),
}
},
);
}
#[cfg(not(target_arch = "wasm32"))]
pub fn load_from_url(&self, url: &str) {
*self.status.lock().unwrap() = SceneLoadStatus::Loading;
let path = std::path::Path::new(url);
match std::fs::read(path) {
Ok(bytes) => match load_scene_from_bytes(&bytes) {
Ok(scene) => *self.status.lock().unwrap() = SceneLoadStatus::Ready(Box::new(scene)),
Err(error) => {
*self.status.lock().unwrap() =
SceneLoadStatus::Failed(format!("Parse error: {}", error))
}
},
Err(error) => {
*self.status.lock().unwrap() =
SceneLoadStatus::Failed(format!("Read error: {}", error))
}
}
}
pub fn load_from_bytes(&self, bytes: &[u8]) {
match load_scene_from_bytes(bytes) {
Ok(scene) => *self.status.lock().unwrap() = SceneLoadStatus::Ready(Box::new(scene)),
Err(error) => {
*self.status.lock().unwrap() =
SceneLoadStatus::Failed(format!("Parse error: {}", error))
}
}
}
}