189 lines
7.0 KiB
Rust
189 lines
7.0 KiB
Rust
#![allow(dead_code)]
|
|
|
|
use std::result::Result;
|
|
|
|
use kioku::Arena;
|
|
|
|
use crate::scene::{Assembly, AssemblyBuilder, Object};
|
|
|
|
use super::{
|
|
psy::{parse_matrix, PsyParseError},
|
|
psy_light::{parse_rectangle_light, parse_sphere_light},
|
|
psy_mesh_surface::parse_mesh_surface,
|
|
psy_surface_shader::parse_surface_shader,
|
|
DataTree,
|
|
};
|
|
|
|
pub fn parse_assembly<'a>(
|
|
arena: &'a Arena,
|
|
tree: &'a DataTree,
|
|
) -> Result<Assembly<'a>, PsyParseError> {
|
|
let mut builder = AssemblyBuilder::new(arena);
|
|
|
|
if tree.is_internal() {
|
|
for child in tree.iter_children() {
|
|
match child.type_name() {
|
|
// Sub-Assembly
|
|
"Assembly" => {
|
|
if let DataTree::Internal {
|
|
ident: Some(ident), ..
|
|
} = *child
|
|
{
|
|
builder.add_assembly(ident, parse_assembly(arena, child)?);
|
|
} else {
|
|
return Err(PsyParseError::UnknownError(child.byte_offset()));
|
|
}
|
|
}
|
|
|
|
// Instance
|
|
"Instance" => {
|
|
// Pre-conditions
|
|
if !child.is_internal() {
|
|
return Err(PsyParseError::UnknownError(child.byte_offset()));
|
|
}
|
|
|
|
// Get data name
|
|
let name = {
|
|
if child.iter_leaf_children_with_type("Data").count() != 1 {
|
|
return Err(PsyParseError::UnknownError(child.byte_offset()));
|
|
}
|
|
child.iter_leaf_children_with_type("Data").nth(0).unwrap().1
|
|
};
|
|
|
|
// Get surface shader binding, if any.
|
|
let surface_shader_name = if child
|
|
.iter_leaf_children_with_type("SurfaceShaderBind")
|
|
.count()
|
|
> 0
|
|
{
|
|
Some(
|
|
child
|
|
.iter_leaf_children_with_type("SurfaceShaderBind")
|
|
.nth(0)
|
|
.unwrap()
|
|
.1,
|
|
)
|
|
} else {
|
|
None
|
|
};
|
|
|
|
// Get xforms
|
|
let mut xforms = Vec::new();
|
|
for (_, contents, _) in child.iter_leaf_children_with_type("Transform") {
|
|
xforms.push(parse_matrix(contents)?);
|
|
}
|
|
|
|
// Add instance
|
|
if builder.name_exists(name) {
|
|
builder.add_instance(name, surface_shader_name, Some(&xforms));
|
|
} else {
|
|
return Err(PsyParseError::InstancedMissingData(
|
|
child.iter_leaf_children_with_type("Data").nth(0).unwrap().2,
|
|
"Attempted to add \
|
|
instance for data with \
|
|
a name that doesn't \
|
|
exist.",
|
|
name.to_string(),
|
|
));
|
|
}
|
|
}
|
|
|
|
// SurfaceShader
|
|
"SurfaceShader" => {
|
|
if let DataTree::Internal {
|
|
ident: Some(ident), ..
|
|
} = *child
|
|
{
|
|
builder.add_surface_shader(ident, parse_surface_shader(arena, child)?);
|
|
} else {
|
|
// TODO: error condition of some kind, because no ident
|
|
panic!(
|
|
"SurfaceShader encountered that was a leaf, but SurfaceShaders cannot \
|
|
be a leaf: {}",
|
|
child.byte_offset()
|
|
);
|
|
}
|
|
}
|
|
|
|
// MeshSurface
|
|
"MeshSurface" => {
|
|
if let DataTree::Internal {
|
|
ident: Some(ident), ..
|
|
} = *child
|
|
{
|
|
builder.add_object(
|
|
ident,
|
|
Object::Surface(arena.alloc(parse_mesh_surface(arena, child)?)),
|
|
);
|
|
} else {
|
|
// TODO: error condition of some kind, because no ident
|
|
panic!(
|
|
"MeshSurface encountered that was a leaf, but MeshSurfaces cannot \
|
|
be a leaf: {}",
|
|
child.byte_offset()
|
|
);
|
|
}
|
|
}
|
|
|
|
// Sphere Light
|
|
"SphereLight" => {
|
|
if let DataTree::Internal {
|
|
ident: Some(ident), ..
|
|
} = *child
|
|
{
|
|
builder.add_object(
|
|
ident,
|
|
Object::SurfaceLight(arena.alloc(parse_sphere_light(arena, child)?)),
|
|
);
|
|
} else {
|
|
// No ident
|
|
return Err(PsyParseError::UnknownError(child.byte_offset()));
|
|
}
|
|
}
|
|
|
|
// Rectangle Light
|
|
"RectangleLight" => {
|
|
if let DataTree::Internal {
|
|
ident: Some(ident), ..
|
|
} = *child
|
|
{
|
|
builder.add_object(
|
|
ident,
|
|
Object::SurfaceLight(arena.alloc(parse_rectangle_light(arena, child)?)),
|
|
);
|
|
} else {
|
|
// No ident
|
|
return Err(PsyParseError::UnknownError(child.byte_offset()));
|
|
}
|
|
}
|
|
|
|
_ => {
|
|
// TODO: some kind of error, because not a known type name
|
|
} // // Bilinear Patch
|
|
// "BilinearPatch" => {
|
|
// assembly->add_object(child.name, parse_bilinear_patch(child));
|
|
// }
|
|
//
|
|
// // Bicubic Patch
|
|
// else if (child.type == "BicubicPatch") {
|
|
// assembly->add_object(child.name, parse_bicubic_patch(child));
|
|
// }
|
|
//
|
|
// // Subdivision surface
|
|
// else if (child.type == "SubdivisionSurface") {
|
|
// assembly->add_object(child.name, parse_subdivision_surface(child));
|
|
// }
|
|
//
|
|
// // Sphere
|
|
// else if (child.type == "Sphere") {
|
|
// assembly->add_object(child.name, parse_sphere(child));
|
|
// }
|
|
}
|
|
}
|
|
} else {
|
|
return Err(PsyParseError::UnknownError(tree.byte_offset()));
|
|
}
|
|
|
|
return Ok(builder.build());
|
|
}
|