Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AssetPack syntax sugar for static assets #13819

Open
wants to merge 17 commits into
base: main
Choose a base branch
from

Conversation

ecoskey
Copy link

@ecoskey ecoskey commented Jun 11, 2024

Objective

Currently there's not a ton of boilerplate for loading assets, either using embedded_asset! or not. But this can still add up, and does especially in rendering code.

Solution

  • Add AssetPack trait and derive macro to wrap the pattern of "initialize some resources, potentially through embedded_asset!, and lazy load them when required"
#[derive(AssetPack)]
struct BloomShaders {
  #[embedded("upscale.wgsl")] //lazy-loads upscale.wgsl as an embedded asset
  upscale_shader: Handle<Shader>,
  #[load("downscale.wgsl")] //lazy-loads downscale.wgsl from the default asset source
  downscale_shader: Handle<Shader>,
}

Limitations

Currently, all assets are loaded at once in Pack<T>::get() and never unloaded. This fits the need of rendering (and I assume other cases as well), where each shader is needed every frame and each pack is accessed (usually) all at once. Loading assets separately and unloading assets when unused would require a function-like proc-macro to be able to rewrite each struct field. For this PR I decided to continue with the simpler implementation.

Testing

I did some quick manual testing to make sure the macro worked as expected. Frankly, I'm not super familiar with macro testing or style for error reporting. Please let me know how to improve this!


Changelog

  • Add AssetPack trait and derive macro
  • Add AssetPackPlugin<T> to setup asset pack state
  • Add Pack<T> resource to wrap access to an AssetPack
  • Add GetPack<T> SystemParam so users don't have to pass in AssetServer themselves
  • Add asset_pack example and docs

Copy link
Contributor

The generated examples/README.md is out of sync with the example metadata in Cargo.toml or the example readme template. Please run cargo run -p build-templated-pages -- update examples to update it, and commit the file change.

@brandon-reinhart
Copy link
Contributor

Instead of AssetPackPlugin, you could just provide a register_asset_pack fn.

@alice-i-cecile alice-i-cecile added A-Assets Load files from disk to use for things like images, models, and sounds C-Usability A simple quality-of-life change that makes Bevy easier to use S-Needs-Review Needs reviewer attention (from anyone!) to move forward labels Jun 12, 2024
Copy link
Contributor

@killercup killercup left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried running the example but got

$ RUST_BACKTRACE=1 cargo run --example asset_pack
[…]
thread 'main' panicked at crates/bevy_asset/src/io/embedded/mod.rs:141:13:
Failed to find src_prefix "src" in "examples/asset/asset_pack.rs"

Maybe this error message can be improved? The file exists, and I have no idea why it's failing.

Comment on lines +6 to +25
fn main() {
App::new()
.add_plugins((DefaultPlugins, AssetPackExamplePlugin))
.add_systems(Startup, setup)
.run();
}

struct AssetPackExamplePlugin;

#[derive(AssetPack)]
struct ExampleAssetPack {
#[embedded("files/bevy_pixel_dark.png")]
sprite: Handle<Image>,
}

impl Plugin for AssetPackExamplePlugin {
fn build(&self, app: &mut App) {
app.add_plugins(AssetPackPlugin::<ExampleAssetPack>::default());
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
fn main() {
App::new()
.add_plugins((DefaultPlugins, AssetPackExamplePlugin))
.add_systems(Startup, setup)
.run();
}
struct AssetPackExamplePlugin;
#[derive(AssetPack)]
struct ExampleAssetPack {
#[embedded("files/bevy_pixel_dark.png")]
sprite: Handle<Image>,
}
impl Plugin for AssetPackExamplePlugin {
fn build(&self, app: &mut App) {
app.add_plugins(AssetPackPlugin::<ExampleAssetPack>::default());
}
}
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_plugins(AssetPackPlugin::<ExampleAssetPack>::default())
.add_systems(Startup, setup)
.run();
}
#[derive(AssetPack)]
struct ExampleAssetPack {
#[embedded("files/bevy_pixel_dark.png")]
sprite: Handle<Image>,
}

No need for a plugin, let's keep this example short :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-Assets Load files from disk to use for things like images, models, and sounds C-Usability A simple quality-of-life change that makes Bevy easier to use S-Needs-Review Needs reviewer attention (from anyone!) to move forward
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants