Skip to content

fix(viewer): honour Show Annotations toggle for IfcAnnotation 3D meshes#1356

Merged
louistrue merged 2 commits into
mainfrom
fix/1354-annotation-visibility
Jun 25, 2026
Merged

fix(viewer): honour Show Annotations toggle for IfcAnnotation 3D meshes#1356
louistrue merged 2 commits into
mainfrom
fix/1354-annotation-visibility

Conversation

@louistrue

@louistrue louistrue commented Jun 24, 2026

Copy link
Copy Markdown
Collaborator

Problem

Closes #1354.

IfcAnnotation entities can carry real 3D solid geometry — e.g. the Bonsai plan-view "DRAWING" boxes in the issue render as grey cubes. The Show Annotations toggle (typeVisibility.ifcAnnotations) only drove the separate 2D symbolic curve overlay (useSymbolicAnnotations in Viewport.tsx). The 3D meshes flow through the normal merged-geometry path, whose type filter handled IfcSpace / IfcOpeningElement / IfcVirtualElement / IfcSite but never IfcAnnotation — so the cubes always rendered and ignored the toggle.

Fix

Gate IfcAnnotation meshes on typeVisibility.ifcAnnotations at the three existing type-visibility filter sites (the same three the other five toggles already live in):

  • ViewportContainer.tsx — merged-geometry render filter (+ change-detection and needsFilter guards)
  • basketVisibleSet.tsmatchesTypeVisibility (selection / list / isolation visible set)
  • GLBExportDialog.tsxbuildHiddenIfcTypes (visible-only export parity)

Turning Annotations off now hides both the 2D overlay and the 3D cubes consistently. Default stays true, so users who want annotations see no change.

This does not tie anything to the section plane — it's a pure global type filter, consistent with the "annotations toggle is global" guidance.

Scope note

This makes the toggle effective; the cubes still show by default. Flipping the default so Bonsai drawing annotations are hidden out-of-the-box is a separate decision (it would also hide legitimate annotations), left out of this PR.

Tests

Summary by CodeRabbit

  • Bug Fixes
    • Updated the “visible only” export and viewport rendering to respect the IfcAnnotation type-visibility toggle.
    • Prevented annotation elements from appearing when IfcAnnotations is disabled, while keeping other visible entities intact.
    • Ensured geometry filtering and visibility results update correctly when type-visibility settings change.
  • Tests
    • Added automated coverage to verify IfcAnnotation visibility is included/excluded appropriately, including the federated/models code path.

… meshes

IfcAnnotation entities can carry real 3D solid geometry (e.g. Bonsai
plan-view "DRAWING" boxes) alongside the 2D symbolic curve overlay. The
ifcAnnotations toggle only drove the curve overlay, so those 3D meshes
rendered as stray grey cubes that ignored the Show Annotations setting.

Gate IfcAnnotation meshes by typeVisibility.ifcAnnotations at the three
existing type-visibility filter sites (merged-geometry render filter,
visible-basket set, and GLB visible-only export) so the toggle hides
both representations consistently.

Fixes #1354
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@vercel

vercel Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
ifc-lite Ready Ready Preview, Comment Jun 24, 2026 5:22pm
2 Skipped Deployments
Project Deployment Actions Updated (UTC)
ifc-lite-dev Ignored Ignored Preview Jun 24, 2026 5:22pm
ifc-lite-viewer-embed Ignored Ignored Jun 24, 2026 5:22pm

@coderabbitai

coderabbitai Bot commented Jun 24, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 43f078c4-0208-485e-a49e-b242b0eabf59

📥 Commits

Reviewing files that changed from the base of the PR and between 8a5b7ab and 81ffbe8.

📒 Files selected for processing (1)
  • apps/viewer/src/store/basketVisibleSet.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • apps/viewer/src/store/basketVisibleSet.test.ts

📝 Walkthrough

Walkthrough

The PR adds IfcAnnotation support to the typeVisibility toggle system. basketVisibleSet.ts gates IfcAnnotation entities, ViewportContainer.tsx extends its mesh filtering to skip annotation meshes, and GLBExportDialog.tsx adds IfcAnnotation to the hidden-type set for visible-only exports.

Changes

IfcAnnotation Visibility Support

