//! `Polygon` type. use super::pnts; use crate::{bin::OptU16, err::*, fixed::Unit, xfer::TransferMode}; use bitflags::bitflags; /// Reads a polygon for either M1 or M2. pub 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 = pnts::read_o[108; 4]; let ori_cei = pnts::read_o[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 = PolygonType::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 = PolygonType::new_old(ptype, pdata)?; Ok((Polygon{ptype, ..poly}, 128)) } impl PolygonType { /// Creates a `PolygonType` from a `n`/`pdata` pair. pub fn new(n: u16, pdata: u16) -> Result { match n { 0 => Ok(PolygonType::Normal), 1 => Ok(PolygonType::ImpassItem), 2 => Ok(PolygonType::ImpassMons), 3 => Ok(PolygonType::Hill), 4 => Ok(PolygonType::Base), 5 => Ok(PolygonType::Platform(pdata)), 6 => Ok(PolygonType::TrigLightOn(pdata)), 7 => Ok(PolygonType::TrigPlatOn(pdata)), 8 => Ok(PolygonType::TrigLightOff(pdata)), 9 => Ok(PolygonType::TrigPlatOff(pdata)), 10 => Ok(PolygonType::Teleporter(pdata)), 11 => Ok(PolygonType::ZoneBorder), 12 => Ok(PolygonType::Goal), 13 => Ok(PolygonType::TrigMonsVis), 14 => Ok(PolygonType::TrigMonsInv), 15 => Ok(PolygonType::TrigMonsDual), 16 => Ok(PolygonType::TrigItems), 17 => Ok(PolygonType::MustExplore), 18 => Ok(PolygonType::AutoExit), 19 => Ok(PolygonType::OuchMinor), 20 => Ok(PolygonType::OuchMajor), 21 => Ok(PolygonType::Glue), 22 => Ok(PolygonType::GlueTrigger(pdata)), 23 => Ok(PolygonType::GlueSuper), n => Err(ReprError::new(n)), } } /// Creates a `PolygonType` from a Marathon 1 compatible `n`/`pdata` pair. fn new_old(n: u16, pdata: u16) -> Result { match n { 0 => Ok(PolygonType::Normal), 1 => Ok(PolygonType::ImpassItem), 2 => Ok(PolygonType::ImpassMons), 3 => Ok(PolygonType::OuchMinor), 4 => Ok(PolygonType::OuchMajor), 5 => Ok(PolygonType::Platform(pdata)), 6 => Ok(PolygonType::TrigLightOn(pdata)), 7 => Ok(PolygonType::TrigPlatOn(pdata)), 8 => Ok(PolygonType::TrigLightOff(pdata)), 9 => Ok(PolygonType::TrigPlatOff(pdata)), 10 => Ok(PolygonType::Teleporter(pdata)), 11 => Ok(PolygonType::Glue), 12 => Ok(PolygonType::GlueTrigger(pdata)), 13 => Ok(PolygonType::GlueSuper), 14 => Ok(PolygonType::MustExplore), 15 => Ok(PolygonType::AutoExit), n => Err(ReprError::new(n)), } } } impl Default for PolygonType { fn default() -> Self {PolygonType::Normal} } /// A polygon segment. #[cfg_attr(feature = "serde_obj", derive(serde::Serialize))] #[derive(Clone, Debug, Default, Eq, PartialEq)] pub struct Polygon { pub ptype: PolygonType, 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: pnts::Point, pub ori_cei: pnts::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(Clone, Copy, Debug, Eq, PartialEq)] pub enum PolygonType { 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 PolygonFlags: u16 { const DETACHED = 1 << 14; } } // EOF