Skip to content

Add orientation axes inset overlay to Scene#6026

Open
Jepson2k wants to merge 3 commits into
zauberzeug:mainfrom
Jepson2k:add-viewhelper-api
Open

Add orientation axes inset overlay to Scene#6026
Jepson2k wants to merge 3 commits into
zauberzeug:mainfrom
Jepson2k:add-viewhelper-api

Conversation

@Jepson2k

@Jepson2k Jepson2k commented May 3, 2026

Copy link
Copy Markdown
Contributor

Motivation

Three.js ships with a ViewHelper — a small XYZ orientation gizmo that indicates the camera's view direction and snap-animates the camera to look down an axis when an axis sprite is clicked. This PR exposes it through Scene so users can drop a small inset into a corner of the canvas without writing JS.

This was originally part of #5993 (scene-clipping-axes), but supporting it on the current ^0.180.0 three.js pin required a manual scissor + viewport block in the render loop and a fake-clientX/clientY synthesis around ViewHelper.handleClick to compensate for r180's hardcoded bottom-right/dim=128 assumptions — both fragile workarounds. r184 added a viewHelper.location field that handles positioning natively, so I split this out as a follow-up that targets nicegui v4 (where the three.js pin can move to r184).

Implementation

Two new methods on Scene:

  • set_axes_inset(*, enabled, margin, margin_x, margin_y, anchor) — toggles the inset on a configurable corner. Position is wired through viewHelper.location ({top|bottom: my, left|right: mx}). The inset is fixed at 128 px (a hardcoded constant inside three.js' ViewHelper).
  • set_axes_labels(*, enabled, labels, font, color, radius) — replaces the default X/Y/Z labels and customizes their typography. Forwards to viewHelper.setLabels and setLabelStyle.

Click-to-snap is wired via a single capture-phase pointerdown listener that calls viewHelper.handleClick(event) and stops propagation when an axis sprite is hit, so OrbitControls doesn't start a drag-rotate on what was meant to be an inset click.

Both methods cache their opts on the Python side and replay them in _handle_init, so a fresh client connect (e.g. after a reload) re-applies the inset without the host having to re-call them.

The scene-bundle's three pin is bumped from ^0.180.0 to ^0.184.0 because viewHelper.location was added in r184. As a result this change can only land in nicegui v4 — earlier versions can't merge it without backporting the location math by hand.

Progress

  • The PR title is a short phrase starting with a verb like "Add ...", "Fix ...", "Update ...", "Remove ...", etc.
  • The implementation is complete. (Otherwise, open a draft PR.) — drafted, blocked on three.js pin bump for v4
  • This PR does not address a security issue. (Security fixes must be coordinated via the security advisory process before opening a PR.)
  • Pytests have been added/updated.
  • Documentation has been added/updated.
  • No breaking changes to the public API.

Co-authored-by: Claude Opus 4.7 (1M context) noreply@anthropic.com

Jepson2k and others added 2 commits May 2, 2026 22:27
`Scene.set_axes_inset` and `set_axes_labels` overlay Three.js'
`ViewHelper` in a configurable corner — a small XYZ gizmo that
indicates camera orientation and snap-animates the camera to look
down an axis when clicked.

Position is wired through r184's `viewHelper.location` field
(`{top|bottom: my, left|right: mx}`); on-click forwards pointerdown
to `viewHelper.handleClick(event)` and stops propagation when an
axis sprite is hit so OrbitControls doesn't start a drag-rotate on
what was meant to be an inset click.

Both methods cache their opts on the Python side and replay them in
`_handle_init`, so a fresh client connect re-applies the inset
without the host having to re-call them.

Bumps the scene-bundle's `three` pin from `^0.180.0` to `^0.184.0`
because `viewHelper.location` was added in r184. As a result this
change targets nicegui v4 — earlier versions can't merge it without
backporting the location math by hand.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Pre-commit's end-of-file-fixer hook flagged this on CI; rebuilt
maps from rollup don't emit a trailing newline by default.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@Jepson2k Jepson2k marked this pull request as ready for review May 6, 2026 02:11
@Jepson2k

Jepson2k commented May 6, 2026

Copy link
Copy Markdown
Contributor Author

@evnchn @falkoschindler Not sure whats the process for PR that require package upgrades (and therefore next nicegui v4 release). Let me know if this should be switched back to a draft or if there is a v4 branch this should target instead.

@falkoschindler

Copy link
Copy Markdown
Contributor

Hi @Jepson2k, there's no separate v4 branch — we keep development on main and use the 4.0 milestone for what's deferred to the next major. I'll attach this PR to that milestone. Once we cut 4.0 and bump the three.js pin on main, you can rebase and we'll take a full review pass.

@falkoschindler falkoschindler added this to the 4.0 milestone May 6, 2026
@falkoschindler falkoschindler added the blocked Status: Blocked by another issue or dependency label May 6, 2026
@evnchn

evnchn commented May 6, 2026

Copy link
Copy Markdown
Collaborator

Posted by Claude Code on @evnchn's behalf.

Reinforcing the v4 gate so this doesn't get accidentally swept onto a 3.x bump in a triage pass — ^0.180.0^0.184.0 crosses four releases with hard removals and renames, not just soft deprecations. User-facing footguns that would silently break downstream JS:

  • r181 renames: PI2TWO_PI, PassNode.setResolution()…Scale(), WaterMesh.resolutionresolutionScale, AfterImageNode.damp no longer accepts plain numbers. PBR indirect-specular brightness also shifts visibly.
  • r182 MeshPostProcessingMaterial deleted; WebGLCubeRenderTarget no longer accepted by WebGPURenderer; colorBufferTypeoutputBufferType.
  • r183 PostProcessingRenderPipeline; FileLoader.load() / ImageBitmapLoader.load() no longer return a value (callers using the return silently break); Sky legacy gamma path gone; RoomEnvironment lighting shifts.
  • r184 FBXLoader auto-rotates +Z-up → +Y-up (existing imports may flip 90°); SSAAPassNode.clearColor / clearAlpha removed.

Scene's own Python surface is fine, but user JS touching scene.three / custom loaders / post-processing absorbs these silently. Defer-to-4.0 is the right call.

@falkoschindler falkoschindler added the feature Type/scope: New or intentionally changed behavior label May 6, 2026
ViewHelper.render() implicitly clears the framebuffer; without this guard
the main scene gets wiped every frame after the helper renders, leaving an
empty canvas. The original feature/additional_scene_features branch had
this guard; it was lost in the simplification that split this PR out of
zauberzeug#5993.
@Jepson2k Jepson2k mentioned this pull request Jun 4, 2026
6 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

blocked Status: Blocked by another issue or dependency feature Type/scope: New or intentionally changed behavior

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants