rpgmxp_types/
event_page_graphic.rs

1use ruby_marshal::FromValue;
2use ruby_marshal::FromValueContext;
3use ruby_marshal::FromValueError;
4use ruby_marshal::IntoValue;
5use ruby_marshal::IntoValueError;
6use ruby_marshal::ObjectValue;
7use ruby_marshal::StringValue;
8use ruby_marshal::SymbolValue;
9use ruby_marshal::Value;
10use ruby_marshal::ValueArena;
11use ruby_marshal::ValueHandle;
12
13const OBJECT_NAME: &[u8] = b"RPG::Event::Page::Graphic";
14
15const OPACITY_FIELD: &[u8] = b"@opacity";
16const CHARACTER_NAME_FIELD: &[u8] = b"@character_name";
17const PATTERN_FIELD: &[u8] = b"@pattern";
18const TILE_ID_FIELD: &[u8] = b"@tile_id";
19const DIRECTION_FIELD: &[u8] = b"@direction";
20const BLEND_TYPE_FIELD: &[u8] = b"@blend_type";
21const CHARACTER_HUE_FIELD: &[u8] = b"@character_hue";
22
23#[derive(Debug, serde::Deserialize, serde::Serialize)]
24pub struct EventPageGraphic {
25    pub opacity: i32,
26    pub character_name: String,
27    pub pattern: i32,
28    pub tile_id: i32,
29    pub direction: i32,
30    pub blend_type: i32,
31    pub character_hue: i32,
32}
33
34impl<'a> FromValue<'a> for EventPageGraphic {
35    fn from_value(ctx: &FromValueContext<'a>, value: &Value) -> Result<Self, FromValueError> {
36        let object: &ObjectValue = FromValue::from_value(ctx, value)?;
37        let name = object.name();
38        let name: &SymbolValue = ctx.from_value(name.into())?;
39        let name = name.value();
40
41        if name != OBJECT_NAME {
42            return Err(FromValueError::UnexpectedObjectName { name: name.into() });
43        }
44
45        let instance_variables = object.instance_variables();
46
47        let mut opacity_field = None;
48        let mut character_name_field = None;
49        let mut pattern_field = None;
50        let mut tile_id_field = None;
51        let mut direction_field = None;
52        let mut blend_type_field = None;
53        let mut character_hue_field = None;
54
55        for (key, value) in instance_variables.iter().copied() {
56            let key: &SymbolValue = ctx.from_value(key.into())?;
57            let key = key.value();
58
59            match key {
60                OPACITY_FIELD => {
61                    if opacity_field.is_some() {
62                        return Err(FromValueError::DuplicateInstanceVariable {
63                            name: OPACITY_FIELD.into(),
64                        });
65                    }
66
67                    let opacity: i32 = ctx.from_value(value)?;
68                    opacity_field = Some(opacity);
69                }
70                CHARACTER_NAME_FIELD => {
71                    if character_name_field.is_some() {
72                        return Err(FromValueError::DuplicateInstanceVariable {
73                            name: CHARACTER_NAME_FIELD.into(),
74                        });
75                    }
76
77                    let character_name: &StringValue = ctx.from_value(value)?;
78                    let character_name = std::str::from_utf8(character_name.value())
79                        .map_err(FromValueError::new_other)?;
80
81                    character_name_field = Some(character_name.into());
82                }
83                PATTERN_FIELD => {
84                    if pattern_field.is_some() {
85                        return Err(FromValueError::DuplicateInstanceVariable {
86                            name: PATTERN_FIELD.into(),
87                        });
88                    }
89
90                    let pattern: i32 = ctx.from_value(value)?;
91                    pattern_field = Some(pattern);
92                }
93                TILE_ID_FIELD => {
94                    if tile_id_field.is_some() {
95                        return Err(FromValueError::DuplicateInstanceVariable {
96                            name: TILE_ID_FIELD.into(),
97                        });
98                    }
99
100                    let tile_id: i32 = ctx.from_value(value)?;
101                    tile_id_field = Some(tile_id);
102                }
103                DIRECTION_FIELD => {
104                    if direction_field.is_some() {
105                        return Err(FromValueError::DuplicateInstanceVariable {
106                            name: DIRECTION_FIELD.into(),
107                        });
108                    }
109
110                    let direction: i32 = ctx.from_value(value)?;
111                    direction_field = Some(direction);
112                }
113                BLEND_TYPE_FIELD => {
114                    if blend_type_field.is_some() {
115                        return Err(FromValueError::DuplicateInstanceVariable {
116                            name: BLEND_TYPE_FIELD.into(),
117                        });
118                    }
119
120                    let blend_type: i32 = ctx.from_value(value)?;
121                    blend_type_field = Some(blend_type);
122                }
123                CHARACTER_HUE_FIELD => {
124                    if character_hue_field.is_some() {
125                        return Err(FromValueError::DuplicateInstanceVariable {
126                            name: CHARACTER_HUE_FIELD.into(),
127                        });
128                    }
129
130                    let character_hue: i32 = ctx.from_value(value)?;
131                    character_hue_field = Some(character_hue);
132                }
133                _ => return Err(FromValueError::UnknownInstanceVariable { name: key.into() }),
134            }
135        }
136
137        let opacity = opacity_field.ok_or(FromValueError::MissingInstanceVariable {
138            name: OPACITY_FIELD.into(),
139        })?;
140        let character_name =
141            character_name_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
142                name: CHARACTER_NAME_FIELD.into(),
143            })?;
144        let pattern = pattern_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
145            name: PATTERN_FIELD.into(),
146        })?;
147        let tile_id = tile_id_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
148            name: TILE_ID_FIELD.into(),
149        })?;
150        let direction = direction_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
151            name: DIRECTION_FIELD.into(),
152        })?;
153        let blend_type =
154            blend_type_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
155                name: BLEND_TYPE_FIELD.into(),
156            })?;
157        let character_hue =
158            character_hue_field.ok_or_else(|| FromValueError::MissingInstanceVariable {
159                name: CHARACTER_HUE_FIELD.into(),
160            })?;
161
162        Ok(Self {
163            opacity,
164            character_name,
165            pattern,
166            tile_id,
167            direction,
168            blend_type,
169            character_hue,
170        })
171    }
172}
173
174impl IntoValue for EventPageGraphic {
175    fn into_value(self, arena: &mut ValueArena) -> Result<ValueHandle, IntoValueError> {
176        let object_name = arena.create_symbol(OBJECT_NAME.into());
177
178        let opacity_field_key = arena.create_symbol(OPACITY_FIELD.into());
179        let character_name_field_key = arena.create_symbol(CHARACTER_NAME_FIELD.into());
180        let pattern_field_key = arena.create_symbol(PATTERN_FIELD.into());
181        let tile_id_field_key = arena.create_symbol(TILE_ID_FIELD.into());
182        let direction_field_key = arena.create_symbol(DIRECTION_FIELD.into());
183        let blend_type_field_key = arena.create_symbol(BLEND_TYPE_FIELD.into());
184        let character_hue_field_key = arena.create_symbol(CHARACTER_HUE_FIELD.into());
185
186        let opacity_field_value = self.opacity.into_value(arena)?;
187        let character_name_field_value = arena.create_string(self.character_name.into()).into();
188        let pattern_field_value = self.pattern.into_value(arena)?;
189        let tile_id_field_value = self.tile_id.into_value(arena)?;
190        let direction_field_value = self.direction.into_value(arena)?;
191        let blend_type_field_value = self.blend_type.into_value(arena)?;
192        let character_hue_field_value = self.character_hue.into_value(arena)?;
193
194        let fields = vec![
195            (opacity_field_key, opacity_field_value),
196            (pattern_field_key, pattern_field_value),
197            (character_name_field_key, character_name_field_value),
198            (tile_id_field_key, tile_id_field_value),
199            (direction_field_key, direction_field_value),
200            (blend_type_field_key, blend_type_field_value),
201            (character_hue_field_key, character_hue_field_value),
202        ];
203        let object = arena.create_object(object_name, fields);
204
205        Ok(object.into())
206    }
207}