mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 07:04:33 +00:00
implement Reflect
for Input<T>
, some misc improvements to reflect value derive (#5676)
# Objective - I'm currently working on being able to call methods on reflect types (https://github.com/jakobhellermann/bevy_reflect_fns) - for that, I'd like to add methods to the `Input<KeyCode>` resource (which I'm doing by registering type data) - implementing `Reflect` is currently a requirement for having type data in the `TypeRegistry` ## Solution - derive `Reflect` for `KeyCode` and `Input` - uses `#[reflect_value]` for `Input`, since it's fields aren't supposed to be observable - using reflect_value would need `Clone` bounds on `T`, but since all the methods (`.pressed` etc) already require `T: Copy`, I unified everything to requiring `Copy` - add `Send + Sync + 'static` bounds, also required by reflect derive ## Unrelated improvements I can extract into a separate PR if needed. - the `Reflect` derive would previously ignore `#[reflect_value]` and only accept `#[reflect_value()]` which was a bit confusing - the generated code used `val.clone()` on a reference, which is fine if `val` impls `Clone`, but otherwise also compiles with a worse error message. Change to `std::clone::Clone::clone(val)` instead which gives a neat `T does not implement Clone` error
This commit is contained in:
parent
7a92555233
commit
7d9e864d9c
4 changed files with 21 additions and 17 deletions
|
@ -1,4 +1,5 @@
|
|||
use bevy_ecs::system::Resource;
|
||||
use bevy_reflect::Reflect;
|
||||
use bevy_utils::HashSet;
|
||||
use std::hash::Hash;
|
||||
|
||||
|
@ -33,8 +34,9 @@ use bevy_ecs::schedule::State;
|
|||
/// * Call the [`Input::press`] method for each press event.
|
||||
/// * Call the [`Input::release`] method for each release event.
|
||||
/// * Call the [`Input::clear`] method at each frame start, before processing events.
|
||||
#[derive(Debug, Clone, Resource)]
|
||||
pub struct Input<T: Eq + Hash> {
|
||||
#[derive(Debug, Clone, Resource, Reflect)]
|
||||
#[reflect_value]
|
||||
pub struct Input<T: Copy + Eq + Hash + Send + Sync + 'static> {
|
||||
/// A collection of every button that is currently being pressed.
|
||||
pressed: HashSet<T>,
|
||||
/// A collection of every button that has just been pressed.
|
||||
|
@ -43,7 +45,7 @@ pub struct Input<T: Eq + Hash> {
|
|||
just_released: HashSet<T>,
|
||||
}
|
||||
|
||||
impl<T: Eq + Hash> Default for Input<T> {
|
||||
impl<T: Copy + Eq + Hash + Send + Sync + 'static> Default for Input<T> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
pressed: Default::default(),
|
||||
|
@ -55,7 +57,7 @@ impl<T: Eq + Hash> Default for Input<T> {
|
|||
|
||||
impl<T> Input<T>
|
||||
where
|
||||
T: Copy + Eq + Hash,
|
||||
T: Copy + Eq + Hash + Send + Sync + 'static,
|
||||
{
|
||||
/// Registers a press for the given `input`.
|
||||
pub fn press(&mut self, input: T) {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use crate::{ButtonState, Input};
|
||||
use bevy_ecs::{event::EventReader, system::ResMut};
|
||||
use bevy_reflect::{FromReflect, Reflect};
|
||||
|
||||
/// A keyboard input event.
|
||||
///
|
||||
|
@ -60,8 +61,9 @@ pub fn keyboard_input_system(
|
|||
/// ## Updating
|
||||
///
|
||||
/// The resource is updated inside of the [`keyboard_input_system`](crate::keyboard::keyboard_input_system).
|
||||
#[derive(Debug, Hash, Ord, PartialOrd, PartialEq, Eq, Clone, Copy)]
|
||||
#[derive(Reflect, FromReflect, Debug, Hash, Ord, PartialOrd, PartialEq, Eq, Clone, Copy)]
|
||||
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
|
||||
#[reflect(Hash, PartialEq)]
|
||||
#[repr(u32)]
|
||||
pub enum KeyCode {
|
||||
/// The `1` key over the letters.
|
||||
|
@ -422,6 +424,7 @@ pub enum KeyCode {
|
|||
/// ## Updating
|
||||
///
|
||||
/// The resource is updated inside of the [`keyboard_input_system`](crate::keyboard::keyboard_input_system).
|
||||
#[derive(Debug, Hash, Ord, PartialOrd, PartialEq, Eq, Clone, Copy)]
|
||||
#[derive(Reflect, FromReflect, Debug, Hash, Ord, PartialOrd, PartialEq, Eq, Clone, Copy)]
|
||||
#[reflect(Hash, PartialEq)]
|
||||
#[cfg_attr(feature = "serialize", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct ScanCode(pub u32);
|
||||
|
|
|
@ -111,19 +111,18 @@ impl<'a> ReflectDerive<'a> {
|
|||
let mut force_reflect_value = false;
|
||||
|
||||
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
|
||||
} else {
|
||||
continue;
|
||||
};
|
||||
|
||||
if let Some(ident) = meta_list.path.get_ident() {
|
||||
if ident == REFLECT_ATTRIBUTE_NAME {
|
||||
match attribute {
|
||||
Meta::List(meta_list) if meta_list.path.is_ident(REFLECT_ATTRIBUTE_NAME) => {
|
||||
traits = ReflectTraits::from_nested_metas(&meta_list.nested);
|
||||
} else if ident == REFLECT_VALUE_ATTRIBUTE_NAME {
|
||||
}
|
||||
Meta::List(meta_list) if meta_list.path.is_ident(REFLECT_VALUE_ATTRIBUTE_NAME) => {
|
||||
force_reflect_value = true;
|
||||
traits = ReflectTraits::from_nested_metas(&meta_list.nested);
|
||||
}
|
||||
Meta::Path(path) if path.is_ident(REFLECT_VALUE_ATTRIBUTE_NAME) => {
|
||||
force_reflect_value = true;
|
||||
}
|
||||
_ => continue,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -68,14 +68,14 @@ pub(crate) fn impl_value(meta: &ReflectMeta) -> TokenStream {
|
|||
|
||||
#[inline]
|
||||
fn clone_value(&self) -> Box<dyn #bevy_reflect_path::Reflect> {
|
||||
Box::new(self.clone())
|
||||
Box::new(std::clone::Clone::clone(self))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn apply(&mut self, value: &dyn #bevy_reflect_path::Reflect) {
|
||||
let value = value.as_any();
|
||||
if let Some(value) = value.downcast_ref::<Self>() {
|
||||
*self = value.clone();
|
||||
*self = std::clone::Clone::clone(value);
|
||||
} else {
|
||||
panic!("Value is not {}.", std::any::type_name::<Self>());
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue