@needle-tools/engine 2.52.0-pre → 2.54.2-pre

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (220) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/dist/needle-engine.d.ts +3018 -2680
  3. package/dist/needle-engine.js +439 -439
  4. package/dist/needle-engine.js.map +4 -4
  5. package/dist/needle-engine.min.js +41 -41
  6. package/dist/needle-engine.min.js.map +4 -4
  7. package/dist/needle-engine.tsbuildinfo +1 -0
  8. package/lib/engine/codegen/register_types.d.ts +1 -0
  9. package/lib/engine/codegen/register_types.js +346 -0
  10. package/lib/engine/codegen/register_types.js.map +1 -0
  11. package/lib/engine/debug/debug.d.ts +1 -0
  12. package/lib/engine/debug/debug.js +4 -0
  13. package/lib/engine/debug/debug.js.map +1 -1
  14. package/lib/engine/debug/debug_console.js +2 -1
  15. package/lib/engine/debug/debug_console.js.map +1 -1
  16. package/lib/engine/debug/debug_overlay.js +3 -1
  17. package/lib/engine/debug/debug_overlay.js.map +1 -1
  18. package/lib/engine/engine_components.js +2 -2
  19. package/lib/engine/engine_components.js.map +1 -1
  20. package/lib/engine/engine_default_parameters.d.ts +2 -2
  21. package/lib/engine/engine_element.js +4 -2
  22. package/lib/engine/engine_element.js.map +1 -1
  23. package/lib/engine/engine_element_loading.d.ts +1 -0
  24. package/lib/engine/engine_element_loading.js +17 -6
  25. package/lib/engine/engine_element_loading.js.map +1 -1
  26. package/lib/engine/engine_element_overlay.js +4 -2
  27. package/lib/engine/engine_element_overlay.js.map +1 -1
  28. package/lib/engine/engine_fileloader.d.ts +3 -0
  29. package/lib/engine/engine_fileloader.js +8 -0
  30. package/lib/engine/engine_fileloader.js.map +1 -0
  31. package/lib/engine/engine_generic_utils.d.ts +1 -0
  32. package/lib/engine/engine_generic_utils.js +14 -0
  33. package/lib/engine/engine_generic_utils.js.map +1 -0
  34. package/lib/engine/engine_input.js +4 -0
  35. package/lib/engine/engine_input.js.map +1 -1
  36. package/lib/engine/engine_networking_instantiate.d.ts +1 -1
  37. package/lib/engine/engine_networking_instantiate.js +3 -0
  38. package/lib/engine/engine_networking_instantiate.js.map +1 -1
  39. package/lib/engine/engine_networking_websocket.d.ts +1 -0
  40. package/lib/engine/engine_networking_websocket.js +1 -1
  41. package/lib/engine/engine_networking_websocket.js.map +1 -1
  42. package/lib/engine/engine_serialization_builtin_serializer.d.ts +6 -0
  43. package/lib/engine/engine_serialization_builtin_serializer.js +35 -7
  44. package/lib/engine/engine_serialization_builtin_serializer.js.map +1 -1
  45. package/lib/engine/engine_serialization_core.d.ts +1 -0
  46. package/lib/engine/engine_serialization_core.js +6 -0
  47. package/lib/engine/engine_serialization_core.js.map +1 -1
  48. package/lib/engine/engine_setup.js +2 -2
  49. package/lib/engine/engine_setup.js.map +1 -1
  50. package/lib/engine/engine_texture.d.ts +3 -0
  51. package/lib/engine/engine_texture.js +4 -0
  52. package/lib/engine/engine_texture.js.map +1 -0
  53. package/lib/engine/engine_utils.d.ts +1 -1
  54. package/lib/engine/engine_utils.js +3 -0
  55. package/lib/engine/engine_utils.js.map +1 -1
  56. package/lib/engine/extensions/NEEDLE_components.d.ts +1 -1
  57. package/lib/engine/extensions/NEEDLE_progressive.d.ts +40 -0
  58. package/lib/engine/extensions/NEEDLE_progressive.js +322 -0
  59. package/lib/engine/extensions/NEEDLE_progressive.js.map +1 -0
  60. package/lib/engine/extensions/extensions.js +2 -2
  61. package/lib/engine/extensions/extensions.js.map +1 -1
  62. package/lib/engine-components/Camera.js +17 -2
  63. package/lib/engine-components/Camera.js.map +1 -1
  64. package/lib/engine-components/GroundProjection.d.ts +2 -1
  65. package/lib/engine-components/GroundProjection.js +19 -12
  66. package/lib/engine-components/GroundProjection.js.map +1 -1
  67. package/lib/engine-components/Light.js +1 -0
  68. package/lib/engine-components/Light.js.map +1 -1
  69. package/lib/engine-components/OrbitControls.js +6 -2
  70. package/lib/engine-components/OrbitControls.js.map +1 -1
  71. package/lib/engine-components/ParticleSystemModules.d.ts +1 -1
  72. package/lib/engine-components/ParticleSystemModules.js +48 -44
  73. package/lib/engine-components/ParticleSystemModules.js.map +1 -1
  74. package/lib/engine-components/ReflectionProbe.d.ts +1 -1
  75. package/lib/engine-components/Renderer.d.ts +1 -1
  76. package/lib/engine-components/Renderer.js +4 -9
  77. package/lib/engine-components/Renderer.js.map +1 -1
  78. package/lib/engine-components/Voip.js +13 -4
  79. package/lib/engine-components/Voip.js.map +1 -1
  80. package/lib/engine-components/Volume.js +8 -1
  81. package/lib/engine-components/Volume.js.map +1 -1
  82. package/lib/engine-components/WebXR.d.ts +2 -2
  83. package/lib/engine-components/WebXRAvatar.d.ts +1 -1
  84. package/lib/engine-components/codegen/components.d.ts +99 -95
  85. package/lib/engine-components/codegen/components.js +99 -95
  86. package/lib/engine-components/codegen/components.js.map +1 -1
  87. package/lib/engine-components/export/{GltfExport.d.ts → gltf/GltfExport.d.ts} +2 -2
  88. package/lib/engine-components/export/{GltfExport.js → gltf/GltfExport.js} +7 -7
  89. package/lib/engine-components/export/gltf/GltfExport.js.map +1 -0
  90. package/lib/engine-components/export/usdz/Extension.d.ts +9 -0
  91. package/lib/engine-components/export/usdz/Extension.js +2 -0
  92. package/lib/engine-components/export/usdz/Extension.js.map +1 -0
  93. package/lib/engine-components/export/usdz/USDZExporter.d.ts +26 -0
  94. package/lib/engine-components/export/usdz/USDZExporter.js +209 -0
  95. package/lib/engine-components/export/usdz/USDZExporter.js.map +1 -0
  96. package/lib/engine-components/export/usdz/extensions/Animation.d.ts +44 -0
  97. package/lib/engine-components/export/usdz/extensions/Animation.js +264 -0
  98. package/lib/engine-components/export/usdz/extensions/Animation.js.map +1 -0
  99. package/lib/engine-components/export/usdz/types.d.ts +34 -0
  100. package/lib/engine-components/export/usdz/types.js +2 -0
  101. package/lib/engine-components/export/usdz/types.js.map +1 -0
  102. package/lib/engine-components/export/usdz/utils/animationutils.d.ts +3 -0
  103. package/lib/engine-components/export/usdz/utils/animationutils.js +46 -0
  104. package/lib/engine-components/export/usdz/utils/animationutils.js.map +1 -0
  105. package/lib/engine-components/export/usdz/utils/quicklook.d.ts +2 -0
  106. package/lib/engine-components/export/usdz/utils/quicklook.js +36 -0
  107. package/lib/engine-components/export/usdz/utils/quicklook.js.map +1 -0
  108. package/lib/engine-components/export/usdz/utils/timeutils.d.ts +1 -0
  109. package/lib/engine-components/export/usdz/utils/timeutils.js +15 -0
  110. package/lib/engine-components/export/usdz/utils/timeutils.js.map +1 -0
  111. package/lib/engine-components/ui/Button.js +30 -0
  112. package/lib/engine-components/ui/Button.js.map +1 -1
  113. package/lib/engine-components/ui/Graphic.d.ts +2 -0
  114. package/lib/engine-components/ui/Graphic.js +15 -0
  115. package/lib/engine-components/ui/Graphic.js.map +1 -1
  116. package/lib/engine-components/ui/InputField.d.ts +2 -0
  117. package/lib/engine-components/ui/InputField.js +23 -1
  118. package/lib/engine-components/ui/InputField.js.map +1 -1
  119. package/lib/engine-components/ui/Utils.d.ts +4 -1
  120. package/lib/engine-components/ui/Utils.js +15 -12
  121. package/lib/engine-components/ui/Utils.js.map +1 -1
  122. package/lib/engine-components-experimental/Presentation.d.ts +6 -0
  123. package/lib/engine-components-experimental/Presentation.js +11 -0
  124. package/lib/engine-components-experimental/Presentation.js.map +1 -0
  125. package/lib/engine-components-experimental/annotation/LineDrawer.d.ts +18 -0
  126. package/lib/engine-components-experimental/annotation/LineDrawer.js +175 -0
  127. package/lib/engine-components-experimental/annotation/LineDrawer.js.map +1 -0
  128. package/lib/engine-components-experimental/annotation/LinesManager.d.ts +54 -0
  129. package/lib/engine-components-experimental/annotation/LinesManager.js +155 -0
  130. package/lib/engine-components-experimental/annotation/LinesManager.js.map +1 -0
  131. package/lib/engine-components-experimental/networking/PlayerSync.d.ts +26 -0
  132. package/lib/engine-components-experimental/networking/PlayerSync.js +121 -0
  133. package/lib/engine-components-experimental/networking/PlayerSync.js.map +1 -0
  134. package/lib/engine-schemes/vec2.d.ts +10 -0
  135. package/lib/engine-schemes/vec2.js +26 -0
  136. package/lib/engine-schemes/vec2.js.map +1 -0
  137. package/lib/include/three/ARButton.d.ts +3 -0
  138. package/lib/include/three/ARButton.js +158 -0
  139. package/lib/include/three/ARButton.js.map +1 -0
  140. package/lib/include/three/EXT_mesh_gpu_instancing_exporter.d.ts +6 -0
  141. package/lib/include/three/EXT_mesh_gpu_instancing_exporter.js +46 -0
  142. package/lib/include/three/EXT_mesh_gpu_instancing_exporter.js.map +1 -0
  143. package/lib/include/three/VRButton.d.ts +5 -0
  144. package/lib/include/three/VRButton.js +122 -0
  145. package/lib/include/three/VRButton.js.map +1 -0
  146. package/lib/tsconfig.tsbuildinfo +1 -0
  147. package/package.json +2 -2
  148. package/src/engine/codegen/register_types.js +212 -204
  149. package/src/engine/debug/debug.ts +5 -0
  150. package/src/engine/debug/debug_console.ts +3 -2
  151. package/src/engine/debug/debug_overlay.ts +3 -1
  152. package/src/engine/engine_components.ts +2 -2
  153. package/src/engine/engine_element.ts +4 -2
  154. package/src/engine/engine_element_loading.ts +13 -6
  155. package/src/engine/engine_element_overlay.ts +4 -2
  156. package/src/engine/engine_input.ts +4 -0
  157. package/src/engine/engine_networking_instantiate.ts +4 -1
  158. package/src/engine/engine_networking_websocket.ts +3 -1
  159. package/src/engine/engine_serialization_builtin_serializer.ts +39 -8
  160. package/src/engine/engine_serialization_core.ts +7 -1
  161. package/src/engine/engine_setup.ts +2 -2
  162. package/src/engine/engine_texture.ts +6 -0
  163. package/src/engine/engine_utils.ts +3 -1
  164. package/src/engine/extensions/NEEDLE_progressive.ts +357 -0
  165. package/src/engine/extensions/extensions.ts +2 -2
  166. package/src/engine-components/Camera.ts +17 -3
  167. package/src/engine-components/GroundProjection.ts +18 -12
  168. package/src/engine-components/Light.ts +3 -1
  169. package/src/engine-components/OrbitControls.ts +7 -3
  170. package/src/engine-components/ParticleSystemModules.ts +50 -47
  171. package/src/engine-components/Renderer.ts +6 -10
  172. package/src/engine-components/Voip.ts +14 -4
  173. package/src/engine-components/Volume.ts +8 -1
  174. package/src/engine-components/WebXR.ts +2 -2
  175. package/src/engine-components/codegen/components.ts +99 -95
  176. package/src/engine-components/export/{GltfExport.ts → gltf/GltfExport.ts} +7 -7
  177. package/src/engine-components/export/usdz/Extension.ts +12 -0
  178. package/src/engine-components/export/usdz/USDZExporter.ts +233 -0
  179. package/src/engine-components/export/usdz/extensions/Animation.ts +306 -0
  180. package/src/engine-components/export/usdz/types.ts +39 -0
  181. package/src/engine-components/export/usdz/utils/animationutils.ts +60 -0
  182. package/src/engine-components/export/usdz/utils/quicklook.ts +43 -0
  183. package/src/engine-components/export/usdz/utils/timeutils.ts +20 -0
  184. package/src/engine-components/ui/Button.ts +8 -8
  185. package/src/engine-components/ui/Graphic.ts +15 -1
  186. package/src/engine-components/ui/InputField.ts +25 -2
  187. package/src/engine-components/ui/Utils.ts +17 -14
  188. package/src/engine-components-experimental/annotation/LineDrawer.ts +10 -7
  189. package/src/engine-components-experimental/annotation/LinesManager.ts +6 -6
  190. package/src/engine-components-experimental/networking/PlayerSync.ts +1 -1
  191. package/lib/engine/engine_caching.d.ts +0 -0
  192. package/lib/engine/engine_caching.js +0 -2
  193. package/lib/engine/engine_caching.js.map +0 -1
  194. package/lib/engine/extensions/NEEDLE_deferred_texture.d.ts +0 -18
  195. package/lib/engine/extensions/NEEDLE_deferred_texture.js +0 -194
  196. package/lib/engine/extensions/NEEDLE_deferred_texture.js.map +0 -1
  197. package/lib/engine/tests/simulate_avatars.d.ts +0 -0
  198. package/lib/engine/tests/simulate_avatars.js +0 -3
  199. package/lib/engine/tests/simulate_avatars.js.map +0 -1
  200. package/lib/engine-components/NavMesh.d.ts +0 -0
  201. package/lib/engine-components/NavMesh.js +0 -101
  202. package/lib/engine-components/NavMesh.js.map +0 -1
  203. package/lib/engine-components/ParticleSystemBehaviours.d.ts +0 -0
  204. package/lib/engine-components/ParticleSystemBehaviours.js +0 -2
  205. package/lib/engine-components/ParticleSystemBehaviours.js.map +0 -1
  206. package/lib/engine-components/SpringJoint.d.ts +0 -0
  207. package/lib/engine-components/SpringJoint.js +0 -43
  208. package/lib/engine-components/SpringJoint.js.map +0 -1
  209. package/lib/engine-components/export/GltfExport.js.map +0 -1
  210. package/lib/engine-components/ui/CanvasScaler.d.ts +0 -0
  211. package/lib/engine-components/ui/CanvasScaler.js +0 -17
  212. package/lib/engine-components/ui/CanvasScaler.js.map +0 -1
  213. package/src/engine/dist/engine_three_utils.js +0 -279
  214. package/src/engine/engine_caching.ts +0 -0
  215. package/src/engine/extensions/NEEDLE_deferred_texture.ts +0 -217
  216. package/src/engine/tests/simulate_avatars.ts +0 -2
  217. package/src/engine-components/NavMesh.ts +0 -117
  218. package/src/engine-components/ParticleSystemBehaviours.ts +0 -0
  219. package/src/engine-components/SpringJoint.ts +0 -45
  220. package/src/engine-components/ui/CanvasScaler.ts +0 -21
