#[cfg(feature = "bevy_reflect")]
use bevy_reflect::Reflect;
use qbsp_macros::{BspValue, BspVariableValue};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use crate::{
BspResult,
data::util::{BspVariableArray, IBspValue, NoField},
reader::{BspByteReader, BspParseContext, BspValue, BspVariableValue},
};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "bevy_reflect", derive(Reflect))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum VisDataRef {
Cluster(IBspValue),
Offset(i32),
}
impl VisDataRef {
pub fn is_empty(&self) -> bool {
match *self {
VisDataRef::Cluster(val) => val.0 == -1,
VisDataRef::Offset(val) => val == -1,
}
}
}
impl BspVariableValue for VisDataRef {
type Bsp29 = i32;
type Bsp2 = i32;
type Bsp30 = i32;
type Bsp38 = IBspValue;
type Qbism = IBspValue;
}
impl From<IBspValue> for VisDataRef {
fn from(value: IBspValue) -> Self {
Self::Cluster(value)
}
}
impl From<i32> for VisDataRef {
fn from(value: i32) -> Self {
Self::Offset(value)
}
}
#[derive(BspValue, Debug, Clone)]
#[cfg_attr(feature = "bevy_reflect", derive(Reflect))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct BspClusterOffsets {
pub pvs: u32,
pub phs: u32,
}
#[derive(BspVariableValue, Default, Debug, Clone)]
#[cfg_attr(feature = "bevy_reflect", derive(Reflect))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[bsp2(NoField)]
#[bsp29(NoField)]
#[bsp30(NoField)]
#[bsp38(BspVariableArray<BspClusterOffsets, u32>)]
#[qbism(BspVariableArray<BspClusterOffsets, u32>)]
pub struct BspVisDataOffsets(pub Option<BspVariableArray<BspClusterOffsets, u32>>);
#[derive(Default, Debug, Clone)]
#[cfg_attr(feature = "bevy_reflect", derive(Reflect))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct BspVisData {
pub vis_data_offsets: BspVisDataOffsets,
pub visdata: Vec<u8>,
}
impl BspVisData {
pub fn pvs(&self, vis_ref: VisDataRef) -> Option<&[u8]> {
match vis_ref {
VisDataRef::Cluster(cluster) => {
let offsets = self.vis_data_offsets.as_ref()?;
let BspClusterOffsets { pvs, .. } = offsets.get(cluster.0 as usize)?;
self.visdata.get(*pvs as usize..)
}
VisDataRef::Offset(vis_leaf) => {
if self.vis_data_offsets.is_some() {
return None;
}
self.visdata.get(usize::try_from(vis_leaf).ok()?..)
}
}
}
pub fn phs(&self, vis_ref: VisDataRef) -> Option<&[u8]> {
match vis_ref {
VisDataRef::Cluster(cluster) => {
let offsets = self.vis_data_offsets.as_ref()?;
let BspClusterOffsets { phs, .. } = offsets.get(cluster.0 as usize)?;
self.visdata.get(*phs as usize..)
}
VisDataRef::Offset(vis_leaf) => {
if self.vis_data_offsets.is_some() {
return None;
}
self.visdata.get(usize::try_from(vis_leaf).ok()?..)
}
}
}
}
impl BspValue for BspVisData {
fn bsp_parse(reader: &mut BspByteReader) -> BspResult<Self> {
if reader.is_empty() {
return Ok(Self::default());
}
let vis_data_offsets: BspVisDataOffsets = reader.read()?;
Ok(Self {
vis_data_offsets,
visdata: reader.read_rest().to_vec(),
})
}
fn bsp_struct_size(_: &BspParseContext) -> usize {
unimplemented!()
}
}