use crate::vpx::biff::{self, BiffRead, BiffReader, BiffWrite};
use super::vertex2d::Vertex2D;
#[derive(Debug, PartialEq)]
pub struct Gate {
pub center: Vertex2D, pub length: f32, pub height: f32, pub rotation: f32, pub material: String, pub is_timer_enabled: bool, pub show_bracket: bool, pub is_collidable: bool, pub timer_interval: f32, pub surface: String, pub elasticity: f32, pub angle_max: f32, pub angle_min: f32, pub friction: f32, pub damping: Option<f32>, pub gravity_factor: Option<f32>, pub is_visible: bool, pub name: String, pub two_way: bool, pub is_reflection_enabled: bool, pub gate_type: u32,
pub is_locked: bool,
pub editor_layer: u32,
pub editor_layer_name: Option<String>, pub editor_layer_visibility: Option<bool>,
}
impl BiffRead for Gate {
fn biff_read(reader: &mut BiffReader<'_>) -> Self {
let mut center = Vertex2D::default();
let mut length: f32 = 100.0;
let mut height: f32 = 50.0;
let mut rotation: f32 = -90.0;
let mut material: String = Default::default();
let mut is_timer_enabled: bool = false;
let mut show_bracket: bool = true;
let mut is_collidable: bool = true;
let mut timer_interval: f32 = Default::default();
let mut surface: String = Default::default();
let mut elasticity: f32 = 0.3;
let mut angle_max: f32 = std::f32::consts::PI / 2.0;
let mut angle_min: f32 = Default::default();
let mut friction: f32 = 0.02;
let mut damping: Option<f32> = None; let mut is_visible: bool = true;
let mut name: String = Default::default();
let mut two_way: bool = false;
let mut is_reflection_enabled: bool = true;
let mut gate_type: u32 = Default::default();
let mut gravity_factor: Option<f32> = None;
let mut is_locked: bool = false;
let mut editor_layer: u32 = Default::default();
let mut editor_layer_name: Option<String> = None;
let mut editor_layer_visibility: Option<bool> = None;
loop {
reader.next(biff::WARN);
if reader.is_eof() {
break;
}
let tag = reader.tag();
let tag_str = tag.as_str();
match tag_str {
"VCEN" => {
center = Vertex2D::biff_read(reader);
}
"LGTH" => {
length = reader.get_f32();
}
"HGTH" => {
height = reader.get_f32();
}
"ROTA" => {
rotation = reader.get_f32();
}
"MATR" => {
material = reader.get_string();
}
"TMON" => {
is_timer_enabled = reader.get_bool();
}
"GSUP" => {
show_bracket = reader.get_bool();
}
"GCOL" => {
is_collidable = reader.get_bool();
}
"TMIN" => {
timer_interval = reader.get_f32();
}
"SURF" => {
surface = reader.get_string();
}
"ELAS" => {
elasticity = reader.get_f32();
}
"GAMA" => {
angle_max = reader.get_f32();
}
"GAMI" => {
angle_min = reader.get_f32();
}
"GFRC" => {
friction = reader.get_f32();
}
"AFRC" => {
damping = Some(reader.get_f32());
}
"GGFC" => {
gravity_factor = Some(reader.get_f32());
}
"GVSB" => {
is_visible = reader.get_bool();
}
"NAME" => {
name = reader.get_wide_string();
}
"TWWA" => {
two_way = reader.get_bool();
}
"REEN" => {
is_reflection_enabled = reader.get_bool();
}
"GATY" => {
gate_type = reader.get_u32();
}
"LOCK" => {
is_locked = reader.get_bool();
}
"LAYR" => {
editor_layer = reader.get_u32();
}
"LANR" => {
editor_layer_name = Some(reader.get_string());
}
"LVIS" => {
editor_layer_visibility = Some(reader.get_bool());
}
_ => {
println!(
"Unknown tag {} for {}",
tag_str,
std::any::type_name::<Self>()
);
reader.skip_tag();
}
}
}
Self {
center,
length,
height,
rotation,
material,
is_timer_enabled,
show_bracket,
is_collidable,
timer_interval,
surface,
elasticity,
angle_max,
angle_min,
friction,
damping,
gravity_factor,
is_visible,
name,
two_way,
is_reflection_enabled,
gate_type,
is_locked,
editor_layer,
editor_layer_name,
editor_layer_visibility,
}
}
}
impl BiffWrite for Gate {
fn biff_write(&self, writer: &mut biff::BiffWriter) {
writer.write_tagged("VCEN", &self.center);
writer.write_tagged_f32("LGTH", self.length);
writer.write_tagged_f32("HGTH", self.height);
writer.write_tagged_f32("ROTA", self.rotation);
writer.write_tagged_string("MATR", &self.material);
writer.write_tagged_bool("TMON", self.is_timer_enabled);
writer.write_tagged_bool("GSUP", self.show_bracket);
writer.write_tagged_bool("GCOL", self.is_collidable);
writer.write_tagged_f32("TMIN", self.timer_interval);
writer.write_tagged_string("SURF", &self.surface);
writer.write_tagged_f32("ELAS", self.elasticity);
writer.write_tagged_f32("GAMA", self.angle_max);
writer.write_tagged_f32("GAMI", self.angle_min);
writer.write_tagged_f32("GFRC", self.friction);
if let Some(damping) = self.damping {
writer.write_tagged_f32("AFRC", damping);
}
if let Some(gravity_factor) = self.gravity_factor {
writer.write_tagged_f32("GGFC", gravity_factor);
}
writer.write_tagged_bool("GVSB", self.is_visible);
writer.write_tagged_wide_string("NAME", &self.name);
writer.write_tagged_bool("TWWA", self.two_way);
writer.write_tagged_bool("REEN", self.is_reflection_enabled);
writer.write_tagged_u32("GATY", self.gate_type);
writer.write_tagged_bool("LOCK", self.is_locked);
writer.write_tagged_u32("LAYR", self.editor_layer);
if let Some(editor_layer_name) = &self.editor_layer_name {
writer.write_tagged_string("LANR", editor_layer_name);
}
if let Some(editor_layer_visibility) = self.editor_layer_visibility {
writer.write_tagged_bool("LVIS", editor_layer_visibility);
}
writer.close(true);
}
}
#[cfg(test)]
mod tests {
use crate::vpx::biff::BiffWriter;
use super::*;
use pretty_assertions::assert_eq;
#[test]
fn test_write_read() {
let gate = Gate {
center: Vertex2D::new(1.0, 2.0),
length: 3.0,
height: 4.0,
rotation: 5.0,
material: "material".to_string(),
is_timer_enabled: true,
show_bracket: false,
is_collidable: false,
timer_interval: 6.0,
surface: "surface".to_string(),
elasticity: 7.0,
angle_max: 8.0,
angle_min: 9.0,
friction: 10.0,
damping: Some(11.0),
gravity_factor: Some(12.0),
is_visible: false,
name: "name".to_string(),
two_way: true,
is_reflection_enabled: false,
gate_type: 13,
is_locked: true,
editor_layer: 14,
editor_layer_name: Some("editor_layer_name".to_string()),
editor_layer_visibility: Some(false),
};
let mut writer = BiffWriter::new();
Gate::biff_write(&gate, &mut writer);
let gate_read = Gate::biff_read(&mut BiffReader::new(writer.get_data()));
assert_eq!(gate, gate_read);
}
}