three-cad-viewer 4.1.2 → 4.2.0

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/Readme.md +12 -5
  2. package/dist/camera/camera.d.ts +14 -2
  3. package/dist/core/studio-manager.d.ts +91 -0
  4. package/dist/core/types.d.ts +260 -9
  5. package/dist/core/viewer-state.d.ts +28 -2
  6. package/dist/core/viewer.d.ts +200 -6
  7. package/dist/index.d.ts +7 -2
  8. package/dist/rendering/environment.d.ts +239 -0
  9. package/dist/rendering/light-detection.d.ts +44 -0
  10. package/dist/rendering/material-factory.d.ts +77 -2
  11. package/dist/rendering/material-presets.d.ts +32 -0
  12. package/dist/rendering/room-environment.d.ts +13 -0
  13. package/dist/rendering/studio-composer.d.ts +130 -0
  14. package/dist/rendering/studio-floor.d.ts +53 -0
  15. package/dist/rendering/texture-cache.d.ts +142 -0
  16. package/dist/rendering/triplanar.d.ts +37 -0
  17. package/dist/scene/animation.d.ts +1 -1
  18. package/dist/scene/clipping.d.ts +31 -0
  19. package/dist/scene/nestedgroup.d.ts +64 -27
  20. package/dist/scene/objectgroup.d.ts +47 -0
  21. package/dist/three-cad-viewer.css +339 -29
  22. package/dist/three-cad-viewer.esm.js +27567 -11874
  23. package/dist/three-cad-viewer.esm.js.map +1 -1
  24. package/dist/three-cad-viewer.esm.min.js +10 -4
  25. package/dist/three-cad-viewer.js +27486 -11787
  26. package/dist/three-cad-viewer.min.js +10 -4
  27. package/dist/ui/display.d.ts +147 -0
  28. package/dist/utils/decode-instances.d.ts +60 -0
  29. package/dist/utils/utils.d.ts +10 -0
  30. package/package.json +4 -2
  31. package/src/_version.ts +1 -1
  32. package/src/camera/camera.ts +27 -10
  33. package/src/core/studio-manager.ts +682 -0
  34. package/src/core/types.ts +328 -9
  35. package/src/core/viewer-state.ts +84 -4
  36. package/src/core/viewer.ts +453 -22
  37. package/src/index.ts +25 -1
  38. package/src/rendering/environment.ts +840 -0
  39. package/src/rendering/light-detection.ts +327 -0
  40. package/src/rendering/material-factory.ts +456 -2
  41. package/src/rendering/material-presets.ts +303 -0
  42. package/src/rendering/raycast.ts +2 -2
  43. package/src/rendering/room-environment.ts +192 -0
  44. package/src/rendering/studio-composer.ts +577 -0
  45. package/src/rendering/studio-floor.ts +108 -0
  46. package/src/rendering/texture-cache.ts +1020 -0
  47. package/src/rendering/triplanar.ts +329 -0
  48. package/src/scene/animation.ts +3 -2
  49. package/src/scene/clipping.ts +59 -0
  50. package/src/scene/nestedgroup.ts +399 -0
  51. package/src/scene/objectgroup.ts +186 -11
  52. package/src/scene/orientation.ts +12 -0
  53. package/src/scene/render-shape.ts +55 -21
  54. package/src/types/n8ao.d.ts +28 -0
  55. package/src/ui/display.ts +1032 -27
  56. package/src/ui/index.html +181 -44
  57. package/src/utils/decode-instances.ts +233 -0
  58. package/src/utils/utils.ts +33 -20
@@ -1,7 +1,38 @@
1
1
  import * as THREE from "three";
2
2
  import { LineMaterial } from "three/examples/jsm/lines/LineMaterial.js";
3
- import type { ColorValue } from "../core/types.js";
3
+ import type { ColorValue, MaterialAppearance } from "../core/types.js";
4
4
  import { gpuTracker } from "../utils/gpu-tracker.js";
