//! `Polygon` type. use crate::{durandal::{bin::OptU16, err::*, fixed::Unit}, marathon::xfer::TransferMode}; use super::pnts::*; use bitflags::bitflags; /// Reads a polygon for either M1 or M2. fn read_poly_inter(b: &[u8]) -> ResultS { read_data! { endian: BIG, buf: b, size: 128, start: 0, data { let tex_flr = OptU16[40]; let tex_cei = OptU16[42]; let hei_flr = Unit[44]; let hei_cei = Unit[46]; let lit_flr = u16[48]; let lit_cei = u16[50]; let xfr_flr = u16[64] enum TransferMode; let xfr_cei = u16[66] enum TransferMode; } } Ok(Polygon{tex_flr, tex_cei, hei_flr, hei_cei, lit_flr, lit_cei, xfr_flr, xfr_cei, ..Polygon::default()}) } /// Reads a `POLY` chunk. pub fn read(b: &[u8]) -> ResultS<(Polygon, usize)> { read_data! { endian: BIG, buf: b, size: 128, start: 0, data { let ptype = u16[0]; let pdata = u16[4]; let ori_flr = read_point[108; 4]; let ori_cei = read_point[112; 4]; let med_ind = OptU16[116]; let med_ctl = u16[118]; let snd_amb = OptU16[122]; let snd_ind = u16[120]; let snd_rnd = OptU16[124]; } } let poly = read_poly_inter(b)?; let ptype = PolyType::new(ptype, pdata)?; Ok((Polygon{ptype, ori_flr, ori_cei, med_ind, med_ctl, snd_ind, snd_amb, snd_rnd, ..poly}, 128)) } /// Reads an old `POLY` chunk. pub fn read_old(b: &[u8]) -> ResultS<(Polygon, usize)> { read_data! { endian: BIG, buf: b, size: 128, start: 0, data { let ptype = u16[0]; let pdata = u16[4]; } } let poly = read_poly_inter(b)?; let ptype = PolyType::new_old(ptype, pdata)?; Ok((Polygon{ptype, ..poly}, 128)) } impl PolyType { /// Creates a `PolyType` from a `n`/`pdata` pair. pub fn new(n: u16, pdata: u16) -> Result { match n { 0 => Ok(PolyType::Normal), 1 => Ok(PolyType::ImpassItem), 2 => Ok(PolyType::ImpassMons), 3 => Ok(PolyType::Hill), 4 => Ok(PolyType::Base), 5 => Ok(PolyType::Platform(pdata)), 6 => Ok(PolyType::TrigLightOn(pdata)), 7 => Ok(PolyType::TrigPlatOn(pdata)), 8 => Ok(PolyType::TrigLightOff(pdata)), 9 => Ok(PolyType::TrigPlatOff(pdata)), 10 => Ok(PolyType::Teleporter(pdata)), 11 => Ok(PolyType::ZoneBorder), 12 => Ok(PolyType::Goal), 13 => Ok(PolyType::TrigMonsVis), 14 => Ok(PolyType::TrigMonsInv), 15 => Ok(PolyType::TrigMonsDual), 16 => Ok(PolyType::TrigItems), 17 => Ok(PolyType::MustExplore), 18 => Ok(PolyType::AutoExit), 19 => Ok(PolyType::OuchMinor), 20 => Ok(PolyType::OuchMajor), 21 => Ok(PolyType::Glue), 22 => Ok(PolyType::GlueTrigger(pdata)), 23 => Ok(PolyType::GlueSuper), n => Err(ReprError::new(n)), } } /// Creates a `PolyType` from a Marathon 1 compatible `n`/`pdata` pair. fn new_old(n: u16, pdata: u16) -> Result { match n { 0 => Ok(PolyType::Normal), 1 => Ok(PolyType::ImpassItem), 2 => Ok(PolyType::ImpassMons), 3 => Ok(PolyType::OuchMinor), 4 => Ok(PolyType::OuchMajor), 5 => Ok(PolyType::Platform(pdata)), 6 => Ok(PolyType::TrigLightOn(pdata)), 7 => Ok(PolyType::TrigPlatOn(pdata)), 8 => Ok(PolyType::TrigLightOff(pdata)), 9 => Ok(PolyType::TrigPlatOff(pdata)), 10 => Ok(PolyType::Teleporter(pdata)), 11 => Ok(PolyType::Glue), 12 => Ok(PolyType::GlueTrigger(pdata)), 13 => Ok(PolyType::GlueSuper), 14 => Ok(PolyType::MustExplore), 15 => Ok(PolyType::AutoExit), n => Err(ReprError::new(n)), } } } impl Default for PolyType { fn default() -> Self {PolyType::Normal} } /// A polygon segment. #[cfg_attr(feature = "serde_obj", derive(serde::Serialize))] #[derive(Debug, Default, Eq, PartialEq)] pub struct Polygon { pub ptype: PolyType, pub tex_flr: OptU16, pub tex_cei: OptU16, pub hei_flr: Unit, pub hei_cei: Unit, pub lit_flr: u16, pub lit_cei: u16, pub xfr_flr: TransferMode, pub xfr_cei: TransferMode, pub ori_flr: Point, pub ori_cei: Point, pub med_ind: OptU16, pub med_ctl: u16, pub snd_ind: u16, pub snd_amb: OptU16, pub snd_rnd: OptU16, } /// The action type of a `Polygon`. #[cfg_attr(feature = "serde_obj", derive(serde::Serialize))] #[derive(Debug, Eq, PartialEq)] pub enum PolyType { Normal, ImpassItem, ImpassMons, Hill, Base, Platform(u16), TrigLightOn(u16), TrigPlatOn(u16), TrigLightOff(u16), TrigPlatOff(u16), Teleporter(u16), ZoneBorder, Goal, TrigMonsVis, TrigMonsInv, TrigMonsDual, TrigItems, MustExplore, AutoExit, OuchMinor, OuchMajor, Glue, GlueTrigger(u16), GlueSuper, } bitflags! { /// Flags for `Polygon`. #[cfg_attr(feature = "serde_obj", derive(serde::Serialize))] pub struct PolyFlags: u16 { const DETACHED = 1 << 14; } } // EOF