1use crate::EventCommand;
2use crate::EventPageCondition;
3use crate::EventPageGraphic;
4use crate::MoveRoute;
5use ruby_marshal::FromValue;
6use ruby_marshal::FromValueContext;
7use ruby_marshal::FromValueError;
8use ruby_marshal::IntoValue;
9use ruby_marshal::IntoValueError;
10use ruby_marshal::ObjectValue;
11use ruby_marshal::SymbolValue;
12use ruby_marshal::Value;
13use ruby_marshal::ValueArena;
14use ruby_marshal::ValueHandle;
15
16const OBJECT_NAME: &[u8] = b"RPG::Event::Page";
17
18const MOVE_TYPE_FIELD: &[u8] = b"@move_type";
19const LIST_FIELD: &[u8] = b"@list";
20const CONDITION_FIELD: &[u8] = b"@condition";
21const DIRECTION_FIX_FIELD: &[u8] = b"@direction_fix";
22const MOVE_ROUTE_FIELD: &[u8] = b"@move_route";
23const TRIGGER_FIELD: &[u8] = b"@trigger";
24const STEP_ANIME_FIELD: &[u8] = b"@step_anime";
25const MOVE_FREQUENCY_FIELD: &[u8] = b"@move_frequency";
26const GRAPHIC_FIELD: &[u8] = b"@graphic";
27const ALWAYS_ON_TOP_FIELD: &[u8] = b"@always_on_top";
28const WALK_ANIME_FIELD: &[u8] = b"@walk_anime";
29const MOVE_SPEED_FIELD: &[u8] = b"@move_speed";
30const THROUGH_FIELD: &[u8] = b"@through";
31
32#[derive(Debug, serde::Deserialize, serde::Serialize)]
33pub struct EventPage {
34 pub move_type: i32,
35 pub list: Vec<EventCommand>,
36 pub condition: EventPageCondition,
37 pub direction_fix: bool,
38 pub move_route: MoveRoute,
39 pub trigger: i32,
40 pub step_anime: bool,
41 pub move_frequency: i32,
42 pub graphic: EventPageGraphic,
43 pub always_on_top: bool,
44 pub walk_anime: bool,
45 pub move_speed: i32,
46 pub through: bool,
47}
48
49impl<'a> FromValue<'a> for EventPage {
50 fn from_value(ctx: &FromValueContext<'a>, value: &Value) -> Result<Self, FromValueError> {
51 let object: &ObjectValue = FromValue::from_value(ctx, value)?;
52 let name = object.name();
53 let name: &SymbolValue = ctx.from_value(name.into())?;
54 let name = name.value();
55 if name != OBJECT_NAME {
56 return Err(FromValueError::UnexpectedObjectName { name: name.into() });
57 }
58
59 let instance_variables = object.instance_variables();
60
61 let mut move_type_field = None;
62 let mut list_field = None;
63 let mut condition_field = None;
64 let mut direction_fix_field = None;
65 let mut move_route_field = None;
66 let mut trigger_field = None;
67 let mut step_anime_field = None;
68 let mut move_frequency_field = None;
69 let mut graphic_field = None;
70 let mut always_on_top_field = None;
71 let mut walk_anime_field = None;
72 let mut move_speed_field = None;
73 let mut through_field = None;
74
75 for (key, value) in instance_variables.iter().copied() {
76 let key: &SymbolValue = ctx.from_value(key.into())?;
77 let key = key.value();
78
79 match key {
80 MOVE_TYPE_FIELD => {
81 if move_type_field.is_some() {
82 return Err(FromValueError::DuplicateInstanceVariable {
83 name: MOVE_TYPE_FIELD.into(),
84 });
85 }
86
87 move_type_field = Some(ctx.from_value(value)?);
88 }
89 LIST_FIELD => {
90 if list_field.is_some() {
91 return Err(FromValueError::DuplicateInstanceVariable {
92 name: LIST_FIELD.into(),
93 });
94 }
95
96 list_field = Some(ctx.from_value(value)?);
97 }
98 CONDITION_FIELD => {
99 if condition_field.is_some() {
100 return Err(FromValueError::DuplicateInstanceVariable {
101 name: CONDITION_FIELD.into(),
102 });
103 }
104
105 condition_field = Some(ctx.from_value(value)?);
106 }
107 DIRECTION_FIX_FIELD => {
108 if direction_fix_field.is_some() {
109 return Err(FromValueError::DuplicateInstanceVariable {
110 name: DIRECTION_FIX_FIELD.into(),
111 });
112 }
113
114 direction_fix_field = Some(ctx.from_value(value)?);
115 }
116 MOVE_ROUTE_FIELD => {
117 if move_route_field.is_some() {
118 return Err(FromValueError::DuplicateInstanceVariable {
119 name: MOVE_ROUTE_FIELD.into(),
120 });
121 }
122
123 move_route_field = Some(ctx.from_value(value)?);
124 }
125 TRIGGER_FIELD => {
126 if trigger_field.is_some() {
127 return Err(FromValueError::DuplicateInstanceVariable {
128 name: TRIGGER_FIELD.into(),
129 });
130 }
131
132 trigger_field = Some(ctx.from_value(value)?);
133 }
134 STEP_ANIME_FIELD => {
135 if step_anime_field.is_some() {
136 return Err(FromValueError::DuplicateInstanceVariable {
137 name: STEP_ANIME_FIELD.into(),
138 });
139 }
140
141 step_anime_field = Some(ctx.from_value(value)?);
142 }
143 MOVE_FREQUENCY_FIELD => {
144 if move_frequency_field.is_some() {
145 return Err(FromValueError::DuplicateInstanceVariable {
146 name: MOVE_FREQUENCY_FIELD.into(),
147 });
148 }
149
150 move_frequency_field = Some(ctx.from_value(value)?);
151 }
152 GRAPHIC_FIELD => {
153 if graphic_field.is_some() {
154 return Err(FromValueError::DuplicateInstanceVariable {
155 name: GRAPHIC_FIELD.into(),
156 });
157 }
158
159 graphic_field = Some(ctx.from_value(value)?);
160 }
161 ALWAYS_ON_TOP_FIELD => {
162 if always_on_top_field.is_some() {
163 return Err(FromValueError::DuplicateInstanceVariable {
164 name: ALWAYS_ON_TOP_FIELD.into(),
165 });
166 }
167
168 always_on_top_field = Some(ctx.from_value(value)?);
169 }
170 WALK_ANIME_FIELD => {
171 if walk_anime_field.is_some() {
172 return Err(FromValueError::DuplicateInstanceVariable {
173 name: WALK_ANIME_FIELD.into(),
174 });
175 }
176
177 walk_anime_field = Some(ctx.from_value(value)?);
178 }
179 MOVE_SPEED_FIELD => {
180 if move_speed_field.is_some() {
181 return Err(FromValueError::DuplicateInstanceVariable {
182 name: MOVE_SPEED_FIELD.into(),
183 });
184 }
185
186 move_speed_field = Some(ctx.from_value(value)?);
187 }
188 THROUGH_FIELD => {
189 if through_field.is_some() {
190 return Err(FromValueError::DuplicateInstanceVariable {
191 name: THROUGH_FIELD.into(),
192 });
193 }
194
195 through_field = Some(ctx.from_value(value)?);
196 }
197 _ => {
198 return Err(FromValueError::UnknownInstanceVariable { name: key.into() });
199 }
200 }
201 }
202
203 let move_type = move_type_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
204 name: MOVE_TYPE_FIELD.into(),
205 })?;
206 let list = list_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
207 name: LIST_FIELD.into(),
208 })?;
209 let condition = condition_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
210 name: CONDITION_FIELD.into(),
211 })?;
212 let direction_fix =
213 direction_fix_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
214 name: DIRECTION_FIX_FIELD.into(),
215 })?;
216 let move_route =
217 move_route_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
218 name: MOVE_ROUTE_FIELD.into(),
219 })?;
220 let trigger = trigger_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
221 name: TRIGGER_FIELD.into(),
222 })?;
223 let step_anime =
224 step_anime_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
225 name: STEP_ANIME_FIELD.into(),
226 })?;
227 let move_frequency =
228 move_frequency_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
229 name: MOVE_FREQUENCY_FIELD.into(),
230 })?;
231 let graphic = graphic_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
232 name: GRAPHIC_FIELD.into(),
233 })?;
234 let always_on_top =
235 always_on_top_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
236 name: ALWAYS_ON_TOP_FIELD.into(),
237 })?;
238 let walk_anime =
239 walk_anime_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
240 name: WALK_ANIME_FIELD.into(),
241 })?;
242 let move_speed =
243 move_speed_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
244 name: MOVE_SPEED_FIELD.into(),
245 })?;
246 let through = through_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
247 name: THROUGH_FIELD.into(),
248 })?;
249
250 Ok(Self {
251 move_type,
252 list,
253 condition,
254 direction_fix,
255 move_route,
256 trigger,
257 step_anime,
258 move_frequency,
259 graphic,
260 always_on_top,
261 walk_anime,
262 move_speed,
263 through,
264 })
265 }
266}
267
268impl IntoValue for EventPage {
269 fn into_value(self, arena: &mut ValueArena) -> Result<ValueHandle, IntoValueError> {
270 let object_name = arena.create_symbol(OBJECT_NAME.into());
271
272 let move_type_field_key = arena.create_symbol(MOVE_TYPE_FIELD.into());
273 let list_field_key = arena.create_symbol(LIST_FIELD.into());
274 let condition_field_key = arena.create_symbol(CONDITION_FIELD.into());
275 let direction_fix_field_key = arena.create_symbol(DIRECTION_FIX_FIELD.into());
276 let move_route_field_key = arena.create_symbol(MOVE_ROUTE_FIELD.into());
277 let trigger_field_key = arena.create_symbol(TRIGGER_FIELD.into());
278 let step_anime_field_key = arena.create_symbol(STEP_ANIME_FIELD.into());
279 let move_frequency_field_key = arena.create_symbol(MOVE_FREQUENCY_FIELD.into());
280 let graphic_field_key = arena.create_symbol(GRAPHIC_FIELD.into());
281 let always_on_top_field_key = arena.create_symbol(ALWAYS_ON_TOP_FIELD.into());
282 let walk_anime_field_key = arena.create_symbol(WALK_ANIME_FIELD.into());
283 let move_speed_field_key = arena.create_symbol(MOVE_SPEED_FIELD.into());
284 let through_field_key = arena.create_symbol(THROUGH_FIELD.into());
285
286 let move_type_field_value = self.move_type.into_value(arena)?;
287 let list_field_value = self.list.into_value(arena)?;
288 let condition_field_value = self.condition.into_value(arena)?;
289 let direction_fix_field_value = self.direction_fix.into_value(arena)?;
290 let move_route_field_value = self.move_route.into_value(arena)?;
291 let trigger_field_value = self.trigger.into_value(arena)?;
292 let step_anime_field_value = self.step_anime.into_value(arena)?;
293 let move_frequency_field_value = self.move_frequency.into_value(arena)?;
294 let graphic_field_value = self.graphic.into_value(arena)?;
295 let always_on_top_field_value = self.always_on_top.into_value(arena)?;
296 let walk_anime_field_value = self.walk_anime.into_value(arena)?;
297 let move_speed_field_value = self.move_speed.into_value(arena)?;
298 let through_field_value = self.through.into_value(arena)?;
299
300 let fields = vec![
301 (move_type_field_key, move_type_field_value),
302 (list_field_key, list_field_value),
303 (condition_field_key, condition_field_value),
304 (direction_fix_field_key, direction_fix_field_value),
305 (move_route_field_key, move_route_field_value),
306 (trigger_field_key, trigger_field_value),
307 (step_anime_field_key, step_anime_field_value),
308 (move_frequency_field_key, move_frequency_field_value),
309 (graphic_field_key, graphic_field_value),
310 (always_on_top_field_key, always_on_top_field_value),
311 (walk_anime_field_key, walk_anime_field_value),
312 (move_speed_field_key, move_speed_field_value),
313 (through_field_key, through_field_value),
314 ];
315
316 let object = arena.create_object(object_name, fields);
317
318 Ok(object.into())
319 }
320}