Skip to main content

pite_core/
props.rs

1// SPDX-License-Identifier: MIT OR Apache-2.0
2use std::collections::HashMap;
3
4/// An 8-bit per channel sRGB color with straight (unmultiplied) alpha.
5#[derive(Clone, Copy, Debug, PartialEq, Eq)]
6pub struct Color {
7    pub r: u8,
8    pub g: u8,
9    pub b: u8,
10    pub a: u8,
11}
12
13impl Color {
14    pub const WHITE: Color = Color {
15        r: 255,
16        g: 255,
17        b: 255,
18        a: 255,
19    };
20    pub const BLACK: Color = Color {
21        r: 0,
22        g: 0,
23        b: 0,
24        a: 255,
25    };
26    pub const TRANSPARENT: Color = Color {
27        r: 0,
28        g: 0,
29        b: 0,
30        a: 0,
31    };
32
33    pub const fn new(r: u8, g: u8, b: u8, a: u8) -> Self {
34        Self { r, g, b, a }
35    }
36
37    pub const fn rgb(r: u8, g: u8, b: u8) -> Self {
38        Self { r, g, b, a: 255 }
39    }
40
41    pub const fn to_array(self) -> [u8; 4] {
42        [self.r, self.g, self.b, self.a]
43    }
44}
45
46impl Default for Color {
47    fn default() -> Self {
48        Self::WHITE
49    }
50}
51
52impl From<[u8; 4]> for Color {
53    fn from(v: [u8; 4]) -> Self {
54        Self {
55            r: v[0],
56            g: v[1],
57            b: v[2],
58            a: v[3],
59        }
60    }
61}
62
63impl From<Color> for [u8; 4] {
64    fn from(c: Color) -> Self {
65        [c.r, c.g, c.b, c.a]
66    }
67}
68
69/// Dynamically-typed property values supported by the engine's scene and node model.
70#[derive(Clone, Debug, PartialEq)]
71pub enum PropValue {
72    /// String text value.
73    Str(String),
74    /// Floating-point number.
75    Num(f64),
76    /// Signed integer value.
77    Int(i64),
78    /// Boolean flag.
79    Bool(bool),
80    /// 2D vector coordinate pair `(x, y)`.
81    Vec2(f64, f64),
82    /// RGBA color represented as 8-bit channels `(r, g, b, a)`.
83    Color(u8, u8, u8, u8),
84}
85
86impl PropValue {
87    /// Returns the value as [`Color`] if this is a [`PropValue::Color`] variant.
88    pub fn as_color(&self) -> Option<Color> {
89        match self {
90            PropValue::Color(r, g, b, a) => Some(Color::new(*r, *g, *b, *a)),
91            _ => None,
92        }
93    }
94
95    /// Returns the canonical type name string (e.g. `"string"`, `"vec2"`), used in diagnostics.
96    pub const fn type_name(&self) -> &'static str {
97        match self {
98            PropValue::Str(_) => "string",
99            PropValue::Num(_) => "number",
100            PropValue::Int(_) => "int",
101            PropValue::Bool(_) => "bool",
102            PropValue::Vec2(_, _) => "vec2",
103            PropValue::Color(_, _, _, _) => "color",
104        }
105    }
106}
107
108/// Supported type declarations permitted in manifest `[props]` tables.
109pub const CUSTOM_PROP_TYPES: &[&str] = &["string", "int", "number", "bool", "vec2", "color"];
110
111/// Key-value property map associated with a [`Node`](crate::Node).
112///
113/// Unrecognized property keys are safely preserved during deserialization and serialization.
114#[derive(Clone, Debug, Default, PartialEq)]
115pub struct Props(pub HashMap<String, PropValue>);
116
117impl Props {
118    /// Retrieves a reference to a property value by key.
119    pub fn get(&self, key: &str) -> Option<&PropValue> {
120        self.0.get(key)
121    }
122
123    /// Inserts or updates a property value by key.
124    pub fn insert(&mut self, key: impl Into<String>, value: PropValue) {
125        self.0.insert(key.into(), value);
126    }
127}