Needle Engine

Changes between version 3.21.5 and 3.22.0
Files changed (134) hide show
  1. src/engine-components/Animation.ts +1 -1
  2. src/engine-components/export/usdz/extensions/Animation.ts +1 -1
  3. src/engine-components/AnimationUtils.ts +1 -1
  4. src/engine-components/Animator.ts +2 -2
  5. src/engine-components/AnimatorController.ts +2 -1
  6. src/engine-components/postprocessing/Effects/Antialiasing.ts +1 -1
  7. src/engine/api.ts +1 -0
  8. src/engine-components/export/usdz/extensions/behavior/AudioExtension.ts +2 -1
  9. src/engine-components/AudioSource.ts +66 -26
  10. src/engine-components/avatar/Avatar_Brain_LookAt.ts +1 -2
  11. src/engine-components/ui/BaseUIComponent.ts +1 -2
  12. src/engine-components/export/usdz/extensions/behavior/Behaviour.ts +2 -2
  13. src/engine-components/export/usdz/extensions/behavior/BehaviourComponents.ts +6 -4
  14. src/engine-components/BoxHelperComponent.ts +1 -1
  15. src/engine-components/ui/Button.ts +1 -1
  16. src/engine-components/Camera.ts +3 -3
  17. src/engine-components/CameraUtils.ts +1 -1
  18. src/engine-components/ui/Canvas.ts +2 -2
  19. src/engine-components/ui/CanvasGroup.ts +1 -1
  20. src/engine-components/postprocessing/Effects/ChromaticAberration.ts +1 -1
  21. src/engine-components/Collider.ts +3 -3
  22. src/engine-components/postprocessing/Effects/ColorAdjustments.ts +2 -2
  23. src/engine-components/Component.ts +1 -1
  24. src/engine-components/export/usdz/extensions/DocumentExtension.ts +1 -1
  25. src/engine-components/DragControls.ts +2 -2
  26. src/engine-components/DropListener.ts +1 -1
  27. src/engine/engine_addressables.ts +1 -2
  28. src/engine/engine_camera.ts +1 -1
  29. src/engine/engine_components_internal.ts +1 -1
  30. src/engine/engine_components.ts +1 -1
  31. src/engine/engine_context_registry.ts +1 -1
  32. src/engine/engine_context.ts +3 -3
  33. src/engine/engine_element.ts +2 -2
  34. src/engine/engine_gameobject.ts +1 -1
  35. src/engine/engine_gizmos.ts +2 -2
  36. src/engine/engine_gltf_builtin_components.ts +2 -3
  37. src/engine/engine_gltf.ts +2 -2
  38. src/engine/engine_hot_reload.ts +1 -1
  39. src/engine/engine_input.ts +8 -6
  40. src/engine/engine_license.ts +1 -1
  41. src/engine/engine_lightdata.ts +1 -1
  42. src/engine/engine_mainloop_utils.ts +2 -2
  43. src/engine/engine_math.ts +1 -4
  44. src/engine/engine_networking_auto.ts +1 -1
  45. src/engine/engine_networking_files_default_components.ts +2 -2
  46. src/engine/engine_networking_files.ts +3 -3
  47. src/engine/engine_networking_instantiate.ts +4 -4
  48. src/engine/engine_networking_peer.ts +3 -3
  49. src/engine/engine_networking.ts +10 -2
  50. src/engine/engine_physics_rapier.ts +25 -10
  51. src/engine/engine_physics.ts +3 -3
  52. src/engine/engine_scenelighting.ts +1 -1
  53. src/engine/engine_scenetools.ts +3 -3
  54. src/engine/engine_serialization_builtin_serializer.ts +7 -1
  55. src/engine/engine_serialization_core.ts +5 -2
  56. src/engine/engine_serialization_decorator.ts +1 -1
  57. src/engine/engine_shaders.ts +1 -1
  58. src/engine/engine_time.ts +1 -1
  59. src/engine/engine_types.ts +4 -3
  60. src/engine/engine_util_decorator.ts +2 -2
  61. src/engine/engine_utils.ts +16 -2
  62. src/engine-components/ui/EventSystem.ts +3 -4
  63. src/engine-components/EventTrigger.ts +1 -1
  64. src/engine/extensions/EXT_texture_exr.ts +1 -1
  65. src/engine/extensions/extension_utils.ts +1 -1
  66. src/engine/extensions/extensions.ts +2 -2
  67. src/engine-components/js-extensions/ExtensionUtils.ts +1 -1
  68. src/engine-components/export/gltf/GltfExport.ts +1 -1
  69. src/engine-components/ui/Graphic.ts +1 -1
  70. src/engine-components/ui/InputField.ts +1 -1
  71. src/engine-components/Interactable.ts +1 -1
  72. src/engine-components/ui/Interfaces.ts +1 -2
  73. src/engine-components/ui/Layout.ts +1 -1
  74. src/engine-components/Light.ts +1 -3
  75. src/engine-components/utils/LookAt.ts +1 -1
  76. src/engine/extensions/NEEDLE_components.ts +2 -2
  77. src/engine/extensions/NEEDLE_gameobject_data.ts +1 -1
  78. src/engine/extensions/NEEDLE_lighting_settings.ts +2 -2
  79. src/engine/extensions/NEEDLE_lightmaps.ts +4 -4
  80. src/engine/extensions/NEEDLE_persistent_assets.ts +2 -2
  81. src/engine/extensions/NEEDLE_progressive.ts +2 -2
  82. src/engine/extensions/NEEDLE_render_objects.ts +5 -5
  83. src/engine/extensions/NEEDLE_techniques_webgl.ts +4 -4
  84. src/engine-components/NestedGltf.ts +1 -1
  85. src/engine-components/Networking.ts +1 -1
  86. src/engine-components/js-extensions/Object3D.ts +1 -2
  87. src/engine-components/utils/OpenURL.ts +1 -1
  88. src/engine-components/OrbitControls.ts +2 -2
  89. src/engine-components/ParticleSystem.ts +3 -2
  90. src/engine-components/ParticleSystemModules.ts +4 -4
  91. src/engine-components/ParticleSystemSubEmitter.ts +2 -2
  92. src/engine-components/postprocessing/Effects/Pixelation.ts +1 -1
  93. src/engine-components/timeline/PlayableDirector.ts +1 -1
  94. src/engine-components/postprocessing/PostProcessingEffect.ts +2 -2
  95. src/engine-components/postprocessing/PostProcessingHandler.ts +1 -1
  96. src/engine-components-experimental/Presentation.ts +1 -1
  97. src/engine-components/ui/RaycastUtils.ts +2 -3
  98. src/engine-components/ui/RectTransform.ts +2 -2
  99. src/engine-components/ReflectionProbe.ts +2 -3
  100. src/engine/codegen/register_types.ts +2 -2
  101. src/engine-components/Renderer.ts +1 -1
  102. src/engine-components/RendererLightmap.ts +2 -3
  103. src/engine-components/RigidBody.ts +18 -18
  104. src/engine-components/ScreenCapture.ts +170 -510
  105. src/engine-components/postprocessing/Effects/ScreenspaceAmbientOcclusion.ts +3 -3
  106. src/engine-components/postprocessing/Effects/ScreenspaceAmbientOcclusionN8.ts +1 -1
  107. src/engine-components/SpectatorCamera.ts +2 -2
  108. src/engine-components/SpriteRenderer.ts +1 -1
  109. src/engine-components/SyncedCamera.ts +2 -1
  110. src/engine-components/TestRunner.ts +1 -1
  111. src/engine-components/ui/Text.ts +3 -3
  112. src/engine-components/postprocessing/Effects/TiltShiftEffect.ts +1 -1
  113. src/engine-components/postprocessing/Effects/Tonemapping.ts +1 -1
  114. src/engine-components/TransformGizmo.ts +1 -1
  115. src/engine/extensions/usage_tracker.ts +2 -2
  116. src/engine-components/export/usdz/USDZExporter.ts +1 -1
  117. src/engine-components/export/usdz/extensions/USDZText.ts +2 -2
  118. src/engine-components/export/usdz/extensions/USDZUI.ts +1 -1
  119. src/engine-components/VideoPlayer.ts +11 -3
  120. src/engine-components/postprocessing/Effects/Vignette.ts +1 -1
  121. src/engine-components/Voip.ts +158 -430
  122. src/engine-components/postprocessing/Volume.ts +1 -1
  123. src/engine-components/webxr/WebXR.ts +3 -3
  124. src/engine-components/webxr/WebXRController.ts +1 -1
  125. src/engine-components/webxr/WebXRGrabRendering.ts +1 -1
  126. src/engine-components/webxr/WebXRPlaneTracking.ts +1 -1
  127. src/engine-components/webxr/WebXRRig.ts +2 -2
  128. src/engine/dist/api.js +73 -0
  129. src/engine-components/dist/AudioSource.js +513 -0
  130. src/engine/dist/engine_networking_streams.js +474 -0
  131. src/engine-components/dist/ScreenCapture.js +490 -0
  132. src/engine-components/dist/VideoPlayer.js +888 -0
  133. src/engine-components/dist/Voip2.js +46 -0
  134. src/engine/engine_networking_streams.ts +489 -0
src/engine-components/Animation.ts CHANGED
@@ -3,7 +3,7 @@
3
3
  import { MixerEvent } from "./Animator.js";
4
4
  import { serializable } from "../engine/engine_serialization_decorator.js";
5
5
  import { Mathf } from "../engine/engine_math.js";
6
- import { Vec2 } from "../engine/engine_types.js";
6
+ import type { Vec2 } from "../engine/engine_types.js";
7
7
  import { getParam } from "../engine/engine_utils.js";
8
8
 
9
9
  const debug = getParam("debuganimation");
src/engine-components/export/usdz/extensions/Animation.ts CHANGED
@@ -2,7 +2,7 @@
2
2
  import { getParam } from "../../../../engine/engine_utils.js";
3
3
 
4
4
  import { USDObject, buildMatrix } from "../ThreeUSDZExporter.js";
5
- import { IUSDExporterExtension } from "../Extension.js";
5
+ import type { IUSDExporterExtension } from "../Extension.js";
6
6
 
7
7
  import { Object3D, Matrix4, Vector3, Quaternion, Interpolant, AnimationClip, KeyframeTrack, PropertyBinding } from "three";
8
8
 
src/engine-components/AnimationUtils.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { GLTF } from "three/examples/jsm/loaders/GLTFLoader.js";
1
+ import type { GLTF } from "three/examples/jsm/loaders/GLTFLoader.js";
2
2
  import { ContextEvent, ContextRegistry } from "../engine/engine_context_registry.js";
3
3
  import { addNewComponent } from "../engine/engine_components.js";
4
4
  import { Animator } from "./Animator.js";
src/engine-components/Animator.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { Behaviour } from "./Component.js";
2
- import { AnimationActionLoopStyles, AnimationAction, AnimationMixer } from "three";
2
+ import type { AnimationActionLoopStyles, AnimationAction, AnimationMixer } from "three";
3
3
  import { getParam } from "../engine/engine_utils.js";
4
- import { AnimatorControllerModel } from "../engine/extensions/NEEDLE_animator_controller_model.js";
4
+ import type { AnimatorControllerModel } from "../engine/extensions/NEEDLE_animator_controller_model.js";
5
5
  import { AnimatorController } from "./AnimatorController.js";
6
6
  import { serializable } from "../engine/engine_serialization_decorator.js";
7
7
  import { Mathf } from "../engine/engine_math.js";
src/engine-components/AnimatorController.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { Animator } from "./Animator.js";
2
- import { AnimatorConditionMode, AnimatorControllerModel, AnimatorControllerParameterType, AnimatorStateInfo, Condition, createMotion, State, StateMachineBehaviour, Transition } from "../engine/extensions/NEEDLE_animator_controller_model.js";
2
+ import type { AnimatorControllerModel, Condition, State, Transition } from "../engine/extensions/NEEDLE_animator_controller_model.js";
3
+ import { AnimatorConditionMode, AnimatorControllerParameterType, AnimatorStateInfo, createMotion, StateMachineBehaviour } from "../engine/extensions/NEEDLE_animator_controller_model.js";
3
4
  import { AnimationAction, AnimationClip, AnimationMixer, AxesHelper, Euler, KeyframeTrack, LoopOnce, Object3D, Quaternion, Vector3 } from "three";
4
5
  import { deepClone, getParam } from "../engine/engine_utils.js";
5
6
  import { Context } from "../engine/engine_setup.js";
src/engine-components/postprocessing/Effects/Antialiasing.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { EdgeDetectionMode, SMAAEffect, SMAAPreset } from "postprocessing";
2
2
  import { serializable } from "../../../engine/engine_serialization.js";
3
- import { EffectProviderResult, PostProcessingEffect } from "../PostProcessingEffect.js";
3
+ import { type EffectProviderResult, PostProcessingEffect } from "../PostProcessingEffect.js";
4
4
  import { VolumeParameter } from "../VolumeParameter.js";
5
5
  import { registerCustomEffectType } from "../VolumeProfile.js";
6
6
 
src/engine/api.ts CHANGED
@@ -24,6 +24,7 @@
24
24
  export { syncField } from "./engine_networking_auto.js";
25
25
  export * from "./engine_networking_files.js";
26
26
  export * from "./engine_networking_instantiate.js";
27
+ export * from "./engine_networking_streams.js";
27
28
  export * from "./engine_networking_utils.js";
28
29
  export * from "./engine_networking_peer.js";
29
30
  export * from "./engine_patcher.js";
src/engine-components/export/usdz/extensions/behavior/AudioExtension.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { GameObject } from "../../../../Component.js";
2
- import { IUSDExporterExtension } from "../../Extension.js";
2
+ import type { IUSDExporterExtension } from "../../Extension.js";
3
3
  import { USDObject, USDWriter, USDZExporterContext } from "../../ThreeUSDZExporter.js";
4
4
  import { Object3D } from "three";
5
5
  import { AudioSource } from "../../../../AudioSource.js";
@@ -19,6 +19,7 @@
19
19
  for (const audioSource of audioSources) {
20
20
 
21
21
  if (!audioSource.clip) continue;
22
+ if(typeof audioSource.clip !== "string") continue;
22
23
 
23
24
  // do nothing if this audio source is not set to play on awake -
24
25
  // should be controlled via PlayAudioOnClick instead then.
src/engine-components/AudioSource.ts CHANGED
@@ -4,7 +4,7 @@
4
4
  import * as utils from "../engine/engine_utils.js";
5
5
  import { serializable } from "../engine/engine_serialization_decorator.js";
6
6
  import { ApplicationEvents } from "../engine/engine_application.js";
7
- import { AudioLoader, PositionalAudio } from "three";
7
+ import { Audio, AudioContext, AudioLoader, PositionalAudio } from "three";
8
8
 
9
9
 
10
10
  const debug = utils.getParam("debugaudio");
@@ -65,7 +65,7 @@
65
65
  if (fn == undefined) return;
66
66
  if (AudioSource._userInteractionRegistered) return;
67
67
  AudioSource._userInteractionRegistered = true;
68
- if(debug) console.log("🔊 registered interaction, can play audio now");
68
+ if (debug) console.log("🔊 registered interaction, can play audio now");
69
69
  document.removeEventListener('pointerdown', fn);
70
70
  document.removeEventListener('click', fn);
71
71
  document.removeEventListener('dragstart', fn);
@@ -83,7 +83,7 @@
83
83
  }
84
84
 
85
85
  @serializable(URL)
86
- clip: string = "";
86
+ clip: string | MediaStream = "";
87
87
 
88
88
  @serializable()
89
89
  playOnAwake: boolean = false;
@@ -97,6 +97,7 @@
97
97
  this._loop = val;
98
98
  if (this.sound) this.sound.setLoop(val);
99
99
  }
100
+ /** 0 = 2D, 1 = 3D */
100
101
  @serializable()
101
102
  get spatialBlend(): number {
102
103
  return this._spatialBlend;
@@ -154,7 +155,8 @@
154
155
  private shouldPlay: boolean = false;
155
156
  // set this from audio context time, used to set clip offset when setting "time" property
156
157
  // there is maybe a better way to set a audio clip current time?!
157
- private _lastClipStartedLoading: string | null = null;
158
+ private _lastClipStartedLoading: string | MediaStream | null = null;
159
+ private _audioElement: HTMLAudioElement | null = null;
158
160
 
159
161
  public get Sound(): PositionalAudio | null {
160
162
  if (!this.sound && AudioSource._userInteractionRegistered) {
@@ -164,7 +166,7 @@
164
166
  this.sound = new PositionalAudio(listener.listener);
165
167
  this.gameObject.add(this.sound);
166
168
  }
167
- else if(debug) console.warn("No audio listener found in scene - can not play audio");
169
+ else if (debug) console.warn("No audio listener found in scene - can not play audio");
168
170
  }
169
171
  return this.sound;
170
172
  }
@@ -181,7 +183,7 @@
181
183
  if (!AudioSource._userInteractionRegistered) {
182
184
  AudioSource._beginWaitForUserInteraction(() => {
183
185
  if (this.enabled && !this.destroyed && this.shouldPlay)
184
- this.loadAndPlay(this.clip);
186
+ this.onNewClip(this.clip);
185
187
  });
186
188
  }
