bevy/crates
Gino Valente 63f1a9dec8 bevy_reflect: Add ReflectFromReflect (v2) (#6245)
# Objective

Resolves #4597 (based on the work from #6056 and a refresh of #4147)

When using reflection, we may often end up in a scenario where we have a Dynamic representing a certain type. Unfortunately, we can't just call `MyType::from_reflect` as we do not have knowledge of the concrete type (`MyType`) at runtime.

Such scenarios happen when we call `Reflect::clone_value`, use the reflection deserializers, or create the Dynamic type ourselves.

## Solution

Add a `ReflectFromReflect` type data struct.

This struct allows us to easily convert Dynamic representations of our types into their respective concrete instances.

```rust
#[derive(Reflect, FromReflect)]
#[reflect(FromReflect)] // <- Register `ReflectFromReflect`
struct MyStruct(String);

let type_id = TypeId::of::<MyStruct>();

// Register our type
let mut registry = TypeRegistry::default();
registry.register::<MyStruct>();

// Create a concrete instance
let my_struct = MyStruct("Hello world".to_string());

// `Reflect::clone_value` will generate a `DynamicTupleStruct` for tuple struct types
let dynamic_value: Box<dyn Reflect> = my_struct.clone_value();
assert!(!dynamic_value.is::<MyStruct>());

// Get the `ReflectFromReflect` type data from the registry
let rfr: &ReflectFromReflect = registry
  .get_type_data::<ReflectFromReflect>(type_id)
  .unwrap();

// Call `FromReflect::from_reflect` on our Dynamic value
let concrete_value: Box<dyn Reflect> = rfr.from_reflect(&dynamic_value);
assert!(concrete_value.is::<MyStruct>());
```

### Why this PR?

###### Why now?

The three main reasons I closed #4147 were that:

1. Registering `ReflectFromReflect` is clunky (deriving `FromReflect` *and* registering `ReflectFromReflect`)
2. The ecosystem and Bevy itself didn't seem to pay much attention to deriving `FromReflect`
3. I didn't see a lot of desire from the community for such a feature

However, as time has passed it seems 2 and 3 are not really true anymore. Bevy is internally adding lots more `FromReflect` derives, which should make this feature all the more useful. Additionally, I have seen a growing number of people look for something like `ReflectFromReflect`.

I think 1 is still an issue, but not a horrible one. Plus it could be made much, much better using #6056. And I think splitting this feature out of #6056 could lead to #6056 being adopted sooner (or at least make the need more clear to users).

###### Why not just re-open #4147?

The main reason is so that this PR can garner more attention than simply re-opening the old one. This helps bring fresh eyes to the PR for potentially more perspectives/reviews.

---

## Changelog

* Added `ReflectFromReflect`

Co-authored-by: Gino Valente <49806985+MrGVSV@users.noreply.github.com>
2022-12-11 17:52:48 +00:00
..
bevy_animation Release 0.9.0 (#6568) 2022-11-12 20:01:29 +00:00
bevy_app Release 0.9.0 (#6568) 2022-11-12 20:01:29 +00:00
bevy_asset Derive clone and debug for AssetPlugin (#6583) 2022-11-14 23:08:26 +00:00
bevy_audio Release 0.9.0 (#6568) 2022-11-12 20:01:29 +00:00
bevy_core Fix reflection for PathBuf and OsString (#6776) 2022-11-27 17:28:06 +00:00
bevy_core_pipeline Fix missing sRGB conversion for dithering non-HDR pipelines (#6707) 2022-11-22 15:55:50 +00:00
bevy_derive Release 0.9.0 (#6568) 2022-11-12 20:01:29 +00:00
bevy_diagnostic pin nightly to 2022-11-28 to fix miri (#6808) 2022-12-01 01:30:55 +00:00
bevy_dylib Release 0.9.0 (#6568) 2022-11-12 20:01:29 +00:00
bevy_dynamic_plugin Adapt path type of dynamically_load_plugin (#6734) 2022-12-05 23:39:43 +00:00
bevy_ecs Fix Sparse Change Detection (#6896) 2022-12-10 09:25:53 +00:00
bevy_ecs_compile_fail_tests Fix trybuild tests broken by rust 1.65 (#6457) 2022-11-03 15:09:27 +00:00
bevy_encase_derive Release 0.9.0 (#6568) 2022-11-12 20:01:29 +00:00
bevy_gilrs Bump gilrs version to 0.10 (#6558) 2022-11-15 20:31:17 +00:00
bevy_gltf Intepret glTF colors as linear instead of sRGB (#6828) 2022-12-04 19:35:13 +00:00
bevy_hierarchy Remove APIs deprecated in 0.9 (#6801) 2022-12-05 22:49:04 +00:00
bevy_input Correct docs for ButtonSettingsError to read 0.0..=1.0 (#6570) 2022-11-12 22:59:49 +00:00
bevy_internal Update dead links in DefaultPlugins docs (#6695) 2022-11-21 20:12:31 +00:00
bevy_log Update tracing-chrome requirement from 0.6.0 to 0.7.0 (#6709) 2022-12-04 22:30:09 +00:00
bevy_macro_utils Release 0.9.0 (#6568) 2022-11-12 20:01:29 +00:00
bevy_math Improve code/comments for Ray::intersect_plane and its tests (#6823) 2022-12-05 22:49:06 +00:00
bevy_mikktspace Release 0.9.0 (#6568) 2022-11-12 20:01:29 +00:00
bevy_pbr ShaderDefVal: add an UInt option (#6881) 2022-12-07 23:10:27 +00:00
bevy_ptr Add safe constructors for untyped pointers Ptr and PtrMut (#6539) 2022-11-14 22:53:50 +00:00
bevy_reflect bevy_reflect: Add ReflectFromReflect (v2) (#6245) 2022-12-11 17:52:48 +00:00
bevy_render ShaderDefVal: add an UInt option (#6881) 2022-12-07 23:10:27 +00:00
bevy_scene Allow iterating over with EntityRef over the entire World (#6843) 2022-12-05 22:35:02 +00:00
bevy_sprite Add DrawFunctionsInternals::id() (#6745) 2022-11-28 13:54:13 +00:00
bevy_tasks await tasks to cancel (#6696) 2022-11-23 00:41:19 +00:00
bevy_text Remove TextError::ExceedMaxTextAtlases(usize) variant (#6796) 2022-12-05 23:23:16 +00:00
bevy_time Update old docs from Timer (#6646) 2022-11-18 20:42:33 +00:00
bevy_transform Parallelized transform propagation (#4775) 2022-11-21 18:18:38 +00:00
bevy_ui Remove TextError::ExceedMaxTextAtlases(usize) variant (#6796) 2022-12-05 23:23:16 +00:00
bevy_utils Release 0.9.0 (#6568) 2022-11-12 20:01:29 +00:00
bevy_window Derive Reflect + FromReflect for window event types (#6235) 2022-12-09 01:20:44 +00:00
bevy_winit Fix set_cursor_grab_mode to try an alternative mode before giving an error (#6599) 2022-11-26 13:10:11 +00:00