Skip to content
Snippets Groups Projects
plugin.rs 3.61 KiB
Newer Older
use bevy::{asset::Asset, ecs::component::Component, prelude::*};

use crate::{Animator, AnimatorState, AssetAnimator, TweenCompleted};
/// Plugin to add systems related to tweening of common components and assets.
///
/// This plugin adds systems for a predefined set of components and assets, to
/// allow their respective animators to be updated each frame:
/// - [`Transform`]
/// - [`Text`]
/// - [`Style`]
/// - [`Sprite`]
/// - [`ColorMaterial`]
///
/// This ensures that all predefined lenses work as intended, as well as any
/// custom lens animating the same component or asset type.
/// For other components and assets, including custom ones, the relevant system
/// needs to be added manually by the application:
/// - For components, add [`component_animator_system::<T>`] where `T:
///   Component`
/// - For assets, add [`asset_animator_system::<T>`] where `T: Asset`
/// This plugin is entirely optional. If you want more control, you can instead
/// add manually the relevant systems for the exact set of components and assets
/// actually animated.
/// [`Transform`]: https://docs.rs/bevy/0.7.0/bevy/transform/components/struct.Transform.html
/// [`Text`]: https://docs.rs/bevy/0.7.0/bevy/text/struct.Text.html
/// [`Style`]: https://docs.rs/bevy/0.7.0/bevy/ui/struct.Style.html
/// [`Sprite`]: https://docs.rs/bevy/0.7.0/bevy/sprite/struct.Sprite.html
/// [`ColorMaterial`]: https://docs.rs/bevy/0.7.0/bevy/sprite/struct.ColorMaterial.html
#[derive(Debug, Clone, Copy)]
pub struct TweeningPlugin;

impl Plugin for TweeningPlugin {
    fn build(&self, app: &mut App) {
        app.add_event::<TweenCompleted>().add_system(
            component_animator_system::<Transform>.label(AnimationSystem::AnimationUpdate),
        );
        #[cfg(feature = "bevy_ui")]
        app.add_system(component_animator_system::<Text>.label(AnimationSystem::AnimationUpdate))
            .add_system(component_animator_system::<Style>.label(AnimationSystem::AnimationUpdate));
        #[cfg(feature = "bevy_sprite")]
        app.add_system(component_animator_system::<Sprite>.label(AnimationSystem::AnimationUpdate))
            .add_system(
                asset_animator_system::<ColorMaterial>.label(AnimationSystem::AnimationUpdate),
            );
/// Label enum for the systems relating to animations
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash, SystemLabel)]
pub enum AnimationSystem {
    /// Ticks animations
    AnimationUpdate,
}

/// Animator system for components.
///
/// This system extracts all components of type `T` with an `Animator<T>`
/// attached to the same entity, and tick the animator to animate the component.
pub fn component_animator_system<T: Component>(
    time: Res<Time>,
    mut query: Query<(Entity, &mut T, &mut Animator<T>)>,
    mut event_writer: EventWriter<TweenCompleted>,
    for (entity, ref mut target, ref mut animator) in query.iter_mut() {
        if animator.state != AnimatorState::Paused {
Alex Saveau's avatar
Alex Saveau committed
            animator.tick(time.delta(), target, entity, &mut event_writer);
/// Animator system for assets.
///
/// This system ticks all `AssetAnimator<T>` components to animate their
/// associated asset.
pub fn asset_animator_system<T: Asset>(
    time: Res<Time>,
    mut assets: ResMut<Assets<T>>,
    mut query: Query<(Entity, &mut AssetAnimator<T>)>,
    mut event_writer: EventWriter<TweenCompleted>,
    for (entity, ref mut animator) in query.iter_mut() {
        if animator.state != AnimatorState::Paused {
            if let Some(target) = assets.get_mut(animator.handle()) {
Alex Saveau's avatar
Alex Saveau committed
                animator.tick(time.delta(), target, entity, &mut event_writer);