Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

stable reflect type name #5805

Closed
wants to merge 96 commits into from
Closed
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
96 commits
Select commit Hold shift + click to select a range
c9ad9a5
add `TypeName` and `ReflectTypeName`
tguichaoua Aug 26, 2022
bab4ae5
replace `Reflect::type_name` by `ReflectTypeName::type_name`
tguichaoua Aug 26, 2022
06e9258
fix tuple TypeName
tguichaoua Aug 26, 2022
312659a
impl_reflect_value use modul less name
tguichaoua Aug 26, 2022
6982351
update tests
tguichaoua Aug 26, 2022
317372f
update `Reflect::represents`
tguichaoua Aug 26, 2022
30a663f
fix ci
tguichaoua Aug 26, 2022
3a8958a
fix examples/3d/skybox
tguichaoua Aug 26, 2022
a710c17
Update crates/bevy_reflect/src/type_name.rs
tguichaoua Aug 27, 2022
006c8e8
Update crates/bevy_reflect/src/type_name.rs
tguichaoua Aug 27, 2022
a7e8dd6
fix the requirement of importing `ReflectTypeName`
tguichaoua Aug 27, 2022
8eeb06d
Merge branch 'reflect/type_name' of https://github.com/tguichaoua/bev…
tguichaoua Aug 27, 2022
140e009
drop Cow in TypeName
tguichaoua Aug 27, 2022
6fba583
remove majority of `any::type_name`
tguichaoua Aug 27, 2022
4f17b0c
fix ci + doc
tguichaoua Aug 27, 2022
c135dae
remove `ReflectTypeName`
tguichaoua Aug 27, 2022
11889a1
allow custom type name for impl_reflect_value
tguichaoua Aug 27, 2022
fe2ff0b
glam type name
tguichaoua Aug 27, 2022
e7fc222
fix glam tests
tguichaoua Aug 27, 2022
ca5e875
fix GenericDataCell soft lock
tguichaoua Aug 27, 2022
0563cf9
Update crates/bevy_reflect/bevy_reflect_derive/src/derive_data.rs
tguichaoua Aug 28, 2022
be2b3d5
Update crates/bevy_reflect/bevy_reflect_derive/src/reflect_value.rs
tguichaoua Aug 28, 2022
8cd535a
Update crates/bevy_reflect/src/impls/std.rs
tguichaoua Aug 28, 2022
8af97fc
Update crates/bevy_reflect/src/type_info.rs
tguichaoua Aug 28, 2022
eb1e2f6
Update crates/bevy_reflect/src/utility.rs
tguichaoua Aug 28, 2022
80b22d8
Update crates/bevy_reflect/src/utility.rs
tguichaoua Aug 28, 2022
9682cec
remove unnecessary `as_ref()`
tguichaoua Aug 28, 2022
d9d3afa
rm last usage of `ReflectTypeName`
tguichaoua Aug 28, 2022
329f248
rm old comment
tguichaoua Aug 28, 2022
e6a3ce8
refactor(reflect_derive): if-else into match
tguichaoua Aug 28, 2022
4722a19
Update crates/bevy_reflect/bevy_reflect_derive/src/impls/type_name.rs
tguichaoua Aug 28, 2022
aecba77
Update crates/bevy_reflect/bevy_reflect_derive/src/impls/type_name.rs
tguichaoua Aug 28, 2022
4fd9a53
Merge branch 'reflect/type_name' of https://github.com/tguichaoua/bev…
tguichaoua Aug 28, 2022
b2be7e9
reflect_derive: cleanup impl_type_name
tguichaoua Aug 28, 2022
9ea7f9a
reflect_derive: impl_type_name accept ReflectMeta as argument
tguichaoua Aug 28, 2022
b697bc3
NamedReflectValueDef::get_reflected_type_name
tguichaoua Aug 28, 2022
a6654c1
reflect_derive: refactoring
tguichaoua Aug 28, 2022
34f57b7
avoid usage of `stringify!`
tguichaoua Aug 28, 2022
26460dd
fix fmt in doc code
tguichaoua Aug 28, 2022
f4a6655
fix utility doc
tguichaoua Aug 28, 2022
45eca48
rm useless `as_ref()`
tguichaoua Aug 28, 2022
e2e3a02
example: add comment
tguichaoua Aug 28, 2022
3f2ee5d
reflect_derive: cleanup get_type_name_attribute
tguichaoua Aug 28, 2022
ba4da30
doc: impl_type_name
tguichaoua Aug 28, 2022
d8987f4
doc: derive_type_name
tguichaoua Aug 28, 2022
d155529
TypeName is 'static
tguichaoua Aug 28, 2022
0c25180
doc: TypeName
tguichaoua Aug 28, 2022
b0a6604
doc: GenericTypeNameCell
tguichaoua Aug 28, 2022
9ef1454
impl TypeName on `dyn Reflect`
tguichaoua Aug 28, 2022
83e3500
fix docs
tguichaoua Aug 28, 2022
b1411ab
fix test
tguichaoua Aug 28, 2022
86ab916
Update crates/bevy_reflect/bevy_reflect_derive/src/lib.rs
tguichaoua Aug 29, 2022
5e87d13
Update crates/bevy_reflect/bevy_reflect_derive/src/lib.rs
tguichaoua Aug 29, 2022
7295583
Update crates/bevy_reflect/bevy_reflect_derive/src/lib.rs
tguichaoua Aug 29, 2022
85739b8
Update crates/bevy_reflect/src/type_name.rs
tguichaoua Aug 29, 2022
c9ec3e8
Update crates/bevy_reflect/src/type_name.rs
tguichaoua Aug 29, 2022
ef4986e
Update crates/bevy_reflect/src/type_name.rs
tguichaoua Aug 29, 2022
4feef51
Update crates/bevy_reflect/src/utility.rs
tguichaoua Aug 29, 2022
6f750c6
Update crates/bevy_reflect/bevy_reflect_derive/src/lib.rs
tguichaoua Aug 29, 2022
563cb75
Update crates/bevy_reflect/bevy_reflect_derive/src/lib.rs
tguichaoua Aug 29, 2022
9c3a034
Update crates/bevy_reflect/bevy_reflect_derive/src/lib.rs
tguichaoua Aug 29, 2022
dbd4bde
Update crates/bevy_reflect/bevy_reflect_derive/src/lib.rs
tguichaoua Aug 29, 2022
f67f1af
Update crates/bevy_reflect/src/type_name.rs
tguichaoua Aug 29, 2022
3aa805a
reflect_derive: update derive_type_name doc
tguichaoua Aug 29, 2022
188b2f3
update TypeName doc
tguichaoua Aug 29, 2022
08e2c8f
fix example comment
tguichaoua Aug 29, 2022
a7aa4de
impl TypeName on Dynamic* structs
tguichaoua Aug 29, 2022
184d335
register_type_data : use TypeName
tguichaoua Aug 30, 2022
fa9bdb4
update some doc links
tguichaoua Aug 30, 2022
9dda494
TypeUuidDynamic : use TypeName
tguichaoua Aug 30, 2022
3668407
relive last std::any::type_name
tguichaoua Aug 30, 2022
b449fbe
update std types TypeName
tguichaoua Aug 30, 2022
4d42f12
Merge branch 'main' into reflect/type_name
tguichaoua Aug 30, 2022
a4c93cf
remove extra spaces
tguichaoua Aug 30, 2022
2afbd85
Merge branch 'main' into reflect/type_name
tguichaoua Aug 31, 2022
fab49b1
Merge branch 'main' into reflect/type_name
tguichaoua Sep 5, 2022
c914af0
rename `TypeName` into `TypePath`
tguichaoua Sep 5, 2022
86e12d2
rename `GenericTypeNameCell` into `GenericTypePathCell`
tguichaoua Sep 5, 2022
cb84e1e
add other methods on `TypePath`
tguichaoua Sep 5, 2022
60ff2b7
fix type path generation
tguichaoua Sep 5, 2022
e4efa1b
fix ci & doc
tguichaoua Sep 5, 2022
02aabfa
refix ci & doc
tguichaoua Sep 5, 2022
afda7b3
fix doc
tguichaoua Sep 5, 2022
aaef516
Merge branch 'main' into reflect/type_name
tguichaoua Sep 14, 2022
ddf4726
refactor: TypePathOptions::parse_meta_list
tguichaoua Sep 14, 2022
0b0cf93
fix tuple impl
tguichaoua Sep 14, 2022
88d2082
fix ci
tguichaoua Sep 14, 2022
4f9d953
minor doc fix
tguichaoua Sep 15, 2022
c28c3b4
remove empty space
tguichaoua Sep 15, 2022
a46a028
Merge branch 'main' into reflect/type_name
tguichaoua Sep 20, 2022
5303da3
fix merge
tguichaoua Sep 20, 2022
5a70e6f
Merge branch 'main' into reflect/type_name
tguichaoua Sep 21, 2022
de07bd5
fix merge error
tguichaoua Sep 21, 2022
858a6c2
fix ser/de for option
tguichaoua Sep 21, 2022
504495b
Merge branch 'main' into reflect/type_name
tguichaoua Oct 16, 2022
226dad2
fix CI
tguichaoua Oct 16, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions crates/bevy_animation/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use bevy_ecs::{
};
use bevy_hierarchy::Children;
use bevy_math::{Quat, Vec3};
use bevy_reflect::{Reflect, TypeUuid};
use bevy_reflect::{Reflect, TypeName, TypeUuid};
use bevy_time::Time;
use bevy_transform::{prelude::Transform, TransformSystem};
use bevy_utils::{tracing::warn, HashMap};
Expand Down Expand Up @@ -60,7 +60,7 @@ pub struct EntityPath {
}

