aboutsummaryrefslogtreecommitdiff
path: root/stockton-levels/src/parts
diff options
context:
space:
mode:
Diffstat (limited to 'stockton-levels/src/parts')
-rw-r--r--stockton-levels/src/parts/entities.rs36
-rw-r--r--stockton-levels/src/parts/faces.rs43
-rw-r--r--stockton-levels/src/parts/mod.rs17
-rw-r--r--stockton-levels/src/parts/textures.rs48
-rw-r--r--stockton-levels/src/parts/vertices.rs156
-rw-r--r--stockton-levels/src/parts/visdata.rs8
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;
+}