aframe/
lib.rs

1#![doc = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/README.md"))]
2
3#[cfg(test)]
4pub mod tests;
5
6pub mod sys;
7pub mod shader;
8pub mod component;
9pub mod utils;
10pub mod entity;
11pub mod scene;
12pub mod assets;
13pub mod system;
14#[cfg(feature = "yew-support")]
15pub mod yew_ext;
16
17pub use shader::*;
18pub use component::*;
19pub use utils::*;
20pub use entity::*;
21pub use scene::*;
22pub use assets::*;
23pub use system::*;
24#[cfg(feature = "yew-support")]
25
26/// Async function which initializes aframe by adding the aframe script tag
27/// to the document header and waiting for the script onload event. 
28/// Current Aframe version: 1.6.0
29#[cfg(feature = "init")]
30pub async fn init_aframe() -> Result<(), InitError>
31{
32    const LINK: &'static str = "https://aframe.io/releases/1.6.0/aframe.min.js";
33    
34    use wasm_bindgen::prelude::*;
35    use std::sync::{Arc, Mutex};
36    use async_lock::Barrier;
37    use futures::executor::block_on;
38
39    let result: Arc<Mutex<Result<(), InitError>>> = Arc::new(Mutex::new(Err(InitError)));
40    let barrier = Arc::new(Barrier::new(2));
41
42    let result_outer = result.clone();
43    let barrier_inner = barrier.clone();
44
45    // Append Aframe to document
46    let document = web_sys::window()
47        .and_then(|win| win.document())
48        .ok_or(InitError)?;
49    let head = document.head()
50        .ok_or(InitError)?;
51    let script_element = document.create_element("script")
52        .map_err(|_| InitError)?;
53    let script_element = script_element.dyn_into::<web_sys::HtmlElement>()
54        .map_err(|_| InitError)?;
55    head.append_child(&script_element)
56        .map_err(|_| InitError)?;
57    let closure = 
58    {
59        Closure::once(Box::new(move || 
60        {
61            *result.lock().unwrap() = Ok(());
62            drop(result);
63            block_on(barrier_inner.wait());
64        }) as Box<dyn FnOnce()>)
65    };
66    script_element.set_onload(Some(closure.as_ref().unchecked_ref()));
67    closure.forget();
68    script_element.set_attribute("src", LINK)
69        .map_err(|_| InitError)?;
70
71    barrier.wait().await;
72    Arc::try_unwrap(result_outer)
73        .map_err(|_| InitError)
74        .and_then(|mutex| mutex.into_inner().map_err(|_| InitError))
75        .and_then(|result| result)
76}
77
78#[cfg(feature = "init")]
79#[derive(Debug, Clone, Copy)]
80pub struct InitError;
81
82#[cfg(feature = "init")]
83impl std::fmt::Display for InitError 
84{
85    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result 
86    {
87        write!(f, "Failed to initialize")
88    }
89}
90
91#[cfg(feature = "init")]
92impl std::error::Error for InitError 
93{
94    fn description(&self) -> &str 
95    {
96        "Failed to initialize"
97    }
98}