luminol_data/
rgss_structs.rs

1#![allow(missing_docs)]
2
3/// **A struct representing an RGBA color.**
4///
5/// Used all over the place in RGSS.
6#[derive(Debug, Clone, Copy, PartialEq)]
7#[derive(serde::Serialize, serde::Deserialize)]
8#[derive(alox_48::Deserialize, alox_48::Serialize)]
9#[marshal(from = "alox_48::Userdata", into = "alox_48::Userdata")]
10#[derive(bytemuck::Pod, bytemuck::Zeroable)]
11#[repr(C)]
12pub struct Color {
13    pub red: f64,
14    pub green: f64,
15    pub blue: f64,
16    pub alpha: f64,
17}
18
19impl From<alox_48::Userdata> for Color {
20    fn from(value: alox_48::Userdata) -> Self {
21        *bytemuck::from_bytes(&value.data)
22    }
23}
24
25impl From<Color> for alox_48::Userdata {
26    fn from(value: Color) -> Self {
27        alox_48::Userdata {
28            class: "Color".into(),
29            data: bytemuck::bytes_of(&value).to_vec(),
30        }
31    }
32}
33
34impl From<Color> for alox_48::Value {
35    fn from(value: Color) -> Self {
36        Self::Userdata(value.into())
37    }
38}
39
40// Default values
41impl Default for Color {
42    fn default() -> Self {
43        Self {
44            red: 255.0,
45            green: 255.0,
46            blue: 255.0,
47            alpha: 255.0,
48        }
49    }
50}
51
52/// **A struct representing an offset to an RGBA color.**
53///
54/// Its members are f64 but must not exceed the range of 255..-255.
55#[derive(Default, Debug, Clone, Copy, PartialEq)]
56#[derive(serde::Serialize, serde::Deserialize)]
57#[derive(alox_48::Deserialize, alox_48::Serialize)]
58#[marshal(from = "alox_48::Userdata", into = "alox_48::Userdata")]
59#[derive(bytemuck::Pod, bytemuck::Zeroable)]
60#[repr(C)]
61pub struct Tone {
62    pub red: f64,
63    pub green: f64,
64    pub blue: f64,
65    pub gray: f64,
66}
67
68impl From<alox_48::Userdata> for Tone {
69    fn from(value: alox_48::Userdata) -> Self {
70        *bytemuck::from_bytes(&value.data)
71    }
72}
73
74impl From<Tone> for alox_48::Userdata {
75    fn from(value: Tone) -> Self {
76        alox_48::Userdata {
77            class: "Tone".into(),
78            data: bytemuck::bytes_of(&value).to_vec(),
79        }
80    }
81}
82
83impl From<Tone> for alox_48::Value {
84    fn from(value: Tone) -> Self {
85        Self::Userdata(value.into())
86    }
87}
88
89use std::ops::{Index, IndexMut};
90
91/// Normal RGSS has dynamically dimensioned arrays, but in practice that does not map well to Rust.
92/// We don't particularly need dynamically sized arrays anyway.
93/// 1D Table.
94#[derive(Debug, Default, Clone)]
95#[derive(serde::Serialize, serde::Deserialize)]
96#[derive(alox_48::Deserialize, alox_48::Serialize)]
97#[marshal(from = "alox_48::Userdata", into = "alox_48::Userdata")]
98pub struct Table1 {
99    xsize: usize,
100    data: Vec<i16>,
101}
102
103impl From<alox_48::Userdata> for Table1 {
104    fn from(value: alox_48::Userdata) -> Self {
105        let u32_slice: &[u32] =
106            bytemuck::cast_slice(&value.data[0..std::mem::size_of::<u32>() * 5]);
107
108        assert_eq!(u32_slice[0], 1);
109        let xsize = u32_slice[1] as usize;
110        let ysize = u32_slice[2] as usize;
111        let zsize = u32_slice[3] as usize;
112        let len = u32_slice[4] as usize;
113
114        assert_eq!(xsize * ysize * zsize, len);
115        let data = bytemuck::cast_slice(&value.data[(std::mem::size_of::<u32>() * 5)..]).to_vec();
116        assert_eq!(data.len(), len);
117
118        Self { xsize, data }
119    }
120}
121
122impl From<Table1> for alox_48::Userdata {
123    fn from(value: Table1) -> Self {
124        let header = &[1, value.xsize as u32, 1, 1, value.len() as u32];
125        let mut data = bytemuck::pod_collect_to_vec(header);
126        data.extend_from_slice(bytemuck::cast_slice(&value.data));
127
128        Self {
129            class: "Table".into(),
130            data,
131        }
132    }
133}
134
135impl Table1 {
136    /// Create a new 1d array with a width of xsize.
137    #[must_use]
138    pub fn new(xsize: usize) -> Self {
139        Self {
140            xsize,
141            data: vec![0; xsize],
142        }
143    }
144
145    /// Width of the table.
146    #[must_use]
147    pub fn xsize(&self) -> usize {
148        self.xsize
149    }
150
151    /// Total number of elements in the table.
152    #[must_use]
153    pub fn len(&self) -> usize {
154        self.data.len()
155    }
156
157    /// Is the table empty?
158    #[must_use]
159    pub fn is_empty(&self) -> bool {
160        self.data.is_empty()
161    }
162
163    pub fn resize(&mut self, xsize: usize) {
164        self.data.resize(xsize, 0);
165        self.xsize = xsize;
166    }
167
168    pub fn resize_with_value(&mut self, xsize: usize, value: i16) {
169        self.data.resize(xsize, value);
170        self.xsize = xsize;
171    }
172
173    pub fn iter(&self) -> impl Iterator<Item = &i16> {
174        self.data.iter()
175    }
176
177    pub fn as_slice(&self) -> &[i16] {
178        self.data.as_slice()
179    }
180
181    pub fn as_mut_slice(&mut self) -> &mut [i16] {
182        self.data.as_mut_slice()
183    }
184}
185
186impl Index<usize> for Table1 {
187    type Output = i16;
188
189    fn index(&self, index: usize) -> &Self::Output {
190        &self.data[index]
191    }
192}
193
194impl IndexMut<usize> for Table1 {
195    fn index_mut(&mut self, index: usize) -> &mut Self::Output {
196        &mut self.data[index]
197    }
198}
199
200/// 2D table. See [`Table1`].
201#[derive(Debug, Default, Clone)]
202#[derive(serde::Serialize, serde::Deserialize)]
203#[derive(alox_48::Deserialize, alox_48::Serialize)]
204#[marshal(from = "alox_48::Userdata", into = "alox_48::Userdata")]
205pub struct Table2 {
206    xsize: usize,
207    ysize: usize,
208    data: Vec<i16>,
209}
210
211impl From<alox_48::Userdata> for Table2 {
212    fn from(value: alox_48::Userdata) -> Self {
213        let u32_slice: &[u32] =
214            bytemuck::cast_slice(&value.data[0..std::mem::size_of::<u32>() * 5]);
215
216        assert_eq!(u32_slice[0], 2);
217        let xsize = u32_slice[1] as usize;
218        let ysize = u32_slice[2] as usize;
219        let zsize = u32_slice[3] as usize;
220        let len = u32_slice[4] as usize;
221
222        assert_eq!(xsize * ysize * zsize, len);
223        let data = bytemuck::cast_slice(&value.data[(std::mem::size_of::<u32>() * 5)..]).to_vec();
224        assert_eq!(data.len(), len);
225
226        Self { xsize, ysize, data }
227    }
228}
229
230impl From<Table2> for alox_48::Userdata {
231    fn from(value: Table2) -> Self {
232        let header = &[
233            2,
234            value.xsize as u32,
235            value.ysize as u32,
236            1,
237            value.len() as u32,
238        ];
239        let mut data = bytemuck::pod_collect_to_vec(header);
240        data.extend_from_slice(bytemuck::cast_slice(&value.data));
241
242        Self {
243            class: "Table".into(),
244            data,
245        }
246    }
247}
248
249impl Table2 {
250    /// Create a new 2D table with a width of xsize and a height of ysize.
251    #[must_use]
252    pub fn new(xsize: usize, ysize: usize) -> Self {
253        Self {
254            xsize,
255            ysize,
256            data: vec![0; xsize * ysize],
257        }
258    }
259
260    #[must_use]
261    pub fn new_data(xsize: usize, ysize: usize, data: Vec<i16>) -> Self {
262        assert_eq!(xsize * ysize, data.len());
263        Self { xsize, ysize, data }
264    }
265
266    /// Width of the table.
267    #[must_use]
268    pub fn xsize(&self) -> usize {
269        self.xsize
270    }
271
272    /// Height of the table.
273    #[must_use]
274    pub fn ysize(&self) -> usize {
275        self.ysize
276    }
277
278    /// Total number of elements in the table.
279    #[must_use]
280    pub fn len(&self) -> usize {
281        self.data.len()
282    }
283
284    /// Is the table empty?
285    #[must_use]
286    pub fn is_empty(&self) -> bool {
287        self.data.is_empty()
288    }
289
290    pub fn resize(&mut self, xsize: usize, ysize: usize) {
291        let mut new_data = vec![0; xsize * ysize];
292
293        for y in 0..self.ysize.min(ysize) {
294            for x in 0..self.xsize.min(xsize) {
295                new_data[xsize * y + x] = self[(x, y)]
296            }
297        }
298
299        self.xsize = xsize;
300        self.ysize = ysize;
301
302        self.data = new_data;
303    }
304
305    pub fn iter(&self) -> impl Iterator<Item = &i16> {
306        self.data.iter()
307    }
308
309    pub fn as_slice(&self) -> &[i16] {
310        self.data.as_slice()
311    }
312
313    pub fn as_mut_slice(&mut self) -> &mut [i16] {
314        self.data.as_mut_slice()
315    }
316}
317
318impl Index<(usize, usize)> for Table2 {
319    type Output = i16;
320
321    fn index(&self, index: (usize, usize)) -> &Self::Output {
322        &self.data[index.0 + index.1 * self.xsize]
323    }
324}
325
326impl IndexMut<(usize, usize)> for Table2 {
327    fn index_mut(&mut self, index: (usize, usize)) -> &mut Self::Output {
328        &mut self.data[index.0 + index.1 * self.xsize]
329    }
330}
331
332#[derive(Debug, Default, Clone)]
333#[derive(serde::Serialize, serde::Deserialize)]
334#[derive(alox_48::Deserialize, alox_48::Serialize)]
335#[marshal(from = "alox_48::Userdata", into = "alox_48::Userdata")]
336/// 3D table. See [`Table2`].
337pub struct Table3 {
338    xsize: usize,
339    ysize: usize,
340    zsize: usize,
341    data: Vec<i16>,
342}
343
344impl From<alox_48::Userdata> for Table3 {
345    fn from(value: alox_48::Userdata) -> Self {
346        let u32_slice: &[u32] =
347            bytemuck::cast_slice(&value.data[0..std::mem::size_of::<u32>() * 5]);
348
349        assert_eq!(u32_slice[0], 3);
350        let xsize = u32_slice[1] as usize;
351        let ysize = u32_slice[2] as usize;
352        let zsize = u32_slice[3] as usize;
353        let len = u32_slice[4] as usize;
354
355        assert_eq!(xsize * ysize * zsize, len);
356        let data = bytemuck::cast_slice(&value.data[(std::mem::size_of::<u32>() * 5)..]).to_vec();
357        assert_eq!(data.len(), len);
358
359        Self {
360            xsize,
361            ysize,
362            zsize,
363            data,
364        }
365    }
366}
367
368impl From<Table3> for alox_48::Userdata {
369    fn from(value: Table3) -> Self {
370        let header = &[
371            3,
372            value.xsize as u32,
373            value.ysize as u32,
374            value.zsize as u32,
375            value.len() as u32,
376        ];
377        let mut data = bytemuck::pod_collect_to_vec(header);
378        data.extend_from_slice(bytemuck::cast_slice(&value.data));
379
380        Self {
381            class: "Table".into(),
382            data,
383        }
384    }
385}
386
387impl Table3 {
388    /// Create a new 3D table with a width of xsize, a height of ysize, and a depth of zsize.
389    #[must_use]
390    pub fn new(xsize: usize, ysize: usize, zsize: usize) -> Self {
391        Self {
392            xsize,
393            ysize,
394            zsize,
395            data: vec![0; xsize * ysize * zsize],
396        }
397    }
398
399    #[must_use]
400    pub fn new_data(xsize: usize, ysize: usize, zsize: usize, data: Vec<i16>) -> Self {
401        assert_eq!(xsize * ysize * zsize, data.len());
402        Self {
403            xsize,
404            ysize,
405            zsize,
406            data,
407        }
408    }
409
410    /// Width of the table.
411    #[must_use]
412    pub fn xsize(&self) -> usize {
413        self.xsize
414    }
415
416    /// Height of the table.
417    #[must_use]
418    pub fn ysize(&self) -> usize {
419        self.ysize
420    }
421
422    /// Depth of the table.
423    #[must_use]
424    pub fn zsize(&self) -> usize {
425        self.zsize
426    }
427
428    /// Total number of elements in the table.
429    #[must_use]
430    pub fn len(&self) -> usize {
431        self.data.len()
432    }
433
434    /// Is the table empty?
435    #[must_use]
436    pub fn is_empty(&self) -> bool {
437        self.data.is_empty()
438    }
439
440    pub fn resize(&mut self, xsize: usize, ysize: usize, zsize: usize) {
441        let mut new_data = vec![0; xsize * ysize];
442
443        // A naive for loop like this is optimized to a handful of memcpys.
444        for z in 0..self.zsize.min(zsize) {
445            for y in 0..self.ysize.min(ysize) {
446                for x in 0..self.xsize.min(xsize) {
447                    new_data[(xsize * ysize * z) + (xsize * y) + x] = self[(x, y, z)]
448                }
449            }
450        }
451
452        self.xsize = xsize;
453        self.ysize = ysize;
454        self.zsize = zsize;
455
456        self.data = new_data;
457    }
458
459    pub fn iter(&self) -> impl Iterator<Item = &i16> {
460        self.data.iter()
461    }
462
463    pub fn as_slice(&self) -> &[i16] {
464        self.data.as_slice()
465    }
466
467    pub fn as_mut_slice(&mut self) -> &mut [i16] {
468        self.data.as_mut_slice()
469    }
470
471    pub fn layer_as_slice(&self, layer: usize) -> &[i16] {
472        let layer_size = self.xsize * self.ysize;
473        &self.data[(layer_size * layer)..(layer_size * (layer + 1))]
474    }
475}
476
477impl Index<(usize, usize, usize)> for Table3 {
478    type Output = i16;
479
480    fn index(&self, index: (usize, usize, usize)) -> &Self::Output {
481        &self.data[index.0 + self.xsize * (index.1 + self.ysize * index.2)]
482    }
483}
484
485impl IndexMut<(usize, usize, usize)> for Table3 {
486    fn index_mut(&mut self, index: (usize, usize, usize)) -> &mut Self::Output {
487        &mut self.data[index.0 + self.xsize * (index.1 + self.ysize * index.2)]
488    }
489}