mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 07:04:33 +00:00
reflect: implement the unique reflect rfc (#7207)
# Objective
- Implements the [Unique Reflect
RFC](https://github.com/nicopap/rfcs/blob/bevy-reflect-api/rfcs/56-better-reflect.md).
## Solution
- Implements the RFC.
- This implementation differs in some ways from the RFC:
- In the RFC, it was suggested `Reflect: Any` but `PartialReflect:
?Any`. During initial implementation I tried this, but we assume the
`PartialReflect: 'static` in a lot of places and the changes required
crept out of the scope of this PR.
- `PartialReflect::try_into_reflect` originally returned `Option<Box<dyn
Reflect>>` but i changed this to `Result<Box<dyn Reflect>, Box<dyn
PartialReflect>>` since the method takes by value and otherwise there
would be no way to recover the type. `as_full` and `as_full_mut` both
still return `Option<&(mut) dyn Reflect>`.
---
## Changelog
- Added `PartialReflect`.
- `Reflect` is now a subtrait of `PartialReflect`.
- Moved most methods on `Reflect` to the new `PartialReflect`.
- Added `PartialReflect::{as_partial_reflect, as_partial_reflect_mut,
into_partial_reflect}`.
- Added `PartialReflect::{try_as_reflect, try_as_reflect_mut,
try_into_reflect}`.
- Added `<dyn PartialReflect>::{try_downcast_ref, try_downcast_mut,
try_downcast, try_take}` supplementing the methods on `dyn Reflect`.
## Migration Guide
- Most instances of `dyn Reflect` should be changed to `dyn
PartialReflect` which is less restrictive, however trait bounds should
generally stay as `T: Reflect`.
- The new `PartialReflect::{as_partial_reflect, as_partial_reflect_mut,
into_partial_reflect, try_as_reflect, try_as_reflect_mut,
try_into_reflect}` methods as well as `Reflect::{as_reflect,
as_reflect_mut, into_reflect}` will need to be implemented for manual
implementors of `Reflect`.
## Future Work
- This PR is designed to be followed up by another "Unique Reflect Phase
2" that addresses the following points:
- Investigate making serialization revolve around `Reflect` instead of
`PartialReflect`.
- [Remove the `try_*` methods on `dyn PartialReflect` since they are
stop
gaps](https://github.com/bevyengine/bevy/pull/7207#discussion_r1083476050).
- Investigate usages like `ReflectComponent`. In the places they
currently use `PartialReflect`, should they be changed to use `Reflect`?
- Merging this opens the door to lots of reflection features we haven't
been able to implement.
- We could re-add [the `Reflectable`
trait](8e3488c880/crates/bevy_reflect/src/reflect.rs (L337-L342)
)
and make `FromReflect` a requirement to improve [`FromReflect`
ergonomics](https://github.com/bevyengine/rfcs/pull/59). This is
currently not possible because dynamic types cannot sensibly be
`FromReflect`.
- Since this is an alternative to #5772, #5781 would be made cleaner.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Gino Valente <49806985+MrGVSV@users.noreply.github.com>
This commit is contained in:
parent
7b81ae7e40
commit
6ab8767d3b
65 changed files with 2271 additions and 1855 deletions
|
@ -515,6 +515,8 @@ pub enum UntypedAssetConversionError {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use bevy_reflect::PartialReflect;
|
||||
|
||||
use super::*;
|
||||
|
||||
type TestAsset = ();
|
||||
|
@ -651,7 +653,7 @@ mod tests {
|
|||
);
|
||||
|
||||
let reflected: &dyn Reflect = &handle;
|
||||
let cloned_handle: Box<dyn Reflect> = reflected.clone_value();
|
||||
let cloned_handle: Box<dyn PartialReflect> = reflected.clone_value();
|
||||
|
||||
assert_eq!(
|
||||
Arc::strong_count(strong),
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std::any::{Any, TypeId};
|
||||
|
||||
use bevy_ecs::world::{unsafe_world_cell::UnsafeWorldCell, World};
|
||||
use bevy_reflect::{FromReflect, FromType, Reflect};
|
||||
use bevy_reflect::{FromReflect, FromType, PartialReflect, Reflect};
|
||||
|
||||
use crate::{Asset, AssetId, Assets, Handle, UntypedAssetId, UntypedHandle};
|
||||
|
||||
|
@ -22,8 +22,8 @@ pub struct ReflectAsset {
|
|||
// - may only be called with an [`UnsafeWorldCell`] which can be used to access the corresponding `Assets<T>` resource mutably
|
||||
// - may only be used to access **at most one** access at once
|
||||
get_unchecked_mut: unsafe fn(UnsafeWorldCell<'_>, UntypedHandle) -> Option<&mut dyn Reflect>,
|
||||
add: fn(&mut World, &dyn Reflect) -> UntypedHandle,
|
||||
insert: fn(&mut World, UntypedHandle, &dyn Reflect),
|
||||
add: fn(&mut World, &dyn PartialReflect) -> UntypedHandle,
|
||||
insert: fn(&mut World, UntypedHandle, &dyn PartialReflect),
|
||||
len: fn(&World) -> usize,
|
||||
ids: for<'w> fn(&'w World) -> Box<dyn Iterator<Item = UntypedAssetId> + 'w>,
|
||||
remove: fn(&mut World, UntypedHandle) -> Option<Box<dyn Reflect>>,
|
||||
|
@ -94,11 +94,11 @@ impl ReflectAsset {
|
|||
}
|
||||
|
||||
/// Equivalent of [`Assets::add`]
|
||||
pub fn add(&self, world: &mut World, value: &dyn Reflect) -> UntypedHandle {
|
||||
pub fn add(&self, world: &mut World, value: &dyn PartialReflect) -> UntypedHandle {
|
||||
(self.add)(world, value)
|
||||
}
|
||||
/// Equivalent of [`Assets::insert`]
|
||||
pub fn insert(&self, world: &mut World, handle: UntypedHandle, value: &dyn Reflect) {
|
||||
pub fn insert(&self, world: &mut World, handle: UntypedHandle, value: &dyn PartialReflect) {
|
||||
(self.insert)(world, handle, value);
|
||||
}
|
||||
|
||||
|
|
|
@ -4,13 +4,15 @@
|
|||
//! This module exports two types: [`ReflectBundleFns`] and [`ReflectBundle`].
|
||||
//!
|
||||
//! Same as [`super::component`], but for bundles.
|
||||
use std::any::TypeId;
|
||||
use std::any::{Any, TypeId};
|
||||
|
||||
use crate::{
|
||||
prelude::Bundle,
|
||||
world::{EntityMut, EntityWorldMut},
|
||||
};
|
||||
use bevy_reflect::{FromReflect, FromType, Reflect, ReflectRef, TypeRegistry};
|
||||
use bevy_reflect::{
|
||||
FromReflect, FromType, PartialReflect, Reflect, ReflectRef, TypePath, TypeRegistry,
|
||||
};
|
||||
|
||||
use super::{from_reflect_with_fallback, ReflectComponent};
|
||||
|
||||
|
@ -27,11 +29,11 @@ pub struct ReflectBundle(ReflectBundleFns);
|
|||
#[derive(Clone)]
|
||||
pub struct ReflectBundleFns {
|
||||
/// Function pointer implementing [`ReflectBundle::insert()`].
|
||||
pub insert: fn(&mut EntityWorldMut, &dyn Reflect, &TypeRegistry),
|
||||
pub insert: fn(&mut EntityWorldMut, &dyn PartialReflect, &TypeRegistry),
|
||||
/// Function pointer implementing [`ReflectBundle::apply()`].
|
||||
pub apply: fn(EntityMut, &dyn Reflect, &TypeRegistry),
|
||||
pub apply: fn(EntityMut, &dyn PartialReflect, &TypeRegistry),
|
||||
/// Function pointer implementing [`ReflectBundle::apply_or_insert()`].
|
||||
pub apply_or_insert: fn(&mut EntityWorldMut, &dyn Reflect, &TypeRegistry),
|
||||
pub apply_or_insert: fn(&mut EntityWorldMut, &dyn PartialReflect, &TypeRegistry),
|
||||
/// Function pointer implementing [`ReflectBundle::remove()`].
|
||||
pub remove: fn(&mut EntityWorldMut),
|
||||
}
|
||||
|
@ -42,7 +44,7 @@ impl ReflectBundleFns {
|
|||
///
|
||||
/// This is useful if you want to start with the default implementation before overriding some
|
||||
/// of the functions to create a custom implementation.
|
||||
pub fn new<T: Bundle + Reflect + FromReflect>() -> Self {
|
||||
pub fn new<T: Bundle + FromReflect + TypePath>() -> Self {
|
||||
<ReflectBundle as FromType<T>>::from_type().0
|
||||
}
|
||||
}
|
||||
|
@ -52,7 +54,7 @@ impl ReflectBundle {
|
|||
pub fn insert(
|
||||
&self,
|
||||
entity: &mut EntityWorldMut,
|
||||
bundle: &dyn Reflect,
|
||||
bundle: &dyn PartialReflect,
|
||||
registry: &TypeRegistry,
|
||||
) {
|
||||
(self.0.insert)(entity, bundle, registry);
|
||||
|
@ -66,7 +68,7 @@ impl ReflectBundle {
|
|||
pub fn apply<'a>(
|
||||
&self,
|
||||
entity: impl Into<EntityMut<'a>>,
|
||||
bundle: &dyn Reflect,
|
||||
bundle: &dyn PartialReflect,
|
||||
registry: &TypeRegistry,
|
||||
) {
|
||||
(self.0.apply)(entity.into(), bundle, registry);
|
||||
|
@ -76,7 +78,7 @@ impl ReflectBundle {
|
|||
pub fn apply_or_insert(
|
||||
&self,
|
||||
entity: &mut EntityWorldMut,
|
||||
bundle: &dyn Reflect,
|
||||
bundle: &dyn PartialReflect,
|
||||
registry: &TypeRegistry,
|
||||
) {
|
||||
(self.0.apply_or_insert)(entity, bundle, registry);
|
||||
|
@ -122,7 +124,7 @@ impl ReflectBundle {
|
|||
}
|
||||
}
|
||||
|
||||
impl<B: Bundle + Reflect> FromType<B> for ReflectBundle {
|
||||
impl<B: Bundle + Reflect + TypePath> FromType<B> for ReflectBundle {
|
||||
fn from_type() -> Self {
|
||||
ReflectBundle(ReflectBundleFns {
|
||||
insert: |entity, reflected_bundle, registry| {
|
||||
|
@ -180,10 +182,16 @@ impl<B: Bundle + Reflect> FromType<B> for ReflectBundle {
|
|||
}
|
||||
}
|
||||
|
||||
fn apply_field(entity: &mut EntityMut, field: &dyn Reflect, registry: &TypeRegistry) {
|
||||
if let Some(reflect_component) = registry.get_type_data::<ReflectComponent>(field.type_id()) {
|
||||
fn apply_field(entity: &mut EntityMut, field: &dyn PartialReflect, registry: &TypeRegistry) {
|
||||
let Some(type_id) = field.try_as_reflect().map(Any::type_id) else {
|
||||
panic!(
|
||||
"`{}` did not implement `Reflect`",
|
||||
field.reflect_type_path()
|
||||
);
|
||||
};
|
||||
if let Some(reflect_component) = registry.get_type_data::<ReflectComponent>(type_id) {
|
||||
reflect_component.apply(entity.reborrow(), field);
|
||||
} else if let Some(reflect_bundle) = registry.get_type_data::<ReflectBundle>(field.type_id()) {
|
||||
} else if let Some(reflect_bundle) = registry.get_type_data::<ReflectBundle>(type_id) {
|
||||
reflect_bundle.apply(entity.reborrow(), field, registry);
|
||||
} else {
|
||||
panic!(
|
||||
|
@ -195,19 +203,22 @@ fn apply_field(entity: &mut EntityMut, field: &dyn Reflect, registry: &TypeRegis
|
|||
|
||||
fn apply_or_insert_field(
|
||||
entity: &mut EntityWorldMut,
|
||||
field: &dyn Reflect,
|
||||
field: &dyn PartialReflect,
|
||||
registry: &TypeRegistry,
|
||||
) {
|
||||
if let Some(reflect_component) = registry.get_type_data::<ReflectComponent>(field.type_id()) {
|
||||
let Some(type_id) = field.try_as_reflect().map(Any::type_id) else {
|
||||
panic!(
|
||||
"`{}` did not implement `Reflect`",
|
||||
field.reflect_type_path()
|
||||
);
|
||||
};
|
||||
|
||||
if let Some(reflect_component) = registry.get_type_data::<ReflectComponent>(type_id) {
|
||||
reflect_component.apply_or_insert(entity, field, registry);
|
||||
} else if let Some(reflect_bundle) = registry.get_type_data::<ReflectBundle>(field.type_id()) {
|
||||
} else if let Some(reflect_bundle) = registry.get_type_data::<ReflectBundle>(type_id) {
|
||||
reflect_bundle.apply_or_insert(entity, field, registry);
|
||||
} else {
|
||||
let is_component = entity
|
||||
.world()
|
||||
.components()
|
||||
.get_id(field.type_id())
|
||||
.is_some();
|
||||
let is_component = entity.world().components().get_id(type_id).is_some();
|
||||
|
||||
if is_component {
|
||||
panic!(
|
||||
|
|
|
@ -67,7 +67,7 @@ use crate::{
|
|||
FilteredEntityRef, World,
|
||||
},
|
||||
};
|
||||
use bevy_reflect::{FromReflect, FromType, Reflect, TypeRegistry};
|
||||
use bevy_reflect::{FromReflect, FromType, PartialReflect, Reflect, TypePath, TypeRegistry};
|
||||
|
||||
/// A struct used to operate on reflected [`Component`] trait of a type.
|
||||
///
|
||||
|
@ -99,11 +99,11 @@ pub struct ReflectComponent(ReflectComponentFns);
|
|||
#[derive(Clone)]
|
||||
pub struct ReflectComponentFns {
|
||||
/// Function pointer implementing [`ReflectComponent::insert()`].
|
||||
pub insert: fn(&mut EntityWorldMut, &dyn Reflect, &TypeRegistry),
|
||||
pub insert: fn(&mut EntityWorldMut, &dyn PartialReflect, &TypeRegistry),
|
||||
/// Function pointer implementing [`ReflectComponent::apply()`].
|
||||
pub apply: fn(EntityMut, &dyn Reflect),
|
||||
pub apply: fn(EntityMut, &dyn PartialReflect),
|
||||
/// Function pointer implementing [`ReflectComponent::apply_or_insert()`].
|
||||
pub apply_or_insert: fn(&mut EntityWorldMut, &dyn Reflect, &TypeRegistry),
|
||||
pub apply_or_insert: fn(&mut EntityWorldMut, &dyn PartialReflect, &TypeRegistry),
|
||||
/// Function pointer implementing [`ReflectComponent::remove()`].
|
||||
pub remove: fn(&mut EntityWorldMut),
|
||||
/// Function pointer implementing [`ReflectComponent::contains()`].
|
||||
|
@ -127,7 +127,7 @@ impl ReflectComponentFns {
|
|||
///
|
||||
/// This is useful if you want to start with the default implementation before overriding some
|
||||
/// of the functions to create a custom implementation.
|
||||
pub fn new<T: Component + Reflect + FromReflect>() -> Self {
|
||||
pub fn new<T: Component + FromReflect + TypePath>() -> Self {
|
||||
<ReflectComponent as FromType<T>>::from_type().0
|
||||
}
|
||||
}
|
||||
|
@ -137,7 +137,7 @@ impl ReflectComponent {
|
|||
pub fn insert(
|
||||
&self,
|
||||
entity: &mut EntityWorldMut,
|
||||
component: &dyn Reflect,
|
||||
component: &dyn PartialReflect,
|
||||
registry: &TypeRegistry,
|
||||
) {
|
||||
(self.0.insert)(entity, component, registry);
|
||||
|
@ -148,7 +148,7 @@ impl ReflectComponent {
|
|||
/// # Panics
|
||||
///
|
||||
/// Panics if there is no [`Component`] of the given type.
|
||||
pub fn apply<'a>(&self, entity: impl Into<EntityMut<'a>>, component: &dyn Reflect) {
|
||||
pub fn apply<'a>(&self, entity: impl Into<EntityMut<'a>>, component: &dyn PartialReflect) {
|
||||
(self.0.apply)(entity.into(), component);
|
||||
}
|
||||
|
||||
|
@ -156,7 +156,7 @@ impl ReflectComponent {
|
|||
pub fn apply_or_insert(
|
||||
&self,
|
||||
entity: &mut EntityWorldMut,
|
||||
component: &dyn Reflect,
|
||||
component: &dyn PartialReflect,
|
||||
registry: &TypeRegistry,
|
||||
) {
|
||||
(self.0.apply_or_insert)(entity, component, registry);
|
||||
|
@ -256,7 +256,7 @@ impl ReflectComponent {
|
|||
}
|
||||
}
|
||||
|
||||
impl<C: Component + Reflect> FromType<C> for ReflectComponent {
|
||||
impl<C: Component + Reflect + TypePath> FromType<C> for ReflectComponent {
|
||||
fn from_type() -> Self {
|
||||
ReflectComponent(ReflectComponentFns {
|
||||
insert: |entity, reflected_component, registry| {
|
||||
|
@ -271,7 +271,7 @@ impl<C: Component + Reflect> FromType<C> for ReflectComponent {
|
|||
},
|
||||
apply_or_insert: |entity, reflected_component, registry| {
|
||||
if let Some(mut component) = entity.get_mut::<C>() {
|
||||
component.apply(reflected_component);
|
||||
component.apply(reflected_component.as_partial_reflect());
|
||||
} else {
|
||||
let component = entity.world_scope(|world| {
|
||||
from_reflect_with_fallback::<C>(reflected_component, world, registry)
|
||||
|
|
|
@ -3,7 +3,7 @@ use crate::reflect::AppTypeRegistry;
|
|||
use crate::system::{EntityCommands, Resource};
|
||||
use crate::world::Command;
|
||||
use crate::{entity::Entity, reflect::ReflectComponent, world::World};
|
||||
use bevy_reflect::{Reflect, TypeRegistry};
|
||||
use bevy_reflect::{PartialReflect, TypeRegistry};
|
||||
use std::borrow::Cow;
|
||||
use std::marker::PhantomData;
|
||||
|
||||
|
@ -18,7 +18,7 @@ pub trait ReflectCommandExt {
|
|||
///
|
||||
/// - If the entity doesn't exist.
|
||||
/// - If [`AppTypeRegistry`] does not have the reflection data for the given [`Component`](crate::component::Component).
|
||||
/// - If the component data is invalid. See [`Reflect::apply`] for further details.
|
||||
/// - If the component data is invalid. See [`PartialReflect::apply`] for further details.
|
||||
/// - If [`AppTypeRegistry`] is not present in the [`World`].
|
||||
///
|
||||
/// # Note
|
||||
|
@ -69,7 +69,7 @@ pub trait ReflectCommandExt {
|
|||
/// }
|
||||
///
|
||||
/// ```
|
||||
fn insert_reflect(&mut self, component: Box<dyn Reflect>) -> &mut Self;
|
||||
fn insert_reflect(&mut self, component: Box<dyn PartialReflect>) -> &mut Self;
|
||||
|
||||
/// Same as [`insert_reflect`](ReflectCommandExt::insert_reflect), but using the `T` resource as type registry instead of
|
||||
/// `AppTypeRegistry`.
|
||||
|
@ -83,7 +83,7 @@ pub trait ReflectCommandExt {
|
|||
/// - The given [`Resource`] is removed from the [`World`] before the command is applied.
|
||||
fn insert_reflect_with_registry<T: Resource + AsRef<TypeRegistry>>(
|
||||
&mut self,
|
||||
component: Box<dyn Reflect>,
|
||||
component: Box<dyn PartialReflect>,
|
||||
) -> &mut Self;
|
||||
|
||||
/// Removes from the entity the component with the given type name registered in [`AppTypeRegistry`].
|
||||
|
@ -142,7 +142,7 @@ pub trait ReflectCommandExt {
|
|||
}
|
||||
|
||||
impl ReflectCommandExt for EntityCommands<'_> {
|
||||
fn insert_reflect(&mut self, component: Box<dyn Reflect>) -> &mut Self {
|
||||
fn insert_reflect(&mut self, component: Box<dyn PartialReflect>) -> &mut Self {
|
||||
self.commands.add(InsertReflect {
|
||||
entity: self.entity,
|
||||
component,
|
||||
|
@ -152,7 +152,7 @@ impl ReflectCommandExt for EntityCommands<'_> {
|
|||
|
||||
fn insert_reflect_with_registry<T: Resource + AsRef<TypeRegistry>>(
|
||||
&mut self,
|
||||
component: Box<dyn Reflect>,
|
||||
component: Box<dyn PartialReflect>,
|
||||
) -> &mut Self {
|
||||
self.commands.add(InsertReflectWithRegistry::<T> {
|
||||
entity: self.entity,
|
||||
|
@ -188,7 +188,7 @@ fn insert_reflect(
|
|||
world: &mut World,
|
||||
entity: Entity,
|
||||
type_registry: &TypeRegistry,
|
||||
component: Box<dyn Reflect>,
|
||||
component: Box<dyn PartialReflect>,
|
||||
) {
|
||||
let type_info = component
|
||||
.get_represented_type_info()
|
||||
|
@ -197,13 +197,13 @@ fn insert_reflect(
|
|||
let Some(mut entity) = world.get_entity_mut(entity) else {
|
||||
panic!("error[B0003]: Could not insert a reflected component (of type {type_path}) for entity {entity:?} because it doesn't exist in this World. See: https://bevyengine.org/learn/errors/b0003");
|
||||
};
|
||||
let Some(type_registration) = type_registry.get_with_type_path(type_path) else {
|
||||
let Some(type_registration) = type_registry.get(type_info.type_id()) else {
|
||||
panic!("Could not get type registration (for component type {type_path}) because it doesn't exist in the TypeRegistry.");
|
||||
};
|
||||
let Some(reflect_component) = type_registration.data::<ReflectComponent>() else {
|
||||
panic!("Could not get ReflectComponent data (for component type {type_path}) because it doesn't exist in this TypeRegistration.");
|
||||
};
|
||||
reflect_component.insert(&mut entity, &*component, type_registry);
|
||||
reflect_component.insert(&mut entity, component.as_partial_reflect(), type_registry);
|
||||
}
|
||||
|
||||
/// A [`Command`] that adds the boxed reflect component to an entity using the data in
|
||||
|
@ -214,7 +214,7 @@ pub struct InsertReflect {
|
|||
/// The entity on which the component will be inserted.
|
||||
pub entity: Entity,
|
||||
/// The reflect [`Component`](crate::component::Component) that will be added to the entity.
|
||||
pub component: Box<dyn Reflect>,
|
||||
pub component: Box<dyn PartialReflect>,
|
||||
}
|
||||
|
||||
impl Command for InsertReflect {
|
||||
|
@ -233,7 +233,7 @@ pub struct InsertReflectWithRegistry<T: Resource + AsRef<TypeRegistry>> {
|
|||
pub entity: Entity,
|
||||
pub _t: PhantomData<T>,
|
||||
/// The reflect [`Component`](crate::component::Component) that will be added to the entity.
|
||||
pub component: Box<dyn Reflect>,
|
||||
pub component: Box<dyn PartialReflect>,
|
||||
}
|
||||
|
||||
impl<T: Resource + AsRef<TypeRegistry>> Command for InsertReflectWithRegistry<T> {
|
||||
|
@ -317,7 +317,7 @@ mod tests {
|
|||
use crate::system::{Commands, SystemState};
|
||||
use crate::{self as bevy_ecs, component::Component, world::World};
|
||||
use bevy_ecs_macros::Resource;
|
||||
use bevy_reflect::{Reflect, TypeRegistry};
|
||||
use bevy_reflect::{PartialReflect, Reflect, TypeRegistry};
|
||||
|
||||
#[derive(Resource)]
|
||||
struct TypeRegistryResource {
|
||||
|
@ -352,7 +352,7 @@ mod tests {
|
|||
let entity = commands.spawn_empty().id();
|
||||
let entity2 = commands.spawn_empty().id();
|
||||
|
||||
let boxed_reflect_component_a = Box::new(ComponentA(916)) as Box<dyn Reflect>;
|
||||
let boxed_reflect_component_a = Box::new(ComponentA(916)) as Box<dyn PartialReflect>;
|
||||
let boxed_reflect_component_a_clone = boxed_reflect_component_a.clone_value();
|
||||
|
||||
commands
|
||||
|
@ -388,7 +388,7 @@ mod tests {
|
|||
|
||||
let entity = commands.spawn_empty().id();
|
||||
|
||||
let boxed_reflect_component_a = Box::new(ComponentA(916)) as Box<dyn Reflect>;
|
||||
let boxed_reflect_component_a = Box::new(ComponentA(916)) as Box<dyn PartialReflect>;
|
||||
|
||||
commands
|
||||
.entity(entity)
|
||||
|
|
|
@ -6,7 +6,9 @@ use std::ops::{Deref, DerefMut};
|
|||
use crate as bevy_ecs;
|
||||
use crate::{system::Resource, world::World};
|
||||
use bevy_reflect::std_traits::ReflectDefault;
|
||||
use bevy_reflect::{Reflect, ReflectFromReflect, TypeRegistry, TypeRegistryArc};
|
||||
use bevy_reflect::{
|
||||
PartialReflect, Reflect, ReflectFromReflect, TypePath, TypeRegistry, TypeRegistryArc,
|
||||
};
|
||||
|
||||
mod bundle;
|
||||
mod component;
|
||||
|
@ -69,7 +71,7 @@ impl DerefMut for AppFunctionRegistry {
|
|||
}
|
||||
}
|
||||
|
||||
/// Creates a `T` from a `&dyn Reflect`.
|
||||
/// Creates a `T` from a `&dyn PartialReflect`.
|
||||
///
|
||||
/// This will try the following strategies, in this order:
|
||||
///
|
||||
|
@ -85,18 +87,17 @@ impl DerefMut for AppFunctionRegistry {
|
|||
/// this method will panic.
|
||||
///
|
||||
/// If none of the strategies succeed, this method will panic.
|
||||
pub fn from_reflect_with_fallback<T: Reflect>(
|
||||
reflected: &dyn Reflect,
|
||||
pub fn from_reflect_with_fallback<T: Reflect + TypePath>(
|
||||
reflected: &dyn PartialReflect,
|
||||
world: &mut World,
|
||||
registry: &TypeRegistry,
|
||||
) -> T {
|
||||
fn different_type_error<T>(reflected: &str) -> ! {
|
||||
fn different_type_error<T: TypePath>(reflected: &str) -> ! {
|
||||
panic!(
|
||||
"The registration for the reflected `{}` trait for the type `{}` produced \
|
||||
a value of a different type",
|
||||
reflected,
|
||||
// FIXME: once we have unique reflect, use `TypePath`.
|
||||
std::any::type_name::<T>(),
|
||||
T::type_path(),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ use crate::{
|
|||
system::Resource,
|
||||
world::{unsafe_world_cell::UnsafeWorldCell, World},
|
||||
};
|
||||
use bevy_reflect::{FromReflect, FromType, Reflect, TypeRegistry};
|
||||
use bevy_reflect::{FromReflect, FromType, PartialReflect, Reflect, TypePath, TypeRegistry};
|
||||
|
||||
use super::from_reflect_with_fallback;
|
||||
|
||||
|
@ -43,11 +43,11 @@ pub struct ReflectResource(ReflectResourceFns);
|
|||
#[derive(Clone)]
|
||||
pub struct ReflectResourceFns {
|
||||
/// Function pointer implementing [`ReflectResource::insert()`].
|
||||
pub insert: fn(&mut World, &dyn Reflect, &TypeRegistry),
|
||||
pub insert: fn(&mut World, &dyn PartialReflect, &TypeRegistry),
|
||||
/// Function pointer implementing [`ReflectResource::apply()`].
|
||||
pub apply: fn(&mut World, &dyn Reflect),
|
||||
pub apply: fn(&mut World, &dyn PartialReflect),
|
||||
/// Function pointer implementing [`ReflectResource::apply_or_insert()`].
|
||||
pub apply_or_insert: fn(&mut World, &dyn Reflect, &TypeRegistry),
|
||||
pub apply_or_insert: fn(&mut World, &dyn PartialReflect, &TypeRegistry),
|
||||
/// Function pointer implementing [`ReflectResource::remove()`].
|
||||
pub remove: fn(&mut World),
|
||||
/// Function pointer implementing [`ReflectResource::reflect()`].
|
||||
|
@ -67,14 +67,19 @@ impl ReflectResourceFns {
|
|||
///
|
||||
/// This is useful if you want to start with the default implementation before overriding some
|
||||
/// of the functions to create a custom implementation.
|
||||
pub fn new<T: Resource + FromReflect>() -> Self {
|
||||
pub fn new<T: Resource + FromReflect + TypePath>() -> Self {
|
||||
<ReflectResource as FromType<T>>::from_type().0
|
||||
}
|
||||
}
|
||||
|
||||
impl ReflectResource {
|
||||
/// Insert a reflected [`Resource`] into the world like [`insert()`](World::insert_resource).
|
||||
pub fn insert(&self, world: &mut World, resource: &dyn Reflect, registry: &TypeRegistry) {
|
||||
pub fn insert(
|
||||
&self,
|
||||
world: &mut World,
|
||||
resource: &dyn PartialReflect,
|
||||
registry: &TypeRegistry,
|
||||
) {
|
||||
(self.0.insert)(world, resource, registry);
|
||||
}
|
||||
|
||||
|
@ -83,7 +88,7 @@ impl ReflectResource {
|
|||
/// # Panics
|
||||
///
|
||||
/// Panics if there is no [`Resource`] of the given type.
|
||||
pub fn apply(&self, world: &mut World, resource: &dyn Reflect) {
|
||||
pub fn apply(&self, world: &mut World, resource: &dyn PartialReflect) {
|
||||
(self.0.apply)(world, resource);
|
||||
}
|
||||
|
||||
|
@ -91,7 +96,7 @@ impl ReflectResource {
|
|||
pub fn apply_or_insert(
|
||||
&self,
|
||||
world: &mut World,
|
||||
resource: &dyn Reflect,
|
||||
resource: &dyn PartialReflect,
|
||||
registry: &TypeRegistry,
|
||||
) {
|
||||
(self.0.apply_or_insert)(world, resource, registry);
|
||||
|
@ -176,7 +181,7 @@ impl ReflectResource {
|
|||
}
|
||||
}
|
||||
|
||||
impl<R: Resource + Reflect> FromType<R> for ReflectResource {
|
||||
impl<R: Resource + FromReflect + TypePath> FromType<R> for ReflectResource {
|
||||
fn from_type() -> Self {
|
||||
ReflectResource(ReflectResourceFns {
|
||||
insert: |world, reflected_resource, registry| {
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
This crate enables you to dynamically interact with Rust types:
|
||||
|
||||
* Derive the Reflect traits
|
||||
* Derive the `Reflect` traits
|
||||
* Interact with fields using their names (for named structs) or indices (for tuple structs)
|
||||
* "Patch" your types with new values
|
||||
* Look up nested fields using "path strings"
|
||||
|
@ -18,10 +18,10 @@ This crate enables you to dynamically interact with Rust types:
|
|||
|
||||
## Features
|
||||
|
||||
### Derive the Reflect traits
|
||||
### Derive the `Reflect` traits
|
||||
|
||||
```rust ignore
|
||||
// this will automatically implement the Reflect trait and the Struct trait (because the type is a struct)
|
||||
// this will automatically implement the `Reflect` trait and the `Struct` trait (because the type is a struct)
|
||||
#[derive(Reflect)]
|
||||
struct Foo {
|
||||
a: u32,
|
||||
|
@ -30,7 +30,7 @@ struct Foo {
|
|||
d: Vec<Baz>,
|
||||
}
|
||||
|
||||
// this will automatically implement the Reflect trait and the TupleStruct trait (because the type is a tuple struct)
|
||||
// this will automatically implement the `Reflect` trait and the `TupleStruct` trait (because the type is a tuple struct)
|
||||
#[derive(Reflect)]
|
||||
struct Bar(String);
|
||||
|
||||
|
|
|
@ -17,5 +17,5 @@ fn main() {
|
|||
|
||||
// foo doesn't implement Reflect because NoReflect doesn't implement Reflect
|
||||
foo.get_field::<NoReflect>("a").unwrap();
|
||||
//~^ ERROR: `NoReflect` can not be reflected
|
||||
//~^ ERROR: `NoReflect` does not implement `Reflect` so cannot be fully reflected
|
||||
}
|
||||
|
|
|
@ -444,7 +444,7 @@ impl ContainerAttributes {
|
|||
&self.type_path_attrs
|
||||
}
|
||||
|
||||
/// Returns the implementation of `Reflect::reflect_hash` as a `TokenStream`.
|
||||
/// Returns the implementation of `PartialReflect::reflect_hash` as a `TokenStream`.
|
||||
///
|
||||
/// If `Hash` was not registered, returns `None`.
|
||||
pub fn get_hash_impl(&self, bevy_reflect_path: &Path) -> Option<proc_macro2::TokenStream> {
|
||||
|
@ -467,7 +467,7 @@ impl ContainerAttributes {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns the implementation of `Reflect::reflect_partial_eq` as a `TokenStream`.
|
||||
/// Returns the implementation of `PartialReflect::reflect_partial_eq` as a `TokenStream`.
|
||||
///
|
||||
/// If `PartialEq` was not registered, returns `None`.
|
||||
pub fn get_partial_eq_impl(
|
||||
|
@ -476,9 +476,9 @@ impl ContainerAttributes {
|
|||
) -> Option<proc_macro2::TokenStream> {
|
||||
match &self.partial_eq {
|
||||
&TraitImpl::Implemented(span) => Some(quote_spanned! {span=>
|
||||
fn reflect_partial_eq(&self, value: &dyn #bevy_reflect_path::Reflect) -> #FQOption<bool> {
|
||||
let value = <dyn #bevy_reflect_path::Reflect>::as_any(value);
|
||||
if let #FQOption::Some(value) = <dyn #FQAny>::downcast_ref::<Self>(value) {
|
||||
fn reflect_partial_eq(&self, value: &dyn #bevy_reflect_path::PartialReflect) -> #FQOption<bool> {
|
||||
let value = <dyn #bevy_reflect_path::PartialReflect>::try_downcast_ref::<Self>(value);
|
||||
if let #FQOption::Some(value) = value {
|
||||
#FQOption::Some(::core::cmp::PartialEq::eq(self, value))
|
||||
} else {
|
||||
#FQOption::Some(false)
|
||||
|
@ -486,7 +486,7 @@ impl ContainerAttributes {
|
|||
}
|
||||
}),
|
||||
&TraitImpl::Custom(ref impl_fn, span) => Some(quote_spanned! {span=>
|
||||
fn reflect_partial_eq(&self, value: &dyn #bevy_reflect_path::Reflect) -> #FQOption<bool> {
|
||||
fn reflect_partial_eq(&self, value: &dyn #bevy_reflect_path::PartialReflect) -> #FQOption<bool> {
|
||||
#FQOption::Some(#impl_fn(self, value))
|
||||
}
|
||||
}),
|
||||
|
@ -494,7 +494,7 @@ impl ContainerAttributes {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns the implementation of `Reflect::debug` as a `TokenStream`.
|
||||
/// Returns the implementation of `PartialReflect::debug` as a `TokenStream`.
|
||||
///
|
||||
/// If `Debug` was not registered, returns `None`.
|
||||
pub fn get_debug_impl(&self) -> Option<proc_macro2::TokenStream> {
|
||||
|
|
|
@ -209,7 +209,7 @@ impl<'a> VariantBuilder for FromReflectVariantBuilder<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Generates the enum variant output data needed to build the `Reflect::try_apply` implementation.
|
||||
/// Generates the enum variant output data needed to build the `PartialReflect::try_apply` implementation.
|
||||
pub(crate) struct TryApplyVariantBuilder<'a> {
|
||||
reflect_enum: &'a ReflectEnum<'a>,
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ use crate::enum_utility::{EnumVariantOutputData, FromReflectVariantBuilder, Vari
|
|||
use crate::field_attributes::DefaultBehavior;
|
||||
use crate::utility::{ident_or_index, WhereClauseOptions};
|
||||
use crate::{ReflectMeta, ReflectStruct};
|
||||
use bevy_macro_utils::fq_std::{FQAny, FQClone, FQDefault, FQOption};
|
||||
use bevy_macro_utils::fq_std::{FQClone, FQDefault, FQOption};
|
||||
use proc_macro2::Span;
|
||||
use quote::{quote, ToTokens};
|
||||
use syn::{Field, Ident, Lit, LitInt, LitStr, Member};
|
||||
|
@ -26,8 +26,12 @@ pub(crate) fn impl_value(meta: &ReflectMeta) -> proc_macro2::TokenStream {
|
|||
let where_from_reflect_clause = WhereClauseOptions::new(meta).extend_where_clause(where_clause);
|
||||
quote! {
|
||||
impl #impl_generics #bevy_reflect_path::FromReflect for #type_path #ty_generics #where_from_reflect_clause {
|
||||
fn from_reflect(reflect: &dyn #bevy_reflect_path::Reflect) -> #FQOption<Self> {
|
||||
#FQOption::Some(#FQClone::clone(<dyn #FQAny>::downcast_ref::<#type_path #ty_generics>(<dyn #bevy_reflect_path::Reflect>::as_any(reflect))?))
|
||||
fn from_reflect(reflect: &dyn #bevy_reflect_path::PartialReflect) -> #FQOption<Self> {
|
||||
#FQOption::Some(
|
||||
#FQClone::clone(
|
||||
<dyn #bevy_reflect_path::PartialReflect>::try_downcast_ref::<#type_path #ty_generics>(reflect)?
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -57,8 +61,10 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> proc_macro2::TokenStream
|
|||
|
||||
quote! {
|
||||
impl #impl_generics #bevy_reflect_path::FromReflect for #enum_path #ty_generics #where_from_reflect_clause {
|
||||
fn from_reflect(#ref_value: &dyn #bevy_reflect_path::Reflect) -> #FQOption<Self> {
|
||||
if let #bevy_reflect_path::ReflectRef::Enum(#ref_value) = #bevy_reflect_path::Reflect::reflect_ref(#ref_value) {
|
||||
fn from_reflect(#ref_value: &dyn #bevy_reflect_path::PartialReflect) -> #FQOption<Self> {
|
||||
if let #bevy_reflect_path::ReflectRef::Enum(#ref_value) =
|
||||
#bevy_reflect_path::PartialReflect::reflect_ref(#ref_value)
|
||||
{
|
||||
match #bevy_reflect_path::Enum::variant_name(#ref_value) {
|
||||
#(#variant_names => #fqoption::Some(#variant_constructors),)*
|
||||
name => panic!("variant with name `{}` does not exist on enum `{}`", name, <Self as #bevy_reflect_path::TypePath>::type_path()),
|
||||
|
@ -138,8 +144,10 @@ fn impl_struct_internal(
|
|||
|
||||
quote! {
|
||||
impl #impl_generics #bevy_reflect_path::FromReflect for #struct_path #ty_generics #where_from_reflect_clause {
|
||||
fn from_reflect(reflect: &dyn #bevy_reflect_path::Reflect) -> #FQOption<Self> {
|
||||
if let #bevy_reflect_path::ReflectRef::#ref_struct_type(#ref_struct) = #bevy_reflect_path::Reflect::reflect_ref(reflect) {
|
||||
fn from_reflect(reflect: &dyn #bevy_reflect_path::PartialReflect) -> #FQOption<Self> {
|
||||
if let #bevy_reflect_path::ReflectRef::#ref_struct_type(#ref_struct)
|
||||
= #bevy_reflect_path::PartialReflect::reflect_ref(reflect)
|
||||
{
|
||||
#constructor
|
||||
} else {
|
||||
#FQOption::None
|
||||
|
|
135
crates/bevy_reflect/derive/src/impls/common.rs
Normal file
135
crates/bevy_reflect/derive/src/impls/common.rs
Normal file
|
@ -0,0 +1,135 @@
|
|||
use bevy_macro_utils::fq_std::{FQAny, FQBox, FQOption, FQResult};
|
||||
|
||||
use quote::quote;
|
||||
|
||||
use crate::{derive_data::ReflectMeta, utility::WhereClauseOptions};
|
||||
|
||||
pub fn impl_full_reflect(
|
||||
meta: &ReflectMeta,
|
||||
where_clause_options: &WhereClauseOptions,
|
||||
) -> proc_macro2::TokenStream {
|
||||
let bevy_reflect_path = meta.bevy_reflect_path();
|
||||
let type_path = meta.type_path();
|
||||
|
||||
let (impl_generics, ty_generics, where_clause) = type_path.generics().split_for_impl();
|
||||
let where_reflect_clause = where_clause_options.extend_where_clause(where_clause);
|
||||
|
||||
quote! {
|
||||
impl #impl_generics #bevy_reflect_path::Reflect for #type_path #ty_generics #where_reflect_clause {
|
||||
#[inline]
|
||||
fn into_any(self: #FQBox<Self>) -> #FQBox<dyn #FQAny> {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_any(&self) -> &dyn #FQAny {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_any_mut(&mut self) -> &mut dyn #FQAny {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn into_reflect(self: #FQBox<Self>) -> #FQBox<dyn #bevy_reflect_path::Reflect> {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_reflect(&self) -> &dyn #bevy_reflect_path::Reflect {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_reflect_mut(&mut self) -> &mut dyn #bevy_reflect_path::Reflect {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set(
|
||||
&mut self,
|
||||
value: #FQBox<dyn #bevy_reflect_path::Reflect>
|
||||
) -> #FQResult<(), #FQBox<dyn #bevy_reflect_path::Reflect>> {
|
||||
*self = <dyn #bevy_reflect_path::Reflect>::take(value)?;
|
||||
#FQResult::Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn common_partial_reflect_methods(
|
||||
meta: &ReflectMeta,
|
||||
default_partial_eq_delegate: impl FnOnce() -> Option<proc_macro2::TokenStream>,
|
||||
default_hash_delegate: impl FnOnce() -> Option<proc_macro2::TokenStream>,
|
||||
) -> proc_macro2::TokenStream {
|
||||
let bevy_reflect_path = meta.bevy_reflect_path();
|
||||
|
||||
let debug_fn = meta.attrs().get_debug_impl();
|
||||
let partial_eq_fn = meta
|
||||
.attrs()
|
||||
.get_partial_eq_impl(bevy_reflect_path)
|
||||
.or_else(move || {
|
||||
let default_delegate = default_partial_eq_delegate();
|
||||
default_delegate.map(|func| {
|
||||
quote! {
|
||||
fn reflect_partial_eq(&self, value: &dyn #bevy_reflect_path::PartialReflect) -> #FQOption<bool> {
|
||||
(#func)(self, value)
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
let hash_fn = meta
|
||||
.attrs()
|
||||
.get_hash_impl(bevy_reflect_path)
|
||||
.or_else(move || {
|
||||
let default_delegate = default_hash_delegate();
|
||||
default_delegate.map(|func| {
|
||||
quote! {
|
||||
fn reflect_hash(&self) -> #FQOption<u64> {
|
||||
(#func)(self)
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
quote! {
|
||||
#[inline]
|
||||
fn try_into_reflect(
|
||||
self: #FQBox<Self>
|
||||
) -> #FQResult<#FQBox<dyn #bevy_reflect_path::Reflect>, #FQBox<dyn #bevy_reflect_path::PartialReflect>> {
|
||||
#FQResult::Ok(self)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn try_as_reflect(&self) -> #FQOption<&dyn #bevy_reflect_path::Reflect> {
|
||||
#FQOption::Some(self)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn try_as_reflect_mut(&mut self) -> #FQOption<&mut dyn #bevy_reflect_path::Reflect> {
|
||||
#FQOption::Some(self)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn into_partial_reflect(self: #FQBox<Self>) -> #FQBox<dyn #bevy_reflect_path::PartialReflect> {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_partial_reflect(&self) -> &dyn #bevy_reflect_path::PartialReflect {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_partial_reflect_mut(&mut self) -> &mut dyn #bevy_reflect_path::PartialReflect {
|
||||
self
|
||||
}
|
||||
|
||||
#hash_fn
|
||||
|
||||
#partial_eq_fn
|
||||
|
||||
#debug_fn
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
use crate::derive_data::{EnumVariantFields, ReflectEnum, StructField};
|
||||
use crate::enum_utility::{EnumVariantOutputData, TryApplyVariantBuilder, VariantBuilder};
|
||||
use crate::impls::{impl_type_path, impl_typed};
|
||||
use bevy_macro_utils::fq_std::{FQAny, FQBox, FQOption, FQResult};
|
||||
use crate::impls::{common_partial_reflect_methods, impl_full_reflect, impl_type_path, impl_typed};
|
||||
use bevy_macro_utils::fq_std::{FQBox, FQOption, FQResult};
|
||||
use proc_macro2::{Ident, Span};
|
||||
use quote::quote;
|
||||
use syn::Fields;
|
||||
|
@ -33,30 +33,6 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> proc_macro2::TokenStream
|
|||
..
|
||||
} = TryApplyVariantBuilder::new(reflect_enum).build(&ref_value);
|
||||
|
||||
let hash_fn = reflect_enum
|
||||
.meta()
|
||||
.attrs()
|
||||
.get_hash_impl(bevy_reflect_path)
|
||||
.unwrap_or_else(|| {
|
||||
quote! {
|
||||
fn reflect_hash(&self) -> #FQOption<u64> {
|
||||
#bevy_reflect_path::enum_hash(self)
|
||||
}
|
||||
}
|
||||
});
|
||||
let debug_fn = reflect_enum.meta().attrs().get_debug_impl();
|
||||
let partial_eq_fn = reflect_enum
|
||||
.meta()
|
||||
.attrs()
|
||||
.get_partial_eq_impl(bevy_reflect_path)
|
||||
.unwrap_or_else(|| {
|
||||
quote! {
|
||||
fn reflect_partial_eq(&self, value: &dyn #bevy_reflect_path::Reflect) -> #FQOption<bool> {
|
||||
#bevy_reflect_path::enum_partial_eq(self, value)
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let typed_impl = impl_typed(
|
||||
reflect_enum.meta(),
|
||||
&where_clause_options,
|
||||
|
@ -64,6 +40,12 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> proc_macro2::TokenStream
|
|||
);
|
||||
|
||||
let type_path_impl = impl_type_path(reflect_enum.meta());
|
||||
let full_reflect_impl = impl_full_reflect(reflect_enum.meta(), &where_clause_options);
|
||||
let common_methods = common_partial_reflect_methods(
|
||||
reflect_enum.meta(),
|
||||
|| Some(quote!(#bevy_reflect_path::enum_partial_eq)),
|
||||
|| Some(quote!(#bevy_reflect_path::enum_hash)),
|
||||
);
|
||||
|
||||
#[cfg(not(feature = "functions"))]
|
||||
let function_impls = None::<proc_macro2::TokenStream>;
|
||||
|
@ -85,31 +67,33 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> proc_macro2::TokenStream
|
|||
|
||||
#type_path_impl
|
||||
|
||||
#full_reflect_impl
|
||||
|
||||
#function_impls
|
||||
|
||||
impl #impl_generics #bevy_reflect_path::Enum for #enum_path #ty_generics #where_reflect_clause {
|
||||
fn field(&self, #ref_name: &str) -> #FQOption<&dyn #bevy_reflect_path::Reflect> {
|
||||
fn field(&self, #ref_name: &str) -> #FQOption<&dyn #bevy_reflect_path::PartialReflect> {
|
||||
match self {
|
||||
#(#enum_field,)*
|
||||
_ => #FQOption::None,
|
||||
}
|
||||
}
|
||||
|
||||
fn field_at(&self, #ref_index: usize) -> #FQOption<&dyn #bevy_reflect_path::Reflect> {
|
||||
fn field_at(&self, #ref_index: usize) -> #FQOption<&dyn #bevy_reflect_path::PartialReflect> {
|
||||
match self {
|
||||
#(#enum_field_at,)*
|
||||
_ => #FQOption::None,
|
||||
}
|
||||
}
|
||||
|
||||
fn field_mut(&mut self, #ref_name: &str) -> #FQOption<&mut dyn #bevy_reflect_path::Reflect> {
|
||||
fn field_mut(&mut self, #ref_name: &str) -> #FQOption<&mut dyn #bevy_reflect_path::PartialReflect> {
|
||||
match self {
|
||||
#(#enum_field,)*
|
||||
_ => #FQOption::None,
|
||||
}
|
||||
}
|
||||
|
||||
fn field_at_mut(&mut self, #ref_index: usize) -> #FQOption<&mut dyn #bevy_reflect_path::Reflect> {
|
||||
fn field_at_mut(&mut self, #ref_index: usize) -> #FQOption<&mut dyn #bevy_reflect_path::PartialReflect> {
|
||||
match self {
|
||||
#(#enum_field_at,)*
|
||||
_ => #FQOption::None,
|
||||
|
@ -171,56 +155,24 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> proc_macro2::TokenStream
|
|||
}
|
||||
}
|
||||
|
||||
impl #impl_generics #bevy_reflect_path::Reflect for #enum_path #ty_generics #where_reflect_clause {
|
||||
impl #impl_generics #bevy_reflect_path::PartialReflect for #enum_path #ty_generics #where_reflect_clause {
|
||||
#[inline]
|
||||
fn get_represented_type_info(&self) -> #FQOption<&'static #bevy_reflect_path::TypeInfo> {
|
||||
#FQOption::Some(<Self as #bevy_reflect_path::Typed>::type_info())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn into_any(self: #FQBox<Self>) -> #FQBox<dyn #FQAny> {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_any(&self) -> &dyn #FQAny {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_any_mut(&mut self) -> &mut dyn #FQAny {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn into_reflect(self: #FQBox<Self>) -> #FQBox<dyn #bevy_reflect_path::Reflect> {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_reflect(&self) -> &dyn #bevy_reflect_path::Reflect {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_reflect_mut(&mut self) -> &mut dyn #bevy_reflect_path::Reflect {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn clone_value(&self) -> #FQBox<dyn #bevy_reflect_path::Reflect> {
|
||||
fn clone_value(&self) -> #FQBox<dyn #bevy_reflect_path::PartialReflect> {
|
||||
#FQBox::new(#bevy_reflect_path::Enum::clone_dynamic(self))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set(&mut self, #ref_value: #FQBox<dyn #bevy_reflect_path::Reflect>) -> #FQResult<(), #FQBox<dyn #bevy_reflect_path::Reflect>> {
|
||||
*self = <dyn #bevy_reflect_path::Reflect>::take(#ref_value)?;
|
||||
#FQResult::Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn try_apply(&mut self, #ref_value: &dyn #bevy_reflect_path::Reflect) -> #FQResult<(), #bevy_reflect_path::ApplyError> {
|
||||
if let #bevy_reflect_path::ReflectRef::Enum(#ref_value) = #bevy_reflect_path::Reflect::reflect_ref(#ref_value) {
|
||||
fn try_apply(
|
||||
&mut self,
|
||||
#ref_value: &dyn #bevy_reflect_path::PartialReflect
|
||||
) -> #FQResult<(), #bevy_reflect_path::ApplyError> {
|
||||
if let #bevy_reflect_path::ReflectRef::Enum(#ref_value) =
|
||||
#bevy_reflect_path::PartialReflect::reflect_ref(#ref_value) {
|
||||
if #bevy_reflect_path::Enum::variant_name(self) == #bevy_reflect_path::Enum::variant_name(#ref_value) {
|
||||
// Same variant -> just update fields
|
||||
match #bevy_reflect_path::Enum::variant_type(#ref_value) {
|
||||
|
@ -228,14 +180,14 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> proc_macro2::TokenStream
|
|||
for field in #bevy_reflect_path::Enum::iter_fields(#ref_value) {
|
||||
let name = field.name().unwrap();
|
||||
if let #FQOption::Some(v) = #bevy_reflect_path::Enum::field_mut(self, name) {
|
||||
#bevy_reflect_path::Reflect::try_apply(v, field.value())?;
|
||||
#bevy_reflect_path::PartialReflect::try_apply(v, field.value())?;
|
||||
}
|
||||
}
|
||||
}
|
||||
#bevy_reflect_path::VariantType::Tuple => {
|
||||
for (index, field) in ::core::iter::Iterator::enumerate(#bevy_reflect_path::Enum::iter_fields(#ref_value)) {
|
||||
if let #FQOption::Some(v) = #bevy_reflect_path::Enum::field_at_mut(self, index) {
|
||||
#bevy_reflect_path::Reflect::try_apply(v, field.value())?;
|
||||
#bevy_reflect_path::PartialReflect::try_apply(v, field.value())?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -260,7 +212,7 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> proc_macro2::TokenStream
|
|||
} else {
|
||||
return #FQResult::Err(
|
||||
#bevy_reflect_path::ApplyError::MismatchedKinds {
|
||||
from_kind: #bevy_reflect_path::Reflect::reflect_kind(#ref_value),
|
||||
from_kind: #bevy_reflect_path::PartialReflect::reflect_kind(#ref_value),
|
||||
to_kind: #bevy_reflect_path::ReflectKind::Enum,
|
||||
}
|
||||
);
|
||||
|
@ -284,11 +236,7 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> proc_macro2::TokenStream
|
|||
#bevy_reflect_path::ReflectOwned::Enum(self)
|
||||
}
|
||||
|
||||
#hash_fn
|
||||
|
||||
#partial_eq_fn
|
||||
|
||||
#debug_fn
|
||||
#common_methods
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
mod common;
|
||||
mod enums;
|
||||
#[cfg(feature = "functions")]
|
||||
mod func;
|
||||
|
@ -6,6 +7,7 @@ mod tuple_structs;
|
|||
mod typed;
|
||||
mod values;
|
||||
|
||||
pub(crate) use common::{common_partial_reflect_methods, impl_full_reflect};
|
||||
pub(crate) use enums::impl_enum;
|
||||
#[cfg(feature = "functions")]
|
||||
pub(crate) use func::impl_function_traits;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::impls::{impl_type_path, impl_typed};
|
||||
use crate::impls::{common_partial_reflect_methods, impl_full_reflect, impl_type_path, impl_typed};
|
||||
use crate::utility::ident_or_index;
|
||||
use crate::ReflectStruct;
|
||||
use bevy_macro_utils::fq_std::{FQAny, FQBox, FQDefault, FQOption, FQResult};
|
||||
use bevy_macro_utils::fq_std::{FQBox, FQDefault, FQOption, FQResult};
|
||||
use quote::{quote, ToTokens};
|
||||
|
||||
/// Implements `Struct`, `GetTypeRegistration`, and `Reflect` for the given derive data.
|
||||
|
@ -29,22 +29,6 @@ pub(crate) fn impl_struct(reflect_struct: &ReflectStruct) -> proc_macro2::TokenS
|
|||
let field_count = field_idents.len();
|
||||
let field_indices = (0..field_count).collect::<Vec<usize>>();
|
||||
|
||||
let hash_fn = reflect_struct
|
||||
.meta()
|
||||
.attrs()
|
||||
.get_hash_impl(bevy_reflect_path);
|
||||
let debug_fn = reflect_struct.meta().attrs().get_debug_impl();
|
||||
let partial_eq_fn = reflect_struct.meta()
|
||||
.attrs()
|
||||
.get_partial_eq_impl(bevy_reflect_path)
|
||||
.unwrap_or_else(|| {
|
||||
quote! {
|
||||
fn reflect_partial_eq(&self, value: &dyn #bevy_reflect_path::Reflect) -> #FQOption<bool> {
|
||||
#bevy_reflect_path::struct_partial_eq(self, value)
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let where_clause_options = reflect_struct.where_clause_options();
|
||||
let typed_impl = impl_typed(
|
||||
reflect_struct.meta(),
|
||||
|
@ -53,6 +37,12 @@ pub(crate) fn impl_struct(reflect_struct: &ReflectStruct) -> proc_macro2::TokenS
|
|||
);
|
||||
|
||||
let type_path_impl = impl_type_path(reflect_struct.meta());
|
||||
let full_reflect_impl = impl_full_reflect(reflect_struct.meta(), &where_clause_options);
|
||||
let common_methods = common_partial_reflect_methods(
|
||||
reflect_struct.meta(),
|
||||
|| Some(quote!(#bevy_reflect_path::struct_partial_eq)),
|
||||
|| None,
|
||||
);
|
||||
|
||||
#[cfg(not(feature = "functions"))]
|
||||
let function_impls = None::<proc_macro2::TokenStream>;
|
||||
|
@ -77,31 +67,33 @@ pub(crate) fn impl_struct(reflect_struct: &ReflectStruct) -> proc_macro2::TokenS
|
|||
|
||||
#type_path_impl
|
||||
|
||||
#full_reflect_impl
|
||||
|
||||
#function_impls
|
||||
|
||||
impl #impl_generics #bevy_reflect_path::Struct for #struct_path #ty_generics #where_reflect_clause {
|
||||
fn field(&self, name: &str) -> #FQOption<&dyn #bevy_reflect_path::Reflect> {
|
||||
fn field(&self, name: &str) -> #FQOption<&dyn #bevy_reflect_path::PartialReflect> {
|
||||
match name {
|
||||
#(#field_names => #fqoption::Some(&self.#field_idents),)*
|
||||
_ => #FQOption::None,
|
||||
}
|
||||
}
|
||||
|
||||
fn field_mut(&mut self, name: &str) -> #FQOption<&mut dyn #bevy_reflect_path::Reflect> {
|
||||
fn field_mut(&mut self, name: &str) -> #FQOption<&mut dyn #bevy_reflect_path::PartialReflect> {
|
||||
match name {
|
||||
#(#field_names => #fqoption::Some(&mut self.#field_idents),)*
|
||||
_ => #FQOption::None,
|
||||
}
|
||||
}
|
||||
|
||||
fn field_at(&self, index: usize) -> #FQOption<&dyn #bevy_reflect_path::Reflect> {
|
||||
fn field_at(&self, index: usize) -> #FQOption<&dyn #bevy_reflect_path::PartialReflect> {
|
||||
match index {
|
||||
#(#field_indices => #fqoption::Some(&self.#field_idents),)*
|
||||
_ => #FQOption::None,
|
||||
}
|
||||
}
|
||||
|
||||
fn field_at_mut(&mut self, index: usize) -> #FQOption<&mut dyn #bevy_reflect_path::Reflect> {
|
||||
fn field_at_mut(&mut self, index: usize) -> #FQOption<&mut dyn #bevy_reflect_path::PartialReflect> {
|
||||
match index {
|
||||
#(#field_indices => #fqoption::Some(&mut self.#field_idents),)*
|
||||
_ => #FQOption::None,
|
||||
|
@ -125,72 +117,40 @@ pub(crate) fn impl_struct(reflect_struct: &ReflectStruct) -> proc_macro2::TokenS
|
|||
|
||||
fn clone_dynamic(&self) -> #bevy_reflect_path::DynamicStruct {
|
||||
let mut dynamic: #bevy_reflect_path::DynamicStruct = #FQDefault::default();
|
||||
dynamic.set_represented_type(#bevy_reflect_path::Reflect::get_represented_type_info(self));
|
||||
#(dynamic.insert_boxed(#field_names, #bevy_reflect_path::Reflect::clone_value(&self.#field_idents));)*
|
||||
dynamic.set_represented_type(#bevy_reflect_path::PartialReflect::get_represented_type_info(self));
|
||||
#(dynamic.insert_boxed(#field_names, #bevy_reflect_path::PartialReflect::clone_value(&self.#field_idents));)*
|
||||
dynamic
|
||||
}
|
||||
}
|
||||
|
||||
impl #impl_generics #bevy_reflect_path::Reflect for #struct_path #ty_generics #where_reflect_clause {
|
||||
impl #impl_generics #bevy_reflect_path::PartialReflect for #struct_path #ty_generics #where_reflect_clause {
|
||||
#[inline]
|
||||
fn get_represented_type_info(&self) -> #FQOption<&'static #bevy_reflect_path::TypeInfo> {
|
||||
#FQOption::Some(<Self as #bevy_reflect_path::Typed>::type_info())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn into_any(self: #FQBox<Self>) -> #FQBox<dyn #FQAny> {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_any(&self) -> &dyn #FQAny {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_any_mut(&mut self) -> &mut dyn #FQAny {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn into_reflect(self: #FQBox<Self>) -> #FQBox<dyn #bevy_reflect_path::Reflect> {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_reflect(&self) -> &dyn #bevy_reflect_path::Reflect {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_reflect_mut(&mut self) -> &mut dyn #bevy_reflect_path::Reflect {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn clone_value(&self) -> #FQBox<dyn #bevy_reflect_path::Reflect> {
|
||||
fn clone_value(&self) -> #FQBox<dyn #bevy_reflect_path::PartialReflect> {
|
||||
#FQBox::new(#bevy_reflect_path::Struct::clone_dynamic(self))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set(&mut self, value: #FQBox<dyn #bevy_reflect_path::Reflect>) -> #FQResult<(), #FQBox<dyn #bevy_reflect_path::Reflect>> {
|
||||
*self = <dyn #bevy_reflect_path::Reflect>::take(value)?;
|
||||
#FQResult::Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn try_apply(&mut self, value: &dyn #bevy_reflect_path::Reflect) -> #FQResult<(), #bevy_reflect_path::ApplyError> {
|
||||
if let #bevy_reflect_path::ReflectRef::Struct(struct_value) = #bevy_reflect_path::Reflect::reflect_ref(value) {
|
||||
fn try_apply(
|
||||
&mut self,
|
||||
value: &dyn #bevy_reflect_path::PartialReflect
|
||||
) -> #FQResult<(), #bevy_reflect_path::ApplyError> {
|
||||
if let #bevy_reflect_path::ReflectRef::Struct(struct_value)
|
||||
= #bevy_reflect_path::PartialReflect::reflect_ref(value) {
|
||||
for (i, value) in ::core::iter::Iterator::enumerate(#bevy_reflect_path::Struct::iter_fields(struct_value)) {
|
||||
let name = #bevy_reflect_path::Struct::name_at(struct_value, i).unwrap();
|
||||
if let #FQOption::Some(v) = #bevy_reflect_path::Struct::field_mut(self, name) {
|
||||
#bevy_reflect_path::Reflect::try_apply(v, value)?;
|
||||
#bevy_reflect_path::PartialReflect::try_apply(v, value)?;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return #FQResult::Err(
|
||||
#bevy_reflect_path::ApplyError::MismatchedKinds {
|
||||
from_kind: #bevy_reflect_path::Reflect::reflect_kind(value),
|
||||
from_kind: #bevy_reflect_path::PartialReflect::reflect_kind(value),
|
||||
to_kind: #bevy_reflect_path::ReflectKind::Struct
|
||||
}
|
||||
);
|
||||
|
@ -214,11 +174,7 @@ pub(crate) fn impl_struct(reflect_struct: &ReflectStruct) -> proc_macro2::TokenS
|
|||
#bevy_reflect_path::ReflectOwned::Struct(self)
|
||||
}
|
||||
|
||||
#hash_fn
|
||||
|
||||
#partial_eq_fn
|
||||
|
||||
#debug_fn
|
||||
#common_methods
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::impls::{impl_type_path, impl_typed};
|
||||
use crate::impls::{common_partial_reflect_methods, impl_full_reflect, impl_type_path, impl_typed};
|
||||
use crate::ReflectStruct;
|
||||
use bevy_macro_utils::fq_std::{FQAny, FQBox, FQDefault, FQOption, FQResult};
|
||||
use bevy_macro_utils::fq_std::{FQBox, FQDefault, FQOption, FQResult};
|
||||
use quote::{quote, ToTokens};
|
||||
use syn::{Index, Member};
|
||||
|
||||
|
@ -21,23 +21,6 @@ pub(crate) fn impl_tuple_struct(reflect_struct: &ReflectStruct) -> proc_macro2::
|
|||
let where_clause_options = reflect_struct.where_clause_options();
|
||||
let get_type_registration_impl = reflect_struct.get_type_registration(&where_clause_options);
|
||||
|
||||
let hash_fn = reflect_struct
|
||||
.meta()
|
||||
.attrs()
|
||||
.get_hash_impl(bevy_reflect_path);
|
||||
let debug_fn = reflect_struct.meta().attrs().get_debug_impl();
|
||||
let partial_eq_fn = reflect_struct
|
||||
.meta()
|
||||
.attrs()
|
||||
.get_partial_eq_impl(bevy_reflect_path)
|
||||
.unwrap_or_else(|| {
|
||||
quote! {
|
||||
fn reflect_partial_eq(&self, value: &dyn #bevy_reflect_path::Reflect) -> #FQOption<bool> {
|
||||
#bevy_reflect_path::tuple_struct_partial_eq(self, value)
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let typed_impl = impl_typed(
|
||||
reflect_struct.meta(),
|
||||
&where_clause_options,
|
||||
|
@ -45,6 +28,12 @@ pub(crate) fn impl_tuple_struct(reflect_struct: &ReflectStruct) -> proc_macro2::
|
|||
);
|
||||
|
||||
let type_path_impl = impl_type_path(reflect_struct.meta());
|
||||
let full_reflect_impl = impl_full_reflect(reflect_struct.meta(), &where_clause_options);
|
||||
let common_methods = common_partial_reflect_methods(
|
||||
reflect_struct.meta(),
|
||||
|| Some(quote!(#bevy_reflect_path::tuple_struct_partial_eq)),
|
||||
|| None,
|
||||
);
|
||||
|
||||
#[cfg(not(feature = "functions"))]
|
||||
let function_impls = None::<proc_macro2::TokenStream>;
|
||||
|
@ -67,17 +56,19 @@ pub(crate) fn impl_tuple_struct(reflect_struct: &ReflectStruct) -> proc_macro2::
|
|||
|
||||
#type_path_impl
|
||||
|
||||
#full_reflect_impl
|
||||
|
||||
#function_impls
|
||||
|
||||
impl #impl_generics #bevy_reflect_path::TupleStruct for #struct_path #ty_generics #where_reflect_clause {
|
||||
fn field(&self, index: usize) -> #FQOption<&dyn #bevy_reflect_path::Reflect> {
|
||||
fn field(&self, index: usize) -> #FQOption<&dyn #bevy_reflect_path::PartialReflect> {
|
||||
match index {
|
||||
#(#field_indices => #fqoption::Some(&self.#field_idents),)*
|
||||
_ => #FQOption::None,
|
||||
}
|
||||
}
|
||||
|
||||
fn field_mut(&mut self, index: usize) -> #FQOption<&mut dyn #bevy_reflect_path::Reflect> {
|
||||
fn field_mut(&mut self, index: usize) -> #FQOption<&mut dyn #bevy_reflect_path::PartialReflect> {
|
||||
match index {
|
||||
#(#field_indices => #fqoption::Some(&mut self.#field_idents),)*
|
||||
_ => #FQOption::None,
|
||||
|
@ -94,71 +85,38 @@ pub(crate) fn impl_tuple_struct(reflect_struct: &ReflectStruct) -> proc_macro2::
|
|||
|
||||
fn clone_dynamic(&self) -> #bevy_reflect_path::DynamicTupleStruct {
|
||||
let mut dynamic: #bevy_reflect_path::DynamicTupleStruct = #FQDefault::default();
|
||||
dynamic.set_represented_type(#bevy_reflect_path::Reflect::get_represented_type_info(self));
|
||||
#(dynamic.insert_boxed(#bevy_reflect_path::Reflect::clone_value(&self.#field_idents));)*
|
||||
dynamic.set_represented_type(#bevy_reflect_path::PartialReflect::get_represented_type_info(self));
|
||||
#(dynamic.insert_boxed(#bevy_reflect_path::PartialReflect::clone_value(&self.#field_idents));)*
|
||||
dynamic
|
||||
}
|
||||
}
|
||||
|
||||
impl #impl_generics #bevy_reflect_path::Reflect for #struct_path #ty_generics #where_reflect_clause {
|
||||
impl #impl_generics #bevy_reflect_path::PartialReflect for #struct_path #ty_generics #where_reflect_clause {
|
||||
#[inline]
|
||||
fn get_represented_type_info(&self) -> #FQOption<&'static #bevy_reflect_path::TypeInfo> {
|
||||
#FQOption::Some(<Self as #bevy_reflect_path::Typed>::type_info())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn into_any(self: #FQBox<Self>) -> #FQBox<dyn #FQAny> {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_any(&self) -> &dyn #FQAny {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_any_mut(&mut self) -> &mut dyn #FQAny {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn into_reflect(self: #FQBox<Self>) -> #FQBox<dyn #bevy_reflect_path::Reflect> {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_reflect(&self) -> &dyn #bevy_reflect_path::Reflect {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_reflect_mut(&mut self) -> &mut dyn #bevy_reflect_path::Reflect {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn clone_value(&self) -> #FQBox<dyn #bevy_reflect_path::Reflect> {
|
||||
fn clone_value(&self) -> #FQBox<dyn #bevy_reflect_path::PartialReflect> {
|
||||
#FQBox::new(#bevy_reflect_path::TupleStruct::clone_dynamic(self))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set(&mut self, value: #FQBox<dyn #bevy_reflect_path::Reflect>) -> #FQResult<(), #FQBox<dyn #bevy_reflect_path::Reflect>> {
|
||||
*self = <dyn #bevy_reflect_path::Reflect>::take(value)?;
|
||||
#FQResult::Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn try_apply(&mut self, value: &dyn #bevy_reflect_path::Reflect) -> #FQResult<(), #bevy_reflect_path::ApplyError> {
|
||||
if let #bevy_reflect_path::ReflectRef::TupleStruct(struct_value) = #bevy_reflect_path::Reflect::reflect_ref(value) {
|
||||
fn try_apply(
|
||||
&mut self,
|
||||
value: &dyn #bevy_reflect_path::PartialReflect
|
||||
) -> #FQResult<(), #bevy_reflect_path::ApplyError> {
|
||||
if let #bevy_reflect_path::ReflectRef::TupleStruct(struct_value) =
|
||||
#bevy_reflect_path::PartialReflect::reflect_ref(value) {
|
||||
for (i, value) in ::core::iter::Iterator::enumerate(#bevy_reflect_path::TupleStruct::iter_fields(struct_value)) {
|
||||
if let #FQOption::Some(v) = #bevy_reflect_path::TupleStruct::field_mut(self, i) {
|
||||
#bevy_reflect_path::Reflect::try_apply(v, value)?;
|
||||
#bevy_reflect_path::PartialReflect::try_apply(v, value)?;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return #FQResult::Err(
|
||||
#bevy_reflect_path::ApplyError::MismatchedKinds {
|
||||
from_kind: #bevy_reflect_path::Reflect::reflect_kind(value),
|
||||
from_kind: #bevy_reflect_path::PartialReflect::reflect_kind(value),
|
||||
to_kind: #bevy_reflect_path::ReflectKind::TupleStruct,
|
||||
}
|
||||
);
|
||||
|
@ -182,11 +140,7 @@ pub(crate) fn impl_tuple_struct(reflect_struct: &ReflectStruct) -> proc_macro2::
|
|||
#bevy_reflect_path::ReflectOwned::TupleStruct(self)
|
||||
}
|
||||
|
||||
#hash_fn
|
||||
|
||||
#partial_eq_fn
|
||||
|
||||
#debug_fn
|
||||
#common_methods
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::impls::{impl_type_path, impl_typed};
|
||||
use crate::impls::{common_partial_reflect_methods, impl_full_reflect, impl_type_path, impl_typed};
|
||||
use crate::utility::WhereClauseOptions;
|
||||
use crate::ReflectMeta;
|
||||
use bevy_macro_utils::fq_std::{FQAny, FQBox, FQClone, FQOption, FQResult};
|
||||
use bevy_macro_utils::fq_std::{FQBox, FQClone, FQOption, FQResult};
|
||||
use quote::quote;
|
||||
|
||||
/// Implements `GetTypeRegistration` and `Reflect` for the given type data.
|
||||
|
@ -9,10 +9,6 @@ pub(crate) fn impl_value(meta: &ReflectMeta) -> proc_macro2::TokenStream {
|
|||
let bevy_reflect_path = meta.bevy_reflect_path();
|
||||
let type_path = meta.type_path();
|
||||
|
||||
let hash_fn = meta.attrs().get_hash_impl(bevy_reflect_path);
|
||||
let partial_eq_fn = meta.attrs().get_partial_eq_impl(bevy_reflect_path);
|
||||
let debug_fn = meta.attrs().get_debug_impl();
|
||||
|
||||
#[cfg(feature = "documentation")]
|
||||
let with_docs = {
|
||||
let doc = quote::ToTokens::to_token_stream(meta.doc());
|
||||
|
@ -32,6 +28,8 @@ pub(crate) fn impl_value(meta: &ReflectMeta) -> proc_macro2::TokenStream {
|
|||
);
|
||||
|
||||
let type_path_impl = impl_type_path(meta);
|
||||
let full_reflect_impl = impl_full_reflect(meta, &where_clause_options);
|
||||
let common_methods = common_partial_reflect_methods(meta, || None, || None);
|
||||
|
||||
#[cfg(not(feature = "functions"))]
|
||||
let function_impls = None::<proc_macro2::TokenStream>;
|
||||
|
@ -49,53 +47,27 @@ pub(crate) fn impl_value(meta: &ReflectMeta) -> proc_macro2::TokenStream {
|
|||
|
||||
#typed_impl
|
||||
|
||||
#full_reflect_impl
|
||||
|
||||
#function_impls
|
||||
|
||||
impl #impl_generics #bevy_reflect_path::Reflect for #type_path #ty_generics #where_reflect_clause {
|
||||
impl #impl_generics #bevy_reflect_path::PartialReflect for #type_path #ty_generics #where_reflect_clause {
|
||||
#[inline]
|
||||
fn get_represented_type_info(&self) -> #FQOption<&'static #bevy_reflect_path::TypeInfo> {
|
||||
#FQOption::Some(<Self as #bevy_reflect_path::Typed>::type_info())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn into_any(self: #FQBox<Self>) -> #FQBox<dyn #FQAny> {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_any(&self) -> &dyn #FQAny {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_any_mut(&mut self) -> &mut dyn #FQAny {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn into_reflect(self: #FQBox<Self>) -> #FQBox<dyn #bevy_reflect_path::Reflect> {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_reflect(&self) -> &dyn #bevy_reflect_path::Reflect {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_reflect_mut(&mut self) -> &mut dyn #bevy_reflect_path::Reflect {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn clone_value(&self) -> #FQBox<dyn #bevy_reflect_path::Reflect> {
|
||||
fn clone_value(&self) -> #FQBox<dyn #bevy_reflect_path::PartialReflect> {
|
||||
#FQBox::new(#FQClone::clone(self))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn try_apply(&mut self, value: &dyn #bevy_reflect_path::Reflect) -> #FQResult<(), #bevy_reflect_path::ApplyError> {
|
||||
let any = #bevy_reflect_path::Reflect::as_any(value);
|
||||
if let #FQOption::Some(value) = <dyn #FQAny>::downcast_ref::<Self>(any) {
|
||||
fn try_apply(
|
||||
&mut self,
|
||||
value: &dyn #bevy_reflect_path::PartialReflect
|
||||
) -> #FQResult<(), #bevy_reflect_path::ApplyError> {
|
||||
if let #FQOption::Some(value) = <dyn #bevy_reflect_path::PartialReflect>::try_downcast_ref::<Self>(value) {
|
||||
*self = #FQClone::clone(value);
|
||||
} else {
|
||||
return #FQResult::Err(
|
||||
|
@ -108,12 +80,6 @@ pub(crate) fn impl_value(meta: &ReflectMeta) -> proc_macro2::TokenStream {
|
|||
#FQResult::Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set(&mut self, value: #FQBox<dyn #bevy_reflect_path::Reflect>) -> #FQResult<(), #FQBox<dyn #bevy_reflect_path::Reflect>> {
|
||||
*self = <dyn #bevy_reflect_path::Reflect>::take(value)?;
|
||||
#FQResult::Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn reflect_kind(&self) -> #bevy_reflect_path::ReflectKind {
|
||||
#bevy_reflect_path::ReflectKind::Value
|
||||
|
@ -134,11 +100,7 @@ pub(crate) fn impl_value(meta: &ReflectMeta) -> proc_macro2::TokenStream {
|
|||
#bevy_reflect_path::ReflectOwned::Value(self)
|
||||
}
|
||||
|
||||
#hash_fn
|
||||
|
||||
#partial_eq_fn
|
||||
|
||||
#debug_fn
|
||||
#common_methods
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -94,7 +94,7 @@ impl<'a, 'b> WhereClauseOptions<'a, 'b> {
|
|||
/// The default bounds added are as follows:
|
||||
/// - `Self` has the bounds `Any + Send + Sync`
|
||||
/// - Type parameters have the bound `TypePath` unless `#[reflect(type_path = false)]` is present
|
||||
/// - Active fields have the bounds `TypePath` and either `Reflect` if `#[reflect(from_reflect = false)]` is present
|
||||
/// - Active fields have the bounds `TypePath` and either `PartialReflect` if `#[reflect(from_reflect = false)]` is present
|
||||
/// or `FromReflect` otherwise (or no bounds at all if `#[reflect(no_field_bounds)]` is present)
|
||||
///
|
||||
/// When the derive is used with `#[reflect(where)]`, the bounds specified in the attribute are added as well.
|
||||
|
@ -236,14 +236,14 @@ impl<'a, 'b> WhereClauseOptions<'a, 'b> {
|
|||
}
|
||||
}
|
||||
|
||||
/// The `Reflect` or `FromReflect` bound to use based on `#[reflect(from_reflect = false)]`.
|
||||
/// The `PartialReflect` or `FromReflect` bound to use based on `#[reflect(from_reflect = false)]`.
|
||||
fn reflect_bound(&self) -> TokenStream {
|
||||
let bevy_reflect_path = self.meta.bevy_reflect_path();
|
||||
|
||||
if self.meta.from_reflect().should_auto_derive() {
|
||||
quote!(#bevy_reflect_path::FromReflect)
|
||||
} else {
|
||||
quote!(#bevy_reflect_path::Reflect)
|
||||
quote!(#bevy_reflect_path::PartialReflect)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::{
|
||||
self as bevy_reflect, utility::reflect_hasher, ApplyError, MaybeTyped, Reflect, ReflectKind,
|
||||
ReflectMut, ReflectOwned, ReflectRef, TypeInfo, TypePath, TypePathTable,
|
||||
self as bevy_reflect, utility::reflect_hasher, ApplyError, MaybeTyped, PartialReflect, Reflect,
|
||||
ReflectKind, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, TypePath, TypePathTable,
|
||||
};
|
||||
use bevy_reflect_derive::impl_type_path;
|
||||
use std::{
|
||||
|
@ -28,13 +28,13 @@ use std::{
|
|||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use bevy_reflect::{Reflect, Array};
|
||||
/// use bevy_reflect::{PartialReflect, Array};
|
||||
///
|
||||
/// let foo: &dyn Array = &[123_u32, 456_u32, 789_u32];
|
||||
/// assert_eq!(foo.len(), 3);
|
||||
///
|
||||
/// let field: &dyn Reflect = foo.get(0).unwrap();
|
||||
/// assert_eq!(field.downcast_ref::<u32>(), Some(&123));
|
||||
/// let field: &dyn PartialReflect = foo.get(0).unwrap();
|
||||
/// assert_eq!(field.try_downcast_ref::<u32>(), Some(&123));
|
||||
/// ```
|
||||
///
|
||||
/// [array-like]: https://doc.rust-lang.org/book/ch03-02-data-types.html#the-array-type
|
||||
|
@ -44,12 +44,12 @@ use std::{
|
|||
/// [`GetTypeRegistration`]: crate::GetTypeRegistration
|
||||
/// [limitation]: https://github.com/serde-rs/serde/issues/1937
|
||||
/// [`Deserialize`]: ::serde::Deserialize
|
||||
pub trait Array: Reflect {
|
||||
pub trait Array: PartialReflect {
|
||||
/// Returns a reference to the element at `index`, or `None` if out of bounds.
|
||||
fn get(&self, index: usize) -> Option<&dyn Reflect>;
|
||||
fn get(&self, index: usize) -> Option<&dyn PartialReflect>;
|
||||
|
||||
/// Returns a mutable reference to the element at `index`, or `None` if out of bounds.
|
||||
fn get_mut(&mut self, index: usize) -> Option<&mut dyn Reflect>;
|
||||
fn get_mut(&mut self, index: usize) -> Option<&mut dyn PartialReflect>;
|
||||
|
||||
/// Returns the number of elements in the array.
|
||||
fn len(&self) -> usize;
|
||||
|
@ -63,13 +63,13 @@ pub trait Array: Reflect {
|
|||
fn iter(&self) -> ArrayIter;
|
||||
|
||||
/// Drain the elements of this array to get a vector of owned values.
|
||||
fn drain(self: Box<Self>) -> Vec<Box<dyn Reflect>>;
|
||||
fn drain(self: Box<Self>) -> Vec<Box<dyn PartialReflect>>;
|
||||
|
||||
/// Clones the list, producing a [`DynamicArray`].
|
||||
fn clone_dynamic(&self) -> DynamicArray {
|
||||
DynamicArray {
|
||||
represented_type: self.get_represented_type_info(),
|
||||
values: self.iter().map(Reflect::clone_value).collect(),
|
||||
values: self.iter().map(PartialReflect::clone_value).collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -191,12 +191,12 @@ impl ArrayInfo {
|
|||
#[derive(Debug)]
|
||||
pub struct DynamicArray {
|
||||
pub(crate) represented_type: Option<&'static TypeInfo>,
|
||||
pub(crate) values: Box<[Box<dyn Reflect>]>,
|
||||
pub(crate) values: Box<[Box<dyn PartialReflect>]>,
|
||||
}
|
||||
|
||||
impl DynamicArray {
|
||||
#[inline]
|
||||
pub fn new(values: Box<[Box<dyn Reflect>]>) -> Self {
|
||||
pub fn new(values: Box<[Box<dyn PartialReflect>]>) -> Self {
|
||||
Self {
|
||||
represented_type: None,
|
||||
values,
|
||||
|
@ -204,7 +204,7 @@ impl DynamicArray {
|
|||
}
|
||||
|
||||
#[deprecated(since = "0.15.0", note = "use from_iter")]
|
||||
pub fn from_vec<T: Reflect>(values: Vec<T>) -> Self {
|
||||
pub fn from_vec<T: PartialReflect>(values: Vec<T>) -> Self {
|
||||
Self::from_iter(values)
|
||||
}
|
||||
|
||||
|
@ -228,56 +228,47 @@ impl DynamicArray {
|
|||
}
|
||||
}
|
||||
|
||||
impl Reflect for DynamicArray {
|
||||
impl PartialReflect for DynamicArray {
|
||||
#[inline]
|
||||
fn get_represented_type_info(&self) -> Option<&'static TypeInfo> {
|
||||
self.represented_type
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn into_any(self: Box<Self>) -> Box<dyn Any> {
|
||||
fn into_partial_reflect(self: Box<Self>) -> Box<dyn PartialReflect> {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
fn as_partial_reflect(&self) -> &dyn PartialReflect {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_any_mut(&mut self) -> &mut dyn Any {
|
||||
fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn into_reflect(self: Box<Self>) -> Box<dyn Reflect> {
|
||||
self
|
||||
fn try_into_reflect(self: Box<Self>) -> Result<Box<dyn Reflect>, Box<dyn PartialReflect>> {
|
||||
Err(self)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_reflect(&self) -> &dyn Reflect {
|
||||
self
|
||||
fn try_as_reflect(&self) -> Option<&dyn Reflect> {
|
||||
None
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_reflect_mut(&mut self) -> &mut dyn Reflect {
|
||||
self
|
||||
fn try_as_reflect_mut(&mut self) -> Option<&mut dyn Reflect> {
|
||||
None
|
||||
}
|
||||
|
||||
fn apply(&mut self, value: &dyn Reflect) {
|
||||
fn apply(&mut self, value: &dyn PartialReflect) {
|
||||
array_apply(self, value);
|
||||
}
|
||||
|
||||
fn try_apply(&mut self, value: &dyn Reflect) -> Result<(), ApplyError> {
|
||||
fn try_apply(&mut self, value: &dyn PartialReflect) -> Result<(), ApplyError> {
|
||||
array_try_apply(self, value)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set(&mut self, value: Box<dyn Reflect>) -> Result<(), Box<dyn Reflect>> {
|
||||
*self = value.take()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn reflect_kind(&self) -> ReflectKind {
|
||||
ReflectKind::Array
|
||||
|
@ -299,7 +290,7 @@ impl Reflect for DynamicArray {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn clone_value(&self) -> Box<dyn Reflect> {
|
||||
fn clone_value(&self) -> Box<dyn PartialReflect> {
|
||||
Box::new(self.clone_dynamic())
|
||||
}
|
||||
|
||||
|
@ -308,7 +299,7 @@ impl Reflect for DynamicArray {
|
|||
array_hash(self)
|
||||
}
|
||||
|
||||
fn reflect_partial_eq(&self, value: &dyn Reflect) -> Option<bool> {
|
||||
fn reflect_partial_eq(&self, value: &dyn PartialReflect) -> Option<bool> {
|
||||
array_partial_eq(self, value)
|
||||
}
|
||||
|
||||
|
@ -326,12 +317,12 @@ impl Reflect for DynamicArray {
|
|||
|
||||
impl Array for DynamicArray {
|
||||
#[inline]
|
||||
fn get(&self, index: usize) -> Option<&dyn Reflect> {
|
||||
fn get(&self, index: usize) -> Option<&dyn PartialReflect> {
|
||||
self.values.get(index).map(|value| &**value)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn get_mut(&mut self, index: usize) -> Option<&mut dyn Reflect> {
|
||||
fn get_mut(&mut self, index: usize) -> Option<&mut dyn PartialReflect> {
|
||||
self.values.get_mut(index).map(|value| &mut **value)
|
||||
}
|
||||
|
||||
|
@ -346,7 +337,7 @@ impl Array for DynamicArray {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn drain(self: Box<Self>) -> Vec<Box<dyn Reflect>> {
|
||||
fn drain(self: Box<Self>) -> Vec<Box<dyn PartialReflect>> {
|
||||
self.values.into_vec()
|
||||
}
|
||||
|
||||
|
@ -363,8 +354,8 @@ impl Array for DynamicArray {
|
|||
}
|
||||
}
|
||||
|
||||
impl FromIterator<Box<dyn Reflect>> for DynamicArray {
|
||||
fn from_iter<I: IntoIterator<Item = Box<dyn Reflect>>>(values: I) -> Self {
|
||||
impl FromIterator<Box<dyn PartialReflect>> for DynamicArray {
|
||||
fn from_iter<I: IntoIterator<Item = Box<dyn PartialReflect>>>(values: I) -> Self {
|
||||
Self {
|
||||
represented_type: None,
|
||||
values: values.into_iter().collect::<Vec<_>>().into_boxed_slice(),
|
||||
|
@ -372,17 +363,17 @@ impl FromIterator<Box<dyn Reflect>> for DynamicArray {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Reflect> FromIterator<T> for DynamicArray {
|
||||
impl<T: PartialReflect> FromIterator<T> for DynamicArray {
|
||||
fn from_iter<I: IntoIterator<Item = T>>(values: I) -> Self {
|
||||
values
|
||||
.into_iter()
|
||||
.map(|value| Box::new(value).into_reflect())
|
||||
.map(|value| Box::new(value).into_partial_reflect())
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoIterator for DynamicArray {
|
||||
type Item = Box<dyn Reflect>;
|
||||
type Item = Box<dyn PartialReflect>;
|
||||
type IntoIter = std::vec::IntoIter<Self::Item>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
|
@ -391,7 +382,7 @@ impl IntoIterator for DynamicArray {
|
|||
}
|
||||
|
||||
impl<'a> IntoIterator for &'a DynamicArray {
|
||||
type Item = &'a dyn Reflect;
|
||||
type Item = &'a dyn PartialReflect;
|
||||
type IntoIter = ArrayIter<'a>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
|
@ -400,8 +391,6 @@ impl<'a> IntoIterator for &'a DynamicArray {
|
|||
}
|
||||
|
||||
impl_type_path!((in bevy_reflect) DynamicArray);
|
||||
#[cfg(feature = "functions")]
|
||||
crate::func::macros::impl_function_traits!(DynamicArray);
|
||||
|
||||
/// An iterator over an [`Array`].
|
||||
pub struct ArrayIter<'a> {
|
||||
|
@ -418,7 +407,7 @@ impl<'a> ArrayIter<'a> {
|
|||
}
|
||||
|
||||
impl<'a> Iterator for ArrayIter<'a> {
|
||||
type Item = &'a dyn Reflect;
|
||||
type Item = &'a dyn PartialReflect;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
|
@ -438,7 +427,7 @@ impl<'a> ExactSizeIterator for ArrayIter<'a> {}
|
|||
|
||||
/// Returns the `u64` hash of the given [array](Array).
|
||||
#[inline]
|
||||
pub fn array_hash<A: Array>(array: &A) -> Option<u64> {
|
||||
pub fn array_hash<A: Array + ?Sized>(array: &A) -> Option<u64> {
|
||||
let mut hasher = reflect_hasher();
|
||||
Any::type_id(array).hash(&mut hasher);
|
||||
array.len().hash(&mut hasher);
|
||||
|
@ -456,7 +445,7 @@ pub fn array_hash<A: Array>(array: &A) -> Option<u64> {
|
|||
/// * Panics if the reflected value is not a [valid array](ReflectRef::Array).
|
||||
///
|
||||
#[inline]
|
||||
pub fn array_apply<A: Array>(array: &mut A, reflect: &dyn Reflect) {
|
||||
pub fn array_apply<A: Array + ?Sized>(array: &mut A, reflect: &dyn PartialReflect) {
|
||||
if let ReflectRef::Array(reflect_array) = reflect.reflect_ref() {
|
||||
if array.len() != reflect_array.len() {
|
||||
panic!("Attempted to apply different sized `Array` types.");
|
||||
|
@ -481,7 +470,10 @@ pub fn array_apply<A: Array>(array: &mut A, reflect: &dyn Reflect) {
|
|||
/// * Returns any error that is generated while applying elements to each other.
|
||||
///
|
||||
#[inline]
|
||||
pub fn array_try_apply<A: Array>(array: &mut A, reflect: &dyn Reflect) -> Result<(), ApplyError> {
|
||||
pub fn array_try_apply<A: Array>(
|
||||
array: &mut A,
|
||||
reflect: &dyn PartialReflect,
|
||||
) -> Result<(), ApplyError> {
|
||||
if let ReflectRef::Array(reflect_array) = reflect.reflect_ref() {
|
||||
if array.len() != reflect_array.len() {
|
||||
return Err(ApplyError::DifferentSize {
|
||||
|
@ -507,7 +499,10 @@ pub fn array_try_apply<A: Array>(array: &mut A, reflect: &dyn Reflect) -> Result
|
|||
///
|
||||
/// Returns [`None`] if the comparison couldn't even be performed.
|
||||
#[inline]
|
||||
pub fn array_partial_eq<A: Array>(array: &A, reflect: &dyn Reflect) -> Option<bool> {
|
||||
pub fn array_partial_eq<A: Array + ?Sized>(
|
||||
array: &A,
|
||||
reflect: &dyn PartialReflect,
|
||||
) -> Option<bool> {
|
||||
match reflect.reflect_ref() {
|
||||
ReflectRef::Array(reflect_array) if reflect_array.len() == array.len() => {
|
||||
for (a, b) in array.iter().zip(reflect_array.iter()) {
|
||||
|
|
|
@ -2,10 +2,10 @@ use bevy_reflect_derive::impl_type_path;
|
|||
|
||||
use crate::{
|
||||
self as bevy_reflect, enum_debug, enum_hash, enum_partial_eq, ApplyError, DynamicStruct,
|
||||
DynamicTuple, Enum, Reflect, ReflectKind, ReflectMut, ReflectOwned, ReflectRef, Struct, Tuple,
|
||||
TypeInfo, VariantFieldIter, VariantType,
|
||||
DynamicTuple, Enum, PartialReflect, Reflect, ReflectKind, ReflectMut, ReflectOwned, ReflectRef,
|
||||
Struct, Tuple, TypeInfo, VariantFieldIter, VariantType,
|
||||
};
|
||||
use std::any::Any;
|
||||
|
||||
use std::fmt::Formatter;
|
||||
|
||||
/// A dynamic representation of an enum variant.
|
||||
|
@ -52,7 +52,7 @@ impl From<()> for DynamicVariant {
|
|||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// # use bevy_reflect::{DynamicEnum, DynamicVariant, Reflect};
|
||||
/// # use bevy_reflect::{DynamicEnum, DynamicVariant, Reflect, PartialReflect};
|
||||
///
|
||||
/// // The original enum value
|
||||
/// let mut value: Option<usize> = Some(123);
|
||||
|
@ -64,7 +64,7 @@ impl From<()> for DynamicVariant {
|
|||
/// );
|
||||
///
|
||||
/// // Apply the DynamicEnum as a patch to the original value
|
||||
/// value.apply(&dyn_enum);
|
||||
/// value.apply(dyn_enum.as_partial_reflect());
|
||||
///
|
||||
/// // Tada!
|
||||
/// assert_eq!(None, value);
|
||||
|
@ -201,7 +201,7 @@ impl DynamicEnum {
|
|||
}
|
||||
|
||||
impl Enum for DynamicEnum {
|
||||
fn field(&self, name: &str) -> Option<&dyn Reflect> {
|
||||
fn field(&self, name: &str) -> Option<&dyn PartialReflect> {
|
||||
if let DynamicVariant::Struct(data) = &self.variant {
|
||||
data.field(name)
|
||||
} else {
|
||||
|
@ -209,7 +209,7 @@ impl Enum for DynamicEnum {
|
|||
}
|
||||
}
|
||||
|
||||
fn field_at(&self, index: usize) -> Option<&dyn Reflect> {
|
||||
fn field_at(&self, index: usize) -> Option<&dyn PartialReflect> {
|
||||
if let DynamicVariant::Tuple(data) = &self.variant {
|
||||
data.field(index)
|
||||
} else {
|
||||
|
@ -217,7 +217,7 @@ impl Enum for DynamicEnum {
|
|||
}
|
||||
}
|
||||
|
||||
fn field_mut(&mut self, name: &str) -> Option<&mut dyn Reflect> {
|
||||
fn field_mut(&mut self, name: &str) -> Option<&mut dyn PartialReflect> {
|
||||
if let DynamicVariant::Struct(data) = &mut self.variant {
|
||||
data.field_mut(name)
|
||||
} else {
|
||||
|
@ -225,7 +225,7 @@ impl Enum for DynamicEnum {
|
|||
}
|
||||
}
|
||||
|
||||
fn field_at_mut(&mut self, index: usize) -> Option<&mut dyn Reflect> {
|
||||
fn field_at_mut(&mut self, index: usize) -> Option<&mut dyn PartialReflect> {
|
||||
if let DynamicVariant::Tuple(data) = &mut self.variant {
|
||||
data.field_mut(index)
|
||||
} else {
|
||||
|
@ -287,44 +287,41 @@ impl Enum for DynamicEnum {
|
|||
}
|
||||
}
|
||||
|
||||
impl Reflect for DynamicEnum {
|
||||
impl PartialReflect for DynamicEnum {
|
||||
#[inline]
|
||||
fn get_represented_type_info(&self) -> Option<&'static TypeInfo> {
|
||||
self.represented_type
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn into_any(self: Box<Self>) -> Box<dyn Any> {
|
||||
fn into_partial_reflect(self: Box<Self>) -> Box<dyn PartialReflect> {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
fn as_partial_reflect(&self) -> &dyn PartialReflect {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_any_mut(&mut self) -> &mut dyn Any {
|
||||
fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn into_reflect(self: Box<Self>) -> Box<dyn Reflect> {
|
||||
self
|
||||
fn try_into_reflect(self: Box<Self>) -> Result<Box<dyn Reflect>, Box<dyn PartialReflect>> {
|
||||
Err(self)
|
||||
}
|
||||
|
||||
fn try_as_reflect(&self) -> Option<&dyn Reflect> {
|
||||
None
|
||||
}
|
||||
|
||||
fn try_as_reflect_mut(&mut self) -> Option<&mut dyn Reflect> {
|
||||
None
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_reflect(&self) -> &dyn Reflect {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_reflect_mut(&mut self) -> &mut dyn Reflect {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn try_apply(&mut self, value: &dyn Reflect) -> Result<(), ApplyError> {
|
||||
fn try_apply(&mut self, value: &dyn PartialReflect) -> Result<(), ApplyError> {
|
||||
if let ReflectRef::Enum(value) = value.reflect_ref() {
|
||||
if Enum::variant_name(self) == value.variant_name() {
|
||||
// Same variant -> just update fields
|
||||
|
@ -377,12 +374,6 @@ impl Reflect for DynamicEnum {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set(&mut self, value: Box<dyn Reflect>) -> Result<(), Box<dyn Reflect>> {
|
||||
*self = value.take()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn reflect_kind(&self) -> ReflectKind {
|
||||
ReflectKind::Enum
|
||||
|
@ -404,7 +395,7 @@ impl Reflect for DynamicEnum {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn clone_value(&self) -> Box<dyn Reflect> {
|
||||
fn clone_value(&self) -> Box<dyn PartialReflect> {
|
||||
Box::new(self.clone_dynamic())
|
||||
}
|
||||
|
||||
|
@ -414,7 +405,7 @@ impl Reflect for DynamicEnum {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn reflect_partial_eq(&self, value: &dyn Reflect) -> Option<bool> {
|
||||
fn reflect_partial_eq(&self, value: &dyn PartialReflect) -> Option<bool> {
|
||||
enum_partial_eq(self, value)
|
||||
}
|
||||
|
||||
|
@ -427,5 +418,3 @@ impl Reflect for DynamicEnum {
|
|||
}
|
||||
|
||||
impl_type_path!((in bevy_reflect) DynamicEnum);
|
||||
#[cfg(feature = "functions")]
|
||||
crate::func::macros::impl_function_traits!(DynamicEnum);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::attributes::{impl_custom_attribute_methods, CustomAttributes};
|
||||
use crate::{DynamicEnum, Reflect, TypePath, TypePathTable, VariantInfo, VariantType};
|
||||
use crate::{DynamicEnum, PartialReflect, TypePath, TypePathTable, VariantInfo, VariantType};
|
||||
use bevy_utils::HashMap;
|
||||
use std::any::{Any, TypeId};
|
||||
use std::slice::Iter;
|
||||
|
@ -89,19 +89,19 @@ use std::sync::Arc;
|
|||
/// [`None`]: Option<T>::None
|
||||
/// [`Some`]: Option<T>::Some
|
||||
/// [`Reflect`]: bevy_reflect_derive::Reflect
|
||||
pub trait Enum: Reflect {
|
||||
pub trait Enum: PartialReflect {
|
||||
/// Returns a reference to the value of the field (in the current variant) with the given name.
|
||||
///
|
||||
/// For non-[`VariantType::Struct`] variants, this should return `None`.
|
||||
fn field(&self, name: &str) -> Option<&dyn Reflect>;
|
||||
fn field(&self, name: &str) -> Option<&dyn PartialReflect>;
|
||||
/// Returns a reference to the value of the field (in the current variant) at the given index.
|
||||
fn field_at(&self, index: usize) -> Option<&dyn Reflect>;
|
||||
fn field_at(&self, index: usize) -> Option<&dyn PartialReflect>;
|
||||
/// Returns a mutable reference to the value of the field (in the current variant) with the given name.
|
||||
///
|
||||
/// For non-[`VariantType::Struct`] variants, this should return `None`.
|
||||
fn field_mut(&mut self, name: &str) -> Option<&mut dyn Reflect>;
|
||||
fn field_mut(&mut self, name: &str) -> Option<&mut dyn PartialReflect>;
|
||||
/// Returns a mutable reference to the value of the field (in the current variant) at the given index.
|
||||
fn field_at_mut(&mut self, index: usize) -> Option<&mut dyn Reflect>;
|
||||
fn field_at_mut(&mut self, index: usize) -> Option<&mut dyn PartialReflect>;
|
||||
/// Returns the index of the field (in the current variant) with the given name.
|
||||
///
|
||||
/// For non-[`VariantType::Struct`] variants, this should return `None`.
|
||||
|
@ -307,8 +307,8 @@ impl<'a> Iterator for VariantFieldIter<'a> {
|
|||
impl<'a> ExactSizeIterator for VariantFieldIter<'a> {}
|
||||
|
||||
pub enum VariantField<'a> {
|
||||
Struct(&'a str, &'a dyn Reflect),
|
||||
Tuple(&'a dyn Reflect),
|
||||
Struct(&'a str, &'a dyn PartialReflect),
|
||||
Tuple(&'a dyn PartialReflect),
|
||||
}
|
||||
|
||||
impl<'a> VariantField<'a> {
|
||||
|
@ -320,7 +320,7 @@ impl<'a> VariantField<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn value(&self) -> &'a dyn Reflect {
|
||||
pub fn value(&self) -> &'a dyn PartialReflect {
|
||||
match *self {
|
||||
Self::Struct(_, value) | Self::Tuple(value) => value,
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use crate::{utility::reflect_hasher, Enum, Reflect, ReflectRef, VariantType};
|
||||
use crate::PartialReflect;
|
||||
use crate::{utility::reflect_hasher, Enum, ReflectRef, VariantType};
|
||||
use std::fmt::Debug;
|
||||
use std::hash::{Hash, Hasher};
|
||||
|
||||
|
@ -15,16 +16,16 @@ pub fn enum_hash<TEnum: Enum>(value: &TEnum) -> Option<u64> {
|
|||
Some(hasher.finish())
|
||||
}
|
||||
|
||||
/// Compares an [`Enum`] with a [`Reflect`] value.
|
||||
/// Compares an [`Enum`] with a [`PartialReflect`] value.
|
||||
///
|
||||
/// Returns true if and only if all of the following are true:
|
||||
/// - `b` is an enum;
|
||||
/// - `b` is the same variant as `a`;
|
||||
/// - For each field in `a`, `b` contains a field with the same name and
|
||||
/// [`Reflect::reflect_partial_eq`] returns `Some(true)` for the two field
|
||||
/// [`PartialReflect::reflect_partial_eq`] returns `Some(true)` for the two field
|
||||
/// values.
|
||||
#[inline]
|
||||
pub fn enum_partial_eq<TEnum: Enum>(a: &TEnum, b: &dyn Reflect) -> Option<bool> {
|
||||
pub fn enum_partial_eq<TEnum: Enum + ?Sized>(a: &TEnum, b: &dyn PartialReflect) -> Option<bool> {
|
||||
// Both enums?
|
||||
let ReflectRef::Enum(b) = b.reflect_ref() else {
|
||||
return Some(false);
|
||||
|
|
|
@ -614,71 +614,71 @@ mod tests {
|
|||
C2 { value: f32 },
|
||||
}
|
||||
|
||||
let a: &dyn Reflect = &TestEnum::A;
|
||||
let b: &dyn Reflect = &TestEnum::A;
|
||||
let a: &dyn PartialReflect = &TestEnum::A;
|
||||
let b: &dyn PartialReflect = &TestEnum::A;
|
||||
assert!(
|
||||
a.reflect_partial_eq(b).unwrap_or_default(),
|
||||
"expected TestEnum::A == TestEnum::A"
|
||||
);
|
||||
|
||||
let a: &dyn Reflect = &TestEnum::A;
|
||||
let b: &dyn Reflect = &TestEnum::A1;
|
||||
let a: &dyn PartialReflect = &TestEnum::A;
|
||||
let b: &dyn PartialReflect = &TestEnum::A1;
|
||||
assert!(
|
||||
!a.reflect_partial_eq(b).unwrap_or_default(),
|
||||
"expected TestEnum::A != TestEnum::A1"
|
||||
);
|
||||
|
||||
let a: &dyn Reflect = &TestEnum::B(123);
|
||||
let b: &dyn Reflect = &TestEnum::B(123);
|
||||
let a: &dyn PartialReflect = &TestEnum::B(123);
|
||||
let b: &dyn PartialReflect = &TestEnum::B(123);
|
||||
assert!(
|
||||
a.reflect_partial_eq(b).unwrap_or_default(),
|
||||
"expected TestEnum::B(123) == TestEnum::B(123)"
|
||||
);
|
||||
|
||||
let a: &dyn Reflect = &TestEnum::B(123);
|
||||
let b: &dyn Reflect = &TestEnum::B(321);
|
||||
let a: &dyn PartialReflect = &TestEnum::B(123);
|
||||
let b: &dyn PartialReflect = &TestEnum::B(321);
|
||||
assert!(
|
||||
!a.reflect_partial_eq(b).unwrap_or_default(),
|
||||
"expected TestEnum::B(123) != TestEnum::B(321)"
|
||||
);
|
||||
|
||||
let a: &dyn Reflect = &TestEnum::B(123);
|
||||
let b: &dyn Reflect = &TestEnum::B1(123);
|
||||
let a: &dyn PartialReflect = &TestEnum::B(123);
|
||||
let b: &dyn PartialReflect = &TestEnum::B1(123);
|
||||
assert!(
|
||||
!a.reflect_partial_eq(b).unwrap_or_default(),
|
||||
"expected TestEnum::B(123) != TestEnum::B1(123)"
|
||||
);
|
||||
|
||||
let a: &dyn Reflect = &TestEnum::B(123);
|
||||
let b: &dyn Reflect = &TestEnum::B2(123, 123);
|
||||
let a: &dyn PartialReflect = &TestEnum::B(123);
|
||||
let b: &dyn PartialReflect = &TestEnum::B2(123, 123);
|
||||
assert!(
|
||||
!a.reflect_partial_eq(b).unwrap_or_default(),
|
||||
"expected TestEnum::B(123) != TestEnum::B2(123, 123)"
|
||||
);
|
||||
|
||||
let a: &dyn Reflect = &TestEnum::C { value: 123 };
|
||||
let b: &dyn Reflect = &TestEnum::C { value: 123 };
|
||||
let a: &dyn PartialReflect = &TestEnum::C { value: 123 };
|
||||
let b: &dyn PartialReflect = &TestEnum::C { value: 123 };
|
||||
assert!(
|
||||
a.reflect_partial_eq(b).unwrap_or_default(),
|
||||
"expected TestEnum::C{{value: 123}} == TestEnum::C{{value: 123}}"
|
||||
);
|
||||
|
||||
let a: &dyn Reflect = &TestEnum::C { value: 123 };
|
||||
let b: &dyn Reflect = &TestEnum::C { value: 321 };
|
||||
let a: &dyn PartialReflect = &TestEnum::C { value: 123 };
|
||||
let b: &dyn PartialReflect = &TestEnum::C { value: 321 };
|
||||
assert!(
|
||||
!a.reflect_partial_eq(b).unwrap_or_default(),
|
||||
"expected TestEnum::C{{value: 123}} != TestEnum::C{{value: 321}}"
|
||||
);
|
||||
|
||||
let a: &dyn Reflect = &TestEnum::C { value: 123 };
|
||||
let b: &dyn Reflect = &TestEnum::C1 { value: 123 };
|
||||
let a: &dyn PartialReflect = &TestEnum::C { value: 123 };
|
||||
let b: &dyn PartialReflect = &TestEnum::C1 { value: 123 };
|
||||
assert!(
|
||||
!a.reflect_partial_eq(b).unwrap_or_default(),
|
||||
"expected TestEnum::C{{value: 123}} != TestEnum::C1{{value: 123}}"
|
||||
);
|
||||
|
||||
let a: &dyn Reflect = &TestEnum::C { value: 123 };
|
||||
let b: &dyn Reflect = &TestEnum::C2 { value: 1.23 };
|
||||
let a: &dyn PartialReflect = &TestEnum::C { value: 123 };
|
||||
let b: &dyn PartialReflect = &TestEnum::C2 { value: 1.23 };
|
||||
assert!(
|
||||
!a.reflect_partial_eq(b).unwrap_or_default(),
|
||||
"expected TestEnum::C{{value: 123}} != TestEnum::C2{{value: 1.23}}"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::attributes::{impl_custom_attribute_methods, CustomAttributes};
|
||||
use crate::{MaybeTyped, Reflect, TypeInfo, TypePath, TypePathTable};
|
||||
use crate::{MaybeTyped, PartialReflect, TypeInfo, TypePath, TypePathTable};
|
||||
use std::any::{Any, TypeId};
|
||||
use std::sync::Arc;
|
||||
|
||||
|
@ -17,7 +17,7 @@ pub struct NamedField {
|
|||
|
||||
impl NamedField {
|
||||
/// Create a new [`NamedField`].
|
||||
pub fn new<T: Reflect + MaybeTyped + TypePath>(name: &'static str) -> Self {
|
||||
pub fn new<T: PartialReflect + MaybeTyped + TypePath>(name: &'static str) -> Self {
|
||||
Self {
|
||||
name,
|
||||
type_info: T::maybe_type_info,
|
||||
|
@ -106,7 +106,7 @@ pub struct UnnamedField {
|
|||
}
|
||||
|
||||
impl UnnamedField {
|
||||
pub fn new<T: Reflect + MaybeTyped + TypePath>(index: usize) -> Self {
|
||||
pub fn new<T: PartialReflect + MaybeTyped + TypePath>(index: usize) -> Self {
|
||||
Self {
|
||||
index,
|
||||
type_info: T::maybe_type_info,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::{FromType, Reflect};
|
||||
use crate::{FromType, PartialReflect, Reflect};
|
||||
|
||||
/// A trait that enables types to be dynamically constructed from reflected data.
|
||||
///
|
||||
|
@ -27,7 +27,7 @@ use crate::{FromType, Reflect};
|
|||
)]
|
||||
pub trait FromReflect: Reflect + Sized {
|
||||
/// Constructs a concrete instance of `Self` from a reflected value.
|
||||
fn from_reflect(reflect: &dyn Reflect) -> Option<Self>;
|
||||
fn from_reflect(reflect: &dyn PartialReflect) -> Option<Self>;
|
||||
|
||||
/// Attempts to downcast the given value to `Self` using,
|
||||
/// constructing the value using [`from_reflect`] if that fails.
|
||||
|
@ -39,8 +39,10 @@ pub trait FromReflect: Reflect + Sized {
|
|||
/// [`from_reflect`]: Self::from_reflect
|
||||
/// [`DynamicStruct`]: crate::DynamicStruct
|
||||
/// [`DynamicList`]: crate::DynamicList
|
||||
fn take_from_reflect(reflect: Box<dyn Reflect>) -> Result<Self, Box<dyn Reflect>> {
|
||||
match reflect.take::<Self>() {
|
||||
fn take_from_reflect(
|
||||
reflect: Box<dyn PartialReflect>,
|
||||
) -> Result<Self, Box<dyn PartialReflect>> {
|
||||
match reflect.try_take::<Self>() {
|
||||
Ok(value) => Ok(value),
|
||||
Err(value) => match Self::from_reflect(value.as_ref()) {
|
||||
None => Err(value),
|
||||
|
@ -101,7 +103,7 @@ pub trait FromReflect: Reflect + Sized {
|
|||
/// [`DynamicEnum`]: crate::DynamicEnum
|
||||
#[derive(Clone)]
|
||||
pub struct ReflectFromReflect {
|
||||
from_reflect: fn(&dyn Reflect) -> Option<Box<dyn Reflect>>,
|
||||
from_reflect: fn(&dyn PartialReflect) -> Option<Box<dyn Reflect>>,
|
||||
}
|
||||
|
||||
impl ReflectFromReflect {
|
||||
|
@ -110,7 +112,7 @@ impl ReflectFromReflect {
|
|||
/// This will convert the object to a concrete type if it wasn't already, and return
|
||||
/// the value as `Box<dyn Reflect>`.
|
||||
#[allow(clippy::wrong_self_convention)]
|
||||
pub fn from_reflect(&self, reflect_value: &dyn Reflect) -> Option<Box<dyn Reflect>> {
|
||||
pub fn from_reflect(&self, reflect_value: &dyn PartialReflect) -> Option<Box<dyn Reflect>> {
|
||||
(self.from_reflect)(reflect_value)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::func::args::{ArgError, FromArg, Ownership};
|
||||
use crate::{Reflect, TypePath};
|
||||
use crate::{PartialReflect, Reflect, TypePath};
|
||||
use std::ops::Deref;
|
||||
|
||||
/// Represents an argument that can be passed to a [`DynamicFunction`], [`DynamicClosure`],
|
||||
|
@ -83,7 +83,7 @@ impl<'a> Arg<'a> {
|
|||
/// ```
|
||||
pub fn take_owned<T: Reflect + TypePath>(self) -> Result<T, ArgError> {
|
||||
match self.value {
|
||||
ArgValue::Owned(arg) => arg.take().map_err(|arg| ArgError::UnexpectedType {
|
||||
ArgValue::Owned(arg) => arg.try_take().map_err(|arg| ArgError::UnexpectedType {
|
||||
index: self.index,
|
||||
expected: std::borrow::Cow::Borrowed(T::type_path()),
|
||||
received: std::borrow::Cow::Owned(arg.reflect_type_path().to_string()),
|
||||
|
@ -124,11 +124,13 @@ impl<'a> Arg<'a> {
|
|||
received: Ownership::Owned,
|
||||
}),
|
||||
ArgValue::Ref(arg) => {
|
||||
Ok(arg.downcast_ref().ok_or_else(|| ArgError::UnexpectedType {
|
||||
index: self.index,
|
||||
expected: std::borrow::Cow::Borrowed(T::type_path()),
|
||||
received: std::borrow::Cow::Owned(arg.reflect_type_path().to_string()),
|
||||
})?)
|
||||
Ok(arg
|
||||
.try_downcast_ref()
|
||||
.ok_or_else(|| ArgError::UnexpectedType {
|
||||
index: self.index,
|
||||
expected: std::borrow::Cow::Borrowed(T::type_path()),
|
||||
received: std::borrow::Cow::Owned(arg.reflect_type_path().to_string()),
|
||||
})?)
|
||||
}
|
||||
ArgValue::Mut(_) => Err(ArgError::InvalidOwnership {
|
||||
index: self.index,
|
||||
|
@ -167,11 +169,13 @@ impl<'a> Arg<'a> {
|
|||
}),
|
||||
ArgValue::Mut(arg) => {
|
||||
let received = std::borrow::Cow::Owned(arg.reflect_type_path().to_string());
|
||||
Ok(arg.downcast_mut().ok_or_else(|| ArgError::UnexpectedType {
|
||||
index: self.index,
|
||||
expected: std::borrow::Cow::Borrowed(T::type_path()),
|
||||
received,
|
||||
})?)
|
||||
Ok(arg
|
||||
.try_downcast_mut()
|
||||
.ok_or_else(|| ArgError::UnexpectedType {
|
||||
index: self.index,
|
||||
expected: std::borrow::Cow::Borrowed(T::type_path()),
|
||||
received,
|
||||
})?)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -182,13 +186,13 @@ impl<'a> Arg<'a> {
|
|||
/// [`DynamicFunction`]: crate::func::DynamicFunction
|
||||
#[derive(Debug)]
|
||||
pub enum ArgValue<'a> {
|
||||
Owned(Box<dyn Reflect>),
|
||||
Ref(&'a dyn Reflect),
|
||||
Mut(&'a mut dyn Reflect),
|
||||
Owned(Box<dyn PartialReflect>),
|
||||
Ref(&'a dyn PartialReflect),
|
||||
Mut(&'a mut dyn PartialReflect),
|
||||
}
|
||||
|
||||
impl<'a> Deref for ArgValue<'a> {
|
||||
type Target = dyn Reflect;
|
||||
type Target = dyn PartialReflect;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
match self {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::func::args::{Arg, ArgValue, FromArg};
|
||||
use crate::func::ArgError;
|
||||
use crate::{Reflect, TypePath};
|
||||
use crate::{PartialReflect, Reflect, TypePath};
|
||||
use std::collections::VecDeque;
|
||||
|
||||
/// A list of arguments that can be passed to a [`DynamicFunction`], [`DynamicClosure`],
|
||||
|
@ -70,7 +70,7 @@ impl<'a> ArgList<'a> {
|
|||
///
|
||||
/// If an argument was previously removed from the beginning of the list,
|
||||
/// this method will also re-index the list.
|
||||
pub fn push_ref(self, arg: &'a dyn Reflect) -> Self {
|
||||
pub fn push_ref(self, arg: &'a dyn PartialReflect) -> Self {
|
||||
self.push_arg(ArgValue::Ref(arg))
|
||||
}
|
||||
|
||||
|
@ -78,7 +78,7 @@ impl<'a> ArgList<'a> {
|
|||
///
|
||||
/// If an argument was previously removed from the beginning of the list,
|
||||
/// this method will also re-index the list.
|
||||
pub fn push_mut(self, arg: &'a mut dyn Reflect) -> Self {
|
||||
pub fn push_mut(self, arg: &'a mut dyn PartialReflect) -> Self {
|
||||
self.push_arg(ArgValue::Mut(arg))
|
||||
}
|
||||
|
||||
|
@ -86,7 +86,7 @@ impl<'a> ArgList<'a> {
|
|||
///
|
||||
/// If an argument was previously removed from the beginning of the list,
|
||||
/// this method will also re-index the list.
|
||||
pub fn push_owned(self, arg: impl Reflect) -> Self {
|
||||
pub fn push_owned(self, arg: impl PartialReflect) -> Self {
|
||||
self.push_arg(ArgValue::Owned(Box::new(arg)))
|
||||
}
|
||||
|
||||
|
@ -94,7 +94,7 @@ impl<'a> ArgList<'a> {
|
|||
///
|
||||
/// If an argument was previously removed from the beginning of the list,
|
||||
/// this method will also re-index the list.
|
||||
pub fn push_boxed(self, arg: Box<dyn Reflect>) -> Self {
|
||||
pub fn push_boxed(self, arg: Box<dyn PartialReflect>) -> Self {
|
||||
self.push_arg(ArgValue::Owned(arg))
|
||||
}
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ use crate::func::{FunctionResult, IntoClosure, ReturnInfo};
|
|||
/// let value = func.call(args).unwrap().unwrap_owned();
|
||||
///
|
||||
/// // Check the result:
|
||||
/// assert_eq!(value.take::<String>().unwrap(), "Hello, world!!!");
|
||||
/// assert_eq!(value.try_take::<String>().unwrap(), "Hello, world!!!");
|
||||
/// ```
|
||||
///
|
||||
/// [`DynamicClosureMut`]: crate::func::closures::DynamicClosureMut
|
||||
|
@ -110,7 +110,7 @@ impl<'env> DynamicClosure<'env> {
|
|||
/// let mut func = add.into_closure().with_name("add");
|
||||
/// let args = ArgList::new().push_owned(25_i32).push_owned(75_i32);
|
||||
/// let result = func.call(args).unwrap().unwrap_owned();
|
||||
/// assert_eq!(result.take::<i32>().unwrap(), 123);
|
||||
/// assert_eq!(result.try_take::<i32>().unwrap(), 123);
|
||||
/// ```
|
||||
pub fn call<'a>(&self, args: ArgList<'a>) -> FunctionResult<'a> {
|
||||
(self.func)(args)
|
||||
|
|
|
@ -42,7 +42,7 @@ use crate::func::{FunctionResult, IntoClosureMut, ReturnInfo};
|
|||
/// let value = func.call(args).unwrap().unwrap_owned();
|
||||
///
|
||||
/// // Check the result:
|
||||
/// assert_eq!(value.take::<i32>().unwrap(), 2);
|
||||
/// assert_eq!(value.try_take::<i32>().unwrap(), 2);
|
||||
///
|
||||
/// // Note that `func` still has a reference to `list`,
|
||||
/// // so we need to drop it before we can access `list` again.
|
||||
|
@ -125,7 +125,7 @@ impl<'env> DynamicClosureMut<'env> {
|
|||
/// let mut func = add.into_closure_mut().with_name("add");
|
||||
/// let args = ArgList::new().push_owned(25_i32).push_owned(75_i32);
|
||||
/// let result = func.call(args).unwrap().unwrap_owned();
|
||||
/// assert_eq!(result.take::<i32>().unwrap(), 100);
|
||||
/// assert_eq!(result.try_take::<i32>().unwrap(), 100);
|
||||
/// ```
|
||||
///
|
||||
/// [`call_once`]: DynamicClosureMut::call_once
|
||||
|
|
|
@ -36,7 +36,7 @@ mod tests {
|
|||
let func = (|a: i32, b: i32| a + b + c).into_closure();
|
||||
let args = ArgList::new().push_owned(25_i32).push_owned(75_i32);
|
||||
let result = func.call(args).unwrap().unwrap_owned();
|
||||
assert_eq!(result.downcast_ref::<i32>(), Some(&123));
|
||||
assert_eq!(result.try_downcast_ref::<i32>(), Some(&123));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -48,7 +48,7 @@ mod tests {
|
|||
let func = add.into_closure();
|
||||
let args = ArgList::new().push_owned(25_i32).push_owned(75_i32);
|
||||
let result = func.call(args).unwrap().unwrap_owned();
|
||||
assert_eq!(result.downcast_ref::<i32>(), Some(&100));
|
||||
assert_eq!(result.try_downcast_ref::<i32>(), Some(&100));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -40,7 +40,7 @@ mod tests {
|
|||
let func = (|a: i32, b: i32| a + b + c).into_closure();
|
||||
let args = ArgList::new().push_owned(25_i32).push_owned(75_i32);
|
||||
let result = func.call(args).unwrap().unwrap_owned();
|
||||
assert_eq!(result.downcast_ref::<i32>(), Some(&123));
|
||||
assert_eq!(result.try_downcast_ref::<i32>(), Some(&123));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -61,7 +61,7 @@ mod tests {
|
|||
let mut func = add.into_closure_mut();
|
||||
let args = ArgList::new().push_owned(25_i32).push_owned(75_i32);
|
||||
let result = func.call(args).unwrap().unwrap_owned();
|
||||
assert_eq!(result.downcast_ref::<i32>(), Some(&100));
|
||||
assert_eq!(result.try_downcast_ref::<i32>(), Some(&100));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -41,7 +41,7 @@ use crate::func::{FunctionResult, IntoFunction, ReturnInfo};
|
|||
/// let value = func.call(args).unwrap().unwrap_owned();
|
||||
///
|
||||
/// // Check the result:
|
||||
/// assert_eq!(value.downcast_ref::<i32>(), Some(&100));
|
||||
/// assert_eq!(value.try_downcast_ref::<i32>(), Some(&100));
|
||||
/// ```
|
||||
///
|
||||
/// However, in some cases, these functions may need to be created manually:
|
||||
|
@ -82,7 +82,7 @@ use crate::func::{FunctionResult, IntoFunction, ReturnInfo};
|
|||
/// let value = func.call(args).unwrap().unwrap_mut();
|
||||
///
|
||||
/// // Mutate the return value:
|
||||
/// value.downcast_mut::<String>().unwrap().push_str("!!!");
|
||||
/// value.try_downcast_mut::<String>().unwrap().push_str("!!!");
|
||||
///
|
||||
/// // Check the result:
|
||||
/// assert_eq!(list, vec!["Hello, World!!!"]);
|
||||
|
@ -151,7 +151,7 @@ impl DynamicFunction {
|
|||
/// let func = add.into_function();
|
||||
/// let args = ArgList::new().push_owned(25_i32).push_owned(75_i32);
|
||||
/// let result = func.call(args).unwrap().unwrap_owned();
|
||||
/// assert_eq!(result.take::<i32>().unwrap(), 100);
|
||||
/// assert_eq!(result.try_take::<i32>().unwrap(), 100);
|
||||
/// ```
|
||||
pub fn call<'a>(&self, args: ArgList<'a>) -> FunctionResult<'a> {
|
||||
(self.func)(args)
|
||||
|
@ -269,7 +269,7 @@ mod tests {
|
|||
.call(ArgList::new().push_owned(0_usize).push_ref(&list))
|
||||
.unwrap()
|
||||
.unwrap_ref()
|
||||
.downcast_ref::<String>()
|
||||
.try_downcast_ref::<String>()
|
||||
.unwrap();
|
||||
assert_eq!(value, "foo");
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@ mod tests {
|
|||
let func = add.into_function();
|
||||
let args = ArgList::new().push_owned(25_i32).push_owned(75_i32);
|
||||
let result = func.call(args).unwrap().unwrap_owned();
|
||||
assert_eq!(result.downcast_ref::<i32>(), Some(&100));
|
||||
assert_eq!(result.try_downcast_ref::<i32>(), Some(&100));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -79,7 +79,7 @@ mod tests {
|
|||
let func = (add as fn(i32, i32) -> i32).into_function();
|
||||
let args = ArgList::new().push_owned(25_i32).push_owned(75_i32);
|
||||
let result = func.call(args).unwrap().unwrap_owned();
|
||||
assert_eq!(result.downcast_ref::<i32>(), Some(&100));
|
||||
assert_eq!(result.try_downcast_ref::<i32>(), Some(&100));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -87,7 +87,7 @@ mod tests {
|
|||
let func = (|a: i32, b: i32| a + b).into_function();
|
||||
let args = ArgList::new().push_owned(25_i32).push_owned(75_i32);
|
||||
let result = func.call(args).unwrap().unwrap_owned();
|
||||
assert_eq!(result.downcast_ref::<i32>(), Some(&100));
|
||||
assert_eq!(result.try_downcast_ref::<i32>(), Some(&100));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -107,7 +107,7 @@ mod tests {
|
|||
let func = Foo::add.into_function();
|
||||
let args = ArgList::new().push_ref(&foo_a).push_ref(&foo_b);
|
||||
let result = func.call(args).unwrap().unwrap_owned();
|
||||
assert_eq!(result.downcast_ref::<Foo>(), Some(&Foo(100)));
|
||||
assert_eq!(result.try_downcast_ref::<Foo>(), Some(&Foo(100)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -120,7 +120,7 @@ mod tests {
|
|||
let args = ArgList::new();
|
||||
let result = func.call(args).unwrap().unwrap_owned();
|
||||
assert_eq!(
|
||||
result.downcast_ref::<String>(),
|
||||
result.try_downcast_ref::<String>(),
|
||||
Some(&String::from("Hello, World!"))
|
||||
);
|
||||
}
|
||||
|
@ -148,7 +148,7 @@ mod tests {
|
|||
.push_owned(String::from("Hello, World!"))
|
||||
.push_ref(&true);
|
||||
let result = func.call(args).unwrap().unwrap_ref();
|
||||
assert_eq!(result.downcast_ref::<i32>(), Some(&123));
|
||||
assert_eq!(result.try_downcast_ref::<i32>(), Some(&123));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -164,7 +164,7 @@ mod tests {
|
|||
.push_owned(String::from("Hello, World!"))
|
||||
.push_ref(&true);
|
||||
let result = func.call(args).unwrap().unwrap_mut();
|
||||
assert_eq!(result.downcast_mut::<i32>(), Some(&mut 123));
|
||||
assert_eq!(result.try_downcast_mut::<i32>(), Some(&mut 123));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -10,12 +10,12 @@
|
|||
//! via an [`ArgList`].
|
||||
//!
|
||||
//! This returns a [`FunctionResult`] containing the [`Return`] value,
|
||||
//! which can be used to extract a [`Reflect`] trait object.
|
||||
//! which can be used to extract a [`PartialReflect`] trait object.
|
||||
//!
|
||||
//! # Example
|
||||
//!
|
||||
//! ```
|
||||
//! # use bevy_reflect::Reflect;
|
||||
//! # use bevy_reflect::PartialReflect;
|
||||
//! # use bevy_reflect::func::args::ArgList;
|
||||
//! # use bevy_reflect::func::{DynamicFunction, FunctionResult, IntoFunction, Return};
|
||||
//! fn add(a: i32, b: i32) -> i32 {
|
||||
|
@ -27,10 +27,10 @@
|
|||
//! // Pushing a known type with owned ownership
|
||||
//! .push_owned(25_i32)
|
||||
//! // Pushing a reflected type with owned ownership
|
||||
//! .push_boxed(Box::new(75_i32) as Box<dyn Reflect>);
|
||||
//! .push_boxed(Box::new(75_i32) as Box<dyn PartialReflect>);
|
||||
//! let result: FunctionResult = func.call(args);
|
||||
//! let value: Return = result.unwrap();
|
||||
//! assert_eq!(value.unwrap_owned().downcast_ref::<i32>(), Some(&100));
|
||||
//! assert_eq!(value.unwrap_owned().try_downcast_ref::<i32>(), Some(&100));
|
||||
//! ```
|
||||
//!
|
||||
//! # Functions vs Closures
|
||||
|
@ -95,6 +95,7 @@
|
|||
//! For other functions that don't conform to one of the above signatures,
|
||||
//! [`DynamicFunction`] and [`DynamicClosure`] can instead be created manually.
|
||||
//!
|
||||
//! [`PartialReflect`]: crate::PartialReflect
|
||||
//! [`Reflect`]: crate::Reflect
|
||||
//! [lack of variadic generics]: https://poignardazur.github.io/2024/05/25/report-on-rustnl-variadics/
|
||||
//! [coherence issues]: https://doc.rust-lang.org/rustc/lints/listing/warn-by-default.html#coherence-leak-check
|
||||
|
|
|
@ -42,7 +42,7 @@ use crate::{Reflect, TypePath};
|
|||
/// let args = ArgList::new().push_owned(25_i32).push_owned(75_i32);
|
||||
///
|
||||
/// let value = add.reflect_call(args).unwrap().unwrap_owned();
|
||||
/// assert_eq!(value.take::<i32>().unwrap(), 100);
|
||||
/// assert_eq!(value.try_take::<i32>().unwrap(), 100);
|
||||
/// ```
|
||||
///
|
||||
/// # Trait Parameters
|
||||
|
|
|
@ -351,7 +351,7 @@ mod tests {
|
|||
|
||||
let function = registry.get(std::any::type_name_of_val(&foo)).unwrap();
|
||||
let value = function.call(ArgList::new()).unwrap().unwrap_owned();
|
||||
assert_eq!(value.downcast_ref::<i32>(), Some(&123));
|
||||
assert_eq!(value.try_downcast_ref::<i32>(), Some(&123));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -361,7 +361,7 @@ mod tests {
|
|||
|
||||
let function = registry.get("foo").unwrap();
|
||||
let value = function.call(ArgList::new()).unwrap().unwrap_owned();
|
||||
assert_eq!(value.downcast_ref::<i32>(), Some(&123));
|
||||
assert_eq!(value.try_downcast_ref::<i32>(), Some(&123));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -377,7 +377,7 @@ mod tests {
|
|||
|
||||
let function = registry.get("custom_name").unwrap();
|
||||
let value = function.call(ArgList::new()).unwrap().unwrap_owned();
|
||||
assert_eq!(value.downcast_ref::<i32>(), Some(&123));
|
||||
assert_eq!(value.try_downcast_ref::<i32>(), Some(&123));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -404,7 +404,7 @@ mod tests {
|
|||
|
||||
let function = registry.get(name).unwrap();
|
||||
let value = function.call(ArgList::new()).unwrap().unwrap_owned();
|
||||
assert_eq!(value.downcast_ref::<i32>(), Some(&123));
|
||||
assert_eq!(value.try_downcast_ref::<i32>(), Some(&123));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -429,7 +429,7 @@ mod tests {
|
|||
|
||||
let function = registry.get(name).unwrap();
|
||||
let value = function.call(ArgList::new()).unwrap().unwrap_owned();
|
||||
assert_eq!(value.downcast_ref::<i32>(), Some(&321));
|
||||
assert_eq!(value.try_downcast_ref::<i32>(), Some(&321));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::Reflect;
|
||||
use crate::PartialReflect;
|
||||
|
||||
/// The return type of a [`DynamicFunction`] or [`DynamicClosure`].
|
||||
///
|
||||
|
@ -9,11 +9,11 @@ pub enum Return<'a> {
|
|||
/// The function returns nothing (i.e. it returns `()`).
|
||||
Unit,
|
||||
/// The function returns an owned value.
|
||||
Owned(Box<dyn Reflect>),
|
||||
Owned(Box<dyn PartialReflect>),
|
||||
/// The function returns a reference to a value.
|
||||
Ref(&'a dyn Reflect),
|
||||
Ref(&'a dyn PartialReflect),
|
||||
/// The function returns a mutable reference to a value.
|
||||
Mut(&'a mut dyn Reflect),
|
||||
Mut(&'a mut dyn PartialReflect),
|
||||
}
|
||||
|
||||
impl<'a> Return<'a> {
|
||||
|
@ -27,7 +27,7 @@ impl<'a> Return<'a> {
|
|||
/// # Panics
|
||||
///
|
||||
/// Panics if the return value is not [`Self::Owned`].
|
||||
pub fn unwrap_owned(self) -> Box<dyn Reflect> {
|
||||
pub fn unwrap_owned(self) -> Box<dyn PartialReflect> {
|
||||
match self {
|
||||
Return::Owned(value) => value,
|
||||
_ => panic!("expected owned value"),
|
||||
|
@ -39,7 +39,7 @@ impl<'a> Return<'a> {
|
|||
/// # Panics
|
||||
///
|
||||
/// Panics if the return value is not [`Self::Ref`].
|
||||
pub fn unwrap_ref(self) -> &'a dyn Reflect {
|
||||
pub fn unwrap_ref(self) -> &'a dyn PartialReflect {
|
||||
match self {
|
||||
Return::Ref(value) => value,
|
||||
_ => panic!("expected reference value"),
|
||||
|
@ -51,7 +51,7 @@ impl<'a> Return<'a> {
|
|||
/// # Panics
|
||||
///
|
||||
/// Panics if the return value is not [`Self::Mut`].
|
||||
pub fn unwrap_mut(self) -> &'a mut dyn Reflect {
|
||||
pub fn unwrap_mut(self) -> &'a mut dyn PartialReflect {
|
||||
match self {
|
||||
Return::Mut(value) => value,
|
||||
_ => panic!("expected mutable reference value"),
|
||||
|
|
|
@ -6,32 +6,32 @@ use std::any::Any;
|
|||
use crate::utility::GenericTypeInfoCell;
|
||||
use crate::{
|
||||
self as bevy_reflect, ApplyError, FromReflect, FromType, GetTypeRegistration, List, ListInfo,
|
||||
ListIter, MaybeTyped, Reflect, ReflectFromPtr, ReflectKind, ReflectMut, ReflectOwned,
|
||||
ReflectRef, TypeInfo, TypePath, TypeRegistration, Typed,
|
||||
ListIter, MaybeTyped, PartialReflect, Reflect, ReflectFromPtr, ReflectKind, ReflectMut,
|
||||
ReflectOwned, ReflectRef, TypeInfo, TypePath, TypeRegistration, Typed,
|
||||
};
|
||||
|
||||
impl<T: SmallArray + TypePath + Send + Sync> List for SmallVec<T>
|
||||
where
|
||||
T::Item: FromReflect + MaybeTyped + TypePath,
|
||||
{
|
||||
fn get(&self, index: usize) -> Option<&dyn Reflect> {
|
||||
fn get(&self, index: usize) -> Option<&dyn PartialReflect> {
|
||||
if index < SmallVec::len(self) {
|
||||
Some(&self[index] as &dyn Reflect)
|
||||
Some(&self[index] as &dyn PartialReflect)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn get_mut(&mut self, index: usize) -> Option<&mut dyn Reflect> {
|
||||
fn get_mut(&mut self, index: usize) -> Option<&mut dyn PartialReflect> {
|
||||
if index < SmallVec::len(self) {
|
||||
Some(&mut self[index] as &mut dyn Reflect)
|
||||
Some(&mut self[index] as &mut dyn PartialReflect)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn insert(&mut self, index: usize, value: Box<dyn Reflect>) {
|
||||
let value = value.take::<T::Item>().unwrap_or_else(|value| {
|
||||
fn insert(&mut self, index: usize, value: Box<dyn PartialReflect>) {
|
||||
let value = value.try_take::<T::Item>().unwrap_or_else(|value| {
|
||||
<T as SmallArray>::Item::from_reflect(&*value).unwrap_or_else(|| {
|
||||
panic!(
|
||||
"Attempted to insert invalid value of type {}.",
|
||||
|
@ -42,12 +42,12 @@ where
|
|||
SmallVec::insert(self, index, value);
|
||||
}
|
||||
|
||||
fn remove(&mut self, index: usize) -> Box<dyn Reflect> {
|
||||
fn remove(&mut self, index: usize) -> Box<dyn PartialReflect> {
|
||||
Box::new(self.remove(index))
|
||||
}
|
||||
|
||||
fn push(&mut self, value: Box<dyn Reflect>) {
|
||||
let value = value.take::<T::Item>().unwrap_or_else(|value| {
|
||||
fn push(&mut self, value: Box<dyn PartialReflect>) {
|
||||
let value = value.try_take::<T::Item>().unwrap_or_else(|value| {
|
||||
<T as SmallArray>::Item::from_reflect(&*value).unwrap_or_else(|| {
|
||||
panic!(
|
||||
"Attempted to push invalid value of type {}.",
|
||||
|
@ -58,8 +58,9 @@ where
|
|||
SmallVec::push(self, value);
|
||||
}
|
||||
|
||||
fn pop(&mut self) -> Option<Box<dyn Reflect>> {
|
||||
self.pop().map(|value| Box::new(value) as Box<dyn Reflect>)
|
||||
fn pop(&mut self) -> Option<Box<dyn PartialReflect>> {
|
||||
self.pop()
|
||||
.map(|value| Box::new(value) as Box<dyn PartialReflect>)
|
||||
}
|
||||
|
||||
fn len(&self) -> usize {
|
||||
|
@ -70,14 +71,13 @@ where
|
|||
ListIter::new(self)
|
||||
}
|
||||
|
||||
fn drain(self: Box<Self>) -> Vec<Box<dyn Reflect>> {
|
||||
fn drain(self: Box<Self>) -> Vec<Box<dyn PartialReflect>> {
|
||||
self.into_iter()
|
||||
.map(|value| Box::new(value) as Box<dyn Reflect>)
|
||||
.map(|value| Box::new(value) as Box<dyn PartialReflect>)
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: SmallArray + TypePath + Send + Sync> Reflect for SmallVec<T>
|
||||
impl<T: SmallArray + TypePath + Send + Sync> PartialReflect for SmallVec<T>
|
||||
where
|
||||
T::Item: FromReflect + MaybeTyped + TypePath,
|
||||
{
|
||||
|
@ -85,6 +85,68 @@ where
|
|||
Some(<Self as Typed>::type_info())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn into_partial_reflect(self: Box<Self>) -> Box<dyn PartialReflect> {
|
||||
self
|
||||
}
|
||||
|
||||
fn as_partial_reflect(&self) -> &dyn PartialReflect {
|
||||
self
|
||||
}
|
||||
|
||||
fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect {
|
||||
self
|
||||
}
|
||||
|
||||
fn try_into_reflect(self: Box<Self>) -> Result<Box<dyn Reflect>, Box<dyn PartialReflect>> {
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
fn try_as_reflect(&self) -> Option<&dyn Reflect> {
|
||||
Some(self)
|
||||
}
|
||||
|
||||
fn try_as_reflect_mut(&mut self) -> Option<&mut dyn Reflect> {
|
||||
Some(self)
|
||||
}
|
||||
|
||||
fn apply(&mut self, value: &dyn PartialReflect) {
|
||||
crate::list_apply(self, value);
|
||||
}
|
||||
|
||||
fn try_apply(&mut self, value: &dyn PartialReflect) -> Result<(), ApplyError> {
|
||||
crate::list_try_apply(self, value)
|
||||
}
|
||||
|
||||
fn reflect_kind(&self) -> ReflectKind {
|
||||
ReflectKind::List
|
||||
}
|
||||
|
||||
fn reflect_ref(&self) -> ReflectRef {
|
||||
ReflectRef::List(self)
|
||||
}
|
||||
|
||||
fn reflect_mut(&mut self) -> ReflectMut {
|
||||
ReflectMut::List(self)
|
||||
}
|
||||
|
||||
fn reflect_owned(self: Box<Self>) -> ReflectOwned {
|
||||
ReflectOwned::List(self)
|
||||
}
|
||||
|
||||
fn clone_value(&self) -> Box<dyn PartialReflect> {
|
||||
Box::new(self.clone_dynamic())
|
||||
}
|
||||
|
||||
fn reflect_partial_eq(&self, value: &dyn PartialReflect) -> Option<bool> {
|
||||
crate::list_partial_eq(self, value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: SmallArray + TypePath + Send + Sync> Reflect for SmallVec<T>
|
||||
where
|
||||
T::Item: FromReflect + MaybeTyped + TypePath,
|
||||
{
|
||||
fn into_any(self: Box<Self>) -> Box<dyn Any> {
|
||||
self
|
||||
}
|
||||
|
@ -109,42 +171,10 @@ where
|
|||
self
|
||||
}
|
||||
|
||||
fn apply(&mut self, value: &dyn Reflect) {
|
||||
crate::list_apply(self, value);
|
||||
}
|
||||
|
||||
fn try_apply(&mut self, value: &dyn Reflect) -> Result<(), ApplyError> {
|
||||
crate::list_try_apply(self, value)
|
||||
}
|
||||
|
||||
fn set(&mut self, value: Box<dyn Reflect>) -> Result<(), Box<dyn Reflect>> {
|
||||
*self = value.take()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn reflect_kind(&self) -> ReflectKind {
|
||||
ReflectKind::List
|
||||
}
|
||||
|
||||
fn reflect_ref(&self) -> ReflectRef {
|
||||
ReflectRef::List(self)
|
||||
}
|
||||
|
||||
fn reflect_mut(&mut self) -> ReflectMut {
|
||||
ReflectMut::List(self)
|
||||
}
|
||||
|
||||
fn reflect_owned(self: Box<Self>) -> ReflectOwned {
|
||||
ReflectOwned::List(self)
|
||||
}
|
||||
|
||||
fn clone_value(&self) -> Box<dyn Reflect> {
|
||||
Box::new(self.clone_dynamic())
|
||||
}
|
||||
|
||||
fn reflect_partial_eq(&self, value: &dyn Reflect) -> Option<bool> {
|
||||
crate::list_partial_eq(self, value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: SmallArray + TypePath + Send + Sync + 'static> Typed for SmallVec<T>
|
||||
|
@ -163,7 +193,7 @@ impl<T: SmallArray + TypePath + Send + Sync> FromReflect for SmallVec<T>
|
|||
where
|
||||
T::Item: FromReflect + MaybeTyped + TypePath,
|
||||
{
|
||||
fn from_reflect(reflect: &dyn Reflect) -> Option<Self> {
|
||||
fn from_reflect(reflect: &dyn PartialReflect) -> Option<Self> {
|
||||
if let ReflectRef::List(ref_list) = reflect.reflect_ref() {
|
||||
let mut new_list = Self::with_capacity(ref_list.len());
|
||||
for field in ref_list.iter() {
|
||||
|
|
|
@ -6,14 +6,14 @@ impl_reflect_value!(::smol_str::SmolStr(Debug, Hash, PartialEq, Default));
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{FromReflect, Reflect};
|
||||
use crate::{FromReflect, PartialReflect};
|
||||
use smol_str::SmolStr;
|
||||
|
||||
#[test]
|
||||
fn should_partial_eq_smolstr() {
|
||||
let a: &dyn Reflect = &SmolStr::new("A");
|
||||
let a2: &dyn Reflect = &SmolStr::new("A");
|
||||
let b: &dyn Reflect = &SmolStr::new("B");
|
||||
let a: &dyn PartialReflect = &SmolStr::new("A");
|
||||
let a2: &dyn PartialReflect = &SmolStr::new("A");
|
||||
let b: &dyn PartialReflect = &SmolStr::new("B");
|
||||
assert_eq!(Some(true), a.reflect_partial_eq(a2));
|
||||
assert_eq!(Some(false), a.reflect_partial_eq(b));
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -26,15 +26,60 @@
|
|||
//! It's important to note that because of missing features in Rust,
|
||||
//! there are some [limitations] with this crate.
|
||||
//!
|
||||
//! # The `Reflect` Trait
|
||||
//! # The `Reflect` and `PartialReflect` traits
|
||||
//!
|
||||
//! At the core of [`bevy_reflect`] is the [`Reflect`] trait.
|
||||
//! At the root of [`bevy_reflect`] is the [`PartialReflect`] trait.
|
||||
//!
|
||||
//! One of its primary purposes is to allow all implementors to be passed around
|
||||
//! as a `dyn Reflect` trait object.
|
||||
//! This allows any such type to be operated upon completely dynamically (at a small [runtime cost]).
|
||||
//! Its purpose is to allow dynamic [introspection] of values,
|
||||
//! following Rust's type system through a system of [subtraits].
|
||||
//!
|
||||
//! Implementing the trait is easily done using the provided [derive macro]:
|
||||
//! Its primary purpose is to allow all implementors to be passed around
|
||||
//! as a `dyn PartialReflect` trait object in one of the following forms:
|
||||
//! * `&dyn PartialReflect`
|
||||
//! * `&mut dyn PartialReflect`
|
||||
//! * `Box<dyn PartialReflect>`
|
||||
//!
|
||||
//! This allows values of types implementing `PartialReflect`
|
||||
//! to be operated upon completely dynamically (at a small [runtime cost]).
|
||||
//!
|
||||
//! Building on `PartialReflect` is the [`Reflect`] trait.
|
||||
//!
|
||||
//! `PartialReflect` is a supertrait of `Reflect`
|
||||
//! so any type implementing `Reflect` implements `PartialReflect` by definition.
|
||||
//! `dyn Reflect` trait objects can be used similarly to `dyn PartialReflect`,
|
||||
//! but `Reflect` is also often used in trait bounds (like `T: Reflect`).
|
||||
//!
|
||||
//! The distinction between `PartialReflect` and `Reflect` is summarised in the following:
|
||||
//! * `PartialReflect` is a trait for interacting with values under `bevy_reflect`'s data model.
|
||||
//! This means values implementing `PartialReflect` can be dynamically constructed and introspected.
|
||||
//! * The `Reflect` trait, however, ensures that the interface exposed by `PartialReflect`
|
||||
//! on types which additionally implement `Reflect` mirrors the structure of a single Rust type.
|
||||
//! * This means `dyn Reflect` trait objects can be directly downcasted to concrete types,
|
||||
//! where `dyn PartialReflect` trait object cannot.
|
||||
//! * `Reflect`, since it provides a stronger type-correctness guarantee,
|
||||
//! is the trait used to interact with [the type registry].
|
||||
//!
|
||||
//! ## Converting between `PartialReflect` and `Reflect`
|
||||
//!
|
||||
//! Since `T: Reflect` implies `T: PartialReflect`, conversion from a `dyn Reflect` to a `dyn PartialReflect`
|
||||
//! trait object (upcasting) is infallible and can be performed with one of the following methods.
|
||||
//! Note that these are temporary while [the language feature for dyn upcasting coercion] is experimental:
|
||||
//! * [`PartialReflect::as_partial_reflect`] for `&dyn PartialReflect`
|
||||
//! * [`PartialReflect::as_partial_reflect_mut`] for `&mut dyn PartialReflect`
|
||||
//! * [`PartialReflect::into_partial_reflect`] for `Box<dyn PartialReflect>`
|
||||
//!
|
||||
//! For conversion in the other direction — downcasting `dyn PartialReflect` to `dyn Reflect` —
|
||||
//! there are fallible methods:
|
||||
//! * [`PartialReflect::try_as_reflect`] for `&dyn Reflect`
|
||||
//! * [`PartialReflect::try_as_reflect_mut`] for `&mut dyn Reflect`
|
||||
//! * [`PartialReflect::try_into_reflect`] for `Box<dyn Reflect>`
|
||||
//!
|
||||
//! Additionally, [`FromReflect::from_reflect`] can be used to convert a `dyn PartialReflect` to a concrete type
|
||||
//! which implements `Reflect`.
|
||||
//!
|
||||
//! # Implementing `Reflect`
|
||||
//!
|
||||
//! Implementing `Reflect` (and `PartialReflect`) is easily done using the provided [derive macro]:
|
||||
//!
|
||||
//! ```
|
||||
//! # use bevy_reflect::Reflect;
|
||||
|
@ -54,8 +99,8 @@
|
|||
//! ## Requirements
|
||||
//!
|
||||
//! We can implement `Reflect` on any type that satisfies _both_ of the following conditions:
|
||||
//! * The type implements `Any`.
|
||||
//! This is true if and only if the type itself has a [`'static` lifetime].
|
||||
//! * The type implements `Any`, `Send`, and `Sync`.
|
||||
//! For the `Any` requirement to be satisfied, the type itself must have a [`'static` lifetime].
|
||||
//! * All fields and sub-elements themselves implement `Reflect`
|
||||
//! (see the [derive macro documentation] for details on how to ignore certain fields when deriving).
|
||||
//!
|
||||
|
@ -63,11 +108,11 @@
|
|||
//! * All fields and sub-elements must implement [`FromReflect`]—
|
||||
//! another important reflection trait discussed in a later section.
|
||||
//!
|
||||
//! # The `Reflect` Subtraits
|
||||
//! # The Reflection Subtraits
|
||||
//!
|
||||
//! Since [`Reflect`] is meant to cover any and every type, this crate also comes with a few
|
||||
//! more traits to accompany `Reflect` and provide more specific interactions.
|
||||
//! We refer to these traits as the _reflection subtraits_ since they all have `Reflect` as a supertrait.
|
||||
//! Since [`PartialReflect`] is meant to cover any and every type, this crate also comes with a few
|
||||
//! more traits to accompany `PartialReflect` and provide more specific interactions.
|
||||
//! We refer to these traits as the _reflection subtraits_ since they all have `PartialReflect` as a supertrait.
|
||||
//! The current list of reflection subtraits include:
|
||||
//! * [`Tuple`]
|
||||
//! * [`Array`]
|
||||
|
@ -83,7 +128,7 @@
|
|||
//! For example, we can access our struct's fields by name using the [`Struct::field`] method.
|
||||
//!
|
||||
//! ```
|
||||
//! # use bevy_reflect::{Reflect, Struct};
|
||||
//! # use bevy_reflect::{PartialReflect, Reflect, Struct};
|
||||
//! # #[derive(Reflect)]
|
||||
//! # struct MyStruct {
|
||||
//! # foo: i32
|
||||
|
@ -91,28 +136,29 @@
|
|||
//! let my_struct: Box<dyn Struct> = Box::new(MyStruct {
|
||||
//! foo: 123
|
||||
//! });
|
||||
//! let foo: &dyn Reflect = my_struct.field("foo").unwrap();
|
||||
//! assert_eq!(Some(&123), foo.downcast_ref::<i32>());
|
||||
//! let foo: &dyn PartialReflect = my_struct.field("foo").unwrap();
|
||||
//! assert_eq!(Some(&123), foo.try_downcast_ref::<i32>());
|
||||
//! ```
|
||||
//!
|
||||
//! Since most data is passed around as `dyn Reflect`,
|
||||
//! the `Reflect` trait has methods for going to and from these subtraits.
|
||||
//! Since most data is passed around as `dyn PartialReflect` or `dyn Reflect` trait objects,
|
||||
//! the `PartialReflect` trait has methods for going to and from these subtraits.
|
||||
//!
|
||||
//! [`Reflect::reflect_kind`], [`Reflect::reflect_ref`], [`Reflect::reflect_mut`], and [`Reflect::reflect_owned`] all return
|
||||
//! [`PartialReflect::reflect_kind`], [`PartialReflect::reflect_ref`],
|
||||
//! [`PartialReflect::reflect_mut`], and [`PartialReflect::reflect_owned`] all return
|
||||
//! an enum that respectively contains zero-sized, immutable, mutable, and owned access to the type as a subtrait object.
|
||||
//!
|
||||
//! For example, we can get out a `dyn Tuple` from our reflected tuple type using one of these methods.
|
||||
//!
|
||||
//! ```
|
||||
//! # use bevy_reflect::{Reflect, ReflectRef};
|
||||
//! let my_tuple: Box<dyn Reflect> = Box::new((1, 2, 3));
|
||||
//! # use bevy_reflect::{PartialReflect, ReflectRef};
|
||||
//! let my_tuple: Box<dyn PartialReflect> = Box::new((1, 2, 3));
|
||||
//! let ReflectRef::Tuple(my_tuple) = my_tuple.reflect_ref() else { unreachable!() };
|
||||
//! assert_eq!(3, my_tuple.field_len());
|
||||
//! ```
|
||||
//!
|
||||
//! And to go back to a general-purpose `dyn Reflect`,
|
||||
//! we can just use the matching [`Reflect::as_reflect`], [`Reflect::as_reflect_mut`],
|
||||
//! or [`Reflect::into_reflect`] methods.
|
||||
//! And to go back to a general-purpose `dyn PartialReflect`,
|
||||
//! we can just use the matching [`PartialReflect::as_partial_reflect`], [`PartialReflect::as_partial_reflect_mut`],
|
||||
//! or [`PartialReflect::into_partial_reflect`] methods.
|
||||
//!
|
||||
//! ## Value Types
|
||||
//!
|
||||
|
@ -120,7 +166,7 @@
|
|||
//! such as for primitives (e.g. `bool`, `usize`, etc.)
|
||||
//! and simple types (e.g. `String`, `Duration`),
|
||||
//! are referred to as _value_ types
|
||||
//! since methods like [`Reflect::reflect_ref`] return a [`ReflectRef::Value`] variant.
|
||||
//! since methods like [`PartialReflect::reflect_ref`] return a [`ReflectRef::Value`] variant.
|
||||
//! While most other types contain their own `dyn Reflect` fields and data,
|
||||
//! these types generally cannot be broken down any further.
|
||||
//!
|
||||
|
@ -143,18 +189,18 @@
|
|||
//! # use bevy_reflect::{DynamicStruct, Struct};
|
||||
//! let mut data = DynamicStruct::default();
|
||||
//! data.insert("foo", 123_i32);
|
||||
//! assert_eq!(Some(&123), data.field("foo").unwrap().downcast_ref::<i32>())
|
||||
//! assert_eq!(Some(&123), data.field("foo").unwrap().try_downcast_ref::<i32>())
|
||||
//! ```
|
||||
//!
|
||||
//! They are most commonly used as "proxies" for other types,
|
||||
//! where they contain the same data as— and therefore, represent— a concrete type.
|
||||
//! The [`Reflect::clone_value`] method will return a dynamic type for all non-value types,
|
||||
//! The [`PartialReflect::clone_value`] method will return a dynamic type for all non-value types,
|
||||
//! allowing all types to essentially be "cloned".
|
||||
//! And since dynamic types themselves implement [`Reflect`],
|
||||
//! we may pass them around just like any other reflected type.
|
||||
//! And since dynamic types themselves implement [`PartialReflect`],
|
||||
//! we may pass them around just like most other reflected types.
|
||||
//!
|
||||
//! ```
|
||||
//! # use bevy_reflect::{DynamicStruct, Reflect};
|
||||
//! # use bevy_reflect::{DynamicStruct, PartialReflect, Reflect};
|
||||
//! # #[derive(Reflect)]
|
||||
//! # struct MyStruct {
|
||||
//! # foo: i32
|
||||
|
@ -164,18 +210,17 @@
|
|||
//! });
|
||||
//!
|
||||
//! // `cloned` will be a `DynamicStruct` representing a `MyStruct`
|
||||
//! let cloned: Box<dyn Reflect> = original.clone_value();
|
||||
//! let cloned: Box<dyn PartialReflect> = original.clone_value();
|
||||
//! assert!(cloned.represents::<MyStruct>());
|
||||
//! assert!(cloned.is::<DynamicStruct>());
|
||||
//! ```
|
||||
//!
|
||||
//! ## Patching
|
||||
//!
|
||||
//! These dynamic types come in handy when needing to apply multiple changes to another type.
|
||||
//! This is known as "patching" and is done using the [`Reflect::apply`] and [`Reflect::try_apply`] methods.
|
||||
//! This is known as "patching" and is done using the [`PartialReflect::apply`] and [`PartialReflect::try_apply`] methods.
|
||||
//!
|
||||
//! ```
|
||||
//! # use bevy_reflect::{DynamicEnum, Reflect};
|
||||
//! # use bevy_reflect::{DynamicEnum, PartialReflect};
|
||||
//! let mut value = Some(123_i32);
|
||||
//! let patch = DynamicEnum::new("None", ());
|
||||
//! value.apply(&patch);
|
||||
|
@ -189,7 +234,7 @@
|
|||
//! or when trying to make use of a reflected trait which expects the actual type.
|
||||
//!
|
||||
//! ```should_panic
|
||||
//! # use bevy_reflect::{DynamicStruct, Reflect};
|
||||
//! # use bevy_reflect::{DynamicStruct, PartialReflect, Reflect};
|
||||
//! # #[derive(Reflect)]
|
||||
//! # struct MyStruct {
|
||||
//! # foo: i32
|
||||
|
@ -198,8 +243,8 @@
|
|||
//! foo: 123
|
||||
//! });
|
||||
//!
|
||||
//! let cloned: Box<dyn Reflect> = original.clone_value();
|
||||
//! let value = cloned.take::<MyStruct>().unwrap(); // PANIC!
|
||||
//! let cloned: Box<dyn PartialReflect> = original.clone_value();
|
||||
//! let value = cloned.try_take::<MyStruct>().unwrap(); // PANIC!
|
||||
//! ```
|
||||
//!
|
||||
//! To resolve this issue, we'll need to convert the dynamic type to the concrete one.
|
||||
|
@ -214,7 +259,7 @@
|
|||
//! using `#[reflect(from_reflect = false)]` on the item.
|
||||
//!
|
||||
//! ```
|
||||
//! # use bevy_reflect::{Reflect, FromReflect};
|
||||
//! # use bevy_reflect::{FromReflect, PartialReflect, Reflect};
|
||||
//! #[derive(Reflect)]
|
||||
//! struct MyStruct {
|
||||
//! foo: i32
|
||||
|
@ -223,7 +268,7 @@
|
|||
//! foo: 123
|
||||
//! });
|
||||
//!
|
||||
//! let cloned: Box<dyn Reflect> = original.clone_value();
|
||||
//! let cloned: Box<dyn PartialReflect> = original.clone_value();
|
||||
//! let value = <MyStruct as FromReflect>::from_reflect(&*cloned).unwrap(); // OK!
|
||||
//! ```
|
||||
//!
|
||||
|
@ -239,7 +284,7 @@
|
|||
//!
|
||||
//! # Path navigation
|
||||
//!
|
||||
//! The [`GetPath`] trait allows accessing arbitrary nested fields of a [`Reflect`] type.
|
||||
//! The [`GetPath`] trait allows accessing arbitrary nested fields of an [`PartialReflect`] type.
|
||||
//!
|
||||
//! Using `GetPath`, it is possible to use a path string to access a specific field
|
||||
//! of a reflected type.
|
||||
|
@ -306,7 +351,8 @@
|
|||
//! ## Reflecting Traits
|
||||
//!
|
||||
//! Type data doesn't have to be tied to a trait, but it's often extremely useful to create trait type data.
|
||||
//! These allow traits to be used directly on a `dyn Reflect` while utilizing the underlying type's implementation.
|
||||
//! These allow traits to be used directly on a `dyn Reflect` (and not a `dyn PartialReflect`)
|
||||
//! while utilizing the underlying type's implementation.
|
||||
//!
|
||||
//! For any [object-safe] trait, we can easily generate a corresponding `ReflectTrait` type for our trait
|
||||
//! using the [`#[reflect_trait]`](reflect_trait) macro.
|
||||
|
@ -358,7 +404,7 @@
|
|||
//! # use serde::de::DeserializeSeed;
|
||||
//! # use bevy_reflect::{
|
||||
//! # serde::{ReflectSerializer, ReflectDeserializer},
|
||||
//! # Reflect, FromReflect, TypeRegistry
|
||||
//! # Reflect, PartialReflect, FromReflect, TypeRegistry
|
||||
//! # };
|
||||
//! #[derive(Reflect, PartialEq, Debug)]
|
||||
//! struct MyStruct {
|
||||
|
@ -374,12 +420,12 @@
|
|||
//! registry.register::<MyStruct>();
|
||||
//!
|
||||
//! // Serialize
|
||||
//! let reflect_serializer = ReflectSerializer::new(&original_value, ®istry);
|
||||
//! let reflect_serializer = ReflectSerializer::new(original_value.as_partial_reflect(), ®istry);
|
||||
//! let serialized_value: String = ron::to_string(&reflect_serializer).unwrap();
|
||||
//!
|
||||
//! // Deserialize
|
||||
//! let reflect_deserializer = ReflectDeserializer::new(®istry);
|
||||
//! let deserialized_value: Box<dyn Reflect> = reflect_deserializer.deserialize(
|
||||
//! let deserialized_value: Box<dyn PartialReflect> = reflect_deserializer.deserialize(
|
||||
//! &mut ron::Deserializer::from_str(&serialized_value).unwrap()
|
||||
//! ).unwrap();
|
||||
//!
|
||||
|
@ -449,7 +495,11 @@
|
|||
//! [Bevy]: https://bevyengine.org/
|
||||
//! [limitations]: #limitations
|
||||
//! [`bevy_reflect`]: crate
|
||||
//! [introspection]: https://en.wikipedia.org/wiki/Type_introspection
|
||||
//! [subtraits]: #the-reflection-subtraits
|
||||
//! [the type registry]: #type-registration
|
||||
//! [runtime cost]: https://doc.rust-lang.org/book/ch17-02-trait-objects.html#trait-objects-perform-dynamic-dispatch
|
||||
//! [the language feature for dyn upcasting coercion]: https://github.com/rust-lang/rust/issues/65991
|
||||
//! [derive macro]: derive@crate::Reflect
|
||||
//! [`'static` lifetime]: https://doc.rust-lang.org/rust-by-example/scope/lifetime/static_lifetime.html#trait-bound
|
||||
//! [derive macro documentation]: derive@crate::Reflect
|
||||
|
@ -515,9 +565,9 @@ pub mod prelude {
|
|||
pub use crate::std_traits::*;
|
||||
#[doc(hidden)]
|
||||
pub use crate::{
|
||||
reflect_trait, FromReflect, GetField, GetPath, GetTupleStructField, Reflect,
|
||||
ReflectDeserialize, ReflectFromReflect, ReflectPath, ReflectSerialize, Struct, TupleStruct,
|
||||
TypePath,
|
||||
reflect_trait, FromReflect, GetField, GetPath, GetTupleStructField, PartialReflect,
|
||||
Reflect, ReflectDeserialize, ReflectFromReflect, ReflectPath, ReflectSerialize, Struct,
|
||||
TupleStruct, TypePath,
|
||||
};
|
||||
|
||||
#[cfg(feature = "functions")]
|
||||
|
@ -732,10 +782,19 @@ mod tests {
|
|||
|
||||
let mut map = DynamicMap::default();
|
||||
map.insert(key_a, 10u32);
|
||||
assert_eq!(10, *map.get(&key_b).unwrap().downcast_ref::<u32>().unwrap());
|
||||
assert_eq!(
|
||||
10,
|
||||
*map.get(&key_b).unwrap().try_downcast_ref::<u32>().unwrap()
|
||||
);
|
||||
assert!(map.get(&key_c).is_none());
|
||||
*map.get_mut(&key_b).unwrap().downcast_mut::<u32>().unwrap() = 20;
|
||||
assert_eq!(20, *map.get(&key_b).unwrap().downcast_ref::<u32>().unwrap());
|
||||
*map.get_mut(&key_b)
|
||||
.unwrap()
|
||||
.try_downcast_mut::<u32>()
|
||||
.unwrap() = 20;
|
||||
assert_eq!(
|
||||
20,
|
||||
*map.get(&key_b).unwrap().try_downcast_ref::<u32>().unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -751,16 +810,22 @@ mod tests {
|
|||
let mut patch = DynamicTupleStruct::default();
|
||||
patch.insert(3u32);
|
||||
patch.insert(4u64);
|
||||
assert_eq!(3, *patch.field(0).unwrap().downcast_ref::<u32>().unwrap());
|
||||
assert_eq!(4, *patch.field(1).unwrap().downcast_ref::<u64>().unwrap());
|
||||
assert_eq!(
|
||||
3,
|
||||
*patch.field(0).unwrap().try_downcast_ref::<u32>().unwrap()
|
||||
);
|
||||
assert_eq!(
|
||||
4,
|
||||
*patch.field(1).unwrap().try_downcast_ref::<u64>().unwrap()
|
||||
);
|
||||
|
||||
foo.apply(&patch);
|
||||
assert_eq!(3, foo.0);
|
||||
assert_eq!(4, foo.1);
|
||||
|
||||
let mut iter = patch.iter_fields();
|
||||
assert_eq!(3, *iter.next().unwrap().downcast_ref::<u32>().unwrap());
|
||||
assert_eq!(4, *iter.next().unwrap().downcast_ref::<u64>().unwrap());
|
||||
assert_eq!(3, *iter.next().unwrap().try_downcast_ref::<u32>().unwrap());
|
||||
assert_eq!(4, *iter.next().unwrap().try_downcast_ref::<u64>().unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -831,7 +896,7 @@ mod tests {
|
|||
|
||||
let values: Vec<u32> = foo
|
||||
.iter_fields()
|
||||
.map(|value| *value.downcast_ref::<u32>().unwrap())
|
||||
.map(|value| *value.try_downcast_ref::<u32>().unwrap())
|
||||
.collect();
|
||||
assert_eq!(values, vec![1]);
|
||||
}
|
||||
|
@ -863,11 +928,11 @@ mod tests {
|
|||
// Assert
|
||||
let expected = MyStruct { foo: 123 };
|
||||
assert!(expected
|
||||
.reflect_partial_eq(reflected.as_ref())
|
||||
.reflect_partial_eq(reflected.as_partial_reflect())
|
||||
.unwrap_or_default());
|
||||
let not_expected = MyStruct { foo: 321 };
|
||||
assert!(!not_expected
|
||||
.reflect_partial_eq(reflected.as_ref())
|
||||
.reflect_partial_eq(reflected.as_partial_reflect())
|
||||
.unwrap_or_default());
|
||||
}
|
||||
|
||||
|
@ -1314,9 +1379,9 @@ mod tests {
|
|||
let mut deserializer = Deserializer::from_str(&serialized).unwrap();
|
||||
let reflect_deserializer = ReflectDeserializer::new(®istry);
|
||||
let value = reflect_deserializer.deserialize(&mut deserializer).unwrap();
|
||||
let dynamic_struct = value.take::<DynamicStruct>().unwrap();
|
||||
let roundtrip_foo = Foo::from_reflect(value.as_partial_reflect()).unwrap();
|
||||
|
||||
assert!(foo.reflect_partial_eq(&dynamic_struct).unwrap());
|
||||
assert!(foo.reflect_partial_eq(&roundtrip_foo).unwrap());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -2071,7 +2136,7 @@ bevy_reflect::tests::Test {
|
|||
}
|
||||
|
||||
let foo = Foo(123);
|
||||
let foo: &dyn Reflect = &foo;
|
||||
let foo: &dyn PartialReflect = &foo;
|
||||
|
||||
assert!(foo.reflect_hash().is_some());
|
||||
assert_eq!(Some(true), foo.reflect_partial_eq(foo));
|
||||
|
@ -2092,7 +2157,7 @@ bevy_reflect::tests::Test {
|
|||
}
|
||||
|
||||
let foo = Foo(123);
|
||||
let foo: &dyn Reflect = &foo;
|
||||
let foo: &dyn PartialReflect = &foo;
|
||||
|
||||
assert!(foo.reflect_hash().is_some());
|
||||
assert_eq!(Some(true), foo.reflect_partial_eq(foo));
|
||||
|
@ -2341,7 +2406,7 @@ bevy_reflect::tests::Test {
|
|||
}
|
||||
let mut map = HashMap::new();
|
||||
map.insert(9, 10);
|
||||
let mut test_struct = TestStruct {
|
||||
let mut test_struct: DynamicStruct = TestStruct {
|
||||
tuple: (0, 1),
|
||||
list: vec![2, 3, 4],
|
||||
array: [5, 6, 7],
|
||||
|
@ -2350,8 +2415,7 @@ bevy_reflect::tests::Test {
|
|||
map,
|
||||
value: 12,
|
||||
}
|
||||
.clone_value();
|
||||
let test_struct = test_struct.downcast_mut::<DynamicStruct>().unwrap();
|
||||
.clone_dynamic();
|
||||
|
||||
// test unknown DynamicStruct
|
||||
let mut test_unknown_struct = DynamicStruct::default();
|
||||
|
@ -2472,7 +2536,7 @@ bevy_reflect::tests::Test {
|
|||
|
||||
let mut result = Quat::default();
|
||||
|
||||
result.apply(&*dynamic_struct);
|
||||
result.apply(dynamic_struct.as_partial_reflect());
|
||||
|
||||
assert_eq!(result, quat(1.0, 2.0, 3.0, 4.0));
|
||||
}
|
||||
|
@ -2529,7 +2593,7 @@ bevy_reflect::tests::Test {
|
|||
|
||||
let mut result = Vec3::default();
|
||||
|
||||
result.apply(&*dynamic_struct);
|
||||
result.apply(dynamic_struct.as_partial_reflect());
|
||||
|
||||
assert_eq!(result, vec3(12.0, 3.0, -6.9));
|
||||
}
|
||||
|
@ -2550,13 +2614,16 @@ bevy_reflect::tests::Test {
|
|||
let mut v = vec3(1.0, 2.0, 3.0);
|
||||
|
||||
assert_eq!(
|
||||
*v.reflect_path("x").unwrap().downcast_ref::<f32>().unwrap(),
|
||||
*v.reflect_path("x")
|
||||
.unwrap()
|
||||
.try_downcast_ref::<f32>()
|
||||
.unwrap(),
|
||||
1.0
|
||||
);
|
||||
|
||||
*v.reflect_path_mut("y")
|
||||
.unwrap()
|
||||
.downcast_mut::<f32>()
|
||||
.try_downcast_mut::<f32>()
|
||||
.unwrap() = 6.0;
|
||||
|
||||
assert_eq!(v.y, 6.0);
|
||||
|
|
|
@ -6,8 +6,8 @@ use bevy_reflect_derive::impl_type_path;
|
|||
|
||||
use crate::utility::reflect_hasher;
|
||||
use crate::{
|
||||
self as bevy_reflect, ApplyError, FromReflect, MaybeTyped, Reflect, ReflectKind, ReflectMut,
|
||||
ReflectOwned, ReflectRef, TypeInfo, TypePath, TypePathTable,
|
||||
self as bevy_reflect, ApplyError, FromReflect, MaybeTyped, PartialReflect, Reflect,
|
||||
ReflectKind, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, TypePath, TypePathTable,
|
||||
};
|
||||
|
||||
/// A trait used to power [list-like] operations via [reflection].
|
||||
|
@ -35,46 +35,46 @@ use crate::{
|
|||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use bevy_reflect::{Reflect, List};
|
||||
/// use bevy_reflect::{PartialReflect, Reflect, List};
|
||||
///
|
||||
/// let foo: &mut dyn List = &mut vec![123_u32, 456_u32, 789_u32];
|
||||
/// assert_eq!(foo.len(), 3);
|
||||
///
|
||||
/// let last_field: Box<dyn Reflect> = foo.pop().unwrap();
|
||||
/// assert_eq!(last_field.downcast_ref::<u32>(), Some(&789));
|
||||
/// let last_field: Box<dyn PartialReflect> = foo.pop().unwrap();
|
||||
/// assert_eq!(last_field.try_downcast_ref::<u32>(), Some(&789));
|
||||
/// ```
|
||||
///
|
||||
/// [list-like]: https://doc.rust-lang.org/book/ch08-01-vectors.html
|
||||
/// [reflection]: crate
|
||||
/// [type-erasing]: https://doc.rust-lang.org/book/ch17-02-trait-objects.html
|
||||
pub trait List: Reflect {
|
||||
pub trait List: PartialReflect {
|
||||
/// Returns a reference to the element at `index`, or `None` if out of bounds.
|
||||
fn get(&self, index: usize) -> Option<&dyn Reflect>;
|
||||
fn get(&self, index: usize) -> Option<&dyn PartialReflect>;
|
||||
|
||||
/// Returns a mutable reference to the element at `index`, or `None` if out of bounds.
|
||||
fn get_mut(&mut self, index: usize) -> Option<&mut dyn Reflect>;
|
||||
fn get_mut(&mut self, index: usize) -> Option<&mut dyn PartialReflect>;
|
||||
|
||||
/// Inserts an element at position `index` within the list,
|
||||
/// shifting all elements after it towards the back of the list.
|
||||
///
|
||||
/// # Panics
|
||||
/// Panics if `index > len`.
|
||||
fn insert(&mut self, index: usize, element: Box<dyn Reflect>);
|
||||
fn insert(&mut self, index: usize, element: Box<dyn PartialReflect>);
|
||||
|
||||
/// Removes and returns the element at position `index` within the list,
|
||||
/// shifting all elements before it towards the front of the list.
|
||||
///
|
||||
/// # Panics
|
||||
/// Panics if `index` is out of bounds.
|
||||
fn remove(&mut self, index: usize) -> Box<dyn Reflect>;
|
||||
fn remove(&mut self, index: usize) -> Box<dyn PartialReflect>;
|
||||
|
||||
/// Appends an element to the _back_ of the list.
|
||||
fn push(&mut self, value: Box<dyn Reflect>) {
|
||||
fn push(&mut self, value: Box<dyn PartialReflect>) {
|
||||
self.insert(self.len(), value);
|
||||
}
|
||||
|
||||
/// Removes the _back_ element from the list and returns it, or [`None`] if it is empty.
|
||||
fn pop(&mut self) -> Option<Box<dyn Reflect>> {
|
||||
fn pop(&mut self) -> Option<Box<dyn PartialReflect>> {
|
||||
if self.is_empty() {
|
||||
None
|
||||
} else {
|
||||
|
@ -94,13 +94,13 @@ pub trait List: Reflect {
|
|||
fn iter(&self) -> ListIter;
|
||||
|
||||
/// Drain the elements of this list to get a vector of owned values.
|
||||
fn drain(self: Box<Self>) -> Vec<Box<dyn Reflect>>;
|
||||
fn drain(self: Box<Self>) -> Vec<Box<dyn PartialReflect>>;
|
||||
|
||||
/// Clones the list, producing a [`DynamicList`].
|
||||
fn clone_dynamic(&self) -> DynamicList {
|
||||
DynamicList {
|
||||
represented_type: self.get_represented_type_info(),
|
||||
values: self.iter().map(Reflect::clone_value).collect(),
|
||||
values: self.iter().map(PartialReflect::clone_value).collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -200,7 +200,7 @@ impl ListInfo {
|
|||
#[derive(Default)]
|
||||
pub struct DynamicList {
|
||||
represented_type: Option<&'static TypeInfo>,
|
||||
values: Vec<Box<dyn Reflect>>,
|
||||
values: Vec<Box<dyn PartialReflect>>,
|
||||
}
|
||||
|
||||
impl DynamicList {
|
||||
|
@ -223,38 +223,38 @@ impl DynamicList {
|
|||
}
|
||||
|
||||
/// Appends a typed value to the list.
|
||||
pub fn push<T: Reflect>(&mut self, value: T) {
|
||||
pub fn push<T: PartialReflect>(&mut self, value: T) {
|
||||
self.values.push(Box::new(value));
|
||||
}
|
||||
|
||||
/// Appends a [`Reflect`] trait object to the list.
|
||||
pub fn push_box(&mut self, value: Box<dyn Reflect>) {
|
||||
pub fn push_box(&mut self, value: Box<dyn PartialReflect>) {
|
||||
self.values.push(value);
|
||||
}
|
||||
}
|
||||
|
||||
impl List for DynamicList {
|
||||
fn get(&self, index: usize) -> Option<&dyn Reflect> {
|
||||
fn get(&self, index: usize) -> Option<&dyn PartialReflect> {
|
||||
self.values.get(index).map(|value| &**value)
|
||||
}
|
||||
|
||||
fn get_mut(&mut self, index: usize) -> Option<&mut dyn Reflect> {
|
||||
fn get_mut(&mut self, index: usize) -> Option<&mut dyn PartialReflect> {
|
||||
self.values.get_mut(index).map(|value| &mut **value)
|
||||
}
|
||||
|
||||
fn insert(&mut self, index: usize, element: Box<dyn Reflect>) {
|
||||
fn insert(&mut self, index: usize, element: Box<dyn PartialReflect>) {
|
||||
self.values.insert(index, element);
|
||||
}
|
||||
|
||||
fn remove(&mut self, index: usize) -> Box<dyn Reflect> {
|
||||
fn remove(&mut self, index: usize) -> Box<dyn PartialReflect> {
|
||||
self.values.remove(index)
|
||||
}
|
||||
|
||||
fn push(&mut self, value: Box<dyn Reflect>) {
|
||||
fn push(&mut self, value: Box<dyn PartialReflect>) {
|
||||
DynamicList::push_box(self, value);
|
||||
}
|
||||
|
||||
fn pop(&mut self) -> Option<Box<dyn Reflect>> {
|
||||
fn pop(&mut self) -> Option<Box<dyn PartialReflect>> {
|
||||
self.values.pop()
|
||||
}
|
||||
|
||||
|
@ -266,7 +266,7 @@ impl List for DynamicList {
|
|||
ListIter::new(self)
|
||||
}
|
||||
|
||||
fn drain(self: Box<Self>) -> Vec<Box<dyn Reflect>> {
|
||||
fn drain(self: Box<Self>) -> Vec<Box<dyn PartialReflect>> {
|
||||
self.values
|
||||
}
|
||||
|
||||
|
@ -282,56 +282,47 @@ impl List for DynamicList {
|
|||
}
|
||||
}
|
||||
|
||||
impl Reflect for DynamicList {
|
||||
impl PartialReflect for DynamicList {
|
||||
#[inline]
|
||||
fn get_represented_type_info(&self) -> Option<&'static TypeInfo> {
|
||||
self.represented_type
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn into_any(self: Box<Self>) -> Box<dyn Any> {
|
||||
fn into_partial_reflect(self: Box<Self>) -> Box<dyn PartialReflect> {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
fn as_partial_reflect(&self) -> &dyn PartialReflect {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_any_mut(&mut self) -> &mut dyn Any {
|
||||
fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn into_reflect(self: Box<Self>) -> Box<dyn Reflect> {
|
||||
self
|
||||
fn try_into_reflect(self: Box<Self>) -> Result<Box<dyn Reflect>, Box<dyn PartialReflect>> {
|
||||
Err(self)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_reflect(&self) -> &dyn Reflect {
|
||||
self
|
||||
fn try_as_reflect(&self) -> Option<&dyn Reflect> {
|
||||
None
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_reflect_mut(&mut self) -> &mut dyn Reflect {
|
||||
self
|
||||
fn try_as_reflect_mut(&mut self) -> Option<&mut dyn Reflect> {
|
||||
None
|
||||
}
|
||||
|
||||
fn apply(&mut self, value: &dyn Reflect) {
|
||||
fn apply(&mut self, value: &dyn PartialReflect) {
|
||||
list_apply(self, value);
|
||||
}
|
||||
|
||||
fn try_apply(&mut self, value: &dyn Reflect) -> Result<(), ApplyError> {
|
||||
fn try_apply(&mut self, value: &dyn PartialReflect) -> Result<(), ApplyError> {
|
||||
list_try_apply(self, value)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set(&mut self, value: Box<dyn Reflect>) -> Result<(), Box<dyn Reflect>> {
|
||||
*self = value.take()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn reflect_kind(&self) -> ReflectKind {
|
||||
ReflectKind::List
|
||||
|
@ -353,7 +344,7 @@ impl Reflect for DynamicList {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn clone_value(&self) -> Box<dyn Reflect> {
|
||||
fn clone_value(&self) -> Box<dyn PartialReflect> {
|
||||
Box::new(self.clone_dynamic())
|
||||
}
|
||||
|
||||
|
@ -362,7 +353,7 @@ impl Reflect for DynamicList {
|
|||
list_hash(self)
|
||||
}
|
||||
|
||||
fn reflect_partial_eq(&self, value: &dyn Reflect) -> Option<bool> {
|
||||
fn reflect_partial_eq(&self, value: &dyn PartialReflect) -> Option<bool> {
|
||||
list_partial_eq(self, value)
|
||||
}
|
||||
|
||||
|
@ -379,8 +370,6 @@ impl Reflect for DynamicList {
|
|||
}
|
||||
|
||||
impl_type_path!((in bevy_reflect) DynamicList);
|
||||
#[cfg(feature = "functions")]
|
||||
crate::func::macros::impl_function_traits!(DynamicList);
|
||||
|
||||
impl Debug for DynamicList {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
|
@ -388,8 +377,8 @@ impl Debug for DynamicList {
|
|||
}
|
||||
}
|
||||
|
||||
impl FromIterator<Box<dyn Reflect>> for DynamicList {
|
||||
fn from_iter<I: IntoIterator<Item = Box<dyn Reflect>>>(values: I) -> Self {
|
||||
impl FromIterator<Box<dyn PartialReflect>> for DynamicList {
|
||||
fn from_iter<I: IntoIterator<Item = Box<dyn PartialReflect>>>(values: I) -> Self {
|
||||
Self {
|
||||
represented_type: None,
|
||||
values: values.into_iter().collect(),
|
||||
|
@ -397,17 +386,17 @@ impl FromIterator<Box<dyn Reflect>> for DynamicList {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T: Reflect> FromIterator<T> for DynamicList {
|
||||
impl<T: PartialReflect> FromIterator<T> for DynamicList {
|
||||
fn from_iter<I: IntoIterator<Item = T>>(values: I) -> Self {
|
||||
values
|
||||
.into_iter()
|
||||
.map(|field| Box::new(field).into_reflect())
|
||||
.map(|field| Box::new(field).into_partial_reflect())
|
||||
.collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoIterator for DynamicList {
|
||||
type Item = Box<dyn Reflect>;
|
||||
type Item = Box<dyn PartialReflect>;
|
||||
type IntoIter = std::vec::IntoIter<Self::Item>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
|
@ -416,7 +405,7 @@ impl IntoIterator for DynamicList {
|
|||
}
|
||||
|
||||
impl<'a> IntoIterator for &'a DynamicList {
|
||||
type Item = &'a dyn Reflect;
|
||||
type Item = &'a dyn PartialReflect;
|
||||
type IntoIter = ListIter<'a>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
|
@ -439,7 +428,7 @@ impl<'a> ListIter<'a> {
|
|||
}
|
||||
|
||||
impl<'a> Iterator for ListIter<'a> {
|
||||
type Item = &'a dyn Reflect;
|
||||
type Item = &'a dyn PartialReflect;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
|
@ -478,7 +467,7 @@ pub fn list_hash<L: List>(list: &L) -> Option<u64> {
|
|||
///
|
||||
/// This function panics if `b` is not a list.
|
||||
#[inline]
|
||||
pub fn list_apply<L: List>(a: &mut L, b: &dyn Reflect) {
|
||||
pub fn list_apply<L: List>(a: &mut L, b: &dyn PartialReflect) {
|
||||
if let Err(err) = list_try_apply(a, b) {
|
||||
panic!("{err}");
|
||||
}
|
||||
|
@ -495,7 +484,7 @@ pub fn list_apply<L: List>(a: &mut L, b: &dyn Reflect) {
|
|||
/// This function returns an [`ApplyError::MismatchedKinds`] if `b` is not a list or if
|
||||
/// applying elements to each other fails.
|
||||
#[inline]
|
||||
pub fn list_try_apply<L: List>(a: &mut L, b: &dyn Reflect) -> Result<(), ApplyError> {
|
||||
pub fn list_try_apply<L: List>(a: &mut L, b: &dyn PartialReflect) -> Result<(), ApplyError> {
|
||||
if let ReflectRef::List(list_value) = b.reflect_ref() {
|
||||
for (i, value) in list_value.iter().enumerate() {
|
||||
if i < a.len() {
|
||||
|
@ -520,11 +509,11 @@ pub fn list_try_apply<L: List>(a: &mut L, b: &dyn Reflect) -> Result<(), ApplyEr
|
|||
/// Returns true if and only if all of the following are true:
|
||||
/// - `b` is a list;
|
||||
/// - `b` is the same length as `a`;
|
||||
/// - [`Reflect::reflect_partial_eq`] returns `Some(true)` for pairwise elements of `a` and `b`.
|
||||
/// - [`PartialReflect::reflect_partial_eq`] returns `Some(true)` for pairwise elements of `a` and `b`.
|
||||
///
|
||||
/// Returns [`None`] if the comparison couldn't even be performed.
|
||||
#[inline]
|
||||
pub fn list_partial_eq<L: List>(a: &L, b: &dyn Reflect) -> Option<bool> {
|
||||
pub fn list_partial_eq<L: List + ?Sized>(a: &L, b: &dyn PartialReflect) -> Option<bool> {
|
||||
let ReflectRef::List(list) = b.reflect_ref() else {
|
||||
return Some(false);
|
||||
};
|
||||
|
@ -583,7 +572,9 @@ mod tests {
|
|||
list.push(2usize);
|
||||
let items = list.into_iter();
|
||||
for (index, item) in items.into_iter().enumerate() {
|
||||
let value = item.take::<usize>().expect("couldn't downcast to usize");
|
||||
let value = item
|
||||
.try_take::<usize>()
|
||||
.expect("couldn't downcast to usize");
|
||||
assert_eq!(index, value);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,8 +5,8 @@ use bevy_reflect_derive::impl_type_path;
|
|||
use bevy_utils::{Entry, HashMap};
|
||||
|
||||
use crate::{
|
||||
self as bevy_reflect, ApplyError, MaybeTyped, Reflect, ReflectKind, ReflectMut, ReflectOwned,
|
||||
ReflectRef, TypeInfo, TypePath, TypePathTable,
|
||||
self as bevy_reflect, ApplyError, MaybeTyped, PartialReflect, Reflect, ReflectKind, ReflectMut,
|
||||
ReflectOwned, ReflectRef, TypeInfo, TypePath, TypePathTable,
|
||||
};
|
||||
|
||||
/// A trait used to power [map-like] operations via [reflection].
|
||||
|
@ -17,7 +17,7 @@ use crate::{
|
|||
///
|
||||
/// # Hashing
|
||||
///
|
||||
/// All keys are expected to return a valid hash value from [`Reflect::reflect_hash`].
|
||||
/// All keys are expected to return a valid hash value from [`PartialReflect::reflect_hash`].
|
||||
/// If using the [`#[derive(Reflect)]`](derive@crate::Reflect) macro, this can be done by adding `#[reflect(Hash)]`
|
||||
/// to the entire struct or enum.
|
||||
/// This is true even for manual implementors who do not use the hashed value,
|
||||
|
@ -26,7 +26,7 @@ use crate::{
|
|||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use bevy_reflect::{Reflect, Map};
|
||||
/// use bevy_reflect::{PartialReflect, Reflect, Map};
|
||||
/// use bevy_utils::HashMap;
|
||||
///
|
||||
///
|
||||
|
@ -34,28 +34,31 @@ use crate::{
|
|||
/// foo.insert_boxed(Box::new(123_u32), Box::new(true));
|
||||
/// assert_eq!(foo.len(), 1);
|
||||
///
|
||||
/// let field: &dyn Reflect = foo.get(&123_u32).unwrap();
|
||||
/// assert_eq!(field.downcast_ref::<bool>(), Some(&true));
|
||||
/// let field: &dyn PartialReflect = foo.get(&123_u32).unwrap();
|
||||
/// assert_eq!(field.try_downcast_ref::<bool>(), Some(&true));
|
||||
/// ```
|
||||
///
|
||||
/// [map-like]: https://doc.rust-lang.org/book/ch08-03-hash-maps.html
|
||||
/// [reflection]: crate
|
||||
pub trait Map: Reflect {
|
||||
pub trait Map: PartialReflect {
|
||||
/// Returns a reference to the value associated with the given key.
|
||||
///
|
||||
/// If no value is associated with `key`, returns `None`.
|
||||
fn get(&self, key: &dyn Reflect) -> Option<&dyn Reflect>;
|
||||
fn get(&self, key: &dyn PartialReflect) -> Option<&dyn PartialReflect>;
|
||||
|
||||
/// Returns a mutable reference to the value associated with the given key.
|
||||
///
|
||||
/// If no value is associated with `key`, returns `None`.
|
||||
fn get_mut(&mut self, key: &dyn Reflect) -> Option<&mut dyn Reflect>;
|
||||
fn get_mut(&mut self, key: &dyn PartialReflect) -> Option<&mut dyn PartialReflect>;
|
||||
|
||||
/// Returns the key-value pair at `index` by reference, or `None` if out of bounds.
|
||||
fn get_at(&self, index: usize) -> Option<(&dyn Reflect, &dyn Reflect)>;
|
||||
fn get_at(&self, index: usize) -> Option<(&dyn PartialReflect, &dyn PartialReflect)>;
|
||||
|
||||
/// Returns the key-value pair at `index` by reference where the value is a mutable reference, or `None` if out of bounds.
|
||||
fn get_at_mut(&mut self, index: usize) -> Option<(&dyn Reflect, &mut dyn Reflect)>;
|
||||
fn get_at_mut(
|
||||
&mut self,
|
||||
index: usize,
|
||||
) -> Option<(&dyn PartialReflect, &mut dyn PartialReflect)>;
|
||||
|
||||
/// Returns the number of elements in the map.
|
||||
fn len(&self) -> usize;
|
||||
|
@ -69,7 +72,7 @@ pub trait Map: Reflect {
|
|||
fn iter(&self) -> MapIter;
|
||||
|
||||
/// Drain the key-value pairs of this map to get a vector of owned values.
|
||||
fn drain(self: Box<Self>) -> Vec<(Box<dyn Reflect>, Box<dyn Reflect>)>;
|
||||
fn drain(self: Box<Self>) -> Vec<(Box<dyn PartialReflect>, Box<dyn PartialReflect>)>;
|
||||
|
||||
/// Clones the map, producing a [`DynamicMap`].
|
||||
fn clone_dynamic(&self) -> DynamicMap;
|
||||
|
@ -80,15 +83,15 @@ pub trait Map: Reflect {
|
|||
/// If the map did have this key present, the value is updated, and the old value is returned.
|
||||
fn insert_boxed(
|
||||
&mut self,
|
||||
key: Box<dyn Reflect>,
|
||||
value: Box<dyn Reflect>,
|
||||
) -> Option<Box<dyn Reflect>>;
|
||||
key: Box<dyn PartialReflect>,
|
||||
value: Box<dyn PartialReflect>,
|
||||
) -> Option<Box<dyn PartialReflect>>;
|
||||
|
||||
/// Removes an entry from the map.
|
||||
///
|
||||
/// If the map did not have this key present, `None` is returned.
|
||||
/// If the map did have this key present, the removed value is returned.
|
||||
fn remove(&mut self, key: &dyn Reflect) -> Option<Box<dyn Reflect>>;
|
||||
fn remove(&mut self, key: &dyn PartialReflect) -> Option<Box<dyn PartialReflect>>;
|
||||
}
|
||||
|
||||
/// A container for compile-time map info.
|
||||
|
@ -246,7 +249,7 @@ macro_rules! hash_error {
|
|||
#[derive(Default)]
|
||||
pub struct DynamicMap {
|
||||
represented_type: Option<&'static TypeInfo>,
|
||||
values: Vec<(Box<dyn Reflect>, Box<dyn Reflect>)>,
|
||||
values: Vec<(Box<dyn PartialReflect>, Box<dyn PartialReflect>)>,
|
||||
indices: HashMap<u64, usize>,
|
||||
}
|
||||
|
||||
|
@ -271,32 +274,35 @@ impl DynamicMap {
|
|||
}
|
||||
|
||||
/// Inserts a typed key-value pair into the map.
|
||||
pub fn insert<K: Reflect, V: Reflect>(&mut self, key: K, value: V) {
|
||||
pub fn insert<K: PartialReflect, V: PartialReflect>(&mut self, key: K, value: V) {
|
||||
self.insert_boxed(Box::new(key), Box::new(value));
|
||||
}
|
||||
}
|
||||
|
||||
impl Map for DynamicMap {
|
||||
fn get(&self, key: &dyn Reflect) -> Option<&dyn Reflect> {
|
||||
fn get(&self, key: &dyn PartialReflect) -> Option<&dyn PartialReflect> {
|
||||
self.indices
|
||||
.get(&key.reflect_hash().expect(hash_error!(key)))
|
||||
.map(|index| &*self.values.get(*index).unwrap().1)
|
||||
}
|
||||
|
||||
fn get_mut(&mut self, key: &dyn Reflect) -> Option<&mut dyn Reflect> {
|
||||
fn get_mut(&mut self, key: &dyn PartialReflect) -> Option<&mut dyn PartialReflect> {
|
||||
self.indices
|
||||
.get(&key.reflect_hash().expect(hash_error!(key)))
|
||||
.cloned()
|
||||
.map(move |index| &mut *self.values.get_mut(index).unwrap().1)
|
||||
}
|
||||
|
||||
fn get_at(&self, index: usize) -> Option<(&dyn Reflect, &dyn Reflect)> {
|
||||
fn get_at(&self, index: usize) -> Option<(&dyn PartialReflect, &dyn PartialReflect)> {
|
||||
self.values
|
||||
.get(index)
|
||||
.map(|(key, value)| (&**key, &**value))
|
||||
}
|
||||
|
||||
fn get_at_mut(&mut self, index: usize) -> Option<(&dyn Reflect, &mut dyn Reflect)> {
|
||||
fn get_at_mut(
|
||||
&mut self,
|
||||
index: usize,
|
||||
) -> Option<(&dyn PartialReflect, &mut dyn PartialReflect)> {
|
||||
self.values
|
||||
.get_mut(index)
|
||||
.map(|(key, value)| (&**key, &mut **value))
|
||||
|
@ -310,7 +316,7 @@ impl Map for DynamicMap {
|
|||
MapIter::new(self)
|
||||
}
|
||||
|
||||
fn drain(self: Box<Self>) -> Vec<(Box<dyn Reflect>, Box<dyn Reflect>)> {
|
||||
fn drain(self: Box<Self>) -> Vec<(Box<dyn PartialReflect>, Box<dyn PartialReflect>)> {
|
||||
self.values
|
||||
}
|
||||
|
||||
|
@ -328,9 +334,9 @@ impl Map for DynamicMap {
|
|||
|
||||
fn insert_boxed(
|
||||
&mut self,
|
||||
key: Box<dyn Reflect>,
|
||||
mut value: Box<dyn Reflect>,
|
||||
) -> Option<Box<dyn Reflect>> {
|
||||
key: Box<dyn PartialReflect>,
|
||||
mut value: Box<dyn PartialReflect>,
|
||||
) -> Option<Box<dyn PartialReflect>> {
|
||||
match self
|
||||
.indices
|
||||
.entry(key.reflect_hash().expect(hash_error!(key)))
|
||||
|
@ -348,7 +354,7 @@ impl Map for DynamicMap {
|
|||
}
|
||||
}
|
||||
|
||||
fn remove(&mut self, key: &dyn Reflect) -> Option<Box<dyn Reflect>> {
|
||||
fn remove(&mut self, key: &dyn PartialReflect) -> Option<Box<dyn PartialReflect>> {
|
||||
let index = self
|
||||
.indices
|
||||
.remove(&key.reflect_hash().expect(hash_error!(key)))?;
|
||||
|
@ -357,52 +363,47 @@ impl Map for DynamicMap {
|
|||
}
|
||||
}
|
||||
|
||||
impl Reflect for DynamicMap {
|
||||
impl PartialReflect for DynamicMap {
|
||||
#[inline]
|
||||
fn get_represented_type_info(&self) -> Option<&'static TypeInfo> {
|
||||
self.represented_type
|
||||
}
|
||||
|
||||
fn into_any(self: Box<Self>) -> Box<dyn Any> {
|
||||
self
|
||||
}
|
||||
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
self
|
||||
}
|
||||
|
||||
fn as_any_mut(&mut self) -> &mut dyn Any {
|
||||
#[inline]
|
||||
fn into_partial_reflect(self: Box<Self>) -> Box<dyn PartialReflect> {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn into_reflect(self: Box<Self>) -> Box<dyn Reflect> {
|
||||
fn as_partial_reflect(&self) -> &dyn PartialReflect {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_reflect(&self) -> &dyn Reflect {
|
||||
fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_reflect_mut(&mut self) -> &mut dyn Reflect {
|
||||
self
|
||||
fn try_into_reflect(self: Box<Self>) -> Result<Box<dyn Reflect>, Box<dyn PartialReflect>> {
|
||||
Err(self)
|
||||
}
|
||||
|
||||
fn apply(&mut self, value: &dyn Reflect) {
|
||||
fn try_as_reflect(&self) -> Option<&dyn Reflect> {
|
||||
None
|
||||
}
|
||||
|
||||
fn try_as_reflect_mut(&mut self) -> Option<&mut dyn Reflect> {
|
||||
None
|
||||
}
|
||||
|
||||
fn apply(&mut self, value: &dyn PartialReflect) {
|
||||
map_apply(self, value);
|
||||
}
|
||||
|
||||
fn try_apply(&mut self, value: &dyn Reflect) -> Result<(), ApplyError> {
|
||||
fn try_apply(&mut self, value: &dyn PartialReflect) -> Result<(), ApplyError> {
|
||||
map_try_apply(self, value)
|
||||
}
|
||||
|
||||
fn set(&mut self, value: Box<dyn Reflect>) -> Result<(), Box<dyn Reflect>> {
|
||||
*self = value.take()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn reflect_kind(&self) -> ReflectKind {
|
||||
ReflectKind::Map
|
||||
}
|
||||
|
@ -419,11 +420,11 @@ impl Reflect for DynamicMap {
|
|||
ReflectOwned::Map(self)
|
||||
}
|
||||
|
||||
fn clone_value(&self) -> Box<dyn Reflect> {
|
||||
fn clone_value(&self) -> Box<dyn PartialReflect> {
|
||||
Box::new(self.clone_dynamic())
|
||||
}
|
||||
|
||||
fn reflect_partial_eq(&self, value: &dyn Reflect) -> Option<bool> {
|
||||
fn reflect_partial_eq(&self, value: &dyn PartialReflect) -> Option<bool> {
|
||||
map_partial_eq(self, value)
|
||||
}
|
||||
|
||||
|
@ -440,8 +441,6 @@ impl Reflect for DynamicMap {
|
|||
}
|
||||
|
||||
impl_type_path!((in bevy_reflect) DynamicMap);
|
||||
#[cfg(feature = "functions")]
|
||||
crate::func::macros::impl_function_traits!(DynamicMap);
|
||||
|
||||
impl Debug for DynamicMap {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
|
@ -464,7 +463,7 @@ impl<'a> MapIter<'a> {
|
|||
}
|
||||
|
||||
impl<'a> Iterator for MapIter<'a> {
|
||||
type Item = (&'a dyn Reflect, &'a dyn Reflect);
|
||||
type Item = (&'a dyn PartialReflect, &'a dyn PartialReflect);
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let value = self.map.get_at(self.index);
|
||||
|
@ -478,8 +477,10 @@ impl<'a> Iterator for MapIter<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
impl FromIterator<(Box<dyn Reflect>, Box<dyn Reflect>)> for DynamicMap {
|
||||
fn from_iter<I: IntoIterator<Item = (Box<dyn Reflect>, Box<dyn Reflect>)>>(items: I) -> Self {
|
||||
impl FromIterator<(Box<dyn PartialReflect>, Box<dyn PartialReflect>)> for DynamicMap {
|
||||
fn from_iter<I: IntoIterator<Item = (Box<dyn PartialReflect>, Box<dyn PartialReflect>)>>(
|
||||
items: I,
|
||||
) -> Self {
|
||||
let mut map = Self::default();
|
||||
for (key, value) in items.into_iter() {
|
||||
map.insert_boxed(key, value);
|
||||
|
@ -499,7 +500,7 @@ impl<K: Reflect, V: Reflect> FromIterator<(K, V)> for DynamicMap {
|
|||
}
|
||||
|
||||
impl IntoIterator for DynamicMap {
|
||||
type Item = (Box<dyn Reflect>, Box<dyn Reflect>);
|
||||
type Item = (Box<dyn PartialReflect>, Box<dyn PartialReflect>);
|
||||
type IntoIter = std::vec::IntoIter<Self::Item>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
|
@ -508,7 +509,7 @@ impl IntoIterator for DynamicMap {
|
|||
}
|
||||
|
||||
impl<'a> IntoIterator for &'a DynamicMap {
|
||||
type Item = (&'a dyn Reflect, &'a dyn Reflect);
|
||||
type Item = (&'a dyn PartialReflect, &'a dyn PartialReflect);
|
||||
type IntoIter = MapIter<'a>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
|
@ -518,17 +519,17 @@ impl<'a> IntoIterator for &'a DynamicMap {
|
|||
|
||||
impl<'a> ExactSizeIterator for MapIter<'a> {}
|
||||
|
||||
/// Compares a [`Map`] with a [`Reflect`] value.
|
||||
/// Compares a [`Map`] with a [`PartialReflect`] value.
|
||||
///
|
||||
/// Returns true if and only if all of the following are true:
|
||||
/// - `b` is a map;
|
||||
/// - `b` is the same length as `a`;
|
||||
/// - For each key-value pair in `a`, `b` contains a value for the given key,
|
||||
/// and [`Reflect::reflect_partial_eq`] returns `Some(true)` for the two values.
|
||||
/// and [`PartialReflect::reflect_partial_eq`] returns `Some(true)` for the two values.
|
||||
///
|
||||
/// Returns [`None`] if the comparison couldn't even be performed.
|
||||
#[inline]
|
||||
pub fn map_partial_eq<M: Map>(a: &M, b: &dyn Reflect) -> Option<bool> {
|
||||
pub fn map_partial_eq<M: Map + ?Sized>(a: &M, b: &dyn PartialReflect) -> Option<bool> {
|
||||
let ReflectRef::Map(map) = b.reflect_ref() else {
|
||||
return Some(false);
|
||||
};
|
||||
|
@ -585,7 +586,7 @@ pub fn map_debug(dyn_map: &dyn Map, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|||
///
|
||||
/// This function panics if `b` is not a reflected map.
|
||||
#[inline]
|
||||
pub fn map_apply<M: Map>(a: &mut M, b: &dyn Reflect) {
|
||||
pub fn map_apply<M: Map>(a: &mut M, b: &dyn PartialReflect) {
|
||||
if let Err(err) = map_try_apply(a, b) {
|
||||
panic!("{err}");
|
||||
}
|
||||
|
@ -601,7 +602,7 @@ pub fn map_apply<M: Map>(a: &mut M, b: &dyn Reflect) {
|
|||
/// This function returns an [`ApplyError::MismatchedKinds`] if `b` is not a reflected map or if
|
||||
/// applying elements to each other fails.
|
||||
#[inline]
|
||||
pub fn map_try_apply<M: Map>(a: &mut M, b: &dyn Reflect) -> Result<(), ApplyError> {
|
||||
pub fn map_try_apply<M: Map>(a: &mut M, b: &dyn PartialReflect) -> Result<(), ApplyError> {
|
||||
if let ReflectRef::Map(map_value) = b.reflect_ref() {
|
||||
for (key, b_value) in map_value.iter() {
|
||||
if let Some(a_value) = a.get_mut(key) {
|
||||
|
@ -623,7 +624,6 @@ pub fn map_try_apply<M: Map>(a: &mut M, b: &dyn Reflect) -> Result<(), ApplyErro
|
|||
mod tests {
|
||||
use super::DynamicMap;
|
||||
use super::Map;
|
||||
use crate::reflect::Reflect;
|
||||
|
||||
#[test]
|
||||
fn test_into_iter() {
|
||||
|
@ -635,10 +635,13 @@ mod tests {
|
|||
map.insert(2usize, expected[2].to_string());
|
||||
|
||||
for (index, item) in map.into_iter().enumerate() {
|
||||
let key = item.0.take::<usize>().expect("couldn't downcast to usize");
|
||||
let key = item
|
||||
.0
|
||||
.try_take::<usize>()
|
||||
.expect("couldn't downcast to usize");
|
||||
let value = item
|
||||
.1
|
||||
.take::<String>()
|
||||
.try_take::<String>()
|
||||
.expect("couldn't downcast to String");
|
||||
assert_eq!(index, key);
|
||||
assert_eq!(expected[index], value);
|
||||
|
@ -655,16 +658,16 @@ mod tests {
|
|||
|
||||
let (key_r, value_r) = map.get_at(1).expect("Item wasn't found");
|
||||
let value = value_r
|
||||
.downcast_ref::<String>()
|
||||
.try_downcast_ref::<String>()
|
||||
.expect("Couldn't downcast to String");
|
||||
let key = key_r
|
||||
.downcast_ref::<usize>()
|
||||
.try_downcast_ref::<usize>()
|
||||
.expect("Couldn't downcast to usize");
|
||||
assert_eq!(key, &1usize);
|
||||
assert_eq!(value, &values[2].to_owned());
|
||||
|
||||
assert!(map.get_at(2).is_none());
|
||||
map.remove(&1usize as &dyn Reflect);
|
||||
map.remove(&1usize);
|
||||
assert!(map.get_at(1).is_none());
|
||||
}
|
||||
|
||||
|
@ -678,10 +681,10 @@ mod tests {
|
|||
|
||||
let (key_r, value_r) = map.get_at_mut(1).expect("Item wasn't found");
|
||||
let value = value_r
|
||||
.downcast_mut::<String>()
|
||||
.try_downcast_mut::<String>()
|
||||
.expect("Couldn't downcast to String");
|
||||
let key = key_r
|
||||
.downcast_ref::<usize>()
|
||||
.try_downcast_ref::<usize>()
|
||||
.expect("Couldn't downcast to usize");
|
||||
assert_eq!(key, &1usize);
|
||||
assert_eq!(value, &mut values[2].to_owned());
|
||||
|
@ -689,9 +692,9 @@ mod tests {
|
|||
value.clone_from(&values[0].to_owned());
|
||||
|
||||
assert_eq!(
|
||||
map.get(&1usize as &dyn Reflect)
|
||||
map.get(&1usize)
|
||||
.expect("Item wasn't found")
|
||||
.downcast_ref::<String>()
|
||||
.try_downcast_ref::<String>()
|
||||
.expect("Couldn't downcast to String"),
|
||||
&values[0].to_owned()
|
||||
);
|
||||
|
|
|
@ -3,14 +3,14 @@
|
|||
use std::{borrow::Cow, fmt};
|
||||
|
||||
use super::error::AccessErrorKind;
|
||||
use crate::{AccessError, Reflect, ReflectKind, ReflectMut, ReflectRef, VariantType};
|
||||
use crate::{AccessError, PartialReflect, ReflectKind, ReflectMut, ReflectRef, VariantType};
|
||||
|
||||
type InnerResult<T> = Result<T, AccessErrorKind>;
|
||||
|
||||
/// A singular element access within a path.
|
||||
/// Multiple accesses can be combined into a [`ParsedPath`](super::ParsedPath).
|
||||
///
|
||||
/// Can be applied to a [`dyn Reflect`](Reflect) to get a reference to the targeted element.
|
||||
/// Can be applied to a [`dyn Reflect`](crate::Reflect) to get a reference to the targeted element.
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub enum Access<'a> {
|
||||
/// A name-based field access on a struct.
|
||||
|
@ -51,15 +51,18 @@ impl<'a> Access<'a> {
|
|||
|
||||
pub(super) fn element<'r>(
|
||||
&self,
|
||||
base: &'r dyn Reflect,
|
||||
base: &'r dyn PartialReflect,
|
||||
offset: Option<usize>,
|
||||
) -> Result<&'r dyn Reflect, AccessError<'a>> {
|
||||
) -> Result<&'r dyn PartialReflect, AccessError<'a>> {
|
||||
self.element_inner(base)
|
||||
.and_then(|opt| opt.ok_or(AccessErrorKind::MissingField(base.reflect_kind())))
|
||||
.map_err(|err| err.with_access(self.clone(), offset))
|
||||
}
|
||||
|
||||
fn element_inner<'r>(&self, base: &'r dyn Reflect) -> InnerResult<Option<&'r dyn Reflect>> {
|
||||
fn element_inner<'r>(
|
||||
&self,
|
||||
base: &'r dyn PartialReflect,
|
||||
) -> InnerResult<Option<&'r dyn PartialReflect>> {
|
||||
use ReflectRef::*;
|
||||
|
||||
let invalid_variant =
|
||||
|
@ -105,9 +108,9 @@ impl<'a> Access<'a> {
|
|||
|
||||
pub(super) fn element_mut<'r>(
|
||||
&self,
|
||||
base: &'r mut dyn Reflect,
|
||||
base: &'r mut dyn PartialReflect,
|
||||
offset: Option<usize>,
|
||||
) -> Result<&'r mut dyn Reflect, AccessError<'a>> {
|
||||
) -> Result<&'r mut dyn PartialReflect, AccessError<'a>> {
|
||||
let kind = base.reflect_kind();
|
||||
|
||||
self.element_inner_mut(base)
|
||||
|
@ -117,8 +120,8 @@ impl<'a> Access<'a> {
|
|||
|
||||
fn element_inner_mut<'r>(
|
||||
&self,
|
||||
base: &'r mut dyn Reflect,
|
||||
) -> InnerResult<Option<&'r mut dyn Reflect>> {
|
||||
base: &'r mut dyn PartialReflect,
|
||||
) -> InnerResult<Option<&'r mut dyn PartialReflect>> {
|
||||
use ReflectMut::*;
|
||||
|
||||
let invalid_variant =
|
||||
|
|
|
@ -8,7 +8,7 @@ mod parse;
|
|||
pub use parse::ParseError;
|
||||
use parse::PathParser;
|
||||
|
||||
use crate::Reflect;
|
||||
use crate::{PartialReflect, Reflect};
|
||||
use std::fmt;
|
||||
use thiserror::Error;
|
||||
|
||||
|
@ -49,19 +49,22 @@ pub trait ReflectPath<'a>: Sized {
|
|||
///
|
||||
/// See [`GetPath::reflect_path`] for more details,
|
||||
/// see [`element`](Self::element) if you want a typed return value.
|
||||
fn reflect_element(self, root: &dyn Reflect) -> PathResult<'a, &dyn Reflect>;
|
||||
fn reflect_element(self, root: &dyn PartialReflect) -> PathResult<'a, &dyn PartialReflect>;
|
||||
|
||||
/// Gets a mutable reference to the specified element on the given [`Reflect`] object.
|
||||
///
|
||||
/// See [`GetPath::reflect_path_mut`] for more details.
|
||||
fn reflect_element_mut(self, root: &mut dyn Reflect) -> PathResult<'a, &mut dyn Reflect>;
|
||||
fn reflect_element_mut(
|
||||
self,
|
||||
root: &mut dyn PartialReflect,
|
||||
) -> PathResult<'a, &mut dyn PartialReflect>;
|
||||
|
||||
/// Gets a `&T` to the specified element on the given [`Reflect`] object.
|
||||
///
|
||||
/// See [`GetPath::path`] for more details.
|
||||
fn element<T: Reflect>(self, root: &dyn Reflect) -> PathResult<'a, &T> {
|
||||
fn element<T: Reflect>(self, root: &dyn PartialReflect) -> PathResult<'a, &T> {
|
||||
self.reflect_element(root).and_then(|p| {
|
||||
p.downcast_ref::<T>()
|
||||
p.try_downcast_ref::<T>()
|
||||
.ok_or(ReflectPathError::InvalidDowncast)
|
||||
})
|
||||
}
|
||||
|
@ -69,22 +72,25 @@ pub trait ReflectPath<'a>: Sized {
|
|||
/// Gets a `&mut T` to the specified element on the given [`Reflect`] object.
|
||||
///
|
||||
/// See [`GetPath::path_mut`] for more details.
|
||||
fn element_mut<T: Reflect>(self, root: &mut dyn Reflect) -> PathResult<'a, &mut T> {
|
||||
fn element_mut<T: Reflect>(self, root: &mut dyn PartialReflect) -> PathResult<'a, &mut T> {
|
||||
self.reflect_element_mut(root).and_then(|p| {
|
||||
p.downcast_mut::<T>()
|
||||
p.try_downcast_mut::<T>()
|
||||
.ok_or(ReflectPathError::InvalidDowncast)
|
||||
})
|
||||
}
|
||||
}
|
||||
impl<'a> ReflectPath<'a> for &'a str {
|
||||
fn reflect_element(self, mut root: &dyn Reflect) -> PathResult<'a, &dyn Reflect> {
|
||||
fn reflect_element(self, mut root: &dyn PartialReflect) -> PathResult<'a, &dyn PartialReflect> {
|
||||
for (access, offset) in PathParser::new(self) {
|
||||
let a = access?;
|
||||
root = a.element(root, Some(offset))?;
|
||||
}
|
||||
Ok(root)
|
||||
}
|
||||
fn reflect_element_mut(self, mut root: &mut dyn Reflect) -> PathResult<'a, &mut dyn Reflect> {
|
||||
fn reflect_element_mut(
|
||||
self,
|
||||
mut root: &mut dyn PartialReflect,
|
||||
) -> PathResult<'a, &mut dyn PartialReflect> {
|
||||
for (access, offset) in PathParser::new(self) {
|
||||
root = access?.element_mut(root, Some(offset))?;
|
||||
}
|
||||
|
@ -234,13 +240,13 @@ impl<'a> ReflectPath<'a> for &'a str {
|
|||
message = "`{Self}` does not provide a reflection path",
|
||||
note = "consider annotating `{Self}` with `#[derive(Reflect)]`"
|
||||
)]
|
||||
pub trait GetPath: Reflect {
|
||||
pub trait GetPath: PartialReflect {
|
||||
/// Returns a reference to the value specified by `path`.
|
||||
///
|
||||
/// To retrieve a statically typed reference, use
|
||||
/// [`path`][GetPath::path].
|
||||
fn reflect_path<'p>(&self, path: impl ReflectPath<'p>) -> PathResult<'p, &dyn Reflect> {
|
||||
path.reflect_element(self.as_reflect())
|
||||
fn reflect_path<'p>(&self, path: impl ReflectPath<'p>) -> PathResult<'p, &dyn PartialReflect> {
|
||||
path.reflect_element(self.as_partial_reflect())
|
||||
}
|
||||
|
||||
/// Returns a mutable reference to the value specified by `path`.
|
||||
|
@ -250,8 +256,8 @@ pub trait GetPath: Reflect {
|
|||
fn reflect_path_mut<'p>(
|
||||
&mut self,
|
||||
path: impl ReflectPath<'p>,
|
||||
) -> PathResult<'p, &mut dyn Reflect> {
|
||||
path.reflect_element_mut(self.as_reflect_mut())
|
||||
) -> PathResult<'p, &mut dyn PartialReflect> {
|
||||
path.reflect_element_mut(self.as_partial_reflect_mut())
|
||||
}
|
||||
|
||||
/// Returns a statically typed reference to the value specified by `path`.
|
||||
|
@ -262,7 +268,7 @@ pub trait GetPath: Reflect {
|
|||
///
|
||||
/// [`DynamicStruct`]: crate::DynamicStruct
|
||||
fn path<'p, T: Reflect>(&self, path: impl ReflectPath<'p>) -> PathResult<'p, &T> {
|
||||
path.element(self.as_reflect())
|
||||
path.element(self.as_partial_reflect())
|
||||
}
|
||||
|
||||
/// Returns a statically typed mutable reference to the value specified by `path`.
|
||||
|
@ -273,7 +279,7 @@ pub trait GetPath: Reflect {
|
|||
///
|
||||
/// [`DynamicStruct`]: crate::DynamicStruct
|
||||
fn path_mut<'p, T: Reflect>(&mut self, path: impl ReflectPath<'p>) -> PathResult<'p, &mut T> {
|
||||
path.element_mut(self.as_reflect_mut())
|
||||
path.element_mut(self.as_partial_reflect_mut())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -427,13 +433,16 @@ impl ParsedPath {
|
|||
}
|
||||
}
|
||||
impl<'a> ReflectPath<'a> for &'a ParsedPath {
|
||||
fn reflect_element(self, mut root: &dyn Reflect) -> PathResult<'a, &dyn Reflect> {
|
||||
fn reflect_element(self, mut root: &dyn PartialReflect) -> PathResult<'a, &dyn PartialReflect> {
|
||||
for OffsetAccess { access, offset } in &self.0 {
|
||||
root = access.element(root, *offset)?;
|
||||
}
|
||||
Ok(root)
|
||||
}
|
||||
fn reflect_element_mut(self, mut root: &mut dyn Reflect) -> PathResult<'a, &mut dyn Reflect> {
|
||||
fn reflect_element_mut(
|
||||
self,
|
||||
mut root: &mut dyn PartialReflect,
|
||||
) -> PathResult<'a, &mut dyn PartialReflect> {
|
||||
for OffsetAccess { access, offset } in &self.0 {
|
||||
root = access.element_mut(root, *offset)?;
|
||||
}
|
||||
|
|
|
@ -54,7 +54,7 @@ macro_rules! impl_reflect_enum {
|
|||
/// Each variant contains a trait object with methods specific to a kind of
|
||||
/// type.
|
||||
///
|
||||
/// A [`ReflectRef`] is obtained via [`Reflect::reflect_ref`].
|
||||
/// A [`ReflectRef`] is obtained via [`PartialReflect::reflect_ref`].
|
||||
pub enum ReflectRef<'a> {
|
||||
Struct(&'a dyn Struct),
|
||||
TupleStruct(&'a dyn TupleStruct),
|
||||
|
@ -64,7 +64,7 @@ pub enum ReflectRef<'a> {
|
|||
Map(&'a dyn Map),
|
||||
Set(&'a dyn Set),
|
||||
Enum(&'a dyn Enum),
|
||||
Value(&'a dyn Reflect),
|
||||
Value(&'a dyn PartialReflect),
|
||||
}
|
||||
impl_reflect_enum!(ReflectRef<'_>);
|
||||
|
||||
|
@ -73,7 +73,7 @@ impl_reflect_enum!(ReflectRef<'_>);
|
|||
/// Each variant contains a trait object with methods specific to a kind of
|
||||
/// type.
|
||||
///
|
||||
/// A [`ReflectMut`] is obtained via [`Reflect::reflect_mut`].
|
||||
/// A [`ReflectMut`] is obtained via [`PartialReflect::reflect_mut`].
|
||||
pub enum ReflectMut<'a> {
|
||||
Struct(&'a mut dyn Struct),
|
||||
TupleStruct(&'a mut dyn TupleStruct),
|
||||
|
@ -83,7 +83,7 @@ pub enum ReflectMut<'a> {
|
|||
Map(&'a mut dyn Map),
|
||||
Set(&'a mut dyn Set),
|
||||
Enum(&'a mut dyn Enum),
|
||||
Value(&'a mut dyn Reflect),
|
||||
Value(&'a mut dyn PartialReflect),
|
||||
}
|
||||
impl_reflect_enum!(ReflectMut<'_>);
|
||||
|
||||
|
@ -92,7 +92,7 @@ impl_reflect_enum!(ReflectMut<'_>);
|
|||
/// Each variant contains a trait object with methods specific to a kind of
|
||||
/// type.
|
||||
///
|
||||
/// A [`ReflectOwned`] is obtained via [`Reflect::reflect_owned`].
|
||||
/// A [`ReflectOwned`] is obtained via [`PartialReflect::reflect_owned`].
|
||||
pub enum ReflectOwned {
|
||||
Struct(Box<dyn Struct>),
|
||||
TupleStruct(Box<dyn TupleStruct>),
|
||||
|
@ -102,11 +102,11 @@ pub enum ReflectOwned {
|
|||
Map(Box<dyn Map>),
|
||||
Set(Box<dyn Set>),
|
||||
Enum(Box<dyn Enum>),
|
||||
Value(Box<dyn Reflect>),
|
||||
Value(Box<dyn PartialReflect>),
|
||||
}
|
||||
impl_reflect_enum!(ReflectOwned);
|
||||
|
||||
/// A enumeration of all error outcomes that might happen when running [`try_apply`](Reflect::try_apply).
|
||||
/// A enumeration of all error outcomes that might happen when running [`try_apply`](PartialReflect::try_apply).
|
||||
#[derive(Error, Debug)]
|
||||
pub enum ApplyError {
|
||||
#[error("attempted to apply `{from_kind}` to `{to_kind}`")]
|
||||
|
@ -144,7 +144,7 @@ pub enum ApplyError {
|
|||
|
||||
/// A zero-sized enumuration of the "kinds" of a reflected type.
|
||||
///
|
||||
/// A [`ReflectKind`] is obtained via [`Reflect::reflect_kind`],
|
||||
/// A [`ReflectKind`] is obtained via [`PartialReflect::reflect_kind`],
|
||||
/// or via [`ReflectRef::kind`],[`ReflectMut::kind`] or [`ReflectOwned::kind`].
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||
pub enum ReflectKind {
|
||||
|
@ -175,22 +175,29 @@ impl std::fmt::Display for ReflectKind {
|
|||
}
|
||||
}
|
||||
|
||||
/// The core trait of [`bevy_reflect`], used for accessing and modifying data dynamically.
|
||||
/// The foundational trait of [`bevy_reflect`], used for accessing and modifying data dynamically.
|
||||
///
|
||||
/// It's recommended to use the [derive macro] rather than manually implementing this trait.
|
||||
/// Doing so will automatically implement many other useful traits for reflection,
|
||||
/// This is a supertrait of [`Reflect`],
|
||||
/// meaning any type which implements `Reflect` implements `PartialReflect` by definition.
|
||||
///
|
||||
/// It's recommended to use [the derive macro for `Reflect`] rather than manually implementing this trait.
|
||||
/// Doing so will automatically implement this trait as well as many other useful traits for reflection,
|
||||
/// including one of the appropriate subtraits: [`Struct`], [`TupleStruct`] or [`Enum`].
|
||||
///
|
||||
/// See the [crate-level documentation] to see how this trait and its subtraits can be used.
|
||||
///
|
||||
/// [`bevy_reflect`]: crate
|
||||
/// [derive macro]: bevy_reflect_derive::Reflect
|
||||
/// [the derive macro for `Reflect`]: bevy_reflect_derive::Reflect
|
||||
/// [crate-level documentation]: crate
|
||||
#[diagnostic::on_unimplemented(
|
||||
message = "`{Self}` can not be reflected",
|
||||
message = "`{Self}` does not implement `PartialReflect` so cannot be introspected",
|
||||
note = "consider annotating `{Self}` with `#[derive(Reflect)]`"
|
||||
)]
|
||||
pub trait Reflect: DynamicTypePath + Any + Send + Sync {
|
||||
pub trait PartialReflect: DynamicTypePath + Send + Sync
|
||||
where
|
||||
// NB: we don't use `Self: Any` since for downcasting, `Reflect` should be used.
|
||||
Self: 'static,
|
||||
{
|
||||
/// Returns the [`TypeInfo`] of the type _represented_ by this value.
|
||||
///
|
||||
/// For most types, this will simply return their own `TypeInfo`.
|
||||
|
@ -208,27 +215,39 @@ pub trait Reflect: DynamicTypePath + Any + Send + Sync {
|
|||
/// [`TypeRegistry::get_type_info`]: crate::TypeRegistry::get_type_info
|
||||
fn get_represented_type_info(&self) -> Option<&'static TypeInfo>;
|
||||
|
||||
/// Returns the value as a [`Box<dyn Any>`][std::any::Any].
|
||||
fn into_any(self: Box<Self>) -> Box<dyn Any>;
|
||||
|
||||
/// Returns the value as a [`&dyn Any`][std::any::Any].
|
||||
fn as_any(&self) -> &dyn Any;
|
||||
|
||||
/// Returns the value as a [`&mut dyn Any`][std::any::Any].
|
||||
fn as_any_mut(&mut self) -> &mut dyn Any;
|
||||
|
||||
/// Casts this type to a boxed reflected value.
|
||||
fn into_reflect(self: Box<Self>) -> Box<dyn Reflect>;
|
||||
/// Casts this type to a boxed, reflected value.
|
||||
///
|
||||
/// This is useful for coercing trait objects.
|
||||
fn into_partial_reflect(self: Box<Self>) -> Box<dyn PartialReflect>;
|
||||
|
||||
/// Casts this type to a reflected value.
|
||||
fn as_reflect(&self) -> &dyn Reflect;
|
||||
///
|
||||
/// This is useful for coercing trait objects.
|
||||
fn as_partial_reflect(&self) -> &dyn PartialReflect;
|
||||
|
||||
/// Casts this type to a mutable reflected value.
|
||||
fn as_reflect_mut(&mut self) -> &mut dyn Reflect;
|
||||
/// Casts this type to a mutable, reflected value.
|
||||
///
|
||||
/// This is useful for coercing trait objects.
|
||||
fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect;
|
||||
|
||||
/// Attempts to cast this type to a boxed, [fully-reflected] value.
|
||||
///
|
||||
/// [fully-reflected]: Reflect
|
||||
fn try_into_reflect(self: Box<Self>) -> Result<Box<dyn Reflect>, Box<dyn PartialReflect>>;
|
||||
|
||||
/// Attempts to cast this type to a [fully-reflected] value.
|
||||
///
|
||||
/// [fully-reflected]: Reflect
|
||||
fn try_as_reflect(&self) -> Option<&dyn Reflect>;
|
||||
|
||||
/// Attempts to cast this type to a mutable, [fully-reflected] value.
|
||||
///
|
||||
/// [fully-reflected]: Reflect
|
||||
fn try_as_reflect_mut(&mut self) -> Option<&mut dyn Reflect>;
|
||||
|
||||
/// Applies a reflected value to this value.
|
||||
///
|
||||
/// If a type implements a subtrait of `Reflect`, then the semantics of this
|
||||
/// If a type implements an [introspection subtrait], then the semantics of this
|
||||
/// method are as follows:
|
||||
/// - If `T` is a [`Struct`], then the value of each named field of `value` is
|
||||
/// applied to the corresponding named field of `self`. Fields which are
|
||||
|
@ -255,6 +274,7 @@ pub trait Reflect: DynamicTypePath + Any + Send + Sync {
|
|||
/// or none of the above depending on the kind of type. For lists and maps, use the
|
||||
/// [`list_apply`] and [`map_apply`] helper functions when implementing this method.
|
||||
///
|
||||
/// [introspection subtrait]: crate#the-introspection-subtraits
|
||||
/// [`list_apply`]: crate::list_apply
|
||||
/// [`map_apply`]: crate::map_apply
|
||||
///
|
||||
|
@ -266,26 +286,20 @@ pub trait Reflect: DynamicTypePath + Any + Send + Sync {
|
|||
/// - If `T` is any complex type and the corresponding fields or elements of
|
||||
/// `self` and `value` are not of the same type.
|
||||
/// - If `T` is a value type and `self` cannot be downcast to `T`
|
||||
fn apply(&mut self, value: &dyn Reflect) {
|
||||
Reflect::try_apply(self, value).unwrap();
|
||||
fn apply(&mut self, value: &dyn PartialReflect) {
|
||||
PartialReflect::try_apply(self, value).unwrap();
|
||||
}
|
||||
|
||||
/// Tries to [`apply`](Reflect::apply) a reflected value to this value.
|
||||
/// Tries to [`apply`](PartialReflect::apply) a reflected value to this value.
|
||||
///
|
||||
/// Functions the same as the [`apply`](Reflect::apply) function but returns an error instead of
|
||||
/// Functions the same as the [`apply`](PartialReflect::apply) function but returns an error instead of
|
||||
/// panicking.
|
||||
///
|
||||
/// # Handling Errors
|
||||
///
|
||||
/// This function may leave `self` in a partially mutated state if a error was encountered on the way.
|
||||
/// consider maintaining a cloned instance of this data you can switch to if a error is encountered.
|
||||
fn try_apply(&mut self, value: &dyn Reflect) -> Result<(), ApplyError>;
|
||||
|
||||
/// Performs a type-checked assignment of a reflected value to this value.
|
||||
///
|
||||
/// If `value` does not contain a value of type `T`, returns an `Err`
|
||||
/// containing the trait object.
|
||||
fn set(&mut self, value: Box<dyn Reflect>) -> Result<(), Box<dyn Reflect>>;
|
||||
fn try_apply(&mut self, value: &dyn PartialReflect) -> Result<(), ApplyError>;
|
||||
|
||||
/// Returns a zero-sized enumeration of "kinds" of type.
|
||||
///
|
||||
|
@ -316,7 +330,7 @@ pub trait Reflect: DynamicTypePath + Any + Send + Sync {
|
|||
/// or [`Enum::clone_dynamic`], respectively.
|
||||
/// Implementors of other `Reflect` subtraits (e.g. [`List`], [`Map`]) should
|
||||
/// use those subtraits' respective `clone_dynamic` methods.
|
||||
fn clone_value(&self) -> Box<dyn Reflect>;
|
||||
fn clone_value(&self) -> Box<dyn PartialReflect>;
|
||||
|
||||
/// Returns a hash of the value (which includes the type).
|
||||
///
|
||||
|
@ -328,7 +342,7 @@ pub trait Reflect: DynamicTypePath + Any + Send + Sync {
|
|||
/// Returns a "partial equality" comparison result.
|
||||
///
|
||||
/// If the underlying type does not support equality testing, returns `None`.
|
||||
fn reflect_partial_eq(&self, _value: &dyn Reflect) -> Option<bool> {
|
||||
fn reflect_partial_eq(&self, _value: &dyn PartialReflect) -> Option<bool> {
|
||||
None
|
||||
}
|
||||
|
||||
|
@ -376,29 +390,116 @@ pub trait Reflect: DynamicTypePath + Any + Send + Sync {
|
|||
}
|
||||
}
|
||||
|
||||
impl Debug for dyn Reflect {
|
||||
/// A core trait of [`bevy_reflect`], used for downcasting to concrete types.
|
||||
///
|
||||
/// This is a subtrait of [`PartialReflect`],
|
||||
/// meaning any type which implements `Reflect` implements `PartialReflect` by definition.
|
||||
///
|
||||
/// It's recommended to use [the derive macro] rather than manually implementing this trait.
|
||||
/// Doing so will automatically implement this trait, [`PartialReflect`], and many other useful traits for reflection,
|
||||
/// including one of the appropriate subtraits: [`Struct`], [`TupleStruct`] or [`Enum`].
|
||||
///
|
||||
/// See the [crate-level documentation] to see how this trait can be used.
|
||||
///
|
||||
/// [`bevy_reflect`]: crate
|
||||
/// [the derive macro]: bevy_reflect_derive::Reflect
|
||||
/// [crate-level documentation]: crate
|
||||
#[diagnostic::on_unimplemented(
|
||||
message = "`{Self}` does not implement `Reflect` so cannot be fully reflected",
|
||||
note = "consider annotating `{Self}` with `#[derive(Reflect)]`"
|
||||
)]
|
||||
pub trait Reflect: PartialReflect + Any {
|
||||
/// Returns the value as a [`Box<dyn Any>`][std::any::Any].
|
||||
fn into_any(self: Box<Self>) -> Box<dyn Any>;
|
||||
|
||||
/// Returns the value as a [`&dyn Any`][std::any::Any].
|
||||
fn as_any(&self) -> &dyn Any;
|
||||
|
||||
/// Returns the value as a [`&mut dyn Any`][std::any::Any].
|
||||
fn as_any_mut(&mut self) -> &mut dyn Any;
|
||||
|
||||
/// Casts this type to a boxed, fully-reflected value.
|
||||
fn into_reflect(self: Box<Self>) -> Box<dyn Reflect>;
|
||||
|
||||
/// Casts this type to a fully-reflected value.
|
||||
fn as_reflect(&self) -> &dyn Reflect;
|
||||
|
||||
/// Casts this type to a mutable, fully-reflected value.
|
||||
fn as_reflect_mut(&mut self) -> &mut dyn Reflect;
|
||||
|
||||
/// Performs a type-checked assignment of a reflected value to this value.
|
||||
///
|
||||
/// If `value` does not contain a value of type `T`, returns an `Err`
|
||||
/// containing the trait object.
|
||||
fn set(&mut self, value: Box<dyn Reflect>) -> Result<(), Box<dyn Reflect>>;
|
||||
}
|
||||
|
||||
impl dyn PartialReflect {
|
||||
/// Returns `true` if the underlying value represents a value of type `T`, or `false`
|
||||
/// otherwise.
|
||||
///
|
||||
/// Read `is` for more information on underlying values and represented types.
|
||||
#[inline]
|
||||
pub fn represents<T: Reflect + TypePath>(&self) -> bool {
|
||||
self.get_represented_type_info()
|
||||
.map(|t| t.type_path() == T::type_path())
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
/// Downcasts the value to type `T`, consuming the trait object.
|
||||
///
|
||||
/// If the underlying value does not implement [`Reflect`]
|
||||
/// or is not of type `T`, returns `Err(self)`.
|
||||
pub fn try_downcast<T: Reflect>(
|
||||
self: Box<dyn PartialReflect>,
|
||||
) -> Result<Box<T>, Box<dyn PartialReflect>> {
|
||||
self.try_into_reflect()?
|
||||
.downcast()
|
||||
.map_err(PartialReflect::into_partial_reflect)
|
||||
}
|
||||
|
||||
/// Downcasts the value to type `T`, unboxing and consuming the trait object.
|
||||
///
|
||||
/// If the underlying value does not implement [`Reflect`]
|
||||
/// or is not of type `T`, returns `Err(self)`.
|
||||
pub fn try_take<T: Reflect>(
|
||||
self: Box<dyn PartialReflect>,
|
||||
) -> Result<T, Box<dyn PartialReflect>> {
|
||||
self.try_downcast().map(|value| *value)
|
||||
}
|
||||
|
||||
/// Downcasts the value to type `T` by reference.
|
||||
///
|
||||
/// If the underlying value does not implement [`Reflect`]
|
||||
/// or is not of type `T`, returns [`None`].
|
||||
pub fn try_downcast_ref<T: Reflect>(&self) -> Option<&T> {
|
||||
self.try_as_reflect()?.downcast_ref()
|
||||
}
|
||||
|
||||
/// Downcasts the value to type `T` by mutable reference.
|
||||
///
|
||||
/// If the underlying value does not implement [`Reflect`]
|
||||
/// or is not of type `T`, returns [`None`].
|
||||
pub fn try_downcast_mut<T: Reflect>(&mut self) -> Option<&mut T> {
|
||||
self.try_as_reflect_mut()?.downcast_mut()
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for dyn PartialReflect {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
self.debug(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl Typed for dyn Reflect {
|
||||
fn type_info() -> &'static TypeInfo {
|
||||
static CELL: NonGenericTypeInfoCell = NonGenericTypeInfoCell::new();
|
||||
CELL.get_or_set(|| TypeInfo::Value(ValueInfo::new::<Self>()))
|
||||
}
|
||||
}
|
||||
|
||||
// The following implementation never actually shadows the concrete TypePath implementation.
|
||||
|
||||
// See this playground (https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=589064053f27bc100d90da89c6a860aa).
|
||||
impl TypePath for dyn Reflect {
|
||||
// See the comment on `dyn Reflect`'s `TypePath` implementation.
|
||||
impl TypePath for dyn PartialReflect {
|
||||
fn type_path() -> &'static str {
|
||||
"dyn bevy_reflect::Reflect"
|
||||
"dyn bevy_reflect::PartialReflect"
|
||||
}
|
||||
|
||||
fn short_type_path() -> &'static str {
|
||||
"dyn Reflect"
|
||||
"dyn PartialReflect"
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -422,17 +523,6 @@ impl dyn Reflect {
|
|||
self.downcast::<T>().map(|value| *value)
|
||||
}
|
||||
|
||||
/// Returns `true` if the underlying value represents a value of type `T`, or `false`
|
||||
/// otherwise.
|
||||
///
|
||||
/// Read `is` for more information on underlying values and represented types.
|
||||
#[inline]
|
||||
pub fn represents<T: Reflect + TypePath>(&self) -> bool {
|
||||
self.get_represented_type_info()
|
||||
.map(|t| t.type_path() == T::type_path())
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
/// Returns `true` if the underlying value is of type `T`, or `false`
|
||||
/// otherwise.
|
||||
///
|
||||
|
@ -464,3 +554,68 @@ impl dyn Reflect {
|
|||
self.as_any_mut().downcast_mut::<T>()
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for dyn Reflect {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
self.debug(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl Typed for dyn Reflect {
|
||||
fn type_info() -> &'static TypeInfo {
|
||||
static CELL: NonGenericTypeInfoCell = NonGenericTypeInfoCell::new();
|
||||
CELL.get_or_set(|| TypeInfo::Value(ValueInfo::new::<Self>()))
|
||||
}
|
||||
}
|
||||
|
||||
// The following implementation never actually shadows the concrete `TypePath` implementation.
|
||||
// See this playground (https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=589064053f27bc100d90da89c6a860aa).
|
||||
impl TypePath for dyn Reflect {
|
||||
fn type_path() -> &'static str {
|
||||
"dyn bevy_reflect::Reflect"
|
||||
}
|
||||
|
||||
fn short_type_path() -> &'static str {
|
||||
"dyn Reflect"
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_full_reflect {
|
||||
($(<$($id:ident),* $(,)?>)? for $ty:ty $(where $($tt:tt)*)?) => {
|
||||
impl $(<$($id),*>)? $crate::Reflect for $ty $(where $($tt)*)? {
|
||||
fn into_any(self: Box<Self>) -> Box<dyn ::std::any::Any> {
|
||||
self
|
||||
}
|
||||
|
||||
fn as_any(&self) -> &dyn ::std::any::Any {
|
||||
self
|
||||
}
|
||||
|
||||
fn as_any_mut(&mut self) -> &mut dyn ::std::any::Any {
|
||||
self
|
||||
}
|
||||
|
||||
fn into_reflect(self: Box<Self>) -> Box<dyn $crate::Reflect> {
|
||||
self
|
||||
}
|
||||
|
||||
fn as_reflect(&self) -> &dyn $crate::Reflect {
|
||||
self
|
||||
}
|
||||
|
||||
fn as_reflect_mut(&mut self) -> &mut dyn $crate::Reflect {
|
||||
self
|
||||
}
|
||||
|
||||
fn set(
|
||||
&mut self,
|
||||
value: Box<dyn $crate::Reflect>,
|
||||
) -> Result<(), Box<dyn $crate::Reflect>> {
|
||||
*self = <dyn $crate::Reflect>::take(value)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
pub(crate) use impl_full_reflect;
|
||||
|
|
|
@ -2,8 +2,9 @@ use crate::serde::SerializationData;
|
|||
use crate::{
|
||||
ArrayInfo, DynamicArray, DynamicEnum, DynamicList, DynamicMap, DynamicSet, DynamicStruct,
|
||||
DynamicTuple, DynamicTupleStruct, DynamicVariant, EnumInfo, ListInfo, Map, MapInfo, NamedField,
|
||||
Reflect, ReflectDeserialize, Set, SetInfo, StructInfo, StructVariantInfo, TupleInfo,
|
||||
TupleStructInfo, TupleVariantInfo, TypeInfo, TypeRegistration, TypeRegistry, VariantInfo,
|
||||
PartialReflect, Reflect, ReflectDeserialize, Set, SetInfo, StructInfo, StructVariantInfo,
|
||||
TupleInfo, TupleStructInfo, TupleVariantInfo, TypeInfo, TypeRegistration, TypeRegistry,
|
||||
VariantInfo,
|
||||
};
|
||||
use erased_serde::Deserializer;
|
||||
use serde::de::{
|
||||
|
@ -339,21 +340,21 @@ impl<'a, 'de> DeserializeSeed<'de> for TypeRegistrationDeserializer<'a> {
|
|||
/// let mut deserializer = ron::Deserializer::from_str(input).unwrap();
|
||||
/// let reflect_deserializer = ReflectDeserializer::new(®istry);
|
||||
///
|
||||
/// let output: Box<dyn Reflect> = reflect_deserializer.deserialize(&mut deserializer).unwrap();
|
||||
/// let output: Box<dyn PartialReflect> = reflect_deserializer.deserialize(&mut deserializer).unwrap();
|
||||
///
|
||||
/// // Since `MyStruct` is not a value type and does not register `ReflectDeserialize`,
|
||||
/// // we know that its deserialized representation will be a `DynamicStruct`.
|
||||
/// assert!(output.is::<DynamicStruct>());
|
||||
/// assert!(output.represents::<MyStruct>());
|
||||
/// // we know that its deserialized value will be a `DynamicStruct`,
|
||||
/// // although it will represent `MyStruct`.
|
||||
/// assert!(output.as_partial_reflect().represents::<MyStruct>());
|
||||
///
|
||||
/// // We can convert back to `MyStruct` using `FromReflect`.
|
||||
/// let value: MyStruct = <MyStruct as FromReflect>::from_reflect(&*output).unwrap();
|
||||
/// let value: MyStruct = <MyStruct as FromReflect>::from_reflect(output.as_partial_reflect()).unwrap();
|
||||
/// assert_eq!(value, MyStruct { value: 123 });
|
||||
///
|
||||
/// // We can also do this dynamically with `ReflectFromReflect`.
|
||||
/// let type_id = output.get_represented_type_info().unwrap().type_id();
|
||||
/// let reflect_from_reflect = registry.get_type_data::<ReflectFromReflect>(type_id).unwrap();
|
||||
/// let value: Box<dyn Reflect> = reflect_from_reflect.from_reflect(&*output).unwrap();
|
||||
/// let value: Box<dyn Reflect> = reflect_from_reflect.from_reflect(output.as_partial_reflect()).unwrap();
|
||||
/// assert!(value.is::<MyStruct>());
|
||||
/// assert_eq!(value.take::<MyStruct>().unwrap(), MyStruct { value: 123 });
|
||||
/// ```
|
||||
|
@ -378,7 +379,7 @@ impl<'a> ReflectDeserializer<'a> {
|
|||
}
|
||||
|
||||
impl<'a, 'de> DeserializeSeed<'de> for ReflectDeserializer<'a> {
|
||||
type Value = Box<dyn Reflect>;
|
||||
type Value = Box<dyn PartialReflect>;
|
||||
|
||||
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
|
||||
where
|
||||
|
@ -389,7 +390,7 @@ impl<'a, 'de> DeserializeSeed<'de> for ReflectDeserializer<'a> {
|
|||
}
|
||||
|
||||
impl<'a, 'de> Visitor<'de> for UntypedReflectDeserializerVisitor<'a> {
|
||||
type Value = Box<dyn Reflect>;
|
||||
type Value = Box<dyn PartialReflect>;
|
||||
|
||||
fn expecting(&self, formatter: &mut Formatter) -> fmt::Result {
|
||||
formatter
|
||||
|
@ -472,21 +473,21 @@ impl<'a, 'de> DeserializeSeed<'de> for ReflectDeserializer<'a> {
|
|||
/// let mut deserializer = ron::Deserializer::from_str(input).unwrap();
|
||||
/// let reflect_deserializer = TypedReflectDeserializer::new(registration, ®istry);
|
||||
///
|
||||
/// let output: Box<dyn Reflect> = reflect_deserializer.deserialize(&mut deserializer).unwrap();
|
||||
/// let output: Box<dyn PartialReflect> = reflect_deserializer.deserialize(&mut deserializer).unwrap();
|
||||
///
|
||||
/// // Since `MyStruct` is not a value type and does not register `ReflectDeserialize`,
|
||||
/// // we know that its deserialized representation will be a `DynamicStruct`.
|
||||
/// assert!(output.is::<DynamicStruct>());
|
||||
/// assert!(output.represents::<MyStruct>());
|
||||
/// // we know that its deserialized value will be a `DynamicStruct`,
|
||||
/// // although it will represent `MyStruct`.
|
||||
/// assert!(output.as_partial_reflect().represents::<MyStruct>());
|
||||
///
|
||||
/// // We can convert back to `MyStruct` using `FromReflect`.
|
||||
/// let value: MyStruct = <MyStruct as FromReflect>::from_reflect(&*output).unwrap();
|
||||
/// let value: MyStruct = <MyStruct as FromReflect>::from_reflect(output.as_partial_reflect()).unwrap();
|
||||
/// assert_eq!(value, MyStruct { value: 123 });
|
||||
///
|
||||
/// // We can also do this dynamically with `ReflectFromReflect`.
|
||||
/// let type_id = output.get_represented_type_info().unwrap().type_id();
|
||||
/// let reflect_from_reflect = registry.get_type_data::<ReflectFromReflect>(type_id).unwrap();
|
||||
/// let value: Box<dyn Reflect> = reflect_from_reflect.from_reflect(&*output).unwrap();
|
||||
/// let value: Box<dyn Reflect> = reflect_from_reflect.from_reflect(output.as_partial_reflect()).unwrap();
|
||||
/// assert!(value.is::<MyStruct>());
|
||||
/// assert_eq!(value.take::<MyStruct>().unwrap(), MyStruct { value: 123 });
|
||||
/// ```
|
||||
|
@ -514,7 +515,7 @@ impl<'a> TypedReflectDeserializer<'a> {
|
|||
}
|
||||
|
||||
impl<'a, 'de> DeserializeSeed<'de> for TypedReflectDeserializer<'a> {
|
||||
type Value = Box<dyn Reflect>;
|
||||
type Value = Box<dyn PartialReflect>;
|
||||
|
||||
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
|
||||
where
|
||||
|
@ -525,7 +526,7 @@ impl<'a, 'de> DeserializeSeed<'de> for TypedReflectDeserializer<'a> {
|
|||
// Handle both Value case and types that have a custom `ReflectDeserialize`
|
||||
if let Some(deserialize_reflect) = self.registration.data::<ReflectDeserialize>() {
|
||||
let value = deserialize_reflect.deserialize(deserializer)?;
|
||||
return Ok(value);
|
||||
return Ok(value.into_partial_reflect());
|
||||
}
|
||||
|
||||
match self.registration.type_info() {
|
||||
|
@ -1107,7 +1108,10 @@ where
|
|||
let Some(field) = info.field_at(*skipped_index) else {
|
||||
continue;
|
||||
};
|
||||
dynamic_struct.insert_boxed(field.name(), skipped_field.generate_default());
|
||||
dynamic_struct.insert_boxed(
|
||||
field.name(),
|
||||
skipped_field.generate_default().into_partial_reflect(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1137,7 +1141,7 @@ where
|
|||
|
||||
for index in 0..len {
|
||||
if let Some(value) = serialization_data.and_then(|data| data.generate_default(index)) {
|
||||
tuple.insert_boxed(value);
|
||||
tuple.insert_boxed(value.into_partial_reflect());
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1182,7 +1186,7 @@ where
|
|||
.unwrap_or_default()
|
||||
{
|
||||
if let Some(value) = serialization_data.unwrap().generate_default(index) {
|
||||
dynamic_struct.insert_boxed(name, value);
|
||||
dynamic_struct.insert_boxed(name, value.into_partial_reflect());
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
@ -1224,7 +1228,9 @@ mod tests {
|
|||
|
||||
use crate as bevy_reflect;
|
||||
use crate::serde::{ReflectDeserializer, ReflectSerializer, TypedReflectDeserializer};
|
||||
use crate::{DynamicEnum, FromReflect, Reflect, ReflectDeserialize, TypeRegistry};
|
||||
use crate::{
|
||||
DynamicEnum, FromReflect, PartialReflect, Reflect, ReflectDeserialize, TypeRegistry,
|
||||
};
|
||||
|
||||
#[derive(Reflect, Debug, PartialEq)]
|
||||
struct MyStruct {
|
||||
|
@ -1445,7 +1451,7 @@ mod tests {
|
|||
.deserialize(&mut ron_deserializer)
|
||||
.unwrap();
|
||||
let output = dynamic_output
|
||||
.take::<f32>()
|
||||
.try_take::<f32>()
|
||||
.expect("underlying type should be f32");
|
||||
assert_eq!(1.23, output);
|
||||
}
|
||||
|
@ -1472,7 +1478,9 @@ mod tests {
|
|||
.deserialize(&mut ron_deserializer)
|
||||
.unwrap();
|
||||
|
||||
let output = <Foo as FromReflect>::from_reflect(dynamic_output.as_ref()).unwrap();
|
||||
let output =
|
||||
<Foo as FromReflect>::from_reflect(dynamic_output.as_ref().as_partial_reflect())
|
||||
.unwrap();
|
||||
assert_eq!(expected, output);
|
||||
}
|
||||
|
||||
|
@ -1585,7 +1593,9 @@ mod tests {
|
|||
let output = reflect_deserializer.deserialize(&mut deserializer).unwrap();
|
||||
|
||||
let expected = DynamicEnum::from(MyEnum::Tuple(1.23, 3.21));
|
||||
assert!(expected.reflect_partial_eq(output.as_ref()).unwrap());
|
||||
assert!(expected
|
||||
.reflect_partial_eq(output.as_partial_reflect())
|
||||
.unwrap());
|
||||
|
||||
// === Struct Variant === //
|
||||
let input = r#"{
|
||||
|
@ -1600,7 +1610,9 @@ mod tests {
|
|||
let expected = DynamicEnum::from(MyEnum::Struct {
|
||||
value: String::from("I <3 Enums"),
|
||||
});
|
||||
assert!(expected.reflect_partial_eq(output.as_ref()).unwrap());
|
||||
assert!(expected
|
||||
.reflect_partial_eq(output.as_partial_reflect())
|
||||
.unwrap());
|
||||
}
|
||||
|
||||
// Regression test for https://github.com/bevyengine/bevy/issues/12462
|
||||
|
@ -1616,7 +1628,7 @@ mod tests {
|
|||
let reflect_deserializer = ReflectDeserializer::new(®istry);
|
||||
let input2 = reflect_deserializer.deserialize(&mut deserializer).unwrap();
|
||||
|
||||
let serializer2 = ReflectSerializer::new(&*input2, ®istry);
|
||||
let serializer2 = ReflectSerializer::new(input2.as_partial_reflect(), ®istry);
|
||||
let serialized2 = ron::ser::to_string(&serializer2).unwrap();
|
||||
|
||||
assert_eq!(serialized1, serialized2);
|
||||
|
|
|
@ -8,7 +8,7 @@ pub use type_data::*;
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{self as bevy_reflect, DynamicTupleStruct, Struct};
|
||||
use crate::{self as bevy_reflect, DynamicTupleStruct, PartialReflect, Struct};
|
||||
use crate::{
|
||||
serde::{ReflectDeserializer, ReflectSerializer},
|
||||
type_registry::TypeRegistry,
|
||||
|
@ -53,8 +53,7 @@ mod tests {
|
|||
|
||||
let mut deserializer = ron::de::Deserializer::from_str(&serialized).unwrap();
|
||||
let reflect_deserializer = ReflectDeserializer::new(®istry);
|
||||
let value = reflect_deserializer.deserialize(&mut deserializer).unwrap();
|
||||
let deserialized = value.take::<DynamicStruct>().unwrap();
|
||||
let deserialized = reflect_deserializer.deserialize(&mut deserializer).unwrap();
|
||||
|
||||
let mut expected = DynamicStruct::default();
|
||||
expected.insert("a", 3);
|
||||
|
@ -64,7 +63,9 @@ mod tests {
|
|||
expected.insert("e", 7);
|
||||
|
||||
assert!(
|
||||
expected.reflect_partial_eq(&deserialized).unwrap(),
|
||||
expected
|
||||
.reflect_partial_eq(deserialized.as_partial_reflect())
|
||||
.unwrap(),
|
||||
"Deserialization failed: expected {expected:?} found {deserialized:?}"
|
||||
);
|
||||
|
||||
|
@ -75,7 +76,8 @@ mod tests {
|
|||
d: -1,
|
||||
e: 7,
|
||||
};
|
||||
let received = <TestStruct as FromReflect>::from_reflect(&deserialized).unwrap();
|
||||
let received =
|
||||
<TestStruct as FromReflect>::from_reflect(deserialized.as_partial_reflect()).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
expected, received,
|
||||
|
@ -112,8 +114,7 @@ mod tests {
|
|||
|
||||
let mut deserializer = ron::de::Deserializer::from_str(&serialized).unwrap();
|
||||
let reflect_deserializer = ReflectDeserializer::new(®istry);
|
||||
let value = reflect_deserializer.deserialize(&mut deserializer).unwrap();
|
||||
let deserialized = value.take::<DynamicTupleStruct>().unwrap();
|
||||
let deserialized = reflect_deserializer.deserialize(&mut deserializer).unwrap();
|
||||
|
||||
let mut expected = DynamicTupleStruct::default();
|
||||
expected.insert(3);
|
||||
|
@ -123,12 +124,15 @@ mod tests {
|
|||
expected.insert(7);
|
||||
|
||||
assert!(
|
||||
expected.reflect_partial_eq(&deserialized).unwrap(),
|
||||
expected
|
||||
.reflect_partial_eq(deserialized.as_partial_reflect())
|
||||
.unwrap(),
|
||||
"Deserialization failed: expected {expected:?} found {deserialized:?}"
|
||||
);
|
||||
|
||||
let expected = TestStruct(3, 0, 0, -1, 7);
|
||||
let received = <TestStruct as FromReflect>::from_reflect(&deserialized).unwrap();
|
||||
let received =
|
||||
<TestStruct as FromReflect>::from_reflect(deserialized.as_partial_reflect()).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
expected, received,
|
||||
|
@ -173,12 +177,10 @@ mod tests {
|
|||
let reflect_deserializer = ReflectDeserializer::new(®istry);
|
||||
|
||||
let expected = value.clone_value();
|
||||
let result = reflect_deserializer
|
||||
.deserialize(&mut deserializer)
|
||||
.unwrap()
|
||||
.take::<DynamicStruct>()
|
||||
.unwrap();
|
||||
let result = reflect_deserializer.deserialize(&mut deserializer).unwrap();
|
||||
|
||||
assert!(expected.reflect_partial_eq(&result).unwrap());
|
||||
assert!(expected
|
||||
.reflect_partial_eq(result.as_partial_reflect())
|
||||
.unwrap());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::{
|
||||
Array, Enum, List, Map, Reflect, ReflectRef, ReflectSerialize, Set, Struct, Tuple, TupleStruct,
|
||||
TypeInfo, TypeRegistry, VariantInfo, VariantType,
|
||||
Array, Enum, List, Map, PartialReflect, ReflectRef, ReflectSerialize, Set, Struct, Tuple,
|
||||
TupleStruct, TypeInfo, TypeRegistry, VariantInfo, VariantType,
|
||||
};
|
||||
use serde::ser::{
|
||||
Error, SerializeStruct, SerializeStructVariant, SerializeTuple, SerializeTupleStruct,
|
||||
|
@ -29,9 +29,15 @@ impl<'a> Serializable<'a> {
|
|||
}
|
||||
|
||||
fn get_serializable<'a, E: Error>(
|
||||
reflect_value: &'a dyn Reflect,
|
||||
reflect_value: &'a dyn PartialReflect,
|
||||
type_registry: &TypeRegistry,
|
||||
) -> Result<Serializable<'a>, E> {
|
||||
let Some(reflect_value) = reflect_value.try_as_reflect() else {
|
||||
return Err(Error::custom(format_args!(
|
||||
"Type '{}' does not implement `Reflect`",
|
||||
reflect_value.reflect_type_path()
|
||||
)));
|
||||
};
|
||||
let info = reflect_value.get_represented_type_info().ok_or_else(|| {
|
||||
Error::custom(format_args!(
|
||||
"Type '{}' does not represent any type",
|
||||
|
@ -93,12 +99,12 @@ fn get_serializable<'a, E: Error>(
|
|||
/// [`ReflectDeserializer`]: crate::serde::ReflectDeserializer
|
||||
/// [type path]: crate::TypePath::type_path
|
||||
pub struct ReflectSerializer<'a> {
|
||||
pub value: &'a dyn Reflect,
|
||||
pub value: &'a dyn PartialReflect,
|
||||
pub registry: &'a TypeRegistry,
|
||||
}
|
||||
|
||||
impl<'a> ReflectSerializer<'a> {
|
||||
pub fn new(value: &'a dyn Reflect, registry: &'a TypeRegistry) -> Self {
|
||||
pub fn new(value: &'a dyn PartialReflect, registry: &'a TypeRegistry) -> Self {
|
||||
ReflectSerializer { value, registry }
|
||||
}
|
||||
}
|
||||
|
@ -171,12 +177,12 @@ impl<'a> Serialize for ReflectSerializer<'a> {
|
|||
/// [`TypedReflectDeserializer`]: crate::serde::TypedReflectDeserializer
|
||||
/// [type path]: crate::TypePath::type_path
|
||||
pub struct TypedReflectSerializer<'a> {
|
||||
pub value: &'a dyn Reflect,
|
||||
pub value: &'a dyn PartialReflect,
|
||||
pub registry: &'a TypeRegistry,
|
||||
}
|
||||
|
||||
impl<'a> TypedReflectSerializer<'a> {
|
||||
pub fn new(value: &'a dyn Reflect, registry: &'a TypeRegistry) -> Self {
|
||||
pub fn new(value: &'a dyn PartialReflect, registry: &'a TypeRegistry) -> Self {
|
||||
TypedReflectSerializer { value, registry }
|
||||
}
|
||||
}
|
||||
|
@ -240,7 +246,7 @@ impl<'a> Serialize for TypedReflectSerializer<'a> {
|
|||
|
||||
pub struct ReflectValueSerializer<'a> {
|
||||
pub registry: &'a TypeRegistry,
|
||||
pub value: &'a dyn Reflect,
|
||||
pub value: &'a dyn PartialReflect,
|
||||
}
|
||||
|
||||
impl<'a> Serialize for ReflectValueSerializer<'a> {
|
||||
|
@ -565,7 +571,7 @@ impl<'a> Serialize for ArraySerializer<'a> {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::serde::ReflectSerializer;
|
||||
use crate::{self as bevy_reflect, Struct};
|
||||
use crate::{self as bevy_reflect, PartialReflect, Struct};
|
||||
use crate::{Reflect, ReflectSerialize, TypeRegistry};
|
||||
use bevy_utils::{HashMap, HashSet};
|
||||
use ron::extensions::Extensions;
|
||||
|
@ -946,7 +952,7 @@ mod tests {
|
|||
none: None,
|
||||
};
|
||||
let dynamic = value.clone_dynamic();
|
||||
let reflect = dynamic.as_reflect();
|
||||
let reflect = dynamic.as_partial_reflect();
|
||||
|
||||
let registry = get_registry();
|
||||
|
||||
|
|
|
@ -6,8 +6,8 @@ use bevy_utils::hashbrown::hash_table::OccupiedEntry as HashTableOccupiedEntry;
|
|||
use bevy_utils::hashbrown::HashTable;
|
||||
|
||||
use crate::{
|
||||
self as bevy_reflect, hash_error, ApplyError, Reflect, ReflectKind, ReflectMut, ReflectOwned,
|
||||
ReflectRef, TypeInfo, TypePath, TypePathTable,
|
||||
self as bevy_reflect, hash_error, ApplyError, PartialReflect, Reflect, ReflectKind, ReflectMut,
|
||||
ReflectOwned, ReflectRef, TypeInfo, TypePath, TypePathTable,
|
||||
};
|
||||
|
||||
/// A trait used to power [set-like] operations via [reflection].
|
||||
|
@ -17,7 +17,7 @@ use crate::{
|
|||
///
|
||||
/// # Hashing
|
||||
///
|
||||
/// All values are expected to return a valid hash value from [`Reflect::reflect_hash`].
|
||||
/// All values are expected to return a valid hash value from [`PartialReflect::reflect_hash`].
|
||||
/// If using the [`#[derive(Reflect)]`](derive@crate::Reflect) macro, this can be done by adding `#[reflect(Hash)]`
|
||||
/// to the entire struct or enum.
|
||||
/// This is true even for manual implementors who do not use the hashed value,
|
||||
|
@ -26,7 +26,7 @@ use crate::{
|
|||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use bevy_reflect::{Reflect, Set};
|
||||
/// use bevy_reflect::{PartialReflect, Set};
|
||||
/// use bevy_utils::HashSet;
|
||||
///
|
||||
///
|
||||
|
@ -34,17 +34,17 @@ use crate::{
|
|||
/// foo.insert_boxed(Box::new(123_u32));
|
||||
/// assert_eq!(foo.len(), 1);
|
||||
///
|
||||
/// let field: &dyn Reflect = foo.get(&123_u32).unwrap();
|
||||
/// assert_eq!(field.downcast_ref::<u32>(), Some(&123_u32));
|
||||
/// let field: &dyn PartialReflect = foo.get(&123_u32).unwrap();
|
||||
/// assert_eq!(field.try_downcast_ref::<u32>(), Some(&123_u32));
|
||||
/// ```
|
||||
///
|
||||
/// [set-like]: https://doc.rust-lang.org/stable/std/collections/struct.HashSet.html
|
||||
/// [reflection]: crate
|
||||
pub trait Set: Reflect {
|
||||
pub trait Set: PartialReflect {
|
||||
/// Returns a reference to the value.
|
||||
///
|
||||
/// If no value is contained, returns `None`.
|
||||
fn get(&self, value: &dyn Reflect) -> Option<&dyn Reflect>;
|
||||
fn get(&self, value: &dyn PartialReflect) -> Option<&dyn PartialReflect>;
|
||||
|
||||
/// Returns the number of elements in the set.
|
||||
fn len(&self) -> usize;
|
||||
|
@ -55,10 +55,10 @@ pub trait Set: Reflect {
|
|||
}
|
||||
|
||||
/// Returns an iterator over the values of the set.
|
||||
fn iter(&self) -> Box<dyn Iterator<Item = &dyn Reflect> + '_>;
|
||||
fn iter(&self) -> Box<dyn Iterator<Item = &dyn PartialReflect> + '_>;
|
||||
|
||||
/// Drain the values of this set to get a vector of owned values.
|
||||
fn drain(self: Box<Self>) -> Vec<Box<dyn Reflect>>;
|
||||
fn drain(self: Box<Self>) -> Vec<Box<dyn PartialReflect>>;
|
||||
|
||||
/// Clones the set, producing a [`DynamicSet`].
|
||||
fn clone_dynamic(&self) -> DynamicSet;
|
||||
|
@ -67,16 +67,16 @@ pub trait Set: Reflect {
|
|||
///
|
||||
/// If the set did not have this value present, `true` is returned.
|
||||
/// If the set did have this value present, `false` is returned.
|
||||
fn insert_boxed(&mut self, value: Box<dyn Reflect>) -> bool;
|
||||
fn insert_boxed(&mut self, value: Box<dyn PartialReflect>) -> bool;
|
||||
|
||||
/// Removes a value from the set.
|
||||
///
|
||||
/// If the set did not have this value present, `true` is returned.
|
||||
/// If the set did have this value present, `false` is returned.
|
||||
fn remove(&mut self, value: &dyn Reflect) -> bool;
|
||||
fn remove(&mut self, value: &dyn PartialReflect) -> bool;
|
||||
|
||||
/// Checks if the given value is contained in the set
|
||||
fn contains(&self, value: &dyn Reflect) -> bool;
|
||||
fn contains(&self, value: &dyn PartialReflect) -> bool;
|
||||
}
|
||||
|
||||
/// A container for compile-time set info.
|
||||
|
@ -164,7 +164,7 @@ impl SetInfo {
|
|||
#[derive(Default)]
|
||||
pub struct DynamicSet {
|
||||
represented_type: Option<&'static TypeInfo>,
|
||||
hash_table: HashTable<Box<dyn Reflect>>,
|
||||
hash_table: HashTable<Box<dyn PartialReflect>>,
|
||||
}
|
||||
|
||||
impl DynamicSet {
|
||||
|
@ -192,13 +192,13 @@ impl DynamicSet {
|
|||
self.insert_boxed(Box::new(value));
|
||||
}
|
||||
|
||||
#[allow(clippy::borrowed_box)]
|
||||
fn internal_hash(value: &Box<dyn Reflect>) -> u64 {
|
||||
fn internal_hash(value: &dyn PartialReflect) -> u64 {
|
||||
value.reflect_hash().expect(hash_error!(value))
|
||||
}
|
||||
|
||||
#[allow(clippy::borrowed_box)]
|
||||
fn internal_eq(value: &Box<dyn Reflect>) -> impl FnMut(&Box<dyn Reflect>) -> bool + '_ {
|
||||
fn internal_eq(
|
||||
value: &dyn PartialReflect,
|
||||
) -> impl FnMut(&Box<dyn PartialReflect>) -> bool + '_ {
|
||||
|other| {
|
||||
value
|
||||
.reflect_partial_eq(&**other)
|
||||
|
@ -207,18 +207,10 @@ impl DynamicSet {
|
|||
}
|
||||
}
|
||||
|
||||
// I just created this function to have only one point where we ignore the rust warning about the
|
||||
// unused allocation
|
||||
fn box_and_clone(val: &dyn Reflect) -> Box<dyn Reflect> {
|
||||
#[allow(unused_allocation)]
|
||||
Box::new(val).clone_value()
|
||||
}
|
||||
|
||||
impl Set for DynamicSet {
|
||||
fn get(&self, value: &dyn Reflect) -> Option<&dyn Reflect> {
|
||||
let boxed = box_and_clone(value);
|
||||
fn get(&self, value: &dyn PartialReflect) -> Option<&dyn PartialReflect> {
|
||||
self.hash_table
|
||||
.find(Self::internal_hash(&boxed), Self::internal_eq(&boxed))
|
||||
.find(Self::internal_hash(value), Self::internal_eq(value))
|
||||
.map(|value| &**value)
|
||||
}
|
||||
|
||||
|
@ -226,12 +218,12 @@ impl Set for DynamicSet {
|
|||
self.hash_table.len()
|
||||
}
|
||||
|
||||
fn iter(&self) -> Box<dyn Iterator<Item = &dyn Reflect> + '_> {
|
||||
fn iter(&self) -> Box<dyn Iterator<Item = &dyn PartialReflect> + '_> {
|
||||
let iter = self.hash_table.iter().map(|v| &**v);
|
||||
Box::new(iter)
|
||||
}
|
||||
|
||||
fn drain(self: Box<Self>) -> Vec<Box<dyn Reflect>> {
|
||||
fn drain(self: Box<Self>) -> Vec<Box<dyn PartialReflect>> {
|
||||
self.hash_table.into_iter().collect::<Vec<_>>()
|
||||
}
|
||||
|
||||
|
@ -241,7 +233,9 @@ impl Set for DynamicSet {
|
|||
.iter()
|
||||
.map(|value| value.clone_value())
|
||||
.for_each(|value| {
|
||||
hash_table.insert_unique(Self::internal_hash(&value), value, Self::internal_hash);
|
||||
hash_table.insert_unique(Self::internal_hash(value.as_ref()), value, |boxed| {
|
||||
Self::internal_hash(boxed.as_ref())
|
||||
});
|
||||
});
|
||||
|
||||
DynamicSet {
|
||||
|
@ -250,7 +244,7 @@ impl Set for DynamicSet {
|
|||
}
|
||||
}
|
||||
|
||||
fn insert_boxed(&mut self, value: Box<dyn Reflect>) -> bool {
|
||||
fn insert_boxed(&mut self, value: Box<dyn PartialReflect>) -> bool {
|
||||
assert_eq!(
|
||||
value.reflect_partial_eq(&*value),
|
||||
Some(true),
|
||||
|
@ -258,7 +252,7 @@ impl Set for DynamicSet {
|
|||
);
|
||||
match self
|
||||
.hash_table
|
||||
.find_mut(Self::internal_hash(&value), Self::internal_eq(&value))
|
||||
.find_mut(Self::internal_hash(&*value), Self::internal_eq(&*value))
|
||||
{
|
||||
Some(old) => {
|
||||
*old = value;
|
||||
|
@ -266,77 +260,73 @@ impl Set for DynamicSet {
|
|||
}
|
||||
None => {
|
||||
self.hash_table.insert_unique(
|
||||
Self::internal_hash(&value),
|
||||
Self::internal_hash(value.as_ref()),
|
||||
value,
|
||||
Self::internal_hash,
|
||||
|boxed| Self::internal_hash(boxed.as_ref()),
|
||||
);
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn remove(&mut self, value: &dyn Reflect) -> bool {
|
||||
let boxed = box_and_clone(value);
|
||||
fn remove(&mut self, value: &dyn PartialReflect) -> bool {
|
||||
self.hash_table
|
||||
.find_entry(Self::internal_hash(&boxed), Self::internal_eq(&boxed))
|
||||
.find_entry(Self::internal_hash(value), Self::internal_eq(value))
|
||||
.map(HashTableOccupiedEntry::remove)
|
||||
.is_ok()
|
||||
}
|
||||
|
||||
fn contains(&self, value: &dyn Reflect) -> bool {
|
||||
let boxed = box_and_clone(value);
|
||||
fn contains(&self, value: &dyn PartialReflect) -> bool {
|
||||
self.hash_table
|
||||
.find(Self::internal_hash(&boxed), Self::internal_eq(&boxed))
|
||||
.find(Self::internal_hash(value), Self::internal_eq(value))
|
||||
.is_some()
|
||||
}
|
||||
}
|
||||
|
||||
impl Reflect for DynamicSet {
|
||||
impl PartialReflect for DynamicSet {
|
||||
#[inline]
|
||||
fn get_represented_type_info(&self) -> Option<&'static TypeInfo> {
|
||||
self.represented_type
|
||||
}
|
||||
|
||||
fn into_any(self: Box<Self>) -> Box<dyn Any> {
|
||||
self
|
||||
}
|
||||
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
self
|
||||
}
|
||||
|
||||
fn as_any_mut(&mut self) -> &mut dyn Any {
|
||||
#[inline]
|
||||
fn into_partial_reflect(self: Box<Self>) -> Box<dyn PartialReflect> {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn into_reflect(self: Box<Self>) -> Box<dyn Reflect> {
|
||||
fn as_partial_reflect(&self) -> &dyn PartialReflect {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_reflect(&self) -> &dyn Reflect {
|
||||
fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_reflect_mut(&mut self) -> &mut dyn Reflect {
|
||||
self
|
||||
fn try_into_reflect(self: Box<Self>) -> Result<Box<dyn Reflect>, Box<dyn PartialReflect>> {
|
||||
Err(self)
|
||||
}
|
||||
|
||||
fn apply(&mut self, value: &dyn Reflect) {
|
||||
#[inline]
|
||||
fn try_as_reflect(&self) -> Option<&dyn Reflect> {
|
||||
None
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn try_as_reflect_mut(&mut self) -> Option<&mut dyn Reflect> {
|
||||
None
|
||||
}
|
||||
|
||||
fn apply(&mut self, value: &dyn PartialReflect) {
|
||||
set_apply(self, value);
|
||||
}
|
||||
|
||||
fn try_apply(&mut self, value: &dyn Reflect) -> Result<(), ApplyError> {
|
||||
fn try_apply(&mut self, value: &dyn PartialReflect) -> Result<(), ApplyError> {
|
||||
set_try_apply(self, value)
|
||||
}
|
||||
|
||||
fn set(&mut self, value: Box<dyn Reflect>) -> Result<(), Box<dyn Reflect>> {
|
||||
*self = value.take()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn reflect_kind(&self) -> ReflectKind {
|
||||
ReflectKind::Set
|
||||
}
|
||||
|
@ -353,11 +343,11 @@ impl Reflect for DynamicSet {
|
|||
ReflectOwned::Set(self)
|
||||
}
|
||||
|
||||
fn clone_value(&self) -> Box<dyn Reflect> {
|
||||
fn clone_value(&self) -> Box<dyn PartialReflect> {
|
||||
Box::new(self.clone_dynamic())
|
||||
}
|
||||
|
||||
fn reflect_partial_eq(&self, value: &dyn Reflect) -> Option<bool> {
|
||||
fn reflect_partial_eq(&self, value: &dyn PartialReflect) -> Option<bool> {
|
||||
set_partial_eq(self, value)
|
||||
}
|
||||
|
||||
|
@ -381,8 +371,8 @@ impl Debug for DynamicSet {
|
|||
}
|
||||
}
|
||||
|
||||
impl FromIterator<Box<dyn Reflect>> for DynamicSet {
|
||||
fn from_iter<I: IntoIterator<Item = Box<dyn Reflect>>>(values: I) -> Self {
|
||||
impl FromIterator<Box<dyn PartialReflect>> for DynamicSet {
|
||||
fn from_iter<I: IntoIterator<Item = Box<dyn PartialReflect>>>(values: I) -> Self {
|
||||
let mut this = Self {
|
||||
represented_type: None,
|
||||
hash_table: HashTable::new(),
|
||||
|
@ -412,7 +402,7 @@ impl<T: Reflect> FromIterator<T> for DynamicSet {
|
|||
}
|
||||
|
||||
impl IntoIterator for DynamicSet {
|
||||
type Item = Box<dyn Reflect>;
|
||||
type Item = Box<dyn PartialReflect>;
|
||||
type IntoIter = bevy_utils::hashbrown::hash_table::IntoIter<Self::Item>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
|
@ -421,28 +411,28 @@ impl IntoIterator for DynamicSet {
|
|||
}
|
||||
|
||||
impl<'a> IntoIterator for &'a DynamicSet {
|
||||
type Item = &'a dyn Reflect;
|
||||
type Item = &'a dyn PartialReflect;
|
||||
type IntoIter = std::iter::Map<
|
||||
bevy_utils::hashbrown::hash_table::Iter<'a, Box<dyn Reflect>>,
|
||||
fn(&'a Box<dyn Reflect>) -> Self::Item,
|
||||
bevy_utils::hashbrown::hash_table::Iter<'a, Box<dyn PartialReflect>>,
|
||||
fn(&'a Box<dyn PartialReflect>) -> Self::Item,
|
||||
>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
self.hash_table.iter().map(|v| v.as_reflect())
|
||||
self.hash_table.iter().map(|v| v.as_ref())
|
||||
}
|
||||
}
|
||||
|
||||
/// Compares a [`Set`] with a [`Reflect`] value.
|
||||
/// Compares a [`Set`] with a [`PartialReflect`] value.
|
||||
///
|
||||
/// Returns true if and only if all of the following are true:
|
||||
/// - `b` is a set;
|
||||
/// - `b` is the same length as `a`;
|
||||
/// - For each value pair in `a`, `b` contains the value too,
|
||||
/// and [`Reflect::reflect_partial_eq`] returns `Some(true)` for the two values.
|
||||
/// and [`PartialReflect::reflect_partial_eq`] returns `Some(true)` for the two values.
|
||||
///
|
||||
/// Returns [`None`] if the comparison couldn't even be performed.
|
||||
#[inline]
|
||||
pub fn set_partial_eq<M: Set>(a: &M, b: &dyn Reflect) -> Option<bool> {
|
||||
pub fn set_partial_eq<M: Set>(a: &M, b: &dyn PartialReflect) -> Option<bool> {
|
||||
let ReflectRef::Set(set) = b.reflect_ref() else {
|
||||
return Some(false);
|
||||
};
|
||||
|
@ -499,7 +489,7 @@ pub fn set_debug(dyn_set: &dyn Set, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|||
///
|
||||
/// This function panics if `b` is not a reflected set.
|
||||
#[inline]
|
||||
pub fn set_apply<M: Set>(a: &mut M, b: &dyn Reflect) {
|
||||
pub fn set_apply<M: Set>(a: &mut M, b: &dyn PartialReflect) {
|
||||
if let ReflectRef::Set(set_value) = b.reflect_ref() {
|
||||
for b_value in set_value.iter() {
|
||||
if a.get(b_value).is_none() {
|
||||
|
@ -521,7 +511,7 @@ pub fn set_apply<M: Set>(a: &mut M, b: &dyn Reflect) {
|
|||
/// This function returns an [`ApplyError::MismatchedKinds`] if `b` is not a reflected set or if
|
||||
/// applying elements to each other fails.
|
||||
#[inline]
|
||||
pub fn set_try_apply<S: Set>(a: &mut S, b: &dyn Reflect) -> Result<(), ApplyError> {
|
||||
pub fn set_try_apply<S: Set>(a: &mut S, b: &dyn PartialReflect) -> Result<(), ApplyError> {
|
||||
if let ReflectRef::Set(set_value) = b.reflect_ref() {
|
||||
for b_value in set_value.iter() {
|
||||
if a.get(b_value).is_none() {
|
||||
|
@ -551,7 +541,9 @@ mod tests {
|
|||
set.insert(expected[2].to_string());
|
||||
|
||||
for item in set.into_iter() {
|
||||
let value = item.take::<String>().expect("couldn't downcast to String");
|
||||
let value = item
|
||||
.try_take::<String>()
|
||||
.expect("couldn't downcast to String");
|
||||
let index = expected
|
||||
.iter()
|
||||
.position(|i| *i == value.as_str())
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::attributes::{impl_custom_attribute_methods, CustomAttributes};
|
||||
use crate::{
|
||||
self as bevy_reflect, ApplyError, NamedField, Reflect, ReflectKind, ReflectMut, ReflectOwned,
|
||||
ReflectRef, TypeInfo, TypePath, TypePathTable,
|
||||
self as bevy_reflect, ApplyError, NamedField, PartialReflect, Reflect, ReflectKind, ReflectMut,
|
||||
ReflectOwned, ReflectRef, TypeInfo, TypePath, TypePathTable,
|
||||
};
|
||||
use bevy_reflect_derive::impl_type_path;
|
||||
use bevy_utils::HashMap;
|
||||
|
@ -25,7 +25,7 @@ use std::{
|
|||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use bevy_reflect::{Reflect, Struct};
|
||||
/// use bevy_reflect::{PartialReflect, Reflect, Struct};
|
||||
///
|
||||
/// #[derive(Reflect)]
|
||||
/// struct Foo {
|
||||
|
@ -37,30 +37,30 @@ use std::{
|
|||
/// assert_eq!(foo.field_len(), 1);
|
||||
/// assert_eq!(foo.name_at(0), Some("bar"));
|
||||
///
|
||||
/// let field: &dyn Reflect = foo.field("bar").unwrap();
|
||||
/// assert_eq!(field.downcast_ref::<u32>(), Some(&123));
|
||||
/// let field: &dyn PartialReflect = foo.field("bar").unwrap();
|
||||
/// assert_eq!(field.try_downcast_ref::<u32>(), Some(&123));
|
||||
/// ```
|
||||
///
|
||||
/// [struct-like]: https://doc.rust-lang.org/book/ch05-01-defining-structs.html
|
||||
/// [reflection]: crate
|
||||
|
||||
/// [unit structs]: https://doc.rust-lang.org/book/ch05-01-defining-structs.html#unit-like-structs-without-any-fields
|
||||
pub trait Struct: Reflect {
|
||||
pub trait Struct: PartialReflect {
|
||||
/// Returns a reference to the value of the field named `name` as a `&dyn
|
||||
/// Reflect`.
|
||||
fn field(&self, name: &str) -> Option<&dyn Reflect>;
|
||||
/// PartialReflect`.
|
||||
fn field(&self, name: &str) -> Option<&dyn PartialReflect>;
|
||||
|
||||
/// Returns a mutable reference to the value of the field named `name` as a
|
||||
/// `&mut dyn Reflect`.
|
||||
fn field_mut(&mut self, name: &str) -> Option<&mut dyn Reflect>;
|
||||
/// `&mut dyn PartialReflect`.
|
||||
fn field_mut(&mut self, name: &str) -> Option<&mut dyn PartialReflect>;
|
||||
|
||||
/// Returns a reference to the value of the field with index `index` as a
|
||||
/// `&dyn Reflect`.
|
||||
fn field_at(&self, index: usize) -> Option<&dyn Reflect>;
|
||||
/// `&dyn PartialReflect`.
|
||||
fn field_at(&self, index: usize) -> Option<&dyn PartialReflect>;
|
||||
|
||||
/// Returns a mutable reference to the value of the field with index `index`
|
||||
/// as a `&mut dyn Reflect`.
|
||||
fn field_at_mut(&mut self, index: usize) -> Option<&mut dyn Reflect>;
|
||||
/// as a `&mut dyn PartialReflect`.
|
||||
fn field_at_mut(&mut self, index: usize) -> Option<&mut dyn PartialReflect>;
|
||||
|
||||
/// Returns the name of the field with index `index`.
|
||||
fn name_at(&self, index: usize) -> Option<&str>;
|
||||
|
@ -214,7 +214,7 @@ impl<'a> FieldIter<'a> {
|
|||
}
|
||||
|
||||
impl<'a> Iterator for FieldIter<'a> {
|
||||
type Item = &'a dyn Reflect;
|
||||
type Item = &'a dyn PartialReflect;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let value = self.struct_val.field_at(self.index);
|
||||
|
@ -262,23 +262,25 @@ pub trait GetField {
|
|||
|
||||
impl<S: Struct> GetField for S {
|
||||
fn get_field<T: Reflect>(&self, name: &str) -> Option<&T> {
|
||||
self.field(name).and_then(|value| value.downcast_ref::<T>())
|
||||
self.field(name)
|
||||
.and_then(|value| value.try_downcast_ref::<T>())
|
||||
}
|
||||
|
||||
fn get_field_mut<T: Reflect>(&mut self, name: &str) -> Option<&mut T> {
|
||||
self.field_mut(name)
|
||||
.and_then(|value| value.downcast_mut::<T>())
|
||||
.and_then(|value| value.try_downcast_mut::<T>())
|
||||
}
|
||||
}
|
||||
|
||||
impl GetField for dyn Struct {
|
||||
fn get_field<T: Reflect>(&self, name: &str) -> Option<&T> {
|
||||
self.field(name).and_then(|value| value.downcast_ref::<T>())
|
||||
self.field(name)
|
||||
.and_then(|value| value.try_downcast_ref::<T>())
|
||||
}
|
||||
|
||||
fn get_field_mut<T: Reflect>(&mut self, name: &str) -> Option<&mut T> {
|
||||
self.field_mut(name)
|
||||
.and_then(|value| value.downcast_mut::<T>())
|
||||
.and_then(|value| value.try_downcast_mut::<T>())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -286,7 +288,7 @@ impl GetField for dyn Struct {
|
|||
#[derive(Default)]
|
||||
pub struct DynamicStruct {
|
||||
represented_type: Option<&'static TypeInfo>,
|
||||
fields: Vec<Box<dyn Reflect>>,
|
||||
fields: Vec<Box<dyn PartialReflect>>,
|
||||
field_names: Vec<Cow<'static, str>>,
|
||||
field_indices: HashMap<Cow<'static, str>, usize>,
|
||||
}
|
||||
|
@ -314,7 +316,11 @@ impl DynamicStruct {
|
|||
/// Inserts a field named `name` with value `value` into the struct.
|
||||
///
|
||||
/// If the field already exists, it is overwritten.
|
||||
pub fn insert_boxed<'a>(&mut self, name: impl Into<Cow<'a, str>>, value: Box<dyn Reflect>) {
|
||||
pub fn insert_boxed<'a>(
|
||||
&mut self,
|
||||
name: impl Into<Cow<'a, str>>,
|
||||
value: Box<dyn PartialReflect>,
|
||||
) {
|
||||
let name: Cow<str> = name.into();
|
||||
if let Some(index) = self.field_indices.get(&name) {
|
||||
self.fields[*index] = value;
|
||||
|
@ -329,7 +335,7 @@ impl DynamicStruct {
|
|||
/// Inserts a field named `name` with the typed value `value` into the struct.
|
||||
///
|
||||
/// If the field already exists, it is overwritten.
|
||||
pub fn insert<'a, T: Reflect>(&mut self, name: impl Into<Cow<'a, str>>, value: T) {
|
||||
pub fn insert<'a, T: PartialReflect>(&mut self, name: impl Into<Cow<'a, str>>, value: T) {
|
||||
self.insert_boxed(name, Box::new(value));
|
||||
}
|
||||
|
||||
|
@ -341,14 +347,14 @@ impl DynamicStruct {
|
|||
|
||||
impl Struct for DynamicStruct {
|
||||
#[inline]
|
||||
fn field(&self, name: &str) -> Option<&dyn Reflect> {
|
||||
fn field(&self, name: &str) -> Option<&dyn PartialReflect> {
|
||||
self.field_indices
|
||||
.get(name)
|
||||
.map(|index| &*self.fields[*index])
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn field_mut(&mut self, name: &str) -> Option<&mut dyn Reflect> {
|
||||
fn field_mut(&mut self, name: &str) -> Option<&mut dyn PartialReflect> {
|
||||
if let Some(index) = self.field_indices.get(name) {
|
||||
Some(&mut *self.fields[*index])
|
||||
} else {
|
||||
|
@ -357,12 +363,12 @@ impl Struct for DynamicStruct {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn field_at(&self, index: usize) -> Option<&dyn Reflect> {
|
||||
fn field_at(&self, index: usize) -> Option<&dyn PartialReflect> {
|
||||
self.fields.get(index).map(|value| &**value)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn field_at_mut(&mut self, index: usize) -> Option<&mut dyn Reflect> {
|
||||
fn field_at_mut(&mut self, index: usize) -> Option<&mut dyn PartialReflect> {
|
||||
self.fields.get_mut(index).map(|value| &mut **value)
|
||||
}
|
||||
|
||||
|
@ -398,43 +404,38 @@ impl Struct for DynamicStruct {
|
|||
}
|
||||
}
|
||||
|
||||
impl Reflect for DynamicStruct {
|
||||
impl PartialReflect for DynamicStruct {
|
||||
#[inline]
|
||||
fn get_represented_type_info(&self) -> Option<&'static TypeInfo> {
|
||||
self.represented_type
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn into_any(self: Box<Self>) -> Box<dyn Any> {
|
||||
fn into_partial_reflect(self: Box<Self>) -> Box<dyn PartialReflect> {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
fn as_partial_reflect(&self) -> &dyn PartialReflect {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_any_mut(&mut self) -> &mut dyn Any {
|
||||
fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn into_reflect(self: Box<Self>) -> Box<dyn Reflect> {
|
||||
self
|
||||
fn try_into_reflect(self: Box<Self>) -> Result<Box<dyn Reflect>, Box<dyn PartialReflect>> {
|
||||
Err(self)
|
||||
}
|
||||
fn try_as_reflect(&self) -> Option<&dyn Reflect> {
|
||||
None
|
||||
}
|
||||
fn try_as_reflect_mut(&mut self) -> Option<&mut dyn Reflect> {
|
||||
None
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_reflect(&self) -> &dyn Reflect {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_reflect_mut(&mut self) -> &mut dyn Reflect {
|
||||
self
|
||||
}
|
||||
|
||||
fn try_apply(&mut self, value: &dyn Reflect) -> Result<(), ApplyError> {
|
||||
fn try_apply(&mut self, value: &dyn PartialReflect) -> Result<(), ApplyError> {
|
||||
if let ReflectRef::Struct(struct_value) = value.reflect_ref() {
|
||||
for (i, value) in struct_value.iter_fields().enumerate() {
|
||||
let name = struct_value.name_at(i).unwrap();
|
||||
|
@ -451,12 +452,6 @@ impl Reflect for DynamicStruct {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set(&mut self, value: Box<dyn Reflect>) -> Result<(), Box<dyn Reflect>> {
|
||||
*self = value.take()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn reflect_kind(&self) -> ReflectKind {
|
||||
ReflectKind::Struct
|
||||
|
@ -478,11 +473,11 @@ impl Reflect for DynamicStruct {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn clone_value(&self) -> Box<dyn Reflect> {
|
||||
fn clone_value(&self) -> Box<dyn PartialReflect> {
|
||||
Box::new(self.clone_dynamic())
|
||||
}
|
||||
|
||||
fn reflect_partial_eq(&self, value: &dyn Reflect) -> Option<bool> {
|
||||
fn reflect_partial_eq(&self, value: &dyn PartialReflect) -> Option<bool> {
|
||||
struct_partial_eq(self, value)
|
||||
}
|
||||
|
||||
|
@ -499,8 +494,6 @@ impl Reflect for DynamicStruct {
|
|||
}
|
||||
|
||||
impl_type_path!((in bevy_reflect) DynamicStruct);
|
||||
#[cfg(feature = "functions")]
|
||||
crate::func::macros::impl_function_traits!(DynamicStruct);
|
||||
|
||||
impl Debug for DynamicStruct {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
|
@ -508,13 +501,13 @@ impl Debug for DynamicStruct {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, N> FromIterator<(N, Box<dyn Reflect>)> for DynamicStruct
|
||||
impl<'a, N> FromIterator<(N, Box<dyn PartialReflect>)> for DynamicStruct
|
||||
where
|
||||
N: Into<Cow<'a, str>>,
|
||||
{
|
||||
/// Create a dynamic struct that doesn't represent a type from the
|
||||
/// field name, field value pairs.
|
||||
fn from_iter<I: IntoIterator<Item = (N, Box<dyn Reflect>)>>(fields: I) -> Self {
|
||||
fn from_iter<I: IntoIterator<Item = (N, Box<dyn PartialReflect>)>>(fields: I) -> Self {
|
||||
let mut dynamic_struct = Self::default();
|
||||
for (name, value) in fields.into_iter() {
|
||||
dynamic_struct.insert_boxed(name, value);
|
||||
|
@ -524,7 +517,7 @@ where
|
|||
}
|
||||
|
||||
impl IntoIterator for DynamicStruct {
|
||||
type Item = Box<dyn Reflect>;
|
||||
type Item = Box<dyn PartialReflect>;
|
||||
type IntoIter = std::vec::IntoIter<Self::Item>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
|
@ -533,7 +526,7 @@ impl IntoIterator for DynamicStruct {
|
|||
}
|
||||
|
||||
impl<'a> IntoIterator for &'a DynamicStruct {
|
||||
type Item = &'a dyn Reflect;
|
||||
type Item = &'a dyn PartialReflect;
|
||||
type IntoIter = FieldIter<'a>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
|
@ -541,17 +534,17 @@ impl<'a> IntoIterator for &'a DynamicStruct {
|
|||
}
|
||||
}
|
||||
|
||||
/// Compares a [`Struct`] with a [`Reflect`] value.
|
||||
/// Compares a [`Struct`] with a [`PartialReflect`] value.
|
||||
///
|
||||
/// Returns true if and only if all of the following are true:
|
||||
/// - `b` is a struct;
|
||||
/// - For each field in `a`, `b` contains a field with the same name and
|
||||
/// [`Reflect::reflect_partial_eq`] returns `Some(true)` for the two field
|
||||
/// [`PartialReflect::reflect_partial_eq`] returns `Some(true)` for the two field
|
||||
/// values.
|
||||
///
|
||||
/// Returns [`None`] if the comparison couldn't even be performed.
|
||||
#[inline]
|
||||
pub fn struct_partial_eq<S: Struct>(a: &S, b: &dyn Reflect) -> Option<bool> {
|
||||
pub fn struct_partial_eq<S: Struct + ?Sized>(a: &S, b: &dyn PartialReflect) -> Option<bool> {
|
||||
let ReflectRef::Struct(struct_value) = b.reflect_ref() else {
|
||||
return Some(false);
|
||||
};
|
||||
|
|
|
@ -6,7 +6,7 @@ use crate::{
|
|||
GetTypeRegistration, MaybeTyped, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo,
|
||||
TypePath, TypeRegistration, TypeRegistry, Typed, UnnamedField,
|
||||
};
|
||||
use crate::{ReflectKind, TypePathTable};
|
||||
use crate::{PartialReflect, ReflectKind, TypePathTable};
|
||||
use std::any::{Any, TypeId};
|
||||
use std::fmt::{Debug, Formatter};
|
||||
use std::slice::Iter;
|
||||
|
@ -22,25 +22,25 @@ use std::slice::Iter;
|
|||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use bevy_reflect::{Reflect, Tuple};
|
||||
/// use bevy_reflect::{PartialReflect, Tuple};
|
||||
///
|
||||
/// let foo = (123_u32, true);
|
||||
/// assert_eq!(foo.field_len(), 2);
|
||||
///
|
||||
/// let field: &dyn Reflect = foo.field(0).unwrap();
|
||||
/// assert_eq!(field.downcast_ref::<u32>(), Some(&123));
|
||||
/// let field: &dyn PartialReflect = foo.field(0).unwrap();
|
||||
/// assert_eq!(field.try_downcast_ref::<u32>(), Some(&123));
|
||||
/// ```
|
||||
///
|
||||
/// [tuple-like]: https://doc.rust-lang.org/book/ch03-02-data-types.html#the-tuple-type
|
||||
/// [reflection]: crate
|
||||
pub trait Tuple: Reflect {
|
||||
pub trait Tuple: PartialReflect {
|
||||
/// Returns a reference to the value of the field with index `index` as a
|
||||
/// `&dyn Reflect`.
|
||||
fn field(&self, index: usize) -> Option<&dyn Reflect>;
|
||||
fn field(&self, index: usize) -> Option<&dyn PartialReflect>;
|
||||
|
||||
/// Returns a mutable reference to the value of the field with index `index`
|
||||
/// as a `&mut dyn Reflect`.
|
||||
fn field_mut(&mut self, index: usize) -> Option<&mut dyn Reflect>;
|
||||
fn field_mut(&mut self, index: usize) -> Option<&mut dyn PartialReflect>;
|
||||
|
||||
/// Returns the number of fields in the tuple.
|
||||
fn field_len(&self) -> usize;
|
||||
|
@ -49,7 +49,7 @@ pub trait Tuple: Reflect {
|
|||
fn iter_fields(&self) -> TupleFieldIter;
|
||||
|
||||
/// Drain the fields of this tuple to get a vector of owned values.
|
||||
fn drain(self: Box<Self>) -> Vec<Box<dyn Reflect>>;
|
||||
fn drain(self: Box<Self>) -> Vec<Box<dyn PartialReflect>>;
|
||||
|
||||
/// Clones the struct into a [`DynamicTuple`].
|
||||
fn clone_dynamic(&self) -> DynamicTuple;
|
||||
|
@ -71,7 +71,7 @@ impl<'a> TupleFieldIter<'a> {
|
|||
}
|
||||
|
||||
impl<'a> Iterator for TupleFieldIter<'a> {
|
||||
type Item = &'a dyn Reflect;
|
||||
type Item = &'a dyn PartialReflect;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let value = self.tuple.field(self.index);
|
||||
|
@ -115,24 +115,24 @@ pub trait GetTupleField {
|
|||
impl<S: Tuple> GetTupleField for S {
|
||||
fn get_field<T: Reflect>(&self, index: usize) -> Option<&T> {
|
||||
self.field(index)
|
||||
.and_then(|value| value.downcast_ref::<T>())
|
||||
.and_then(|value| value.try_downcast_ref::<T>())
|
||||
}
|
||||
|
||||
fn get_field_mut<T: Reflect>(&mut self, index: usize) -> Option<&mut T> {
|
||||
self.field_mut(index)
|
||||
.and_then(|value| value.downcast_mut::<T>())
|
||||
.and_then(|value| value.try_downcast_mut::<T>())
|
||||
}
|
||||
}
|
||||
|
||||
impl GetTupleField for dyn Tuple {
|
||||
fn get_field<T: Reflect>(&self, index: usize) -> Option<&T> {
|
||||
self.field(index)
|
||||
.and_then(|value| value.downcast_ref::<T>())
|
||||
.and_then(|value| value.try_downcast_ref::<T>())
|
||||
}
|
||||
|
||||
fn get_field_mut<T: Reflect>(&mut self, index: usize) -> Option<&mut T> {
|
||||
self.field_mut(index)
|
||||
.and_then(|value| value.downcast_mut::<T>())
|
||||
.and_then(|value| value.try_downcast_mut::<T>())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -222,7 +222,7 @@ impl TupleInfo {
|
|||
#[derive(Default, Debug)]
|
||||
pub struct DynamicTuple {
|
||||
represented_type: Option<&'static TypeInfo>,
|
||||
fields: Vec<Box<dyn Reflect>>,
|
||||
fields: Vec<Box<dyn PartialReflect>>,
|
||||
}
|
||||
|
||||
impl DynamicTuple {
|
||||
|
@ -245,13 +245,13 @@ impl DynamicTuple {
|
|||
}
|
||||
|
||||
/// Appends an element with value `value` to the tuple.
|
||||
pub fn insert_boxed(&mut self, value: Box<dyn Reflect>) {
|
||||
pub fn insert_boxed(&mut self, value: Box<dyn PartialReflect>) {
|
||||
self.represented_type = None;
|
||||
self.fields.push(value);
|
||||
}
|
||||
|
||||
/// Appends a typed element with value `value` to the tuple.
|
||||
pub fn insert<T: Reflect>(&mut self, value: T) {
|
||||
pub fn insert<T: PartialReflect>(&mut self, value: T) {
|
||||
self.represented_type = None;
|
||||
self.insert_boxed(Box::new(value));
|
||||
}
|
||||
|
@ -259,12 +259,12 @@ impl DynamicTuple {
|
|||
|
||||
impl Tuple for DynamicTuple {
|
||||
#[inline]
|
||||
fn field(&self, index: usize) -> Option<&dyn Reflect> {
|
||||
fn field(&self, index: usize) -> Option<&dyn PartialReflect> {
|
||||
self.fields.get(index).map(|field| &**field)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn field_mut(&mut self, index: usize) -> Option<&mut dyn Reflect> {
|
||||
fn field_mut(&mut self, index: usize) -> Option<&mut dyn PartialReflect> {
|
||||
self.fields.get_mut(index).map(|field| &mut **field)
|
||||
}
|
||||
|
||||
|
@ -282,7 +282,7 @@ impl Tuple for DynamicTuple {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn drain(self: Box<Self>) -> Vec<Box<dyn Reflect>> {
|
||||
fn drain(self: Box<Self>) -> Vec<Box<dyn PartialReflect>> {
|
||||
self.fields
|
||||
}
|
||||
|
||||
|
@ -299,51 +299,41 @@ impl Tuple for DynamicTuple {
|
|||
}
|
||||
}
|
||||
|
||||
impl Reflect for DynamicTuple {
|
||||
impl PartialReflect for DynamicTuple {
|
||||
#[inline]
|
||||
fn get_represented_type_info(&self) -> Option<&'static TypeInfo> {
|
||||
self.represented_type
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn into_any(self: Box<Self>) -> Box<dyn Any> {
|
||||
fn into_partial_reflect(self: Box<Self>) -> Box<dyn PartialReflect> {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
fn as_partial_reflect(&self) -> &dyn PartialReflect {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_any_mut(&mut self) -> &mut dyn Any {
|
||||
fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn into_reflect(self: Box<Self>) -> Box<dyn Reflect> {
|
||||
self
|
||||
fn try_into_reflect(self: Box<Self>) -> Result<Box<dyn Reflect>, Box<dyn PartialReflect>> {
|
||||
Err(self)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_reflect(&self) -> &dyn Reflect {
|
||||
self
|
||||
fn try_as_reflect(&self) -> Option<&dyn Reflect> {
|
||||
None
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_reflect_mut(&mut self) -> &mut dyn Reflect {
|
||||
self
|
||||
fn try_as_reflect_mut(&mut self) -> Option<&mut dyn Reflect> {
|
||||
None
|
||||
}
|
||||
|
||||
fn apply(&mut self, value: &dyn Reflect) {
|
||||
fn apply(&mut self, value: &dyn PartialReflect) {
|
||||
tuple_apply(self, value);
|
||||
}
|
||||
|
||||
fn set(&mut self, value: Box<dyn Reflect>) -> Result<(), Box<dyn Reflect>> {
|
||||
*self = value.take()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn reflect_kind(&self) -> ReflectKind {
|
||||
ReflectKind::Tuple
|
||||
|
@ -365,15 +355,15 @@ impl Reflect for DynamicTuple {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn clone_value(&self) -> Box<dyn Reflect> {
|
||||
fn clone_value(&self) -> Box<dyn PartialReflect> {
|
||||
Box::new(self.clone_dynamic())
|
||||
}
|
||||
|
||||
fn try_apply(&mut self, value: &dyn Reflect) -> Result<(), ApplyError> {
|
||||
fn try_apply(&mut self, value: &dyn PartialReflect) -> Result<(), ApplyError> {
|
||||
tuple_try_apply(self, value)
|
||||
}
|
||||
|
||||
fn reflect_partial_eq(&self, value: &dyn Reflect) -> Option<bool> {
|
||||
fn reflect_partial_eq(&self, value: &dyn PartialReflect) -> Option<bool> {
|
||||
tuple_partial_eq(self, value)
|
||||
}
|
||||
|
||||
|
@ -391,8 +381,8 @@ impl Reflect for DynamicTuple {
|
|||
|
||||
impl_type_path!((in bevy_reflect) DynamicTuple);
|
||||
|
||||
impl FromIterator<Box<dyn Reflect>> for DynamicTuple {
|
||||
fn from_iter<I: IntoIterator<Item = Box<dyn Reflect>>>(fields: I) -> Self {
|
||||
impl FromIterator<Box<dyn PartialReflect>> for DynamicTuple {
|
||||
fn from_iter<I: IntoIterator<Item = Box<dyn PartialReflect>>>(fields: I) -> Self {
|
||||
Self {
|
||||
represented_type: None,
|
||||
fields: fields.into_iter().collect(),
|
||||
|
@ -401,7 +391,7 @@ impl FromIterator<Box<dyn Reflect>> for DynamicTuple {
|
|||
}
|
||||
|
||||
impl IntoIterator for DynamicTuple {
|
||||
type Item = Box<dyn Reflect>;
|
||||
type Item = Box<dyn PartialReflect>;
|
||||
type IntoIter = std::vec::IntoIter<Self::Item>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
|
@ -410,7 +400,7 @@ impl IntoIterator for DynamicTuple {
|
|||
}
|
||||
|
||||
impl<'a> IntoIterator for &'a DynamicTuple {
|
||||
type Item = &'a dyn Reflect;
|
||||
type Item = &'a dyn PartialReflect;
|
||||
type IntoIter = TupleFieldIter<'a>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
|
@ -424,7 +414,7 @@ impl<'a> IntoIterator for &'a DynamicTuple {
|
|||
///
|
||||
/// This function panics if `b` is not a tuple.
|
||||
#[inline]
|
||||
pub fn tuple_apply<T: Tuple>(a: &mut T, b: &dyn Reflect) {
|
||||
pub fn tuple_apply<T: Tuple>(a: &mut T, b: &dyn PartialReflect) {
|
||||
if let Err(err) = tuple_try_apply(a, b) {
|
||||
panic!("{err}");
|
||||
}
|
||||
|
@ -438,7 +428,7 @@ pub fn tuple_apply<T: Tuple>(a: &mut T, b: &dyn Reflect) {
|
|||
/// This function returns an [`ApplyError::MismatchedKinds`] if `b` is not a tuple or if
|
||||
/// applying elements to each other fails.
|
||||
#[inline]
|
||||
pub fn tuple_try_apply<T: Tuple>(a: &mut T, b: &dyn Reflect) -> Result<(), ApplyError> {
|
||||
pub fn tuple_try_apply<T: Tuple>(a: &mut T, b: &dyn PartialReflect) -> Result<(), ApplyError> {
|
||||
if let ReflectRef::Tuple(tuple) = b.reflect_ref() {
|
||||
for (i, value) in tuple.iter_fields().enumerate() {
|
||||
if let Some(v) = a.field_mut(i) {
|
||||
|
@ -454,16 +444,16 @@ pub fn tuple_try_apply<T: Tuple>(a: &mut T, b: &dyn Reflect) -> Result<(), Apply
|
|||
Ok(())
|
||||
}
|
||||
|
||||
/// Compares a [`Tuple`] with a [`Reflect`] value.
|
||||
/// Compares a [`Tuple`] with a [`PartialReflect`] value.
|
||||
///
|
||||
/// Returns true if and only if all of the following are true:
|
||||
/// - `b` is a tuple;
|
||||
/// - `b` has the same number of elements as `a`;
|
||||
/// - [`Reflect::reflect_partial_eq`] returns `Some(true)` for pairwise elements of `a` and `b`.
|
||||
/// - [`PartialReflect::reflect_partial_eq`] returns `Some(true)` for pairwise elements of `a` and `b`.
|
||||
///
|
||||
/// Returns [`None`] if the comparison couldn't even be performed.
|
||||
#[inline]
|
||||
pub fn tuple_partial_eq<T: Tuple>(a: &T, b: &dyn Reflect) -> Option<bool> {
|
||||
pub fn tuple_partial_eq<T: Tuple + ?Sized>(a: &T, b: &dyn PartialReflect) -> Option<bool> {
|
||||
let ReflectRef::Tuple(b) = b.reflect_ref() else {
|
||||
return Some(false);
|
||||
};
|
||||
|
@ -512,17 +502,17 @@ macro_rules! impl_reflect_tuple {
|
|||
{$($index:tt : $name:tt),*} => {
|
||||
impl<$($name: Reflect + MaybeTyped + TypePath + GetTypeRegistration),*> Tuple for ($($name,)*) {
|
||||
#[inline]
|
||||
fn field(&self, index: usize) -> Option<&dyn Reflect> {
|
||||
fn field(&self, index: usize) -> Option<&dyn PartialReflect> {
|
||||
match index {
|
||||
$($index => Some(&self.$index as &dyn Reflect),)*
|
||||
$($index => Some(&self.$index as &dyn PartialReflect),)*
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn field_mut(&mut self, index: usize) -> Option<&mut dyn Reflect> {
|
||||
fn field_mut(&mut self, index: usize) -> Option<&mut dyn PartialReflect> {
|
||||
match index {
|
||||
$($index => Some(&mut self.$index as &mut dyn Reflect),)*
|
||||
$($index => Some(&mut self.$index as &mut dyn PartialReflect),)*
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
@ -542,7 +532,7 @@ macro_rules! impl_reflect_tuple {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn drain(self: Box<Self>) -> Vec<Box<dyn Reflect>> {
|
||||
fn drain(self: Box<Self>) -> Vec<Box<dyn PartialReflect>> {
|
||||
vec![
|
||||
$(Box::new(self.$index),)*
|
||||
]
|
||||
|
@ -561,11 +551,70 @@ macro_rules! impl_reflect_tuple {
|
|||
}
|
||||
}
|
||||
|
||||
impl<$($name: Reflect + MaybeTyped + TypePath + GetTypeRegistration),*> Reflect for ($($name,)*) {
|
||||
impl<$($name: Reflect + MaybeTyped + TypePath + GetTypeRegistration),*> PartialReflect for ($($name,)*) {
|
||||
fn get_represented_type_info(&self) -> Option<&'static TypeInfo> {
|
||||
Some(<Self as Typed>::type_info())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn into_partial_reflect(self: Box<Self>) -> Box<dyn PartialReflect> {
|
||||
self
|
||||
}
|
||||
|
||||
fn as_partial_reflect(&self) -> &dyn PartialReflect {
|
||||
self
|
||||
}
|
||||
|
||||
fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect {
|
||||
self
|
||||
}
|
||||
|
||||
fn try_into_reflect(self: Box<Self>) -> Result<Box<dyn Reflect>, Box<dyn PartialReflect>> {
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
fn try_as_reflect(&self) -> Option<&dyn Reflect> {
|
||||
Some(self)
|
||||
}
|
||||
|
||||
fn try_as_reflect_mut(&mut self) -> Option<&mut dyn Reflect> {
|
||||
Some(self)
|
||||
}
|
||||
|
||||
fn reflect_kind(&self) -> ReflectKind {
|
||||
ReflectKind::Tuple
|
||||
}
|
||||
|
||||
fn reflect_ref(&self) -> ReflectRef {
|
||||
ReflectRef::Tuple(self)
|
||||
}
|
||||
|
||||
fn reflect_mut(&mut self) -> ReflectMut {
|
||||
ReflectMut::Tuple(self)
|
||||
}
|
||||
|
||||
fn reflect_owned(self: Box<Self>) -> ReflectOwned {
|
||||
ReflectOwned::Tuple(self)
|
||||
}
|
||||
|
||||
fn clone_value(&self) -> Box<dyn PartialReflect> {
|
||||
Box::new(self.clone_dynamic())
|
||||
}
|
||||
|
||||
fn reflect_partial_eq(&self, value: &dyn PartialReflect) -> Option<bool> {
|
||||
crate::tuple_partial_eq(self, value)
|
||||
}
|
||||
|
||||
fn apply(&mut self, value: &dyn PartialReflect) {
|
||||
crate::tuple_apply(self, value);
|
||||
}
|
||||
|
||||
fn try_apply(&mut self, value: &dyn PartialReflect) -> Result<(), ApplyError> {
|
||||
crate::tuple_try_apply(self, value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<$($name: Reflect + MaybeTyped + TypePath + GetTypeRegistration),*> Reflect for ($($name,)*) {
|
||||
fn into_any(self: Box<Self>) -> Box<dyn Any> {
|
||||
self
|
||||
}
|
||||
|
@ -590,42 +639,10 @@ macro_rules! impl_reflect_tuple {
|
|||
self
|
||||
}
|
||||
|
||||
fn apply(&mut self, value: &dyn Reflect) {
|
||||
crate::tuple_apply(self, value);
|
||||
}
|
||||
|
||||
fn try_apply(&mut self, value: &dyn Reflect) -> Result<(), ApplyError> {
|
||||
crate::tuple_try_apply(self, value)
|
||||
}
|
||||
|
||||
fn set(&mut self, value: Box<dyn Reflect>) -> Result<(), Box<dyn Reflect>> {
|
||||
*self = value.take()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn reflect_kind(&self) -> ReflectKind {
|
||||
ReflectKind::Tuple
|
||||
}
|
||||
|
||||
fn reflect_ref(&self) -> ReflectRef {
|
||||
ReflectRef::Tuple(self)
|
||||
}
|
||||
|
||||
fn reflect_mut(&mut self) -> ReflectMut {
|
||||
ReflectMut::Tuple(self)
|
||||
}
|
||||
|
||||
fn reflect_owned(self: Box<Self>) -> ReflectOwned {
|
||||
ReflectOwned::Tuple(self)
|
||||
}
|
||||
|
||||
fn clone_value(&self) -> Box<dyn Reflect> {
|
||||
Box::new(self.clone_dynamic())
|
||||
}
|
||||
|
||||
fn reflect_partial_eq(&self, value: &dyn Reflect) -> Option<bool> {
|
||||
crate::tuple_partial_eq(self, value)
|
||||
}
|
||||
}
|
||||
|
||||
impl <$($name: Reflect + MaybeTyped + TypePath + GetTypeRegistration),*> Typed for ($($name,)*) {
|
||||
|
@ -653,7 +670,7 @@ macro_rules! impl_reflect_tuple {
|
|||
|
||||
impl<$($name: FromReflect + MaybeTyped + TypePath + GetTypeRegistration),*> FromReflect for ($($name,)*)
|
||||
{
|
||||
fn from_reflect(reflect: &dyn Reflect) -> Option<Self> {
|
||||
fn from_reflect(reflect: &dyn PartialReflect) -> Option<Self> {
|
||||
if let ReflectRef::Tuple(_ref_tuple) = reflect.reflect_ref() {
|
||||
Some(
|
||||
(
|
||||
|
|
|
@ -2,8 +2,8 @@ use bevy_reflect_derive::impl_type_path;
|
|||
|
||||
use crate::attributes::{impl_custom_attribute_methods, CustomAttributes};
|
||||
use crate::{
|
||||
self as bevy_reflect, ApplyError, DynamicTuple, Reflect, ReflectKind, ReflectMut, ReflectOwned,
|
||||
ReflectRef, Tuple, TypeInfo, TypePath, TypePathTable, UnnamedField,
|
||||
self as bevy_reflect, ApplyError, DynamicTuple, PartialReflect, Reflect, ReflectKind,
|
||||
ReflectMut, ReflectOwned, ReflectRef, Tuple, TypeInfo, TypePath, TypePathTable, UnnamedField,
|
||||
};
|
||||
use std::any::{Any, TypeId};
|
||||
use std::fmt::{Debug, Formatter};
|
||||
|
@ -21,7 +21,7 @@ use std::sync::Arc;
|
|||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use bevy_reflect::{Reflect, TupleStruct};
|
||||
/// use bevy_reflect::{PartialReflect, Reflect, TupleStruct};
|
||||
///
|
||||
/// #[derive(Reflect)]
|
||||
/// struct Foo(u32);
|
||||
|
@ -30,20 +30,20 @@ use std::sync::Arc;
|
|||
///
|
||||
/// assert_eq!(foo.field_len(), 1);
|
||||
///
|
||||
/// let field: &dyn Reflect = foo.field(0).unwrap();
|
||||
/// assert_eq!(field.downcast_ref::<u32>(), Some(&123));
|
||||
/// let field: &dyn PartialReflect = foo.field(0).unwrap();
|
||||
/// assert_eq!(field.try_downcast_ref::<u32>(), Some(&123));
|
||||
/// ```
|
||||
///
|
||||
/// [tuple struct-like]: https://doc.rust-lang.org/book/ch05-01-defining-structs.html#using-tuple-structs-without-named-fields-to-create-different-types
|
||||
/// [reflection]: crate
|
||||
pub trait TupleStruct: Reflect {
|
||||
pub trait TupleStruct: PartialReflect {
|
||||
/// Returns a reference to the value of the field with index `index` as a
|
||||
/// `&dyn Reflect`.
|
||||
fn field(&self, index: usize) -> Option<&dyn Reflect>;
|
||||
fn field(&self, index: usize) -> Option<&dyn PartialReflect>;
|
||||
|
||||
/// Returns a mutable reference to the value of the field with index `index`
|
||||
/// as a `&mut dyn Reflect`.
|
||||
fn field_mut(&mut self, index: usize) -> Option<&mut dyn Reflect>;
|
||||
fn field_mut(&mut self, index: usize) -> Option<&mut dyn PartialReflect>;
|
||||
|
||||
/// Returns the number of fields in the tuple struct.
|
||||
fn field_len(&self) -> usize;
|
||||
|
@ -165,7 +165,7 @@ impl<'a> TupleStructFieldIter<'a> {
|
|||
}
|
||||
|
||||
impl<'a> Iterator for TupleStructFieldIter<'a> {
|
||||
type Item = &'a dyn Reflect;
|
||||
type Item = &'a dyn PartialReflect;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let value = self.tuple_struct.field(self.index);
|
||||
|
@ -212,24 +212,24 @@ pub trait GetTupleStructField {
|
|||
impl<S: TupleStruct> GetTupleStructField for S {
|
||||
fn get_field<T: Reflect>(&self, index: usize) -> Option<&T> {
|
||||
self.field(index)
|
||||
.and_then(|value| value.downcast_ref::<T>())
|
||||
.and_then(|value| value.try_downcast_ref::<T>())
|
||||
}
|
||||
|
||||
fn get_field_mut<T: Reflect>(&mut self, index: usize) -> Option<&mut T> {
|
||||
self.field_mut(index)
|
||||
.and_then(|value| value.downcast_mut::<T>())
|
||||
.and_then(|value| value.try_downcast_mut::<T>())
|
||||
}
|
||||
}
|
||||
|
||||
impl GetTupleStructField for dyn TupleStruct {
|
||||
fn get_field<T: Reflect>(&self, index: usize) -> Option<&T> {
|
||||
self.field(index)
|
||||
.and_then(|value| value.downcast_ref::<T>())
|
||||
.and_then(|value| value.try_downcast_ref::<T>())
|
||||
}
|
||||
|
||||
fn get_field_mut<T: Reflect>(&mut self, index: usize) -> Option<&mut T> {
|
||||
self.field_mut(index)
|
||||
.and_then(|value| value.downcast_mut::<T>())
|
||||
.and_then(|value| value.try_downcast_mut::<T>())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -237,7 +237,7 @@ impl GetTupleStructField for dyn TupleStruct {
|
|||
#[derive(Default)]
|
||||
pub struct DynamicTupleStruct {
|
||||
represented_type: Option<&'static TypeInfo>,
|
||||
fields: Vec<Box<dyn Reflect>>,
|
||||
fields: Vec<Box<dyn PartialReflect>>,
|
||||
}
|
||||
|
||||
impl DynamicTupleStruct {
|
||||
|
@ -261,24 +261,24 @@ impl DynamicTupleStruct {
|
|||
}
|
||||
|
||||
/// Appends an element with value `value` to the tuple struct.
|
||||
pub fn insert_boxed(&mut self, value: Box<dyn Reflect>) {
|
||||
pub fn insert_boxed(&mut self, value: Box<dyn PartialReflect>) {
|
||||
self.fields.push(value);
|
||||
}
|
||||
|
||||
/// Appends a typed element with value `value` to the tuple struct.
|
||||
pub fn insert<T: Reflect>(&mut self, value: T) {
|
||||
pub fn insert<T: PartialReflect>(&mut self, value: T) {
|
||||
self.insert_boxed(Box::new(value));
|
||||
}
|
||||
}
|
||||
|
||||
impl TupleStruct for DynamicTupleStruct {
|
||||
#[inline]
|
||||
fn field(&self, index: usize) -> Option<&dyn Reflect> {
|
||||
fn field(&self, index: usize) -> Option<&dyn PartialReflect> {
|
||||
self.fields.get(index).map(|field| &**field)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn field_mut(&mut self, index: usize) -> Option<&mut dyn Reflect> {
|
||||
fn field_mut(&mut self, index: usize) -> Option<&mut dyn PartialReflect> {
|
||||
self.fields.get_mut(index).map(|field| &mut **field)
|
||||
}
|
||||
|
||||
|
@ -307,43 +307,40 @@ impl TupleStruct for DynamicTupleStruct {
|
|||
}
|
||||
}
|
||||
|
||||
impl Reflect for DynamicTupleStruct {
|
||||
impl PartialReflect for DynamicTupleStruct {
|
||||
#[inline]
|
||||
fn get_represented_type_info(&self) -> Option<&'static TypeInfo> {
|
||||
self.represented_type
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn into_any(self: Box<Self>) -> Box<dyn Any> {
|
||||
fn into_partial_reflect(self: Box<Self>) -> Box<dyn PartialReflect> {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
fn as_partial_reflect(&self) -> &dyn PartialReflect {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_any_mut(&mut self) -> &mut dyn Any {
|
||||
fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect {
|
||||
self
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn into_reflect(self: Box<Self>) -> Box<dyn Reflect> {
|
||||
self
|
||||
fn try_into_reflect(self: Box<Self>) -> Result<Box<dyn Reflect>, Box<dyn PartialReflect>> {
|
||||
Err(self)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_reflect(&self) -> &dyn Reflect {
|
||||
self
|
||||
fn try_as_reflect(&self) -> Option<&dyn Reflect> {
|
||||
None
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_reflect_mut(&mut self) -> &mut dyn Reflect {
|
||||
self
|
||||
fn try_as_reflect_mut(&mut self) -> Option<&mut dyn Reflect> {
|
||||
None
|
||||
}
|
||||
|
||||
fn try_apply(&mut self, value: &dyn Reflect) -> Result<(), ApplyError> {
|
||||
fn try_apply(&mut self, value: &dyn PartialReflect) -> Result<(), ApplyError> {
|
||||
if let ReflectRef::TupleStruct(tuple_struct) = value.reflect_ref() {
|
||||
for (i, value) in tuple_struct.iter_fields().enumerate() {
|
||||
if let Some(v) = self.field_mut(i) {
|
||||
|
@ -359,12 +356,6 @@ impl Reflect for DynamicTupleStruct {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn set(&mut self, value: Box<dyn Reflect>) -> Result<(), Box<dyn Reflect>> {
|
||||
*self = value.take()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn reflect_kind(&self) -> ReflectKind {
|
||||
ReflectKind::TupleStruct
|
||||
|
@ -386,12 +377,12 @@ impl Reflect for DynamicTupleStruct {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn clone_value(&self) -> Box<dyn Reflect> {
|
||||
fn clone_value(&self) -> Box<dyn PartialReflect> {
|
||||
Box::new(self.clone_dynamic())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn reflect_partial_eq(&self, value: &dyn Reflect) -> Option<bool> {
|
||||
fn reflect_partial_eq(&self, value: &dyn PartialReflect) -> Option<bool> {
|
||||
tuple_struct_partial_eq(self, value)
|
||||
}
|
||||
|
||||
|
@ -408,8 +399,6 @@ impl Reflect for DynamicTupleStruct {
|
|||
}
|
||||
|
||||
impl_type_path!((in bevy_reflect) DynamicTupleStruct);
|
||||
#[cfg(feature = "functions")]
|
||||
crate::func::macros::impl_function_traits!(DynamicTupleStruct);
|
||||
|
||||
impl Debug for DynamicTupleStruct {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
|
@ -426,8 +415,8 @@ impl From<DynamicTuple> for DynamicTupleStruct {
|
|||
}
|
||||
}
|
||||
|
||||
impl FromIterator<Box<dyn Reflect>> for DynamicTupleStruct {
|
||||
fn from_iter<I: IntoIterator<Item = Box<dyn Reflect>>>(fields: I) -> Self {
|
||||
impl FromIterator<Box<dyn PartialReflect>> for DynamicTupleStruct {
|
||||
fn from_iter<I: IntoIterator<Item = Box<dyn PartialReflect>>>(fields: I) -> Self {
|
||||
Self {
|
||||
represented_type: None,
|
||||
fields: fields.into_iter().collect(),
|
||||
|
@ -436,7 +425,7 @@ impl FromIterator<Box<dyn Reflect>> for DynamicTupleStruct {
|
|||
}
|
||||
|
||||
impl IntoIterator for DynamicTupleStruct {
|
||||
type Item = Box<dyn Reflect>;
|
||||
type Item = Box<dyn PartialReflect>;
|
||||
type IntoIter = std::vec::IntoIter<Self::Item>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
|
@ -445,7 +434,7 @@ impl IntoIterator for DynamicTupleStruct {
|
|||
}
|
||||
|
||||
impl<'a> IntoIterator for &'a DynamicTupleStruct {
|
||||
type Item = &'a dyn Reflect;
|
||||
type Item = &'a dyn PartialReflect;
|
||||
type IntoIter = TupleStructFieldIter<'a>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
|
@ -453,16 +442,19 @@ impl<'a> IntoIterator for &'a DynamicTupleStruct {
|
|||
}
|
||||
}
|
||||
|
||||
/// Compares a [`TupleStruct`] with a [`Reflect`] value.
|
||||
/// Compares a [`TupleStruct`] with a [`PartialReflect`] value.
|
||||
///
|
||||
/// Returns true if and only if all of the following are true:
|
||||
/// - `b` is a tuple struct;
|
||||
/// - `b` has the same number of fields as `a`;
|
||||
/// - [`Reflect::reflect_partial_eq`] returns `Some(true)` for pairwise fields of `a` and `b`.
|
||||
/// - [`PartialReflect::reflect_partial_eq`] returns `Some(true)` for pairwise fields of `a` and `b`.
|
||||
///
|
||||
/// Returns [`None`] if the comparison couldn't even be performed.
|
||||
#[inline]
|
||||
pub fn tuple_struct_partial_eq<S: TupleStruct>(a: &S, b: &dyn Reflect) -> Option<bool> {
|
||||
pub fn tuple_struct_partial_eq<S: TupleStruct + ?Sized>(
|
||||
a: &S,
|
||||
b: &dyn PartialReflect,
|
||||
) -> Option<bool> {
|
||||
let ReflectRef::TupleStruct(tuple_struct) = b.reflect_ref() else {
|
||||
return Some(false);
|
||||
};
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::{
|
||||
ArrayInfo, DynamicArray, DynamicEnum, DynamicList, DynamicMap, DynamicStruct, DynamicTuple,
|
||||
DynamicTupleStruct, EnumInfo, ListInfo, MapInfo, Reflect, ReflectKind, SetInfo, StructInfo,
|
||||
TupleInfo, TupleStructInfo, TypePath, TypePathTable,
|
||||
DynamicTupleStruct, EnumInfo, ListInfo, MapInfo, PartialReflect, Reflect, ReflectKind, SetInfo,
|
||||
StructInfo, TupleInfo, TupleStructInfo, TypePath, TypePathTable,
|
||||
};
|
||||
use std::any::{Any, TypeId};
|
||||
use std::fmt::Debug;
|
||||
|
@ -27,7 +27,7 @@ use thiserror::Error;
|
|||
///
|
||||
/// ```
|
||||
/// # use std::any::Any;
|
||||
/// # use bevy_reflect::{DynamicTypePath, NamedField, Reflect, ReflectMut, ReflectOwned, ReflectRef, StructInfo, TypeInfo, TypePath, ValueInfo, ApplyError};
|
||||
/// # use bevy_reflect::{DynamicTypePath, NamedField, PartialReflect, Reflect, ReflectMut, ReflectOwned, ReflectRef, StructInfo, TypeInfo, TypePath, ValueInfo, ApplyError};
|
||||
/// # use bevy_reflect::utility::NonGenericTypeInfoCell;
|
||||
/// use bevy_reflect::Typed;
|
||||
///
|
||||
|
@ -54,20 +54,28 @@ use thiserror::Error;
|
|||
/// # fn type_path() -> &'static str { todo!() }
|
||||
/// # fn short_type_path() -> &'static str { todo!() }
|
||||
/// # }
|
||||
/// # impl PartialReflect for MyStruct {
|
||||
/// # fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { todo!() }
|
||||
/// # fn into_partial_reflect(self: Box<Self>) -> Box<dyn PartialReflect> { todo!() }
|
||||
/// # fn as_partial_reflect(&self) -> &dyn PartialReflect { todo!() }
|
||||
/// # fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect { todo!() }
|
||||
/// # fn try_into_reflect(self: Box<Self>) -> Result<Box<dyn Reflect>, Box<dyn PartialReflect>> { todo!() }
|
||||
/// # fn try_as_reflect(&self) -> Option<&dyn Reflect> { todo!() }
|
||||
/// # fn try_as_reflect_mut(&mut self) -> Option<&mut dyn Reflect> { todo!() }
|
||||
/// # fn try_apply(&mut self, value: &dyn PartialReflect) -> Result<(), ApplyError> { todo!() }
|
||||
/// # fn reflect_ref(&self) -> ReflectRef { todo!() }
|
||||
/// # fn reflect_mut(&mut self) -> ReflectMut { todo!() }
|
||||
/// # fn reflect_owned(self: Box<Self>) -> ReflectOwned { todo!() }
|
||||
/// # fn clone_value(&self) -> Box<dyn PartialReflect> { todo!() }
|
||||
/// # }
|
||||
/// # impl Reflect for MyStruct {
|
||||
/// # fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { todo!() }
|
||||
/// # fn into_any(self: Box<Self>) -> Box<dyn Any> { todo!() }
|
||||
/// # fn as_any(&self) -> &dyn Any { todo!() }
|
||||
/// # fn as_any_mut(&mut self) -> &mut dyn Any { todo!() }
|
||||
/// # fn into_reflect(self: Box<Self>) -> Box<dyn Reflect> { todo!() }
|
||||
/// # fn as_reflect(&self) -> &dyn Reflect { todo!() }
|
||||
/// # fn as_reflect_mut(&mut self) -> &mut dyn Reflect { todo!() }
|
||||
/// # fn try_apply(&mut self, value: &dyn Reflect) -> Result<(), ApplyError> { todo!() }
|
||||
/// # fn set(&mut self, value: Box<dyn Reflect>) -> Result<(), Box<dyn Reflect>> { todo!() }
|
||||
/// # fn reflect_ref(&self) -> ReflectRef { todo!() }
|
||||
/// # fn reflect_mut(&mut self) -> ReflectMut { todo!() }
|
||||
/// # fn reflect_owned(self: Box<Self>) -> ReflectOwned { todo!() }
|
||||
/// # fn clone_value(&self) -> Box<dyn Reflect> { todo!() }
|
||||
/// # fn into_any(self: Box<Self>) -> Box<dyn Any> { todo!() }
|
||||
/// # fn as_any(&self) -> &dyn Any { todo!() }
|
||||
/// # fn as_any_mut(&mut self) -> &mut dyn Any { todo!() }
|
||||
/// # fn into_reflect(self: Box<Self>) -> Box<dyn Reflect> { todo!() }
|
||||
/// # fn as_reflect(&self) -> &dyn Reflect { todo!() }
|
||||
/// # fn as_reflect_mut(&mut self) -> &mut dyn Reflect { todo!() }
|
||||
/// # fn set(&mut self, value: Box<dyn Reflect>) -> Result<(), Box<dyn Reflect>> { todo!() }
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
|
@ -93,7 +101,7 @@ pub trait Typed: Reflect + TypePath {
|
|||
/// This trait has a blanket implementation for all types that implement `Typed`
|
||||
/// and manual implementations for all dynamic types (which simply return `None`).
|
||||
#[doc(hidden)]
|
||||
pub trait MaybeTyped: Reflect {
|
||||
pub trait MaybeTyped: PartialReflect {
|
||||
/// Returns the compile-time [info] for the underlying type, if it exists.
|
||||
///
|
||||
/// [info]: TypeInfo
|
||||
|
@ -140,12 +148,12 @@ pub enum TypeInfoError {
|
|||
/// Generally, for any given type, this value can be retrieved one of three ways:
|
||||
///
|
||||
/// 1. [`Typed::type_info`]
|
||||
/// 2. [`Reflect::get_represented_type_info`]
|
||||
/// 2. [`PartialReflect::get_represented_type_info`]
|
||||
/// 3. [`TypeRegistry::get_type_info`]
|
||||
///
|
||||
/// Each return a static reference to [`TypeInfo`], but they all have their own use cases.
|
||||
/// For example, if you know the type at compile time, [`Typed::type_info`] is probably
|
||||
/// the simplest. If all you have is a `dyn Reflect`, you'll probably want [`Reflect::get_represented_type_info`].
|
||||
/// the simplest. If all you have is a `dyn PartialReflect`, you'll probably want [`PartialReflect::get_represented_type_info`].
|
||||
/// Lastly, if all you have is a [`TypeId`] or [type path], you will need to go through
|
||||
/// [`TypeRegistry::get_type_info`].
|
||||
///
|
||||
|
@ -153,8 +161,8 @@ pub enum TypeInfoError {
|
|||
/// it can be more performant. This is because those other methods may require attaining a lock on
|
||||
/// the static [`TypeInfo`], while the registry simply checks a map.
|
||||
///
|
||||
/// [`Reflect::get_represented_type_info`]: Reflect::get_represented_type_info
|
||||
/// [`TypeRegistry::get_type_info`]: crate::TypeRegistry::get_type_info
|
||||
/// [`PartialReflect::get_represented_type_info`]: crate::PartialReflect::get_represented_type_info
|
||||
/// [type path]: TypePath::type_path
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum TypeInfo {
|
||||
|
|
|
@ -584,7 +584,7 @@ impl<T: TypePath + FromReflect + erased_serde::Serialize> FromType<T> for Reflec
|
|||
value
|
||||
.downcast_ref::<T>()
|
||||
.map(|value| Serializable::Borrowed(value))
|
||||
.or_else(|| T::from_reflect(value).map(|value| Serializable::Owned(Box::new(value))))
|
||||
.or_else(|| T::from_reflect(value.as_partial_reflect()).map(|value| Serializable::Owned(Box::new(value))))
|
||||
.unwrap_or_else(|| {
|
||||
panic!(
|
||||
"FromReflect::from_reflect failed when called on type `{}` with this value: {value:?}",
|
||||
|
@ -788,7 +788,11 @@ mod test {
|
|||
let dyn_reflect = unsafe { reflect_from_ptr.as_reflect(Ptr::from(&value)) };
|
||||
match dyn_reflect.reflect_ref() {
|
||||
bevy_reflect::ReflectRef::Struct(strukt) => {
|
||||
let a = strukt.field("a").unwrap().downcast_ref::<f32>().unwrap();
|
||||
let a = strukt
|
||||
.field("a")
|
||||
.unwrap()
|
||||
.try_downcast_ref::<f32>()
|
||||
.unwrap();
|
||||
assert_eq!(*a, 2.0);
|
||||
}
|
||||
_ => panic!("invalid reflection"),
|
||||
|
|
|
@ -49,7 +49,7 @@ mod sealed {
|
|||
///
|
||||
/// ```
|
||||
/// # use std::any::Any;
|
||||
/// # use bevy_reflect::{DynamicTypePath, NamedField, Reflect, ReflectMut, ReflectOwned, ReflectRef, StructInfo, Typed, TypeInfo, TypePath, ApplyError};
|
||||
/// # use bevy_reflect::{DynamicTypePath, NamedField, PartialReflect, Reflect, ReflectMut, ReflectOwned, ReflectRef, StructInfo, Typed, TypeInfo, TypePath, ApplyError};
|
||||
/// use bevy_reflect::utility::NonGenericTypeInfoCell;
|
||||
///
|
||||
/// struct Foo {
|
||||
|
@ -70,20 +70,28 @@ mod sealed {
|
|||
/// # fn type_path() -> &'static str { todo!() }
|
||||
/// # fn short_type_path() -> &'static str { todo!() }
|
||||
/// # }
|
||||
/// # impl Reflect for Foo {
|
||||
/// # impl PartialReflect for Foo {
|
||||
/// # fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { todo!() }
|
||||
/// # fn into_partial_reflect(self: Box<Self>) -> Box<dyn PartialReflect> { todo!() }
|
||||
/// # fn as_partial_reflect(&self) -> &dyn PartialReflect { todo!() }
|
||||
/// # fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect { todo!() }
|
||||
/// # fn try_into_reflect(self: Box<Self>) -> Result<Box<dyn Reflect>, Box<dyn PartialReflect>> { todo!() }
|
||||
/// # fn try_as_reflect(&self) -> Option<&dyn Reflect> { todo!() }
|
||||
/// # fn try_as_reflect_mut(&mut self) -> Option<&mut dyn Reflect> { todo!() }
|
||||
/// # fn try_apply(&mut self, value: &dyn PartialReflect) -> Result<(), ApplyError> { todo!() }
|
||||
/// # fn reflect_ref(&self) -> ReflectRef { todo!() }
|
||||
/// # fn reflect_mut(&mut self) -> ReflectMut { todo!() }
|
||||
/// # fn reflect_owned(self: Box<Self>) -> ReflectOwned { todo!() }
|
||||
/// # fn clone_value(&self) -> Box<dyn PartialReflect> { todo!() }
|
||||
/// # }
|
||||
/// # impl Reflect for Foo {
|
||||
/// # fn into_any(self: Box<Self>) -> Box<dyn Any> { todo!() }
|
||||
/// # fn as_any(&self) -> &dyn Any { todo!() }
|
||||
/// # fn as_any_mut(&mut self) -> &mut dyn Any { todo!() }
|
||||
/// # fn into_reflect(self: Box<Self>) -> Box<dyn Reflect> { todo!() }
|
||||
/// # fn as_reflect(&self) -> &dyn Reflect { todo!() }
|
||||
/// # fn as_reflect_mut(&mut self) -> &mut dyn Reflect { todo!() }
|
||||
/// # fn try_apply(&mut self, value: &dyn Reflect) -> Result<(), ApplyError> { todo!() }
|
||||
/// # fn set(&mut self, value: Box<dyn Reflect>) -> Result<(), Box<dyn Reflect>> { todo!() }
|
||||
/// # fn reflect_ref(&self) -> ReflectRef { todo!() }
|
||||
/// # fn reflect_mut(&mut self) -> ReflectMut { todo!() }
|
||||
/// # fn reflect_owned(self: Box<Self>) -> ReflectOwned { todo!() }
|
||||
/// # fn clone_value(&self) -> Box<dyn Reflect> { todo!() }
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
|
@ -130,7 +138,7 @@ impl<T: TypedProperty> Default for NonGenericTypeCell<T> {
|
|||
///
|
||||
/// ```
|
||||
/// # use std::any::Any;
|
||||
/// # use bevy_reflect::{DynamicTypePath, Reflect, ReflectMut, ReflectOwned, ReflectRef, TupleStructInfo, Typed, TypeInfo, TypePath, UnnamedField, ApplyError};
|
||||
/// # use bevy_reflect::{DynamicTypePath, PartialReflect, Reflect, ReflectMut, ReflectOwned, ReflectRef, TupleStructInfo, Typed, TypeInfo, TypePath, UnnamedField, ApplyError};
|
||||
/// use bevy_reflect::utility::GenericTypeInfoCell;
|
||||
///
|
||||
/// struct Foo<T>(T);
|
||||
|
@ -149,20 +157,28 @@ impl<T: TypedProperty> Default for NonGenericTypeCell<T> {
|
|||
/// # fn type_path() -> &'static str { todo!() }
|
||||
/// # fn short_type_path() -> &'static str { todo!() }
|
||||
/// # }
|
||||
/// # impl<T: Reflect + Typed + TypePath> Reflect for Foo<T> {
|
||||
/// # impl<T: PartialReflect + TypePath> PartialReflect for Foo<T> {
|
||||
/// # fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { todo!() }
|
||||
/// # fn into_partial_reflect(self: Box<Self>) -> Box<dyn PartialReflect> { todo!() }
|
||||
/// # fn as_partial_reflect(&self) -> &dyn PartialReflect { todo!() }
|
||||
/// # fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect { todo!() }
|
||||
/// # fn try_into_reflect(self: Box<Self>) -> Result<Box<dyn Reflect>, Box<dyn PartialReflect>> { todo!() }
|
||||
/// # fn try_as_reflect(&self) -> Option<&dyn Reflect> { todo!() }
|
||||
/// # fn try_as_reflect_mut(&mut self) -> Option<&mut dyn Reflect> { todo!() }
|
||||
/// # fn try_apply(&mut self, value: &dyn PartialReflect) -> Result<(), ApplyError> { todo!() }
|
||||
/// # fn reflect_ref(&self) -> ReflectRef { todo!() }
|
||||
/// # fn reflect_mut(&mut self) -> ReflectMut { todo!() }
|
||||
/// # fn reflect_owned(self: Box<Self>) -> ReflectOwned { todo!() }
|
||||
/// # fn clone_value(&self) -> Box<dyn PartialReflect> { todo!() }
|
||||
/// # }
|
||||
/// # impl<T: Reflect + TypePath> Reflect for Foo<T> {
|
||||
/// # fn into_any(self: Box<Self>) -> Box<dyn Any> { todo!() }
|
||||
/// # fn as_any(&self) -> &dyn Any { todo!() }
|
||||
/// # fn as_any_mut(&mut self) -> &mut dyn Any { todo!() }
|
||||
/// # fn into_reflect(self: Box<Self>) -> Box<dyn Reflect> { todo!() }
|
||||
/// # fn as_reflect(&self) -> &dyn Reflect { todo!() }
|
||||
/// # fn as_reflect_mut(&mut self) -> &mut dyn Reflect { todo!() }
|
||||
/// # fn try_apply(&mut self, value: &dyn Reflect) -> Result<(), ApplyError> { todo!() }
|
||||
/// # fn set(&mut self, value: Box<dyn Reflect>) -> Result<(), Box<dyn Reflect>> { todo!() }
|
||||
/// # fn reflect_ref(&self) -> ReflectRef { todo!() }
|
||||
/// # fn reflect_mut(&mut self) -> ReflectMut { todo!() }
|
||||
/// # fn reflect_owned(self: Box<Self>) -> ReflectOwned { todo!() }
|
||||
/// # fn clone_value(&self) -> Box<dyn Reflect> { todo!() }
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
|
|
|
@ -5,7 +5,7 @@ use bevy_ecs::{
|
|||
reflect::{AppTypeRegistry, ReflectComponent, ReflectMapEntities},
|
||||
world::World,
|
||||
};
|
||||
use bevy_reflect::{Reflect, TypePath, TypeRegistry};
|
||||
use bevy_reflect::{PartialReflect, TypePath, TypeRegistry};
|
||||
use bevy_utils::TypeIdMap;
|
||||
|
||||
#[cfg(feature = "serialize")]
|
||||
|
@ -28,7 +28,7 @@ use serde::Serialize;
|
|||
#[derive(Asset, TypePath, Default)]
|
||||
pub struct DynamicScene {
|
||||
/// Resources stored in the dynamic scene.
|
||||
pub resources: Vec<Box<dyn Reflect>>,
|
||||
pub resources: Vec<Box<dyn PartialReflect>>,
|
||||
/// Entities contained in the dynamic scene.
|
||||
pub entities: Vec<DynamicEntity>,
|
||||
}
|
||||
|
@ -40,8 +40,8 @@ pub struct DynamicEntity {
|
|||
/// Components that reference this entity must consistently use this identifier.
|
||||
pub entity: Entity,
|
||||
/// A vector of boxed components that belong to the given entity and
|
||||
/// implement the [`Reflect`] trait.
|
||||
pub components: Vec<Box<dyn Reflect>>,
|
||||
/// implement the [`PartialReflect`] trait.
|
||||
pub components: Vec<Box<dyn PartialReflect>>,
|
||||
}
|
||||
|
||||
impl DynamicScene {
|
||||
|
@ -117,7 +117,11 @@ impl DynamicScene {
|
|||
// If the entity already has the given component attached,
|
||||
// just apply the (possibly) new value, otherwise add the
|
||||
// component to the entity.
|
||||
reflect_component.apply_or_insert(entity_mut, &**component, &type_registry);
|
||||
reflect_component.apply_or_insert(
|
||||
entity_mut,
|
||||
component.as_partial_reflect(),
|
||||
&type_registry,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ use bevy_ecs::{
|
|||
reflect::{AppTypeRegistry, ReflectComponent, ReflectResource},
|
||||
world::World,
|
||||
};
|
||||
use bevy_reflect::Reflect;
|
||||
use bevy_reflect::PartialReflect;
|
||||
use bevy_utils::default;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
|
@ -52,8 +52,10 @@ use std::collections::BTreeMap;
|
|||
/// # let entity = world.spawn(ComponentA).id();
|
||||
/// let dynamic_scene = DynamicSceneBuilder::from_world(&world).extract_entity(entity).build();
|
||||
/// ```
|
||||
///
|
||||
/// [`Reflect`]: bevy_reflect::Reflect
|
||||
pub struct DynamicSceneBuilder<'w> {
|
||||
extracted_resources: BTreeMap<ComponentId, Box<dyn Reflect>>,
|
||||
extracted_resources: BTreeMap<ComponentId, Box<dyn PartialReflect>>,
|
||||
extracted_scene: BTreeMap<Entity, DynamicEntity>,
|
||||
component_filter: SceneFilter,
|
||||
resource_filter: SceneFilter,
|
||||
|
|
|
@ -3,9 +3,10 @@
|
|||
use crate::{DynamicEntity, DynamicScene};
|
||||
use bevy_ecs::entity::Entity;
|
||||
use bevy_reflect::serde::{TypedReflectDeserializer, TypedReflectSerializer};
|
||||
use bevy_reflect::PartialReflect;
|
||||
use bevy_reflect::{
|
||||
serde::{ReflectDeserializer, TypeRegistrationDeserializer},
|
||||
Reflect, TypeRegistry,
|
||||
TypeRegistry,
|
||||
};
|
||||
use bevy_utils::HashSet;
|
||||
use serde::ser::SerializeMap;
|
||||
|
@ -155,7 +156,7 @@ impl<'a> Serialize for EntitySerializer<'a> {
|
|||
/// deserializing through [`SceneMapDeserializer`].
|
||||
pub struct SceneMapSerializer<'a> {
|
||||
/// List of boxed values of unique type to serialize.
|
||||
pub entries: &'a [Box<dyn Reflect>],
|
||||
pub entries: &'a [Box<dyn PartialReflect>],
|
||||
/// Type registry in which the types used in `entries` are registered.
|
||||
pub registry: &'a TypeRegistry,
|
||||
}
|
||||
|
@ -169,7 +170,7 @@ impl<'a> Serialize for SceneMapSerializer<'a> {
|
|||
for reflect in self.entries {
|
||||
state.serialize_entry(
|
||||
reflect.get_represented_type_info().unwrap().type_path(),
|
||||
&TypedReflectSerializer::new(&**reflect, self.registry),
|
||||
&TypedReflectSerializer::new(reflect.as_partial_reflect(), self.registry),
|
||||
)?;
|
||||
}
|
||||
state.end()
|
||||
|
@ -419,7 +420,7 @@ pub struct SceneMapDeserializer<'a> {
|
|||
}
|
||||
|
||||
impl<'a, 'de> DeserializeSeed<'de> for SceneMapDeserializer<'a> {
|
||||
type Value = Vec<Box<dyn Reflect>>;
|
||||
type Value = Vec<Box<dyn PartialReflect>>;
|
||||
|
||||
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
|
||||
where
|
||||
|
@ -436,7 +437,7 @@ struct SceneMapVisitor<'a> {
|
|||
}
|
||||
|
||||
impl<'a, 'de> Visitor<'de> for SceneMapVisitor<'a> {
|
||||
type Value = Vec<Box<dyn Reflect>>;
|
||||
type Value = Vec<Box<dyn PartialReflect>>;
|
||||
|
||||
fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
|
||||
formatter.write_str("map of reflect types")
|
||||
|
|
|
@ -2,7 +2,7 @@ use crate::state::{FreelyMutableState, NextState, State, States};
|
|||
|
||||
use bevy_ecs::reflect::from_reflect_with_fallback;
|
||||
use bevy_ecs::world::World;
|
||||
use bevy_reflect::{FromType, Reflect, TypeRegistry};
|
||||
use bevy_reflect::{FromType, Reflect, TypePath, TypeRegistry};
|
||||
|
||||
/// A struct used to operate on the reflected [`States`] trait of a type.
|
||||
///
|
||||
|
@ -68,7 +68,7 @@ impl ReflectFreelyMutableStateFns {
|
|||
///
|
||||
/// This is useful if you want to start with the default implementation before overriding some
|
||||
/// of the functions to create a custom implementation.
|
||||
pub fn new<T: FreelyMutableState + Reflect>() -> Self {
|
||||
pub fn new<T: FreelyMutableState + Reflect + TypePath>() -> Self {
|
||||
<ReflectFreelyMutableState as FromType<T>>::from_type().0
|
||||
}
|
||||
}
|
||||
|
@ -80,11 +80,15 @@ impl ReflectFreelyMutableState {
|
|||
}
|
||||
}
|
||||
|
||||
impl<S: FreelyMutableState + Reflect> FromType<S> for ReflectFreelyMutableState {
|
||||
impl<S: FreelyMutableState + Reflect + TypePath> FromType<S> for ReflectFreelyMutableState {
|
||||
fn from_type() -> Self {
|
||||
ReflectFreelyMutableState(ReflectFreelyMutableStateFns {
|
||||
set_next_state: |world, reflected_state, registry| {
|
||||
let new_state: S = from_reflect_with_fallback(reflected_state, world, registry);
|
||||
let new_state: S = from_reflect_with_fallback(
|
||||
reflected_state.as_partial_reflect(),
|
||||
world,
|
||||
registry,
|
||||
);
|
||||
if let Some(mut next_state) = world.get_resource_mut::<NextState<S>>() {
|
||||
next_state.set(new_state);
|
||||
}
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
use bevy::reflect::{
|
||||
reflect_trait, serde::TypedReflectDeserializer, std_traits::ReflectDefault, DynamicArray,
|
||||
DynamicEnum, DynamicList, DynamicMap, DynamicSet, DynamicStruct, DynamicTuple,
|
||||
DynamicTupleStruct, DynamicVariant, FromReflect, Reflect, ReflectFromReflect, ReflectRef, Set,
|
||||
TypeRegistry, Typed,
|
||||
DynamicTupleStruct, DynamicVariant, FromReflect, PartialReflect, Reflect, ReflectFromReflect,
|
||||
ReflectRef, Set, TypeRegistry, Typed,
|
||||
};
|
||||
use serde::de::DeserializeSeed;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
@ -34,6 +34,7 @@ fn main() {
|
|||
|
||||
// When working with reflected types, however, we often "erase" this type information
|
||||
// using the `Reflect` trait object.
|
||||
// This trait object also gives us access to all the methods in the `PartialReflect` trait too.
|
||||
// The underlying type is still the same (in this case, `Player`),
|
||||
// but now we've hidden that information from the compiler.
|
||||
let reflected: Box<dyn Reflect> = Box::new(player);
|
||||
|
@ -41,23 +42,24 @@ fn main() {
|
|||
// Because it's the same type under the hood, we can still downcast it back to the original type.
|
||||
assert!(reflected.downcast_ref::<Player>().is_some());
|
||||
|
||||
// But now let's "clone" our type using `Reflect::clone_value`.
|
||||
let cloned: Box<dyn Reflect> = reflected.clone_value();
|
||||
// But now let's "clone" our type using `PartialReflect::clone_value`.
|
||||
// Notice here we bind it as a `dyn PartialReflect`.
|
||||
let cloned: Box<dyn PartialReflect> = reflected.clone_value();
|
||||
|
||||
// If we try to downcast back to `Player`, we'll get an error.
|
||||
assert!(cloned.downcast_ref::<Player>().is_none());
|
||||
// If we try and convert it to a `dyn Reflect` trait object, we'll get an error.
|
||||
assert!(cloned.try_as_reflect().is_none());
|
||||
|
||||
// Why is this?
|
||||
// Well the reason is that `Reflect::clone_value` actually creates a dynamic type.
|
||||
// Since `Player` is a struct, we actually get a `DynamicStruct` back.
|
||||
assert!(cloned.is::<DynamicStruct>());
|
||||
// Well the reason is that `PartialReflect::clone_value` actually creates a dynamic type.
|
||||
// Since `Player` is a struct, our trait object is actually a value of `DynamicStruct`.
|
||||
assert!(cloned.is_dynamic());
|
||||
|
||||
// This dynamic type is used to represent (or "proxy") the original type,
|
||||
// so that we can continue to access its fields and overall structure.
|
||||
let ReflectRef::Struct(cloned_ref) = cloned.reflect_ref() else {
|
||||
panic!("expected struct")
|
||||
};
|
||||
let id = cloned_ref.field("id").unwrap().downcast_ref::<u32>();
|
||||
let id = cloned_ref.field("id").unwrap().try_downcast_ref::<u32>();
|
||||
assert_eq!(id, Some(&123));
|
||||
|
||||
// It also enables us to create a representation of a type without having compile-time
|
||||
|
@ -73,7 +75,6 @@ fn main() {
|
|||
.unwrap();
|
||||
|
||||
// Our deserialized output is a `DynamicStruct` that proxies/represents a `Player`.
|
||||
assert!(deserialized.downcast_ref::<DynamicStruct>().is_some());
|
||||
assert!(deserialized.represents::<Player>());
|
||||
|
||||
// And while this does allow us to access the fields and structure of the type,
|
||||
|
@ -84,20 +85,24 @@ fn main() {
|
|||
.data::<ReflectIdentifiable>()
|
||||
.expect("`ReflectIdentifiable` should be registered");
|
||||
|
||||
// Trying to access the registry with our `deserialized` will give a compile error
|
||||
// since it doesn't implement `Reflect`, only `PartialReflect`.
|
||||
// Similarly, trying to force the operation will fail.
|
||||
// This fails since the underlying type of `deserialized` is `DynamicStruct` and not `Player`.
|
||||
assert!(reflect_identifiable
|
||||
.get(deserialized.as_reflect())
|
||||
assert!(deserialized
|
||||
.try_as_reflect()
|
||||
.and_then(|reflect_trait_obj| reflect_identifiable.get(reflect_trait_obj))
|
||||
.is_none());
|
||||
|
||||
// So how can we go from a dynamic type to a concrete type?
|
||||
// There are two ways:
|
||||
|
||||
// 1. Using `Reflect::apply`.
|
||||
// 1. Using `PartialReflect::apply`.
|
||||
{
|
||||
// If you know the type at compile time, you can construct a new value and apply the dynamic
|
||||
// value to it.
|
||||
let mut value = Player::default();
|
||||
value.apply(deserialized.as_reflect());
|
||||
value.apply(deserialized.as_ref());
|
||||
assert_eq!(value.id, 123);
|
||||
|
||||
// If you don't know the type at compile time, you need a dynamic way of constructing
|
||||
|
@ -107,7 +112,7 @@ fn main() {
|
|||
.expect("`ReflectDefault` should be registered");
|
||||
|
||||
let mut value: Box<dyn Reflect> = reflect_default.default();
|
||||
value.apply(deserialized.as_reflect());
|
||||
value.apply(deserialized.as_ref());
|
||||
|
||||
let identifiable: &dyn Identifiable = reflect_identifiable.get(value.as_reflect()).unwrap();
|
||||
assert_eq!(identifiable.id(), 123);
|
||||
|
@ -117,7 +122,7 @@ fn main() {
|
|||
{
|
||||
// If you know the type at compile time, you can use the `FromReflect` trait to convert the
|
||||
// dynamic value into the concrete type directly.
|
||||
let value: Player = Player::from_reflect(deserialized.as_reflect()).unwrap();
|
||||
let value: Player = Player::from_reflect(deserialized.as_ref()).unwrap();
|
||||
assert_eq!(value.id, 123);
|
||||
|
||||
// If you don't know the type at compile time, you can use the `ReflectFromReflect` type data
|
||||
|
@ -127,14 +132,14 @@ fn main() {
|
|||
.expect("`ReflectFromReflect` should be registered");
|
||||
|
||||
let value: Box<dyn Reflect> = reflect_from_reflect
|
||||
.from_reflect(deserialized.as_reflect())
|
||||
.from_reflect(deserialized.as_ref())
|
||||
.unwrap();
|
||||
let identifiable: &dyn Identifiable = reflect_identifiable.get(value.as_reflect()).unwrap();
|
||||
assert_eq!(identifiable.id(), 123);
|
||||
}
|
||||
|
||||
// Lastly, while dynamic types are commonly generated via reflection methods like
|
||||
// `Reflect::clone_value` or via the reflection deserializers,
|
||||
// `PartialReflect::clone_value` or via the reflection deserializers,
|
||||
// you can also construct them manually.
|
||||
let mut my_dynamic_list = DynamicList::from_iter([1u32, 2u32, 3u32]);
|
||||
|
||||
|
@ -144,9 +149,13 @@ fn main() {
|
|||
assert_eq!(my_list, vec![1, 2, 3]);
|
||||
|
||||
// And if you want it to actually proxy a type, you can configure it to do that as well:
|
||||
assert!(!my_dynamic_list.as_reflect().represents::<Vec<u32>>());
|
||||
assert!(!my_dynamic_list
|
||||
.as_partial_reflect()
|
||||
.represents::<Vec<u32>>());
|
||||
my_dynamic_list.set_represented_type(Some(<Vec<u32>>::type_info()));
|
||||
assert!(my_dynamic_list.as_reflect().represents::<Vec<u32>>());
|
||||
assert!(my_dynamic_list
|
||||
.as_partial_reflect()
|
||||
.represents::<Vec<u32>>());
|
||||
|
||||
// ============================= REFERENCE ============================= //
|
||||
// For reference, here are all the available dynamic types:
|
||||
|
|
|
@ -10,7 +10,7 @@ use bevy::reflect::func::{
|
|||
ArgList, DynamicClosure, DynamicClosureMut, DynamicFunction, FunctionError, FunctionInfo,
|
||||
IntoClosure, IntoClosureMut, IntoFunction, Return,
|
||||
};
|
||||
use bevy::reflect::Reflect;
|
||||
use bevy::reflect::{PartialReflect, Reflect};
|
||||
|
||||
// Note that the `dbg!` invocations are used purely for demonstration purposes
|
||||
// and are not strictly necessary for the example to work.
|
||||
|
@ -52,8 +52,8 @@ fn main() {
|
|||
|
||||
// The `Return` value can be pattern matched or unwrapped to get the underlying reflection data.
|
||||
// For the sake of brevity, we'll just unwrap it here and downcast it to the expected type of `i32`.
|
||||
let value: Box<dyn Reflect> = return_value.unwrap_owned();
|
||||
assert_eq!(value.take::<i32>().unwrap(), 4);
|
||||
let value: Box<dyn PartialReflect> = return_value.unwrap_owned();
|
||||
assert_eq!(value.try_take::<i32>().unwrap(), 4);
|
||||
|
||||
// The same can also be done for closures that capture references to their environment.
|
||||
// Closures that capture their environment immutably can be converted into a `DynamicClosure`
|
||||
|
@ -64,8 +64,8 @@ fn main() {
|
|||
let function: DynamicClosure = dbg!(clamp.into_closure());
|
||||
let args = dbg!(ArgList::new().push_owned(2_i32));
|
||||
let return_value = dbg!(function.call(args).unwrap());
|
||||
let value: Box<dyn Reflect> = return_value.unwrap_owned();
|
||||
assert_eq!(value.take::<i32>().unwrap(), 5);
|
||||
let value: Box<dyn PartialReflect> = return_value.unwrap_owned();
|
||||
assert_eq!(value.try_take::<i32>().unwrap(), 5);
|
||||
|
||||
// We can also handle closures that capture their environment mutably
|
||||
// using the `IntoClosureMut` trait.
|
||||
|
@ -112,8 +112,8 @@ fn main() {
|
|||
let get_value = dbg!(Data::get_value.into_function());
|
||||
let args = dbg!(ArgList::new().push_ref(&data));
|
||||
let return_value = dbg!(get_value.call(args).unwrap());
|
||||
let value: &dyn Reflect = return_value.unwrap_ref();
|
||||
assert_eq!(value.downcast_ref::<String>().unwrap(), "Hello, world!");
|
||||
let value: &dyn PartialReflect = return_value.unwrap_ref();
|
||||
assert_eq!(value.try_downcast_ref::<String>().unwrap(), "Hello, world!");
|
||||
|
||||
// Lastly, for more complex use cases, you can always create a custom `DynamicFunction` manually.
|
||||
// This is useful for functions that can't be converted via the `IntoFunction` trait.
|
||||
|
@ -172,9 +172,9 @@ fn main() {
|
|||
|
||||
let args = dbg!(ArgList::new().push_owned(5_i32).push_mut(&mut container));
|
||||
let value = dbg!(get_or_insert_function.call(args).unwrap()).unwrap_ref();
|
||||
assert_eq!(value.downcast_ref::<i32>(), Some(&5));
|
||||
assert_eq!(value.try_downcast_ref::<i32>(), Some(&5));
|
||||
|
||||
let args = dbg!(ArgList::new().push_owned(500_i32).push_mut(&mut container));
|
||||
let value = dbg!(get_or_insert_function.call(args).unwrap()).unwrap_ref();
|
||||
assert_eq!(value.downcast_ref::<i32>(), Some(&5));
|
||||
assert_eq!(value.try_downcast_ref::<i32>(), Some(&5));
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ use bevy::{
|
|||
prelude::*,
|
||||
reflect::{
|
||||
serde::{ReflectDeserializer, ReflectSerializer},
|
||||
DynamicStruct,
|
||||
DynamicStruct, PartialReflect,
|
||||
},
|
||||
};
|
||||
use serde::de::DeserializeSeed;
|
||||
|
@ -65,13 +65,20 @@ fn setup(type_registry: Res<AppTypeRegistry>) {
|
|||
assert_eq!(value.a, 2);
|
||||
assert_eq!(*value.get_field::<usize>("a").unwrap(), 2);
|
||||
|
||||
// You can also get the &dyn Reflect value of a field like this
|
||||
// You can also get the `&dyn PartialReflect` value of a field like this
|
||||
let field = value.field("a").unwrap();
|
||||
|
||||
// you can downcast Reflect values like this:
|
||||
assert_eq!(*field.downcast_ref::<usize>().unwrap(), 2);
|
||||
// But values introspected via `PartialReflect` will not return `dyn Reflect` trait objects
|
||||
// (even if the containing type does implement `Reflect`), so we need to convert them:
|
||||
let fully_reflected_field = field.try_as_reflect().unwrap();
|
||||
|
||||
// DynamicStruct also implements the `Struct` and `Reflect` traits.
|
||||
// Now, you can downcast your `Reflect` value like this:
|
||||
assert_eq!(*fully_reflected_field.downcast_ref::<usize>().unwrap(), 2);
|
||||
|
||||
// For this specific case, we also support the shortcut `try_downcast_ref`:
|
||||
assert_eq!(*field.try_downcast_ref::<usize>().unwrap(), 2);
|
||||
|
||||
// `DynamicStruct` also implements the `Struct` and `Reflect` traits.
|
||||
let mut patch = DynamicStruct::default();
|
||||
patch.insert("a", 4usize);
|
||||
|
||||
|
@ -94,10 +101,14 @@ fn setup(type_registry: Res<AppTypeRegistry>) {
|
|||
let mut deserializer = ron::de::Deserializer::from_str(&ron_string).unwrap();
|
||||
let reflect_value = reflect_deserializer.deserialize(&mut deserializer).unwrap();
|
||||
|
||||
// Deserializing returns a Box<dyn Reflect> value. Generally, deserializing a value will return
|
||||
// the "dynamic" variant of a type. For example, deserializing a struct will return the
|
||||
// DynamicStruct type. "Value types" will be deserialized as themselves.
|
||||
let _deserialized_struct = reflect_value.downcast_ref::<DynamicStruct>();
|
||||
// Deserializing returns a `Box<dyn PartialReflect>` value.
|
||||
// Generally, deserializing a value will return the "dynamic" variant of a type.
|
||||
// For example, deserializing a struct will return the DynamicStruct type.
|
||||
// "Value types" will be deserialized as themselves.
|
||||
assert_eq!(
|
||||
reflect_value.reflect_type_path(),
|
||||
DynamicStruct::type_path(),
|
||||
);
|
||||
|
||||
// Reflect has its own `partial_eq` implementation, named `reflect_partial_eq`. This behaves
|
||||
// like normal `partial_eq`, but it treats "dynamic" and "non-dynamic" types the same. The
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
use bevy::{
|
||||
prelude::*,
|
||||
reflect::{DynamicList, ReflectRef},
|
||||
reflect::{DynamicList, PartialReflect, ReflectRef},
|
||||
utils::HashMap,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
@ -42,8 +42,9 @@ enum D {
|
|||
}
|
||||
|
||||
/// Reflect has "built in" support for some common traits like `PartialEq`, `Hash`, and `Serialize`.
|
||||
/// These are exposed via methods like `Reflect::reflect_hash()`, `Reflect::reflect_partial_eq()`, and
|
||||
/// `Reflect::serializable()`. You can force these implementations to use the actual trait
|
||||
/// These are exposed via methods like `PartialReflect::reflect_hash()`,
|
||||
/// `PartialReflect::reflect_partial_eq()`, and `PartialReflect::serializable()`.
|
||||
/// You can force these implementations to use the actual trait
|
||||
/// implementations (instead of their defaults) like this:
|
||||
#[derive(Reflect, Hash, Serialize, PartialEq, Eq)]
|
||||
#[reflect(Hash, Serialize, PartialEq)]
|
||||
|
|
Loading…
Reference in a new issue