reflect: stable type path v2 (#7184)
# Objective
- Introduce a stable alternative to
[`std::any::type_name`](https://doc.rust-lang.org/std/any/fn.type_name.html).
- Rewrite of #5805 with heavy inspiration in design.
- On the path to #5830.
- Part of solving #3327.
## Solution
- Add a `TypePath` trait for static stable type path/name information.
- Add a `TypePath` derive macro.
- Add a `impl_type_path` macro for implementing internal and foreign
types in `bevy_reflect`.
---
## Changelog
- Added `TypePath` trait.
- Added `DynamicTypePath` trait and `get_type_path` method to `Reflect`.
- Added a `TypePath` derive macro.
- Added a `bevy_reflect::impl_type_path` for implementing `TypePath` on
internal and foreign types in `bevy_reflect`.
- Changed `bevy_reflect::utility::(Non)GenericTypeInfoCell` to
`(Non)GenericTypedCell<T>` which allows us to be generic over both
`TypeInfo` and `TypePath`.
- `TypePath` is now a supertrait of `Asset`, `Material` and
`Material2d`.
- `impl_reflect_struct` needs a `#[type_path = "..."]` attribute to be
specified.
- `impl_reflect_value` needs to either specify path starting with a
double colon (`::core::option::Option`) or an `in my_crate::foo`
declaration.
- Added `bevy_reflect_derive::ReflectTypePath`.
- Most uses of `Ident` in `bevy_reflect_derive` changed to use
`ReflectTypePath`.
## Migration Guide
- Implementors of `Asset`, `Material` and `Material2d` now also need to
derive `TypePath`.
- Manual implementors of `Reflect` will need to implement the new
`get_type_path` method.
## Open Questions
- [x] ~This PR currently does not migrate any usages of
`std::any::type_name` to use `bevy_reflect::TypePath` to ease the review
process. Should it?~ Migration will be left to a follow-up PR.
- [ ] This PR adds a lot of `#[derive(TypePath)]` and `T: TypePath` to
satisfy new bounds, mostly when deriving `TypeUuid`. Should we make
`TypePath` a supertrait of `TypeUuid`? [Should we remove `TypeUuid` in
favour of
`TypePath`?](2afbd85532 (r961067892))
This commit is contained in:
parent
94dce091a9
commit
1efc762924
@ -98,7 +98,7 @@ pub struct AssetServerInternal {
|
|||||||
/// use bevy_asset::{AssetServer, Handle};
|
/// use bevy_asset::{AssetServer, Handle};
|
||||||
/// use bevy_ecs::prelude::{Commands, Res};
|
/// use bevy_ecs::prelude::{Commands, Res};
|
||||||
///
|
///
|
||||||
/// # #[derive(Debug, bevy_reflect::TypeUuid)]
|
/// # #[derive(Debug, bevy_reflect::TypeUuid, bevy_reflect::TypePath)]
|
||||||
/// # #[uuid = "00000000-0000-0000-0000-000000000000"]
|
/// # #[uuid = "00000000-0000-0000-0000-000000000000"]
|
||||||
/// # struct Image;
|
/// # struct Image;
|
||||||
///
|
///
|
||||||
@ -647,10 +647,10 @@ mod test {
|
|||||||
use crate::{loader::LoadedAsset, update_asset_storage_system};
|
use crate::{loader::LoadedAsset, update_asset_storage_system};
|
||||||
use bevy_app::{App, Update};
|
use bevy_app::{App, Update};
|
||||||
use bevy_ecs::prelude::*;
|
use bevy_ecs::prelude::*;
|
||||||
use bevy_reflect::TypeUuid;
|
use bevy_reflect::{TypePath, TypeUuid};
|
||||||
use bevy_utils::BoxedFuture;
|
use bevy_utils::BoxedFuture;
|
||||||
|
|
||||||
#[derive(Debug, TypeUuid)]
|
#[derive(Debug, TypeUuid, TypePath)]
|
||||||
#[uuid = "a5189b72-0572-4290-a2e0-96f73a491c44"]
|
#[uuid = "a5189b72-0572-4290-a2e0-96f73a491c44"]
|
||||||
struct PngAsset;
|
struct PngAsset;
|
||||||
|
|
||||||
|
|||||||
@ -488,7 +488,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn asset_overwriting() {
|
fn asset_overwriting() {
|
||||||
#[derive(bevy_reflect::TypeUuid)]
|
#[derive(bevy_reflect::TypeUuid, bevy_reflect::TypePath)]
|
||||||
#[uuid = "44115972-f31b-46e5-be5c-2b9aece6a52f"]
|
#[uuid = "44115972-f31b-46e5-be5c-2b9aece6a52f"]
|
||||||
struct MyAsset;
|
struct MyAsset;
|
||||||
let mut app = App::new();
|
let mut app = App::new();
|
||||||
|
|||||||
@ -5,6 +5,7 @@ use crate::{
|
|||||||
use anyhow::Error;
|
use anyhow::Error;
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use bevy_ecs::system::{Res, ResMut};
|
use bevy_ecs::system::{Res, ResMut};
|
||||||
|
use bevy_reflect::TypePath;
|
||||||
use bevy_reflect::{TypeUuid, TypeUuidDynamic};
|
use bevy_reflect::{TypeUuid, TypeUuidDynamic};
|
||||||
use bevy_utils::{BoxedFuture, HashMap};
|
use bevy_utils::{BoxedFuture, HashMap};
|
||||||
use crossbeam_channel::{Receiver, Sender};
|
use crossbeam_channel::{Receiver, Sender};
|
||||||
@ -47,13 +48,13 @@ pub trait AssetLoader: Send + Sync + 'static {
|
|||||||
///
|
///
|
||||||
/// In order to load assets into your game you must either add them manually to an asset storage
|
/// In order to load assets into your game you must either add them manually to an asset storage
|
||||||
/// with [`Assets::add`] or load them from the filesystem with [`AssetServer::load`].
|
/// with [`Assets::add`] or load them from the filesystem with [`AssetServer::load`].
|
||||||
pub trait Asset: TypeUuid + AssetDynamic {}
|
pub trait Asset: TypeUuid + TypePath + AssetDynamic {}
|
||||||
|
|
||||||
/// An untyped version of the [`Asset`] trait.
|
/// An untyped version of the [`Asset`] trait.
|
||||||
pub trait AssetDynamic: Downcast + TypeUuidDynamic + Send + Sync + 'static {}
|
pub trait AssetDynamic: Downcast + TypeUuidDynamic + Send + Sync + 'static {}
|
||||||
impl_downcast!(AssetDynamic);
|
impl_downcast!(AssetDynamic);
|
||||||
|
|
||||||
impl<T> Asset for T where T: TypeUuid + AssetDynamic + TypeUuidDynamic {}
|
impl<T> Asset for T where T: TypeUuid + TypePath + AssetDynamic + TypeUuidDynamic {}
|
||||||
|
|
||||||
impl<T> AssetDynamic for T where T: Send + Sync + 'static + TypeUuidDynamic {}
|
impl<T> AssetDynamic for T where T: Send + Sync + 'static + TypeUuidDynamic {}
|
||||||
|
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use bevy_asset::{Asset, AssetLoader, LoadContext, LoadedAsset};
|
use bevy_asset::{Asset, AssetLoader, LoadContext, LoadedAsset};
|
||||||
use bevy_reflect::TypeUuid;
|
use bevy_reflect::{TypePath, TypeUuid};
|
||||||
use bevy_utils::BoxedFuture;
|
use bevy_utils::BoxedFuture;
|
||||||
use std::{io::Cursor, sync::Arc};
|
use std::{io::Cursor, sync::Arc};
|
||||||
|
|
||||||
/// A source of audio data
|
/// A source of audio data
|
||||||
#[derive(Debug, Clone, TypeUuid)]
|
#[derive(Debug, Clone, TypeUuid, TypePath)]
|
||||||
#[uuid = "7a14806a-672b-443b-8d16-4f18afefa463"]
|
#[uuid = "7a14806a-672b-443b-8d16-4f18afefa463"]
|
||||||
pub struct AudioSource {
|
pub struct AudioSource {
|
||||||
/// Raw data of the audio source.
|
/// Raw data of the audio source.
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
use bevy_math::Vec3;
|
use bevy_math::Vec3;
|
||||||
use bevy_reflect::TypeUuid;
|
use bevy_reflect::{TypePath, TypeUuid};
|
||||||
use bevy_transform::prelude::Transform;
|
use bevy_transform::prelude::Transform;
|
||||||
use rodio::{Sink, SpatialSink};
|
use rodio::{Sink, SpatialSink};
|
||||||
|
|
||||||
@ -87,7 +87,7 @@ pub trait AudioSinkPlayback {
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
#[derive(TypeUuid)]
|
#[derive(TypePath, TypeUuid)]
|
||||||
#[uuid = "8BEE570C-57C2-4FC0-8CFB-983A22F7D981"]
|
#[uuid = "8BEE570C-57C2-4FC0-8CFB-983A22F7D981"]
|
||||||
pub struct AudioSink {
|
pub struct AudioSink {
|
||||||
// This field is an Option in order to allow us to have a safe drop that will detach the sink.
|
// This field is an Option in order to allow us to have a safe drop that will detach the sink.
|
||||||
@ -158,7 +158,7 @@ impl AudioSinkPlayback for AudioSink {
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
#[derive(TypeUuid)]
|
#[derive(TypePath, TypeUuid)]
|
||||||
#[uuid = "F3CA4C47-595E-453B-96A7-31C3DDF2A177"]
|
#[uuid = "F3CA4C47-595E-453B-96A7-31C3DDF2A177"]
|
||||||
pub struct SpatialAudioSink {
|
pub struct SpatialAudioSink {
|
||||||
// This field is an Option in order to allow us to have a safe drop that will detach the sink.
|
// This field is an Option in order to allow us to have a safe drop that will detach the sink.
|
||||||
|
|||||||
@ -407,7 +407,7 @@ impl<C: Resource + Reflect + FromWorld> FromType<C> for ReflectResource {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_reflect_value!(Entity(Hash, PartialEq, Serialize, Deserialize));
|
impl_reflect_value!((in bevy_ecs) Entity(Hash, PartialEq, Serialize, Deserialize));
|
||||||
impl_from_reflect_value!(Entity);
|
impl_from_reflect_value!(Entity);
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
|||||||
@ -12,7 +12,7 @@ use bevy_app::prelude::*;
|
|||||||
use bevy_asset::{AddAsset, Handle};
|
use bevy_asset::{AddAsset, Handle};
|
||||||
use bevy_ecs::{prelude::Component, reflect::ReflectComponent};
|
use bevy_ecs::{prelude::Component, reflect::ReflectComponent};
|
||||||
use bevy_pbr::StandardMaterial;
|
use bevy_pbr::StandardMaterial;
|
||||||
use bevy_reflect::{Reflect, TypeUuid};
|
use bevy_reflect::{Reflect, TypePath, TypeUuid};
|
||||||
use bevy_render::{
|
use bevy_render::{
|
||||||
mesh::{Mesh, MeshVertexAttribute},
|
mesh::{Mesh, MeshVertexAttribute},
|
||||||
renderer::RenderDevice,
|
renderer::RenderDevice,
|
||||||
@ -58,7 +58,7 @@ impl Plugin for GltfPlugin {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Representation of a loaded glTF file.
|
/// Representation of a loaded glTF file.
|
||||||
#[derive(Debug, TypeUuid)]
|
#[derive(Debug, TypeUuid, TypePath)]
|
||||||
#[uuid = "5c7d5f8a-f7b0-4e45-a09e-406c0372fea2"]
|
#[uuid = "5c7d5f8a-f7b0-4e45-a09e-406c0372fea2"]
|
||||||
pub struct Gltf {
|
pub struct Gltf {
|
||||||
pub scenes: Vec<Handle<Scene>>,
|
pub scenes: Vec<Handle<Scene>>,
|
||||||
@ -78,7 +78,7 @@ pub struct Gltf {
|
|||||||
|
|
||||||
/// A glTF node with all of its child nodes, its [`GltfMesh`],
|
/// A glTF node with all of its child nodes, its [`GltfMesh`],
|
||||||
/// [`Transform`](bevy_transform::prelude::Transform) and an optional [`GltfExtras`].
|
/// [`Transform`](bevy_transform::prelude::Transform) and an optional [`GltfExtras`].
|
||||||
#[derive(Debug, Clone, TypeUuid)]
|
#[derive(Debug, Clone, TypeUuid, TypePath)]
|
||||||
#[uuid = "dad74750-1fd6-460f-ac51-0a7937563865"]
|
#[uuid = "dad74750-1fd6-460f-ac51-0a7937563865"]
|
||||||
pub struct GltfNode {
|
pub struct GltfNode {
|
||||||
pub children: Vec<GltfNode>,
|
pub children: Vec<GltfNode>,
|
||||||
@ -89,7 +89,7 @@ pub struct GltfNode {
|
|||||||
|
|
||||||
/// A glTF mesh, which may consist of multiple [`GltfPrimitives`](GltfPrimitive)
|
/// A glTF mesh, which may consist of multiple [`GltfPrimitives`](GltfPrimitive)
|
||||||
/// and an optional [`GltfExtras`].
|
/// and an optional [`GltfExtras`].
|
||||||
#[derive(Debug, Clone, TypeUuid)]
|
#[derive(Debug, Clone, TypeUuid, TypePath)]
|
||||||
#[uuid = "8ceaec9a-926a-4f29-8ee3-578a69f42315"]
|
#[uuid = "8ceaec9a-926a-4f29-8ee3-578a69f42315"]
|
||||||
pub struct GltfMesh {
|
pub struct GltfMesh {
|
||||||
pub primitives: Vec<GltfPrimitive>,
|
pub primitives: Vec<GltfPrimitive>,
|
||||||
@ -97,7 +97,7 @@ pub struct GltfMesh {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Part of a [`GltfMesh`] that consists of a [`Mesh`], an optional [`StandardMaterial`] and [`GltfExtras`].
|
/// Part of a [`GltfMesh`] that consists of a [`Mesh`], an optional [`StandardMaterial`] and [`GltfExtras`].
|
||||||
#[derive(Debug, Clone, TypeUuid)]
|
#[derive(Debug, Clone, TypeUuid, TypePath)]
|
||||||
#[uuid = "cbfca302-82fd-41cb-af77-cab6b3d50af1"]
|
#[uuid = "cbfca302-82fd-41cb-af77-cab6b3d50af1"]
|
||||||
pub struct GltfPrimitive {
|
pub struct GltfPrimitive {
|
||||||
pub mesh: Handle<Mesh>,
|
pub mesh: Handle<Mesh>,
|
||||||
|
|||||||
@ -174,10 +174,12 @@ where
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
|
use bevy_reflect::TypePath;
|
||||||
|
|
||||||
use crate::Input;
|
use crate::Input;
|
||||||
|
|
||||||
/// Used for testing the functionality of [`Input`].
|
/// Used for testing the functionality of [`Input`].
|
||||||
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
|
#[derive(TypePath, Copy, Clone, Eq, PartialEq, Hash)]
|
||||||
enum DummyInput {
|
enum DummyInput {
|
||||||
Input1,
|
Input1,
|
||||||
Input2,
|
Input2,
|
||||||
|
|||||||
@ -19,7 +19,7 @@ use bevy_ecs::{
|
|||||||
SystemParamItem,
|
SystemParamItem,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use bevy_reflect::TypeUuid;
|
use bevy_reflect::{TypePath, TypeUuid};
|
||||||
use bevy_render::{
|
use bevy_render::{
|
||||||
extract_component::ExtractComponentPlugin,
|
extract_component::ExtractComponentPlugin,
|
||||||
mesh::{Mesh, MeshVertexBufferLayout},
|
mesh::{Mesh, MeshVertexBufferLayout},
|
||||||
@ -59,11 +59,11 @@ use std::marker::PhantomData;
|
|||||||
/// ```
|
/// ```
|
||||||
/// # use bevy_pbr::{Material, MaterialMeshBundle};
|
/// # use bevy_pbr::{Material, MaterialMeshBundle};
|
||||||
/// # use bevy_ecs::prelude::*;
|
/// # use bevy_ecs::prelude::*;
|
||||||
/// # use bevy_reflect::TypeUuid;
|
/// # use bevy_reflect::{TypeUuid, TypePath};
|
||||||
/// # use bevy_render::{render_resource::{AsBindGroup, ShaderRef}, texture::Image, color::Color};
|
/// # use bevy_render::{render_resource::{AsBindGroup, ShaderRef}, texture::Image, color::Color};
|
||||||
/// # use bevy_asset::{Handle, AssetServer, Assets};
|
/// # use bevy_asset::{Handle, AssetServer, Assets};
|
||||||
///
|
///
|
||||||
/// #[derive(AsBindGroup, TypeUuid, Debug, Clone)]
|
/// #[derive(AsBindGroup, TypeUuid, TypePath, Debug, Clone)]
|
||||||
/// #[uuid = "f690fdae-d598-45ab-8225-97e2a3f056e0"]
|
/// #[uuid = "f690fdae-d598-45ab-8225-97e2a3f056e0"]
|
||||||
/// pub struct CustomMaterial {
|
/// pub struct CustomMaterial {
|
||||||
/// // Uniform bindings must implement `ShaderType`, which will be used to convert the value to
|
/// // Uniform bindings must implement `ShaderType`, which will be used to convert the value to
|
||||||
@ -106,7 +106,7 @@ use std::marker::PhantomData;
|
|||||||
/// @group(1) @binding(2)
|
/// @group(1) @binding(2)
|
||||||
/// var color_sampler: sampler;
|
/// var color_sampler: sampler;
|
||||||
/// ```
|
/// ```
|
||||||
pub trait Material: AsBindGroup + Send + Sync + Clone + TypeUuid + Sized + 'static {
|
pub trait Material: AsBindGroup + Send + Sync + Clone + TypeUuid + TypePath + Sized {
|
||||||
/// Returns this material's vertex shader. If [`ShaderRef::Default`] is returned, the default mesh vertex shader
|
/// Returns this material's vertex shader. If [`ShaderRef::Default`] is returned, the default mesh vertex shader
|
||||||
/// will be used.
|
/// will be used.
|
||||||
fn vertex_shader() -> ShaderRef {
|
fn vertex_shader() -> ShaderRef {
|
||||||
|
|||||||
@ -1,15 +1,22 @@
|
|||||||
use crate::container_attributes::ReflectTraits;
|
use crate::container_attributes::ReflectTraits;
|
||||||
use crate::field_attributes::{parse_field_attrs, ReflectFieldAttr};
|
use crate::field_attributes::{parse_field_attrs, ReflectFieldAttr};
|
||||||
use crate::fq_std::{FQAny, FQDefault, FQSend, FQSync};
|
use crate::fq_std::{FQAny, FQDefault, FQSend, FQSync};
|
||||||
use crate::utility::{members_to_serialization_denylist, WhereClauseOptions};
|
use crate::type_path::parse_path_no_leading_colon;
|
||||||
|
use crate::utility::{members_to_serialization_denylist, StringExpr, WhereClauseOptions};
|
||||||
use bit_set::BitSet;
|
use bit_set::BitSet;
|
||||||
use quote::quote;
|
use quote::{quote, ToTokens};
|
||||||
use syn::token::Comma;
|
use syn::token::Comma;
|
||||||
|
|
||||||
use crate::{utility, REFLECT_ATTRIBUTE_NAME, REFLECT_VALUE_ATTRIBUTE_NAME};
|
use crate::{
|
||||||
|
utility, REFLECT_ATTRIBUTE_NAME, REFLECT_VALUE_ATTRIBUTE_NAME, TYPE_NAME_ATTRIBUTE_NAME,
|
||||||
|
TYPE_PATH_ATTRIBUTE_NAME,
|
||||||
|
};
|
||||||
use syn::punctuated::Punctuated;
|
use syn::punctuated::Punctuated;
|
||||||
use syn::spanned::Spanned;
|
use syn::spanned::Spanned;
|
||||||
use syn::{Data, DeriveInput, Field, Fields, Generics, Ident, Meta, Path, Variant};
|
use syn::{
|
||||||
|
parse_str, Data, DeriveInput, Field, Fields, GenericParam, Generics, Ident, LitStr, Meta, Path,
|
||||||
|
PathSegment, Type, TypeParam, Variant,
|
||||||
|
};
|
||||||
|
|
||||||
pub(crate) enum ReflectDerive<'a> {
|
pub(crate) enum ReflectDerive<'a> {
|
||||||
Struct(ReflectStruct<'a>),
|
Struct(ReflectStruct<'a>),
|
||||||
@ -36,9 +43,7 @@ pub(crate) struct ReflectMeta<'a> {
|
|||||||
/// The registered traits for this type.
|
/// The registered traits for this type.
|
||||||
traits: ReflectTraits,
|
traits: ReflectTraits,
|
||||||
/// The name of this type.
|
/// The name of this type.
|
||||||
type_name: &'a Ident,
|
type_path: ReflectTypePath<'a>,
|
||||||
/// The generics defined on this type.
|
|
||||||
generics: &'a Generics,
|
|
||||||
/// A cached instance of the path to the `bevy_reflect` crate.
|
/// A cached instance of the path to the `bevy_reflect` crate.
|
||||||
bevy_reflect_path: Path,
|
bevy_reflect_path: Path,
|
||||||
/// The documentation for this type, if any
|
/// The documentation for this type, if any
|
||||||
@ -131,8 +136,12 @@ enum ReflectMode {
|
|||||||
impl<'a> ReflectDerive<'a> {
|
impl<'a> ReflectDerive<'a> {
|
||||||
pub fn from_input(input: &'a DeriveInput) -> Result<Self, syn::Error> {
|
pub fn from_input(input: &'a DeriveInput) -> Result<Self, syn::Error> {
|
||||||
let mut traits = ReflectTraits::default();
|
let mut traits = ReflectTraits::default();
|
||||||
// Should indicate whether `#[reflect_value]` was used
|
// Should indicate whether `#[reflect_value]` was used.
|
||||||
let mut reflect_mode = None;
|
let mut reflect_mode = None;
|
||||||
|
// Should indicate whether `#[type_path = "..."]` was used.
|
||||||
|
let mut custom_path: Option<Path> = None;
|
||||||
|
// Should indicate whether `#[type_name = "..."]` was used.
|
||||||
|
let mut custom_type_name: Option<Ident> = None;
|
||||||
|
|
||||||
#[cfg(feature = "documentation")]
|
#[cfg(feature = "documentation")]
|
||||||
let mut doc = crate::documentation::Documentation::default();
|
let mut doc = crate::documentation::Documentation::default();
|
||||||
@ -177,6 +186,35 @@ impl<'a> ReflectDerive<'a> {
|
|||||||
|
|
||||||
reflect_mode = Some(ReflectMode::Value);
|
reflect_mode = Some(ReflectMode::Value);
|
||||||
}
|
}
|
||||||
|
Meta::NameValue(pair) if pair.path.is_ident(TYPE_PATH_ATTRIBUTE_NAME) => {
|
||||||
|
let syn::Expr::Lit(syn::ExprLit {
|
||||||
|
lit: syn::Lit::Str(lit),
|
||||||
|
..
|
||||||
|
}) = &pair.value else {
|
||||||
|
return Err(syn::Error::new(
|
||||||
|
pair.span(),
|
||||||
|
format_args!("`#[{TYPE_PATH_ATTRIBUTE_NAME} = \"...\"]` must be a string literal"),
|
||||||
|
));
|
||||||
|
};
|
||||||
|
|
||||||
|
custom_path = Some(syn::parse::Parser::parse_str(
|
||||||
|
parse_path_no_leading_colon,
|
||||||
|
&lit.value(),
|
||||||
|
)?);
|
||||||
|
}
|
||||||
|
Meta::NameValue(pair) if pair.path.is_ident(TYPE_NAME_ATTRIBUTE_NAME) => {
|
||||||
|
let syn::Expr::Lit(syn::ExprLit {
|
||||||
|
lit: syn::Lit::Str(lit),
|
||||||
|
..
|
||||||
|
}) = &pair.value else {
|
||||||
|
return Err(syn::Error::new(
|
||||||
|
pair.span(),
|
||||||
|
format_args!("`#[{TYPE_NAME_ATTRIBUTE_NAME} = \"...\"]` must be a string literal"),
|
||||||
|
));
|
||||||
|
};
|
||||||
|
|
||||||
|
custom_type_name = Some(parse_str(&lit.value())?);
|
||||||
|
}
|
||||||
#[cfg(feature = "documentation")]
|
#[cfg(feature = "documentation")]
|
||||||
Meta::NameValue(pair) if pair.path.is_ident("doc") => {
|
Meta::NameValue(pair) if pair.path.is_ident("doc") => {
|
||||||
if let syn::Expr::Lit(syn::ExprLit {
|
if let syn::Expr::Lit(syn::ExprLit {
|
||||||
@ -190,8 +228,27 @@ impl<'a> ReflectDerive<'a> {
|
|||||||
_ => continue,
|
_ => continue,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
match (&mut custom_path, custom_type_name) {
|
||||||
|
(Some(path), custom_type_name) => {
|
||||||
|
let ident = custom_type_name.unwrap_or_else(|| input.ident.clone());
|
||||||
|
path.segments.push(PathSegment::from(ident));
|
||||||
|
}
|
||||||
|
(None, Some(name)) => {
|
||||||
|
return Err(syn::Error::new(
|
||||||
|
name.span(),
|
||||||
|
format!("cannot use `#[{TYPE_NAME_ATTRIBUTE_NAME} = \"...\"]` without a `#[{TYPE_PATH_ATTRIBUTE_NAME} = \"...\"]` attribute."),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
|
||||||
let meta = ReflectMeta::new(&input.ident, &input.generics, traits);
|
let type_path = ReflectTypePath::Internal {
|
||||||
|
ident: &input.ident,
|
||||||
|
custom_path,
|
||||||
|
generics: &input.generics,
|
||||||
|
};
|
||||||
|
|
||||||
|
let meta = ReflectMeta::new(type_path, traits);
|
||||||
|
|
||||||
#[cfg(feature = "documentation")]
|
#[cfg(feature = "documentation")]
|
||||||
let meta = meta.with_docs(doc);
|
let meta = meta.with_docs(doc);
|
||||||
@ -233,6 +290,16 @@ impl<'a> ReflectDerive<'a> {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn meta(&self) -> &ReflectMeta<'a> {
|
||||||
|
match self {
|
||||||
|
ReflectDerive::Struct(data)
|
||||||
|
| ReflectDerive::TupleStruct(data)
|
||||||
|
| ReflectDerive::UnitStruct(data) => data.meta(),
|
||||||
|
ReflectDerive::Enum(data) => data.meta(),
|
||||||
|
ReflectDerive::Value(meta) => meta,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn collect_struct_fields(fields: &'a Fields) -> Result<Vec<StructField<'a>>, syn::Error> {
|
fn collect_struct_fields(fields: &'a Fields) -> Result<Vec<StructField<'a>>, syn::Error> {
|
||||||
let sifter: utility::ResultSifter<StructField<'a>> = fields
|
let sifter: utility::ResultSifter<StructField<'a>> = fields
|
||||||
.iter()
|
.iter()
|
||||||
@ -288,11 +355,10 @@ impl<'a> ReflectDerive<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ReflectMeta<'a> {
|
impl<'a> ReflectMeta<'a> {
|
||||||
pub fn new(type_name: &'a Ident, generics: &'a Generics, traits: ReflectTraits) -> Self {
|
pub fn new(type_path: ReflectTypePath<'a>, traits: ReflectTraits) -> Self {
|
||||||
Self {
|
Self {
|
||||||
traits,
|
traits,
|
||||||
type_name,
|
type_path,
|
||||||
generics,
|
|
||||||
bevy_reflect_path: utility::get_bevy_reflect_path(),
|
bevy_reflect_path: utility::get_bevy_reflect_path(),
|
||||||
#[cfg(feature = "documentation")]
|
#[cfg(feature = "documentation")]
|
||||||
docs: Default::default(),
|
docs: Default::default(),
|
||||||
@ -311,13 +377,8 @@ impl<'a> ReflectMeta<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The name of this struct.
|
/// The name of this struct.
|
||||||
pub fn type_name(&self) -> &'a Ident {
|
pub fn type_path(&self) -> &ReflectTypePath<'a> {
|
||||||
self.type_name
|
&self.type_path
|
||||||
}
|
|
||||||
|
|
||||||
/// The generics associated with this struct.
|
|
||||||
pub fn generics(&self) -> &'a Generics {
|
|
||||||
self.generics
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The cached `bevy_reflect` path.
|
/// The cached `bevy_reflect` path.
|
||||||
@ -330,14 +391,7 @@ impl<'a> ReflectMeta<'a> {
|
|||||||
&self,
|
&self,
|
||||||
where_clause_options: &WhereClauseOptions,
|
where_clause_options: &WhereClauseOptions,
|
||||||
) -> proc_macro2::TokenStream {
|
) -> proc_macro2::TokenStream {
|
||||||
crate::registration::impl_get_type_registration(
|
crate::registration::impl_get_type_registration(self, where_clause_options, None)
|
||||||
self.type_name,
|
|
||||||
&self.bevy_reflect_path,
|
|
||||||
self.traits.idents(),
|
|
||||||
self.generics,
|
|
||||||
where_clause_options,
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The collection of docstrings for this type, if any.
|
/// The collection of docstrings for this type, if any.
|
||||||
@ -368,13 +422,8 @@ impl<'a> ReflectStruct<'a> {
|
|||||||
&self,
|
&self,
|
||||||
where_clause_options: &WhereClauseOptions,
|
where_clause_options: &WhereClauseOptions,
|
||||||
) -> proc_macro2::TokenStream {
|
) -> proc_macro2::TokenStream {
|
||||||
let reflect_path = self.meta.bevy_reflect_path();
|
|
||||||
|
|
||||||
crate::registration::impl_get_type_registration(
|
crate::registration::impl_get_type_registration(
|
||||||
self.meta.type_name(),
|
self.meta(),
|
||||||
reflect_path,
|
|
||||||
self.meta.traits().idents(),
|
|
||||||
self.meta.generics(),
|
|
||||||
where_clause_options,
|
where_clause_options,
|
||||||
Some(&self.serialization_denylist),
|
Some(&self.serialization_denylist),
|
||||||
)
|
)
|
||||||
@ -421,6 +470,7 @@ impl<'a> ReflectStruct<'a> {
|
|||||||
active_trait_bounds: quote! { #bevy_reflect_path::Reflect },
|
active_trait_bounds: quote! { #bevy_reflect_path::Reflect },
|
||||||
ignored_types: self.ignored_types().into(),
|
ignored_types: self.ignored_types().into(),
|
||||||
ignored_trait_bounds: quote! { #FQAny + #FQSend + #FQSync },
|
ignored_trait_bounds: quote! { #FQAny + #FQSend + #FQSync },
|
||||||
|
..WhereClauseOptions::type_path_bounds(self.meta())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -433,7 +483,7 @@ impl<'a> ReflectEnum<'a> {
|
|||||||
|
|
||||||
/// Returns the given ident as a qualified unit variant of this enum.
|
/// Returns the given ident as a qualified unit variant of this enum.
|
||||||
pub fn get_unit(&self, variant: &Ident) -> proc_macro2::TokenStream {
|
pub fn get_unit(&self, variant: &Ident) -> proc_macro2::TokenStream {
|
||||||
let name = self.meta.type_name;
|
let name = self.meta.type_path();
|
||||||
quote! {
|
quote! {
|
||||||
#name::#variant
|
#name::#variant
|
||||||
}
|
}
|
||||||
@ -479,6 +529,7 @@ impl<'a> ReflectEnum<'a> {
|
|||||||
active_trait_bounds: quote! { #bevy_reflect_path::FromReflect },
|
active_trait_bounds: quote! { #bevy_reflect_path::FromReflect },
|
||||||
ignored_types: self.ignored_types().into(),
|
ignored_types: self.ignored_types().into(),
|
||||||
ignored_trait_bounds: quote! { #FQAny + #FQSend + #FQSync + #FQDefault },
|
ignored_trait_bounds: quote! { #FQAny + #FQSend + #FQSync + #FQDefault },
|
||||||
|
..WhereClauseOptions::type_path_bounds(self.meta())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -509,3 +560,355 @@ impl<'a> EnumVariant<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Represents a path to a type.
|
||||||
|
///
|
||||||
|
/// This is used over [`struct@Ident`] or [`Path`]
|
||||||
|
/// to have the correct semantics for [deriving `TypePath`].
|
||||||
|
///
|
||||||
|
/// The type can always be reached with its [`ToTokens`] implementation.
|
||||||
|
///
|
||||||
|
/// The [`short_type_path`], [`type_ident`], [`crate_name`], and [`module_path`] methods
|
||||||
|
/// have corresponding methods on the `TypePath` trait.
|
||||||
|
/// [`long_type_path`] corresponds to the `type_path` method on `TypePath`.
|
||||||
|
///
|
||||||
|
/// [deriving `TypePath`]: crate::derive_type_path
|
||||||
|
/// [`long_type_path`]: ReflectTypePath::long_type_path
|
||||||
|
/// [`short_type_path`]: ReflectTypePath::short_type_path
|
||||||
|
/// [`type_ident`]: ReflectTypePath::type_ident
|
||||||
|
/// [`crate_name`]: ReflectTypePath::crate_name
|
||||||
|
/// [`module_path`]: ReflectTypePath::module_path
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// ```rust,ignore
|
||||||
|
/// # use syn::parse_quote;
|
||||||
|
/// # use bevy_reflect_derive::ReflectTypePath;
|
||||||
|
/// let path: syn::Path = parse_quote!(::core::marker::PhantomData)?;
|
||||||
|
///
|
||||||
|
/// let type_path = ReflectTypePath::External {
|
||||||
|
/// path,
|
||||||
|
/// custom_path: None,
|
||||||
|
/// };
|
||||||
|
///
|
||||||
|
/// // Eqivalent to "core::marker".
|
||||||
|
/// let module_path = type_path.module_path();
|
||||||
|
/// # Ok::<(), syn::Error>(())
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
pub(crate) enum ReflectTypePath<'a> {
|
||||||
|
/// Types without a crate/module that can be named from any scope (e.g. `bool`).
|
||||||
|
Primitive(&'a Ident),
|
||||||
|
/// Using `::my_crate::foo::Bar` syntax.
|
||||||
|
///
|
||||||
|
/// May have a seperate custom path used for the `TypePath` implementation.
|
||||||
|
External {
|
||||||
|
path: &'a Path,
|
||||||
|
custom_path: Option<Path>,
|
||||||
|
generics: &'a Generics,
|
||||||
|
},
|
||||||
|
/// The name of a type relative to its scope.
|
||||||
|
///
|
||||||
|
/// The type must be able to be reached with just its name.
|
||||||
|
///
|
||||||
|
/// May have a seperate alias path used for the `TypePath` implementation.
|
||||||
|
///
|
||||||
|
/// Module and crate are found with [`module_path!()`](core::module_path),
|
||||||
|
/// if there is no custom path specified.
|
||||||
|
Internal {
|
||||||
|
ident: &'a Ident,
|
||||||
|
custom_path: Option<Path>,
|
||||||
|
generics: &'a Generics,
|
||||||
|
},
|
||||||
|
/// Any [`syn::Type`] with only a defined `type_path` and `short_type_path`.
|
||||||
|
#[allow(dead_code)]
|
||||||
|
// Not currently used but may be useful in the future due to its generality.
|
||||||
|
Anonymous {
|
||||||
|
qualified_type: Type,
|
||||||
|
long_type_path: StringExpr,
|
||||||
|
short_type_path: StringExpr,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> ReflectTypePath<'a> {
|
||||||
|
/// Returns the path interpreted as an [`struct@Ident`].
|
||||||
|
///
|
||||||
|
/// Returns [`None`] if [anonymous].
|
||||||
|
///
|
||||||
|
/// [anonymous]: ReflectTypePath::Anonymous
|
||||||
|
pub fn get_ident(&self) -> Option<&Ident> {
|
||||||
|
match self {
|
||||||
|
Self::Internal {
|
||||||
|
ident, custom_path, ..
|
||||||
|
} => Some(
|
||||||
|
custom_path
|
||||||
|
.as_ref()
|
||||||
|
.map(|path| &path.segments.last().unwrap().ident)
|
||||||
|
.unwrap_or(ident),
|
||||||
|
),
|
||||||
|
Self::External {
|
||||||
|
path, custom_path, ..
|
||||||
|
} => Some(
|
||||||
|
&custom_path
|
||||||
|
.as_ref()
|
||||||
|
.unwrap_or(path)
|
||||||
|
.segments
|
||||||
|
.last()
|
||||||
|
.unwrap()
|
||||||
|
.ident,
|
||||||
|
),
|
||||||
|
Self::Primitive(ident) => Some(ident),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The generics associated with the type.
|
||||||
|
///
|
||||||
|
/// Empty if [anonymous] or [primitive].
|
||||||
|
///
|
||||||
|
/// [primitive]: ReflectTypePath::Primitive
|
||||||
|
/// [anonymous]: ReflectTypePath::Anonymous
|
||||||
|
pub fn generics(&self) -> &'a Generics {
|
||||||
|
// Use a constant because we need to return a reference of at least 'a.
|
||||||
|
const EMPTY_GENERICS: &Generics = &Generics {
|
||||||
|
gt_token: None,
|
||||||
|
lt_token: None,
|
||||||
|
where_clause: None,
|
||||||
|
params: Punctuated::new(),
|
||||||
|
};
|
||||||
|
match self {
|
||||||
|
Self::Internal { generics, .. } | Self::External { generics, .. } => generics,
|
||||||
|
_ => EMPTY_GENERICS,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Whether an implementation of `Typed` or `TypePath` should be generic.
|
||||||
|
///
|
||||||
|
/// Returning true that it should use a `GenericTypeCell` in its implementation.
|
||||||
|
pub fn impl_is_generic(&self) -> bool {
|
||||||
|
// Whether to use `GenericTypeCell` is not dependent on lifetimes
|
||||||
|
// (which all have to be 'static anyway).
|
||||||
|
!self
|
||||||
|
.generics()
|
||||||
|
.params
|
||||||
|
.iter()
|
||||||
|
.all(|param| matches!(param, GenericParam::Lifetime(_)))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the path interpreted as a [`Path`].
|
||||||
|
///
|
||||||
|
/// Returns [`None`] if [anonymous], [primitive],
|
||||||
|
/// or a [`ReflectTypePath::Internal`] without a custom path.
|
||||||
|
///
|
||||||
|
/// [primitive]: ReflectTypePath::Primitive
|
||||||
|
/// [anonymous]: ReflectTypePath::Anonymous
|
||||||
|
pub fn get_path(&self) -> Option<&Path> {
|
||||||
|
match self {
|
||||||
|
Self::Internal { custom_path, .. } => custom_path.as_ref(),
|
||||||
|
Self::External {
|
||||||
|
path, custom_path, ..
|
||||||
|
} => Some(custom_path.as_ref().unwrap_or(path)),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns whether this [internal] or [external] path has a custom path.
|
||||||
|
///
|
||||||
|
/// [internal]: ReflectTypePath::Internal
|
||||||
|
/// [external]: ReflectTypePath::External
|
||||||
|
pub fn has_custom_path(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
Self::Internal { custom_path, .. } | Self::External { custom_path, .. } => {
|
||||||
|
custom_path.is_some()
|
||||||
|
}
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a [`StringExpr`] representing the name of the type's crate.
|
||||||
|
///
|
||||||
|
/// Returns [`None`] if the type is [primitive] or [anonymous].
|
||||||
|
///
|
||||||
|
/// For non-customised [internal] paths this is created from [`module_path`].
|
||||||
|
///
|
||||||
|
/// For `Option<PhantomData>`, this is `"core"`.
|
||||||
|
///
|
||||||
|
/// [primitive]: ReflectTypePath::Primitive
|
||||||
|
/// [anonymous]: ReflectTypePath::Anonymous
|
||||||
|
/// [internal]: ReflectTypePath::Internal
|
||||||
|
pub fn crate_name(&self) -> Option<StringExpr> {
|
||||||
|
if let Some(path) = self.get_path() {
|
||||||
|
let crate_name = &path.segments.first().unwrap().ident;
|
||||||
|
return Some(StringExpr::from(crate_name));
|
||||||
|
}
|
||||||
|
|
||||||
|
match self {
|
||||||
|
Self::Internal { .. } => Some(StringExpr::Borrowed(quote! {
|
||||||
|
::core::module_path!()
|
||||||
|
.split(':')
|
||||||
|
.next()
|
||||||
|
.unwrap()
|
||||||
|
})),
|
||||||
|
Self::External { .. } => unreachable!(),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Combines type generics and const generics into one [`StringExpr`].
|
||||||
|
///
|
||||||
|
/// This string can be used with a `GenericTypePathCell` in a `TypePath` implementation.
|
||||||
|
///
|
||||||
|
/// The `ty_generic_fn` param maps [`TypeParam`]s to [`StringExpr`]s.
|
||||||
|
fn reduce_generics(
|
||||||
|
generics: &Generics,
|
||||||
|
mut ty_generic_fn: impl FnMut(&TypeParam) -> StringExpr,
|
||||||
|
) -> StringExpr {
|
||||||
|
let mut params = generics.params.iter().filter_map(|param| match param {
|
||||||
|
GenericParam::Type(type_param) => Some(ty_generic_fn(type_param)),
|
||||||
|
GenericParam::Const(const_param) => {
|
||||||
|
let ident = &const_param.ident;
|
||||||
|
let ty = &const_param.ty;
|
||||||
|
|
||||||
|
Some(StringExpr::Owned(quote! {
|
||||||
|
<#ty as ::std::string::ToString>::to_string(&#ident)
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
GenericParam::Lifetime(_) => None,
|
||||||
|
});
|
||||||
|
|
||||||
|
params
|
||||||
|
.next()
|
||||||
|
.into_iter()
|
||||||
|
.chain(params.flat_map(|x| [StringExpr::from_str(", "), x]))
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a [`StringExpr`] representing the "type path" of the type.
|
||||||
|
///
|
||||||
|
/// For `Option<PhantomData>`, this is `"core::option::Option<core::marker::PhantomData>"`.
|
||||||
|
pub fn long_type_path(&self, bevy_reflect_path: &Path) -> StringExpr {
|
||||||
|
match self {
|
||||||
|
Self::Primitive(ident) => StringExpr::from(ident),
|
||||||
|
Self::Anonymous { long_type_path, .. } => long_type_path.clone(),
|
||||||
|
Self::Internal { generics, .. } | Self::External { generics, .. } => {
|
||||||
|
let ident = self.type_ident().unwrap();
|
||||||
|
let module_path = self.module_path().unwrap();
|
||||||
|
|
||||||
|
if self.impl_is_generic() {
|
||||||
|
let generics = ReflectTypePath::reduce_generics(
|
||||||
|
generics,
|
||||||
|
|TypeParam { ident, .. }| {
|
||||||
|
StringExpr::Borrowed(quote! {
|
||||||
|
<#ident as #bevy_reflect_path::TypePath>::type_path()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
StringExpr::from_iter([
|
||||||
|
module_path,
|
||||||
|
StringExpr::from_str("::"),
|
||||||
|
ident,
|
||||||
|
StringExpr::from_str("<"),
|
||||||
|
generics,
|
||||||
|
StringExpr::from_str(">"),
|
||||||
|
])
|
||||||
|
} else {
|
||||||
|
StringExpr::from_iter([module_path, StringExpr::from_str("::"), ident])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a [`StringExpr`] representing the "short path" of the type.
|
||||||
|
///
|
||||||
|
/// For `Option<PhantomData>`, this is `"Option<PhantomData>"`.
|
||||||
|
pub fn short_type_path(&self, bevy_reflect_path: &Path) -> StringExpr {
|
||||||
|
match self {
|
||||||
|
Self::Anonymous {
|
||||||
|
short_type_path, ..
|
||||||
|
} => short_type_path.clone(),
|
||||||
|
Self::Primitive(ident) => StringExpr::from(ident),
|
||||||
|
Self::External { generics, .. } | Self::Internal { generics, .. } => {
|
||||||
|
let ident = self.type_ident().unwrap();
|
||||||
|
|
||||||
|
if self.impl_is_generic() {
|
||||||
|
let generics = ReflectTypePath::reduce_generics(
|
||||||
|
generics,
|
||||||
|
|TypeParam { ident, .. }| {
|
||||||
|
StringExpr::Borrowed(quote! {
|
||||||
|
<#ident as #bevy_reflect_path::TypePath>::short_type_path()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
StringExpr::from_iter([
|
||||||
|
ident,
|
||||||
|
StringExpr::from_str("<"),
|
||||||
|
generics,
|
||||||
|
StringExpr::from_str(">"),
|
||||||
|
])
|
||||||
|
} else {
|
||||||
|
ident
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a [`StringExpr`] representing the path to the module
|
||||||
|
/// that the type is in.
|
||||||
|
///
|
||||||
|
/// Returns [`None`] if the type is [primitive] or [anonymous].
|
||||||
|
///
|
||||||
|
/// For non-customised [internal] paths this is created from [`module_path`].
|
||||||
|
///
|
||||||
|
/// For `Option<PhantomData>`, this is `"core::option"`.
|
||||||
|
///
|
||||||
|
/// [primitive]: ReflectTypePath::Primitive
|
||||||
|
/// [anonymous]: ReflectTypePath::Anonymous
|
||||||
|
/// [internal]: ReflectTypePath::Internal
|
||||||
|
pub fn module_path(&self) -> Option<StringExpr> {
|
||||||
|
if let Some(path) = self.get_path() {
|
||||||
|
let path_string = path
|
||||||
|
.segments
|
||||||
|
.pairs()
|
||||||
|
.take(path.segments.len() - 1)
|
||||||
|
.map(|pair| pair.value().ident.to_string())
|
||||||
|
.reduce(|path, ident| path + "::" + &ident)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let path_lit = LitStr::new(&path_string, path.span());
|
||||||
|
return Some(StringExpr::from_lit(&path_lit));
|
||||||
|
}
|
||||||
|
|
||||||
|
match self {
|
||||||
|
Self::Internal { .. } => Some(StringExpr::Const(quote! {
|
||||||
|
::core::module_path!()
|
||||||
|
})),
|
||||||
|
Self::External { .. } => unreachable!(),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a [`StringExpr`] representing the type's final ident.
|
||||||
|
///
|
||||||
|
/// Returns [`None`] if the type is [anonymous].
|
||||||
|
///
|
||||||
|
/// This is not necessarily a valid qualified path to the type.
|
||||||
|
///
|
||||||
|
/// For `Option<PhantomData>`, this is `"Option"`.
|
||||||
|
///
|
||||||
|
/// [anonymous]: ReflectTypePath::Anonymous
|
||||||
|
pub fn type_ident(&self) -> Option<StringExpr> {
|
||||||
|
self.get_ident().map(StringExpr::from)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> ToTokens for ReflectTypePath<'a> {
|
||||||
|
fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
|
||||||
|
match self {
|
||||||
|
Self::Internal { ident, .. } | Self::Primitive(ident) => ident.to_tokens(tokens),
|
||||||
|
Self::External { path, .. } => path.to_tokens(tokens),
|
||||||
|
Self::Anonymous { qualified_type, .. } => qualified_type.to_tokens(tokens),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -22,13 +22,13 @@ pub(crate) fn impl_tuple_struct(reflect_struct: &ReflectStruct) -> TokenStream {
|
|||||||
|
|
||||||
/// Implements `FromReflect` for the given value type
|
/// Implements `FromReflect` for the given value type
|
||||||
pub(crate) fn impl_value(meta: &ReflectMeta) -> TokenStream {
|
pub(crate) fn impl_value(meta: &ReflectMeta) -> TokenStream {
|
||||||
let type_name = meta.type_name();
|
let type_path = meta.type_path();
|
||||||
let bevy_reflect_path = meta.bevy_reflect_path();
|
let bevy_reflect_path = meta.bevy_reflect_path();
|
||||||
let (impl_generics, ty_generics, where_clause) = meta.generics().split_for_impl();
|
let (impl_generics, ty_generics, where_clause) = type_path.generics().split_for_impl();
|
||||||
TokenStream::from(quote! {
|
TokenStream::from(quote! {
|
||||||
impl #impl_generics #bevy_reflect_path::FromReflect for #type_name #ty_generics #where_clause {
|
impl #impl_generics #bevy_reflect_path::FromReflect for #type_path #ty_generics #where_clause {
|
||||||
fn from_reflect(reflect: &dyn #bevy_reflect_path::Reflect) -> #FQOption<Self> {
|
fn from_reflect(reflect: &dyn #bevy_reflect_path::Reflect) -> #FQOption<Self> {
|
||||||
#FQOption::Some(#FQClone::clone(<dyn #FQAny>::downcast_ref::<#type_name #ty_generics>(<dyn #bevy_reflect_path::Reflect>::as_any(reflect))?))
|
#FQOption::Some(#FQClone::clone(<dyn #FQAny>::downcast_ref::<#type_path #ty_generics>(<dyn #bevy_reflect_path::Reflect>::as_any(reflect))?))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -38,7 +38,7 @@ pub(crate) fn impl_value(meta: &ReflectMeta) -> TokenStream {
|
|||||||
pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> TokenStream {
|
pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> TokenStream {
|
||||||
let fqoption = FQOption.into_token_stream();
|
let fqoption = FQOption.into_token_stream();
|
||||||
|
|
||||||
let type_name = reflect_enum.meta().type_name();
|
let enum_path = reflect_enum.meta().type_path();
|
||||||
let bevy_reflect_path = reflect_enum.meta().bevy_reflect_path();
|
let bevy_reflect_path = reflect_enum.meta().bevy_reflect_path();
|
||||||
|
|
||||||
let ref_value = Ident::new("__param0", Span::call_site());
|
let ref_value = Ident::new("__param0", Span::call_site());
|
||||||
@ -47,8 +47,7 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> TokenStream {
|
|||||||
variant_constructors,
|
variant_constructors,
|
||||||
} = get_variant_constructors(reflect_enum, &ref_value, false);
|
} = get_variant_constructors(reflect_enum, &ref_value, false);
|
||||||
|
|
||||||
let (impl_generics, ty_generics, where_clause) =
|
let (impl_generics, ty_generics, where_clause) = enum_path.generics().split_for_impl();
|
||||||
reflect_enum.meta().generics().split_for_impl();
|
|
||||||
|
|
||||||
// Add FromReflect bound for each active field
|
// Add FromReflect bound for each active field
|
||||||
let where_from_reflect_clause = extend_where_clause(
|
let where_from_reflect_clause = extend_where_clause(
|
||||||
@ -58,11 +57,12 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> TokenStream {
|
|||||||
ignored_types: reflect_enum.ignored_types().into_boxed_slice(),
|
ignored_types: reflect_enum.ignored_types().into_boxed_slice(),
|
||||||
active_trait_bounds: quote!(#bevy_reflect_path::FromReflect),
|
active_trait_bounds: quote!(#bevy_reflect_path::FromReflect),
|
||||||
ignored_trait_bounds: quote!(#FQDefault),
|
ignored_trait_bounds: quote!(#FQDefault),
|
||||||
|
..WhereClauseOptions::type_path_bounds(reflect_enum.meta())
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
TokenStream::from(quote! {
|
TokenStream::from(quote! {
|
||||||
impl #impl_generics #bevy_reflect_path::FromReflect for #type_name #ty_generics #where_from_reflect_clause {
|
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> {
|
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) {
|
if let #bevy_reflect_path::ReflectRef::Enum(#ref_value) = #bevy_reflect_path::Reflect::reflect_ref(#ref_value) {
|
||||||
match #bevy_reflect_path::Enum::variant_name(#ref_value) {
|
match #bevy_reflect_path::Enum::variant_name(#ref_value) {
|
||||||
@ -90,8 +90,7 @@ impl MemberValuePair {
|
|||||||
fn impl_struct_internal(reflect_struct: &ReflectStruct, is_tuple: bool) -> TokenStream {
|
fn impl_struct_internal(reflect_struct: &ReflectStruct, is_tuple: bool) -> TokenStream {
|
||||||
let fqoption = FQOption.into_token_stream();
|
let fqoption = FQOption.into_token_stream();
|
||||||
|
|
||||||
let struct_name = reflect_struct.meta().type_name();
|
let struct_path = reflect_struct.meta().type_path();
|
||||||
let generics = reflect_struct.meta().generics();
|
|
||||||
let bevy_reflect_path = reflect_struct.meta().bevy_reflect_path();
|
let bevy_reflect_path = reflect_struct.meta().bevy_reflect_path();
|
||||||
|
|
||||||
let ref_struct = Ident::new("__ref_struct", Span::call_site());
|
let ref_struct = Ident::new("__ref_struct", Span::call_site());
|
||||||
@ -129,7 +128,11 @@ fn impl_struct_internal(reflect_struct: &ReflectStruct, is_tuple: bool) -> Token
|
|||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
|
let (impl_generics, ty_generics, where_clause) = reflect_struct
|
||||||
|
.meta()
|
||||||
|
.type_path()
|
||||||
|
.generics()
|
||||||
|
.split_for_impl();
|
||||||
|
|
||||||
// Add FromReflect bound for each active field
|
// Add FromReflect bound for each active field
|
||||||
let where_from_reflect_clause = extend_where_clause(
|
let where_from_reflect_clause = extend_where_clause(
|
||||||
@ -143,11 +146,12 @@ fn impl_struct_internal(reflect_struct: &ReflectStruct, is_tuple: bool) -> Token
|
|||||||
} else {
|
} else {
|
||||||
quote!(#FQDefault)
|
quote!(#FQDefault)
|
||||||
},
|
},
|
||||||
|
..WhereClauseOptions::type_path_bounds(reflect_struct.meta())
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
TokenStream::from(quote! {
|
TokenStream::from(quote! {
|
||||||
impl #impl_generics #bevy_reflect_path::FromReflect for #struct_name #ty_generics #where_from_reflect_clause
|
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> {
|
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) {
|
if let #bevy_reflect_path::ReflectRef::#ref_struct_type(#ref_struct) = #bevy_reflect_path::Reflect::reflect_ref(reflect) {
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
use crate::derive_data::{EnumVariant, EnumVariantFields, ReflectEnum, StructField};
|
use crate::derive_data::{EnumVariant, EnumVariantFields, ReflectEnum, StructField};
|
||||||
use crate::enum_utility::{get_variant_constructors, EnumVariantConstructors};
|
use crate::enum_utility::{get_variant_constructors, EnumVariantConstructors};
|
||||||
use crate::fq_std::{FQAny, FQBox, FQOption, FQResult};
|
use crate::fq_std::{FQAny, FQBox, FQOption, FQResult};
|
||||||
use crate::impls::impl_typed;
|
use crate::impls::{impl_type_path, impl_typed};
|
||||||
use crate::utility::extend_where_clause;
|
use crate::utility::extend_where_clause;
|
||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
use proc_macro2::{Ident, Span};
|
use proc_macro2::{Ident, Span};
|
||||||
@ -10,7 +10,7 @@ use syn::Fields;
|
|||||||
|
|
||||||
pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> TokenStream {
|
pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> TokenStream {
|
||||||
let bevy_reflect_path = reflect_enum.meta().bevy_reflect_path();
|
let bevy_reflect_path = reflect_enum.meta().bevy_reflect_path();
|
||||||
let enum_name = reflect_enum.meta().type_name();
|
let enum_path = reflect_enum.meta().type_path();
|
||||||
|
|
||||||
let ref_name = Ident::new("__name_param", Span::call_site());
|
let ref_name = Ident::new("__name_param", Span::call_site());
|
||||||
let ref_index = Ident::new("__index_param", Span::call_site());
|
let ref_index = Ident::new("__index_param", Span::call_site());
|
||||||
@ -59,7 +59,7 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> TokenStream {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let string_name = enum_name.to_string();
|
let string_name = enum_path.get_ident().unwrap().to_string();
|
||||||
|
|
||||||
#[cfg(feature = "documentation")]
|
#[cfg(feature = "documentation")]
|
||||||
let info_generator = {
|
let info_generator = {
|
||||||
@ -77,22 +77,23 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> TokenStream {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let typed_impl = impl_typed(
|
let typed_impl = impl_typed(
|
||||||
enum_name,
|
reflect_enum.meta(),
|
||||||
reflect_enum.meta().generics(),
|
|
||||||
&where_clause_options,
|
&where_clause_options,
|
||||||
quote! {
|
quote! {
|
||||||
let variants = [#(#variant_info),*];
|
let variants = [#(#variant_info),*];
|
||||||
let info = #info_generator;
|
let info = #info_generator;
|
||||||
#bevy_reflect_path::TypeInfo::Enum(info)
|
#bevy_reflect_path::TypeInfo::Enum(info)
|
||||||
},
|
},
|
||||||
bevy_reflect_path,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let type_path_impl = impl_type_path(reflect_enum.meta(), &where_clause_options);
|
||||||
|
|
||||||
let get_type_registration_impl = reflect_enum
|
let get_type_registration_impl = reflect_enum
|
||||||
.meta()
|
.meta()
|
||||||
.get_type_registration(&where_clause_options);
|
.get_type_registration(&where_clause_options);
|
||||||
|
|
||||||
let (impl_generics, ty_generics, where_clause) =
|
let (impl_generics, ty_generics, where_clause) =
|
||||||
reflect_enum.meta().generics().split_for_impl();
|
reflect_enum.meta().type_path().generics().split_for_impl();
|
||||||
|
|
||||||
let where_reflect_clause = extend_where_clause(where_clause, &where_clause_options);
|
let where_reflect_clause = extend_where_clause(where_clause, &where_clause_options);
|
||||||
|
|
||||||
@ -101,7 +102,9 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> TokenStream {
|
|||||||
|
|
||||||
#typed_impl
|
#typed_impl
|
||||||
|
|
||||||
impl #impl_generics #bevy_reflect_path::Enum for #enum_name #ty_generics #where_reflect_clause {
|
#type_path_impl
|
||||||
|
|
||||||
|
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::Reflect> {
|
||||||
match self {
|
match self {
|
||||||
#(#enum_field,)*
|
#(#enum_field,)*
|
||||||
@ -185,7 +188,7 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> TokenStream {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl #impl_generics #bevy_reflect_path::Reflect for #enum_name #ty_generics #where_reflect_clause {
|
impl #impl_generics #bevy_reflect_path::Reflect for #enum_path #ty_generics #where_reflect_clause {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn type_name(&self) -> &str {
|
fn type_name(&self) -> &str {
|
||||||
::core::any::type_name::<Self>()
|
::core::any::type_name::<Self>()
|
||||||
@ -196,6 +199,11 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> TokenStream {
|
|||||||
#FQOption::Some(<Self as #bevy_reflect_path::Typed>::type_info())
|
#FQOption::Some(<Self as #bevy_reflect_path::Typed>::type_info())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn get_type_path(&self) -> &dyn #bevy_reflect_path::DynamicTypePath {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn into_any(self: #FQBox<Self>) -> #FQBox<dyn #FQAny> {
|
fn into_any(self: #FQBox<Self>) -> #FQBox<dyn #FQAny> {
|
||||||
self
|
self
|
||||||
|
|||||||
@ -7,5 +7,6 @@ mod values;
|
|||||||
pub(crate) use enums::impl_enum;
|
pub(crate) use enums::impl_enum;
|
||||||
pub(crate) use structs::impl_struct;
|
pub(crate) use structs::impl_struct;
|
||||||
pub(crate) use tuple_structs::impl_tuple_struct;
|
pub(crate) use tuple_structs::impl_tuple_struct;
|
||||||
|
pub(crate) use typed::impl_type_path;
|
||||||
pub(crate) use typed::impl_typed;
|
pub(crate) use typed::impl_typed;
|
||||||
pub(crate) use values::impl_value;
|
pub(crate) use values::impl_value;
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
use crate::fq_std::{FQAny, FQBox, FQDefault, FQOption, FQResult};
|
use crate::fq_std::{FQAny, FQBox, FQDefault, FQOption, FQResult};
|
||||||
use crate::impls::impl_typed;
|
use crate::impls::{impl_type_path, impl_typed};
|
||||||
use crate::utility::{extend_where_clause, ident_or_index};
|
use crate::utility::{extend_where_clause, ident_or_index};
|
||||||
use crate::ReflectStruct;
|
use crate::ReflectStruct;
|
||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
@ -10,7 +10,7 @@ pub(crate) fn impl_struct(reflect_struct: &ReflectStruct) -> TokenStream {
|
|||||||
let fqoption = FQOption.into_token_stream();
|
let fqoption = FQOption.into_token_stream();
|
||||||
|
|
||||||
let bevy_reflect_path = reflect_struct.meta().bevy_reflect_path();
|
let bevy_reflect_path = reflect_struct.meta().bevy_reflect_path();
|
||||||
let struct_name = reflect_struct.meta().type_name();
|
let struct_path = reflect_struct.meta().type_path();
|
||||||
|
|
||||||
let field_names = reflect_struct
|
let field_names = reflect_struct
|
||||||
.active_fields()
|
.active_fields()
|
||||||
@ -64,7 +64,7 @@ pub(crate) fn impl_struct(reflect_struct: &ReflectStruct) -> TokenStream {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let string_name = struct_name.to_string();
|
let string_name = struct_path.get_ident().unwrap().to_string();
|
||||||
|
|
||||||
#[cfg(feature = "documentation")]
|
#[cfg(feature = "documentation")]
|
||||||
let info_generator = {
|
let info_generator = {
|
||||||
@ -83,20 +83,24 @@ pub(crate) fn impl_struct(reflect_struct: &ReflectStruct) -> TokenStream {
|
|||||||
|
|
||||||
let where_clause_options = reflect_struct.where_clause_options();
|
let where_clause_options = reflect_struct.where_clause_options();
|
||||||
let typed_impl = impl_typed(
|
let typed_impl = impl_typed(
|
||||||
struct_name,
|
reflect_struct.meta(),
|
||||||
reflect_struct.meta().generics(),
|
|
||||||
&where_clause_options,
|
&where_clause_options,
|
||||||
quote! {
|
quote! {
|
||||||
let fields = [#field_generator];
|
let fields = [#field_generator];
|
||||||
let info = #info_generator;
|
let info = #info_generator;
|
||||||
#bevy_reflect_path::TypeInfo::Struct(info)
|
#bevy_reflect_path::TypeInfo::Struct(info)
|
||||||
},
|
},
|
||||||
bevy_reflect_path,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let type_path_impl = impl_type_path(reflect_struct.meta(), &where_clause_options);
|
||||||
|
|
||||||
let get_type_registration_impl = reflect_struct.get_type_registration(&where_clause_options);
|
let get_type_registration_impl = reflect_struct.get_type_registration(&where_clause_options);
|
||||||
let (impl_generics, ty_generics, where_clause) =
|
|
||||||
reflect_struct.meta().generics().split_for_impl();
|
let (impl_generics, ty_generics, where_clause) = reflect_struct
|
||||||
|
.meta()
|
||||||
|
.type_path()
|
||||||
|
.generics()
|
||||||
|
.split_for_impl();
|
||||||
|
|
||||||
let where_reflect_clause = extend_where_clause(where_clause, &where_clause_options);
|
let where_reflect_clause = extend_where_clause(where_clause, &where_clause_options);
|
||||||
|
|
||||||
@ -105,7 +109,9 @@ pub(crate) fn impl_struct(reflect_struct: &ReflectStruct) -> TokenStream {
|
|||||||
|
|
||||||
#typed_impl
|
#typed_impl
|
||||||
|
|
||||||
impl #impl_generics #bevy_reflect_path::Struct for #struct_name #ty_generics #where_reflect_clause {
|
#type_path_impl
|
||||||
|
|
||||||
|
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::Reflect> {
|
||||||
match name {
|
match name {
|
||||||
#(#field_names => #fqoption::Some(&self.#field_idents),)*
|
#(#field_names => #fqoption::Some(&self.#field_idents),)*
|
||||||
@ -157,7 +163,7 @@ pub(crate) fn impl_struct(reflect_struct: &ReflectStruct) -> TokenStream {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl #impl_generics #bevy_reflect_path::Reflect for #struct_name #ty_generics #where_reflect_clause {
|
impl #impl_generics #bevy_reflect_path::Reflect for #struct_path #ty_generics #where_reflect_clause {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn type_name(&self) -> &str {
|
fn type_name(&self) -> &str {
|
||||||
::core::any::type_name::<Self>()
|
::core::any::type_name::<Self>()
|
||||||
@ -168,6 +174,11 @@ pub(crate) fn impl_struct(reflect_struct: &ReflectStruct) -> TokenStream {
|
|||||||
#FQOption::Some(<Self as #bevy_reflect_path::Typed>::type_info())
|
#FQOption::Some(<Self as #bevy_reflect_path::Typed>::type_info())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn get_type_path(&self) -> &dyn #bevy_reflect_path::DynamicTypePath {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn into_any(self: #FQBox<Self>) -> #FQBox<dyn #FQAny> {
|
fn into_any(self: #FQBox<Self>) -> #FQBox<dyn #FQAny> {
|
||||||
self
|
self
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
use crate::fq_std::{FQAny, FQBox, FQDefault, FQOption, FQResult};
|
use crate::fq_std::{FQAny, FQBox, FQDefault, FQOption, FQResult};
|
||||||
use crate::impls::impl_typed;
|
use crate::impls::{impl_type_path, impl_typed};
|
||||||
use crate::utility::extend_where_clause;
|
use crate::utility::extend_where_clause;
|
||||||
use crate::ReflectStruct;
|
use crate::ReflectStruct;
|
||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
@ -11,7 +11,7 @@ pub(crate) fn impl_tuple_struct(reflect_struct: &ReflectStruct) -> TokenStream {
|
|||||||
let fqoption = FQOption.into_token_stream();
|
let fqoption = FQOption.into_token_stream();
|
||||||
|
|
||||||
let bevy_reflect_path = reflect_struct.meta().bevy_reflect_path();
|
let bevy_reflect_path = reflect_struct.meta().bevy_reflect_path();
|
||||||
let struct_name = reflect_struct.meta().type_name();
|
let struct_path = reflect_struct.meta().type_path();
|
||||||
|
|
||||||
let field_idents = reflect_struct
|
let field_idents = reflect_struct
|
||||||
.active_fields()
|
.active_fields()
|
||||||
@ -58,7 +58,7 @@ pub(crate) fn impl_tuple_struct(reflect_struct: &ReflectStruct) -> TokenStream {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let string_name = struct_name.to_string();
|
let string_name = struct_path.get_ident().unwrap().to_string();
|
||||||
|
|
||||||
#[cfg(feature = "documentation")]
|
#[cfg(feature = "documentation")]
|
||||||
let info_generator = {
|
let info_generator = {
|
||||||
@ -76,19 +76,22 @@ pub(crate) fn impl_tuple_struct(reflect_struct: &ReflectStruct) -> TokenStream {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let typed_impl = impl_typed(
|
let typed_impl = impl_typed(
|
||||||
struct_name,
|
reflect_struct.meta(),
|
||||||
reflect_struct.meta().generics(),
|
|
||||||
&where_clause_options,
|
&where_clause_options,
|
||||||
quote! {
|
quote! {
|
||||||
let fields = [#field_generator];
|
let fields = [#field_generator];
|
||||||
let info = #info_generator;
|
let info = #info_generator;
|
||||||
#bevy_reflect_path::TypeInfo::TupleStruct(info)
|
#bevy_reflect_path::TypeInfo::TupleStruct(info)
|
||||||
},
|
},
|
||||||
bevy_reflect_path,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let (impl_generics, ty_generics, where_clause) =
|
let type_path_impl = impl_type_path(reflect_struct.meta(), &where_clause_options);
|
||||||
reflect_struct.meta().generics().split_for_impl();
|
|
||||||
|
let (impl_generics, ty_generics, where_clause) = reflect_struct
|
||||||
|
.meta()
|
||||||
|
.type_path()
|
||||||
|
.generics()
|
||||||
|
.split_for_impl();
|
||||||
|
|
||||||
let where_reflect_clause = extend_where_clause(where_clause, &where_clause_options);
|
let where_reflect_clause = extend_where_clause(where_clause, &where_clause_options);
|
||||||
|
|
||||||
@ -97,7 +100,9 @@ pub(crate) fn impl_tuple_struct(reflect_struct: &ReflectStruct) -> TokenStream {
|
|||||||
|
|
||||||
#typed_impl
|
#typed_impl
|
||||||
|
|
||||||
impl #impl_generics #bevy_reflect_path::TupleStruct for #struct_name #ty_generics #where_reflect_clause {
|
#type_path_impl
|
||||||
|
|
||||||
|
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::Reflect> {
|
||||||
match index {
|
match index {
|
||||||
#(#field_indices => #fqoption::Some(&self.#field_idents),)*
|
#(#field_indices => #fqoption::Some(&self.#field_idents),)*
|
||||||
@ -128,7 +133,7 @@ pub(crate) fn impl_tuple_struct(reflect_struct: &ReflectStruct) -> TokenStream {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl #impl_generics #bevy_reflect_path::Reflect for #struct_name #ty_generics #where_reflect_clause {
|
impl #impl_generics #bevy_reflect_path::Reflect for #struct_path #ty_generics #where_reflect_clause {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn type_name(&self) -> &str {
|
fn type_name(&self) -> &str {
|
||||||
::core::any::type_name::<Self>()
|
::core::any::type_name::<Self>()
|
||||||
@ -139,6 +144,11 @@ pub(crate) fn impl_tuple_struct(reflect_struct: &ReflectStruct) -> TokenStream {
|
|||||||
#FQOption::Some(<Self as #bevy_reflect_path::Typed>::type_info())
|
#FQOption::Some(<Self as #bevy_reflect_path::Typed>::type_info())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn get_type_path(&self) -> &dyn #bevy_reflect_path::DynamicTypePath {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn into_any(self: #FQBox<Self>) -> #FQBox<dyn #FQAny> {
|
fn into_any(self: #FQBox<Self>) -> #FQBox<dyn #FQAny> {
|
||||||
self
|
self
|
||||||
|
|||||||
@ -1,43 +1,149 @@
|
|||||||
use crate::utility::{extend_where_clause, WhereClauseOptions};
|
use crate::utility::{extend_where_clause, StringExpr, WhereClauseOptions};
|
||||||
use proc_macro2::Ident;
|
use quote::{quote, ToTokens};
|
||||||
use quote::quote;
|
|
||||||
use syn::{Generics, Path};
|
|
||||||
|
|
||||||
#[allow(clippy::too_many_arguments)]
|
use crate::{
|
||||||
pub(crate) fn impl_typed(
|
derive_data::{ReflectMeta, ReflectTypePath},
|
||||||
type_name: &Ident,
|
utility::wrap_in_option,
|
||||||
generics: &Generics,
|
};
|
||||||
where_clause_options: &WhereClauseOptions,
|
|
||||||
|
/// Returns an expression for a `NonGenericTypeCell` or `GenericTypeCell` to generate `'static` references.
|
||||||
|
fn static_type_cell(
|
||||||
|
meta: &ReflectMeta,
|
||||||
|
property: TypedProperty,
|
||||||
generator: proc_macro2::TokenStream,
|
generator: proc_macro2::TokenStream,
|
||||||
bevy_reflect_path: &Path,
|
|
||||||
) -> proc_macro2::TokenStream {
|
) -> proc_macro2::TokenStream {
|
||||||
let is_generic = !generics.params.is_empty();
|
let bevy_reflect_path = meta.bevy_reflect_path();
|
||||||
|
if meta.type_path().impl_is_generic() {
|
||||||
|
let cell_type = match property {
|
||||||
|
TypedProperty::TypePath => quote!(GenericTypePathCell),
|
||||||
|
TypedProperty::TypeInfo => quote!(GenericTypeInfoCell),
|
||||||
|
};
|
||||||
|
|
||||||
let static_generator = if is_generic {
|
|
||||||
quote! {
|
quote! {
|
||||||
static CELL: #bevy_reflect_path::utility::GenericTypeInfoCell = #bevy_reflect_path::utility::GenericTypeInfoCell::new();
|
static CELL: #bevy_reflect_path::utility::#cell_type = #bevy_reflect_path::utility::#cell_type::new();
|
||||||
CELL.get_or_insert::<Self, _>(|| {
|
CELL.get_or_insert::<Self, _>(|| {
|
||||||
#generator
|
#generator
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
let cell_type = match property {
|
||||||
|
TypedProperty::TypePath => unreachable!(
|
||||||
|
"Cannot have a non-generic type path cell. Use string literals and core::concat instead."
|
||||||
|
),
|
||||||
|
TypedProperty::TypeInfo => quote!(NonGenericTypeInfoCell),
|
||||||
|
};
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
static CELL: #bevy_reflect_path::utility::NonGenericTypeInfoCell = #bevy_reflect_path::utility::NonGenericTypeInfoCell::new();
|
static CELL: #bevy_reflect_path::utility::#cell_type = #bevy_reflect_path::utility::#cell_type::new();
|
||||||
CELL.get_or_set(|| {
|
CELL.get_or_set(|| {
|
||||||
#generator
|
#generator
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
pub(crate) enum TypedProperty {
|
||||||
|
TypeInfo,
|
||||||
|
TypePath,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn impl_type_path(
|
||||||
|
meta: &ReflectMeta,
|
||||||
|
where_clause_options: &WhereClauseOptions,
|
||||||
|
) -> proc_macro2::TokenStream {
|
||||||
|
let type_path = meta.type_path();
|
||||||
|
let bevy_reflect_path = meta.bevy_reflect_path();
|
||||||
|
|
||||||
|
let (long_type_path, short_type_path) = if type_path.impl_is_generic() {
|
||||||
|
let long_path_cell = static_type_cell(
|
||||||
|
meta,
|
||||||
|
TypedProperty::TypePath,
|
||||||
|
type_path.long_type_path(bevy_reflect_path).into_owned(),
|
||||||
|
);
|
||||||
|
let short_path_cell = static_type_cell(
|
||||||
|
meta,
|
||||||
|
TypedProperty::TypePath,
|
||||||
|
type_path.short_type_path(bevy_reflect_path).into_owned(),
|
||||||
|
);
|
||||||
|
(
|
||||||
|
long_path_cell.to_token_stream(),
|
||||||
|
short_path_cell.to_token_stream(),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
(
|
||||||
|
type_path.long_type_path(bevy_reflect_path).into_borrowed(),
|
||||||
|
type_path.short_type_path(bevy_reflect_path).into_borrowed(),
|
||||||
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
|
let type_ident = wrap_in_option(type_path.type_ident().map(StringExpr::into_borrowed));
|
||||||
|
let module_path = wrap_in_option(type_path.module_path().map(StringExpr::into_borrowed));
|
||||||
|
let crate_name = wrap_in_option(type_path.crate_name().map(StringExpr::into_borrowed));
|
||||||
|
|
||||||
|
let primitive_assert = if let ReflectTypePath::Primitive(_) = type_path {
|
||||||
|
Some(quote! {
|
||||||
|
const _: () = {
|
||||||
|
mod private_scope {
|
||||||
|
// Compiles if it can be named when there are no imports.
|
||||||
|
type AssertIsPrimitive = #type_path;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
let (impl_generics, ty_generics, where_clause) = type_path.generics().split_for_impl();
|
||||||
|
|
||||||
// Add Typed bound for each active field
|
// Add Typed bound for each active field
|
||||||
let where_reflect_clause = extend_where_clause(where_clause, where_clause_options);
|
let where_reflect_clause = extend_where_clause(where_clause, where_clause_options);
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
impl #impl_generics #bevy_reflect_path::Typed for #type_name #ty_generics #where_reflect_clause {
|
#primitive_assert
|
||||||
fn type_info() -> &'static #bevy_reflect_path::TypeInfo {
|
|
||||||
#static_generator
|
impl #impl_generics #bevy_reflect_path::TypePath for #type_path #ty_generics #where_reflect_clause {
|
||||||
|
fn type_path() -> &'static str {
|
||||||
|
#long_type_path
|
||||||
|
}
|
||||||
|
|
||||||
|
fn short_type_path() -> &'static str {
|
||||||
|
#short_type_path
|
||||||
|
}
|
||||||
|
|
||||||
|
fn type_ident() -> Option<&'static str> {
|
||||||
|
#type_ident
|
||||||
|
}
|
||||||
|
|
||||||
|
fn crate_name() -> Option<&'static str> {
|
||||||
|
#crate_name
|
||||||
|
}
|
||||||
|
|
||||||
|
fn module_path() -> Option<&'static str> {
|
||||||
|
#module_path
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn impl_typed(
|
||||||
|
meta: &ReflectMeta,
|
||||||
|
where_clause_options: &WhereClauseOptions,
|
||||||
|
type_info_generator: proc_macro2::TokenStream,
|
||||||
|
) -> proc_macro2::TokenStream {
|
||||||
|
let type_path = meta.type_path();
|
||||||
|
let bevy_reflect_path = meta.bevy_reflect_path();
|
||||||
|
|
||||||
|
let type_info_cell = static_type_cell(meta, TypedProperty::TypeInfo, type_info_generator);
|
||||||
|
|
||||||
|
let (impl_generics, ty_generics, where_clause) = type_path.generics().split_for_impl();
|
||||||
|
|
||||||
|
let where_reflect_clause = extend_where_clause(where_clause, where_clause_options);
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
impl #impl_generics #bevy_reflect_path::Typed for #type_path #ty_generics #where_reflect_clause {
|
||||||
|
fn type_info() -> &'static #bevy_reflect_path::TypeInfo {
|
||||||
|
#type_info_cell
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
use crate::fq_std::{FQAny, FQBox, FQClone, FQOption, FQResult};
|
use crate::fq_std::{FQAny, FQBox, FQClone, FQOption, FQResult};
|
||||||
use crate::impls::impl_typed;
|
use crate::impls::{impl_type_path, impl_typed};
|
||||||
use crate::utility::WhereClauseOptions;
|
use crate::utility::{extend_where_clause, WhereClauseOptions};
|
||||||
use crate::ReflectMeta;
|
use crate::ReflectMeta;
|
||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
@ -8,7 +8,7 @@ use quote::quote;
|
|||||||
/// Implements `GetTypeRegistration` and `Reflect` for the given type data.
|
/// Implements `GetTypeRegistration` and `Reflect` for the given type data.
|
||||||
pub(crate) fn impl_value(meta: &ReflectMeta) -> TokenStream {
|
pub(crate) fn impl_value(meta: &ReflectMeta) -> TokenStream {
|
||||||
let bevy_reflect_path = meta.bevy_reflect_path();
|
let bevy_reflect_path = meta.bevy_reflect_path();
|
||||||
let type_name = meta.type_name();
|
let type_path = meta.type_path();
|
||||||
|
|
||||||
let hash_fn = meta.traits().get_hash_impl(bevy_reflect_path);
|
let hash_fn = meta.traits().get_hash_impl(bevy_reflect_path);
|
||||||
let partial_eq_fn = meta.traits().get_partial_eq_impl(bevy_reflect_path);
|
let partial_eq_fn = meta.traits().get_partial_eq_impl(bevy_reflect_path);
|
||||||
@ -22,27 +22,30 @@ pub(crate) fn impl_value(meta: &ReflectMeta) -> TokenStream {
|
|||||||
#[cfg(not(feature = "documentation"))]
|
#[cfg(not(feature = "documentation"))]
|
||||||
let with_docs: Option<proc_macro2::TokenStream> = None;
|
let with_docs: Option<proc_macro2::TokenStream> = None;
|
||||||
|
|
||||||
let where_clause_options = WhereClauseOptions::default();
|
let where_clause_options = WhereClauseOptions::type_path_bounds(meta);
|
||||||
let typed_impl = impl_typed(
|
let typed_impl = impl_typed(
|
||||||
type_name,
|
meta,
|
||||||
meta.generics(),
|
|
||||||
&where_clause_options,
|
&where_clause_options,
|
||||||
quote! {
|
quote! {
|
||||||
let info = #bevy_reflect_path::ValueInfo::new::<Self>() #with_docs;
|
let info = #bevy_reflect_path::ValueInfo::new::<Self>() #with_docs;
|
||||||
#bevy_reflect_path::TypeInfo::Value(info)
|
#bevy_reflect_path::TypeInfo::Value(info)
|
||||||
},
|
},
|
||||||
bevy_reflect_path,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
let (impl_generics, ty_generics, where_clause) = meta.generics().split_for_impl();
|
let type_path_impl = impl_type_path(meta, &where_clause_options);
|
||||||
|
|
||||||
|
let (impl_generics, ty_generics, where_clause) = type_path.generics().split_for_impl();
|
||||||
|
let where_reflect_clause = extend_where_clause(where_clause, &where_clause_options);
|
||||||
let get_type_registration_impl = meta.get_type_registration(&where_clause_options);
|
let get_type_registration_impl = meta.get_type_registration(&where_clause_options);
|
||||||
|
|
||||||
TokenStream::from(quote! {
|
TokenStream::from(quote! {
|
||||||
#get_type_registration_impl
|
#get_type_registration_impl
|
||||||
|
|
||||||
|
#type_path_impl
|
||||||
|
|
||||||
#typed_impl
|
#typed_impl
|
||||||
|
|
||||||
impl #impl_generics #bevy_reflect_path::Reflect for #type_name #ty_generics #where_clause {
|
impl #impl_generics #bevy_reflect_path::Reflect for #type_path #ty_generics #where_reflect_clause {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn type_name(&self) -> &str {
|
fn type_name(&self) -> &str {
|
||||||
::core::any::type_name::<Self>()
|
::core::any::type_name::<Self>()
|
||||||
@ -53,6 +56,11 @@ pub(crate) fn impl_value(meta: &ReflectMeta) -> TokenStream {
|
|||||||
#FQOption::Some(<Self as #bevy_reflect_path::Typed>::type_info())
|
#FQOption::Some(<Self as #bevy_reflect_path::Typed>::type_info())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn get_type_path(&self) -> &dyn #bevy_reflect_path::DynamicTypePath {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn into_any(self: #FQBox<Self>) -> #FQBox<dyn #FQAny> {
|
fn into_any(self: #FQBox<Self>) -> #FQBox<dyn #FQAny> {
|
||||||
self
|
self
|
||||||
|
|||||||
@ -26,20 +26,27 @@ mod impls;
|
|||||||
mod reflect_value;
|
mod reflect_value;
|
||||||
mod registration;
|
mod registration;
|
||||||
mod trait_reflection;
|
mod trait_reflection;
|
||||||
|
mod type_path;
|
||||||
mod type_uuid;
|
mod type_uuid;
|
||||||
mod utility;
|
mod utility;
|
||||||
|
|
||||||
use crate::derive_data::{ReflectDerive, ReflectMeta, ReflectStruct};
|
use crate::derive_data::{ReflectDerive, ReflectMeta, ReflectStruct};
|
||||||
use crate::type_uuid::gen_impl_type_uuid;
|
use crate::type_uuid::gen_impl_type_uuid;
|
||||||
|
use container_attributes::ReflectTraits;
|
||||||
|
use derive_data::ReflectTypePath;
|
||||||
use proc_macro::TokenStream;
|
use proc_macro::TokenStream;
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
use reflect_value::ReflectValueDef;
|
use reflect_value::ReflectValueDef;
|
||||||
use syn::spanned::Spanned;
|
use syn::spanned::Spanned;
|
||||||
use syn::{parse_macro_input, DeriveInput};
|
use syn::{parse_macro_input, DeriveInput};
|
||||||
|
use type_path::NamedTypePathDef;
|
||||||
use type_uuid::TypeUuidDef;
|
use type_uuid::TypeUuidDef;
|
||||||
|
use utility::WhereClauseOptions;
|
||||||
|
|
||||||
pub(crate) static REFLECT_ATTRIBUTE_NAME: &str = "reflect";
|
pub(crate) static REFLECT_ATTRIBUTE_NAME: &str = "reflect";
|
||||||
pub(crate) static REFLECT_VALUE_ATTRIBUTE_NAME: &str = "reflect_value";
|
pub(crate) static REFLECT_VALUE_ATTRIBUTE_NAME: &str = "reflect_value";
|
||||||
|
pub(crate) static TYPE_PATH_ATTRIBUTE_NAME: &str = "type_path";
|
||||||
|
pub(crate) static TYPE_NAME_ATTRIBUTE_NAME: &str = "type_name";
|
||||||
|
|
||||||
/// The main derive macro used by `bevy_reflect` for deriving its `Reflect` trait.
|
/// The main derive macro used by `bevy_reflect` for deriving its `Reflect` trait.
|
||||||
///
|
///
|
||||||
@ -52,6 +59,8 @@ pub(crate) static REFLECT_VALUE_ATTRIBUTE_NAME: &str = "reflect_value";
|
|||||||
/// This macro comes with some helper attributes that can be added to the container item
|
/// This macro comes with some helper attributes that can be added to the container item
|
||||||
/// in order to provide additional functionality or alter the generated implementations.
|
/// in order to provide additional functionality or alter the generated implementations.
|
||||||
///
|
///
|
||||||
|
/// In addition to those listed, this macro can also use the attributes for [`TypePath`] derives.
|
||||||
|
///
|
||||||
/// ## `#[reflect(Ident)]`
|
/// ## `#[reflect(Ident)]`
|
||||||
///
|
///
|
||||||
/// The `#[reflect(Ident)]` attribute is used to add type data registrations to the `GetTypeRegistration`
|
/// The `#[reflect(Ident)]` attribute is used to add type data registrations to the `GetTypeRegistration`
|
||||||
@ -124,7 +133,7 @@ pub(crate) static REFLECT_VALUE_ATTRIBUTE_NAME: &str = "reflect_value";
|
|||||||
/// which will be used by the reflection serializers to determine whether or not the field is serializable.
|
/// which will be used by the reflection serializers to determine whether or not the field is serializable.
|
||||||
///
|
///
|
||||||
/// [`reflect_trait`]: macro@reflect_trait
|
/// [`reflect_trait`]: macro@reflect_trait
|
||||||
#[proc_macro_derive(Reflect, attributes(reflect, reflect_value))]
|
#[proc_macro_derive(Reflect, attributes(reflect, reflect_value, type_path, type_name))]
|
||||||
pub fn derive_reflect(input: TokenStream) -> TokenStream {
|
pub fn derive_reflect(input: TokenStream) -> TokenStream {
|
||||||
let ast = parse_macro_input!(input as DeriveInput);
|
let ast = parse_macro_input!(input as DeriveInput);
|
||||||
|
|
||||||
@ -188,6 +197,36 @@ pub fn derive_from_reflect(input: TokenStream) -> TokenStream {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Derives the `TypePath` trait, providing a stable alternative to [`std::any::type_name`].
|
||||||
|
///
|
||||||
|
/// # Container Attributes
|
||||||
|
///
|
||||||
|
/// ## `#[type_path = "my_crate::foo"]`
|
||||||
|
///
|
||||||
|
/// Optionally specifies a custom module path to use instead of [`module_path`].
|
||||||
|
///
|
||||||
|
/// This path does not include the final identifier.
|
||||||
|
///
|
||||||
|
/// ## `#[type_name = "RenamedType"]`
|
||||||
|
///
|
||||||
|
/// Optionally specifies a new terminating identifier for `TypePath`.
|
||||||
|
///
|
||||||
|
/// To use this attribute, `#[type_path = "..."]` must also be specified.
|
||||||
|
#[proc_macro_derive(TypePath, attributes(type_path, type_name))]
|
||||||
|
pub fn derive_type_path(input: TokenStream) -> TokenStream {
|
||||||
|
let ast = parse_macro_input!(input as DeriveInput);
|
||||||
|
let derive_data = match ReflectDerive::from_input(&ast) {
|
||||||
|
Ok(data) => data,
|
||||||
|
Err(err) => return err.into_compile_error().into(),
|
||||||
|
};
|
||||||
|
|
||||||
|
impls::impl_type_path(
|
||||||
|
derive_data.meta(),
|
||||||
|
&WhereClauseOptions::type_path_bounds(derive_data.meta()),
|
||||||
|
)
|
||||||
|
.into()
|
||||||
|
}
|
||||||
|
|
||||||
// From https://github.com/randomPoison/type-uuid
|
// From https://github.com/randomPoison/type-uuid
|
||||||
#[proc_macro_derive(TypeUuid, attributes(uuid))]
|
#[proc_macro_derive(TypeUuid, attributes(uuid))]
|
||||||
pub fn derive_type_uuid(input: TokenStream) -> TokenStream {
|
pub fn derive_type_uuid(input: TokenStream) -> TokenStream {
|
||||||
@ -254,30 +293,47 @@ pub fn reflect_trait(args: TokenStream, input: TokenStream) -> TokenStream {
|
|||||||
/// The only reason for this macro's existence is so that `bevy_reflect` can easily implement the reflection traits
|
/// The only reason for this macro's existence is so that `bevy_reflect` can easily implement the reflection traits
|
||||||
/// on primitives and other Rust types internally.
|
/// on primitives and other Rust types internally.
|
||||||
///
|
///
|
||||||
|
/// Since this macro also implements `TypePath`, the type path must be explicit.
|
||||||
|
/// See [`impl_type_path!`] for the exact syntax.
|
||||||
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// Types can be passed with or without registering type data:
|
/// Types can be passed with or without registering type data:
|
||||||
///
|
///
|
||||||
/// ```ignore
|
/// ```ignore
|
||||||
/// impl_reflect_value!(foo);
|
/// impl_reflect_value!(::my_crate::Foo);
|
||||||
/// impl_reflect_value!(bar(Debug, Default, Serialize, Deserialize));
|
/// impl_reflect_value!(::my_crate::Bar(Debug, Default, Serialize, Deserialize));
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// Generic types can also specify their parameters and bounds:
|
/// Generic types can also specify their parameters and bounds:
|
||||||
///
|
///
|
||||||
/// ```ignore
|
/// ```ignore
|
||||||
/// impl_reflect_value!(foo<T1, T2: Baz> where T1: Bar (Default, Serialize, Deserialize));
|
/// impl_reflect_value!(::my_crate::Foo<T1, T2: Baz> where T1: Bar (Default, Serialize, Deserialize));
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Custom type paths can be specified:
|
||||||
|
///
|
||||||
|
/// ```ignore
|
||||||
|
/// impl_reflect_value!((in not_my_crate as NotFoo) Foo(Debug, Default));
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// [deriving `Reflect`]: Reflect
|
/// [deriving `Reflect`]: Reflect
|
||||||
#[proc_macro]
|
#[proc_macro]
|
||||||
pub fn impl_reflect_value(input: TokenStream) -> TokenStream {
|
pub fn impl_reflect_value(input: TokenStream) -> TokenStream {
|
||||||
let def = parse_macro_input!(input as ReflectValueDef);
|
let def = parse_macro_input!(input as ReflectValueDef);
|
||||||
let meta = ReflectMeta::new(
|
|
||||||
&def.type_name,
|
let default_name = &def.type_path.segments.last().unwrap().ident;
|
||||||
&def.generics,
|
let type_path = if def.type_path.leading_colon.is_none() && def.custom_path.is_none() {
|
||||||
def.traits.unwrap_or_default(),
|
ReflectTypePath::Primitive(default_name)
|
||||||
);
|
} else {
|
||||||
|
ReflectTypePath::External {
|
||||||
|
path: &def.type_path,
|
||||||
|
custom_path: def.custom_path.map(|path| path.into_path(default_name)),
|
||||||
|
generics: &def.generics,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let meta = ReflectMeta::new(type_path, def.traits.unwrap_or_default());
|
||||||
|
|
||||||
#[cfg(feature = "documentation")]
|
#[cfg(feature = "documentation")]
|
||||||
let meta = meta.with_docs(documentation::Documentation::from_attributes(&def.attrs));
|
let meta = meta.with_docs(documentation::Documentation::from_attributes(&def.attrs));
|
||||||
@ -294,23 +350,27 @@ pub fn impl_reflect_value(input: TokenStream) -> TokenStream {
|
|||||||
/// which have greater functionality. The type being reflected must be in scope, as you cannot
|
/// which have greater functionality. The type being reflected must be in scope, as you cannot
|
||||||
/// qualify it in the macro as e.g. `bevy::prelude::Vec3`.
|
/// qualify it in the macro as e.g. `bevy::prelude::Vec3`.
|
||||||
///
|
///
|
||||||
|
/// It is necessary to add a `#[type_path = "my_crate::foo"]` attribute to all types.
|
||||||
|
///
|
||||||
/// It may be necessary to add `#[reflect(Default)]` for some types, specifically non-constructible
|
/// It may be necessary to add `#[reflect(Default)]` for some types, specifically non-constructible
|
||||||
/// foreign types. Without `Default` reflected for such types, you will usually get an arcane
|
/// foreign types. Without `Default` reflected for such types, you will usually get an arcane
|
||||||
/// error message and fail to compile. If the type does not implement `Default`, it may not
|
/// error message and fail to compile. If the type does not implement `Default`, it may not
|
||||||
/// be possible to reflect without extending the macro.
|
/// be possible to reflect without extending the macro.
|
||||||
///
|
///
|
||||||
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
/// Implementing `Reflect` for `bevy::prelude::Vec3` as a struct type:
|
/// Implementing `Reflect` for `bevy::prelude::Vec3` as a struct type:
|
||||||
/// ```ignore
|
/// ```ignore
|
||||||
/// use bevy::prelude::Vec3;
|
/// use bevy::prelude::Vec3;
|
||||||
///
|
///
|
||||||
/// impl_reflect_struct!(
|
/// impl_reflect_struct!(
|
||||||
/// #[reflect(PartialEq, Serialize, Deserialize, Default)]
|
/// #[reflect(PartialEq, Serialize, Deserialize, Default)]
|
||||||
/// struct Vec3 {
|
/// #[type_path = "bevy::prelude"]
|
||||||
/// x: f32,
|
/// struct Vec3 {
|
||||||
/// y: f32,
|
/// x: f32,
|
||||||
/// z: f32
|
/// y: f32,
|
||||||
/// }
|
/// z: f32
|
||||||
|
/// }
|
||||||
/// );
|
/// );
|
||||||
/// ```
|
/// ```
|
||||||
#[proc_macro]
|
#[proc_macro]
|
||||||
@ -323,6 +383,15 @@ pub fn impl_reflect_struct(input: TokenStream) -> TokenStream {
|
|||||||
|
|
||||||
match derive_data {
|
match derive_data {
|
||||||
ReflectDerive::Struct(struct_data) => {
|
ReflectDerive::Struct(struct_data) => {
|
||||||
|
if !struct_data.meta().type_path().has_custom_path() {
|
||||||
|
return syn::Error::new(
|
||||||
|
struct_data.meta().type_path().span(),
|
||||||
|
format!("a #[{TYPE_PATH_ATTRIBUTE_NAME} = \"...\"] attribute must be specified when using `impl_reflect_struct`")
|
||||||
|
)
|
||||||
|
.into_compile_error()
|
||||||
|
.into();
|
||||||
|
}
|
||||||
|
|
||||||
let impl_struct: proc_macro2::TokenStream = impls::impl_struct(&struct_data).into();
|
let impl_struct: proc_macro2::TokenStream = impls::impl_struct(&struct_data).into();
|
||||||
let impl_from_struct: proc_macro2::TokenStream =
|
let impl_from_struct: proc_macro2::TokenStream =
|
||||||
from_reflect::impl_struct(&struct_data).into();
|
from_reflect::impl_struct(&struct_data).into();
|
||||||
@ -370,11 +439,84 @@ pub fn impl_reflect_struct(input: TokenStream) -> TokenStream {
|
|||||||
#[proc_macro]
|
#[proc_macro]
|
||||||
pub fn impl_from_reflect_value(input: TokenStream) -> TokenStream {
|
pub fn impl_from_reflect_value(input: TokenStream) -> TokenStream {
|
||||||
let def = parse_macro_input!(input as ReflectValueDef);
|
let def = parse_macro_input!(input as ReflectValueDef);
|
||||||
from_reflect::impl_value(&ReflectMeta::new(
|
|
||||||
&def.type_name,
|
let default_name = &def.type_path.segments.last().unwrap().ident;
|
||||||
&def.generics,
|
let type_path = if def.type_path.leading_colon.is_none()
|
||||||
def.traits.unwrap_or_default(),
|
&& def.custom_path.is_none()
|
||||||
))
|
&& def.generics.params.is_empty()
|
||||||
|
{
|
||||||
|
ReflectTypePath::Primitive(default_name)
|
||||||
|
} else {
|
||||||
|
ReflectTypePath::External {
|
||||||
|
path: &def.type_path,
|
||||||
|
custom_path: def.custom_path.map(|alias| alias.into_path(default_name)),
|
||||||
|
generics: &def.generics,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
from_reflect::impl_value(&ReflectMeta::new(type_path, def.traits.unwrap_or_default()))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A replacement for [deriving `TypePath`] for use on foreign types.
|
||||||
|
///
|
||||||
|
/// Since (unlike the derive) this macro may be invoked in a different module to where the type is defined,
|
||||||
|
/// it requires an 'absolute' path definition.
|
||||||
|
///
|
||||||
|
/// Specifically, a leading `::` denoting a global path must be specified
|
||||||
|
/// or a preceeding `(in my_crate::foo)` to specify the custom path must be used.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// Implementing `TypePath` on a foreign type:
|
||||||
|
/// ```rust,ignore
|
||||||
|
/// impl_type_path!(::foreign_crate::foo::bar::Baz);
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// On a generic type:
|
||||||
|
/// ```rust,ignore
|
||||||
|
/// impl_type_path!(::foreign_crate::Foo<T>);
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// On a primitive (note this will not compile for a non-primitive type):
|
||||||
|
/// ```rust,ignore
|
||||||
|
/// impl_type_path!(bool);
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// With a custom type path:
|
||||||
|
/// ```rust,ignore
|
||||||
|
/// impl_type_path!((in other_crate::foo::bar) Baz);
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// With a custom type path and a custom type name:
|
||||||
|
/// ```rust,ignore
|
||||||
|
/// impl_type_path!((in other_crate::foo as Baz) Bar);
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// [deriving `TypePath`]: TypePath
|
||||||
|
#[proc_macro]
|
||||||
|
pub fn impl_type_path(input: TokenStream) -> TokenStream {
|
||||||
|
let def = parse_macro_input!(input as NamedTypePathDef);
|
||||||
|
|
||||||
|
let type_path = match def {
|
||||||
|
NamedTypePathDef::External {
|
||||||
|
ref path,
|
||||||
|
custom_path,
|
||||||
|
ref generics,
|
||||||
|
} => {
|
||||||
|
let default_name = &path.segments.last().unwrap().ident;
|
||||||
|
|
||||||
|
ReflectTypePath::External {
|
||||||
|
path,
|
||||||
|
custom_path: custom_path.map(|path| path.into_path(default_name)),
|
||||||
|
generics,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NamedTypePathDef::Primtive(ref ident) => ReflectTypePath::Primitive(ident),
|
||||||
|
};
|
||||||
|
|
||||||
|
let meta = ReflectMeta::new(type_path, ReflectTraits::default());
|
||||||
|
|
||||||
|
impls::impl_type_path(&meta, &WhereClauseOptions::type_path_bounds(&meta)).into()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Derives `TypeUuid` for the given type. This is used internally to implement `TypeUuid` on foreign types, such as those in the std. This macro should be used in the format of `<[Generic Params]> [Type (Path)], [Uuid (String Literal)]`.
|
/// Derives `TypeUuid` for the given type. This is used internally to implement `TypeUuid` on foreign types, such as those in the std. This macro should be used in the format of `<[Generic Params]> [Type (Path)], [Uuid (String Literal)]`.
|
||||||
|
|||||||
@ -1,58 +1,59 @@
|
|||||||
use crate::container_attributes::ReflectTraits;
|
use crate::container_attributes::ReflectTraits;
|
||||||
use proc_macro2::Ident;
|
use crate::type_path::CustomPathDef;
|
||||||
use syn::parse::{Parse, ParseStream};
|
use syn::parse::{Parse, ParseStream};
|
||||||
use syn::token::{Paren, Where};
|
use syn::token::Paren;
|
||||||
use syn::{parenthesized, Attribute, Generics};
|
use syn::{parenthesized, Attribute, Generics, Path};
|
||||||
|
|
||||||
/// A struct used to define a simple reflected value type (such as primitives).
|
/// A struct used to define a simple reflected value type (such as primitives).
|
||||||
///
|
///
|
||||||
|
///
|
||||||
|
///
|
||||||
/// This takes the form:
|
/// This takes the form:
|
||||||
///
|
///
|
||||||
/// ```ignore
|
/// ```ignore
|
||||||
/// // Standard
|
/// // Standard
|
||||||
/// foo(TraitA, TraitB)
|
/// ::my_crate::foo::Bar(TraitA, TraitB)
|
||||||
///
|
///
|
||||||
/// // With generics
|
/// // With generics
|
||||||
/// foo<T1: Bar, T2>(TraitA, TraitB)
|
/// ::my_crate::foo::Bar<T1: Bar, T2>(TraitA, TraitB)
|
||||||
///
|
///
|
||||||
/// // With generics and where clause
|
/// // With generics and where clause
|
||||||
/// foo<T1, T2> where T1: Bar (TraitA, TraitB)
|
/// ::my_crate::foo::Bar<T1, T2> where T1: Bar (TraitA, TraitB)
|
||||||
|
///
|
||||||
|
/// // With a custom path (not with impl_from_reflect_value)
|
||||||
|
/// (in my_crate::bar) Bar(TraitA, TraitB)
|
||||||
/// ```
|
/// ```
|
||||||
pub(crate) struct ReflectValueDef {
|
pub(crate) struct ReflectValueDef {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub attrs: Vec<Attribute>,
|
pub attrs: Vec<Attribute>,
|
||||||
pub type_name: Ident,
|
pub type_path: Path,
|
||||||
pub generics: Generics,
|
pub generics: Generics,
|
||||||
pub traits: Option<ReflectTraits>,
|
pub traits: Option<ReflectTraits>,
|
||||||
|
pub custom_path: Option<CustomPathDef>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for ReflectValueDef {
|
impl Parse for ReflectValueDef {
|
||||||
fn parse(input: ParseStream) -> syn::Result<Self> {
|
fn parse(input: ParseStream) -> syn::Result<Self> {
|
||||||
let attrs = input.call(Attribute::parse_outer)?;
|
let attrs = input.call(Attribute::parse_outer)?;
|
||||||
let type_ident = input.parse::<Ident>()?;
|
|
||||||
let generics = input.parse::<Generics>()?;
|
let custom_path = CustomPathDef::parse_parenthesized(input)?;
|
||||||
let mut lookahead = input.lookahead1();
|
|
||||||
let mut where_clause = None;
|
let type_path = Path::parse_mod_style(input)?;
|
||||||
if lookahead.peek(Where) {
|
let mut generics = input.parse::<Generics>()?;
|
||||||
where_clause = Some(input.parse()?);
|
generics.where_clause = input.parse()?;
|
||||||
lookahead = input.lookahead1();
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut traits = None;
|
let mut traits = None;
|
||||||
if lookahead.peek(Paren) {
|
if input.peek(Paren) {
|
||||||
let content;
|
let content;
|
||||||
parenthesized!(content in input);
|
parenthesized!(content in input);
|
||||||
traits = Some(content.parse::<ReflectTraits>()?);
|
traits = Some(content.parse::<ReflectTraits>()?);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(ReflectValueDef {
|
Ok(ReflectValueDef {
|
||||||
attrs,
|
attrs,
|
||||||
type_name: type_ident,
|
type_path,
|
||||||
generics: Generics {
|
generics,
|
||||||
where_clause,
|
|
||||||
..generics
|
|
||||||
},
|
|
||||||
traits,
|
traits,
|
||||||
|
custom_path,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,21 +2,21 @@
|
|||||||
|
|
||||||
use crate::utility::{extend_where_clause, WhereClauseOptions};
|
use crate::utility::{extend_where_clause, WhereClauseOptions};
|
||||||
use bit_set::BitSet;
|
use bit_set::BitSet;
|
||||||
use proc_macro2::Ident;
|
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
use syn::{Generics, Path};
|
|
||||||
|
use crate::derive_data::ReflectMeta;
|
||||||
|
|
||||||
/// Creates the `GetTypeRegistration` impl for the given type data.
|
/// Creates the `GetTypeRegistration` impl for the given type data.
|
||||||
#[allow(clippy::too_many_arguments)]
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub(crate) fn impl_get_type_registration(
|
pub(crate) fn impl_get_type_registration(
|
||||||
type_name: &Ident,
|
meta: &ReflectMeta,
|
||||||
bevy_reflect_path: &Path,
|
|
||||||
registration_data: &[Ident],
|
|
||||||
generics: &Generics,
|
|
||||||
where_clause_options: &WhereClauseOptions,
|
where_clause_options: &WhereClauseOptions,
|
||||||
serialization_denylist: Option<&BitSet<u32>>,
|
serialization_denylist: Option<&BitSet<u32>>,
|
||||||
) -> proc_macro2::TokenStream {
|
) -> proc_macro2::TokenStream {
|
||||||
let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
|
let type_path = meta.type_path();
|
||||||
|
let bevy_reflect_path = meta.bevy_reflect_path();
|
||||||
|
let registration_data = meta.traits().idents();
|
||||||
|
let (impl_generics, ty_generics, where_clause) = type_path.generics().split_for_impl();
|
||||||
let serialization_data = serialization_denylist.map(|denylist| {
|
let serialization_data = serialization_denylist.map(|denylist| {
|
||||||
let denylist = denylist.into_iter();
|
let denylist = denylist.into_iter();
|
||||||
quote! {
|
quote! {
|
||||||
@ -29,12 +29,12 @@ pub(crate) fn impl_get_type_registration(
|
|||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
#[allow(unused_mut)]
|
#[allow(unused_mut)]
|
||||||
impl #impl_generics #bevy_reflect_path::GetTypeRegistration for #type_name #ty_generics #where_reflect_clause {
|
impl #impl_generics #bevy_reflect_path::GetTypeRegistration for #type_path #ty_generics #where_reflect_clause {
|
||||||
fn get_type_registration() -> #bevy_reflect_path::TypeRegistration {
|
fn get_type_registration() -> #bevy_reflect_path::TypeRegistration {
|
||||||
let mut registration = #bevy_reflect_path::TypeRegistration::of::<#type_name #ty_generics>();
|
let mut registration = #bevy_reflect_path::TypeRegistration::of::<Self>();
|
||||||
registration.insert::<#bevy_reflect_path::ReflectFromPtr>(#bevy_reflect_path::FromType::<#type_name #ty_generics>::from_type());
|
registration.insert::<#bevy_reflect_path::ReflectFromPtr>(#bevy_reflect_path::FromType::<Self>::from_type());
|
||||||
#serialization_data
|
#serialization_data
|
||||||
#(registration.insert::<#registration_data>(#bevy_reflect_path::FromType::<#type_name #ty_generics>::from_type());)*
|
#(registration.insert::<#registration_data>(#bevy_reflect_path::FromType::<Self>::from_type());)*
|
||||||
registration
|
registration
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
102
crates/bevy_reflect/bevy_reflect_derive/src/type_path.rs
Normal file
102
crates/bevy_reflect/bevy_reflect_derive/src/type_path.rs
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
use proc_macro2::Ident;
|
||||||
|
use syn::{
|
||||||
|
parenthesized,
|
||||||
|
parse::{Parse, ParseStream},
|
||||||
|
token::Paren,
|
||||||
|
Generics, Path, PathSegment, Token,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub(crate) fn parse_path_no_leading_colon(input: ParseStream) -> syn::Result<Path> {
|
||||||
|
if input.peek(Token![::]) {
|
||||||
|
return Err(input.error("did not expect a leading double colon (`::`)"));
|
||||||
|
}
|
||||||
|
|
||||||
|
let path = Path::parse_mod_style(input)?;
|
||||||
|
|
||||||
|
if path.segments.is_empty() {
|
||||||
|
Err(input.error("expected a path"))
|
||||||
|
} else {
|
||||||
|
Ok(path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// An alias for a `TypePath`.
|
||||||
|
///
|
||||||
|
/// This is the parenthesized part of `(in my_crate::foo as MyType) SomeType`.
|
||||||
|
pub(crate) struct CustomPathDef {
|
||||||
|
path: Path,
|
||||||
|
name: Option<Ident>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CustomPathDef {
|
||||||
|
pub fn into_path(mut self, default_name: &Ident) -> Path {
|
||||||
|
let name = PathSegment::from(self.name.unwrap_or_else(|| default_name.clone()));
|
||||||
|
self.path.segments.push(name);
|
||||||
|
self.path
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parse_parenthesized(input: ParseStream) -> syn::Result<Option<Self>> {
|
||||||
|
if input.peek(Paren) {
|
||||||
|
let path;
|
||||||
|
parenthesized!(path in input);
|
||||||
|
Ok(Some(path.call(Self::parse)?))
|
||||||
|
} else {
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse(input: ParseStream) -> syn::Result<Self> {
|
||||||
|
input.parse::<Token![in]>()?;
|
||||||
|
|
||||||
|
let custom_path = parse_path_no_leading_colon(input)?;
|
||||||
|
|
||||||
|
if !input.peek(Token![as]) {
|
||||||
|
return Ok(Self {
|
||||||
|
path: custom_path,
|
||||||
|
name: None,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
input.parse::<Token![as]>()?;
|
||||||
|
let custom_name: Ident = input.parse()?;
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
path: custom_path,
|
||||||
|
name: Some(custom_name),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) enum NamedTypePathDef {
|
||||||
|
External {
|
||||||
|
path: Path,
|
||||||
|
generics: Generics,
|
||||||
|
custom_path: Option<CustomPathDef>,
|
||||||
|
},
|
||||||
|
Primtive(Ident),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Parse for NamedTypePathDef {
|
||||||
|
fn parse(input: ParseStream) -> syn::Result<Self> {
|
||||||
|
let custom_path = CustomPathDef::parse_parenthesized(input)?;
|
||||||
|
|
||||||
|
let path = Path::parse_mod_style(input)?;
|
||||||
|
let mut generics = input.parse::<Generics>()?;
|
||||||
|
generics.where_clause = input.parse()?;
|
||||||
|
|
||||||
|
if path.leading_colon.is_none() && custom_path.is_none() {
|
||||||
|
if path.segments.len() == 1 {
|
||||||
|
let ident = path.segments.into_iter().next().unwrap().ident;
|
||||||
|
Ok(NamedTypePathDef::Primtive(ident))
|
||||||
|
} else {
|
||||||
|
Err(input.error("non-customized paths must start with a double colon (`::`)"))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Ok(NamedTypePathDef::External {
|
||||||
|
path,
|
||||||
|
generics,
|
||||||
|
custom_path,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,11 +1,11 @@
|
|||||||
//! General-purpose utility functions for internal usage within this crate.
|
//! General-purpose utility functions for internal usage within this crate.
|
||||||
|
|
||||||
use crate::field_attributes::ReflectIgnoreBehavior;
|
use crate::{derive_data::ReflectMeta, field_attributes::ReflectIgnoreBehavior, fq_std::FQOption};
|
||||||
use bevy_macro_utils::BevyManifest;
|
use bevy_macro_utils::BevyManifest;
|
||||||
use bit_set::BitSet;
|
use bit_set::BitSet;
|
||||||
use proc_macro2::{Ident, Span};
|
use proc_macro2::{Ident, Span};
|
||||||
use quote::quote;
|
use quote::{quote, ToTokens};
|
||||||
use syn::{Member, Path, Type, WhereClause};
|
use syn::{spanned::Spanned, LitStr, Member, Path, Type, WhereClause};
|
||||||
|
|
||||||
/// Returns the correct path for `bevy_reflect`.
|
/// Returns the correct path for `bevy_reflect`.
|
||||||
pub(crate) fn get_bevy_reflect_path() -> Path {
|
pub(crate) fn get_bevy_reflect_path() -> Path {
|
||||||
@ -60,6 +60,10 @@ pub(crate) fn ident_or_index(ident: Option<&Ident>, index: usize) -> Member {
|
|||||||
|
|
||||||
/// Options defining how to extend the `where` clause in reflection with any additional bounds needed.
|
/// Options defining how to extend the `where` clause in reflection with any additional bounds needed.
|
||||||
pub(crate) struct WhereClauseOptions {
|
pub(crate) struct WhereClauseOptions {
|
||||||
|
/// Type parameters that need extra trait bounds.
|
||||||
|
pub(crate) parameter_types: Box<[Ident]>,
|
||||||
|
/// Trait bounds to add to the type parameters.
|
||||||
|
pub(crate) parameter_trait_bounds: proc_macro2::TokenStream,
|
||||||
/// Any types that will be reflected and need an extra trait bound
|
/// Any types that will be reflected and need an extra trait bound
|
||||||
pub(crate) active_types: Box<[Type]>,
|
pub(crate) active_types: Box<[Type]>,
|
||||||
/// Trait bounds to add to the active types
|
/// Trait bounds to add to the active types
|
||||||
@ -70,12 +74,31 @@ pub(crate) struct WhereClauseOptions {
|
|||||||
pub(crate) ignored_trait_bounds: proc_macro2::TokenStream,
|
pub(crate) ignored_trait_bounds: proc_macro2::TokenStream,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl WhereClauseOptions {
|
||||||
|
/// Extends a where clause, adding a `TypePath` bound to each type parameter.
|
||||||
|
pub fn type_path_bounds(meta: &ReflectMeta) -> Self {
|
||||||
|
let bevy_reflect_path = meta.bevy_reflect_path();
|
||||||
|
Self {
|
||||||
|
parameter_types: meta
|
||||||
|
.type_path()
|
||||||
|
.generics()
|
||||||
|
.type_params()
|
||||||
|
.map(|ty| ty.ident.clone())
|
||||||
|
.collect(),
|
||||||
|
parameter_trait_bounds: quote! { #bevy_reflect_path::TypePath },
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Default for WhereClauseOptions {
|
impl Default for WhereClauseOptions {
|
||||||
/// By default, don't add any additional bounds to the `where` clause
|
/// By default, don't add any additional bounds to the `where` clause
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
parameter_types: Box::new([]),
|
||||||
active_types: Box::new([]),
|
active_types: Box::new([]),
|
||||||
ignored_types: Box::new([]),
|
ignored_types: Box::new([]),
|
||||||
|
parameter_trait_bounds: quote! {},
|
||||||
active_trait_bounds: quote! {},
|
active_trait_bounds: quote! {},
|
||||||
ignored_trait_bounds: quote! {},
|
ignored_trait_bounds: quote! {},
|
||||||
}
|
}
|
||||||
@ -117,22 +140,26 @@ pub(crate) fn extend_where_clause(
|
|||||||
where_clause: Option<&WhereClause>,
|
where_clause: Option<&WhereClause>,
|
||||||
where_clause_options: &WhereClauseOptions,
|
where_clause_options: &WhereClauseOptions,
|
||||||
) -> proc_macro2::TokenStream {
|
) -> proc_macro2::TokenStream {
|
||||||
|
let parameter_types = &where_clause_options.parameter_types;
|
||||||
let active_types = &where_clause_options.active_types;
|
let active_types = &where_clause_options.active_types;
|
||||||
let ignored_types = &where_clause_options.ignored_types;
|
let ignored_types = &where_clause_options.ignored_types;
|
||||||
|
let parameter_trait_bounds = &where_clause_options.parameter_trait_bounds;
|
||||||
let active_trait_bounds = &where_clause_options.active_trait_bounds;
|
let active_trait_bounds = &where_clause_options.active_trait_bounds;
|
||||||
let ignored_trait_bounds = &where_clause_options.ignored_trait_bounds;
|
let ignored_trait_bounds = &where_clause_options.ignored_trait_bounds;
|
||||||
|
|
||||||
let mut generic_where_clause = if let Some(where_clause) = where_clause {
|
let mut generic_where_clause = if let Some(where_clause) = where_clause {
|
||||||
let predicates = where_clause.predicates.iter();
|
let predicates = where_clause.predicates.iter();
|
||||||
quote! {where #(#predicates,)*}
|
quote! {where #(#predicates,)*}
|
||||||
} else if !(active_types.is_empty() && ignored_types.is_empty()) {
|
} else if !(parameter_types.is_empty() && active_types.is_empty() && ignored_types.is_empty()) {
|
||||||
quote! {where}
|
quote! {where}
|
||||||
} else {
|
} else {
|
||||||
quote! {}
|
quote!()
|
||||||
};
|
};
|
||||||
generic_where_clause.extend(quote! {
|
generic_where_clause.extend(quote! {
|
||||||
#(#active_types: #active_trait_bounds,)*
|
#(#active_types: #active_trait_bounds,)*
|
||||||
#(#ignored_types: #ignored_trait_bounds,)*
|
#(#ignored_types: #ignored_trait_bounds,)*
|
||||||
|
// Leave parameter bounds to the end for more sane error messages.
|
||||||
|
#(#parameter_types: #parameter_trait_bounds,)*
|
||||||
});
|
});
|
||||||
generic_where_clause
|
generic_where_clause
|
||||||
}
|
}
|
||||||
@ -212,3 +239,118 @@ where
|
|||||||
|
|
||||||
bitset
|
bitset
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Turns an `Option<TokenStream>` into a `TokenStream` for an `Option`.
|
||||||
|
pub(crate) fn wrap_in_option(tokens: Option<proc_macro2::TokenStream>) -> proc_macro2::TokenStream {
|
||||||
|
match tokens {
|
||||||
|
Some(tokens) => quote! {
|
||||||
|
#FQOption::Some(#tokens)
|
||||||
|
},
|
||||||
|
None => quote! {
|
||||||
|
#FQOption::None
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Contains tokens representing different kinds of string.
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub(crate) enum StringExpr {
|
||||||
|
/// A string that is valid at compile time.
|
||||||
|
///
|
||||||
|
/// This is either a string literal like `"mystring"`,
|
||||||
|
/// or a string created by a macro like [`module_path`]
|
||||||
|
/// or [`concat`].
|
||||||
|
Const(proc_macro2::TokenStream),
|
||||||
|
/// A [string slice](str) that is borrowed for a `'static` lifetime.
|
||||||
|
Borrowed(proc_macro2::TokenStream),
|
||||||
|
/// An [owned string](String).
|
||||||
|
Owned(proc_macro2::TokenStream),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: ToString + Spanned> From<T> for StringExpr {
|
||||||
|
fn from(value: T) -> Self {
|
||||||
|
Self::from_lit(&LitStr::new(&value.to_string(), value.span()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StringExpr {
|
||||||
|
/// Creates a [constant] [`StringExpr`] from a [`struct@LitStr`].
|
||||||
|
///
|
||||||
|
/// [constant]: StringExpr::Const
|
||||||
|
pub fn from_lit(lit: &LitStr) -> Self {
|
||||||
|
Self::Const(lit.to_token_stream())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a [constant] [`StringExpr`] by interpreting a [string slice][str] as a [`struct@LitStr`].
|
||||||
|
///
|
||||||
|
/// [constant]: StringExpr::Const
|
||||||
|
pub fn from_str(string: &str) -> Self {
|
||||||
|
Self::Const(string.into_token_stream())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns tokens for an [owned string](String).
|
||||||
|
///
|
||||||
|
/// The returned expression will allocate unless the [`StringExpr`] is [already owned].
|
||||||
|
///
|
||||||
|
/// [already owned]: StringExpr::Owned
|
||||||
|
pub fn into_owned(self) -> proc_macro2::TokenStream {
|
||||||
|
match self {
|
||||||
|
Self::Const(tokens) | Self::Borrowed(tokens) => quote! {
|
||||||
|
::std::string::ToString::to_string(#tokens)
|
||||||
|
},
|
||||||
|
Self::Owned(owned) => owned,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns tokens for a statically borrowed [string slice](str).
|
||||||
|
pub fn into_borrowed(self) -> proc_macro2::TokenStream {
|
||||||
|
match self {
|
||||||
|
Self::Const(tokens) | Self::Borrowed(tokens) => tokens,
|
||||||
|
Self::Owned(owned) => quote! {
|
||||||
|
&#owned
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Appends a [`StringExpr`] to another.
|
||||||
|
///
|
||||||
|
/// If both expressions are [`StringExpr::Const`] this will use [`concat`] to merge them.
|
||||||
|
pub fn appended_by(mut self, other: StringExpr) -> Self {
|
||||||
|
if let Self::Const(tokens) = self {
|
||||||
|
if let Self::Const(more) = other {
|
||||||
|
return Self::Const(quote! {
|
||||||
|
::core::concat!(#tokens, #more)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
self = Self::Const(tokens);
|
||||||
|
}
|
||||||
|
|
||||||
|
let owned = self.into_owned();
|
||||||
|
let borrowed = other.into_borrowed();
|
||||||
|
Self::Owned(quote! {
|
||||||
|
#owned + #borrowed
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for StringExpr {
|
||||||
|
fn default() -> Self {
|
||||||
|
StringExpr::from_str("")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromIterator<StringExpr> for StringExpr {
|
||||||
|
fn from_iter<T: IntoIterator<Item = StringExpr>>(iter: T) -> Self {
|
||||||
|
let mut iter = iter.into_iter();
|
||||||
|
match iter.next() {
|
||||||
|
Some(mut expr) => {
|
||||||
|
for next in iter {
|
||||||
|
expr = expr.appended_by(next);
|
||||||
|
}
|
||||||
|
|
||||||
|
expr
|
||||||
|
}
|
||||||
|
None => Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -1,4 +1,9 @@
|
|||||||
use crate::{utility::reflect_hasher, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo};
|
use bevy_reflect_derive::impl_type_path;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
self as bevy_reflect, utility::reflect_hasher, DynamicTypePath, Reflect, ReflectMut,
|
||||||
|
ReflectOwned, ReflectRef, TypeInfo,
|
||||||
|
};
|
||||||
use std::{
|
use std::{
|
||||||
any::{Any, TypeId},
|
any::{Any, TypeId},
|
||||||
fmt::Debug,
|
fmt::Debug,
|
||||||
@ -221,6 +226,11 @@ impl Reflect for DynamicArray {
|
|||||||
self.represented_type
|
self.represented_type
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn get_type_path(&self) -> &dyn DynamicTypePath {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn into_any(self: Box<Self>) -> Box<dyn Any> {
|
fn into_any(self: Box<Self>) -> Box<dyn Any> {
|
||||||
self
|
self
|
||||||
@ -335,6 +345,7 @@ impl Array for DynamicArray {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl_type_path!((in bevy_reflect) DynamicArray);
|
||||||
/// An iterator over an [`Array`].
|
/// An iterator over an [`Array`].
|
||||||
pub struct ArrayIter<'a> {
|
pub struct ArrayIter<'a> {
|
||||||
array: &'a dyn Array,
|
array: &'a dyn Array,
|
||||||
|
|||||||
@ -1,6 +1,9 @@
|
|||||||
|
use bevy_reflect_derive::impl_type_path;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
enum_debug, enum_hash, enum_partial_eq, DynamicStruct, DynamicTuple, Enum, Reflect, ReflectMut,
|
self as bevy_reflect, enum_debug, enum_hash, enum_partial_eq, DynamicStruct, DynamicTuple,
|
||||||
ReflectOwned, ReflectRef, Struct, Tuple, TypeInfo, VariantFieldIter, VariantType,
|
DynamicTypePath, Enum, Reflect, ReflectMut, ReflectOwned, ReflectRef, Struct, Tuple, TypeInfo,
|
||||||
|
VariantFieldIter, VariantType,
|
||||||
};
|
};
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::fmt::Formatter;
|
use std::fmt::Formatter;
|
||||||
@ -297,6 +300,11 @@ impl Reflect for DynamicEnum {
|
|||||||
self.represented_type
|
self.represented_type
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn get_type_path(&self) -> &dyn DynamicTypePath {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn into_any(self: Box<Self>) -> Box<dyn Any> {
|
fn into_any(self: Box<Self>) -> Box<dyn Any> {
|
||||||
self
|
self
|
||||||
@ -420,3 +428,5 @@ impl Reflect for DynamicEnum {
|
|||||||
write!(f, ")")
|
write!(f, ")")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl_type_path!((in bevy_reflect) DynamicEnum);
|
||||||
|
|||||||
@ -6,6 +6,7 @@ use glam::*;
|
|||||||
|
|
||||||
impl_reflect_struct!(
|
impl_reflect_struct!(
|
||||||
#[reflect(Debug, Hash, PartialEq, Default)]
|
#[reflect(Debug, Hash, PartialEq, Default)]
|
||||||
|
#[type_path = "glam"]
|
||||||
struct IVec2 {
|
struct IVec2 {
|
||||||
x: i32,
|
x: i32,
|
||||||
y: i32,
|
y: i32,
|
||||||
@ -13,6 +14,7 @@ impl_reflect_struct!(
|
|||||||
);
|
);
|
||||||
impl_reflect_struct!(
|
impl_reflect_struct!(
|
||||||
#[reflect(Debug, Hash, PartialEq, Default)]
|
#[reflect(Debug, Hash, PartialEq, Default)]
|
||||||
|
#[type_path = "glam"]
|
||||||
struct IVec3 {
|
struct IVec3 {
|
||||||
x: i32,
|
x: i32,
|
||||||
y: i32,
|
y: i32,
|
||||||
@ -21,6 +23,7 @@ impl_reflect_struct!(
|
|||||||
);
|
);
|
||||||
impl_reflect_struct!(
|
impl_reflect_struct!(
|
||||||
#[reflect(Debug, Hash, PartialEq, Default)]
|
#[reflect(Debug, Hash, PartialEq, Default)]
|
||||||
|
#[type_path = "glam"]
|
||||||
struct IVec4 {
|
struct IVec4 {
|
||||||
x: i32,
|
x: i32,
|
||||||
y: i32,
|
y: i32,
|
||||||
@ -31,6 +34,7 @@ impl_reflect_struct!(
|
|||||||
|
|
||||||
impl_reflect_struct!(
|
impl_reflect_struct!(
|
||||||
#[reflect(Debug, Hash, PartialEq, Default)]
|
#[reflect(Debug, Hash, PartialEq, Default)]
|
||||||
|
#[type_path = "glam"]
|
||||||
struct UVec2 {
|
struct UVec2 {
|
||||||
x: u32,
|
x: u32,
|
||||||
y: u32,
|
y: u32,
|
||||||
@ -38,6 +42,7 @@ impl_reflect_struct!(
|
|||||||
);
|
);
|
||||||
impl_reflect_struct!(
|
impl_reflect_struct!(
|
||||||
#[reflect(Debug, Hash, PartialEq, Default)]
|
#[reflect(Debug, Hash, PartialEq, Default)]
|
||||||
|
#[type_path = "glam"]
|
||||||
struct UVec3 {
|
struct UVec3 {
|
||||||
x: u32,
|
x: u32,
|
||||||
y: u32,
|
y: u32,
|
||||||
@ -46,6 +51,7 @@ impl_reflect_struct!(
|
|||||||
);
|
);
|
||||||
impl_reflect_struct!(
|
impl_reflect_struct!(
|
||||||
#[reflect(Debug, Hash, PartialEq, Default)]
|
#[reflect(Debug, Hash, PartialEq, Default)]
|
||||||
|
#[type_path = "glam"]
|
||||||
struct UVec4 {
|
struct UVec4 {
|
||||||
x: u32,
|
x: u32,
|
||||||
y: u32,
|
y: u32,
|
||||||
@ -53,9 +59,9 @@ impl_reflect_struct!(
|
|||||||
w: u32,
|
w: u32,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
impl_reflect_struct!(
|
impl_reflect_struct!(
|
||||||
#[reflect(Debug, PartialEq, Default)]
|
#[reflect(Debug, PartialEq, Default)]
|
||||||
|
#[type_path = "glam"]
|
||||||
struct Vec2 {
|
struct Vec2 {
|
||||||
x: f32,
|
x: f32,
|
||||||
y: f32,
|
y: f32,
|
||||||
@ -63,6 +69,7 @@ impl_reflect_struct!(
|
|||||||
);
|
);
|
||||||
impl_reflect_struct!(
|
impl_reflect_struct!(
|
||||||
#[reflect(Debug, PartialEq, Default)]
|
#[reflect(Debug, PartialEq, Default)]
|
||||||
|
#[type_path = "glam"]
|
||||||
struct Vec3 {
|
struct Vec3 {
|
||||||
x: f32,
|
x: f32,
|
||||||
y: f32,
|
y: f32,
|
||||||
@ -71,6 +78,7 @@ impl_reflect_struct!(
|
|||||||
);
|
);
|
||||||
impl_reflect_struct!(
|
impl_reflect_struct!(
|
||||||
#[reflect(Debug, PartialEq, Default)]
|
#[reflect(Debug, PartialEq, Default)]
|
||||||
|
#[type_path = "glam"]
|
||||||
struct Vec3A {
|
struct Vec3A {
|
||||||
x: f32,
|
x: f32,
|
||||||
y: f32,
|
y: f32,
|
||||||
@ -79,6 +87,7 @@ impl_reflect_struct!(
|
|||||||
);
|
);
|
||||||
impl_reflect_struct!(
|
impl_reflect_struct!(
|
||||||
#[reflect(Debug, PartialEq, Default)]
|
#[reflect(Debug, PartialEq, Default)]
|
||||||
|
#[type_path = "glam"]
|
||||||
struct Vec4 {
|
struct Vec4 {
|
||||||
x: f32,
|
x: f32,
|
||||||
y: f32,
|
y: f32,
|
||||||
@ -89,6 +98,7 @@ impl_reflect_struct!(
|
|||||||
|
|
||||||
impl_reflect_struct!(
|
impl_reflect_struct!(
|
||||||
#[reflect(Debug, PartialEq, Default)]
|
#[reflect(Debug, PartialEq, Default)]
|
||||||
|
#[type_path = "glam"]
|
||||||
struct BVec2 {
|
struct BVec2 {
|
||||||
x: bool,
|
x: bool,
|
||||||
y: bool,
|
y: bool,
|
||||||
@ -96,6 +106,7 @@ impl_reflect_struct!(
|
|||||||
);
|
);
|
||||||
impl_reflect_struct!(
|
impl_reflect_struct!(
|
||||||
#[reflect(Debug, PartialEq, Default)]
|
#[reflect(Debug, PartialEq, Default)]
|
||||||
|
#[type_path = "glam"]
|
||||||
struct BVec3 {
|
struct BVec3 {
|
||||||
x: bool,
|
x: bool,
|
||||||
y: bool,
|
y: bool,
|
||||||
@ -104,6 +115,7 @@ impl_reflect_struct!(
|
|||||||
);
|
);
|
||||||
impl_reflect_struct!(
|
impl_reflect_struct!(
|
||||||
#[reflect(Debug, PartialEq, Default)]
|
#[reflect(Debug, PartialEq, Default)]
|
||||||
|
#[type_path = "glam"]
|
||||||
struct BVec4 {
|
struct BVec4 {
|
||||||
x: bool,
|
x: bool,
|
||||||
y: bool,
|
y: bool,
|
||||||
@ -114,6 +126,7 @@ impl_reflect_struct!(
|
|||||||
|
|
||||||
impl_reflect_struct!(
|
impl_reflect_struct!(
|
||||||
#[reflect(Debug, PartialEq, Default)]
|
#[reflect(Debug, PartialEq, Default)]
|
||||||
|
#[type_path = "glam"]
|
||||||
struct DVec2 {
|
struct DVec2 {
|
||||||
x: f64,
|
x: f64,
|
||||||
y: f64,
|
y: f64,
|
||||||
@ -121,6 +134,7 @@ impl_reflect_struct!(
|
|||||||
);
|
);
|
||||||
impl_reflect_struct!(
|
impl_reflect_struct!(
|
||||||
#[reflect(Debug, PartialEq, Default)]
|
#[reflect(Debug, PartialEq, Default)]
|
||||||
|
#[type_path = "glam"]
|
||||||
struct DVec3 {
|
struct DVec3 {
|
||||||
x: f64,
|
x: f64,
|
||||||
y: f64,
|
y: f64,
|
||||||
@ -129,6 +143,7 @@ impl_reflect_struct!(
|
|||||||
);
|
);
|
||||||
impl_reflect_struct!(
|
impl_reflect_struct!(
|
||||||
#[reflect(Debug, PartialEq, Default)]
|
#[reflect(Debug, PartialEq, Default)]
|
||||||
|
#[type_path = "glam"]
|
||||||
struct DVec4 {
|
struct DVec4 {
|
||||||
x: f64,
|
x: f64,
|
||||||
y: f64,
|
y: f64,
|
||||||
@ -139,6 +154,7 @@ impl_reflect_struct!(
|
|||||||
|
|
||||||
impl_reflect_struct!(
|
impl_reflect_struct!(
|
||||||
#[reflect(Debug, PartialEq, Default)]
|
#[reflect(Debug, PartialEq, Default)]
|
||||||
|
#[type_path = "glam"]
|
||||||
struct Mat2 {
|
struct Mat2 {
|
||||||
x_axis: Vec2,
|
x_axis: Vec2,
|
||||||
y_axis: Vec2,
|
y_axis: Vec2,
|
||||||
@ -146,6 +162,7 @@ impl_reflect_struct!(
|
|||||||
);
|
);
|
||||||
impl_reflect_struct!(
|
impl_reflect_struct!(
|
||||||
#[reflect(Debug, PartialEq, Default)]
|
#[reflect(Debug, PartialEq, Default)]
|
||||||
|
#[type_path = "glam"]
|
||||||
struct Mat3 {
|
struct Mat3 {
|
||||||
x_axis: Vec3,
|
x_axis: Vec3,
|
||||||
y_axis: Vec3,
|
y_axis: Vec3,
|
||||||
@ -154,6 +171,7 @@ impl_reflect_struct!(
|
|||||||
);
|
);
|
||||||
impl_reflect_struct!(
|
impl_reflect_struct!(
|
||||||
#[reflect(Debug, PartialEq, Default)]
|
#[reflect(Debug, PartialEq, Default)]
|
||||||
|
#[type_path = "glam"]
|
||||||
struct Mat3A {
|
struct Mat3A {
|
||||||
x_axis: Vec3A,
|
x_axis: Vec3A,
|
||||||
y_axis: Vec3A,
|
y_axis: Vec3A,
|
||||||
@ -162,6 +180,7 @@ impl_reflect_struct!(
|
|||||||
);
|
);
|
||||||
impl_reflect_struct!(
|
impl_reflect_struct!(
|
||||||
#[reflect(Debug, PartialEq, Default)]
|
#[reflect(Debug, PartialEq, Default)]
|
||||||
|
#[type_path = "glam"]
|
||||||
struct Mat4 {
|
struct Mat4 {
|
||||||
x_axis: Vec4,
|
x_axis: Vec4,
|
||||||
y_axis: Vec4,
|
y_axis: Vec4,
|
||||||
@ -172,6 +191,7 @@ impl_reflect_struct!(
|
|||||||
|
|
||||||
impl_reflect_struct!(
|
impl_reflect_struct!(
|
||||||
#[reflect(Debug, PartialEq, Default)]
|
#[reflect(Debug, PartialEq, Default)]
|
||||||
|
#[type_path = "glam"]
|
||||||
struct DMat2 {
|
struct DMat2 {
|
||||||
x_axis: DVec2,
|
x_axis: DVec2,
|
||||||
y_axis: DVec2,
|
y_axis: DVec2,
|
||||||
@ -179,6 +199,7 @@ impl_reflect_struct!(
|
|||||||
);
|
);
|
||||||
impl_reflect_struct!(
|
impl_reflect_struct!(
|
||||||
#[reflect(Debug, PartialEq, Default)]
|
#[reflect(Debug, PartialEq, Default)]
|
||||||
|
#[type_path = "glam"]
|
||||||
struct DMat3 {
|
struct DMat3 {
|
||||||
x_axis: DVec3,
|
x_axis: DVec3,
|
||||||
y_axis: DVec3,
|
y_axis: DVec3,
|
||||||
@ -187,6 +208,7 @@ impl_reflect_struct!(
|
|||||||
);
|
);
|
||||||
impl_reflect_struct!(
|
impl_reflect_struct!(
|
||||||
#[reflect(Debug, PartialEq, Default)]
|
#[reflect(Debug, PartialEq, Default)]
|
||||||
|
#[type_path = "glam"]
|
||||||
struct DMat4 {
|
struct DMat4 {
|
||||||
x_axis: DVec4,
|
x_axis: DVec4,
|
||||||
y_axis: DVec4,
|
y_axis: DVec4,
|
||||||
@ -197,6 +219,7 @@ impl_reflect_struct!(
|
|||||||
|
|
||||||
impl_reflect_struct!(
|
impl_reflect_struct!(
|
||||||
#[reflect(Debug, PartialEq, Default)]
|
#[reflect(Debug, PartialEq, Default)]
|
||||||
|
#[type_path = "glam"]
|
||||||
struct Affine2 {
|
struct Affine2 {
|
||||||
matrix2: Mat2,
|
matrix2: Mat2,
|
||||||
translation: Vec2,
|
translation: Vec2,
|
||||||
@ -204,6 +227,7 @@ impl_reflect_struct!(
|
|||||||
);
|
);
|
||||||
impl_reflect_struct!(
|
impl_reflect_struct!(
|
||||||
#[reflect(Debug, PartialEq, Default)]
|
#[reflect(Debug, PartialEq, Default)]
|
||||||
|
#[type_path = "glam"]
|
||||||
struct Affine3A {
|
struct Affine3A {
|
||||||
matrix3: Mat3A,
|
matrix3: Mat3A,
|
||||||
translation: Vec3A,
|
translation: Vec3A,
|
||||||
@ -212,6 +236,7 @@ impl_reflect_struct!(
|
|||||||
|
|
||||||
impl_reflect_struct!(
|
impl_reflect_struct!(
|
||||||
#[reflect(Debug, PartialEq, Default)]
|
#[reflect(Debug, PartialEq, Default)]
|
||||||
|
#[type_path = "glam"]
|
||||||
struct DAffine2 {
|
struct DAffine2 {
|
||||||
matrix2: DMat2,
|
matrix2: DMat2,
|
||||||
translation: DVec2,
|
translation: DVec2,
|
||||||
@ -219,6 +244,7 @@ impl_reflect_struct!(
|
|||||||
);
|
);
|
||||||
impl_reflect_struct!(
|
impl_reflect_struct!(
|
||||||
#[reflect(Debug, PartialEq, Default)]
|
#[reflect(Debug, PartialEq, Default)]
|
||||||
|
#[type_path = "glam"]
|
||||||
struct DAffine3 {
|
struct DAffine3 {
|
||||||
matrix3: DMat3,
|
matrix3: DMat3,
|
||||||
translation: DVec3,
|
translation: DVec3,
|
||||||
@ -229,12 +255,24 @@ impl_reflect_struct!(
|
|||||||
// mechanisms for read-only fields. I doubt those mechanisms would be added,
|
// mechanisms for read-only fields. I doubt those mechanisms would be added,
|
||||||
// so for now quaternions will remain as values. They are represented identically
|
// so for now quaternions will remain as values. They are represented identically
|
||||||
// to Vec4 and DVec4, so you may use those instead and convert between.
|
// to Vec4 and DVec4, so you may use those instead and convert between.
|
||||||
impl_reflect_value!(Quat(Debug, PartialEq, Serialize, Deserialize, Default));
|
impl_reflect_value!(::glam::Quat(
|
||||||
impl_reflect_value!(DQuat(Debug, PartialEq, Serialize, Deserialize, Default));
|
Debug,
|
||||||
|
PartialEq,
|
||||||
|
Serialize,
|
||||||
|
Deserialize,
|
||||||
|
Default
|
||||||
|
));
|
||||||
|
impl_reflect_value!(::glam::DQuat(
|
||||||
|
Debug,
|
||||||
|
PartialEq,
|
||||||
|
Serialize,
|
||||||
|
Deserialize,
|
||||||
|
Default
|
||||||
|
));
|
||||||
|
|
||||||
impl_from_reflect_value!(Quat);
|
impl_from_reflect_value!(Quat);
|
||||||
impl_from_reflect_value!(DQuat);
|
impl_from_reflect_value!(DQuat);
|
||||||
|
|
||||||
impl_reflect_value!(EulerRot(Debug, Default));
|
impl_reflect_value!(::glam::EulerRot(Debug, Default));
|
||||||
impl_reflect_value!(BVec3A(Debug, Default));
|
impl_reflect_value!(::glam::BVec3A(Debug, Default));
|
||||||
impl_reflect_value!(BVec4A(Debug, Default));
|
impl_reflect_value!(::glam::BVec4A(Debug, Default));
|
||||||
|
|||||||
@ -6,6 +6,7 @@ use bevy_reflect_derive::impl_reflect_struct;
|
|||||||
|
|
||||||
impl_reflect_struct!(
|
impl_reflect_struct!(
|
||||||
#[reflect(Debug, PartialEq, Serialize, Deserialize, Default)]
|
#[reflect(Debug, PartialEq, Serialize, Deserialize, Default)]
|
||||||
|
#[type_path = "bevy_math"]
|
||||||
struct Rect {
|
struct Rect {
|
||||||
min: Vec2,
|
min: Vec2,
|
||||||
max: Vec2,
|
max: Vec2,
|
||||||
|
|||||||
@ -1,13 +1,15 @@
|
|||||||
|
use bevy_reflect_derive::impl_type_path;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
|
|
||||||
use crate::utility::GenericTypeInfoCell;
|
use crate::utility::GenericTypeInfoCell;
|
||||||
use crate::{
|
use crate::{
|
||||||
FromReflect, FromType, GetTypeRegistration, List, ListInfo, ListIter, Reflect, ReflectFromPtr,
|
self as bevy_reflect, DynamicTypePath, FromReflect, FromType, GetTypeRegistration, List,
|
||||||
ReflectMut, ReflectOwned, ReflectRef, TypeInfo, TypeRegistration, Typed,
|
ListInfo, ListIter, Reflect, ReflectFromPtr, ReflectMut, ReflectOwned, ReflectRef, TypeInfo,
|
||||||
|
TypePath, TypeRegistration, Typed,
|
||||||
};
|
};
|
||||||
|
|
||||||
impl<T: smallvec::Array + Send + Sync + 'static> List for SmallVec<T>
|
impl<T: smallvec::Array + TypePath + Send + Sync> List for SmallVec<T>
|
||||||
where
|
where
|
||||||
T::Item: FromReflect,
|
T::Item: FromReflect,
|
||||||
{
|
{
|
||||||
@ -74,7 +76,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: smallvec::Array + Send + Sync + 'static> Reflect for SmallVec<T>
|
impl<T: smallvec::Array + TypePath + Send + Sync> Reflect for SmallVec<T>
|
||||||
where
|
where
|
||||||
T::Item: FromReflect,
|
T::Item: FromReflect,
|
||||||
{
|
{
|
||||||
@ -86,6 +88,11 @@ where
|
|||||||
Some(<Self as Typed>::type_info())
|
Some(<Self as Typed>::type_info())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn get_type_path(&self) -> &dyn DynamicTypePath {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
fn into_any(self: Box<Self>) -> Box<dyn Any> {
|
fn into_any(self: Box<Self>) -> Box<dyn Any> {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -140,7 +147,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: smallvec::Array + Send + Sync + 'static> Typed for SmallVec<T>
|
impl<T: smallvec::Array + TypePath + Send + Sync + 'static> Typed for SmallVec<T>
|
||||||
where
|
where
|
||||||
T::Item: FromReflect,
|
T::Item: FromReflect,
|
||||||
{
|
{
|
||||||
@ -150,7 +157,9 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: smallvec::Array + Send + Sync + 'static> FromReflect for SmallVec<T>
|
impl_type_path!(::smallvec::SmallVec<T: smallvec::Array + TypePath + Send + Sync>);
|
||||||
|
|
||||||
|
impl<T: smallvec::Array + TypePath + Send + Sync> FromReflect for SmallVec<T>
|
||||||
where
|
where
|
||||||
T::Item: FromReflect,
|
T::Item: FromReflect,
|
||||||
{
|
{
|
||||||
@ -167,7 +176,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: smallvec::Array + Send + Sync + 'static> GetTypeRegistration for SmallVec<T>
|
impl<T: smallvec::Array + TypePath + Send + Sync> GetTypeRegistration for SmallVec<T>
|
||||||
where
|
where
|
||||||
T::Item: FromReflect,
|
T::Item: FromReflect,
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,14 +1,16 @@
|
|||||||
use crate::std_traits::ReflectDefault;
|
use crate::std_traits::ReflectDefault;
|
||||||
use crate::{self as bevy_reflect, ReflectFromPtr, ReflectFromReflect, ReflectOwned};
|
use crate::{self as bevy_reflect, ReflectFromPtr, ReflectFromReflect, ReflectOwned};
|
||||||
use crate::{
|
use crate::{
|
||||||
map_apply, map_partial_eq, Array, ArrayInfo, ArrayIter, DynamicEnum, DynamicMap, Enum,
|
impl_type_path, map_apply, map_partial_eq, Array, ArrayInfo, ArrayIter, DynamicEnum,
|
||||||
EnumInfo, FromReflect, FromType, GetTypeRegistration, List, ListInfo, Map, MapInfo, MapIter,
|
DynamicMap, DynamicTypePath, Enum, EnumInfo, FromReflect, FromType, GetTypeRegistration, List,
|
||||||
Reflect, ReflectDeserialize, ReflectMut, ReflectRef, ReflectSerialize, TupleVariantInfo,
|
ListInfo, ListIter, Map, MapInfo, MapIter, Reflect, ReflectDeserialize, ReflectMut, ReflectRef,
|
||||||
TypeInfo, TypeRegistration, Typed, UnitVariantInfo, UnnamedField, ValueInfo, VariantFieldIter,
|
ReflectSerialize, TupleVariantInfo, TypeInfo, TypePath, TypeRegistration, Typed,
|
||||||
VariantInfo, VariantType,
|
UnitVariantInfo, UnnamedField, ValueInfo, VariantFieldIter, VariantInfo, VariantType,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::utility::{reflect_hasher, GenericTypeInfoCell, NonGenericTypeInfoCell};
|
use crate::utility::{
|
||||||
|
reflect_hasher, GenericTypeInfoCell, GenericTypePathCell, NonGenericTypeInfoCell,
|
||||||
|
};
|
||||||
use bevy_reflect_derive::{impl_from_reflect_value, impl_reflect_value};
|
use bevy_reflect_derive::{impl_from_reflect_value, impl_reflect_value};
|
||||||
use bevy_utils::HashSet;
|
use bevy_utils::HashSet;
|
||||||
use bevy_utils::{Duration, Instant};
|
use bevy_utils::{Duration, Instant};
|
||||||
@ -93,7 +95,7 @@ impl_reflect_value!(String(
|
|||||||
Deserialize,
|
Deserialize,
|
||||||
Default
|
Default
|
||||||
));
|
));
|
||||||
impl_reflect_value!(PathBuf(
|
impl_reflect_value!(::std::path::PathBuf(
|
||||||
Debug,
|
Debug,
|
||||||
Hash,
|
Hash,
|
||||||
PartialEq,
|
PartialEq,
|
||||||
@ -101,15 +103,18 @@ impl_reflect_value!(PathBuf(
|
|||||||
Deserialize,
|
Deserialize,
|
||||||
Default
|
Default
|
||||||
));
|
));
|
||||||
impl_reflect_value!(Result<T: Clone + Reflect + 'static, E: Clone + Reflect + 'static>());
|
impl_reflect_value!(
|
||||||
impl_reflect_value!(HashSet<T: Hash + Eq + Clone + Send + Sync + 'static>());
|
::core::result::Result < T: Clone + Reflect + TypePath,
|
||||||
impl_reflect_value!(Range<T: Clone + Send + Sync + 'static>());
|
E: Clone + Reflect + TypePath > ()
|
||||||
impl_reflect_value!(RangeInclusive<T: Clone + Send + Sync + 'static>());
|
);
|
||||||
impl_reflect_value!(RangeFrom<T: Clone + Send + Sync + 'static>());
|
impl_reflect_value!(::bevy_utils::HashSet<T: Hash + Eq + Clone + Send + Sync>());
|
||||||
impl_reflect_value!(RangeTo<T: Clone + Send + Sync + 'static>());
|
impl_reflect_value!(::core::ops::Range<T: Clone + Send + Sync>());
|
||||||
impl_reflect_value!(RangeToInclusive<T: Clone + Send + Sync + 'static>());
|
impl_reflect_value!(::core::ops::RangeInclusive<T: Clone + Send + Sync>());
|
||||||
impl_reflect_value!(RangeFull());
|
impl_reflect_value!(::core::ops::RangeFrom<T: Clone + Send + Sync>());
|
||||||
impl_reflect_value!(Duration(
|
impl_reflect_value!(::core::ops::RangeTo<T: Clone + Send + Sync>());
|
||||||
|
impl_reflect_value!(::core::ops::RangeToInclusive<T: Clone + Send + Sync>());
|
||||||
|
impl_reflect_value!(::core::ops::RangeFull());
|
||||||
|
impl_reflect_value!(::bevy_utils::Duration(
|
||||||
Debug,
|
Debug,
|
||||||
Hash,
|
Hash,
|
||||||
PartialEq,
|
PartialEq,
|
||||||
@ -117,26 +122,104 @@ impl_reflect_value!(Duration(
|
|||||||
Deserialize,
|
Deserialize,
|
||||||
Default
|
Default
|
||||||
));
|
));
|
||||||
impl_reflect_value!(Instant(Debug, Hash, PartialEq));
|
impl_reflect_value!(::bevy_utils::Instant(Debug, Hash, PartialEq));
|
||||||
impl_reflect_value!(NonZeroI128(Debug, Hash, PartialEq, Serialize, Deserialize));
|
impl_reflect_value!(::core::num::NonZeroI128(
|
||||||
impl_reflect_value!(NonZeroU128(Debug, Hash, PartialEq, Serialize, Deserialize));
|
Debug,
|
||||||
impl_reflect_value!(NonZeroIsize(Debug, Hash, PartialEq, Serialize, Deserialize));
|
Hash,
|
||||||
impl_reflect_value!(NonZeroUsize(Debug, Hash, PartialEq, Serialize, Deserialize));
|
PartialEq,
|
||||||
impl_reflect_value!(NonZeroI64(Debug, Hash, PartialEq, Serialize, Deserialize));
|
Serialize,
|
||||||
impl_reflect_value!(NonZeroU64(Debug, Hash, PartialEq, Serialize, Deserialize));
|
Deserialize
|
||||||
impl_reflect_value!(NonZeroU32(Debug, Hash, PartialEq, Serialize, Deserialize));
|
));
|
||||||
impl_reflect_value!(NonZeroI32(Debug, Hash, PartialEq, Serialize, Deserialize));
|
impl_reflect_value!(::core::num::NonZeroU128(
|
||||||
impl_reflect_value!(NonZeroI16(Debug, Hash, PartialEq, Serialize, Deserialize));
|
Debug,
|
||||||
impl_reflect_value!(NonZeroU16(Debug, Hash, PartialEq, Serialize, Deserialize));
|
Hash,
|
||||||
impl_reflect_value!(NonZeroU8(Debug, Hash, PartialEq, Serialize, Deserialize));
|
PartialEq,
|
||||||
impl_reflect_value!(NonZeroI8(Debug, Hash, PartialEq, Serialize, Deserialize));
|
Serialize,
|
||||||
|
Deserialize
|
||||||
|
));
|
||||||
|
impl_reflect_value!(::core::num::NonZeroIsize(
|
||||||
|
Debug,
|
||||||
|
Hash,
|
||||||
|
PartialEq,
|
||||||
|
Serialize,
|
||||||
|
Deserialize
|
||||||
|
));
|
||||||
|
impl_reflect_value!(::core::num::NonZeroUsize(
|
||||||
|
Debug,
|
||||||
|
Hash,
|
||||||
|
PartialEq,
|
||||||
|
Serialize,
|
||||||
|
Deserialize
|
||||||
|
));
|
||||||
|
impl_reflect_value!(::core::num::NonZeroI64(
|
||||||
|
Debug,
|
||||||
|
Hash,
|
||||||
|
PartialEq,
|
||||||
|
Serialize,
|
||||||
|
Deserialize
|
||||||
|
));
|
||||||
|
impl_reflect_value!(::core::num::NonZeroU64(
|
||||||
|
Debug,
|
||||||
|
Hash,
|
||||||
|
PartialEq,
|
||||||
|
Serialize,
|
||||||
|
Deserialize
|
||||||
|
));
|
||||||
|
impl_reflect_value!(::core::num::NonZeroU32(
|
||||||
|
Debug,
|
||||||
|
Hash,
|
||||||
|
PartialEq,
|
||||||
|
Serialize,
|
||||||
|
Deserialize
|
||||||
|
));
|
||||||
|
impl_reflect_value!(::core::num::NonZeroI32(
|
||||||
|
Debug,
|
||||||
|
Hash,
|
||||||
|
PartialEq,
|
||||||
|
Serialize,
|
||||||
|
Deserialize
|
||||||
|
));
|
||||||
|
impl_reflect_value!(::core::num::NonZeroI16(
|
||||||
|
Debug,
|
||||||
|
Hash,
|
||||||
|
PartialEq,
|
||||||
|
Serialize,
|
||||||
|
Deserialize
|
||||||
|
));
|
||||||
|
impl_reflect_value!(::core::num::NonZeroU16(
|
||||||
|
Debug,
|
||||||
|
Hash,
|
||||||
|
PartialEq,
|
||||||
|
Serialize,
|
||||||
|
Deserialize
|
||||||
|
));
|
||||||
|
impl_reflect_value!(::core::num::NonZeroU8(
|
||||||
|
Debug,
|
||||||
|
Hash,
|
||||||
|
PartialEq,
|
||||||
|
Serialize,
|
||||||
|
Deserialize
|
||||||
|
));
|
||||||
|
impl_reflect_value!(::core::num::NonZeroI8(
|
||||||
|
Debug,
|
||||||
|
Hash,
|
||||||
|
PartialEq,
|
||||||
|
Serialize,
|
||||||
|
Deserialize
|
||||||
|
));
|
||||||
|
|
||||||
// `Serialize` and `Deserialize` only for platforms supported by serde:
|
// `Serialize` and `Deserialize` only for platforms supported by serde:
|
||||||
// https://github.com/serde-rs/serde/blob/3ffb86fc70efd3d329519e2dddfa306cc04f167c/serde/src/de/impls.rs#L1732
|
// https://github.com/serde-rs/serde/blob/3ffb86fc70efd3d329519e2dddfa306cc04f167c/serde/src/de/impls.rs#L1732
|
||||||
#[cfg(any(unix, windows))]
|
#[cfg(any(unix, windows))]
|
||||||
impl_reflect_value!(OsString(Debug, Hash, PartialEq, Serialize, Deserialize));
|
impl_reflect_value!(::std::ffi::OsString(
|
||||||
|
Debug,
|
||||||
|
Hash,
|
||||||
|
PartialEq,
|
||||||
|
Serialize,
|
||||||
|
Deserialize
|
||||||
|
));
|
||||||
#[cfg(not(any(unix, windows)))]
|
#[cfg(not(any(unix, windows)))]
|
||||||
impl_reflect_value!(OsString(Debug, Hash, PartialEq));
|
impl_reflect_value!(::std::ffi::OsString(Debug, Hash, PartialEq));
|
||||||
|
|
||||||
impl_from_reflect_value!(bool);
|
impl_from_reflect_value!(bool);
|
||||||
impl_from_reflect_value!(char);
|
impl_from_reflect_value!(char);
|
||||||
@ -157,12 +240,12 @@ impl_from_reflect_value!(f64);
|
|||||||
impl_from_reflect_value!(String);
|
impl_from_reflect_value!(String);
|
||||||
impl_from_reflect_value!(PathBuf);
|
impl_from_reflect_value!(PathBuf);
|
||||||
impl_from_reflect_value!(OsString);
|
impl_from_reflect_value!(OsString);
|
||||||
impl_from_reflect_value!(HashSet<T: Hash + Eq + Clone + Send + Sync + 'static>);
|
impl_from_reflect_value!(HashSet<T: TypePath + Hash + Eq + Clone + Send + Sync>);
|
||||||
impl_from_reflect_value!(Range<T: Clone + Send + Sync + 'static>);
|
impl_from_reflect_value!(Range<T: TypePath + Clone + Send + Sync>);
|
||||||
impl_from_reflect_value!(RangeInclusive<T: Clone + Send + Sync + 'static>);
|
impl_from_reflect_value!(RangeInclusive<T: TypePath + Clone + Send + Sync>);
|
||||||
impl_from_reflect_value!(RangeFrom<T: Clone + Send + Sync + 'static>);
|
impl_from_reflect_value!(RangeFrom<T: TypePath + Clone + Send + Sync>);
|
||||||
impl_from_reflect_value!(RangeTo<T: Clone + Send + Sync + 'static>);
|
impl_from_reflect_value!(RangeTo<T: TypePath + Clone + Send + Sync>);
|
||||||
impl_from_reflect_value!(RangeToInclusive<T: Clone + Send + Sync + 'static>);
|
impl_from_reflect_value!(RangeToInclusive<T: TypePath + Clone + Send + Sync>);
|
||||||
impl_from_reflect_value!(RangeFull);
|
impl_from_reflect_value!(RangeFull);
|
||||||
impl_from_reflect_value!(Duration);
|
impl_from_reflect_value!(Duration);
|
||||||
impl_from_reflect_value!(Instant);
|
impl_from_reflect_value!(Instant);
|
||||||
@ -180,8 +263,8 @@ impl_from_reflect_value!(NonZeroU8);
|
|||||||
impl_from_reflect_value!(NonZeroI8);
|
impl_from_reflect_value!(NonZeroI8);
|
||||||
|
|
||||||
macro_rules! impl_reflect_for_veclike {
|
macro_rules! impl_reflect_for_veclike {
|
||||||
($ty:ty, $insert:expr, $remove:expr, $push:expr, $pop:expr, $sub:ty) => {
|
($ty:path, $insert:expr, $remove:expr, $push:expr, $pop:expr, $sub:ty) => {
|
||||||
impl<T: FromReflect> List for $ty {
|
impl<T: FromReflect + TypePath> List for $ty {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn get(&self, index: usize) -> Option<&dyn Reflect> {
|
fn get(&self, index: usize) -> Option<&dyn Reflect> {
|
||||||
<$sub>::get(self, index).map(|value| value as &dyn Reflect)
|
<$sub>::get(self, index).map(|value| value as &dyn Reflect)
|
||||||
@ -228,8 +311,8 @@ macro_rules! impl_reflect_for_veclike {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn iter(&self) -> $crate::ListIter {
|
fn iter(&self) -> ListIter {
|
||||||
$crate::ListIter::new(self)
|
ListIter::new(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -240,7 +323,7 @@ macro_rules! impl_reflect_for_veclike {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: FromReflect> Reflect for $ty {
|
impl<T: FromReflect + TypePath> Reflect for $ty {
|
||||||
fn type_name(&self) -> &str {
|
fn type_name(&self) -> &str {
|
||||||
std::any::type_name::<Self>()
|
std::any::type_name::<Self>()
|
||||||
}
|
}
|
||||||
@ -249,6 +332,11 @@ macro_rules! impl_reflect_for_veclike {
|
|||||||
Some(<Self as Typed>::type_info())
|
Some(<Self as Typed>::type_info())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn get_type_path(&self) -> &dyn DynamicTypePath {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
fn into_any(self: Box<Self>) -> Box<dyn Any> {
|
fn into_any(self: Box<Self>) -> Box<dyn Any> {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -307,14 +395,16 @@ macro_rules! impl_reflect_for_veclike {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: FromReflect> Typed for $ty {
|
impl<T: FromReflect + TypePath> Typed for $ty {
|
||||||
fn type_info() -> &'static TypeInfo {
|
fn type_info() -> &'static TypeInfo {
|
||||||
static CELL: GenericTypeInfoCell = GenericTypeInfoCell::new();
|
static CELL: GenericTypeInfoCell = GenericTypeInfoCell::new();
|
||||||
CELL.get_or_insert::<Self, _>(|| TypeInfo::List(ListInfo::new::<Self, T>()))
|
CELL.get_or_insert::<Self, _>(|| TypeInfo::List(ListInfo::new::<Self, T>()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: FromReflect> GetTypeRegistration for $ty {
|
impl_type_path!($ty where T: FromReflect);
|
||||||
|
|
||||||
|
impl<T: FromReflect + TypePath> GetTypeRegistration for $ty {
|
||||||
fn get_type_registration() -> TypeRegistration {
|
fn get_type_registration() -> TypeRegistration {
|
||||||
let mut registration = TypeRegistration::of::<$ty>();
|
let mut registration = TypeRegistration::of::<$ty>();
|
||||||
registration.insert::<ReflectFromPtr>(FromType::<$ty>::from_type());
|
registration.insert::<ReflectFromPtr>(FromType::<$ty>::from_type());
|
||||||
@ -322,7 +412,7 @@ macro_rules! impl_reflect_for_veclike {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: FromReflect> FromReflect for $ty {
|
impl<T: FromReflect + TypePath> FromReflect for $ty {
|
||||||
fn from_reflect(reflect: &dyn Reflect) -> Option<Self> {
|
fn from_reflect(reflect: &dyn Reflect) -> Option<Self> {
|
||||||
if let ReflectRef::List(ref_list) = reflect.reflect_ref() {
|
if let ReflectRef::List(ref_list) = reflect.reflect_ref() {
|
||||||
let mut new_list = Self::with_capacity(ref_list.len());
|
let mut new_list = Self::with_capacity(ref_list.len());
|
||||||
@ -338,9 +428,16 @@ macro_rules! impl_reflect_for_veclike {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_reflect_for_veclike!(Vec<T>, Vec::insert, Vec::remove, Vec::push, Vec::pop, [T]);
|
|
||||||
impl_reflect_for_veclike!(
|
impl_reflect_for_veclike!(
|
||||||
VecDeque<T>,
|
::alloc::vec::Vec<T>,
|
||||||
|
Vec::insert,
|
||||||
|
Vec::remove,
|
||||||
|
Vec::push,
|
||||||
|
Vec::pop,
|
||||||
|
[T]
|
||||||
|
);
|
||||||
|
impl_reflect_for_veclike!(
|
||||||
|
::alloc::collections::VecDeque<T>,
|
||||||
VecDeque::insert,
|
VecDeque::insert,
|
||||||
VecDeque::remove,
|
VecDeque::remove,
|
||||||
VecDeque::push_back,
|
VecDeque::push_back,
|
||||||
@ -349,12 +446,12 @@ impl_reflect_for_veclike!(
|
|||||||
);
|
);
|
||||||
|
|
||||||
macro_rules! impl_reflect_for_hashmap {
|
macro_rules! impl_reflect_for_hashmap {
|
||||||
($ty:ty) => {
|
($ty:path) => {
|
||||||
impl<K, V, S> Map for $ty
|
impl<K, V, S> Map for $ty
|
||||||
where
|
where
|
||||||
K: FromReflect + Eq + Hash,
|
K: FromReflect + TypePath + Eq + Hash,
|
||||||
V: FromReflect,
|
V: FromReflect + TypePath,
|
||||||
S: BuildHasher + Send + Sync + 'static,
|
S: TypePath + BuildHasher + Send + Sync,
|
||||||
{
|
{
|
||||||
fn get(&self, key: &dyn Reflect) -> Option<&dyn Reflect> {
|
fn get(&self, key: &dyn Reflect) -> Option<&dyn Reflect> {
|
||||||
key.downcast_ref::<K>()
|
key.downcast_ref::<K>()
|
||||||
@ -446,9 +543,9 @@ macro_rules! impl_reflect_for_hashmap {
|
|||||||
|
|
||||||
impl<K, V, S> Reflect for $ty
|
impl<K, V, S> Reflect for $ty
|
||||||
where
|
where
|
||||||
K: FromReflect + Eq + Hash,
|
K: FromReflect + TypePath + Eq + Hash,
|
||||||
V: FromReflect,
|
V: FromReflect + TypePath,
|
||||||
S: BuildHasher + Send + Sync + 'static,
|
S: TypePath + BuildHasher + Send + Sync,
|
||||||
{
|
{
|
||||||
fn type_name(&self) -> &str {
|
fn type_name(&self) -> &str {
|
||||||
std::any::type_name::<Self>()
|
std::any::type_name::<Self>()
|
||||||
@ -458,6 +555,10 @@ macro_rules! impl_reflect_for_hashmap {
|
|||||||
Some(<Self as Typed>::type_info())
|
Some(<Self as Typed>::type_info())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_type_path(&self) -> &dyn DynamicTypePath {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
fn into_any(self: Box<Self>) -> Box<dyn Any> {
|
fn into_any(self: Box<Self>) -> Box<dyn Any> {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -515,9 +616,9 @@ macro_rules! impl_reflect_for_hashmap {
|
|||||||
|
|
||||||
impl<K, V, S> Typed for $ty
|
impl<K, V, S> Typed for $ty
|
||||||
where
|
where
|
||||||
K: FromReflect + Eq + Hash,
|
K: FromReflect + TypePath + Eq + Hash,
|
||||||
V: FromReflect,
|
V: FromReflect + TypePath,
|
||||||
S: BuildHasher + Send + Sync + 'static,
|
S: TypePath + BuildHasher + Send + Sync,
|
||||||
{
|
{
|
||||||
fn type_info() -> &'static TypeInfo {
|
fn type_info() -> &'static TypeInfo {
|
||||||
static CELL: GenericTypeInfoCell = GenericTypeInfoCell::new();
|
static CELL: GenericTypeInfoCell = GenericTypeInfoCell::new();
|
||||||
@ -527,9 +628,9 @@ macro_rules! impl_reflect_for_hashmap {
|
|||||||
|
|
||||||
impl<K, V, S> GetTypeRegistration for $ty
|
impl<K, V, S> GetTypeRegistration for $ty
|
||||||
where
|
where
|
||||||
K: FromReflect + Eq + Hash,
|
K: FromReflect + TypePath + Eq + Hash,
|
||||||
V: FromReflect,
|
V: FromReflect + TypePath,
|
||||||
S: BuildHasher + Send + Sync + 'static,
|
S: TypePath + BuildHasher + Send + Sync,
|
||||||
{
|
{
|
||||||
fn get_type_registration() -> TypeRegistration {
|
fn get_type_registration() -> TypeRegistration {
|
||||||
let mut registration = TypeRegistration::of::<Self>();
|
let mut registration = TypeRegistration::of::<Self>();
|
||||||
@ -540,9 +641,9 @@ macro_rules! impl_reflect_for_hashmap {
|
|||||||
|
|
||||||
impl<K, V, S> FromReflect for $ty
|
impl<K, V, S> FromReflect for $ty
|
||||||
where
|
where
|
||||||
K: FromReflect + Eq + Hash,
|
K: FromReflect + TypePath + Eq + Hash,
|
||||||
V: FromReflect,
|
V: FromReflect + TypePath,
|
||||||
S: BuildHasher + Default + Send + Sync + 'static,
|
S: TypePath + BuildHasher + Default + Send + Sync,
|
||||||
{
|
{
|
||||||
fn from_reflect(reflect: &dyn Reflect) -> Option<Self> {
|
fn from_reflect(reflect: &dyn Reflect) -> Option<Self> {
|
||||||
if let ReflectRef::Map(ref_map) = reflect.reflect_ref() {
|
if let ReflectRef::Map(ref_map) = reflect.reflect_ref() {
|
||||||
@ -561,10 +662,27 @@ macro_rules! impl_reflect_for_hashmap {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
impl_reflect_for_hashmap!(bevy_utils::hashbrown::HashMap<K, V, S>);
|
impl_reflect_for_hashmap!(::std::collections::HashMap<K, V, S>);
|
||||||
impl_reflect_for_hashmap!(std::collections::HashMap<K, V, S>);
|
impl_type_path!(::std::collections::hash_map::RandomState);
|
||||||
|
impl_type_path!(
|
||||||
|
::std::collections::HashMap<K, V, S>
|
||||||
|
where
|
||||||
|
K: FromReflect + Eq + Hash + ?Sized,
|
||||||
|
V: FromReflect + ?Sized,
|
||||||
|
S: BuildHasher + Send + Sync + 'static,
|
||||||
|
);
|
||||||
|
|
||||||
impl<T: Reflect, const N: usize> Array for [T; N] {
|
impl_reflect_for_hashmap!(bevy_utils::hashbrown::HashMap<K, V, S>);
|
||||||
|
impl_type_path!(::bevy_utils::hashbrown::hash_map::DefaultHashBuilder);
|
||||||
|
impl_type_path!(
|
||||||
|
::bevy_utils::hashbrown::HashMap<K, V, S>
|
||||||
|
where
|
||||||
|
K: FromReflect + Eq + Hash + ?Sized,
|
||||||
|
V: FromReflect + ?Sized,
|
||||||
|
S: BuildHasher + Send + Sync + 'static,
|
||||||
|
);
|
||||||
|
|
||||||
|
impl<T: Reflect + TypePath, const N: usize> Array for [T; N] {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn get(&self, index: usize) -> Option<&dyn Reflect> {
|
fn get(&self, index: usize) -> Option<&dyn Reflect> {
|
||||||
<[T]>::get(self, index).map(|value| value as &dyn Reflect)
|
<[T]>::get(self, index).map(|value| value as &dyn Reflect)
|
||||||
@ -593,7 +711,7 @@ impl<T: Reflect, const N: usize> Array for [T; N] {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Reflect, const N: usize> Reflect for [T; N] {
|
impl<T: Reflect + TypePath, const N: usize> Reflect for [T; N] {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn type_name(&self) -> &str {
|
fn type_name(&self) -> &str {
|
||||||
std::any::type_name::<Self>()
|
std::any::type_name::<Self>()
|
||||||
@ -603,6 +721,11 @@ impl<T: Reflect, const N: usize> Reflect for [T; N] {
|
|||||||
Some(<Self as Typed>::type_info())
|
Some(<Self as Typed>::type_info())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn get_type_path(&self) -> &dyn DynamicTypePath {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn into_any(self: Box<Self>) -> Box<dyn Any> {
|
fn into_any(self: Box<Self>) -> Box<dyn Any> {
|
||||||
self
|
self
|
||||||
@ -675,7 +798,7 @@ impl<T: Reflect, const N: usize> Reflect for [T; N] {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: FromReflect, const N: usize> FromReflect for [T; N] {
|
impl<T: FromReflect + TypePath, const N: usize> FromReflect for [T; N] {
|
||||||
fn from_reflect(reflect: &dyn Reflect) -> Option<Self> {
|
fn from_reflect(reflect: &dyn Reflect) -> Option<Self> {
|
||||||
if let ReflectRef::Array(ref_array) = reflect.reflect_ref() {
|
if let ReflectRef::Array(ref_array) = reflect.reflect_ref() {
|
||||||
let mut temp_vec = Vec::with_capacity(ref_array.len());
|
let mut temp_vec = Vec::with_capacity(ref_array.len());
|
||||||
@ -689,13 +812,25 @@ impl<T: FromReflect, const N: usize> FromReflect for [T; N] {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Reflect, const N: usize> Typed for [T; N] {
|
impl<T: Reflect + TypePath, const N: usize> Typed for [T; N] {
|
||||||
fn type_info() -> &'static TypeInfo {
|
fn type_info() -> &'static TypeInfo {
|
||||||
static CELL: GenericTypeInfoCell = GenericTypeInfoCell::new();
|
static CELL: GenericTypeInfoCell = GenericTypeInfoCell::new();
|
||||||
CELL.get_or_insert::<Self, _>(|| TypeInfo::Array(ArrayInfo::new::<Self, T>(N)))
|
CELL.get_or_insert::<Self, _>(|| TypeInfo::Array(ArrayInfo::new::<Self, T>(N)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T: Reflect + TypePath, const N: usize> TypePath for [T; N] {
|
||||||
|
fn type_path() -> &'static str {
|
||||||
|
static CELL: GenericTypePathCell = GenericTypePathCell::new();
|
||||||
|
CELL.get_or_insert::<Self, _>(|| format!("[{t}; {N}]", t = T::type_path()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn short_type_path() -> &'static str {
|
||||||
|
static CELL: GenericTypePathCell = GenericTypePathCell::new();
|
||||||
|
CELL.get_or_insert::<Self, _>(|| format!("[{t}; {N}]", t = T::short_type_path()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO:
|
// TODO:
|
||||||
// `FromType::from_type` requires `Deserialize<'de>` to be implemented for `T`.
|
// `FromType::from_type` requires `Deserialize<'de>` to be implemented for `T`.
|
||||||
// Currently serde only supports `Deserialize<'de>` for arrays up to size 32.
|
// Currently serde only supports `Deserialize<'de>` for arrays up to size 32.
|
||||||
@ -704,7 +839,7 @@ impl<T: Reflect, const N: usize> Typed for [T; N] {
|
|||||||
macro_rules! impl_array_get_type_registration {
|
macro_rules! impl_array_get_type_registration {
|
||||||
($($N:expr)+) => {
|
($($N:expr)+) => {
|
||||||
$(
|
$(
|
||||||
impl<T: Reflect > GetTypeRegistration for [T; $N] {
|
impl<T: Reflect + TypePath> GetTypeRegistration for [T; $N] {
|
||||||
fn get_type_registration() -> TypeRegistration {
|
fn get_type_registration() -> TypeRegistration {
|
||||||
TypeRegistration::of::<[T; $N]>()
|
TypeRegistration::of::<[T; $N]>()
|
||||||
}
|
}
|
||||||
@ -720,13 +855,13 @@ impl_array_get_type_registration! {
|
|||||||
30 31 32
|
30 31 32
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: FromReflect> GetTypeRegistration for Option<T> {
|
impl<T: FromReflect + TypePath> GetTypeRegistration for Option<T> {
|
||||||
fn get_type_registration() -> TypeRegistration {
|
fn get_type_registration() -> TypeRegistration {
|
||||||
TypeRegistration::of::<Option<T>>()
|
TypeRegistration::of::<Option<T>>()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: FromReflect> Enum for Option<T> {
|
impl<T: FromReflect + TypePath> Enum for Option<T> {
|
||||||
fn field(&self, _name: &str) -> Option<&dyn Reflect> {
|
fn field(&self, _name: &str) -> Option<&dyn Reflect> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
@ -797,7 +932,7 @@ impl<T: FromReflect> Enum for Option<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: FromReflect> Reflect for Option<T> {
|
impl<T: FromReflect + TypePath> Reflect for Option<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn type_name(&self) -> &str {
|
fn type_name(&self) -> &str {
|
||||||
std::any::type_name::<Self>()
|
std::any::type_name::<Self>()
|
||||||
@ -808,6 +943,11 @@ impl<T: FromReflect> Reflect for Option<T> {
|
|||||||
Some(<Self as Typed>::type_info())
|
Some(<Self as Typed>::type_info())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn get_type_path(&self) -> &dyn DynamicTypePath {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn into_any(self: Box<Self>) -> Box<dyn Any> {
|
fn into_any(self: Box<Self>) -> Box<dyn Any> {
|
||||||
self
|
self
|
||||||
@ -911,7 +1051,7 @@ impl<T: FromReflect> Reflect for Option<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: FromReflect> FromReflect for Option<T> {
|
impl<T: FromReflect + TypePath> FromReflect for Option<T> {
|
||||||
fn from_reflect(reflect: &dyn Reflect) -> Option<Self> {
|
fn from_reflect(reflect: &dyn Reflect) -> Option<Self> {
|
||||||
if let ReflectRef::Enum(dyn_enum) = reflect.reflect_ref() {
|
if let ReflectRef::Enum(dyn_enum) = reflect.reflect_ref() {
|
||||||
match dyn_enum.variant_name() {
|
match dyn_enum.variant_name() {
|
||||||
@ -949,7 +1089,7 @@ impl<T: FromReflect> FromReflect for Option<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: FromReflect> Typed for Option<T> {
|
impl<T: FromReflect + TypePath> Typed for Option<T> {
|
||||||
fn type_info() -> &'static TypeInfo {
|
fn type_info() -> &'static TypeInfo {
|
||||||
static CELL: GenericTypeInfoCell = GenericTypeInfoCell::new();
|
static CELL: GenericTypeInfoCell = GenericTypeInfoCell::new();
|
||||||
CELL.get_or_insert::<Self, _>(|| {
|
CELL.get_or_insert::<Self, _>(|| {
|
||||||
@ -964,6 +1104,8 @@ impl<T: FromReflect> Typed for Option<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl_type_path!(::core::option::Option<T: FromReflect + TypePath>);
|
||||||
|
|
||||||
impl Reflect for Cow<'static, str> {
|
impl Reflect for Cow<'static, str> {
|
||||||
fn type_name(&self) -> &str {
|
fn type_name(&self) -> &str {
|
||||||
std::any::type_name::<Self>()
|
std::any::type_name::<Self>()
|
||||||
@ -973,6 +1115,11 @@ impl Reflect for Cow<'static, str> {
|
|||||||
Some(<Self as Typed>::type_info())
|
Some(<Self as Typed>::type_info())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn get_type_path(&self) -> &dyn DynamicTypePath {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
fn into_any(self: Box<Self>) -> Box<dyn Any> {
|
fn into_any(self: Box<Self>) -> Box<dyn Any> {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -1051,6 +1198,30 @@ impl Typed for Cow<'static, str> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl TypePath for Cow<'static, str> {
|
||||||
|
fn type_path() -> &'static str {
|
||||||
|
static CELL: GenericTypePathCell = GenericTypePathCell::new();
|
||||||
|
CELL.get_or_insert::<Self, _>(|| "std::borrow::Cow::<str>".to_owned())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn short_type_path() -> &'static str {
|
||||||
|
static CELL: GenericTypePathCell = GenericTypePathCell::new();
|
||||||
|
CELL.get_or_insert::<Self, _>(|| "Cow<str>".to_owned())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn type_ident() -> Option<&'static str> {
|
||||||
|
Some("Cow")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn crate_name() -> Option<&'static str> {
|
||||||
|
Some("std")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn module_path() -> Option<&'static str> {
|
||||||
|
Some("std::borrow")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl GetTypeRegistration for Cow<'static, str> {
|
impl GetTypeRegistration for Cow<'static, str> {
|
||||||
fn get_type_registration() -> TypeRegistration {
|
fn get_type_registration() -> TypeRegistration {
|
||||||
let mut registration = TypeRegistration::of::<Cow<'static, str>>();
|
let mut registration = TypeRegistration::of::<Cow<'static, str>>();
|
||||||
@ -1081,6 +1252,11 @@ impl Reflect for &'static Path {
|
|||||||
Some(<Self as Typed>::type_info())
|
Some(<Self as Typed>::type_info())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn get_type_path(&self) -> &dyn DynamicTypePath {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
fn into_any(self: Box<Self>) -> Box<dyn Any> {
|
fn into_any(self: Box<Self>) -> Box<dyn Any> {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -1159,6 +1335,18 @@ impl Typed for &'static Path {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl TypePath for &'static Path {
|
||||||
|
fn type_path() -> &'static str {
|
||||||
|
static CELL: GenericTypePathCell = GenericTypePathCell::new();
|
||||||
|
CELL.get_or_insert::<Self, _>(|| "&std::path::Path".to_owned())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn short_type_path() -> &'static str {
|
||||||
|
static CELL: GenericTypePathCell = GenericTypePathCell::new();
|
||||||
|
CELL.get_or_insert::<Self, _>(|| "&Path".to_owned())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl GetTypeRegistration for &'static Path {
|
impl GetTypeRegistration for &'static Path {
|
||||||
fn get_type_registration() -> TypeRegistration {
|
fn get_type_registration() -> TypeRegistration {
|
||||||
let mut registration = TypeRegistration::of::<Self>();
|
let mut registration = TypeRegistration::of::<Self>();
|
||||||
@ -1178,6 +1366,11 @@ impl Reflect for Cow<'static, Path> {
|
|||||||
std::any::type_name::<Self>()
|
std::any::type_name::<Self>()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn get_type_path(&self) -> &dyn DynamicTypePath {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
fn get_represented_type_info(&self) -> Option<&'static TypeInfo> {
|
fn get_represented_type_info(&self) -> Option<&'static TypeInfo> {
|
||||||
Some(<Self as Typed>::type_info())
|
Some(<Self as Typed>::type_info())
|
||||||
}
|
}
|
||||||
@ -1264,6 +1457,11 @@ impl Typed for Cow<'static, Path> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trait PathOnly: ToOwned {}
|
||||||
|
impl PathOnly for Path {}
|
||||||
|
impl_type_path!(::alloc::borrow::Cow<'a: 'static, T: PathOnly + ?Sized>);
|
||||||
|
impl_type_path!(::std::path::Path);
|
||||||
|
|
||||||
impl FromReflect for Cow<'static, Path> {
|
impl FromReflect for Cow<'static, Path> {
|
||||||
fn from_reflect(reflect: &dyn Reflect) -> Option<Self> {
|
fn from_reflect(reflect: &dyn Reflect) -> Option<Self> {
|
||||||
Some(reflect.as_any().downcast_ref::<Self>()?.clone())
|
Some(reflect.as_any().downcast_ref::<Self>()?.clone())
|
||||||
|
|||||||
@ -448,6 +448,7 @@ mod struct_trait;
|
|||||||
mod tuple;
|
mod tuple;
|
||||||
mod tuple_struct;
|
mod tuple_struct;
|
||||||
mod type_info;
|
mod type_info;
|
||||||
|
mod type_path;
|
||||||
mod type_registry;
|
mod type_registry;
|
||||||
mod type_uuid;
|
mod type_uuid;
|
||||||
mod type_uuid_impl;
|
mod type_uuid_impl;
|
||||||
@ -496,12 +497,15 @@ pub use struct_trait::*;
|
|||||||
pub use tuple::*;
|
pub use tuple::*;
|
||||||
pub use tuple_struct::*;
|
pub use tuple_struct::*;
|
||||||
pub use type_info::*;
|
pub use type_info::*;
|
||||||
|
pub use type_path::*;
|
||||||
pub use type_registry::*;
|
pub use type_registry::*;
|
||||||
pub use type_uuid::*;
|
pub use type_uuid::*;
|
||||||
|
|
||||||
pub use bevy_reflect_derive::*;
|
pub use bevy_reflect_derive::*;
|
||||||
pub use erased_serde;
|
pub use erased_serde;
|
||||||
|
|
||||||
|
extern crate alloc;
|
||||||
|
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub mod __macro_exports {
|
pub mod __macro_exports {
|
||||||
use crate::Uuid;
|
use crate::Uuid;
|
||||||
@ -543,8 +547,8 @@ mod tests {
|
|||||||
ser::{to_string_pretty, PrettyConfig},
|
ser::{to_string_pretty, PrettyConfig},
|
||||||
Deserializer,
|
Deserializer,
|
||||||
};
|
};
|
||||||
use std::any::TypeId;
|
|
||||||
use std::fmt::{Debug, Formatter};
|
use std::fmt::{Debug, Formatter};
|
||||||
|
use std::{any::TypeId, marker::PhantomData};
|
||||||
|
|
||||||
use super::prelude::*;
|
use super::prelude::*;
|
||||||
use super::*;
|
use super::*;
|
||||||
@ -1118,6 +1122,98 @@ mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn reflect_type_path() {
|
||||||
|
#[derive(TypePath)]
|
||||||
|
struct Param;
|
||||||
|
|
||||||
|
#[derive(TypePath)]
|
||||||
|
struct Derive;
|
||||||
|
|
||||||
|
#[derive(TypePath)]
|
||||||
|
#[type_path = "my_alias"]
|
||||||
|
struct DerivePath;
|
||||||
|
|
||||||
|
#[derive(TypePath)]
|
||||||
|
#[type_path = "my_alias"]
|
||||||
|
#[type_name = "MyDerivePathName"]
|
||||||
|
struct DerivePathName;
|
||||||
|
|
||||||
|
#[derive(TypePath)]
|
||||||
|
struct DeriveG<T>(PhantomData<T>);
|
||||||
|
|
||||||
|
#[derive(TypePath)]
|
||||||
|
#[type_path = "my_alias"]
|
||||||
|
struct DerivePathG<T, const N: usize>(PhantomData<T>);
|
||||||
|
|
||||||
|
#[derive(TypePath)]
|
||||||
|
#[type_path = "my_alias"]
|
||||||
|
#[type_name = "MyDerivePathNameG"]
|
||||||
|
struct DerivePathNameG<T>(PhantomData<T>);
|
||||||
|
|
||||||
|
struct Macro;
|
||||||
|
impl_type_path!((in my_alias) Macro);
|
||||||
|
|
||||||
|
struct MacroName;
|
||||||
|
impl_type_path!((in my_alias as MyMacroName) MacroName);
|
||||||
|
|
||||||
|
struct MacroG<T, const N: usize>(PhantomData<T>);
|
||||||
|
impl_type_path!((in my_alias) MacroG<T, const N: usize>);
|
||||||
|
|
||||||
|
struct MacroNameG<T>(PhantomData<T>);
|
||||||
|
impl_type_path!((in my_alias as MyMacroNameG) MacroNameG<T>);
|
||||||
|
|
||||||
|
assert_eq!(Derive::type_path(), "bevy_reflect::tests::Derive");
|
||||||
|
assert_eq!(DerivePath::type_path(), "my_alias::DerivePath");
|
||||||
|
assert_eq!(DerivePathName::type_path(), "my_alias::MyDerivePathName");
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
DeriveG::<Param>::type_path(),
|
||||||
|
"bevy_reflect::tests::DeriveG<bevy_reflect::tests::Param>"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
DerivePathG::<Param, 10>::type_path(),
|
||||||
|
"my_alias::DerivePathG<bevy_reflect::tests::Param, 10>"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
DerivePathNameG::<Param>::type_path(),
|
||||||
|
"my_alias::MyDerivePathNameG<bevy_reflect::tests::Param>"
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(Macro::type_path(), "my_alias::Macro");
|
||||||
|
assert_eq!(MacroName::type_path(), "my_alias::MyMacroName");
|
||||||
|
assert_eq!(
|
||||||
|
MacroG::<Param, 10>::type_path(),
|
||||||
|
"my_alias::MacroG<bevy_reflect::tests::Param, 10>"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
MacroNameG::<Param>::type_path(),
|
||||||
|
"my_alias::MyMacroNameG<bevy_reflect::tests::Param>"
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(Derive::short_type_path(), "Derive");
|
||||||
|
assert_eq!(DerivePath::short_type_path(), "DerivePath");
|
||||||
|
assert_eq!(DerivePathName::short_type_path(), "MyDerivePathName");
|
||||||
|
|
||||||
|
assert_eq!(DeriveG::<Param>::short_type_path(), "DeriveG<Param>");
|
||||||
|
assert_eq!(
|
||||||
|
DerivePathG::<Param, 10>::short_type_path(),
|
||||||
|
"DerivePathG<Param, 10>"
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
DerivePathNameG::<Param>::short_type_path(),
|
||||||
|
"MyDerivePathNameG<Param>"
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(Macro::short_type_path(), "Macro");
|
||||||
|
assert_eq!(MacroName::short_type_path(), "MyMacroName");
|
||||||
|
assert_eq!(MacroG::<Param, 10>::short_type_path(), "MacroG<Param, 10>");
|
||||||
|
assert_eq!(
|
||||||
|
MacroNameG::<Param>::short_type_path(),
|
||||||
|
"MyMacroNameG<Param>"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn reflect_type_info() {
|
fn reflect_type_info() {
|
||||||
// TypeInfo
|
// TypeInfo
|
||||||
@ -1171,7 +1267,7 @@ mod tests {
|
|||||||
|
|
||||||
// Struct (generic)
|
// Struct (generic)
|
||||||
#[derive(Reflect)]
|
#[derive(Reflect)]
|
||||||
struct MyGenericStruct<T: Reflect> {
|
struct MyGenericStruct<T: Reflect + TypePath> {
|
||||||
foo: T,
|
foo: T,
|
||||||
bar: usize,
|
bar: usize,
|
||||||
}
|
}
|
||||||
@ -1420,7 +1516,7 @@ mod tests {
|
|||||||
struct SomePrimitive;
|
struct SomePrimitive;
|
||||||
impl_reflect_value!(
|
impl_reflect_value!(
|
||||||
/// Some primitive for which we have attributed custom documentation.
|
/// Some primitive for which we have attributed custom documentation.
|
||||||
SomePrimitive
|
(in bevy_reflect::tests) SomePrimitive
|
||||||
);
|
);
|
||||||
|
|
||||||
let info = <SomePrimitive as Typed>::type_info();
|
let info = <SomePrimitive as Typed>::type_info();
|
||||||
|
|||||||
@ -2,8 +2,13 @@ use std::any::{Any, TypeId};
|
|||||||
use std::fmt::{Debug, Formatter};
|
use std::fmt::{Debug, Formatter};
|
||||||
use std::hash::{Hash, Hasher};
|
use std::hash::{Hash, Hasher};
|
||||||
|
|
||||||
|
use bevy_reflect_derive::impl_type_path;
|
||||||
|
|
||||||
use crate::utility::reflect_hasher;
|
use crate::utility::reflect_hasher;
|
||||||
use crate::{FromReflect, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo};
|
use crate::{
|
||||||
|
self as bevy_reflect, DynamicTypePath, FromReflect, Reflect, ReflectMut, ReflectOwned,
|
||||||
|
ReflectRef, TypeInfo,
|
||||||
|
};
|
||||||
|
|
||||||
/// A trait used to power [list-like] operations via [reflection].
|
/// A trait used to power [list-like] operations via [reflection].
|
||||||
///
|
///
|
||||||
@ -271,6 +276,11 @@ impl Reflect for DynamicList {
|
|||||||
self.represented_type
|
self.represented_type
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn get_type_path(&self) -> &dyn DynamicTypePath {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn into_any(self: Box<Self>) -> Box<dyn Any> {
|
fn into_any(self: Box<Self>) -> Box<dyn Any> {
|
||||||
self
|
self
|
||||||
@ -352,6 +362,8 @@ impl Reflect for DynamicList {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl_type_path!((in bevy_reflect) DynamicList);
|
||||||
|
|
||||||
impl Debug for DynamicList {
|
impl Debug for DynamicList {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
self.debug(f)
|
self.debug(f)
|
||||||
|
|||||||
@ -2,9 +2,12 @@ use std::any::{Any, TypeId};
|
|||||||
use std::fmt::{Debug, Formatter};
|
use std::fmt::{Debug, Formatter};
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
|
|
||||||
|
use bevy_reflect_derive::impl_type_path;
|
||||||
use bevy_utils::{Entry, HashMap};
|
use bevy_utils::{Entry, HashMap};
|
||||||
|
|
||||||
use crate::{Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo};
|
use crate::{
|
||||||
|
self as bevy_reflect, DynamicTypePath, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo,
|
||||||
|
};
|
||||||
|
|
||||||
/// A trait used to power [map-like] operations via [reflection].
|
/// A trait used to power [map-like] operations via [reflection].
|
||||||
///
|
///
|
||||||
@ -307,6 +310,11 @@ impl Reflect for DynamicMap {
|
|||||||
self.represented_type
|
self.represented_type
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn get_type_path(&self) -> &dyn DynamicTypePath {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
fn into_any(self: Box<Self>) -> Box<dyn Any> {
|
fn into_any(self: Box<Self>) -> Box<dyn Any> {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -375,6 +383,8 @@ impl Reflect for DynamicMap {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl_type_path!((in bevy_reflect) DynamicMap);
|
||||||
|
|
||||||
impl Debug for DynamicMap {
|
impl Debug for DynamicMap {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
self.debug(f)
|
self.debug(f)
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
array_debug, enum_debug, list_debug, map_debug, serde::Serializable, struct_debug, tuple_debug,
|
array_debug, enum_debug, list_debug, map_debug, serde::Serializable, struct_debug, tuple_debug,
|
||||||
tuple_struct_debug, Array, Enum, List, Map, Struct, Tuple, TupleStruct, TypeInfo, Typed,
|
tuple_struct_debug, Array, DynamicTypePath, Enum, List, Map, Struct, Tuple, TupleStruct,
|
||||||
ValueInfo,
|
TypeInfo, Typed, ValueInfo,
|
||||||
};
|
};
|
||||||
use std::{
|
use std::{
|
||||||
any::{self, Any, TypeId},
|
any::{self, Any, TypeId},
|
||||||
@ -93,6 +93,14 @@ pub trait Reflect: Any + Send + Sync {
|
|||||||
/// [`TypeRegistry::get_type_info`]: crate::TypeRegistry::get_type_info
|
/// [`TypeRegistry::get_type_info`]: crate::TypeRegistry::get_type_info
|
||||||
fn get_represented_type_info(&self) -> Option<&'static TypeInfo>;
|
fn get_represented_type_info(&self) -> Option<&'static TypeInfo>;
|
||||||
|
|
||||||
|
/// Returns the [`TypePath`] implementation for the underlying type.
|
||||||
|
///
|
||||||
|
/// Methods on [`DynamicTypePath`] suffer the same performance concerns as [`get_represented_type_info`].
|
||||||
|
///
|
||||||
|
/// [`TypePath`]: crate::TypePath
|
||||||
|
/// [`get_represented_type_info`]: Reflect::get_represented_type_info
|
||||||
|
fn get_type_path(&self) -> &dyn DynamicTypePath;
|
||||||
|
|
||||||
/// Returns the value as a [`Box<dyn Any>`][std::any::Any].
|
/// Returns the value as a [`Box<dyn Any>`][std::any::Any].
|
||||||
fn into_any(self: Box<Self>) -> Box<dyn Any>;
|
fn into_any(self: Box<Self>) -> Box<dyn Any>;
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,8 @@
|
|||||||
use crate::{NamedField, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo};
|
use crate::{
|
||||||
|
self as bevy_reflect, DynamicTypePath, NamedField, Reflect, ReflectMut, ReflectOwned,
|
||||||
|
ReflectRef, TypeInfo,
|
||||||
|
};
|
||||||
|
use bevy_reflect_derive::impl_type_path;
|
||||||
use bevy_utils::{Entry, HashMap};
|
use bevy_utils::{Entry, HashMap};
|
||||||
use std::fmt::{Debug, Formatter};
|
use std::fmt::{Debug, Formatter};
|
||||||
use std::{
|
use std::{
|
||||||
@ -401,6 +405,11 @@ impl Reflect for DynamicStruct {
|
|||||||
self.represented_type
|
self.represented_type
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn get_type_path(&self) -> &dyn DynamicTypePath {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn into_any(self: Box<Self>) -> Box<dyn Any> {
|
fn into_any(self: Box<Self>) -> Box<dyn Any> {
|
||||||
self
|
self
|
||||||
@ -485,6 +494,8 @@ impl Reflect for DynamicStruct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl_type_path!((in bevy_reflect) DynamicStruct);
|
||||||
|
|
||||||
impl Debug for DynamicStruct {
|
impl Debug for DynamicStruct {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
self.debug(f)
|
self.debug(f)
|
||||||
|
|||||||
@ -1,5 +1,8 @@
|
|||||||
|
use bevy_reflect_derive::impl_type_path;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
FromReflect, GetTypeRegistration, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo,
|
self as bevy_reflect, utility::GenericTypePathCell, DynamicTypePath, FromReflect,
|
||||||
|
GetTypeRegistration, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, TypePath,
|
||||||
TypeRegistration, Typed, UnnamedField,
|
TypeRegistration, Typed, UnnamedField,
|
||||||
};
|
};
|
||||||
use std::any::{Any, TypeId};
|
use std::any::{Any, TypeId};
|
||||||
@ -318,6 +321,11 @@ impl Reflect for DynamicTuple {
|
|||||||
self.represented_type
|
self.represented_type
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn get_type_path(&self) -> &dyn DynamicTypePath {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn into_any(self: Box<Self>) -> Box<dyn Any> {
|
fn into_any(self: Box<Self>) -> Box<dyn Any> {
|
||||||
self
|
self
|
||||||
@ -393,6 +401,8 @@ impl Reflect for DynamicTuple {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl_type_path!((in bevy_reflect) DynamicTuple);
|
||||||
|
|
||||||
/// Applies the elements of `b` to the corresponding elements of `a`.
|
/// Applies the elements of `b` to the corresponding elements of `a`.
|
||||||
///
|
///
|
||||||
/// # Panics
|
/// # Panics
|
||||||
@ -467,7 +477,7 @@ pub fn tuple_debug(dyn_tuple: &dyn Tuple, f: &mut std::fmt::Formatter<'_>) -> st
|
|||||||
|
|
||||||
macro_rules! impl_reflect_tuple {
|
macro_rules! impl_reflect_tuple {
|
||||||
{$($index:tt : $name:tt),*} => {
|
{$($index:tt : $name:tt),*} => {
|
||||||
impl<$($name: Reflect),*> Tuple for ($($name,)*) {
|
impl<$($name: Reflect + TypePath),*> Tuple for ($($name,)*) {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn field(&self, index: usize) -> Option<&dyn Reflect> {
|
fn field(&self, index: usize) -> Option<&dyn Reflect> {
|
||||||
match index {
|
match index {
|
||||||
@ -519,7 +529,7 @@ macro_rules! impl_reflect_tuple {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<$($name: Reflect),*> Reflect for ($($name,)*) {
|
impl<$($name: Reflect + TypePath),*> Reflect for ($($name,)*) {
|
||||||
fn type_name(&self) -> &str {
|
fn type_name(&self) -> &str {
|
||||||
std::any::type_name::<Self>()
|
std::any::type_name::<Self>()
|
||||||
}
|
}
|
||||||
@ -528,6 +538,11 @@ macro_rules! impl_reflect_tuple {
|
|||||||
Some(<Self as Typed>::type_info())
|
Some(<Self as Typed>::type_info())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn get_type_path(&self) -> &dyn DynamicTypePath {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
fn into_any(self: Box<Self>) -> Box<dyn Any> {
|
fn into_any(self: Box<Self>) -> Box<dyn Any> {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -582,7 +597,7 @@ macro_rules! impl_reflect_tuple {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl <$($name: Reflect),*> Typed for ($($name,)*) {
|
impl <$($name: Reflect + TypePath),*> Typed for ($($name,)*) {
|
||||||
fn type_info() -> &'static TypeInfo {
|
fn type_info() -> &'static TypeInfo {
|
||||||
static CELL: $crate::utility::GenericTypeInfoCell = $crate::utility::GenericTypeInfoCell::new();
|
static CELL: $crate::utility::GenericTypeInfoCell = $crate::utility::GenericTypeInfoCell::new();
|
||||||
CELL.get_or_insert::<Self, _>(|| {
|
CELL.get_or_insert::<Self, _>(|| {
|
||||||
@ -595,13 +610,30 @@ macro_rules! impl_reflect_tuple {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<$($name: Reflect + Typed),*> GetTypeRegistration for ($($name,)*) {
|
impl <$($name: Reflect + TypePath),*> TypePath for ($($name,)*) {
|
||||||
|
fn type_path() -> &'static str {
|
||||||
|
static CELL: GenericTypePathCell = GenericTypePathCell::new();
|
||||||
|
CELL.get_or_insert::<Self, _>(|| {
|
||||||
|
"(".to_owned() $(+ <$name as TypePath>::type_path())* + ")"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn short_type_path() -> &'static str {
|
||||||
|
static CELL: GenericTypePathCell = GenericTypePathCell::new();
|
||||||
|
CELL.get_or_insert::<Self, _>(|| {
|
||||||
|
"(".to_owned() $(+ <$name as TypePath>::short_type_path())* + ")"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl<$($name: Reflect + TypePath),*> GetTypeRegistration for ($($name,)*) {
|
||||||
fn get_type_registration() -> TypeRegistration {
|
fn get_type_registration() -> TypeRegistration {
|
||||||
TypeRegistration::of::<($($name,)*)>()
|
TypeRegistration::of::<($($name,)*)>()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<$($name: FromReflect),*> FromReflect for ($($name,)*)
|
impl<$($name: FromReflect + TypePath),*> FromReflect for ($($name,)*)
|
||||||
{
|
{
|
||||||
fn from_reflect(reflect: &dyn Reflect) -> Option<Self> {
|
fn from_reflect(reflect: &dyn Reflect) -> Option<Self> {
|
||||||
if let ReflectRef::Tuple(_ref_tuple) = reflect.reflect_ref() {
|
if let ReflectRef::Tuple(_ref_tuple) = reflect.reflect_ref() {
|
||||||
|
|||||||
@ -1,4 +1,9 @@
|
|||||||
use crate::{Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, UnnamedField};
|
use bevy_reflect_derive::impl_type_path;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
self as bevy_reflect, DynamicTypePath, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo,
|
||||||
|
UnnamedField,
|
||||||
|
};
|
||||||
use std::any::{Any, TypeId};
|
use std::any::{Any, TypeId};
|
||||||
use std::fmt::{Debug, Formatter};
|
use std::fmt::{Debug, Formatter};
|
||||||
use std::slice::Iter;
|
use std::slice::Iter;
|
||||||
@ -303,6 +308,11 @@ impl Reflect for DynamicTupleStruct {
|
|||||||
self.represented_type
|
self.represented_type
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn get_type_path(&self) -> &dyn DynamicTypePath {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn into_any(self: Box<Self>) -> Box<dyn Any> {
|
fn into_any(self: Box<Self>) -> Box<dyn Any> {
|
||||||
self
|
self
|
||||||
@ -386,6 +396,8 @@ impl Reflect for DynamicTupleStruct {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl_type_path!((in bevy_reflect) DynamicTupleStruct);
|
||||||
|
|
||||||
impl Debug for DynamicTupleStruct {
|
impl Debug for DynamicTupleStruct {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
self.debug(f)
|
self.debug(f)
|
||||||
|
|||||||
@ -24,7 +24,7 @@ use std::fmt::Debug;
|
|||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use std::any::Any;
|
/// # use std::any::Any;
|
||||||
/// # use bevy_reflect::{NamedField, Reflect, ReflectMut, ReflectOwned, ReflectRef, StructInfo, TypeInfo, ValueInfo};
|
/// # use bevy_reflect::{DynamicTypePath, NamedField, Reflect, ReflectMut, ReflectOwned, ReflectRef, StructInfo, TypeInfo, ValueInfo};
|
||||||
/// # use bevy_reflect::utility::NonGenericTypeInfoCell;
|
/// # use bevy_reflect::utility::NonGenericTypeInfoCell;
|
||||||
/// use bevy_reflect::Typed;
|
/// use bevy_reflect::Typed;
|
||||||
///
|
///
|
||||||
@ -51,6 +51,7 @@ use std::fmt::Debug;
|
|||||||
/// # impl Reflect for MyStruct {
|
/// # impl Reflect for MyStruct {
|
||||||
/// # fn type_name(&self) -> &str { todo!() }
|
/// # fn type_name(&self) -> &str { todo!() }
|
||||||
/// # fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { todo!() }
|
/// # fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { todo!() }
|
||||||
|
/// # fn get_type_path(&self) -> &dyn DynamicTypePath { todo!() }
|
||||||
/// # fn into_any(self: Box<Self>) -> Box<dyn Any> { todo!() }
|
/// # fn into_any(self: Box<Self>) -> Box<dyn Any> { todo!() }
|
||||||
/// # fn as_any(&self) -> &dyn Any { todo!() }
|
/// # fn as_any(&self) -> &dyn Any { todo!() }
|
||||||
/// # fn as_any_mut(&mut self) -> &mut dyn Any { todo!() }
|
/// # fn as_any_mut(&mut self) -> &mut dyn Any { todo!() }
|
||||||
|
|||||||
167
crates/bevy_reflect/src/type_path.rs
Normal file
167
crates/bevy_reflect/src/type_path.rs
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
/// A static accessor to type paths and names.
|
||||||
|
///
|
||||||
|
/// The engine uses this trait over [`std::any::type_name`] for stability and flexibility.
|
||||||
|
///
|
||||||
|
/// This trait is automatically implemented by the `#[derive(Reflect)]` macro
|
||||||
|
/// and allows type path information to be processed without an instance of that type.
|
||||||
|
///
|
||||||
|
/// Implementors may have difficulty in generating references with static
|
||||||
|
/// lifetimes. Luckily, this crate comes with some [utility] structs, to make generating these
|
||||||
|
/// statics much simpler.
|
||||||
|
///
|
||||||
|
/// # Stability
|
||||||
|
///
|
||||||
|
/// Certain parts of the engine, e.g. [(de)serialization], rely on type paths as identifiers
|
||||||
|
/// for matching dynamic values to concrete types.
|
||||||
|
///
|
||||||
|
/// Using [`std::any::type_name`], a scene containing `my_crate::foo::MyComponent` would break,
|
||||||
|
/// failing to deserialize if the component was moved from the `foo` module to the `bar` module,
|
||||||
|
/// becoming `my_crate::bar::MyComponent`.
|
||||||
|
/// This trait, through attributes when deriving itself or [`Reflect`], can ensure breaking changes are avoidable.
|
||||||
|
///
|
||||||
|
/// The only external factor we rely on for stability when deriving is the [`module_path!`] macro,
|
||||||
|
/// only if the derive does not provide a `#[type_path = "..."]` attribute.
|
||||||
|
///
|
||||||
|
/// # Anonymity
|
||||||
|
///
|
||||||
|
/// Some methods on this trait return `Option<&'static str>` over `&'static str`
|
||||||
|
/// because not all types define all parts of a type path, for example the array type `[T; N]`.
|
||||||
|
///
|
||||||
|
/// Such types are 'anonymous' in that they have only a defined [`type_path`] and [`short_type_path`]
|
||||||
|
/// and the methods [`crate_name`], [`module_path`] and [`type_ident`] all return `None`.
|
||||||
|
///
|
||||||
|
/// Primitives are treated like anonymous types, except they also have a defined [`type_ident`].
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// use bevy_reflect::TypePath;
|
||||||
|
///
|
||||||
|
/// // This type path will not change with compiler versions or recompiles,
|
||||||
|
/// // although it will not be the same if the definition is moved.
|
||||||
|
/// #[derive(TypePath)]
|
||||||
|
/// struct NonStableTypePath;
|
||||||
|
///
|
||||||
|
/// // This type path will never change, even if the definition is moved.
|
||||||
|
/// #[derive(TypePath)]
|
||||||
|
/// #[type_path = "my_crate::foo"]
|
||||||
|
/// struct StableTypePath;
|
||||||
|
///
|
||||||
|
/// // Type paths can have any number of path segments.
|
||||||
|
/// #[derive(TypePath)]
|
||||||
|
/// #[type_path = "my_crate::foo::bar::baz"]
|
||||||
|
/// struct DeeplyNestedStableTypePath;
|
||||||
|
///
|
||||||
|
/// // Including just a crate name!
|
||||||
|
/// #[derive(TypePath)]
|
||||||
|
/// #[type_path = "my_crate"]
|
||||||
|
/// struct ShallowStableTypePath;
|
||||||
|
///
|
||||||
|
/// // We can also rename the identifier/name of types.
|
||||||
|
/// #[derive(TypePath)]
|
||||||
|
/// #[type_path = "my_crate::foo"]
|
||||||
|
/// #[type_name = "RenamedStableTypePath"]
|
||||||
|
/// struct NamedStableTypePath;
|
||||||
|
///
|
||||||
|
/// // Generics are also supported.
|
||||||
|
/// #[derive(TypePath)]
|
||||||
|
/// #[type_path = "my_crate::foo"]
|
||||||
|
/// struct StableGenericTypePath<T, const N: usize>([T; N]);
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// [utility]: crate::utility
|
||||||
|
/// [(de)serialization]: crate::serde::UntypedReflectDeserializer
|
||||||
|
/// [`Reflect`]: crate::Reflect
|
||||||
|
/// [`type_path`]: TypePath::type_path
|
||||||
|
/// [`short_type_path`]: TypePath::short_type_path
|
||||||
|
/// [`crate_name`]: TypePath::crate_name
|
||||||
|
/// [`module_path`]: TypePath::module_path
|
||||||
|
/// [`type_ident`]: TypePath::type_ident
|
||||||
|
pub trait TypePath: 'static {
|
||||||
|
/// Returns the fully qualified path of the underlying type.
|
||||||
|
///
|
||||||
|
/// Generic parameter types are also fully expanded.
|
||||||
|
///
|
||||||
|
/// For `Option<PhantomData>`, this is `"core::option::Option<core::marker::PhantomData>"`.
|
||||||
|
fn type_path() -> &'static str;
|
||||||
|
|
||||||
|
/// Returns a short, pretty-print enabled path to the type.
|
||||||
|
///
|
||||||
|
/// Generic parameter types are also shortened.
|
||||||
|
///
|
||||||
|
/// For `Option<PhantomData>`, this is `"Option<PhantomData>"`.
|
||||||
|
fn short_type_path() -> &'static str;
|
||||||
|
|
||||||
|
/// Returns the name of the type, or [`None`] if it is [anonymous].
|
||||||
|
///
|
||||||
|
/// Primitive types will return [`Some`].
|
||||||
|
///
|
||||||
|
/// For `Option<PhantomData>`, this is `"Option"`.
|
||||||
|
///
|
||||||
|
/// [anonymous]: TypePath#anonymity
|
||||||
|
fn type_ident() -> Option<&'static str> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the name of the crate the type is in, or [`None`] if it is [anonymous].
|
||||||
|
///
|
||||||
|
/// For `Option<PhantomData>`, this is `"core"`.
|
||||||
|
///
|
||||||
|
/// [anonymous]: TypePath#anonymity
|
||||||
|
fn crate_name() -> Option<&'static str> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the path to the moudle the type is in, or [`None`] if it is [anonymous].
|
||||||
|
///
|
||||||
|
/// For `Option<PhantomData>`, this is `"core::option"`.
|
||||||
|
///
|
||||||
|
/// [anonymous]: TypePath#anonymity
|
||||||
|
fn module_path() -> Option<&'static str> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Dynamic dispatch for [`TypePath`].
|
||||||
|
///
|
||||||
|
/// Retrieved using [`Reflect::get_type_path`].
|
||||||
|
///
|
||||||
|
/// [`Reflect::get_type_path`]: crate::Reflect::get_type_path
|
||||||
|
pub trait DynamicTypePath {
|
||||||
|
/// See [`TypePath::type_path`].
|
||||||
|
fn reflect_type_path(&self) -> &str;
|
||||||
|
|
||||||
|
/// See [`TypePath::short_type_path`].
|
||||||
|
fn reflect_short_type_path(&self) -> &str;
|
||||||
|
|
||||||
|
/// See [`TypePath::type_ident`].
|
||||||
|
fn reflect_type_ident(&self) -> Option<&str>;
|
||||||
|
|
||||||
|
/// See [`TypePath::crate_name`].
|
||||||
|
fn reflect_crate_name(&self) -> Option<&str>;
|
||||||
|
|
||||||
|
/// See [`TypePath::module_path`].
|
||||||
|
fn reflect_module_path(&self) -> Option<&str>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: TypePath> DynamicTypePath for T {
|
||||||
|
fn reflect_type_path(&self) -> &str {
|
||||||
|
Self::type_path()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reflect_short_type_path(&self) -> &str {
|
||||||
|
Self::short_type_path()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reflect_type_ident(&self) -> Option<&str> {
|
||||||
|
Self::type_ident()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reflect_crate_name(&self) -> Option<&str> {
|
||||||
|
Self::crate_name()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reflect_module_path(&self) -> Option<&str> {
|
||||||
|
Self::module_path()
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -9,132 +9,220 @@ use std::{
|
|||||||
hash::BuildHasher,
|
hash::BuildHasher,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// A type that can be stored in a ([`Non`])[`GenericTypeCell`].
|
||||||
|
///
|
||||||
|
/// [`Non`]: NonGenericTypeCell
|
||||||
|
pub trait TypedProperty: sealed::Sealed {
|
||||||
|
type Stored: 'static;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Used to store a [`String`] in a [`GenericTypePathCell`] as part of a [`TypePath`] implementation.
|
||||||
|
///
|
||||||
|
/// [`TypePath`]: crate::TypePath
|
||||||
|
pub struct TypePathComponent;
|
||||||
|
|
||||||
|
mod sealed {
|
||||||
|
use super::{TypeInfo, TypePathComponent, TypedProperty};
|
||||||
|
|
||||||
|
pub trait Sealed {}
|
||||||
|
|
||||||
|
impl Sealed for TypeInfo {}
|
||||||
|
impl Sealed for TypePathComponent {}
|
||||||
|
|
||||||
|
impl TypedProperty for TypeInfo {
|
||||||
|
type Stored = Self;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TypedProperty for TypePathComponent {
|
||||||
|
type Stored = String;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A container for [`TypeInfo`] over non-generic types, allowing instances to be stored statically.
|
/// A container for [`TypeInfo`] over non-generic types, allowing instances to be stored statically.
|
||||||
///
|
///
|
||||||
/// This is specifically meant for use with _non_-generic types. If your type _is_ generic,
|
/// This is specifically meant for use with _non_-generic types. If your type _is_ generic,
|
||||||
/// then use [`GenericTypeInfoCell`] instead. Otherwise, it will not take into account all
|
/// then use [`GenericTypeCell`] instead. Otherwise, it will not take into account all
|
||||||
/// monomorphizations of your type.
|
/// monomorphizations of your type.
|
||||||
///
|
///
|
||||||
|
/// Non-generic [`TypePath`]s should be trivially generated with string literals and [`concat!`].
|
||||||
|
///
|
||||||
/// ## Example
|
/// ## Example
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use std::any::Any;
|
/// # use std::any::Any;
|
||||||
/// # use bevy_reflect::{NamedField, Reflect, ReflectMut, ReflectOwned, ReflectRef, StructInfo, Typed, TypeInfo};
|
/// # use bevy_reflect::{DynamicTypePath, NamedField, Reflect, ReflectMut, ReflectOwned, ReflectRef, StructInfo, Typed, TypeInfo};
|
||||||
/// use bevy_reflect::utility::NonGenericTypeInfoCell;
|
/// use bevy_reflect::utility::NonGenericTypeInfoCell;
|
||||||
///
|
///
|
||||||
/// struct Foo {
|
/// struct Foo {
|
||||||
/// bar: i32
|
/// bar: i32
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// impl Typed for Foo {
|
/// impl Typed for Foo {
|
||||||
/// fn type_info() -> &'static TypeInfo {
|
/// fn type_info() -> &'static TypeInfo {
|
||||||
/// static CELL: NonGenericTypeInfoCell = NonGenericTypeInfoCell::new();
|
/// static CELL: NonGenericTypeInfoCell = NonGenericTypeInfoCell::new();
|
||||||
/// CELL.get_or_set(|| {
|
/// CELL.get_or_set(|| {
|
||||||
/// let fields = [NamedField::new::<i32>("bar")];
|
/// let fields = [NamedField::new::<i32>("bar")];
|
||||||
/// let info = StructInfo::new::<Self>("Foo", &fields);
|
/// let info = StructInfo::new::<Self>("Foo", &fields);
|
||||||
/// TypeInfo::Struct(info)
|
/// TypeInfo::Struct(info)
|
||||||
/// })
|
/// })
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
/// #
|
/// #
|
||||||
/// # impl Reflect for Foo {
|
/// # impl Reflect for Foo {
|
||||||
/// # fn type_name(&self) -> &str { todo!() }
|
/// # fn type_name(&self) -> &str { todo!() }
|
||||||
/// # fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { todo!() }
|
/// # fn get_type_path(&self) -> &dyn DynamicTypePath { todo!() }
|
||||||
/// # fn into_any(self: Box<Self>) -> Box<dyn Any> { todo!() }
|
/// # fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { todo!() }
|
||||||
/// # fn as_any(&self) -> &dyn Any { todo!() }
|
/// # fn into_any(self: Box<Self>) -> Box<dyn Any> { todo!() }
|
||||||
/// # fn as_any_mut(&mut self) -> &mut dyn Any { todo!() }
|
/// # fn as_any(&self) -> &dyn Any { todo!() }
|
||||||
/// # fn into_reflect(self: Box<Self>) -> Box<dyn Reflect> { todo!() }
|
/// # fn as_any_mut(&mut self) -> &mut dyn Any { todo!() }
|
||||||
/// # fn as_reflect(&self) -> &dyn Reflect { todo!() }
|
/// # fn into_reflect(self: Box<Self>) -> Box<dyn Reflect> { todo!() }
|
||||||
/// # fn as_reflect_mut(&mut self) -> &mut dyn Reflect { todo!() }
|
/// # fn as_reflect(&self) -> &dyn Reflect { todo!() }
|
||||||
/// # fn apply(&mut self, value: &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!() }
|
/// # fn apply(&mut self, value: &dyn Reflect) { todo!() }
|
||||||
/// # fn reflect_ref(&self) -> ReflectRef { todo!() }
|
/// # fn set(&mut self, value: Box<dyn Reflect>) -> Result<(), Box<dyn Reflect>> { todo!() }
|
||||||
/// # fn reflect_mut(&mut self) -> ReflectMut { todo!() }
|
/// # fn reflect_ref(&self) -> ReflectRef { todo!() }
|
||||||
/// # fn reflect_owned(self: Box<Self>) -> ReflectOwned { todo!() }
|
/// # fn reflect_mut(&mut self) -> ReflectMut { todo!() }
|
||||||
/// # fn clone_value(&self) -> Box<dyn Reflect> { todo!() }
|
/// # fn reflect_owned(self: Box<Self>) -> ReflectOwned { todo!() }
|
||||||
|
/// # fn clone_value(&self) -> Box<dyn Reflect> { todo!() }
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
pub struct NonGenericTypeInfoCell(OnceBox<TypeInfo>);
|
///
|
||||||
|
/// [`TypePath`]: crate::TypePath
|
||||||
|
pub struct NonGenericTypeCell<T: TypedProperty>(OnceBox<T::Stored>);
|
||||||
|
|
||||||
impl NonGenericTypeInfoCell {
|
/// See [`NonGenericTypeCell`].
|
||||||
/// Initialize a [`NonGenericTypeInfoCell`] for non-generic types.
|
pub type NonGenericTypeInfoCell = NonGenericTypeCell<TypeInfo>;
|
||||||
|
|
||||||
|
impl<T: TypedProperty> NonGenericTypeCell<T> {
|
||||||
|
/// Initialize a [`NonGenericTypeCell`] for non-generic types.
|
||||||
pub const fn new() -> Self {
|
pub const fn new() -> Self {
|
||||||
Self(OnceBox::new())
|
Self(OnceBox::new())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a reference to the [`TypeInfo`] stored in the cell.
|
/// Returns a reference to the [`TypedProperty`] stored in the cell.
|
||||||
///
|
///
|
||||||
/// If there is no [`TypeInfo`] found, a new one will be generated from the given function.
|
/// If there is no entry found, a new one will be generated from the given function.
|
||||||
///
|
pub fn get_or_set<F>(&self, f: F) -> &T::Stored
|
||||||
/// [`TypeInfos`]: TypeInfo
|
|
||||||
pub fn get_or_set<F>(&self, f: F) -> &TypeInfo
|
|
||||||
where
|
where
|
||||||
F: FnOnce() -> TypeInfo,
|
F: FnOnce() -> T::Stored,
|
||||||
{
|
{
|
||||||
self.0.get_or_init(|| Box::new(f()))
|
self.0.get_or_init(|| Box::new(f()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A container for [`TypeInfo`] over generic types, allowing instances to be stored statically.
|
/// A container for [`TypedProperty`] over generic types, allowing instances to be stored statically.
|
||||||
///
|
///
|
||||||
/// This is specifically meant for use with generic types. If your type isn't generic,
|
/// This is specifically meant for use with generic types. If your type isn't generic,
|
||||||
/// then use [`NonGenericTypeInfoCell`] instead as it should be much more performant.
|
/// then use [`NonGenericTypeCell`] instead as it should be much more performant.
|
||||||
///
|
///
|
||||||
/// ## Example
|
/// `#[derive(TypePath)]` and [`impl_type_path`] should always be used over [`GenericTypePathCell`]
|
||||||
|
/// where possible.
|
||||||
|
///
|
||||||
|
/// ## Examples
|
||||||
|
///
|
||||||
|
/// Implementing [`TypeInfo`] with generics.
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// # use std::any::Any;
|
/// # use std::any::Any;
|
||||||
/// # use bevy_reflect::{Reflect, ReflectMut, ReflectOwned, ReflectRef, TupleStructInfo, Typed, TypeInfo, UnnamedField};
|
/// # use bevy_reflect::{DynamicTypePath, Reflect, ReflectMut, ReflectOwned, ReflectRef, TupleStructInfo, Typed, TypeInfo, UnnamedField};
|
||||||
/// use bevy_reflect::utility::GenericTypeInfoCell;
|
/// use bevy_reflect::utility::GenericTypeInfoCell;
|
||||||
///
|
///
|
||||||
/// struct Foo<T: Reflect>(T);
|
/// struct Foo<T>(T);
|
||||||
///
|
///
|
||||||
/// impl<T: Reflect> Typed for Foo<T> {
|
/// impl<T: Reflect> Typed for Foo<T> {
|
||||||
/// fn type_info() -> &'static TypeInfo {
|
/// fn type_info() -> &'static TypeInfo {
|
||||||
/// static CELL: GenericTypeInfoCell = GenericTypeInfoCell::new();
|
/// static CELL: GenericTypeInfoCell = GenericTypeInfoCell::new();
|
||||||
/// CELL.get_or_insert::<Self, _>(|| {
|
/// CELL.get_or_insert::<Self, _>(|| {
|
||||||
/// let fields = [UnnamedField::new::<T>(0)];
|
/// let fields = [UnnamedField::new::<T>(0)];
|
||||||
/// let info = TupleStructInfo::new::<Self>("Foo", &fields);
|
/// let info = TupleStructInfo::new::<Self>("Foo", &fields);
|
||||||
/// TypeInfo::TupleStruct(info)
|
/// TypeInfo::TupleStruct(info)
|
||||||
/// })
|
/// })
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
/// #
|
/// #
|
||||||
/// # impl<T: Reflect> Reflect for Foo<T> {
|
/// # impl<T: Reflect> Reflect for Foo<T> {
|
||||||
/// # fn type_name(&self) -> &str { todo!() }
|
/// # fn type_name(&self) -> &str { todo!() }
|
||||||
/// # fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { todo!() }
|
/// # fn get_type_path(&self) -> &dyn DynamicTypePath { todo!() }
|
||||||
/// # fn into_any(self: Box<Self>) -> Box<dyn Any> { todo!() }
|
/// # fn get_represented_type_info(&self) -> Option<&'static TypeInfo> { todo!() }
|
||||||
/// # fn as_any(&self) -> &dyn Any { todo!() }
|
/// # fn into_any(self: Box<Self>) -> Box<dyn Any> { todo!() }
|
||||||
/// # fn as_any_mut(&mut self) -> &mut dyn Any { todo!() }
|
/// # fn as_any(&self) -> &dyn Any { todo!() }
|
||||||
/// # fn into_reflect(self: Box<Self>) -> Box<dyn Reflect> { todo!() }
|
/// # fn as_any_mut(&mut self) -> &mut dyn Any { todo!() }
|
||||||
/// # fn as_reflect(&self) -> &dyn Reflect { todo!() }
|
/// # fn into_reflect(self: Box<Self>) -> Box<dyn Reflect> { todo!() }
|
||||||
/// # fn as_reflect_mut(&mut self) -> &mut dyn Reflect { todo!() }
|
/// # fn as_reflect(&self) -> &dyn Reflect { todo!() }
|
||||||
/// # fn apply(&mut self, value: &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!() }
|
/// # fn apply(&mut self, value: &dyn Reflect) { todo!() }
|
||||||
/// # fn reflect_ref(&self) -> ReflectRef { todo!() }
|
/// # fn set(&mut self, value: Box<dyn Reflect>) -> Result<(), Box<dyn Reflect>> { todo!() }
|
||||||
/// # fn reflect_mut(&mut self) -> ReflectMut { todo!() }
|
/// # fn reflect_ref(&self) -> ReflectRef { todo!() }
|
||||||
/// # fn reflect_owned(self: Box<Self>) -> ReflectOwned { todo!() }
|
/// # fn reflect_mut(&mut self) -> ReflectMut { todo!() }
|
||||||
/// # fn clone_value(&self) -> Box<dyn Reflect> { todo!() }
|
/// # fn reflect_owned(self: Box<Self>) -> ReflectOwned { todo!() }
|
||||||
|
/// # fn clone_value(&self) -> Box<dyn Reflect> { todo!() }
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
pub struct GenericTypeInfoCell(OnceBox<RwLock<HashMap<TypeId, &'static TypeInfo>>>);
|
///
|
||||||
|
/// Implementing [`TypePath`] with generics.
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
|
/// # use std::any::Any;
|
||||||
|
/// # use bevy_reflect::{DynamicTypePath, Reflect, ReflectMut, ReflectOwned, ReflectRef, TypeInfo, TypePath};
|
||||||
|
/// use bevy_reflect::utility::GenericTypePathCell;
|
||||||
|
///
|
||||||
|
/// struct Foo<T>(T);
|
||||||
|
///
|
||||||
|
/// impl<T: Reflect + TypePath> TypePath for Foo<T> {
|
||||||
|
/// fn type_path() -> &'static str {
|
||||||
|
/// static CELL: GenericTypePathCell = GenericTypePathCell::new();
|
||||||
|
/// CELL.get_or_insert::<Self, _>(|| format!("my_crate::foo::Foo<{}>", T::type_path()))
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// fn short_type_path() -> &'static str {
|
||||||
|
/// static CELL: GenericTypePathCell = GenericTypePathCell::new();
|
||||||
|
/// CELL.get_or_insert::<Self, _>(|| format!("Foo<{}>", T::short_type_path()))
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// #
|
||||||
|
/// # impl<T: Reflect> Reflect for Foo<T> {
|
||||||
|
/// # fn type_name(&self) -> &str { todo!() }
|
||||||
|
/// # fn get_type_path(&self) -> &dyn DynamicTypePath { todo!() }
|
||||||
|
/// # 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 apply(&mut self, value: &dyn Reflect) { 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!() }
|
||||||
|
/// # }
|
||||||
|
/// ```
|
||||||
|
/// [`impl_type_path`]: crate::impl_type_path
|
||||||
|
/// [`TypePath`]: crate::TypePath
|
||||||
|
pub struct GenericTypeCell<T: TypedProperty>(OnceBox<RwLock<HashMap<TypeId, &'static T::Stored>>>);
|
||||||
|
|
||||||
impl GenericTypeInfoCell {
|
/// See [`GenericTypeCell`].
|
||||||
/// Initialize a [`GenericTypeInfoCell`] for generic types.
|
pub type GenericTypeInfoCell = GenericTypeCell<TypeInfo>;
|
||||||
|
/// See [`GenericTypeCell`].
|
||||||
|
pub type GenericTypePathCell = GenericTypeCell<TypePathComponent>;
|
||||||
|
|
||||||
|
impl<T: TypedProperty> GenericTypeCell<T> {
|
||||||
|
/// Initialize a [`GenericTypeCell`] for generic types.
|
||||||
pub const fn new() -> Self {
|
pub const fn new() -> Self {
|
||||||
Self(OnceBox::new())
|
Self(OnceBox::new())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a reference to the [`TypeInfo`] stored in the cell.
|
/// Returns a reference to the [`TypedProperty`] stored in the cell.
|
||||||
///
|
///
|
||||||
/// This method will then return the correct [`TypeInfo`] reference for the given type `T`.
|
/// This method will then return the correct [`TypedProperty`] reference for the given type `T`.
|
||||||
/// If there is no [`TypeInfo`] found, a new one will be generated from the given function.
|
/// If there is no entry found, a new one will be generated from the given function.
|
||||||
pub fn get_or_insert<T, F>(&self, f: F) -> &TypeInfo
|
pub fn get_or_insert<G, F>(&self, f: F) -> &T::Stored
|
||||||
where
|
where
|
||||||
T: Any + ?Sized,
|
G: Any + ?Sized,
|
||||||
F: FnOnce() -> TypeInfo,
|
F: FnOnce() -> T::Stored,
|
||||||
{
|
{
|
||||||
let type_id = TypeId::of::<T>();
|
let type_id = TypeId::of::<G>();
|
||||||
// let mapping = self.0.get_or_init(|| Box::new(RwLock::default()));
|
// let mapping = self.0.get_or_init(|| Box::new(RwLock::default()));
|
||||||
let mapping = self.0.get_or_init(Box::default);
|
let mapping = self.0.get_or_init(Box::default);
|
||||||
if let Some(info) = mapping.read().get(&type_id) {
|
if let Some(info) = mapping.read().get(&type_id) {
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
use bevy_reflect::Reflect;
|
use bevy_reflect::{Reflect, TypePath};
|
||||||
|
|
||||||
#[derive(Reflect)]
|
#[derive(Reflect)]
|
||||||
struct Foo<T> {
|
struct Foo<T> {
|
||||||
@ -6,10 +6,11 @@ struct Foo<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Type that doesn't implement Reflect
|
// Type that doesn't implement Reflect
|
||||||
|
#[derive(TypePath)]
|
||||||
struct NoReflect(f32);
|
struct NoReflect(f32);
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let mut foo: Box<dyn Reflect> = Box::new(Foo::<NoReflect> { a: NoReflect(42.0) });
|
let mut foo: Box<dyn Reflect> = Box::new(Foo::<NoReflect> { a: NoReflect(42.0) });
|
||||||
// foo doesn't implement Reflect because NoReflect doesn't implement Reflect
|
// foo doesn't implement Reflect because NoReflect doesn't implement Reflect
|
||||||
foo.get_field::<NoReflect>("a").unwrap();
|
foo.get_field::<NoReflect>("a").unwrap();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,13 +1,13 @@
|
|||||||
error[E0599]: no method named `get_field` found for struct `Box<(dyn Reflect + 'static)>` in the current scope
|
error[E0599]: no method named `get_field` found for struct `Box<(dyn Reflect + 'static)>` in the current scope
|
||||||
--> tests/reflect_derive/generics.fail.rs:14:9
|
--> tests/reflect_derive/generics.fail.rs:15:9
|
||||||
|
|
|
|
||||||
14 | foo.get_field::<NoReflect>("a").unwrap();
|
15 | foo.get_field::<NoReflect>("a").unwrap();
|
||||||
| ^^^^^^^^^ method not found in `Box<dyn Reflect>`
|
| ^^^^^^^^^ method not found in `Box<dyn Reflect>`
|
||||||
|
|
||||||
error[E0277]: the trait bound `NoReflect: Reflect` is not satisfied
|
error[E0277]: the trait bound `NoReflect: Reflect` is not satisfied
|
||||||
--> tests/reflect_derive/generics.fail.rs:12:37
|
--> tests/reflect_derive/generics.fail.rs:13:37
|
||||||
|
|
|
|
||||||
12 | let mut foo: Box<dyn Reflect> = Box::new(Foo::<NoReflect> { a: NoReflect(42.0) });
|
13 | let mut foo: Box<dyn Reflect> = Box::new(Foo::<NoReflect> { a: NoReflect(42.0) });
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Reflect` is not implemented for `NoReflect`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Reflect` is not implemented for `NoReflect`
|
||||||
|
|
|
|
||||||
= help: the following other types implement trait `Reflect`:
|
= help: the following other types implement trait `Reflect`:
|
||||||
|
|||||||
@ -12,7 +12,7 @@ use bevy_core::cast_slice;
|
|||||||
use bevy_derive::EnumVariantMeta;
|
use bevy_derive::EnumVariantMeta;
|
||||||
use bevy_ecs::system::{lifetimeless::SRes, SystemParamItem};
|
use bevy_ecs::system::{lifetimeless::SRes, SystemParamItem};
|
||||||
use bevy_math::*;
|
use bevy_math::*;
|
||||||
use bevy_reflect::TypeUuid;
|
use bevy_reflect::{TypePath, TypeUuid};
|
||||||
use bevy_utils::{tracing::error, Hashed};
|
use bevy_utils::{tracing::error, Hashed};
|
||||||
use std::{collections::BTreeMap, hash::Hash, iter::FusedIterator};
|
use std::{collections::BTreeMap, hash::Hash, iter::FusedIterator};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
@ -25,7 +25,7 @@ pub const INDEX_BUFFER_ASSET_INDEX: u64 = 0;
|
|||||||
pub const VERTEX_ATTRIBUTE_BUFFER_ID: u64 = 10;
|
pub const VERTEX_ATTRIBUTE_BUFFER_ID: u64 = 10;
|
||||||
|
|
||||||
// TODO: allow values to be unloaded after been submitting to the GPU to conserve memory
|
// TODO: allow values to be unloaded after been submitting to the GPU to conserve memory
|
||||||
#[derive(Debug, TypeUuid, Clone)]
|
#[derive(Debug, TypeUuid, TypePath, Clone)]
|
||||||
#[uuid = "8ecbac0f-f545-4473-ad43-e1f4243af51e"]
|
#[uuid = "8ecbac0f-f545-4473-ad43-e1f4243af51e"]
|
||||||
pub struct Mesh {
|
pub struct Mesh {
|
||||||
primitive_topology: PrimitiveTopology,
|
primitive_topology: PrimitiveTopology,
|
||||||
|
|||||||
@ -6,7 +6,7 @@ use bevy_ecs::{
|
|||||||
reflect::ReflectMapEntities,
|
reflect::ReflectMapEntities,
|
||||||
};
|
};
|
||||||
use bevy_math::Mat4;
|
use bevy_math::Mat4;
|
||||||
use bevy_reflect::{Reflect, TypeUuid};
|
use bevy_reflect::{Reflect, TypePath, TypeUuid};
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
||||||
#[derive(Component, Debug, Default, Clone, Reflect)]
|
#[derive(Component, Debug, Default, Clone, Reflect)]
|
||||||
@ -24,7 +24,7 @@ impl MapEntities for SkinnedMesh {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, TypeUuid)]
|
#[derive(Debug, TypeUuid, TypePath)]
|
||||||
#[uuid = "b9f155a9-54ec-4026-988f-e0a03e99a76f"]
|
#[uuid = "b9f155a9-54ec-4026-988f-e0a03e99a76f"]
|
||||||
pub struct SkinnedMeshInverseBindposes(Box<[Mat4]>);
|
pub struct SkinnedMeshInverseBindposes(Box<[Mat4]>);
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
use super::ShaderDefVal;
|
use super::ShaderDefVal;
|
||||||
use crate::define_atomic_id;
|
use crate::define_atomic_id;
|
||||||
use bevy_asset::{AssetLoader, AssetPath, Handle, LoadContext, LoadedAsset};
|
use bevy_asset::{AssetLoader, AssetPath, Handle, LoadContext, LoadedAsset};
|
||||||
use bevy_reflect::TypeUuid;
|
use bevy_reflect::{TypePath, TypeUuid};
|
||||||
use bevy_utils::{tracing::error, BoxedFuture, HashMap};
|
use bevy_utils::{tracing::error, BoxedFuture, HashMap};
|
||||||
#[cfg(feature = "shader_format_glsl")]
|
#[cfg(feature = "shader_format_glsl")]
|
||||||
use naga::back::wgsl::WriterFlags;
|
use naga::back::wgsl::WriterFlags;
|
||||||
@ -31,7 +31,7 @@ pub enum ShaderReflectError {
|
|||||||
}
|
}
|
||||||
/// A shader, as defined by its [`ShaderSource`] and [`ShaderStage`](naga::ShaderStage)
|
/// A shader, as defined by its [`ShaderSource`] and [`ShaderStage`](naga::ShaderStage)
|
||||||
/// This is an "unprocessed" shader. It can contain preprocessor directives.
|
/// This is an "unprocessed" shader. It can contain preprocessor directives.
|
||||||
#[derive(Debug, Clone, TypeUuid)]
|
#[derive(Debug, Clone, TypeUuid, TypePath)]
|
||||||
#[uuid = "d95bc916-6c55-4de3-9622-37e7b6969fda"]
|
#[uuid = "d95bc916-6c55-4de3-9622-37e7b6969fda"]
|
||||||
pub struct Shader {
|
pub struct Shader {
|
||||||
source: Source,
|
source: Source,
|
||||||
|
|||||||
@ -69,7 +69,7 @@ bitflags::bitflags! {
|
|||||||
const VISIBLE_IN_HIERARCHY = 1 << 1;
|
const VISIBLE_IN_HIERARCHY = 1 << 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bevy_reflect::impl_reflect_value!(ComputedVisibilityFlags);
|
bevy_reflect::impl_reflect_value!((in bevy_render::view) ComputedVisibilityFlags);
|
||||||
bevy_reflect::impl_from_reflect_value!(ComputedVisibilityFlags);
|
bevy_reflect::impl_from_reflect_value!(ComputedVisibilityFlags);
|
||||||
|
|
||||||
/// Algorithmically-computed indication of whether an entity is visible and should be extracted for rendering
|
/// Algorithmically-computed indication of whether an entity is visible and should be extracted for rendering
|
||||||
|
|||||||
@ -8,7 +8,7 @@ use bevy_ecs::{
|
|||||||
reflect::{ReflectComponent, ReflectMapEntities},
|
reflect::{ReflectComponent, ReflectMapEntities},
|
||||||
world::World,
|
world::World,
|
||||||
};
|
};
|
||||||
use bevy_reflect::{Reflect, TypeRegistryArc, TypeUuid};
|
use bevy_reflect::{Reflect, TypePath, TypeRegistryArc, TypeUuid};
|
||||||
use bevy_utils::HashMap;
|
use bevy_utils::HashMap;
|
||||||
|
|
||||||
#[cfg(feature = "serialize")]
|
#[cfg(feature = "serialize")]
|
||||||
@ -26,7 +26,7 @@ use serde::Serialize;
|
|||||||
/// * adding the [`Handle<DynamicScene>`](bevy_asset::Handle) to an entity (the scene will only be
|
/// * adding the [`Handle<DynamicScene>`](bevy_asset::Handle) to an entity (the scene will only be
|
||||||
/// visible if the entity already has [`Transform`](bevy_transform::components::Transform) and
|
/// visible if the entity already has [`Transform`](bevy_transform::components::Transform) and
|
||||||
/// [`GlobalTransform`](bevy_transform::components::GlobalTransform) components)
|
/// [`GlobalTransform`](bevy_transform::components::GlobalTransform) components)
|
||||||
#[derive(Default, TypeUuid)]
|
#[derive(Default, TypeUuid, TypePath)]
|
||||||
#[uuid = "749479b1-fb8c-4ff8-a775-623aa76014f5"]
|
#[uuid = "749479b1-fb8c-4ff8-a775-623aa76014f5"]
|
||||||
pub struct DynamicScene {
|
pub struct DynamicScene {
|
||||||
pub resources: Vec<Box<dyn Reflect>>,
|
pub resources: Vec<Box<dyn Reflect>>,
|
||||||
|
|||||||
@ -4,7 +4,7 @@ use bevy_ecs::{
|
|||||||
reflect::{ReflectComponent, ReflectMapEntities, ReflectResource},
|
reflect::{ReflectComponent, ReflectMapEntities, ReflectResource},
|
||||||
world::World,
|
world::World,
|
||||||
};
|
};
|
||||||
use bevy_reflect::TypeUuid;
|
use bevy_reflect::{TypePath, TypeUuid};
|
||||||
|
|
||||||
use crate::{DynamicScene, InstanceInfo, SceneSpawnError};
|
use crate::{DynamicScene, InstanceInfo, SceneSpawnError};
|
||||||
|
|
||||||
@ -14,7 +14,7 @@ use crate::{DynamicScene, InstanceInfo, SceneSpawnError};
|
|||||||
/// * adding the [`Handle<Scene>`](bevy_asset::Handle) to an entity (the scene will only be
|
/// * adding the [`Handle<Scene>`](bevy_asset::Handle) to an entity (the scene will only be
|
||||||
/// visible if the entity already has [`Transform`](bevy_transform::components::Transform) and
|
/// visible if the entity already has [`Transform`](bevy_transform::components::Transform) and
|
||||||
/// [`GlobalTransform`](bevy_transform::components::GlobalTransform) components)
|
/// [`GlobalTransform`](bevy_transform::components::GlobalTransform) components)
|
||||||
#[derive(Debug, TypeUuid)]
|
#[derive(Debug, TypeUuid, TypePath)]
|
||||||
#[uuid = "c156503c-edd9-4ec7-8d33-dab392df03cd"]
|
#[uuid = "c156503c-edd9-4ec7-8d33-dab392df03cd"]
|
||||||
pub struct Scene {
|
pub struct Scene {
|
||||||
pub world: World,
|
pub world: World,
|
||||||
|
|||||||
@ -14,7 +14,7 @@ use bevy_ecs::{
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
use bevy_log::error;
|
use bevy_log::error;
|
||||||
use bevy_reflect::TypeUuid;
|
use bevy_reflect::{TypePath, TypeUuid};
|
||||||
use bevy_render::{
|
use bevy_render::{
|
||||||
extract_component::ExtractComponentPlugin,
|
extract_component::ExtractComponentPlugin,
|
||||||
mesh::{Mesh, MeshVertexBufferLayout},
|
mesh::{Mesh, MeshVertexBufferLayout},
|
||||||
@ -60,11 +60,11 @@ use crate::{
|
|||||||
/// ```
|
/// ```
|
||||||
/// # use bevy_sprite::{Material2d, MaterialMesh2dBundle};
|
/// # use bevy_sprite::{Material2d, MaterialMesh2dBundle};
|
||||||
/// # use bevy_ecs::prelude::*;
|
/// # use bevy_ecs::prelude::*;
|
||||||
/// # use bevy_reflect::TypeUuid;
|
/// # use bevy_reflect::{TypeUuid, TypePath};
|
||||||
/// # use bevy_render::{render_resource::{AsBindGroup, ShaderRef}, texture::Image, color::Color};
|
/// # use bevy_render::{render_resource::{AsBindGroup, ShaderRef}, texture::Image, color::Color};
|
||||||
/// # use bevy_asset::{Handle, AssetServer, Assets};
|
/// # use bevy_asset::{Handle, AssetServer, Assets};
|
||||||
///
|
///
|
||||||
/// #[derive(AsBindGroup, TypeUuid, Debug, Clone)]
|
/// #[derive(AsBindGroup, TypeUuid, TypePath, Debug, Clone)]
|
||||||
/// #[uuid = "f690fdae-d598-45ab-8225-97e2a3f056e0"]
|
/// #[uuid = "f690fdae-d598-45ab-8225-97e2a3f056e0"]
|
||||||
/// pub struct CustomMaterial {
|
/// pub struct CustomMaterial {
|
||||||
/// // Uniform bindings must implement `ShaderType`, which will be used to convert the value to
|
/// // Uniform bindings must implement `ShaderType`, which will be used to convert the value to
|
||||||
@ -111,7 +111,7 @@ use crate::{
|
|||||||
/// @group(1) @binding(2)
|
/// @group(1) @binding(2)
|
||||||
/// var color_sampler: sampler;
|
/// var color_sampler: sampler;
|
||||||
/// ```
|
/// ```
|
||||||
pub trait Material2d: AsBindGroup + Send + Sync + Clone + TypeUuid + Sized + 'static {
|
pub trait Material2d: AsBindGroup + Send + Sync + Clone + TypeUuid + TypePath + Sized {
|
||||||
/// Returns this material's vertex shader. If [`ShaderRef::Default`] is returned, the default mesh vertex shader
|
/// Returns this material's vertex shader. If [`ShaderRef::Default`] is returned, the default mesh vertex shader
|
||||||
/// will be used.
|
/// will be used.
|
||||||
fn vertex_shader() -> ShaderRef {
|
fn vertex_shader() -> ShaderRef {
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
use ab_glyph::{FontArc, FontVec, InvalidFont, OutlinedGlyph};
|
use ab_glyph::{FontArc, FontVec, InvalidFont, OutlinedGlyph};
|
||||||
use bevy_reflect::TypeUuid;
|
use bevy_reflect::{TypePath, TypeUuid};
|
||||||
use bevy_render::{
|
use bevy_render::{
|
||||||
render_resource::{Extent3d, TextureDimension, TextureFormat},
|
render_resource::{Extent3d, TextureDimension, TextureFormat},
|
||||||
texture::Image,
|
texture::Image,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, TypeUuid, Clone)]
|
#[derive(Debug, TypeUuid, TypePath, Clone)]
|
||||||
#[uuid = "97059ac6-c9ba-4da9-95b6-bed82c3ce198"]
|
#[uuid = "97059ac6-c9ba-4da9-95b6-bed82c3ce198"]
|
||||||
pub struct Font {
|
pub struct Font {
|
||||||
pub font: FontArc,
|
pub font: FontArc,
|
||||||
|
|||||||
@ -2,6 +2,7 @@ use crate::{error::TextError, Font, FontAtlas};
|
|||||||
use ab_glyph::{GlyphId, OutlinedGlyph, Point};
|
use ab_glyph::{GlyphId, OutlinedGlyph, Point};
|
||||||
use bevy_asset::{Assets, Handle};
|
use bevy_asset::{Assets, Handle};
|
||||||
use bevy_math::Vec2;
|
use bevy_math::Vec2;
|
||||||
|
use bevy_reflect::TypePath;
|
||||||
use bevy_reflect::TypeUuid;
|
use bevy_reflect::TypeUuid;
|
||||||
use bevy_render::texture::Image;
|
use bevy_render::texture::Image;
|
||||||
use bevy_sprite::TextureAtlas;
|
use bevy_sprite::TextureAtlas;
|
||||||
@ -10,7 +11,7 @@ use bevy_utils::HashMap;
|
|||||||
|
|
||||||
type FontSizeKey = FloatOrd;
|
type FontSizeKey = FloatOrd;
|
||||||
|
|
||||||
#[derive(TypeUuid)]
|
#[derive(TypeUuid, TypePath)]
|
||||||
#[uuid = "73ba778b-b6b5-4f45-982d-d21b6b86ace2"]
|
#[uuid = "73ba778b-b6b5-4f45-982d-d21b6b86ace2"]
|
||||||
pub struct FontAtlasSet {
|
pub struct FontAtlasSet {
|
||||||
font_atlases: HashMap<FontSizeKey, Vec<FontAtlas>>,
|
font_atlases: HashMap<FontSizeKey, Vec<FontAtlas>>,
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
use bevy::gltf::GltfPlugin;
|
use bevy::gltf::GltfPlugin;
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy::reflect::TypeUuid;
|
use bevy::reflect::{TypePath, TypeUuid};
|
||||||
use bevy::render::mesh::{MeshVertexAttribute, MeshVertexBufferLayout};
|
use bevy::render::mesh::{MeshVertexAttribute, MeshVertexBufferLayout};
|
||||||
use bevy::render::render_resource::*;
|
use bevy::render::render_resource::*;
|
||||||
use bevy::sprite::{
|
use bevy::sprite::{
|
||||||
@ -55,7 +55,7 @@ fn setup(
|
|||||||
/// This custom material uses barycentric coordinates from
|
/// This custom material uses barycentric coordinates from
|
||||||
/// `ATTRIBUTE_BARYCENTRIC` to shade a white border around each triangle. The
|
/// `ATTRIBUTE_BARYCENTRIC` to shade a white border around each triangle. The
|
||||||
/// thickness of the border is animated using the global time shader uniform.
|
/// thickness of the border is animated using the global time shader uniform.
|
||||||
#[derive(AsBindGroup, TypeUuid, Debug, Clone)]
|
#[derive(AsBindGroup, TypeUuid, TypePath, Debug, Clone)]
|
||||||
#[uuid = "50ffce9e-1582-42e9-87cb-2233724426c0"]
|
#[uuid = "50ffce9e-1582-42e9-87cb-2233724426c0"]
|
||||||
struct CustomMaterial {}
|
struct CustomMaterial {}
|
||||||
|
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
use bevy::{
|
use bevy::{
|
||||||
pbr::{MaterialPipeline, MaterialPipelineKey},
|
pbr::{MaterialPipeline, MaterialPipelineKey},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
reflect::TypeUuid,
|
reflect::{TypePath, TypeUuid},
|
||||||
render::{
|
render::{
|
||||||
mesh::{MeshVertexBufferLayout, PrimitiveTopology},
|
mesh::{MeshVertexBufferLayout, PrimitiveTopology},
|
||||||
render_resource::{
|
render_resource::{
|
||||||
@ -62,7 +62,7 @@ fn setup(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, AsBindGroup, TypeUuid, Debug, Clone)]
|
#[derive(Default, AsBindGroup, TypeUuid, TypePath, Debug, Clone)]
|
||||||
#[uuid = "050ce6ac-080a-4d8c-b6b5-b5bab7560d8f"]
|
#[uuid = "050ce6ac-080a-4d8c-b6b5-b5bab7560d8f"]
|
||||||
struct LineMaterial {
|
struct LineMaterial {
|
||||||
#[uniform(0)]
|
#[uniform(0)]
|
||||||
|
|||||||
@ -5,7 +5,7 @@ use bevy::{
|
|||||||
math::vec2,
|
math::vec2,
|
||||||
pbr::CascadeShadowConfigBuilder,
|
pbr::CascadeShadowConfigBuilder,
|
||||||
prelude::*,
|
prelude::*,
|
||||||
reflect::TypeUuid,
|
reflect::{TypePath, TypeUuid},
|
||||||
render::{
|
render::{
|
||||||
render_resource::{
|
render_resource::{
|
||||||
AsBindGroup, Extent3d, SamplerDescriptor, ShaderRef, TextureDimension, TextureFormat,
|
AsBindGroup, Extent3d, SamplerDescriptor, ShaderRef, TextureDimension, TextureFormat,
|
||||||
@ -689,7 +689,7 @@ impl Material for ColorGradientMaterial {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(AsBindGroup, Debug, Clone, TypeUuid)]
|
#[derive(AsBindGroup, Debug, Clone, TypeUuid, TypePath)]
|
||||||
#[uuid = "117f64fe-6844-1822-8926-e3ed372291c8"]
|
#[uuid = "117f64fe-6844-1822-8926-e3ed372291c8"]
|
||||||
pub struct ColorGradientMaterial {}
|
pub struct ColorGradientMaterial {}
|
||||||
|
|
||||||
|
|||||||
@ -3,12 +3,12 @@
|
|||||||
use bevy::{
|
use bevy::{
|
||||||
asset::{AssetLoader, LoadContext, LoadedAsset},
|
asset::{AssetLoader, LoadContext, LoadedAsset},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
reflect::TypeUuid,
|
reflect::{TypePath, TypeUuid},
|
||||||
utils::BoxedFuture,
|
utils::BoxedFuture,
|
||||||
};
|
};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, TypeUuid)]
|
#[derive(Debug, Deserialize, TypeUuid, TypePath)]
|
||||||
#[uuid = "39cadc56-aa9c-4543-8640-a018b74b5052"]
|
#[uuid = "39cadc56-aa9c-4543-8640-a018b74b5052"]
|
||||||
pub struct CustomAsset {
|
pub struct CustomAsset {
|
||||||
pub value: i32,
|
pub value: i32,
|
||||||
|
|||||||
@ -3,14 +3,14 @@ use bevy::audio::AddAudioSource;
|
|||||||
use bevy::audio::AudioPlugin;
|
use bevy::audio::AudioPlugin;
|
||||||
use bevy::audio::Source;
|
use bevy::audio::Source;
|
||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy::reflect::TypeUuid;
|
use bevy::reflect::{TypePath, TypeUuid};
|
||||||
use bevy::utils::Duration;
|
use bevy::utils::Duration;
|
||||||
|
|
||||||
// This struct usually contains the data for the audio being played.
|
// This struct usually contains the data for the audio being played.
|
||||||
// This is where data read from an audio file would be stored, for example.
|
// This is where data read from an audio file would be stored, for example.
|
||||||
// Implementing `TypeUuid` will automatically implement `Asset`.
|
// Implementing `TypeUuid` will automatically implement `Asset`.
|
||||||
// This allows the type to be registered as an asset.
|
// This allows the type to be registered as an asset.
|
||||||
#[derive(TypeUuid)]
|
#[derive(TypePath, TypeUuid)]
|
||||||
#[uuid = "c2090c23-78fd-44f1-8508-c89b1f3cec29"]
|
#[uuid = "c2090c23-78fd-44f1-8508-c89b1f3cec29"]
|
||||||
struct SineAudio {
|
struct SineAudio {
|
||||||
frequency: f32,
|
frequency: f32,
|
||||||
|
|||||||
@ -1,7 +1,11 @@
|
|||||||
//! A shader that uses dynamic data like the time since startup.
|
//! A shader that uses dynamic data like the time since startup.
|
||||||
//! The time data is in the globals binding which is part of the `mesh_view_bindings` shader import.
|
//! The time data is in the globals binding which is part of the `mesh_view_bindings` shader import.
|
||||||
|
|
||||||
use bevy::{prelude::*, reflect::TypeUuid, render::render_resource::*};
|
use bevy::{
|
||||||
|
prelude::*,
|
||||||
|
reflect::{TypePath, TypeUuid},
|
||||||
|
render::render_resource::*,
|
||||||
|
};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
App::new()
|
App::new()
|
||||||
@ -31,7 +35,7 @@ fn setup(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(AsBindGroup, TypeUuid, Debug, Clone)]
|
#[derive(AsBindGroup, TypeUuid, TypePath, Debug, Clone)]
|
||||||
#[uuid = "a3d71c04-d054-4946-80f8-ba6cfbc90cad"]
|
#[uuid = "a3d71c04-d054-4946-80f8-ba6cfbc90cad"]
|
||||||
struct CustomMaterial {}
|
struct CustomMaterial {}
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
use bevy::{
|
use bevy::{
|
||||||
asset::LoadState,
|
asset::LoadState,
|
||||||
prelude::*,
|
prelude::*,
|
||||||
reflect::TypeUuid,
|
reflect::{TypePath, TypeUuid},
|
||||||
render::render_resource::{AsBindGroup, ShaderRef},
|
render::render_resource::{AsBindGroup, ShaderRef},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -89,7 +89,7 @@ fn create_array_texture(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(AsBindGroup, Debug, Clone, TypeUuid)]
|
#[derive(AsBindGroup, Debug, Clone, TypeUuid, TypePath)]
|
||||||
#[uuid = "9c5a0ddf-1eaf-41b4-9832-ed736fd26af3"]
|
#[uuid = "9c5a0ddf-1eaf-41b4-9832-ed736fd26af3"]
|
||||||
struct ArrayTextureMaterial {
|
struct ArrayTextureMaterial {
|
||||||
#[texture(0, dimension = "2d_array")]
|
#[texture(0, dimension = "2d_array")]
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
use bevy::{
|
use bevy::{
|
||||||
pbr::{MaterialPipeline, MaterialPipelineKey},
|
pbr::{MaterialPipeline, MaterialPipelineKey},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
reflect::TypeUuid,
|
reflect::{TypePath, TypeUuid},
|
||||||
render::{
|
render::{
|
||||||
mesh::{MeshVertexAttribute, MeshVertexBufferLayout},
|
mesh::{MeshVertexAttribute, MeshVertexBufferLayout},
|
||||||
render_resource::{
|
render_resource::{
|
||||||
@ -57,7 +57,7 @@ fn setup(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This is the struct that will be passed to your shader
|
// This is the struct that will be passed to your shader
|
||||||
#[derive(AsBindGroup, Debug, Clone, TypeUuid)]
|
#[derive(AsBindGroup, Debug, Clone, TypeUuid, TypePath)]
|
||||||
#[uuid = "f690fdae-d598-45ab-8225-97e2a3f056e0"]
|
#[uuid = "f690fdae-d598-45ab-8225-97e2a3f056e0"]
|
||||||
pub struct CustomMaterial {
|
pub struct CustomMaterial {
|
||||||
#[uniform(0)]
|
#[uniform(0)]
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
use bevy::{
|
use bevy::{
|
||||||
pbr::{MaterialPipeline, MaterialPipelineKey},
|
pbr::{MaterialPipeline, MaterialPipelineKey},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
reflect::TypeUuid,
|
reflect::{TypePath, TypeUuid},
|
||||||
render::{
|
render::{
|
||||||
mesh::MeshVertexBufferLayout,
|
mesh::MeshVertexBufferLayout,
|
||||||
render_resource::{
|
render_resource::{
|
||||||
@ -75,7 +75,7 @@ impl Material for CustomMaterial {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This is the struct that will be passed to your shader
|
// This is the struct that will be passed to your shader
|
||||||
#[derive(AsBindGroup, TypeUuid, Debug, Clone)]
|
#[derive(AsBindGroup, TypeUuid, TypePath, Debug, Clone)]
|
||||||
#[uuid = "f690fdae-d598-45ab-8225-97e2a3f056e0"]
|
#[uuid = "f690fdae-d598-45ab-8225-97e2a3f056e0"]
|
||||||
#[bind_group_data(CustomMaterialKey)]
|
#[bind_group_data(CustomMaterialKey)]
|
||||||
pub struct CustomMaterial {
|
pub struct CustomMaterial {
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
use bevy::{
|
use bevy::{
|
||||||
prelude::*,
|
prelude::*,
|
||||||
reflect::TypeUuid,
|
reflect::{TypePath, TypeUuid},
|
||||||
render::render_resource::{AsBindGroup, ShaderRef},
|
render::render_resource::{AsBindGroup, ShaderRef},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -53,7 +53,7 @@ impl Material for CustomMaterial {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This is the struct that will be passed to your shader
|
// This is the struct that will be passed to your shader
|
||||||
#[derive(AsBindGroup, TypeUuid, Debug, Clone)]
|
#[derive(AsBindGroup, TypeUuid, TypePath, Debug, Clone)]
|
||||||
#[uuid = "f690fdae-d598-45ab-8225-97e2a3f056e0"]
|
#[uuid = "f690fdae-d598-45ab-8225-97e2a3f056e0"]
|
||||||
pub struct CustomMaterial {
|
pub struct CustomMaterial {
|
||||||
#[uniform(0)]
|
#[uniform(0)]
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
use bevy::{
|
use bevy::{
|
||||||
pbr::{MaterialPipeline, MaterialPipelineKey},
|
pbr::{MaterialPipeline, MaterialPipelineKey},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
reflect::TypeUuid,
|
reflect::{TypePath, TypeUuid},
|
||||||
render::{
|
render::{
|
||||||
mesh::MeshVertexBufferLayout,
|
mesh::MeshVertexBufferLayout,
|
||||||
render_resource::{
|
render_resource::{
|
||||||
@ -47,7 +47,7 @@ fn setup(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This is the struct that will be passed to your shader
|
// This is the struct that will be passed to your shader
|
||||||
#[derive(AsBindGroup, Clone, TypeUuid)]
|
#[derive(AsBindGroup, Clone, TypeUuid, TypePath)]
|
||||||
#[uuid = "4ee9c363-1124-4113-890e-199d81b00281"]
|
#[uuid = "4ee9c363-1124-4113-890e-199d81b00281"]
|
||||||
pub struct CustomMaterial {
|
pub struct CustomMaterial {
|
||||||
#[uniform(0)]
|
#[uniform(0)]
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
use bevy::{
|
use bevy::{
|
||||||
prelude::*,
|
prelude::*,
|
||||||
reflect::TypeUuid,
|
reflect::{TypePath, TypeUuid},
|
||||||
render::render_resource::{AsBindGroup, ShaderRef},
|
render::render_resource::{AsBindGroup, ShaderRef},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -66,7 +66,7 @@ fn rotate_camera(mut camera: Query<&mut Transform, With<MainCamera>>, time: Res<
|
|||||||
cam_transform.look_at(Vec3::ZERO, Vec3::Y);
|
cam_transform.look_at(Vec3::ZERO, Vec3::Y);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(AsBindGroup, Debug, Clone, TypeUuid)]
|
#[derive(AsBindGroup, Debug, Clone, TypeUuid, TypePath)]
|
||||||
#[uuid = "b62bb455-a72c-4b56-87bb-81e0554e234f"]
|
#[uuid = "b62bb455-a72c-4b56-87bb-81e0554e234f"]
|
||||||
pub struct CustomMaterial {
|
pub struct CustomMaterial {
|
||||||
#[texture(0)]
|
#[texture(0)]
|
||||||
|
|||||||
@ -6,7 +6,7 @@ use bevy::{
|
|||||||
core_pipeline::prepass::{DepthPrepass, MotionVectorPrepass, NormalPrepass},
|
core_pipeline::prepass::{DepthPrepass, MotionVectorPrepass, NormalPrepass},
|
||||||
pbr::{NotShadowCaster, PbrPlugin},
|
pbr::{NotShadowCaster, PbrPlugin},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
reflect::TypeUuid,
|
reflect::{TypePath, TypeUuid},
|
||||||
render::render_resource::{AsBindGroup, ShaderRef, ShaderType},
|
render::render_resource::{AsBindGroup, ShaderRef, ShaderType},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -155,7 +155,7 @@ fn setup(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This is the struct that will be passed to your shader
|
// This is the struct that will be passed to your shader
|
||||||
#[derive(AsBindGroup, TypeUuid, Debug, Clone)]
|
#[derive(AsBindGroup, TypePath, TypeUuid, Debug, Clone)]
|
||||||
#[uuid = "f690fdae-d598-45ab-8225-97e2a3f056e0"]
|
#[uuid = "f690fdae-d598-45ab-8225-97e2a3f056e0"]
|
||||||
pub struct CustomMaterial {
|
pub struct CustomMaterial {
|
||||||
#[uniform(0)]
|
#[uniform(0)]
|
||||||
@ -204,7 +204,7 @@ struct ShowPrepassSettings {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This shader simply loads the prepass texture and outputs it directly
|
// This shader simply loads the prepass texture and outputs it directly
|
||||||
#[derive(AsBindGroup, TypeUuid, Debug, Clone)]
|
#[derive(AsBindGroup, TypePath, TypeUuid, Debug, Clone)]
|
||||||
#[uuid = "0af99895-b96e-4451-bc12-c6b1c1c52750"]
|
#[uuid = "0af99895-b96e-4451-bc12-c6b1c1c52750"]
|
||||||
pub struct PrepassOutputMaterial {
|
pub struct PrepassOutputMaterial {
|
||||||
#[uniform(0)]
|
#[uniform(0)]
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
use bevy::{
|
use bevy::{
|
||||||
prelude::*,
|
prelude::*,
|
||||||
reflect::TypeUuid,
|
reflect::{TypePath, TypeUuid},
|
||||||
render::{
|
render::{
|
||||||
render_asset::RenderAssets,
|
render_asset::RenderAssets,
|
||||||
render_resource::{AsBindGroupError, PreparedBindGroup, *},
|
render_resource::{AsBindGroupError, PreparedBindGroup, *},
|
||||||
@ -85,7 +85,7 @@ fn setup(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, TypeUuid)]
|
#[derive(Debug, Clone, TypePath, TypeUuid)]
|
||||||
#[uuid = "8dd2b424-45a2-4a53-ac29-7ce356b2d5fe"]
|
#[uuid = "8dd2b424-45a2-4a53-ac29-7ce356b2d5fe"]
|
||||||
struct BindlessMaterial {
|
struct BindlessMaterial {
|
||||||
textures: Vec<Handle<Image>>,
|
textures: Vec<Handle<Image>>,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user