use std::mem::size_of;
use crate::{Color, Dict, Rotation, parser::validate_count};
use nom::{
IResult, Parser,
multi::count,
number::complete::{le_i32, le_u32},
sequence::pair,
};
use crate::parser::parse_dict;
#[derive(Debug, PartialEq, Eq)]
pub struct NodeHeader {
pub id: u32,
pub attributes: Dict,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ShapeModel {
pub model_id: u32,
pub attributes: Dict,
}
impl ShapeModel {
pub fn frame_index(&self) -> Option<u32> {
if let Some(input) = self.attributes.get("_f") {
if let IResult::<&str, u32>::Ok((_, idx)) =
nom::character::complete::u32.parse(input.as_str())
{
return Some(idx);
} else {
debug!("Could not parse frame index of model: {}", input);
}
}
None
}
}
#[derive(Debug, PartialEq, Eq)]
pub struct SceneTransform {
pub header: NodeHeader,
pub child: u32,
pub layer_id: u32,
pub frames: Vec<Dict>,
}
#[derive(Debug, PartialEq, Eq)]
pub struct SceneGroup {
pub header: NodeHeader,
pub children: Vec<u32>,
}
#[derive(Debug, PartialEq, Eq)]
pub struct SceneShape {
pub header: NodeHeader,
pub models: Vec<ShapeModel>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct RawLayer {
pub id: u32,
pub attributes: Dict,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Layer {
pub attributes: Dict,
}
impl Layer {
pub fn name(&self) -> Option<String> {
self.attributes.get("_name").cloned()
}
pub fn hidden(&self) -> bool {
if let Some(x) = self.attributes.get("_hidden") {
return x == "1";
}
false
}
pub fn color(&self) -> Option<Color> {
if let Some(x) = self.attributes.get("_color") {
if let IResult::<&str, (u8, &str, u8, &str, u8)>::Ok((_, (r, _, g, _, b))) = (
nom::character::complete::u8,
nom::character::complete::space1,
nom::character::complete::u8,
nom::character::complete::space1,
nom::character::complete::u8,
)
.parse(x.as_str())
{
return Some(Color { r, g, b, a: 0 });
} else {
debug!(
"Encountered _color attribute in layer that appears to be malformed: {}",
x
)
}
}
None
}
}
fn parse_node_header(i: &[u8]) -> IResult<&[u8], NodeHeader> {
let (i, (id, attributes)) = pair(le_u32, parse_dict).parse(i)?;
Ok((i, NodeHeader { id, attributes }))
}
fn parse_scene_shape_model(i: &[u8]) -> IResult<&[u8], ShapeModel> {
let (i, (model_id, attributes)) = pair(le_u32, parse_dict).parse(i)?;
Ok((
i,
ShapeModel {
model_id,
attributes,
},
))
}
pub fn parse_scene_transform(i: &[u8]) -> IResult<&[u8], SceneTransform> {
let (i, header) = parse_node_header(i)?;
let (i, child) = le_u32.parse(i)?;
let (i, _ignored) = le_i32.parse(i)?;
let (i, layer_id) = le_u32.parse(i)?;
let (i, frame_count) = le_u32.parse(i)?;
let frame_count = validate_count(i, frame_count, size_of::<u32>())?;
let (i, frames) = count(parse_dict, frame_count).parse(i)?;
Ok((
i,
SceneTransform {
header,
child,
layer_id,
frames,
},
))
}
pub fn parse_scene_group(i: &[u8]) -> IResult<&[u8], SceneGroup> {
let (i, header) = parse_node_header(i)?;
let (i, child_count) = le_u32.parse(i)?;
let child_count = validate_count(i, child_count, size_of::<u32>())?;
let (i, children) = count(le_u32, child_count).parse(i)?;
Ok((i, SceneGroup { header, children }))
}
pub fn parse_scene_shape(i: &[u8]) -> IResult<&[u8], SceneShape> {
let (i, header) = parse_node_header(i)?;
let (i, model_count) = le_u32.parse(i)?;
let model_count = validate_count(i, model_count, size_of::<u32>() * 2)?;
let (i, models) = count(parse_scene_shape_model, model_count).parse(i)?;
Ok((i, SceneShape { header, models }))
}
pub fn parse_layer(i: &[u8]) -> IResult<&[u8], RawLayer> {
let (i, id) = le_u32.parse(i)?;
let (i, attributes) = parse_dict(i)?;
let (i, _ignored) = le_u32.parse(i)?;
Ok((i, RawLayer { id, attributes }))
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Position {
pub x: i32,
pub y: i32,
pub z: i32,
}
impl From<(i32, i32, i32)> for Position {
fn from(pos: (i32, i32, i32)) -> Self {
Position {
x: pos.0,
y: pos.1,
z: pos.2,
}
}
}
impl From<Position> for (i32, i32, i32) {
fn from(pos: Position) -> Self {
(pos.x, pos.y, pos.z)
}
}
#[derive(Clone, Debug, PartialEq, Eq, Default)]
pub struct Frame {
pub attributes: Dict,
}
impl Frame {
pub fn new(attributes: Dict) -> Frame {
Frame { attributes }
}
pub fn orientation(&self) -> Option<Rotation> {
if let Some(value) = self.attributes.get("_r") {
if let IResult::<&str, u8>::Ok((_, byte_rotation)) =
nom::character::complete::u8.parse(value.as_str())
{
return Some(Rotation::from_byte(byte_rotation));
} else {
debug!("'_r' attribute for Frame could not be parsed! {}", value);
}
}
None
}
pub fn position(&self) -> Option<Position> {
if let Some(value) = self.attributes.get("_t") {
match (
nom::character::complete::i32,
nom::character::complete::space1,
nom::character::complete::i32,
nom::character::complete::space1,
nom::character::complete::i32,
)
.parse(value.as_str())
{
IResult::<&str, (i32, &str, i32, &str, i32)>::Ok((_, (x, _, y, _, z))) => {
return Some(Position { x, y, z });
}
Err(_) => {
debug!("'_t' attribute for Frame could not be parsed! {}", value)
}
}
}
None
}
pub fn frame_index(&self) -> Option<u32> {
if let Some(value) = self.attributes.get("_f") {
if let IResult::<&str, u32>::Ok((_, frame_idx)) =
nom::character::complete::u32.parse(value.as_str())
{
return Some(frame_idx);
} else {
debug!("'_f' attribute for Frame could not be parsed! {}", value);
}
}
None
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum SceneNode {
Transform {
attributes: Dict,
frames: Vec<Frame>,
child: u32,
layer_id: u32,
},
Group {
attributes: Dict,
children: Vec<u32>,
},
Shape {
attributes: Dict,
models: Vec<ShapeModel>,
},
}