Skip to content

Commit 2ea51fc

Browse files
yrnsMrGVSV
andauthored
Use FromReflect when extracting entities in dynamic scenes (#15174)
# Objective Fix #10284. ## Solution When `DynamicSceneBuilder` extracts entities, they are cloned via `PartialReflect::clone_value`, making them into dynamic versions of the original components. This loses any custom `ReflectSerialize` type data. Dynamic scenes are deserialized with the original types, not the dynamic versions, and so any component with a custom serialize may fail. In this case `Rect` and `Vec2`. The dynamic version includes the field names 'x' and 'y' but the `Serialize` impl doesn't, hence the "expect float" error. The solution here: Instead of using `clone_value` to clone the components, `FromReflect` clones and retains the original information needed to serialize with any custom `Serialize` impls. I think using something like `reflect_clone` from (#13432) might make this more efficient. I also did the same when deserializing dynamic scenes to appease some of the round-trip tests which use `ReflectPartialEq`, which requires the types be the same and not a unique/proxy pair. I'm not sure it's otherwise necessary. Maybe this would also be more efficient when spawning dynamic scenes with `reflect_clone` instead of `FromReflect` again? An alternative solution would be to fall back to the dynamic version when deserializing `DynamicScene`s if the custom version fails. I think that's possible. Or maybe simply always deserializing via the dynamic route for dynamic scenes? ## Testing This example is similar to the original test case in #10284: ``` rust #![allow(missing_docs)] use bevy::{prelude::*, scene::SceneInstanceReady}; fn main() { App::new() .add_plugins(DefaultPlugins) .add_systems(Startup, (save, load).chain()) .observe(check) .run(); } static SAVEGAME_SAVE_PATH: &str = "savegame.scn.ron"; fn save(world: &mut World) { let entity = world.spawn(OrthographicProjection::default()).id(); let scene = DynamicSceneBuilder::from_world(world) .extract_entity(entity) .build(); if let Some(registry) = world.get_resource::<AppTypeRegistry>() { let registry = registry.read(); let serialized_scene = scene.serialize(&registry).unwrap(); // println!("{}", serialized_scene); std::fs::write(format!("assets/{SAVEGAME_SAVE_PATH}"), serialized_scene).unwrap(); } world.entity_mut(entity).despawn_recursive(); } fn load(mut commands: Commands, asset_server: Res<AssetServer>) { commands.spawn(DynamicSceneBundle { scene: asset_server.load(SAVEGAME_SAVE_PATH), ..default() }); } fn check(_trigger: Trigger<SceneInstanceReady>, query: Query<&OrthographicProjection>) { dbg!(query.single()); } ``` ## Migration Guide The `DynamicScene` format is changed to use custom serialize impls so old scene files will need updating: Old: ```ron ( resources: {}, entities: { 4294967299: ( components: { "bevy_render::camera::projection::OrthographicProjection": ( near: 0.0, far: 1000.0, viewport_origin: ( x: 0.5, y: 0.5, ), scaling_mode: WindowSize(1.0), scale: 1.0, area: ( min: ( x: -1.0, y: -1.0, ), max: ( x: 1.0, y: 1.0, ), ), ), }, ), }, ) ``` New: ```ron ( resources: {}, entities: { 4294967299: ( components: { "bevy_render::camera::projection::OrthographicProjection": ( near: 0.0, far: 1000.0, viewport_origin: (0.5, 0.5), scaling_mode: WindowSize(1.0), scale: 1.0, area: ( min: (-1.0, -1.0), max: (1.0, 1.0), ), ), }, ), }, ) ``` --------- Co-authored-by: Gino Valente <49806985+MrGVSV@users.noreply.github.com>
1 parent 21e3936 commit 2ea51fc

File tree

4 files changed

+130
-84
lines changed

4 files changed

+130
-84
lines changed

crates/bevy_reflect/src/impls/glam.rs

Lines changed: 39 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
use crate as bevy_reflect;
2-
use crate::prelude::ReflectDefault;
2+
use crate::{std_traits::ReflectDefault, ReflectDeserialize, ReflectSerialize};
33
use bevy_reflect_derive::{impl_reflect, impl_reflect_value};
44
use glam::*;
55

66
impl_reflect!(
7-
#[reflect(Debug, Hash, PartialEq, Default)]
7+
#[reflect(Debug, Hash, PartialEq, Default, Deserialize, Serialize)]
88
#[type_path = "glam"]
99
struct IVec2 {
1010
x: i32,
1111
y: i32,
1212
}
1313
);
1414
impl_reflect!(
15-
#[reflect(Debug, Hash, PartialEq, Default)]
15+
#[reflect(Debug, Hash, PartialEq, Default, Deserialize, Serialize)]
1616
#[type_path = "glam"]
1717
struct IVec3 {
1818
x: i32,
@@ -21,7 +21,7 @@ impl_reflect!(
2121
}
2222
);
2323
impl_reflect!(
24-
#[reflect(Debug, Hash, PartialEq, Default)]
24+
#[reflect(Debug, Hash, PartialEq, Default, Deserialize, Serialize)]
2525
#[type_path = "glam"]
2626
struct IVec4 {
2727
x: i32,
@@ -32,7 +32,7 @@ impl_reflect!(
3232
);
3333

3434
impl_reflect!(
35-
#[reflect(Debug, Hash, PartialEq, Default)]
35+
#[reflect(Debug, Hash, PartialEq, Default, Deserialize, Serialize)]
3636
#[type_path = "glam"]
3737
struct I64Vec2 {
3838
x: i64,
@@ -41,7 +41,7 @@ impl_reflect!(
4141
);
4242

4343
impl_reflect!(
44-
#[reflect(Debug, Hash, PartialEq, Default)]
44+
#[reflect(Debug, Hash, PartialEq, Default, Deserialize, Serialize)]
4545
#[type_path = "glam"]
4646
struct I64Vec3 {
4747
x: i64,
@@ -51,7 +51,7 @@ impl_reflect!(
5151
);
5252

5353
impl_reflect!(
54-
#[reflect(Debug, Hash, PartialEq, Default)]
54+
#[reflect(Debug, Hash, PartialEq, Default, Deserialize, Serialize)]
5555
#[type_path = "glam"]
5656
struct I64Vec4 {
5757
x: i64,
@@ -62,15 +62,15 @@ impl_reflect!(
6262
);
6363

6464
impl_reflect!(
65-
#[reflect(Debug, Hash, PartialEq, Default)]
65+
#[reflect(Debug, Hash, PartialEq, Default, Deserialize, Serialize)]
6666
#[type_path = "glam"]
6767
struct UVec2 {
6868
x: u32,
6969
y: u32,
7070
}
7171
);
7272
impl_reflect!(
73-
#[reflect(Debug, Hash, PartialEq, Default)]
73+
#[reflect(Debug, Hash, PartialEq, Default, Deserialize, Serialize)]
7474
#[type_path = "glam"]
7575
struct UVec3 {
7676
x: u32,
@@ -79,7 +79,7 @@ impl_reflect!(
7979
}
8080
);
8181
impl_reflect!(
82-
#[reflect(Debug, Hash, PartialEq, Default)]
82+
#[reflect(Debug, Hash, PartialEq, Default, Deserialize, Serialize)]
8383
#[type_path = "glam"]
8484
struct UVec4 {
8585
x: u32,
@@ -90,15 +90,15 @@ impl_reflect!(
9090
);
9191

9292
impl_reflect!(
93-
#[reflect(Debug, Hash, PartialEq, Default)]
93+
#[reflect(Debug, Hash, PartialEq, Default, Deserialize, Serialize)]
9494
#[type_path = "glam"]
9595
struct U64Vec2 {
9696
x: u64,
9797
y: u64,
9898
}
9999
);
100100
impl_reflect!(
101-
#[reflect(Debug, Hash, PartialEq, Default)]
101+
#[reflect(Debug, Hash, PartialEq, Default, Deserialize, Serialize)]
102102
#[type_path = "glam"]
103103
struct U64Vec3 {
104104
x: u64,
@@ -107,7 +107,7 @@ impl_reflect!(
107107
}
108108
);
109109
impl_reflect!(
110-
#[reflect(Debug, Hash, PartialEq, Default)]
110+
#[reflect(Debug, Hash, PartialEq, Default, Deserialize, Serialize)]
111111
#[type_path = "glam"]
112112
struct U64Vec4 {
113113
x: u64,
@@ -118,15 +118,15 @@ impl_reflect!(
118118
);
119119

120120
impl_reflect!(
121-
#[reflect(Debug, PartialEq, Default)]
121+
#[reflect(Debug, PartialEq, Default, Deserialize, Serialize)]
122122
#[type_path = "glam"]
123123
struct Vec2 {
124124
x: f32,
125125
y: f32,
126126
}
127127
);
128128
impl_reflect!(
129-
#[reflect(Debug, PartialEq, Default)]
129+
#[reflect(Debug, PartialEq, Default, Deserialize, Serialize)]
130130
#[type_path = "glam"]
131131
struct Vec3 {
132132
x: f32,
@@ -135,7 +135,7 @@ impl_reflect!(
135135
}
136136
);
137137
impl_reflect!(
138-
#[reflect(Debug, PartialEq, Default)]
138+
#[reflect(Debug, PartialEq, Default, Deserialize, Serialize)]
139139
#[type_path = "glam"]
140140
struct Vec3A {
141141
x: f32,
@@ -144,7 +144,7 @@ impl_reflect!(
144144
}
145145
);
146146
impl_reflect!(
147-
#[reflect(Debug, PartialEq, Default)]
147+
#[reflect(Debug, PartialEq, Default, Deserialize, Serialize)]
148148
#[type_path = "glam"]
149149
struct Vec4 {
150150
x: f32,
@@ -155,15 +155,15 @@ impl_reflect!(
155155
);
156156

157157
impl_reflect!(
158-
#[reflect(Debug, PartialEq, Default)]
158+
#[reflect(Debug, PartialEq, Default, Deserialize, Serialize)]
159159
#[type_path = "glam"]
160160
struct BVec2 {
161161
x: bool,
162162
y: bool,
163163
}
164164
);
165165
impl_reflect!(
166-
#[reflect(Debug, PartialEq, Default)]
166+
#[reflect(Debug, PartialEq, Default, Deserialize, Serialize)]
167167
#[type_path = "glam"]
168168
struct BVec3 {
169169
x: bool,
@@ -172,7 +172,7 @@ impl_reflect!(
172172
}
173173
);
174174
impl_reflect!(
175-
#[reflect(Debug, PartialEq, Default)]
175+
#[reflect(Debug, PartialEq, Default, Deserialize, Serialize)]
176176
#[type_path = "glam"]
177177
struct BVec4 {
178178
x: bool,
@@ -183,15 +183,15 @@ impl_reflect!(
183183
);
184184

185185
impl_reflect!(
186-
#[reflect(Debug, PartialEq, Default)]
186+
#[reflect(Debug, PartialEq, Default, Deserialize, Serialize)]
187187
#[type_path = "glam"]
188188
struct DVec2 {
189189
x: f64,
190190
y: f64,
191191
}
192192
);
193193
impl_reflect!(
194-
#[reflect(Debug, PartialEq, Default)]
194+
#[reflect(Debug, PartialEq, Default, Deserialize, Serialize)]
195195
#[type_path = "glam"]
196196
struct DVec3 {
197197
x: f64,
@@ -200,7 +200,7 @@ impl_reflect!(
200200
}
201201
);
202202
impl_reflect!(
203-
#[reflect(Debug, PartialEq, Default)]
203+
#[reflect(Debug, PartialEq, Default, Deserialize, Serialize)]
204204
#[type_path = "glam"]
205205
struct DVec4 {
206206
x: f64,
@@ -211,15 +211,15 @@ impl_reflect!(
211211
);
212212

213213
impl_reflect!(
214-
#[reflect(Debug, PartialEq, Default)]
214+
#[reflect(Debug, PartialEq, Default, Deserialize, Serialize)]
215215
#[type_path = "glam"]
216216
struct Mat2 {
217217
x_axis: Vec2,
218218
y_axis: Vec2,
219219
}
220220
);
221221
impl_reflect!(
222-
#[reflect(Debug, PartialEq, Default)]
222+
#[reflect(Debug, PartialEq, Default, Deserialize, Serialize)]
223223
#[type_path = "glam"]
224224
struct Mat3 {
225225
x_axis: Vec3,
@@ -228,7 +228,7 @@ impl_reflect!(
228228
}
229229
);
230230
impl_reflect!(
231-
#[reflect(Debug, PartialEq, Default)]
231+
#[reflect(Debug, PartialEq, Default, Deserialize, Serialize)]
232232
#[type_path = "glam"]
233233
struct Mat3A {
234234
x_axis: Vec3A,
@@ -237,7 +237,7 @@ impl_reflect!(
237237
}
238238
);
239239
impl_reflect!(
240-
#[reflect(Debug, PartialEq, Default)]
240+
#[reflect(Debug, PartialEq, Default, Deserialize, Serialize)]
241241
#[type_path = "glam"]
242242
struct Mat4 {
243243
x_axis: Vec4,
@@ -248,15 +248,15 @@ impl_reflect!(
248248
);
249249

250250
impl_reflect!(
251-
#[reflect(Debug, PartialEq, Default)]
251+
#[reflect(Debug, PartialEq, Default, Deserialize, Serialize)]
252252
#[type_path = "glam"]
253253
struct DMat2 {
254254
x_axis: DVec2,
255255
y_axis: DVec2,
256256
}
257257
);
258258
impl_reflect!(
259-
#[reflect(Debug, PartialEq, Default)]
259+
#[reflect(Debug, PartialEq, Default, Deserialize, Serialize)]
260260
#[type_path = "glam"]
261261
struct DMat3 {
262262
x_axis: DVec3,
@@ -265,7 +265,7 @@ impl_reflect!(
265265
}
266266
);
267267
impl_reflect!(
268-
#[reflect(Debug, PartialEq, Default)]
268+
#[reflect(Debug, PartialEq, Default, Deserialize, Serialize)]
269269
#[type_path = "glam"]
270270
struct DMat4 {
271271
x_axis: DVec4,
@@ -276,15 +276,15 @@ impl_reflect!(
276276
);
277277

278278
impl_reflect!(
279-
#[reflect(Debug, PartialEq, Default)]
279+
#[reflect(Debug, PartialEq, Default, Deserialize, Serialize)]
280280
#[type_path = "glam"]
281281
struct Affine2 {
282282
matrix2: Mat2,
283283
translation: Vec2,
284284
}
285285
);
286286
impl_reflect!(
287-
#[reflect(Debug, PartialEq, Default)]
287+
#[reflect(Debug, PartialEq, Default, Deserialize, Serialize)]
288288
#[type_path = "glam"]
289289
struct Affine3A {
290290
matrix3: Mat3A,
@@ -293,15 +293,15 @@ impl_reflect!(
293293
);
294294

295295
impl_reflect!(
296-
#[reflect(Debug, PartialEq, Default)]
296+
#[reflect(Debug, PartialEq, Default, Deserialize, Serialize)]
297297
#[type_path = "glam"]
298298
struct DAffine2 {
299299
matrix2: DMat2,
300300
translation: DVec2,
301301
}
302302
);
303303
impl_reflect!(
304-
#[reflect(Debug, PartialEq, Default)]
304+
#[reflect(Debug, PartialEq, Default, Deserialize, Serialize)]
305305
#[type_path = "glam"]
306306
struct DAffine3 {
307307
matrix3: DMat3,
@@ -310,7 +310,7 @@ impl_reflect!(
310310
);
311311

312312
impl_reflect!(
313-
#[reflect(Debug, PartialEq, Default)]
313+
#[reflect(Debug, PartialEq, Default, Deserialize, Serialize)]
314314
#[type_path = "glam"]
315315
struct Quat {
316316
x: f32,
@@ -320,7 +320,7 @@ impl_reflect!(
320320
}
321321
);
322322
impl_reflect!(
323-
#[reflect(Debug, PartialEq, Default)]
323+
#[reflect(Debug, PartialEq, Default, Deserialize, Serialize)]
324324
#[type_path = "glam"]
325325
struct DQuat {
326326
x: f64,
@@ -330,6 +330,6 @@ impl_reflect!(
330330
}
331331
);
332332

333-
impl_reflect_value!(::glam::EulerRot(Debug, Default));
334-
impl_reflect_value!(::glam::BVec3A(Debug, Default));
335-
impl_reflect_value!(::glam::BVec4A(Debug, Default));
333+
impl_reflect_value!(::glam::EulerRot(Debug, Default, Deserialize, Serialize));
334+
impl_reflect_value!(::glam::BVec3A(Debug, Default, Deserialize, Serialize));
335+
impl_reflect_value!(::glam::BVec4A(Debug, Default, Deserialize, Serialize));

crates/bevy_reflect/src/lib.rs

Lines changed: 4 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2961,12 +2961,7 @@ bevy_reflect::tests::Test {
29612961
let output = to_string_pretty(&ser, config).unwrap();
29622962
let expected = r#"
29632963
{
2964-
"glam::Quat": (
2965-
x: 1.0,
2966-
y: 2.0,
2967-
z: 3.0,
2968-
w: 4.0,
2969-
),
2964+
"glam::Quat": (1.0, 2.0, 3.0, 4.0),
29702965
}"#;
29712966

29722967
assert_eq!(expected, format!("\n{output}"));
@@ -2976,12 +2971,7 @@ bevy_reflect::tests::Test {
29762971
fn quat_deserialization() {
29772972
let data = r#"
29782973
{
2979-
"glam::Quat": (
2980-
x: 1.0,
2981-
y: 2.0,
2982-
z: 3.0,
2983-
w: 4.0,
2984-
),
2974+
"glam::Quat": (1.0, 2.0, 3.0, 4.0),
29852975
}"#;
29862976

29872977
let mut registry = TypeRegistry::default();
@@ -3020,11 +3010,7 @@ bevy_reflect::tests::Test {
30203010
let output = to_string_pretty(&ser, config).unwrap();
30213011
let expected = r#"
30223012
{
3023-
"glam::Vec3": (
3024-
x: 12.0,
3025-
y: 3.0,
3026-
z: -6.9,
3027-
),
3013+
"glam::Vec3": (12.0, 3.0, -6.9),
30283014
}"#;
30293015

30303016
assert_eq!(expected, format!("\n{output}"));
@@ -3034,11 +3020,7 @@ bevy_reflect::tests::Test {
30343020
fn vec3_deserialization() {
30353021
let data = r#"
30363022
{
3037-
"glam::Vec3": (
3038-
x: 12.0,
3039-
y: 3.0,
3040-
z: -6.9,
3041-
),
3023+
"glam::Vec3": (12.0, 3.0, -6.9),
30423024
}"#;
30433025

30443026
let mut registry = TypeRegistry::default();

0 commit comments

Comments
 (0)