### 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?
24 lines
615 B
Rust
24 lines
615 B
Rust
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, Default)]
|
|
pub enum AlphaMode {
|
|
Opaque,
|
|
/// An alpha cutoff must be supplied where alpha values >= the cutoff
|
|
/// will be fully opaque and < will be fully transparent
|
|
Mask(f32),
|
|
Blend,
|
|
}
|
|
|
|
impl Eq for AlphaMode {}
|
|
|
|
impl Default for AlphaMode {
|
|
fn default() -> Self {
|
|
AlphaMode::Opaque
|
|
}
|
|
}
|