ifcviewer-web: let host pages choose the mouse nav preset

ViewportCore has had a preset table (blender / rhino / revit / web) since the
nav bindings were shared with the desktop, and the web input handlers already
classify presses against it — but main() hard-coded "web" and nothing could
reach setNavPreset from JS, so every page was stuck on LMB-orbit.

Export ifcv_set_nav_preset_c and wrap it as IfcViewer.create's `navPreset`
option plus a setNavPreset() method. The preset is only the button/modifier
table, so it needs no GPU state: it applies as soon as the module resolves,
which means the first drag already uses the host's scheme rather than
flipping after a frame or two.

Names are validated in JS against the four the core knows. The core silently
falls back to blender for anything unrecognised, which would turn a typo into
a mystery change of scheme rather than an error.

The default stays "web", so existing pages and the smoke tests are unaffected.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Dion Moult
2026-07-28 15:44:37 +10:00
parent 6bcfb175a3
commit 8cc96127ce
3 changed files with 50 additions and 5 deletions
+13
View File
@@ -627,6 +627,17 @@ extern "C" EMSCRIPTEN_KEEPALIVE void ifcv_set_ortho_c(int on) {
if (bool(on) != g_app->core.projectionOrtho()) g_app->core.toggleProjection();
}
// Mouse navigation scheme: "blender" | "rhino" | "revit" | "web". The preset
// only rewrites the button/modifier table classifyPress reads, so unlike the
// rest of the scripting API it does not need the GPU app to be live — a host
// page can pick its scheme the moment the module resolves. Unknown names fall
// back to blender inside the core; web/ifcviewer.js rejects them before they
// get here so a typo is an error rather than a silent scheme change.
extern "C" EMSCRIPTEN_KEEPALIVE void ifcv_set_nav_preset_c(const char* name) {
if (!g_app || !name) return;
g_app->core.setNavPreset(name);
}
// Selection.
extern "C" EMSCRIPTEN_KEEPALIVE int ifcv_get_selection_c(std::uint32_t* out, int max) {
if (!g_app || !g_app->ready) return 0;
@@ -778,6 +789,8 @@ int main(int /*argc*/, char** /*argv*/) {
Log::info() << "ifcviewer-web: starting";
g_app = new AppState();
// Default to the web mouse scheme: LMB orbit, MMB pan, RMB select/marquee.
// Host pages override it with ifcv_set_nav_preset_c (IfcViewer.create's
// `navPreset` option) — e.g. "blender" for MMB-orbit.
g_app->core.setNavPreset("web");
g_app->core.initWgpuAsyncWeb([](bool ok) {
if (!ok) {