aseprite_loader/binary/chunks/
layer.rs1use bitflags::bitflags;
2use nom::{bytes::complete::take, combinator::cond, Parser};
3
4use crate::binary::{
5 blend_mode::BlendMode,
6 errors::ParseResult,
7 scalars::{byte, dword, parse_string, word, Byte, Dword, Word},
8};
9
10#[derive(Debug)]
11pub struct LayerChunk<'a> {
12 pub flags: LayerFlags,
13 pub layer_type: LayerType,
14 pub child_level: Word,
15 pub blend_mode: BlendMode,
16 pub opacity: Byte,
17 pub name: &'a str,
18 pub tileset_index: Option<Dword>,
19}
20
21bitflags! {
22 #[derive(Debug)]
23 pub struct LayerFlags: Word {
24 const VISIBLE = 0x1;
25 const EDITABLE = 0x2;
26 const LOCK_MOVEMENT = 0x4;
27 const BACKGROUND = 0x8;
28 const PREFER_LINKED_CELS = 0x16;
29 const COLLAPSED = 0x32;
30 const REFERENCE = 0x64;
31 }
32}
33
34#[derive(Debug, Clone, Copy, PartialEq, Eq)]
35pub enum LayerType {
36 Normal,
37 Group,
38 Tilemap,
39 Unknown(Word),
40}
41
42impl From<Word> for LayerType {
43 fn from(word: Word) -> Self {
44 match word {
45 0 => Self::Normal,
46 1 => Self::Group,
47 2 => Self::Tilemap,
48 n => Self::Unknown(n),
49 }
50 }
51}
52
53pub fn parse_layer_chunk(input: &[u8]) -> ParseResult<'_, LayerChunk<'_>> {
54 let (input, flags) = word(input)?;
55 let flags = LayerFlags::from_bits_truncate(flags);
56 let (input, layer_type) = word(input)?;
57 let layer_type = LayerType::from(layer_type);
58 let (input, child_level) = word(input)?;
59 let (input, _default_layer_width) = word(input)?;
60 let (input, _default_layer_height) = word(input)?;
61 let (input, blend_mode) = word(input)?;
62 let blend_mode = BlendMode::from(blend_mode);
63 let (input, opacity) = byte(input)?;
64 let (input, _) = take(3usize)(input)?;
65 let (input, name) = parse_string(input)?;
66 let (input, tileset_index) =
67 cond(matches!(layer_type, LayerType::Tilemap), dword).parse(input)?;
68 Ok((
69 input,
70 LayerChunk {
71 flags,
72 layer_type,
73 child_level,
74 blend_mode,
75 opacity,
76 name,
77 tileset_index,
78 },
79 ))
80}
81
82#[test]
83fn test_layers() {
84 use crate::binary::file::parse_file;
85 let input = std::fs::read("./tests/layers.aseprite").unwrap();
86 let file = parse_file(&input).unwrap();
87 assert_eq!(file.frames.len(), 1);
88 assert_eq!(file.frames[0].duration, 100);
89 assert_eq!(file.layers.len(), 3);
90 assert_eq!(file.layers[0].name, "Layer 1");
91 assert_eq!(file.layers[1].name, "Layer 2");
92 assert_eq!(file.layers[2].name, "Layer 3");
93}