Support multiple simultaneous asset directories
- Dominant language
- Rust
- Stars
- 48.2k
- Forks
- 4.8k
- Avg merge
- 3d 16h
- Merged PRs (30d)
- 171
Description
## What problem does this solve or what need does it fill?
One might, for example, want to load user configuration from the platform's conventional directory for configuration, which might look like `$XDG_CONFIG_HOME/$APP_NAME/some_file.toml` on Linux. While user configuration may not be an "asset" in the typical sense, if a game wanted to support custom texture packs like Minecraft, that would be equally "configuration" and "asset" in my eyes. All of this alongside still loading static assets from the current `assets` directory.
Additionally, things from these extra places should be hot-reloaded in the same way they are for the current `assets` directory.
## What solution would you like?
### Approach A
A new function on `AssetServer` like this:
```rust
pub fn load_from<'a, T: Asset, D: Directory, P: Into>>(&self, directory: D, path: P) -> Handle
// NEW: ^^^^^ NEW: ^^^^^^^^^^^^^ NEW: ^^^^^^^^^^^^^
```
Where `Directory` and an example implementor would look like this:
```rust
pub trait Directory {
// `None` is for when the platform doesn't have an equivalent
fn path(/* some arguments */) -> Option;
}
pub struct Config;
impl Directory for Config {
fn path(/* some arguments */) -> Option {
// On Linux, use the arguments to construct the expansion of `Some("$XDG_CONFIG_HOME/$APP_NAME")`
}
}
```
And a usage in user code would look like this:
```rust
let handle = asset_server.load_from(Config, "some_file.toml");
```
### Approach B
An extension to the `AssetPath` formatting that specifies in the string which directory it should come from. I personally like this less because the compiler couldn't help catch typos that way, and it's potentially less extensible.
### Approach C
Suggested by cart on Discord: instead of having a single asset server that can load from multiple directories, have many asset servers that can each load from a single directory.
After thinking about it for a while, I think this may be the most flexible solution. For example, if you currently need some behavior not afforded to you by `AssetServer`, you need to either fork `bevy_asset`, get your change merged, or... implement your own asset server. This would also make the most sense in some situations like desiring the ability to save assets modified by the running game; not all backing stores are writable, which could be represented by the related asset server simply not providing a `save` method.
In order to facilitate this, I think `bevy_asset` should be split into two crates: `bevy_asset` and `bevy_asset_server`, the former containing most of the types and common traits required to interact with Bevy's Asset subsystem like `Handle`, `Assets`, and `AssetIo`, and the latter containing `AssetServer` and anything specific to it. The reason for this would be to guarantee that it's possible to implement a custom asset server outside Bevy that can still load things into `Assets` and produce `Handle`s.
A potential downside is that implementing an asset server just to load configuration from the right place seems like an excessive amount of code for the use-case. Maybe this should be combined with one of the other approaches.
## What alternative(s) have you considered?
1. Putting configuration in the `assets` folder
* I don't like this because I feel configuration should live in the conventional place on whatever the current platform is
2. Loading the configuration before the app starts/outside bevy
* I don't like this because it doesn't feel very cohesive, and doesn't easily allow for hot-reloading when available
## Unresolved problems
### Approach A and B
* How do we reference these different directories in scenes? - pointed out by cart on Discord
### Approach C
* Presumably this would have the same problem regarding scenes as A and B
## Additional context
Discussion on Discord starting [here](https://discord.com/channels/691052431525675048/749332104487108618/1012133948442300506).
Contributor guide
Research direction
No files, tests, or entry points are named. Start by examining Bevy's asset subsystem and the current AssetServer, AssetPath, AssetIo, and hot-reload behavior, then resolve which proposed approach should be implemented, including how scenes reference multiple directories. Done means the chosen design supports simultaneous directories and hot-reloading with documented behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- game-dev
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100