Skip to content

Commit 39529de

Browse files
authored
Test all remaining wasm bindings (#2554)
1 parent 7e74262 commit 39529de

File tree

7 files changed

+156
-10
lines changed

7 files changed

+156
-10
lines changed

doc/libf3d/LANGUAGE_BINDINGS.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ public class F3DExample {
5454
}
5555
```
5656

57-
## Javascript (experimental)
57+
## Javascript
5858

5959
If the Javascript bindings have been generated by building F3D with webassembly and emscriptem, the libf3d can be used directly from a browser.
6060

@@ -124,3 +124,11 @@ f3d(settings)
124124
console.error("Internal exception: " + error);
125125
});
126126
```
127+
128+
Some advanced libf3d API are not bound yet, here's the exhaustive list:
129+
130+
- `f3d::scene`: light related functions
131+
- `f3d::scene`: `scene& add(const mesh_t& mesh)`
132+
- `f3d::camera`: state management
133+
- `f3d::interactor`: bindings related functions
134+
- `f3d::interactor`: `playInteraction` and `recordInteraction`
Lines changed: 3 additions & 0 deletions
Loading

webassembly/F3DEmscriptenBindings.cxx

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -284,10 +284,22 @@ EMSCRIPTEN_BINDINGS(f3d)
284284
.function("render", &f3d::window::render)
285285
.function("renderToImage", &f3d::window::renderToImage)
286286
.function("setSize", &f3d::window::setSize, emscripten::return_value_policy::reference())
287-
.function("getWidth", &f3d::window::getWidth)
288-
.function("getHeight", &f3d::window::getHeight)
289-
.function("getWorldFromDisplay", &f3d::window::getWorldFromDisplay)
290-
.function("getDisplayFromWorld", &f3d::window::getDisplayFromWorld);
287+
.property("width", &f3d::window::getWidth)
288+
.property("height", &f3d::window::getHeight)
289+
.function(
290+
"getWorldFromDisplay",
291+
+[](const f3d::window& win, emscripten::val jsArray) -> emscripten::val
292+
{
293+
return containerToJSArray(win.getWorldFromDisplay(
294+
{ jsArray[0].as<float>(), jsArray[1].as<float>(), jsArray[2].as<float>() }));
295+
})
296+
.function(
297+
"getDisplayFromWorld",
298+
+[](const f3d::window& win, emscripten::val jsArray) -> emscripten::val
299+
{
300+
return containerToJSArray(win.getDisplayFromWorld(
301+
{ jsArray[0].as<float>(), jsArray[1].as<float>(), jsArray[2].as<float>() }));
302+
});
291303

292304
// f3d::interactor
293305
// Not bound on purpose because usually used for external interactors:
@@ -298,11 +310,24 @@ EMSCRIPTEN_BINDINGS(f3d)
298310
.function(
299311
"initCommands", &f3d::interactor::initCommands, emscripten::return_value_policy::reference())
300312
.function(
301-
"addCommand", &f3d::interactor::addCommand, emscripten::return_value_policy::reference())
313+
"addCommand",
314+
+[](f3d::interactor& interactor, const std::string& action,
315+
const emscripten::val& callback) -> f3d::interactor&
316+
{
317+
auto wrapCallback = [=](const std::vector<std::string>& args)
318+
{ callback(containerToJSArray(args)); };
319+
return interactor.addCommand(action, wrapCallback);
320+
},
321+
emscripten::return_value_policy::reference())
302322
.function("removeCommand", &f3d::interactor::removeCommand,
303323
emscripten::return_value_policy::reference())
304-
.function("getCommandActions", &f3d::interactor::getCommandActions)
305-
.function("triggerCommand", &f3d::interactor::triggerCommand)
324+
.function(
325+
"getCommandActions", +[](const f3d::interactor& interactor) -> emscripten::val
326+
{ return containerToJSArray(interactor.getCommandActions()); })
327+
.function(
328+
"triggerCommand",
329+
+[](f3d::interactor& interactor, const std::string& command, bool keepComments) -> bool
330+
{ return interactor.triggerCommand(command, keepComments); })
306331
.function("toggleAnimation", &f3d::interactor::toggleAnimation,
307332
emscripten::return_value_policy::reference())
308333
.function("startAnimation", &f3d::interactor::startAnimation,
@@ -314,8 +339,6 @@ EMSCRIPTEN_BINDINGS(f3d)
314339
emscripten::return_value_policy::reference())
315340
.function("disableCameraMovement", &f3d::interactor::disableCameraMovement,
316341
emscripten::return_value_policy::reference())
317-
.function("playInteraction", &f3d::interactor::playInteraction)
318-
.function("recordInteraction", &f3d::interactor::recordInteraction)
319342
.function(
320343
"start", +[](f3d::interactor& interactor) -> f3d::interactor& { return interactor.start(); },
321344
emscripten::return_value_policy::reference())

