use std::collections::HashMap;
use binrw::BinRead;
#[derive(Debug, Clone, BinRead)]
#[br(little)]
pub struct MomtEntry {
pub flags: u32,
pub shader: u32,
pub blend_mode: u32,
pub texture_1: u32,
pub emissive_color: [u8; 4],
pub frame_emissive_color: [u8; 4],
pub texture_2: u32,
pub diff_color: [u8; 4],
pub ground_type: u32,
pub texture_3: u32,
pub color_2: u32,
pub flags_2: u32,
#[br(count = 16)]
pub runtime_data: Vec<u8>,
}
impl MomtEntry {
pub fn get_texture1_index(&self, texture_offset_index_map: &HashMap<u32, u32>) -> u32 {
texture_offset_index_map
.get(&self.texture_1)
.copied()
.unwrap()
}
pub fn get_texture2_index(&self, texture_offset_index_map: &HashMap<u32, u32>) -> u32 {
texture_offset_index_map
.get(&self.texture_2)
.copied()
.unwrap()
}
pub fn get_texture3_index(&self, texture_offset_index_map: &HashMap<u32, u32>) -> u32 {
texture_offset_index_map
.get(&self.texture_3)
.copied()
.unwrap()
}
}
#[derive(Debug, Clone)]
pub struct Mogn {
pub names: Vec<String>,
}
impl Mogn {
pub fn parse(data: &[u8]) -> Result<Self, Box<dyn std::error::Error>> {
let mut names = Vec::new();
let mut start = 0;
for i in 0..data.len() {
if data[i] == 0 {
if i > start {
let name = String::from_utf8(data[start..i].to_vec())?;
names.push(name);
}
start = i + 1;
}
}
Ok(Self { names })
}
}
#[derive(Debug, Clone, BinRead)]
#[br(little)]
pub struct MogiEntry {
pub flags: u32,
pub bounding_box_min: [f32; 3],
pub bounding_box_max: [f32; 3],
pub name_offset: i32,
}
#[derive(Debug, Clone, BinRead)]
#[br(little)]
pub struct MoltEntry {
pub light_type: u8,
pub use_attenuation: u8,
pub padding: [u8; 2],
pub color: [u8; 4],
pub position: [f32; 3],
pub intensity: f32,
pub attenuation_start: f32,
pub attenuation_end: f32,
}
#[derive(Debug, Clone, BinRead)]
#[br(little)]
pub struct ModsEntry {
pub name: [u8; 20],
pub start_index: u32,
pub count: u32,
pub padding: u32,
}
#[derive(Debug, Clone, BinRead)]
#[br(little)]
pub struct ModdEntry {
pub name_index_and_flags: u32, pub position: [f32; 3], pub orientation: [f32; 4], pub scale: f32,
pub color: [u8; 4], }
impl ModdEntry {
pub fn name_index(&self) -> u32 {
self.name_index_and_flags & 0x00FFFFFF
}
pub fn accepts_proj_tex(&self) -> bool {
(self.name_index_and_flags & 0x01000000) != 0
}
pub fn uses_interior_lighting(&self) -> bool {
(self.name_index_and_flags & 0x02000000) != 0
}
}
#[derive(Debug, Clone, BinRead)]
#[br(little)]
pub struct MfogEntry {
pub flags: u32,
pub position: [f32; 3],
pub smaller_radius: f32,
pub larger_radius: f32,
pub fog_end: f32,
pub fog_start_multiplier: f32,
pub color_1: [u8; 4],
pub color_2: [u8; 4],
}
#[derive(Debug, Clone, BinRead)]
#[br(little)]
pub struct McvpEntry {
pub plane: [f32; 4], }
#[derive(Debug, Clone, BinRead)]
#[br(little)]
pub struct MopyEntry {
pub flags: u8,
pub material_id: u8,
}
pub type MoviEntry = u16;
#[derive(Debug, Clone, BinRead)]
#[br(little)]
pub struct MovtEntry {
pub x: f32,
pub y: f32,
pub z: f32,
}
#[derive(Debug, Clone, BinRead)]
#[br(little)]
pub struct MonrEntry {
pub x: f32,
pub y: f32,
pub z: f32,
}
#[derive(Debug, Clone, BinRead)]
#[br(little)]
pub struct MotvEntry {
pub u: f32,
pub v: f32,
}
#[derive(Debug, Clone, BinRead)]
#[br(little)]
pub struct MobaEntry {
pub bounding_box_min: [i16; 3],
pub bounding_box_max: [i16; 3],
pub start_index: u32,
pub count: u16,
pub min_index: u16,
pub max_index: u16,
pub flags: u8,
pub material_id: u8,
}
pub type MolrEntry = u16;
pub type ModrEntry = u16;
#[derive(Debug, Clone, BinRead)]
#[br(little)]
pub struct MobnEntry {
pub flags: u16,
pub neg_child: i16,
pub pos_child: i16,
pub n_faces: u16,
pub face_start: u32,
pub plane_distance: f32,
}
pub type MobrEntry = u16;
#[derive(Debug, Clone, BinRead)]
#[br(little)]
pub struct MocvEntry {
pub b: u8,
pub g: u8,
pub r: u8,
pub a: u8,
}
#[derive(Debug, Clone, BinRead)]
#[br(little)]
pub struct MliqHeader {
pub x_tiles: u32,
pub y_tiles: u32,
pub x_corner: f32,
pub y_corner: f32,
pub liquid_type: u32,
pub material_id: u32,
}
#[derive(Debug, Clone, BinRead)]
#[br(little)]
pub struct MliqVertex {
pub position: [f32; 3],
pub texture_coord: [f32; 2],
}
#[derive(Debug, Clone)]
pub struct Motx {
pub textures: Vec<String>,
pub texture_offset_index_map: HashMap<u32, u32>,
}
impl Motx {
pub fn parse(data: &[u8]) -> Result<Self, Box<dyn std::error::Error>> {
let mut textures = Vec::new();
let mut start = 0;
let mut texture_offset_index_map = HashMap::new();
for i in 0..data.len() {
if data[i] == 0 {
if i > start {
let texture = String::from_utf8(data[start..i].to_vec())?;
textures.push(texture);
texture_offset_index_map.insert(start as u32, textures.len() as u32 - 1);
}
start = i + 1;
}
}
Ok(Self {
textures,
texture_offset_index_map,
})
}
}
#[derive(Debug, Clone)]
pub struct Mosb {
pub skybox: Option<String>,
}
impl Mosb {
pub fn parse(data: &[u8]) -> Result<Self, Box<dyn std::error::Error>> {
if data.is_empty() {
return Ok(Self { skybox: None });
}
let end = data.iter().position(|&b| b == 0).unwrap_or(data.len());
if end > 0 {
let skybox = String::from_utf8(data[..end].to_vec())?;
Ok(Self {
skybox: Some(skybox),
})
} else {
Ok(Self { skybox: None })
}
}
}
#[derive(Debug, Clone, BinRead)]
#[br(little)]
pub struct MopvEntry {
pub x: f32,
pub y: f32,
pub z: f32,
}
#[derive(Debug, Clone, BinRead)]
#[br(little)]
pub struct MoptEntry {
pub start_vertex: u16,
pub n_vertices: u16,
pub normal: MopvEntry, pub distance: f32,
}
#[derive(Debug, Clone, BinRead)]
#[br(little)]
pub struct MoprEntry {
pub portal_index: u16,
pub group_index: u16,
pub side: i16,
pub padding: u16,
}
#[derive(Debug, Clone, BinRead)]
#[br(little)]
pub struct MovvEntry {
pub x: f32,
pub y: f32,
pub z: f32,
}
#[derive(Debug, Clone, BinRead)]
#[br(little)]
pub struct MovbEntry {
pub start_vertex: u16,
pub vertex_count: u16,
}
#[derive(Debug, Clone)]
pub struct Modn {
pub names: Vec<String>,
}
#[derive(Debug, Clone)]
pub struct MomoEntry {
}
#[derive(Debug, Clone)]
pub struct Mom3Entry {
pub data: Vec<u8>,
}
#[derive(Debug, Clone, BinRead)]
#[br(little)]
pub struct MouvEntry {
pub translation_speed: [[f32; 2]; 2], }
#[derive(Debug, Clone, BinRead)]
#[br(little)]
pub struct MopeEntry {
pub portal_index: u32, pub unk1: u32,
pub unk2: u32,
pub unk3: u32,
}
#[derive(Debug, Clone, BinRead)]
#[br(little)]
pub struct MolvEntry {
pub directions: [[f32; 4]; 6], pub unknown: [u8; 3],
pub molt_index: u8,
}
pub type ModiEntry = u32;
pub type MogxEntry = u32;
#[derive(Debug, Clone, BinRead)]
#[br(little)]
pub struct Mpy2Entry {
pub flags: u16,
pub material_id: u16,
}
pub type MovxEntry = u32;
pub type MoqgEntry = u32;
pub type GfidEntry = u32;
pub type MoriEntry = u16;
#[derive(Debug, Clone, BinRead)]
#[br(little)]
pub struct MorbEntry {
pub start_index: u16,
pub index_count: u16,
pub min_index: u16,
pub max_index: u16,
pub flags: u8,
pub material_id: u8,
}
#[derive(Debug, Clone, BinRead)]
#[br(little)]
pub struct MotaEntry {
pub tangent: [i16; 4], }
impl MotaEntry {
pub fn to_float_tangent(&self) -> [f32; 4] {
[
self.tangent[0] as f32 / 32767.0,
self.tangent[1] as f32 / 32767.0,
self.tangent[2] as f32 / 32767.0,
self.tangent[3] as f32 / 32767.0,
]
}
}
#[derive(Debug, Clone, BinRead)]
#[br(little)]
pub struct MobsEntry {
pub start_index: u16,
pub index_count: i16, pub min_index: u16,
pub max_index: u16,
pub flags: u8,
pub material_id: u8,
}
impl Modn {
pub fn parse(data: &[u8]) -> Result<Self, Box<dyn std::error::Error>> {
let mut names = Vec::new();
let mut start = 0;
for i in 0..data.len() {
if data[i] == 0 {
if i > start {
let name = String::from_utf8(data[start..i].to_vec())?;
names.push(name);
}
start = i + 1;
}
}
Ok(Self { names })
}
}