use {
crate::parse::{
common::{fields, parse},
formats::{
Format,
standard::Vector2,
shared::{self, Vector3, separator, sep_terminated, maybe_sep_terminated}
},
core::{
Parse,
Input,
ParseResult,
nom::{
number::float,
character::char,
error::ParseError,
combinator::{map, opt},
sequence::{pair, delimited}
},
},
}
};
#[derive(Debug, Clone, Copy, PartialEq, Default)]
pub struct Valve;
impl Format for Valve {
type Entity = Entity;
}
pub type Entity = shared::Entity<Brush>;
pub type Brush = shared::Brush<TextureAlignment>;
pub type Plane = shared::Plane<TextureAlignment>;
pub type Texture = shared::Texture<TextureAlignment>;
#[derive(Debug, Copy, Clone, PartialEq, Default)]
pub struct TextureAlignment {
pub axes: Axes,
pub rotation: f32,
pub scale: Scale
}
impl <'i, E> Parse<'i, E> for TextureAlignment
where E: ParseError<Input<'i>> + Clone {
fn parse(input: Input<'i>) -> ParseResult<Self, E> {
fields!(TextureAlignment:
axes = maybe_sep_terminated(parse),
rotation = sep_terminated(float),
scale = parse
)(input)
}
}
#[derive(Debug, Copy, Clone, PartialEq, Default)]
pub struct Axes {
pub u: Axis,
pub v: Axis
}
impl <'i, E> Parse<'i, E> for Axes
where E: ParseError<Input<'i>> + Clone {
fn parse(input: Input<'i>) -> ParseResult<Self, E> {
fields!(Axes:
u = maybe_sep_terminated(parse),
v = parse
)(input)
}
}
#[derive(Debug, Copy, Clone, PartialEq, Default)]
pub struct Axis {
pub normal: Vector3,
pub offset: f32
}
impl <'i, E> Parse<'i, E> for Axis
where E: ParseError<Input<'i>> + Clone {
fn parse(input: Input<'i>) -> ParseResult<Self, E> {
delimited(
pair(char('['), opt(separator)),
fields!(Axis:
normal = sep_terminated(parse),
offset = float
),
pair(opt(separator), char(']'))
)(input)
}
}
#[derive(Debug, Copy, Clone, PartialEq, Default)]
pub struct Scale {
pub u: f32,
pub v: f32
}
impl <'i, E> Parse<'i, E> for Scale
where E: ParseError<Input<'i>> + Clone {
fn parse(input: Input<'i>) -> ParseResult<Self, E> {
map(
Vector2::parse,
|vec| Scale {
u: vec.x,
v: vec.y
}
)(input)
}
}
#[cfg(test)]
mod test {
use {
super::*,
crate::parse::common::test::expected
};
#[test]
fn axis() {
assert_eq!(
parse(r"[ -41 541 -876.2 8 ]"),
expected(Axis {
normal: Vector3 { x: -41., y: 541., z: -876.2 },
offset: 8.
})
)
}
#[test]
fn axis_weird() {
assert_eq!(
parse(r"[-41
541 // j
-876.2
8]"),
expected(Axis {
normal: Vector3 { x: -41., y: 541., z: -876.2 },
offset: 8.
})
)
}
#[test]
fn axes() {
assert_eq!(
parse(r"[ -41 541 -876.2 8 ] [ 82 -1082 1752.4 -16 ]"),
expected(Axes {
u: Axis {
normal: Vector3 { x: -41., y: 541., z: -876.2 },
offset: 8.
},
v: Axis {
normal: Vector3 { x: 82., y: -1082., z: 1752.4 },
offset: -16.
}
})
)
}
#[test]
fn axes_weird() {
assert_eq!(
parse(r"[
-20.5 270.5 -438.1 4
][
82 -1082 1752.4 -16
]"),
expected(Axes {
u: Axis {
normal: Vector3 { x: -20.5, y: 270.5, z: -438.1 },
offset: 4.
},
v: Axis {
normal: Vector3 { x: 82., y: -1082., z: 1752.4 },
offset: -16.
}
})
)
}
#[test]
fn texture_alignment() {
assert_eq!(
parse(r"[ 0 -1 33 -31.4111 ] [ 0.242536 0 -0.970143 -31.4109 ] .1 1 1.03078"),
expected(TextureAlignment {
axes: Axes {
u: Axis {
normal: Vector3 { x: 0., y: -1., z: 33. },
offset: -31.4111
}, v: Axis {
normal: Vector3 { x: 0.242536, y: 0., z: -0.970143 },
offset: -31.4109
}
},
rotation: 0.1,
scale: Scale { u: 1., v: 1.03078 }
})
)
}
#[test]
fn texture_alignment_weird() {
assert_eq!(
parse(r"[ 0 -1 33 -31.4111 ] [ 0.242536 0 -0.970143 -31.4109 ].1
// HUH
1 1.03078"),
expected(TextureAlignment {
axes: Axes {
u: Axis {
normal: Vector3 { x: 0., y: -1., z: 33. },
offset: -31.4111
}, v: Axis {
normal: Vector3 { x: 0.242536, y: 0., z: -0.970143 },
offset: -31.4109
}
},
rotation: 0.1,
scale: Scale { u: 1., v: 1.03078 }
})
)
}
#[cfg(feature = "display")]
#[test]
fn roundtrip() {
let map = crate::Map::<Valve> {
entities: vec![Entity {
fields: crate::formats::shared::Fields(std::iter::once(("k".into(), "v".into())).collect()),
brushes: vec![Brush {
planes: vec![Plane {
texture: Texture {
name: "texture".into(),
..<_>::default()
},
..<_>::default()
}]
}]
}]
};
let string = map.to_string();
assert_eq!(
expected(map),
parse(&string)
)
}
}