pmx_parser 0.2.0

load and save .pmx model file.
Documentation
use std::io::{Read, Write};

use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use crate::{BoneIndex, MorphIndex};

use crate::error::PmxError;
use crate::header::Header;
use crate::kits::{read_bool, read_vec};

#[derive(Default, Debug, Clone, Eq, PartialEq)]
pub struct DisplayFrames {
    pub display_frames: Vec<DisplayFrame>,
}

impl DisplayFrames {
    pub fn count(&self) -> u32 {
        self.display_frames.len() as u32
    }
    pub fn read<R: Read>(header: &Header, read: &mut R) -> Result<Self, PmxError> {
        Ok(Self {
            display_frames: read_vec(read, |read| DisplayFrame::read(header, read))?,
        })
    }
    pub fn write<W: Write>(&self, header: &Header, write: &mut W) -> Result<(), PmxError> {
        write.write_u32::<LittleEndian>(self.count())?;
        for i in &self.display_frames {
            i.write(header, write)?;
        }
        Ok(())
    }
}

#[derive(Default, Debug, Clone, PartialEq, Eq)]
pub struct DisplayFrame {
    pub name: String,
    pub name_en: String,
    pub is_special: bool,
    pub items: Vec<DisplayFrameItem>,
}

impl DisplayFrame {
    pub fn read<R: Read>(header: &Header, read: &mut R) -> Result<Self, PmxError> {
        Ok(Self {
            name: header.encoding.read(read)?,
            name_en: header.encoding.read(read)?,
            is_special: read_bool(read)?,
            items: read_vec(read, |read| DisplayFrameItem::read(header, read))?,
        })
    }
    pub fn write<W: Write>(&self, header: &Header, write: &mut W) -> Result<(), PmxError> {
        header.encoding.write(write, self.name.as_str())?;
        header.encoding.write(write, self.name_en.as_str())?;
        write.write_u8(self.is_special as u8)?;
        write.write_u32::<LittleEndian>(self.items.len() as u32)?;
        for i in &self.items {
            i.write(header, write)?;
        }
        Ok(())
    }
}

#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum DisplayFrameItem {
    BoneIndex(BoneIndex),
    MorphIndex(MorphIndex),
}

impl DisplayFrameItem {
    pub fn read<R: Read>(header: &Header, read: &mut R) -> Result<Self, PmxError> {
        let t = read.read_u8()?;
        match t {
            0 => Ok(Self::BoneIndex(header.bone_index.read(read)?)),
            1 => Ok(Self::MorphIndex(header.morph_index.read(read)?)),
            _ => Err(PmxError::DisplayFrameError),
        }
    }
    pub fn write<W: Write>(&self, header: &Header, write: &mut W) -> Result<(), PmxError> {
        match *self {
            DisplayFrameItem::BoneIndex(i) => {
                write.write_u8(0x00)?;
                header.bone_index.write(write, i)?;
            }
            DisplayFrameItem::MorphIndex(i) => {
                write.write_u8(0x01)?;
                header.morph_index.write(write, i)?;
            }
        }
        Ok(())
    }
}