use std::sync::Arc; use crate::{loader::LoaderError, ResourceState, UntypedResHandle}; #[derive(Clone)] pub enum DependencyState { Loading, Error { /// The resource that had the error. handle: UntypedResHandle, /// The error that the resource ran into when loading. error: Arc, }, Ready, } impl DependencyState { /// Creates a DependencyState from a resource by retrieving its state. Does not include /// the states of the dependencies. pub fn shallow_from_res(handle: &UntypedResHandle) -> DependencyState { let res = handle.read(); match &res.state { ResourceState::Loading => DependencyState::Loading, ResourceState::Error(er) => DependencyState::Error { handle: handle.clone(), error: er.clone(), }, ResourceState::Ready(_) => DependencyState::Ready, } } /// Retrieve the state of the handle and its dependencies, does not recursively retrieve. pub fn from_res(handle: &UntypedResHandle) -> DependencyState { let res = handle.read(); match &res.state { ResourceState::Loading => DependencyState::Loading, ResourceState::Error(er) => DependencyState::Error { handle: handle.clone(), error: er.clone(), }, ResourceState::Ready(res) => { let mut lowest_state = DependencyState::Ready; for dep in res.dependencies() { let state = DependencyState::shallow_from_res(&dep); // try to find the "lowest" dependency. Meaning the state of a dependency // that would stop the parent from being ready. if state.is_loading() { lowest_state = state; break; } else if state.is_error() { lowest_state = state; break; } // anything else would be loaded, so no need to update `lowest_state` } lowest_state }, } } /// Retrieve the state of the handle and its dependencies, does not recursively retrieve. pub fn from_res_recurse(handle: &UntypedResHandle) -> DependencyState { let res = handle.read(); match &res.state { ResourceState::Loading => DependencyState::Loading, ResourceState::Error(er) => DependencyState::Error { handle: handle.clone(), error: er.clone(), }, ResourceState::Ready(res) => { let mut lowest_state = DependencyState::Ready; for dep in res.dependencies() { let state = DependencyState::from_res_recurse(&dep); // try to find the "lowest" dependency. Meaning the state of a dependency // that would stop the parent from being ready. if state.is_loading() { lowest_state = state; break; } else if state.is_error() { lowest_state = state; break; } // anything else would be loaded, so no need to update `lowest_state` } lowest_state }, } } pub fn is_ready(&self) -> bool { matches!(self, DependencyState::Ready) } pub fn is_error(&self) -> bool { matches!(self, DependencyState::Error { handle: _, error: _ }) } pub fn is_loading(&self) -> bool { matches!(self, DependencyState::Loading) } }