pub struct AssetDatabase {
pub storage: World,
pub events: AssetEventBindings,
pub allow_asset_progression_failures: bool,
/* private fields */
}Expand description
Asset database for managing assets and their states.
Fields§
§storage: World§events: AssetEventBindings§allow_asset_progression_failures: boolImplementations§
Source§impl AssetDatabase
impl AssetDatabase
Sourcepub fn with_fetch(self, fetch: impl AssetFetch + 'static) -> Self
pub fn with_fetch(self, fetch: impl AssetFetch + 'static) -> Self
Adds a fetcher to its fetch stack.
§Arguments
fetch: A concrete implementation of theAssetFetchtrait.
§Returns
The updated AssetDatabase with the fetcher added.
Examples found in repository?
10fn main() -> Result<(), Box<dyn Error>> {
11 /* ANCHOR: main */
12 let mut database = AssetDatabase::default()
13 .with_protocol(FutureAssetProtocol::new("lines").process(process_lines))
14 .with_fetch(FileAssetFetch::default().with_root("resources"));
15
16 let lines = database.schedule("lines://lorem.txt")?;
17
18 while database.is_busy() {
19 database.maintain()?;
20 }
21
22 println!(
23 "Lines count: {}",
24 lines.access::<&Vec<String>>(&database).len()
25 );
26 /* ANCHOR_END: main */
27
28 Ok(())
29}More examples
11fn main() -> Result<(), Box<dyn Error>> {
12 /* ANCHOR: main */
13 let mut database = AssetDatabase::default()
14 .with_protocol(BundleAssetProtocol::new("custom", CustomAssetProcessor))
15 .with_fetch(FileAssetFetch::default().with_root("resources"));
16
17 let handle = database.ensure("custom://part1.json")?;
18
19 while database.is_busy() {
20 database.maintain()?;
21 }
22
23 let contents = handle.access::<&CustomAsset>(&database).contents(&database);
24 println!("Custom chain contents: {contents:?}");
25 /* ANCHOR_END: main */
26
27 Ok(())
28}9fn main() -> Result<(), Box<dyn Error>> {
10 /* ANCHOR: main */
11 let mut database = AssetDatabase::default()
12 .with_protocol(TextAssetProtocol)
13 // Container asset fetch allows to use partial asset fetch object
14 // that can take asset path and returns bytes from some container.
15 .with_fetch(ContainerAssetFetch::new(ZipContainerPartialFetch::new(
16 ZipArchive::new(File::open("./resources/package.zip")?)?,
17 )));
18
19 let lorem = database.ensure("text://lorem.txt")?;
20 println!("Lorem Ipsum: {}", lorem.access::<&String>(&database));
21 /* ANCHOR_END: main */
22
23 Ok(())
24}8fn main() -> Result<(), Box<dyn Error>> {
9 /* ANCHOR: main */
10 let mut database = AssetDatabase::default()
11 .with_protocol(TextAssetProtocol)
12 .with_protocol(BytesAssetProtocol)
13 // Dummy empty asset fetch to start with.
14 .with_fetch([]);
15
16 // Temporarily use different asset fetch to load asset from file.
17 let lorem = database.using_fetch(
18 FileAssetFetch::default().with_root("resources"),
19 |database| database.ensure("text://lorem.txt"),
20 )?;
21
22 println!("Lorem Ipsum: {}", lorem.access::<&String>(&database));
23 /* ANCHOR_END: main */
24
25 Ok(())
26}14fn main() -> Result<(), Box<dyn Error>> {
15 let mut database = AssetDatabase::default()
16 // Register custom asset protocol.
17 .with_protocol(CustomAssetProtocol)
18 .with_fetch(FileAssetFetch::default().with_root("resources"))
19 .with_event(|event| {
20 println!("Asset closure event: {event:#?}");
21 Ok(())
22 });
23
24 let handle = database.ensure("custom://part1.json")?;
25
26 while database.is_busy() {
27 database.maintain()?;
28 }
29
30 let contents = handle.access::<&CustomAsset>(&database).contents(&database);
31 println!("Custom chain contents: {contents:?}");
32
33 Ok(())
34}11fn main() -> Result<(), Box<dyn Error>> {
12 let mut database = AssetDatabase::default()
13 // Register custom asset processor.
14 .with_protocol(BundleAssetProtocol::new("custom", CustomAssetProcessor))
15 .with_fetch(FileAssetFetch::default().with_root("resources"));
16
17 // Ensure custom asset existence.
18 let handle = database.ensure("custom://part1.json")?;
19
20 // Make database process loaded dependencies.
21 while database.is_busy() {
22 database.maintain()?;
23 }
24
25 let contents = handle.access::<&CustomAsset>(&database).contents(&database);
26 println!("Custom chain contents: {contents:?}");
27
28 Ok(())
29}- examples/23_future_fetch.rs
- examples/05_deferred_fetch.rs
- examples/20_consumed_asset_load.rs
- examples/25_tokio_axum.rs
- examples/28_protocol_extract.rs
- examples/ingame.rs
- examples/26_throttled_fetch.rs
- examples/24_future_store.rs
- examples/21_store_asset.rs
- examples/15_localized_assets.rs
- examples/03_dependencies.rs
- examples/04_events.rs
- examples/16_extract_from_asset.rs
- examples/19_loading_progress.rs
- examples/08_dlcs_asset_packs.rs
- examples/14_assets_versioning.rs
- examples/06_router_fetch.rs
- examples/07_fallback.rs
- examples/22_store_custom_asset.rs
- examples/09_hot_reloading.rs
- examples/01_hello_world.rs
- examples/17_smart_references.rs
Sourcepub fn with_store(self, store: impl AssetStore + 'static) -> Self
pub fn with_store(self, store: impl AssetStore + 'static) -> Self
Adds a store to its store stack.
§Arguments
store: A concrete implementation of theAssetStoretrait.
§Returns
The updated AssetDatabase with the store added.
Examples found in repository?
10async fn main() -> Result<(), Box<dyn Error>> {
11 /* ANCHOR: main */
12 let mut database = AssetDatabase::default()
13 .with_protocol(TextAssetProtocol)
14 .with_fetch(FileAssetFetch::default().with_root("resources"))
15 .with_store(FutureAssetStore::new(tokio_save_file));
16
17 let _ = tokio::fs::remove_file("./resources/saved2.txt").await;
18
19 // Spawn a new asset.
20 let before = database.spawn("text://saved2.txt", ("Abra cadabra!".to_owned(),))?;
21 println!("Before: {}", before.access::<&String>(&database));
22 // Request the asset to be stored using active asset store engine.
23 before.store(&mut database)?;
24
25 // Wait until the asset is stored.
26 while database.is_busy() {
27 database.maintain()?;
28 tokio::time::sleep(tokio::time::Duration::from_millis(10)).await;
29 }
30
31 // Delete spawned asset from database just to show it will load from storage.
32 before.delete(&mut database).unwrap();
33 assert!(!before.does_exists(&database));
34
35 // Load the asset from storage, we get previously saved asset content.
36 let after = database.ensure("text://saved2.txt")?;
37 println!("After: {}", after.access::<&String>(&database));
38 /* ANCHOR_END: main */
39
40 Ok(())
41}More examples
7fn main() -> Result<(), Box<dyn Error>> {
8 /* ANCHOR: main */
9 let mut database = AssetDatabase::default()
10 .with_protocol(TextAssetProtocol)
11 .with_fetch(FileAssetFetch::default().with_root("resources"))
12 // We can enable saving assets to storage using asset stores.
13 // This one stores assets to the file system.
14 .with_store(FileAssetStore::default().with_root("resources"));
15
16 let _ = std::fs::remove_file("./resources/saved.txt");
17
18 // Spawn a new asset.
19 let before = database.spawn("text://saved.txt", ("Abra cadabra!".to_owned(),))?;
20 println!("Before: {}", before.access::<&String>(&database));
21 // Request the asset to be stored using active asset store engine.
22 before.store(&mut database)?;
23
24 // Wait until the asset is stored.
25 while database.is_busy() {
26 database.maintain()?;
27 }
28
29 // Delete spawned asset from database just to show it will load from storage.
30 before.delete(&mut database).unwrap();
31 assert!(!before.does_exists(&database));
32
33 // Load the asset from storage, we get previously saved asset content.
34 let after = database.ensure("text://saved.txt")?;
35 println!("After: {}", after.access::<&String>(&database));
36 /* ANCHOR_END: main */
37
38 Ok(())
39}17fn main() -> Result<(), Box<dyn Error>> {
18 /* ANCHOR: main */
19 let mut database = AssetDatabase::default()
20 .with_protocol(BundleAssetProtocol::new(
21 "json",
22 (
23 |bytes: Vec<u8>| {
24 let asset = serde_json::from_slice::<Person>(&bytes)?;
25 Ok((asset,).into())
26 },
27 // Additionally to decoding asset we can also encode it back to bytes.
28 // This is useful for saving assets to storage.
29 |inspector: AssetInspector| {
30 let asset = inspector.access::<&Person>();
31 let bytes = serde_json::to_vec(asset)?;
32 Ok(bytes.into())
33 },
34 ),
35 ))
36 .with_fetch(FileAssetFetch::default().with_root("resources"))
37 .with_store(FileAssetStore::default().with_root("resources"));
38
39 let _ = std::fs::remove_file("./resources/saved.json");
40
41 let before = database.spawn(
42 "json://saved.json",
43 (Person {
44 name: "Alice".to_owned(),
45 age: 42,
46 },),
47 )?;
48 println!("Before: {:?}", before.access::<&Person>(&database));
49 before.store(&mut database)?;
50
51 while database.is_busy() {
52 database.maintain()?;
53 }
54
55 before.delete(&mut database).unwrap();
56 assert!(!before.does_exists(&database));
57
58 // Load the asset from storage, we get previously saved asset content.
59 let after = database.ensure("json://saved.json")?;
60 println!("After: {:?}", after.access::<&Person>(&database));
61 /* ANCHOR_END: main */
62
63 Ok(())
64}Sourcepub fn with_protocol(self, protocol: impl AssetProtocol + 'static) -> Self
pub fn with_protocol(self, protocol: impl AssetProtocol + 'static) -> Self
Registers a new asset protocol with the database.
§Arguments
protocol: An implementation of theAssetProtocoltrait.
§Returns
The updated AssetDatabase with the protocol added.
Examples found in repository?
10fn main() -> Result<(), Box<dyn Error>> {
11 /* ANCHOR: main */
12 let mut database = AssetDatabase::default()
13 .with_protocol(FutureAssetProtocol::new("lines").process(process_lines))
14 .with_fetch(FileAssetFetch::default().with_root("resources"));
15
16 let lines = database.schedule("lines://lorem.txt")?;
17
18 while database.is_busy() {
19 database.maintain()?;
20 }
21
22 println!(
23 "Lines count: {}",
24 lines.access::<&Vec<String>>(&database).len()
25 );
26 /* ANCHOR_END: main */
27
28 Ok(())
29}More examples
11fn main() -> Result<(), Box<dyn Error>> {
12 /* ANCHOR: main */
13 let mut database = AssetDatabase::default()
14 .with_protocol(BundleAssetProtocol::new("custom", CustomAssetProcessor))
15 .with_fetch(FileAssetFetch::default().with_root("resources"));
16
17 let handle = database.ensure("custom://part1.json")?;
18
19 while database.is_busy() {
20 database.maintain()?;
21 }
22
23 let contents = handle.access::<&CustomAsset>(&database).contents(&database);
24 println!("Custom chain contents: {contents:?}");
25 /* ANCHOR_END: main */
26
27 Ok(())
28}9fn main() -> Result<(), Box<dyn Error>> {
10 /* ANCHOR: main */
11 let mut database = AssetDatabase::default()
12 .with_protocol(TextAssetProtocol)
13 // Container asset fetch allows to use partial asset fetch object
14 // that can take asset path and returns bytes from some container.
15 .with_fetch(ContainerAssetFetch::new(ZipContainerPartialFetch::new(
16 ZipArchive::new(File::open("./resources/package.zip")?)?,
17 )));
18
19 let lorem = database.ensure("text://lorem.txt")?;
20 println!("Lorem Ipsum: {}", lorem.access::<&String>(&database));
21 /* ANCHOR_END: main */
22
23 Ok(())
24}8fn main() -> Result<(), Box<dyn Error>> {
9 /* ANCHOR: main */
10 let mut database = AssetDatabase::default()
11 .with_protocol(TextAssetProtocol)
12 .with_protocol(BytesAssetProtocol)
13 // Dummy empty asset fetch to start with.
14 .with_fetch([]);
15
16 // Temporarily use different asset fetch to load asset from file.
17 let lorem = database.using_fetch(
18 FileAssetFetch::default().with_root("resources"),
19 |database| database.ensure("text://lorem.txt"),
20 )?;
21
22 println!("Lorem Ipsum: {}", lorem.access::<&String>(&database));
23 /* ANCHOR_END: main */
24
25 Ok(())
26}14fn main() -> Result<(), Box<dyn Error>> {
15 let mut database = AssetDatabase::default()
16 // Register custom asset protocol.
17 .with_protocol(CustomAssetProtocol)
18 .with_fetch(FileAssetFetch::default().with_root("resources"))
19 .with_event(|event| {
20 println!("Asset closure event: {event:#?}");
21 Ok(())
22 });
23
24 let handle = database.ensure("custom://part1.json")?;
25
26 while database.is_busy() {
27 database.maintain()?;
28 }
29
30 let contents = handle.access::<&CustomAsset>(&database).contents(&database);
31 println!("Custom chain contents: {contents:?}");
32
33 Ok(())
34}11fn main() -> Result<(), Box<dyn Error>> {
12 let mut database = AssetDatabase::default()
13 // Register custom asset processor.
14 .with_protocol(BundleAssetProtocol::new("custom", CustomAssetProcessor))
15 .with_fetch(FileAssetFetch::default().with_root("resources"));
16
17 // Ensure custom asset existence.
18 let handle = database.ensure("custom://part1.json")?;
19
20 // Make database process loaded dependencies.
21 while database.is_busy() {
22 database.maintain()?;
23 }
24
25 let contents = handle.access::<&CustomAsset>(&database).contents(&database);
26 println!("Custom chain contents: {contents:?}");
27
28 Ok(())
29}- examples/23_future_fetch.rs
- examples/05_deferred_fetch.rs
- examples/20_consumed_asset_load.rs
- examples/25_tokio_axum.rs
- examples/28_protocol_extract.rs
- examples/ingame.rs
- examples/26_throttled_fetch.rs
- examples/24_future_store.rs
- examples/21_store_asset.rs
- examples/15_localized_assets.rs
- examples/03_dependencies.rs
- examples/04_events.rs
- examples/16_extract_from_asset.rs
- examples/19_loading_progress.rs
- examples/08_dlcs_asset_packs.rs
- examples/14_assets_versioning.rs
- examples/06_router_fetch.rs
- examples/07_fallback.rs
- examples/22_store_custom_asset.rs
- examples/09_hot_reloading.rs
- examples/01_hello_world.rs
- examples/17_smart_references.rs
Sourcepub fn with_asset_progression_failures(self) -> Self
pub fn with_asset_progression_failures(self) -> Self
Enables allowing asset progression failures.
§Returns
The updated AssetDatabase with the option enabled.
Sourcepub fn with_event(self, listener: impl AssetEventListener + 'static) -> Self
pub fn with_event(self, listener: impl AssetEventListener + 'static) -> Self
Examples found in repository?
14fn main() -> Result<(), Box<dyn Error>> {
15 let mut database = AssetDatabase::default()
16 // Register custom asset protocol.
17 .with_protocol(CustomAssetProtocol)
18 .with_fetch(FileAssetFetch::default().with_root("resources"))
19 .with_event(|event| {
20 println!("Asset closure event: {event:#?}");
21 Ok(())
22 });
23
24 let handle = database.ensure("custom://part1.json")?;
25
26 while database.is_busy() {
27 database.maintain()?;
28 }
29
30 let contents = handle.access::<&CustomAsset>(&database).contents(&database);
31 println!("Custom chain contents: {contents:?}");
32
33 Ok(())
34}More examples
13fn main() -> Result<(), Box<dyn Error>> {
14 let mut database = AssetDatabase::default()
15 // Register custom asset protocol.
16 .with_protocol(CustomAssetProtocol)
17 .with_fetch(FileAssetFetch::default().with_root("resources"))
18 .with_event(|event| {
19 println!("Asset closure event: {event:#?}");
20 Ok(())
21 });
22
23 // We spawn an asset with configuration meta to be extracted into asset
24 // components, as well as path being rewritten to not contain meta values.
25 database.ensure("custom://lorem.txt?uppercase")?;
26
27 while database.is_busy() {
28 database.maintain()?;
29 }
30
31 // Accessing asset and its extracted meta data via shortened path.
32 let handle = database.find("custom://lorem.txt").unwrap();
33 let (contents, meta) = handle.access::<(&String, &Meta)>(&database);
34 println!("Custom asset meta: {meta:?}");
35 println!("Custom asset contents: {contents:?}");
36
37 Ok(())
38}Sourcepub fn push_fetch(&mut self, fetch: impl AssetFetch + 'static)
pub fn push_fetch(&mut self, fetch: impl AssetFetch + 'static)
Examples found in repository?
12fn main() -> Result<(), Box<dyn Error>> {
13 /* ANCHOR: main */
14 let mut database = AssetDatabase::default()
15 .with_protocol(TextAssetProtocol)
16 .with_protocol(BytesAssetProtocol)
17 // We start with regular fetch engine.
18 .with_fetch(FileAssetFetch::default().with_root("resources"));
19
20 // Start loading package ZIP bytes.
21 database.ensure("bytes://package.zip")?;
22
23 // Maintain database while busy.
24 while database.is_busy() {
25 database.maintain()?;
26 }
27
28 // Then we push extraction asset fetch to fetch engine stack. From now on
29 // any future asset request will be extracted from loaded ZIP archive.
30 database.push_fetch(ExtractAssetFetch::new(from_asset_extractor(
31 "bytes://package.zip",
32 |bytes: &Vec<u8>, path| {
33 let mut archive = ZipArchive::new(Cursor::new(bytes))?;
34 let mut file = archive.by_name(path.path())?;
35 let mut result = vec![];
36 file.read_to_end(&mut result)?;
37 Ok(result)
38 },
39 )));
40
41 // Extract some assets from ZIP asset.
42 let lorem = database.ensure("text://lorem.txt")?;
43 let trash = database.ensure("bytes://trash.bin")?;
44
45 // Run maintenance to process extracted asset bytes.
46 database.maintain()?;
47
48 println!("Lorem Ipsum: {}", lorem.access::<&String>(&database));
49 println!("Bytes: {:?}", trash.access::<&Vec<u8>>(&database));
50 /* ANCHOR_END: main */
51
52 Ok(())
53}Sourcepub fn pop_fetch(&mut self) -> Option<Box<dyn AssetFetch>>
pub fn pop_fetch(&mut self) -> Option<Box<dyn AssetFetch>>
Removes and returns the top fetch engine from the stack.
§Returns
The old fetch engine if present.
Returns None if the stack is empty.
Sourcepub fn swap_fetch(
&mut self,
fetch: impl AssetFetch + 'static,
) -> Option<Box<dyn AssetFetch>>
pub fn swap_fetch( &mut self, fetch: impl AssetFetch + 'static, ) -> Option<Box<dyn AssetFetch>>
Sourcepub fn using_fetch<R>(
&mut self,
fetch: impl AssetFetch + 'static,
f: impl FnOnce(&mut Self) -> Result<R, Box<dyn Error>>,
) -> Result<R, Box<dyn Error>>
pub fn using_fetch<R>( &mut self, fetch: impl AssetFetch + 'static, f: impl FnOnce(&mut Self) -> Result<R, Box<dyn Error>>, ) -> Result<R, Box<dyn Error>>
Temporarily uses a fetch engine to perform a closure and removes it afterward.
§Arguments
fetch: The fetch engine to add temporarily.f: The closure to execute using the fetch engine.
§Returns
The result of the closure if successful, or an error otherwise.
Examples found in repository?
8fn main() -> Result<(), Box<dyn Error>> {
9 /* ANCHOR: main */
10 let mut database = AssetDatabase::default()
11 .with_protocol(TextAssetProtocol)
12 .with_protocol(BytesAssetProtocol)
13 // Dummy empty asset fetch to start with.
14 .with_fetch([]);
15
16 // Temporarily use different asset fetch to load asset from file.
17 let lorem = database.using_fetch(
18 FileAssetFetch::default().with_root("resources"),
19 |database| database.ensure("text://lorem.txt"),
20 )?;
21
22 println!("Lorem Ipsum: {}", lorem.access::<&String>(&database));
23 /* ANCHOR_END: main */
24
25 Ok(())
26}Sourcepub fn push_store(&mut self, store: impl AssetStore + 'static)
pub fn push_store(&mut self, store: impl AssetStore + 'static)
Sourcepub fn pop_store(&mut self) -> Option<Box<dyn AssetStore>>
pub fn pop_store(&mut self) -> Option<Box<dyn AssetStore>>
Removes and returns the top store engine from the stack.
§Returns
The old store engine if present.
Returns None if the stack is empty.
Sourcepub fn swap_store(
&mut self,
store: impl AssetStore + 'static,
) -> Option<Box<dyn AssetStore>>
pub fn swap_store( &mut self, store: impl AssetStore + 'static, ) -> Option<Box<dyn AssetStore>>
Sourcepub fn using_store<R>(
&mut self,
store: impl AssetStore + 'static,
f: impl FnOnce(&mut Self) -> Result<R, Box<dyn Error>>,
) -> Result<R, Box<dyn Error>>
pub fn using_store<R>( &mut self, store: impl AssetStore + 'static, f: impl FnOnce(&mut Self) -> Result<R, Box<dyn Error>>, ) -> Result<R, Box<dyn Error>>
Sourcepub fn add_protocol(&mut self, protocol: impl AssetProtocol + 'static)
pub fn add_protocol(&mut self, protocol: impl AssetProtocol + 'static)
Registers a new protocol for processing assets.
§Arguments
protocol: An implementation of theAssetProtocoltrait.
Sourcepub fn remove_protocol(&mut self, name: &str) -> Option<Box<dyn AssetProtocol>>
pub fn remove_protocol(&mut self, name: &str) -> Option<Box<dyn AssetProtocol>>
Sourcepub fn find(&self, path: impl Into<AssetPathStatic>) -> Option<AssetHandle>
pub fn find(&self, path: impl Into<AssetPathStatic>) -> Option<AssetHandle>
Finds an asset by its path and returns a handle.
§Arguments
path: The path of the asset to find.
§Returns
An AssetHandle if the asset is found, otherwise None.
Examples found in repository?
13fn main() -> Result<(), Box<dyn Error>> {
14 let mut database = AssetDatabase::default()
15 // Register custom asset protocol.
16 .with_protocol(CustomAssetProtocol)
17 .with_fetch(FileAssetFetch::default().with_root("resources"))
18 .with_event(|event| {
19 println!("Asset closure event: {event:#?}");
20 Ok(())
21 });
22
23 // We spawn an asset with configuration meta to be extracted into asset
24 // components, as well as path being rewritten to not contain meta values.
25 database.ensure("custom://lorem.txt?uppercase")?;
26
27 while database.is_busy() {
28 database.maintain()?;
29 }
30
31 // Accessing asset and its extracted meta data via shortened path.
32 let handle = database.find("custom://lorem.txt").unwrap();
33 let (contents, meta) = handle.access::<(&String, &Meta)>(&database);
34 println!("Custom asset meta: {meta:?}");
35 println!("Custom asset contents: {contents:?}");
36
37 Ok(())
38}More examples
12fn main() -> Result<(), Box<dyn Error>> {
13 let mut database = AssetDatabase::default()
14 .with_protocol(TextAssetProtocol)
15 .with_protocol(BytesAssetProtocol)
16 .with_protocol(BundleAssetProtocol::new("json", |bytes: Vec<u8>| {
17 let asset = serde_json::from_slice::<Value>(&bytes)?;
18 Ok((asset,).into())
19 }))
20 .with_protocol(GroupAssetProtocol)
21 .with_fetch(FileAssetFetch::default().with_root("resources"));
22
23 /* ANCHOR: events */
24 // We can bind closures to asset event bindings for any asset progression tracking.
25 database.events.bind(|event| {
26 println!("Asset closure event: {event:#?}");
27 Ok(())
28 });
29
30 // Create channel for asset events communication.
31 let (tx, rx) = channel();
32
33 // Start loading asset and its dependencies.
34 let group = database.ensure("group://group.txt")?;
35 // We can also bind sender to asset event bindings.
36 group.ensure::<AssetEventBindings>(&mut database)?.bind(tx);
37
38 while database.is_busy() {
39 database.maintain()?;
40 }
41
42 // Read sent events from receiver.
43 while let Ok(event) = rx.try_recv() {
44 println!("Group channel event: {event:#?}");
45 }
46 /* ANCHOR_END: events */
47
48 println!(
49 "Lorem Ipsum: {}",
50 database
51 .find("text://lorem.txt")
52 .unwrap()
53 .access::<&String>(&database)
54 );
55
56 Ok(())
57}Sourcepub fn schedule(
&mut self,
path: impl Into<AssetPathStatic>,
) -> Result<AssetHandle, Box<dyn Error>>
pub fn schedule( &mut self, path: impl Into<AssetPathStatic>, ) -> Result<AssetHandle, Box<dyn Error>>
Schedules an asset to be resolved later if not already existing.
§Arguments
path: The path of the asset to schedule.
§Returns
An AssetHandle for the scheduled asset.
Examples found in repository?
10fn main() -> Result<(), Box<dyn Error>> {
11 /* ANCHOR: main */
12 let mut database = AssetDatabase::default()
13 .with_protocol(FutureAssetProtocol::new("lines").process(process_lines))
14 .with_fetch(FileAssetFetch::default().with_root("resources"));
15
16 let lines = database.schedule("lines://lorem.txt")?;
17
18 while database.is_busy() {
19 database.maintain()?;
20 }
21
22 println!(
23 "Lines count: {}",
24 lines.access::<&Vec<String>>(&database).len()
25 );
26 /* ANCHOR_END: main */
27
28 Ok(())
29}More examples
11fn main() -> Result<(), Box<dyn Error>> {
12 /* ANCHOR: main */
13 let mut database = AssetDatabase::default()
14 .with_protocol(BytesAssetProtocol)
15 .with_fetch(DeferredAssetFetch::new(
16 FileAssetFetch::default().with_root("resources"),
17 ));
18
19 // Create tracker to track specific assets loading status.
20 // We schedule them to load later at first database maintainance
21 // to not load them too quickly.
22 let tracker = AssetsTracker::default().with_many([
23 database.schedule("bytes://dlc.zip")?,
24 database.schedule("bytes://ferris.png")?,
25 database.schedule("bytes://main.zip")?,
26 database.schedule("bytes://package.zip")?,
27 ]);
28
29 // Prepare loading status to fill in.
30 // Its structure tells level of detail for particular categories. Each
31 // category can be either amount or list of assets. Here we use amount
32 // for every category, because we track just numeric progress.
33 let mut status = AssetsStatus::amount();
34
35 // Track progress as long as database is busy.
36 while database.is_busy() {
37 database.maintain()?;
38
39 // Report current loading status (progress).
40 tracker.report(&database, &mut status);
41 let progress = status.progress();
42
43 println!(
44 "Loading {}% ({}/{})",
45 progress.factor() * 100.0,
46 progress.ready_to_use,
47 progress.total()
48 );
49 }
50 /* ANCHOR_END: main */
51
52 Ok(())
53}Sourcepub fn spawn(
&mut self,
path: impl Into<AssetPathStatic>,
bundle: impl Bundle,
) -> Result<AssetHandle, Box<dyn Error>>
pub fn spawn( &mut self, path: impl Into<AssetPathStatic>, bundle: impl Bundle, ) -> Result<AssetHandle, Box<dyn Error>>
Adds an asset to database, already resolved. Great for runtime generated assets.
§Arguments
path: The path of the asset to schedule.bundle: Components bundle to put into spawned asset.
§Returns
An AssetHandle for the scheduled asset.
Examples found in repository?
10async fn main() -> Result<(), Box<dyn Error>> {
11 /* ANCHOR: main */
12 let mut database = AssetDatabase::default()
13 .with_protocol(TextAssetProtocol)
14 .with_fetch(FileAssetFetch::default().with_root("resources"))
15 .with_store(FutureAssetStore::new(tokio_save_file));
16
17 let _ = tokio::fs::remove_file("./resources/saved2.txt").await;
18
19 // Spawn a new asset.
20 let before = database.spawn("text://saved2.txt", ("Abra cadabra!".to_owned(),))?;
21 println!("Before: {}", before.access::<&String>(&database));
22 // Request the asset to be stored using active asset store engine.
23 before.store(&mut database)?;
24
25 // Wait until the asset is stored.
26 while database.is_busy() {
27 database.maintain()?;
28 tokio::time::sleep(tokio::time::Duration::from_millis(10)).await;
29 }
30
31 // Delete spawned asset from database just to show it will load from storage.
32 before.delete(&mut database).unwrap();
33 assert!(!before.does_exists(&database));
34
35 // Load the asset from storage, we get previously saved asset content.
36 let after = database.ensure("text://saved2.txt")?;
37 println!("After: {}", after.access::<&String>(&database));
38 /* ANCHOR_END: main */
39
40 Ok(())
41}More examples
7fn main() -> Result<(), Box<dyn Error>> {
8 /* ANCHOR: main */
9 let mut database = AssetDatabase::default()
10 .with_protocol(TextAssetProtocol)
11 .with_fetch(FileAssetFetch::default().with_root("resources"))
12 // We can enable saving assets to storage using asset stores.
13 // This one stores assets to the file system.
14 .with_store(FileAssetStore::default().with_root("resources"));
15
16 let _ = std::fs::remove_file("./resources/saved.txt");
17
18 // Spawn a new asset.
19 let before = database.spawn("text://saved.txt", ("Abra cadabra!".to_owned(),))?;
20 println!("Before: {}", before.access::<&String>(&database));
21 // Request the asset to be stored using active asset store engine.
22 before.store(&mut database)?;
23
24 // Wait until the asset is stored.
25 while database.is_busy() {
26 database.maintain()?;
27 }
28
29 // Delete spawned asset from database just to show it will load from storage.
30 before.delete(&mut database).unwrap();
31 assert!(!before.does_exists(&database));
32
33 // Load the asset from storage, we get previously saved asset content.
34 let after = database.ensure("text://saved.txt")?;
35 println!("After: {}", after.access::<&String>(&database));
36 /* ANCHOR_END: main */
37
38 Ok(())
39}17fn main() -> Result<(), Box<dyn Error>> {
18 /* ANCHOR: main */
19 let mut database = AssetDatabase::default()
20 .with_protocol(BundleAssetProtocol::new(
21 "json",
22 (
23 |bytes: Vec<u8>| {
24 let asset = serde_json::from_slice::<Person>(&bytes)?;
25 Ok((asset,).into())
26 },
27 // Additionally to decoding asset we can also encode it back to bytes.
28 // This is useful for saving assets to storage.
29 |inspector: AssetInspector| {
30 let asset = inspector.access::<&Person>();
31 let bytes = serde_json::to_vec(asset)?;
32 Ok(bytes.into())
33 },
34 ),
35 ))
36 .with_fetch(FileAssetFetch::default().with_root("resources"))
37 .with_store(FileAssetStore::default().with_root("resources"));
38
39 let _ = std::fs::remove_file("./resources/saved.json");
40
41 let before = database.spawn(
42 "json://saved.json",
43 (Person {
44 name: "Alice".to_owned(),
45 age: 42,
46 },),
47 )?;
48 println!("Before: {:?}", before.access::<&Person>(&database));
49 before.store(&mut database)?;
50
51 while database.is_busy() {
52 database.maintain()?;
53 }
54
55 before.delete(&mut database).unwrap();
56 assert!(!before.does_exists(&database));
57
58 // Load the asset from storage, we get previously saved asset content.
59 let after = database.ensure("json://saved.json")?;
60 println!("After: {:?}", after.access::<&Person>(&database));
61 /* ANCHOR_END: main */
62
63 Ok(())
64}Sourcepub fn ensure(
&mut self,
path: impl Into<AssetPathStatic>,
) -> Result<AssetHandle, Box<dyn Error>>
pub fn ensure( &mut self, path: impl Into<AssetPathStatic>, ) -> Result<AssetHandle, Box<dyn Error>>
Ensures an asset exists or is scheduled for resolution.
§Arguments
path: The path of the asset to ensure.
§Returns
An AssetHandle for the asset.
Examples found in repository?
89 fn on_init(&mut self, graphics: &mut Graphics<Vertex>, _: &mut AppControl) {
90 // Setup scene camera.
91 graphics.state.color = [0.25, 0.25, 0.25, 1.0];
92 graphics.state.main_camera.screen_alignment = 0.5.into();
93 graphics.state.main_camera.scaling = CameraScaling::FitToView {
94 size: 1000.0.into(),
95 inside: false,
96 };
97
98 // Load this scene group.
99 self.assets.ensure("group://ingame.txt").unwrap();
100 }More examples
106async fn get_asset<T: Component + Clone>(
107 path: impl Into<AssetPathStatic>,
108 database: Arc<RwLock<AssetDatabase>>,
109) -> Result<T, String> {
110 let path = path.into();
111
112 let handle = database
113 .write()
114 .await
115 .ensure(path.clone())
116 .map_err(|e| e.to_string())?;
117
118 while !handle.is_ready_to_use(&*database.read().await) {
119 sleep(Duration::from_millis(10)).await;
120 }
121
122 handle
123 .access_checked::<&T>(&*database.read().await)
124 .cloned()
125 .ok_or_else(|| format!("Asset has no bytes: {path}"))
126}11fn main() -> Result<(), Box<dyn Error>> {
12 /* ANCHOR: main */
13 let mut database = AssetDatabase::default()
14 .with_protocol(BundleAssetProtocol::new("custom", CustomAssetProcessor))
15 .with_fetch(FileAssetFetch::default().with_root("resources"));
16
17 let handle = database.ensure("custom://part1.json")?;
18
19 while database.is_busy() {
20 database.maintain()?;
21 }
22
23 let contents = handle.access::<&CustomAsset>(&database).contents(&database);
24 println!("Custom chain contents: {contents:?}");
25 /* ANCHOR_END: main */
26
27 Ok(())
28}9fn main() -> Result<(), Box<dyn Error>> {
10 /* ANCHOR: main */
11 let mut database = AssetDatabase::default()
12 .with_protocol(TextAssetProtocol)
13 // Container asset fetch allows to use partial asset fetch object
14 // that can take asset path and returns bytes from some container.
15 .with_fetch(ContainerAssetFetch::new(ZipContainerPartialFetch::new(
16 ZipArchive::new(File::open("./resources/package.zip")?)?,
17 )));
18
19 let lorem = database.ensure("text://lorem.txt")?;
20 println!("Lorem Ipsum: {}", lorem.access::<&String>(&database));
21 /* ANCHOR_END: main */
22
23 Ok(())
24}8fn main() -> Result<(), Box<dyn Error>> {
9 /* ANCHOR: main */
10 let mut database = AssetDatabase::default()
11 .with_protocol(TextAssetProtocol)
12 .with_protocol(BytesAssetProtocol)
13 // Dummy empty asset fetch to start with.
14 .with_fetch([]);
15
16 // Temporarily use different asset fetch to load asset from file.
17 let lorem = database.using_fetch(
18 FileAssetFetch::default().with_root("resources"),
19 |database| database.ensure("text://lorem.txt"),
20 )?;
21
22 println!("Lorem Ipsum: {}", lorem.access::<&String>(&database));
23 /* ANCHOR_END: main */
24
25 Ok(())
26}14fn main() -> Result<(), Box<dyn Error>> {
15 let mut database = AssetDatabase::default()
16 // Register custom asset protocol.
17 .with_protocol(CustomAssetProtocol)
18 .with_fetch(FileAssetFetch::default().with_root("resources"))
19 .with_event(|event| {
20 println!("Asset closure event: {event:#?}");
21 Ok(())
22 });
23
24 let handle = database.ensure("custom://part1.json")?;
25
26 while database.is_busy() {
27 database.maintain()?;
28 }
29
30 let contents = handle.access::<&CustomAsset>(&database).contents(&database);
31 println!("Custom chain contents: {contents:?}");
32
33 Ok(())
34}- examples/11_custom_protocol_simple.rs
- examples/23_future_fetch.rs
- examples/05_deferred_fetch.rs
- examples/28_protocol_extract.rs
- examples/26_throttled_fetch.rs
- examples/24_future_store.rs
- examples/21_store_asset.rs
- examples/15_localized_assets.rs
- examples/03_dependencies.rs
- examples/04_events.rs
- examples/16_extract_from_asset.rs
- examples/08_dlcs_asset_packs.rs
- examples/14_assets_versioning.rs
- examples/06_router_fetch.rs
- examples/07_fallback.rs
- examples/22_store_custom_asset.rs
- examples/09_hot_reloading.rs
- examples/01_hello_world.rs
Sourcepub fn unload<'a>(
&mut self,
path: impl Into<AssetPath<'a>>,
) -> Result<(), Box<dyn Error>>
pub fn unload<'a>( &mut self, path: impl Into<AssetPath<'a>>, ) -> Result<(), Box<dyn Error>>
Unloads an asset by its path, removing it from the storage.
§Arguments
path: The path of the asset to unload.
Sourcepub fn dereference_or_unload<'a>(
&mut self,
path: impl Into<AssetPath<'a>>,
) -> Result<(), Box<dyn Error>>
pub fn dereference_or_unload<'a>( &mut self, path: impl Into<AssetPath<'a>>, ) -> Result<(), Box<dyn Error>>
Tries to dereference an asset by its path. If asset has no references left, it gets removed it from the storage.
§Arguments
path: The path of the asset to unload.
Sourcepub fn reload(
&mut self,
path: impl Into<AssetPathStatic>,
) -> Result<AssetHandle, Box<dyn Error>>
pub fn reload( &mut self, path: impl Into<AssetPathStatic>, ) -> Result<AssetHandle, Box<dyn Error>>
Sourcepub fn assets_with<T: Component>(
&self,
) -> impl Iterator<Item = AssetHandle> + '_
pub fn assets_with<T: Component>( &self, ) -> impl Iterator<Item = AssetHandle> + '_
Returns an iterator over all assets with a specific component.
§Returns
An iterator that yields AssetHandle instances.
Sourcepub fn has<T: Component>(&self) -> bool
pub fn has<T: Component>(&self) -> bool
Checks if there are any assets with a specific component.
§Returns
true if there is at least one asset with the component, otherwise `false
Sourcepub fn is_busy(&self) -> bool
pub fn is_busy(&self) -> bool
Determines if the asset database is currently busy with tasks.
§Returns
true if busy, otherwise false.
Examples found in repository?
10fn main() -> Result<(), Box<dyn Error>> {
11 /* ANCHOR: main */
12 let mut database = AssetDatabase::default()
13 .with_protocol(FutureAssetProtocol::new("lines").process(process_lines))
14 .with_fetch(FileAssetFetch::default().with_root("resources"));
15
16 let lines = database.schedule("lines://lorem.txt")?;
17
18 while database.is_busy() {
19 database.maintain()?;
20 }
21
22 println!(
23 "Lines count: {}",
24 lines.access::<&Vec<String>>(&database).len()
25 );
26 /* ANCHOR_END: main */
27
28 Ok(())
29}More examples
11fn main() -> Result<(), Box<dyn Error>> {
12 /* ANCHOR: main */
13 let mut database = AssetDatabase::default()
14 .with_protocol(BundleAssetProtocol::new("custom", CustomAssetProcessor))
15 .with_fetch(FileAssetFetch::default().with_root("resources"));
16
17 let handle = database.ensure("custom://part1.json")?;
18
19 while database.is_busy() {
20 database.maintain()?;
21 }
22
23 let contents = handle.access::<&CustomAsset>(&database).contents(&database);
24 println!("Custom chain contents: {contents:?}");
25 /* ANCHOR_END: main */
26
27 Ok(())
28}14fn main() -> Result<(), Box<dyn Error>> {
15 let mut database = AssetDatabase::default()
16 // Register custom asset protocol.
17 .with_protocol(CustomAssetProtocol)
18 .with_fetch(FileAssetFetch::default().with_root("resources"))
19 .with_event(|event| {
20 println!("Asset closure event: {event:#?}");
21 Ok(())
22 });
23
24 let handle = database.ensure("custom://part1.json")?;
25
26 while database.is_busy() {
27 database.maintain()?;
28 }
29
30 let contents = handle.access::<&CustomAsset>(&database).contents(&database);
31 println!("Custom chain contents: {contents:?}");
32
33 Ok(())
34}11fn main() -> Result<(), Box<dyn Error>> {
12 let mut database = AssetDatabase::default()
13 // Register custom asset processor.
14 .with_protocol(BundleAssetProtocol::new("custom", CustomAssetProcessor))
15 .with_fetch(FileAssetFetch::default().with_root("resources"));
16
17 // Ensure custom asset existence.
18 let handle = database.ensure("custom://part1.json")?;
19
20 // Make database process loaded dependencies.
21 while database.is_busy() {
22 database.maintain()?;
23 }
24
25 let contents = handle.access::<&CustomAsset>(&database).contents(&database);
26 println!("Custom chain contents: {contents:?}");
27
28 Ok(())
29}13fn main() -> Result<(), Box<dyn Error>> {
14 let mut database = AssetDatabase::default()
15 // Register custom asset protocol.
16 .with_protocol(CustomAssetProtocol)
17 .with_fetch(FileAssetFetch::default().with_root("resources"))
18 .with_event(|event| {
19 println!("Asset closure event: {event:#?}");
20 Ok(())
21 });
22
23 // We spawn an asset with configuration meta to be extracted into asset
24 // components, as well as path being rewritten to not contain meta values.
25 database.ensure("custom://lorem.txt?uppercase")?;
26
27 while database.is_busy() {
28 database.maintain()?;
29 }
30
31 // Accessing asset and its extracted meta data via shortened path.
32 let handle = database.find("custom://lorem.txt").unwrap();
33 let (contents, meta) = handle.access::<(&String, &Meta)>(&database);
34 println!("Custom asset meta: {meta:?}");
35 println!("Custom asset contents: {contents:?}");
36
37 Ok(())
38}10async fn main() -> Result<(), Box<dyn Error>> {
11 /* ANCHOR: main */
12 let mut database = AssetDatabase::default()
13 .with_protocol(TextAssetProtocol)
14 .with_fetch(FileAssetFetch::default().with_root("resources"))
15 .with_store(FutureAssetStore::new(tokio_save_file));
16
17 let _ = tokio::fs::remove_file("./resources/saved2.txt").await;
18
19 // Spawn a new asset.
20 let before = database.spawn("text://saved2.txt", ("Abra cadabra!".to_owned(),))?;
21 println!("Before: {}", before.access::<&String>(&database));
22 // Request the asset to be stored using active asset store engine.
23 before.store(&mut database)?;
24
25 // Wait until the asset is stored.
26 while database.is_busy() {
27 database.maintain()?;
28 tokio::time::sleep(tokio::time::Duration::from_millis(10)).await;
29 }
30
31 // Delete spawned asset from database just to show it will load from storage.
32 before.delete(&mut database).unwrap();
33 assert!(!before.does_exists(&database));
34
35 // Load the asset from storage, we get previously saved asset content.
36 let after = database.ensure("text://saved2.txt")?;
37 println!("After: {}", after.access::<&String>(&database));
38 /* ANCHOR_END: main */
39
40 Ok(())
41}Sourcepub fn report_loading_status(&self, out_status: &mut AssetsStatus)
pub fn report_loading_status(&self, out_status: &mut AssetsStatus)
Reports the status of assets in the database.
§Arguments
out_status: A mutable reference to outputAssetsLoadingStatus.
Sourcepub fn commands_sender(&self) -> AssetDatabaseCommandsSender
pub fn commands_sender(&self) -> AssetDatabaseCommandsSender
Returns the sender for asset database commands. This can be used to send commands to the asset database from external places.
Sourcepub fn maintain(&mut self) -> Result<(), Box<dyn Error>>
pub fn maintain(&mut self) -> Result<(), Box<dyn Error>>
Performs maintenance on the asset database, processing events and managing states.
- Processes changed assets and dispatches relevant events.
- Maintains fetch and store engines and protocols.
- Resolves assets and processes their data using protocols.
- Stores requested assets.
§Returns
Ok(()) if successful, or an error if any step fails.
Examples found in repository?
10fn main() -> Result<(), Box<dyn Error>> {
11 /* ANCHOR: main */
12 let mut database = AssetDatabase::default()
13 .with_protocol(FutureAssetProtocol::new("lines").process(process_lines))
14 .with_fetch(FileAssetFetch::default().with_root("resources"));
15
16 let lines = database.schedule("lines://lorem.txt")?;
17
18 while database.is_busy() {
19 database.maintain()?;
20 }
21
22 println!(
23 "Lines count: {}",
24 lines.access::<&Vec<String>>(&database).len()
25 );
26 /* ANCHOR_END: main */
27
28 Ok(())
29}More examples
11fn main() -> Result<(), Box<dyn Error>> {
12 /* ANCHOR: main */
13 let mut database = AssetDatabase::default()
14 .with_protocol(BundleAssetProtocol::new("custom", CustomAssetProcessor))
15 .with_fetch(FileAssetFetch::default().with_root("resources"));
16
17 let handle = database.ensure("custom://part1.json")?;
18
19 while database.is_busy() {
20 database.maintain()?;
21 }
22
23 let contents = handle.access::<&CustomAsset>(&database).contents(&database);
24 println!("Custom chain contents: {contents:?}");
25 /* ANCHOR_END: main */
26
27 Ok(())
28}14fn main() -> Result<(), Box<dyn Error>> {
15 let mut database = AssetDatabase::default()
16 // Register custom asset protocol.
17 .with_protocol(CustomAssetProtocol)
18 .with_fetch(FileAssetFetch::default().with_root("resources"))
19 .with_event(|event| {
20 println!("Asset closure event: {event:#?}");
21 Ok(())
22 });
23
24 let handle = database.ensure("custom://part1.json")?;
25
26 while database.is_busy() {
27 database.maintain()?;
28 }
29
30 let contents = handle.access::<&CustomAsset>(&database).contents(&database);
31 println!("Custom chain contents: {contents:?}");
32
33 Ok(())
34}11fn main() -> Result<(), Box<dyn Error>> {
12 let mut database = AssetDatabase::default()
13 // Register custom asset processor.
14 .with_protocol(BundleAssetProtocol::new("custom", CustomAssetProcessor))
15 .with_fetch(FileAssetFetch::default().with_root("resources"));
16
17 // Ensure custom asset existence.
18 let handle = database.ensure("custom://part1.json")?;
19
20 // Make database process loaded dependencies.
21 while database.is_busy() {
22 database.maintain()?;
23 }
24
25 let contents = handle.access::<&CustomAsset>(&database).contents(&database);
26 println!("Custom chain contents: {contents:?}");
27
28 Ok(())
29}10async fn main() -> Result<(), Box<dyn Error>> {
11 /* ANCHOR: main */
12 let mut database = AssetDatabase::default()
13 .with_protocol(BytesAssetProtocol)
14 // Future asset fetch uses async function to handle providing
15 // asset bytes asynchronously with async/await.
16 .with_fetch(FutureAssetFetch::new(tokio_load_file_bundle));
17
18 let package = database.ensure("bytes://package.zip")?;
19
20 // Run maintain passes to load and process loaded bytes.
21 while !package.is_ready_to_use(&database) {
22 database.maintain()?;
23 tokio::time::sleep(tokio::time::Duration::from_millis(10)).await;
24 }
25
26 println!(
27 "Package byte size: {}",
28 package.access::<&Vec<u8>>(&database).len()
29 );
30 /* ANCHOR_END: main */
31
32 Ok(())
33}8fn main() -> Result<(), Box<dyn Error>> {
9 /* ANCHOR: main */
10 let mut database = AssetDatabase::default()
11 .with_protocol(BytesAssetProtocol)
12 // Deferred asset fetch runs fetching jobs in threads for any fetch engine.
13 .with_fetch(DeferredAssetFetch::new(
14 FileAssetFetch::default().with_root("resources"),
15 ));
16
17 let package = database.ensure("bytes://package.zip")?;
18
19 // Simulate waiting for asset bytes loading to complete.
20 while package.has::<AssetAwaitsAsyncFetch>(&database) {
21 println!("Package awaits async fetch done");
22 database.maintain()?;
23 }
24
25 // Run another maintain pass to process loaded bytes.
26 database.maintain()?;
27
28 println!(
29 "Package byte size: {}",
30 package.access::<&Vec<u8>>(&database).len()
31 );
32 /* ANCHOR_END: main */
33
34 Ok(())
35}- examples/20_consumed_asset_load.rs
- examples/25_tokio_axum.rs
- examples/28_protocol_extract.rs
- examples/26_throttled_fetch.rs
- examples/24_future_store.rs
- examples/21_store_asset.rs
- examples/03_dependencies.rs
- examples/04_events.rs
- examples/16_extract_from_asset.rs
- examples/19_loading_progress.rs
- examples/ingame.rs
- examples/22_store_custom_asset.rs
- examples/09_hot_reloading.rs
- examples/17_smart_references.rs