three-cad-viewer 4.3.4 → 4.3.6

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