@needle-tools/engine 2.64.0-pre → 2.65.0-pre.1

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 (255) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/needle-engine.js +5083 -5055
  3. package/dist/needle-engine.umd.cjs +84 -84
  4. package/lib/engine/api.js.map +1 -1
  5. package/lib/engine/assets/index.js.map +1 -1
  6. package/lib/engine/assets/logo.svg +1 -0
  7. package/lib/engine/codegen/register_types.js +169 -169
  8. package/lib/engine/codegen/register_types.js.map +1 -1
  9. package/lib/engine/debug/debug.js.map +1 -1
  10. package/lib/engine/debug/debug_console.js.map +1 -1
  11. package/lib/engine/debug/debug_overlay.js.map +1 -1
  12. package/lib/engine/debug/index.js.map +1 -1
  13. package/lib/engine/engine.js.map +1 -1
  14. package/lib/engine/engine_addressables.js.map +1 -1
  15. package/lib/engine/engine_application.js.map +1 -1
  16. package/lib/engine/engine_assetdatabase.js.map +1 -1
  17. package/lib/engine/engine_camera.js.map +1 -1
  18. package/lib/engine/engine_components.js.map +1 -1
  19. package/lib/engine/engine_constants.js.map +1 -1
  20. package/lib/engine/engine_context_registry.js.map +1 -1
  21. package/lib/engine/engine_coroutine.js.map +1 -1
  22. package/lib/engine/engine_create_objects.js.map +1 -1
  23. package/lib/engine/engine_default_parameters.js.map +1 -1
  24. package/lib/engine/engine_element.d.ts +8 -4
  25. package/lib/engine/engine_element.js +174 -165
  26. package/lib/engine/engine_element.js.map +1 -1
  27. package/lib/engine/engine_element_loading.js.map +1 -1
  28. package/lib/engine/engine_element_overlay.js.map +1 -1
  29. package/lib/engine/engine_fileloader.js.map +1 -1
  30. package/lib/engine/engine_gameobject.d.ts +4 -2
  31. package/lib/engine/engine_gameobject.js +32 -13
  32. package/lib/engine/engine_gameobject.js.map +1 -1
  33. package/lib/engine/engine_generic_utils.js.map +1 -1
  34. package/lib/engine/engine_gizmos.js.map +1 -1
  35. package/lib/engine/engine_gltf.d.ts +1 -1
  36. package/lib/engine/engine_gltf.js.map +1 -1
  37. package/lib/engine/engine_gltf_builtin_components.js.map +1 -1
  38. package/lib/engine/engine_hot_reload.js.map +1 -1
  39. package/lib/engine/engine_input.js.map +1 -1
  40. package/lib/engine/engine_input_utils.js.map +1 -1
  41. package/lib/engine/engine_instancing.js.map +1 -1
  42. package/lib/engine/engine_license.js.map +1 -1
  43. package/lib/engine/engine_lightdata.js.map +1 -1
  44. package/lib/engine/engine_loaders.js.map +1 -1
  45. package/lib/engine/engine_mainloop_utils.js +36 -6
  46. package/lib/engine/engine_mainloop_utils.js.map +1 -1
  47. package/lib/engine/engine_math.js.map +1 -1
  48. package/lib/engine/engine_networking.js.map +1 -1
  49. package/lib/engine/engine_networking_auto.js.map +1 -1
  50. package/lib/engine/engine_networking_files.js.map +1 -1
  51. package/lib/engine/engine_networking_files_default_components.js.map +1 -1
  52. package/lib/engine/engine_networking_instantiate.js.map +1 -1
  53. package/lib/engine/engine_networking_peer.js.map +1 -1
  54. package/lib/engine/engine_networking_types.js.map +1 -1
  55. package/lib/engine/engine_networking_utils.js.map +1 -1
  56. package/lib/engine/engine_networking_websocket.js.map +1 -1
  57. package/lib/engine/engine_physics.js.map +1 -1
  58. package/lib/engine/engine_physics.types.js.map +1 -1
  59. package/lib/engine/engine_playerview.js.map +1 -1
  60. package/lib/engine/engine_rendererdata.js.map +1 -1
  61. package/lib/engine/engine_scenetools.js.map +1 -1
  62. package/lib/engine/engine_serialization.js.map +1 -1
  63. package/lib/engine/engine_serialization_builtin_serializer.js.map +1 -1
  64. package/lib/engine/engine_serialization_core.js.map +1 -1
  65. package/lib/engine/engine_serialization_decorator.js.map +1 -1
  66. package/lib/engine/engine_setup.d.ts +5 -2
  67. package/lib/engine/engine_setup.js +14 -5
  68. package/lib/engine/engine_setup.js.map +1 -1
  69. package/lib/engine/engine_shaders.js.map +1 -1
  70. package/lib/engine/engine_texture.js.map +1 -1
  71. package/lib/engine/engine_three_utils.js.map +1 -1
  72. package/lib/engine/engine_time.js.map +1 -1
  73. package/lib/engine/engine_types.js.map +1 -1
  74. package/lib/engine/engine_typestore.js.map +1 -1
  75. package/lib/engine/engine_util_decorator.js.map +1 -1
  76. package/lib/engine/engine_utils.js.map +1 -1
  77. package/lib/engine/engine_utils_screenshot.js.map +1 -1
  78. package/lib/engine/engine_web_api.js.map +1 -1
  79. package/lib/engine/extensions/EXT_texture_exr.js.map +1 -1
  80. package/lib/engine/extensions/NEEDLE_animator_controller_model.js.map +1 -1
  81. package/lib/engine/extensions/NEEDLE_components.js.map +1 -1
  82. package/lib/engine/extensions/NEEDLE_gameobject_data.js.map +1 -1
  83. package/lib/engine/extensions/NEEDLE_lighting_settings.js.map +1 -1
  84. package/lib/engine/extensions/NEEDLE_lightmaps.js.map +1 -1
  85. package/lib/engine/extensions/NEEDLE_persistent_assets.js.map +1 -1
  86. package/lib/engine/extensions/NEEDLE_progressive.js.map +1 -1
  87. package/lib/engine/extensions/NEEDLE_render_objects.js.map +1 -1
  88. package/lib/engine/extensions/NEEDLE_techniques_webgl.js.map +1 -1
  89. package/lib/engine/extensions/extension_resolver.js.map +1 -1
  90. package/lib/engine/extensions/extension_utils.js.map +1 -1
  91. package/lib/engine/extensions/extensions.js.map +1 -1
  92. package/lib/engine/js-extensions/Camera.js.map +1 -1
  93. package/lib/engine/js-extensions/Layers.js.map +1 -1
  94. package/lib/engine/js-extensions/index.js.map +1 -1
  95. package/lib/engine/shaders/shaderData.js.map +1 -1
  96. package/lib/engine/tests/test_utils.js.map +1 -1
  97. package/lib/engine-components/AlignmentConstraint.js.map +1 -1
  98. package/lib/engine-components/Animation.js.map +1 -1
  99. package/lib/engine-components/AnimationCurve.js.map +1 -1
  100. package/lib/engine-components/Animator.js.map +1 -1
  101. package/lib/engine-components/AnimatorController.js.map +1 -1
  102. package/lib/engine-components/AudioListener.js.map +1 -1
  103. package/lib/engine-components/AudioSource.js.map +1 -1
  104. package/lib/engine-components/AvatarLoader.js.map +1 -1
  105. package/lib/engine-components/AxesHelper.js.map +1 -1
  106. package/lib/engine-components/BasicIKConstraint.js.map +1 -1
  107. package/lib/engine-components/BoxCollider.js.map +1 -1
  108. package/lib/engine-components/BoxHelperComponent.js.map +1 -1
  109. package/lib/engine-components/Camera.d.ts +3 -1
  110. package/lib/engine-components/Camera.js +11 -10
  111. package/lib/engine-components/Camera.js.map +1 -1
  112. package/lib/engine-components/CameraUtils.js.map +1 -1
  113. package/lib/engine-components/CharacterController.js.map +1 -1
  114. package/lib/engine-components/Collider.js.map +1 -1
  115. package/lib/engine-components/Component.d.ts +1 -1
  116. package/lib/engine-components/Component.js +2 -2
  117. package/lib/engine-components/Component.js.map +1 -1
  118. package/lib/engine-components/DeleteBox.js.map +1 -1
  119. package/lib/engine-components/DeviceFlag.js.map +1 -1
  120. package/lib/engine-components/DragControls.js.map +1 -1
  121. package/lib/engine-components/DropListener.js.map +1 -1
  122. package/lib/engine-components/Duplicatable.js.map +1 -1
  123. package/lib/engine-components/EventList.js.map +1 -1
  124. package/lib/engine-components/EventTrigger.js.map +1 -1
  125. package/lib/engine-components/EventType.js.map +1 -1
  126. package/lib/engine-components/FlyControls.js.map +1 -1
  127. package/lib/engine-components/Fog.js.map +1 -1
  128. package/lib/engine-components/Gizmos.js.map +1 -1
  129. package/lib/engine-components/GridHelper.js.map +1 -1
  130. package/lib/engine-components/GroundProjection.js.map +1 -1
  131. package/lib/engine-components/Interactable.js.map +1 -1
  132. package/lib/engine-components/Joints.js.map +1 -1
  133. package/lib/engine-components/LODGroup.js.map +1 -1
  134. package/lib/engine-components/Light.d.ts +0 -2
  135. package/lib/engine-components/Light.js +22 -14
  136. package/lib/engine-components/Light.js.map +1 -1
  137. package/lib/engine-components/LookAtConstraint.js.map +1 -1
  138. package/lib/engine-components/NestedGltf.js.map +1 -1
  139. package/lib/engine-components/Networking.js.map +1 -1
  140. package/lib/engine-components/OffsetConstraint.js.map +1 -1
  141. package/lib/engine-components/OrbitControls.js.map +1 -1
  142. package/lib/engine-components/ParticleSystem.js.map +1 -1
  143. package/lib/engine-components/ParticleSystemModules.js.map +1 -1
  144. package/lib/engine-components/ParticleSystemSubEmitter.js.map +1 -1
  145. package/lib/engine-components/PlayerColor.js.map +1 -1
  146. package/lib/engine-components/ReflectionProbe.js.map +1 -1
  147. package/lib/engine-components/Renderer.js.map +1 -1
  148. package/lib/engine-components/RendererLightmap.js.map +1 -1
  149. package/lib/engine-components/RigidBody.js.map +1 -1
  150. package/lib/engine-components/ScreenCapture.js.map +1 -1
  151. package/lib/engine-components/ShadowCatcher.js.map +1 -1
  152. package/lib/engine-components/Skybox.d.ts +2 -0
  153. package/lib/engine-components/Skybox.js +43 -21
  154. package/lib/engine-components/Skybox.js.map +1 -1
  155. package/lib/engine-components/SmoothFollow.js.map +1 -1
  156. package/lib/engine-components/SpatialTrigger.js.map +1 -1
  157. package/lib/engine-components/SpectatorCamera.js.map +1 -1
  158. package/lib/engine-components/SphereCollider.js.map +1 -1
  159. package/lib/engine-components/SpriteRenderer.js.map +1 -1
  160. package/lib/engine-components/SyncedCamera.js.map +1 -1
  161. package/lib/engine-components/SyncedRoom.js.map +1 -1
  162. package/lib/engine-components/SyncedTransform.js.map +1 -1
  163. package/lib/engine-components/TestRunner.js.map +1 -1
  164. package/lib/engine-components/TransformGizmo.js.map +1 -1
  165. package/lib/engine-components/VideoPlayer.js.map +1 -1
  166. package/lib/engine-components/Voip.js.map +1 -1
  167. package/lib/engine-components/Volume.js +2 -0
  168. package/lib/engine-components/Volume.js.map +1 -1
  169. package/lib/engine-components/WebARSessionRoot.js.map +1 -1
  170. package/lib/engine-components/WebXR.js.map +1 -1
  171. package/lib/engine-components/WebXRAvatar.js.map +1 -1
  172. package/lib/engine-components/WebXRController.js.map +1 -1
  173. package/lib/engine-components/WebXRGrabRendering.js.map +1 -1
  174. package/lib/engine-components/WebXRRig.js.map +1 -1
  175. package/lib/engine-components/WebXRSync.js.map +1 -1
  176. package/lib/engine-components/XRFlag.js.map +1 -1
  177. package/lib/engine-components/avatar/AvatarBlink_Simple.js.map +1 -1
  178. package/lib/engine-components/avatar/AvatarEyeLook_Rotation.js.map +1 -1
  179. package/lib/engine-components/avatar/Avatar_Brain_LookAt.js.map +1 -1
  180. package/lib/engine-components/avatar/Avatar_MouthShapes.js.map +1 -1
  181. package/lib/engine-components/avatar/Avatar_MustacheShake.js.map +1 -1
  182. package/lib/engine-components/codegen/components.js.map +1 -1
  183. package/lib/engine-components/debug/LogStats.js.map +1 -1
  184. package/lib/engine-components/export/gltf/GltfExport.js.map +1 -1
  185. package/lib/engine-components/export/usdz/Extension.js.map +1 -1
  186. package/lib/engine-components/export/usdz/USDZExporter.js.map +1 -1
  187. package/lib/engine-components/export/usdz/extensions/Animation.js.map +1 -1
  188. package/lib/engine-components/export/usdz/types.js.map +1 -1
  189. package/lib/engine-components/export/usdz/utils/animationutils.js.map +1 -1
  190. package/lib/engine-components/export/usdz/utils/quicklook.js.map +1 -1
  191. package/lib/engine-components/export/usdz/utils/timeutils.js.map +1 -1
  192. package/lib/engine-components/js-extensions/ExtensionUtils.js.map +1 -1
  193. package/lib/engine-components/js-extensions/Object3D.js +1 -1
  194. package/lib/engine-components/js-extensions/Object3D.js.map +1 -1
  195. package/lib/engine-components/js-extensions/RGBAColor.js.map +1 -1
  196. package/lib/engine-components/js-extensions/Vector.js.map +1 -1
  197. package/lib/engine-components/timeline/PlayableDirector.js.map +1 -1
  198. package/lib/engine-components/timeline/SignalAsset.js.map +1 -1
  199. package/lib/engine-components/timeline/TimelineModels.js.map +1 -1
  200. package/lib/engine-components/timeline/TimelineTracks.js.map +1 -1
  201. package/lib/engine-components/ui/BaseUIComponent.js.map +1 -1
  202. package/lib/engine-components/ui/Button.js.map +1 -1
  203. package/lib/engine-components/ui/Canvas.js +2 -2
  204. package/lib/engine-components/ui/Canvas.js.map +1 -1
  205. package/lib/engine-components/ui/CanvasGroup.js.map +1 -1
  206. package/lib/engine-components/ui/EventSystem.js.map +1 -1
  207. package/lib/engine-components/ui/Graphic.js.map +1 -1
  208. package/lib/engine-components/ui/Image.js.map +1 -1
  209. package/lib/engine-components/ui/InputField.js.map +1 -1
  210. package/lib/engine-components/ui/Interfaces.js.map +1 -1
  211. package/lib/engine-components/ui/Keyboard.js.map +1 -1
  212. package/lib/engine-components/ui/Layout.js.map +1 -1
  213. package/lib/engine-components/ui/PointerEvents.js.map +1 -1
  214. package/lib/engine-components/ui/RaycastUtils.js.map +1 -1
  215. package/lib/engine-components/ui/Raycaster.js.map +1 -1
  216. package/lib/engine-components/ui/RectTransform.js.map +1 -1
  217. package/lib/engine-components/ui/SpatialHtml.js.map +1 -1
  218. package/lib/engine-components/ui/Text.js.map +1 -1
  219. package/lib/engine-components/ui/Utils.js.map +1 -1
  220. package/lib/engine-components-experimental/Presentation.js.map +1 -1
  221. package/lib/engine-components-experimental/networking/PlayerSync.js.map +1 -1
  222. package/lib/engine-schemes/schemes.js.map +1 -1
  223. package/lib/engine-schemes/synced-camera-model.js.map +1 -1
  224. package/lib/engine-schemes/synced-transform-model.js.map +1 -1
  225. package/lib/engine-schemes/transform.js.map +1 -1
  226. package/lib/engine-schemes/vec2.js.map +1 -1
  227. package/lib/engine-schemes/vec3.js.map +1 -1
  228. package/lib/engine-schemes/vec4.js.map +1 -1
  229. package/lib/engine-schemes/vr-user-state-buffer.js.map +1 -1
  230. package/lib/include/three/ARButton.js.map +1 -1
  231. package/lib/include/three/EXT_mesh_gpu_instancing_exporter.js.map +1 -1
  232. package/lib/include/three/VRButton.js.map +1 -1
  233. package/lib/needle-engine.js.map +1 -1
  234. package/package.json +16 -3
  235. package/plugins/generate-font.js +65 -0
  236. package/plugins/vite/poster-client.js +3 -5
  237. package/plugins/vite/reload.js +2 -2
  238. package/src/engine/codegen/register_types.js +171 -171
  239. package/src/engine/engine_element.ts +188 -178
  240. package/src/engine/engine_gameobject.ts +583 -558
  241. package/src/engine/engine_gltf.ts +1 -1
  242. package/src/engine/engine_mainloop_utils.ts +36 -7
  243. package/src/engine/engine_setup.ts +20 -7
  244. package/src/engine-components/Camera.ts +14 -12
  245. package/src/engine-components/Component.ts +2 -2
  246. package/src/engine-components/Light.ts +20 -13
  247. package/src/engine-components/Skybox.ts +49 -22
  248. package/src/engine-components/Volume.ts +1 -0
  249. package/src/engine-components/js-extensions/Object3D.ts +1 -1
  250. package/src/engine-components/ui/Canvas.ts +2 -2
  251. package/lib/tsconfig.tsbuildinfo +0 -1
  252. package/lib/vite.config.d.ts +0 -2
  253. package/lib/vite.config.js +0 -26
  254. package/lib/vite.config.js.map +0 -1
  255. package/src/tsconfig.json +0 -33
@@ -8,64 +8,12 @@ import { setDracoDecoderPath, setDracoDecoderType, setKtx2TranscoderPath } from
8
8
  import { getLoader, registerLoader } from "../engine/engine_gltf";
9
9
  import { NeedleGltfLoader } from "./engine_scenetools";
10
10
  import { INeedleEngineComponent } from "./engine_types";
11
-
11
+ //
12
12
  // registering loader here too to make sure it's imported when using engine via vanilla js
13
13
  registerLoader(NeedleGltfLoader);
14
14
 
15
15
  const debug = getParam("debugwebcomponent");
16
16
 
17
- class EngineElementSourceFileWatcher {
18
-
19
- private id: string;
20
- private context: Context;
21
- private previouslyAdded: any;
22
- private previousSource?: string;
23
- private networkEvent: string;
24
-
25
- constructor(id: string, context: Context) {
26
- this.id = id;
27
- this.context = context;
28
- this.networkEvent = "needle-engine-source-changed";
29
- if (this.id) this.networkEvent += "-" + this.id;
30
- this.context.connection.beginListen(this.networkEvent, fn => {
31
- this.onSourceChanged(fn, true);
32
- });
33
- }
34
-
35
- async onSourceChanged(newSource: string, dontSend: boolean = false, isStartup: boolean = false) {
36
- if (this.previouslyAdded) {
37
- // if event was from remote and source didnt change do nothing
38
- if (dontSend && newSource === this.previousSource) { }
39
- else
40
- GameObject.destroySynced(this.previouslyAdded);
41
- }
42
- this.previouslyAdded = null;
43
-
44
- if (!dontSend) {
45
- this.context.connection.send(this.networkEvent, newSource);
46
- }
47
-
48
- this.previousSource = newSource;
49
- Context.Current = this.context;
50
- const res = await getLoader().loadSync(this.context, newSource, this.getHashFromString(newSource), false);
51
- if (!isStartup)
52
- processNewScripts(this.context);
53
- const obj = res?.scene;
54
- if (obj) {
55
- this.previouslyAdded = obj;
56
- this.context.scene.add(obj);
57
- }
58
- }
59
-
60
- private getHashFromString(str: string) {
61
- let hash = 0;
62
- for (let i = 0; i < str.length; i++) {
63
- hash = str.charCodeAt(i) + ((hash << 5) - hash);
64
- }
65
- return hash;
66
- }
67
- }
68
-
69
17
  const htmlTagName = "needle-engine";
