dreamwell_engine/physics/
properties.rs1use super::tags::TagSet;
2use serde::{Deserialize, Serialize};
3
4pub type PropertyKey = u32;
6
7#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
9pub enum PropertyValue {
10 Bool(bool),
11 Int(i32),
12 Float(f32),
13 Vec2([f32; 2]),
14 Vec3([f32; 3]),
15 Vec4([f32; 4]),
16 Tag(String),
17 Enum(String),
18 String(String),
19}
20
21#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
23pub enum PropertyEnum {
24 Material(super::materials::MaterialClass),
25 Custom(String),
26}
27
28#[derive(Debug, Clone, Serialize, Deserialize)]
30pub struct PropertyAssignment {
31 pub key: String,
32 pub value: PropertyValue,
33}
34
35#[derive(Debug, Clone, Serialize, Deserialize)]
37pub enum PropertyPredicate {
38 GreaterThan(String, f32),
39 LessThan(String, f32),
40 EqualsBool(String, bool),
41 EqualsEnum(String, String),
42}
43
44#[derive(Debug, Clone, Default)]
49pub struct SemanticProperties {
50 pub traits: TagSet,
51 pub signals: TagSet,
52 pub receivers: TagSet,
53 pub scalars: Vec<(PropertyKey, f32)>,
54 pub vectors: Vec<(PropertyKey, [f32; 4])>,
55 pub ints: Vec<(PropertyKey, i32)>,
56 pub bools: Vec<(PropertyKey, bool)>,
57 pub enums: Vec<(PropertyKey, PropertyEnum)>,
58}
59
60fn vec_insert<V>(entries: &mut Vec<(PropertyKey, V)>, key: PropertyKey, value: V) {
62 match entries.binary_search_by_key(&key, |(k, _)| *k) {
63 Ok(idx) => entries[idx].1 = value,
64 Err(idx) => entries.insert(idx, (key, value)),
65 }
66}
67
68fn vec_get<V: Copy>(entries: &[(PropertyKey, V)], key: PropertyKey) -> Option<V> {
70 entries
71 .binary_search_by_key(&key, |(k, _)| *k)
72 .ok()
73 .map(|idx| entries[idx].1)
74}
75
76fn vec_get_ref<V>(entries: &[(PropertyKey, V)], key: PropertyKey) -> Option<&V> {
78 entries
79 .binary_search_by_key(&key, |(k, _)| *k)
80 .ok()
81 .map(|idx| &entries[idx].1)
82}
83
84impl SemanticProperties {
85 pub fn new() -> Self {
86 Self::default()
87 }
88
89 pub fn set_scalar(&mut self, key: PropertyKey, value: f32) {
90 vec_insert(&mut self.scalars, key, value);
91 }
92
93 pub fn get_scalar(&self, key: PropertyKey) -> Option<f32> {
94 vec_get(&self.scalars, key)
95 }
96
97 pub fn set_bool(&mut self, key: PropertyKey, value: bool) {
98 vec_insert(&mut self.bools, key, value);
99 }
100
101 pub fn get_bool(&self, key: PropertyKey) -> Option<bool> {
102 vec_get(&self.bools, key)
103 }
104
105 pub fn set_int(&mut self, key: PropertyKey, value: i32) {
106 vec_insert(&mut self.ints, key, value);
107 }
108
109 pub fn get_int(&self, key: PropertyKey) -> Option<i32> {
110 vec_get(&self.ints, key)
111 }
112
113 pub fn set_vec4(&mut self, key: PropertyKey, value: [f32; 4]) {
114 vec_insert(&mut self.vectors, key, value);
115 }
116
117 pub fn get_vec4(&self, key: PropertyKey) -> Option<[f32; 4]> {
118 vec_get(&self.vectors, key)
119 }
120
121 pub fn get_enum(&self, key: PropertyKey) -> Option<&PropertyEnum> {
122 vec_get_ref(&self.enums, key)
123 }
124
125 pub fn set_enum(&mut self, key: PropertyKey, value: PropertyEnum) {
126 vec_insert(&mut self.enums, key, value);
127 }
128}
129
130#[cfg(test)]
131mod tests {
132 use super::*;
133
134 #[test]
135 fn semantic_properties_scalar_roundtrip() {
136 let mut props = SemanticProperties::new();
137 props.set_scalar(0, 42.0);
138 assert_eq!(props.get_scalar(0), Some(42.0));
139 assert_eq!(props.get_scalar(1), None);
140 }
141
142 #[test]
143 fn semantic_properties_bool_roundtrip() {
144 let mut props = SemanticProperties::new();
145 props.set_bool(5, true);
146 assert_eq!(props.get_bool(5), Some(true));
147 }
148
149 #[test]
150 fn property_value_serde_roundtrip() {
151 let val = PropertyValue::Float(3.14);
152 let json = serde_json::to_string(&val).unwrap();
153 let restored: PropertyValue = serde_json::from_str(&json).unwrap();
154 assert_eq!(val, restored);
155 }
156
157 #[test]
158 fn property_assignment_serde() {
159 let pa = PropertyAssignment {
160 key: "durability".to_string(),
161 value: PropertyValue::Float(600.0),
162 };
163 let json = serde_json::to_string(&pa).unwrap();
164 assert!(json.contains("durability"));
165 }
166}