bevyengine / bevy

A refreshingly simple data-driven game engine built in Rust
https://bevyengine.org
Apache License 2.0
36.29k stars 3.58k forks source link

`AssetIo::root_path` #2147

Open NathanSWard opened 3 years ago

NathanSWard commented 3 years ago

What problem does this solve or what need does it fill?

It is useful to get the asset directory path however, currently this is only achievable via the AssetServerSettings which is a little unintuitive.

What solution would you like?

The AssetIo trait should expose a root_dir function (or something similar to that name asset_root_dir) which returns a &Path (or Option<&Path>) to the asset directory. This spawned form this discussion.

It should also be noted that this would need to be based on #2123 since this PR exposes an asset_io() method on AssetServer.

What alternative(s) have you considered?

Use the AssetServerSettings resource or manually use "assets/" (though this is not reliable).

Additional context

Ideally the API would be something like:

fn asset_directory(asset_server: Res<AssetServer>) {
    let asset_dir = asset_server.asset_io().root_dir();
}
cart commented 3 years ago

How do you propose handling root_dir in the context of AssetIo backends where that doesn't make sense? (ex: the wasm backend makes web requests, so there isn't a root dir, android is relative to the "deployed assets" not a real dir, etc)

NathanSWard commented 3 years ago

How do you propose handling root_dir in the context of AssetIo backends where that doesn't make sense?

It could be as simple as returning an Option<&Path> where Android/Wasm return None.

Another solution would instead support something like

pub fn load_folder_where<F>(dir: &Path, f: F) -> Result<Vec<HandleUntyped>, AssetServerError>
where
    F: FnMut(&Path) -> bool

To address the specific problem mentioned on discord.

Though I'm in favor of the former.

mockersf commented 3 years ago

from the original discussion in discord, I think a nice solution would be to have a way to load only assets of a certain type from a folder

james7132 commented 3 years ago

When I brought this up on Discord initially, the goal was to allow for finer control over batch loaded assets. One of the other proposed ideas was to provide support for globbed paths (i.e. characters/*/*.chr or **/*.custom_asset).

The envisioned use case would be an metadata load step at initialization. For example, building an metadata index of all available characters or levels in the game without loading them all into memory at startup. Example assets directory structure:

asssets/
  - characters/
    - mario/
      - models/
      - textures/
      - character.chr
    - luigi/
      - models/
      - textures/
      - character.chr
    - wario/
      - models/
      - textures/
      - character.chr

Having a metadata asset like a JSON/RON file that is loaded at startup and then points to where to load associated assets. In this example, characters/*/character.chr would be batch loaded at game startup to know that they're present, and the metadata asset points to how to load actual character assets like UI portraits or models/textures when actually needed.

When asset bundles/compressed archives are supported, this may be necessary to support a plug-and-play modding scheme.

Shatur commented 1 year ago

Currently WasmAssetIo have root_path too. Currently it's the only way to get this path at runtime since settings are no longer resources.

nicopap commented 1 year ago

Workaround

Currently it's possible to use the root_path method on FileSystemAssetIo (and WasmAssetIo as Shatur mentions) by using the downcast_ref() method on Any (as seen here)

Interest

I find that root_path doesn't have its place in AssetIo, since the concept of path is dependent on the kind of IO we have. I'm not exactly for it.

Shatur commented 1 year ago

Currently it's possible to use the root_path method on FileSystemAssetIo

Sure, but If I want it to work with AndroidAssetIo and WasmAssetIo it becomes a little verbose. I believe it's common to access this folder, so it would be nice to have a cross-platform way for it.

since the concept of path is dependent on the kind of IO we have

Do you have an I/O example for which there might not be a root path to load resources? If yes, it could be an Option.

nicopap commented 1 year ago

Well, for one, the meaning of root_path in WasmAssetIo is very different from FileSystemAssetIo. When implementing something that depends on the asset path, you then need to look at what's in the asset path. Which requires a drastically different approach for WasmAssetIo (http requests) and FileSystemAssetIo (whatever filesystem API you can use). So the distinction here is relevant, and the downcast_ref makes all of this explicit. As an example of things that doesn't have a root path: bevy_emdedded_assets.

Here I'm assuming you want to read whatever is in the root_path (and therefore need a different handling depending on the AssetIo impl). Do you have an example where you want to use root_path independently of the AssetIo impl?

Shatur commented 1 year ago

Which requires a drastically different approach for WasmAssetIo (http requests) and FileSystemAssetIo (whatever filesystem API you can use)

Makes sense...

Do you have an example where you want to use root_path independently of the AssetIo impl?

I assumed that using AndroidAssetIo I could read filesystem as usual on Android.

Shatur commented 1 year ago

So I agree with you, instead of root_path we probably should add this feature instead:

I think a nice solution would be to have a way to load only assets of a certain type from a folder