Skip to main content

babylon/
api.rs

1use alloc::boxed::Box;
2use js_ffi::*;
3
4pub struct BabylonApi {
5    fn_log: JSInvoker,
6    fn_error: JSInvoker,
7    fn_debug: JSInvoker,
8    fn_random: JSInvoker,
9    fn_create_basic_scene: JSInvoker,
10    fn_create_scene: JSInvoker,
11    fn_create_sphere: JSInvoker,
12    fn_create_cube: JSInvoker,
13    fn_create_standard_material: JSInvoker,
14    fn_dispose_mesh: JSInvoker,
15    fn_set_position: JSInvoker,
16    fn_set_scaling: JSInvoker,
17    fn_set_material: JSInvoker,
18    fn_set_emmisive_color: JSInvoker,
19    fn_set_diffuse_color: JSInvoker,
20    fn_set_specular_color: JSInvoker,
21    fn_set_ambient_color: JSInvoker,
22    fn_set_clear_color: JSInvoker,
23    fn_set_alpha: JSInvoker,
24    fn_add_keyboard_observable: JSInvoker,
25    fn_add_observable: JSInvoker,
26    fn_get_delta_time: JSInvoker,
27    fn_create_arc_rotate_camera: JSInvoker,
28    fn_create_hemispheric_light: JSInvoker,
29    fn_create_point_light: JSInvoker,
30    fn_create_gltf: JSInvoker,
31}
32
33impl Default for BabylonApi {
34    fn default() -> Self {
35        BabylonApi {
36            fn_create_basic_scene: register_function(
37                r#"
38                function(selector){
39                    var canvas = document.querySelector(selector);
40                    var engine = new BABYLON.Engine(canvas, true); 
41                    var createScene = function () {
42                        var scene = new BABYLON.Scene(engine);
43                        scene.createDefaultEnvironment({
44                            createGround: false,
45                            createSkybox: false,
46                        });
47    
48                        // Add a camera to the scene and attach it to the canvas
49                        var camera = new BABYLON.ArcRotateCamera(
50                            "Camera",
51                            Math.PI / 2,
52                            Math.PI / 2,
53                            2,
54                            BABYLON.Vector3.Zero(),
55                            scene
56                        );
57                        camera.attachControl(canvas, true);
58    
59                        // Add lights to the scene
60                        var light1 = new BABYLON.HemisphericLight(
61                            "light1",
62                            new BABYLON.Vector3(1, 1, 0),
63                            scene
64                        );
65                        var light2 = new BABYLON.PointLight(
66                            "light2",
67                            new BABYLON.Vector3(0, 1, -1),
68                            scene
69                        );
70    
71                        return scene;
72                    };
73                    var scene = createScene();
74                    engine.runRenderLoop(function () {
75                            scene.render();
76                    });
77                    window.addEventListener("resize", function () {
78                            engine.resize();
79                    });
80                    return scene;
81                }
82            "#,
83            ),
84            fn_create_scene: register_function(
85                r#"
86                function(selector){
87                    var canvas = document.querySelector(selector);
88                    var engine = new BABYLON.Engine(canvas, true); 
89                    var createScene = function () {
90                        var scene = new BABYLON.Scene(engine);
91                        return scene;
92                    };
93                    var scene = createScene();
94                    engine.runRenderLoop(function () {
95                            scene.render();
96                    });
97                    window.addEventListener("resize", function () {
98                            engine.resize();
99                    });
100                    return scene;
101                }
102            "#,
103            ),
104            fn_create_sphere: register_function(
105                r#"
106                function(scene,size){
107                    return BABYLON.MeshBuilder.CreateSphere(
108                        null,
109                        { diameter: size },
110                        scene);
111                }
112            "#,
113            ),
114            fn_create_cube: register_function(
115                r#"
116                function(scene,w,h,d){
117                    return BABYLON.MeshBuilder.CreateBox(
118                        null,
119                        { height: h, width: w, depth: d },
120                        scene);
121                }
122            "#,
123            ),
124            fn_create_standard_material: register_function(
125                r#"
126                function(scene){
127                    return new BABYLON.StandardMaterial(null, scene);
128                }
129            "#,
130            ),
131            fn_dispose_mesh: register_function(
132                r#"
133                function(mesh){
134                    mesh.dispose()
135                }
136            "#,
137            ),
138            fn_log: register_function(
139                r#"
140                function(msg){
141                    console.log(msg);
142                }
143            "#,
144            ),
145            fn_error: register_function(
146                r#"
147                function(msg){
148                    console.error(msg);
149                }
150            "#,
151            ),
152            fn_debug: register_function(
153                r#"
154                function(){
155                    debugger;
156                }
157            "#,
158            ),
159            fn_random: register_function(
160                r#"
161                function(){
162                    return Math.random();
163                }
164            "#,
165            ),
166            fn_set_position: register_function(
167                r#"
168                function(mesh,x,y,z){
169                    mesh.position = new BABYLON.Vector3(x,y,z);
170                }
171            "#,
172            ),
173            fn_set_scaling: register_function(
174                r#"
175                function(mesh,x,y,z){
176                    mesh.scaling = new BABYLON.Vector3(x,y,z);
177                }
178            "#,
179            ),
180            fn_set_material: register_function(
181                r#"
182                function(mesh,mat){
183                    mesh.material = mat;
184                }
185            "#,
186            ),
187            fn_set_emmisive_color: register_function(
188                r#"
189                function(mat,r,g,b){
190                    mat.emissiveColor = new BABYLON.Color3(r, g, b);
191                }
192            "#,
193            ),
194            fn_set_diffuse_color: register_function(
195                r#"
196                function(mat,r,g,b){
197                    mat.diffuseColor = new BABYLON.Color3(r, g, b);
198                }
199            "#,
200            ),
201            fn_set_specular_color: register_function(
202                r#"
203                function(mat,r,g,b){
204                    mat.specularColor = new BABYLON.Color3(r, g, b);
205                }
206            "#,
207            ),
208            fn_set_ambient_color: register_function(
209                r#"
210                function(mat,r,g,b){
211                    mat.ambientColor = new BABYLON.Color3(r, g, b);
212                }
213            "#,
214            ),
215            fn_set_clear_color: register_function(
216                r#"
217                function(scene,r,g,b){
218                    scene.clearColor = new BABYLON.Color3(r, g, b);
219                }
220            "#,
221            ),
222            fn_set_alpha: register_function(
223                r#"
224                function(mat,a){
225                    mat.alpha = a;
226                }
227            "#,
228            ),
229            fn_add_keyboard_observable: register_function(
230                r#"
231                function(scene,cb){
232                    scene.onKeyboardObservable.add((kbInfo) => {
233                        cb(kbInfo.type,kbInfo.event.keyCode)
234                    });
235                }
236            "#,
237            ),
238            fn_add_observable: register_function(
239                r#"
240                function(scene,name,cb){
241                    scene[name].add(() => {
242                        cb()
243                    });
244                }
245            "#,
246            ),
247            fn_get_delta_time: register_function(
248                r#"
249                function(scene){
250                    return scene.getEngine().getDeltaTime();
251                }
252            "#,
253            ),
254            fn_create_arc_rotate_camera: register_function(
255                r#"
256                function(scene){
257                    var camera = new BABYLON.ArcRotateCamera(
258                        "Camera",
259                        Math.PI / 2,
260                        Math.PI / 2,
261                        2,
262                        BABYLON.Vector3.Zero(),
263                        scene
264                    );
265                    return camera;
266                }
267            "#,
268            ),
269            fn_create_hemispheric_light: register_function(
270                r#"
271                function(scene){
272                    var light = new BABYLON.HemisphericLight(
273                        null,
274                        new BABYLON.Vector3(1, 1, 0),
275                        scene
276                    );
277                    return light;
278                }
279            "#,
280            ),
281            fn_create_point_light: register_function(
282                r#"
283                function(scene){
284                    var light = new BABYLON.PointLight(
285                        null,
286                        new BABYLON.Vector3(0, 1, -1),
287                        scene
288                    );
289                    return light;
290                }
291            "#,
292            ),
293            fn_create_gltf: register_function(
294                r#"
295                function(scene,file){
296                    var dummy = new BABYLON.Mesh(null, scene);
297                    BABYLON.SceneLoader.ImportMesh(null, "", file, scene, function (newMeshes, particleSystems, skeletons) {
298                        for(v in newMeshes){
299                            var dude = newMeshes[v];
300                            dude.parent = dummy;
301                        }
302                    });
303                    return dummy;
304                }
305                "#,
306            ),
307        }
308    }
309}
310
311impl BabylonApi {
312    pub fn create_basic_scene(selector: &str) -> JSObject {
313        let api = globals::get::<BabylonApi>();
314        api.fn_create_basic_scene.invoke_1(selector).to_js_object()
315    }
316    pub fn create_scene(selector: &str) -> JSObject {
317        let api = globals::get::<BabylonApi>();
318        api.fn_create_scene.invoke_1(selector).to_js_object()
319    }
320    pub fn create_sphere(scene_ref: &JSObject, size: f64) -> JSObject {
321        let api = globals::get::<BabylonApi>();
322        api.fn_create_sphere
323            .invoke_2(scene_ref, size)
324            .to_js_object()
325    }
326
327    pub fn create_cube(scene_ref: &JSObject, width: f64, height: f64, depth: f64) -> JSObject {
328        let api = globals::get::<BabylonApi>();
329        api.fn_create_cube
330            .invoke_4(scene_ref, width, height, depth)
331            .to_js_object()
332    }
333
334    pub fn create_standard_material(scene_ref: &JSObject) -> JSObject {
335        let api = globals::get::<BabylonApi>();
336        api.fn_create_standard_material
337            .invoke_1(scene_ref)
338            .to_js_object()
339    }
340
341    pub fn dispose_mesh(mesh: &JSObject) {
342        let api = globals::get::<BabylonApi>();
343        api.fn_dispose_mesh.invoke_1(mesh);
344    }
345
346    pub fn log(msg: &str) {
347        let api = globals::get::<BabylonApi>();
348        api.fn_log.invoke_1(msg);
349    }
350
351    pub fn error(msg: &str) {
352        let api = globals::get::<BabylonApi>();
353        api.fn_error.invoke_1(msg);
354    }
355
356    pub fn debugger() {
357        let api = globals::get::<BabylonApi>();
358        api.fn_debug.invoke_0();
359    }
360
361    pub fn random() -> f64 {
362        let api = globals::get::<BabylonApi>();
363        api.fn_random.invoke_0()
364    }
365
366    pub fn set_position(mesh: &JSObject, x: f64, y: f64, z: f64) {
367        let api = globals::get::<BabylonApi>();
368        api.fn_set_position.invoke_4(mesh, x, y, z);
369    }
370
371    pub fn set_scaling(mesh: &JSObject, x: f64, y: f64, z: f64) {
372        let api = globals::get::<BabylonApi>();
373        api.fn_set_scaling.invoke_4(mesh, x, y, z);
374    }
375
376    pub fn set_material(mesh: &JSObject, mat: &JSObject) {
377        let api = globals::get::<BabylonApi>();
378        api.fn_set_material.invoke_2(mesh, mat);
379    }
380
381    pub fn set_emmisive_color(mat: &JSObject, r: f64, g: f64, b: f64) {
382        let api = globals::get::<BabylonApi>();
383        api.fn_set_emmisive_color.invoke_4(mat, r, g, b);
384    }
385
386    pub fn set_diffuse_color(mat: &JSObject, r: f64, g: f64, b: f64) {
387        let api = globals::get::<BabylonApi>();
388        api.fn_set_diffuse_color.invoke_4(mat, r, g, b);
389    }
390
391    pub fn set_specular_color(mat: &JSObject, r: f64, g: f64, b: f64) {
392        let api = globals::get::<BabylonApi>();
393        api.fn_set_specular_color.invoke_4(mat, r, g, b);
394    }
395
396    pub fn set_ambient_color(mat: &JSObject, r: f64, g: f64, b: f64) {
397        let api = globals::get::<BabylonApi>();
398        api.fn_set_ambient_color.invoke_4(mat, r, g, b);
399    }
400
401    pub fn set_clear_color(mat: &JSObject, r: f64, g: f64, b: f64) {
402        let api = globals::get::<BabylonApi>();
403        api.fn_set_clear_color.invoke_4(mat, r, g, b);
404    }
405
406    pub fn set_alpha(mat: &JSObject, a: f64) {
407        let api = globals::get::<BabylonApi>();
408        api.fn_set_alpha.invoke_2(mat, a);
409    }
410
411    pub fn add_keyboard_observable(
412        scene: &JSObject,
413        callback: Box<dyn FnMut(JSValue, JSValue) -> () + Send>,
414    ) {
415        let cb = create_callback_2(callback);
416        let api = globals::get::<BabylonApi>();
417        api.fn_add_keyboard_observable.invoke_2(scene, cb);
418    }
419
420    pub fn add_observable(
421        scene: &JSObject,
422        observable_name: &str,
423        callback: Box<dyn FnMut() -> () + Send>,
424    ) {
425        let cb = create_callback_0(callback);
426        let api = globals::get::<BabylonApi>();
427        api.fn_add_observable.invoke_3(scene, observable_name, cb);
428    }
429
430    pub fn get_delta_time(scene: &JSObject) -> f64 {
431        let api = globals::get::<BabylonApi>();
432        api.fn_get_delta_time.invoke_1(scene)
433    }
434
435    pub fn create_arc_rotate_camera(scene: &JSObject) -> JSObject {
436        let api = globals::get::<BabylonApi>();
437        api.fn_create_arc_rotate_camera
438            .invoke_1(scene)
439            .to_js_object()
440    }
441
442    pub fn create_hemispheric_light(scene: &JSObject) -> JSObject {
443        let api = globals::get::<BabylonApi>();
444        api.fn_create_hemispheric_light
445            .invoke_1(scene)
446            .to_js_object()
447    }
448
449    pub fn create_point_light(scene: &JSObject) -> JSObject {
450        let api = globals::get::<BabylonApi>();
451        api.fn_create_point_light.invoke_1(scene).to_js_object()
452    }
453
454    pub fn create_gltf(scene: &JSObject, file: &str) -> JSObject {
455        let api = globals::get::<BabylonApi>();
456        api.fn_create_gltf
457            .invoke_2(scene, file)
458            .to_js_object()
459    }
460}