Skip to content

Commit f4de173

Browse files
nartcclaude
andcommitted
fix(soba): hide html overlay when ancestor is hidden by LOD
- check ancestor visibility in beforeRender loop, hide html when any ancestor has visible=false - force re-evaluation when transitioning from hidden back to visible - add WithLOD story for html component Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 0a1e320 commit f4de173

File tree

2 files changed

+67
-0
lines changed

2 files changed

+67
-0
lines changed

libs/soba/misc/src/lib/html/html-content.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,11 +370,32 @@ export class NgtsHTMLContent extends NgtHTML {
370370
];
371371

372372
if (group) {
373+
// Check if any ancestor is hidden (e.g., by LOD)
374+
let ancestorVisible = true;
375+
let ancestor: THREE.Object3D | null = group;
376+
while (ancestor) {
377+
if (!ancestor.visible) {
378+
ancestorVisible = false;
379+
break;
380+
}
381+
ancestor = ancestor.parent;
382+
}
383+
384+
if (!ancestorVisible) {
385+
if (visible) {
386+
visible = false;
387+
if (this.occluded['listeners']) this.occluded.emit(true);
388+
else renderer.setStyle(hostEl, 'display', 'none');
389+
}
390+
return;
391+
}
392+
373393
camera.updateMatrixWorld();
374394
group.updateWorldMatrix(true, false);
375395
const vec = transform ? oldPosition : calculatePosition(group, camera, size);
376396

377397
if (
398+
!visible ||
378399
transform ||
379400
Math.abs(oldZoom - camera.zoom) > eps ||
380401
Math.abs(oldPosition[0] - vec[0]) > eps ||

libs/soba/src/misc/html.stories.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { ChangeDetectionStrategy, Component, CUSTOM_ELEMENTS_SCHEMA, input } fro
22
import { Meta } from '@storybook/angular';
33
import { NgtArgs } from 'angular-three';
44
import { NgtsHTML, NgtsHTMLContentOptions, NgtsHTMLOptions } from 'angular-three-soba/misc';
5+
import { NgtsDetailed } from 'angular-three-soba/performances';
56
import { ColorRepresentation } from 'three';
67
import { storyDecorators, storyFunction, storyObject, Turnable } from '../setup-canvas';
78

@@ -78,12 +79,57 @@ class HtmlTransformScene {
7879
htmlContentOptions = input({} as NgtsHTMLContentOptions);
7980
}
8081

82+
@Component({
83+
selector: 'html-lod-scene',
84+
template: `
85+
<ngts-detailed [distances]="[0, 8, 18]">
86+
<ngt-mesh>
87+
<ngt-icosahedron-geometry *args="[2, 4]" />
88+
<ngt-mesh-basic-material color="hotpink" wireframe />
89+
90+
<ngts-html [options]="{ position: [2.5, 0, 0] }">
91+
<div [htmlContent]="{ center: true }" style="color: white; background: rgba(0,0,0,0.5); padding: 4px 8px; white-space: nowrap;">
92+
High Detail
93+
</div>
94+
</ngts-html>
95+
</ngt-mesh>
96+
97+
<ngt-mesh>
98+
<ngt-icosahedron-geometry *args="[2, 2]" />
99+
<ngt-mesh-basic-material color="orange" wireframe />
100+
101+
<ngts-html [options]="{ position: [2.5, 0, 0] }">
102+
<div [htmlContent]="{ center: true }" style="color: white; background: rgba(0,0,0,0.5); padding: 4px 8px; white-space: nowrap;">
103+
Medium Detail
104+
</div>
105+
</ngts-html>
106+
</ngt-mesh>
107+
108+
<ngt-mesh>
109+
<ngt-icosahedron-geometry *args="[2, 1]" />
110+
<ngt-mesh-basic-material color="skyblue" wireframe />
111+
112+
<ngts-html [options]="{ position: [2.5, 0, 0] }">
113+
<div [htmlContent]="{ center: true }" style="color: white; background: rgba(0,0,0,0.5); padding: 4px 8px; white-space: nowrap;">
114+
Low Detail
115+
</div>
116+
</ngts-html>
117+
</ngt-mesh>
118+
</ngts-detailed>
119+
`,
120+
schemas: [CUSTOM_ELEMENTS_SCHEMA],
121+
changeDetection: ChangeDetectionStrategy.OnPush,
122+
imports: [NgtArgs, NgtsHTML, NgtsDetailed],
123+
})
124+
class HtmlWithLODScene {}
125+
81126
export default {
82127
title: 'Misc/HTML',
83128
decorators: storyDecorators(),
84129
} as Meta;
85130

86131
export const Default = storyFunction(HtmlScene, { camera: { position: [-20, 20, -20] } });
132+
export const WithLOD = storyFunction(HtmlWithLODScene, { camera: { position: [0, 0, 10] } });
87133
export const Transform = storyObject(HtmlTransformScene, {
88134
camera: { position: [-20, 20, -20] },
89135
argsOptions: {

0 commit comments

Comments
 (0)