Skip to content

Commit

Permalink
bevy_scene: Use FromReflect on extracted resources (#15753)
Browse files Browse the repository at this point in the history
# Objective

Fixes #15726

The extraction logic for components makes use of `FromReflect` to try
and ensure we have a concrete type for serialization. However, we did
not do the same for resources.

The reason we're seeing this for the glam types is that #15174 also made
a change to rely on the glam type's `Serialize` and `Deserialize` impls,
which I don't think should have been merged (I'll put up a PR addressing
this specifically soon).

## Solution

Use `FromReflect` on extracted resources.

## Testing

You can test locally by running:

```
cargo test --package bevy_scene
```
  • Loading branch information
MrGVSV authored Oct 9, 2024
1 parent bc35256 commit 05b0f28
Showing 1 changed file with 46 additions and 4 deletions.
50 changes: 46 additions & 4 deletions crates/bevy_scene/src/dynamic_scene_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -365,12 +365,19 @@ impl<'w> DynamicSceneBuilder<'w> {
return None;
}

let resource = type_registry
.get(type_id)?
let type_registration = type_registry.get(type_id)?;

let resource = type_registration
.data::<ReflectResource>()?
.reflect(self.original_world)?;
self.extracted_resources
.insert(component_id, resource.clone_value());

let resource = type_registration
.data::<ReflectFromReflect>()
.and_then(|fr| fr.from_reflect(resource.as_partial_reflect()))
.map(PartialReflect::into_partial_reflect)
.unwrap_or_else(|| resource.clone_value());

self.extracted_resources.insert(component_id, resource);
Some(())
};
extract_and_push();
Expand Down Expand Up @@ -688,4 +695,39 @@ mod tests {
assert_eq!(scene.resources.len(), 1);
assert!(scene.resources[0].represents::<ResourceB>());
}

#[test]
fn should_use_from_reflect() {
#[derive(Resource, Component, Reflect)]
#[reflect(Resource, Component)]
struct SomeType(i32);

let mut world = World::default();
let atr = AppTypeRegistry::default();
{
let mut register = atr.write();
register.register::<SomeType>();
}
world.insert_resource(atr);

world.insert_resource(SomeType(123));
let entity = world.spawn(SomeType(123)).id();

let scene = DynamicSceneBuilder::from_world(&world)
.extract_resources()
.extract_entities(vec![entity].into_iter())
.build();

let component = &scene.entities[0].components[0];
assert!(component
.try_as_reflect()
.expect("component should be concrete due to `FromReflect`")
.is::<SomeType>());

let resource = &scene.resources[0];
assert!(resource
.try_as_reflect()
.expect("resource should be concrete due to `FromReflect`")
.is::<SomeType>());
}
}

0 comments on commit 05b0f28

Please sign in to comment.