use anyhow::Result; use cgmath::Point2; pub(super) mod syntax { use serde::Deserialize; // Raw serde syntax structs. // These are never seen by code outside this crate. #[derive(Debug, Deserialize)] pub struct Ship { pub sprite: String, pub size: f32, pub engines: Vec, pub guns: Vec, pub hull: f32, } #[derive(Debug, Deserialize)] pub struct Engine { pub x: f32, pub y: f32, pub size: f32, } #[derive(Debug, Deserialize)] pub struct Gun { pub x: f32, pub y: f32, } } // Processed data structs. // These are exported. /// Represents a ship chassis. #[derive(Debug, Clone)] pub struct Ship { /// This ship's name pub name: String, /// This ship's sprite pub sprite: String, /// The size of this ship. /// Measured as unrotated height, /// in terms of game units. pub size: f32, /// Engine points on this ship. /// This is where engine flares are drawn. pub engines: Vec, /// Gun points on this ship. /// A gun outfit can be mounted on each. pub guns: Vec, /// This ship's hull strength pub hull: f32, } /// An engine point on a ship. /// This is where flares are drawn. #[derive(Debug, Clone)] pub struct EnginePoint { /// This engine point's position, in game units, /// relative to the ship's center. pub pos: Point2, /// The size of the flare that should be drawn /// at this point, measured as height in game units. pub size: f32, } /// A gun point on a ship. #[derive(Debug, Clone)] pub struct GunPoint { /// This gun point's position, in game units, /// relative to the ship's center. pub pos: Point2, } impl super::Build for Ship { fn build(root: &super::syntax::Root) -> Result> { let ship = if let Some(ship) = &root.ship { ship } else { return Ok(vec![]); }; let mut out = Vec::new(); for (ship_name, ship) in ship { let size = ship.size; out.push(Self { name: ship_name.to_owned(), sprite: ship.sprite.to_owned(), size, hull: ship.hull, engines: ship .engines .iter() .map(|e| EnginePoint { pos: Point2 { x: e.x * size, y: e.y * size, }, size: e.size, }) .collect(), guns: ship .guns .iter() .map(|e| GunPoint { pos: Point2 { x: e.x * size, y: e.y * size, }, }) .collect(), }); } return Ok(out); } }