flour/bxcad/
qol.rs

1use serde::{Deserialize, Serialize};
2
3use crate::{
4    bxcad::{bccad, brcad},
5    BXCAD,
6};
7use std::collections::BTreeMap;
8
9/// Trait for BXCAD types that allow "indexization", that is, conversion for their `Sprite` lists
10/// from a Vec to some sort of Map (usually `BTreeMap<uX, Sprite>`)
11///
12/// This is so that the list of `Sprite`s can be more easily edited by hand, and more easily referenced,
13/// due to including the number of the sprite right next to the entry.
14///
15/// Unless you're going to deal with `BXCAD` files by hand (for example, as JSON in the flour binary), you
16/// probably don't need this.
17pub trait Indexizable: BXCAD {
18    /// The type that contains indexized data for this BXCAD
19    type Indexized;
20    /// Convert a standard BXCAD to indexized
21    fn to_indexized(self) -> Self::Indexized;
22    /// Convert the indexized data to a standard BXCAD
23    fn from_indexized(og: Self::Indexized) -> Self;
24}
25
26/// [Indexizable::Indexized] variant of [crate::BCCAD]
27///
28/// See that type for more information
29#[derive(Serialize, Deserialize, Clone)]
30pub struct IndexizedBCCAD {
31    pub timestamp: Option<u32>,
32    pub texture_width: u16,
33    pub texture_height: u16,
34    pub sprites: BTreeMap<u16, bccad::Sprite>,
35    pub animations: Vec<bccad::Animation>,
36}
37
38impl Indexizable for bccad::BCCAD {
39    type Indexized = IndexizedBCCAD;
40    fn to_indexized(self) -> Self::Indexized {
41        let mut sprites = BTreeMap::new();
42
43        for (i, sprite) in self.sprites.iter().enumerate() {
44            sprites.insert(i as u16, sprite.clone());
45        }
46
47        IndexizedBCCAD {
48            timestamp: self.timestamp,
49            texture_width: self.texture_width,
50            texture_height: self.texture_height,
51            sprites,
52            animations: self.animations,
53        }
54    }
55
56    fn from_indexized(og: Self::Indexized) -> Self {
57        let mut sprites = vec![];
58
59        for i in 0..=*og.sprites.keys().max().unwrap() {
60            let sprite = match og.sprites.get(&i) {
61                Some(c) => c.clone(),
62                None => bccad::Sprite { parts: vec![] },
63            };
64            sprites.push(sprite);
65        }
66
67        Self {
68            timestamp: og.timestamp,
69            texture_width: og.texture_width,
70            texture_height: og.texture_height,
71            sprites,
72            animations: og.animations,
73        }
74    }
75}
76
77/// [Indexizable::Indexized] variant of [crate::BRCAD]
78///
79/// See that type for more information
80#[derive(Serialize, Deserialize, Clone)]
81pub struct IndexizedBRCAD {
82    pub timestamp: Option<u32>,
83    pub unk0: u32,
84    pub spritesheet_num: u16,
85    pub spritesheet_control: u16,
86    pub texture_width: u16,
87    pub texture_height: u16,
88    pub unk1: u16,
89    pub sprites: BTreeMap<u16, brcad::Sprite>,
90    pub unk2: u16,
91    pub animations: Vec<brcad::Animation>,
92}
93
94impl Indexizable for brcad::BRCAD {
95    type Indexized = IndexizedBRCAD;
96    fn to_indexized(self) -> Self::Indexized {
97        let mut sprites = BTreeMap::new();
98
99        for (i, sprite) in self.sprites.iter().enumerate() {
100            sprites.insert(i as u16, sprite.clone());
101        }
102
103        IndexizedBRCAD {
104            timestamp: self.timestamp,
105            unk0: self.unk0,
106            spritesheet_num: self.spritesheet_num,
107            spritesheet_control: self.spritesheet_control,
108            texture_width: self.texture_width,
109            texture_height: self.texture_height,
110            unk1: self.unk1,
111            sprites,
112            unk2: self.unk2,
113            animations: self.animations,
114        }
115    }
116
117    fn from_indexized(og: Self::Indexized) -> Self {
118        let mut sprites = vec![];
119
120        for i in 0..=*og.sprites.keys().max().unwrap() {
121            let sprite = match og.sprites.get(&i) {
122                Some(c) => c.clone(),
123                None => brcad::Sprite {
124                    parts: vec![],
125                    unk: 0,
126                },
127            };
128            sprites.push(sprite);
129        }
130
131        Self {
132            timestamp: og.timestamp,
133            unk0: og.unk0,
134            spritesheet_num: og.spritesheet_num,
135            spritesheet_control: og.spritesheet_control,
136            texture_width: og.texture_width,
137            texture_height: og.texture_height,
138            unk1: og.unk1,
139            sprites,
140            unk2: og.unk2,
141            animations: og.animations,
142        }
143    }
144}