70
18
  const vrContainerClassName = "vr";
71
19
  const desktopContainerClassname = "desktop";
@@ -81,7 +29,7 @@ export class EngineElement extends HTMLElement implements INeedleEngineComponent
81
29
 
82
30
  public get cameraControls(): boolean {
83
31
  const attr = this.getAttribute("camera-controls");
84
- if(attr === null || attr === "False" || attr === "false" || attr === "0") return false;
32
+ if (attr === null || attr === "False" || attr === "false" || attr === "0") return false;
85
33
  return true;
86
34
  }
87
35
 
@@ -102,144 +50,43 @@ export class EngineElement extends HTMLElement implements INeedleEngineComponent
102
50
  });
103
51
  }
104
52
 
105
- public get Context() { return this._context; }
53
+ public get context() { return this._context; }
106
54
 
107
- /**@obsolete use GameObject */
108
- private gameObject = GameObject; // used to access static methods from regular js
55
+ /**@obsolete use context */
56
+ public get Context() { return this._context; }
57
+ /**@obsolete use Needle.GameObject */
58
+ private gameObject = GameObject;
59
+ /**@obsolete use Needle.GameObject */
109
60
  private GameObject = GameObject;
110
61
 
111
- private _context: Context | null = null;
62
+ private _context: Context;
112
63
  private _overlay_ar: AROverlayHandler;
