Skip to content
Snippets Groups Projects
systems.rs 2.62 KiB
Newer Older
Louis's avatar
Louis committed
use bevy::prelude::*;

use crate::definitions::*;
use crate::query::AnimationQuery;

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, SystemLabel)]
pub enum AnimationSystems {
	TickAnimations,
	SyncAnimations,
}

#[derive(Copy, Clone, Debug, Component, PartialEq, Eq, Ord, PartialOrd)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct AnimationCompleted {
	pub entity: Entity,
	pub user_data: u128,
}

pub fn tick_animations(time: Res<Time>, mut query: AnimationQuery) {
	let seconds = time.delta_seconds();
	let _ = query.tick_all(seconds);
}

pub fn tick_simple_sprite_animations(
	time: Res<Time>,
	mut query: Query<
		(
			&SimpleLoopedAnimation,
			&mut SimpleLoopedAnimationStatus,
			&mut TextureAtlasSprite,
		),
		With<HasSimpleAnimations>,
	>,
) {
	let seconds = time.delta_seconds();
	for (animation, mut state, mut sprite) in &mut query {
		state.frame_time += seconds;
		while state.frame_time >= animation.frame_secs {
			state.frame_time -= animation.frame_secs;
			state.active_step += 1;
			if state.active_step >= animation.frames.len() {
				state.active_step = 0;
			}
		}

		sprite.index = animation.frames[state.active_step];
	}
}

pub fn sync_parent_animations(mut query: AnimationQuery) {
	query.sync_parent_animations();
}

#[cfg(feature = "ecs_tilemap")]
pub fn tick_simple_tilemap_animation(
	time: Res<Time>,
	mut query: Query<
		(
			&SimpleLoopedAnimation,
			&mut SimpleLoopedAnimationStatus,
			&mut bevy_ecs_tilemap::tiles::TileTextureIndex,
Louis's avatar
Louis committed
		),
		With<HasSimpleAnimations>,
	>,
) {
	let seconds = time.delta_seconds();
	for (animation, mut state, mut tile) in &mut query {
		state.frame_time += seconds;
		while state.frame_time >= animation.frame_secs {
			state.frame_time -= animation.frame_secs;
			state.active_step += 1;
			if state.active_step >= animation.frames.len() {
				state.active_step = 0;
			}
		}

		*tile =
			bevy_ecs_tilemap::tiles::TileTextureIndex(animation.frames[state.active_step] as u32);
Louis's avatar
Louis committed
	}
}

pub struct AnimationSystemsPlugin;

impl Plugin for AnimationSystemsPlugin {
	fn build(&self, app: &mut App) {
		let mut tick_systems = SystemSet::new()
			.label(AnimationSystems::TickAnimations)
			.with_system(tick_animations)
			.with_system(tick_simple_sprite_animations);

		#[cfg(feature = "ecs_tilemap")]
		{
			tick_systems = tick_systems.with_system(tick_simple_tilemap_animation);
		}

		app.add_event::<AnimationCompleted>()
			.add_system_set_to_stage(CoreStage::PostUpdate, tick_systems)
			.add_system_to_stage(
				CoreStage::PostUpdate,
				sync_parent_animations
					.label(AnimationSystems::SyncAnimations)
					.after(AnimationSystems::TickAnimations),
			);
	}
}