191 lines
5.4 KiB
Rust
191 lines
5.4 KiB
Rust
#![allow(dead_code)]
|
|
|
|
use std::{io::BufRead, result::Result};
|
|
|
|
use nom::{combinator::all_consuming, sequence::tuple, IResult};
|
|
|
|
use kioku::Arena;
|
|
|
|
use data_tree::{DataTreeReader, Event};
|
|
|
|
use crate::{
|
|
light::{DistantDiskLight, RectangleLight, SphereLight},
|
|
math::Vector,
|
|
};
|
|
|
|
use super::{
|
|
parse_utils::ws_f32,
|
|
psy::{parse_color, PsyError, PsyResult},
|
|
};
|
|
|
|
pub fn parse_distant_disk_light<'a>(
|
|
arena: &'a Arena,
|
|
events: &mut DataTreeReader<impl BufRead>,
|
|
_ident: Option<&str>,
|
|
) -> PsyResult<DistantDiskLight<'a>> {
|
|
let mut radii = Vec::new();
|
|
let mut directions = Vec::new();
|
|
let mut colors = Vec::new();
|
|
|
|
// Parse
|
|
loop {
|
|
match events.next_event()? {
|
|
Event::Leaf {
|
|
type_name: "Radius",
|
|
contents,
|
|
byte_offset,
|
|
} => {
|
|
if let IResult::Ok((_, radius)) = all_consuming(ws_f32)(&contents) {
|
|
radii.push(radius);
|
|
} else {
|
|
// Found radius, but its contents is not in the right format
|
|
return Err(PsyError::UnknownError(byte_offset));
|
|
}
|
|
}
|
|
|
|
// Direction
|
|
Event::Leaf {
|
|
type_name: "Direction",
|
|
contents,
|
|
byte_offset,
|
|
} => {
|
|
if let IResult::Ok((_, direction)) =
|
|
all_consuming(tuple((ws_f32, ws_f32, ws_f32)))(&contents)
|
|
{
|
|
directions.push(Vector::new(direction.0, direction.1, direction.2));
|
|
} else {
|
|
// Found direction, but its contents is not in the right format
|
|
return Err(PsyError::UnknownError(byte_offset));
|
|
}
|
|
}
|
|
|
|
// Color
|
|
Event::Leaf {
|
|
type_name: "Color",
|
|
contents,
|
|
byte_offset,
|
|
} => {
|
|
if let Ok(color) = parse_color(&contents) {
|
|
colors.push(color);
|
|
} else {
|
|
// Found color, but its contents is not in the right format
|
|
return Err(PsyError::UnknownError(byte_offset));
|
|
}
|
|
}
|
|
|
|
Event::InnerClose { .. } => {
|
|
break;
|
|
}
|
|
|
|
_ => {
|
|
todo!(); // Return error.
|
|
}
|
|
}
|
|
}
|
|
|
|
return Ok(DistantDiskLight::new(arena, &radii, &directions, &colors));
|
|
}
|
|
|
|
pub fn parse_sphere_light<'a>(
|
|
arena: &'a Arena,
|
|
events: &mut DataTreeReader<impl BufRead>,
|
|
) -> Result<SphereLight<'a>, PsyError> {
|
|
let mut radii = Vec::new();
|
|
let mut colors = Vec::new();
|
|
|
|
// Parse
|
|
loop {
|
|
match events.next_event()? {
|
|
// Radius
|
|
Event::Leaf {
|
|
type_name: "Radius",
|
|
contents,
|
|
byte_offset,
|
|
} => {
|
|
if let IResult::Ok((_, radius)) = all_consuming(ws_f32)(&contents) {
|
|
radii.push(radius);
|
|
} else {
|
|
// Found radius, but its contents is not in the right format
|
|
return Err(PsyError::UnknownError(byte_offset));
|
|
}
|
|
}
|
|
|
|
// Color
|
|
Event::Leaf {
|
|
type_name: "Color",
|
|
contents,
|
|
byte_offset,
|
|
} => {
|
|
if let Ok(color) = parse_color(&contents) {
|
|
colors.push(color);
|
|
} else {
|
|
// Found color, but its contents is not in the right format
|
|
return Err(PsyError::UnknownError(byte_offset));
|
|
}
|
|
}
|
|
|
|
Event::InnerClose { .. } => {
|
|
break;
|
|
}
|
|
|
|
_ => {
|
|
todo!(); // Return error.
|
|
}
|
|
}
|
|
}
|
|
|
|
return Ok(SphereLight::new(arena, &radii, &colors));
|
|
}
|
|
|
|
pub fn parse_rectangle_light<'a>(
|
|
arena: &'a Arena,
|
|
events: &mut DataTreeReader<impl BufRead>,
|
|
) -> Result<RectangleLight<'a>, PsyError> {
|
|
let mut dimensions = Vec::new();
|
|
let mut colors = Vec::new();
|
|
|
|
// Parse
|
|
loop {
|
|
match events.next_event()? {
|
|
// Dimensions
|
|
Event::Leaf {
|
|
type_name: "Dimensions",
|
|
contents,
|
|
byte_offset,
|
|
} => {
|
|
if let IResult::Ok((_, radius)) = all_consuming(tuple((ws_f32, ws_f32)))(&contents)
|
|
{
|
|
dimensions.push(radius);
|
|
} else {
|
|
// Found dimensions, but its contents is not in the right format
|
|
return Err(PsyError::UnknownError(byte_offset));
|
|
}
|
|
}
|
|
|
|
// Color
|
|
Event::Leaf {
|
|
type_name: "Color",
|
|
contents,
|
|
byte_offset,
|
|
} => {
|
|
if let Ok(color) = parse_color(&contents) {
|
|
colors.push(color);
|
|
} else {
|
|
// Found color, but its contents is not in the right format
|
|
return Err(PsyError::UnknownError(byte_offset));
|
|
}
|
|
}
|
|
|
|
Event::InnerClose { .. } => {
|
|
break;
|
|
}
|
|
|
|
_ => {
|
|
todo!(); // Return error.
|
|
}
|
|
}
|
|
}
|
|
|
|
return Ok(RectangleLight::new(arena, &dimensions, &colors));
|
|
}
|