bevy/crates/bevy_animation/src/animation_event.rs
Tim 3da0ef048e
Remove the Component trait implementation from Handle (#15796)
# Objective

- Closes #15716
- Closes #15718

## Solution

- Replace `Handle<MeshletMesh>` with a new `MeshletMesh3d` component
- As expected there were some random things that needed fixing:
- A couple tests were storing handles just to prevent them from being
dropped I believe, which seems to have been unnecessary in some.
- The `SpriteBundle` still had a `Handle<Image>` field. I've removed
this.
- Tests in `bevy_sprite` incorrectly added a `Handle<Image>` field
outside of the `Sprite` component.
- A few examples were still inserting `Handle`s, switched those to their
corresponding wrappers.
- 2 examples that were still querying for `Handle<Image>` were changed
to query `Sprite`

## Testing

- I've verified that the changed example work now

## Migration Guide

`Handle` can no longer be used as a `Component`. All existing Bevy types
using this pattern have been wrapped in their own semantically
meaningful type. You should do the same for any custom `Handle`
components your project needs.

The `Handle<MeshletMesh>` component is now `MeshletMesh3d`.

The `WithMeshletMesh` type alias has been removed. Use
`With<MeshletMesh3d>` instead.
2024-10-09 21:10:01 +00:00

282 lines
8.1 KiB
Rust

//! Traits and types for triggering events from animations.
use core::{any::Any, fmt::Debug};
use bevy_ecs::prelude::*;
use bevy_reflect::{
prelude::*, utility::NonGenericTypeInfoCell, ApplyError, DynamicTupleStruct, FromType,
GetTypeRegistration, ReflectFromPtr, ReflectKind, ReflectMut, ReflectOwned, ReflectRef,
TupleStructFieldIter, TupleStructInfo, TypeInfo, TypeRegistration, Typed, UnnamedField,
};
pub use bevy_animation_derive::AnimationEvent;
pub(crate) fn trigger_animation_event(
entity: Entity,
time: f32,
weight: f32,
event: Box<dyn AnimationEvent>,
) -> impl Command {
move |world: &mut World| {
event.trigger(time, weight, entity, world);
}
}
/// An event that can be used with animations.
/// It can be derived to trigger as an observer event,
/// if you need more complex behaviour, consider
/// a manual implementation.
///
/// # Example
///
/// ```rust
/// # use bevy_animation::prelude::*;
/// # use bevy_ecs::prelude::*;
/// # use bevy_reflect::prelude::*;
/// # use bevy_asset::prelude::*;
/// #
/// #[derive(Event, AnimationEvent, Reflect, Clone)]
/// struct Say(String);
///
/// fn on_say(trigger: Trigger<Say>) {
/// println!("{}", trigger.event().0);
/// }
///
/// fn setup_animation(
/// mut commands: Commands,
/// mut animations: ResMut<Assets<AnimationClip>>,
/// mut graphs: ResMut<Assets<AnimationGraph>>,
/// ) {
/// // Create a new animation and add an event at 1.0s.
/// let mut animation = AnimationClip::default();
/// animation.add_event(1.0, Say("Hello".into()));
///
/// // Create an animation graph.
/// let (graph, animation_index) = AnimationGraph::from_clip(animations.add(animation));
///
/// // Start playing the animation.
/// let mut player = AnimationPlayer::default();
/// player.play(animation_index).repeat();
///
/// commands.spawn((AnimationGraphHandle(graphs.add(graph)), player));
/// }
/// #
/// # bevy_ecs::system::assert_is_system(setup_animation);
/// ```
#[reflect_trait]
pub trait AnimationEvent: CloneableAnimationEvent + Reflect + Send + Sync {
/// Trigger the event, targeting `entity`.
fn trigger(&self, time: f32, weight: f32, entity: Entity, world: &mut World);
}
/// This trait exist so that manual implementors of [`AnimationEvent`]
/// do not have to implement `clone_value`.
#[diagnostic::on_unimplemented(
message = "`{Self}` does not implement `Clone`",
note = "consider annotating `{Self}` with `#[derive(Clone)]`"
)]
pub trait CloneableAnimationEvent {
/// Clone this value into a new `Box<dyn AnimationEvent>`
fn clone_value(&self) -> Box<dyn AnimationEvent>;
}
impl<T: AnimationEvent + Clone> CloneableAnimationEvent for T {
fn clone_value(&self) -> Box<dyn AnimationEvent> {
Box::new(self.clone())
}
}
/// The data that will be used to trigger an animation event.
#[derive(TypePath)]
pub(crate) struct AnimationEventData(pub(crate) Box<dyn AnimationEvent>);
impl AnimationEventData {
pub(crate) fn new(event: impl AnimationEvent) -> Self {
Self(Box::new(event))
}
}
impl Debug for AnimationEventData {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.write_str("AnimationEventData(")?;
PartialReflect::debug(self.0.as_ref(), f)?;
f.write_str(")")?;
Ok(())
}
}
impl Clone for AnimationEventData {
fn clone(&self) -> Self {
Self(CloneableAnimationEvent::clone_value(self.0.as_ref()))
}
}
// We have to implement `GetTypeRegistration` manually because of the embedded
// `Box<dyn AnimationEvent>`, which can't be automatically derived yet.
impl GetTypeRegistration for AnimationEventData {
fn get_type_registration() -> TypeRegistration {
let mut registration = TypeRegistration::of::<Self>();
registration.insert::<ReflectFromPtr>(FromType::<Self>::from_type());
registration
}
}
// We have to implement `Typed` manually because of the embedded
// `Box<dyn AnimationEvent>`, which can't be automatically derived yet.
impl Typed for AnimationEventData {
fn type_info() -> &'static TypeInfo {
static CELL: NonGenericTypeInfoCell = NonGenericTypeInfoCell::new();
CELL.get_or_set(|| {
TypeInfo::TupleStruct(TupleStructInfo::new::<Self>(&[UnnamedField::new::<()>(0)]))
})
}
}
// We have to implement `TupleStruct` manually because of the embedded
// `Box<dyn AnimationEvent>`, which can't be automatically derived yet.
impl TupleStruct for AnimationEventData {
fn field(&self, index: usize) -> Option<&dyn PartialReflect> {
match index {
0 => Some(self.0.as_partial_reflect()),
_ => None,
}
}
fn field_mut(&mut self, index: usize) -> Option<&mut dyn PartialReflect> {
match index {
0 => Some(self.0.as_partial_reflect_mut()),
_ => None,
}
}
fn field_len(&self) -> usize {
1
}
fn iter_fields(&self) -> TupleStructFieldIter {
TupleStructFieldIter::new(self)
}
fn clone_dynamic(&self) -> DynamicTupleStruct {
DynamicTupleStruct::from_iter([PartialReflect::clone_value(&*self.0)])
}
}
// We have to implement `PartialReflect` manually because of the embedded
// `Box<dyn AnimationEvent>`, which can't be automatically derived yet.
impl PartialReflect for AnimationEventData {
#[inline]
fn get_represented_type_info(&self) -> Option<&'static TypeInfo> {
Some(<Self as Typed>::type_info())
}
#[inline]
fn into_partial_reflect(self: Box<Self>) -> Box<dyn PartialReflect> {
self
}
#[inline]
fn as_partial_reflect(&self) -> &dyn PartialReflect {
self
}
#[inline]
fn as_partial_reflect_mut(&mut self) -> &mut dyn PartialReflect {
self
}
fn try_into_reflect(self: Box<Self>) -> Result<Box<dyn Reflect>, Box<dyn PartialReflect>> {
Ok(self)
}
#[inline]
fn try_as_reflect(&self) -> Option<&dyn Reflect> {
Some(self)
}
#[inline]
fn try_as_reflect_mut(&mut self) -> Option<&mut dyn Reflect> {
Some(self)
}
fn try_apply(&mut self, value: &dyn PartialReflect) -> Result<(), ApplyError> {
if let ReflectRef::TupleStruct(struct_value) = value.reflect_ref() {
for (i, value) in struct_value.iter_fields().enumerate() {
if let Some(v) = self.field_mut(i) {
v.try_apply(value)?;
}
}
} else {
return Err(ApplyError::MismatchedKinds {
from_kind: value.reflect_kind(),
to_kind: ReflectKind::TupleStruct,
});
}
Ok(())
}
fn reflect_ref(&self) -> ReflectRef {
ReflectRef::TupleStruct(self)
}
fn reflect_mut(&mut self) -> ReflectMut {
ReflectMut::TupleStruct(self)
}
fn reflect_owned(self: Box<Self>) -> ReflectOwned {
ReflectOwned::TupleStruct(self)
}
fn clone_value(&self) -> Box<dyn PartialReflect> {
Box::new(Clone::clone(self))
}
}
// We have to implement `Reflect` manually because of the embedded
// `Box<dyn AnimationEvent>`, which can't be automatically derived yet.
impl Reflect for AnimationEventData {
#[inline]
fn into_any(self: Box<Self>) -> Box<dyn Any> {
self
}
#[inline]
fn as_any(&self) -> &dyn Any {
self
}
#[inline]
fn as_any_mut(&mut self) -> &mut dyn Any {
self
}
#[inline]
fn into_reflect(self: Box<Self>) -> Box<dyn Reflect> {
self
}
#[inline]
fn as_reflect(&self) -> &dyn Reflect {
self
}
#[inline]
fn as_reflect_mut(&mut self) -> &mut dyn Reflect {
self
}
#[inline]
fn set(&mut self, value: Box<dyn Reflect>) -> Result<(), Box<dyn Reflect>> {
*self = value.take()?;
Ok(())
}
}
// We have to implement `FromReflect` manually because of the embedded
// `Box<dyn AnimationEvent>`, which can't be automatically derived yet.
impl FromReflect for AnimationEventData {
fn from_reflect(reflect: &dyn PartialReflect) -> Option<Self> {
Some(reflect.try_downcast_ref::<AnimationEventData>()?.clone())
}
}