psychopath/src/parse/psy_light.rs

199 lines
6.9 KiB
Rust

#![allow(dead_code)]
use std::result::Result;
use nom::IResult;
use mem_arena::MemArena;
use math::Vector;
use color::{XYZ, rec709_e_to_xyz};
use light::{DistantDiskLight, SphereLight, RectangleLight};
use super::basics::ws_f32;
use super::DataTree;
use super::psy::PsyParseError;
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 IResult::Done(_, color) =
closure!(tuple!(ws_f32, ws_f32, ws_f32))(contents.as_bytes())
{
// TODO: handle color space conversions properly.
// Probably will need a special color type with its
// own parser...?
colors.push(XYZ::from_tuple(rec709_e_to_xyz(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 IResult::Done(_, color) =
closure!(tuple!(ws_f32, ws_f32, ws_f32))(contents.as_bytes())
{
// TODO: handle color space conversions properly.
// Probably will need a special color type with its
// own parser...?
colors.push(XYZ::from_tuple(rec709_e_to_xyz(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 IResult::Done(_, color) =
closure!(tuple!(ws_f32, ws_f32, ws_f32))(contents.as_bytes())
{
// TODO: handle color space conversions properly.
// Probably will need a special color type with its
// own parser...?
colors.push(XYZ::from_tuple(rec709_e_to_xyz(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()));
}
}