1use std::{
4 borrow::Cow,
5 collections::HashMap,
6 fmt,
7 io::{Cursor, Read, Seek, SeekFrom},
8};
9
10use binrw::{binread, BinRead, BinResult, NullString, ReadOptions};
11
12use crate::error::Result;
13
14use super::file::File;
15
16#[binread]
18#[br(little)]
19#[derive(Debug)]
20pub struct PreBoneDeformer {
21 #[br(temp)]
22 data_count: u32,
23
24 #[br(count = data_count)]
25 deformers: Vec<DeformerData>,
26
27 #[br(count = data_count)]
28 nodes: Vec<NodeData>,
29}
30
31impl PreBoneDeformer {
32 pub fn deformers(&self) -> impl Iterator<Item = Deformer> {
34 self.deformers.iter().map(|deformer| Deformer {
35 pbd: self,
36 deformer,
37 })
38 }
39
40 pub fn root_node(&self) -> Option<Node> {
42 self.nodes
43 .iter()
44 .find(|node| node.parent_index == u16::MAX)
45 .map(|node| Node { pbd: self, node })
46 }
47}
48
49impl File for PreBoneDeformer {
50 fn read<'a>(data: impl Into<Cow<'a, [u8]>>) -> Result<Self> {
51 Ok(<Self as BinRead>::read(&mut Cursor::new(data.into()))?)
52 }
53}
54
55pub struct Node<'a> {
57 pbd: &'a PreBoneDeformer,
58 node: &'a NodeData,
59}
60
61impl Node<'_> {
62 pub fn deformer(&self) -> Deformer {
64 Deformer {
65 pbd: self.pbd,
66 deformer: &self.pbd.deformers[usize::from(self.node.deformer_index)],
67 }
68 }
69
70 pub fn parent(&self) -> Option<Node> {
72 self.get_relation(self.node.parent_index)
73 }
74
75 pub fn first_child(&self) -> Option<Node> {
77 self.get_relation(self.node.first_child_index)
78 }
79
80 pub fn next(&self) -> Option<Node> {
82 self.get_relation(self.node.next_index)
83 }
84
85 fn get_relation(&self, index: u16) -> Option<Node> {
86 match index {
87 u16::MAX => None,
88 index => Some(Node {
89 pbd: self.pbd,
90 node: &self.pbd.nodes[usize::from(index)],
91 }),
92 }
93 }
94}
95
96impl fmt::Debug for Node<'_> {
97 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
98 self.node.fmt(formatter)
99 }
100}
101
102pub struct Deformer<'a> {
104 pbd: &'a PreBoneDeformer,
105 deformer: &'a DeformerData,
106}
107
108impl Deformer<'_> {
109 pub fn node(&self) -> Node {
111 Node {
112 pbd: self.pbd,
113 node: &self.pbd.nodes[usize::from(self.deformer.node_index)],
114 }
115 }
116
117 pub fn id(&self) -> u16 {
119 self.deformer.id
120 }
121
122 pub fn bone_matrices(&self) -> Option<&HashMap<String, BoneMatrix>> {
124 self.deformer
125 .bone_matrices
126 .as_ref()
127 .map(|s| &s.bone_matrices)
128 }
129}
130
131impl fmt::Debug for Deformer<'_> {
132 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
133 self.deformer.fmt(formatter)
134 }
135}
136
137#[binread]
138#[br(little)]
139#[derive(Debug)]
140struct DeformerData {
141 id: u16,
142 node_index: u16,
143
144 #[br(temp)]
145 data_offset: i32,
146
147 #[br(
148 if(data_offset > 0),
149 seek_before = SeekFrom::Start(data_offset.try_into().unwrap()),
150 restore_position,
151 )]
152 bone_matrices: Option<BoneMatrices>,
153
154 _unknown: f32,
156}
157
158type BoneMatrix = [[f32; 4]; 3];
159
160#[binread]
161#[br(little)]
162struct BoneMatrices {
163 #[br(temp, parse_with = current_position)]
164 base_offset: u64,
165
166 #[br(temp)]
167 bone_count: u32,
168
169 #[br(temp, args {
170 count: bone_count.try_into().unwrap(),
171 inner: (base_offset,)
172 })]
173 bone_names: Vec<BoneName>,
174
175 #[br(temp, align_before = 4, count = bone_count)]
176 matrices: Vec<BoneMatrix>,
177
178 #[br(calc = (0..bone_count)
179 .map(|index| {
180 let i = usize::try_from(index).unwrap();
181 (bone_names[i].bone_name.to_string(), matrices[i])
182 })
183 .collect()
184 )]
185 bone_matrices: HashMap<String, BoneMatrix>,
186}
187
188impl fmt::Debug for BoneMatrices {
189 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
190 self.bone_matrices.fmt(formatter)
191 }
192}
193
194#[binread]
195#[br(little, import(base_offset: u64))]
196#[derive(Debug)]
197struct BoneName {
198 #[br(temp)]
199 offset: i16,
200
201 #[br(
202 seek_before = SeekFrom::Start(base_offset + u64::try_from(offset).unwrap()),
203 restore_position,
204 )]
205 bone_name: NullString,
206}
207
208#[binread]
209#[br(little)]
210#[derive(Debug)]
211struct NodeData {
212 parent_index: u16,
213 first_child_index: u16,
214 next_index: u16,
215 deformer_index: u16,
216}
217
218fn current_position<R: Read + Seek>(reader: &mut R, _: &ReadOptions, _: ()) -> BinResult<u64> {
219 Ok(reader.stream_position()?)
220}