use crate::sys::{registerComponent, registerGeometry};
use crate::utils::*;
use std::{borrow::Cow, collections::HashMap};
use serde::{Serialize};
use wasm_bindgen::{JsCast, prelude::*};
#[macro_export]
macro_rules! component_def
{
(
$(dependencies: $($deps:expr),*;)?
$(schema: $schema:expr,)?
$(multiple: $mult:expr,)?
$(init: $init:expr,)?
$(update: $update:expr,)?
$(tick: $tick:expr,)?
$(tock: $tock:expr,)?
$(remove: $remove:expr,)?
$(pause: $pause:expr,)?
$(play: $play:expr,)?
$(update_schema: $update_schema:expr,)?
) =>
{
$crate::component::ComponentReg
{
$(schema: $schema,)?
$(dependencies: std::borrow::Cow::Borrowed(&[$(std::borrow::Cow::Borrowed($deps)),*]),)?
$(multiple: $mult,)?
$(init: $init.into(),)?
$(update: $update.into(),)?
$(tick: $tick.into(),)?
$(tock: $tock.into(),)?
$(remove: $remove.into(),)?
$(pause: $pause.into(),)?
$(play: $play.into(),)?
$(update_schema: $update_schema.into(),)?
..$crate::component::ComponentReg::default()
}
}
}
#[macro_export]
macro_rules! geometry_def
{
(
$(schema: $schema:expr,)?
$(init: $init:expr)?
) =>
{
$crate::component::GeometryReg
{
$(schema: $schema,)?
$(init: $init.into(),)?
..$crate::component::GeometryReg::default()
}
}
}
#[derive(Serialize, Clone)]
pub struct ComponentReg
{
pub schema: HashMap<&'static str, AframeProperty>,
pub dependencies: Cow<'static, [Cow<'static, str>]>,
pub multiple: bool,
#[serde(skip)] pub init: JsValue,
#[serde(skip)] pub update: JsValue,
#[serde(skip)] pub tick: JsValue,
#[serde(skip)] pub tock: JsValue,
#[serde(skip)] pub remove: JsValue,
#[serde(skip)] pub pause: JsValue,
#[serde(skip)] pub play: JsValue,
#[serde(skip)] pub update_schema: JsValue
}
impl Default for ComponentReg
{
fn default() -> Self
{
let empty_fn: JsValue = js_sys::Function::default().into();
Self
{
schema: HashMap::new(),
dependencies: Cow::Borrowed(&[]),
multiple: false,
init: empty_fn.clone(),
update: empty_fn.clone(),
tick: empty_fn.clone(),
tock: empty_fn.clone(),
remove: empty_fn.clone(),
pause: empty_fn.clone(),
play: empty_fn.clone(),
update_schema: empty_fn
}
}
}
impl From<&ComponentReg> for JsValue
{
fn from(cmr: &ComponentReg) -> Self
{
let js_value = serde_wasm_bindgen::to_value(cmr).expect("Failed to convert ComponentReg into JsObject");
define_property(js_value.unchecked_ref(), "init", (cmr.init).unchecked_ref());
define_property(js_value.unchecked_ref(), "update", (cmr.update).unchecked_ref());
define_property(js_value.unchecked_ref(), "tick", (cmr.tick).unchecked_ref());
define_property(js_value.unchecked_ref(), "tock", (cmr.tock).unchecked_ref());
define_property(js_value.unchecked_ref(), "remove", (cmr.remove).unchecked_ref());
define_property(js_value.unchecked_ref(), "pause", (cmr.pause).unchecked_ref());
define_property(js_value.unchecked_ref(), "play", (cmr.play).unchecked_ref());
define_property(js_value.unchecked_ref(), "update_schema", (cmr.update_schema).unchecked_ref());
js_value
}
}
impl ComponentReg
{
pub unsafe fn register(self, name: &str)
{
registerComponent(name, (&self).into());
}
}
#[derive(Serialize, Clone)]
pub struct GeometryReg
{
pub schema: HashMap<&'static str, GeometryProperty>,
#[serde(skip)] pub init: JsValue,
}
impl Default for GeometryReg
{
fn default() -> Self
{
Self
{
schema: HashMap::new(),
init: js_sys::Function::default().into(),
}
}
}
impl From<&GeometryReg> for JsValue
{
fn from(cmr: &GeometryReg) -> Self
{
let js_value: JsValue = serde_wasm_bindgen::to_value(cmr).expect("Failed to convert GeometryReg into JsObject");
define_property(js_value.unchecked_ref(), "init", (cmr.init).unchecked_ref());
js_value
}
}
impl GeometryReg
{
pub unsafe fn register(self, name: &str)
{
registerGeometry(name, (&self).into());
}
}
#[derive(Serialize, Clone)]
pub struct GeometryProperty
{
default: AframeVal,
#[serde(skip_serializing_if = "Option::is_none")]
min: Option<AframeVal>,
#[serde(skip_serializing_if = "Option::is_none")]
max: Option<AframeVal>,
#[serde(skip_serializing_if = "Option::is_none")]
#[serde(rename = "type")]
component_type: Option<&'static str>
}
impl GeometryProperty
{
pub fn new(default: AframeVal, min: Option<AframeVal>, max: Option<AframeVal>, component_type: Option<&'static str>) -> Self
{
GeometryProperty{ default, component_type, min, max }
}
}