use bilge::prelude::*;
use binrw::{BinRead, BinWrite, binread};
use xc3_write::{Xc3Write, Xc3WriteOffsets};
use crate::{
mxmd::{Materials, ModelsV112, PackedTextures},
parse_count32_offset32, parse_offset32_count32, parse_ptr32, parse_string_ptr32,
spch::Spch,
vertex::VertexData,
xc3_write_binwrite_impl,
};
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
pub struct PropModelData {
pub unk1: [u32; 3],
#[br(parse_with = parse_ptr32)]
#[xc3(offset(u32))]
pub models: ModelsV112,
#[br(parse_with = parse_ptr32)]
#[xc3(offset(u32))]
pub materials: Materials,
pub unk2: u32,
#[br(parse_with = parse_ptr32)]
#[xc3(offset(u32))]
pub lods: PropLods,
pub unk3: u32,
#[br(parse_with = parse_offset32_count32)]
#[xc3(offset_count(u32, u32))]
pub textures: Vec<Texture>,
#[br(parse_with = parse_offset32_count32)]
#[xc3(offset_count(u32, u32))]
pub model_vertex_data_indices: Vec<u32>,
pub unk4_1: u32,
pub unk4_2: u32,
#[br(parse_with = parse_offset32_count32)]
#[xc3(offset_count(u32, u32))]
pub prop_info: Vec<PropPositionInfo>,
pub unk4_5: u32,
#[br(parse_with = parse_ptr32)]
#[xc3(offset(u32))]
pub spch: Spch,
#[br(parse_with = parse_offset32_count32)]
#[xc3(offset_count(u32, u32))]
pub low_texture_entry_indices: Vec<u16>,
}
#[binread]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
#[br(stream = r)]
#[xc3(base_offset)]
pub struct PropLods {
#[br(temp, try_calc = r.stream_position())]
base_offset: u64,
pub unk1: u32,
#[br(parse_with = parse_count32_offset32, offset = base_offset)]
#[xc3(count_offset(u32, u32))]
pub props: Vec<PropLod>,
#[br(parse_with = parse_count32_offset32, offset = base_offset)]
#[xc3(count_offset(u32, u32))]
pub lods: Vec<PropModelLod>,
#[br(parse_with = parse_count32_offset32, offset = base_offset)]
#[xc3(count_offset(u32, u32))]
pub instances: Vec<PropInstance>,
pub count2: u32,
pub offset2: u32,
#[br(parse_with = parse_count32_offset32, offset = base_offset)]
#[xc3(count_offset(u32, u32))]
pub unk3: Vec<PropUnk3>,
pub unk2: u32,
pub unks: [u32; 10],
pub animated_parts_start_index: u32,
pub animated_parts_count: u32,
pub static_parts_start_index: u32,
pub static_parts_count: u32,
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
pub struct PropLod {
pub base_lod_index: u32,
pub lod_count: u32,
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
pub struct PropModelLod {
pub radius: f32,
pub distance: f32,
pub index: u32,
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
pub struct PropInstance {
pub transform: [[f32; 4]; 4],
pub position: [f32; 3],
pub radius: f32,
pub center: [f32; 3],
pub prop_index: u32,
pub unk1: u16,
pub part_id: u16,
pub unk3: u16,
pub unk4: u16,
pub unks: [u32; 2],
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
pub struct PropUnk3 {
pub unk1: [f32; 5],
pub unk2: [u32; 3],
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
pub struct PropPositionInfo {
pub prop_position_entry_index: u32,
pub instance_start_index: u32,
pub max_xyz: [f32; 3],
pub min_xyz: [f32; 3],
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
pub struct MapModelData {
pub unk1: [u32; 3],
#[br(parse_with = parse_ptr32)]
#[xc3(offset(u32))]
pub models: ModelsV112,
#[br(parse_with = parse_ptr32)]
#[xc3(offset(u32))]
pub materials: Materials,
pub m_unk2: [u32; 2],
#[br(parse_with = parse_offset32_count32)]
#[xc3(offset_count(u32, u32))]
pub textures: Vec<Texture>,
pub m_unk3: [u32; 2],
#[br(parse_with = parse_ptr32)]
#[xc3(offset(u32))]
pub spch: Spch,
#[br(parse_with = parse_offset32_count32)]
#[xc3(offset_count(u32, u32))]
pub low_texture_entry_indices: Vec<u16>,
#[br(parse_with = parse_ptr32)]
#[xc3(offset(u32))]
pub groups: MapModelGroups,
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
pub struct Texture {
pub low_texture_index: i16,
pub low_textures_entry_index: i16,
pub texture_index: i16,
pub flags: TextureFlags,
}
#[bitsize(16)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(DebugBits, FromBits, BinRead, BinWrite, PartialEq, Clone, Copy)]
#[br(map = u16::into)]
#[bw(map = |&x| u16::from(x))]
pub struct TextureFlags {
pub has_low_texture: bool,
pub has_high_texture: bool,
pub unk: u14,
}
#[binread]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
#[br(stream = r)]
#[xc3(base_offset)]
pub struct MapModelGroups {
#[br(temp, try_calc = r.stream_position())]
base_offset: u64,
#[br(parse_with = parse_offset32_count32, offset = base_offset)]
#[xc3(offset_count(u32, u32))]
pub groups: Vec<MapModelGroup>,
#[br(parse_with = parse_offset32_count32, offset = base_offset)]
#[xc3(offset_count(u32, u32))]
pub model_group_index: Vec<u16>,
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
pub struct MapModelGroup {
pub max_xyz: [f32; 3],
pub min_xyz: [f32; 3],
pub vertex_data_index: u32,
pub unk_vertex_data_index: u32,
pub unk3: u32,
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
pub struct EnvModelData {
#[br(parse_with = parse_ptr32)]
#[xc3(offset(u32))]
pub models: ModelsV112,
#[br(parse_with = parse_ptr32)]
#[xc3(offset(u32))]
pub materials: Materials,
pub unk_offset1: u32,
#[br(parse_with = parse_ptr32)]
#[xc3(offset(u32))]
pub vertex_data: VertexData,
#[br(parse_with = parse_ptr32)]
#[xc3(offset(u32))]
pub textures: PackedTextures,
pub unk6: u32,
#[br(parse_with = parse_ptr32)]
#[xc3(offset(u32))]
pub spch: Spch,
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
pub struct FoliageModelData {
#[br(parse_with = parse_ptr32)]
#[xc3(offset(u32))]
pub models: ModelsV112,
#[br(parse_with = parse_ptr32)]
#[xc3(offset(u32))]
pub materials: FoliageMaterials,
pub unk1: u32,
#[br(parse_with = parse_ptr32)]
#[xc3(offset(u32))]
pub vertex_data: VertexData,
#[br(parse_with = parse_ptr32)]
#[xc3(offset(u32))]
pub textures: PackedTextures,
pub unk4: [u32; 11], }
#[binread]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
#[br(stream = r)]
#[xc3(base_offset)]
pub struct FoliageMaterials {
#[br(temp, try_calc = r.stream_position())]
base_offset: u64,
#[br(parse_with = parse_offset32_count32, args { offset: base_offset, inner: base_offset })]
#[xc3(offset_count(u32, u32))]
pub materials: Vec<FoliageMaterial>,
pub unk1: u32,
pub unk2: u32,
pub unk3: u32,
pub unk4: u32,
pub unk5: u32,
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
#[br(import_raw(base_offset: u64))]
pub struct FoliageMaterial {
#[br(parse_with = parse_string_ptr32, offset = base_offset)]
#[xc3(offset(u32))]
pub name: String,
pub unk1: u16,
pub unk2: u16,
pub unk3: u16,
pub unk4: u16,
pub unk5: u16,
pub unk6: u16,
pub unk7: u16,
pub unk8: u16,
pub unk9: u16,
pub unk10: u16,
pub unk11: u16,
pub unk12: u16,
pub unk13: u16,
pub unk14: u16,
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
pub struct FoliageVertexData {
#[br(parse_with = parse_count32_offset32)]
#[xc3(count_offset(u32, u32))]
pub unk1: Vec<FoliageVertex1>,
#[br(parse_with = parse_count32_offset32)]
#[xc3(count_offset(u32, u32))]
pub unk2: Vec<FoliageVertex2>,
pub unk3: u32,
pub unks: [u32; 7],
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
pub struct FoliageVertex1 {
pub unk1: [f32; 3],
pub unk2: [u8; 4],
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
pub struct FoliageVertex2 {
pub unk1: [f32; 4],
pub unk2: u32, pub unk3: u32, pub unk4: u32,
pub unk5: u32,
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
pub struct FoliageUnkData {
pub unk1: [u32; 9], pub unk2: [f32; 4],
pub unk3: [u32; 8],
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
pub struct MapLowModelData {
pub unk1: u32,
pub unk2: u32,
#[br(parse_with = parse_ptr32)]
#[xc3(offset(u32))]
pub models: ModelsV112,
#[br(parse_with = parse_ptr32)]
#[xc3(offset(u32))]
pub materials: Materials,
pub unk5: u32,
pub unk6: u32,
#[br(parse_with = parse_ptr32)]
#[xc3(offset(u32))]
pub vertex_data: VertexData,
pub unk8: u32,
#[br(parse_with = parse_ptr32)]
#[xc3(offset(u32))]
pub spch: Spch,
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
pub struct PropPositions {
#[br(parse_with = parse_count32_offset32)]
#[xc3(count_offset(u32, u32))]
pub instances: Vec<PropInstance>,
pub unk1: u32,
pub unk2: u32,
#[br(parse_with = parse_count32_offset32)]
#[xc3(count_offset(u32, u32))]
pub nodes: Vec<RenderNode>,
pub unk3: u32,
pub unk4: u32,
pub unk5: u32,
pub animated_parts_start_index: u32,
pub animated_parts_count: u32,
pub tree_offset: u32,
pub unk6: u32,
}
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[derive(Debug, BinRead, Xc3Write, Xc3WriteOffsets, PartialEq, Clone)]
pub struct RenderNode {
pub center: [f32; 3],
pub radius: f32,
pub unk1: f32,
pub unk2: u32,
pub unk3: u32,
pub unk4: u32,
}
xc3_write_binwrite_impl!(TextureFlags);