diff --git a/lyra-resource/src/resource_manager.rs b/lyra-resource/src/resource_manager.rs index d8326de..4d2f0ba 100644 --- a/lyra-resource/src/resource_manager.rs +++ b/lyra-resource/src/resource_manager.rs @@ -7,7 +7,7 @@ use notify_debouncer_full::{DebouncedEvent, FileIdMap}; use thiserror::Error; use uuid::Uuid; -use crate::{gltf::ModelLoader, loader::{ImageLoader, LoaderError, ResourceLoader}, resource::ResHandle, ResourceData, ResourceState}; +use crate::{gltf::ModelLoader, loader::{ImageLoader, LoaderError, ResourceLoader}, resource::ResHandle, ResourceData, ResourceState, UntypedResHandle}; /// A trait for type erased storage of a resource. /// Implemented for [`ResHandle`] @@ -26,6 +26,7 @@ pub trait ResourceStorage: Send + Sync + Any + 'static { fn is_watched(&self) -> bool; fn is_loaded(&self) -> bool; fn set_state(&self, new: ResourceState); + fn clone_untyped(&self) -> UntypedResHandle; } #[derive(Error, Debug)] @@ -121,54 +122,14 @@ impl ResourceManager { /// /// Loading resources is done asynchronously on a task spawned by `async-std`. You can use the /// handle to check if the resource is loaded. + #[inline(always)] pub fn request(&self, path: &str) -> Result, RequestError> where T: ResourceData { - let mut state = self.state_mut(); - match state.resources.get(&path.to_string()) { - Some(res) => { - let res = res.clone().as_arc_any(); - let res: Arc> = res.downcast::>().expect("Failure to downcast resource"); - let res = ResHandle::::clone(&res); - - Ok(res) - }, - None => { - if let Some(loader) = state.loaders.iter() - .find(|l| l.does_support_file(path)) { - - // Load the resource and store it - let loader = Arc::clone(loader); // stop borrowing from self - let res = loader.load(self.clone(), path); - - let handle = ResHandle::::new_loading(Some(path)); - - let thand = handle.clone(); - task::spawn(async move { - match res.await { - Ok(data) => { - let mut d = thand.write(); - d.state = ResourceState::Ready(data); - d.condvar.1.notify_all(); - } - Err(err) => { - let mut d = thand.write(); - d.state = ResourceState::Error(Arc::new(err)); - } - } - }); - - let res: Arc = Arc::from(handle.clone()); - state.resources.insert(path.to_string(), res.clone()); - state.uuid_resources.insert(res.uuid(), res); - - Ok(handle) - } else { - Err(RequestError::UnsupportedFileExtension(path.to_string())) - } - } - } + self.request_raw(path) + .map(|res| res.as_typed::() + .expect("mismatched asset type, cannot downcast")) } /// Request a resource without downcasting to a `ResHandle`. @@ -177,11 +138,11 @@ impl ResourceManager { /// let arc_any = res_arc.as_arc_any(); /// let res: Arc> = res.downcast::>().expect("Failure to downcast resource"); /// ``` - pub fn request_raw(&self, path: &str) -> Result, RequestError> { + pub fn request_raw(&self, path: &str) -> Result { let mut state = self.state_mut(); match state.resources.get(&path.to_string()) { Some(res) => { - Ok(res.clone()) + Ok(res.clone().clone_untyped()) }, None => { if let Some(loader) = state.loaders.iter() @@ -192,24 +153,29 @@ impl ResourceManager { let res = loader.load(self.clone(), path); let handle = loader.create_erased_handle(); - //let handle = ResHandle::::new_loading(); - let thand = handle.clone(); + let untyped = handle.clone_untyped(); + untyped.write().path = Some(path.to_string()); + task::spawn(async move { match res.await { Ok(data) => { - thand.set_state(ResourceState::Ready(data)); + let mut d = untyped.write(); + d.state = ResourceState::Ready(data); + d.condvar.1.notify_all(); } Err(err) => { - thand.set_state(ResourceState::Error(Arc::new(err))); + let mut d = untyped.write(); + d.state = ResourceState::Error(Arc::new(err)); } } }); let res: Arc = Arc::from(handle.clone()); + state.resources.insert(path.to_string(), res.clone()); state.uuid_resources.insert(res.uuid(), res); - Ok(handle) + Ok(handle.clone_untyped()) } else { Err(RequestError::UnsupportedFileExtension(path.to_string())) }