mirror of
https://github.com/PrimeDecomp/retrotool.git
synced 2026-07-12 18:18:58 -07:00
Add support for viewing WMDL and SMDL files
This commit is contained in:
+20
-3
@@ -14,9 +14,15 @@ use crate::{
|
||||
|
||||
// Cooked model
|
||||
pub const K_FORM_CMDL: FourCC = FourCC(*b"CMDL");
|
||||
pub const K_FORM_SMDL: FourCC = FourCC(*b"SMDL");
|
||||
pub const K_FORM_WMDL: FourCC = FourCC(*b"WMDL");
|
||||
|
||||
// Model header
|
||||
pub const K_CHUNK_HEAD: FourCC = FourCC(*b"HEAD");
|
||||
// World header
|
||||
pub const K_CHUNK_WDHD: FourCC = FourCC(*b"WDHD");
|
||||
// Skinned header
|
||||
pub const K_CHUNK_SKHD: FourCC = FourCC(*b"SKHD");
|
||||
// Material data
|
||||
pub const K_CHUNK_MTRL: FourCC = FourCC(*b"MTRL");
|
||||
// Mesh data
|
||||
@@ -776,9 +782,18 @@ pub struct ModelData {
|
||||
impl ModelData {
|
||||
pub fn slice(data: &[u8], meta: &[u8], e: Endian) -> Result<ModelData> {
|
||||
let (cmdl_desc, mut cmdl_data, _) = FormDescriptor::slice(data, Endian::Little)?;
|
||||
ensure!(cmdl_desc.id == K_FORM_CMDL);
|
||||
ensure!(cmdl_desc.version_a == 114);
|
||||
ensure!(cmdl_desc.version_b == 125);
|
||||
ensure!(cmdl_desc.id == K_FORM_CMDL || cmdl_desc.id == K_FORM_SMDL || cmdl_desc.id == K_FORM_WMDL);
|
||||
if cmdl_desc.id == K_FORM_CMDL {
|
||||
ensure!(cmdl_desc.version_a == 114);
|
||||
ensure!(cmdl_desc.version_b == 125);
|
||||
} else if cmdl_desc.id == K_FORM_SMDL {
|
||||
ensure!(cmdl_desc.version_a == 127);
|
||||
ensure!(cmdl_desc.version_b == 133);
|
||||
} else if cmdl_desc.id == K_FORM_WMDL {
|
||||
ensure!(cmdl_desc.version_a == 118);
|
||||
ensure!(cmdl_desc.version_b == 124);
|
||||
}
|
||||
|
||||
|
||||
let meta: SModelMetaData = Cursor::new(meta).read_type(e)?;
|
||||
let vtx_buffers = decompress_gpu_buffers(data, &meta.read_info, &meta.vtx_buffer_info)?;
|
||||
@@ -792,6 +807,8 @@ impl ModelData {
|
||||
while !cmdl_data.is_empty() {
|
||||
let (chunk_desc, chunk_data, remain) = ChunkDescriptor::slice(cmdl_data, e)?;
|
||||
match chunk_desc.id {
|
||||
K_CHUNK_WDHD => head = Some(Cursor::new(chunk_data).read_type(e)?),
|
||||
K_CHUNK_SKHD => head = Some(Cursor::new(chunk_data).read_type(e)?),
|
||||
K_CHUNK_HEAD => head = Some(Cursor::new(chunk_data).read_type(e)?),
|
||||
K_CHUNK_MTRL => mtrl = Some(Cursor::new(chunk_data).read_type(e)?),
|
||||
K_CHUNK_MESH => mesh = Some(Cursor::new(chunk_data).read_type(e)?),
|
||||
|
||||
@@ -297,7 +297,7 @@ impl AssetLoader for ModelAssetLoader {
|
||||
})
|
||||
}
|
||||
|
||||
fn extensions(&self) -> &[&str] { &["cmdl"] }
|
||||
fn extensions(&self) -> &[&str] { &["cmdl", "smdl", "wmdl"] }
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, bevy::reflect::TypeUuid)]
|
||||
|
||||
@@ -3,7 +3,7 @@ use bevy::{
|
||||
prelude::*,
|
||||
};
|
||||
use egui::{text::LayoutJob, Color32, TextFormat, Widget};
|
||||
use retrolib::format::{cmdl::K_FORM_CMDL, txtr::K_FORM_TXTR, FourCC};
|
||||
use retrolib::format::{cmdl::{K_FORM_CMDL, K_FORM_SMDL, K_FORM_WMDL}, txtr::K_FORM_TXTR, FourCC};
|
||||
|
||||
use crate::{
|
||||
icon,
|
||||
@@ -41,7 +41,7 @@ impl SystemTab for ProjectTab {
|
||||
"{} {} {}",
|
||||
match entry.kind {
|
||||
K_FORM_TXTR => icon::TEXTURE,
|
||||
K_FORM_CMDL => icon::FILE_3D,
|
||||
K_FORM_CMDL | K_FORM_SMDL | K_FORM_WMDL => icon::FILE_3D,
|
||||
K_FORM_FMV0 => icon::FILE_MOVIE,
|
||||
K_FORM_ROOM => icon::SCENE_DATA,
|
||||
_ => icon::FILE,
|
||||
@@ -77,7 +77,7 @@ impl SystemTab for ProjectTab {
|
||||
loaded_texture: None,
|
||||
}));
|
||||
}
|
||||
K_FORM_CMDL => {
|
||||
K_FORM_CMDL | K_FORM_SMDL | K_FORM_WMDL => {
|
||||
let handle = server
|
||||
.load::<ModelAsset, _>(format!("{}.{}", entry.id, entry.kind));
|
||||
state.open_tab = Some(TabType::Model(ModelTab {
|
||||
|
||||
Reference in New Issue
Block a user