three-cad-viewer 4.3.5 → 4.3.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/dist/three-cad-viewer.esm.js +8 -5
  2. package/dist/three-cad-viewer.esm.js.map +1 -1
  3. package/dist/three-cad-viewer.esm.min.js +1 -1
  4. package/dist/three-cad-viewer.js +8 -5
  5. package/dist/three-cad-viewer.min.js +1 -1
  6. package/package.json +2 -3
  7. package/src/_version.ts +0 -1
  8. package/src/camera/camera.ts +0 -445
  9. package/src/camera/controls/CADOrbitControls.ts +0 -241
  10. package/src/camera/controls/CADTrackballControls.ts +0 -598
  11. package/src/camera/controls.ts +0 -380
  12. package/src/core/patches.ts +0 -16
  13. package/src/core/studio-manager.ts +0 -652
  14. package/src/core/types.ts +0 -892
  15. package/src/core/viewer-state.ts +0 -784
  16. package/src/core/viewer.ts +0 -4821
  17. package/src/index.ts +0 -151
  18. package/src/rendering/environment.ts +0 -840
  19. package/src/rendering/light-detection.ts +0 -327
  20. package/src/rendering/material-factory.ts +0 -735
  21. package/src/rendering/material-presets.ts +0 -289
  22. package/src/rendering/raycast.ts +0 -291
  23. package/src/rendering/room-environment.ts +0 -192
  24. package/src/rendering/studio-composer.ts +0 -577
  25. package/src/rendering/studio-floor.ts +0 -108
  26. package/src/rendering/texture-cache.ts +0 -324
  27. package/src/rendering/tree-model.ts +0 -542
  28. package/src/rendering/triplanar.ts +0 -329
  29. package/src/scene/animation.ts +0 -343
  30. package/src/scene/axes.ts +0 -108
  31. package/src/scene/bbox.ts +0 -223
  32. package/src/scene/clipping.ts +0 -650
  33. package/src/scene/grid.ts +0 -864
  34. package/src/scene/nestedgroup.ts +0 -1448
  35. package/src/scene/objectgroup.ts +0 -866
  36. package/src/scene/orientation.ts +0 -259
  37. package/src/scene/render-shape.ts +0 -634
  38. package/src/tools/cad_tools/measure.ts +0 -811
  39. package/src/tools/cad_tools/select.ts +0 -100
  40. package/src/tools/cad_tools/tools.ts +0 -231
  41. package/src/tools/cad_tools/ui.ts +0 -454
  42. package/src/tools/cad_tools/zebra.ts +0 -369
  43. package/src/types/html.d.ts +0 -5
  44. package/src/types/n8ao.d.ts +0 -28
  45. package/src/types/three-augmentation.d.ts +0 -60
  46. package/src/ui/display.ts +0 -3295
  47. package/src/ui/index.html +0 -505
  48. package/src/ui/info.ts +0 -177
  49. package/src/ui/slider.ts +0 -206
  50. package/src/ui/toolbar.ts +0 -347
  51. package/src/ui/treeview.ts +0 -945
  52. package/src/utils/decode-instances.ts +0 -233
  53. package/src/utils/font.ts +0 -60
  54. package/src/utils/gpu-tracker.ts +0 -265
  55. package/src/utils/logger.ts +0 -92
  56. package/src/utils/sizeof.ts +0 -116
  57. package/src/utils/timer.ts +0 -69
  58. package/src/utils/utils.ts +0 -446
