3527288342
5 Commits
Author | SHA1 | Message | Date | |
---|---|---|---|---|
![]() |
72fc63e594
|
implement insert and remove reflected entity commands (#8895)
# Objective To enable non exclusive system usage of reflected components and make reflection more ergonomic to use by making it more in line with standard entity commands. ## Solution - Implements a new `EntityCommands` extension trait for reflection related functions in the reflect module of bevy_ecs. - Implements 4 new commands, `insert_reflect`, `insert_reflect_with_registry`, `remove_reflect`, and `remove_reflect_with_registry`. Both insert commands take a `Box<dyn Reflect>` component while the remove commands take the component type name. - Made `EntityCommands` fields pub(crate) to allow access in the reflect module. (Might be worth making these just public to enable user end custom entity commands in a different pr) - Added basic tests to ensure the commands are actually working. - Documentation of functions. --- ## Changelog Added: - Implements 4 new commands on the new entity commands extension. - `insert_reflect` - `remove_reflect` - `insert_reflect_with_registry` - `remove_reflect_with_registry` The commands operate the same except the with_registry commands take a generic parameter for a resource that implements `AsRef<TypeRegistry>`. Otherwise the default commands use the `AppTypeRegistry` for reflection data. Changed: - Made `EntityCommands` fields pub(crate) to allow access in the reflect module. > Hopefully this time it works. Please don't make me rebase again ☹ |
||
![]() |
fb9a65fa0d
|
bevy_scene: Add ReflectBundle (#9165)
# Objective Similar to #6344, but contains only `ReflectBundle` changes. Useful for scripting. The implementation has also been updated to look exactly like `ReflectComponent`. --- ## Changelog ### Added - Reflection for bundles. --------- Co-authored-by: Gino Valente <49806985+MrGVSV@users.noreply.github.com> |
||
![]() |
aeeb20ec4c
|
bevy_reflect: FromReflect Ergonomics Implementation (#6056)
# Objective **This implementation is based on https://github.com/bevyengine/rfcs/pull/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(®istry); let mut deserializer = ron:🇩🇪:Deserializer::from_str(input)?; let output: SomeStruct = reflect_deserializer.deserialize(&mut deserializer)?.take()?; // Returns the Dynamic type let reflect_deserializer = UntypedReflectDeserializer::new_dynamic(®istry); let mut deserializer = ron:🇩🇪: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(®istry); let mut deserializer = ron:🇩🇪: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(®istry); // NEW let reflect_deserializer = UntypedReflectDeserializer::new_dynamic(®istry); ``` </details> --------- Co-authored-by: Carter Anderson <mcanders1@gmail.com> |
||
![]() |
0294bb191d
|
Move AppTypeRegistry to bevy_ecs (#8901)
# Objective - Use `AppTypeRegistry` on API defined in `bevy_ecs` (https://github.com/bevyengine/bevy/pull/8895#discussion_r1234748418) A lot of the API on `Reflect` depends on a registry. When it comes to the ECS. We should use `AppTypeRegistry` in the general case. This is however impossible in `bevy_ecs`, since `AppTypeRegistry` is defined in `bevy_app`. ## Solution - Move `AppTypeRegistry` resource definition from `bevy_app` to `bevy_ecs` - Still add the resource in the `App` plugin, since bevy_ecs itself doesn't know of plugins Note that `bevy_ecs` is a dependency of `bevy_app`, so nothing revolutionary happens. ## Alternative - Define the API as a trait in `bevy_app` over `bevy_ecs`. (though this prevents us from using bevy_ecs internals) - Do not rely on `AppTypeRegistry` for the API in question, requring users to extract themselves the resource and pass it to the API methods. --- ## Changelog - Moved `AppTypeRegistry` resource definition from `bevy_app` to `bevy_ecs` ## Migration Guide - If you were **not** using a `prelude::*` to import `AppTypeRegistry`, you should update your imports: ```diff - use bevy::app::AppTypeRegistry; + use bevy::ecs::reflect::AppTypeRegistry ``` |
||
![]() |
08962f1e50
|
Split the bevy_ecs reflect.rs module (#8834)
# Objective - Cleanup the `reflect.rs` file in `bevy_ecs`, it's very large and can get difficult to navigate ## Solution - Split the file into 3 modules, re-export the types in the `reflect/mod.rs` to keep a perfectly identical API. - Add **internal** architecture doc explaining how `ReflectComponent` works. Note that this doc is internal only, since `component.rs` is not exposed publicly. ### Tips to reviewers To review this change properly, you need to compare it to the previous version of `reflect.rs`. The diff from this PR does not help at all! What you will need to do is compare `reflect.rs` individually with each newly created file. Here is how I did it: - Adding my fork as remote `git remote add nicopap https://github.com/nicopap/bevy.git` - Checkout out the branch `git checkout nicopap/split_ecs_reflect` - Checkout the old `reflect.rs` by running `git checkout HEAD~1 -- crates/bevy_ecs/src/reflect.rs` - Compare the old with the new with `git diff --no-index crates/bevy_ecs/src/reflect.rs crates/bevy_ecs/src/reflect/component.rs` You could also concatenate everything into a single file and compare against it: - `cat crates/bevy_ecs/src/reflect/{component,resource,map_entities,mod}.rs > new_reflect.rs` - `git diff --no-index crates/bevy_ecs/src/reflect.rs new_reflect.rs` |