use crate::binary::{boolean, col, float, str, varint_usize, vec2};
use crate::skeleton::{Bone, ParentTransform};
use nom::number::complete::be_u8;
use nom::sequence::tuple;
use nom::IResult;
use tracing::{debug, instrument, trace};
#[instrument(skip(b))]
pub(crate) fn bones(b: &[u8]) -> IResult<&[u8], Vec<Bone>> {
let (b, bone_count) = varint_usize(b)?;
let mut bones = Vec::with_capacity(bone_count);
if bone_count == 0 {
return Ok((b, bones));
}
let (mut b, parent) = bone(b, true)?;
bones.push(parent);
for _ in 1..bone_count {
let v = bone(b, false)?;
b = v.0;
bones.push(v.1);
}
debug!(bones = ?bones.len());
Ok((b, bones))
}
#[instrument(skip(b))]
pub(crate) fn bone(b: &[u8], root: bool) -> IResult<&[u8], Bone> {
let (b, name) = str(b)?;
let (b, parent) = bone_parent(b, root)?;
let (b, (rotation, position, scale, shear, length)) =
tuple((float, vec2, vec2, vec2, float))(b)?;
let (b, (transform, skin, color)) = tuple((transform_mode, boolean, col))(b)?;
let bone = Bone {
name,
parent,
rotation,
position,
scale,
shear,
length,
transform,
skin,
color,
};
trace!(?bone);
Ok((b, bone))
}
pub(crate) fn transform_mode(b: &[u8]) -> IResult<&[u8], ParentTransform> {
let (b, v) = be_u8(b)?;
Ok((b, v.into()))
}
pub(crate) fn bone_parent(b: &[u8], root: bool) -> IResult<&[u8], Option<usize>> {
Ok(match root {
true => (b, None),
false => {
let (b, v) = varint_usize(b)?;
(b, Some(v))
}
})
}