diff options
author | tcmal <me@aria.rip> | 2024-08-25 17:44:23 +0100 |
---|---|---|
committer | tcmal <me@aria.rip> | 2024-08-25 17:44:23 +0100 |
commit | 439219e74090c7158f8dbc33fed4107a5eb7c003 (patch) | |
tree | 7ba62254b2d888578ff6c1c8de4f0f35c01c75dd /stockton-levels/src/parts | |
parent | 04f17923d38171f07f72603a54237f20ca3572dd (diff) |
refactor(levels): no longer q3 specific
Diffstat (limited to 'stockton-levels/src/parts')
-rw-r--r-- | stockton-levels/src/parts/entities.rs | 36 | ||||
-rw-r--r-- | stockton-levels/src/parts/faces.rs | 43 | ||||
-rw-r--r-- | stockton-levels/src/parts/mod.rs | 17 | ||||
-rw-r--r-- | stockton-levels/src/parts/textures.rs | 48 | ||||
-rw-r--r-- | stockton-levels/src/parts/vertices.rs | 156 | ||||
-rw-r--r-- | stockton-levels/src/parts/visdata.rs | 8 |
6 files changed, 308 insertions, 0 deletions
diff --git a/stockton-levels/src/parts/entities.rs b/stockton-levels/src/parts/entities.rs new file mode 100644 index 0000000..7a5ac74 --- /dev/null +++ b/stockton-levels/src/parts/entities.rs @@ -0,0 +1,36 @@ +use std::iter::Iterator; + +pub type EntityRef = u32; + +/// A game entity +pub trait IsEntity<C: HasEntities + ?Sized> { + fn get_attr(&self, container: &C) -> Option<&str>; +} + +pub trait HasEntities { + type Entity: IsEntity<Self>; + + fn get_entity(&self, idx: EntityRef) -> Option<&Self::Entity>; + fn iter_entities(&self) -> Entities<Self> { + Entities { + next: 0, + container: self, + } + } +} + +#[derive(Debug, Clone, Copy)] +pub struct Entities<'a, T: HasEntities + ?Sized> { + next: EntityRef, + container: &'a T, +} + +impl<'a, T: HasEntities> Iterator for Entities<'a, T> { + type Item = &'a T::Entity; + + fn next(&mut self) -> Option<Self::Item> { + let res = self.container.get_entity(self.next); + self.next += 1; + res + } +} diff --git a/stockton-levels/src/parts/faces.rs b/stockton-levels/src/parts/faces.rs new file mode 100644 index 0000000..0168cd8 --- /dev/null +++ b/stockton-levels/src/parts/faces.rs @@ -0,0 +1,43 @@ +use super::{textures::TextureRef, vertices::Vertex}; +use serde::{Deserialize, Serialize}; + +pub type FaceRef = u32; + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub enum Geometry { + Vertices(Vertex, Vertex, Vertex), +} + +pub trait IsFace<C: HasFaces + ?Sized> { + fn index(&self, container: &C) -> FaceRef; + fn geometry(&self, container: &C) -> Geometry; + fn texture_idx(&self, container: &C) -> TextureRef; +} + +pub trait HasFaces { + type Face: IsFace<Self>; + + fn get_face(&self, index: FaceRef) -> Option<&Self::Face>; + fn iter_faces(&self) -> Faces<Self> { + Faces { + next: 0, + container: self, + } + } +} + +#[derive(Debug, Clone, Copy)] +pub struct Faces<'a, T: HasFaces + ?Sized> { + next: FaceRef, + container: &'a T, +} + +impl<'a, T: HasFaces> Iterator for Faces<'a, T> { + type Item = &'a T::Face; + + fn next(&mut self) -> Option<Self::Item> { + let res = self.container.get_face(self.next); + self.next += 1; + res + } +} diff --git a/stockton-levels/src/parts/mod.rs b/stockton-levels/src/parts/mod.rs new file mode 100644 index 0000000..05697f0 --- /dev/null +++ b/stockton-levels/src/parts/mod.rs @@ -0,0 +1,17 @@ +mod entities; +mod faces; +mod textures; +mod vertices; +mod visdata; + +pub mod data { + pub use super::entities::{Entities, EntityRef}; + pub use super::faces::{FaceRef, Faces, Geometry}; + pub use super::textures::{TextureRef, Textures}; + pub use super::vertices::{Vertex, VertexRef}; +} + +pub use entities::{HasEntities, IsEntity}; +pub use faces::{HasFaces, IsFace}; +pub use textures::{HasTextures, IsTexture}; +pub use visdata::HasVisData; diff --git a/stockton-levels/src/parts/textures.rs b/stockton-levels/src/parts/textures.rs new file mode 100644 index 0000000..8e6cb9a --- /dev/null +++ b/stockton-levels/src/parts/textures.rs @@ -0,0 +1,48 @@ +// This program is free software: you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by the Free +// Software Foundation, either version 3 of the License, or (at your option) +// any later version. + +// This program is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +// more details. + +// You should have received a copy of the GNU General Public License along +// with this program. If not, see <http://www.gnu.org/licenses/>. + +use std::iter::Iterator; + +pub type TextureRef = u32; + +pub trait IsTexture { + fn name(&self) -> &str; +} + +pub trait HasTextures { + type Texture: IsTexture; + + fn get_texture(&self, idx: TextureRef) -> Option<&Self::Texture>; + fn iter_textures(&self) -> Textures<Self> { + Textures { + next: 0, + container: self, + } + } +} + +#[derive(Debug, Clone, Copy)] +pub struct Textures<'a, T: HasTextures + ?Sized> { + next: TextureRef, + container: &'a T, +} + +impl<'a, T: HasTextures> Iterator for Textures<'a, T> { + type Item = &'a T::Texture; + + fn next(&mut self) -> Option<Self::Item> { + let res = self.container.get_texture(self.next); + self.next += 1; + res + } +} diff --git a/stockton-levels/src/parts/vertices.rs b/stockton-levels/src/parts/vertices.rs new file mode 100644 index 0000000..0b7dfd6 --- /dev/null +++ b/stockton-levels/src/parts/vertices.rs @@ -0,0 +1,156 @@ +use crate::types::Rgba; +use na::{Vector2, Vector3}; +use serde::de; +use serde::de::{Deserializer, MapAccess, SeqAccess, Visitor}; +use serde::ser::{Serialize, SerializeStruct, Serializer}; +use serde::Deserialize; +use std::fmt; + +pub type VertexRef = u32; + +/// A vertex, used to describe a face. +#[derive(Debug, Clone, Copy, PartialEq)] +pub struct Vertex { + pub position: Vector3<f32>, + pub tex: Vector2<f32>, + pub color: Rgba, +} + +impl Serialize for Vertex { + fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { + let mut state = serializer.serialize_struct("Vertex", 5)?; + state.serialize_field("pos_x", &self.position.x)?; + state.serialize_field("pos_y", &self.position.y)?; + state.serialize_field("pos_z", &self.position.z)?; + state.serialize_field("tex_u", &self.tex.x)?; + state.serialize_field("tex_v", &self.tex.y)?; + state.serialize_field("color", &self.color)?; + + state.end() + } +} + +impl<'de> Deserialize<'de> for Vertex { + fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> { + #[derive(Deserialize)] + #[serde(field_identifier, rename_all = "snake_case")] + enum Field { + PosX, + PosY, + PosZ, + TexU, + TexV, + Color, + } + const FIELDS: &'static [&'static str] = + &["pos_x", "pos_y", "pos_z", "tex_x", "tex_y", "color"]; + + struct VertexVisitor; + + impl<'de> Visitor<'de> for VertexVisitor { + type Value = Vertex; + + fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str("struct Vertex") + } + + fn visit_seq<V>(self, mut seq: V) -> Result<Vertex, V::Error> + where + V: SeqAccess<'de>, + { + let pos_x = seq + .next_element()? + .ok_or_else(|| de::Error::invalid_length(0, &self))?; + let pos_y = seq + .next_element()? + .ok_or_else(|| de::Error::invalid_length(1, &self))?; + let pos_z = seq + .next_element()? + .ok_or_else(|| de::Error::invalid_length(2, &self))?; + let tex_u = seq + .next_element()? + .ok_or_else(|| de::Error::invalid_length(3, &self))?; + let tex_v = seq + .next_element()? + .ok_or_else(|| de::Error::invalid_length(4, &self))?; + let color = seq + .next_element()? + .ok_or_else(|| de::Error::invalid_length(5, &self))?; + Ok(Vertex { + position: Vector3::new(pos_x, pos_y, pos_z), + tex: Vector2::new(tex_u, tex_v), + color, + }) + } + + fn visit_map<V>(self, mut map: V) -> Result<Vertex, V::Error> + where + V: MapAccess<'de>, + { + let mut pos_x = None; + let mut pos_y = None; + let mut pos_z = None; + let mut tex_u = None; + let mut tex_v = None; + let mut color = None; + while let Some(key) = map.next_key()? { + match key { + Field::PosX => { + if pos_x.is_some() { + return Err(de::Error::duplicate_field("pos_x")); + } + pos_x = Some(map.next_value()?); + } + Field::PosY => { + if pos_y.is_some() { + return Err(de::Error::duplicate_field("pos_y")); + } + pos_y = Some(map.next_value()?); + } + Field::PosZ => { + if pos_z.is_some() { + return Err(de::Error::duplicate_field("pos_z")); + } + pos_z = Some(map.next_value()?); + } + Field::TexU => { + if tex_u.is_some() { + return Err(de::Error::duplicate_field("tex_u")); + } + tex_u = Some(map.next_value()?); + } + Field::TexV => { + if tex_v.is_some() { + return Err(de::Error::duplicate_field("tex_v")); + } + tex_v = Some(map.next_value()?); + } + Field::Color => { + if color.is_some() { + return Err(de::Error::duplicate_field("color")); + } + color = Some(map.next_value()?); + } + } + } + let position = Vector3::new( + pos_x.ok_or_else(|| de::Error::missing_field("pos_x"))?, + pos_y.ok_or_else(|| de::Error::missing_field("pos_y"))?, + pos_z.ok_or_else(|| de::Error::missing_field("pos_z"))?, + ); + let tex = Vector2::new( + tex_u.ok_or_else(|| de::Error::missing_field("tex_u"))?, + tex_v.ok_or_else(|| de::Error::missing_field("tex_v"))?, + ); + let color = color.ok_or_else(|| de::Error::missing_field("nanos"))?; + Ok(Vertex { + position, + tex, + color, + }) + } + } + + deserializer.deserialize_struct("Vertex", FIELDS, VertexVisitor) + } +} diff --git a/stockton-levels/src/parts/visdata.rs b/stockton-levels/src/parts/visdata.rs new file mode 100644 index 0000000..f311bf7 --- /dev/null +++ b/stockton-levels/src/parts/visdata.rs @@ -0,0 +1,8 @@ +use super::faces::FaceRef; +use na::Vector3; +use std::iter::Iterator; + +pub trait HasVisData { + type Faces: Iterator<Item = FaceRef>; + fn get_visible(pos: Vector3<f32>, rot: Vector3<f32>) -> Self::Faces; +} |