Skip to content

editor: stop a hidden Site from emptying exports and the 2D plan - #907

Merged
Aymericr merged 2 commits into
mainfrom
fix/hidden-site-export
Sep 22, 2026
Merged

Aymericr merged 2 commits into
mainfrom
fix/hidden-site-export

Conversation

@Aymericr

@Aymericr Aymericr commented Sep 22, 2026

Copy link
Copy Markdown
Contributor

What does this PR do?

A layout whose root Site is saved with visible: false came out empty from every export while the editor showed the full house. Three code paths walked the parentId chain and treated the Site like any other container, so its flag hid every building, level and node beneath it:

  • pruneHiddenSceneNodes in glb-export.ts, which feeds GLB, USDZ, STL, OBJ, the print formats and the production bake. A 275-node house exported as a 184-byte GLB holding one empty node.
  • isVisibleInFloorplan in the shared viewer's FloorplanPreview, which left the public viewer's 2D tab blank for the same layout (0 of 198 level nodes passed against the real file).
  • isFloorplanHierarchyVisible, which gated site-scoped plugin kinds on the Site's flag in the PDF export and the live 2D view.

The viewer never applies that flag: the Site renderer ignores visible, and the Site row in the sidebar has no eye toggle, so the state only arrives through the CLI, MCP or a hand-authored layout.

One rule now lives in core, hidesDescendants(node), false only for a Site: hiding a Site hides its own ground fill and boundary and nothing beneath it. The exporter, the plan preview and the 2D hierarchy gate all read it. The declaredSiteParents map, which existed solely to cascade Site visibility onto detached Environment children, is gone.

Because nothing told the author the flag was presentation-only, validate_scene now returns a warnings list (same { nodeId, path, message } shape as errors) and flags a hidden Site with that note, and Load Build (validateBuildJson) emits a site_hidden warning. wiki/architecture/node-schemas.md documents the rule.

Hosts that implement SceneBridge.validateScene (the hosted MCP bridge in private-editor) need to return warnings too; that lands with the submodule bump.

How to test

  1. cd packages/editor && bun test src/lib/glb-export.test.ts src/components/viewer/floorplan-preview-visibility.test.ts src/components/editor-2d/renderers/floorplan-registry-layer.test.ts src/lib/floorplan/floorplan-export.test.ts — the new tests cover a hidden Site over a visible building/level/item for the exporter, the plan preview and the 2D gate, plus hidden buildings, levels and leaves still hiding.
  2. cd packages/mcp && bun test src/tools/validate-scene.test.ts — a hidden Site yields valid: true with one warning; cd packages/core && bun test src/validation/validate-build-json.test.ts — Load Build warns with site_hidden.
  3. Full suites: core 2866, editor 1104, mcp 381 passing; bun run build in core and mcp; tsgo --noEmit in editor.
  4. Load a project whose root Site has visible: false (through MCP update_node or the layout JSON), leave "Export visible nodes only" on, and click Export GLB: the file contains the building. Open the shared viewer's 2D tab: the plan draws. Run validate_scene: one warning names the Site.

Screenshots / screen recording

N/A — non-visual change in the export, plan-collection and validation paths.

Checklist

  • I've tested this locally with bun dev
  • My code follows the existing code style (run bun check to verify)
  • I've updated relevant documentation (if applicable)
  • This PR targets the main branch

Not ticked: the in-app export and 2D tab were not exercised in a browser from this checkout; coverage is the unit suites above.


Note

Medium Risk
Changes visibility semantics across GLB/USDZ and floorplan export paths; behavior is centralized and heavily unit-tested but affects all visible-only exports.

Overview
Hiding a root Site with visible: false no longer cascades to buildings and levels. Core now exports hidesDescendants (false only for site) and HIDDEN_SITE_NOTE, so a hidden Site affects only its own ground/boundary while children keep their own visibility flags.

GLB export, the shared viewer floorplan preview, and live 2D / PDF floorplan hierarchy checks all use that rule instead of walking parentId and treating Site like any other container. Export pruning drops non–scene-node children under a hidden Site (parcel geometry) but keeps hosted building content; the old declaredSiteParents Site-visibility map is removed.

Validation surfaces the behavior: Load Build emits a site_hidden warning, and MCP validate_scene adds a non-failing warnings array (same shape as errors) for hidden Sites. Wiki node-schema docs describe the Site exception.

Reviewed by Cursor Bugbot for commit f4dcdc2. Bugbot is set up for automated code reviews on this repo. Configure here.

A layout whose root Site was saved with visible: false exported as an
empty file: pruneHiddenSceneNodes inherited visibility up the parentId
chain, so the Site's flag hid every building, level and node beneath it.
The viewer never applies that flag (the Site renderer ignores it and the
Site row has no eye toggle), so the editor showed the full house while
the GLB held one empty scene-renderer node.

The Site's own visibility now stops at the Site: hosted nodes keep their
own flag, and a hidden Site drops only its ground fill and boundary. The
declaredSiteParents map existed solely to cascade Site visibility to
detached children, so it goes too.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@pascal

pascal Bot commented Sep 22, 2026

Copy link
Copy Markdown

I hit an error while handling your request (Model unavailable on AI Gateway free tier: Free tier users do not have access to this model. Upgrade to paid credits at https://vercel.com/d?to=%2F%5Bteam%5D%2F%7E%2Fai%3Fmodal%3Dtop-up for unrestricted…).

Please try again, rephrase, or reach out if it keeps failing.

Error id: 863d3c77-80fd-4915-89f5-0c4393865bd3

…lidators

The GLB fix left the same ancestor walk in two 2D paths: the shared
viewer's FloorplanPreview rejected every node under a hidden Site (an
empty plan for the same layout), and isFloorplanHierarchyVisible gated
site-scoped plugin kinds on the Site's flag for the PDF export and the
live 2D view.

One rule now lives in core: hidesDescendants(node) is false only for a
Site, whose flag hides its own ground fill and boundary and nothing
beneath it. The exporter, the plan preview and the 2D hierarchy gate
read it. validate_scene returns a warnings list and flags a hidden Site
with that note; Load Build (validateBuildJson) warns the same way, so
an author who hides the Site learns what the flag does.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@Aymericr Aymericr changed the title editor: stop a hidden Site from emptying visible-only exports editor: stop a hidden Site from emptying exports and the 2D plan Sep 22, 2026
@Aymericr
Aymericr merged commit 95591f0 into main Sep 22, 2026
4 checks passed
@Aymericr
Aymericr deleted the fix/hidden-site-export branch September 22, 2026 19:42
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.

1 participant