Skip to content

Commit

Permalink
reflect: stable type path v2 (#7184)
Browse files Browse the repository at this point in the history
# 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`?](https://github.com/bevyengine/bevy/pull/5805/files/2afbd855327c4b68e0a6b6f03118f289988441a4#r961067892)
  • Loading branch information
soqb authored Jun 5, 2023
1 parent 94dce09 commit 1efc762
Show file tree
Hide file tree
Showing 63 changed files with 2,062 additions and 411 deletions.
6 changes: 3 additions & 3 deletions crates/bevy_asset/src/asset_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,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::TypePath)]
/// # #[uuid = "00000000-0000-0000-0000-000000000000"]
/// # struct Image;
///
Expand Down Expand Up @@ -647,10 +647,10 @@ mod test {
use crate::{loader::LoadedAsset, update_asset_storage_system};
use bevy_app::{App, Update};
use bevy_ecs::prelude::*;
use bevy_reflect::TypeUuid;
use bevy_reflect::{TypePath, TypeUuid};
use bevy_utils::BoxedFuture;

#[derive(Debug, TypeUuid)]
#[derive(Debug, TypeUuid, TypePath)]
#[uuid = "a5189b72-0572-4290-a2e0-96f73a491c44"]
struct PngAsset;

Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_asset/src/assets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -488,7 +488,7 @@ mod tests {

#[test]
fn asset_overwriting() {
#[derive(bevy_reflect::TypeUuid)]
#[derive(bevy_reflect::TypeUuid, bevy_reflect::TypePath)]
#[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::TypePath;
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 + TypePath + AssetDynamic {}

/// 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 + TypePath + AssetDynamic + TypeUuidDynamic {}

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

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::{Asset, AssetLoader, LoadContext, LoadedAsset};
use bevy_reflect::TypeUuid;
use bevy_reflect::{TypePath, TypeUuid};
use bevy_utils::BoxedFuture;
use std::{io::Cursor, sync::Arc};

/// A source of audio data
#[derive(Debug, Clone, TypeUuid)]
#[derive(Debug, Clone, TypeUuid, TypePath)]
#[uuid = "7a14806a-672b-443b-8d16-4f18afefa463"]
pub struct AudioSource {
/// Raw data of the audio source.
Expand Down
6 changes: 3 additions & 3 deletions crates/bevy_audio/src/sinks.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use bevy_math::Vec3;
use bevy_reflect::TypeUuid;
use bevy_reflect::{TypePath, TypeUuid};
use bevy_transform::prelude::Transform;
use rodio::{Sink, SpatialSink};

Expand Down Expand Up @@ -87,7 +87,7 @@ pub trait AudioSinkPlayback {
/// }
/// ```
///
#[derive(TypeUuid)]
#[derive(TypePath, TypeUuid)]
#[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 Expand Up @@ -158,7 +158,7 @@ impl AudioSinkPlayback for AudioSink {
/// }
/// ```
///
#[derive(TypeUuid)]
#[derive(TypePath, TypeUuid)]
#[uuid = "F3CA4C47-595E-453B-96A7-31C3DDF2A177"]
pub struct SpatialAudioSink {
// This field is an Option in order to allow us to have a safe drop that will detach the sink.
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_ecs/src/reflect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);

#[derive(Clone)]
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 @@ -12,7 +12,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, TypePath, TypeUuid};
use bevy_render::{
mesh::{Mesh, MeshVertexAttribute},
renderer::RenderDevice,
Expand Down Expand Up @@ -58,7 +58,7 @@ impl Plugin for GltfPlugin {
}

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

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

/// A glTF mesh, which may consist of multiple [`GltfPrimitives`](GltfPrimitive)
/// and an optional [`GltfExtras`].
#[derive(Debug, Clone, TypeUuid)]
#[derive(Debug, Clone, TypeUuid, TypePath)]
#[uuid = "8ceaec9a-926a-4f29-8ee3-578a69f42315"]
pub struct GltfMesh {
pub primitives: Vec<GltfPrimitive>,
pub extras: Option<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"]
pub struct GltfPrimitive {
pub mesh: Handle<Mesh>,
Expand Down
4 changes: 3 additions & 1 deletion crates/bevy_input/src/input.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,10 +174,12 @@ where

#[cfg(test)]
mod test {
use bevy_reflect::TypePath;

use crate::Input;

/// Used for testing the functionality of [`Input`].
#[derive(Copy, Clone, Eq, PartialEq, Hash)]
#[derive(TypePath, Copy, Clone, Eq, PartialEq, Hash)]
enum DummyInput {
Input1,
Input2,
Expand Down
8 changes: 4 additions & 4 deletions crates/bevy_pbr/src/material.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use bevy_ecs::{
SystemParamItem,
},
};
use bevy_reflect::TypeUuid;
use bevy_reflect::{TypePath, TypeUuid};
use bevy_render::{
extract_component::ExtractComponentPlugin,
mesh::{Mesh, MeshVertexBufferLayout},
Expand Down Expand Up @@ -59,11 +59,11 @@ use std::marker::PhantomData;
/// ```
/// # use bevy_pbr::{Material, MaterialMeshBundle};
/// # 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_asset::{Handle, AssetServer, Assets};
///
/// #[derive(AsBindGroup, TypeUuid, Debug, Clone)]
/// #[derive(AsBindGroup, TypeUuid, TypePath, 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 @@ -106,7 +106,7 @@ 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 + TypePath + Sized {
/// 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
Loading

0 comments on commit 1efc762

Please sign in to comment.