fix(export): stamp openable only when an open clip bakes
A door/window only carries extras.openable + extras.clips when an open animation actually bakes. Cased openings (no leaf) and fixed windows (no operable sash) are no longer mislabelled openable, so the GLB never claims a part opens when nothing moves. /viewer is unaffected (it already required openable && clips). Adds a regression test for the no-clip case. (Export barrels reordered by the formatter.) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
0629c7d3e3
commit
6cfc6ae01b
@@ -218,7 +218,6 @@ export {
|
||||
resolveCeilingPlanPointSnap,
|
||||
} from './lib/ceiling-plan-snap'
|
||||
export { EDITOR_LAYER } from './lib/constants'
|
||||
export { exportSceneToGlb } from './lib/glb-export'
|
||||
// Helper libs used by the kind-owned roof / stair / elevator panels.
|
||||
export {
|
||||
resolveCurrentBuildingId,
|
||||
@@ -247,6 +246,7 @@ export {
|
||||
getFloorplanWallThickness,
|
||||
} from './lib/floorplan'
|
||||
export { commitFreshPlacementSubtree } from './lib/fresh-planar-placement'
|
||||
export { exportSceneToGlb } from './lib/glb-export'
|
||||
export {
|
||||
buildResetSurfaceMaterialUpdates,
|
||||
buildRoofSurfaceMaterialPatch,
|
||||
|
||||
@@ -146,6 +146,38 @@ describe('prepareSceneForExport', () => {
|
||||
expect(leafMarkerSurvived).toBe(false)
|
||||
})
|
||||
|
||||
test('does not flag a door/window openable when no open clip bakes', () => {
|
||||
// A cased opening (no swing leaf) / fixed window (no operable sash) builds
|
||||
// no movable part, so no clip bakes and the node must not claim openable.
|
||||
const root = new THREE.Group()
|
||||
const openingGroup = new THREE.Group()
|
||||
openingGroup.add(meshWithNodeMaterial(nodeMaterial()))
|
||||
root.add(openingGroup)
|
||||
|
||||
const openingId = 'door_opening'
|
||||
sceneRegistry.nodes.set(openingId, openingGroup)
|
||||
const nodes: Record<string, AnyNode> = {
|
||||
[openingId]: {
|
||||
object: 'node',
|
||||
id: openingId,
|
||||
type: 'door',
|
||||
name: 'Cased opening',
|
||||
} as unknown as AnyNode,
|
||||
}
|
||||
|
||||
const { scene, animations } = prepareSceneForExport(root, nodes)
|
||||
|
||||
expect(animations).toHaveLength(0)
|
||||
const exported = scene.getObjectByProperty('name', openingId)
|
||||
expect(exported?.userData).toEqual({
|
||||
pascalId: openingId,
|
||||
kind: 'door',
|
||||
label: 'Cased opening',
|
||||
})
|
||||
expect(exported?.userData.openable).toBeUndefined()
|
||||
expect(exported?.userData.clips).toBeUndefined()
|
||||
})
|
||||
|
||||
test('keeps the zone identity node with its polygon and strips the fill mesh', () => {
|
||||
const root = new THREE.Group()
|
||||
const zoneGroup = new THREE.Group()
|
||||
|
||||
@@ -497,10 +497,15 @@ function stampIdentity(
|
||||
extras.label = getLevelDisplayName(node as LevelNode)
|
||||
target.visible = true
|
||||
}
|
||||
// Only doors/windows that actually baked an open clip are openable. A cased
|
||||
// opening (no leaf) or a fixed window (no operable sash) produces no clip, so
|
||||
// it stays unflagged — the file never claims a part opens when nothing moves.
|
||||
if (node.type === 'door' || node.type === 'window') {
|
||||
extras.openable = true
|
||||
const clipNames = clipNamesByNode.get(id)
|
||||
if (clipNames) extras.clips = clipNames
|
||||
if (clipNames?.length) {
|
||||
extras.openable = true
|
||||
extras.clips = clipNames
|
||||
}
|
||||
}
|
||||
if (node.type === 'zone') {
|
||||
// Zone fills are stripped from the bake; /viewer rebuilds the room from
|
||||
|
||||
@@ -14,10 +14,10 @@ export { ErrorBoundary } from './components/error-boundary'
|
||||
export { NodeRenderer } from './components/renderers/node-renderer'
|
||||
export { default as Viewer, type ViewerHandle } from './components/viewer'
|
||||
export {
|
||||
GlbScene,
|
||||
type GlbHover,
|
||||
type GlbIdentity,
|
||||
type GlbLevel,
|
||||
GlbScene,
|
||||
} from './components/viewer/glb-scene'
|
||||
export type { HoverStyle, HoverStyles } from './components/viewer/post-processing'
|
||||
export {
|
||||
|
||||
Reference in New Issue
Block a user