asr/game_engine/godot/core/variant/
variant.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
//! <https://github.com/godotengine/godot/blob/07cf36d21c9056fb4055f020949fb90ebd795afb/core/variant/variant.h>

use core::{fmt, mem::size_of};

use bytemuck::{Pod, Zeroable};

use crate::game_engine::godot::SizeInTargetProcess;

/// The type of a [`Variant`].
#[derive(Copy, Clone, PartialEq, Eq, Hash, Pod, Zeroable)]
#[repr(transparent)]
pub struct VariantType(u8);

impl fmt::Debug for VariantType {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(match *self {
            Self::NIL => "NIL",
            Self::BOOL => "BOOL",
            Self::INT => "INT",
            Self::FLOAT => "FLOAT",
            Self::STRING => "STRING",
            Self::VECTOR2 => "VECTOR2",
            Self::VECTOR2I => "VECTOR2I",
            Self::RECT2 => "RECT2",
            Self::RECT2I => "RECT2I",
            Self::VECTOR3 => "VECTOR3",
            Self::VECTOR3I => "VECTOR3I",
            Self::TRANSFORM2D => "TRANSFORM2D",
            Self::VECTOR4 => "VECTOR4",
            Self::VECTOR4I => "VECTOR4I",
            Self::PLANE => "PLANE",
            Self::QUATERNION => "QUATERNION",
            Self::AABB => "AABB",
            Self::BASIS => "BASIS",
            Self::TRANSFORM3D => "TRANSFORM3D",
            Self::PROJECTION => "PROJECTION",
            Self::COLOR => "COLOR",
            Self::STRING_NAME => "STRING_NAME",
            Self::NODE_PATH => "NODE_PATH",
            Self::RID => "RID",
            Self::OBJECT => "OBJECT",
            Self::CALLABLE => "CALLABLE",
            Self::SIGNAL => "SIGNAL",
            Self::DICTIONARY => "DICTIONARY",
            Self::ARRAY => "ARRAY",
            Self::PACKED_BYTE_ARRAY => "PACKED_BYTE_ARRAY",
            Self::PACKED_INT32_ARRAY => "PACKED_INT32_ARRAY",
            Self::PACKED_INT64_ARRAY => "PACKED_INT64_ARRAY",
            Self::PACKED_FLOAT32_ARRAY => "PACKED_FLOAT32_ARRAY",
            Self::PACKED_FLOAT64_ARRAY => "PACKED_FLOAT64_ARRAY",
            Self::PACKED_STRING_ARRAY => "PACKED_STRING_ARRAY",
            Self::PACKED_VECTOR2_ARRAY => "PACKED_VECTOR2_ARRAY",
            Self::PACKED_VECTOR3_ARRAY => "PACKED_VECTOR3_ARRAY",
            Self::PACKED_COLOR_ARRAY => "PACKED_COLOR_ARRAY",
            _ => "<Unknown>",
        })
    }
}

#[allow(missing_docs)]
impl VariantType {
    pub const NIL: Self = Self(0);

    // atomic types
    pub const BOOL: Self = Self(1);
    pub const INT: Self = Self(2);
    pub const FLOAT: Self = Self(3);
    pub const STRING: Self = Self(4);

    // math types
    pub const VECTOR2: Self = Self(5);
    pub const VECTOR2I: Self = Self(6);
    pub const RECT2: Self = Self(7);
    pub const RECT2I: Self = Self(8);
    pub const VECTOR3: Self = Self(9);
    pub const VECTOR3I: Self = Self(10);
    pub const TRANSFORM2D: Self = Self(11);
    pub const VECTOR4: Self = Self(12);
    pub const VECTOR4I: Self = Self(13);
    pub const PLANE: Self = Self(14);
    pub const QUATERNION: Self = Self(15);
    pub const AABB: Self = Self(16);
    pub const BASIS: Self = Self(17);
    pub const TRANSFORM3D: Self = Self(18);
    pub const PROJECTION: Self = Self(19);

    // misc types
    pub const COLOR: Self = Self(20);
    pub const STRING_NAME: Self = Self(21);
    pub const NODE_PATH: Self = Self(22);
    pub const RID: Self = Self(23);
    pub const OBJECT: Self = Self(24);
    pub const CALLABLE: Self = Self(25);
    pub const SIGNAL: Self = Self(26);
    pub const DICTIONARY: Self = Self(27);
    pub const ARRAY: Self = Self(28);

    // typed arrays
    pub const PACKED_BYTE_ARRAY: Self = Self(29);
    pub const PACKED_INT32_ARRAY: Self = Self(30);
    pub const PACKED_INT64_ARRAY: Self = Self(31);
    pub const PACKED_FLOAT32_ARRAY: Self = Self(32);
    pub const PACKED_FLOAT64_ARRAY: Self = Self(33);
    pub const PACKED_STRING_ARRAY: Self = Self(34);
    pub const PACKED_VECTOR2_ARRAY: Self = Self(35);
    pub const PACKED_VECTOR3_ARRAY: Self = Self(36);
    pub const PACKED_COLOR_ARRAY: Self = Self(37);
}

/// The most important data type in Godot.
///
/// [`Variant`](https://docs.godotengine.org/en/4.2/classes/class_variant.html)
#[derive(Copy, Clone, PartialEq, Eq, Hash, Pod, Zeroable)]
#[repr(C)]
pub struct Variant {
    /// The type of the variant.
    pub ty: VariantType,
    _padding: [u8; 7],
    /// The data of the variant. Use one of the accessors to get the data, based
    /// on the type.
    pub data: [u8; 16],
}

impl Variant {
    /// Assume the variant is a boolean and returns its value. Make sure this is
    /// the correct type beforehand.
    pub fn get_bool(&self) -> bool {
        self.data[0] != 0
    }

    /// Assume the variant is an integer and returns its value. Make sure this
    /// is the correct type beforehand.
    pub fn get_int(&self) -> i32 {
        let [i, _, _, _]: &[i32; 4] = bytemuck::cast_ref(&self.data);
        *i
    }

    /// Assume the variant is a float and returns its value. Make sure this is
    /// the correct type beforehand.
    pub fn get_float(&self) -> f32 {
        let [f, _, _, _]: &[f32; 4] = bytemuck::cast_ref(&self.data);
        *f
    }
}

impl fmt::Debug for Variant {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self.ty {
            VariantType::NIL => write!(f, "Variant::NIL"),
            VariantType::BOOL => write!(f, "Variant::BOOL({})", self.get_bool()),
            VariantType::INT => write!(f, "Variant::INT({})", self.get_int()),
            VariantType::FLOAT => write!(f, "Variant::FLOAT({})", self.get_float()),
            _ => f
                .debug_struct("Variant")
                .field("ty", &self.ty)
                .field("data", &self.data)
                .finish(),
        }
    }
}

impl SizeInTargetProcess for Variant {
    const SIZE: u64 = size_of::<Variant>() as u64;
}