Skip to content

Commit aeeb20e

Browse files
MrGVSVcart
andauthored
bevy_reflect: FromReflect Ergonomics Implementation (#6056)
# Objective **This implementation is based on bevyengine/rfcs#59 --- Resolves #4597 Full details and motivation can be found in the RFC, but here's a brief summary. `FromReflect` is a very powerful and important trait within the reflection API. It allows Dynamic types (e.g., `DynamicList`, etc.) to be formed into Real ones (e.g., `Vec<i32>`, etc.). This mainly comes into play concerning deserialization, where the reflection deserializers both return a `Box<dyn Reflect>` that almost always contain one of these Dynamic representations of a Real type. To convert this to our Real type, we need to use `FromReflect`. It also sneaks up in other ways. For example, it's a required bound for `T` in `Vec<T>` so that `Vec<T>` as a whole can be made `FromReflect`. It's also required by all fields of an enum as it's used as part of the `Reflect::apply` implementation. So in other words, much like `GetTypeRegistration` and `Typed`, it is very much a core reflection trait. The problem is that it is not currently treated like a core trait and is not automatically derived alongside `Reflect`. This makes using it a bit cumbersome and easy to forget. ## Solution Automatically derive `FromReflect` when deriving `Reflect`. Users can then choose to opt-out if needed using the `#[reflect(from_reflect = false)]` attribute. ```rust #[derive(Reflect)] struct Foo; #[derive(Reflect)] #[reflect(from_reflect = false)] struct Bar; fn test<T: FromReflect>(value: T) {} test(Foo); // <-- OK test(Bar); // <-- Panic! Bar does not implement trait `FromReflect` ``` #### `ReflectFromReflect` This PR also automatically adds the `ReflectFromReflect` (introduced in #6245) registration to the derived `GetTypeRegistration` impl— if the type hasn't opted out of `FromReflect` of course. <details> <summary><h4>Improved Deserialization</h4></summary> > **Warning** > This section includes changes that have since been descoped from this PR. They will likely be implemented again in a followup PR. I am mainly leaving these details in for archival purposes, as well as for reference when implementing this logic again. And since we can do all the above, we might as well improve deserialization. We can now choose to deserialize into a Dynamic type or automatically convert it using `FromReflect` under the hood. `[Un]TypedReflectDeserializer::new` will now perform the conversion and return the `Box`'d Real type. `[Un]TypedReflectDeserializer::new_dynamic` will work like what we have now and simply return the `Box`'d Dynamic type. ```rust // Returns the Real type let reflect_deserializer = UntypedReflectDeserializer::new(&registry); let mut deserializer = ron::de::Deserializer::from_str(input)?; let output: SomeStruct = reflect_deserializer.deserialize(&mut deserializer)?.take()?; // Returns the Dynamic type let reflect_deserializer = UntypedReflectDeserializer::new_dynamic(&registry); let mut deserializer = ron::de::Deserializer::from_str(input)?; let output: DynamicStruct = reflect_deserializer.deserialize(&mut deserializer)?.take()?; ``` </details> --- ## Changelog * `FromReflect` is now automatically derived within the `Reflect` derive macro * This includes auto-registering `ReflectFromReflect` in the derived `GetTypeRegistration` impl * ~~Renamed `TypedReflectDeserializer::new` and `UntypedReflectDeserializer::new` to `TypedReflectDeserializer::new_dynamic` and `UntypedReflectDeserializer::new_dynamic`, respectively~~ **Descoped** * ~~Changed `TypedReflectDeserializer::new` and `UntypedReflectDeserializer::new` to automatically convert the deserialized output using `FromReflect`~~ **Descoped** ## Migration Guide * `FromReflect` is now automatically derived within the `Reflect` derive macro. Items with both derives will need to remove the `FromReflect` one. ```rust // OLD #[derive(Reflect, FromReflect)] struct Foo; // NEW #[derive(Reflect)] struct Foo; ``` If using a manual implementation of `FromReflect` and the `Reflect` derive, users will need to opt-out of the automatic implementation. ```rust // OLD #[derive(Reflect)] struct Foo; impl FromReflect for Foo {/* ... */} // NEW #[derive(Reflect)] #[reflect(from_reflect = false)] struct Foo; impl FromReflect for Foo {/* ... */} ``` <details> <summary><h4>Removed Migrations</h4></summary> > **Warning** > This section includes changes that have since been descoped from this PR. They will likely be implemented again in a followup PR. I am mainly leaving these details in for archival purposes, as well as for reference when implementing this logic again. * The reflect deserializers now perform a `FromReflect` conversion internally. The expected output of `TypedReflectDeserializer::new` and `UntypedReflectDeserializer::new` is no longer a Dynamic (e.g., `DynamicList`), but its Real counterpart (e.g., `Vec<i32>`). ```rust let reflect_deserializer = UntypedReflectDeserializer::new_dynamic(&registry); let mut deserializer = ron::de::Deserializer::from_str(input)?; // OLD let output: DynamicStruct = reflect_deserializer.deserialize(&mut deserializer)?.take()?; // NEW let output: SomeStruct = reflect_deserializer.deserialize(&mut deserializer)?.take()?; ``` Alternatively, if this behavior isn't desired, use the `TypedReflectDeserializer::new_dynamic` and `UntypedReflectDeserializer::new_dynamic` methods instead: ```rust // OLD let reflect_deserializer = UntypedReflectDeserializer::new(&registry); // NEW let reflect_deserializer = UntypedReflectDeserializer::new_dynamic(&registry); ``` </details> --------- Co-authored-by: Carter Anderson <[email protected]>
1 parent de1dcb9 commit aeeb20e

File tree

94 files changed

+922
-779
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

94 files changed

+922
-779
lines changed

crates/bevy_animation/src/lib.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use bevy_core::Name;
1212
use bevy_ecs::prelude::*;
1313
use bevy_hierarchy::{Children, Parent};
1414
use bevy_math::{Quat, Vec3};
15-
use bevy_reflect::{FromReflect, Reflect, TypeUuid};
15+
use bevy_reflect::{Reflect, TypeUuid};
1616
use bevy_render::mesh::morph::MorphWeights;
1717
use bevy_time::Time;
1818
use bevy_transform::{prelude::Transform, TransformSystem};
@@ -27,7 +27,7 @@ pub mod prelude {
2727
}
2828

2929
/// List of keyframes for one of the attribute of a [`Transform`].
30-
#[derive(Reflect, FromReflect, Clone, Debug)]
30+
#[derive(Reflect, Clone, Debug)]
3131
pub enum Keyframes {
3232
/// Keyframes for rotation.
3333
Rotation(Vec<Quat>),
@@ -49,7 +49,7 @@ pub enum Keyframes {
4949
/// Describes how an attribute of a [`Transform`] or [`MorphWeights`] should be animated.
5050
///
5151
/// `keyframe_timestamps` and `keyframes` should have the same length.
52-
#[derive(Reflect, FromReflect, Clone, Debug)]
52+
#[derive(Reflect, Clone, Debug)]
5353
pub struct VariableCurve {
5454
/// Timestamp for each of the keyframes.
5555
pub keyframe_timestamps: Vec<f32>,
@@ -58,14 +58,14 @@ pub struct VariableCurve {
5858
}
5959

6060
/// Path to an entity, with [`Name`]s. Each entity in a path must have a name.
61-
#[derive(Reflect, FromReflect, Clone, Debug, Hash, PartialEq, Eq, Default)]
61+
#[derive(Reflect, Clone, Debug, Hash, PartialEq, Eq, Default)]
6262
pub struct EntityPath {
6363
/// Parts of the path
6464
pub parts: Vec<Name>,
6565
}
6666

6767
/// A list of [`VariableCurve`], and the [`EntityPath`] to which they apply.
68-
#[derive(Reflect, FromReflect, Clone, TypeUuid, Debug, Default)]
68+
#[derive(Reflect, Clone, TypeUuid, Debug, Default)]
6969
#[uuid = "d81b7179-0448-4eb0-89fe-c067222725bf"]
7070
pub struct AnimationClip {
7171
curves: Vec<Vec<VariableCurve>>,

crates/bevy_asset/src/handle.rs

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,28 +10,14 @@ use crate::{
1010
Asset, Assets,
1111
};
1212
use bevy_ecs::{component::Component, reflect::ReflectComponent};
13-
use bevy_reflect::{
14-
std_traits::ReflectDefault, FromReflect, Reflect, ReflectDeserialize, ReflectFromReflect,
15-
ReflectSerialize,
16-
};
13+
use bevy_reflect::{std_traits::ReflectDefault, Reflect, ReflectDeserialize, ReflectSerialize};
1714
use bevy_utils::Uuid;
1815
use crossbeam_channel::{Receiver, Sender};
1916
use serde::{Deserialize, Serialize};
2017

2118
/// A unique, stable asset id.
2219
#[derive(
23-
Debug,
24-
Clone,
25-
Copy,
26-
Eq,
27-
PartialEq,
28-
Hash,
29-
Ord,
30-
PartialOrd,
31-
Serialize,
32-
Deserialize,
33-
Reflect,
34-
FromReflect,
20+
Debug, Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Serialize, Deserialize, Reflect,
3521
)]
3622
#[reflect_value(Serialize, Deserialize, PartialEq, Hash)]
3723
pub enum HandleId {
@@ -103,8 +89,8 @@ impl HandleId {
10389
/// handle to the unloaded asset, but it will not be able to retrieve the image data, resulting in
10490
/// collisions no longer being detected for that entity.
10591
///
106-
#[derive(Component, Reflect, FromReflect)]
107-
#[reflect(Component, Default, FromReflect)]
92+
#[derive(Component, Reflect)]
93+
#[reflect(Component, Default)]
10894
pub struct Handle<T>
10995
where
11096
T: Asset,
@@ -117,7 +103,9 @@ where
117103
marker: PhantomData<fn() -> T>,
118104
}
119105

106+
#[derive(Default)]
120107
enum HandleType {
108+
#[default]
121109
Weak,
122110
Strong(Sender<RefChange>),
123111
}

crates/bevy_asset/src/path.rs

Lines changed: 7 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
use bevy_reflect::{
2-
FromReflect, Reflect, ReflectDeserialize, ReflectFromReflect, ReflectSerialize,
3-
};
1+
use bevy_reflect::{Reflect, ReflectDeserialize, ReflectSerialize};
42
use bevy_utils::{AHasher, RandomState};
53
use serde::{Deserialize, Serialize};
64
use std::{
@@ -10,8 +8,8 @@ use std::{
108
};
119

1210
/// Represents a path to an asset in the file system.
13-
#[derive(Debug, Eq, PartialEq, Hash, Clone, Serialize, Deserialize, Reflect, FromReflect)]
14-
#[reflect(Debug, PartialEq, Hash, Serialize, Deserialize, FromReflect)]
11+
#[derive(Debug, Eq, PartialEq, Hash, Clone, Serialize, Deserialize, Reflect)]
12+
#[reflect(Debug, PartialEq, Hash, Serialize, Deserialize)]
1513
pub struct AssetPath<'a> {
1614
path: Cow<'a, Path>,
1715
label: Option<Cow<'a, str>>,
@@ -69,38 +67,16 @@ impl<'a> AssetPath<'a> {
6967

7068
/// An unique identifier to an asset path.
7169
#[derive(
72-
Debug,
73-
Clone,
74-
Copy,
75-
Eq,
76-
PartialEq,
77-
Hash,
78-
Ord,
79-
PartialOrd,
80-
Serialize,
81-
Deserialize,
82-
Reflect,
83-
FromReflect,
70+
Debug, Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Serialize, Deserialize, Reflect,
8471
)]
85-
#[reflect_value(PartialEq, Hash, Serialize, Deserialize, FromReflect)]
72+
#[reflect_value(PartialEq, Hash, Serialize, Deserialize)]
8673
pub struct AssetPathId(SourcePathId, LabelId);
8774

8875
/// An unique identifier to the source path of an asset.
8976
#[derive(
90-
Debug,
91-
Clone,
92-
Copy,
93-
Eq,
94-
PartialEq,
95-
Hash,
96-
Ord,
97-
PartialOrd,
98-
Serialize,
99-
Deserialize,
100-
Reflect,
101-
FromReflect,
77+
Debug, Clone, Copy, Eq, PartialEq, Hash, Ord, PartialOrd, Serialize, Deserialize, Reflect,
10278
)]
103-
#[reflect_value(PartialEq, Hash, Serialize, Deserialize, FromReflect)]
79+
#[reflect_value(PartialEq, Hash, Serialize, Deserialize)]
10480
pub struct SourcePathId(u64);
10581

10682
/// An unique identifier to a sub-asset label.

crates/bevy_asset/src/reflect.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -255,11 +255,11 @@ mod tests {
255255

256256
use bevy_app::App;
257257
use bevy_ecs::reflect::AppTypeRegistry;
258-
use bevy_reflect::{FromReflect, Reflect, ReflectMut, TypeUuid};
258+
use bevy_reflect::{Reflect, ReflectMut, TypeUuid};
259259

260260
use crate::{AddAsset, AssetPlugin, HandleUntyped, ReflectAsset};
261261

262-
#[derive(Reflect, FromReflect, TypeUuid)]
262+
#[derive(Reflect, TypeUuid)]
263263
#[uuid = "09191350-1238-4736-9a89-46f04bda6966"]
264264
struct AssetType {
265265
field: String,

crates/bevy_core/src/name.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use bevy_ecs::{
22
component::Component, entity::Entity, query::WorldQuery, reflect::ReflectComponent,
33
};
4-
use bevy_reflect::{std_traits::ReflectDefault, FromReflect};
5-
use bevy_reflect::{Reflect, ReflectFromReflect};
4+
use bevy_reflect::std_traits::ReflectDefault;
5+
use bevy_reflect::Reflect;
66
use bevy_utils::AHasher;
77
use std::{
88
borrow::Cow,
@@ -17,8 +17,8 @@ use std::{
1717
/// [`Name`] should not be treated as a globally unique identifier for entities,
1818
/// as multiple entities can have the same name. [`bevy_ecs::entity::Entity`] should be
1919
/// used instead as the default unique identifier.
20-
#[derive(Reflect, FromReflect, Component, Clone)]
21-
#[reflect(Component, Default, Debug, FromReflect)]
20+
#[derive(Reflect, Component, Clone)]
21+
#[reflect(Component, Default, Debug)]
2222
pub struct Name {
2323
hash: u64, // TODO: Shouldn't be serialized
2424
name: Cow<'static, str>,

crates/bevy_core_pipeline/src/bloom/settings.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use super::downsampling_pipeline::BloomUniforms;
22
use bevy_ecs::{prelude::Component, query::QueryItem, reflect::ReflectComponent};
33
use bevy_math::{UVec4, Vec4};
4-
use bevy_reflect::{std_traits::ReflectDefault, FromReflect, Reflect, ReflectFromReflect};
4+
use bevy_reflect::{std_traits::ReflectDefault, Reflect};
55
use bevy_render::{extract_component::ExtractComponent, prelude::Camera};
66

77
/// Applies a bloom effect to an HDR-enabled 2d or 3d camera.
@@ -160,8 +160,7 @@ impl Default for BloomSettings {
160160
/// * Changing these settings creates a physically inaccurate image
161161
/// * Changing these settings makes it easy to make the final result look worse
162162
/// * Non-default prefilter settings should be used in conjuction with [`BloomCompositeMode::Additive`]
163-
#[derive(Default, Clone, Reflect, FromReflect)]
164-
#[reflect(FromReflect)]
163+
#[derive(Default, Clone, Reflect)]
165164
pub struct BloomPrefilterSettings {
166165
/// Baseline of the quadratic threshold curve (default: 0.0).
167166
///

crates/bevy_core_pipeline/src/clear_color.rs

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
use bevy_derive::{Deref, DerefMut};
22
use bevy_ecs::prelude::*;
3-
use bevy_reflect::{
4-
FromReflect, Reflect, ReflectDeserialize, ReflectFromReflect, ReflectSerialize,
5-
};
3+
use bevy_reflect::{Reflect, ReflectDeserialize, ReflectSerialize};
64
use bevy_render::{color::Color, extract_resource::ExtractResource};
75
use serde::{Deserialize, Serialize};
86

9-
#[derive(Reflect, FromReflect, Serialize, Deserialize, Clone, Debug, Default)]
10-
#[reflect(Serialize, Deserialize, FromReflect)]
7+
#[derive(Reflect, Serialize, Deserialize, Clone, Debug, Default)]
8+
#[reflect(Serialize, Deserialize)]
119
pub enum ClearColorConfig {
1210
#[default]
1311
Default,
@@ -19,8 +17,8 @@ pub enum ClearColorConfig {
1917
///
2018
/// This color appears as the "background" color for simple apps,
2119
/// when there are portions of the screen with nothing rendered.
22-
#[derive(Resource, Clone, Debug, Deref, DerefMut, ExtractResource, Reflect, FromReflect)]
23-
#[reflect(Resource, FromReflect)]
20+
#[derive(Resource, Clone, Debug, Deref, DerefMut, ExtractResource, Reflect)]
21+
#[reflect(Resource)]
2422
pub struct ClearColor(pub Color);
2523

2624
impl Default for ClearColor {

crates/bevy_core_pipeline/src/core_2d/camera_2d.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crate::{
33
tonemapping::{DebandDither, Tonemapping},
44
};
55
use bevy_ecs::prelude::*;
6-
use bevy_reflect::{FromReflect, Reflect, ReflectFromReflect};
6+
use bevy_reflect::Reflect;
77
use bevy_render::{
88
camera::{Camera, CameraProjection, CameraRenderGraph, OrthographicProjection},
99
extract_component::ExtractComponent,
@@ -12,9 +12,9 @@ use bevy_render::{
1212
};
1313
use bevy_transform::prelude::{GlobalTransform, Transform};
1414

15-
#[derive(Component, Default, Reflect, FromReflect, Clone, ExtractComponent)]
15+
#[derive(Component, Default, Reflect, Clone, ExtractComponent)]
1616
#[extract_component_filter(With<Camera>)]
17-
#[reflect(Component, FromReflect)]
17+
#[reflect(Component)]
1818
pub struct Camera2d {
1919
pub clear_color: ClearColorConfig,
2020
}

crates/bevy_core_pipeline/src/core_3d/camera_3d.rs

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,7 @@ use crate::{
33
tonemapping::{DebandDither, Tonemapping},
44
};
55
use bevy_ecs::prelude::*;
6-
use bevy_reflect::{
7-
FromReflect, Reflect, ReflectDeserialize, ReflectFromReflect, ReflectSerialize,
8-
};
6+
use bevy_reflect::{Reflect, ReflectDeserialize, ReflectSerialize};
97
use bevy_render::{
108
camera::{Camera, CameraRenderGraph, Projection},
119
extract_component::ExtractComponent,
@@ -17,9 +15,9 @@ use bevy_transform::prelude::{GlobalTransform, Transform};
1715
use serde::{Deserialize, Serialize};
1816

1917
/// Configuration for the "main 3d render graph".
20-
#[derive(Component, Reflect, FromReflect, Clone, ExtractComponent)]
18+
#[derive(Component, Reflect, Clone, ExtractComponent)]
2119
#[extract_component_filter(With<Camera>)]
22-
#[reflect(Component, FromReflect)]
20+
#[reflect(Component)]
2321
pub struct Camera3d {
2422
/// The clear color operation to perform for the main 3d pass.
2523
pub clear_color: ClearColorConfig,
@@ -39,8 +37,7 @@ impl Default for Camera3d {
3937
}
4038
}
4139

42-
#[derive(Clone, Copy, Reflect, FromReflect)]
43-
#[reflect(FromReflect)]
40+
#[derive(Clone, Copy, Reflect)]
4441
pub struct Camera3dDepthTextureUsage(u32);
4542

4643
impl From<TextureUsages> for Camera3dDepthTextureUsage {
@@ -55,8 +52,8 @@ impl From<Camera3dDepthTextureUsage> for TextureUsages {
5552
}
5653

5754
/// The depth clear operation to perform for the main 3d pass.
58-
#[derive(Reflect, FromReflect, Serialize, Deserialize, Clone, Debug)]
59-
#[reflect(Serialize, Deserialize, FromReflect)]
55+
#[derive(Reflect, Serialize, Deserialize, Clone, Debug)]
56+
#[reflect(Serialize, Deserialize)]
6057
pub enum Camera3dDepthLoadOp {
6158
/// Clear with a specified value.
6259
/// Note that 0.0 is the far plane due to bevy's use of reverse-z projections.

crates/bevy_core_pipeline/src/fxaa/mod.rs

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,7 @@ use bevy_app::prelude::*;
77
use bevy_asset::{load_internal_asset, HandleUntyped};
88
use bevy_derive::Deref;
99
use bevy_ecs::prelude::*;
10-
use bevy_reflect::{
11-
std_traits::ReflectDefault, FromReflect, Reflect, ReflectFromReflect, TypeUuid,
12-
};
10+
use bevy_reflect::{std_traits::ReflectDefault, Reflect, TypeUuid};
1311
use bevy_render::{
1412
extract_component::{ExtractComponent, ExtractComponentPlugin},
1513
prelude::Camera,
@@ -26,8 +24,8 @@ mod node;
2624

2725
pub use node::FxaaNode;
2826

29-
#[derive(Reflect, FromReflect, Eq, PartialEq, Hash, Clone, Copy)]
30-
#[reflect(FromReflect, PartialEq, Hash)]
27+
#[derive(Reflect, Eq, PartialEq, Hash, Clone, Copy)]
28+
#[reflect(PartialEq, Hash)]
3129
pub enum Sensitivity {
3230
Low,
3331
Medium,
@@ -48,8 +46,8 @@ impl Sensitivity {
4846
}
4947
}
5048

51-
#[derive(Reflect, FromReflect, Component, Clone, ExtractComponent)]
52-
#[reflect(Component, FromReflect, Default)]
49+
#[derive(Reflect, Component, Clone, ExtractComponent)]
50+
#[reflect(Component, Default)]
5351
#[extract_component_filter(With<Camera>)]
5452
pub struct Fxaa {
5553
/// Enable render passes for FXAA.

crates/bevy_core_pipeline/src/prepass/mod.rs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ pub mod node;
3030
use std::cmp::Reverse;
3131

3232
use bevy_ecs::prelude::*;
33-
use bevy_reflect::{FromReflect, Reflect, ReflectFromReflect};
33+
use bevy_reflect::Reflect;
3434
use bevy_render::{
3535
render_phase::{CachedRenderPipelinePhaseItem, DrawFunctionId, PhaseItem},
3636
render_resource::{CachedRenderPipelineId, Extent3d, TextureFormat},
@@ -43,19 +43,16 @@ pub const NORMAL_PREPASS_FORMAT: TextureFormat = TextureFormat::Rgb10a2Unorm;
4343
pub const MOTION_VECTOR_PREPASS_FORMAT: TextureFormat = TextureFormat::Rg16Float;
4444

4545
/// If added to a [`crate::prelude::Camera3d`] then depth values will be copied to a separate texture available to the main pass.
46-
#[derive(Component, Default, Reflect, FromReflect)]
47-
#[reflect(FromReflect)]
46+
#[derive(Component, Default, Reflect)]
4847
pub struct DepthPrepass;
4948

5049
/// If added to a [`crate::prelude::Camera3d`] then vertex world normals will be copied to a separate texture available to the main pass.
5150
/// Normals will have normal map textures already applied.
52-
#[derive(Component, Default, Reflect, FromReflect)]
53-
#[reflect(FromReflect)]
51+
#[derive(Component, Default, Reflect)]
5452
pub struct NormalPrepass;
5553

5654
/// If added to a [`crate::prelude::Camera3d`] then screen space motion vectors will be copied to a separate texture available to the main pass.
57-
#[derive(Component, Default, Reflect, FromReflect)]
58-
#[reflect(FromReflect)]
55+
#[derive(Component, Default, Reflect)]
5956
pub struct MotionVectorPrepass;
6057

6158
/// Textures that are written to by the prepass.

0 commit comments

Comments
 (0)