@needle-tools/engine 4.10.0-next.55c0bf9 → 4.10.0-next.f5ce0ae

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 (129) hide show
  1. package/components.needle.json +1 -1
  2. package/dist/{needle-engine.bundle-CUo74dPe.js → needle-engine.bundle-DSzlnhCs.js} +7419 -7146
  3. package/dist/{needle-engine.bundle-Cf5H9Zy9.umd.cjs → needle-engine.bundle-VqrrECGF.umd.cjs} +154 -141
  4. package/dist/needle-engine.bundle-pI8o_eru.min.js +1652 -0
  5. package/dist/needle-engine.js +259 -257
  6. package/dist/needle-engine.min.js +1 -1
  7. package/dist/needle-engine.umd.cjs +1 -1
  8. package/dist/vendor-CPuBPspY.umd.cjs +1121 -0
  9. package/dist/vendor-DPCU8cUF.min.js +1121 -0
  10. package/dist/vendor-MBoqSyFm.js +16240 -0
  11. package/lib/engine/codegen/register_types.js +2 -0
  12. package/lib/engine/codegen/register_types.js.map +1 -1
  13. package/lib/engine/engine_camera.d.ts +7 -1
  14. package/lib/engine/engine_camera.fit.d.ts +1 -1
  15. package/lib/engine/engine_camera.fit.js +3 -30
  16. package/lib/engine/engine_camera.fit.js.map +1 -1
  17. package/lib/engine/engine_camera.js +46 -6
  18. package/lib/engine/engine_camera.js.map +1 -1
  19. package/lib/engine/engine_context.d.ts +6 -0
  20. package/lib/engine/engine_context.js +48 -9
  21. package/lib/engine/engine_context.js.map +1 -1
  22. package/lib/engine/engine_gizmos.d.ts +11 -10
  23. package/lib/engine/engine_gizmos.js +24 -10
  24. package/lib/engine/engine_gizmos.js.map +1 -1
  25. package/lib/engine/engine_license.js +1 -1
  26. package/lib/engine/engine_license.js.map +1 -1
  27. package/lib/engine/engine_lightdata.d.ts +3 -3
  28. package/lib/engine/engine_lightdata.js +10 -10
  29. package/lib/engine/engine_lightdata.js.map +1 -1
  30. package/lib/engine/engine_physics_rapier.js +4 -0
  31. package/lib/engine/engine_physics_rapier.js.map +1 -1
  32. package/lib/engine/engine_scenelighting.d.ts +1 -1
  33. package/lib/engine/engine_scenelighting.js +4 -5
  34. package/lib/engine/engine_scenelighting.js.map +1 -1
  35. package/lib/engine/engine_utils.d.ts +3 -1
  36. package/lib/engine/engine_utils.js +11 -0
  37. package/lib/engine/engine_utils.js.map +1 -1
  38. package/lib/engine/extensions/NEEDLE_lightmaps.js +1 -1
  39. package/lib/engine/extensions/NEEDLE_lightmaps.js.map +1 -1
  40. package/lib/engine/extensions/extension_utils.js +1 -1
  41. package/lib/engine/extensions/extension_utils.js.map +1 -1
  42. package/lib/engine/webcomponents/logo-element.d.ts +1 -1
  43. package/lib/engine/webcomponents/logo-element.js +29 -5
  44. package/lib/engine/webcomponents/logo-element.js.map +1 -1
  45. package/lib/engine/webcomponents/needle menu/needle-menu.js +4 -3
  46. package/lib/engine/webcomponents/needle menu/needle-menu.js.map +1 -1
  47. package/lib/engine/webcomponents/needle-engine.js +22 -0
  48. package/lib/engine/webcomponents/needle-engine.js.map +1 -1
  49. package/lib/engine/webcomponents/needle-engine.loading.d.ts +0 -1
  50. package/lib/engine/webcomponents/needle-engine.loading.js +3 -36
  51. package/lib/engine/webcomponents/needle-engine.loading.js.map +1 -1
  52. package/lib/engine/xr/NeedleXRController.d.ts +3 -3
  53. package/lib/engine/xr/NeedleXRController.js +28 -0
  54. package/lib/engine/xr/NeedleXRController.js.map +1 -1
  55. package/lib/engine-components/CameraUtils.js +2 -1
  56. package/lib/engine-components/CameraUtils.js.map +1 -1
  57. package/lib/engine-components/OrbitControls.d.ts +4 -1
  58. package/lib/engine-components/OrbitControls.js +30 -6
  59. package/lib/engine-components/OrbitControls.js.map +1 -1
  60. package/lib/engine-components/Renderer.js +6 -1
  61. package/lib/engine-components/Renderer.js.map +1 -1
  62. package/lib/engine-components/Skybox.js +22 -4
  63. package/lib/engine-components/Skybox.js.map +1 -1
  64. package/lib/engine-components/codegen/components.d.ts +1 -0
  65. package/lib/engine-components/codegen/components.js +1 -0
  66. package/lib/engine-components/codegen/components.js.map +1 -1
  67. package/lib/engine-components/debug/LogStats.d.ts +1 -0
  68. package/lib/engine-components/debug/LogStats.js +1 -0
  69. package/lib/engine-components/debug/LogStats.js.map +1 -1
  70. package/lib/engine-components/timeline/PlayableDirector.d.ts +7 -0
  71. package/lib/engine-components/timeline/PlayableDirector.js +8 -1
  72. package/lib/engine-components/timeline/PlayableDirector.js.map +1 -1
  73. package/lib/engine-components/timeline/TimelineModels.d.ts +9 -1
  74. package/lib/engine-components/timeline/TimelineTracks.d.ts +2 -1
  75. package/lib/engine-components/timeline/TimelineTracks.js +30 -25
  76. package/lib/engine-components/timeline/TimelineTracks.js.map +1 -1
  77. package/lib/engine-components/utils/LookAt.js +5 -1
  78. package/lib/engine-components/utils/LookAt.js.map +1 -1
  79. package/lib/engine-components/web/Clickthrough.js +10 -2
  80. package/lib/engine-components/web/Clickthrough.js.map +1 -1
  81. package/lib/engine-components/web/ScrollFollow.d.ts +23 -0
  82. package/lib/engine-components/web/ScrollFollow.js +166 -41
  83. package/lib/engine-components/web/ScrollFollow.js.map +1 -1
  84. package/lib/engine-components/web/ViewBox.d.ts +27 -0
  85. package/lib/engine-components/web/ViewBox.js +242 -0
  86. package/lib/engine-components/web/ViewBox.js.map +1 -0
  87. package/lib/engine-components/web/index.d.ts +1 -0
  88. package/lib/engine-components/web/index.js +1 -0
  89. package/lib/engine-components/web/index.js.map +1 -1
  90. package/lib/engine-components-experimental/Presentation.d.ts +1 -0
  91. package/lib/engine-components-experimental/Presentation.js +1 -0
  92. package/lib/engine-components-experimental/Presentation.js.map +1 -1
  93. package/package.json +2 -1
  94. package/src/engine/codegen/register_types.ts +2 -0
  95. package/src/engine/engine_camera.fit.ts +2 -32
  96. package/src/engine/engine_camera.ts +61 -9
  97. package/src/engine/engine_context.ts +50 -10
  98. package/src/engine/engine_gizmos.ts +37 -23
  99. package/src/engine/engine_license.ts +1 -1
  100. package/src/engine/engine_lightdata.ts +11 -11
  101. package/src/engine/engine_physics_rapier.ts +3 -0
  102. package/src/engine/engine_scenelighting.ts +5 -6
  103. package/src/engine/engine_utils.ts +12 -0
  104. package/src/engine/extensions/NEEDLE_lightmaps.ts +1 -1
  105. package/src/engine/extensions/extension_utils.ts +1 -1
  106. package/src/engine/webcomponents/logo-element.ts +29 -4
  107. package/src/engine/webcomponents/needle menu/needle-menu.ts +4 -3
  108. package/src/engine/webcomponents/needle-engine.loading.ts +32 -32
  109. package/src/engine/webcomponents/needle-engine.ts +33 -6
  110. package/src/engine/xr/NeedleXRController.ts +36 -4
  111. package/src/engine-components/CameraUtils.ts +1 -1
  112. package/src/engine-components/OrbitControls.ts +40 -1
  113. package/src/engine-components/Renderer.ts +6 -1
  114. package/src/engine-components/Skybox.ts +26 -7
  115. package/src/engine-components/codegen/components.ts +1 -0
  116. package/src/engine-components/debug/LogStats.ts +1 -0
  117. package/src/engine-components/timeline/PlayableDirector.ts +10 -1
  118. package/src/engine-components/timeline/TimelineModels.ts +9 -1
  119. package/src/engine-components/timeline/TimelineTracks.ts +30 -25
  120. package/src/engine-components/utils/LookAt.ts +5 -1
  121. package/src/engine-components/web/Clickthrough.ts +11 -2
  122. package/src/engine-components/web/ScrollFollow.ts +199 -48
  123. package/src/engine-components/web/ViewBox.ts +262 -0
  124. package/src/engine-components/web/index.ts +2 -1
  125. package/src/engine-components-experimental/Presentation.ts +1 -0
  126. package/dist/needle-engine.bundle-DlAVTipB.min.js +0 -1639
  127. package/dist/vendor-D0Yvltn9.umd.cjs +0 -1121
  128. package/dist/vendor-DU8tJyl_.js +0 -14366
  129. package/dist/vendor-JyrX4DVM.min.js +0 -1121
