Skip to content

Commit

Permalink
Fix issue caused by unknown chunks causing an error when reading xfbin
Browse files Browse the repository at this point in the history
  • Loading branch information
maxcabd authored Jul 28, 2024
1 parent e44f166 commit a2571fe
Show file tree
Hide file tree
Showing 6 changed files with 105 additions and 187 deletions.
18 changes: 12 additions & 6 deletions src/nucc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,11 @@ impl Clone for Box<dyn NuccStruct> {
let nucc_camera: &NuccCamera = self.downcast_ref().unwrap();
Box::new(nucc_camera.clone()) as Box<dyn NuccStruct>
}

NuccChunkType::NuccChunkUnknown => {
let nucc_unknown: &NuccUnknown = self.downcast_ref().unwrap();
Box::new(nucc_unknown.clone()) as Box<dyn NuccStruct>
}
// Add other cases for the remaining concrete types
_ => panic!("Unsupported NuccStruct type for cloning"),
}
Expand Down Expand Up @@ -292,9 +297,13 @@ impl<'a> FromPyObject<'a> for Box<dyn NuccStruct> {
return Ok(Box::new(nucc_camera));
}

Err(pyo3::exceptions::PyTypeError::new_err(
"Unsupported NuccStruct type for conversion from PyAny",
))
if let Ok(nucc_unknown) = obj.extract::<NuccUnknown>() {
return Ok(Box::new(nucc_unknown));
}

// Add other cases for the remaining concrete types
Err(pyo3::exceptions::PyTypeError::new_err("Unsupported NuccStruct type"))

}
}

