ifcviewer-web: draw the axis indicator (corner gizmo + orbit pivot)

The desktop viewport draws an RGB triad in the bottom-left corner and a
second one at the orbit target while navigating; the web build drew
neither. Both lived in the Qt-coupled OverlayRenderer, which only
ViewportWindow drives — the web host no-ops the overlay hooks — so the
wasm build had no path to them at all.

Lift them into AxisIndicatorRenderer, a Qt-free renderer in
IfcViewerCore, and drive it from ViewportCore::render for desktop and
web alike. Same move SectionGizmoRenderer already made; the drawing code
is unchanged apart from swapping qDegreesToRadians for CameraMath's kPiF.

Pivot visibility moves to the core with it: it was a QTimer on
ViewportWindow, so the afterglow couldn't follow the gizmo across. It is
now a Stopwatch deadline next to the drawing, with render() requesting
frames until an armed afterglow expires. Hosts keep the same three
triggers (on for orbit/pan drags, off on release, 600 ms on wheel).

The web demo shell's log overlay sat exactly on top of the corner gizmo,
so it shifts right of the 110 px box.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Dion Moult
2026-08-21 11:16:41 +10:00
parent 973f61c6dc
commit d86f89090b
12 changed files with 722 additions and 456 deletions
+11
View File
@@ -253,6 +253,10 @@ EM_BOOL onMouseDown(int, const EmscriptenMouseEvent* e, void* user) {
app->nav_drag_px = 0.0f;
app->down_x = e->targetX; // canvas-relative CSS px
app->down_y = e->targetY;
// Show the pivot triad for the duration of an orbit / pan drag, so
// it's visible what the camera turns around (matches the desktop).
if (kind == NavKind::Orbit || kind == NavKind::Pan)
app->core.setPivotIndicatorVisible(true);
}
return EM_TRUE;
}
@@ -297,6 +301,10 @@ EM_BOOL onMouseUp(int, const EmscriptenMouseEvent* e, void* user) {
const NavKind kind = app->nav_kind;
app->nav_active = false;
app->nav_kind = NavKind::None;
// Drag is over — hide the pivot indicator without afterglow. Only for the
// gesture that raised it; a stray mouseup must not cut a wheel afterglow.
if (was_active && (kind == NavKind::Orbit || kind == NavKind::Pan))
app->core.setPivotIndicatorVisible(false);
// End a section-gizmo drag (took over the press; no pick/orbit on release).
if (app->section_dragging) {
@@ -373,6 +381,9 @@ EM_BOOL onWheel(int, const EmscriptenWheelEvent* e, void* user) {
// In fly mode the wheel tunes move speed (Blender convention), not zoom.
if (app->fly_mode) { app->core.flyAdjustSpeed(-float(dy) / 100.0f); return EM_TRUE; }
app->core.dollyBy(-float(dy) / 100.0f);
// Pivot afterglow on wheel — visible for 600 ms so the user can see what
// they're zooming around without holding a drag.
app->core.setPivotIndicatorVisible(true, 600);
return EM_TRUE; // consume so the page doesn't scroll
}