@needle-tools/engine 4.14.0-next.31f837e → 4.14.0-next.b2e3b1a

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 (95) hide show
  1. package/CHANGELOG.md +9 -0
  2. package/components.needle.json +1 -1
  3. package/dist/{generateMeshBVH.worker-DFcS3P04.js → generateMeshBVH.worker-DiCnZlf3.js} +1 -1
  4. package/dist/{gltf-progressive-8voIgNp_.js → gltf-progressive-Bm_6aEi4.js} +4 -4
  5. package/dist/{gltf-progressive-BRRBj-nY.umd.cjs → gltf-progressive-BttGBXw6.umd.cjs} +3 -3
  6. package/dist/{gltf-progressive-Dkh3tG4-.min.js → gltf-progressive-T5WKTux5.min.js} +1 -1
  7. package/dist/{loader.worker-C6cXDgR1.js → loader.worker-BqODMeeW.js} +1 -1
  8. package/dist/{materialx-Dx8st96L.min.js → materialx-CJyQZtjt.min.js} +1 -1
  9. package/dist/{materialx-D66rYPqe.js → materialx-DMs1E08Z.js} +2 -2
  10. package/dist/{materialx-CxlgposR.umd.cjs → materialx-DaKKOoVk.umd.cjs} +1 -1
  11. package/dist/{needle-engine.bundle-BQXG5qbQ.umd.cjs → needle-engine.bundle-BC1QDiuv.umd.cjs} +139 -139
  12. package/dist/{needle-engine.bundle-D7w0XD7M.min.js → needle-engine.bundle-Bhgt3W8p.min.js} +134 -134
  13. package/dist/{needle-engine.bundle-Byl5i6zJ.js → needle-engine.bundle-CeQXs7Hh.js} +5966 -5880
  14. package/dist/needle-engine.d.ts +552 -31
  15. package/dist/needle-engine.js +4 -4
  16. package/dist/needle-engine.min.js +1 -1
  17. package/dist/needle-engine.umd.cjs +1 -1
  18. package/dist/{postprocessing-Ce5-UWiA.min.js → postprocessing-06AXuvdv.min.js} +2 -2
  19. package/dist/{postprocessing-BkSpxpYB.js → postprocessing-CI2x8Cln.js} +4 -4
  20. package/dist/{postprocessing-DFVElmAh.umd.cjs → postprocessing-CPDcA21P.umd.cjs} +2 -2
  21. package/dist/{three-Bad8p1pf.umd.cjs → three-BjYim-vL.umd.cjs} +47 -47
  22. package/dist/{three-DFV1-P9z.js → three-Bvk2VKbF.js} +2 -2
  23. package/dist/{three-CWn13_u1.min.js → three-IG2qPafA.min.js} +2 -2
  24. package/dist/{three-examples-CO-tx3Sp.umd.cjs → three-examples-BMmNgNCN.umd.cjs} +1 -1
  25. package/dist/{three-examples-43yqn3mL.js → three-examples-CMYCd5nH.js} +1 -1
  26. package/dist/{three-examples-DKuJVGT4.min.js → three-examples-CQl1fFZp.min.js} +1 -1
  27. package/dist/{three-mesh-ui-DyEA5HQF.min.js → three-mesh-ui-5HVE2RV-.min.js} +1 -1
  28. package/dist/{three-mesh-ui-fSAQJxdI.js → three-mesh-ui-BlakAItG.js} +1 -1
  29. package/dist/{three-mesh-ui-ChzVOraf.umd.cjs → three-mesh-ui-D828VbQp.umd.cjs} +1 -1
  30. package/dist/{vendor-pe19S9r5.min.js → vendor-BxK0WKmT.min.js} +1 -1
  31. package/dist/{vendor-B51YffMU.umd.cjs → vendor-CIDkyBaO.umd.cjs} +1 -1
  32. package/dist/{vendor-CgpZ5ivC.js → vendor-ixwD-vv2.js} +1 -1
  33. package/lib/engine/api.d.ts +1 -1
  34. package/lib/engine/api.js +1 -1
  35. package/lib/engine/api.js.map +1 -1
  36. package/lib/engine/engine_components.d.ts +1 -1
  37. package/lib/engine/engine_components.js +7 -3
  38. package/lib/engine/engine_components.js.map +1 -1
  39. package/lib/engine/engine_context.d.ts +12 -0
  40. package/lib/engine/engine_context.js +29 -0
  41. package/lib/engine/engine_context.js.map +1 -1
  42. package/lib/engine/engine_gltf_builtin_components.js +16 -1
  43. package/lib/engine/engine_gltf_builtin_components.js.map +1 -1
  44. package/lib/engine/engine_materialpropertyblock.d.ts +223 -11
  45. package/lib/engine/engine_materialpropertyblock.js +303 -33
  46. package/lib/engine/engine_materialpropertyblock.js.map +1 -1
  47. package/lib/engine-components/Camera.js.map +1 -1
  48. package/lib/engine-components/DropListener.js.map +1 -1
  49. package/lib/engine-components/Duplicatable.js.map +1 -1
  50. package/lib/engine-components/GroundProjection.js.map +1 -1
  51. package/lib/engine-components/NeedleMenu.js.map +1 -1
  52. package/lib/engine-components/NestedGltf.js.map +1 -1
  53. package/lib/engine-components/ReflectionProbe.d.ts +32 -3
  54. package/lib/engine-components/ReflectionProbe.js +57 -26
  55. package/lib/engine-components/ReflectionProbe.js.map +1 -1
  56. package/lib/engine-components/Renderer.d.ts +2 -0
  57. package/lib/engine-components/Renderer.js +30 -6
  58. package/lib/engine-components/Renderer.js.map +1 -1
  59. package/lib/engine-components/RendererLightmap.js +2 -3
  60. package/lib/engine-components/RendererLightmap.js.map +1 -1
  61. package/lib/engine-components/SeeThrough.d.ts +0 -2
  62. package/lib/engine-components/SeeThrough.js +114 -88
  63. package/lib/engine-components/SeeThrough.js.map +1 -1
  64. package/lib/engine-components/SmoothFollow.js.map +1 -1
  65. package/lib/engine-components/ui/Button.js.map +1 -1
  66. package/lib/engine-components/ui/Raycaster.js.map +1 -1
  67. package/lib/engine-components/web/ViewBox.d.ts +2 -2
  68. package/lib/engine-components/web/ViewBox.js +2 -2
  69. package/lib/engine-components/web/ViewBox.js.map +1 -1
  70. package/lib/engine-components/webxr/WebXRPlaneTracking.js.map +1 -1
  71. package/lib/engine-components/webxr/controllers/XRControllerFollow.js.map +1 -1
  72. package/lib/engine-components/webxr/controllers/XRControllerMovement.js.map +1 -1
  73. package/package.json +4 -4
  74. package/src/engine/api.ts +1 -1
  75. package/src/engine/engine_components.ts +7 -3
  76. package/src/engine/engine_context.ts +28 -2
  77. package/src/engine/engine_gltf_builtin_components.ts +17 -1
  78. package/src/engine/engine_materialpropertyblock.ts +405 -39
  79. package/src/engine-components/Camera.ts +2 -2
  80. package/src/engine-components/DropListener.ts +1 -1
  81. package/src/engine-components/Duplicatable.ts +1 -1
  82. package/src/engine-components/GroundProjection.ts +3 -0
  83. package/src/engine-components/NeedleMenu.ts +3 -0
  84. package/src/engine-components/NestedGltf.ts +1 -1
  85. package/src/engine-components/ReflectionProbe.ts +61 -30
  86. package/src/engine-components/Renderer.ts +34 -6
  87. package/src/engine-components/RendererLightmap.ts +2 -3
  88. package/src/engine-components/SeeThrough.ts +122 -107
  89. package/src/engine-components/SmoothFollow.ts +2 -2
  90. package/src/engine-components/ui/Button.ts +1 -1
  91. package/src/engine-components/ui/Raycaster.ts +1 -1
  92. package/src/engine-components/web/ViewBox.ts +9 -2
  93. package/src/engine-components/webxr/WebXRPlaneTracking.ts +3 -3
  94. package/src/engine-components/webxr/controllers/XRControllerFollow.ts +1 -1
  95. package/src/engine-components/webxr/controllers/XRControllerMovement.ts +4 -4
