euv_engine/asset/struct.rs
1use super::*;
2
3/// An entry in the asset cache containing the loaded data and its state.
4#[derive(Clone, Data, Debug, New, PartialEq)]
5pub struct AssetEntry {
6 /// The type of this asset.
7 #[get(type(copy))]
8 pub(crate) asset_type: AssetType,
9 /// The current loading state.
10 #[get(type(copy))]
11 pub(crate) state: AssetState,
12 /// The loaded image element, if this is an image asset.
13 #[get(type(clone))]
14 pub(crate) image: Option<HtmlImageElement>,
15 /// The URL this asset was loaded from.
16 pub(crate) url: String,
17}
18
19/// A cache for storing loaded game assets, keyed by URL.
20#[derive(Clone, Data, Debug, New, PartialEq)]
21pub struct AssetCache {
22 /// All cached assets keyed by their source URL.
23 #[get_mut(pub(crate))]
24 #[set(pub(crate))]
25 #[new(skip)]
26 pub(crate) entries: HashMap<String, AssetEntry>,
27}
28
29/// An asynchronous asset loader that fetches resources over HTTP
30/// and populates a shared `AssetCache`.
31#[derive(Clone, Data, New)]
32pub struct AssetLoader {
33 /// The shared cache that loaded assets are stored into.
34 #[new(skip)]
35 pub(crate) cache: Rc<EngineCell<AssetCache>>,
36 /// The shared counter of loads that have been requested but have not
37 /// settled yet. Read through [`AssetLoader::pending_count`].
38 #[new(skip)]
39 pub(crate) pending: AssetPending,
40 /// Stored closures keeping `onload`/`onerror` callbacks alive, preventing memory leaks.
41 #[new(skip)]
42 pub(crate) closures: AssetClosures,
43}
44
45/// The backing store behind [`AssetClosures`].
46///
47/// Slots are appended in pairs by [`AssetLoader::load_image`] — even indices
48/// hold an `onload` closure, odd indices the matching `onerror` closure — so
49/// a callback can identify its own slot with one captured index.
50///
51/// The fields are public because the type is reachable from the public
52/// [`AssetClosures`] alias: a private-field type exposed through a public
53/// alias would be unusable to callers, and the retained-slot count is
54/// genuinely useful as a leak diagnostic.
55#[derive(Debug, Default)]
56pub struct AssetClosureStore {
57 /// The load callbacks, in registration order. A `None` slot is one that
58 /// has already been released by [`AssetLoader::collect`].
59 pub slots: Vec<Option<Closure<dyn FnMut()>>>,
60 /// Whether the closure in the slot at the same index has run. A settled
61 /// closure cannot free itself (see [`AssetClosures`]) but is no longer
62 /// keeping anything alive that the cache still needs.
63 pub settled: Vec<bool>,
64}