-
-
Notifications
You must be signed in to change notification settings - Fork 3.7k
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
[Merged by Bors] - ExtractComponent output optional associated type #6699
[Merged by Bors] - ExtractComponent output optional associated type #6699
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 <[email protected]>
Signed-off-by: Torstein Grindvik <[email protected]>
7b55bfb
to
d52ac8d
Compare
Added a second commit which uses the changes on the bloom plugin. The results are:
|
Signed-off-by: Torstein Grindvik <[email protected]>
#[derive(ShaderType)] | ||
struct BloomUniform { | ||
#[derive(Component, ShaderType, Clone)] | ||
pub struct BloomUniform { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doc strings :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extracting uncloneable components generally seems impossible or at least poorly thought out?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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 <[email protected]>
Co-authored-by: Alice Cecile <[email protected]>
Co-authored-by: Alice Cecile <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Replace if-let with Option::map.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now that you removed this, where are you checking for these conditions? Did I miss this somewhere?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we keep this struct private? I don't like exposing bloom implementation details.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can use #[doc(hidden)]
to reduce public visibility.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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 <[email protected]>
Signed-off-by: Torstein Grindvik <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm!
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 <[email protected]>
# 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 <[email protected]>
# 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 <[email protected]>
# 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 <[email protected]>
Objective
Allow more use cases where the user may benefit from both
ExtractComponentPlugin
andUniformComponentPlugin
.Solution
Add an associated type to
ExtractComponent
in order to allow specifying the output component (or bundle).Make
extract_component
return anOption<_>
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:
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:
This then saves the user a fair amount of boilerplate.
Changelog
Changed
ExtractComponent
can specify output type, and outputting is optional.