webassembly/testing/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ set(f3djsTests_list
22
"test_camera"
33
"test_engine"
44
"test_image"
5+
"test_interactor"
56
"test_options"
67
"test_render"
78
"test_scene"
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import utils from "./utils.js";
2+
3+
const settings = {
4+
runBefore: (Module) => {
5+
// does nothing but called for coverage
6+
Module.engineInstance.getScene().clear();
7+
8+
const options = Module.engineInstance.getOptions();
9+
10+
// background must be set to black for proper blending with transparent canvas
11+
options.setAsString("render.background.color", "#000000");
12+
13+
// display widgets
14+
options.toggle("ui.axis");
15+
options.toggle("render.grid.enable");
16+
},
17+
18+
runAfter: (Module) => {
19+
const interactor = Module.engineInstance.getInteractor();
20+
21+
// commands
22+
interactor.initCommands();
23+
24+
let callbackCalled = false;
25+
26+
interactor.addCommand("foo", (args) => {
27+
utils.assert(args[0] === "bar");
28+
callbackCalled = true;
29+
});
30+
31+
utils.assert(
32+
interactor.getCommandActions().includes("foo"),
33+
"command not added",
34+
);
35+
36+
interactor.triggerCommand("foo bar baz", true);
37+
38+
utils.assert(callbackCalled, "command callback not called");
39+
40+
interactor.removeCommand("foo");
41+
utils.assert(
42+
!interactor.getCommandActions().includes("foo"),
43+
"command not removed",
44+
);
45+
46+
// animations
47+
utils.assert(
48+
!interactor.isPlayingAnimation(),
49+
"animation should not be playing",
50+
);
51+
52+
interactor.startAnimation();
53+
utils.assert(
54+
interactor.isPlayingAnimation(),
55+
"animation should be playing",
56+
);
57+
58+
interactor.stopAnimation();
59+
utils.assert(
60+
!interactor.isPlayingAnimation(),
61+
"animation should not be playing",
62+
);
63+
64+
interactor.toggleAnimation();
65+
utils.assert(
66+
interactor.isPlayingAnimation(),
67+
"animation should be playing",
68+
);
69+
70+
// only for coverage, do not test the actual feature yet
71+
interactor.disableCameraMovement();
72+
interactor.enableCameraMovement();
73+
interactor.requestRender();
74+
interactor.stop();
75+
},
76+
};
77+
78+
utils.runRenderTest(settings, {
79+
data: "f3d.glb",
80+
baseline: "TestWasmInteraction.png",
81+
});

webassembly/testing/test_render.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,25 @@ const settings = {
2626
// default to +Z
2727
options.setAsString("scene.up_direction", "+Z");
2828
},
29+
30+
runAfter: (Module) => {
31+
// check that space conversion works
32+
const window = Module.engineInstance.getWindow();
33+
34+
const ptWorld = window.getWorldFromDisplay([0, 0, 0]);
35+
36+
utils.assert(
37+
!utils.numArrayEquals(ptWorld, [0, 0, 0], 0.001),
38+
"point has no been transformed",
39+
);
40+
41+
const ptDisplay = window.getDisplayFromWorld(ptWorld);
42+
43+
utils.assert(
44+
utils.numArrayEquals(ptDisplay, [0, 0, 0], 0.001),
45+
"point has no been restored to original value",
46+
);
47+
},
2948
};
3049

3150
utils.runRenderTest(settings, {

webassembly/testing/utils.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,17 @@ const utils = {
9090
scale * Module.canvas.clientHeight,
9191
);
9292

93+
utils.assert(
94+
Module.engineInstance.getWindow().width ===
95+
scale * Module.canvas.clientWidth,
96+
"Failed to get width",
97+
);
98+
utils.assert(
99+
Module.engineInstance.getWindow().height ===
100+
scale * Module.canvas.clientHeight,
101+
"Failed to get height",
102+
);
103+
93104
const scene = Module.engineInstance.getScene();
94105

95106
utils.assert(

0 commit comments

Comments
 (0)