Expand Down Expand Up @@ -347,9 +356,6 @@ impl From<NuccChunkConverter> for Box<dyn NuccChunk> {
NuccChunkType::NuccChunkAmbient => { Box::<NuccChunkAmbient>::from(converter) as Box<dyn NuccChunk> }
NuccChunkType::NuccChunkMorphModel => { Box::<NuccChunkMorphModel>::from(converter) as Box<dyn NuccChunk> }
NuccChunkType::NuccChunkUnknown => { Box::<NuccChunkUnknown>::from(converter) as Box<dyn NuccChunk> }



any => panic!("Unexpected NuccChunkType: {any}"),
}
}
Expand Down
100 changes: 57 additions & 43 deletions src/nucc/nucc_anm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ pub struct NuccAnm {
pub is_looped: bool,

#[pyo3(get, set)]
pub other_entries_indices: Vec<u32>,
pub other_entries_indices: Py<PyList>,

#[pyo3(get, set)]
pub unk_entry_indices: Vec<u32>,
Expand All @@ -38,6 +38,48 @@ pub struct NuccAnm {
pub entries: Py<PyList>,
}

#[pymethods]
impl NuccAnm {
#[new]
#[pyo3(signature = (struct_info = None, version = 121, frame_count = 0, is_looped = false, other_entries_indices = None, unk_entry_indices = None, clumps = None, coord_parents = None, entries = None))]
pub fn __new__(
py: Python,
struct_info: Option<NuccStructInfo>,
version: u16,
frame_count: u32,
is_looped: bool,
other_entries_indices: Option<Py<PyList>>,
unk_entry_indices: Option<Vec<u32>>,
clumps: Option<Py<PyList>>,
coord_parents: Option<Py<PyList>>,
entries: Option<Py<PyList>>,
) -> Self {
Self {
struct_info: struct_info.unwrap_or_default(),
version,
frame_count,
is_looped,
other_entries_indices: other_entries_indices.unwrap_or(PyList::empty_bound(py).into()),
unk_entry_indices: unk_entry_indices.unwrap_or_default(),
clumps: clumps.unwrap_or(PyList::empty_bound(py).into()),
coord_parents: coord_parents.unwrap_or(PyList::empty_bound(py).into()),
entries: entries.unwrap_or(PyList::empty_bound(py).into()),
}
}

fn __repr__(&self) -> PyResult<String> {
Ok(format!(
"NuccAnm(struct_info={:?}, version={}, frame_count={}, is_looped={}, other_entries_indices={:?}, unk_entry_indices={:?} clumps={:?}, coord_parents={:?}, entries={:?})",
self.struct_info, self.version, self.frame_count, self.is_looped, self.other_entries_indices, self.unk_entry_indices, self.clumps, self.coord_parents, self.entries
))
}

fn __str__(&self) -> PyResult<String> {
self.__repr__()
}

}

#[derive(Debug, Clone)]
#[pyclass(name = "AnmEntry")]
pub struct Entry {
Expand Down Expand Up @@ -129,47 +171,7 @@ impl Track {

}

#[pymethods]
impl NuccAnm {
#[new]
#[pyo3(signature = (struct_info = None, version = 121, frame_count = 0, is_looped = false, other_entries_indices = None, unk_entry_indices = None, clumps = None, coord_parents = None, entries = None))]
pub fn __new__(
py: Python,
struct_info: Option<NuccStructInfo>,
version: u16,
frame_count: u32,
is_looped: bool,
other_entries_indices: Option<Vec<u32>>,
unk_entry_indices: Option<Vec<u32>>,
clumps: Option<Py<PyList>>,
coord_parents: Option<Py<PyList>>,
entries: Option<Py<PyList>>,
) -> Self {
Self {
struct_info: struct_info.unwrap_or_default(),
version,
frame_count,
is_looped,
other_entries_indices: other_entries_indices.unwrap_or_default(),
unk_entry_indices: unk_entry_indices.unwrap_or_default(),
clumps: clumps.unwrap_or(PyList::empty_bound(py).into()),
coord_parents: coord_parents.unwrap_or(PyList::empty_bound(py).into()),
entries: entries.unwrap_or(PyList::empty_bound(py).into()),
}
}

fn __repr__(&self) -> PyResult<String> {
Ok(format!(
"NuccAnm(struct_info={:?}, version={}, frame_count={}, is_looped={}, other_entries_indices={:?}, unk_entry_indices={:?} clumps={:?}, coord_parents={:?}, entries={:?})",
self.struct_info, self.version, self.frame_count, self.is_looped, self.other_entries_indices, self.unk_entry_indices, self.clumps, self.coord_parents, self.entries
))
}

fn __str__(&self) -> PyResult<String> {
self.__repr__()
}

}

impl_nucc_info!(NuccAnm, struct_info);

Expand All @@ -186,6 +188,14 @@ impl From<NuccStructConverter> for NuccAnm {
.map(|c| *c)
.ok()
.unwrap();

let other_entries_indices: Py<PyList> = Python::with_gil(|py| {
let other_entries_indices: Vec<PyObject> = chunk.other_entries_indices.iter().map(|&value| {
value.into_py(py)
}).collect();

PyList::new_bound(py, other_entries_indices).into()
});


let clumps: Py<PyList> = Python::with_gil(|py| {
Expand Down Expand Up @@ -261,7 +271,7 @@ impl From<NuccStructConverter> for NuccAnm {
frame_count: chunk.frame_count,
is_looped: chunk.is_looped == 1,
clumps,
other_entries_indices: chunk.other_entries_indices,
other_entries_indices,
unk_entry_indices: chunk.unk_entry_indices,
coord_parents,
entries,
Expand All @@ -279,6 +289,10 @@ impl From<NuccChunkConverter> for Box<NuccChunkAnm> {

let anm = nucc_struct.downcast::<NuccAnm>().map(|s| *s).ok().unwrap();

let other_entries_indices: Vec<u32> = Python::with_gil(|py| {
anm.other_entries_indices.extract(py).unwrap()
});

let clumps: Vec<AnmClump> = Python::with_gil(|py| {
anm.clumps.extract(py).unwrap()
});
Expand Down Expand Up @@ -320,7 +334,7 @@ impl From<NuccChunkConverter> for Box<NuccChunkAnm> {
chunk.frame_count = anm.frame_count;
chunk.is_looped = if anm.is_looped { 1 } else { 0 };
chunk.clumps = clumps;
chunk.other_entries_indices = anm.other_entries_indices;
chunk.other_entries_indices = other_entries_indices;
chunk.unk_entry_indices = anm.unk_entry_indices;
chunk.coord_parents = coord_parents;
chunk.entries = anm_entries;
Expand Down
1 change: 1 addition & 0 deletions src/nucc/nucc_unknown.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use super::*;
use pyo3::prelude::*;

#[pyclass]
#[derive(Debug, Clone)]
pub struct NuccUnknown {
pub struct_info: NuccStructInfo,
pub version: u16,
Expand Down
16 changes: 5 additions & 11 deletions src/nucc_chunk/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,7 @@ pub trait NuccChunk: Downcast + fmt::Debug {

// set the version of the chunk
Ok((input.into(), Box::new(result) as Box<dyn NuccChunk>))



}

fn write_boxed(
Expand Down Expand Up @@ -94,9 +93,6 @@ pub enum NuccChunkType {
NuccChunkAmbient,
NuccChunkMorphModel,
NuccChunkUnknown,



}

impl Default for NuccChunkType {
Expand All @@ -116,7 +112,6 @@ impl NuccChunkType {
NuccChunkType::NuccChunkPage => NuccChunkPage::read_boxed(&data, version),
NuccChunkType::NuccChunkIndex => Ok((data, Box::new(NuccChunkIndex))),
NuccChunkType::NuccChunkBinary => NuccChunkBinary::read_boxed(&data, version),

NuccChunkType::NuccChunkAnm => NuccChunkAnm::read_boxed(&data, version), // Fix: Change `u16` to `()`
NuccChunkType::NuccChunkAnmStrm => NuccChunkAnmStrm::read_boxed(&data, version),
NuccChunkType::NuccChunkAnmStrmFrame => { NuccChunkAnmStrmFrame::read_boxed(&data, version)}
Expand All @@ -126,9 +121,8 @@ impl NuccChunkType {
NuccChunkType::NuccChunkLayerSet => NuccChunkLayerSet::read_boxed(&data, version),
NuccChunkType::NuccChunkAmbient => NuccChunkAmbient::read_boxed(&data, version),
NuccChunkType::NuccChunkMorphModel => NuccChunkMorphModel::read_boxed(&data, version),


NuccChunkType::NuccChunkUnknown => Ok((
// If the chunk type is unknown, return the data as an unknown chunk
_ => Ok((
data.clone(),
Box::new(NuccChunkUnknown {
version,
Expand Down Expand Up @@ -157,8 +151,8 @@ impl NuccChunkType {
NuccChunkType::NuccChunkLayerSet => { NuccChunkLayerSet::write_boxed(boxed, &mut output, version)?; }
NuccChunkType::NuccChunkAmbient => { NuccChunkAmbient::write_boxed(boxed, &mut output, version)?; }
NuccChunkType::NuccChunkMorphModel => { NuccChunkMorphModel::write_boxed(boxed, &mut output, version)?; }

NuccChunkType::NuccChunkUnknown => {
// If the chunk type is unknown, return the data as an unknown chunk
_ => {
let unknown = boxed
.downcast::<NuccChunkUnknown>()
.map(|x| x.data)
Expand Down
103 changes: 11 additions & 92 deletions src/nucc_chunk/nucc_chunk_anm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -425,20 +425,22 @@ fn read_track_data<R: Read + Seek>(
keyframes.push(NuccAnmKey::Vec4Linear { frame, values: (x, y, z, w) });
}



NuccAnmKeyFormat::FloatFixed => {
let x = reader.read_be::<f32>()?;
keyframes.push(NuccAnmKey::Float { values: x });
}

NuccAnmKeyFormat::FloatTable => {
let x = reader.read_be::<f32>()?;
keyframes.push(NuccAnmKey::Float { values: x });
}

NuccAnmKeyFormat::FloatLinear => {
let frame = reader.read_be::<i32>()?;
let x = reader.read_be::<f32>()?;
keyframes.push(NuccAnmKey::FloatLinear { frame, values: x });
}


NuccAnmKeyFormat::OpacityShortTable => {
let x = reader.read_be::<i16>()?;
keyframes.push(NuccAnmKey::I16Vec { values: x });
Expand All @@ -457,101 +459,20 @@ fn read_track_data<R: Read + Seek>(
let b = reader.read_be::<u8>()?;
keyframes.push(NuccAnmKey::Color { values: (r, g, b) });
}



_ => todo!(),
// Return an error saying that the key format is not supported and the key format itself
_ => {

dbg!(format!("Key format {:?} is not supported", header.key_format));
}
}






}

Ok(keyframes)
}


fn write_fcurve_data<R: Write + Seek>(
anm_key: NuccAnmKeyFormat,
values: NuccAnmKey,
writer: &mut R,
wo: &WriteOptions,

_: ()
) -> BinResult<()> {

match (anm_key, values) {
(NuccAnmKeyFormat::Vector3Fixed, NuccAnmKey::Vec3 { values }) |
(NuccAnmKeyFormat::EulerXYZFixed, NuccAnmKey::Vec3 { values }) |
(NuccAnmKeyFormat::Vector3Table, NuccAnmKey::Vec3 { values }) => {
values.0.write_options(writer, wo, ())?;
values.1.write_options(writer, wo, ())?;
values.2.write_options(writer, wo, ())?;
}

(NuccAnmKeyFormat::Vector3Linear, NuccAnmKey::Vec3Linear { frame, values }) => {
frame.write_options(writer, wo, ())?;
values.0.write_options(writer, wo, ())?;
values.1.write_options(writer, wo, ())?;
values.2.write_options(writer, wo, ())?;
}

(NuccAnmKeyFormat::QuaternionLinear, NuccAnmKey::Vec4Linear { frame, values }) => {
frame.write_options(writer, wo, ())?;
values.0.write_options(writer, wo, ())?;
values.1.write_options(writer, wo, ())?;
values.2.write_options(writer, wo, ())?;
values.3.write_options(writer, wo, ())?;
}

(NuccAnmKeyFormat::FloatFixed, NuccAnmKey::Float { values }) |
(NuccAnmKeyFormat::FloatTable, NuccAnmKey::Float { values}) |
(NuccAnmKeyFormat::FloatTableNoInterp, NuccAnmKey::Float { values}) => {
values.write_options(writer, wo, ())?;
}

(NuccAnmKeyFormat::FloatLinear, NuccAnmKey::FloatLinear { frame, values }) => {
frame.write_options(writer, wo, ())?;
values.write_options(writer, wo, ())?;
}

(NuccAnmKeyFormat::OpacityShortTable, NuccAnmKey::I16Vec { values }) |
(NuccAnmKeyFormat::OpacityShortTableNoInterp, NuccAnmKey::I16Vec { values }) => {
values.write_options(writer, wo, ())?;
}

(NuccAnmKeyFormat::ScaleShortTable, NuccAnmKey::I16Vec3 { values }) => {
values.0.write_options(writer, wo, ())?;
values.1.write_options(writer, wo, ())?;
values.2.write_options(writer, wo, ())?;
}

(NuccAnmKeyFormat::QuaternionShortTable, NuccAnmKey::ShortVec4 { values }) |
(NuccAnmKeyFormat::QuaternionShortTableNoInterp, NuccAnmKey::ShortVec4 { values }) => {
values.0.write_options(writer, wo, ())?;
values.1.write_options(writer, wo, ())?;
values.2.write_options(writer, wo, ())?;
values.3.write_options(writer, wo, ())?;
}

(NuccAnmKeyFormat::ColorRGBTable, NuccAnmKey::Color { values }) => {
values.0.write_options(writer, wo, ())?;
values.1.write_options(writer, wo, ())?;
values.2.write_options(writer, wo, ())?;
}
// Handle other NuccAnmKeyFormat cases and Keyframe variants...
_ => todo!(),
}

Ok(())
}




impl NuccChunk for NuccChunkAnm {
fn chunk_type(&self) -> NuccChunkType {
NuccChunkType::NuccChunkAnm
Expand All @@ -560,6 +481,4 @@ impl NuccChunk for NuccChunkAnm {
fn version(&self) -> u16 {
self.version
}


}
}
Loading

0 comments on commit a2571fe

Please sign in to comment.