113
64
  private _loadingProgress01: number = 0;
114
-
115
- private _watcher?: EngineElementSourceFileWatcher;
116
65
  private _loadingView?: ILoadingViewHandler;
66
+ private _previousSrc: string | null | string[] = null;
117
67
 
118
68
  constructor() {
119
69
  super();
120
70
  this._overlay_ar = new AROverlayHandler();
71
+ this._context = new Context({ domElement: this });
121
72
  }
122
73
 
123
74
  async connectedCallback() {
124
- this.onSetupDesktop();
125
-
126
- var observer = new MutationObserver(this.onElementsChanged.bind(this));
127
- observer.observe(this, { childList: true })
128
-
129
- // user can set a function name or a path to a gltf or glb to be loaded
130
- const srcFile = () => {
131
- const srcVal = this.getAttribute("src");
132
- if (srcVal?.endsWith(".glb") || srcVal?.endsWith(".gltf")) {
133
- return srcVal;
134
- }
135
- return null;
136
- };
137
- let src: string | null = "loadScene";
138
- const srcAttributeValue = srcFile();
139
- if (srcAttributeValue) src = srcAttributeValue;
140
-
141
- const alias = this.getAttribute("alias");
142
- const hash = this.getAttribute("hash");
143
- this._context = new Context({ name: src, domElement: this, alias: alias, hash: hash ?? undefined });
144
- this._watcher = new EngineElementSourceFileWatcher(this.getAttribute("id") ?? alias ?? "", this._context);
75
+ if (debug) {
76
+ console.log("<needle-engine> connected");
77
+ console.dir(this);
78
+ }
145
79
 
80
+ this.onSetupDesktop();
81
+ const src = this.getAttribute("src") ?? globalThis["needle:codegen_files"];
146
82
  if (src && src.length > 0) {
147
- // try to get the load function
148
-
149
- // HACK: if no explicit glb is assigned we have to wait for the codegen function to be available
150
- // it happened in one case during local development where the function was not yet registered
151
- // but this component was connected already
152
- if (!srcAttributeValue) {
153
- while (Object.keys(build_scene_functions).length <= 0) {
154
- if (!this.isConnected) return;
155
- await delay(10);
156
- }
157
- }
158
-
159
- let fn: (context: Context) => Promise<void> = build_scene_functions[src] ?? window[src];
160
- // if no load function is found (e.g. when generated code was deleted or import removed) then just load the glb
161
- // or if an explicit src file is provided
162
- let previousFileLoaded: string | null = null;
163
- if (!fn || srcAttributeValue) {
164
- if (srcAttributeValue)
165
- src = srcAttributeValue;
166
- fn = async _ => {
167
- const file = srcFile();
168
- if (file && this._watcher) {
169
- previousFileLoaded = file;
170
- await this._watcher.onSourceChanged(file, true, true);
171
- }
172
- }
173
- }
174
- if (fn) {
175
- this.classList.add("loading");
176
- if (debug)
177
- console.log("Needle Engine: Begin loading", alias ?? "");
178
- const allowOverridingDefaultLoading = true;
179
- // default loading can be overriden by calling preventDefault in the onload start event
180
- const useDefaultLoading = this.dispatchEvent(new CustomEvent("loadstart", {
181
- detail: {
182
- context: this._context,
183
- alias: alias
184
- },
185
- cancelable: allowOverridingDefaultLoading
186
- }));
187
- if (!this._loadingView && useDefaultLoading)
188
- this._loadingView = new EngineLoadingView(this);
189
- if (useDefaultLoading)
190
- this._loadingView?.onLoadingBegin("begin load");
191
- // setup the loading callback for the default loading handler and the user defined one
192
- const loadingCallback = (progress: LoadingProgressArgs, message?: string) => {
193
- this._loadingProgress01 = calculateProgress01(progress);
194
- if (useDefaultLoading)
195
- this._loadingView?.onLoadingUpdate(progress, message);
196
- this.dispatchEvent(new CustomEvent("progress", {
197
- detail: {
198
- context: this._context,
199
- name: progress.name,
200
- progress: progress.progress,
201
- index: progress.index,
202
- count: progress.count,
203
- totalProgress01: this._loadingProgress01
204
- }
205
- }));
206
- }
207
- this.onBeforeBeginLoading();
208
- await this._context.onCreate(fn, { progress: loadingCallback });
209
- const file = srcFile();
210
- if (file) {
211
- // only if we didnt load this file here already
212
- if (file !== previousFileLoaded)
213
- await this._watcher.onSourceChanged(file, true, true);
214
- }
215
- this._loadingProgress01 = 1;
216
- if (useDefaultLoading)
217
- this._loadingView?.onLoadingFinished("creating scene");
218
- this.classList.remove("loading");
219
- this.classList.add("loading-finished");
220
- if (debug)
221
- console.log("Needle Engine: finished loading", alias ?? "");
222
- this.dispatchEvent(new CustomEvent("loadfinished", {
223
- detail: {
224
- context: this._context,
225
- src: alias ?? src
226
- }
227
- }));
228
- this.onSetupDesktop();
229
- }
230
- else {
231
- console.error("Could not find scene function named \"" + src + "\", it must be either in global scope " +
232
- "or added to build_scene_functions", build_scene_functions);
233
- }
234
- } else {
235
- console.error("Missing src attribute - please provide a function name", this);
83
+ await this.onLoad(src, true);
236
84
  }
85
+ this.onSetupDesktop();
237
86
  }
