186 lines
6.0 KiB
Rust
186 lines
6.0 KiB
Rust
#![allow(dead_code)]
|
|
|
|
use std::result::Result;
|
|
|
|
use nom::{call, closure, tuple, tuple_parser, IResult};
|
|
|
|
use mem_arena::MemArena;
|
|
|
|
use crate::{
|
|
color::{rec709_e_to_xyz, Color},
|
|
light::{DistantDiskLight, RectangleLight, SphereLight},
|
|
math::Vector,
|
|
};
|
|
|
|
use super::{
|
|
basics::ws_f32,
|
|
psy::{parse_color, PsyParseError},
|
|
DataTree,
|
|
};
|
|
|
|
pub fn parse_distant_disk_light<'a>(
|
|
arena: &'a MemArena,
|
|
tree: &'a DataTree,
|
|
) -> Result<DistantDiskLight<'a>, PsyParseError> {
|
|
if let DataTree::Internal { ref children, .. } = *tree {
|
|
let mut radii = Vec::new();
|
|
let mut directions = Vec::new();
|
|
let mut colors = Vec::new();
|
|
|
|
// Parse
|
|
for child in children.iter() {
|
|
match *child {
|
|
// Radius
|
|
DataTree::Leaf {
|
|
type_name,
|
|
contents,
|
|
byte_offset,
|
|
} if type_name == "Radius" => {
|
|
if let IResult::Done(_, radius) = ws_f32(contents.as_bytes()) {
|
|
radii.push(radius);
|
|
} else {
|
|
// Found radius, but its contents is not in the right format
|
|
return Err(PsyParseError::UnknownError(byte_offset));
|
|
}
|
|
}
|
|
|
|
// Direction
|
|
DataTree::Leaf {
|
|
type_name,
|
|
contents,
|
|
byte_offset,
|
|
} if type_name == "Direction" => {
|
|
if let IResult::Done(_, direction) =
|
|
closure!(tuple!(ws_f32, ws_f32, ws_f32))(contents.as_bytes())
|
|
{
|
|
directions.push(Vector::new(direction.0, direction.1, direction.2));
|
|
} else {
|
|
// Found direction, but its contents is not in the right format
|
|
return Err(PsyParseError::UnknownError(byte_offset));
|
|
}
|
|
}
|
|
|
|
// Color
|
|
DataTree::Leaf {
|
|
type_name,
|
|
contents,
|
|
byte_offset,
|
|
} if type_name == "Color" => {
|
|
if let Ok(color) = parse_color(contents) {
|
|
colors.push(color);
|
|
} else {
|
|
// Found color, but its contents is not in the right format
|
|
return Err(PsyParseError::UnknownError(byte_offset));
|
|
}
|
|
}
|
|
|
|
_ => {}
|
|
}
|
|
}
|
|
|
|
return Ok(DistantDiskLight::new(arena, &radii, &directions, &colors));
|
|
} else {
|
|
return Err(PsyParseError::UnknownError(tree.byte_offset()));
|
|
}
|
|
}
|
|
|
|
pub fn parse_sphere_light<'a>(
|
|
arena: &'a MemArena,
|
|
tree: &'a DataTree,
|
|
) -> Result<SphereLight<'a>, PsyParseError> {
|
|
if let DataTree::Internal { ref children, .. } = *tree {
|
|
let mut radii = Vec::new();
|
|
let mut colors = Vec::new();
|
|
|
|
// Parse
|
|
for child in children.iter() {
|
|
match *child {
|
|
// Radius
|
|
DataTree::Leaf {
|
|
type_name,
|
|
contents,
|
|
byte_offset,
|
|
} if type_name == "Radius" => {
|
|
if let IResult::Done(_, radius) = ws_f32(contents.as_bytes()) {
|
|
radii.push(radius);
|
|
} else {
|
|
// Found radius, but its contents is not in the right format
|
|
return Err(PsyParseError::UnknownError(byte_offset));
|
|
}
|
|
}
|
|
|
|
// Color
|
|
DataTree::Leaf {
|
|
type_name,
|
|
contents,
|
|
byte_offset,
|
|
} if type_name == "Color" => {
|
|
if let Ok(color) = parse_color(contents) {
|
|
colors.push(color);
|
|
} else {
|
|
// Found color, but its contents is not in the right format
|
|
return Err(PsyParseError::UnknownError(byte_offset));
|
|
}
|
|
}
|
|
|
|
_ => {}
|
|
}
|
|
}
|
|
|
|
return Ok(SphereLight::new(arena, &radii, &colors));
|
|
} else {
|
|
return Err(PsyParseError::UnknownError(tree.byte_offset()));
|
|
}
|
|
}
|
|
|
|
pub fn parse_rectangle_light<'a>(
|
|
arena: &'a MemArena,
|
|
tree: &'a DataTree,
|
|
) -> Result<RectangleLight<'a>, PsyParseError> {
|
|
if let DataTree::Internal { ref children, .. } = *tree {
|
|
let mut dimensions = Vec::new();
|
|
let mut colors = Vec::new();
|
|
|
|
// Parse
|
|
for child in children.iter() {
|
|
match *child {
|
|
// Dimensions
|
|
DataTree::Leaf {
|
|
type_name,
|
|
contents,
|
|
byte_offset,
|
|
} if type_name == "Dimensions" => {
|
|
if let IResult::Done(_, radius) =
|
|
closure!(tuple!(ws_f32, ws_f32))(contents.as_bytes())
|
|
{
|
|
dimensions.push(radius);
|
|
} else {
|
|
// Found dimensions, but its contents is not in the right format
|
|
return Err(PsyParseError::UnknownError(byte_offset));
|
|
}
|
|
}
|
|
|
|
// Color
|
|
DataTree::Leaf {
|
|
type_name,
|
|
contents,
|
|
byte_offset,
|
|
} if type_name == "Color" => {
|
|
if let Ok(color) = parse_color(contents) {
|
|
colors.push(color);
|
|
} else {
|
|
// Found color, but its contents is not in the right format
|
|
return Err(PsyParseError::UnknownError(byte_offset));
|
|
}
|
|
}
|
|
|
|
_ => {}
|
|
}
|
|
}
|
|
|
|
return Ok(RectangleLight::new(arena, &dimensions, &colors));
|
|
} else {
|
|
return Err(PsyParseError::UnknownError(tree.byte_offset()));
|
|
}
|
|
}
|