1use std::num::NonZeroU32;
2
3use crate::{reader::AseReader, user_data::UserData, AsepriteParseError, Result};
4
5#[derive(Debug, Clone)]
10pub struct Tag {
11 name: String,
12 from_frame: u16,
13 to_frame: u16,
14 repeat: u16,
15 animation_direction: AnimationDirection,
16 pub(crate) user_data: Option<UserData>,
17}
18
19impl Tag {
20 pub fn name(&self) -> &str {
22 &self.name
23 }
24
25 pub fn from_frame(&self) -> u32 {
27 self.from_frame as u32
28 }
29
30 pub fn to_frame(&self) -> u32 {
32 self.to_frame as u32
33 }
34
35 pub fn animation_direction(&self) -> AnimationDirection {
37 self.animation_direction
38 }
39
40 pub fn repeat(&self) -> Option<NonZeroU32> {
44 NonZeroU32::new(self.repeat as u32)
45 }
46
47 pub fn user_data(&self) -> Option<&UserData> {
49 self.user_data.as_ref()
50 }
51
52 pub(crate) fn set_user_data(&mut self, user_data: UserData) {
53 self.user_data = Some(user_data);
54 }
55}
56
57#[derive(Debug, Clone, Copy, PartialEq, Eq)]
59pub enum AnimationDirection {
60 Forward,
62 Reverse,
64 PingPong,
66}
67
68pub(crate) fn parse_chunk(data: &[u8]) -> Result<Vec<Tag>> {
69 let mut reader = AseReader::new(data);
70
71 let num_tags = reader.word()?;
72 reader.skip_reserved(8)?;
73
74 let mut result = Vec::with_capacity(num_tags as usize);
75
76 for _tag in 0..num_tags {
77 let from_frame = reader.word()?;
78 let to_frame = reader.word()?;
79 let anim_dir = reader.byte()?;
80 let repeat = reader.word()?;
81 reader.skip_reserved(6)?;
82 let _color = reader.dword()?;
83 let name = reader.string()?;
84 let animation_direction = parse_animation_direction(anim_dir)?;
85 result.push(Tag {
86 name,
87 from_frame,
88 to_frame,
89 animation_direction,
90 repeat,
91 user_data: None,
92 });
93 }
94
95 Ok(result)
96}
97
98fn parse_animation_direction(id: u8) -> Result<AnimationDirection> {
99 match id {
100 0 => Ok(AnimationDirection::Forward),
101 1 => Ok(AnimationDirection::Reverse),
102 2 => Ok(AnimationDirection::PingPong),
103 _ => Err(AsepriteParseError::InvalidInput(format!(
104 "Unknown animation direction: {}",
105 id
106 ))),
107 }
108}