mod displacement;
mod face;
mod game;
use crate::data::*;
use crate::Bsp;
use std::fmt::{Debug, Formatter};
use std::ops::Deref;
pub struct Handle<'a, T> {
bsp: &'a Bsp,
data: &'a T,
}
impl<T: Debug> Debug for Handle<'_, T> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Handle")
.field("data", self.data)
.finish_non_exhaustive()
}
}
impl<T> Clone for Handle<'_, T> {
fn clone(&self) -> Self {
Handle { ..*self }
}
}
impl<'a, T> AsRef<T> for Handle<'a, T> {
fn as_ref(&self) -> &'a T {
self.data
}
}
impl<T> Deref for Handle<'_, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
self.data
}
}
impl<'a, T> Handle<'a, T> {
pub fn new(bsp: &'a Bsp, data: &'a T) -> Self {
Handle { bsp, data }
}
}
impl<'a> Handle<'a, Model> {
pub fn faces(&self) -> impl Iterator<Item = Handle<'a, Face>> {
let start = self.first_face as usize;
let end = start + self.face_count as usize;
let bsp = self.bsp;
bsp.faces[start..end]
.iter()
.map(move |face| Handle::new(bsp, face))
}
}
impl<'a> Handle<'a, TextureInfo> {
pub fn texture(&self) -> Handle<'a, TextureData> {
let texture = self
.bsp
.textures_data
.get(self.data.texture_data_index as usize)
.unwrap();
Handle::new(self.bsp, texture)
}
}
impl Handle<'_, Node> {
pub fn plane(&self) -> Handle<'_, Plane> {
self.bsp.plane(self.plane_index as _).unwrap()
}
}
impl<'a> Handle<'a, Leaf> {
pub fn visible_set(&self) -> Option<impl Iterator<Item = Handle<'a, Leaf>>> {
let cluster = self.cluster;
let bsp = self.bsp;
if cluster < 0 {
None
} else {
let visible_clusters = bsp.vis_data.visible_clusters(cluster);
Some(
bsp.leaves
.iter()
.filter(move |leaf| {
if leaf.cluster == cluster {
true
} else if leaf.cluster > 0 {
visible_clusters[leaf.cluster as u64]
} else {
false
}
})
.map(move |leaf| Handle { bsp, data: leaf }),
)
}
}
pub fn faces(&self) -> impl Iterator<Item = Handle<'a, Face>> {
let start = self.first_leaf_face as usize;
let end = start + self.leaf_face_count as usize;
let bsp = self.bsp;
bsp.leaf_faces[start..end]
.iter()
.filter_map(move |leaf_face| bsp.face(leaf_face.face as usize))
}
}
impl<'a> Handle<'a, TextureInfo> {
pub fn texture_data(&self) -> Handle<'a, TextureData> {
Handle::new(
self.bsp,
&self.bsp.textures_data[self.data.texture_data_index as usize],
)
}
pub fn name(&self) -> &'a str {
self.texture_data().name()
}
}
impl<'a> Handle<'a, TextureData> {
pub fn name(&self) -> &'a str {
let start = self.bsp.texture_string_tables[self.name_string_table_id as usize] as usize;
let part = &self.bsp.texture_string_data[start..];
if let Some((s, _)) = part.split_once('\0') {
s
} else {
part
}
}
}