mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-19 19:54:07 +00:00
ifcviewer-web: navigation parity — view all, XYZ views, ortho, zoom-to-selected
The camera math already lived in the shared ViewportCore; the desktop just bound keys to it. The web build had no keyboard handler and no camera UI, so none of it was reachable. Wire it up (Tier 1 + 2 of nav parity; fly mode is a separate follow-up). Shared core: - setStandardView(StandardView) — named Front/Back/Left/Right/Top/Bottom wrapper over setStandardView(yaw,pitch), so the axis→angle mapping lives in one place. - frameSelection() — lifts the desktop's "union selected AABBs → frameAabb(1.30)" focus logic out of ViewportWindow into the core. Desktop's focusOnSelectedObject and the X/Y/Z hotkeys now call these (DRY, behaviour unchanged). Web: - main_web gains a keydown handler matching the desktop bindings — Home=view all, F=zoom to selected, P=ortho toggle, X/Y/Z (+Shift=negative)=standard views — plus exported entry points (view_all_c / frame_selection_c / toggle_projection_c / projection_is_ortho_c / standard_view_c) for the toolbar. - shell.html adds a bottom nav toolbar (Fit / Focus / Persp-Ortho / the six views) with the hotkeys in tooltips; the ortho button reflects state. Verified: Z key and Front button both move the camera, ortho toggles render + label, zero GPU errors; 111/111 unit + 6/6 web smoke pass. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -29,6 +29,14 @@
|
||||
#open-btn:hover { background: #3182ce; }
|
||||
#add-btn:hover { background: #3b465c; }
|
||||
#file-input { display: none; }
|
||||
/* Navigation toolbar (bottom-centre): buttons mirror the desktop hotkeys. */
|
||||
#nav-toolbar { position: fixed; bottom: 10px; left: 50%;
|
||||
transform: translateX(-50%); z-index: 10; display: flex; gap: 4px;
|
||||
background: rgba(20,22,28,.82); padding: 5px 6px; border-radius: 6px; }
|
||||
#nav-toolbar button { background: #2d3748; color: #c8ccd6; border: none;
|
||||
padding: 5px 9px; border-radius: 4px; font-size: 12px; cursor: pointer; }
|
||||
#nav-toolbar button:hover { background: #3b465c; }
|
||||
#nav-toolbar .sep { width: 1px; background: #3b465c; margin: 2px 3px; }
|
||||
/* Streaming loading UI: a thin top progress strip (aggregate) + a centred
|
||||
panel with a per-model segmented bar. Shown only while models stream. */
|
||||
#progress { position: fixed; top: 0; left: 0; right: 0; height: 3px;
|
||||
@@ -60,6 +68,18 @@
|
||||
<button id="add-btn" title="Add file(s) to the current scene (federation)">Add</button>
|
||||
<button id="open-btn">Open .ifcview…</button>
|
||||
<input id="file-input" type="file" accept=".ifcview" multiple>
|
||||
<div id="nav-toolbar">
|
||||
<button data-act="fit" title="Fit all (Home)">Fit</button>
|
||||
<button data-act="focus" title="Zoom to selected (F)">Focus</button>
|
||||
<button data-act="ortho" id="ortho-btn" title="Toggle orthographic / perspective (P)">Persp</button>
|
||||
<span class="sep"></span>
|
||||
<button data-view="0" title="Front (X)">Front</button>
|
||||
<button data-view="1" title="Back (Shift+X)">Back</button>
|
||||
<button data-view="2" title="Left (Shift+Y)">Left</button>
|
||||
<button data-view="3" title="Right (Y)">Right</button>
|
||||
<button data-view="4" title="Top (Z)">Top</button>
|
||||
<button data-view="5" title="Bottom (Shift+Z)">Bottom</button>
|
||||
</div>
|
||||
<div id="status">Starting…</div>
|
||||
<script>
|
||||
// Emscripten Module hook: route stderr to the status overlay so any
|
||||
@@ -273,6 +293,24 @@
|
||||
}
|
||||
fileInput.value = ''; // let the same file be re-picked
|
||||
});
|
||||
|
||||
// Navigation toolbar → C camera calls (same core methods as the hotkeys).
|
||||
function refreshOrthoLabel() {
|
||||
var b = document.getElementById('ortho-btn');
|
||||
if (b && Module._projection_is_ortho_c)
|
||||
b.textContent = Module._projection_is_ortho_c() ? 'Ortho' : 'Persp';
|
||||
}
|
||||
document.querySelectorAll('#nav-toolbar button').forEach(function(b) {
|
||||
b.addEventListener('click', function() {
|
||||
if (!Module._view_all_c) return; // viewer not ready yet
|
||||
var act = b.getAttribute('data-act');
|
||||
var view = b.getAttribute('data-view');
|
||||
if (act === 'fit') Module._view_all_c();
|
||||
else if (act === 'focus') Module._frame_selection_c();
|
||||
else if (act === 'ortho') { Module._toggle_projection_c(); refreshOrthoLabel(); }
|
||||
else if (view !== null) Module._standard_view_c(parseInt(view, 10));
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<!-- IfcViewerWeb.js is emitted alongside this shell by the emcc build;
|
||||
`--shell-file` injects this HTML around it. -->
|
||||
|
||||
Reference in New Issue
Block a user