@@ -2,6 +2,9 @@ import type { Context } from '../engine/engine_context.js';
2
2
  import { serializable } from '../engine/engine_serialization.js';
3
3
  import { DeviceUtilities } from '../engine/engine_utils.js';
4
4
  import { Behaviour } from './Component.js';
5
+ // Type-only imports for TSDoc @see links
6
+ import type { ScreenCapture } from './ScreenCapture.js';
7
+ import type { Voip } from './Voip.js';
5
8
 
6
9
  /**
7
10
  * [NeedleMenu](https://engine.needle.tools/docs/api/NeedleMenu) provides configuration for the built-in UI menu.
@@ -64,7 +64,7 @@ export class NestedGltf extends Behaviour {
64
64
  * EXPERIMENTAL for cloud asset loading
65
65
  */
66
66
  @serializable()
67
- loadAssetInParent = true;
67
+ loadAssetInParent: boolean = true;
68
68
 
69
69
 
70
70
  private _isLoadingOrDoneLoading: boolean = false;
@@ -1,13 +1,14 @@
1
1
  import { Color, CubeReflectionMapping, CubeTexture, EquirectangularReflectionMapping, LinearSRGBColorSpace, Material, MeshBasicMaterial, MeshStandardMaterial, Object3D, SRGBColorSpace, Texture, Vector3 } from "three";
2
2
 
3
3
  import { isDevEnvironment, showBalloonWarning } from "../engine/debug/index.js";
4
+ import { MaterialPropertyBlock } from "../engine/engine_materialpropertyblock.js";
4
5
  import { serializable } from "../engine/engine_serialization.js";
5
6
  import { Context } from "../engine/engine_setup.js";
6
7
  import type { IRenderer } from "../engine/engine_types.js";
7
8
  import { getParam } from "../engine/engine_utils.js";
8
9
  import { BoxHelperComponent } from "./BoxHelperComponent.js";
