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 dynamic system parameters. #1

Closed

Conversation

chescock
Copy link
Owner

Objective

Support building systems with parameters whose types can be determined at runtime.

Solution

Create a DynSystemParam type that can be built using a SystemParamBuilder of any type and then downcast to the appropriate type dynamically.

Example

let system = (vec![
    DynParamBuilder::new(LocalBuilder(3_usize)),
    DynParamBuilder::new::<Query<()>>(QueryParamBuilder::new(|builder| {
        builder.with::<A>();
    })),
    DynParamBuilder::new::<&Entities>(ParamBuilder),
],)
    .build_state(&mut world)
    .build_system(|mut params: Vec<DynSystemParam>| {
        let local = *params[0].downcast_mut::<Local<usize>>().unwrap();
        let query_count = params[1]
            .downcast_mut::<Query<()>>()
            .unwrap()
            .iter()
            .count();
        let entities = params[2].downcast_mut::<&Entities>().unwrap();
    });

github-merge-queue bot pushed a commit to bevyengine/bevy that referenced this pull request Aug 12, 2024
# Objective

Support more kinds of system params in buildable systems, such as a
`ParamSet` or `Vec` containing buildable params or tuples of buildable
params.

## Solution

Replace the `BuildableSystemParam` trait with `SystemParamBuilder` to
make it easier to compose builders. Provide implementations for existing
buildable params, plus tuples, `ParamSet`, and `Vec`.

## Examples

```rust
// ParamSet of tuple: 
let system = (ParamSetBuilder((
    QueryParamBuilder::new(|builder| { builder.with::<B>(); }),
    QueryParamBuilder::new(|builder| { builder.with::<C>(); }),
)),)
    .build_state(&mut world)
    .build_system(|mut params: ParamSet<(Query<&mut A>, Query<&mut A>)>| {
        params.p0().iter().count() + params.p1().iter().count()
    });
	
// ParamSet of Vec:
let system = (ParamSetBuilder(vec![
    QueryParamBuilder::new_box(|builder| { builder.with::<B>(); }),
    QueryParamBuilder::new_box(|builder| { builder.with::<C>(); }),
]),)
    .build_state(&mut world)
    .build_system(|mut params: ParamSet<Vec<Query<&mut A>>>| {
        let mut count = 0;
        params.for_each(|mut query| count += query.iter_mut().count());
        count
    });
```

## Migration Guide

The API for `SystemBuilder` has changed. Instead of constructing a
builder with a world and then adding params, you first create a tuple of
param builders and then supply the world.

```rust
// Before
let system = SystemBuilder::<()>::new(&mut world)
    .local::<u64>()
    .builder::<Local<u64>>(|x| *x = 10)
    .builder::<Query<&A>>(|builder| { builder.with::<B>(); })
    .build(system);

// After
let system = (
    ParamBuilder,
    LocalBuilder(10),
    QueryParamBuilder::new(|builder| { builder.with::<B>(); }),
)
    .build_state(&mut world)
    .build_system(system);
```

## Possible Future Work

Here are a few possible follow-up changes. I coded them up to prove that
this API can support them, but they aren't necessary for this PR.

* chescock#1
* chescock#2
* chescock#3
@chescock chescock closed this Aug 12, 2024
chescock pushed a commit that referenced this pull request Feb 18, 2025
…res. (bevyengine#17887)

Fixes bevyengine#17290.
<details>
  <summary>Compilation errors before fix</summary>

`cargo clippy --tests --all-features --package bevy_image`:
```rust
error[E0061]: this function takes 7 arguments but 6 arguments were supplied
   --> crates/bevy_core_pipeline/src/tonemapping/mod.rs:451:5
    |
451 |     Image::from_buffer(
    |     ^^^^^^^^^^^^^^^^^^
...
454 |         bytes,
    |         ----- argument #1 of type `std::string::String` is missing
    |
note: associated function defined here
   --> /Users/josiahnelson/Desktop/Programming/Rust/bevy/crates/bevy_image/src/image.rs:930:12
    |
930 |     pub fn from_buffer(
    |            ^^^^^^^^^^^
help: provide the argument
    |
451 |     Image::from_buffer(/* std::string::String */, bytes, image_type, CompressedImageFormats::NONE, false, image_sampler, RenderAssetUsages::RENDER_WORLD)
    |                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
```
`cargo clippy --tests --all-features --package bevy_gltf`:
```rust
error[E0560]: struct `bevy_pbr::StandardMaterial` has no field named `specular_channel`
    --> crates/bevy_gltf/src/loader.rs:1343:13
     |
1343 |             specular_channel: specular.specular_channel,
     |             ^^^^^^^^^^^^^^^^ `bevy_pbr::StandardMaterial` does not have this field
     |
     = note: available fields are: `emissive_exposure_weight`, `diffuse_transmission`, `diffuse_transmission_channel`, `diffuse_transmission_texture`, `flip_normal_map_y` ... and 9 others

error[E0560]: struct `bevy_pbr::StandardMaterial` has no field named `specular_texture`
    --> crates/bevy_gltf/src/loader.rs:1345:13
     |
1345 |             specular_texture: specular.specular_texture,
     |             ^^^^^^^^^^^^^^^^ `bevy_pbr::StandardMaterial` does not have this field
     |
     = note: available fields are: `emissive_exposure_weight`, `diffuse_transmission`, `diffuse_transmission_channel`, `diffuse_transmission_texture`, `flip_normal_map_y` ... and 9 others

error[E0560]: struct `bevy_pbr::StandardMaterial` has no field named `specular_tint_channel`
    --> crates/bevy_gltf/src/loader.rs:1351:13
     |
1351 |             specular_tint_channel: specular.specular_color_channel,
     |             ^^^^^^^^^^^^^^^^^^^^^ `bevy_pbr::StandardMaterial` does not have this field
     |
     = note: available fields are: `emissive_exposure_weight`, `diffuse_transmission`, `diffuse_transmission_channel`, `diffuse_transmission_texture`, `flip_normal_map_y` ... and 9 others

error[E0560]: struct `bevy_pbr::StandardMaterial` has no field named `specular_tint_texture`
    --> crates/bevy_gltf/src/loader.rs:1353:13
     |
1353 |             specular_tint_texture: specular.specular_color_texture,
     |             ^^^^^^^^^^^^^^^^^^^^^ `bevy_pbr::StandardMaterial` does not have this field
     |
     = note: available fields are: `emissive_exposure_weight`, `diffuse_transmission`, `diffuse_transmission_channel`, `diffuse_transmission_texture`, `flip_normal_map_y` ... and 9 others
```
</details>
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

Successfully merging this pull request may close these issues.

1 participant