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

Support generic asset settings when loading an asset #243

Open
mgi388 opened this issue Nov 5, 2024 · 0 comments
Open

Support generic asset settings when loading an asset #243

mgi388 opened this issue Nov 5, 2024 · 0 comments

Comments

@mgi388
Copy link
Contributor

mgi388 commented Nov 5, 2024

Some asset formats like image have special treatment in this crate for configuring the asset on a per-asset-collection basis:

#[derive(AssetCollection, Resource)]
struct ImageAssets {
    #[asset(path = "images/pixel_tree.png")]
    #[asset(image(sampler = linear))]
    tree_linear: Handle<Image>,
}

But for many assets, you want to provide different settings for the same asset, depending on the asset collection. You can't rely on the asset meta file because you need different settings per asset collection.

For example, in an RTS game, during a level, you might want to load an asset for the Army. The Army asset itself has some settings that control whether additional assets are loaded. Those assets are not needed during the level, but are used in other scenes in the game. It would be good if bevy_asset_loader had a way to configure the assets settings near the #[asset] macro.

Even the GltfLoader inside Bevy has some settings, and you can imagine scenarios where you want to be able to configure these on a per-asset-collection basis:

pub struct GltfLoaderSettings {
    /// If true, the loader will spawn cameras for gltf camera nodes.
    pub load_cameras: bool,
    /// If true, the loader will spawn lights for gltf light nodes.
    pub load_lights: bool,
    /// If true, the loader will include the root of the gltf root node.
    pub include_source: bool,
}

I don't know what a solution looks like. It doesn't have to sit next to the #[asset] macro, but that seems like the most obvious ergonomic choice.

BTW, for DynamicAssets, there seems to be a way to achieve this already. Something like this:

When registering your asset:

dynamic_assets.register_asset(
    "foo",
    Box::new(WrappedFoo {
        path: "my/bar.foo",
        settings: FooLoaderSettings {
            load_a: true,
            load_b: false,
        },
    }),
);

And:

#[derive(Debug, Reflect)]
#[reflect(Debug)]
pub struct WrappedFoo {
    pub path: String,
    pub settings: FooLoaderSettings,
}

impl DynamicAsset for WrappedFoo {
    fn load(&self, asset_server: &AssetServer) -> Vec<UntypedHandle> {
        let settings = self.settings.clone();

        let foo_handle: Handle<OriginalFoo> =
            asset_server.load_with_settings(&self.path, move |s: &mut FooLoaderSettings| {
                *s = settings.clone();
            });

        vec![foo_handle.untyped()]
    }

    fn build(&self, world: &mut World) -> Result<DynamicAssetType, anyhow::Error> {
        let asset_server = world
            .get_resource::<AssetServer>()
            .expect("AssetServer resource should exist");
        Ok(DynamicAssetType::Single(
            asset_server.get_handle_untyped(&self.path).unwrap(),
        ))
    }
}

This seems to work AFAICT.

Originally raised in Discord.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant