mirror of
https://github.com/bevyengine/bevy
synced 2025-02-16 14:08:32 +00:00
add #[reflect(Default)]
to create default value for reflected types (#3733)
### Problem It currently isn't possible to construct the default value of a reflected type. Because of that, it isn't possible to use `add_component` of `ReflectComponent` to add a new component to an entity because you can't know what the initial value should be. ### Solution 1. add `ReflectDefault` type ```rust #[derive(Clone)] pub struct ReflectDefault { default: fn() -> Box<dyn Reflect>, } impl ReflectDefault { pub fn default(&self) -> Box<dyn Reflect> { (self.default)() } } impl<T: Reflect + Default> FromType<T> for ReflectDefault { fn from_type() -> Self { ReflectDefault { default: || Box::new(T::default()), } } } ``` 2. add `#[reflect(Default)]` to all component types that implement `Default` and are user facing (so not `ComputedSize`, `CubemapVisibleEntities` etc.) This makes it possible to add the default value of a component to an entity without any compile-time information: ```rust fn main() { let mut app = App::new(); app.register_type::<Camera>(); let type_registry = app.world.get_resource::<TypeRegistry>().unwrap(); let type_registry = type_registry.read(); let camera_registration = type_registry.get(std::any::TypeId::of::<Camera>()).unwrap(); let reflect_default = camera_registration.data::<ReflectDefault>().unwrap(); let reflect_component = camera_registration .data::<ReflectComponent>() .unwrap() .clone(); let default = reflect_default.default(); drop(type_registry); let entity = app.world.spawn().id(); reflect_component.add_component(&mut app.world, entity, &*default); let camera = app.world.entity(entity).get::<Camera>().unwrap(); dbg!(&camera); } ``` ### Open questions - should we have `ReflectDefault` or `ReflectFromWorld` or both?
This commit is contained in:
parent
479f43bbf3
commit
2b6e67f4cb
17 changed files with 65 additions and 26 deletions
|
@ -1,4 +1,5 @@
|
|||
use bevy_ecs::{component::Component, reflect::ReflectComponent};
|
||||
use bevy_reflect::std_traits::ReflectDefault;
|
||||
use bevy_reflect::Reflect;
|
||||
use bevy_utils::AHasher;
|
||||
use std::{
|
||||
|
@ -14,7 +15,7 @@ use std::{
|
|||
/// 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)]
|
||||
#[reflect(Component)]
|
||||
#[reflect(Component, Default)]
|
||||
pub struct Name {
|
||||
hash: u64, // TODO: Shouldn't be serialized
|
||||
name: Cow<'static, str>,
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
use bevy_reflect::prelude::*;
|
||||
use bevy_reflect::Reflect;
|
||||
use bevy_utils::Duration;
|
||||
|
||||
|
@ -23,6 +24,7 @@ use bevy_utils::Duration;
|
|||
/// assert_eq!(stopwatch.elapsed_secs(), 0.0);
|
||||
/// ```
|
||||
#[derive(Clone, Debug, Default, Reflect)]
|
||||
#[reflect(Default)]
|
||||
pub struct Stopwatch {
|
||||
elapsed: Duration,
|
||||
paused: bool,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::Stopwatch;
|
||||
use bevy_reflect::Reflect;
|
||||
use bevy_reflect::prelude::*;
|
||||
use bevy_utils::Duration;
|
||||
|
||||
/// Tracks elapsed time. Enters the finished state once `duration` is reached.
|
||||
|
@ -10,6 +10,7 @@ use bevy_utils::Duration;
|
|||
///
|
||||
/// Paused timers will not have elapsed time increased.
|
||||
#[derive(Clone, Debug, Default, Reflect)]
|
||||
#[reflect(Default)]
|
||||
pub struct Timer {
|
||||
stopwatch: Stopwatch,
|
||||
duration: Duration,
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
use bevy_ecs::{component::Component, reflect::ReflectComponent};
|
||||
use bevy_reflect::std_traits::ReflectDefault;
|
||||
use bevy_reflect::Reflect;
|
||||
|
||||
// FIXME: This should probably be part of bevy_render2!
|
||||
/// Alpha mode
|
||||
#[derive(Component, Debug, Reflect, Copy, Clone, PartialEq)]
|
||||
#[reflect(Component)]
|
||||
#[reflect(Component, Default)]
|
||||
pub enum AlphaMode {
|
||||
Opaque,
|
||||
/// An alpha cutoff must be supplied where alpha values >= the cutoff
|
||||
|
|
|
@ -3,7 +3,7 @@ use std::collections::HashSet;
|
|||
use bevy_asset::Assets;
|
||||
use bevy_ecs::prelude::*;
|
||||
use bevy_math::{Mat4, UVec2, UVec3, Vec2, Vec3, Vec3A, Vec3Swizzles, Vec4, Vec4Swizzles};
|
||||
use bevy_reflect::Reflect;
|
||||
use bevy_reflect::prelude::*;
|
||||
use bevy_render::{
|
||||
camera::{Camera, CameraProjection, OrthographicProjection},
|
||||
color::Color,
|
||||
|
@ -41,7 +41,7 @@ use crate::{
|
|||
///
|
||||
/// Source: [Wikipedia](https://en.wikipedia.org/wiki/Lumen_(unit)#Lighting)
|
||||
#[derive(Component, Debug, Clone, Copy, Reflect)]
|
||||
#[reflect(Component)]
|
||||
#[reflect(Component, Default)]
|
||||
pub struct PointLight {
|
||||
pub color: Color,
|
||||
pub intensity: f32,
|
||||
|
@ -113,7 +113,7 @@ impl Default for PointLightShadowMap {
|
|||
///
|
||||
/// Source: [Wikipedia](https://en.wikipedia.org/wiki/Lux)
|
||||
#[derive(Component, Debug, Clone, Reflect)]
|
||||
#[reflect(Component)]
|
||||
#[reflect(Component, Default)]
|
||||
pub struct DirectionalLight {
|
||||
pub color: Color,
|
||||
/// Illuminance in lux
|
||||
|
@ -185,10 +185,12 @@ impl Default for AmbientLight {
|
|||
}
|
||||
|
||||
/// Add this component to make a [`Mesh`](bevy_render::mesh::Mesh) not cast shadows.
|
||||
#[derive(Component)]
|
||||
#[derive(Component, Reflect, Default)]
|
||||
#[reflect(Component, Default)]
|
||||
pub struct NotShadowCaster;
|
||||
/// Add this component to make a [`Mesh`](bevy_render::mesh::Mesh) not receive shadows.
|
||||
#[derive(Component)]
|
||||
#[derive(Component, Reflect, Default)]
|
||||
#[reflect(Component, Default)]
|
||||
pub struct NotShadowReceiver;
|
||||
|
||||
#[derive(Debug, Hash, PartialEq, Eq, Clone, SystemLabel)]
|
||||
|
|
|
@ -4,6 +4,7 @@ use bevy_app::Plugin;
|
|||
use bevy_asset::{load_internal_asset, Handle, HandleUntyped};
|
||||
use bevy_core_pipeline::Opaque3d;
|
||||
use bevy_ecs::{prelude::*, reflect::ReflectComponent};
|
||||
use bevy_reflect::std_traits::ReflectDefault;
|
||||
use bevy_reflect::{Reflect, TypeUuid};
|
||||
use bevy_render::{
|
||||
mesh::{Mesh, MeshVertexBufferLayout},
|
||||
|
@ -61,7 +62,7 @@ fn extract_wireframes(mut commands: Commands, query: Query<Entity, With<Wirefram
|
|||
|
||||
/// Controls whether an entity should rendered in wireframe-mode if the [`WireframePlugin`] is enabled
|
||||
#[derive(Component, Debug, Clone, Default, Reflect)]
|
||||
#[reflect(Component)]
|
||||
#[reflect(Component, Default)]
|
||||
pub struct Wireframe;
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
|
|
|
@ -24,7 +24,10 @@ mod impls {
|
|||
}
|
||||
|
||||
pub mod serde;
|
||||
pub mod std_traits;
|
||||
|
||||
pub mod prelude {
|
||||
pub use crate::std_traits::*;
|
||||
#[doc(hidden)]
|
||||
pub use crate::{
|
||||
reflect_trait, GetField, GetTupleStructField, Reflect, ReflectDeserialize, Struct,
|
||||
|
|
23
crates/bevy_reflect/src/std_traits.rs
Normal file
23
crates/bevy_reflect/src/std_traits.rs
Normal file
|
@ -0,0 +1,23 @@
|
|||
use crate::{FromType, Reflect};
|
||||
|
||||
/// A struct used to provide the default value of a type.
|
||||
///
|
||||
/// A [`ReflectDefault`] for type `T` can be obtained via [`FromType::from_type`].
|
||||
#[derive(Clone)]
|
||||
pub struct ReflectDefault {
|
||||
default: fn() -> Box<dyn Reflect>,
|
||||
}
|
||||
|
||||
impl ReflectDefault {
|
||||
pub fn default(&self) -> Box<dyn Reflect> {
|
||||
(self.default)()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Reflect + Default> FromType<T> for ReflectDefault {
|
||||
fn from_type() -> Self {
|
||||
ReflectDefault {
|
||||
default: || Box::new(T::default()),
|
||||
}
|
||||
}
|
||||
}
|
|
@ -21,7 +21,7 @@ use bevy_ecs::{
|
|||
system::{Commands, ParamSet, Query, Res, ResMut},
|
||||
};
|
||||
use bevy_math::{Mat4, UVec2, Vec2, Vec3};
|
||||
use bevy_reflect::{Reflect, ReflectDeserialize};
|
||||
use bevy_reflect::prelude::*;
|
||||
use bevy_transform::components::GlobalTransform;
|
||||
use bevy_utils::HashSet;
|
||||
use bevy_window::{WindowCreated, WindowId, WindowResized, Windows};
|
||||
|
@ -29,7 +29,7 @@ use serde::{Deserialize, Serialize};
|
|||
use wgpu::Extent3d;
|
||||
|
||||
#[derive(Component, Default, Debug, Reflect, Clone)]
|
||||
#[reflect(Component)]
|
||||
#[reflect(Component, Default)]
|
||||
pub struct Camera {
|
||||
pub projection_matrix: Mat4,
|
||||
#[reflect(ignore)]
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use super::DepthCalculation;
|
||||
use bevy_ecs::{component::Component, reflect::ReflectComponent};
|
||||
use bevy_math::Mat4;
|
||||
use bevy_reflect::std_traits::ReflectDefault;
|
||||
use bevy_reflect::{Reflect, ReflectDeserialize};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
|
@ -12,7 +13,7 @@ pub trait CameraProjection {
|
|||
}
|
||||
|
||||
#[derive(Component, Debug, Clone, Reflect)]
|
||||
#[reflect(Component)]
|
||||
#[reflect(Component, Default)]
|
||||
pub struct PerspectiveProjection {
|
||||
pub fov: f32,
|
||||
pub aspect_ratio: f32,
|
||||
|
@ -72,7 +73,7 @@ pub enum ScalingMode {
|
|||
}
|
||||
|
||||
#[derive(Component, Debug, Clone, Reflect)]
|
||||
#[reflect(Component)]
|
||||
#[reflect(Component, Default)]
|
||||
pub struct OrthographicProjection {
|
||||
pub left: f32,
|
||||
pub right: f32,
|
||||
|
|
|
@ -6,6 +6,7 @@ pub use render_layers::*;
|
|||
use bevy_app::{CoreStage, Plugin};
|
||||
use bevy_asset::{Assets, Handle};
|
||||
use bevy_ecs::prelude::*;
|
||||
use bevy_reflect::std_traits::ReflectDefault;
|
||||
use bevy_reflect::Reflect;
|
||||
use bevy_transform::components::GlobalTransform;
|
||||
use bevy_transform::TransformSystem;
|
||||
|
@ -18,7 +19,7 @@ use crate::{
|
|||
|
||||
/// User indication of whether an entity is visible
|
||||
#[derive(Component, Clone, Reflect, Debug)]
|
||||
#[reflect(Component)]
|
||||
#[reflect(Component, Default)]
|
||||
pub struct Visibility {
|
||||
pub is_visible: bool,
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use bevy_ecs::prelude::{Component, ReflectComponent};
|
||||
use bevy_reflect::std_traits::ReflectDefault;
|
||||
use bevy_reflect::Reflect;
|
||||
|
||||
type LayerMask = u32;
|
||||
|
@ -20,7 +21,7 @@ pub type Layer = u8;
|
|||
///
|
||||
/// Entities without this component belong to layer `0`.
|
||||
#[derive(Component, Copy, Clone, Reflect, PartialEq, Eq, PartialOrd, Ord)]
|
||||
#[reflect(Component, PartialEq)]
|
||||
#[reflect(Component, Default, PartialEq)]
|
||||
pub struct RenderLayers(LayerMask);
|
||||
|
||||
impl std::fmt::Debug for RenderLayers {
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
use bevy_asset::Handle;
|
||||
use bevy_ecs::{prelude::Component, reflect::ReflectComponent};
|
||||
use bevy_reflect::{FromReflect, Reflect, ReflectDeserialize};
|
||||
use bevy_reflect::{prelude::*, FromReflect};
|
||||
use bevy_render::color::Color;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::Font;
|
||||
|
||||
#[derive(Component, Debug, Default, Clone, Reflect)]
|
||||
#[reflect(Component)]
|
||||
#[reflect(Component, Default)]
|
||||
pub struct Text {
|
||||
pub sections: Vec<TextSection>,
|
||||
pub alignment: TextAlignment,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use super::Transform;
|
||||
use bevy_ecs::{component::Component, reflect::ReflectComponent};
|
||||
use bevy_math::{const_vec3, Affine3A, Mat3, Mat4, Quat, Vec3};
|
||||
use bevy_reflect::Reflect;
|
||||
use bevy_reflect::prelude::*;
|
||||
use std::ops::Mul;
|
||||
|
||||
/// Describe the position of an entity relative to the reference frame.
|
||||
|
@ -25,7 +25,7 @@ use std::ops::Mul;
|
|||
/// update the[`Transform`] of an entity in this stage or after, you will notice a 1 frame lag
|
||||
/// before the [`GlobalTransform`] is updated.
|
||||
#[derive(Component, Debug, PartialEq, Clone, Copy, Reflect)]
|
||||
#[reflect(Component, PartialEq)]
|
||||
#[reflect(Component, Default, PartialEq)]
|
||||
pub struct GlobalTransform {
|
||||
/// The position of the global transform
|
||||
pub translation: Vec3,
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use super::GlobalTransform;
|
||||
use bevy_ecs::{component::Component, reflect::ReflectComponent};
|
||||
use bevy_math::{const_vec3, Mat3, Mat4, Quat, Vec3};
|
||||
use bevy_reflect::prelude::*;
|
||||
use bevy_reflect::Reflect;
|
||||
use std::ops::Mul;
|
||||
|
||||
|
@ -26,7 +27,7 @@ use std::ops::Mul;
|
|||
/// update the[`Transform`] of an entity in this stage or after, you will notice a 1 frame lag
|
||||
/// before the [`GlobalTransform`] is updated.
|
||||
#[derive(Component, Debug, PartialEq, Clone, Copy, Reflect)]
|
||||
#[reflect(Component, PartialEq)]
|
||||
#[reflect(Component, Default, PartialEq)]
|
||||
pub struct Transform {
|
||||
/// Position of the entity. In 2d, the last value of the `Vec3` is used for z-ordering.
|
||||
pub translation: Vec3,
|
||||
|
|
|
@ -2,7 +2,7 @@ use crate::{Size, UiRect};
|
|||
use bevy_asset::Handle;
|
||||
use bevy_ecs::{prelude::Component, reflect::ReflectComponent};
|
||||
use bevy_math::Vec2;
|
||||
use bevy_reflect::{Reflect, ReflectDeserialize};
|
||||
use bevy_reflect::prelude::*;
|
||||
use bevy_render::{
|
||||
color::Color,
|
||||
texture::{Image, DEFAULT_IMAGE_HANDLE},
|
||||
|
@ -12,7 +12,7 @@ use std::ops::{Add, AddAssign};
|
|||
|
||||
/// Describes the size of a UI node
|
||||
#[derive(Component, Debug, Clone, Default, Reflect)]
|
||||
#[reflect(Component)]
|
||||
#[reflect(Component, Default)]
|
||||
pub struct Node {
|
||||
/// The size of the node as width and height in pixels
|
||||
pub size: Vec2,
|
||||
|
@ -68,7 +68,7 @@ impl AddAssign<f32> for Val {
|
|||
/// **Note:** Bevy's UI is upside down compared to how Flexbox normally works, to stay consistent with engine paradigms about layouting from
|
||||
/// the upper left corner of the display
|
||||
#[derive(Component, Clone, PartialEq, Debug, Reflect)]
|
||||
#[reflect(Component, PartialEq)]
|
||||
#[reflect(Component, Default, PartialEq)]
|
||||
pub struct Style {
|
||||
/// Whether to arrange this node and its children with flexbox layout
|
||||
pub display: Display,
|
||||
|
@ -359,7 +359,7 @@ pub struct CalculatedSize {
|
|||
|
||||
/// The color of the node
|
||||
#[derive(Component, Default, Copy, Clone, Debug, Reflect)]
|
||||
#[reflect(Component)]
|
||||
#[reflect(Component, Default)]
|
||||
pub struct UiColor(pub Color);
|
||||
|
||||
impl From<Color> for UiColor {
|
||||
|
@ -370,7 +370,7 @@ impl From<Color> for UiColor {
|
|||
|
||||
/// The image of the node
|
||||
#[derive(Component, Clone, Debug, Reflect)]
|
||||
#[reflect(Component)]
|
||||
#[reflect(Component, Default)]
|
||||
pub struct UiImage(pub Handle<Image>);
|
||||
|
||||
impl Default for UiImage {
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
use bevy_ecs::prelude::Component;
|
||||
use bevy_ecs::reflect::ReflectComponent;
|
||||
use bevy_reflect::std_traits::ReflectDefault;
|
||||
use bevy_reflect::Reflect;
|
||||
|
||||
/// Marker struct for buttons
|
||||
#[derive(Component, Debug, Default, Clone, Copy, Reflect)]
|
||||
#[reflect(Component)]
|
||||
#[reflect(Component, Default)]
|
||||
pub struct Button;
|
||||
|
|
Loading…
Add table
Reference in a new issue