Layer / File(s) Summary
basketVisibleSet visibility gate and tests
apps/viewer/src/store/basketVisibleSet.ts, apps/viewer/src/store/basketVisibleSet.test.ts
matchesTypeVisibility returns false for IfcAnnotation entities when typeVisibility.ifcAnnotations is disabled. Tests cover enabled and disabled states and the federated models path.
ViewportContainer WebGPU mesh filter
apps/viewer/src/components/viewer/ViewportContainer.tsx
The type-visibility cache key, needsFilter condition, and per-mesh filter loop are extended to include ifcAnnotations, skipping IfcAnnotation meshes when the toggle is off.
GLB export hidden-type extension
apps/viewer/src/components/viewer/GLBExportDialog.tsx
buildHiddenIfcTypes accepts ifcAnnotations in its typeVisibility parameter and adds IfcAnnotation to the hidden-type set when the toggle is disabled.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

Poem

🐇 I hop through cubes and annotations bright,
With one tiny toggle, they slip from sight.
Basket, viewport, GLB in a neat little row,
Hidden by the switch, away they go!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly states the viewer change and the specific IfcAnnotation toggle behavior.
Linked Issues check ✅ Passed The PR addresses #1354 by hiding IfcAnnotation meshes when annotations are off, matching the grey cube fix.
Out of Scope Changes check ✅ Passed The added export and visibility-path changes align with the stated fix and are not unrelated scope creep.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/1354-annotation-visibility

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
apps/viewer/src/store/basketVisibleSet.test.ts (1)

264-293: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add a models-backed case for this toggle.

These assertions only cover the legacy state.geometryResult fallback. The same visibility gate also runs through the state.models path, so this change should be locked down with at least one models.size === 1/federated case as well. As per coding guidelines, "Resolve selections/IDs through FederationRegistry (toGlobalId/fromGlobalId/getModelForGlobalId), never ad-hoc math; honor the single-model fallback globalId === expressId. Verify behaviour at models.size of 1 and N."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/viewer/src/store/basketVisibleSet.test.ts` around lines 264 - 293, The
IfcAnnotation visibility toggle is only covered through the legacy
geometryResult fallback, so add a models-backed test case to lock down the same
behavior in the state.models path. Update the basket visibility tests around
getVisibleBasketEntityRefsFromStore and invalidateVisibleBasketCache to include
at least one federated setup with models.size === 1 (and, if practical, an
N-model case) so the toggle is verified when IDs are resolved through
FederationRegistry. Keep the assertions aligned with the existing ifcAnnotations
on/off behavior and ensure the models path uses the same selection/ID resolution
flow as the rest of the store.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/viewer/src/store/basketVisibleSet.test.ts`:
- Around line 270-285: The tests are bypassing the GeometryResult type by
casting geometryResult as any in basketVisibleSet.test.ts, which makes the
fixture brittle. Replace those ad hoc casts with a small typed helper or shared
fixture that returns a correctly shaped geometryResult for the relevant test
cases, and use it wherever setState is populating geometryResult in this spec.

---

Nitpick comments:
In `@apps/viewer/src/store/basketVisibleSet.test.ts`:
- Around line 264-293: The IfcAnnotation visibility toggle is only covered
through the legacy geometryResult fallback, so add a models-backed test case to
lock down the same behavior in the state.models path. Update the basket
visibility tests around getVisibleBasketEntityRefsFromStore and
invalidateVisibleBasketCache to include at least one federated setup with
models.size === 1 (and, if practical, an N-model case) so the toggle is verified
when IDs are resolved through FederationRegistry. Keep the assertions aligned
with the existing ifcAnnotations on/off behavior and ensure the models path uses
the same selection/ID resolution flow as the rest of the store.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 851889a3-55fd-4294-913f-88f5ca397025

📥 Commits

Reviewing files that changed from the base of the PR and between c7a6ddb and 8a5b7ab.

📒 Files selected for processing (4)
  • apps/viewer/src/components/viewer/GLBExportDialog.tsx
  • apps/viewer/src/components/viewer/ViewportContainer.tsx
  • apps/viewer/src/store/basketVisibleSet.test.ts
  • apps/viewer/src/store/basketVisibleSet.ts

Comment on lines +270 to +285
geometryResult: { meshes } as any,
typeVisibility: { ...useViewerStore.getState().typeVisibility, ifcAnnotations: true },
});
invalidateVisibleBasketCache();

const refs = getVisibleBasketEntityRefsFromStore();
assert.ok(refs.some((r) => entityRefToString(r) === 'legacy:2'));
});

