From 266f7b6583006888a9369c02222506233d86a315 Mon Sep 17 00:00:00 2001 From: Jakob Hellermann Date: Fri, 9 Sep 2022 11:18:54 +0200 Subject: [PATCH 01/18] add ReflectAsset and ReflectHandle --- crates/bevy_asset/src/handle.rs | 10 ++ crates/bevy_asset/src/lib.rs | 2 + crates/bevy_asset/src/reflect.rs | 159 +++++++++++++++++++++++++++++++ 3 files changed, 171 insertions(+) create mode 100644 crates/bevy_asset/src/reflect.rs diff --git a/crates/bevy_asset/src/handle.rs b/crates/bevy_asset/src/handle.rs index c374c6b070ace..006d11504b690 100644 --- a/crates/bevy_asset/src/handle.rs +++ b/crates/bevy_asset/src/handle.rs @@ -410,6 +410,16 @@ impl Drop for HandleUntyped { } } +impl From> for HandleUntyped { + fn from(mut handle: Handle) -> Self { + let handle_type = std::mem::replace(&mut handle.handle_type, HandleType::Weak); + HandleUntyped { + id: handle.id, + handle_type, + } + } +} + impl From<&HandleUntyped> for HandleId { fn from(value: &HandleUntyped) -> Self { value.id diff --git a/crates/bevy_asset/src/lib.rs b/crates/bevy_asset/src/lib.rs index ff125d3abd275..5c3e3690dd1f6 100644 --- a/crates/bevy_asset/src/lib.rs +++ b/crates/bevy_asset/src/lib.rs @@ -25,6 +25,7 @@ mod info; mod io; mod loader; mod path; +mod reflect; /// The `bevy_asset` prelude. pub mod prelude { @@ -43,6 +44,7 @@ pub use info::*; pub use io::*; pub use loader::*; pub use path::*; +pub use reflect::*; use bevy_app::{prelude::Plugin, App}; use bevy_ecs::schedule::{StageLabel, SystemStage}; diff --git a/crates/bevy_asset/src/reflect.rs b/crates/bevy_asset/src/reflect.rs new file mode 100644 index 0000000000000..907b791949d4b --- /dev/null +++ b/crates/bevy_asset/src/reflect.rs @@ -0,0 +1,159 @@ +use std::any::{Any, TypeId}; + +use bevy_ecs::world::World; +use bevy_reflect::{FromReflect, FromType, Reflect, Uuid}; + +use crate::{Asset, Assets, Handle, HandleUntyped}; + +/// A struct used to operate on reflected [`Asset`] of a type. +/// +/// A [`ReflectAsset`] for type `T` can be obtained via +/// [`bevy_reflect::TypeRegistration::data`]. +#[derive(Clone)] +pub struct ReflectAsset { + type_uuid: Uuid, + assets_resource_type_id: TypeId, + + get: fn(&World, HandleUntyped) -> Option<&dyn Reflect>, + get_mut: fn(&mut World, HandleUntyped) -> Option<&mut dyn Reflect>, + get_unchecked_mut: unsafe fn(&World, HandleUntyped) -> Option<&mut dyn Reflect>, + add: fn(&mut World, &dyn Reflect) -> HandleUntyped, + set: fn(&mut World, HandleUntyped, &dyn Reflect) -> HandleUntyped, +} + +impl ReflectAsset { + /// The [`TypeUuid`] of the asset + pub fn type_uuid(&self) -> Uuid { + self.type_uuid + } + + /// The [`TypeId`] of the [`Assets`] resource + pub fn assets_resource_type_id(&self) -> TypeId { + self.assets_resource_type_id + } + + /// Equivalent of [`Assets::get`] + pub fn get<'w>(&self, world: &'w World, handle: HandleUntyped) -> Option<&'w dyn Reflect> { + (self.get)(world, handle) + } + /// Equivalent of [`Assets::get_mut`] + pub fn get_mut<'w>( + &self, + world: &'w mut World, + handle: HandleUntyped, + ) -> Option<&'w mut dyn Reflect> { + (self.get_mut)(world, handle) + } + + /// Equivalent of [`Assets::get_mut`], but does not require a mutable reference to the world. + /// This is fine if you have ensure that you are the *only* one having access to the `Assets` resource + /// of the asset type. Furthermore, this does *not* allow you to have look up two distinct handles, + /// you can only have at most one alive at the same time. + /// + /// # Safety + /// This method does not prevent you from having two mutable pointers to the same data, + /// violating Rust's aliasing rules. To avoid this: + /// * Only call this method when you have exclusive access to the world + /// (or use a scheduler that enforces unique access to the `Assets` resource). + /// * Don't call this method more than once in the same scope. + pub unsafe fn get_unchecked_mut<'w>( + &self, + world: &'w World, + handle: HandleUntyped, + ) -> Option<&'w mut dyn Reflect> { + // SAFETY: requirements are deferred to the caller + (self.get_unchecked_mut)(world, handle) + } + + /// Equivalent of [`Assets::add`] + pub fn add<'w>(&self, world: &'w mut World, value: &dyn Reflect) -> HandleUntyped { + (self.add)(world, value) + } + /// Equivalent of [`Assets::set`] + pub fn set<'w>( + &self, + world: &'w mut World, + handle: HandleUntyped, + value: &dyn Reflect, + ) -> HandleUntyped { + (self.set)(world, handle, value) + } +} + +impl FromType for ReflectAsset { + fn from_type() -> Self { + ReflectAsset { + type_uuid: A::TYPE_UUID, + assets_resource_type_id: TypeId::of::>(), + get: |world, handle| { + let assets = world.resource::>(); + let asset = assets.get(&handle.typed()); + asset.map(|asset| asset as &dyn Reflect) + }, + get_mut: |world, handle| { + let assets = world.resource_mut::>().into_inner(); + let asset = assets.get_mut(&handle.typed()); + asset.map(|asset| asset as &mut dyn Reflect) + }, + get_unchecked_mut: |world, handle| { + let assets = unsafe { + world + .get_resource_unchecked_mut::>() + .unwrap() + .into_inner() + }; + let asset = assets.get_mut(&handle.typed()); + asset.map(|asset| asset as &mut dyn Reflect) + }, + add: |world, value| { + let mut assets = world.resource_mut::>(); + let value: A = FromReflect::from_reflect(value) + .expect("could not call `FromReflect::from_reflect` in `ReflectAsset::insert`"); + assets.add(value).into() + }, + set: |world, handle, value| { + let mut assets = world.resource_mut::>(); + let value: A = FromReflect::from_reflect(value) + .expect("could not call `FromReflect::from_reflect` in `ReflectAsset::insert`"); + assets.set(handle, value).into() + }, + } + } +} + +/// A struct relating a `Handle` back to the `T` asset type. +#[derive(Clone)] +pub struct ReflectHandle { + type_uuid: Uuid, + asset_type_id: TypeId, + downcast_handle_untyped: fn(&dyn Any) -> Option, +} +impl ReflectHandle { + /// The [`TypeUuid`] of the asset + pub fn type_uuid(&self) -> Uuid { + self.type_uuid + } + /// The [`TypeId`] of the asset + pub fn asset_type_id(&self) -> TypeId { + self.asset_type_id + } + + /// A way to go from a `Handle` in a `dyn Any` to a [`HandleUntyped`] + pub fn downcast_handle_untyped(&self, handle: &dyn Any) -> Option { + (self.downcast_handle_untyped)(handle) + } +} + +impl FromType> for ReflectHandle { + fn from_type() -> Self { + ReflectHandle { + type_uuid: A::TYPE_UUID, + asset_type_id: TypeId::of::(), + downcast_handle_untyped: |handle: &dyn Any| { + handle + .downcast_ref::>() + .map(|handle| handle.clone_untyped()) + }, + } + } +} From de346a7d2abc1996a8260738ad500c0ef0704779 Mon Sep 17 00:00:00 2001 From: Jakob Hellermann Date: Fri, 9 Sep 2022 11:53:54 +0200 Subject: [PATCH 02/18] add register_asset_reflect function --- crates/bevy_asset/src/assets.rs | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/crates/bevy_asset/src/assets.rs b/crates/bevy_asset/src/assets.rs index f54217be6ccc3..b741862b2541b 100644 --- a/crates/bevy_asset/src/assets.rs +++ b/crates/bevy_asset/src/assets.rs @@ -1,13 +1,14 @@ use crate::{ update_asset_storage_system, Asset, AssetLoader, AssetServer, AssetStage, Handle, HandleId, - RefChange, + RefChange, ReflectAsset, ReflectHandle, }; -use bevy_app::App; +use bevy_app::{App, AppTypeRegistry}; use bevy_ecs::{ event::{EventWriter, Events}, system::{ResMut, Resource}, world::FromWorld, }; +use bevy_reflect::{FromReflect, FromType, GetTypeRegistration, Reflect}; use bevy_utils::HashMap; use crossbeam_channel::Sender; use std::fmt::Debug; @@ -279,6 +280,11 @@ pub trait AddAsset { where T: Asset; + /// Registers [`ReflectAsset`] and [`ReflectHandle`] in the [`TypeRegistry]` so that the asset can be used in reflection contexts. + fn register_asset_reflect(&mut self) -> &mut Self + where + T: Asset + Reflect + FromReflect + GetTypeRegistration; + /// Registers `T` as a supported internal asset in the application. /// /// Internal assets (e.g. shaders) are bundled directly into the app and can't be hot reloaded @@ -332,6 +338,29 @@ impl AddAsset for App { .add_event::>() } + fn register_asset_reflect(&mut self) -> &mut Self + where + T: Asset + Reflect + FromReflect + GetTypeRegistration, + { + let type_registry = self.world.resource::(); + { + let mut type_registry = type_registry.write(); + + type_registry.register::(); + type_registry.register::>(); + type_registry + .get_mut(std::any::TypeId::of::()) + .unwrap() + .insert(>::from_type()); + type_registry + .get_mut(std::any::TypeId::of::>()) + .unwrap() + .insert(>>::from_type()); + } + + self + } + fn add_debug_asset(&mut self) -> &mut Self where T: Asset, From 443e816f85f403d44c2da64ffedd193aa97dbe1b Mon Sep 17 00:00:00 2001 From: Jakob Hellermann Date: Fri, 9 Sep 2022 12:03:16 +0200 Subject: [PATCH 03/18] register assets as reflect: StandardMaterial, ColorMaterial, AnimationClip --- crates/bevy_animation/src/lib.rs | 11 ++++++----- crates/bevy_core/src/name.rs | 4 ++-- crates/bevy_pbr/src/alpha.rs | 4 ++-- crates/bevy_pbr/src/lib.rs | 3 ++- crates/bevy_pbr/src/pbr_material.rs | 7 +++++-- crates/bevy_sprite/src/mesh2d/color_material.rs | 10 ++++++---- 6 files changed, 23 insertions(+), 16 deletions(-) diff --git a/crates/bevy_animation/src/lib.rs b/crates/bevy_animation/src/lib.rs index ae3455b09edd1..0ab68da7c8788 100644 --- a/crates/bevy_animation/src/lib.rs +++ b/crates/bevy_animation/src/lib.rs @@ -17,7 +17,7 @@ use bevy_ecs::{ }; use bevy_hierarchy::Children; use bevy_math::{Quat, Vec3}; -use bevy_reflect::{Reflect, TypeUuid}; +use bevy_reflect::{FromReflect, Reflect, TypeUuid}; use bevy_time::Time; use bevy_transform::{prelude::Transform, TransformSystem}; use bevy_utils::{tracing::warn, HashMap}; @@ -31,7 +31,7 @@ pub mod prelude { } /// List of keyframes for one of the attribute of a [`Transform`]. -#[derive(Clone, Debug)] +#[derive(Reflect, FromReflect, Clone, Debug)] pub enum Keyframes { /// Keyframes for rotation. Rotation(Vec), @@ -44,7 +44,7 @@ pub enum Keyframes { /// Describes how an attribute of a [`Transform`] should be animated. /// /// `keyframe_timestamps` and `keyframes` should have the same length. -#[derive(Clone, Debug)] +#[derive(Reflect, FromReflect, Clone, Debug)] pub struct VariableCurve { /// Timestamp for each of the keyframes. pub keyframe_timestamps: Vec, @@ -53,14 +53,14 @@ pub struct VariableCurve { } /// Path to an entity, with [`Name`]s. Each entity in a path must have a name. -#[derive(Clone, Debug, Hash, PartialEq, Eq, Default)] +#[derive(Reflect, FromReflect, Clone, Debug, Hash, PartialEq, Eq, Default)] pub struct EntityPath { /// Parts of the path pub parts: Vec, } /// A list of [`VariableCurve`], and the [`EntityPath`] to which they apply. -#[derive(Clone, TypeUuid, Debug, Default)] +#[derive(Reflect, FromReflect, Clone, TypeUuid, Debug, Default)] #[uuid = "d81b7179-0448-4eb0-89fe-c067222725bf"] pub struct AnimationClip { curves: HashMap>, @@ -301,6 +301,7 @@ pub struct AnimationPlugin {} impl Plugin for AnimationPlugin { fn build(&self, app: &mut App) { app.add_asset::() + .register_asset_reflect::() .register_type::() .add_system_to_stage( CoreStage::PostUpdate, diff --git a/crates/bevy_core/src/name.rs b/crates/bevy_core/src/name.rs index fe320300fd03d..f7fad0ca18e26 100644 --- a/crates/bevy_core/src/name.rs +++ b/crates/bevy_core/src/name.rs @@ -1,6 +1,6 @@ use bevy_ecs::{component::Component, reflect::ReflectComponent}; -use bevy_reflect::std_traits::ReflectDefault; use bevy_reflect::Reflect; +use bevy_reflect::{std_traits::ReflectDefault, FromReflect}; use bevy_utils::AHasher; use std::{ borrow::Cow, @@ -14,7 +14,7 @@ use std::{ /// [`Name`] should not be treated as a globally unique identifier for entities, /// as multiple entities can have the same name. [`bevy_ecs::entity::Entity`] should be /// used instead as the default unique identifier. -#[derive(Component, Debug, Clone, Reflect)] +#[derive(Reflect, FromReflect, Component, Debug, Clone)] #[reflect(Component, Default)] pub struct Name { hash: u64, // TODO: Shouldn't be serialized diff --git a/crates/bevy_pbr/src/alpha.rs b/crates/bevy_pbr/src/alpha.rs index 79fb198f54b8e..0bd1360ec6122 100644 --- a/crates/bevy_pbr/src/alpha.rs +++ b/crates/bevy_pbr/src/alpha.rs @@ -1,10 +1,10 @@ use bevy_ecs::{component::Component, reflect::ReflectComponent}; use bevy_reflect::std_traits::ReflectDefault; -use bevy_reflect::Reflect; +use bevy_reflect::{FromReflect, Reflect}; // TODO: add discussion about performance. /// Sets how a material's base color alpha channel is used for transparency. -#[derive(Component, Debug, Default, Reflect, Copy, Clone, PartialEq)] +#[derive(Component, Debug, Default, Reflect, Copy, Clone, PartialEq, FromReflect)] #[reflect(Component, Default)] pub enum AlphaMode { /// Base color alpha values are overridden to be fully opaque (1.0). diff --git a/crates/bevy_pbr/src/lib.rs b/crates/bevy_pbr/src/lib.rs index 12988ab56dda1..c133442e8dd3a 100644 --- a/crates/bevy_pbr/src/lib.rs +++ b/crates/bevy_pbr/src/lib.rs @@ -38,7 +38,7 @@ pub mod draw_3d_graph { } use bevy_app::prelude::*; -use bevy_asset::{load_internal_asset, Assets, Handle, HandleUntyped}; +use bevy_asset::{load_internal_asset, AddAsset, Assets, Handle, HandleUntyped}; use bevy_ecs::prelude::*; use bevy_reflect::TypeUuid; use bevy_render::{ @@ -129,6 +129,7 @@ impl Plugin for PbrPlugin { .register_type::() .add_plugin(MeshRenderPlugin) .add_plugin(MaterialPlugin::::default()) + .register_asset_reflect::() .register_type::() .register_type::() .register_type::() diff --git a/crates/bevy_pbr/src/pbr_material.rs b/crates/bevy_pbr/src/pbr_material.rs index db61a1fe70e38..5735b7c51fcd3 100644 --- a/crates/bevy_pbr/src/pbr_material.rs +++ b/crates/bevy_pbr/src/pbr_material.rs @@ -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::{std_traits::ReflectDefault, FromReflect, Reflect, TypeUuid}; use bevy_render::{ color::Color, mesh::MeshVertexBufferLayout, render_asset::RenderAssets, render_resource::*, texture::Image, @@ -12,10 +12,11 @@ use bevy_render::{ /// . /// /// May be created directly from a [`Color`] or an [`Image`]. -#[derive(AsBindGroup, Debug, Clone, TypeUuid)] +#[derive(AsBindGroup, Reflect, FromReflect, Debug, Clone, TypeUuid)] #[uuid = "7494888b-c082-457b-aacf-517228cc0c22"] #[bind_group_data(StandardMaterialKey)] #[uniform(0, StandardMaterialUniform)] +#[reflect(Default)] pub struct StandardMaterial { /// The color of the surface of the material before lighting. /// @@ -193,6 +194,8 @@ pub struct StandardMaterial { /// Your 3D editing software should manage all of that. /// /// [`Mesh`]: bevy_render::mesh::Mesh + // TODO: include this in reflection somehow (maybe via remote types like serde https://serde.rs/remote-derive.html) + #[reflect(ignore)] pub cull_mode: Option, /// Whether to apply only the base color to this material. diff --git a/crates/bevy_sprite/src/mesh2d/color_material.rs b/crates/bevy_sprite/src/mesh2d/color_material.rs index b0f68db9795e4..cdafc1f70fd32 100644 --- a/crates/bevy_sprite/src/mesh2d/color_material.rs +++ b/crates/bevy_sprite/src/mesh2d/color_material.rs @@ -1,7 +1,7 @@ use bevy_app::{App, Plugin}; -use bevy_asset::{load_internal_asset, Assets, Handle, HandleUntyped}; +use bevy_asset::{load_internal_asset, AddAsset, Assets, Handle, HandleUntyped}; use bevy_math::Vec4; -use bevy_reflect::TypeUuid; +use bevy_reflect::{prelude::*, TypeUuid}; use bevy_render::{ color::Color, prelude::Shader, render_asset::RenderAssets, render_resource::*, texture::Image, }; @@ -23,7 +23,8 @@ impl Plugin for ColorMaterialPlugin { Shader::from_wgsl ); - app.add_plugin(Material2dPlugin::::default()); + app.add_plugin(Material2dPlugin::::default()) + .register_asset_reflect::(); app.world .resource_mut::>() @@ -38,7 +39,8 @@ impl Plugin for ColorMaterialPlugin { } /// A [2d material](Material2d) that renders [2d meshes](crate::Mesh2dHandle) with a texture tinted by a uniform color -#[derive(AsBindGroup, Debug, Clone, TypeUuid)] +#[derive(AsBindGroup, Reflect, FromReflect, Debug, Clone, TypeUuid)] +#[reflect(Default)] #[uuid = "e228a544-e3ca-4e1e-bb9d-4d8bc1ad8c19"] #[uniform(0, ColorMaterialUniform)] pub struct ColorMaterial { From b46db7428908296bf9896d706d2c3d11264e0c04 Mon Sep 17 00:00:00 2001 From: Jakob Hellermann Date: Fri, 9 Sep 2022 13:21:50 +0200 Subject: [PATCH 04/18] add len, ids and remove --- crates/bevy_asset/src/reflect.rs | 33 +++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/crates/bevy_asset/src/reflect.rs b/crates/bevy_asset/src/reflect.rs index 907b791949d4b..a7ce8788a7e39 100644 --- a/crates/bevy_asset/src/reflect.rs +++ b/crates/bevy_asset/src/reflect.rs @@ -3,7 +3,7 @@ use std::any::{Any, TypeId}; use bevy_ecs::world::World; use bevy_reflect::{FromReflect, FromType, Reflect, Uuid}; -use crate::{Asset, Assets, Handle, HandleUntyped}; +use crate::{Asset, Assets, Handle, HandleId, HandleUntyped}; /// A struct used to operate on reflected [`Asset`] of a type. /// @@ -19,6 +19,9 @@ pub struct ReflectAsset { get_unchecked_mut: unsafe fn(&World, HandleUntyped) -> Option<&mut dyn Reflect>, add: fn(&mut World, &dyn Reflect) -> HandleUntyped, set: fn(&mut World, HandleUntyped, &dyn Reflect) -> HandleUntyped, + len: fn(&World) -> usize, + ids: for<'w> fn(&'w World) -> Box + 'w>, + remove: fn(&mut World, HandleUntyped) -> Option>, } impl ReflectAsset { @@ -78,6 +81,21 @@ impl ReflectAsset { ) -> HandleUntyped { (self.set)(world, handle, value) } + + /// Equivalent of [`Assets::remove`] + pub fn remove(&self, world: &mut World, handle: HandleUntyped) -> Option> { + (self.remove)(world, handle) + } + + /// Equivalent of [`Assets::len`] + pub fn len(&self, world: &World) -> usize { + (self.len)(world) + } + + /// Equivalent of [`Assets::ids`] + pub fn ids<'w>(&self, world: &'w World) -> impl Iterator + 'w { + (self.ids)(world) + } } impl FromType for ReflectAsset { @@ -117,6 +135,19 @@ impl FromType for ReflectAsset { .expect("could not call `FromReflect::from_reflect` in `ReflectAsset::insert`"); assets.set(handle, value).into() }, + len: |world| { + let assets = world.resource::>(); + assets.len() + }, + ids: |world| { + let assets = world.resource::>(); + Box::new(assets.ids()) + }, + remove: |world, handle| { + let mut assets = world.resource_mut::>(); + let value = assets.remove(handle); + value.map(|value| Box::new(value) as Box) + }, } } } From de862d8a1a314914e414bf1850e16850ac2fc42e Mon Sep 17 00:00:00 2001 From: Jakob Hellermann Date: Fri, 9 Sep 2022 14:27:01 +0200 Subject: [PATCH 05/18] make Image reflect_value and register it as reflect asset --- crates/bevy_render/src/texture/image.rs | 5 +++-- crates/bevy_render/src/texture/mod.rs | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/crates/bevy_render/src/texture/image.rs b/crates/bevy_render/src/texture/image.rs index 5c2ef73911e4c..58de8eee4f86b 100644 --- a/crates/bevy_render/src/texture/image.rs +++ b/crates/bevy_render/src/texture/image.rs @@ -15,7 +15,7 @@ use bevy_asset::HandleUntyped; use bevy_derive::{Deref, DerefMut}; use bevy_ecs::system::{lifetimeless::SRes, Resource, SystemParamItem}; use bevy_math::Vec2; -use bevy_reflect::TypeUuid; +use bevy_reflect::{FromReflect, Reflect, TypeUuid}; use std::hash::Hash; use thiserror::Error; use wgpu::{ @@ -101,8 +101,9 @@ impl ImageFormat { } } -#[derive(Debug, Clone, TypeUuid)] +#[derive(Reflect, FromReflect, Debug, Clone, TypeUuid)] #[uuid = "6ea26da6-6cf8-4ea2-9986-1d7bf6c17d6f"] +#[reflect_value] pub struct Image { pub data: Vec, // TODO: this nesting makes accessing Image metadata verbose. Either flatten out descriptor or add accessors diff --git a/crates/bevy_render/src/texture/mod.rs b/crates/bevy_render/src/texture/mod.rs index 7600d5e1305b5..596b586f44cba 100644 --- a/crates/bevy_render/src/texture/mod.rs +++ b/crates/bevy_render/src/texture/mod.rs @@ -86,7 +86,8 @@ impl Plugin for ImagePlugin { app.add_plugin(RenderAssetPlugin::::with_prepare_asset_label( PrepareAssetLabel::PreAssetPrepare, )) - .add_asset::(); + .add_asset::() + .register_asset_reflect::(); app.world .resource_mut::>() .set_untracked(DEFAULT_IMAGE_HANDLE, Image::default()); From 26d5c6172ffe896b565c530e8d3b781bc286bcb4 Mon Sep 17 00:00:00 2001 From: Jakob Hellermann Date: Fri, 9 Sep 2022 14:39:02 +0200 Subject: [PATCH 06/18] tweak wording --- crates/bevy_asset/src/reflect.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/bevy_asset/src/reflect.rs b/crates/bevy_asset/src/reflect.rs index a7ce8788a7e39..ce410cdd84b72 100644 --- a/crates/bevy_asset/src/reflect.rs +++ b/crates/bevy_asset/src/reflect.rs @@ -5,10 +5,10 @@ use bevy_reflect::{FromReflect, FromType, Reflect, Uuid}; use crate::{Asset, Assets, Handle, HandleId, HandleUntyped}; -/// A struct used to operate on reflected [`Asset`] of a type. +/// A struct used to operate on reflected [`Asset`]s. /// /// A [`ReflectAsset`] for type `T` can be obtained via -/// [`bevy_reflect::TypeRegistration::data`]. +/// [`bevy_reflect::TypeRegistration::data`] if it was registered using [`crate::AddAsset::register_asset_reflect`]. #[derive(Clone)] pub struct ReflectAsset { type_uuid: Uuid, @@ -25,7 +25,7 @@ pub struct ReflectAsset { } impl ReflectAsset { - /// The [`TypeUuid`] of the asset + /// The [`bevy_reflect::TypeUuid`] of the asset pub fn type_uuid(&self) -> Uuid { self.type_uuid } @@ -152,7 +152,7 @@ impl FromType for ReflectAsset { } } -/// A struct relating a `Handle` back to the `T` asset type. +/// Reflect type data struct relating a `Handle` back to the `T` asset type. #[derive(Clone)] pub struct ReflectHandle { type_uuid: Uuid, @@ -160,7 +160,7 @@ pub struct ReflectHandle { downcast_handle_untyped: fn(&dyn Any) -> Option, } impl ReflectHandle { - /// The [`TypeUuid`] of the asset + /// The [`bevy_reflect::TypeUuid`] of the asset pub fn type_uuid(&self) -> Uuid { self.type_uuid } From 467d1c2d7651f843c4a4605cdc60b90cfe069758 Mon Sep 17 00:00:00 2001 From: Jakob Hellermann Date: Fri, 9 Sep 2022 14:50:24 +0200 Subject: [PATCH 07/18] add a test --- crates/bevy_asset/src/reflect.rs | 67 ++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/crates/bevy_asset/src/reflect.rs b/crates/bevy_asset/src/reflect.rs index ce410cdd84b72..da6d9b868c96c 100644 --- a/crates/bevy_asset/src/reflect.rs +++ b/crates/bevy_asset/src/reflect.rs @@ -188,3 +188,70 @@ impl FromType> for ReflectHandle { } } } + +#[cfg(test)] +mod tests { + use std::any::TypeId; + + use bevy_app::{App, AppTypeRegistry}; + use bevy_reflect::{FromReflect, Reflect, ReflectMut, TypeUuid}; + + use crate::{AddAsset, AssetPlugin, HandleUntyped, ReflectAsset}; + + #[derive(Reflect, FromReflect, TypeUuid)] + #[uuid = "09191350-1238-4736-9a89-46f04bda6966"] + struct AssetType { + field: String, + } + + #[test] + fn test() { + let mut app = App::new(); + app.add_plugin(AssetPlugin) + .add_asset::() + .register_asset_reflect::(); + + let reflect_asset = { + let type_registry = app.world.resource::(); + let type_registry = type_registry.read(); + + type_registry + .get_type_data::(TypeId::of::()) + .unwrap() + .clone() + }; + + let value = AssetType { + field: "test".into(), + }; + + let handle = reflect_asset.add(&mut app.world, &value); + let strukt = match reflect_asset + .get_mut(&mut app.world, handle) + .unwrap() + .reflect_mut() + { + ReflectMut::Struct(s) => s, + _ => unreachable!(), + }; + strukt + .field_mut("field") + .unwrap() + .apply(&String::from("edited")); + + assert_eq!(reflect_asset.len(&app.world), 1); + let ids: Vec<_> = reflect_asset.ids(&app.world).collect(); + assert_eq!(ids.len(), 1); + + let fetched_handle = HandleUntyped::weak(ids[0]); + let asset = reflect_asset + .get(&app.world, fetched_handle.clone_weak()) + .unwrap(); + assert_eq!(asset.downcast_ref::().unwrap().field, "edited"); + + reflect_asset + .remove(&mut app.world, fetched_handle) + .unwrap(); + assert_eq!(reflect_asset.len(&app.world), 0); + } +} From cf44ca72c51d8d0539b294d05141632adaa750d0 Mon Sep 17 00:00:00 2001 From: Jakob Hellermann Date: Fri, 9 Sep 2022 14:55:38 +0200 Subject: [PATCH 08/18] add is_empty --- crates/bevy_asset/src/reflect.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/crates/bevy_asset/src/reflect.rs b/crates/bevy_asset/src/reflect.rs index da6d9b868c96c..04bc954712d5c 100644 --- a/crates/bevy_asset/src/reflect.rs +++ b/crates/bevy_asset/src/reflect.rs @@ -92,6 +92,11 @@ impl ReflectAsset { (self.len)(world) } + /// Equivalent of [`Assets::is_empty`] + pub fn is_empty(&self, world: &World) -> bool { + self.len(world) == 0 + } + /// Equivalent of [`Assets::ids`] pub fn ids<'w>(&self, world: &'w World) -> impl Iterator + 'w { (self.ids)(world) From ab4822ac8ed9a23e3f72fea9c50e4dbaaf77dce5 Mon Sep 17 00:00:00 2001 From: Jakob Hellermann Date: Fri, 9 Sep 2022 15:00:47 +0200 Subject: [PATCH 09/18] silence clippy --- crates/bevy_asset/src/reflect.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/bevy_asset/src/reflect.rs b/crates/bevy_asset/src/reflect.rs index 04bc954712d5c..888a3e6903687 100644 --- a/crates/bevy_asset/src/reflect.rs +++ b/crates/bevy_asset/src/reflect.rs @@ -88,6 +88,7 @@ impl ReflectAsset { } /// Equivalent of [`Assets::len`] + #[allow(clippy::len_without_is_empty)] // clippy expects the `is_empty` method to have the signature `(&self) -> bool` pub fn len(&self, world: &World) -> usize { (self.len)(world) } From b2af704cb76fdb237ffe5d5affc69ff1e2d43250 Mon Sep 17 00:00:00 2001 From: Jakob Hellermann Date: Sat, 10 Sep 2022 18:04:48 +0200 Subject: [PATCH 10/18] expand docs --- crates/bevy_asset/src/assets.rs | 5 ++++- crates/bevy_asset/src/reflect.rs | 37 +++++++++++++++++++++++++++----- 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/crates/bevy_asset/src/assets.rs b/crates/bevy_asset/src/assets.rs index b741862b2541b..b058dc3f423ed 100644 --- a/crates/bevy_asset/src/assets.rs +++ b/crates/bevy_asset/src/assets.rs @@ -280,7 +280,10 @@ pub trait AddAsset { where T: Asset; - /// Registers [`ReflectAsset`] and [`ReflectHandle`] in the [`TypeRegistry]` so that the asset can be used in reflection contexts. + /// Registers the asset type `T` using `[App::register]`, + /// and adds [`ReflectAsset`] type data to `T` and [`ReflectHandle`] type data to `Handle` in the type registry. + /// + /// This enables reflection code to access assets. For detailed information, see the docs on [`ReflectAsset`] and [`ReflectHandle`]. fn register_asset_reflect(&mut self) -> &mut Self where T: Asset + Reflect + FromReflect + GetTypeRegistration; diff --git a/crates/bevy_asset/src/reflect.rs b/crates/bevy_asset/src/reflect.rs index 888a3e6903687..24f1b482367f9 100644 --- a/crates/bevy_asset/src/reflect.rs +++ b/crates/bevy_asset/src/reflect.rs @@ -5,10 +5,12 @@ use bevy_reflect::{FromReflect, FromType, Reflect, Uuid}; use crate::{Asset, Assets, Handle, HandleId, HandleUntyped}; -/// A struct used to operate on reflected [`Asset`]s. +/// Type data for the [`TypeRegistry`](bevy_reflect::TypeRegistry) used to operate on reflected [`Asset`]s. /// -/// A [`ReflectAsset`] for type `T` can be obtained via -/// [`bevy_reflect::TypeRegistration::data`] if it was registered using [`crate::AddAsset::register_asset_reflect`]. +/// This type provides similar methods to [`Assets`] like `get`, `add` and `remove`, but can be used in situations where you don't know which asset type `T` you want +/// until runtime. +/// +/// [`ReflectAsset`] can be obtained via [`TypeRegistration::data`](bevy_reflect::TypeRegistration::data) if the asset was registered using [`register_asset_reflect`](crate::AddAsset::register_asset_reflect). #[derive(Clone)] pub struct ReflectAsset { type_uuid: Uuid, @@ -49,8 +51,9 @@ impl ReflectAsset { } /// Equivalent of [`Assets::get_mut`], but does not require a mutable reference to the world. - /// This is fine if you have ensure that you are the *only* one having access to the `Assets` resource - /// of the asset type. Furthermore, this does *not* allow you to have look up two distinct handles, + /// + /// Only use this method when you have ensured that you are the *only* one with access to the `Assets` resource of the asset type. + /// Furthermore, this does *not* allow you to have look up two distinct handles, /// you can only have at most one alive at the same time. /// /// # Safety @@ -159,6 +162,30 @@ impl FromType for ReflectAsset { } /// Reflect type data struct relating a `Handle` back to the `T` asset type. +/// +/// Say you want to look up the asset values of a list of handles when you have access to their `&dyn Reflect` form. +/// Assets can be looked up in the world using [`ReflectAsset`], but how do you determine which [`ReflectAsset`] to use when +/// only looking at the handle? [`ReflectHandle`] is stored in the type registry on each `Handle` type, so you can use [`ReflectHandle::asset_type_id`] to look up +/// the [`ReflectAsset`] type data on the corresponding `T` asset type: +/// +/// +/// ```rust,no_run +/// # use bevy_reflect::{TypeRegistry, prelude::*}; +/// # use bevy_ecs::prelude::*; +/// use bevy_asset::{ReflectHandle, ReflectAsset}; +/// +/// # let world: &World = unimplemented!(); +/// # let type_registry: TypeRegistry = unimplemented!(); +/// let handles: Vec<&dyn Reflect> = unimplemented!(); +/// for handle in handles { +/// let reflect_handle = type_registry.get_type_data::(handle.type_id()).unwrap(); +/// let reflect_asset = type_registry.get_type_data::(reflect_handle.asset_type_id()).unwrap(); +/// +/// let handle = reflect_handle.downcast_handle_untyped(handle.as_any()).unwrap(); +/// let value = reflect_asset.get(world, handle).unwrap(); +/// println!("{value:?}"); +/// } +/// ``` #[derive(Clone)] pub struct ReflectHandle { type_uuid: Uuid, From d21c2f5f032327e55972a167cf84e63030c48944 Mon Sep 17 00:00:00 2001 From: Jakob Hellermann Date: Sat, 10 Sep 2022 18:08:02 +0200 Subject: [PATCH 11/18] add handle type id to ReflectAsset as well --- crates/bevy_asset/src/reflect.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/crates/bevy_asset/src/reflect.rs b/crates/bevy_asset/src/reflect.rs index 24f1b482367f9..c8d70c90bd598 100644 --- a/crates/bevy_asset/src/reflect.rs +++ b/crates/bevy_asset/src/reflect.rs @@ -14,6 +14,7 @@ use crate::{Asset, Assets, Handle, HandleId, HandleUntyped}; #[derive(Clone)] pub struct ReflectAsset { type_uuid: Uuid, + handle_type_id: TypeId, assets_resource_type_id: TypeId, get: fn(&World, HandleUntyped) -> Option<&dyn Reflect>, @@ -32,6 +33,11 @@ impl ReflectAsset { self.type_uuid } + /// The [`TypeId`] of the [`Handle`] for this asset + pub fn handle_type_id(&self) -> TypeId { + self.handle_type_id + } + /// The [`TypeId`] of the [`Assets`] resource pub fn assets_resource_type_id(&self) -> TypeId { self.assets_resource_type_id @@ -111,6 +117,7 @@ impl FromType for ReflectAsset { fn from_type() -> Self { ReflectAsset { type_uuid: A::TYPE_UUID, + handle_type_id: TypeId::of::>(), assets_resource_type_id: TypeId::of::>(), get: |world, handle| { let assets = world.resource::>(); From d51bb6cb307ee6958fe78f2d567bdcd3978d02a9 Mon Sep 17 00:00:00 2001 From: Jakob Hellermann Date: Sat, 10 Sep 2022 18:17:57 +0200 Subject: [PATCH 12/18] register texture atlas as reflect asset --- crates/bevy_sprite/src/lib.rs | 1 + crates/bevy_sprite/src/texture_atlas.rs | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/crates/bevy_sprite/src/lib.rs b/crates/bevy_sprite/src/lib.rs index 03db00144b153..8529e01ab3e98 100644 --- a/crates/bevy_sprite/src/lib.rs +++ b/crates/bevy_sprite/src/lib.rs @@ -54,6 +54,7 @@ impl Plugin for SpritePlugin { let sprite_shader = Shader::from_wgsl(include_str!("render/sprite.wgsl")); shaders.set_untracked(SPRITE_SHADER_HANDLE, sprite_shader); app.add_asset::() + .register_asset_reflect::() .register_type::() .register_type::() .register_type::() diff --git a/crates/bevy_sprite/src/texture_atlas.rs b/crates/bevy_sprite/src/texture_atlas.rs index 53cc9cadd6be2..bc4003a1bf1dd 100644 --- a/crates/bevy_sprite/src/texture_atlas.rs +++ b/crates/bevy_sprite/src/texture_atlas.rs @@ -2,14 +2,14 @@ use crate::Anchor; use bevy_asset::Handle; use bevy_ecs::component::Component; use bevy_math::{Rect, Vec2}; -use bevy_reflect::{Reflect, TypeUuid}; +use bevy_reflect::{FromReflect, Reflect, TypeUuid}; use bevy_render::{color::Color, texture::Image}; use bevy_utils::HashMap; /// An atlas containing multiple textures (like a spritesheet or a tilemap). /// [Example usage animating sprite.](https://github.com/bevyengine/bevy/blob/latest/examples/2d/sprite_sheet.rs) /// [Example usage loading sprite sheet.](https://github.com/bevyengine/bevy/blob/latest/examples/2d/texture_atlas.rs) -#[derive(Debug, Clone, TypeUuid)] +#[derive(Reflect, FromReflect, Debug, Clone, TypeUuid)] #[uuid = "7233c597-ccfa-411f-bd59-9af349432ada"] pub struct TextureAtlas { /// The handle to the texture in which the sprites are stored From f862b372129b231a2bfa563ca04a63f1d172d465 Mon Sep 17 00:00:00 2001 From: Jakob Hellermann Date: Sun, 11 Sep 2022 20:57:33 +0200 Subject: [PATCH 13/18] add typed method --- crates/bevy_asset/src/reflect.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/crates/bevy_asset/src/reflect.rs b/crates/bevy_asset/src/reflect.rs index c8d70c90bd598..dad2c80f892d9 100644 --- a/crates/bevy_asset/src/reflect.rs +++ b/crates/bevy_asset/src/reflect.rs @@ -198,6 +198,7 @@ pub struct ReflectHandle { type_uuid: Uuid, asset_type_id: TypeId, downcast_handle_untyped: fn(&dyn Any) -> Option, + typed: fn(HandleUntyped) -> Box, } impl ReflectHandle { /// The [`bevy_reflect::TypeUuid`] of the asset @@ -213,6 +214,12 @@ impl ReflectHandle { pub fn downcast_handle_untyped(&self, handle: &dyn Any) -> Option { (self.downcast_handle_untyped)(handle) } + + /// A way to go from a [`HandleUntyped`] to a `Handle` in a `Box`. + /// Equivalent of [`HandleUntyped::typed`]. + pub fn typed(&self, handle: HandleUntyped) -> Box { + (self.typed)(handle) + } } impl FromType> for ReflectHandle { @@ -225,6 +232,7 @@ impl FromType> for ReflectHandle { .downcast_ref::>() .map(|handle| handle.clone_untyped()) }, + typed: |handle: HandleUntyped| Box::new(handle.typed::()), } } } From c511ba70b6a50228e3a6b7788dd1c069ec87d4c9 Mon Sep 17 00:00:00 2001 From: Jakob Hellermann Date: Wed, 14 Sep 2022 11:10:15 +0200 Subject: [PATCH 14/18] Apply suggestions from code review Co-authored-by: Gino Valente <49806985+MrGVSV@users.noreply.github.com> --- crates/bevy_asset/src/assets.rs | 12 +++--------- crates/bevy_asset/src/reflect.rs | 15 ++++++++------- 2 files changed, 11 insertions(+), 16 deletions(-) diff --git a/crates/bevy_asset/src/assets.rs b/crates/bevy_asset/src/assets.rs index b058dc3f423ed..23cf6459e1b3f 100644 --- a/crates/bevy_asset/src/assets.rs +++ b/crates/bevy_asset/src/assets.rs @@ -281,7 +281,7 @@ pub trait AddAsset { T: Asset; /// Registers the asset type `T` using `[App::register]`, - /// and adds [`ReflectAsset`] type data to `T` and [`ReflectHandle`] type data to `Handle` in the type registry. + /// and adds [`ReflectAsset`] type data to `T` and [`ReflectHandle`] type data to [`Handle`] in the type registry. /// /// This enables reflection code to access assets. For detailed information, see the docs on [`ReflectAsset`] and [`ReflectHandle`]. fn register_asset_reflect(&mut self) -> &mut Self @@ -351,14 +351,8 @@ impl AddAsset for App { type_registry.register::(); type_registry.register::>(); - type_registry - .get_mut(std::any::TypeId::of::()) - .unwrap() - .insert(>::from_type()); - type_registry - .get_mut(std::any::TypeId::of::>()) - .unwrap() - .insert(>>::from_type()); + type_registry.register_type_data::(); + type_registry.register_type_data::, ReflectHandle>(); } self diff --git a/crates/bevy_asset/src/reflect.rs b/crates/bevy_asset/src/reflect.rs index dad2c80f892d9..b170302e359f2 100644 --- a/crates/bevy_asset/src/reflect.rs +++ b/crates/bevy_asset/src/reflect.rs @@ -38,7 +38,7 @@ impl ReflectAsset { self.handle_type_id } - /// The [`TypeId`] of the [`Assets`] resource + /// The [`TypeId`] of the [`Assets`] resource pub fn assets_resource_type_id(&self) -> TypeId { self.assets_resource_type_id } @@ -47,6 +47,7 @@ impl ReflectAsset { pub fn get<'w>(&self, world: &'w World, handle: HandleUntyped) -> Option<&'w dyn Reflect> { (self.get)(world, handle) } + /// Equivalent of [`Assets::get_mut`] pub fn get_mut<'w>( &self, @@ -58,7 +59,7 @@ impl ReflectAsset { /// Equivalent of [`Assets::get_mut`], but does not require a mutable reference to the world. /// - /// Only use this method when you have ensured that you are the *only* one with access to the `Assets` resource of the asset type. + /// Only use this method when you have ensured that you are the *only* one with access to the [`Assets`] resource of the asset type. /// Furthermore, this does *not* allow you to have look up two distinct handles, /// you can only have at most one alive at the same time. /// @@ -142,13 +143,13 @@ impl FromType for ReflectAsset { add: |world, value| { let mut assets = world.resource_mut::>(); let value: A = FromReflect::from_reflect(value) - .expect("could not call `FromReflect::from_reflect` in `ReflectAsset::insert`"); + .expect("could not call `FromReflect::from_reflect` in `ReflectAsset::add`"); assets.add(value).into() }, set: |world, handle, value| { let mut assets = world.resource_mut::>(); let value: A = FromReflect::from_reflect(value) - .expect("could not call `FromReflect::from_reflect` in `ReflectAsset::insert`"); + .expect("could not call `FromReflect::from_reflect` in `ReflectAsset::set`"); assets.set(handle, value).into() }, len: |world| { @@ -168,7 +169,7 @@ impl FromType for ReflectAsset { } } -/// Reflect type data struct relating a `Handle` back to the `T` asset type. +/// Reflect type data struct relating a [`Handle`] back to the `T` asset type. /// /// Say you want to look up the asset values of a list of handles when you have access to their `&dyn Reflect` form. /// Assets can be looked up in the world using [`ReflectAsset`], but how do you determine which [`ReflectAsset`] to use when @@ -210,12 +211,12 @@ impl ReflectHandle { self.asset_type_id } - /// A way to go from a `Handle` in a `dyn Any` to a [`HandleUntyped`] + /// A way to go from a [`Handle`] in a `dyn Any` to a [`HandleUntyped`] pub fn downcast_handle_untyped(&self, handle: &dyn Any) -> Option { (self.downcast_handle_untyped)(handle) } - /// A way to go from a [`HandleUntyped`] to a `Handle` in a `Box`. + /// A way to go from a [`HandleUntyped`] to a [`Handle`] in a `Box`. /// Equivalent of [`HandleUntyped::typed`]. pub fn typed(&self, handle: HandleUntyped) -> Box { (self.typed)(handle) From e4e93eea2c54f9a99a8305c551eff758f45dd82b Mon Sep 17 00:00:00 2001 From: Jakob Hellermann Date: Wed, 14 Sep 2022 11:05:52 +0200 Subject: [PATCH 15/18] fix warnings and errors when compiling bevy_app with default_features = false --- crates/bevy_app/src/app.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/bevy_app/src/app.rs b/crates/bevy_app/src/app.rs index 450485d05db9e..300504bfad6ca 100644 --- a/crates/bevy_app/src/app.rs +++ b/crates/bevy_app/src/app.rs @@ -1,6 +1,5 @@ use crate::{CoreStage, Plugin, PluginGroup, StartupSchedule, StartupStage}; pub use bevy_derive::AppLabel; -use bevy_derive::{Deref, DerefMut}; use bevy_ecs::{ event::{Event, Events}, prelude::FromWorld, @@ -25,7 +24,7 @@ bevy_utils::define_label!( /// The [`Resource`] that stores the [`App`]'s [`TypeRegistry`](bevy_reflect::TypeRegistry). #[cfg(feature = "bevy_reflect")] -#[derive(Resource, Clone, Deref, DerefMut, Default)] +#[derive(Resource, Clone, bevy_derive::Deref, bevy_derive::DerefMut, Default)] pub struct AppTypeRegistry(pub bevy_reflect::TypeRegistryArc); #[allow(clippy::needless_doctest_main)] From 592e1365958e2eebee84ce3d7abd577cd82382c4 Mon Sep 17 00:00:00 2001 From: Jakob Hellermann Date: Wed, 14 Sep 2022 11:27:39 +0200 Subject: [PATCH 16/18] more review feedback --- crates/bevy_asset/src/assets.rs | 2 +- crates/bevy_asset/src/reflect.rs | 17 ++++++++++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/crates/bevy_asset/src/assets.rs b/crates/bevy_asset/src/assets.rs index 23cf6459e1b3f..f637250780b6a 100644 --- a/crates/bevy_asset/src/assets.rs +++ b/crates/bevy_asset/src/assets.rs @@ -8,7 +8,7 @@ use bevy_ecs::{ system::{ResMut, Resource}, world::FromWorld, }; -use bevy_reflect::{FromReflect, FromType, GetTypeRegistration, Reflect}; +use bevy_reflect::{FromReflect, GetTypeRegistration, Reflect}; use bevy_utils::HashMap; use crossbeam_channel::Sender; use std::fmt::Debug; diff --git a/crates/bevy_asset/src/reflect.rs b/crates/bevy_asset/src/reflect.rs index b170302e359f2..444096386588e 100644 --- a/crates/bevy_asset/src/reflect.rs +++ b/crates/bevy_asset/src/reflect.rs @@ -62,6 +62,21 @@ impl ReflectAsset { /// Only use this method when you have ensured that you are the *only* one with access to the [`Assets`] resource of the asset type. /// Furthermore, this does *not* allow you to have look up two distinct handles, /// you can only have at most one alive at the same time. + /// This means that this is *not allowed*: + /// ```rust,no_run + /// # use bevy_asset::{ReflectAsset, HandleUntyped}; + /// # use bevy_ecs::prelude::World; + /// # let reflect_asset: ReflectAsset = unimplemented!(); + /// # let world: World = unimplemented!(); + /// # let handle_1: HandleUntyped = unimplemented!(); + /// # let handle_2: HandleUntyped = unimplemented!(); + /// let a = unsafe { reflect_asset.get_unchecked_mut(&world, handle_1).unwrap() }; + /// let b = unsafe { reflect_asset.get_unchecked_mut(&world, handle_2).unwrap() }; + /// // ^ not allowed, two mutable references through the same asset resource, even though the + /// // handles are distinct + /// + /// println!("a = {a:?}, b = {b:?}"); + /// ``` /// /// # Safety /// This method does not prevent you from having two mutable pointers to the same data, @@ -254,7 +269,7 @@ mod tests { } #[test] - fn test() { + fn test_reflect_asset_operations() { let mut app = App::new(); app.add_plugin(AssetPlugin) .add_asset::() From 48eb298474b76089056293932f3357639c0e3873 Mon Sep 17 00:00:00 2001 From: Jakob Hellermann Date: Wed, 14 Sep 2022 11:29:51 +0200 Subject: [PATCH 17/18] reflect(Debug) --- crates/bevy_pbr/src/alpha.rs | 2 +- crates/bevy_pbr/src/pbr_material.rs | 2 +- crates/bevy_sprite/src/mesh2d/color_material.rs | 2 +- crates/bevy_sprite/src/texture_atlas.rs | 1 + 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/crates/bevy_pbr/src/alpha.rs b/crates/bevy_pbr/src/alpha.rs index 0bd1360ec6122..b42a78bd8ad4d 100644 --- a/crates/bevy_pbr/src/alpha.rs +++ b/crates/bevy_pbr/src/alpha.rs @@ -5,7 +5,7 @@ use bevy_reflect::{FromReflect, Reflect}; // TODO: add discussion about performance. /// Sets how a material's base color alpha channel is used for transparency. #[derive(Component, Debug, Default, Reflect, Copy, Clone, PartialEq, FromReflect)] -#[reflect(Component, Default)] +#[reflect(Component, Default, Debug)] pub enum AlphaMode { /// Base color alpha values are overridden to be fully opaque (1.0). #[default] diff --git a/crates/bevy_pbr/src/pbr_material.rs b/crates/bevy_pbr/src/pbr_material.rs index 5735b7c51fcd3..8e48acf5821c6 100644 --- a/crates/bevy_pbr/src/pbr_material.rs +++ b/crates/bevy_pbr/src/pbr_material.rs @@ -16,7 +16,7 @@ use bevy_render::{ #[uuid = "7494888b-c082-457b-aacf-517228cc0c22"] #[bind_group_data(StandardMaterialKey)] #[uniform(0, StandardMaterialUniform)] -#[reflect(Default)] +#[reflect(Default, Debug)] pub struct StandardMaterial { /// The color of the surface of the material before lighting. /// diff --git a/crates/bevy_sprite/src/mesh2d/color_material.rs b/crates/bevy_sprite/src/mesh2d/color_material.rs index cdafc1f70fd32..57c57deb2bc2c 100644 --- a/crates/bevy_sprite/src/mesh2d/color_material.rs +++ b/crates/bevy_sprite/src/mesh2d/color_material.rs @@ -40,7 +40,7 @@ impl Plugin for ColorMaterialPlugin { /// A [2d material](Material2d) that renders [2d meshes](crate::Mesh2dHandle) with a texture tinted by a uniform color #[derive(AsBindGroup, Reflect, FromReflect, Debug, Clone, TypeUuid)] -#[reflect(Default)] +#[reflect(Default, Debug)] #[uuid = "e228a544-e3ca-4e1e-bb9d-4d8bc1ad8c19"] #[uniform(0, ColorMaterialUniform)] pub struct ColorMaterial { diff --git a/crates/bevy_sprite/src/texture_atlas.rs b/crates/bevy_sprite/src/texture_atlas.rs index bc4003a1bf1dd..ae9891914fe3d 100644 --- a/crates/bevy_sprite/src/texture_atlas.rs +++ b/crates/bevy_sprite/src/texture_atlas.rs @@ -11,6 +11,7 @@ use bevy_utils::HashMap; /// [Example usage loading sprite sheet.](https://github.com/bevyengine/bevy/blob/latest/examples/2d/texture_atlas.rs) #[derive(Reflect, FromReflect, Debug, Clone, TypeUuid)] #[uuid = "7233c597-ccfa-411f-bd59-9af349432ada"] +#[reflect(Debug)] pub struct TextureAtlas { /// The handle to the texture in which the sprites are stored pub texture: Handle, From 51697dd0add1a38d7f527aae79c113c0f45392d8 Mon Sep 17 00:00:00 2001 From: Jakob Hellermann Date: Fri, 28 Oct 2022 21:24:40 +0200 Subject: [PATCH 18/18] fix test --- crates/bevy_asset/src/reflect.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bevy_asset/src/reflect.rs b/crates/bevy_asset/src/reflect.rs index 444096386588e..81b22b5603999 100644 --- a/crates/bevy_asset/src/reflect.rs +++ b/crates/bevy_asset/src/reflect.rs @@ -271,7 +271,7 @@ mod tests { #[test] fn test_reflect_asset_operations() { let mut app = App::new(); - app.add_plugin(AssetPlugin) + app.add_plugin(AssetPlugin::default()) .add_asset::() .register_asset_reflect::();