5
+ import { logger } from "../utils/logger.js";
6
+ import { getColorSpaceForMap } from "./texture-cache.js";
7
+
8
+ /** threejs-materials property keys that hold [r,g,b] color arrays (linear RGB). */
9
+ const COLOR_ARRAY_KEYS = new Set([
10
+ "color", "specularColor", "sheenColor", "emissive", "attenuationColor",
11
+ ]);
12
+
13
+ /** Map from threejs-materials property names to Three.js texture map property names. */
14
+ const PROPERTY_TO_MAP: Record<string, string> = {
15
+ color: "map",
16
+ metalness: "metalnessMap",
17
+ roughness: "roughnessMap",
18
+ normal: "normalMap",
19
+ emissive: "emissiveMap",
20
+ specularIntensity: "specularIntensityMap",
21
+ specularColor: "specularColorMap",
22
+ clearcoat: "clearcoatMap",
23
+ clearcoatRoughness: "clearcoatRoughnessMap",
24
+ clearcoatNormal: "clearcoatNormalMap",
25
+ transmission: "transmissionMap",
26
+ sheenColor: "sheenColorMap",
27
+ sheenRoughness: "sheenRoughnessMap",
28
+ anisotropy: "anisotropyMap",
29
+ iridescence: "iridescenceMap",
30
+ iridescenceThickness: "iridescenceThicknessMap",
31
+ ao: "aoMap",
32
+ occlusion: "aoMap",
33
+ thickness: "thicknessMap",
34
+ opacity: "alphaMap",
35
+ };
5
36
 
6
37
  /**
7
38
  * Options for MaterialFactory constructor
@@ -80,6 +111,29 @@ interface TextureMaterialOptions {
80
111
  visible?: boolean;
81
112
  }
82
113
 
114
+ /**
115
+ * Interface for the TextureCache dependency.
116
+ * The actual TextureCache class is defined in texture-cache.ts.
117
+ * We depend only on its get() method for loose coupling.
118
+ */
119
+ interface TextureCacheInterface {
120
+ get(ref: string, textureRole: string): Promise<THREE.Texture | null>;
121
+ }
122
+
123
+ /**
124
+ * Options for Studio mode materials.
125
+ */
126
+ interface StudioMaterialOptions {
127
+ /** Resolved MaterialAppearance definition (already looked up from materials table / presets) */
128
+ materialDef: MaterialAppearance;
129
+ /** Fallback CSS hex color from the leaf node (e.g., "#cc0000") */
130
+ fallbackColor: ColorValue;
131
+ /** Fallback alpha from the leaf node (0-1) */
132
+ fallbackAlpha: number;
133
+ /** TextureCache for resolving texture references */
134
+ textureCache: TextureCacheInterface | null;
135
+ }
136
+
83
137
  /**
84
138
  * Options for updating factory settings
85
139
  */
@@ -266,6 +320,406 @@ class MaterialFactory {
266
320
  return material;
267
321
  }
268
322
 