@@ -1,4 +1,4 @@
1
- import { AxesHelper, Box3, BoxGeometry, BufferAttribute, BufferGeometry, Color, type ColorRepresentation, CylinderGeometry, EdgesGeometry, Line, LineBasicMaterial, LineSegments, Matrix4, Mesh, MeshBasicMaterial, Object3D, Quaternion, SphereGeometry, Vector3 } from 'three';
1
+ import { AxesHelper, Box3, BoxGeometry, BufferAttribute, BufferGeometry, Color, type ColorRepresentation, CylinderGeometry, EdgesGeometry, Line, LineBasicMaterial, LineSegments, Material,Matrix4, Mesh, MeshBasicMaterial, Object3D, Quaternion, SphereGeometry, Vector3 } from 'three';
2
2
  import ThreeMeshUI, { Inline, Text } from "three-mesh-ui"
3
3
  import { type Options } from 'three-mesh-ui/build/types/core/elements/MeshUIBaseElement.js';
4
4
 
@@ -8,6 +8,7 @@ import { getTempVector, getWorldPosition, lookAtObject, setWorldPositionXYZ } fr
8
8
  import type { Vec3, Vec4 } from './engine_types.js';
9
9
  import { getParam } from './engine_utils.js';
10
10
  import { NeedleXRSession } from './engine_xr.js';