@@ -1,650 +0,0 @@
1
- import * as THREE from "three";
2
- import type { Vector3Tuple } from "three";
3
- import { ObjectGroup } from "./nestedgroup.js";
4
- import { CLIP_INDICES } from "../core/types";
5
- import type { Theme, ClipIndex } from "../core/types";
6
- import { toVector3Tuple, deepDispose } from "../utils/utils.js";
7
-
8
- // ============================================================================
9
- // Constants
10
- // ============================================================================
11
-
12
- /** Default normals for the three clipping planes (X, Y, Z) */
13
- const DEFAULT_NORMALS = [
14
- new THREE.Vector3(-1, 0, 0),
15
- new THREE.Vector3(0, -1, 0),
16
- new THREE.Vector3(0, 0, -1),
17
- ];
18
-
19
- /** Plane colors by theme */
20
- const PLANE_COLORS: Record<Theme, number[]> = {
21
- light: [0xff0000, 0x00ff00, 0x0000ff],
22
- dark: [0xff4500, 0x32cd32, 0x3b9eff],
23
- };
24
-
25
- /** Plane helper opacity by theme */
26
- const PLANE_HELPER_OPACITY: Record<Theme, number> = {
27
- light: 0.1,
28
- dark: 0.2,
29
- };
30
-
31
- // ============================================================================
32
- // ClippingMaterials - Factory for clipping-related materials
33
- // ============================================================================
34
-
35
- /**
36
- * Factory for creating clipping-related materials.
37
- * Centralizes material creation and avoids global state.
38
- */
39
- class ClippingMaterials {
40
- /**
41
- * Create a plane helper material.
42
- * @param theme - The UI theme ('light' or 'dark').
43
- * @returns The plane helper material.
44
- */
45
- static createPlaneHelperMaterial(theme: Theme): THREE.MeshBasicMaterial {
46
- return new THREE.MeshBasicMaterial({
47
- opacity: PLANE_HELPER_OPACITY[theme] || 0.1,
48
- transparent: true,
49
- depthWrite: false,
50
- toneMapped: false,
51
- side: THREE.DoubleSide,
52
- });
53
- }
54
-
55
- /**
56
- * Create a back stencil material.
57
- * Increments stencil buffer where back faces are visible (clipped region).
58
- * @returns The back stencil material.
59
- */
60
- static createBackStencilMaterial(): THREE.MeshBasicMaterial {
61
- return new THREE.MeshBasicMaterial({
62
- depthWrite: false,
63
- depthTest: false,
64
- colorWrite: false,
65
- side: THREE.BackSide,
66
- stencilWrite: true,
67
- stencilFunc: THREE.AlwaysStencilFunc,
68
- stencilFail: THREE.IncrementWrapStencilOp,
69
- stencilZFail: THREE.IncrementWrapStencilOp,
70
- stencilZPass: THREE.IncrementWrapStencilOp,
71
- });
72
- }
73
-
74
- /**
75
- * Create a front stencil material.
76
- * Decrements stencil buffer where front faces are visible.
77
- * @returns The front stencil material.
78
- */
79
- static createFrontStencilMaterial(): THREE.MeshBasicMaterial {
80
- return new THREE.MeshBasicMaterial({
81
- depthWrite: false,
82
- depthTest: false,
83
- colorWrite: false,
84
- side: THREE.FrontSide,
85
- stencilWrite: true,
86
- stencilFunc: THREE.AlwaysStencilFunc,
87
- stencilFail: THREE.DecrementWrapStencilOp,
88
- stencilZFail: THREE.DecrementWrapStencilOp,
89
- stencilZPass: THREE.DecrementWrapStencilOp,
90
- });
91
- }
92
-
93
- /**
94
- * Create a stencil plane material.
95
- * Draws plane where stencil buffer != 0 (clipped region).
96
- * @param color - The plane color as hex.
97
- * @param clippingPlanes - Other clipping planes to apply.
98
- * @returns The stencil plane material.
99
- */
100
- static createStencilPlaneMaterial(color: number, clippingPlanes: THREE.Plane[]): THREE.MeshStandardMaterial {
101
- const material = new THREE.MeshStandardMaterial({
102
- color: new THREE.Color(color),
103
- metalness: 0.3,
104
- roughness: 0.65,
105
- opacity: 1.0,
106
- transparent: false,
107
- side: THREE.DoubleSide,
108
- polygonOffset: true,
109
- polygonOffsetFactor: 1.0,
110
- polygonOffsetUnits: 1.0,
111
- stencilWrite: true,
112
- stencilRef: 0,
113
- stencilFunc: THREE.NotEqualStencilFunc,
114
- stencilFail: THREE.ReplaceStencilOp,
115
- stencilZFail: THREE.ReplaceStencilOp,
116
- stencilZPass: THREE.ReplaceStencilOp,
117
- clippingPlanes: clippingPlanes,
118
- });
119
- return material;
120
- }
121
- }
122
-
123
- // ============================================================================
124
- // CenteredPlane - Plane with center-relative constant
125
- // ============================================================================
126
-
127
- /**
128
- * A THREE.Plane that maintains a constant relative to a center point.
129
- */
130
- class CenteredPlane extends THREE.Plane {
131
- center: number[];
132
- centeredConstant: number;
133
-
134
- /**
135
- * Create a CenteredPlane.
136
- * @param normal - The plane normal vector.
137
- * @param constant - The centered constant value.
138
- * @param center - The center point [x, y, z].
139
- */
140
- constructor(normal: THREE.Vector3, constant: number, center: number[]) {
141
- super(normal, constant);
142
- this.center = center;
143
- this.centeredConstant = constant;
144
- this.setConstant(constant);
145
- }
146
-
147
- /**
148
- * Set the constant relative to the center point.
149
- * @param value - The centered constant value.
150
- */
151
- setConstant(value: number): void {
152
- this.centeredConstant = value;
153
- const c = this.distanceToPoint(new THREE.Vector3(...this.center));
154
- const z = this.distanceToPoint(new THREE.Vector3(0, 0, 0));
155
- this.constant = z - c + value;
156
- }
157
-
158
- /**
159
- * Clone this CenteredPlane.
160
- * Overrides THREE.Plane.clone() which calls `new this.constructor()` without
161
- * arguments, causing `center` to be undefined during shadow map generation.
162
- */
163
- // @ts-expect-error -- THREE.Plane.clone() returns `this`, but we need a concrete CenteredPlane
164
- clone(): CenteredPlane {
165
- return new CenteredPlane(this.normal.clone(), this.centeredConstant, [...this.center]);
166
- }
167
- }
168
-
169
- // ============================================================================
170
- // PlaneMesh - Visual representation of a clipping plane
171
- // ============================================================================
172
-
173
- /**
174
- * A THREE.Group that only contains PlaneMesh children.
175
- */
176
- class PlaneMeshGroup extends THREE.Group {
177
- declare children: PlaneMesh[];
178
- }
179
-
180
- /**
181
- * A mesh that visually represents a clipping plane.
182
- */
183
- class PlaneMesh extends THREE.Mesh {
184
- declare type: string;
185
- declare material: THREE.MeshBasicMaterial | THREE.MeshStandardMaterial;
186
-
187
- /** Shared matrix for lookAt calculations */
188
- static matrix = new THREE.Matrix4();
189
-
190
- index: number;
191
- plane: CenteredPlane;
192
- size: number;
193
- center: number[];
194
-
195
- /**
196
- * Create a PlaneMesh.
197
- * @param index - The plane index (0, 1, or 2).
198
- * @param plane - The clipping plane.
199
- * @param center - The center point [x, y, z].
200
- * @param size - The size of the plane mesh.
201
- * @param material - The material for the mesh.
202
- * @param color - The color as hex value.
203
- * @param type - The mesh type identifier.
204
- */
205
- constructor(
206
- index: number,
207
- plane: CenteredPlane,
208
- center: number[],
209
- size: number,
210
- material: THREE.MeshBasicMaterial | THREE.MeshStandardMaterial,
211
- color: number,
212
- type: string
213
- ) {
214
- const meshGeometry = new THREE.PlaneGeometry(2, 2);
215
- meshGeometry.computeBoundingSphere();
216
- material.color.set(new THREE.Color(color));
217
- super(meshGeometry, material);
218
-
219
- this.type = type;
220
- this.index = index;
221
- this.plane = plane;
222
- this.size = size;
223
- this.center = center;
224
- }
225
-
226
- /**
227
- * Clear stencil buffer after rendering stencil planes.
228
- * @param renderer - The renderer.
229
- */
230
- onAfterRender = (renderer: THREE.WebGLRenderer): void => {
231
- if (this.type.startsWith("StencilPlane")) {
232
- renderer.clearStencil();
233
- }
234
- };
235
-
236
- /**
237
- * Update the mesh's world matrix to align with the clipping plane.
238
- * @param force - Force update even if not needed.
239
- */
240
- updateMatrixWorld(force?: boolean): void {
241
- this.position.set(0, 0, 0);
242
- this.scale.set(0.5 * this.size, 0.5 * this.size, 1);
243
-
244
- PlaneMesh.matrix.lookAt(this.position, this.plane.normal, this.up);
245
- this.quaternion.setFromRotationMatrix(PlaneMesh.matrix);
246
-
247
- this.translateZ(this.plane.constant);
248
- super.updateMatrixWorld(force);
249
- }
250
- }
251
-
252
- /**
253
- * Create a stencil mesh for clipping visualization.
254
- * @param name - The mesh name.
255
- * @param material - The stencil material.
256
- * @param geometry - The shape geometry.
257
- * @param plane - The clipping plane.
258
- * @returns The stencil mesh.
259
- */
260
- function createStencil(
261
- name: string,
262
- material: THREE.MeshBasicMaterial,
263
- geometry: THREE.BufferGeometry,
264
- plane: THREE.Plane
265
- ): THREE.Mesh {
266
- material.clippingPlanes = [plane];
267
- const mesh = new THREE.Mesh(geometry, material);
268
- mesh.name = name;
269
- return mesh;
270
- }
271
-
272
- // ============================================================================
273
- // Clipping - Main clipping management class
274
- // ============================================================================
275
-
276
- interface NestedGroupLike {
277
- groups: Record<string, ObjectGroup | unknown>;
278
- rootGroup: THREE.Group | null;
279
- }
280
-
281
- interface ClippingOptions {
282
- onNormalChange?: (index: ClipIndex, normalArray: Vector3Tuple) => void;
283
- }
284
-
285
- /**
286
- * Saved clipping state for mode transitions (e.g., entering/leaving Studio mode).
287
- * Captures only Clipping-internal state; renderer flags and ViewerState keys
288
- * are managed by the caller.
289
- */
290
- interface ClippingState {
291
- /** Centered constant (position) for each of the 3 clip planes */
292
- planeConstants: [number, number, number];
293
- /** Whether the plane helper meshes (translucent colored rectangles) are visible */
294
- helperVisible: boolean;
295
- /** Whether the stencil plane meshes (solid colored caps) are visible */
296
- planesVisible: boolean;
297
- }
298
-
299
- /**
300
- * Manages clipping planes, stencil rendering, and plane visualization.
301
- */
302
- class Clipping extends THREE.Group {
303
- center: number[] | null;
304
- distance: number;
305
- onNormalChange: ((index: ClipIndex, normalArray: Vector3Tuple) => void) | null;
306
- theme: Theme;
307
- nestedGroup!: NestedGroupLike;
308
- size: number;
309
- clipPlanes!: CenteredPlane[];
310
- reverseClipPlanes!: CenteredPlane[];
311
- objectColors!: number[];
312
- objectColorCaps: boolean;
313
- planeHelpers!: PlaneMeshGroup | null;
314
- private _planeMeshGroup: PlaneMeshGroup | null;
315
-
316
- /**
317
- * Create a Clipping instance.
318
- * @param center - The center point [x, y, z].
319
- * @param size - The size of the clipping region.
320
- * @param nestedGroup - The nested group containing objects to clip.
321
- * @param options - Configuration options.
322
- * @param theme - The UI theme ('light' or 'dark').
323
- */
324
- constructor(
325
- center: number[],
326
- size: number,
327
- nestedGroup: NestedGroupLike,
328
- options: ClippingOptions,
329
- theme: Theme
330
- ) {
331
- super();
332
- this.center = center;
333
- this.distance = size / 2;
334
- this.onNormalChange = options.onNormalChange || null;
335
- this.theme = theme;
336
- this.nestedGroup = nestedGroup;
337
- this.size = size;
338
-
339
- this.clipPlanes = [];
340
- this.reverseClipPlanes = [];
341
- this.objectColors = [];
342
- this.objectColorCaps = false;
343
-
344
- // Cached reference to avoid O(n) lookups
345
- this._planeMeshGroup = null;
346
-
347
- this.name = "PlaneHelpers";
348
-
349
- this._createClipPlanes(center);
350
- this._createPlaneHelpers(center, size, theme);
351
- this._createStencils(center, size, theme);
352
- }
353
-
354
- /**
355
- * Create the three clipping planes and their reverse counterparts.
356
- * @param center - The center point.
357
- */
358
- private _createClipPlanes(center: number[]): void {
359
- for (const i of CLIP_INDICES) {
360
- const plane = new CenteredPlane(DEFAULT_NORMALS[i], this.distance, center);
361
- this.clipPlanes.push(plane);
362
-
363
- const reversePlane = new CenteredPlane(
364
- DEFAULT_NORMALS[i].clone().negate(),
365
- -this.distance,
366
- center,
367
- );
368
- this.reverseClipPlanes.push(reversePlane);
369
-
370
- if (this.onNormalChange) {
371
- this.onNormalChange(i, toVector3Tuple(DEFAULT_NORMALS[i].toArray()));
372
- }
373
- }
374
- }
375
-
376
- /**
377
- * Create the visual plane helpers.
378
- * @param center - The center point.
379
- * @param size - The size of the plane helpers.
380
- * @param theme - The UI theme.
381
- */
382
- private _createPlaneHelpers(center: number[], size: number, theme: Theme): void {
383
- this.planeHelpers = new PlaneMeshGroup();
384
- this.planeHelpers.name = "PlaneHelpers";
385
-
386
- for (let i = 0; i < 3; i++) {
387
- const material = ClippingMaterials.createPlaneHelperMaterial(theme);
388
-
389
- this.planeHelpers.add(
390
- new PlaneMesh(
391
- i,
392
- this.clipPlanes[i],
393
- center,
394
- size,
395
- material,
396
- PLANE_COLORS[theme][i],
397
- "PlaneHelper",
398
- ),
399
- );
400
- }
401
-
402
- // Each plane helper is clipped by the other two planes
403
- for (let i = 0; i < 3; i++) {
404
- const otherPlanes = this.clipPlanes.filter((_, j) => j !== i);
405
- this.planeHelpers.children[i].material.clippingPlanes = otherPlanes;
406
- }
407
-
408
- this.planeHelpers.visible = false;
409
- this.add(this.planeHelpers);
410
- }
411
-
412
- /**
413
- * Create stencil meshes for solid objects.
414
- * @param center - The center point.
415
- * @param size - The size of the stencil planes.
416
- * @param theme - The UI theme.
417
- */
418
- private _createStencils(center: number[], size: number, theme: Theme): void {
419
- this._planeMeshGroup = new PlaneMeshGroup();
420
- this._planeMeshGroup.name = "PlaneMeshes";
421
-
422
- for (let i = 0; i < 3; i++) {
423
- const plane = this.clipPlanes[i];
424
- const otherPlanes = this.clipPlanes.filter((_, j) => j !== i);
425
- let j = 0;
426
-
427
- for (const path in this.nestedGroup.groups) {
428
- const group = this.nestedGroup.groups[path];
429
-
430
- if (group instanceof ObjectGroup && group.subtype === "solid" && group.front) {
431
- // Store color for each plane-solid combination (mirrors _planeMeshGroup order)
432
- const frontMesh = group.front;
433
- const material = frontMesh.material;
434
- this.objectColors.push(material.color.getHex());
435
-
436
- // Create clipping group with front and back stencils
437
- const clippingGroup = new THREE.Group();
438
- clippingGroup.name = `clipping-${i}`;
439
-
440
- clippingGroup.add(
441
- createStencil(
442
- `frontStencil-${i}-${j}`,
443
- ClippingMaterials.createFrontStencilMaterial(),
444
- group.shapeGeometry!,
445
- plane,
446
- ),
447
- );
448
-
449
- clippingGroup.add(
450
- createStencil(
451
- `backStencil-${i}-${j}`,
452
- ClippingMaterials.createBackStencilMaterial(),
453
- group.shapeGeometry!,
454
- plane,
455
- ),
456
- );
457
-
458
- group.addClipping(clippingGroup, i);
459
-
460
- // Create stencil plane mesh
461
- const planeMaterial = ClippingMaterials.createStencilPlaneMaterial(
462
- PLANE_COLORS[theme][i],
463
- otherPlanes,
464
- );
465
-
466
- this._planeMeshGroup.add(
467
- new PlaneMesh(
468
- i,
469
- plane,
470
- center,
471
- size,
472
- planeMaterial,
473
- PLANE_COLORS[theme][i],
474
- `StencilPlane-${i}-${j}`,
475
- ),
476
- );
477
- j++;
478
- }
479
- }
480
- }
481
-
482
- this.nestedGroup.rootGroup!.add(this._planeMeshGroup);
483
- }
484
-
485
- /**
486
- * Rebuild stencil meshes after scene changes (part add/remove).
487
- * Clears existing stencils from all ObjectGroups and rebuilds from scratch.
488
- * Also updates clipping region size if center/size changed.
489
- * @param center - The new center point [x, y, z].
490
- * @param size - The new size of the clipping region.
491
- */
492
- rebuildStencils(center: number[], size: number): void {
493
- // Clear existing clipping stencils from all ObjectGroups
494
- for (const path in this.nestedGroup.groups) {
495
- const group = this.nestedGroup.groups[path];
496
- if (group instanceof ObjectGroup) {
497
- group.clearClipping();
498
- }
499
- }
500
-
501
- // Remove old plane mesh group from scene
502
- if (this._planeMeshGroup && this.nestedGroup.rootGroup) {
503
- this.nestedGroup.rootGroup.remove(this._planeMeshGroup);
504
- deepDispose(this._planeMeshGroup);
505
- this._planeMeshGroup = null;
506
- }
507
-
508
- // Clear object colors
509
- this.objectColors = [];
510
-
511
- // Update size/distance
512
- this.center = center;
513
- this.size = size;
514
- this.distance = size / 2;
515
-
516
- // Rebuild stencils with current state
517
- this._createStencils(center, size, this.theme);
518
-
519
- // Reapply object color caps if enabled
520
- if (this.objectColorCaps) {
521
- this.setObjectColorCaps(true);
522
- }
523
- }
524
-
525
- /**
526
- * Set the constant (distance from center) for a clipping plane.
527
- * @param index - The plane index (0, 1, or 2).
528
- * @param value - The constant value relative to center.
529
- */
530
- setConstant(index: ClipIndex, value: number): void {
531
- this.clipPlanes[index].setConstant(value);
532
- this.reverseClipPlanes[index].setConstant(-value);
533
- }
534
-
535
- /**
536
- * Set the normal vector for a clipping plane.
537
- * @param index - The plane index (0, 1, or 2).
538
- * @param normal - The new normal vector.
539
- */
540
- setNormal = (index: ClipIndex, normal: THREE.Vector3): void => {
541
- const n = normal.clone();
542
- this.clipPlanes[index].normal = n;
543
- this.reverseClipPlanes[index].normal = n.clone().negate();
544
- this.setConstant(index, this.distance);
545
- if (this.onNormalChange) {
546
- this.onNormalChange(index, toVector3Tuple(n.toArray()));
547
- }
548
- };
549
-
550
- /**
551
- * Get whether object color caps mode is enabled.
552
- * @returns True if object color caps mode is enabled.
553
- */
554
- getObjectColorCaps = (): boolean => {
555
- return this.objectColorCaps;
556
- };
557
-
558
- /**
559
- * Toggle object color caps mode.
560
- * When enabled, stencil planes use the original object colors.
561
- * When disabled, stencil planes use theme-based plane colors.
562
- * @param flag - True to enable object color caps.
563
- */
564
- setObjectColorCaps = (flag: boolean): void => {
565
- if (!this._planeMeshGroup) return;
566
-
567
- let i = 0;
568
- let j = -1;
569
- const len = this._planeMeshGroup.children.length / 3;
570
- for (const mesh of this._planeMeshGroup.children) {
571
- if (i % len === 0) {
572
- j++;
573
- }
574
- const color = flag ? this.objectColors[i] : PLANE_COLORS[this.theme][j];
575
- mesh.material.color.set(new THREE.Color(color));
576
- i++;
577
- }
578
- this.objectColorCaps = flag;
579
- };
580
-
581
- /**
582
- * Set visibility of stencil plane meshes.
583
- * @param flag - True to show, false to hide.
584
- */
585
- setVisible = (flag: boolean): void => {
586
- if (!this._planeMeshGroup) return;
587
-
588
- for (const mesh of this._planeMeshGroup.children) {
589
- mesh.material.visible = flag;
590
- }
591
- };
592
-
593
- /**
594
- * Save the current clipping state for later restoration.
595
- * Captures plane positions, helper visibility, and stencil plane visibility.
596
- * Used by Studio mode to snapshot clipping state before disabling clipping.
597
- *
598
- * Note: `renderer.localClippingEnabled` and `clipPlaneHelpers` ViewerState
599
- * are managed by the caller (Display/Viewer layer), not captured here.
600
- */
601
- saveState(): ClippingState {
602
- return {
603
- planeConstants: [
604
- this.clipPlanes[0].centeredConstant,
605
- this.clipPlanes[1].centeredConstant,
606
- this.clipPlanes[2].centeredConstant,
607
- ],
608
- helperVisible: this.planeHelpers?.visible ?? false,
609
- planesVisible: this._planeMeshGroup?.children.length
610
- ? this._planeMeshGroup.children[0].material.visible
611
- : false,
612
- };
613
- }
614
-
615
- /**
616
- * Restore a previously saved clipping state.
617
- * Re-applies plane positions, helper visibility, and stencil plane visibility.
618
- * Used by Studio mode when leaving to restore the clipping configuration.
619
- *
620
- * @param state - The state previously captured by `saveState()`.
621
- */
622
- restoreState(state: ClippingState): void {
623
- // Restore plane positions
624
- for (const i of CLIP_INDICES) {
625
- this.setConstant(i, state.planeConstants[i]);
626
- }
627
-
628
- // Restore plane helper visibility
629
- if (this.planeHelpers) {
630
- this.planeHelpers.visible = state.helperVisible;
631
- }
632
-
633
- // Restore stencil plane mesh visibility
634
- this.setVisible(state.planesVisible);
635
- }
636
-
637
- /**
638
- * Clean up resources.
639
- * Note: We don't null out arrays/references as GC handles cleanup when the Clipping object is collected.
640
- */
641
- dispose(): void {
642
- this.onNormalChange = null;
643
- this.center = null;
644
- this.planeHelpers = null;
645
- this._planeMeshGroup = null;
646
- }
647
- }
648
-
649
- export { Clipping };
650
- export type { ClippingState };