9
10
  import { Behaviour } from "./Component.js";
10
- import { MaterialPropertyBlock } from "../engine/engine_materialpropertyblock.js";
11
+ import { EventList } from "./EventList.js";
11
12
 
12
13
  export const debug = getParam("debugreflectionprobe");
13
14
  const disable = getParam("noreflectionprobe");
@@ -37,7 +38,6 @@ const $reflectionProbeKey = Symbol("reflectionProbeKey");
37
38
  * @see {@link Renderer} for material and rendering control
38
39
  * @see {@link Light} for scene lighting
39
40
  */
40
-
41
41
  export class ReflectionProbe extends Behaviour {
42
42
 
43
43
  private static _probes: Map<Context, ReflectionProbe[]> = new Map();
@@ -46,6 +46,24 @@ export class ReflectionProbe extends Behaviour {
46
46
  return !!(material as any)[$reflectionProbeKey];
47
47
  }
48
48
 
49
+
50
+ /**
51
+ * Event invoked when a reflection probe is enabled. Used internally by Renderer components to update probes when they become active. Not recommended to call this directly in most cases.
52
+ */
53
+ static readonly onEnabled: EventList<ReflectionProbe> = new EventList();
54
+ static readonly onDisabled: EventList<ReflectionProbe> = new EventList();
55
+
56
+ /**
57
+ * Gets the active reflection probe for the given object and context. If `isAnchor` is true, it will only return a probe if the object is the anchor of that probe. Otherwise, it checks if the object is within the probe's influence area.
58
+ *
59
+ * Note: This method is used internally by the Renderer component to determine which reflection probe to apply. It is not recommended to call this method directly in most cases. Instead, assign probes to renderers using the "anchor" property or rely on automatic assignment when supported.
60
+ * Note: Volume-based automatic assignment is not fully supported yet, so explicit assignment is recommended for now.
61
+ *
62
+ * @param object The object to find a reflection probe for
63
+ * @param context The context to search within
64
+ * @param isAnchor If true, only return a probe if the object is the anchor of that probe
65
+ * @param anchor Optional anchor object to match against probes
66
+ */
49
67
  public static get(object: Object3D | null | undefined, context: Context, isAnchor: boolean, anchor?: Object3D): ReflectionProbe | null {
50
68
  if (!object || object.isObject3D !== true) return null;
51
69
  if (disable) return null;
@@ -73,6 +91,7 @@ export class ReflectionProbe extends Behaviour {
73
91
 
74
92
  private _texture!: Texture;
75
93
 
94
+ @serializable(Texture)
76
95
  set texture(tex: Texture) {
77
96
  if (this._texture === tex) return;
78
97
  this._texture = tex;
@@ -93,11 +112,26 @@ export class ReflectionProbe extends Behaviour {
93
112
  return this._texture;
94
113
  }
95
114
 
115
+ @serializable()
116
+ intensity: number = 1;
117
+
118
+ /**
119
+ * Defines the center and size of the reflection probe's influence area.
120
+ */
96
121
  @serializable(Vector3)
97
122
  center?: Vector3;
123
+
124
+ /**
125
+ * Defines the size of the reflection probe's influence area. Objects within this box will be affected by the probe's reflections.
126
+ */
98
127
  @serializable(Vector3)
99
128
  size?: Vector3;
100
129
 
130
+ /**
131
+ * Workaround for lightmap. Compensates for the fact that lightmaps are pre-multiplied by intensity, while reflection probes are not. This means that if you use both lightmaps and reflection probes, you may need to adjust this value to get the correct balance between them. The default value of `Math.PI` is a good starting point for most cases, but you may need to tweak it based on your specific lighting setup and artistic needs.
132
+ */
133
+ __lightmapIntensityScale: boolean = true;
134
+
101
135
  private _boxHelper?: BoxHelperComponent;
102
136
 
103
137
  private isInBox(obj: Object3D) {
@@ -124,6 +158,15 @@ export class ReflectionProbe extends Behaviour {
124
158
  this._texture.needsUpdate = true;
125
159
  }
126
160
  }
161
+
162
+ onEnable(): void {
163
+ ReflectionProbe.onEnabled?.invoke(this);
164
+ }
165
+
166
+ onDisable(): void {
167
+ ReflectionProbe.onDisabled?.invoke(this);
168
+ }
169
+
127
170
  start(): void {
128
171
  if (!this._texture) {
129
172
  console.warn(`[ReflectionProbe] Missing texture. Please assign a custom cubemap texture. To use reflection probes assign them to your renderer's "anchor" property.`);
@@ -140,40 +183,28 @@ export class ReflectionProbe extends Behaviour {
140
183
  }
141
184
  }
142
185
 
143
- onSet(_rend: IRenderer) {
186
+ apply(object: Object3D) {
144
187
  if (disable) return;
145
188
  if (!this.enabled) return;
146
- if (_rend.sharedMaterials?.length <= 0) return;
147
189
  if (!this.texture) return;
148
-
149
- const object = _rend.gameObject as unknown as Object3D;
150
-
151
- for (let i = 0; i < _rend.sharedMaterials.length; i++) {
152
- const material = _rend.sharedMaterials[i];
153
- if (!material) {
154
- continue;
155
- }
156
- if (material["envMap"] === undefined) {
157
- continue;
158
- }
159
-
160
- if (debug) console.log("Setting reflection probe on material", material.name, "for renderer", _rend.name);
161
-
162
- const propertyBlock = MaterialPropertyBlock.get(object);
163
- propertyBlock.setOverride("envMap", this.texture);
164
- // propertyBlock.setOverride("color", new Color(0xff0000));
165
-
166
- (material as any)[$reflectionProbeKey] = true;
190
+ const propertyBlock = MaterialPropertyBlock.get(object);
191
+ propertyBlock.setOverride("envMap", this.texture);
192
+ propertyBlock.setOverride("envMapRotation", this.gameObject.rotation);
193
+
194
+ let intensity = this.intensity;
195
+ if (this.__lightmapIntensityScale && propertyBlock.getOverride("lightMap")) {
196
+ // @TODO: Remove this here and in Renderer https://linear.app/needle/issue/NE-6922
197
+ intensity /= Math.PI;
167
198
  }
199
+ propertyBlock.setOverride("envMapIntensity", intensity);
168
200
  }
169
201
 
170
- onUnset(_rend: IRenderer) {
171
- // const object = _rend.gameObject as unknown as Object3D;
172
-
173
- for (let i = 0; i < _rend.sharedMaterials.length; i++) {
174
- const material = _rend.sharedMaterials[i];
175
- if (material) {
176
- delete (material as any)[$reflectionProbeKey];
202
+ unapply(obj: Object3D) {
203
+ const block = MaterialPropertyBlock.get(obj);
204
+ if (block) {
205
+ const current = block.getOverride("envMap")?.value;
206
+ if (current === this.texture) {
207
+ block.removeOveride("envMap");
177
208
  }
178
209
  }
179
210
  }
@@ -638,12 +638,16 @@ export class Renderer extends Behaviour implements IRenderer {
638
638
 
639
639
  this.updateReflectionProbe();
640
640
 
641
- // this.testIfLODLevelsAreAvailable();
641
+ ReflectionProbe.onEnabled.addEventListener(this.onReflectionProbeEnabled);
642
+ ReflectionProbe.onDisabled.addEventListener(this.onReflectionProbeDisabled);
642
643
  }
643
644
 
644
645
  onDisable() {
645
646
  this.setVisibility(false);
646
647
 
648
+ ReflectionProbe.onEnabled.removeEventListener(this.onReflectionProbeEnabled);
649
+ ReflectionProbe.onDisabled.removeEventListener(this.onReflectionProbeDisabled);
650
+
647
651
  if (this._handles && this._handles.length > 0) {
648
652
  this.setInstancingEnabled(false);
649
653
  }
@@ -662,14 +666,24 @@ export class Renderer extends Behaviour implements IRenderer {
662
666
  }
663
667
  }
664
668
 
669
+ private readonly onReflectionProbeEnabled = () => {
670
+ this.updateReflectionProbe();
671
+ }
672
+ private onReflectionProbeDisabled = (probe: ReflectionProbe) => {
673
+ if (this._reflectionProbe === probe) {
674
+ this._reflectionProbe.unapply(this.gameObject);
675
+ this._reflectionProbe = null;
676
+ }
677
+ }
678
+
665
679
 
666
680
  onBeforeRender() {
667
681
  if (!this.gameObject) {
668
682
  return;
669
683
  }
670
684
 
671
- if (this._probeAnchorLastFrame !== this.probeAnchor) {
672
- this._reflectionProbe?.onUnset(this);
685
+ if (this._probeAnchorLastFrame !== this.probeAnchor || this._reflectionProbe?.activeAndEnabled === false) {
686
+ this._reflectionProbe?.unapply(this.gameObject);
673
687
  this.updateReflectionProbe();
674
688
  }
675
689
 
@@ -726,8 +740,21 @@ export class Renderer extends Behaviour implements IRenderer {
726
740
  }
727
741
 
728
742
  if (this.reflectionProbeUsage !== ReflectionProbeUsage.Off && this._reflectionProbe) {
729
- this._reflectionProbe.onSet(this);
743
+ // @TODO: when reflection probes are applied via bounding box we currently NEVER update it again
744
+ // if(this.probeAnchor === this._reflectionProbe.gameObject)
745
+ this._reflectionProbe.apply(this.gameObject);
746
+ // else {
747
+ // const probe = this._reflectionProbe;
748
+ // this._updateReflectionProbe();
749
+ // console.log(this.name, "Reflection probe updated on before render. Probe anchor changed:", this.probeAnchor !== this._probeAnchorLastFrame, "Probe active:", probe.activeAndEnabled, "New probe anchor:", this._reflectionProbe?.gameObject.name);
750
+ // if(!this._reflectionProbe) probe?.unapply(this.gameObject);
751
+ // else this._reflectionProbe?.apply(this.gameObject);
752
+ // }
753
+ }
754
+ else if (this.reflectionProbeUsage === ReflectionProbeUsage.Off && this._reflectionProbe) {
755
+ this._reflectionProbe.unapply(this.gameObject);
730
756
  }
757
+
731
758
  // since three 163 we need to set the envMap to the scene envMap if it is not set
732
759
  // otherwise the envmapIntensity has no effect: https://github.com/mrdoob/three.js/pull/27903
733
760
  // internal issue: https://linear.app/needle/issue/NE-6363
@@ -766,8 +793,8 @@ export class Renderer extends Behaviour implements IRenderer {
766
793
  }
767
794
  }
768
795
 
769
- if (this.reflectionProbeUsage !== ReflectionProbeUsage.Off && this._reflectionProbe) {
770
- this._reflectionProbe.onUnset(this);
796
+ if (this._reflectionProbe?.activeAndEnabled === false) {
797
+ this._reflectionProbe.unapply(this.gameObject);
771
798
  }
772
799
 
773
800
  if (this.static && this.gameObject.matrixAutoUpdate) {
@@ -798,6 +825,7 @@ export class Renderer extends Behaviour implements IRenderer {
798
825
  private updateReflectionProbe() {
799
826
  // handle reflection probe
800
827
  this._reflectionProbe = null;
828
+
801
829
  if (this.reflectionProbeUsage !== ReflectionProbeUsage.Off) {
802
830
  // update the reflection probe right before rendering
803
831
  // if we do it immediately the reflection probe might not be enabled yet
@@ -1,9 +1,9 @@
1
1
  import { NEEDLE_progressive } from "@needle-tools/gltf-progressive";
2
2
  import { Group, Mesh, Object3D, ShaderMaterial, Texture, Vector2, Vector4 } from "three";
3
3
 
4
+ import { MaterialPropertyBlock } from "../engine/engine_materialpropertyblock.js";
4
5
  import type { Context } from "../engine/engine_setup.js";
5
6
  import { getParam } from "../engine/engine_utils.js";
6
- import { MaterialPropertyBlock } from "../engine/engine_materialpropertyblock.js";
7
7
  import { type Renderer } from "./Renderer.js";
8
8
 
9
9
  const debug = getParam("debuglightmaps");
@@ -146,8 +146,7 @@ export class RendererLightmap {
146
146
  }
147
147
  const block = MaterialPropertyBlock.get(this.gameObject);
148
148
  if (block) {
149
- block.clearOverride("lightMap");
150
- block.clearOverride("lightMapIntensity");
149
+ block.removeOveride("lightMap");
151
150
  }
152
151
  }
153
152
 
@@ -1,11 +1,11 @@
1
1
  import { Material, Object3D, Object3DEventMap, Vector3 } from "three";
2
2
 
3
3
  import { Gizmos } from "../engine/engine_gizmos.js";
4
+ import { MaterialPropertyBlock } from "../engine/engine_materialpropertyblock.js";
4
5
  import { Mathf } from "../engine/engine_math.js";
5
6
  import { serializable } from "../engine/engine_serialization_decorator.js";
6
7
  import { getTempVector } from "../engine/engine_three_utils.js";
7
8
  import { getParam } from "../engine/engine_utils.js";
8
- import { USDObject, USDZExporterContext } from "./api.js";
9
9
  import type { Camera } from "./Camera.js";
10
10
  import { Behaviour } from "./Component.js";
11
11
  import { IUSDExporterExtension } from "./export/usdz/Extension.js";
@@ -15,20 +15,20 @@ import { Renderer } from "./Renderer.js";
15
15
 
16
16
  const debugSeeThrough = getParam("debugseethrough");
17
17
 
18
- type MaterialState = {
19
- opacity: number,
20
- transparent: boolean,
21
- alphaHash: boolean
22
- }
23
-
24
- type MaterialWithState = Material & {
25
- /** Original values */
26
- userData: {
27
- seeThrough: {
28
- initial: MaterialState,
29
- }
30
- }
31
- };
18
+ // type MaterialState = {
19
+ // opacity: number,
20
+ // transparent: boolean,
21
+ // alphaHash: boolean
22
+ // }
23
+
24
+ // type MaterialWithState = Material & {
25
+ // /** Original values */
26
+ // userData: {
27
+ // seeThrough: {
28
+ // initial: MaterialState,
29
+ // }
30
+ // }
31
+ // };
32
32
 
33
33
  let i = 0;
34
34
 
@@ -176,26 +176,26 @@ export class SeeThrough extends Behaviour {
176
176
  onEnable() {
177
177
  this._needsUpdate = true;
178
178
  this._renderer = null;
179
- SeeThroughUsdzExporterPlugin.components.push(this);
179
+ // SeeThroughUsdzExporterPlugin.components.push(this);
180
180
  }
181
181
 
182
182
  /** @internal */
183
183
  onDisable() {
184
- this._renderer?.forEach(r => {
185
- const original = this.rendererMaterialsOriginal.get(r);
186
- for (let i = 0; i < r.sharedMaterials.length; i++) {
187
- const mat = r.sharedMaterials[i];
188
- if (!mat) continue;
189
- if (original && original[i]) {
190
- r.sharedMaterials[i] = original[i];
191
- }
192
- }
193
- this.rendererMaterials.delete(r);
194
- this.rendererMaterialsOriginal.delete(r);
195
- });
196
-
197
- const index = SeeThroughUsdzExporterPlugin.components.indexOf(this);
198
- if (index !== -1) SeeThroughUsdzExporterPlugin.components.splice(index, 1);
184
+ // this._renderer?.forEach(r => {
185
+ // const original = this.rendererMaterialsOriginal.get(r);
186
+ // for (let i = 0; i < r.sharedMaterials.length; i++) {
187
+ // const mat = r.sharedMaterials[i];
188
+ // if (!mat) continue;
189
+ // if (original && original[i]) {
190
+ // r.sharedMaterials[i] = original[i];
191
+ // }
192
+ // }
193
+ // this.rendererMaterials.delete(r);
194
+ // this.rendererMaterialsOriginal.delete(r);
195
+ // });
196
+
197
+ // const index = SeeThroughUsdzExporterPlugin.components.indexOf(this);
198
+ // if (index !== -1) SeeThroughUsdzExporterPlugin.components.splice(index, 1);
199
199
  }
200
200
 
201
201
  /**
@@ -239,8 +239,8 @@ export class SeeThrough extends Behaviour {
239
239
  }
240
240
  }
241
241
 
242
- private readonly rendererMaterials = new WeakMap<Renderer, Array<MaterialWithState>>();
243
- private readonly rendererMaterialsOriginal = new WeakMap<Renderer, Array<Material>>();
242
+ // private readonly rendererMaterials = new WeakMap<Renderer, Array<MaterialWithState>>();
243
+ // private readonly rendererMaterialsOriginal = new WeakMap<Renderer, Array<Material>>();
244
244
 
245
245
  private updateDirection() {
246
246
  this.referencePoint ??= this.context.scene;
@@ -272,66 +272,81 @@ export class SeeThrough extends Behaviour {
272
272
  renderer.gameObject.raycastAllowed = true;
273
273
  }
274
274
 
275
- if (!this.rendererMaterials.has(renderer)) {
276
- const originalMaterials = new Array<Material>();
277
- const clonedMaterials = new Array<MaterialWithState>();
278
-
279
- // We clone the materials once and store them, so we can modify the opacity without affecting other objects using the same material. This could potentially be optimized further to re-use materials between renderers if multiple renderers use the same material.
280
- for (let i = 0; i < renderer.sharedMaterials.length; i++) {
281
- const mat = renderer.sharedMaterials[i];
282
- if (!mat) continue;
283
- originalMaterials.push(mat);
284
- const matClone = mat.clone() as MaterialWithState;
285
- // @ts-ignore
286
- matClone.userData = mat.userData || {};
287
- matClone.userData.seeThrough = {
288
- initial: {
289
- opacity: matClone.opacity,
290
- transparent: matClone.transparent,
291
- alphaHash: matClone.alphaHash
292
- }
293
- }
294
- clonedMaterials.push(matClone);
295
- renderer.sharedMaterials[i] = matClone;
296
- }
297
-
298
- this.rendererMaterials.set(renderer, clonedMaterials);
299
- this.rendererMaterialsOriginal.set(renderer, originalMaterials);
300
- }
301
-
302
- const materials = renderer.hasLightmap ? renderer.sharedMaterials : this.rendererMaterials.get(renderer);
275
+ // if (!this.rendererMaterials.has(renderer)) {
276
+ // const originalMaterials = new Array<Material>();
277
+ // const clonedMaterials = new Array<MaterialWithState>();
278
+
279
+ // // We clone the materials once and store them, so we can modify the opacity without affecting other objects using the same material. This could potentially be optimized further to re-use materials between renderers if multiple renderers use the same material.
280
+ // for (let i = 0; i < renderer.sharedMaterials.length; i++) {
281
+ // const mat = renderer.sharedMaterials[i];
282
+ // if (!mat) continue;
283
+ // originalMaterials.push(mat);
284
+ // const matClone = mat.clone() as MaterialWithState;
285
+ // // @ts-ignore
286
+ // matClone.userData = mat.userData || {};
287
+ // matClone.userData.seeThrough = {
288
+ // initial: {
289
+ // opacity: matClone.opacity,
290
+ // transparent: matClone.transparent,
291
+ // alphaHash: matClone.alphaHash
292
+ // }
293
+ // }
294
+ // clonedMaterials.push(matClone);
295
+ // // renderer.sharedMaterials[i] = matClone;
296
+ // }
297
+
298
+ // this.rendererMaterials.set(renderer, clonedMaterials);
299
+ // this.rendererMaterialsOriginal.set(renderer, originalMaterials);
300
+ // }
301
+
302
+ const materials = renderer.sharedMaterials;// : this.rendererMaterials.get(renderer);
303
303
  if (!materials) return;
304
304
 
305
- for (const mat of materials) {
306
- if (!mat) continue;
305
+ const block = MaterialPropertyBlock.get(renderer.gameObject);
307
306
 
308
- let newAlpha = Mathf.lerp(mat.opacity, targetAlpha, duration <= 0 ? 1 : this.context.time.deltaTime / duration);;
309
- if (newAlpha >= 0.99) newAlpha = 1;
310
- else if (newAlpha <= 0.01) newAlpha = 0;
307
+ const currentOpacity = (block.getOverride("opacity")?.value ?? materials[0].opacity ?? 1);
311
308
 
309
+ let newAlpha = Mathf.lerp(currentOpacity, targetAlpha, duration <= 0 ? 1 : this.context.time.deltaTime / duration);;
310
+ if (newAlpha >= 0.99) newAlpha = 1;
311
+ else if (newAlpha <= 0.01) newAlpha = 0;
312
312
 
313
- const wasTransparent = mat.transparent;
314
- const wasAlphaHash = mat.alphaHash;
315
- const previousOpacity = mat.opacity;
313
+ // const currentTransparent = (block.getOverride("transparent")?.value ?? materials[0].transparent ?? false) as boolean;
316
314
 
317
- mat.alphaHash = this.useAlphaHash;
315
+ block.setOverride("alphaHash", this.useAlphaHash);
316
+ block.setOverride("opacity", newAlpha);
317
+ block.setOverride("transparent", newAlpha >= 0.99999 ? false : !this.useAlphaHash);
318
318
 
319
- if (mat.userData && "seeThrough" in mat.userData) {
320
- const initial = mat.userData.seeThrough.initial as MaterialState;
321
- mat.opacity = initial.opacity * newAlpha;
322
- mat.transparent = mat.opacity >= 1 ? initial.transparent : !this.useAlphaHash;
323
- }
324
- else {
325
- mat.transparent = mat.opacity >= 1 ? false : !this.useAlphaHash;
326
- }
327
319
 
328
- if (wasTransparent !== mat.transparent
329
- || wasAlphaHash !== mat.alphaHash
330
- || mat.opacity !== previousOpacity // MeshPhysicsMaterial needs that and maybe other materials too...
331
- ) {
332
- mat.needsUpdate = true;
333
- }
334
- }
320
+ // for (const mat of materials) {
321
+ // if (!mat) continue;
322
+
323
+ // let newAlpha = Mathf.lerp(mat.opacity, targetAlpha, duration <= 0 ? 1 : this.context.time.deltaTime / duration);;
324
+ // if (newAlpha >= 0.99) newAlpha = 1;
325
+ // else if (newAlpha <= 0.01) newAlpha = 0;
326
+
327
+
328
+ // const wasTransparent = mat.transparent;
329
+ // const wasAlphaHash = mat.alphaHash;
330
+ // const previousOpacity = mat.opacity;
331
+
332
+ // mat.alphaHash = this.useAlphaHash;
333
+
334
+ // if (mat.userData && "seeThrough" in mat.userData) {
335
+ // const initial = mat.userData.seeThrough.initial as MaterialState;
336
+ // mat.opacity = initial.opacity * newAlpha;
337
+ // mat.transparent = mat.opacity >= 1 ? initial.transparent : !this.useAlphaHash;
338
+ // }
339
+ // else {
340
+ // mat.transparent = mat.opacity >= 1 ? false : !this.useAlphaHash;
341
+ // }
342
+
343
+ // if (wasTransparent !== mat.transparent
344
+ // || wasAlphaHash !== mat.alphaHash
345
+ // || mat.opacity !== previousOpacity // MeshPhysicsMaterial needs that and maybe other materials too...
346
+ // ) {
347
+ // mat.needsUpdate = true;
348
+ // }
349
+ // }
335
350
  });
336
351
  }
337
352
 
@@ -339,33 +354,33 @@ export class SeeThrough extends Behaviour {
339
354
 
340
355
 
341
356
  ;
342
- class SeeThroughUsdzExporterPlugin implements IUSDExporterExtension {
357
+ // class SeeThroughUsdzExporterPlugin implements IUSDExporterExtension {
343
358
 
344
- static readonly components: SeeThrough[] = [];
359
+ // static readonly components: SeeThrough[] = [];
345
360
 
346
- get extensionName() {
347
- return "SeeThrough";
348
- }
361
+ // get extensionName() {
362
+ // return "SeeThrough";
363
+ // }
349
364
 
350
- // onExportObject(object: Object3D<Object3DEventMap>, model: USDObject, context: USDZExporterContext) {
351
- // const component = SeeThroughUsdzExporterPlugin.components.find(c => c.gameObject === object);
352
- // if(!component) return;
353
- // console.log("OH MY GOD SEE THROUGH USDZ EXPORTER", component, model);
365
+ // // onExportObject(object: Object3D<Object3DEventMap>, model: USDObject, context: USDZExporterContext) {
366
+ // // const component = SeeThroughUsdzExporterPlugin.components.find(c => c.gameObject === object);
367
+ // // if(!component) return;
368
+ // // console.log("OH MY GOD SEE THROUGH USDZ EXPORTER", component, model);
354
369
 
355
- // model.materialName = "AlphaHashMaterialInstance"; // we could make this unique per object if needed
370
+ // // model.materialName = "AlphaHashMaterialInstance"; // we could make this unique per object if needed
356
371
 
357
- // model.addEventListener("serialize", (writer, context) => {
358
- // writer.appendLine(`# SeeThrough component on ${object.name}`);
359
- // });
360
- // }
372
+ // // model.addEventListener("serialize", (writer, context) => {
373
+ // // writer.appendLine(`# SeeThrough component on ${object.name}`);
374
+ // // });
375
+ // // }
361
376
 
362
- }
377
+ // }
363
378
 
364
- const seeThroughUsdzExporterPlugin = new SeeThroughUsdzExporterPlugin();
379
+ // const seeThroughUsdzExporterPlugin = new SeeThroughUsdzExporterPlugin();
365
380
 
366
- USDZExporter.beforeExport.addEventListener(args => {
367
- if (SeeThroughUsdzExporterPlugin.components.length === 0) return;
368
- if (args.exporter.extensions.includes(seeThroughUsdzExporterPlugin) === false) {
369
- args.exporter.extensions.push(seeThroughUsdzExporterPlugin);
370
- }
371
- });
381
+ // USDZExporter.beforeExport.addEventListener(args => {
382
+ // if (SeeThroughUsdzExporterPlugin.components.length === 0) return;
383
+ // if (args.exporter.extensions.includes(seeThroughUsdzExporterPlugin) === false) {
384
+ // args.exporter.extensions.push(seeThroughUsdzExporterPlugin);
385
+ // }
386
+ // });
@@ -73,7 +73,7 @@ export class SmoothFollow extends Behaviour {
73
73
  * @default 0.1
74
74
  */
75
75
  @serializable()
76
- followFactor = .1;
76
+ followFactor: number = .1;
77
77
 
78
78
  /**
79
79
  * Speed factor for rotation following.
@@ -83,7 +83,7 @@ export class SmoothFollow extends Behaviour {
83
83
  * @default 0.1
84
84
  */
85
85
  @serializable()
86
- rotateFactor = .1;
86
+ rotateFactor: number = .1;
87
87
 
88
88
  /**
89
89
  * Which position axes to follow. Use bitwise OR to combine:
@@ -204,7 +204,7 @@ export class Button extends Behaviour implements IPointerEventHandler {
204
204
  // image? : Image;
205
205
 
206
206
  @serializable()
207
- set interactable(value) {
207
+ set interactable(value: boolean) {
208
208
  this._interactable = value;
209
209
  if (this._image) {
210
210
  this._image.setInteractable(value);
@@ -63,7 +63,7 @@ export class ObjectRaycaster extends Raycaster {
63
63
  private raycastHits: Intersection[] = [];
64
64
 
65
65
  @serializable()
66
- ignoreSkinnedMeshes = false;
66
+ ignoreSkinnedMeshes: boolean = false;
67
67
 
68
68
  start(): void {
69
69
  this.targets = [this.gameObject];
@@ -1,13 +1,20 @@
1
1
  import { Camera, Matrix4, PerspectiveCamera, Vector3 } from "three";
2
2
 
3
3
  import { isDevEnvironment } from "../../engine/debug/debug.js";
4
+ // Type-only imports for TSDoc @see links
5
+ import type { Context } from "../../engine/engine_context.js";
4
6
  import { Gizmos } from "../../engine/engine_gizmos.js";
5
7
  import { serializable } from "../../engine/engine_serialization_decorator.js";
6
8
  import { getTempVector } from "../../engine/engine_three_utils.js";
7
9
  import { registerType } from "../../engine/engine_typestore.js";
8
10
  import { getParam } from "../../engine/engine_utils.js";
9
11
  import { RGBAColor } from "../../engine/js-extensions/RGBAColor.js";
12
+ import type { Camera as CameraComponent } from "../Camera.js";
10
13
  import { Behaviour } from "../Component.js";
14
+ import type { DragControls } from "../DragControls.js";
15
+ import type { LookAtConstraint } from "../LookAtConstraint.js";
16
+ import type { OrbitControls } from "../OrbitControls.js";
17
+ import type { SceneSwitcher } from "../SceneSwitcher.js";
11
18
 
12
19
 
13
20
  const debugParam = getParam("debugviewbox");
@@ -83,7 +90,7 @@ export type ViewBoxMode = "continuous" | "once";
83
90
  * scene.add(viewBox);
84
91
  * ```
85
92
  *
86
- * @see {@link Camera} - The camera component that ViewBox controls
93
+ * @see {@link CameraComponent} - The camera component that ViewBox controls
87
94
  * @see {@link OrbitControls} - Camera controls that work alongside ViewBox
88
95
  * @see {@link DragControls} - Alternative camera controls compatible with ViewBox
89
96
  * @see {@link LookAtConstraint} - Another way to control camera targeting
@@ -121,7 +128,7 @@ export class ViewBox extends Behaviour {
121
128
  * as they would appear with that field of view. Setting it to a wider FOV (e.g., 90) makes objects appear
122
129
  * smaller, while a narrower FOV (e.g., 30) makes them appear larger.
123
130
  *
124
- * @see {@link Camera} for the camera component and its FOV property
131
+ * @see {@link CameraComponent} for the camera component and its FOV property
125
132
  * @default -1 (automatically uses the camera's FOV on the first frame)
126
133
  */
127
134
  @serializable()