[Merged by Bors] - ExtractComponent output optional associated type#6699
[Merged by Bors] - ExtractComponent output optional associated type#6699torsteingrindvik wants to merge 8 commits into
Conversation
Add an associated type to `ExtractComponent` in order to allow specifying
the output component.
Make `extract_component` return an `Option<_>` such that components can
be extracted only when needed.
What problem does this solve?
`ExtractComponentPlugin` allows extracting components, but currently the
output type is the same as the input.
This means that use cases such as having a settings struct which turns
into a uniform is awkward.
For example we might have:
```rust
struct MyStruct {
enabled: bool,
val: f32
}
struct MyStructUniform {
val: f32
}
```
With the new approach, we can extract `MyStruct` only when it is
enabled, and turn it into its related uniform.
This chains well with `UniformComponentPlugin`.
The user may then:
```rust
app.add_plugin(ExtractComponentPlugin::<MyStruct>::default());
app.add_plugin(UniformComponentPlugin::<MyStructUniform>::default());
```
This then saves the user a fair amount of boilerplate.
Signed-off-by: Torstein Grindvik <torstein.grindvik@nordicsemi.no>
Signed-off-by: Torstein Grindvik <torstein.grindvik@nordicsemi.no>
7b55bfb to
d52ac8d
Compare
|
Added a second commit which uses the changes on the bloom plugin. The results are:
|
Signed-off-by: Torstein Grindvik <torstein.grindvik@nordicsemi.no>
| #[derive(ShaderType)] | ||
| struct BloomUniform { | ||
| #[derive(Component, ShaderType, Clone)] | ||
| pub struct BloomUniform { |
There was a problem hiding this comment.
Added a docstring.
|
|
||
| /// Defines how the component is transferred into the "render world". | ||
| fn extract_component(item: QueryItem<'_, Self::Query>) -> Self; | ||
| fn extract_component(item: QueryItem<'_, Self::Query>) -> Option<Self::Out>; |
There was a problem hiding this comment.
Do we want to add a Clone trait bound and add a default impl here? Some(item.clone()) seems to be the common pattern.
There was a problem hiding this comment.
Extracting uncloneable components generally seems impossible or at least poorly thought out?
There was a problem hiding this comment.
Hmm, I'm not too sure.
After these changes, the output type can be something entirely different than what is queried.
So a Clone bound on Self in that case is not strictly needed.
Signed-off-by: Torstein Grindvik <torstein.grindvik@nordicsemi.no>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
alice-i-cecile
left a comment
There was a problem hiding this comment.
The lack of associated type defaults sucks, but this is still an improvement.
| type Out = BloomUniform; | ||
|
|
||
| fn extract_component((settings, camera): QueryItem<'_, Self::Query>) -> Option<Self::Out> { | ||
| if let Some(size) = camera.physical_viewport_size() { |
There was a problem hiding this comment.
Replace if-let with Option::map.
| cameras: Extract<Query<(Entity, &Camera, &BloomSettings), With<Camera>>>, | ||
| ) { | ||
| for (entity, camera, bloom_settings) in &cameras { | ||
| if camera.is_active && camera.hdr { |
There was a problem hiding this comment.
Now that you removed this, where are you checking for these conditions? Did I miss this somewhere?
There was a problem hiding this comment.
Good catch, that was my bad.
Added that check in the extract component impl for BloomSettings
| /// The uniform struct extracted from [`BloomSettings`] attached to a [`Camera`]. | ||
| /// Will be available for use in the Bloom shader. | ||
| #[derive(Component, ShaderType, Clone)] | ||
| pub struct BloomUniform { |
There was a problem hiding this comment.
Can we keep this struct private? I don't like exposing bloom implementation details.
There was a problem hiding this comment.
I'd like that too, but by doing impl ExtractComponent on something public like BloomSettings and having the Out type be BloomUniform means that BloomUniform too must be public (else compile error)
There was a problem hiding this comment.
You can use #[doc(hidden)] to reduce public visibility.
There was a problem hiding this comment.
I don't love this, but I think the reduction in boilerplate is worth it, given that we can somewhat mitigate it with doc hidden (does anyone know if rust analyzer ignores hidden items when it comes to autocomplete?). I'm good with these changes once doc hidden is added :).
There was a problem hiding this comment.
I added the hidden attr now.
I kept the docstring anyway since I saw that was done in other instances of hiding pub items in Bevy.
Signed-off-by: Torstein Grindvik <torstein.grindvik@nordicsemi.no>
Signed-off-by: Torstein Grindvik <torstein.grindvik@nordicsemi.no>
|
bors r+ |
# Objective
Allow more use cases where the user may benefit from both `ExtractComponentPlugin` _and_ `UniformComponentPlugin`.
## Solution
Add an associated type to `ExtractComponent` in order to allow specifying the output component (or bundle).
Make `extract_component` return an `Option<_>` such that components can be extracted only when needed.
What problem does this solve?
`ExtractComponentPlugin` allows extracting components, but currently the output type is the same as the input.
This means that use cases such as having a settings struct which turns into a uniform is awkward.
For example we might have:
```rust
struct MyStruct {
enabled: bool,
val: f32
}
struct MyStructUniform {
val: f32
}
```
With the new approach, we can extract `MyStruct` only when it is enabled, and turn it into its related uniform.
This chains well with `UniformComponentPlugin`.
The user may then:
```rust
app.add_plugin(ExtractComponentPlugin::<MyStruct>::default());
app.add_plugin(UniformComponentPlugin::<MyStructUniform>::default());
```
This then saves the user a fair amount of boilerplate.
## Changelog
### Changed
- `ExtractComponent` can specify output type, and outputting is optional.
Co-authored-by: Torstein Grindvik <52322338+torsteingrindvik@users.noreply.github.com>
# Objective
Allow more use cases where the user may benefit from both `ExtractComponentPlugin` _and_ `UniformComponentPlugin`.
## Solution
Add an associated type to `ExtractComponent` in order to allow specifying the output component (or bundle).
Make `extract_component` return an `Option<_>` such that components can be extracted only when needed.
What problem does this solve?
`ExtractComponentPlugin` allows extracting components, but currently the output type is the same as the input.
This means that use cases such as having a settings struct which turns into a uniform is awkward.
For example we might have:
```rust
struct MyStruct {
enabled: bool,
val: f32
}
struct MyStructUniform {
val: f32
}
```
With the new approach, we can extract `MyStruct` only when it is enabled, and turn it into its related uniform.
This chains well with `UniformComponentPlugin`.
The user may then:
```rust
app.add_plugin(ExtractComponentPlugin::<MyStruct>::default());
app.add_plugin(UniformComponentPlugin::<MyStructUniform>::default());
```
This then saves the user a fair amount of boilerplate.
## Changelog
### Changed
- `ExtractComponent` can specify output type, and outputting is optional.
Co-authored-by: Torstein Grindvik <52322338+torsteingrindvik@users.noreply.github.com>
# Objective
Allow more use cases where the user may benefit from both `ExtractComponentPlugin` _and_ `UniformComponentPlugin`.
## Solution
Add an associated type to `ExtractComponent` in order to allow specifying the output component (or bundle).
Make `extract_component` return an `Option<_>` such that components can be extracted only when needed.
What problem does this solve?
`ExtractComponentPlugin` allows extracting components, but currently the output type is the same as the input.
This means that use cases such as having a settings struct which turns into a uniform is awkward.
For example we might have:
```rust
struct MyStruct {
enabled: bool,
val: f32
}
struct MyStructUniform {
val: f32
}
```
With the new approach, we can extract `MyStruct` only when it is enabled, and turn it into its related uniform.
This chains well with `UniformComponentPlugin`.
The user may then:
```rust
app.add_plugin(ExtractComponentPlugin::<MyStruct>::default());
app.add_plugin(UniformComponentPlugin::<MyStructUniform>::default());
```
This then saves the user a fair amount of boilerplate.
## Changelog
### Changed
- `ExtractComponent` can specify output type, and outputting is optional.
Co-authored-by: Torstein Grindvik <52322338+torsteingrindvik@users.noreply.github.com>
Objective
Allow more use cases where the user may benefit from both
ExtractComponentPluginandUniformComponentPlugin.Solution
Add an associated type to
ExtractComponentin order to allow specifying the output component (or bundle).Make
extract_componentreturn anOption<_>such that components can be extracted only when needed.What problem does this solve?
ExtractComponentPluginallows extracting components, but currently the output type is the same as the input.This means that use cases such as having a settings struct which turns into a uniform is awkward.
For example we might have:
With the new approach, we can extract
MyStructonly when it is enabled, and turn it into its related uniform.This chains well with
UniformComponentPlugin.The user may then:
This then saves the user a fair amount of boilerplate.
Changelog
Changed
ExtractComponentcan specify output type, and outputting is optional.