238
87
 
239
88
  disconnectedCallback() {
240
- if (this._context) {
241
- this._context.onDestroy();
242
- }
89
+ this._context?.onDestroy();
243
90
  }
244
91
 
245
92
  static get observedAttributes() {
@@ -260,7 +107,14 @@ export class EngineElement extends HTMLElement implements INeedleEngineComponent
260
107
  // console.log(name, oldValue, newValue);
261
108
  switch (name) {
262
109
  case "src":
263
- this._watcher?.onSourceChanged(newValue);
110
+ if (debug) console.log("src changed to type:", typeof newValue, ", from \"", _oldValue, "\" to \"", newValue)
111
+ this.onLoad(newValue, false);
112
+ // this._watcher?.onSourceChanged(newValue);
113
+ break;
114
+ case "hash":
115
+ if (this._context) {
116
+ this._context.hash = newValue;
117
+ }
264
118
  break;
265
119
  case "loadstart":
266
120
  case "progress":
@@ -288,6 +142,144 @@ export class EngineElement extends HTMLElement implements INeedleEngineComponent
288
142
  }
289
143
  }
290
144
 
145
+ private _isCurrentlySettingsSourceAttribute = false;
146
+
147
+ private async onLoad(src: string | null | string[], isStartup: boolean) {
148
+ if (this._isCurrentlySettingsSourceAttribute) {
149
+ return;
150
+ }
151
+ if (src === this._previousSrc) {
152
+ return;
153
+ }
154
+ if (!src || !src.length) {
155
+ console.error("Needle Engine: No source specified", src);
156
+ return;
157
+ }
158
+ if (!this._context) {
159
+ console.error("Needle Engine: Context not initialized");
160
+ return;
161
+ }
162
+
163
+ this._previousSrc = src;
164
+
165
+ // Set the source attribute so codegen doesnt try to re-assign it again and we communicate to the outside which root files are being loaded
166
+ this._isCurrentlySettingsSourceAttribute = true;
167
+ this.setAttribute("src", src?.toString());
168
+ this._isCurrentlySettingsSourceAttribute = false;
169
+
170
+ const alias = this.getAttribute("alias");
171
+ this.classList.add("loading");
172
+ if (debug) console.log("Needle Engine: Begin loading", alias ?? "");
173
+
174
+
175
+ // Loading start events
176
+ const allowOverridingDefaultLoading = true;
177
+ // default loading can be overriden by calling preventDefault in the onload start event
178
+ const useDefaultLoading = this.dispatchEvent(new CustomEvent("loadstart", {
179
+ detail: {
180
+ context: this._context,
181
+ alias: alias
182
+ },
183
+ cancelable: allowOverridingDefaultLoading
184
+ }));
185
+ if (!this._loadingView && useDefaultLoading)
186
+ this._loadingView = new EngineLoadingView(this);
187
+ if (useDefaultLoading)
188
+ this._loadingView?.onLoadingBegin("begin load");
189
+ this.onBeforeBeginLoading();
190
+
191
+ if (debug) console.log(src);
192
+ let filesToLoad: Array<string>;
193
+ // When using globalThis the src is an array already
194
+ if (Array.isArray(src)) {
195
+ filesToLoad = src;
196
+ }
197
+ // When assigned from codegen the src is a stringified array
198
+ else if (src.startsWith("[") && src.endsWith("]")) {
199
+ filesToLoad = JSON.parse(src);
200
+ }
201
+ // src.toString for an array produces a comma separated list
202
+ else if (src.includes(",")) {
203
+ filesToLoad = src.split(",");
204
+ }
205
+ else filesToLoad = [src];
206
+
207
+ let loadFunction: any = null;
208
+
209
+ if (filesToLoad?.length > 0) {
210
+ loadFunction = async (ctx: Context) => {
211
+ let hash = 0;
212
+ if (ctx.hash) hash = Number.parseInt(ctx.hash) ?? 0;
213
+ const loader = getLoader();
214
+ for (let i = 0; i < filesToLoad.length; i++) {
215
+ const url = filesToLoad[i];
216
+ const fileName = getNameFromUrl(url);
217
+ const progress: LoadingProgressArgs = {
218
+ name: fileName,
219
+ progress: null!,
220
+ index: i,
221
+ count: filesToLoad.length
222
+ };
223
+ const progressEventArgs = {
224
+ detail: {
225
+ context: ctx,
226
+ name: fileName,
227
+ progress: progress.progress,
228
+ index: i,
229
+ count: filesToLoad.length,
230
+ totalProgress01: this._loadingProgress01
231
+ }
232
+ }
233
+ const res = await loader.loadSync(ctx, url, hash, false, prog => {
234
+ // Calc progress
235
+ progress.progress = prog;
236
+ this._loadingProgress01 = calculateProgress01(progress);
237
+ // Update overlay if we use it
238
+ if (useDefaultLoading) this._loadingView?.onLoadingUpdate(progress);
239
+ // Dispatch event
240
+ progressEventArgs.detail.progress = prog;
241
+ progressEventArgs.detail.totalProgress01 = this._loadingProgress01;
242
+ this.dispatchEvent(new CustomEvent("progress", progressEventArgs));
243
+ });
244
+ const obj = res?.scene;
245
+ if (obj) GameObject.add(obj, ctx.scene, ctx);
246
+ }
247
+ if (!isStartup)
248
+ processNewScripts(ctx);
249
+ };
250
+ }
251
+ if (!loadFunction) {
252
+ console.error("Needle Engine: No files to load", src);
253
+ return;
254
+ }
255
+ const currentHash = this.getAttribute("hash");
256
+ if (currentHash !== null && currentHash !== undefined)
257
+ this._context.hash = currentHash;
258
+ this._context.alias = alias;
259
+ if (!this._context.isCreated)
260
+ await this._context.onCreate(loadFunction);
261
+ else {
262
+ await loadFunction(this._context);
263
+ }
264
+
265
+
266
+
267
+
268
+ this._loadingProgress01 = 1;
269
+ if (useDefaultLoading)
270
+ this._loadingView?.onLoadingFinished("creating scene");
271
+ this.classList.remove("loading");
272
+ this.classList.add("loading-finished");
273
+ if (debug)
274
+ console.log("Needle Engine: finished loading", alias ?? "");
275
+ this.dispatchEvent(new CustomEvent("loadfinished", {
276
+ detail: {
277
+ context: this._context,
278
+ src: alias ?? src
279
+ }
280
+ }));
281
+ }
282
+
291
283
  private registerEventFromAttribute(eventName: string, code: string) {
292
284
  if (typeof code === "string" && code.length > 0) {
293
285
  // indirect eval https://esbuild.github.io/content-types/#direct-eval
@@ -334,10 +326,6 @@ export class EngineElement extends HTMLElement implements INeedleEngineComponent
334
326
  this.dispatchEvent(new CustomEvent("exit-vr", { detail: { session: session, context: this._context } }));
335
327
  }
336
328
 
337
- private onElementsChanged() {
338
-
339
- }
340
-
341
329
  private onSetupAR() {
342
330
  this.classList.add(arSessionActiveClassName);
343
331
  this.classList.remove(desktopSessionActiveClassName);
@@ -425,3 +413,25 @@ if (!window.customElements.get(htmlTagName))
425
413
 
426
414
 
427
415
 
416
+
417
+
418
+
419
+
420
+
421
+ function getHashFromString(str: string) {
422
+ let hash = 0;
423
+ for (let i = 0; i < str.length; i++) {
424
+ hash = str.charCodeAt(i) + ((hash << 5) - hash);
425
+ }
426
+ return hash;
427
+ }
428
+
429
+ function getNameFromUrl(str: string) {
430
+ const parts = str.split("/");
431
+ let name = parts[parts.length - 1];
432
+ // Remove params
433
+ let index = name.indexOf("?")
434
+ if (index > 0)
435
+ name = name.substring(0, index);
436
+ return name;
437
+ }