187
189
  else if (this.playOnAwake && this.context.application.isVisible) {
@@ -225,7 +227,7 @@
225
227
 
226
228
  private lerp = (x, y, a) => x * (1 - a) + y * a;
227
229
 
228
- private onLoaded = (buffer) => {
230
+ private createAudio = (buffer?: AudioBuffer) => {
229
231
  if (debug) console.log("audio buffer loaded");
230
232
  AudioSource.registerWaitForAllowAudio(() => {
231
233
  if (debug)
@@ -239,9 +241,10 @@
239
241
  if (sound.isPlaying)
240
242
  sound.stop();
241
243
 
242
- sound.setBuffer(buffer);
244
+ if (buffer)
245
+ sound.setBuffer(buffer);
243
246
  sound.loop = this._loop;
244
- if(this.context.application.muted) sound.setVolume(0);
247
+ if (this.context.application.muted) sound.setVolume(0);
245
248
  else sound.setVolume(this.volume);
246
249
  sound.autoplay = this.shouldPlay;
247
250
  // sound.setDistanceModel('linear');
@@ -289,34 +292,49 @@
289
292
  }
290
293
  }
291
294
 
292
- private loadAndPlay(clip?: string) {
293
- if (clip)
294
- this.clip = clip;
295
- if (this.clip) {
295
+ private onNewClip(clip?: string | MediaStream) {
296
+ if (clip) this.clip = clip;
297
+ if (typeof clip === "string") {
296
298
  if (debug)
297
- console.log(this.clip);
298
- if (this.clip.endsWith(".mp3") || this.clip.endsWith(".wav")) {
299
+ console.log(clip);
300
+ if (clip.endsWith(".mp3") || clip.endsWith(".wav")) {
299
301
  if (!this.audioLoader)
300
302
  this.audioLoader = new AudioLoader();
301
303
  this.shouldPlay = true;
302
- if (this._lastClipStartedLoading === this.clip) {
304
+ if (this._lastClipStartedLoading === clip) {
303
305
  if (debug) console.log("Is currently loading:", this._lastClipStartedLoading, this)
304
306
  return;
305
307
  }
306
- this._lastClipStartedLoading = this.clip;
308
+ this._lastClipStartedLoading = clip;
307
309
  if (debug)
308
- console.log("load audio", this.clip);
309
- this.audioLoader.load(this.clip, this.onLoaded, () => { }, console.error);
310
+ console.log("load audio", clip);
311
+ this.audioLoader.load(clip, this.createAudio, () => { }, console.error);
310
312
  }
313
+ else console.warn("Unsupported audio clip type", clip)
311
314
  }
315
+ else {
316
+ this.shouldPlay = true;
317
+ this.createAudio();
318
+ }
312
319
  }
313
320
 
314
- play(clip: string | undefined = undefined) {
315
- // Make sure this is always just a string
316
- if (typeof clip !== "string") clip = undefined;
321
+ /** Play a mediastream */
322
+ play(clip: string | MediaStream | undefined = undefined) {
323
+ // We only support strings and media stream
324
+ // TODO: maybe we should return here if an invalid value is passed in
325
+ if (clip !== undefined && typeof clip !== "string" && !(clip instanceof MediaStream)) {
326
+ console.warn("Called play on AudioSource with unknown argument type", clip)
327
+ clip = undefined;
328
+ }
317
329
 
318
- if (!this.audioLoader || !this.sound || (clip && clip !== this.clip)) {
319
- this.loadAndPlay(clip);
330
+ // Check if we need to call load first
331
+ let needsLoading = !this.sound || (clip && clip !== this.clip);
332
+ if (typeof clip === "string" && !this.audioLoader) needsLoading = true;
333
+ if (clip instanceof MediaStream || typeof clip === "string")
334
+ this.clip = clip;
335
+ if (needsLoading) {
336
+ this.shouldPlay = true;
337
+ this.onNewClip(clip);
320
338
  return;
321
339
  }
322
340
 
@@ -326,8 +344,28 @@
326
344
  console.log("play", this.sound?.getVolume(), this.sound);
327
345
  if (this.sound && !this.sound.isPlaying) {
328
346
  const muted = this.context.application.muted;
329
- if(muted) this.sound.setVolume(0);
330
- this.sound.play(muted ? .1 : 0);
347
+ if (muted) this.sound.setVolume(0);
348
+
349
+ if (this.clip instanceof MediaStream) {
350
+
351
+ // We have to set the audio element source to the mediastream as well
352
+ // otherwise it will not play for some reason...
353
+ this.sound.setMediaStreamSource(this.clip);
354
+
355
+ if (!this._audioElement) {
356
+ this._audioElement = document.createElement('audio');
357
+ this._audioElement.style.display = "none";
358
+ }
359
+ if (!this._audioElement.parentNode)
360
+ this.context.domElement.shadowRoot?.append(this._audioElement);
361
+ this._audioElement.srcObject = this.clip;
362
+ this._audioElement.autoplay = false;
363
+
364
+ }
365
+ else {
366
+ if (this._audioElement) this._audioElement.remove();
367
+ this.sound.play(muted ? .1 : 0);
368
+ }
331
369
  }
332
370
  }
333
371
 
@@ -339,6 +377,7 @@
339
377
  this._lastContextTime = this.sound?.context.currentTime;
340
378
  this.sound.pause();
341
379
  }
380
+ this._audioElement?.remove();
342
381
  }
343
382
 
344
383
  stop() {
@@ -351,6 +390,7 @@
351
390
  console.log(this._lastContextTime)
352
391
  this.sound.stop();
353
392
  }
393
+ this._audioElement?.remove();
354
394
  }
355
395
 
356
396
  private _lastContextTime: number = 0;
src/engine-components/avatar/Avatar_Brain_LookAt.ts CHANGED
@@ -4,9 +4,8 @@
4
4
  import { AvatarMarker } from "../webxr/WebXRAvatar.js";
5
5
  import * as utils from "../../engine/engine_three_utils.js";
6
6
  import { OwnershipModel } from "../../engine/engine_networking.js";
7
- import { Int8BufferAttribute } from "three";
8
7
  import { Context } from "../../engine/engine_setup.js";
9
- import { IModel } from "../../engine/engine_networking_types.js";
8
+ import type { IModel } from "../../engine/engine_networking_types.js";
10
9
 
11
10
  export class Avatar_POI {
12
11
 
src/engine-components/ui/BaseUIComponent.ts CHANGED
@@ -4,8 +4,7 @@
4
4
  import { EventSystem } from "./EventSystem.js";
5
5
  import { showGizmos } from '../../engine/engine_default_parameters.js';
6
6
  import { AxesHelper, Object3D } from 'three';
7
- import { ICanvas, IGraphic } from './Interfaces.js';
8
- import { ShadowCastingMode } from '../Renderer.js';
7
+ import type { ICanvas } from './Interfaces.js';
9
8
  import { getParam } from '../../engine/engine_utils.js';
10
9
  export const includesDir = "./include";
11
10
 
src/engine-components/export/usdz/extensions/behavior/Behaviour.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { GameObject } from "../../../../Component.js";
2
- import { IContext } from "../../../../../engine/engine_types.js";
3
- import { IUSDExporterExtension } from "../../Extension.js";
2
+ import type { IContext } from "../../../../../engine/engine_types.js";
3
+ import type { IUSDExporterExtension } from "../../Extension.js";
4
4
  import { USDObject, USDWriter } from "../../ThreeUSDZExporter.js";
5
5
  import { BehaviorModel } from "./BehavioursBuilder.js";
6
6
  import { getParam } from "../../../../../engine/engine_utils.js";
src/engine-components/export/usdz/extensions/behavior/BehaviourComponents.ts CHANGED
@@ -2,15 +2,15 @@
2
2
  import { Animator } from "../../../../Animator.js";
3
3
  import { Renderer } from "../../../../Renderer.js";
4
4
  import { serializable } from "../../../../../engine/engine_serialization_decorator.js";
5
- import { IPointerClickHandler, PointerEventData } from "../../../../ui/PointerEvents.js";
6
- import { RegisteredAnimationInfo, UsdzAnimation } from "../Animation.js";
5
+ import type { IPointerClickHandler, PointerEventData } from "../../../../ui/PointerEvents.js";
6
+ import { RegisteredAnimationInfo, type UsdzAnimation } from "../Animation.js";
7
7
  import { getWorldPosition, getWorldQuaternion, getWorldScale, setWorldPosition, setWorldQuaternion, setWorldScale } from "../../../../../engine/engine_three_utils.js";
8
8
 
9
9
  import { Object3D, Material, Vector3, Quaternion, Mesh, Group } from "three";
10
10
  import { USDDocument, USDObject } from "../../ThreeUSDZExporter.js";
11
11
 
12
- import { BehaviorExtension, UsdzBehaviour } from "./Behaviour.js";
13
- import { ActionBuilder, ActionModel, AuralMode, BehaviorModel, IBehaviorElement, MotionType, PlayAction, Space, TriggerBuilder } from "./BehavioursBuilder.js";
12
+ import type { BehaviorExtension, UsdzBehaviour } from "./Behaviour.js";
13
+ import { ActionBuilder, ActionModel, AuralMode, BehaviorModel, type IBehaviorElement, MotionType, PlayAction, Space, TriggerBuilder } from "./BehavioursBuilder.js";
14
14
  import { AudioSource } from "../../../../AudioSource.js";
15
15
  import { NEEDLE_progressive } from "../../../../../engine/extensions/NEEDLE_progressive.js";
16
16
  import { isDevEnvironment } from "../../../../../engine/debug/index.js";
@@ -496,6 +496,7 @@
496
496
 
497
497
  const clipUrl = this.clip ? this.clip : this.target ? this.target.clip : undefined;
498
498
  if (!clipUrl) return;
499
+ if(typeof clipUrl !== "string") return;
499
500
 
500
501
  const playbackTarget = this.target ? this.target.gameObject : this.gameObject;
501
502
  const clipName = clipUrl.split("/").pop();
@@ -513,6 +514,7 @@
513
514
  if (!this.target && !this.clip) return;
514
515
  const clipUrl = this.clip ? this.clip : this.target ? this.target.clip : undefined;
515
516
  if (!clipUrl) return;
517
+ if(typeof clipUrl !== "string") return;
516
518
  const clipName = clipUrl.split("/").pop();
517
519
 
518
520
  const audio = await fetch(this.clip);
src/engine-components/BoxHelperComponent.ts CHANGED
@@ -2,7 +2,7 @@
2
2
  import { getParam } from "../engine/engine_utils.js";
3
3
  import { CreateWireCube, Gizmos } from "../engine/engine_gizmos.js";
4
4
  import { getWorldPosition, getWorldScale } from "../engine/engine_three_utils.js";
5
- import { Box3, Color, ColorRepresentation, LineSegments, Object3D, Vector3 } from "three";
5
+ import { Box3, Color, type ColorRepresentation, LineSegments, Object3D, Vector3 } from "three";
6
6
 
7
7
  const gizmos = getParam("gizmos");
8
8
  const debug = getParam("debugboxhelper");
src/engine-components/ui/Button.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Behaviour, GameObject } from "../Component.js";
2
2
  import { EventList } from "../EventList.js";
3
- import { IPointerClickHandler, IPointerEnterHandler, IPointerEventHandler, IPointerExitHandler, PointerEventData } from "./PointerEvents.js";
3
+ import type { IPointerClickHandler, IPointerEnterHandler, IPointerEventHandler, IPointerExitHandler, PointerEventData } from "./PointerEvents.js";
4
4
  import { Image } from "./Image.js";
5
5
  import { RGBAColor } from "../js-extensions/RGBAColor.js";
6
6
  import { serializable } from "../../engine/engine_serialization_decorator.js";
src/engine-components/Camera.ts CHANGED
@@ -3,12 +3,12 @@
3
3
  import { serializable } from "../engine/engine_serialization_decorator.js";
4
4
  import { RGBAColor } from "./js-extensions/RGBAColor.js";
5
5
  import { Context, XRSessionMode } from "../engine/engine_setup.js";
6
- import { ICamera } from "../engine/engine_types.js"
6
+ import type { ICamera } from "../engine/engine_types.js"
7
7
  import { isDevEnvironment, showBalloonMessage, showBalloonWarning } from "../engine/debug/index.js";
8
- import { getWorldPosition, Graphics } from "../engine/engine_three_utils.js";
8
+ import { getWorldPosition } from "../engine/engine_three_utils.js";
9
9
  import { Gizmos } from "../engine/engine_gizmos.js";
10
10
 
11
- import { EquirectangularReflectionMapping, OrthographicCamera, PerspectiveCamera, Ray, SRGBColorSpace, sRGBEncoding, Vector3 } from "three";
11
+ import { EquirectangularReflectionMapping, OrthographicCamera, PerspectiveCamera, Ray, SRGBColorSpace, Vector3 } from "three";
12
12
  import { OrbitControls } from "./OrbitControls.js";
13
13
  import { RenderTexture } from "../engine/engine_texture.js";
14
14
 
src/engine-components/CameraUtils.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { OrbitControls } from "./OrbitControls.js";
2
2
  import { addNewComponent, getOrAddComponent } from "../engine/engine_components.js";
3
3
  import { Object3D } from "three";
4
- import { ICamera, IContext } from "../engine/engine_types.js";
4
+ import type { ICamera, IContext } from "../engine/engine_types.js";
5
5
  import { RGBAColor } from "./js-extensions/RGBAColor.js";
6
6
  import { ContextEvent, ContextRegistry } from "../engine/engine_context_registry.js";
7
7
  import { getCameraController } from "../engine/engine_camera.js";
src/engine-components/ui/Canvas.ts CHANGED
@@ -1,11 +1,11 @@
1
- import { onChange, updateRenderSettings as updateRenderSettingsRecursive } from "./Utils.js";
1
+ import { updateRenderSettings as updateRenderSettingsRecursive } from "./Utils.js";
2
2
  import { serializable } from "../../engine/engine_serialization_decorator.js";
3
3
  import { FrameEvent } from "../../engine/engine_setup.js";
4
4
  import { BaseUIComponent, UIRootComponent } from "./BaseUIComponent.js";
5
5
  import { GameObject } from "../Component.js";
6
6
  import { Matrix4, Object3D } from "three";
7
7
  import { RectTransform } from "./RectTransform.js";
8
- import { ICanvas, ICanvasEventReceiver, ILayoutGroup, IRectTransform } from "./Interfaces.js";
8
+ import type { ICanvas, ICanvasEventReceiver, ILayoutGroup, IRectTransform } from "./Interfaces.js";
9
9
  import { Camera } from "../Camera.js";
10
10
  import { EventSystem } from "./EventSystem.js";
11
11
  import * as ThreeMeshUI from 'three-mesh-ui'
src/engine-components/ui/CanvasGroup.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { Graphic } from "./Graphic.js";
2
2
  import { FrameEvent } from "../../engine/engine_setup.js";
3
3
  import { Behaviour, GameObject } from "../Component.js";
4
- import { ICanvasGroup, IHasAlphaFactor } from "./Interfaces.js";
4
+ import { type ICanvasGroup, type IHasAlphaFactor } from "./Interfaces.js";
5
5
  import { serializable } from "../../engine/engine_serialization_decorator.js";
6
6
  import { BaseUIComponent } from "./BaseUIComponent.js";
7
7
 
src/engine-components/postprocessing/Effects/ChromaticAberration.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { ChromaticAberrationEffect } from "postprocessing";
2
2
  import { Vector2 } from "three";
3
3
  import { serializable } from "../../../engine/engine_serialization.js";
4
- import { EffectProviderResult, PostProcessingEffect } from "../PostProcessingEffect.js";
4
+ import { type EffectProviderResult, PostProcessingEffect } from "../PostProcessingEffect.js";
5
5
  import { VolumeParameter } from "../VolumeParameter.js";
6
6
  import { registerCustomEffectType, VolumeProfile } from "../VolumeProfile.js";
7
7
 
src/engine-components/Collider.ts CHANGED
@@ -1,11 +1,11 @@
1
1
  import { Behaviour } from "./Component.js";
2
2
  import { Rigidbody } from "./RigidBody.js";
3
3
  import { serializable } from "../engine/engine_serialization_decorator.js";
4
- import { Event, Group, Mesh, Object3D, Vector3 } from "three"
4
+ import { Group, Mesh, Vector3 } from "three"
5
5
  // import { IColliderProvider, registerColliderProvider } from "../engine/engine_physics.js";
6
- import { IBoxCollider, ICollider, ISphereCollider } from "../engine/engine_types.js";
6
+ import type { IBoxCollider, ICollider, ISphereCollider } from "../engine/engine_types.js";
7
7
  import { getWorldScale } from "../engine/engine_three_utils.js";
8
- import { PhysicsMaterial } from "../engine/engine_physics.types.js";
8
+ import type { PhysicsMaterial } from "../engine/engine_physics.types.js";
9
9
  import { validate } from "../engine/engine_util_decorator.js";
10
10
  import { unwatchWrite, watchWrite } from "../engine/engine_utils.js";
11
11
 
src/engine-components/postprocessing/Effects/ColorAdjustments.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  import { BrightnessContrastEffect, HueSaturationEffect } from "postprocessing";
2
2
  import { serializable } from "../../../engine/engine_serialization.js";
3
- import { EffectProviderResult, PostProcessingEffect } from "../PostProcessingEffect.js";
3
+ import { type EffectProviderResult, PostProcessingEffect } from "../PostProcessingEffect.js";
4
4
  import { VolumeParameter } from "../VolumeParameter.js";
5
5
  import { registerCustomEffectType } from "../VolumeProfile.js";
6
- import { CustomToneMapping, LinearToneMapping, NoToneMapping } from "three";
6
+ import { LinearToneMapping, NoToneMapping } from "three";
7
7
 
8
8
 
9
9
  export class ColorAdjustments extends PostProcessingEffect {
src/engine-components/Component.ts CHANGED
@@ -4,7 +4,7 @@
4
4
  import { Context, FrameEvent } from "../engine/engine_setup.js";
5
5
  import * as main from "../engine/engine_mainloop_utils.js";
6
6
  import { syncDestroy, syncInstantiate } from "../engine/engine_networking_instantiate.js";
7
- import { ConstructorConcrete, SourceIdentifier, IComponent, IGameObject, Constructor, GuidsMap, Collision, ICollider } from "../engine/engine_types.js";
7
+ import type { ConstructorConcrete, SourceIdentifier, IComponent, IGameObject, Constructor, GuidsMap, Collision, ICollider } from "../engine/engine_types.js";
8
8
  import { addNewComponent, destroyComponentInstance, findObjectOfType, findObjectsOfType, getComponent, getComponentInChildren, getComponentInParent, getComponents, getComponentsInChildren, getComponentsInParent, getOrAddComponent, moveComponentInstance, removeComponent } from "../engine/engine_components.js";
9
9
  import { findByGuid, destroy, InstantiateOptions, instantiate, HideFlags, foreachComponent, markAsInstancedRendered, isActiveInHierarchy, isActiveSelf, isUsingInstancing, setActive, isDestroyed } from "../engine/engine_gameobject.js";
10
10
 
src/engine-components/export/usdz/extensions/DocumentExtension.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { IUSDExporterExtension } from "../Extension.js";
1
+ import type { IUSDExporterExtension } from "../Extension.js";
2
2
 
3
3
  export class DocumentExtension implements IUSDExporterExtension {
4
4
 
src/engine-components/DragControls.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { GameObject } from "./Component.js";
2
2
  import { SyncedTransform } from "./SyncedTransform.js";
3
- import { IPointerDownHandler, IPointerEnterHandler, IPointerEventHandler, IPointerExitHandler, IPointerUpHandler, PointerEventData } from "./ui/PointerEvents.js";
3
+ import type { IPointerDownHandler, IPointerEnterHandler, IPointerEventHandler, IPointerExitHandler, IPointerUpHandler, PointerEventData } from "./ui/PointerEvents.js";
4
4
  import { Context } from "../engine/engine_setup.js";
5
5
  import { Interactable, UsageMarker } from "./Interactable.js";
6
6
  import { Rigidbody } from "./RigidBody.js";
@@ -8,7 +8,7 @@
8
8
  import { Avatar_POI } from "./avatar/Avatar_Brain_LookAt.js";
9
9
  import { RaycastOptions } from "../engine/engine_physics.js";
10
10
  import { getWorldPosition, setWorldPosition } from "../engine/engine_three_utils.js";
11
- import { KeyCode } from "../engine/engine_input.js";
11
+ import type { KeyCode } from "../engine/engine_input.js";
12
12
  import { nameofFactory } from "../engine/engine_utils.js";
13
13
  import { InstancingUtil } from "../engine/engine_instancing.js";
14
14
  import { OrbitControls } from "./OrbitControls.js";
src/engine-components/DropListener.ts CHANGED
@@ -3,7 +3,7 @@
3
3
  import * as files from "../engine/engine_networking_files.js";
4
4
  import { serializable } from "../engine/engine_serialization_decorator.js";
5
5
  import { Networking } from "../engine-components/Networking.js";
6
- import { GLTF } from "three/examples/jsm/loaders/GLTFLoader.js";
6
+ import type { GLTF } from "three/examples/jsm/loaders/GLTFLoader.js";
7
7
  import { getParam } from "../engine/engine_utils.js";
8
8
 
9
9
  const debug = getParam("debugdroplistener");
src/engine/engine_addressables.ts CHANGED
@@ -6,9 +6,8 @@
6
6
  import { registerPrefabProvider, syncInstantiate } from "./engine_networking_instantiate.js";
7
7
  import { download } from "./engine_web_api.js";
8
8
  import { getLoader } from "./engine_gltf.js";
9
- import { IComponent, SourceIdentifier } from "./engine_types.js";
9
+ import type { IComponent, IGameObject, SourceIdentifier } from "./engine_types.js";
10
10
  import { destroy, instantiate, InstantiateOptions, isDestroyed } from "./engine_gameobject.js";
11
- import { IGameObject } from "./engine_types.js";
12
11
 
13
12
  const debug = getParam("debugaddressables");
14
13
 
src/engine/engine_camera.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { ICameraController } from "./engine_types.js";
1
+ import type { ICameraController } from "./engine_types.js";
2
2
  import { Camera } from "three";
3
3
 
4
4
 
src/engine/engine_components_internal.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { IComponent } from "./engine_types.js";
1
+ import { type IComponent } from "./engine_types.js";
2
2
  import { getParam } from "./engine_utils.js";
3
3
 
4
4
  export enum ComponentEvents {
src/engine/engine_components.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Object3D, Scene } from "three";
2
- import { Constructor, ConstructorConcrete, IComponent as Component, IComponent, IGameObject } from "./engine_types.js";
2
+ import type { Constructor, ConstructorConcrete, IComponent, IGameObject } from "./engine_types.js";
3
3
  import { Context, registerComponent } from "./engine_setup.js";
4
4
  import { getParam } from "./engine_utils.js";
5
5
  import { removeScriptFromContext, updateActiveInHierarchyWithoutEventCall } from "./engine_mainloop_utils.js";
src/engine/engine_context_registry.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { IComponent, IContext, LoadedGLTF } from "./engine_types.js";
1
+ import { type IComponent, type IContext, type LoadedGLTF } from "./engine_types.js";
2
2
 
3
3
  export enum ContextEvent {
4
4
  /** called when the context is registered to the registry, the context is not fully initialized at this point */
src/engine/engine_context.ts CHANGED
@@ -2,7 +2,7 @@
2
2
  BufferGeometry, Cache, Camera, Clock, Color, DepthTexture, Group,
3
3
  Material, NearestFilter, NoToneMapping, Object3D, PCFSoftShadowMap,
4
4
  PerspectiveCamera, RGBAFormat, Scene, SRGBColorSpace,
5
- Texture, WebGLRenderer, WebGLRendererParameters, WebGLRenderTarget, WebXRArrayCamera
5
+ Texture, WebGLRenderer, type WebGLRendererParameters, WebGLRenderTarget, type WebXRArrayCamera
6
6
  } from 'three'
7
7
  import { Input } from './engine_input.js';
8
8
  import { Physics } from './engine_physics.js';
@@ -22,10 +22,10 @@
22
22
  import { RendererData as SceneLighting } from './engine_scenelighting.js';
23
23
  import { Addressables } from './engine_addressables.js';
24
24
  import { Application } from './engine_application.js';
25
- import { LightDataRegistry, ILightDataRegistry } from './engine_lightdata.js';
25
+ import { LightDataRegistry, type ILightDataRegistry } from './engine_lightdata.js';
26
26
  import { PlayerViewManager } from './engine_playerview.js';
27
27
 
28
- import { CoroutineData, GLTF, ICamera, IComponent, IContext, ILight, LoadedGLTF } from "./engine_types.js"
28
+ import { type CoroutineData, type GLTF, type ICamera, type IComponent, type IContext, type ILight, type LoadedGLTF } from "./engine_types.js"
29
29
  import { destroy, foreachComponent } from './engine_gameobject.js';
30
30
  import { ContextEvent, ContextRegistry } from './engine_context_registry.js';
31
31
  import { delay, getParam } from './engine_utils.js';
src/engine/engine_element.ts CHANGED
@@ -1,12 +1,12 @@
1
1
  import { Context, ContextCreateArgs, LoadingProgressArgs } from "./engine_setup.js";
2
2
  import { AROverlayHandler, arContainerClassName } from "./engine_element_overlay.js";
3
3
  import { GameObject } from "../engine-components/Component.js";
4
- import { calculateProgress01, EngineLoadingView, ILoadingViewHandler } from "./engine_element_loading.js";
4
+ import { calculateProgress01, EngineLoadingView, type ILoadingViewHandler } from "./engine_element_loading.js";
5
5
  import { getParam } from "./engine_utils.js";
6
6
  import { setDracoDecoderPath, setDracoDecoderType, setKtx2TranscoderPath } from "./engine_loaders.js";
7
7
  import { getLoader, registerLoader } from "../engine/engine_gltf.js";
8
8
  import { NeedleGltfLoader } from "./engine_scenetools.js";
9
- import { INeedleEngineComponent, LoadedGLTF } from "./engine_types.js";
9
+ import { type INeedleEngineComponent, type LoadedGLTF } from "./engine_types.js";
10
10
  import { isDevEnvironment, showBalloonWarning } from "./debug/index.js";
11
11
  import { hasCommercialLicense } from "./engine_license.js";
12
12
  import { VERSION } from "./engine_constants.js";
src/engine/engine_gameobject.ts CHANGED
@@ -3,7 +3,7 @@
3
3
  import { InstantiateIdProvider } from "./engine_networking_instantiate.js";
4
4
  import { Context, registerComponent } from "./engine_setup.js";
5
5
  import { logHierarchy, setWorldPosition, setWorldQuaternion } from "./engine_three_utils.js";
6
- import { GuidsMap, IComponent as Component, IComponent, IGameObject as GameObject, UIDProvider, Constructor } from "./engine_types.js";
6
+ import { type GuidsMap, type IComponent as Component, type IComponent, type IGameObject as GameObject, type UIDProvider, type Constructor } from "./engine_types.js";
7
7
  import { getParam, tryFindObject } from "./engine_utils.js";
8
8
  import { apply } from "../engine-components/js-extensions/Object3D.js";
9
9
  import { $isUsingInstancing, InstancingUtil } from "./engine_instancing.js";
src/engine/engine_gizmos.ts CHANGED
@@ -1,7 +1,7 @@
1
- import { BufferAttribute, Line, BoxGeometry, EdgesGeometry, Color, LineSegments, LineBasicMaterial, Object3D, Mesh, SphereGeometry, ColorRepresentation, Vector3, Box3, Quaternion, CylinderGeometry } from 'three';
1
+ import { BufferAttribute, Line, BoxGeometry, EdgesGeometry, Color, LineSegments, LineBasicMaterial, Object3D, Mesh, SphereGeometry, type ColorRepresentation, Vector3, Box3, Quaternion, CylinderGeometry } from 'three';
2
2
  import { Context } from './engine_setup.js';
3
3
  import { setWorldPositionXYZ } from './engine_three_utils.js';
4
- import { Vec3, Vec4 } from './engine_types.js';
4
+ import type { Vec3, Vec4 } from './engine_types.js';
5
5
 
6
6
  const _tmp = new Vector3();
7
7
  const _tmp2 = new Vector3();
src/engine/engine_gltf_builtin_components.ts CHANGED
@@ -3,12 +3,11 @@
3
3
  import { InstantiateIdProvider } from "./engine_networking_instantiate.js"
4
4
  import { Context } from "./engine_setup.js";
5
5
  import { deserializeObject, serializeObject } from "./engine_serialization.js";
6
- import { assign, ImplementationInformation, ISerializable, SerializationContext } from "./engine_serialization_core.js";
6
+ import { assign, ImplementationInformation, type ISerializable, SerializationContext } from "./engine_serialization_core.js";
7
7
  import { NEEDLE_components } from "./extensions/NEEDLE_components.js";
8
8
  import { debugExtension } from "./engine_default_parameters.js";
9
9
  import { editorGuidKeyName, builtinComponentKeyName } from "./engine_constants.js";
10
- import { GuidsMap, ICamera, IComponent, IGameObject, SourceIdentifier } from "./engine_types.js";
11
- import { UIDProvider } from "./engine_types.js";
10
+ import type { GuidsMap, ICamera, IComponent, IGameObject, SourceIdentifier, UIDProvider } from "./engine_types.js";
12
11
  import { addNewComponent } from "./engine_components.js";
13
12
  import { getParam } from "./engine_utils.js";
14
13
  import { LogType, showBalloonMessage } from "./debug/index.js";
src/engine/engine_gltf.ts CHANGED
@@ -1,8 +1,8 @@
1
- import { Constructor, ConstructorConcrete, SourceIdentifier, UIDProvider } from "./engine_types.js";
1
+ import type { ConstructorConcrete, SourceIdentifier, UIDProvider } from "./engine_types.js";
2
2
  import { Context } from "./engine_setup.js";
3
3
  import { NEEDLE_components } from "./extensions/NEEDLE_components.js";
4
4
  import { SerializationContext } from "./engine_serialization_core.js";
5
- import { GLTF } from 'three/examples/jsm/loaders/GLTFLoader.js'
5
+ import type { GLTF } from 'three/examples/jsm/loaders/GLTFLoader.js'
6
6
 
7
7
 
8
8
  export interface INeedleGltfLoader {
src/engine/engine_hot_reload.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { IComponent } from "./engine_types.js";
1
+ import type { IComponent } from "./engine_types.js";
2
2
  import { TypeStore } from "./engine_typestore.js";
3
3
  import { addScriptToArrays, removeScriptFromContext } from "./engine_mainloop_utils.js"
4
4
  import { getParam } from "./engine_utils.js";
src/engine/engine_input.ts CHANGED
@@ -1,8 +1,7 @@
1
1
  import { Vector2 } from 'three';
2
2
  import { showBalloonMessage, showBalloonWarning } from './debug/debug.js';
3
- import { assign } from './engine_serialization_core.js';
4
3
  import { Context } from './engine_setup.js';
5
- import { IInput, Vec2 } from './engine_types.js';
4
+ import type { IInput, Vec2 } from './engine_types.js';
6
5
  import { getParam } from './engine_utils.js';
7
6
 
8
7
  const debug = getParam("debuginput");
@@ -646,10 +645,13 @@
646
645
  let dx = evt.clientX - lf.x;
647
646
  let dy = evt.clientY - lf.y;
648
647
  // if pointer is locked, clientX and Y are not changed, but Movement is.
649
- if(dx === 0 && evt.movementX !== 0)
650
- dx = evt.movementX || 0;
651
- if(dy === 0 && evt.movementY !== 0)
652
- dy = evt.movementY || 0;
648
+ if(evt.source instanceof MouseEvent || evt.source instanceof TouchEvent) {
649
+ const source = evt.source as PointerEvent;
650
+ if(dx === 0 && source.movementX !== 0)
651
+ dx = source.movementX || 0;
652
+ if(dy === 0 && source.movementY !== 0)
653
+ dy = source.movementY || 0;
654
+ }
653
655
  delta.x += dx;
654
656
  delta.y += dy;
655
657
 
src/engine/engine_license.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { getParam, isMobileDevice } from "./engine_utils.js";
2
2
  import { ContextEvent, ContextRegistry } from "./engine_context_registry.js";
3
- import { IContext } from "./engine_types.js";
3
+ import type { IContext } from "./engine_types.js";
4
4
  import { logoSVG } from "./assets/index.js";
5
5
  import { GENERATOR, VERSION } from "./engine_constants.js";
6
6
 
src/engine/engine_lightdata.ts CHANGED
@@ -2,7 +2,7 @@
2
2
  import { Texture, ShaderChunk, UniformsLib, Vector4 } from "three";
3
3
  import { Context } from "./engine_setup.js";
4
4
  import { getParam } from "./engine_utils.js";
5
- import { SourceIdentifier } from "./engine_types.js";
5
+ import type { SourceIdentifier } from "./engine_types.js";
6
6
 
7
7
  const debugLightmap = getParam("debuglightmaps") ? true : false;
8
8
 
src/engine/engine_mainloop_utils.ts CHANGED
@@ -2,10 +2,10 @@
2
2
  import * as constants from "./engine_constants.js";
3
3
  import { getParam } from './engine_utils.js';
4
4
  import { CubeCamera, Object3D, Scene, WebGLCubeRenderTarget } from 'three';
5
- import { IComponent, IContext } from './engine_types.js';
5
+ import type { IComponent, IContext } from './engine_types.js';
6
6
  import { isActiveSelf } from './engine_gameobject.js';
7
7
  import { ContextRegistry } from "./engine_context_registry.js";
8
- import { showBalloonWarning, isDevEnvironment, showBalloonMessage, LogType } from "./debug/index.js";
8
+ import { isDevEnvironment } from "./debug/index.js";
9
9
 
10
10
  const debug = getParam("debugnewscripts");
11
11
  const debugHierarchy = getParam("debughierarchy");
src/engine/engine_math.ts CHANGED
@@ -1,8 +1,5 @@
1
- import { Vector } from "three";
2
- import { inverseLerp } from "three/src/math/MathUtils.js";
1
+ import type { Vector } from "three";
3
2
 
4
-
5
-
6
3
  class MathHelper {
7
4
 
8
5
  random(): number {
src/engine/engine_networking_auto.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { getParam } from "./engine_utils.js";
2
2
  import { isDevEnvironment } from "./debug/index.js";
3
- import { IComponent } from "./engine_types.js";
3
+ import type { IComponent } from "./engine_types.js";
4
4
 
5
5
  const debug = getParam("debugautosync");
6
6
 
src/engine/engine_networking_files_default_components.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  // import { SyncedTransform } from "../engine-components/SyncedTransform.js";
2
2
  // import { DragControls } from "../engine-components/DragControls.js"
3
3
  // import { ObjectRaycaster } from "../engine-components/ui/Raycaster.js";
4
- import { UIDProvider } from "./engine_types.js";
5
- import { GLTF } from "three/examples/jsm/loaders/GLTFLoader.js";
4
+ import type { UIDProvider } from "./engine_types.js";
5
+ import type { GLTF } from "three/examples/jsm/loaders/GLTFLoader.js";
6
6
  // import { Animation } from "../engine-components/Animation.js";
7
7
 
8
8
 
src/engine/engine_networking_files.ts CHANGED
@@ -3,10 +3,10 @@
3
3
  import { NetworkConnection } from "../engine/engine_networking.js";
4
4
  import { generateSeed, InstantiateIdProvider } from "../engine/engine_networking_instantiate.js";
5
5
  import * as def from "./engine_networking_files_default_components.js"
6
- import { GLTF } from 'three/examples/jsm/loaders/GLTFLoader.js'
6
+ import type { GLTF } from 'three/examples/jsm/loaders/GLTFLoader.js'
7
7
  import { getLoader } from "../engine/engine_gltf.js";
8
- import { IModel } from "./engine_networking_types.js";
9
- import { IGameObject } from "./engine_types.js";
8
+ import type { IModel } from "./engine_networking_types.js";
9
+ import type { IGameObject } from "./engine_types.js";
10
10
  import { findByGuid } from "./engine_gameobject.js";
11
11
  import { ContextEvent, ContextRegistry } from "./engine_context_registry.js";
12
12
  import { BoxGeometry, BoxHelper, Mesh, MeshBasicMaterial, Object3D, Vector3 } from "three";
src/engine/engine_networking_instantiate.ts CHANGED
@@ -2,14 +2,14 @@
2
2
  import * as THREE from "three";
3
3
  import { Context } from "./engine_setup.js"
4
4
  import * as utils from "./engine_utils.js"
5
- import { INetworkConnection } from "./engine_networking_types.js";
6
- import { IGameObject as GameObject, IComponent as Component } from "./engine_types.js"
5
+ import type { INetworkConnection } from "./engine_networking_types.js";
6
+ import type { IGameObject as GameObject, IComponent as Component } from "./engine_types.js"
7
7
 
8
8
  // https://github.com/uuidjs/uuid
9
9
  // v5 takes string and namespace
10
10
  import { v5 } from 'uuid';
11
- import { UIDProvider } from "./engine_types.js";
12
- import { IModel } from "./engine_networking_types.js";
11
+ import type { UIDProvider } from "./engine_types.js";
12
+ import type { IModel } from "./engine_networking_types.js";
13
13
  import { SendQueue } from "./engine_networking_types.js";
14
14
  import { destroy, findByGuid, instantiate } from "./engine_gameobject.js";
15
15
  import { Object3D } from "three";
src/engine/engine_networking_peer.ts CHANGED
@@ -1,6 +1,6 @@
1
- import Peer, { PeerConnectOption } from "peerjs";
2
- import { type DataConnection, type PeerJSOption } from "peerjs";
3
- import { ConstructorConcrete } from "./engine_types.js";
1
+ import Peer, { type PeerConnectOption } from "peerjs";
2
+ import type { DataConnection, PeerJSOption } from "peerjs";
3
+ import { type ConstructorConcrete } from "./engine_types.js";
4
4
 
5
5
  let peerOptions: PeerJSOption | undefined = undefined;
6
6
 
src/engine/engine_networking.ts CHANGED
@@ -8,7 +8,7 @@
8
8
  import * as flatbuffers from 'flatbuffers';
9
9
  import * as schemes from "../engine-schemes/schemes.js";
10
10
  import { PeerNetworking } from './engine_networking_peer.js';
11
- import { IModel, INetworkConnection, SendQueue } from './engine_networking_types.js';
11
+ import { type IModel, type INetworkConnection, SendQueue } from './engine_networking_types.js';
12
12
  import { isHostedOnGlitch } from './engine_networking_utils.js';
13
13
 
14
14
  export const debugNet = utils.getParam("debugnet") ? true : false;
@@ -481,6 +481,7 @@
481
481
 
482
482
  console.log("⊡ Connecting to networking backend on\n" + serverUrl)
483
483
  const pkg = await import('websocket-ts');
484
+ // @ts-ignore
484
485
  const WebsocketBuilder = pkg.default?.WebsocketBuilder ?? pkg.WebsocketBuilder;
485
486
  const ws = new WebsocketBuilder(serverUrl)
486
487
  .onOpen(() => {
@@ -580,11 +581,18 @@
580
581
  this._currentRoomName = model.room;
581
582
  this._currentRoomViewId = model.viewId;
582
583
  this._currentRoomAllowEditing = model.allowEditing ?? true;
583
- console.log("Room view id", this._currentRoomViewId);
584
+
584
585
  this._currentInRoom.length = 0;
585
586
  this._currentInRoom.push(...model.inRoom);
586
587
  if (debugNet)
587
588
  console.log("joined room with", this._currentInRoom, this.context.alias ?? "");
589
+
590
+ const viewUrl = new URL(window.location.href);
591
+ if (viewUrl.searchParams.has("room")) {
592
+ viewUrl.searchParams.delete("room");
593
+ }
594
+ viewUrl.searchParams.set("view", this._currentRoomViewId);
595
+ console.log("Room view id: " + this._currentRoomViewId + "\n" + viewUrl.href);
588
596
  }
589
597
 
590
598
  this.onSendQueued(SendQueue.OnRoomJoin);
src/engine/engine_physics_rapier.ts CHANGED
@@ -2,13 +2,11 @@
2
2
  import * as BufferGeometryUtils from 'three/examples/jsm/utils/BufferGeometryUtils.js'
3
3
  import { CircularBuffer, getParam } from "./engine_utils.js"
4
4
  import { getWorldPosition, getWorldQuaternion, getWorldScale, setWorldPositionXYZ, setWorldQuaternionXYZW } from "./engine_three_utils.js"
5
- import {
5
+ import type {
6
6
  IPhysicsEngine,
7
7
  IComponent,
8
8
  ICollider,
9
9
  IRigidbody,
10
- Collision,
11
- ContactPoint,
12
10
  Vec3,
13
11
  IGameObject,
14
12
  Vec2,
@@ -16,6 +14,7 @@
16
14
  ISphereCollider,
17
15
  IBoxCollider,
18
16
  } from './engine_types.js';
17
+ import { ContactPoint, Collision } from './engine_types.js';
19
18
  import { foreachComponent } from './engine_gameobject.js';
20
19
 
21
20
  import { ActiveCollisionTypes, ActiveEvents, CoefficientCombineRule, Ball, Collider, ColliderDesc, EventQueue, JointData, QueryFilterFlags, RigidBody, RigidBodyType, ShapeColliderTOI, World, Ray, ShapeType, Cuboid } from '@dimforge/rapier3d-compat';
@@ -593,7 +592,7 @@
593
592
  positions = this._meshCache.get(key)!;
594
593
  }
595
594
  else {
596
- console.warn("Your model is using scaled mesh colliders which is not optimal for performance", mesh.name, Object.assign({}, scale));
595
+ console.warn(`Your MeshCollider \"${collider.name}\" is scaled\nthis is not optimal for performance since this isn't supported by the Rapier physics engine yet. Consider applying the scale to the collider mesh`);
597
596
  // showBalloonWarning("Your model is using scaled mesh colliders which is not optimal for performance: " + mesh.name + ", consider using unscaled objects");
598
597
  const scaledPositions = new Float32Array(positions.length);
599
598
  for (let i = 0; i < positions.length; i += 3) {
@@ -758,6 +757,7 @@
758
757
 
759
758
  private internalUpdateColliderProperties(col: ICollider, collider: Collider) {
760
759
  const shape = collider.shape;
760
+ let sizeHasChanged = false;
761
761
  switch (shape.type) {
762
762
  // Sphere Collider
763
763
  case ShapeType.Ball:
@@ -767,21 +767,36 @@
767
767
  const obj = col.gameObject;
768
768
  const scale = getWorldScale(obj, this._tempPosition);
769
769
  const radius = Math.abs(sc.radius * scale.x);
770
- const changed = ball.radius !== radius;
770
+ sizeHasChanged = ball.radius !== radius;
771
771
  ball.radius = radius;
772
- if (changed)
772
+ if (sizeHasChanged) {
773
773
  collider.setShape(ball);
774
+ }
774
775
  break;
775
776
  }
776
777
  case ShapeType.Cuboid:
777
778
  const cuboid = shape as Cuboid;
778
779
  const sc = col as IBoxCollider;
779
- cuboid.halfExtents.x = sc.size.x * 0.5;
780
- cuboid.halfExtents.y = sc.size.y * 0.5;
781
- cuboid.halfExtents.z = sc.size.z * 0.5;
782
- collider.setShape(cuboid);
780
+ const newX = sc.size.x * 0.5;
781
+ const newY = sc.size.y * 0.5;
782
+ const newZ = sc.size.z * 0.5;
783
+ sizeHasChanged = cuboid.halfExtents.x !== newX || cuboid.halfExtents.y !== newY || cuboid.halfExtents.z !== newZ;
784
+ cuboid.halfExtents.x = newX;
785
+ cuboid.halfExtents.y = newY;
786
+ cuboid.halfExtents.z = newZ;
787
+ if (sizeHasChanged) {
788
+ collider.setShape(cuboid);
789
+ }
783
790
  break;
784
791
  }
792
+
793
+ if (sizeHasChanged) {
794
+ const rb = col.attachedRigidbody;
795
+ if (rb?.autoMass) {
796
+ const ph = this.getBody(rb) as RigidBody
797
+ ph?.recomputeMassPropertiesFromColliders();
798
+ }
799
+ }
785
800
  }
786
801
 
787
802
  private internalUpdateRigidbodyProperties(rb: IRigidbody, rigidbody: RigidBody) {
src/engine/engine_physics.ts CHANGED
@@ -1,9 +1,9 @@
1
- import { Box3, Camera, Intersection, Layers, Mesh, Object3D, Ray, Raycaster, Sphere, Vector2, Vector3 } from 'three'
1
+ import { Box3, Camera, type Intersection, Layers, Mesh, Object3D, Ray, Raycaster, Sphere, Vector2, Vector3 } from 'three'
2
2
  import { Context } from './engine_setup.js';
3
3
  import { getParam } from "./engine_utils.js"
4
4
  import { getWorldPosition } from "./engine_three_utils.js"
5
- import { Vec2, Vec3, } from './engine_types.js';
6
- import { IPhysicsEngine } from './engine_types.js';
5
+ import type { Vec2, Vec3, } from './engine_types.js';
6
+ import type { IPhysicsEngine } from './engine_types.js';
7
7
 
8
8
  const debugPhysics = getParam("debugphysics");
9
9
  const layerMaskHelper: Layers = new Layers();
src/engine/engine_scenelighting.ts CHANGED
@@ -4,7 +4,7 @@
4
4
  import { SceneLightSettings } from "./extensions/NEEDLE_lighting_settings.js";
5
5
  import { createFlatTexture, createTrilightTexture } from "./engine_shaders.js";
6
6
  import { getParam } from "./engine_utils.js";
7
- import { SourceIdentifier } from "./engine_types.js";
7
+ import { type SourceIdentifier } from "./engine_types.js";
8
8
  import { AssetReference } from "./engine_addressables.js";
9
9
 
10
10
  const debug = getParam("debugenvlight");
src/engine/engine_scenetools.ts CHANGED
@@ -1,11 +1,11 @@
1
1
  import { Context } from "./engine_setup.js"
2
- import { GLTF, GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'
2
+ import { type GLTF, GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader.js'
3
3
  // import * as object from "./engine_gltf_builtin_components.js";
4
4
  import * as loaders from "./engine_loaders.js"
5
5
  import * as utils from "./engine_utils.js";
6
6
  import { registerComponentExtension, registerExtensions } from "./extensions/extensions.js";
7
- import { getLoader, INeedleGltfLoader, registerLoader } from "./engine_gltf.js";
8
- import { SourceIdentifier, UIDProvider } from "./engine_types.js";
7
+ import { getLoader, type INeedleGltfLoader, registerLoader } from "./engine_gltf.js";
8
+ import { type SourceIdentifier, type UIDProvider } from "./engine_types.js";
9
9
  import { createBuiltinComponents, writeBuiltinComponentData } from "./engine_gltf_builtin_components.js";
10
10
  import { SerializationContext } from "./engine_serialization_core.js";
11
11
  import { NEEDLE_components } from "./extensions/NEEDLE_components.js";
src/engine/engine_serialization_builtin_serializer.ts CHANGED
@@ -8,6 +8,7 @@
8
8
  import { RenderTexture } from "./engine_texture.js";
9
9
  import { isDevEnvironment, showBalloonMessage, showBalloonWarning } from "../engine/debug/index.js";
10
10
  import { resolveUrl } from "./engine_utils.js";
11
+ import { AssetReference } from "./engine_addressables.js";
11
12
 
12
13
  // export class SourcePath {
13
14
  // src?:string
@@ -75,9 +76,14 @@
75
76
 
76
77
  if (typeof data === "string") {
77
78
  if (data.endsWith(".glb") || data.endsWith(".gltf")) {
79
+ // If the @serializable([Object3D, AssetReference]) looks like this we don't need to warn here. This is the case e.g. with SyncedCamera referencing a scene
80
+ if (context.serializable instanceof Array) {
81
+ if (context.serializable.includes(AssetReference)) return undefined;
82
+ }
78
83
  if (isDevEnvironment())
79
84
  showBalloonWarning("Detected wrong usage of @serializable with Object3D or GameObject. Instead you should use AssetReference here! Please see the console for details.");
80
- console.warn("Wrong usage of @serializable detected:\n\nIt looks like you used @serializable(Object3D) or @serializable(GameObject) for a prefab or scene reference named \"" + context.path + "\" in your script \"" + context.target?.constructor?.name + "\". \nTo fix this replace it with @serializable(AssetReference). Make sure to replace the type with AssetReference too.\n\nIt should then look something like this:\n\n@serializable(AssetReference)\n" + context.path + "! : AssetReference;\n\0");
85
+ const scriptname = context.target?.constructor?.name;
86
+ console.warn(`Wrong usage of @serializable detected in your script \"${scriptname}\"\n\nIt looks like you used @serializable(Object3D) or @serializable(GameObject) for a prefab or scene reference which is exported to a separate glTF file.\n\nTo fix this please change your code to:\n\n@serializable(AssetReference)\n${context.path}! : AssetReference;\n\0`);
81
87
  }
82
88
  // ACTUALLY: this is already handled by the extension_utils where we resolve json pointers recursively
83
89
  // if(data.startsWith("/nodes/")){
src/engine/engine_serialization_core.ts CHANGED
@@ -1,9 +1,9 @@
1
- import { GLTF } from "three/examples/jsm/loaders/GLTFLoader.js";
1
+ import { type GLTF } from "three/examples/jsm/loaders/GLTFLoader.js";
2
2
  import { getParam } from "./engine_utils.js";
3
3
  import { AnimationClip, Material, Mesh, Object3D, Texture } from "three";
4
4
  import { Context } from "./engine_setup.js";
5
5
  import { isPersistentAsset } from "./extensions/NEEDLE_persistent_assets.js";
6
- import { ConstructorConcrete, SourceIdentifier } from "./engine_types.js";
6
+ import { type ConstructorConcrete, type SourceIdentifier } from "./engine_types.js";
7
7
  import { debugExtension } from "../engine/engine_default_parameters.js";
8
8
  import { LogType, addLog } from "./debug/debug_overlay.js";
9
9
  import { isLocalNetwork } from "./engine_networking_utils.js";
@@ -182,6 +182,8 @@
182
182
  context?: Context;
183
183
  path?: string;
184
184
  type?: ConstructorConcrete<any>;
185
+ /** the serializable attribute for this field (target.path) */
186
+ serializable?: any;
185
187
  /** holds information if a field was undefined before serialization. This gives us info if we might want to warn the user about missing attributes */
186
188
  implementationInformation?: ImplementationInformation;
187
189
 
@@ -289,6 +291,7 @@
289
291
 
290
292
  context.type = undefined;
291
293
  context.path = key;
294
+ context.serializable = serializedEntryInfo
292
295
 
293
296
  if (obj.onBeforeDeserializeMember !== undefined) {
294
297
  // callback to the instance, if it returns true assume it's done all the things itself
src/engine/engine_serialization_decorator.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Constructor } from "./engine_types.js";
1
+ import { type Constructor } from "./engine_types.js";
2
2
 
3
3
  export declare type TypeResolver<T> = (data) => Constructor<T> | null;
4
4
 
src/engine/engine_shaders.ts CHANGED
@@ -1,7 +1,7 @@
1
1
 
2
2
  import * as loader from "./engine_fileloader.js"
3
3
  import * as SHADERDATA from "./shaders/shaderData.js"
4
- import { Vector4, FileLoader, DataTexture, RGBAFormat, Color, TextureDataType } from "three";
4
+ import { Vector4, FileLoader, DataTexture, RGBAFormat, Color } from "three";
5
5
  import { RGBAColor } from "../engine-components/js-extensions/RGBAColor.js";
6
6
  import { Mathf } from "./engine_math.js";
7
7
 
src/engine/engine_time.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Clock } from 'three'
2
2
  import { getParam } from './engine_utils.js';
3
- import { ITime } from './engine_types.js';
3
+ import { type ITime } from './engine_types.js';
4
4
 
5
5
  const timescaleUrl = getParam("timescale");
6
6
  let timeScale = 1;
src/engine/engine_types.ts CHANGED
@@ -1,9 +1,10 @@
1
1
  import { RenderTexture } from "./engine_texture.js";
2
- import { Camera, Color, Material, Object3D, Vector3, Quaternion, Ray, Scene, Renderer, WebGLRenderer, Mesh, AnimationClip } from "three";
2
+ import type { Camera, Color, Material, Object3D, Quaternion, Ray, Scene, WebGLRenderer, Mesh } from "three";
3
+ import { Vector3 } from "three";
3
4
  import { RGBAColor } from "../engine-components/js-extensions/RGBAColor.js";
4
- import { CollisionDetectionMode, PhysicsMaterial, RigidbodyConstraints } from "./engine_physics.types.js";
5
+ import { CollisionDetectionMode, type PhysicsMaterial, RigidbodyConstraints } from "./engine_physics.types.js";
5
6
  import { CircularBuffer } from "./engine_utils.js";
6
- import { GLTF as GLTF3 } from "three/examples/jsm/loaders/GLTFLoader.js";
7
+ import { type GLTF as GLTF3 } from "three/examples/jsm/loaders/GLTFLoader.js";
7
8
 
8
9
  export type GLTF = GLTF3 & {
9
10
  // asset: { generator: string, version: string }
src/engine/engine_util_decorator.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import { $isAssigningProperties } from "./engine_serialization_core.js";
2
2
  import { LogType, isDevEnvironment, showBalloonMessage } from "./debug/index.js";
3
- import { Constructor, IComponent } from "./engine_types.js";
3
+ import { type Constructor, type IComponent } from "./engine_types.js";
4
4
  import { Quaternion, Vector2, Vector3, Vector4 } from "three";
5
- import { Watch, unwatchWrite, watchWrite } from "./engine_utils.js";
5
+ import { watchWrite } from "./engine_utils.js";
6
6
 
7
7
 
8
8
  declare type setter = (v: any) => void;
src/engine/engine_utils.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  // use for typesafe interface method calls
2
- import { Quaternion, Vector, Vector2, Vector3, Vector4 } from "three";
3
- import { SourceIdentifier } from "./engine_types.js";
2
+ import { Quaternion, type Vector, Vector2, Vector3, Vector4 } from "three";
3
+ import { type SourceIdentifier } from "./engine_types.js";
4
4
 
5
5
  // https://schneidenbach.gitbooks.io/typescript-cookbook/content/nameof-operator.html
6
6
  export const nameofFactory = <T>() => (name: keyof T) => name;
@@ -458,6 +458,20 @@
458
458
  return navigator.userAgent.includes("OculusBrowser");
459
459
  }
460
460
 
461
+ export async function microphonePermissionsGranted() {
462
+ try {
463
+ //@ts-ignore
464
+ const res = await navigator.permissions.query({ name: 'microphone' });
465
+ if (res.state === "denied") {
466
+ return false;
467
+ }
468
+ return true;
469
+ }
470
+ catch (err) {
471
+ console.error("Error querying `microphone` permissions.", err);
472
+ return false;
473
+ }
474
+ }
461
475
 
462
476
 
463
477
  const cloudflareIPRegex = /ip=(?<ip>.+?)\n/s;
src/engine-components/ui/EventSystem.ts CHANGED
@@ -4,16 +4,15 @@
4
4
  import { ControllerEvents, WebXRController } from "../webxr/WebXRController.js";
5
5
  import * as ThreeMeshUI from 'three-mesh-ui'
6
6
  import { Context } from "../../engine/engine_setup.js";
7
- import { OrbitControls } from "../OrbitControls.js";
8
- import { IPointerEventHandler, PointerEventData } from "./PointerEvents.js";
7
+ import { type IPointerEventHandler, PointerEventData } from "./PointerEvents.js";
9
8
  import { ObjectRaycaster, Raycaster } from "./Raycaster.js";
10
9
  import { InputEvents, NEPointerEvent, PointerType } from "../../engine/engine_input.js";
11
10
  import { Object3D } from "three";
12
- import { ICanvasGroup, IGraphic } from "./Interfaces.js";
11
+ import type { ICanvasGroup } from "./Interfaces.js";
13
12
  import { getParam } from "../../engine/engine_utils.js";
14
13
  import { UIRaycastUtils } from "./RaycastUtils.js";
15
14
  import { $shadowDomOwner } from "./BaseUIComponent.js";
16
- import { isDevEnvironment, showBalloonMessage, showBalloonWarning } from "../../engine/debug/index.js";
15
+ import { isDevEnvironment, showBalloonMessage } from "../../engine/debug/index.js";
17
16
  import { Mathf } from "../../engine/engine_math.js";
18
17
 
19
18
  const debug = getParam("debugeventsystem");
src/engine-components/EventTrigger.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { serializable } from "../engine/engine_serialization.js";
2
2
  import { EventList } from "./EventList.js";
3
- import { IPointerEventHandler, PointerEventData } from "./ui/PointerEvents.js"
3
+ import type { IPointerEventHandler, PointerEventData } from "./ui/PointerEvents.js"
4
4
  import { Behaviour } from "./Component.js"
5
5
  import { EventType } from "./EventType.js"
6
6
 
src/engine/extensions/EXT_texture_exr.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { getParam } from "../engine_utils.js";
2
2
  import { EXRLoader } from "three/examples/jsm/loaders/EXRLoader.js";
3
3
  import { Texture } from "three";
4
- import { GLTFLoaderPlugin, GLTFParser } from "three/examples/jsm/loaders/GLTFLoader.js";
4
+ import { type GLTFLoaderPlugin, GLTFParser } from "three/examples/jsm/loaders/GLTFLoader.js";
5
5
 
6
6
 
7
7
  const debug = getParam("debugexr");
src/engine/extensions/extension_utils.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { IExtensionReferenceResolver } from "./extension_resolver.js";
1
+ import { type IExtensionReferenceResolver } from "./extension_resolver.js";
2
2
  import { GLTFParser } from "three/examples/jsm/loaders/GLTFLoader.js";
3
3
  import { debugExtension } from "../engine_default_parameters.js";
4
4
  import { getParam } from "../engine_utils.js";
src/engine/extensions/extensions.ts CHANGED
@@ -8,14 +8,14 @@
8
8
  import { NEEDLE_persistent_assets } from "./NEEDLE_persistent_assets.js";
9
9
  // import { KHR_animation_pointer } from "./KHR_animation_pointer.js";
10
10
  import { NEEDLE_lightmaps } from "../extensions/NEEDLE_lightmaps.js";
11
- import { Constructor, ConstructorConcrete, SourceIdentifier } from "../engine_types.js";
11
+ import { type ConstructorConcrete, type SourceIdentifier } from "../engine_types.js";
12
12
  import { Context } from "../engine_setup.js";
13
13
  import { NEEDLE_lighting_settings } from "./NEEDLE_lighting_settings.js";
14
14
  import { NEEDLE_render_objects } from "./NEEDLE_render_objects.js";
15
15
  import { NEEDLE_progressive } from "./NEEDLE_progressive.js";
16
16
  import { InternalUsageTrackerPlugin } from "./usage_tracker.js";
17
17
  import { isResourceTrackingEnabled } from "../engine_assetdatabase.js";
18
- import { GLTFLoaderPlugin } from "three/examples/jsm/loaders/GLTFLoader.js";
18
+ import { type GLTFLoaderPlugin } from "three/examples/jsm/loaders/GLTFLoader.js";
19
19
  import { getParam } from "../engine_utils.js";
20
20
  import { isDevEnvironment } from "../debug/index.js";
21
21
  // import { GLTFAnimationPointerExtension } from "three/examples/jsm/loaders/GLTFLoaderAnimationPointer.js";
src/engine-components/js-extensions/ExtensionUtils.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Object3D } from "three";
2
- import { Constructor } from "../../engine/engine_types.js";
2
+ import type { Constructor } from "../../engine/engine_types.js";
3
3
 
4
4
  const handlers: Map<any, ApplyPrototypeExtension> = new Map();
5
5
 
src/engine-components/export/gltf/GltfExport.ts CHANGED
@@ -131,7 +131,7 @@
131
131
  this.ext!.context = serializationContext;
132
132
 
133
133
  return new Promise((resolve, reject) => {
134
-
134
+ if (debugExport) console.log("Starting glTF export.")
135
135
  try {
136
136
  // Parse the input and generate the glTF output
137
137
  this.exporter?.parse(
src/engine-components/ui/Graphic.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { IGraphic, IRectTransformChangedReceiver } from './Interfaces.js';
1
+ import { type IGraphic, type IRectTransformChangedReceiver } from './Interfaces.js';
2
2
  import * as ThreeMeshUI from 'three-mesh-ui'
3
3
  import { RGBAColor } from "../js-extensions/RGBAColor.js"
4
4
  import { BaseUIComponent } from "./BaseUIComponent.js";
src/engine-components/ui/InputField.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Behaviour, GameObject } from "../Component.js";
2
- import { IPointerEventHandler } from "./PointerEvents.js";
2
+ import { type IPointerEventHandler } from "./PointerEvents.js";
3
3
  import { FrameEvent } from "../../engine/engine_setup.js";
4
4
  import { serializable } from "../../engine/engine_serialization_decorator.js";
5
5
  import { Text } from "./Text.js";
src/engine-components/Interactable.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Behaviour } from "./Component.js";
2
- import { IPointerClickHandler, PointerEventData } from "./ui/PointerEvents.js";
2
+ import type { IPointerClickHandler, PointerEventData } from "./ui/PointerEvents.js";
3
3
 
4
4
 
5
5
  export class Interactable extends Behaviour implements IPointerClickHandler {
src/engine-components/ui/Interfaces.ts CHANGED
@@ -1,5 +1,4 @@
1
- import { Behaviour } from "../Component.js";
2
- import { IComponent } from "../../engine/engine_types.js";
1
+ import { type IComponent } from "../../engine/engine_types.js";
3
2
 
4
3
  export interface ICanvas extends IComponent {
5
4
  get isCanvas(): boolean;
src/engine-components/ui/Layout.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { ILayoutGroup, IRectTransform, IRectTransformChangedReceiver } from "./Interfaces.js";
1
+ import { type ILayoutGroup, type IRectTransform } from "./Interfaces.js";
2
2
  import { Behaviour, GameObject } from "../Component.js";
3
3
  import { serializable } from "../../engine/engine_serialization.js";
4
4
  import { Canvas } from "./Canvas.js";
src/engine-components/Light.ts CHANGED
@@ -7,9 +7,7 @@
7
7
  import { Color, DirectionalLight, OrthographicCamera } from "three";
8
8
  import { WebXR, WebXREvent } from "./webxr/WebXR.js";
9
9
  import { WebARSessionRoot } from "./webxr/WebARSessionRoot.js";
10
- import { ILight } from "../engine/engine_types.js";
11
- import { Mathf } from "../engine/engine_math.js";
12
- import { isLocalNetwork } from "../engine/engine_networking_utils.js";
10
+ import type { ILight } from "../engine/engine_types.js";
13
11
 
14
12
  // https://threejs.org/examples/webgl_shadowmap_csm.html
15
13
 
src/engine-components/utils/LookAt.ts CHANGED
@@ -4,7 +4,7 @@
4
4
  import { getWorldPosition, getWorldQuaternion, setWorldQuaternion } from "../../engine/engine_three_utils.js";
5
5
 
6
6
  import { USDObject } from "../../engine-components/export/usdz/ThreeUSDZExporter.js";
7
- import { UsdzBehaviour } from "../../engine-components/export/usdz/extensions/behavior/Behaviour.js";
7
+ import { type UsdzBehaviour } from "../../engine-components/export/usdz/extensions/behavior/Behaviour.js";
8
8
  import { ActionBuilder, BehaviorModel, TriggerBuilder, USDVec3 } from "../../engine-components/export/usdz/extensions/behavior/BehavioursBuilder.js";
9
9
 
10
10
  export class LookAt extends Behaviour implements UsdzBehaviour {
src/engine/extensions/NEEDLE_components.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { GLTF, GLTFLoaderPlugin, GLTFParser } from "three/examples/jsm/loaders/GLTFLoader.js";
2
- import { NodeToObjectMap, ObjectToNodeMap, SerializationContext } from "../engine_serialization_core.js";
1
+ import { type GLTF, type GLTFLoaderPlugin, GLTFParser } from "three/examples/jsm/loaders/GLTFLoader.js";
2
+ import { type NodeToObjectMap, type ObjectToNodeMap, SerializationContext } from "../engine_serialization_core.js";
3
3
  import { GLTFExporter } from 'three/examples/jsm/exporters/GLTFExporter.js';
4
4
  import { debugExtension } from "../engine_default_parameters.js";
5
5
  import { builtinComponentKeyName } from "../engine_constants.js";
src/engine/extensions/NEEDLE_gameobject_data.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Object3D } from "three";
2
- import { GLTF, GLTFLoaderPlugin, GLTFParser } from "three/examples/jsm/loaders/GLTFLoader.js";
2
+ import { type GLTF, type GLTFLoaderPlugin, GLTFParser } from "three/examples/jsm/loaders/GLTFLoader.js";
3
3
 
4
4
  export const EXTENSION_NAME = "NEEDLE_gameobject_data";
5
5
 
src/engine/extensions/NEEDLE_lighting_settings.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { AmbientLight, Color, HemisphereLight, Object3D } from "three";
2
- import { GLTF, GLTFLoaderPlugin, GLTFParser } from "three/examples/jsm/loaders/GLTFLoader.js";
3
- import { SourceIdentifier } from "../engine_types.js";
2
+ import { type GLTF, type GLTFLoaderPlugin, GLTFParser } from "three/examples/jsm/loaders/GLTFLoader.js";
3
+ import { type SourceIdentifier } from "../engine_types.js";
4
4
  import { Behaviour, GameObject } from "../../engine-components/Component.js";
5
5
  import { AmbientMode, DefaultReflectionMode } from "../engine_scenelighting.js";
6
6
  import { LightmapType } from "./NEEDLE_lightmaps.js";
src/engine/extensions/NEEDLE_lightmaps.ts CHANGED
@@ -1,7 +1,7 @@
1
- import { ILightDataRegistry } from "../engine_lightdata.js";
2
- import { FloatType, HalfFloatType, LinearEncoding, LinearSRGBColorSpace, SRGBColorSpace, sRGBEncoding, Texture, TextureLoader } from "three";
3
- import { GLTF, GLTFLoaderPlugin, GLTFParser } from "three/examples/jsm/loaders/GLTFLoader.js";
4
- import { SourceIdentifier } from "../engine_types.js";
1
+ import { type ILightDataRegistry } from "../engine_lightdata.js";
2
+ import { LinearSRGBColorSpace, SRGBColorSpace, Texture, TextureLoader } from "three";
3
+ import { type GLTF, type GLTFLoaderPlugin, GLTFParser } from "three/examples/jsm/loaders/GLTFLoader.js";
4
+ import { type SourceIdentifier } from "../engine_types.js";
5
5
  import { resolveReferences } from "./extension_utils.js";
6
6
  import { getParam, PromiseAllWithErrors, resolveUrl } from "../engine_utils.js";
7
7
  import { EXRLoader } from "three/examples/jsm/loaders/EXRLoader.js";
src/engine/extensions/NEEDLE_persistent_assets.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { resolveReferences } from "./extension_utils.js";
2
- import { GLTF, GLTFLoaderPlugin, GLTFParser } from "three/examples/jsm/loaders/GLTFLoader.js";
3
- import { IExtensionReferenceResolver } from "./extension_resolver.js";
2
+ import { type GLTF, type GLTFLoaderPlugin, GLTFParser } from "three/examples/jsm/loaders/GLTFLoader.js";
3
+ import { type IExtensionReferenceResolver } from "./extension_resolver.js";
4
4
  import { debugExtension } from "../engine_default_parameters.js";
5
5
  import { TypeStore } from "../engine_typestore.js";
6
6
 
src/engine/extensions/NEEDLE_progressive.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Material, RawShaderMaterial, Texture, TextureLoader } from "three";
2
- import { GLTF, GLTFLoader, GLTFLoaderPlugin, GLTFParser } from "three/examples/jsm/loaders/GLTFLoader.js";
3
- import { SourceIdentifier } from "../engine_types.js";
2
+ import { type GLTF, GLTFLoader, type GLTFLoaderPlugin, GLTFParser } from "three/examples/jsm/loaders/GLTFLoader.js";
3
+ import { type SourceIdentifier } from "../engine_types.js";
4
4
  import { Context } from "../engine_setup.js";
5
5
  import { addDracoAndKTX2Loaders } from "../engine_loaders.js";
6
6
  import { PromiseAllWithErrors, PromiseErrorResult, delay, getParam, resolveUrl } from "../engine_utils.js";
src/engine/extensions/NEEDLE_render_objects.ts CHANGED
@@ -1,7 +1,7 @@
1
1
 
2
- import { SourceIdentifier } from "../engine_types.js";
3
- import { GLTF, GLTFLoaderPlugin, GLTFParser } from "three/examples/jsm/loaders/GLTFLoader.js";
4
- import { IComponent as Component, IRenderer } from "../engine_types.js";
2
+ import { type SourceIdentifier } from "../engine_types.js";
3
+ import { type GLTF, type GLTFLoaderPlugin, GLTFParser } from "three/examples/jsm/loaders/GLTFLoader.js";
4
+ import { type IComponent as Component, type IRenderer } from "../engine_types.js";
5
5
 
6
6
  import {
7
7
  // stencil funcs
@@ -22,8 +22,8 @@
22
22
  IncrementWrapStencilOp,
23
23
  DecrementWrapStencilOp,
24
24
  InvertStencilOp,
25
- StencilFunc,
26
- StencilOp as ThreeStencilOp,
25
+ type StencilFunc,
26
+ type StencilOp as ThreeStencilOp,
27
27
  } from "three";
28
28
  import { getParam } from "../engine_utils.js";
29
29
  import { showBalloonWarning } from "../debug/index.js";
src/engine/extensions/NEEDLE_techniques_webgl.ts CHANGED
@@ -1,11 +1,11 @@
1
- import { GLTFLoaderPlugin, GLTFParser } from "three/examples/jsm/loaders/GLTFLoader.js";
1
+ import { type GLTFLoaderPlugin, GLTFParser } from "three/examples/jsm/loaders/GLTFLoader.js";
2
2
  import { FindShaderTechniques, whiteDefaultTexture, ToUnityMatrixArray, SetUnitySphericalHarmonics } from '../engine_shaders.js';
3
- import { AlwaysDepth, BackSide, Camera, DoubleSide, EqualDepth, FrontSide, GLSL3, GreaterDepth, GreaterEqualDepth, IUniform, LessDepth, LessEqualDepth, LinearEncoding, LinearSRGBColorSpace, Material, Matrix4, NotEqualDepth, Object3D, RawShaderMaterial, Texture, Vector3, Vector4 } from 'three';
3
+ import { AlwaysDepth, BackSide, Camera, DoubleSide, EqualDepth, FrontSide, GLSL3, GreaterDepth, GreaterEqualDepth, type IUniform, LessDepth, LessEqualDepth, LinearSRGBColorSpace, Material, Matrix4, NotEqualDepth, Object3D, RawShaderMaterial, Texture, Vector3, Vector4 } from 'three';
4
4
  import { Context } from '../engine_setup.js';
5
5
  import { getParam } from "../engine_utils.js";
6
6
  import * as SHADERDATA from "../shaders/shaderData.js"
7
- import { SourceIdentifier } from "../engine_types.js";
8
- import { ILight } from "../engine_types.js";
7
+ import { type SourceIdentifier } from "../engine_types.js";
8
+ import { type ILight } from "../engine_types.js";
9
9
  import { getWorldPosition } from "../engine_three_utils.js";
10
10
 
11
11
  const debug = getParam("debugcustomshader");
src/engine-components/NestedGltf.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { getParam } from "../engine/engine_utils.js";
2
2
  import { Behaviour } from "../engine-components/Component.js";
3
- import { AssetReference, ProgressCallback } from "../engine/engine_addressables.js";
3
+ import { AssetReference, type ProgressCallback } from "../engine/engine_addressables.js";
4
4
  import { serializable } from "../engine/engine_serialization_decorator.js";
5
5
  import { InstantiateIdProvider } from "../engine/engine_networking_instantiate.js";
6
6
  import { InstantiateOptions } from "../engine/engine_gameobject.js";
src/engine-components/Networking.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { serializable } from "../engine/engine_serialization.js";
2
- import { INetworkingWebsocketUrlProvider } from "../engine/engine_networking.js";
2
+ import type { INetworkingWebsocketUrlProvider } from "../engine/engine_networking.js";
3
3
  import { isLocalNetwork } from "../engine/engine_networking_utils.js";
4
4
  import { getParam } from "../engine/engine_utils.js";
5
5
  import { Behaviour } from "./Component.js";
src/engine-components/js-extensions/Object3D.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  import { applyPrototypeExtensions, registerPrototypeExtensions } from "./ExtensionUtils.js";
2
2
  import { Object3D } from "three";
3
- import { Constructor, ConstructorConcrete, IComponent } from "../../engine/engine_types.js"
4
- import { IComponent as Component } from "../../engine/engine_types.js";
3
+ import type { Constructor, ConstructorConcrete, IComponent, IComponent as Component } from "../../engine/engine_types.js";
5
4
  import { moveComponentInstance, addNewComponent, getComponent, getComponentInChildren, getComponentInParent, getComponents, getComponentsInChildren, getComponentsInParent, getOrAddComponent, removeComponent } from "../../engine/engine_components.js";
6
5
  import { isActiveSelf, setActive, destroy } from "../../engine/engine_gameobject.js";
7
6
 
src/engine-components/utils/OpenURL.ts CHANGED
@@ -1,5 +1,5 @@
1
1
 
2
- import { IPointerClickHandler, PointerEventData } from "../ui/index.js";
2
+ import { type IPointerClickHandler, PointerEventData } from "../ui/index.js";
3
3
  import { Behaviour } from "../Component.js";
4
4
  import { serializable } from "../../engine/engine_serialization.js";
5
5
  import { isDevEnvironment, showBalloonMessage } from "../../engine/debug/index.js";
src/engine-components/OrbitControls.ts CHANGED
@@ -8,8 +8,8 @@
8
8
 
9
9
  import { Camera as ThreeCamera, Box3, Object3D, PerspectiveCamera, Vector2, Vector3, Box3Helper, GridHelper, Mesh, ShadowMaterial, RGBA_ASTC_10x10_Format } from "three";
10
10
  import { OrbitControls as ThreeOrbitControls } from "three/examples/jsm/controls/OrbitControls.js";
11
- import { AfterHandleInputEvent, EventSystem, EventSystemEvents } from "./ui/EventSystem.js";
12
- import { ICameraController } from "../engine/engine_types.js";
11
+ import { type AfterHandleInputEvent, EventSystem, EventSystemEvents } from "./ui/EventSystem.js";
12
+ import type { ICameraController } from "../engine/engine_types.js";
13
13
  import { setCameraController } from "../engine/engine_camera.js";
14
14
  import { SyncedTransform } from "./SyncedTransform.js";
15
15
  import { tryGetUIComponent } from "./ui/Utils.js";
src/engine-components/ParticleSystem.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { Behaviour, GameObject } from "./Component.js";
2
2
  import * as THREE from "three";
3
- import { MainModule, EmissionModule, ShapeModule, ParticleSystemShapeType, MinMaxCurve, MinMaxGradient, ColorOverLifetimeModule, SizeOverLifetimeModule, NoiseModule, ParticleSystemSimulationSpace, ParticleBurst, IParticleSystem, ParticleSystemRenderMode, TrailModule, VelocityOverLifetimeModule, TextureSheetAnimationModule, RotationOverLifetimeModule, LimitVelocityOverLifetimeModule, RotationBySpeedModule, InheritVelocityModule, SizeBySpeedModule, ColorBySpeedModule, ParticleSystemScalingMode } from "./ParticleSystemModules.js"
3
+ import { MainModule, EmissionModule, ShapeModule, ParticleSystemShapeType, MinMaxCurve, MinMaxGradient, ColorOverLifetimeModule, SizeOverLifetimeModule, NoiseModule, ParticleSystemSimulationSpace, ParticleBurst, type IParticleSystem, ParticleSystemRenderMode, TrailModule, VelocityOverLifetimeModule, TextureSheetAnimationModule, RotationOverLifetimeModule, LimitVelocityOverLifetimeModule, RotationBySpeedModule, InheritVelocityModule, SizeBySpeedModule, ColorBySpeedModule, ParticleSystemScalingMode } from "./ParticleSystemModules.js"
4
4
  import { getParam } from "../engine/engine_utils.js";
5
5
 
6
6
  // https://github.dev/creativelifeform/three-nebula
@@ -11,7 +11,8 @@
11
11
  import { AxesHelper, BufferGeometry, Color, Material, Matrix4, Mesh, MeshStandardMaterial, Object3D, OneMinusDstAlphaFactor, PlaneGeometry, Quaternion, Sprite, SpriteMaterial, Vector3, Vector4 } from "three";
12
12
  import { getWorldPosition, getWorldQuaternion, getWorldScale, setWorldScale } from "../engine/engine_three_utils.js";
13
13
  import { assign } from "../engine/engine_serialization_core.js";
14
- import { BatchedRenderer, BatchedParticleRenderer, Behavior, BillBoardSettings, BurstParameters, ColorGenerator, ConstantColor, ConstantValue, EmissionState, EmitSubParticleSystem, EmitterShape, FunctionColorGenerator, FunctionJSON, FunctionValueGenerator, IntervalValue, MeshSettings, Particle, ParticleEmitter, ParticleSystem as _ParticleSystem, ParticleSystemParameters, PointEmitter, RecordState, RenderMode, RotationGenerator, SizeOverLife, TrailBatch, TrailParticle, TrailSettings, ValueGenerator } from "three.quarks";
14
+ import { ParticleSystem as _ParticleSystem, ConstantValue, ConstantColor, BatchedParticleRenderer, TrailBatch, TrailParticle, RenderMode } from "three.quarks";
15
+ import type { BatchedRenderer, Behavior, BillBoardSettings, BurstParameters, ColorGenerator, EmissionState, EmitSubParticleSystem, EmitterShape, FunctionColorGenerator, FunctionJSON, FunctionValueGenerator, IntervalValue, MeshSettings, Particle, ParticleEmitter, ParticleSystemParameters, PointEmitter, RecordState, RotationGenerator, SizeOverLife, TrailSettings, ValueGenerator } from "three.quarks";
15
16
  import { createFlatTexture } from "../engine/engine_shaders.js";
16
17
  import { Mathf } from "../engine/engine_math.js";
17
18
  import { Context } from "../engine/engine_setup.js";
src/engine-components/ParticleSystemModules.ts CHANGED
@@ -1,12 +1,12 @@
1
- import { Color, Matrix4, Object3D, PointLightShadow, Quaternion, Vector3, Vector2, Euler, Vector4, DirectionalLightHelper } from "three";
1
+ import { Matrix4, Object3D, Quaternion, Vector3, Vector2, Euler, Vector4 } from "three";
2
2
  import { Mathf } from "../engine/engine_math.js";
3
3
  import { serializable } from "../engine/engine_serialization.js";
4
4
  import { RGBAColor } from "./js-extensions/RGBAColor.js";
5
5
  import { AnimationCurve } from "./AnimationCurve.js";
6
- import { Vec2, Vec3 } from "../engine/engine_types.js";
6
+ import type { Vec2, Vec3 } from "../engine/engine_types.js";
7
7
  import { Context } from "../engine/engine_setup.js";
8
- import { EmitterShape, FrameOverLife, Particle, ShapeJSON } from "three.quarks";
9
- import { createNoise4D, NoiseFunction4D } from 'simplex-noise';
8
+ import type { EmitterShape, Particle, ShapeJSON } from "three.quarks";
9
+ import { createNoise4D, type NoiseFunction4D } from 'simplex-noise';
10
10
  import { Gizmos } from "../engine/engine_gizmos.js";
11
11
  import { getParam } from "../engine/engine_utils.js";
12
12
 
src/engine-components/ParticleSystemSubEmitter.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { Behavior, Particle, EmissionState, ParticleSystem, ParticleEmitter } from "three.quarks";
1
+ import { type Behavior, type Particle, type EmissionState, type ParticleSystem } from "three.quarks";
2
2
  import { Vector3, Quaternion, Matrix4 } from "three";
3
- import { IParticleSystem } from "./ParticleSystemModules.js";
3
+ import type { IParticleSystem } from "./ParticleSystemModules.js";
4
4
  import { CircularBuffer } from "../engine/engine_utils.js";
5
5
  import { $particleLife, SubEmitterType } from "./ParticleSystem.js";
6
6
 
src/engine-components/postprocessing/Effects/Pixelation.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { registerCustomEffectType } from "../VolumeProfile.js";
2
- import { EffectProviderResult, PostProcessingEffect } from "../PostProcessingEffect.js";
2
+ import { type EffectProviderResult, PostProcessingEffect } from "../PostProcessingEffect.js";
3
3
  import { PixelationEffect as PixelationEffectPP } from "postprocessing";
4
4
  import { VolumeParameter } from "../VolumeParameter.js";
5
5
  import { serializable } from "../../../engine/engine_serialization.js";
src/engine-components/timeline/PlayableDirector.ts CHANGED
@@ -7,7 +7,7 @@
7
7
  import * as Models from "./TimelineModels.js";
8
8
  import * as Tracks from "./TimelineTracks.js";
9
9
  import { deepClone, delay, getParam } from '../../engine/engine_utils.js';
10
- import { GuidsMap } from '../../engine/engine_types.js';
10
+ import type { GuidsMap } from '../../engine/engine_types.js';
11
11
  import { Object3D, Quaternion, Vector3 } from 'three';
12
12
  import { isLocalNetwork } from '../../engine/engine_networking_utils.js';
13
13
  import { FrameEvent } from '../../engine/engine_context.js';
src/engine-components/postprocessing/PostProcessingEffect.ts CHANGED
@@ -2,8 +2,8 @@
2
2
  import { Effect, Pass } from "postprocessing";
3
3
  import { VolumeParameter } from "./VolumeParameter.js";
4
4
  import { Component } from "../Component.js";
5
- import { ISerializable, SerializationContext } from "../../engine/engine_serialization_core.js";
6
- import { EditorModification, IEditorModification } from "../../engine/engine_editor-sync.js";
5
+ import type { ISerializable, SerializationContext } from "../../engine/engine_serialization_core.js";
6
+ import type { EditorModification, IEditorModification } from "../../engine/engine_editor-sync.js";
7
7
  import { getParam } from "../../engine/engine_utils.js";
8
8
 
9
9
  const debug = getParam("debugpost");
src/engine-components/postprocessing/PostProcessingHandler.ts CHANGED
@@ -5,7 +5,7 @@
5
5
  import { showBalloonWarning } from "../../engine/debug/index.js";
6
6
  import { Camera } from "../Camera.js";
7
7
  import { PostProcessingEffect } from "./PostProcessingEffect.js";
8
- import { Constructor } from "../../engine/engine_types.js";
8
+ import type { Constructor } from "../../engine/engine_types.js";
9
9
  import { N8AOPostPass } from "n8ao";
10
10
 
11
11
  const debug = getParam("debugpost");
src/engine-components-experimental/Presentation.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Behaviour } from "../engine-components/Component.js";
2
- import { KeyCode } from "../engine/engine_input.js";
2
+ import type { KeyCode } from "../engine/engine_input.js";
3
3
 
4
4
  export class PresentationMode extends Behaviour {
5
5
 
src/engine-components/ui/RaycastUtils.ts CHANGED
@@ -1,8 +1,7 @@
1
1
  import { foreachComponent } from "../../engine/engine_gameobject.js";
2
- import { objectSerializer } from "../../engine/engine_serialization_builtin_serializer.js";
3
- import { IComponent } from "../../engine/engine_types.js";
2
+ import { type IComponent } from "../../engine/engine_types.js";
4
3
  import { $shadowDomOwner } from "./BaseUIComponent.js";
5
- import { ICanvasGroup, IGraphic } from "./Interfaces.js";
4
+ import { type ICanvasGroup, type IGraphic } from "./Interfaces.js";
6
5
  import { Object3D } from "three";
7
6
 
8
7
 
src/engine-components/ui/RectTransform.ts CHANGED
@@ -1,12 +1,12 @@
1
1
  import * as ThreeMeshUI from 'three-mesh-ui'
2
2
  import { BaseUIComponent } from "./BaseUIComponent.js";
3
- import { DocumentedOptions as ThreeMeshUIEveryOptions } from "three-mesh-ui/build/types/core/elements/MeshUIBaseElement.js";
3
+ import { type DocumentedOptions as ThreeMeshUIEveryOptions } from "three-mesh-ui/build/types/core/elements/MeshUIBaseElement.js";
4
4
  import { serializable } from "../../engine/engine_serialization_decorator.js";
5
5
  import { Matrix4, Object3D, Quaternion, Vector2, Vector3 } from "three";
6
6
  import { getParam } from "../../engine/engine_utils.js";
7
7
  import { onChange } from "./Utils.js";
8
8
  import { foreachComponentEnumerator } from "../../engine/engine_gameobject.js";
9
- import { ICanvas, IRectTransform, IRectTransformChangedReceiver } from "./Interfaces.js";
9
+ import { type ICanvas, type IRectTransform, type IRectTransformChangedReceiver } from "./Interfaces.js";
10
10
  import { GameObject } from '../Component.js';
11
11
 
12
12
  const debug = getParam("debugui");
src/engine-components/ReflectionProbe.ts CHANGED
@@ -1,9 +1,8 @@
1
1
  import { Behaviour } from "./Component.js";
2
- import { Box3, Color, EquirectangularReflectionMapping, LinearEncoding, LineBasicMaterial, Material, MeshStandardMaterial, Object3D, SrcAlphaFactor, SRGBColorSpace, sRGBEncoding, Texture, Vector3, WebGLCubeRenderTarget, WebGLRenderTarget } from "three";
2
+ import { EquirectangularReflectionMapping, Material, Object3D, SRGBColorSpace, Texture, Vector3 } from "three";
3
3
  import { serializable } from "../engine/engine_serialization.js";
4
4
  import { Context } from "../engine/engine_setup.js";
5
- import { getWorldPosition, getWorldScale } from "../engine/engine_three_utils.js";
6
- import { IRenderer } from "../engine/engine_types.js";
5
+ import type { IRenderer } from "../engine/engine_types.js";
7
6
  import { BoxHelperComponent } from "./BoxHelperComponent.js";
8
7
  import { getParam } from "../engine/engine_utils.js";
9
8
 
src/engine/codegen/register_types.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { TypeStore } from "./../engine_typestore.js"
2
-
2
+
3
3
  // Import types
4
4
  import { __Ignore } from "../../engine-components/codegen/components.js";
5
5
  import { ActionBuilder } from "../../engine-components/export/usdz/extensions/behavior/BehavioursBuilder.js";
@@ -217,7 +217,7 @@
217
217
  import { XRGrabRendering } from "../../engine-components/webxr/WebXRGrabRendering.js";
218
218
  import { XRRig } from "../../engine-components/webxr/WebXRRig.js";
219
219
  import { XRState } from "../../engine-components/XRFlag.js";
220
-
220
+
221
221
  // Register types
222
222
  TypeStore.add("__Ignore", __Ignore);
223
223
  TypeStore.add("ActionBuilder", ActionBuilder);
src/engine-components/Renderer.ts CHANGED
@@ -9,7 +9,7 @@
9
9
  import { NEEDLE_render_objects } from "../engine/extensions/NEEDLE_render_objects.js";
10
10
  import { NEEDLE_progressive } from "../engine/extensions/NEEDLE_progressive.js";
11
11
  import { NEED_UPDATE_INSTANCE_KEY } from "../engine/engine_instancing.js";
12
- import { IRenderer, ISharedMaterials } from "../engine/engine_types.js";
12
+ import type { IRenderer, ISharedMaterials } from "../engine/engine_types.js";
13
13
  import { ReflectionProbe } from "./ReflectionProbe.js";
14
14
  import { setCustomVisibility } from "../engine/js-extensions/Layers.js";
15
15
  import { isLocalNetwork } from "../engine/engine_networking_utils.js";
src/engine-components/RendererLightmap.ts CHANGED
@@ -1,6 +1,5 @@
1
- import { Behaviour, GameObject } from "./Component.js";
2
- import { Material, Mesh, Shader, ShaderMaterial, Texture, Vector4 } from "three";
3
- import { Context, OnRenderCallback } from "../engine/engine_setup.js";
1
+ import { Material, Mesh, type Shader, ShaderMaterial, Texture, Vector4 } from "three";
2
+ import type { Context, OnRenderCallback } from "../engine/engine_setup.js";
4
3
  import { getParam } from "../engine/engine_utils.js";
5
4
 
6
5
  const debug = getParam("debuglightmaps");
src/engine-components/RigidBody.ts CHANGED
@@ -4,7 +4,7 @@
4
4
  import { serializable } from "../engine/engine_serialization_decorator.js";
5
5
  import { Watch } from "../engine/engine_utils.js";
6
6
  import { Matrix4, Object3D, Vector3 } from "three";
7
- import { IRigidbody } from "../engine/engine_types.js";
7
+ import type { IRigidbody, Vec3 } from "../engine/engine_types.js";
8
8
  import { CollisionDetectionMode, RigidbodyConstraints } from "../engine/engine_physics.types.js";
9
9
  import { validate } from "../engine/engine_util_decorator.js";
10
10
  import { Context, FrameEvent } from "../engine/engine_setup.js";
@@ -307,12 +307,12 @@
307
307
  this.resetVelocities();
308
308
  }
309
309
 
310
- public resetForces() {
311
- this.context.physics.engine?.resetForces(this, true);
310
+ public resetForces(wakeup:boolean = true) {
311
+ this.context.physics.engine?.resetForces(this, wakeup);
312
312
  }
313
313
 
314
- public resetTorques() {
315
- this.context.physics.engine?.resetTorques(this, true);
314
+ public resetTorques(wakeup:boolean = true) {
315
+ this.context.physics.engine?.resetTorques(this, wakeup);
316
316
  }
317
317
 
318
318
  public resetVelocities() {
@@ -329,17 +329,17 @@
329
329
  this.context.physics.engine?.wakeup(this);
330
330
  }
331
331
 
332
- public applyForce(vec: Vector3, _rel?: THREE.Vector3) {
333
- this.context.physics.engine?.addForce(this, vec, true);
332
+ public applyForce(vec: Vector3 | Vec3, _rel?: THREE.Vector3, wakeup: boolean = true) {
333
+ this.context.physics.engine?.addForce(this, vec, wakeup);
334
334
  }
335
335
 
336
- public applyImpulse(vec: Vector3) {
337
- this.context.physics.engine?.applyImpulse(this, vec, true);
336
+ public applyImpulse(vec: Vector3 | Vec3, wakeup: boolean = true) {
337
+ this.context.physics.engine?.applyImpulse(this, vec, wakeup);
338
338
  }
339
339
 
340
- public setForce(x: number, y: number, z: number) {
341
- this.context.physics.engine?.resetForces(this, true);
342
- this.context.physics.engine?.addForce(this, { x, y, z }, true);
340
+ public setForce(x: number, y: number, z: number, wakeup: boolean = true) {
341
+ this.context.physics.engine?.resetForces(this, wakeup);
342
+ this.context.physics.engine?.addForce(this, { x, y, z }, wakeup);
343
343
  }
344
344
 
345
345
  public getVelocity(): Vector3 {
@@ -351,24 +351,24 @@
351
351
  return this._currentVelocity;
352
352
  }
353
353
 
354
- public setVelocity(x: number | Vector3, y?: number, z?: number) {
354
+ public setVelocity(x: number | Vector3, y?: number, z?: number, wakeup: boolean = true) {
355
355
  if (x instanceof Vector3) {
356
356
  const vec = x;
357
- this.context.physics.engine?.setLinearVelocity(this,vec, true);
357
+ this.context.physics.engine?.setLinearVelocity(this, vec, wakeup);
358
358
  return;
359
359
  }
360
360
  if (y === undefined || z === undefined) return;
361
- this.context.physics.engine?.setLinearVelocity(this, { x: x, y: y, z: z }, true);
361
+ this.context.physics.engine?.setLinearVelocity(this, { x: x, y: y, z: z }, wakeup);
362
362
  }
363
363
 
364
- public setAngularVelocity(x: number | Vector3, y?: number, z?: number) {
364
+ public setAngularVelocity(x: number | Vector3, y?: number, z?: number, wakeup: boolean = true) {
365
365
  if (x instanceof Vector3) {
366
366
  const vec = x;
367
- this.context.physics.engine?.setAngularVelocity(this, vec, true);
367
+ this.context.physics.engine?.setAngularVelocity(this, vec, wakeup);
368
368
  return;
369
369
  }
370
370
  if (y === undefined || z === undefined) return;
371
- this.context.physics.engine?.setAngularVelocity(this, { x: x, y: y, z: z }, true);
371
+ this.context.physics.engine?.setAngularVelocity(this, { x: x, y: y, z: z }, wakeup);
372
372
  }
373
373
 
374
374
  public getAngularVelocity(): Vector3 {
src/engine-components/ScreenCapture.ts CHANGED
@@ -1,24 +1,22 @@
1
1
  import { Behaviour, GameObject } from "./Component.js";
2
- import { VideoPlayer } from "./VideoPlayer.js";
3
- import Peer, { MediaConnection } from "peerjs"
4
- import { Context } from "../engine/engine_setup.js";
5
- import { RoomEvents } from "../engine/engine_networking.js";
6
- import { UserJoinedOrLeftRoomModel } from "../engine/engine_networking.js";
2
+ import { AspectMode, VideoPlayer } from "./VideoPlayer.js";
7
3
  import { serializable } from "../engine/engine_serialization.js";
8
- import { IPointerClickHandler, PointerEventData } from "./ui/PointerEvents.js";
9
- import { EventDispatcher } from "three";
4
+ import type { IPointerClickHandler, PointerEventData } from "./ui/PointerEvents.js";
10
5
  import { AudioSource } from "./AudioSource.js";
11
6
  import { getParam } from "../engine/engine_utils.js";
12
- import { IModel } from "../engine/engine_networking_types.js";
13
7
  import { showBalloonWarning } from "../engine/debug/index.js";
14
- import { getPeerjsInstance } from "../engine/engine_networking_peer.js";
8
+ import { NetworkedStreams, disposeStream, StreamReceivedEvent, StreamEndedEvent, PeerHandle, NetworkedStreamEvents } from "../engine/engine_networking_streams.js";
9
+ import { RoomEvents } from "../engine/engine_networking.js";
15
10
 
16
11
  const debug = getParam("debugscreensharing");
17
12
 
18
13
  export enum ScreenCaptureDevice {
19
14
  Screen = 0,
20
15
  Camera = 1,
21
- Canvas = 2
16
+ /** Please note that canvas streaming might not work reliably on chrome: https://bugs.chromium.org/p/chromium/issues/detail?id=1156408 */
17
+ Canvas = 2,
18
+ /** When using Microphone only the voice will be sent */
19
+ Microphone = 3
22
20
  }
23
21
 
24
22
  export enum ScreenCaptureMode {
@@ -27,11 +25,6 @@
27
25
  Receiving = 2
28
26
  }
29
27
 
30
- function disposeStream(str: MediaStream | null | undefined) {
31
- if (!str) return;
32
- for (const cap of str.getTracks())
33
- cap.stop();
34
- }
35
28
 
36
29
  declare type ScreenCaptureOptions = {
37
30
  device?: ScreenCaptureDevice,
@@ -44,6 +37,7 @@
44
37
 
45
38
  export class ScreenCapture extends Behaviour implements IPointerClickHandler {
46
39
 
40
+ @serializable()
47
41
  allowStartOnClick: boolean = true;
48
42
 
49
43
  onPointerEnter() {
@@ -73,16 +67,36 @@
73
67
  }
74
68
 
75
69
 
70
+ /** When enabled the stream will start when this component becomes active (enabled in the scene) */
71
+ @serializable()
72
+ autoConnect: boolean = false;
73
+
74
+
76
75
  @serializable(VideoPlayer)
77
- videoPlayer?: VideoPlayer;
76
+ set videoPlayer(val: VideoPlayer | undefined) {
77
+ if (this._videoPlayer && (this.isSending || this.isReceiving)) {
78
+ this._videoPlayer.stop();
79
+ }
80
+ this._videoPlayer = val;
81
+ if (this._videoPlayer && this._currentStream && (this.isSending || this.isReceiving)) {
82
+ this._videoPlayer.setVideo(this._currentStream);
83
+ }
84
+ }
85
+ get videoPlayer() { return this._videoPlayer; }
86
+ private _videoPlayer?: VideoPlayer;
87
+ private _audioSource?: AudioSource;
78
88
 
89
+ get screenspace() { return this.videoPlayer?.screenspace ?? false; }
90
+ set screenspace(v: boolean) { if (this.videoPlayer) this.videoPlayer.screenspace = v; }
91
+
92
+ // TODO: make this a property
93
+ /** Note: this can not be changed while streaming */
79
94
  @serializable()
80
95
  device: ScreenCaptureDevice = ScreenCaptureDevice.Screen;
81
96
 
82
97
  get currentScream(): MediaStream | null {
83
98
  return this._currentStream;
84
99
  }
85
-
86
100
  get currentMode(): ScreenCaptureMode {
87
101
  return this._currentMode;
88
102
  }
@@ -102,7 +116,9 @@
102
116
  return false;
103
117
  }
104
118
 
105
- private _net?: NetworkedVideo;
119
+ private get requiresVideoPlayer() { return this.device !== ScreenCaptureDevice.Microphone }
120
+
121
+ private _net?: NetworkedStreams;
106
122
  private _requestOpen: boolean = false;
107
123
  private _currentStream: MediaStream | null = null;
108
124
  private _currentMode: ScreenCaptureMode = ScreenCaptureMode.Idle;
@@ -116,26 +132,36 @@
116
132
  this.videoPlayer.setVideo(this._currentStream);
117
133
  }
118
134
  });
135
+ const handle = PeerHandle.getOrCreate(this.context, this.guid);
136
+ this._net = new NetworkedStreams(this.context, handle);
119
137
  }
120
138
 
139
+ onEnable(): void {
140
+ this._net?.enable();
141
+ //@ts-ignore
142
+ this._net?.addEventListener(NetworkedStreamEvents.StreamReceived, this.onReceiveStream);
143
+ //@ts-ignore
144
+ this._net?.addEventListener(NetworkedStreamEvents.StreamEnded, this.onCallEnded);
145
+ this.context.connection.beginListen(RoomEvents.JoinedRoom, this.onJoinedRoom);
146
+ if (this.context.connection.isInRoom && this.autoConnect) {
147
+ this.share();
148
+ }
149
+ }
121
150
 
122
151
  onDisable(): void {
152
+ //@ts-ignore
153
+ this._net?.removeEventListener(NetworkedStreamEvents.StreamReceived, this.onReceiveStream);
154
+ //@ts-ignore
155
+ this._net?.removeEventListener(NetworkedStreamEvents.StreamEnded, this.onCallEnded);
156
+ this.context.connection.stopListen(RoomEvents.JoinedRoom, this.onJoinedRoom);
157
+ this._net?.disable();
123
158
  this.close();
124
159
  }
125
160
 
126
- start() {
127
- if (!this.videoPlayer) {
128
- this.videoPlayer = GameObject.getComponent(this.gameObject, VideoPlayer) ?? undefined;
161
+ private onJoinedRoom = () => {
162
+ if (this.autoConnect && !this.isSending && !this.isReceiving) {
163
+ this.share();
129
164
  }
130
- if (!this.videoPlayer) {
131
- console.warn("ScreenCapture: Requires an assigned VideoPlayer or a VideoPlayer component on the same object as this component.");
132
- return;
133
- }
134
- const handle = PeerHandle.getOrCreate(this.context, this.guid);
135
- this._net = new NetworkedVideo(this.context, handle);
136
- this._net.enable();
137
- //@ts-ignore
138
- this._net.addEventListener(PeerEvent.ReceiveVideo, this.onReceiveVideo.bind(this));
139
165
  }
140
166
 
141
167
  /** Call to begin screensharing */
@@ -144,62 +170,94 @@
144
170
  if (opts?.device)
145
171
  this.device = opts.device;
146
172
 
173
+ if (!this.videoPlayer && this.requiresVideoPlayer) {
174
+ if (!this._videoPlayer) {
175
+ this._videoPlayer = GameObject.getComponent(this.gameObject, VideoPlayer) ?? undefined;
176
+ }
177
+ if (!this.videoPlayer) {
178
+ const vp = new VideoPlayer();
179
+ vp.aspectMode = AspectMode.AdjustWidth;
180
+ GameObject.addComponent(this.gameObject, vp);
181
+ this._videoPlayer = vp;
182
+ }
183
+ if (!this.videoPlayer) {
184
+ console.warn("Can not share video without a videoPlayer assigned");
185
+ return;
186
+ }
187
+ }
188
+
147
189
  this._requestOpen = true;
148
190
  try {
149
- if (this.videoPlayer) {
150
191
 
151
- const settings: MediaTrackConstraints = opts?.constraints ?? {
152
- echoCancellation: true,
153
- autoGainControl: false,
154
- };
155
- const displayMediaOptions: MediaStreamConstraints = {
156
- video: settings,
157
- audio: settings,
158
- };
159
- const videoOptions = displayMediaOptions.video;
160
- if (videoOptions !== undefined && typeof videoOptions !== "boolean") {
161
- // Set default video settings
162
- if (!videoOptions.width)
163
- videoOptions.width = { max: 1920 };
164
- if (!videoOptions.height)
165
- videoOptions.height = { max: 1920 };
166
- if (!videoOptions.aspectRatio)
167
- videoOptions.aspectRatio = { ideal: 1.7777777778 };
168
- if (!videoOptions.frameRate)
169
- videoOptions.frameRate = { ideal: 24 };
170
- if (!videoOptions.facingMode)
171
- videoOptions.facingMode = { ideal: "user" };
172
- }
192
+ const settings: MediaTrackConstraints = opts?.constraints ?? {
193
+ echoCancellation: true,
194
+ autoGainControl: false,
195
+ };
196
+ const displayMediaOptions: MediaStreamConstraints = {
197
+ video: settings,
198
+ audio: settings,
199
+ };
200
+ const videoOptions = displayMediaOptions.video;
201
+ if (videoOptions !== undefined && typeof videoOptions !== "boolean") {
202
+ // Set default video settings
203
+ if (!videoOptions.width)
204
+ videoOptions.width = { max: 1920 };
205
+ if (!videoOptions.height)
206
+ videoOptions.height = { max: 1920 };
207
+ if (!videoOptions.aspectRatio)
208
+ videoOptions.aspectRatio = { ideal: 1.7777777778 };
209
+ if (!videoOptions.frameRate)
210
+ videoOptions.frameRate = { ideal: 24 };
211
+ if (!videoOptions.facingMode)
212
+ videoOptions.facingMode = { ideal: "user" };
213
+ }
173
214
 
174
- switch (this.device) {
175
- // Capture a connected camera
176
- case ScreenCaptureDevice.Camera:
177
- this.tryShareUserCamera(displayMediaOptions, opts);
178
- break;
215
+ switch (this.device) {
216
+ // Capture a connected camera
217
+ case ScreenCaptureDevice.Camera:
218
+ this.tryShareUserCamera(displayMediaOptions, opts);
219
+ break;
179
220
 
180
- // capture any screen, will show a popup
181
- case ScreenCaptureDevice.Screen:
221
+ // capture any screen, will show a popup
222
+ case ScreenCaptureDevice.Screen:
223
+ {
182
224
  if (!navigator.mediaDevices.getDisplayMedia) {
183
225
  console.error("No getDisplayMedia support");
184
226
  return;
185
227
  }
186
228
  const myVideo = await navigator.mediaDevices.getDisplayMedia(displayMediaOptions);
187
229
  if (this._requestOpen) {
188
- this.setVideo(myVideo, ScreenCaptureMode.Sending);
230
+ this.setStream(myVideo, ScreenCaptureMode.Sending);
189
231
  }
190
232
  else disposeStream(myVideo);
191
- break;
233
+ }
234
+ break;
192
235
 
193
- // capture the canvas meaning the threejs view
194
- case ScreenCaptureDevice.Canvas:
195
- // looks like this doesnt work reliably on chrome https://stackoverflow.com/a/66848674
196
- // firefox updates fine
197
- // https://bugs.chromium.org/p/chromium/issues/detail?id=1156408
198
- const fps = 0;
199
- const stream = this.context.renderer.domElement.captureStream(fps);
200
- this.setVideo(stream, ScreenCaptureMode.Sending);
201
- break;
202
- }
236
+ // capture the canvas meaning the threejs view
237
+ case ScreenCaptureDevice.Canvas:
238
+ // looks like this doesnt work reliably on chrome https://stackoverflow.com/a/66848674
239
+ // firefox updates fine
240
+ // https://bugs.chromium.org/p/chromium/issues/detail?id=1156408
241
+ const fps = 0;
242
+ const stream = this.context.renderer.domElement.captureStream(fps);
243
+ this.setStream(stream, ScreenCaptureMode.Sending);
244
+ break;
245
+
246
+ case ScreenCaptureDevice.Microphone:
247
+ {
248
+ if (!navigator.mediaDevices.getUserMedia) {
249
+ console.error("No getDisplayMedia support");
250
+ return;
251
+ }
252
+ displayMediaOptions.video = false;
253
+ const myStream = await navigator.mediaDevices.getUserMedia(displayMediaOptions);
254
+ if (this._requestOpen) {
255
+ this.setStream(myStream, ScreenCaptureMode.Sending);
256
+ }
257
+ else disposeStream(myStream);
258
+ }
259
+ break
260
+
203
261
  }
204
262
  } catch (err: any) {
205
263
  if (err.name === "NotAllowedError") {
@@ -217,30 +275,56 @@
217
275
  if (this._currentStream) {
218
276
  if (debug)
219
277
  console.warn("Close current stream / disposing resources, stream was active?", this._currentStream.active);
220
- this._net?.stopSendingVideo(this._currentStream);
278
+ this._net?.stopSendingStream(this._currentStream);
221
279
  disposeStream(this._currentStream);
222
280
  this._currentMode = ScreenCaptureMode.Idle;
223
281
  this._currentStream = null;
224
282
  }
225
283
  }
226
284
 
227
- private setVideo(stream: MediaStream, mode: ScreenCaptureMode) {
285
+ private setStream(stream: MediaStream, mode: ScreenCaptureMode) {
286
+
228
287
  if (stream === this._currentStream) return;
288
+
229
289
  this.close();
230
- if (!stream || !this.videoPlayer) return;
290
+ if (!stream) return;
291
+
231
292
  this._currentStream = stream;
232
293
  this._requestOpen = true;
233
294
  this._currentMode = mode;
234
- this.videoPlayer.setVideo(stream);
235
295
 
296
+ const isVideoStream = this.device !== ScreenCaptureDevice.Microphone;
236
297
  const isSending = mode === ScreenCaptureMode.Sending;
298
+
299
+ if (isVideoStream) {
300
+ if (this._videoPlayer)
301
+ this._videoPlayer.setVideo(stream);
302
+ else console.error("No video player assigned for video stream");
303
+ }
304
+ else {
305
+ if (!this._audioSource) {
306
+ this._audioSource = new AudioSource();
307
+ this._audioSource.spatialBlend = 0;
308
+ this._audioSource.volume = 1;
309
+ this.gameObject.addComponent(this._audioSource);
310
+ }
311
+ if (!isSending) {
312
+ console.log("PLAY", stream.getAudioTracks())
313
+ this._audioSource.volume = 1;
314
+ this._audioSource?.play(stream);
315
+ }
316
+ }
317
+
237
318
  if (isSending) {
238
- this._net?.startSendingVideo(stream);
319
+ this._net?.startSendingStream(stream);
239
320
  }
240
321
 
241
322
  // Mute audio for the video we are sending
242
- if (mode === ScreenCaptureMode.Sending)
243
- this.videoPlayer.muted = true;
323
+ if (isSending) {
324
+ if (this._videoPlayer)
325
+ this._videoPlayer.muted = true;
326
+ this._audioSource?.stop();
327
+ }
244
328
 
245
329
  for (const track of stream.getTracks()) {
246
330
  track.addEventListener("ended", () => {
@@ -260,10 +344,14 @@
260
344
 
261
345
  }
262
346
 
263
- private onReceiveVideo(evt: ReceiveVideoEvent) {
347
+ private onReceiveStream = (evt: StreamReceivedEvent) => {
264
348
  if (evt.stream?.active !== true) return;
265
- this.setVideo(evt.stream, ScreenCaptureMode.Receiving);
349
+ this.setStream(evt.stream, ScreenCaptureMode.Receiving);
266
350
  }
351
+ private onCallEnded = (_evt: StreamEndedEvent) => {
352
+ if (debug) console.log("CALL ENDED", this.isReceiving, this?.screenspace)
353
+ if (this.isReceiving) this.screenspace = false;
354
+ }
267
355
 
268
356
 
269
357
 
@@ -298,7 +386,7 @@
298
386
  }
299
387
  const userMedia = await navigator.mediaDevices.getUserMedia(opts);
300
388
  if (this._requestOpen) {
301
- this.setVideo(userMedia, ScreenCaptureMode.Sending);
389
+ this.setStream(userMedia, ScreenCaptureMode.Sending);
302
390
  }
303
391
  else disposeStream(userMedia);
304
392
  if (debug)
@@ -324,431 +412,3 @@
324
412
  // }
325
413
  }
326
414
 
327
-
328
- /////// PEER
329
-
330
- enum PeerEvent {
331
- Connected = "peer-user-connected",
332
- ReceiveVideo = "receive-video",
333
- Disconnected = "peer-user-disconnected",
334
- UserJoined = "user-joined",
335
- }
336
-
337
- class ReceiveVideoEvent {
338
- readonly type = PeerEvent.ReceiveVideo;
339
- readonly stream: MediaStream;
340
- readonly target: CallHandle;
341
- constructor(stream: MediaStream, target: CallHandle) {
342
- this.stream = stream
343
- this.target = target;
344
- }
345
- }
346
-
347
- class PeerUserConnectedModel implements IModel {
348
- /** the peer handle id */
349
- readonly guid: string;
350
- readonly peerId: string;
351
- // internal so server doesnt save it to persistent storage
352
- readonly dontSave: boolean = true;
353
- constructor(handle: PeerHandle, peerId: string) {
354
- this.guid = handle.id;
355
- this.peerId = peerId;
356
- }
357
- }
358
-
359
- enum CallDirection {
360
- Incoming = "incoming",
361
- Outgoing = "outgoing",
362
- }
363
-
364
- class CallHandle extends EventDispatcher {
365
- readonly userId: string;
366
- readonly direction: CallDirection;
367
- readonly call: MediaConnection;
368
- get stream() { return this._stream; };
369
-
370
- private _stream: MediaStream | null = null;
371
- private _isDisposed: boolean = false;
372
-
373
- close() {
374
- if (this._isDisposed) return;
375
- this._isDisposed = true;
376
- this.call.close();
377
- disposeStream(this._stream);
378
- }
379
-
380
- get isOpen() {
381
- return this.call.peerConnection?.connectionState === "connected";// && this._stream?.active;
382
- }
383
-
384
- get isClosed() {
385
- return !this.isOpen;
386
- }
387
-
388
- constructor(userId: string, call: MediaConnection, direction: CallDirection) {
389
- super();
390
- this.userId = userId;
391
- this.call = call;
392
- this.direction = direction;
393
- this._stream = null;
394
- call.on("stream", stream => {
395
- if (debug)
396
- console.log("Receive video", stream.getAudioTracks(), stream.getVideoTracks());
397
- this._stream = stream;
398
- if (direction === CallDirection.Incoming) {
399
- const args: ReceiveVideoEvent = new ReceiveVideoEvent(stream, this);
400
- this.dispatchEvent(args);
401
- }
402
- });
403
- }
404
- }
405
-
406
- class PeerHandle extends EventDispatcher {
407
-
408
- private static readonly instances: Map<string, PeerHandle> = new Map();
409
-
410
- static getOrCreate(context: Context, guid: string): PeerHandle {
411
- // if (id === undefined) {
412
- // // randomId
413
- // id = Math.random().toFixed(5);
414
- // }
415
- if (PeerHandle.instances.has(guid))
416
- return PeerHandle.instances.get(guid)!;
417
- const peer = new PeerHandle(context, guid);
418
- PeerHandle.instances.set(guid, peer);
419
- return peer;
420
- }
421
-
422
- getMyPeerId(): string | undefined {
423
- if (this.context.connection.connectionId)
424
- return this.getPeerIdFromUserId(this.context.connection.connectionId);
425
- return undefined;
426
- }
427
-
428
- getPeerIdFromUserId(userConnectionId: string): string {
429
- // we build the peer id ourselves so we dont need to wait for peer to report it
430
- return this.id + "-" + userConnectionId;
431
- }
432
-
433
- getUserIdFromPeerId(peerId: string): string {
434
- return peerId.substring(this.id.length + 1);
435
- }
436
-
437
- makeCall(peerId: string, stream: MediaStream): CallHandle | undefined {
438
- const opts = { metadata: { userId: this.context.connection.connectionId } };
439
- const call = this._peer?.call(peerId, stream, opts);
440
- if (call)
441
- return this.registerCall(call, CallDirection.Outgoing);
442
- return undefined;
443
- }
444
-
445
- get peer(): Peer | undefined { return this._peer; }
446
-
447
- readonly id: string;
448
- readonly context: Context;
449
- private _peer: Peer | undefined;
450
- private _incomingCalls: CallHandle[] = [];
451
- private _outgoingCalls: CallHandle[] = [];
452
-
453
- private constructor(context: Context, id: string) {
454
- super();
455
- this.context = context;
456
- this.id = id;
457
- this.setupPeer();
458
- navigator["getUserMedia"] = (
459
- navigator["getUserMedia"] || navigator["webkitGetUserMedia"] ||
460
- navigator["mozGetUserMedia"] || navigator["msGetUserMedia"]
461
- );
462
- }
463
-
464
- private _enabled: boolean = false;
465
- private _enabledPeer: boolean = false;
466
- private onConnectRoomFn: Function = this.onConnectRoom.bind(this);
467
- // private onUserJoinedOrLeftRoomFn: Function = this.onUserJoinedOrLeftRoom.bind(this);
468
- private onPeerConnectFn: (id) => void = this.onPeerConnect.bind(this);
469
- private onPeerReceiveCallFn: (call) => void = this.onPeerReceivingCall.bind(this);
470
- // private _connectionPeerIdMap : Map<string, string> = new Map();
471
-
472
- enable() {
473
- if (this._enabled) return;
474
- this._enabled = true;
475
- this.context.connection.beginListen(RoomEvents.JoinedRoom, this.onConnectRoomFn);
476
- // this.context.connection.beginListen(RoomEvents.UserJoinedRoom, this.onUserJoinedOrLeftRoomFn);
477
- // this.context.connection.beginListen(RoomEvents.UserLeftRoom, this.onUserJoinedOrLeftRoomFn);
478
- this.subscribePeerEvents();
479
- }
480
-
481
- disable() {
482
- if (!this._enabled) return;
483
- this._enabled = false;
484
- this.context.connection.stopListen(RoomEvents.JoinedRoom, this.onConnectRoomFn);
485
- // this.context.connection.stopListen(RoomEvents.UserJoinedRoom, this.onUserJoinedOrLeftRoomFn);
486
- // this.context.connection.stopListen(RoomEvents.UserLeftRoom, this.onUserJoinedOrLeftRoomFn);
487
- this.unsubscribePeerEvents();
488
- }
489
-
490
- private onConnectRoom(): void {
491
- this.setupPeer();
492
- };
493
-
494
- // private onUserJoinedOrLeftRoom(_: UserJoinedOrLeftRoomModel): void {
495
- // };
496
-
497
- private setupPeer() {
498
- if (!this.context.connection.connectionId) return;
499
- if (this._enabledPeer) return;
500
- this._enabledPeer = true;
501
- if (!this._peer) {
502
- const peerId = this.getMyPeerId();
503
- if (peerId)
504
- this._peer = getPeerjsInstance(peerId);
505
- else console.error("Failed to setup peerjs because we dont have a connection id", this.context.connection.connectionId);
506
- }
507
- if (this._enabled)
508
- this.subscribePeerEvents();
509
- }
510
-
511
- private subscribePeerEvents() {
512
- if (!this._peer) return;
513
- this._peer.on("open", this.onPeerConnectFn);
514
- this._peer.on("call", this.onPeerReceiveCallFn);
515
- // this.context.connection.beginListen(PeerEvent.Connected, this.onRemotePeerConnect.bind(this));
516
- // TODO: make connection to all current active calls even if the user is not anymore in the needle room
517
- }
518
-
519
- private unsubscribePeerEvents() {
520
- if (!this._peer) return;
521
- this._peer.off("open", this.onPeerConnectFn);
522
- this._peer.off("call", this.onPeerReceiveCallFn);
523
- // this.context.connection.stopListen(PeerEvent.Connected, this.onRemotePeerConnect.bind(this));
524
- }
525
-
526
- private onPeerConnect(id): void {
527
- if (debug)
528
- console.log("Peer connected as", id);
529
- this.context.connection.send(PeerEvent.Connected, new PeerUserConnectedModel(this, id));
530
- }
531
-
532
- private onPeerReceivingCall(call: MediaConnection): void {
533
- call.answer();
534
- this.registerCall(call, CallDirection.Incoming);
535
- }
536
-
537
- private registerCall(call: MediaConnection, direction: CallDirection): CallHandle {
538
-
539
- const meta = call.metadata;
540
- if (!meta || !meta.userId) {
541
- console.error("Missing call metadata", call);
542
- }
543
- const userId = meta.userId;
544
-
545
- if (direction === CallDirection.Incoming && debug) console.log("Receive call from", call.metadata);
546
- else if (debug) console.log("Make call to", call.metadata);
547
-
548
- const arr = direction === CallDirection.Incoming ? this._incomingCalls : this._outgoingCalls;
549
- const handle = new CallHandle(userId, call, direction);
550
- arr.push(handle);
551
- call.on("error", err => {
552
- console.error("Call error", err);
553
- });
554
- call.on("close", () => {
555
- if (debug)
556
- console.log("Call ended", call.metadata);
557
- call.close();
558
- const index = arr.indexOf(handle);
559
- if (index !== -1)
560
- arr.splice(index, 1);
561
- });
562
-
563
- if (direction === CallDirection.Incoming) {
564
-
565
- handle.addEventListener(PeerEvent.ReceiveVideo, e => {
566
- this.dispatchEvent(e);
567
- });
568
-
569
- call.on("stream", () => {
570
- // workaround for https://github.com/peers/peerjs/issues/636
571
- let intervalCounter = 0;
572
- const closeInterval = setInterval(() => {
573
- const isFirstInterval = intervalCounter === 0;
574
- if (!handle.isOpen && isFirstInterval) {
575
- intervalCounter += 1;
576
- clearInterval(closeInterval);
577
- handle.close();
578
- }
579
- }, 2000);
580
- });
581
- }
582
- return handle;
583
- }
584
-
585
- // private onRemotePeerConnect(user: PeerUserConnectedModel) {
586
- // console.log("other user connected", user);
587
- // }
588
- }
589
-
590
-
591
- // type UserVideoCall = {
592
- // call: Peer.MediaConnection;
593
- // stream: MediaStream;
594
- // userId: string;
595
- // }
596
-
597
- // type IncomingStreamArgs = {
598
- // stream: MediaStream;
599
- // userId: string;
600
- // }
601
-
602
- class NetworkedVideo extends EventDispatcher {
603
-
604
- private readonly context: Context;
605
- private readonly peer: PeerHandle;
606
-
607
- // private _receiveVideoStreamListeners: Array<(info: IncomingStreamArgs) => void> = [];
608
- private _sendingVideoStreams: Map<MediaStream, CallHandle[]> = new Map();
609
-
610
- constructor(context: Context, peer: PeerHandle) {
611
- super();
612
- this.context = context;
613
- this.peer = peer;
614
- }
615
-
616
- startSendingVideo(stream: MediaStream) {
617
- if (!this._sendingVideoStreams.has(stream)) {
618
- this._sendingVideoStreams.set(stream, []);
619
- this.updateSendingCalls();
620
- };
621
- }
622
-
623
- stopSendingVideo(_steam: MediaStream | undefined | null) {
624
- if (_steam) {
625
- const calls = this._sendingVideoStreams.get(_steam);
626
- if (calls) {
627
- if (debug)
628
- console.log("Closing calls", calls);
629
- for (const call of calls) {
630
- call.close();
631
- }
632
- }
633
- this._sendingVideoStreams.delete(_steam);
634
- if (calls && debug)
635
- console.log("Currently sending", this._sendingVideoStreams);
636
- }