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}