/// A list of [`VariableCurve`], and the [`EntityPath`] to which they apply.
#[derive(Clone, TypeUuid, Debug, Default)]
#[derive(Clone, TypeUuid, Debug, Default, TypeName)]
#[uuid = "d81b7179-0448-4eb0-89fe-c067222725bf"]
pub struct AnimationClip {
curves: HashMap<EntityPath, Vec<VariableCurve>>,
Expand Down
7 changes: 4 additions & 3 deletions crates/bevy_asset/src/asset_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ pub struct AssetServerInternal {
/// use bevy_asset::{AssetServer, Handle};
/// use bevy_ecs::prelude::{Commands, Res};
///
/// # #[derive(Debug, bevy_reflect::TypeUuid)]
/// # #[derive(Debug, bevy_reflect::TypeUuid, bevy_reflect::TypeName)]
/// # #[uuid = "00000000-0000-0000-0000-000000000000"]
/// # struct Image;
///
Expand Down Expand Up @@ -647,10 +647,11 @@ mod test {
use crate::{loader::LoadedAsset, update_asset_storage_system};
use bevy_app::App;
use bevy_ecs::prelude::*;
use bevy_reflect::TypeUuid;
use bevy_reflect::{TypeName, TypeUuid};
use bevy_utils::BoxedFuture;

#[derive(Debug, TypeUuid)]
// FIXME: reflect only the type name
tguichaoua marked this conversation as resolved.
Show resolved Hide resolved
#[derive(Debug, TypeUuid, TypeName)]
tguichaoua marked this conversation as resolved.
Show resolved Hide resolved
#[uuid = "a5189b72-0572-4290-a2e0-96f73a491c44"]
struct PngAsset;

Expand Down
3 changes: 2 additions & 1 deletion crates/bevy_asset/src/assets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -420,12 +420,13 @@ macro_rules! load_internal_asset {
#[cfg(test)]
mod tests {
use bevy_app::App;
use bevy_reflect::TypeName;

use crate::{AddAsset, Assets};

#[test]
fn asset_overwriting() {
#[derive(bevy_reflect::TypeUuid)]
#[derive(bevy_reflect::TypeUuid, TypeName)]
#[uuid = "44115972-f31b-46e5-be5c-2b9aece6a52f"]
struct MyAsset;
let mut app = App::new();
Expand Down
5 changes: 3 additions & 2 deletions crates/bevy_asset/src/loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use crate::{
use anyhow::Error;
use anyhow::Result;
use bevy_ecs::system::{Res, ResMut};
use bevy_reflect::TypeName;
use bevy_reflect::{TypeUuid, TypeUuidDynamic};
use bevy_utils::{BoxedFuture, HashMap};
use crossbeam_channel::{Receiver, Sender};
Expand Down Expand Up @@ -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
/// with [`Assets::add`] or load them from the filesystem with [`AssetServer::load`].
pub trait Asset: TypeUuid + AssetDynamic {}
pub trait Asset: TypeUuid + AssetDynamic + TypeName {}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Heres an idea (which I haven't yet fully sorted out my opinion on) : now that we're allowing people to define "canonical" names, maybe we should replace TypeUuid with that? Not something to decide or implement in this pr, but a good thought experiment.

It would give the people the option to fall back to the default type name if they don't want the extra boilerplate:

// current
#[derive(TypeUuid)]
#[type_uuid("7a14806a-672b-443b-8d16-4f18afefa463")]
struct MyAsset {
}

// replaced with type name
#[derive(TypeName)]
struct MyAsset {
}

Library authors would have the option to define a shorter / "stable to module refactors" type name like:

#[derive(TypeName)]
#[type_name("some_lib::MyAsset")]
struct MyAsset {
}

The biggest wins are:

  1. Defining assets is "easier". sorting out how to generate a UUID is a hurdle for new users
  2. Consistency with Component reflection / the bevy scene system (which will be relevant if/when we add "inline assets" to bevy scenes ... which we should imo).

The question we should ask is "if its good enough for components, why isn't it good enough for Assets"?

Some downsides are:

  1. TypeUuid is "small" and cheap to compare. Comparing TypeNames is more expensive. On asset registration during app startup, we would need to correlate to the asset TypeId and refactor some code to rely on that over TypeUuid.
  2. Users that define custom assets with the "default" type name derive might accidentally break their assets when they move the type to a new module.
  3. Higher risk of collisions. If two users define the same TypeName (either manually or by creating the same crate name with the same path), then those assets will be treated as "the same". UUID collision risk is essentially zero.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

However, requiring the crate name in TypeName does largely alleviate problem (3). Weirdness when pulling in two crates with the same names and type paths is a corner case I think I'm willing to accept.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Weirdness when pulling in two crates with the same names and type paths is a corner case I think I'm willing to accept.

What about two incompatible versions of the same crate? Even if they aren't used in the same version of the game, you could still have assets using the old version lying around. With uuid's that is easy to fix by generating a new uuid every time there is a breaking change, but for type names you would have to rename the type in code (and all usages) and make sure you don't accidentally every reuse the name again.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about two incompatible versions of the same crate? Even if they aren't used in the same version of the game, you could still have assets using the old version lying around. With uuid's that is easy to fix by generating a new uuid every time there is a breaking change, but for type names you would have to rename the type in code (and all usages) and make sure you don't accidentally every reuse the name again.

Haven't given this a ton of thought yet, but I think asset versioning should be done in the AssetLoader trait, not by changing the identity. Having a stable identity across versions feels like the right way to establish continuity / link loader versions.


/// An untyped version of the [`Asset`] trait.
pub trait AssetDynamic: Downcast + TypeUuidDynamic + Send + Sync + 'static {}
impl_downcast!(AssetDynamic);

impl<T> Asset for T where T: TypeUuid + AssetDynamic + TypeUuidDynamic {}
impl<T> Asset for T where T: TypeUuid + AssetDynamic + TypeUuidDynamic + TypeName {}

impl<T> AssetDynamic for T where T: Send + Sync + 'static + TypeUuidDynamic {}

Expand Down
4 changes: 2 additions & 2 deletions crates/bevy_audio/src/audio_output.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::{Audio, AudioSource, Decodable};
use bevy_asset::{Asset, Assets};
use bevy_ecs::system::{NonSend, Res, ResMut};
use bevy_reflect::TypeUuid;
use bevy_reflect::{TypeName, TypeUuid};
use bevy_utils::tracing::warn;
use rodio::{OutputStream, OutputStreamHandle, Sink, Source};
use std::marker::PhantomData;
Expand Down Expand Up @@ -116,7 +116,7 @@ pub fn play_queued_audio_system<Source: Asset + Decodable>(
/// }
/// ```
///
#[derive(TypeUuid)]
#[derive(TypeUuid, TypeName)]
#[uuid = "8BEE570C-57C2-4FC0-8CFB-983A22F7D981"]
pub struct AudioSink {
// This field is an Option in order to allow us to have a safe drop that will detach the sink.
Expand Down
4 changes: 2 additions & 2 deletions crates/bevy_audio/src/audio_source.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use anyhow::Result;
use bevy_asset::{AssetLoader, LoadContext, LoadedAsset};
use bevy_reflect::TypeUuid;
use bevy_reflect::{TypeName, TypeUuid};
use bevy_utils::BoxedFuture;
use std::{io::Cursor, sync::Arc};

/// A source of audio data
#[derive(Debug, Clone, TypeUuid)]
#[derive(Debug, Clone, TypeUuid, TypeName)]
#[uuid = "7a14806a-672b-443b-8d16-4f18afefa463"]
pub struct AudioSource {
/// Raw data of the audio source
Expand Down
10 changes: 5 additions & 5 deletions crates/bevy_gltf/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use bevy_app::prelude::*;
use bevy_asset::{AddAsset, Handle};
use bevy_ecs::{prelude::Component, reflect::ReflectComponent};
use bevy_pbr::StandardMaterial;
use bevy_reflect::{Reflect, TypeUuid};
use bevy_reflect::{Reflect, TypeName, TypeUuid};
use bevy_render::mesh::Mesh;
use bevy_scene::Scene;

Expand All @@ -29,7 +29,7 @@ impl Plugin for GltfPlugin {
}

/// Representation of a loaded glTF file.
#[derive(Debug, TypeUuid)]
#[derive(Debug, TypeUuid, TypeName)]
#[uuid = "5c7d5f8a-f7b0-4e45-a09e-406c0372fea2"]
pub struct Gltf {
pub scenes: Vec<Handle<Scene>>,
Expand All @@ -49,7 +49,7 @@ pub struct Gltf {

/// A glTF node with all of its child nodes, its [`GltfMesh`] and
/// [`Transform`](bevy_transform::prelude::Transform).
#[derive(Debug, Clone, TypeUuid)]
#[derive(Debug, Clone, TypeUuid, TypeName)]
#[uuid = "dad74750-1fd6-460f-ac51-0a7937563865"]
pub struct GltfNode {
pub children: Vec<GltfNode>,
Expand All @@ -58,14 +58,14 @@ pub struct GltfNode {
}

/// A glTF mesh, which may consist of multiple [`GltfPrimitives`](GltfPrimitive).
#[derive(Debug, Clone, TypeUuid)]
#[derive(Debug, Clone, TypeUuid, TypeName)]
#[uuid = "8ceaec9a-926a-4f29-8ee3-578a69f42315"]
pub struct GltfMesh {
pub primitives: Vec<GltfPrimitive>,
}

/// Part of a [`GltfMesh`] that consists of a [`Mesh`] and an optional [`StandardMaterial`].
#[derive(Debug, Clone, TypeUuid)]
#[derive(Debug, Clone, TypeUuid, TypeName)]
#[uuid = "cbfca302-82fd-41cb-af77-cab6b3d50af1"]
pub struct GltfPrimitive {
pub mesh: Handle<Mesh>,
Expand Down
10 changes: 6 additions & 4 deletions crates/bevy_pbr/src/material.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use bevy_ecs::{
},
world::FromWorld,
};
use bevy_reflect::TypeUuid;
use bevy_reflect::{TypeName, TypeUuid};
use bevy_render::{
extract_component::ExtractComponentPlugin,
mesh::{Mesh, MeshVertexBufferLayout},
Expand Down Expand Up @@ -57,11 +57,11 @@ use std::marker::PhantomData;
/// ```
/// # use bevy_pbr::{Material, MaterialMeshBundle};
/// # use bevy_ecs::prelude::*;
/// # use bevy_reflect::TypeUuid;
/// # use bevy_reflect::{TypeUuid, TypeName};
/// # use bevy_render::{render_resource::{AsBindGroup, ShaderRef}, texture::Image, color::Color};
/// # use bevy_asset::{Handle, AssetServer, Assets};
///
/// #[derive(AsBindGroup, TypeUuid, Debug, Clone)]
/// #[derive(AsBindGroup, TypeUuid, TypeName, Debug, Clone)]
/// #[uuid = "f690fdae-d598-45ab-8225-97e2a3f056e0"]
/// pub struct CustomMaterial {
/// // Uniform bindings must implement `ShaderType`, which will be used to convert the value to
Expand Down Expand Up @@ -108,7 +108,9 @@ use std::marker::PhantomData;
/// @group(1) @binding(2)
/// var color_sampler: sampler;
/// ```
pub trait Material: AsBindGroup + Send + Sync + Clone + TypeUuid + Sized + 'static {
pub trait Material:
AsBindGroup + Send + Sync + Clone + TypeUuid + TypeName + Sized + 'static
{
/// Returns this material's vertex shader. If [`ShaderRef::Default`] is returned, the default mesh vertex shader
/// will be used.
fn vertex_shader() -> ShaderRef {
Expand Down
4 changes: 2 additions & 2 deletions crates/bevy_pbr/src/pbr_material.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::{AlphaMode, Material, MaterialPipeline, MaterialPipelineKey, PBR_SHADER_HANDLE};
use bevy_asset::Handle;
use bevy_math::Vec4;
use bevy_reflect::TypeUuid;
use bevy_reflect::{TypeName, TypeUuid};
use bevy_render::{
color::Color, mesh::MeshVertexBufferLayout, render_asset::RenderAssets, render_resource::*,
texture::Image,
Expand All @@ -12,7 +12,7 @@ use bevy_render::{
/// <https://google.github.io/filament/Material%20Properties.pdf>.
///
/// May be created directly from a [`Color`] or an [`Image`].
#[derive(AsBindGroup, Debug, Clone, TypeUuid)]
#[derive(AsBindGroup, Debug, Clone, TypeUuid, TypeName)]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Kind of just riffing on my previous comment about "replacing TypeUuid with TypeName", but I'm not a huge fan of adding "yet another" required derive in places like this.

#[uuid = "7494888b-c082-457b-aacf-517228cc0c22"]
#[bind_group_data(StandardMaterialKey)]
#[uniform(0, StandardMaterialUniform)]
Expand Down
42 changes: 38 additions & 4 deletions crates/bevy_reflect/bevy_reflect_derive/src/derive_data.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
use crate::container_attributes::ReflectTraits;
use crate::field_attributes::{parse_field_attrs, ReflectFieldAttr};
use quote::quote;
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,
};
use syn::punctuated::Punctuated;
use syn::spanned::Spanned;
use syn::{Data, DeriveInput, Field, Fields, Generics, Ident, Meta, Path, Token, Type, Variant};
use syn::{
Data, DeriveInput, Field, Fields, Generics, Ident, Lit, Meta, NestedMeta, Path, Token, Type,
Variant,
};

pub(crate) enum ReflectDerive<'a> {
Struct(ReflectStruct<'a>),
Expand Down Expand Up @@ -35,6 +41,8 @@ pub(crate) struct ReflectMeta<'a> {
type_name: &'a Ident,
/// The generics defined on this type.
generics: &'a Generics,
/// Override the default type name for `ReflectTypeName`.
reflected_type_name: Option<String>,
/// A cached instance of the path to the `bevy_reflect` crate.
bevy_reflect_path: Path,
}
Expand Down Expand Up @@ -110,6 +118,8 @@ impl<'a> ReflectDerive<'a> {
// Should indicate whether `#[reflect_value]` was used
let mut force_reflect_value = false;

let mut reflected_type_name = None;

for attribute in input.attrs.iter().filter_map(|attr| attr.parse_meta().ok()) {
let meta_list = if let Meta::List(meta_list) = attribute {
meta_list
Expand All @@ -123,11 +133,14 @@ impl<'a> ReflectDerive<'a> {
} else if ident == REFLECT_VALUE_ATTRIBUTE_NAME {
force_reflect_value = true;
traits = ReflectTraits::from_nested_metas(&meta_list.nested);
} else if ident == TYPE_NAME_ATTRIBUTE_NAME {
let type_name = get_type_name_attribute(&meta_list.nested).ok_or_else(||syn::Error::new(meta_list.span(), format!("The attribute `{TYPE_NAME_ATTRIBUTE_NAME}` require a single literal string. \n\n #[{TYPE_NAME_ATTRIBUTE_NAME}(\"my_lib::foo\")]")) )?;
tguichaoua marked this conversation as resolved.
Show resolved Hide resolved
reflected_type_name = Some(type_name);
}
tguichaoua marked this conversation as resolved.
Show resolved Hide resolved
}
}

let meta = ReflectMeta::new(&input.ident, &input.generics, traits);
let meta = ReflectMeta::new(&input.ident, &input.generics, traits, reflected_type_name);

if force_reflect_value {
return Ok(Self::Value(meta));
Expand Down Expand Up @@ -211,11 +224,17 @@ impl<'a> ReflectDerive<'a> {
}

impl<'a> ReflectMeta<'a> {
pub fn new(type_name: &'a Ident, generics: &'a Generics, traits: ReflectTraits) -> Self {
pub fn new(
type_name: &'a Ident,
generics: &'a Generics,
traits: ReflectTraits,
reflected_type_name: Option<String>,
) -> Self {
Self {
traits,
type_name,
generics,
reflected_type_name,
bevy_reflect_path: utility::get_bevy_reflect_path(),
}
}
Expand All @@ -235,6 +254,11 @@ impl<'a> ReflectMeta<'a> {
self.generics
}

/// Override the default type name for `TypeName`.
pub fn reflected_type_name(&self) -> Option<&str> {
self.reflected_type_name.as_deref()
}

/// The cached `bevy_reflect` path.
pub fn bevy_reflect_path(&self) -> &Path {
&self.bevy_reflect_path
Expand Down Expand Up @@ -310,3 +334,13 @@ impl<'a> ReflectEnum<'a> {
&self.variants
}
}

/// Extracts the type name attribute or returns [`None`].
fn get_type_name_attribute(nested_metas: &Punctuated<NestedMeta, Comma>) -> Option<String> {
(nested_metas.len() == 1)
.then(|| match nested_metas.first().unwrap() {
NestedMeta::Lit(Lit::Str(s)) => Some(s.value()),
_ => None,
})
.flatten()
tguichaoua marked this conversation as resolved.
Show resolved Hide resolved
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> TokenStream {
if let #bevy_reflect_path::ReflectRef::Enum(#ref_value) = #ref_value.reflect_ref() {
match #ref_value.variant_name() {
#(#variant_names => Some(#variant_constructors),)*
name => panic!("variant with name `{}` does not exist on enum `{}`", name, std::any::type_name::<Self>()),
name => panic!("variant with name `{}` does not exist on enum `{}`", name, <Self as #bevy_reflect_path::TypeName>::name()),
}
} else {
None
Expand Down
20 changes: 13 additions & 7 deletions crates/bevy_reflect/bevy_reflect_derive/src/impls/enums.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::derive_data::{EnumVariantFields, ReflectEnum, StructField};
use crate::enum_utility::{get_variant_constructors, EnumVariantConstructors};
use crate::impls::impl_typed;
use crate::impls::{impl_type_name, impl_typed};
use proc_macro::TokenStream;
use proc_macro2::{Ident, Span};
use quote::quote;
Expand Down Expand Up @@ -64,6 +64,13 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> TokenStream {
bevy_reflect_path,
);

let type_name_impl = impl_type_name(
enum_name,
reflect_enum.meta().generics(),
reflect_enum.meta().reflected_type_name(),
bevy_reflect_path,
);

let get_type_registration_impl = reflect_enum.meta().get_type_registration();
let (impl_generics, ty_generics, where_clause) =
reflect_enum.meta().generics().split_for_impl();
Expand All @@ -73,6 +80,8 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> TokenStream {

#typed_impl

#type_name_impl

impl #impl_generics #bevy_reflect_path::Enum for #enum_name #ty_generics #where_clause {
fn field(&self, #ref_name: &str) -> Option<&dyn #bevy_reflect_path::Reflect> {
match self {
Expand Down Expand Up @@ -150,11 +159,6 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> TokenStream {
}

impl #impl_generics #bevy_reflect_path::Reflect for #enum_name #ty_generics #where_clause {
#[inline]
fn type_name(&self) -> &str {
std::any::type_name::<Self>()
}

#[inline]
fn get_type_info(&self) -> &'static #bevy_reflect_path::TypeInfo {
<Self as #bevy_reflect_path::Typed>::type_info()
Expand Down Expand Up @@ -198,6 +202,8 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> TokenStream {

#[inline]
fn apply(&mut self, #ref_value: &dyn #bevy_reflect_path::Reflect) {
use #bevy_reflect_path::ReflectTypeName;
tguichaoua marked this conversation as resolved.
Show resolved Hide resolved

if let #bevy_reflect_path::ReflectRef::Enum(#ref_value) = #ref_value.reflect_ref() {
if #bevy_reflect_path::Enum::variant_name(self) == #ref_value.variant_name() {
// Same variant -> just update fields
Expand All @@ -221,7 +227,7 @@ pub(crate) fn impl_enum(reflect_enum: &ReflectEnum) -> TokenStream {
#(#variant_names => {
*self = #variant_constructors
})*
name => panic!("variant with name `{}` does not exist on enum `{}`", name, std::any::type_name::<Self>()),
name => panic!("variant with name `{}` does not exist on enum `{}`", name, <Self as #bevy_reflect_path::TypeName>::name()),
}
}
} else {
Expand Down
2 changes: 2 additions & 0 deletions crates/bevy_reflect/bevy_reflect_derive/src/impls/mod.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
mod enums;
mod structs;
mod tuple_structs;
mod type_name;
mod typed;
mod values;

pub(crate) use enums::impl_enum;
pub(crate) use structs::impl_struct;
pub(crate) use tuple_structs::impl_tuple_struct;
pub(crate) use type_name::impl_type_name;
pub(crate) use typed::impl_typed;
pub(crate) use values::impl_value;
Loading