11
+ import { RGBAColor } from './js-extensions/RGBAColor.js';
11
12
 
12
13
  const _tmp = new Vector3();
13
14
  const _tmp2 = new Vector3();
@@ -21,7 +22,7 @@ const circleSegments: number = 32;
21
22
  export type LabelHandle = {
22
23
  setText(str: string);
23
24
  }
24
- declare type ColorWithAlpha = Color & { a: number };
25
+ type GizmoColor = ColorRepresentation | (Color & { a: number }) | RGBAColor;
25
26
 
26
27
  /** Gizmos are temporary objects that are drawn in the scene for debugging or visualization purposes
27
28
  * They are automatically removed after a given duration and cached internally to reduce overhead.
@@ -62,7 +63,7 @@ export class Gizmos {
62
63
  * @param parent the parent object to attach the label to. If no parent is provided the label will be attached to the scene
63
64
  * @returns a handle to the label that can be used to update the text
64
65
  */
65
- static DrawLabel(position: Vec3, text: string, size: number = .05, duration: number = 0, color?: ColorRepresentation, backgroundColor?: ColorRepresentation | ColorWithAlpha, parent?: Object3D,) {
66
+ static DrawLabel(position: Vec3, text: string, size: number = .05, duration: number = 0, color?: ColorRepresentation, backgroundColor?: ColorRepresentation | GizmoColor, parent?: Object3D,) {
66
67
  if (!Gizmos.enabled) return null;
67
68
  if (!color) color = defaultColor;
68
69
  const rigScale = NeedleXRSession.active?.rigScale ?? 1;
@@ -82,7 +83,7 @@ export class Gizmos {
82
83
  * @param duration the duration in seconds the ray will be rendered. If 0 it will be rendered for one frame
83
84
  * @param depthTest if true the ray will be rendered with depth test
84
85
  */
85
- static DrawRay(origin: Vec3, dir: Vec3, color: ColorRepresentation = defaultColor, duration: number = 0, depthTest: boolean = true) {
86
+ static DrawRay(origin: Vec3, dir: Vec3, color: GizmoColor = defaultColor, duration: number = 0, depthTest: boolean = true) {
86
87
  if (!Gizmos.enabled) return;
87
88
  const obj = Internal.getLine(duration);
88
89
  const positions = obj.geometry.getAttribute("position");
@@ -90,9 +91,10 @@ export class Gizmos {
90
91
  _tmp.set(dir.x, dir.y, dir.z).multiplyScalar(999999999);
91
92
  positions.setXYZ(1, origin.x + _tmp.x, origin.y + _tmp.y, origin.z + _tmp.z);
92
93
  positions.needsUpdate = true;
93
- obj.material["color"].set(color);
94
94
  obj.material["depthTest"] = depthTest;
95
95
  obj.material["depthWrite"] = false;
96
+ obj.material["fog"] = false;
97
+ applyGizmoColor(obj.material, color);
96
98
  }
97
99
 
98
100
  /**
@@ -104,7 +106,7 @@ export class Gizmos {
104
106
  * @param depthTest if true the line will be rendered with depth test
105
107
  * @param lengthFactor the length of the line. Default is 1
106
108
  */
107
- static DrawDirection(pt: Vec3, direction: Vec3 | Vec4, color: ColorRepresentation = defaultColor, duration: number = 0, depthTest: boolean = true, lengthFactor: number = 1) {
109
+ static DrawDirection(pt: Vec3, direction: Vec3 | Vec4, color: GizmoColor = defaultColor, duration: number = 0, depthTest: boolean = true, lengthFactor: number = 1) {
108
110
  if (!Gizmos.enabled) return;
109
111
  const obj = Internal.getLine(duration);
110
112
  const positions = obj.geometry.getAttribute("position");
@@ -120,10 +122,9 @@ export class Gizmos {
120
122
  }
121
123
  positions.setXYZ(1, pt.x + _tmp.x, pt.y + _tmp.y, pt.z + _tmp.z);
122
124
  positions.needsUpdate = true;
123
- obj.material["color"].set(color);
124
125
  obj.material["depthTest"] = depthTest;
125
126
  obj.material["depthWrite"] = false;
126
-
127
+ applyGizmoColor(obj.material, color);
127
128
  }
128
129
 
129
130
  /**
@@ -134,17 +135,17 @@ export class Gizmos {
134
135
  * @param duration the duration in seconds the line will be rendered. If 0 it will be rendered for one frame
135
136
  * @param depthTest if true the line will be rendered with depth test
136
137
  */
137
- static DrawLine(pt0: Vec3, pt1: Vec3, color: ColorRepresentation = defaultColor, duration: number = 0, depthTest: boolean = true) {
138
+ static DrawLine(pt0: Vec3, pt1: Vec3, color: GizmoColor = defaultColor, duration: number = 0, depthTest: boolean = true) {
138
139
  if (!Gizmos.enabled) return;
139
140
  const obj = Internal.getLine(duration);
140
141
  const positions = obj.geometry.getAttribute("position");
141
142
  positions.setXYZ(0, pt0.x, pt0.y, pt0.z);
142
143
  positions.setXYZ(1, pt1.x, pt1.y, pt1.z);
143
144
  positions.needsUpdate = true;
144
- obj.material["color"].set(color);
145
145
  obj.material["depthTest"] = depthTest;
146
146
  obj.material["depthWrite"] = false;
147
147
  obj.material["fog"] = false;
148
+ applyGizmoColor(obj.material, color);
148
149
  }
149
150
 
150
151
  /**
@@ -162,10 +163,10 @@ export class Gizmos {
162
163
  obj.position.set(pt0.x, pt0.y, pt0.z);
163
164
  obj.scale.set(radius, radius, radius);
164
165
  obj.quaternion.setFromUnitVectors(this._up, _tmp.set(normal.x, normal.y, normal.z).normalize());
165
- obj.material["color"].set(color);
166
166
  obj.material["depthTest"] = depthTest;
167
167
  obj.material["depthWrite"] = false;
168
168
  obj.material["fog"] = false;
169
+ applyGizmoColor(obj.material, color);
169
170
  }
170
171
 
171
172
  /**
@@ -176,14 +177,14 @@ export class Gizmos {
176
177
  * @param duration the duration in seconds the sphere will be rendered. If 0 it will be rendered for one frame
177
178
  * @param depthTest if true the sphere will be rendered with depth test
178
179
  */
179
- static DrawWireSphere(center: Vec3, radius: number, color: ColorRepresentation = defaultColor, duration: number = 0, depthTest: boolean = true) {
180
+ static DrawWireSphere(center: Vec3, radius: number, color: GizmoColor = defaultColor, duration: number = 0, depthTest: boolean = true) {
180
181
  if (!Gizmos.enabled) return;
181
182
  const obj = Internal.getSphere(radius, duration, true);
182
183
  setWorldPositionXYZ(obj, center.x, center.y, center.z);
183
- obj.material["color"].set(color);
184
184
  obj.material["depthTest"] = depthTest;
185
185
  obj.material["depthWrite"] = false;
186
186
  obj.material["fog"] = false;
187
+ applyGizmoColor(obj.material, color);
187
188
  }
188
189
 
189
190
  /**
@@ -194,13 +195,13 @@ export class Gizmos {
194
195
  * @param duration the duration in seconds the sphere will be rendered. If 0 it will be rendered for one frame
195
196
  * @param depthTest if true the sphere will be rendered with depth test
196
197
  */
197
- static DrawSphere(center: Vec3, radius: number, color: ColorRepresentation = defaultColor, duration: number = 0, depthTest: boolean = true) {
198
+ static DrawSphere(center: Vec3, radius: number, color: GizmoColor = defaultColor, duration: number = 0, depthTest: boolean = true) {
198
199
  if (!Gizmos.enabled) return;
199
200
  const obj = Internal.getSphere(radius, duration, false);
200
201
  setWorldPositionXYZ(obj, center.x, center.y, center.z);
201
- obj.material["color"].set(color);
202
202
  obj.material["depthTest"] = depthTest;
203
203
  obj.material["depthWrite"] = false;
204
+ applyGizmoColor(obj.material, color);
204
205
  }
205
206
 
206
207
  /**
@@ -212,18 +213,18 @@ export class Gizmos {
212
213
  * @param duration the duration in seconds the box will be rendered. If 0 it will be rendered for one frame
213
214
  * @param depthTest if true the box will be rendered with depth test
214
215
  */
215
- static DrawWireBox(center: Vec3, size: Vec3, color: ColorRepresentation = defaultColor, duration: number = 0, depthTest: boolean = true, rotation: Quaternion|undefined = undefined) {
216
+ static DrawWireBox(center: Vec3, size: Vec3, color: GizmoColor = defaultColor, duration: number = 0, depthTest: boolean = true, rotation: Quaternion | undefined = undefined) {
216
217
  if (!Gizmos.enabled) return;
217
218
  const obj = Internal.getBox(duration);
218
219
  obj.position.set(center.x, center.y, center.z);
219
220
  obj.scale.set(size.x, size.y, size.z);
220
- if(rotation) obj.quaternion.copy(rotation);
221
+ if (rotation) obj.quaternion.copy(rotation);
221
222
  else obj.quaternion.identity();
222
- obj.material["color"].set(color);
223
223
  obj.material["depthTest"] = depthTest;
224
224
  obj.material["wireframe"] = true;
225
225
  obj.material["depthWrite"] = false;
226
226
  obj.material["fog"] = false;
227
+ applyGizmoColor(obj.material, color);
227
228
  }
228
229
 
229
230
  /**
@@ -233,16 +234,16 @@ export class Gizmos {
233
234
  * @param duration the duration in seconds the box will be rendered. If 0 it will be rendered for one frame. Default: 0
234
235
  * @param depthTest if true the box will be rendered with depth test. Default: true
235
236
  */
236
- static DrawWireBox3(box: Box3, color: ColorRepresentation = defaultColor, duration: number = 0, depthTest: boolean = true) {
237
+ static DrawWireBox3(box: Box3, color: GizmoColor = defaultColor, duration: number = 0, depthTest: boolean = true) {
237
238
  if (!Gizmos.enabled) return;
238
239
  const obj = Internal.getBox(duration);
239
240
  obj.position.copy(box.getCenter(_tmp));
240
241
  obj.scale.copy(box.getSize(_tmp));
241
- obj.material["color"].set(color);
242
242
  obj.material["depthTest"] = depthTest;
243
243
  obj.material["wireframe"] = true;
244
244
  obj.material["depthWrite"] = false;
245
245
  obj.material["fog"] = false;
246
+ applyGizmoColor(obj.material, color);
246
247
  }
247
248
 
248
249
  private static _up = new Vector3(0, 1, 0);
@@ -263,9 +264,9 @@ export class Gizmos {
263
264
  const dist = _tmp.set(pt1.x, pt1.y, pt1.z).sub(_tmp2.set(pt0.x, pt0.y, pt0.z)).length();
264
265
  const scale = dist * 0.1;
265
266
  obj.scale.set(scale, scale, scale);
266
- obj.material["color"].set(color);
267
267
  obj.material["depthTest"] = depthTest;
268
268
  obj.material["wireframe"] = wireframe;
269
+ applyGizmoColor(obj.material, color);
269
270
  this.DrawLine(pt0, pt1, color, duration, depthTest);
270
271
  }
271
272
 
@@ -296,9 +297,9 @@ export class Gizmos {
296
297
  }
297
298
  mesh.matrixAutoUpdate = false;
298
299
  mesh.matrixWorldAutoUpdate = false;
299
- mesh.material["color"].set(options.color ?? defaultColor);
300
300
  mesh.material["depthTest"] = options.depthTest ?? true;
301
301
  mesh.material["wireframe"] = true;
302
+ applyGizmoColor(mesh.material, options.color ?? defaultColor);
302
303
  }
303
304
  }
304
305
 
@@ -316,6 +317,19 @@ export function CreateWireCube(col: ColorRepresentation | null = null): LineSegm
316
317
  }
317
318
 
318
319
 
320
+ function applyGizmoColor(material: Material | Material[], color: GizmoColor) {
321
+ if (Array.isArray(material)) {
322
+ for (const mat of material) {
323
+ applyGizmoColor(mat, color);
324
+ }
325
+ return;
326
+ }
327
+ const alpha = (color instanceof RGBAColor) ? color.a : 1.0;
328
+ material["color"].set(color);
329
+ material["opacity"] = alpha;
330
+ material["transparent"] = alpha < 1.0;
331
+ }
332
+
319
333
 
320
334
  const $cacheSymbol = Symbol("GizmoCache");
321
335
  class Internal {
@@ -335,7 +349,7 @@ class Internal {
335
349
  }
336
350
  }
337
351
 
338
- static getTextLabel(duration: number, text: string, size: number, color: ColorRepresentation, backgroundColor?: ColorRepresentation | ColorWithAlpha): Text & LabelHandle {
352
+ static getTextLabel(duration: number, text: string, size: number, color: ColorRepresentation, backgroundColor?: ColorRepresentation | GizmoColor): Text & LabelHandle {
339
353
  this.ensureFont();
340
354
  let element = this.textLabelCache.pop();
341
355
 
@@ -342,7 +342,7 @@ async function sendUsageMessageToAnalyticsBackend(context: IContext) {
342
342
  if (window.crossOriginIsolated) return;
343
343
 
344
344
  const licenseType = NEEDLE_ENGINE_LICENSE_TYPE;
345
- if (licenseType === "pro") {
345
+ if (licenseType === "pro" || licenseType === "enterprise") {
346
346
  const attribute = context?.domElement?.getAttribute("no-telemetry");
347
347
  if (attribute === "" || attribute === "true" || attribute === "1") {
348
348
  if (debug) console.debug("Telemetry is disabled");
@@ -1,7 +1,7 @@
1
1
  import { ShaderChunk, Texture, UniformsLib, Vector4 } from "three";
2
2
 
3
3
  import { setDisposable } from "./engine_assetdatabase.js";
4
- import { Context } from "./engine_setup.js";
4
+ import type { Context } from "./engine_setup.js";
5
5
  import type { SourceIdentifier } from "./engine_types.js";
6
6
  import { getParam } from "./engine_utils.js";
7
7
  import { LightmapType } from "./extensions/NEEDLE_lightmaps.js";
@@ -27,22 +27,22 @@ export interface ILightDataRegistry {
27
27
 
28
28
  export class LightDataRegistry implements ILightDataRegistry {
29
29
 
30
- private _context: Context;
31
- private _lightmaps: Map<SourceIdentifier, Map<LightmapType, Texture[]>> = new Map();
30
+ private readonly context: Context;
31
+ private readonly map: Map<SourceIdentifier, Map<LightmapType, Texture[]>> = new Map();
32
32
 
33
33
  clear() {
34
- this._lightmaps.clear();
34
+ this.map.clear();
35
35
  }
36
36
 
37
37
  constructor(context: Context) {
38
- this._context = context;
38
+ this.context = context;
39
39
  }
40
40
 
41
41
  registerTexture(sourceId: SourceIdentifier, type: LightmapType, tex: Texture, index: number) {
42
42
  if (debugLightmap) console.log("Registering ", LightmapType[type] + " \"" + sourceId + "\"", tex);
43
- if (!this._lightmaps.has(sourceId))
44
- this._lightmaps.set(sourceId, new Map());
45
- const map = this._lightmaps.get(sourceId);
43
+ if (!this.map.has(sourceId))
44
+ this.map.set(sourceId, new Map());
45
+ const map = this.map.get(sourceId);
46
46
  const arr = map?.get(type) ?? [];
47
47
  if (arr.length < index) arr.length = index + 1;
48
48
  setDisposable(tex, false);
@@ -55,12 +55,12 @@ export class LightDataRegistry implements ILightDataRegistry {
55
55
  }
56
56
 
57
57
  tryGetSkybox(sourceId?: SourceIdentifier | null): Texture | null {
58
- if (debugLightmap) console.log("[Get Skybox]", sourceId, this._lightmaps)
58
+ if (debugLightmap) console.log("[Get Skybox]", sourceId, this.map)
59
59
  return this.tryGet(sourceId, LightmapType.Skybox, 0);
60
60
  }
61
61
 
62
62
  tryGetReflection(sourceId?: SourceIdentifier | null): Texture | null {
63
- if (debugLightmap) console.log("[Get Reflection]", sourceId, this._lightmaps)
63
+ if (debugLightmap) console.log("[Get Reflection]", sourceId, this.map)
64
64
  return this.tryGet(sourceId, LightmapType.Reflection, 0);
65
65
  }
66
66
 
@@ -69,7 +69,7 @@ export class LightDataRegistry implements ILightDataRegistry {
69
69
  if (debugLightmap) console.warn("Missing source id");
70
70
  return null;
71
71
  }
72
- const entry = this._lightmaps.get(sourceId);
72
+ const entry = this.map.get(sourceId);
73
73
  if (!entry) {
74
74
  if (debugLightmap) console.warn(`[Lighting] No ${LightmapType[type]} texture entry for`, sourceId);
75
75
  return null;
@@ -67,6 +67,7 @@ export class RapierPhysics implements IPhysicsEngine {
67
67
  debugRenderRaycasts: boolean = false;
68
68
 
69
69
  removeBody(obj: IComponent) {
70
+ if(debugPhysics) console.log("REMOVE BODY", obj?.name, obj[$bodyKey]);
70
71
  if (!obj) return;
71
72
  this.validate();
72
73
  const body = obj[$bodyKey];
@@ -901,6 +902,8 @@ export class RapierPhysics implements IPhysicsEngine {
901
902
  // set the collider layers
902
903
  this.updateColliderCollisionGroups(collider);
903
904
 
905
+ if (debugPhysics) console.log("Created collider", collider.name, col);
906
+
904
907
  return col;
905
908
  }
906
909
  catch (e) {
@@ -162,7 +162,7 @@ export class RendererData {
162
162
  private __currentReflectionId: SourceIdentifier | null = null;
163
163
 
164
164
  /** @internal */
165
- internalEnableReflection(sourceId: SourceIdentifier) {
165
+ internalEnableReflection(sourceId: SourceIdentifier) : Texture | null {
166
166
  this.__currentReflectionId = sourceId;
167
167
  const settings = this._sceneLightSettings?.get(sourceId);
168
168
 
@@ -181,7 +181,7 @@ export class RendererData {
181
181
  const tex = existing.Source;
182
182
  tex.mapping = EquirectangularReflectionMapping;
183
183
  scene.environment = tex;
184
- return;
184
+ return tex;
185
185
  }
186
186
  else if (debug) console.warn("Could not find reflection for source", sourceId);
187
187
  break;
@@ -196,22 +196,21 @@ export class RendererData {
196
196
  tex.colorSpace = SRGBColorSpace;
197
197
  tex.mapping = EquirectangularReflectionMapping;
198
198
  this.context.scene.environment = tex;
199
+ return tex;
199
200
  }
200
201
  else console.error("Missing ambient trilight", settings.sourceId);
201
- return;
202
202
  case AmbientMode.Flat:
203
203
  if (settings.ambientLight) {
204
204
  const tex = createFlatTexture(settings.ambientLight, 64);
205
205
  tex.colorSpace = SRGBColorSpace;
206
206
  tex.mapping = EquirectangularReflectionMapping;
207
207
  this.context.scene.environment = tex;
208
+ return tex;
208
209
  }
209
210
  else console.error("Missing ambientlight", settings.sourceId);
210
- return;
211
- default:
212
- return;
213
211
  }
214
212
  }
213
+ return null;
215
214
  }
216
215
 
217
216
  /** @internal */
@@ -381,6 +381,14 @@ export function resolveUrl(source: SourceIdentifier | undefined, uri: string): s
381
381
  }
382
382
  return uri;
383
383
  }
384
+
385
+ export function toSourceId(src: string | null): SourceIdentifier | undefined {
386
+ if (!src) return undefined;
387
+ src = src.trim();
388
+ src = src.split("?")[0]?.split("#")[0];
389
+ return src;
390
+ }
391
+
384
392
  // export function getPath(glbLocation: SourceIdentifier | undefined, path: string) {
385
393
  // if (path && glbLocation && !path.includes("/")) {
386
394
  // // get directory of glb and prepend it to the audio file path
@@ -793,6 +801,7 @@ const mutationObserverMap = new WeakMap<HTMLElement, HtmlElementExtra>();
793
801
  /**
794
802
  * Register a callback when an {@link HTMLElement} attribute changes.
795
803
  * This is used, for example, by the Skybox component to watch for changes to the environment-* and skybox-* attributes.
804
+ * @returns A function that can be used to unregister the callback
796
805
  */
797
806
  export function addAttributeChangeCallback(domElement: HTMLElement, name: string, callback: AttributeChangeCallback) {
798
807
  if (!mutationObserverMap.get(domElement)) {
@@ -811,6 +820,9 @@ export function addAttributeChangeCallback(domElement: HTMLElement, name: string
811
820
  listeners.set(name, []);
812
821
  }
813
822
  listeners.get(name)!.push(callback);
823
+ return () => {
824
+ removeAttributeChangeCallback(domElement, name, callback);
825
+ }
814
826
  };
815
827
 
816
828
  /**
@@ -107,7 +107,7 @@ export class NEEDLE_lightmaps implements GLTFLoaderPlugin {
107
107
 
108
108
  private resolveTexture(entry: LightmapInfo, res: any) {
109
109
  const tex: Texture = res as unknown as Texture;
110
- if (debug) console.log("Lightmap loaded:", tex);
110
+ if (debug) console.log("Light Texture loaded:", tex);
111
111
  if (tex?.isTexture) {
112
112
  if (!this.registry)
113
113
  console.log(LightmapType[entry.type], entry.pointer, tex);
@@ -89,7 +89,7 @@ function internalResolve(paths: DependencyInfo[], parser: GLTFParserWithCache, o
89
89
  for (let i = 0; i < val.length; i++) {
90
90
  const entry = val[i];
91
91
  const ext = resolveExtension(parser, entry);
92
- if (ext !== null) {
92
+ if (ext !== null && ext !== undefined) {
93
93
  if (typeof ext.then === "function")
94
94
  promises.push(ext.then(res => val[i] = res));
95
95
  else val[i] = ext;
@@ -32,10 +32,22 @@ export class NeedleLogoElement extends HTMLElement {
32
32
  cursor: pointer;
33
33
  }
34
34
  img {
35
- width: 95px;
36
35
  height: 100%;
37
36
  align-self: end;
38
37
  margin-left: 0.6rem;
38
+ transition: transform 0.2s;
39
+ }
40
+ img.with-text {
41
+ width: 11.5ch;
42
+ &:hover {
43
+ transform: scale(1.02);
44
+ }
45
+ }
46
+ img.compact {
47
+ width: 1.7em;
48
+ &:hover {
49
+ transform: scale(1.1);
50
+ }
39
51
  }
40
52
  span {
41
53
  font-size: 1rem;
@@ -43,12 +55,14 @@ export class NeedleLogoElement extends HTMLElement {
43
55
  }
44
56
  </style>
45
57
  <div class="wrapper">
46
- <img class="logo" src=${needleLogoSVG} />
58
+ <img class="logo with-text" src=${needleLogoSVG} />
47
59
  </div>
48
60
  `;
49
61
  this._root.appendChild(template.content.cloneNode(true));
50
62
  this.wrapper = this._root.querySelector(".wrapper") as HTMLDivElement;
51
63
  this._root.appendChild(this.wrapper);
64
+ this.logoElement = this._root.querySelector("img.logo") as HTMLImageElement;
65
+
52
66
  // this.wrapper.classList.add("wrapper");
53
67
 
54
68
  // this.wrapper.appendChild(this.logoElement);
@@ -67,13 +81,24 @@ export class NeedleLogoElement extends HTMLElement {
67
81
 
68
82
  private readonly _root: ShadowRoot;
69
83
  private readonly wrapper: HTMLDivElement;
70
- private readonly logoElement: HTMLImageElement = document.createElement("img");
71
- private readonly textElement: HTMLSpanElement = document.createElement("span");
84
+ private readonly logoElement: HTMLImageElement;
72
85
 
73
86
  setLogoVisible(val: boolean) {
74
87
  this.logoElement.style.display = val ? "block" : "none";
75
88
  }
76
89
 
90
+ setType(type: "full" | "compact") {
91
+ if (type === "full") {
92
+ this.logoElement.src = needleLogoSVG;
93
+ this.logoElement.classList.remove("with-text");
94
+ this.logoElement.classList.remove("compact");
95
+ } else {
96
+ this.logoElement.src = needleLogoOnlySVG;
97
+ this.logoElement.classList.add("with-text");
98
+ this.logoElement.classList.add("compact");
99
+ }
100
+ }
101
+
77
102
  }
78
103
  if (!customElements.get(elementName))
79
104
  customElements.define(elementName, NeedleLogoElement);
@@ -459,7 +459,7 @@ export class NeedleMenuElement extends HTMLElement {
459
459
 
460
460
  .logo {
461
461
  cursor: pointer;
462
- padding-left: 0.6rem;
462
+ padding-left: 0.0rem;
463
463
  padding-bottom: .02rem;
464
464
  margin-right: 0.5rem;
465
465
  }
@@ -664,8 +664,8 @@ export class NeedleMenuElement extends HTMLElement {
664
664
  <slot name="end"></slot>
665
665
  </div>
666
666
  </div>
667
- <div style="user-select:none" class="logo">
668
- <span class="madewith notranslate">powered by</span>
667
+ <div style="user-select:none;" class="logo">
668
+ <span class="madewith notranslate" style="display:none;">powered by</span>
669
669
  </div>
670
670
  </div>
671
671
  <button class="compact-menu-button">
@@ -698,6 +698,7 @@ export class NeedleMenuElement extends HTMLElement {
698
698
  this.wrapper.classList.add("wrapper");
699
699
 
700
700
  const logo = NeedleLogoElement.create();
701
+ logo.setType("compact");
701
702
  logo.style.minHeight = "1rem";
702
703
  this.logoContainer.append(logo);
703
704
  this.logoContainer.addEventListener("click", () => {
@@ -374,40 +374,40 @@ export class EngineLoadingView implements ILoadingViewHandler {
374
374
  // }
375
375
  // }
376
376
 
377
- this.handleRuntimeLicense(this._loadingElement);
377
+ // this.handleRuntimeLicense(this._loadingElement);
378
378
 
379
379
  return this._loadingElement;
380
380
  }
381
381
 
382
- private async handleRuntimeLicense(loadingElement: HTMLElement) {
383
- // First check if we have a commercial license
384
- let commercialLicense = hasCommercialLicense();
385
- // if it's the case then we don't need to perform a runtime check
386
- if (commercialLicense) return;
387
-
388
- // If we don't have a commercial license, then we need to display our message
389
- if (debugLicense) console.log("Loading UI has commercial license?", commercialLicense);
390
- const nonCommercialContainer = document.createElement("div");
391
- nonCommercialContainer.style.paddingTop = ".6em";
392
- nonCommercialContainer.style.fontSize = ".8em";
393
- nonCommercialContainer.style.textTransform = "uppercase";
394
- nonCommercialContainer.innerText = "NEEDLE ENGINE NON COMMERCIAL VERSION\nCLICK HERE TO GET A LICENSE";
395
- nonCommercialContainer.style.cursor = "pointer";
396
- nonCommercialContainer.style.userSelect = "none";
397
- nonCommercialContainer.style.textAlign = "center";
398
- nonCommercialContainer.style.pointerEvents = "all";
399
- nonCommercialContainer.addEventListener("click", () => window.open("https://needle.tools/pricing", "_self"));
400
- nonCommercialContainer.style.opacity = "0";
401
- loadingElement.appendChild(nonCommercialContainer);
402
-
403
- // Use the runtime license check
404
- if (!isDevEnvironment() && runtimeLicenseCheckPromise) {
405
- if (debugLicense) console.log("Waiting for runtime license check");
406
- await runtimeLicenseCheckPromise;
407
- commercialLicense = hasCommercialLicense();
408
- }
409
- if (commercialLicense) return;
410
- nonCommercialContainer.style.transition = "opacity .5s ease-in-out";
411
- nonCommercialContainer.style.opacity = "1";
412
- }
382
+ // private async handleRuntimeLicense(loadingElement: HTMLElement) {
383
+ // // First check if we have a commercial license
384
+ // let commercialLicense = hasCommercialLicense();
385
+ // // if it's the case then we don't need to perform a runtime check
386
+ // if (commercialLicense) return;
387
+
388
+ // // If we don't have a commercial license, then we need to display our message
389
+ // if (debugLicense) console.log("Loading UI has commercial license?", commercialLicense);
390
+ // const nonCommercialContainer = document.createElement("div");
391
+ // nonCommercialContainer.style.paddingTop = ".6em";
392
+ // nonCommercialContainer.style.fontSize = ".8em";
393
+ // nonCommercialContainer.style.textTransform = "uppercase";
394
+ // nonCommercialContainer.innerText = "NEEDLE ENGINE NON COMMERCIAL VERSION\nCLICK HERE TO GET A LICENSE";
395
+ // nonCommercialContainer.style.cursor = "pointer";
396
+ // nonCommercialContainer.style.userSelect = "none";
397
+ // nonCommercialContainer.style.textAlign = "center";
398
+ // nonCommercialContainer.style.pointerEvents = "all";
399
+ // nonCommercialContainer.addEventListener("click", () => window.open("https://needle.tools/pricing", "_self"));
400
+ // nonCommercialContainer.style.opacity = "0";
401
+ // loadingElement.appendChild(nonCommercialContainer);
402
+
403
+ // // Use the runtime license check
404
+ // if (!isDevEnvironment() && runtimeLicenseCheckPromise) {
405
+ // if (debugLicense) console.log("Waiting for runtime license check");
406
+ // await runtimeLicenseCheckPromise;
407
+ // commercialLicense = hasCommercialLicense();
408
+ // }
409
+ // if (commercialLicense) return;
410
+ // nonCommercialContainer.style.transition = "opacity .5s ease-in-out";
411
+ // nonCommercialContainer.style.opacity = "1";
412
+ // }
413
413
  }