1pub mod color;
4pub mod htmlify;
5
6pub use ::htmlify::*;
7pub use const_default::ConstDefault;
8use js_sys::{Object, Reflect};
9use wasm_bindgen::{JsCast, JsValue};
10use std::{borrow::Cow, fmt::Display};
11use serde::{Serialize, Serializer};
12pub use js_sys::Function;
13
14#[macro_export]
22macro_rules! js
23{
24 ($($arg:ident),* =>> $($tt:tt)*) =>
25 {
26 $crate::utils::Function::new_with_args(stringify!($($arg), *), stringify!($($tt)*))
27 };
28 ($($tt:tt)*) =>
29 {
30 $crate::utils::Function::new_no_args(stringify!($($tt)*))
31 }
32}
33
34#[derive(Debug, Clone, Copy, PartialEq, Serialize)]
36pub struct Vector2
37{
38 pub x: f64,
39 pub y: f64
40}
41impl ConstDefault for Vector2
42{
43 const DEFAULT: Vector2 = Vector2 { x: 0.0, y: 0.0 };
44}
45
46#[derive(Debug, Clone, Copy, PartialEq, Serialize)]
48pub struct Vector3
49{
50 pub x: f64,
51 pub y: f64,
52 pub z: f64
53}
54impl ConstDefault for Vector3
55{
56 const DEFAULT: Vector3 = Vector3 { x: 0.0, y: 0.0, z: 0.0 };
57}
58
59#[derive(Debug, Clone, Copy, PartialEq, Serialize)]
61pub struct Vector4
62{
63 pub x: f64,
64 pub y: f64,
65 pub z: f64,
66 pub w: f64
67}
68impl ConstDefault for Vector4
69{
70 const DEFAULT: Vector4 = Vector4 { x: 0.0, y: 0.0, z: 0.0, w: 0.0 };
71}
72
73impl Display for Vector2
74{
75 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result
76 {
77 write!(f, "{} {}", self.x, self.y)
78 }
79}
80
81impl Display for Vector3
82{
83 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result
84 {
85 write!(f, "{} {} {}", self.x, self.y, self.z)
86 }
87}
88
89impl Display for Vector4
90{
91 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result
92 {
93 write!(f, "{} {} {} {}", self.x, self.y, self.z, self.w)
94 }
95}
96
97pub(crate) fn define_property(src: &Object, name: &str, value: &Object)
99{
100 if src.unchecked_ref::<JsValue>() != &JsValue::UNDEFINED
101 {
102 #[allow(unused_unsafe)]
103 unsafe
104 {
105 Reflect::set(src, &JsValue::from_str(name), value).expect(&format!("Failed to define property on: {}", name));
106 }
107 }
108}
109
110#[derive(Serialize, Clone)]
113pub struct AframeProperty
114{
115 #[serde(rename = "type")]
116 component_type: &'static str,
117 #[serde(skip_serializing_if = "Option::is_none")]
118 default: Option<AframeVal>
119}
120
121impl AframeProperty
122{
123 pub fn array(default: Option<Vec<Cow<'static, str>>>) -> Self
124 {
125 Self { component_type: "array", default: default.map(AframeVal::Array) }
126 }
127
128 pub fn asset(default: Option<Cow<'static, str>>) -> Self
129 {
130 Self { component_type: "asset", default: default.map(AframeVal::Str) }
131 }
132
133 pub fn audio(default: Option<Cow<'static, str>>) -> Self
134 {
135 Self { component_type: "audio", default: default.map(AframeVal::Str) }
136 }
137
138 pub fn boolean(default: Option<bool>) -> Self
139 {
140 Self { component_type: "boolean", default: default.map(AframeVal::Bool) }
141 }
142
143 pub fn color(default: Option<Cow<'static, str>>) -> Self
144 {
145 Self { component_type: "color", default: default.map(AframeVal::Str) }
146 }
147
148 pub fn int(default: Option<i64>) -> Self
149 {
150 Self { component_type: "int", default: default.map(AframeVal::Int) }
151 }
152
153 pub fn map(default: Option<Cow<'static, str>>) -> Self
154 {
155 Self { component_type: "map", default: default.map(AframeVal::Str) }
156 }
157
158 pub fn model(default: Option<Cow<'static, str>>) -> Self
159 {
160 Self { component_type: "model", default: default.map(AframeVal::Str) }
161 }
162
163 pub fn number(default: Option<f32>) -> Self
164 {
165 Self { component_type: "number", default: default.map(AframeVal::Float) }
166 }
167
168 pub fn selector(default: Option<Cow<'static, str>>) -> Self
169 {
170 Self { component_type: "selector", default: default.map(AframeVal::Str) }
171 }
172
173 pub fn selector_all(default: Option<Cow<'static, str>>) -> Self
174 {
175 Self { component_type: "selectorAll", default: default.map(AframeVal::Str) }
176 }
177
178 pub fn string(default: Option<Cow<'static, str>>) -> Self
179 {
180 Self { component_type: "string", default: default.map(AframeVal::Str) }
181 }
182
183 pub fn vec2(default: Option<Vector2>) -> Self
184 {
185 Self { component_type: "vec2", default: default.map(AframeVal::Vec2) }
186 }
187
188 pub fn vec3(default: Option<Vector3>) -> Self
189 {
190 Self { component_type: "vec3", default: default.map(AframeVal::Vec3) }
191 }
192
193 pub fn vec4(default: Option<Vector4>) -> Self
194 {
195 Self { component_type: "vec4", default: default.map(AframeVal::Vec4) }
196 }
197}
198
199#[derive(Clone)]
200pub enum AframeVal
201{
202 Array(Vec<Cow<'static, str>>),
203 Bool(bool),
204 Int(i64),
205 Str(Cow<'static, str>),
206 Float(f32),
207 Vec2(Vector2),
208 Vec3(Vector3),
209 Vec4(Vector4)
210}
211
212impl Serialize for AframeVal
213{
214 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error>
215 {
216 match self
217 {
218 Self::Str(s) => s.serialize(serializer),
219 Self::Float(f) => f.serialize(serializer),
220 Self::Vec2(vec) => vec.serialize(serializer),
221 Self::Vec3(vec) => vec.serialize(serializer),
222 Self::Vec4(vec) => vec.serialize(serializer),
223 Self::Array(arr) => arr.serialize(serializer),
224 Self::Bool(b) => b.serialize(serializer),
225 Self::Int(i) => i.serialize(serializer),
226 }
227 }
228}