engine/entity_manager/src/animation_info.rs

174 lines
4.5 KiB
Rust
Raw Normal View History

2024-08-23 11:22:09 +00:00
use std::{collections::HashMap, time::Duration};
use anyhow::Result;
use engine::prelude::*;
2024-08-25 07:11:52 +00:00
use crate::entityparser::AnimationData;
#[derive(PartialEq, Eq, Hash, Clone, Copy, Debug, Serialize, Deserialize)]
pub enum AnimationType {
Move,
Idle,
Cast,
Attack,
// Add more as you need
}
2024-08-23 11:22:09 +00:00
#[derive(PartialEq, Clone, Serialize, Deserialize, Debug)]
struct AnimationLockInfo {
start: Duration,
duration: Duration,
}
#[derive(Debug, Default, PartialEq, Eq, Clone, Serialize, Deserialize)]
pub struct AnimationState {
index: Option<u32>,
start_time: Duration,
repeat: bool,
lock: bool,
}
pub struct AnimationInfo {
animation_map: HashMap<AnimationType, Vec<u32>>,
animation_info: Vec<AnimationData>,
animation_type: Option<AnimationType>,
animation_state: AnimationState,
lock: Option<AnimationLockInfo>,
}
impl AnimationInfo {
pub fn new(
animation_info: Vec<AnimationData>,
animation_map: HashMap<AnimationType, Vec<u32>>,
) -> Self {
Self {
animation_map,
animation_info,
animation_type: None,
animation_state: Default::default(),
lock: None,
}
}
pub fn animation_map(&self) -> &HashMap<AnimationType, Vec<u32>> {
&self.animation_map
}
pub fn animation_type(&self) -> Option<AnimationType> {
self.animation_type
}
pub fn is_locked(&self) -> bool {
self.lock.is_some()
}
/// Returns true if there is no lock, otherwise the animation is locked
pub fn check_lock(&mut self, now: Duration) -> bool {
match &mut self.lock {
Some(lock) => {
if now < lock.start {
panic!("Animation::check_lock: `now < start` !?");
}
if (now - lock.start) < lock.duration {
false
} else {
self.lock = None;
true
}
}
None => true,
}
}
/// Make sure `start` is `scene_time`, otherwise you will experience strange behavior
pub fn set_animation(
&mut self,
animation: &mut Animation,
draw: &mut Draw,
animation_type: Option<AnimationType>,
start: Duration,
lock: bool,
mut repeat: bool,
) -> Result<()> {
debug_assert!(self.lock.is_none());
self.animation_type = animation_type;
match animation_type {
Some(animation_type) => {
if let Some(animation_indices) = self.animation_map.get(&animation_type) {
assert!(!animation_indices.is_empty());
let index = if animation_indices.len() > 1 {
animation_indices[Random::range(0, animation_indices.len() as u32) as usize]
} else {
animation_indices[0]
};
if lock {
repeat = false;
let duration = self.animation_info[index as usize].duration;
self.lock = Some(AnimationLockInfo { start, duration });
}
self.animation_state = AnimationState {
index: Some(index),
start_time: start,
repeat,
lock,
};
unsafe { animation.set_animation(draw, Some(index), start, repeat)? };
}
}
None => {
self.lock = None;
self.animation_state = AnimationState {
index: None,
start_time: Duration::default(),
repeat: false,
lock: false,
};
unsafe { animation.set_animation(draw, None, Duration::default(), false)? };
}
}
Ok(())
}
}
impl Clone for AnimationInfo {
fn clone(&self) -> Self {
Self {
animation_map: self.animation_map.clone(),
animation_info: self.animation_info.clone(),
animation_type: None,
animation_state: AnimationState::default(),
lock: None,
}
}
}
impl EntityComponent for AnimationInfo {
fn name(&self) -> &str {
Self::debug_name()
}
}
impl ComponentDebug for AnimationInfo {
fn debug_name() -> &'static str {
"AnimationInfo"
}
}