@@ -167,7 +167,8 @@ export class EngineElement extends HTMLElement implements INeedleEngineComponent
167
167
  }
168
168
  if (fn) {
169
169
  this.classList.add("loading");
170
- console.log("Needle Engine: Begin loading", alias ?? "");
170
+ if (debug)
171
+ console.log("Needle Engine: Begin loading", alias ?? "");
171
172
  const allowOverridingDefaultLoading = true;
172
173
  // default loading can be overriden by calling preventDefault in the onload start event
173
174
  const useDefaultLoading = this.dispatchEvent(new CustomEvent("loadstart", {
@@ -210,7 +211,8 @@ export class EngineElement extends HTMLElement implements INeedleEngineComponent
210
211
  this._loadingView?.onLoadingFinished("create scene");
211
212
  this.classList.remove("loading");
212
213
  this.classList.add("loading-finished");
213
- console.log("Needle Engine: finished loading", alias ?? "");
214
+ if (debug)
215
+ console.log("Needle Engine: finished loading", alias ?? "");
214
216
  this.dispatchEvent(new CustomEvent("loadfinished", {
215
217
  detail: {
216
218
  context: this._context,
@@ -4,6 +4,7 @@ import { LoadingProgressArgs } from "./engine_setup";
4
4
  import { getParam } from "./engine_utils";
5
5
 
6
6
  const debug = getParam("debugloadingbar");
7
+ const debugRendering = getParam("debugloadingbarrendering");
7
8
 
8
9
  export class LoadingElementOptions {
9
10
  className?: string;
@@ -43,12 +44,14 @@ export function calculateProgress01(progress: LoadingProgressArgs) {
43
44
 
44
45
  export class EngineLoadingView implements ILoadingViewHandler {
45
46
 
47
+ static LoadingContainerClassName = "loading";
48
+
46
49
  // the raw progress
47
50
  loadingProgress: number = 0;
48
51
 
49
52
  private container: HTMLElement;
50
53
  private _progress: number = 0;
51
- private _allowCustomLoadingElement: boolean = false;
54
+ private _allowCustomLoadingElement: boolean = true;
52
55
  private _loadingElement?: HTMLElement;
53
56
  private _loadingTextContainer: HTMLElement | null = null;
54
57
  private _loadingBar: HTMLElement | null = null;
@@ -61,20 +64,21 @@ export class EngineLoadingView implements ILoadingViewHandler {
61
64
  }
62
65
 
63
66
  onLoadingBegin(message?: string) {
67
+ if(debug) console.log("Begin Loading")
64
68
  if (!this._loadingElement) {
65
69
  for (let i = 0; i < this.container.children.length; i++) {
66
70
  const el = this.container.children[i] as HTMLElement;
67
- if (el.classList.contains("loading")) {
71
+ if (el.classList.contains(EngineLoadingView.LoadingContainerClassName)) {
68
72
  if (!this._allowCustomLoadingElement) {
69
- console.warn("Custom loading container is not allowed")
73
+ if(debug) console.warn("Remove custom loading container")
70
74
  this.container.removeChild(el);
71
75
  continue;
72
76
  }
73
77
  this._loadingElement = this.createLoadingElement(el);
74
- return;
75
78
  }
76
79
  }
77
- this._loadingElement = this.createLoadingElement();
80
+ if (!this._loadingElement)
81
+ this._loadingElement = this.createLoadingElement();
78
82
  }
79
83
  this._progress = 0;
80
84
  this.loadingProgress = 0;
@@ -121,9 +125,11 @@ export class EngineLoadingView implements ILoadingViewHandler {
121
125
  if (this._progressLoop) return;
122
126
  let dt = 1 / 12;
123
127
  const max = 1 - .05;
128
+ if(debugRendering) dt = 1 / 500;
124
129
  this._progressLoop = setInterval(() => {
125
130
  if (this.loadingProgress >= 1 && this._progress >= max) {
126
131
  if (this._loadingElement) {
132
+ if(debug) console.log("Hiding loading element");
127
133
  this._loadingElement.style.display = "none";
128
134
  this._loadingElement.remove();
129
135
  }
@@ -148,6 +154,7 @@ export class EngineLoadingView implements ILoadingViewHandler {
148
154
  }
149
155
 
150
156
  private createLoadingElement(existing?: HTMLElement): HTMLElement {
157
+ if(debug && !existing) console.log("Creating loading element");
151
158
  this._loadingElement = existing || document.createElement("div");
152
159
  if (!existing) {
153
160
  this._loadingElement.style.position = "fixed";
@@ -165,7 +172,7 @@ export class EngineLoadingView implements ILoadingViewHandler {
165
172
  this._loadingElement.style.color = "white";
166
173
  }
167
174
 
168
- const className = this._loadingElementOptions?.className ?? "loading";
175
+ const className = this._loadingElementOptions?.className ?? EngineLoadingView.LoadingContainerClassName;
169
176
  this._loadingElement.classList.add(className);
170
177
  if (this._loadingElementOptions?.additionalClasses) {
171
178
  for (const c of this._loadingElementOptions.additionalClasses) {
@@ -1,6 +1,7 @@
1
1
  import { Context } from "./engine_setup";
2
- import { isMozillaXR } from "./engine_utils";
2
+ import { getParam, isMozillaXR } from "./engine_utils";
3
3
 
4
+ const debug = getParam("debugaroverlay");
4
5
  export const arContainerClassName = "ar";
5
6
  export const quitARClassName = "quit-ar";
6
7
 
@@ -110,7 +111,8 @@ export class AROverlayHandler {
110
111
  if (arElements && arElements.length > 0)
111
112
  return arElements[0] as HTMLElement;
112
113
 
113
- console.log("No overlay container found in document - generating new ony");
114
+ if (debug)
115
+ console.log("No overlay container found in document - generating new ony");
114
116
  const el = document.createElement("div");
115
117
  el.classList.add(arContainerClassName);
116
118
  el.style.position = "absolute";
@@ -384,6 +384,8 @@ export class Input extends EventTarget {
384
384
  for (let i = 0; i < evt.changedTouches.length; i++) {
385
385
  const touch = evt.changedTouches[i];
386
386
  const id = this.getPointerIndex(touch.identifier)
387
+ if (debug)
388
+ showBalloonMessage(`touch start #${id}, identifier:${touch.identifier}`);
387
389
  const args: PointerEventArgs = { button: id, clientX: touch.clientX, clientY: touch.clientY, pointerType: PointerType.Touch, source: evt };
388
390
  this.onDown(args);
389
391
  }
@@ -404,6 +406,8 @@ export class Input extends EventTarget {
404
406
  for (let i = 0; i < evt.changedTouches.length; i++) {
405
407
  const touch = evt.changedTouches[i];
406
408
  const id = this.getPointerIndex(touch.identifier)
409
+ if (debug)
410
+ showBalloonMessage(`touch up #${id}, identifier:${touch.identifier}`);
407
411
  const args: PointerEventArgs = { button: id, clientX: touch.clientX, clientY: touch.clientY, pointerType: PointerType.Touch, source: evt };
408
412
  this.onUp(args);
409
413
  }
@@ -35,7 +35,10 @@ export class InstantiateIdProvider implements UIDProvider {
35
35
  private _originalSeed: number;
36
36
  private _seed: number;
37
37
 
38
- constructor(seed: number) {
38
+ constructor(seed: string | number) {
39
+ if (typeof seed === "string") {
40
+ seed = InstantiateIdProvider.hash(seed);
41
+ }
39
42
  this._originalSeed = seed;
40
43
  this._seed = seed;
41
44
  }
@@ -1 +1,3 @@
1
- // TODO: move websocket specific networking code here!
1
+ // TODO: move websocket specific networking code here!
2
+
3
+ export {}
@@ -4,7 +4,9 @@ import { SerializationContext, TypeSerializer } from "./engine_serialization_cor
4
4
  import { Behaviour, Component, GameObject } from "../engine-components/Component";
5
5
  import { debugExtension } from "./engine_default_parameters";
6
6
  import { CallInfo, EventList } from "../engine-components/EventList";
7
- import { Color, Object3D } from "three";
7
+ import { Color, Object3D, Texture, WebGLRenderTarget } from "three";
8
+ import { RenderTexture } from "./engine_texture";
9
+ import { isDevEnvironment } from "../engine/debug/debug";
8
10
 
9
11
  // export class SourcePath {
10
12
  // src?:string
@@ -96,7 +98,11 @@ class ObjectSerializer extends TypeSerializer {
96
98
  if (!res) {
97
99
  res = GameObject.findByGuid(data.guid, context.context.scene);
98
100
  }
99
- if (!res) console.warn("could not resolve reference", data, context.target, context.path, context.context.scene);
101
+ if (!res) {
102
+ if (isDevEnvironment() || debugExtension)
103
+ console.warn("Could not resolve object reference", context.path, data, context.target, context.context.scene);
104
+ data["could_not_resolve"] = true;
105
+ }
100
106
  else if (debugExtension)
101
107
  console.log("Deserialized object reference?", data, res, context?.nodeToObject);
102
108
  return res;
@@ -129,15 +135,20 @@ class ComponentSerializer extends TypeSerializer {
129
135
  console.log(data.guid, context.root, context.object, context.target);
130
136
  // first search within the gltf (e.g. necessary when using AssetReference and loading a gltf without adding it to the scene)
131
137
  // if we would search JUST the scene those references would NEVER be resolved
132
- const res = this.findObjectForGuid(data.guid, context.root);
138
+ let res = this.findObjectForGuid(data.guid, context.root);
133
139
  if (res) {
134
140
  return res;
135
141
  }
136
- else if (context.context) {
142
+ if (context.context) {
137
143
  // if not found within the gltf use the provided context scene
138
144
  // to find references outside
139
- return this.findObjectForGuid(data.guid, context.context?.scene);
145
+ res = this.findObjectForGuid(data.guid, context.context?.scene);
146
+ if (res) return res;
140
147
  }
148
+ if (isDevEnvironment() || debugExtension)
149
+ console.warn("Could not resolve component reference", context.path, data, context.target);
150
+ data["could_not_resolve"] = true;
151
+ return undefined;
141
152
  }
142
153
  // if (data?.node !== undefined && context.nodeToObject) {
143
154
  // return context.nodeToObject[data.node];
@@ -191,8 +202,7 @@ class EventListSerializer extends TypeSerializer {
191
202
 
192
203
  onDeserialize(data: EventListData, context: SerializationContext): EventList | undefined | null {
193
204
  // TODO: check that we dont accidentally deserialize methods to EventList objects. This is here to make is easy for react-three-fiber to just add props as { () => { } }
194
- if(typeof data === "function")
195
- {
205
+ if (typeof data === "function") {
196
206
  const evtList = new EventList([new CallInfo(data, true)]);
197
207
  return evtList;
198
208
  }
@@ -220,7 +230,7 @@ class EventListSerializer extends TypeSerializer {
220
230
  call.method = call.method.substring(4);
221
231
  if (target[call.method] !== undefined) foundMethod = true;
222
232
  }
223
- if (!foundMethod)
233
+ if (!foundMethod && (isDevEnvironment() || debugExtension))
224
234
  printWarningMethodNotFound();
225
235
  }
226
236
  }
@@ -284,3 +294,24 @@ class EventListSerializer extends TypeSerializer {
284
294
  }
285
295
  export const eventListSerializer = new EventListSerializer();
286
296
 
297
+
298
+
299
+ export class RenderTextureSerializer extends TypeSerializer {
300
+ constructor() {
301
+ super([RenderTexture, WebGLRenderTarget]);
302
+ }
303
+
304
+ onSerialize(_data: any, _context: SerializationContext) {
305
+ }
306
+
307
+ onDeserialize(data: any, context: SerializationContext) {
308
+ if (data instanceof Texture && context.type === RenderTexture) {
309
+ const tex = data as Texture;
310
+ const rt = new RenderTexture(tex.image.width, tex.image.height);
311
+ rt.texture = tex;
312
+ return rt;
313
+ }
314
+ return undefined;
315
+ }
316
+ }
317
+ new RenderTextureSerializer();
@@ -181,6 +181,7 @@ export class SerializationContext {
181
181
  objectToNode?: ObjectToNodeMap;
182
182
  context?: Context;
183
183
  path?: string;
184
+ type?: Constructor<any>;
184
185
  /** holds information if a field was undefined before serialization. This gives us info if we might want to warn the user about missing attributes */
185
186
  implementationInformation?: ImplementationInformation;
186
187
 
@@ -286,6 +287,7 @@ export function deserializeObject(obj: ISerializable, serializedData: object, co
286
287
  continue;
287
288
  }
288
289
 
290
+ context.type = undefined;
289
291
  context.path = key;
290
292
 
291
293
  if (serializedEntryInfo === null) {
@@ -376,6 +378,9 @@ function checkObjectAssignments(obj: any, serializedData: any, implementationInf
376
378
  if (typeof serialized === "object") {
377
379
  if (value === undefined || !value.isObject3D) {
378
380
  if (typeof serialized["node"] === "number" || typeof serialized["guid"] === "string") {
381
+ if (serialized["could_not_resolve"]) {
382
+ continue;
383
+ }
379
384
  const hasOtherKeys = value !== undefined && Object.keys(value).length > 1;
380
385
  if (!hasOtherKeys) {
381
386
  showBalloonMessage(`<strong>Missing serialization for object reference!</strong>\n\nPlease change to: \n@serializable(Object3D)\n${key}? : Object3D;\n\nin script ${typeName}.ts\n<a href="https://docs.needle.tools/serializable" target="_blank">documentation</a>`, LogType.Warn);
@@ -453,7 +458,8 @@ function deserializeObjectWithType(data: any, typeOrConstructor: Constructor<any
453
458
  console.error("Error in callback", err, data);
454
459
  }
455
460
  }
456
-
461
+ context.type = type;
462
+
457
463
  // e.g. when @serializable(Texture) and the texture is already resolved via json pointer from gltf
458
464
  // then we dont need to do anything else
459
465
  if (!typeIsFunction && currentValue instanceof type) return currentValue;
@@ -134,8 +134,8 @@ export class Context {
134
134
  private calculateBoundingClientRect() {
135
135
  // workaround for mozilla webXR viewer
136
136
  if (this.isInAR) {
137
- this._domX = window.innerWidth;
138
- this._domY = window.innerHeight;
137
+ this._domX = 0;
138
+ this._domY = 0;
139
139
  return;
140
140
  }
141
141
  if (this._boundingClientRectFrame === this.time.frame) return;
@@ -0,0 +1,6 @@
1
+ import { WebGLRenderTarget } from "three"
2
+
3
+ export class RenderTexture extends WebGLRenderTarget
4
+ {
5
+
6
+ }
@@ -52,7 +52,7 @@ export function getUrlParams() {
52
52
  return new URLSearchParams(window.location.search);
53
53
  }
54
54
 
55
- export function getParam(paramName: string): string | boolean {
55
+ export function getParam(paramName: string): string | boolean | number {
56
56
 
57
57
  if (saveParams && !requestedParams.includes(paramName))
58
58
  requestedParams.push(paramName);
@@ -60,6 +60,8 @@ export function getParam(paramName: string): string | boolean {
60
60
  if (urlParams.has(paramName)) {
61
61
  const val = urlParams.get(paramName);
62
62
  if (val) {
63
+ const num = Number(val);
64
+ if (!isNaN(num)) return num;
63
65
  return val;
64
66
  }
65
67
  else return true;
@@ -0,0 +1,357 @@
1
+ import { Material, Texture, TextureLoader } from "three";
2
+ import { GLTF, GLTFLoader, GLTFLoaderPlugin, GLTFParser } from "three/examples/jsm/loaders/GLTFLoader";
3
+ import { SourceIdentifier } from "../engine_types";
4
+ import { Context } from "../engine_setup";
5
+ import { addDracoAndKTX2Loaders } from "../engine_loaders";
6
+ import { delay, getParam, getPath } from "../engine_utils";
7
+
8
+ export const EXTENSION_NAME = "NEEDLE_progressive";
9
+
10
+ const debug = getParam("debugprogressive");
11
+
12
+ declare type ProgressiveTextureSchema = {
13
+ uri: string;
14
+ guid: string;
15
+ }
16
+
17
+
18
+ const debug_toggle_maps: Map<Material, { [key: string]: { original: Texture, lod0: Texture } }> = new Map();
19
+ let show_lod0 = false;
20
+ if (debug) {
21
+ window.addEventListener("keyup", evt => {
22
+ if (evt.key === "p") {
23
+ debug_toggle_maps.forEach((map, material) => {
24
+ Object.entries(map).forEach(([key, value]) => {
25
+ if (show_lod0) {
26
+ material[key] = value.lod0;
27
+ } else {
28
+ material[key] = value.original;
29
+ }
30
+ material.needsUpdate = true;
31
+ });
32
+ });
33
+ show_lod0 = !show_lod0;
34
+ }
35
+ });
36
+ }
37
+
38
+ export class NEEDLE_progressive implements GLTFLoaderPlugin {
39
+
40
+ static assignTextureLOD(context: Context, source: SourceIdentifier | undefined, material: Material, level: number = 0) {
41
+ if (!material) return;
42
+ for (let slot of Object.keys(material)) {
43
+ const val = material[slot];
44
+ if (val?.isTexture === true) {
45
+
46
+ if (debug) console.log("-----------\n", "FIND", material.name, slot, val?.name, val?.userData, val, material);
47
+
48
+ NEEDLE_progressive.getOrLoadTexture(context, source, material, slot, val, level).then(t => {
49
+ if (t?.isTexture === true) {
50
+
51
+ if (debug) console.log("Assign LOD", material.name, slot, t.name, t["guid"], material, "Prev:", val, "Now:", t, "\n--------------");
52
+
53
+ material[slot] = t;
54
+ t.needsUpdate = true;
55
+ material.needsUpdate = true;
56
+
57
+ if (debug) {
58
+ let debug_map = debug_toggle_maps.get(material);
59
+ if (!debug_map) {
60
+ debug_map = {};
61
+ debug_toggle_maps.set(material, debug_map);
62
+ }
63
+ let entry = debug_map[slot];
64
+ if (!entry) {
65
+ entry = debug_map[slot] = { original: val, lod0: t };
66
+ }
67
+ entry.lod0 = t;
68
+ }
69
+ }
70
+ });
71
+ }
72
+ }
73
+ }
74
+
75
+ get name(): string {
76
+ return EXTENSION_NAME;
77
+ }
78
+
79
+ private parser: GLTFParser;
80
+ private sourceId: SourceIdentifier;
81
+ private context: Context;
82
+
83
+ constructor(parser: GLTFParser, sourceId: SourceIdentifier, context: Context) {
84
+ this.parser = parser;
85
+ this.sourceId = sourceId;
86
+ this.context = context;
87
+ }
88
+
89
+ private _loading: number[] = [];
90
+
91
+ // beforeRoot(): null {
92
+ // console.log("BEFORE ROOT", this.parser);
93
+ // return null;
94
+ // }
95
+
96
+ // loadTexture(index: number): Promise<Texture> | null {
97
+ // console.log(index, this._loading);
98
+ // if (this._loading.includes(index)) return null;
99
+ // const textureInfo = this.parser.json.textures[index];
100
+ // if (debug)
101
+ // console.log(index, textureInfo);
102
+ // return null;
103
+ // }
104
+
105
+ afterRoot(gltf: GLTF): null {
106
+ if (debug)
107
+ console.log("AFTER", this.sourceId, gltf);
108
+ this.parser.json.textures?.forEach((textureInfo, index) => {
109
+ if (textureInfo?.extensions) {
110
+ const ext: ProgressiveTextureSchema = textureInfo?.extensions[EXTENSION_NAME];
111
+ if (ext) {
112
+ const prom = this.parser.getDependency("texture", index);
113
+ this._loading.splice(this._loading.indexOf(index), 1);
114
+ prom.then(t => {
115
+ if (debug) console.log("register texture", t.name, t.uuid, ext);
116
+ t.userData.deferred = ext;
117
+ NEEDLE_progressive.cache.set(t.uuid, ext);
118
+ });
119
+ }
120
+ }
121
+ });
122
+
123
+ return null;
124
+ }
125
+
126
+ private static cache = new Map<string, ProgressiveTextureSchema>();
127
+ private static resolved: { [key: string]: Texture } = {};
128
+ private static currentlyLoading: { [key: string]: Promise<Texture | null> } = {};
129
+
130
+ private static async getOrLoadTexture(context: Context, source: SourceIdentifier | undefined, material: Material, slot: string, current: Texture, _level: number): Promise<Texture | null> {
131
+
132
+ const key = current.uuid;
133
+ const ext: ProgressiveTextureSchema | undefined = NEEDLE_progressive.cache.get(key);// || current.userData.deferred;
134
+ if (ext) {
135
+ if (debug)
136
+ console.log(key, ext.uri, ext.guid);
137
+ const uri = getPath(source, ext.uri);
138
+ if (uri.endsWith(".glb") || uri.endsWith(".gltf")) {
139
+ if (!ext.guid) {
140
+ console.warn("missing pointer for glb/gltf texture", ext);
141
+ return null;
142
+ }
143
+ const resolveKey = uri + "_" + ext.guid;
144
+ if (this.resolved[resolveKey]) {
145
+ if (debug) console.log("Texture has already been loaded: " + resolveKey, material.name, slot, current.name);
146
+ return this.resolved[resolveKey];
147
+ }
148
+
149
+ const info = this.onProgressiveLoadStart(context, source, uri, material, slot);
150
+ try {
151
+ if(this.currentlyLoading[resolveKey] !== undefined) {
152
+ if(debug)
153
+ console.log("Already loading:", material.name + "." + slot, resolveKey);
154
+ const tex = await this.currentlyLoading[resolveKey];
155
+ return tex;
156
+ }
157
+ const request = new Promise<Texture | null>(async (resolve, _) => {
158
+ const loader = new GLTFLoader();
159
+ addDracoAndKTX2Loaders(loader, context);
160
+
161
+ if (debug) console.log("Load " + uri, material.name, slot, ext.guid);
162
+ if (debug) {
163
+ await delay(Math.random() * 1000);
164
+ }
165
+
166
+ const gltf = await loader.loadAsync(uri);
167
+ const parser = gltf.parser;
168
+ if (debug) console.log("Loading finished " + uri, material.name, slot, ext.guid);
169
+ let index = -1;
170
+ let found = false;
171
+ for (const tex of gltf.parser.json.textures) {
172
+ index++;
173
+ if (tex?.extensions) {
174
+ const other: ProgressiveTextureSchema = tex?.extensions[EXTENSION_NAME];
175
+ if (other?.guid) {
176
+ if (other.guid === ext.guid) {
177
+ found = true;
178
+ break;
179
+ }
180
+ }
181
+ }
182
+ }
183
+ if (!found)
184
+ return resolve(null);
185
+
186
+ const tex = await parser.getDependency("texture", index);
187
+ tex.encoding = current.encoding;
188
+ if (tex) {
189
+ tex.guid = ext.guid;
190
+ }
191
+ this.resolved[resolveKey] = tex as Texture;
192
+ if (debug)
193
+ console.log(material.name, slot, "change \"" + current.name + "\" → \"" + tex.name + "\"", uri, index, tex, material, resolveKey);
194
+ resolve(tex);
195
+ });
196
+ this.currentlyLoading[resolveKey] = request;
197
+ const tex = await request;
198
+ return tex;
199
+ }
200
+ finally {
201
+ delete this.currentlyLoading[resolveKey];
202
+ this.onProgressiveLoadEnd(info);
203
+ }
204
+ }
205
+ else {
206
+ const info = this.onProgressiveLoadStart(context, source, uri, material, slot);
207
+ try {
208
+ if (debug) console.log("Load texture from uri: " + uri);
209
+ const loader = new TextureLoader();
210
+ const tex = await loader.loadAsync(uri);
211
+ if (tex) {
212
+ (tex as any).guid = ext.guid;
213
+ tex.flipY = false;
214
+ tex.needsUpdate = true;
215
+ tex.encoding = current.encoding;
216
+ if (debug)
217
+ console.log(ext, tex);
218
+ }
219
+ else if (debug) console.warn("failed loading", uri);
220
+ return tex;
221
+ }
222
+ finally {
223
+ this.onProgressiveLoadEnd(info);
224
+ }
225
+ }
226
+ // loader.then((h: Texture) => {
227
+ // // console.log(t, h);
228
+ // // t.image = h.image;
229
+ // // // this.context.renderer.copyTextureToTexture(new Vector2(0, 0), h, t);
230
+ // // // console.log(h);
231
+
232
+ // // // t.source = h.source;
233
+ // // // t.version++;
234
+ // // t.width = h.width;
235
+ // // t.height = h.height;
236
+ // // t.needsUpdate = true;
237
+ // });
238
+ }
239
+ else {
240
+ if (debug)
241
+ console.warn("unknown uuid", current.name, current.uuid, current);
242
+ }
243
+ return null;
244
+ }
245
+
246
+
247
+ /** subscribe to events whenever a loading event starts, invoked for every single loading process that starts */
248
+ static beginListenStart(context: Context, evt: ProgressiveLoadingEvent) {
249
+ if (!this._progressiveEventListeners.has(context)) {
250
+ this._progressiveEventListeners.set(context, new ProgressiveLoadingEventHandler());
251
+ }
252
+ this._progressiveEventListeners.get(context)!.start.push(evt);
253
+ }
254
+ static stopListenStart(context: Context, evt: ProgressiveLoadingEvent) {
255
+ if (!this._progressiveEventListeners.has(context)) {
256
+ return;
257
+ }
258
+ const listeners = this._progressiveEventListeners.get(context)!.start;
259
+ const index = listeners.indexOf(evt);
260
+ if (index >= 0) {
261
+ listeners.splice(index, 1);
262
+ }
263
+ }
264
+
265
+ /** subscribe to loading event ended event */
266
+ static beginListenEnd(context: Context, evt: ProgressiveLoadingEvent) {
267
+ if (!this._progressiveEventListeners.has(context)) {
268
+ this._progressiveEventListeners.set(context, new ProgressiveLoadingEventHandler());
269
+ }
270
+ this._progressiveEventListeners.get(context)!.end.push(evt);
271
+ }
272
+ static stopListenEnd(context: Context, evt: ProgressiveLoadingEvent) {
273
+ if (!this._progressiveEventListeners.has(context)) {
274
+ return;
275
+ }
276
+ const listeners = this._progressiveEventListeners.get(context)!.end;
277
+ const index = listeners.indexOf(evt);
278
+ if (index >= 0) {
279
+ listeners.splice(index, 1);
280
+ }
281
+ }
282
+
283
+ /** event listeners per context */
284
+ private static _progressiveEventListeners: Map<Context, ProgressiveLoadingEventHandler> = new Map();
285
+ //** loading info per context, contains an array of urls that are currently being loaded */
286
+ private static _currentProgressiveLoadingInfo: Map<Context, ProgressiveLoadingInfo[]> = new Map();
287
+
288
+ // called whenever a progressive loading event starts
289
+ private static onProgressiveLoadStart(context: Context, source: SourceIdentifier | undefined, uri: string, material: Material, slot: string): ProgressiveLoadingInfo {
290
+ if (!this._currentProgressiveLoadingInfo.has(context)) {
291
+ this._currentProgressiveLoadingInfo.set(context, []);
292
+ }
293
+ const info = new ProgressiveLoadingInfo(context, source, uri, material, slot);
294
+ const current = this._currentProgressiveLoadingInfo.get(context)!;
295
+ const listener = this._progressiveEventListeners.get(context);
296
+ if (listener) listener.onStart(info);
297
+
298
+ current.push(info);
299
+ return info;
300
+ }
301
+
302
+ private static onProgressiveLoadEnd(info: ProgressiveLoadingInfo) {
303
+ if (!info) return;
304
+ const context = info.context;
305
+ if (!this._currentProgressiveLoadingInfo.has(context)) {
306
+ return;
307
+ }
308
+ const current = this._currentProgressiveLoadingInfo.get(context)!;
309
+ const index = current.indexOf(info);
310
+ if (index < 0) {
311
+ return;
312
+ }
313
+ current.splice(index, 1);
314
+ const listener = this._progressiveEventListeners.get(context);
315
+ if (listener) listener.onEnd(info);
316
+ }
317
+ }
318
+
319
+
320
+ /** info object that holds information about a file that is currently being loaded */
321
+ export class ProgressiveLoadingInfo {
322
+ readonly context: Context;
323
+ readonly source: SourceIdentifier | undefined;
324
+ readonly uri: string;
325
+ readonly material?: Material;
326
+ readonly slot?: string;
327
+ // TODO: can contain information if the event is a background process / preloading or if the object is currently visible
328
+
329
+ constructor(context: Context, source: SourceIdentifier | undefined, uri: string, material?: Material, slot?: string) {
330
+ this.context = context;
331
+ this.source = source;
332
+ this.uri = uri;
333
+ this.material = material;
334
+ this.slot = slot;
335
+ }
336
+ };
337
+
338
+
339
+ export declare type ProgressiveLoadingEvent = (info: ProgressiveLoadingInfo) => void;
340
+
341
+ /** progressive loading event handler implementation */
342
+ class ProgressiveLoadingEventHandler {
343
+ start: ProgressiveLoadingEvent[] = [];
344
+ end: ProgressiveLoadingEvent[] = [];
345
+
346
+ onStart(listener: ProgressiveLoadingInfo) {
347
+ for (const l of this.start) {
348
+ l(listener);
349
+ }
350
+ }
351
+
352
+ onEnd(listener: ProgressiveLoadingInfo) {
353
+ for (const l of this.end) {
354
+ l(listener);
355
+ }
356
+ }
357
+ }