323
+ /**
324
+ * Create a Studio mode material from a resolved MaterialAppearance.
325
+ *
326
+ * Always creates MeshPhysicalMaterial (except when `unlit: true`, which
327
+ * uses MeshBasicMaterial). MeshPhysicalMaterial is a superset of
328
+ * MeshStandardMaterial; when advanced features are off (transmission=0,
329
+ * clearcoat=0, sheen=0, etc.), the shader compiles to essentially the
330
+ * same cost.
331
+ *
332
+ * @param options - Studio material options
333
+ * @param label - Optional label for GPU tracking
334
+ * @returns Configured MeshPhysicalMaterial (or MeshBasicMaterial if unlit)
335
+ */
336
+ async createStudioMaterial(
337
+ { materialDef, fallbackColor, fallbackAlpha, textureCache }: StudioMaterialOptions,
338
+ label?: string,
339
+ ): Promise<THREE.MeshPhysicalMaterial | THREE.MeshBasicMaterial> {
340
+ const def = materialDef;
341
+ const side = def.doubleSided ? THREE.DoubleSide : THREE.FrontSide;
342
+
343
+ // --- Resolve base color and opacity ---
344
+ let baseColor: THREE.Color;
345
+ let opacity: number;
346
+
347
+ if (def.color) {
348
+ if (typeof def.color === "string") {
349
+ // CSS hex string (e.g. "#55a0e3") — THREE.Color parses as sRGB
350
+ baseColor = new THREE.Color(def.color);
351
+ opacity = 1.0;
352
+ } else {
353
+ // sRGB RGBA tuple [R, G, B, A?] (0-1)
354
+ baseColor = new THREE.Color().setRGB(
355
+ def.color[0], def.color[1], def.color[2],
356
+ THREE.SRGBColorSpace,
357
+ );
358
+ opacity = def.color[3] ?? 1.0;
359
+ }
360
+ } else {
361
+ // Fall back to leaf node's CSS hex color + alpha.
362
+ // THREE.Color constructor with a hex number or CSS string produces
363
+ // linear-space values in Three.js r152+.
364
+ baseColor = new THREE.Color(fallbackColor);
365
+ opacity = fallbackAlpha;
366
+ }
367
+
368
+ // --- Unlit path: MeshBasicMaterial ---
369
+ if (def.unlit) {
370
+ const basicMat = new THREE.MeshBasicMaterial({
371
+ ...this._createBaseProps(opacity),
372
+ color: baseColor,
373
+ side,
374
+ });
375
+ // Apply alpha mode to basic material too
376
+ this._applyAlphaMode(basicMat, def, opacity);
377
+ // Resolve base color texture
378
+ if (def.map && textureCache) {
379
+ const tex = await textureCache.get(def.map, "baseColorTexture");
380
+ if (tex) basicMat.map = tex;
381
+ }
382
+ gpuTracker.track("material", basicMat, label ?? "MeshBasicMaterial (studio unlit)");
383
+ return basicMat;
384
+ }
385
+
386
+ // --- PBR path: MeshPhysicalMaterial ---
387
+ // Studio materials default to opaque (transparent: false). Unlike CAD
388
+ // mode, Studio mode has no clipping and doesn't need the global
389
+ // transparent:true flag. Only BLEND alpha mode enables transparency.
390
+ const isBlend = def.alphaMode === "BLEND" || (!def.alphaMode && opacity < 1.0);
391
+ const material = new THREE.MeshPhysicalMaterial({
392
+ color: baseColor,
393
+ metalness: def.metalness ?? 0.0,
394
+ roughness: def.roughness ?? 0.5,
395
+ flatShading: false,
396
+ side,
397
+ transparent: isBlend,
398
+ opacity: opacity,
399
+ depthWrite: !isBlend,
400
+ depthTest: true,
401
+ polygonOffset: true,
402
+ polygonOffsetFactor: 1.0,
403
+ polygonOffsetUnits: 1.0,
404
+ });
405
+
406
+ // --- Alpha mode ---
407
+ this._applyAlphaMode(material, def, opacity);
408
+
409
+ // --- Emissive ---
410
+ if (def.emissive) {
411
+ material.emissive = new THREE.Color(def.emissive[0], def.emissive[1], def.emissive[2]);
412
+ }
413
+ if (def.emissiveIntensity !== undefined) {
414
+ material.emissiveIntensity = def.emissiveIntensity;
415
+ }
416
+
417
+ // --- Transmission (glass, water) ---
418
+ // Transmission uses a separate render target in Three.js and must NOT
419
+ // be combined with alpha blending (transparent: true). Override here
420
+ // so users don't need to set alphaMode: "OPAQUE" manually.
421
+ if (def.transmission !== undefined) {
422
+ material.transmission = def.transmission;
423
+ if (def.transmission > 0) {
424
+ material.transparent = false;
425
+ material.opacity = 1.0;
426
+ material.depthWrite = true;
427
+ }
428
+ }
429
+
430
+ // --- Clearcoat (car paint, varnish) ---
431
+ if (def.clearcoat !== undefined) {
432
+ material.clearcoat = def.clearcoat;
433
+ }
434
+ if (def.clearcoatRoughness !== undefined) {
435
+ material.clearcoatRoughness = def.clearcoatRoughness;
436
+ }
437
+
438
+ // --- Volume (subsurface: jade, wax, skin) ---
439
+ if (def.thickness !== undefined) {
440
+ material.thickness = def.thickness;
441
+ }
442
+ if (def.attenuationDistance !== undefined) {
443
+ material.attenuationDistance = def.attenuationDistance;
444
+ }
445
+ if (def.attenuationColor) {
446
+ material.attenuationColor = new THREE.Color(
447
+ def.attenuationColor[0], def.attenuationColor[1], def.attenuationColor[2],
448
+ );
449
+ }
450
+
451
+ // --- IOR ---
452
+ if (def.ior !== undefined) {
453
+ material.ior = def.ior;
454
+ }
455
+
456
+ // --- Specular ---
457
+ if (def.specularIntensity !== undefined) {
458
+ material.specularIntensity = def.specularIntensity;
459
+ }
460
+ if (def.specularColor) {
461
+ material.specularColor = new THREE.Color(
462
+ def.specularColor[0], def.specularColor[1], def.specularColor[2],
463
+ );
464
+ }
465
+
466
+ // --- Sheen (fabric, velvet) ---
467
+ // sheen > 0 enables the sheen layer in Three.js
468
+ if (def.sheen !== undefined && def.sheen > 0) {
469
+ material.sheen = def.sheen;
470
+ if (def.sheenColor) {
471
+ material.sheenColor = new THREE.Color(
472
+ def.sheenColor[0], def.sheenColor[1], def.sheenColor[2],
473
+ );
474
+ }
475
+ if (def.sheenRoughness !== undefined) {
476
+ material.sheenRoughness = def.sheenRoughness;
477
+ }
478
+ }
479
+
480
+ // --- Anisotropy (brushed metal) ---
481
+ if (def.anisotropy !== undefined) {
482
+ material.anisotropy = def.anisotropy;
483
+ }
484
+ if (def.anisotropyRotation !== undefined) {
485
+ material.anisotropyRotation = def.anisotropyRotation;
486
+ }
487
+
488
+ // --- Textures ---
489
+ // Resolve all texture references via TextureCache.
490
+ // The TextureCache determines colorSpace internally from the texture role name.
491
+ if (textureCache) {
492
+ await this._applyStudioTextures(material, def, textureCache);
493
+ }
494
+
495
+ gpuTracker.track("material", material, label ?? "MeshPhysicalMaterial (studio)");
496
+ return material;
497
+ }
498
+
499
+ /**
500
+ * Create a Studio mode material from a threejs-materials format entry.
501
+ *
502
+ * threejs-materials `properties` uses simplified property names (e.g., "color",
503
+ * "roughness", "normal") where each entry has an optional `value` (scalar or
504
+ * [r,g,b] array in **linear RGB**) and/or `texture` (inline data URI).
505
+ *
506
+ * @param properties - Material properties from threejs-materials
507
+ * @param textureRepeat - Optional [u, v] texture tiling applied to all loaded textures
508
+ * @param textureCache - TextureCache for resolving data URI textures
509
+ * @param label - Optional label for GPU tracking
510
+ * @returns Configured MeshPhysicalMaterial
511
+ */
512
+ async createStudioMaterialFromMaterialX(
513
+ properties: Record<string, { value?: unknown; texture?: string }>,
514
+ textureRepeat: [number, number] | undefined,
515
+ textureCache: TextureCacheInterface | null,
516
+ label?: string,
517
+ ): Promise<THREE.MeshPhysicalMaterial> {
518
+ // --- Build material options from scalar values ---
519
+ const matOptions: Record<string, unknown> = {
520
+ flatShading: false,
521
+ side: THREE.FrontSide,
522
+ polygonOffset: true,
523
+ polygonOffsetFactor: 1.0,
524
+ polygonOffsetUnits: 1.0,
525
+ depthTest: true,
526
+ };
527
+
528
+ // Warn once if displacement data is present (not supported in Studio)
529
+ if (properties.displacement?.texture || properties.displacementScale?.value !== undefined) {
530
+ logger.warn("Displacement not supported by the Studio");
531
+ }
532
+
533
+ for (const [key, prop] of Object.entries(properties)) {
534
+ if (prop.value === undefined) continue;
535
+
536
+ // Skip displacement properties (not supported, would waste GPU memory)
537
+ if (key === "displacement" || key === "displacementScale" || key === "displacementBias") continue;
538
+
539
+ // Color arrays → THREE.Color (already linear, no sRGB conversion)
540
+ if (COLOR_ARRAY_KEYS.has(key) && Array.isArray(prop.value)) {
541
+ const [r, g, b] = prop.value as number[];
542
+ matOptions[key] = new THREE.Color(r, g, b);
543
+ } else if (key === "iridescenceThicknessRange" && Array.isArray(prop.value)) {
544
+ matOptions[key] = prop.value;
545
+ } else {
546
+ matOptions[key] = prop.value;
547
+ }
548
+ }
549
+
550
+ // --- Handle transmission ---
551
+ const transmissionVal = properties.transmission?.value;
552
+ const opacityVal = properties.opacity?.value;
553
+ const transparentVal = properties.transparent?.value;
554
+ if (typeof transmissionVal === "number" && transmissionVal > 0) {
555
+ matOptions.transparent = false;
556
+ matOptions.opacity = 1.0;
557
+ matOptions.depthWrite = true;
558
+ } else if (transparentVal === true || (typeof opacityVal === "number" && opacityVal < 1.0)) {
559
+ matOptions.transparent = true;
560
+ matOptions.depthWrite = false;
561
+ } else {
562
+ matOptions.transparent = false;
563
+ matOptions.depthWrite = true;
564
+ }
565
+
566
+ const material = new THREE.MeshPhysicalMaterial(matOptions);
567
+
568
+ // --- Resolve textures ---
569
+ let hasTextures = false;
570
+ if (textureCache) {
571
+ for (const [key, prop] of Object.entries(properties)) {
572
+ if (!prop.texture) continue;
573
+
574
+ const mapName = PROPERTY_TO_MAP[key];
575
+ if (!mapName) continue;
576
+
577
+ // Determine color space from the Three.js map property name.
578
+ // TextureCache.get() expects a role name to decide colorSpace.
579
+ // Bridge from Three.js map name → colorSpace → a proxy role name.
580
+ const colorSpace = getColorSpaceForMap(mapName);
581
+ const roleForCache = colorSpace === THREE.SRGBColorSpace
582
+ ? "baseColorTexture"
583
+ : "normalTexture";
584
+ const tex = await textureCache.get(prop.texture, roleForCache);
585
+ if (tex) {
586
+ if (textureRepeat) {
587
+ tex.repeat.set(textureRepeat[0], textureRepeat[1]);
588
+ }
589
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
590
+ (material as any)[mapName] = tex;
591
+ hasTextures = true;
592
+ }
593
+ }
594
+
595
+ }
596
+
597
+ // Enable alpha cutout when an alphaMap is present
598
+ if (material.alphaMap) {
599
+ material.alphaTest = 0.5;
600
+ material.side = THREE.DoubleSide;
601
+ }
602
+
603
+ // Force shader recompile if textures were assigned post-construction
604
+ if (hasTextures) {
605
+ material.needsUpdate = true;
606
+ }
607
+
608
+ gpuTracker.track("material", material, label ?? "MeshPhysicalMaterial (threejs-materials)");
609
+ return material;
610
+ }
611
+
612
+ /**
613
+ * Apply alpha mode settings to a material.
614
+ *
615
+ * - OPAQUE: fully opaque, no transparency
616
+ * - MASK: alpha testing with cutoff threshold
617
+ * - BLEND: standard alpha blending
618
+ * - Default (no alphaMode): transparent: true (current viewer behavior)
619
+ */
620
+ private _applyAlphaMode(
621
+ material: THREE.Material & { opacity: number },
622
+ def: MaterialAppearance,
623
+ opacity: number,
624
+ ): void {
625
+ switch (def.alphaMode) {
626
+ case "OPAQUE":
627
+ material.transparent = false;
628
+ material.opacity = 1.0;
629
+ material.depthWrite = true;
630
+ break;
631
+ case "MASK":
632
+ material.transparent = false;
633
+ material.alphaTest = def.alphaCutoff ?? 0.5;
634
+ material.opacity = opacity;
635
+ material.depthWrite = true;
636
+ break;
637
+ case "BLEND":
638
+ material.transparent = true;
639
+ material.opacity = opacity;
640
+ material.depthWrite = false;
641
+ break;
642
+ // default: no alphaMode set -- keep _createBaseProps defaults (transparent: true)
643
+ }
644
+ }
645
+
646
+ /**
647
+ * Resolve and apply texture references from a MaterialAppearance onto a
648
+ * MeshPhysicalMaterial via the TextureCache.
649
+ *
650
+ * Color-data textures (base color, emissive, sheen color, specular color)
651
+ * are requested with SRGBColorSpace. All other textures (normal, metallic-
652
+ * roughness, occlusion, roughness maps, transmission, thickness) are
653
+ * requested with LinearSRGBColorSpace (the default).
654
+ *
655
+ * The metallicRoughnessTexture is a single combined texture where
656
+ * B channel = metalness and G channel = roughness. It is assigned to
657
+ * both metalnessMap and roughnessMap on the material.
658
+ */
659
+ private async _applyStudioTextures(
660
+ material: THREE.MeshPhysicalMaterial,
661
+ def: MaterialAppearance,
662
+ textureCache: TextureCacheInterface,
663
+ ): Promise<void> {
664
+ // Helper to resolve a texture reference. The TextureCache determines
665
+ // colorSpace internally from the textureRole name (sRGB for color-data
666
+ // textures like baseColorTexture, linear for non-color data like normalTexture).
667
+ const resolve = async (key: string | undefined, textureRole: string): Promise<THREE.Texture | null> => {
668
+ if (!key) return null;
669
+ return textureCache.get(key, textureRole);
670
+ };
671
+
672
+ // --- sRGB color-data textures ---
673
+ const baseColorTex = await resolve(def.map, "baseColorTexture");
674
+ if (baseColorTex) material.map = baseColorTex;
675
+
676
+ const emissiveTex = await resolve(def.emissiveMap, "emissiveTexture");
677
+ if (emissiveTex) material.emissiveMap = emissiveTex;
678
+
679
+ const sheenColorTex = await resolve(def.sheenColorMap, "sheenColorTexture");
680
+ if (sheenColorTex) material.sheenColorMap = sheenColorTex;
681
+
682
+ const specularColorTex = await resolve(def.specularColorMap, "specularColorTexture");
683
+ if (specularColorTex) material.specularColorMap = specularColorTex;
684
+
685
+ // --- Linear non-color data textures ---
686
+ const normalTex = await resolve(def.normalMap, "normalTexture");
687
+ if (normalTex) material.normalMap = normalTex;
688
+
689
+ const occlusionTex = await resolve(def.aoMap, "occlusionTexture");
690
+ if (occlusionTex) material.aoMap = occlusionTex;
691
+
692
+ const metalnessTex = await resolve(def.metalnessMap, "metallicRoughnessTexture");
693
+ if (metalnessTex) material.metalnessMap = metalnessTex;
694
+
695
+ const roughnessTex = await resolve(def.roughnessMap, "metallicRoughnessTexture");
696
+ if (roughnessTex) material.roughnessMap = roughnessTex;
697
+
698
+ const transmissionTex = await resolve(def.transmissionMap, "transmissionTexture");
699
+ if (transmissionTex) material.transmissionMap = transmissionTex;
700
+
701
+ const thicknessTex = await resolve(def.thicknessMap, "thicknessTexture");
702
+ if (thicknessTex) material.thicknessMap = thicknessTex;
703
+
704
+ const clearcoatTex = await resolve(def.clearcoatMap, "clearcoatTexture");
705
+ if (clearcoatTex) material.clearcoatMap = clearcoatTex;
706
+
707
+ const clearcoatRoughnessTex = await resolve(def.clearcoatRoughnessMap, "clearcoatRoughnessTexture");
708
+ if (clearcoatRoughnessTex) material.clearcoatRoughnessMap = clearcoatRoughnessTex;
709
+
710
+ const clearcoatNormalTex = await resolve(def.clearcoatNormalMap, "clearcoatNormalTexture");
711
+ if (clearcoatNormalTex) material.clearcoatNormalMap = clearcoatNormalTex;
712
+
713
+ const specularIntensityTex = await resolve(def.specularIntensityMap, "specularIntensityTexture");
714
+ if (specularIntensityTex) material.specularIntensityMap = specularIntensityTex;
715
+
716
+ const sheenRoughnessTex = await resolve(def.sheenRoughnessMap, "sheenRoughnessTexture");
717
+ if (sheenRoughnessTex) material.sheenRoughnessMap = sheenRoughnessTex;
718
+
719
+ const anisotropyTex = await resolve(def.anisotropyMap, "anisotropyTexture");
720
+ if (anisotropyTex) material.anisotropyMap = anisotropyTex;
721
+ }
722
+
269
723
  /**
270
724
  * Update global settings.
271
725
  */
@@ -279,4 +733,4 @@ class MaterialFactory {
279
733
  }
280
734
 
281
735
  export { MaterialFactory };
282
- export type { MaterialFactoryOptions, UpdateOptions };
736
+ export type { MaterialFactoryOptions, UpdateOptions, StudioMaterialOptions, TextureCacheInterface };