bevyengine / bevyengine/bevy

Unable to define textures for `StandardMaterial` assets within `bsn!` macro

Open
#24,925 2 comments 0 reactions 0 assignees View on GitHub
A-Assets A-Scenes C-Bug S-Needs-Design
Dominant language
Rust
Stars
48.2k
Forks
4.8k
Avg merge
3d 22h
Merged PRs (30d)
161

Description

## Bevy version and features

Bevy 0.19

## What you did

I'm loving the new `bsn!` macro, but I've been running into problems trying to define `StandardMaterial` with image assets:

```rust
fn spawn_capsule() -> impl Scene {
bsn! {
Mesh3d(asset_value(Capsule3d { radius: 0.5, half_length: 0.5 }))
MeshMaterial3d::(asset_value(StandardMaterial {
base_color_texture: Some("checkered_texture_blue.png"),
..default()
}))
}
}
```

## What went wrong

It's surprising\* to me that `Option<&'static str>` -> `Option>` doesn't work like `&'static str` -> `Handle`.

```
| base_color_texture: Some("checkered_texture_blue.png"),
| ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Handle`, found `&str`
| |
| arguments to this enum variant are incorrect
|
= note: expected enum `bevy::bevy_asset::Handle`
found reference `&'static str`
help: the type constructed contains `&'static str` due to the type of the argument passed
--> src/main.rs:45:33
|
| base_color_texture: Some("checkered_texture_blue.png"),
| ^^^^^----------------------------^
| |
| this argument influences the type of `Some`
```

\* Surprising to me as a BSN noob :)

## Additional information

As far as I can tell, the problem lies with `StandardMaterial` not specifying its own `FromTemplate` and relying on the one generated for `Default` & `Clone` instead. As a consequence, the BSN macro tries to resolve the value normally as a literal `Option<&'static str>`, rather than using `.into()` on the wrapped string.

Right now, I can workaround this with a small helper:

```rust
fn spawn_capsule() -> impl Scene {
bsn! {
Mesh3d(asset_value(Capsule3d { radius: 0.5, half_length: 0.5 }))
image_texture_material("checkered_texture_blue.png")
}
}

fn image_texture_material(path: &'static str) -> impl Scene {
template(move |ctx| {
let image_texture = ctx.resource::().load(path);
let material_handle =
ctx.resource_mut::>()
.add(StandardMaterial {
base_color_texture: Some(image_texture),
..default()
});

Ok(MeshMaterial3d::(material_handle))
})
}
```

However this is less than ideal since I can no longer (easily) update individual fields on the StandardMaterial from my Scene Constructors.

Contributor guide

Open the contributing guide

Research direction

Start with the bsn! macro's handling of StandardMaterial and its generated FromTemplate implementations, then compare that path with the asset_value and template entry points shown here. Done means an Option<&'static str> texture value is converted to Option> within bsn! while preserving the ability to update other StandardMaterial fields; verify against the reported Bevy 0.19 example.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
game-dev
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
56/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.