it('drops IfcAnnotation 3D meshes when the toggle is off', () => {
useViewerStore.setState({
selectedEntitiesSet: new Set(),
selectedEntity: null,
selectedEntityIds: new Set(),
hierarchyBasketSelection: new Set(),
geometryResult: { meshes } as any,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== GeometryResult declarations =="
rg -n -C2 "export (type|interface) GeometryResult|type GeometryResult|interface GeometryResult" apps/viewer/src -g '**/*.ts' -g '**/*.tsx'

echo
echo "== New casts in basketVisibleSet.test.ts =="
rg -n -C2 "geometryResult: \{ meshes \} as any|as any" apps/viewer/src/store/basketVisibleSet.test.ts

echo
echo "== Existing typed geometry fixtures in tests =="
rg -n -C2 "GeometryResult|geometryResult:" apps/viewer/src -g '**/*.test.ts' -g '**/*.test.tsx'

Repository: LTplus-AG/ifc-lite

Length of output: 15800


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== basketVisibleSet.test.ts around the casts =="
sed -n '1,360p' apps/viewer/src/store/basketVisibleSet.test.ts

echo
echo "== GeometryResult / MeshData declarations =="
fd -a 'index.ts' apps -t f | rg '`@ifc-lite/geometry`|geometry' || true
rg -n -C3 "export (type|interface) GeometryResult|export (type|interface) MeshData|type GeometryResult|interface GeometryResult|type MeshData|interface MeshData" . -g '**/*.ts' -g '**/*.tsx'

echo
echo "== Where geometryResult is typed in viewer store types =="
rg -n -C3 "geometryResult" apps/viewer/src/store -g '**/*.ts' -g '**/*.tsx'

Repository: LTplus-AG/ifc-lite

Length of output: 50374


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== basketVisibleSet.test.ts around the casts =="
sed -n '1,360p' apps/viewer/src/store/basketVisibleSet.test.ts

echo
echo "== GeometryResult / MeshData declarations =="
rg -n -C3 "export (type|interface) GeometryResult|export (type|interface) MeshData|type GeometryResult|interface GeometryResult|type MeshData|interface MeshData" . -g '**/*.ts' -g '**/*.tsx'

echo
echo "== Where geometryResult is typed in viewer store types =="
rg -n -C3 "geometryResult" apps/viewer/src/store -g '**/*.ts' -g '**/*.tsx'

Repository: LTplus-AG/ifc-lite

Length of output: 50374


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== basketVisibleSet.test.ts around the casts =="
sed -n '1,360p' apps/viewer/src/store/basketVisibleSet.test.ts

echo
echo "== GeometryResult / MeshData declarations =="
rg -n -C3 "export (type|interface) GeometryResult|export (type|interface) MeshData|type GeometryResult|interface GeometryResult|type MeshData|interface MeshData" . -g '**/*.ts' -g '**/*.tsx'

echo
echo "== Where geometryResult is typed in viewer store types =="
rg -n -C3 "geometryResult" apps/viewer/src/store -g '**/*.ts' -g '**/*.tsx'

Repository: LTplus-AG/ifc-lite

Length of output: 50374


Replace the geometryResult casts with a typed fixture/helper

apps/viewer/src/store/basketVisibleSet.test.ts uses as any for geometryResult in several places. That bypasses the GeometryResult shape and makes the test brittle if the fixture drifts. Use a small typed helper/fixture instead.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/viewer/src/store/basketVisibleSet.test.ts` around lines 270 - 285, The
tests are bypassing the GeometryResult type by casting geometryResult as any in
basketVisibleSet.test.ts, which makes the fixture brittle. Replace those ad hoc
casts with a small typed helper or shared fixture that returns a correctly
shaped geometryResult for the relevant test cases, and use it wherever setState
is populating geometryResult in this spec.

Source: Coding guidelines

…y gate

Addresses CodeRabbit review on #1356: the prior cases only exercised the
legacy geometryResult fallback; add a state.models-backed case so the
collectVisibleCandidates models path is locked down too.
@louistrue louistrue merged commit 68b2703 into main Jun 25, 2026
14 checks passed
@louistrue louistrue deleted the fix/1354-annotation-visibility branch June 25, 2026 05:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Plane/cross section drawings from Bonsai showing as cubes

1 participant