resource: fix wait_for_load haning when using handles from 'request_raw'

This commit is contained in:
SeanOMik 2024-04-27 00:31:20 -04:00
parent 15807a3dc1
commit 1b08482ef7
Signed by: SeanOMik
GPG Key ID: FEC9E2FC15235964
1 changed files with 18 additions and 52 deletions

View File

@ -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<T>`]
@ -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<T>(&self, path: &str) -> Result<ResHandle<T>, 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<ResHandle<T>> = res.downcast::<ResHandle<T>>().expect("Failure to downcast resource");
let res = ResHandle::<T>::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::<T>::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<dyn ResourceStorage> = 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::<T>()
.expect("mismatched asset type, cannot downcast"))
}
/// Request a resource without downcasting to a `ResHandle<T>`.
@ -177,11 +138,11 @@ impl ResourceManager {
/// let arc_any = res_arc.as_arc_any();
/// let res: Arc<ResHandle<T>> = res.downcast::<ResHandle<T>>().expect("Failure to downcast resource");
/// ```
pub fn request_raw(&self, path: &str) -> Result<Arc<dyn ResourceStorage>, RequestError> {
pub fn request_raw(&self, path: &str) -> Result<UntypedResHandle, RequestError> {
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::<T>::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<dyn ResourceStorage> = 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()))
}