1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
use js_sys::{Promise, Array};
use crate::prelude::*;

#[wasm_bindgen]
extern "C" {
    type MeshBuilder;

    #[wasm_bindgen(static_method_of = MeshBuilder, js_namespace = BABYLON)]
    fn CreateSphere(name: &str, options: SphereOptions, scene: &Scene) -> Mesh;

    #[wasm_bindgen(static_method_of = MeshBuilder, js_namespace = BABYLON)]
    fn CreateBox(name: &str, options: BoxOptions, scene: &Scene) -> Mesh;
}

#[wasm_bindgen]
#[derive(Default)]
pub struct SphereOptions {
    pub arc: Option<f64>,
    pub diameter: Option<f64>,
    pub diameterX: Option<f64>,
    pub diameterY: Option<f64>,
    pub diameterZ: Option<f64>,
    pub segments: Option<f64>,
    pub sideOrientation: Option<f64>,
    pub slice: Option<f64>,
    pub updatable: Option<bool>,
}

#[wasm_bindgen]
#[derive(Default)]
pub struct BoxOptions {
    pub bottomBaseAt: Option<f64>,
    pub depth: Option<f64>,
    pub height: Option<f64>,
    pub sideOrientation: Option<f64>,
    pub size: Option<f64>,
    pub topBaseAt: Option<f64>,
    pub updatable: Option<bool>,
    pub width: Option<f64>,
    pub wrap: Option<bool>,
}

#[wasm_bindgen]
extern "C" {
    pub(crate) type SceneLoader;

    #[wasm_bindgen(static_method_of = SceneLoader, js_namespace = BABYLON)]
    pub(crate) fn ImportMeshAsync(meshNames: Option<&str>, rootUrl: &str, sceneFilename: &str, scene: Option<&Scene>) -> Promise;
}

impl BabylonMesh {
    pub fn create_sphere(scene: &Scene, name: &str, options: SphereOptions) -> BabylonMesh {
        BabylonMesh {
            mesh: MeshBuilder::CreateSphere(name, options, scene),
        }
    }

    pub fn create_box(scene: &Scene, name: &str, options: BoxOptions) -> BabylonMesh {
        BabylonMesh {
            mesh: MeshBuilder::CreateBox(name, options, scene),
        }
    }

    pub async fn create_gltf(scene: &Scene, name: &str, file: &str) -> BabylonMesh {
        let dummy = Mesh::new(name, scene.into());
        let promise = SceneLoader::ImportMeshAsync(None, "", file, scene.into());
        let import = wasm_bindgen_futures::JsFuture::from(promise);

        let import_result = import.await.expect("Error reading GLTF file");

        let imported_meshes = &Reflect::get(&import_result, &JsValue::from_str("meshes")).expect("Error reading GLTF file");
        let imported_meshes_array = imported_meshes.unchecked_ref::<Array>();

        for val in imported_meshes_array.iter() { 
            let mesh: &Mesh = val.unchecked_ref::<Mesh>();
            mesh.set_parent(&dummy);
        }

        BabylonMesh {
            mesh: dummy,
        }
    }
}