lf2_parse/element/
bdy.rs

1use std::convert::TryFrom;
2
3use pest::iterators::Pair;
4
5use crate::{Error, ObjectDataParser, Rule, SubRuleFn};
6
7pub use self::{bdy_kind::BdyKind, bdy_kind_parse_error::BdyKindParseError};
8
9mod bdy_kind;
10mod bdy_kind_parse_error;
11
12/// Hittable body of the object.
13#[derive(Clone, Copy, Debug, PartialEq, Eq)]
14pub struct Bdy {
15    /// Only used in criminal (type 5) objects.
16    ///
17    /// If you use `kind: 1050` (1000 + Frame number) and the bdy is hit by some
18    /// `itr`s, the object switches to frame 50.
19    pub kind: BdyKind,
20    /// X coordinate.
21    pub x: i32,
22    /// Y coordinate.
23    pub y: i32,
24    /// Width.
25    pub w: u32,
26    /// Height.
27    pub h: u32,
28    /// Z Width extends in both directions + 1 center pixel.
29    ///
30    /// `zwidth: 10` means 10 pixels up, 10 pixels down, and one pixel for
31    /// center of the shadow for 21 pixels total.
32    pub z_width: u32,
33}
34
35impl Default for Bdy {
36    fn default() -> Bdy {
37        Bdy {
38            kind: Default::default(),
39            x: Default::default(),
40            y: Default::default(),
41            w: Default::default(),
42            h: Default::default(),
43            z_width: Self::Z_WIDTH_DEFAULT,
44        }
45    }
46}
47
48impl Bdy {
49    /// Default `Z_WIDTH` for `Bdy` volumes.
50    pub const Z_WIDTH_DEFAULT: u32 = 13;
51
52    fn parse_tags<'i>(bdy: Bdy, bdy_data_pair: Pair<'i, Rule>) -> Result<Bdy, Error<'i>> {
53        bdy_data_pair.into_inner().try_fold(bdy, Bdy::parse_tag)
54    }
55
56    fn parse_tag<'i>(bdy: Bdy, bdy_tag_pair: Pair<'i, Rule>) -> Result<Bdy, Error<'i>> {
57        ObjectDataParser::parse_as_type(
58            bdy,
59            bdy_tag_pair,
60            Rule::BdyTag,
61            &[Self::parse_tag_value as SubRuleFn<_>],
62        )
63    }
64
65    fn parse_tag_value<'i>(mut bdy: Bdy, bdy_tag_pair: Pair<'i, Rule>) -> Result<Bdy, Error<'i>> {
66        bdy = match bdy_tag_pair.as_rule() {
67            Rule::TagKind => {
68                ObjectDataParser::parse_value(bdy, bdy_tag_pair, Self::parse_kind_value)?
69            }
70            Rule::TagX => ObjectDataParser::parse_value(bdy, bdy_tag_pair, Self::parse_x_value)?,
71            Rule::TagY => ObjectDataParser::parse_value(bdy, bdy_tag_pair, Self::parse_y_value)?,
72            Rule::TagW => ObjectDataParser::parse_value(bdy, bdy_tag_pair, Self::parse_w_value)?,
73            Rule::TagH => ObjectDataParser::parse_value(bdy, bdy_tag_pair, Self::parse_h_value)?,
74            Rule::TagZWidth => {
75                ObjectDataParser::parse_value(bdy, bdy_tag_pair, Self::parse_z_width_value)?
76            }
77            _ => bdy,
78        };
79        Ok(bdy)
80    }
81
82    fn parse_kind_value<'i>(mut bdy: Bdy, value_pair: Pair<'i, Rule>) -> Result<Bdy, Error<'i>> {
83        let kind = value_pair
84            .as_str()
85            .parse()
86            .map_err(|error| Error::ParseBdyKind { value_pair, error })?;
87        bdy.kind = kind;
88        Ok(bdy)
89    }
90
91    fn parse_x_value<'i>(mut bdy: Bdy, value_pair: Pair<'i, Rule>) -> Result<Bdy, Error<'i>> {
92        let x = value_pair
93            .as_str()
94            .parse()
95            .map_err(|error| Error::ParseInt {
96                field: stringify!(x),
97                value_pair,
98                error,
99            })?;
100        bdy.x = x;
101        Ok(bdy)
102    }
103
104    fn parse_y_value<'i>(mut bdy: Bdy, value_pair: Pair<'i, Rule>) -> Result<Bdy, Error<'i>> {
105        let y = value_pair
106            .as_str()
107            .parse()
108            .map_err(|error| Error::ParseInt {
109                field: stringify!(y),
110                value_pair,
111                error,
112            })?;
113        bdy.y = y;
114        Ok(bdy)
115    }
116
117    fn parse_w_value<'i>(mut bdy: Bdy, value_pair: Pair<'i, Rule>) -> Result<Bdy, Error<'i>> {
118        let w = value_pair
119            .as_str()
120            .parse()
121            .map_err(|error| Error::ParseInt {
122                field: stringify!(w),
123                value_pair,
124                error,
125            })?;
126        bdy.w = w;
127        Ok(bdy)
128    }
129
130    fn parse_h_value<'i>(mut bdy: Bdy, value_pair: Pair<'i, Rule>) -> Result<Bdy, Error<'i>> {
131        let h = value_pair
132            .as_str()
133            .parse()
134            .map_err(|error| Error::ParseInt {
135                field: stringify!(h),
136                value_pair,
137                error,
138            })?;
139        bdy.h = h;
140        Ok(bdy)
141    }
142
143    fn parse_z_width_value<'i>(mut bdy: Bdy, value_pair: Pair<'i, Rule>) -> Result<Bdy, Error<'i>> {
144        let z_width = value_pair
145            .as_str()
146            .parse()
147            .map_err(|error| Error::ParseInt {
148                field: stringify!(zwidth),
149                value_pair,
150                error,
151            })?;
152        bdy.z_width = z_width;
153        Ok(bdy)
154    }
155}
156
157impl<'i> TryFrom<Pair<'i, Rule>> for Bdy {
158    type Error = Error<'i>;
159
160    fn try_from(pair: Pair<'i, Rule>) -> Result<Self, Self::Error> {
161        let sub_rule_fns: &[SubRuleFn<_>] = &[Bdy::parse_tags];
162        ObjectDataParser::parse_as_type(Bdy::default(), pair, Rule::Bdy, sub_rule_fns)
163    }
164}