NiklasEi / bevy_asset_loader

Bevy plugin helping with asset loading and organization
Apache License 2.0
452 stars 53 forks source link

Specifying Asset Handles without an Instance of the AssetCollection from File / Const time #138

Open Braymatter opened 1 year ago

Braymatter commented 1 year ago

I've got a set of const custom materials that I need to swap out with the standard materials that are loaded from GLTF's like so:

These materials are basically a copy of the StandardMaterial with a Thermal glow blending emissivity layered on top. I need a way to indicate that I need a specific field from within the AssetCollection.

The two things I can come up with for this are either some macro wizardry to secretly do const handles internally, or using something the key attribute of the asset macro to generate some form of index.

Additionally, you could probably get somewhere with Reflect / get_field, but I have a very strong preference to not litter duplicate &str's around. That specifically would be less of an issue if we could reference Const &str's in macro attributes.

My use case for the key solution would be the ability to reference the handle from a file or a const Material at compile time.

{
    "base_color_texture": "GameAssets::colored_paint_albedo",
   <other JSON fields>
}

Here is an example of where I'm forced to do lookups on the asset_server directly and create a bunch of adidtional consts:

pub fn hydrate_material(
    desc: ThermalMaterialDescriptor,
    server: &Res<AssetServer>,
) -> ThermalPbrMaterial {
    //Using asset_server.load is alright as if the texture is already loaded it will just return the handle at the cost of a lookup
    let base_color_texture = desc.base_color_path.map(|path| server.load(path));

    let thermal_texture = desc.channel_pack_path.map(|path| server.load(path));

    let emissive_texture = desc.emissive_path.map(|path| server.load(path));

    let normal_map_texture = desc.normal_map_path.map(|path| server.load(path));

    let metallic_roughness_texture = desc.metallic_roughness_path.map(|path| server.load(path));

    let occlusion_texture = desc.occlusion_path.map(|path| server.load(path));

    ThermalPbrMaterial {
        base_color_texture,
        emissive_texture,
        normal_map_texture,
        metallic_roughness_texture,
        occlusion_texture,
        thermal_accent_boost_texture: thermal_texture,
        base_color: desc.uniform.base_color.into(),
        thermal_color: desc.uniform.thermal_color.into(),
        emissive: desc.uniform.emissive.into(),
        reflectance: desc.uniform.reflectance,
        perceptual_roughness: desc.uniform.roughness,
        metallic: desc.uniform.metallic,
        min_radiant_temp: desc.uniform.min_radiant_temp,
        max_radiant_temp: desc.uniform.max_radiant_temp,
        temp: desc.uniform.temp,
        thermal_boost_scalar: desc.uniform.thermal_boost_scalar,
        thermal_pulse_frequency: desc.uniform.thermal_pulse_frequency,
        thermal_pulse_intensity: desc.uniform.thermal_pulse_intensity,

        flip_normal_map_y: desc.flip_normal_map_y,
        double_sided: desc.double_sided,
        cull_mode: desc.cull_mode,
        unlit: desc.unlit,
        fog_enabled: desc.fog_enabled,
        alpha_mode: desc.alpha_mode,
        depth_bias: desc.depth_bias,
    }
}
NiklasEi commented 1 year ago

Here is an example of where I'm forced to do lookups on the asset_server directly and create a bunch of adidtional consts:

What additional consts do you mean? There is no const in the code example.

Have you looked into custom dynamic assets for this issue? Maybe that could help reducing the direct usage of the asset server.

Just FYI: Bevy v0.12 (in~3 months) will likely support properly typed const asset handles. That might make it easier.

NiklasEi commented 2 months ago

I am not sure If I understood your issue correctly. Could you please explain a bit more if you are still missing some functionality?