//! `Light` type. use super::{ltfn, TICKS_PER_SECOND}; use crate::{err::*, fixed::Fixed}; /// Reads a `LITE` chunk. pub fn read(b: &[u8]) -> ResultS<(Light, usize)> { read_data! { endian: BIG, buf: b, size: 100, start: 0, data { let ltype = u16[0] enum LightType; let flags = u16[2] flag LightFlags; let phase = i16[4]; let act_pri = ltfn::read[6; 14]; let act_sec = ltfn::read[20; 14]; let act_mid = ltfn::read[34; 14]; let ina_pri = ltfn::read[48; 14]; let ina_sec = ltfn::read[62; 14]; let ina_mid = ltfn::read[76; 14]; let tag = u16[90]; } } Ok((Light{ltype, flags, phase, act_pri, act_sec, act_mid, ina_pri, ina_sec, ina_mid, tag}, 100)) } /// Reads an old `LITE` chunk. pub fn read_old(b: &[u8]) -> ResultS<(Light, usize)> { read_data! { endian: BIG, buf: b, size: 32, start: 0, data { let ltype = u16[2] usize; let mode = u16[4]; let phase = i16[6]; let min = Fixed[8]; let max = Fixed[12]; let prd = u16[16]; } } if OLD_LIGHT_DEFINITIONS.len() < ltype { bail!("bad old light type"); } let lite = &OLD_LIGHT_DEFINITIONS[ltype]; let on = mode == 0 || mode == 1; let strobe = ltype == 3; let flags = if on {lite.flags | LightFlags::INIT_ACTIVE} else {lite.flags}; // modify each old light function accordingly let old_lfun = move |func: <fn::LightFunc| -> ltfn::LightFunc { ltfn::LightFunc{ftype: func.ftype, prd_nrm: if strobe {prd / 4 + 1} else {func.prd_nrm}, prd_dta: func.prd_dta, val_nrm: if func.val_nrm > 0.into() {max} else {min}, val_dta: func.val_dta} }; Ok((Light{flags, phase, act_pri: old_lfun(&lite.act_pri), act_sec: old_lfun(&lite.act_sec), act_mid: old_lfun(&lite.act_mid), ina_pri: old_lfun(&lite.ina_pri), ina_sec: old_lfun(&lite.ina_sec), ina_mid: old_lfun(&lite.ina_mid), tag: 0, ..*lite}, 32)) } /// A dynamic polygon light. #[cfg_attr(feature = "serde_obj", derive(serde::Serialize))] #[derive(Clone, Debug, Eq, PartialEq)] pub struct Light { pub ltype: LightType, pub flags: LightFlags, pub phase: i16, pub act_pri: ltfn::LightFunc, pub act_sec: ltfn::LightFunc, pub act_mid: ltfn::LightFunc, pub ina_pri: ltfn::LightFunc, pub ina_sec: ltfn::LightFunc, pub ina_mid: ltfn::LightFunc, pub tag: u16, } c_bitfield! { /// Flags for `Light`. #[cfg_attr(feature = "serde_obj", derive(serde::Serialize))] pub struct LightFlags: u16 { INIT_ACTIVE = 0, SLAVE_VALUE = 1, STATELESS = 2, } } c_enum! { /// The type of a `Light`. #[cfg_attr(feature = "serde_obj", derive(serde::Serialize))] pub enum LightType: u16 { Normal = 0, Strobe = 1, Media = 2, } } const OLD_LIGHT_DEFINITIONS: [Light; 8] = [ // Normal Light{ltype: LightType::Normal, flags: LightFlags::SLAVE_VALUE, phase: 0, act_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant, prd_nrm: TICKS_PER_SECOND, prd_dta: 0, val_nrm: Fixed::from_int(1), val_dta: Fixed::from_int(0)}, act_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant, prd_nrm: TICKS_PER_SECOND, prd_dta: 0, val_nrm: Fixed::from_int(1), val_dta: Fixed::from_int(0)}, act_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant, prd_nrm: 1, prd_dta: 0, val_nrm: Fixed::from_int(1), val_dta: Fixed::from_int(0)}, ina_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant, prd_nrm: TICKS_PER_SECOND, prd_dta: 0, val_nrm: Fixed::from_int(0), val_dta: Fixed::from_int(0)}, ina_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant, prd_nrm: TICKS_PER_SECOND, prd_dta: 0, val_nrm: Fixed::from_int(0), val_dta: Fixed::from_int(0)}, ina_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant, prd_nrm: 1, prd_dta: 0, val_nrm: Fixed::from_int(1), val_dta: Fixed::from_int(0)}, tag: 0}, // Rheostat Light{ltype: LightType::Normal, flags: LightFlags::SLAVE_VALUE, phase: 0, act_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant, prd_nrm: TICKS_PER_SECOND, prd_dta: 0, val_nrm: Fixed::from_int(1), val_dta: Fixed::from_int(0)}, act_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant, prd_nrm: TICKS_PER_SECOND, prd_dta: 0, val_nrm: Fixed::from_int(1), val_dta: Fixed::from_int(0)}, act_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Smooth, prd_nrm: TICKS_PER_SECOND * 3, prd_dta: 0, val_nrm: Fixed::from_int(1), val_dta: Fixed::from_int(0)}, ina_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant, prd_nrm: TICKS_PER_SECOND, prd_dta: 0, val_nrm: Fixed::from_int(0), val_dta: Fixed::from_int(0)}, ina_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant, prd_nrm: TICKS_PER_SECOND, prd_dta: 0, val_nrm: Fixed::from_int(0), val_dta: Fixed::from_int(0)}, ina_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Smooth, prd_nrm: TICKS_PER_SECOND * 3, prd_dta: 0, val_nrm: Fixed::from_int(0), val_dta: Fixed::from_int(0)}, tag: 0}, // Flourescent Light{ltype: LightType::Normal, flags: LightFlags::SLAVE_VALUE, phase: 0, act_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant, prd_nrm: TICKS_PER_SECOND, prd_dta: 0, val_nrm: Fixed::from_int(1), val_dta: Fixed::from_int(0)}, act_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant, prd_nrm: TICKS_PER_SECOND, prd_dta: 0, val_nrm: Fixed::from_int(1), val_dta: Fixed::from_int(0)}, act_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Fluorescent, prd_nrm: TICKS_PER_SECOND * 3, prd_dta: 0, val_nrm: Fixed::from_int(1), val_dta: Fixed::from_int(0)}, ina_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant, prd_nrm: TICKS_PER_SECOND, prd_dta: 0, val_nrm: Fixed::from_int(0), val_dta: Fixed::from_int(0)}, ina_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant, prd_nrm: TICKS_PER_SECOND, prd_dta: 0, val_nrm: Fixed::from_int(0), val_dta: Fixed::from_int(0)}, ina_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant, prd_nrm: 1, prd_dta: 0, val_nrm: Fixed::from_int(0), val_dta: Fixed::from_int(0)}, tag: 0}, // Strobe Light{ltype: LightType::Normal, flags: LightFlags::SLAVE_VALUE, phase: 0, act_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant, prd_nrm: TICKS_PER_SECOND, prd_dta: 0, val_nrm: Fixed::from_int(1), val_dta: Fixed::from_int(0)}, act_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant, prd_nrm: TICKS_PER_SECOND, prd_dta: 0, val_nrm: Fixed::from_int(0), val_dta: Fixed::from_int(0)}, act_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant, prd_nrm: 1, prd_dta: 0, val_nrm: Fixed::from_int(1), val_dta: Fixed::from_int(0)}, ina_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant, prd_nrm: TICKS_PER_SECOND, prd_dta: 0, val_nrm: Fixed::from_int(0), val_dta: Fixed::from_int(0)}, ina_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant, prd_nrm: TICKS_PER_SECOND, prd_dta: 0, val_nrm: Fixed::from_int(1), val_dta: Fixed::from_int(0)}, ina_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant, prd_nrm: 1, prd_dta: 0, val_nrm: Fixed::from_int(0), val_dta: Fixed::from_int(0)}, tag: 0}, // Flicker Light{ltype: LightType::Normal, flags: LightFlags::SLAVE_VALUE, phase: 0, act_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant, prd_nrm: TICKS_PER_SECOND, prd_dta: 0, val_nrm: Fixed::from_int(1), val_dta: Fixed::from_int(0)}, act_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant, prd_nrm: TICKS_PER_SECOND, prd_dta: 0, val_nrm: Fixed::from_int(1), val_dta: Fixed::from_int(0)}, act_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Flicker, prd_nrm: TICKS_PER_SECOND * 3, prd_dta: 0, val_nrm: Fixed::from_int(1), val_dta: Fixed::from_int(0)}, ina_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant, prd_nrm: TICKS_PER_SECOND, prd_dta: 0, val_nrm: Fixed::from_int(0), val_dta: Fixed::from_int(0)}, ina_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant, prd_nrm: TICKS_PER_SECOND, prd_dta: 0, val_nrm: Fixed::from_int(0), val_dta: Fixed::from_int(0)}, ina_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant, prd_nrm: 1, prd_dta: 0, val_nrm: Fixed::from_int(0), val_dta: Fixed::from_int(0)}, tag: 0}, // Pulsate Light{ltype: LightType::Normal, flags: LightFlags::SLAVE_VALUE, phase: 0, act_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Smooth, prd_nrm: TICKS_PER_SECOND * 2, prd_dta: 0, val_nrm: Fixed::from_int(1), val_dta: Fixed::from_int(0)}, act_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Smooth, prd_nrm: TICKS_PER_SECOND * 2 - 1, prd_dta: 0, val_nrm: Fixed::from_int(0), val_dta: Fixed::from_int(0)}, act_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Smooth, prd_nrm: TICKS_PER_SECOND * 2 - 1, prd_dta: 0, val_nrm: Fixed::from_int(1), val_dta: Fixed::from_int(0)}, ina_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Smooth, prd_nrm: TICKS_PER_SECOND * 2, prd_dta: 0, val_nrm: Fixed::from_int(0), val_dta: Fixed::from_int(0)}, ina_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Smooth, prd_nrm: TICKS_PER_SECOND * 2 - 1, prd_dta: 0, val_nrm: Fixed::from_int(1), val_dta: Fixed::from_int(0)}, ina_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Smooth, prd_nrm: TICKS_PER_SECOND * 2, prd_dta: 0, val_nrm: Fixed::from_int(0), val_dta: Fixed::from_int(0)}, tag: 0}, // Annoying Light{ltype: LightType::Normal, flags: LightFlags::SLAVE_VALUE, phase: 0, act_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Random, prd_nrm: 2, prd_dta: 1, val_nrm: Fixed::from_int(1), val_dta: Fixed::from_int(0)}, act_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant, prd_nrm: 2, prd_dta: 0, val_nrm: Fixed::from_int(0), val_dta: Fixed::from_int(0)}, act_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Random, prd_nrm: 1, prd_dta: 0, val_nrm: Fixed::from_int(1), val_dta: Fixed::from_int(0)}, ina_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant, prd_nrm: TICKS_PER_SECOND, prd_dta: 0, val_nrm: Fixed::from_int(0), val_dta: Fixed::from_int(0)}, ina_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant, prd_nrm: TICKS_PER_SECOND, prd_dta: 0, val_nrm: Fixed::from_int(0), val_dta: Fixed::from_int(0)}, ina_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant, prd_nrm: TICKS_PER_SECOND, prd_dta: 0, val_nrm: Fixed::from_int(0), val_dta: Fixed::from_int(0)}, tag: 0}, // Energy Efficient Light{ltype: LightType::Normal, flags: LightFlags::SLAVE_VALUE, phase: 0, act_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant, prd_nrm: TICKS_PER_SECOND, prd_dta: 0, val_nrm: Fixed::from_int(1), val_dta: Fixed::from_int(0)}, act_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant, prd_nrm: TICKS_PER_SECOND, prd_dta: 0, val_nrm: Fixed::from_int(0), val_dta: Fixed::from_int(0)}, act_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Linear, prd_nrm: TICKS_PER_SECOND * 2, prd_dta: 0, val_nrm: Fixed::from_int(1), val_dta: Fixed::from_int(0)}, ina_pri: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant, prd_nrm: TICKS_PER_SECOND, prd_dta: 0, val_nrm: Fixed::from_int(0), val_dta: Fixed::from_int(0)}, ina_sec: ltfn::LightFunc{ftype: ltfn::LightFuncType::Constant, prd_nrm: TICKS_PER_SECOND, prd_dta: 0, val_nrm: Fixed::from_int(0), val_dta: Fixed::from_int(0)}, ina_mid: ltfn::LightFunc{ftype: ltfn::LightFuncType::Linear, prd_nrm: TICKS_PER_SECOND * 2, prd_dta: 0, val_nrm: Fixed::from_int(0), val_dta: Fixed::from_int(0)}, tag: 0}, ]; // EOF