@needle-tools/engine 4.4.0-beta.7 → 4.4.0-beta.9

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 (1043) hide show
  1. package/CHANGELOG.md +3618 -3616
  2. package/LICENSE.md +10 -10
  3. package/README.md +64 -64
  4. package/components.needle.json +1 -1
  5. package/dist/needle-engine.bundle.js +5029 -4950
  6. package/dist/needle-engine.bundle.light.js +5030 -4951
  7. package/dist/needle-engine.bundle.light.min.js +146 -116
  8. package/dist/needle-engine.bundle.light.umd.cjs +148 -118
  9. package/dist/needle-engine.bundle.min.js +146 -116
  10. package/dist/needle-engine.bundle.umd.cjs +148 -118
  11. package/dist/needle-engine.d.ts +129 -130
  12. package/dist/needle-engine.light.d.ts +129 -130
  13. package/lib/asap/needle-asap.d.ts +1 -1
  14. package/lib/asap/needle-asap.js +95 -95
  15. package/lib/asap/sessiongranted.d.ts +3 -3
  16. package/lib/asap/sessiongranted.js +65 -65
  17. package/lib/asap/utils.d.ts +1 -1
  18. package/lib/asap/utils.js +3 -3
  19. package/lib/engine/analytics/index.d.ts +6 -6
  20. package/lib/engine/analytics/index.js +12 -12
  21. package/lib/engine/analytics/lcp.d.ts +3 -3
  22. package/lib/engine/analytics/lcp.js +34 -34
  23. package/lib/engine/api.d.ts +81 -81
  24. package/lib/engine/api.js +80 -80
  25. package/lib/engine/assets/index.d.ts +11 -11
  26. package/lib/engine/assets/index.js +47 -47
  27. package/lib/engine/assets/static.d.ts +1 -1
  28. package/lib/engine/assets/static.js +4 -4
  29. package/lib/engine/codegen/register_types.d.ts +1 -1
  30. package/lib/engine/codegen/register_types.js +300 -300
  31. package/lib/engine/debug/debug.d.ts +15 -15
  32. package/lib/engine/debug/debug.js +44 -44
  33. package/lib/engine/debug/debug_console.d.ts +2 -2
  34. package/lib/engine/debug/debug_console.js +307 -307
  35. package/lib/engine/debug/debug_overlay.d.ts +22 -22
  36. package/lib/engine/debug/debug_overlay.js +316 -316
  37. package/lib/engine/debug/debug_spatial_console.d.ts +2 -2
  38. package/lib/engine/debug/debug_spatial_console.js +390 -390
  39. package/lib/engine/debug/index.d.ts +2 -2
  40. package/lib/engine/debug/index.js +2 -2
  41. package/lib/engine/engine.d.ts +4 -0
  42. package/lib/engine/engine.js +12 -0
  43. package/lib/engine/engine.js.map +1 -0
  44. package/lib/engine/engine_addressables.d.ts +166 -166
  45. package/lib/engine/engine_addressables.js +608 -608
  46. package/lib/engine/engine_animation.d.ts +43 -43
  47. package/lib/engine/engine_animation.js +133 -133
  48. package/lib/engine/engine_application.d.ts +40 -40
  49. package/lib/engine/engine_application.js +104 -104
  50. package/lib/engine/engine_assetdatabase.d.ts +25 -25
  51. package/lib/engine/engine_assetdatabase.js +344 -344
  52. package/lib/engine/engine_audio.d.ts +4 -4
  53. package/lib/engine/engine_audio.js +23 -23
  54. package/lib/engine/engine_camera.d.ts +13 -13
  55. package/lib/engine/engine_camera.js +30 -30
  56. package/lib/engine/engine_components.d.ts +110 -110
  57. package/lib/engine/engine_components.js +382 -382
  58. package/lib/engine/engine_components_internal.d.ts +9 -9
  59. package/lib/engine/engine_components_internal.js +36 -36
  60. package/lib/engine/engine_constants.d.ts +10 -10
  61. package/lib/engine/engine_constants.js +41 -41
  62. package/lib/engine/engine_context.d.ts +354 -354
  63. package/lib/engine/engine_context.js +1536 -1536
  64. package/lib/engine/engine_context_registry.d.ts +71 -71
  65. package/lib/engine/engine_context_registry.js +117 -117
  66. package/lib/engine/engine_coroutine.d.ts +35 -35
  67. package/lib/engine/engine_coroutine.js +52 -52
  68. package/lib/engine/engine_create_objects.d.ts +118 -118
  69. package/lib/engine/engine_create_objects.js +308 -308
  70. package/lib/engine/engine_default_parameters.d.ts +2 -2
  71. package/lib/engine/engine_default_parameters.js +3 -3
  72. package/lib/engine/engine_editor-sync.d.ts +21 -21
  73. package/lib/engine/engine_editor-sync.js +4 -4
  74. package/lib/engine/engine_element.d.ts +113 -113
  75. package/lib/engine/engine_element.js +832 -829
  76. package/lib/engine/engine_element.js.map +1 -1
  77. package/lib/engine/engine_element_attributes.d.ts +72 -72
  78. package/lib/engine/engine_element_attributes.js +1 -1
  79. package/lib/engine/engine_element_extras.d.ts +6 -6
  80. package/lib/engine/engine_element_extras.js +13 -13
  81. package/lib/engine/engine_element_loading.d.ts +44 -44
  82. package/lib/engine/engine_element_loading.js +349 -349
  83. package/lib/engine/engine_element_overlay.d.ts +21 -21
  84. package/lib/engine/engine_element_overlay.js +166 -166
  85. package/lib/engine/engine_fileloader.d.ts +2 -2
  86. package/lib/engine/engine_fileloader.js +8 -8
  87. package/lib/engine/engine_gameobject.d.ts +68 -68
  88. package/lib/engine/engine_gameobject.js +591 -591
  89. package/lib/engine/engine_generic_utils.d.ts +1 -1
  90. package/lib/engine/engine_generic_utils.js +13 -13
  91. package/lib/engine/engine_gizmos.d.ts +149 -149
  92. package/lib/engine/engine_gizmos.js +530 -530
  93. package/lib/engine/engine_gltf.d.ts +12 -12
  94. package/lib/engine/engine_gltf.js +15 -15
  95. package/lib/engine/engine_gltf_builtin_components.d.ts +7 -7
  96. package/lib/engine/engine_gltf_builtin_components.js +341 -341
  97. package/lib/engine/engine_hot_reload.d.ts +7 -7
  98. package/lib/engine/engine_hot_reload.js +184 -184
  99. package/lib/engine/engine_input.d.ts +352 -352
  100. package/lib/engine/engine_input.js +1265 -1265
  101. package/lib/engine/engine_input_utils.d.ts +2 -2
  102. package/lib/engine/engine_input_utils.js +22 -22
  103. package/lib/engine/engine_instancing.d.ts +19 -19
  104. package/lib/engine/engine_instancing.js +39 -39
  105. package/lib/engine/engine_license.d.ts +11 -9
  106. package/lib/engine/engine_license.js +361 -320
  107. package/lib/engine/engine_license.js.map +1 -1
  108. package/lib/engine/engine_lifecycle_api.d.ts +76 -76
  109. package/lib/engine/engine_lifecycle_api.js +99 -99
  110. package/lib/engine/engine_lifecycle_functions_internal.d.ts +32 -32
  111. package/lib/engine/engine_lifecycle_functions_internal.js +146 -146
  112. package/lib/engine/engine_lightdata.d.ts +23 -23
  113. package/lib/engine/engine_lightdata.js +91 -91
  114. package/lib/engine/engine_loaders.d.ts +13 -13
  115. package/lib/engine/engine_loaders.js +62 -62
  116. package/lib/engine/engine_lods.d.ts +31 -31
  117. package/lib/engine/engine_lods.js +146 -146
  118. package/lib/engine/engine_mainloop_utils.d.ts +32 -32
  119. package/lib/engine/engine_mainloop_utils.js +466 -466
  120. package/lib/engine/engine_math.d.ts +114 -114
  121. package/lib/engine/engine_math.js +247 -247
  122. package/lib/engine/engine_modules.d.ts +36 -36
  123. package/lib/engine/engine_modules.js +85 -85
  124. package/lib/engine/engine_networking.d.ts +252 -252
  125. package/lib/engine/engine_networking.js +743 -743
  126. package/lib/engine/engine_networking_auto.d.ts +24 -24
  127. package/lib/engine/engine_networking_auto.js +310 -310
  128. package/lib/engine/engine_networking_blob.d.ts +48 -48
  129. package/lib/engine/engine_networking_blob.js +212 -212
  130. package/lib/engine/engine_networking_files.d.ts +35 -35
  131. package/lib/engine/engine_networking_files.js +172 -172
  132. package/lib/engine/engine_networking_files_default_components.d.ts +6 -6
  133. package/lib/engine/engine_networking_files_default_components.js +42 -42
  134. package/lib/engine/engine_networking_instantiate.d.ts +100 -100
  135. package/lib/engine/engine_networking_instantiate.js +345 -345
  136. package/lib/engine/engine_networking_peer.d.ts +15 -15
  137. package/lib/engine/engine_networking_peer.js +132 -132
  138. package/lib/engine/engine_networking_streams.d.ts +123 -123
  139. package/lib/engine/engine_networking_streams.js +645 -645
  140. package/lib/engine/engine_networking_types.d.ts +22 -22
  141. package/lib/engine/engine_networking_types.js +7 -7
  142. package/lib/engine/engine_networking_utils.d.ts +2 -2
  143. package/lib/engine/engine_networking_utils.js +20 -20
  144. package/lib/engine/engine_networking_websocket.d.ts +1 -1
  145. package/lib/engine/engine_networking_websocket.js +2 -2
  146. package/lib/engine/engine_patcher.d.ts +10 -10
  147. package/lib/engine/engine_patcher.js +142 -142
  148. package/lib/engine/engine_physics.d.ts +152 -152
  149. package/lib/engine/engine_physics.js +645 -645
  150. package/lib/engine/engine_physics.types.d.ts +40 -40
  151. package/lib/engine/engine_physics.types.js +33 -33
  152. package/lib/engine/engine_physics_rapier.d.ts +147 -147
  153. package/lib/engine/engine_physics_rapier.js +1432 -1432
  154. package/lib/engine/engine_playerview.d.ts +26 -26
  155. package/lib/engine/engine_playerview.js +64 -64
  156. package/lib/engine/engine_scenelighting.d.ts +71 -71
  157. package/lib/engine/engine_scenelighting.js +226 -226
  158. package/lib/engine/engine_scenetools.d.ts +50 -50
  159. package/lib/engine/engine_scenetools.js +321 -321
  160. package/lib/engine/engine_serialization.d.ts +3 -3
  161. package/lib/engine/engine_serialization.js +3 -3
  162. package/lib/engine/engine_serialization_builtin_serializer.d.ts +72 -72
  163. package/lib/engine/engine_serialization_builtin_serializer.js +403 -403
  164. package/lib/engine/engine_serialization_core.d.ts +85 -85
  165. package/lib/engine/engine_serialization_core.js +602 -602
  166. package/lib/engine/engine_serialization_decorator.d.ts +23 -23
  167. package/lib/engine/engine_serialization_decorator.js +66 -66
  168. package/lib/engine/engine_setup.d.ts +1 -1
  169. package/lib/engine/engine_setup.js +2 -2
  170. package/lib/engine/engine_shaders.d.ts +53 -53
  171. package/lib/engine/engine_shaders.js +252 -252
  172. package/lib/engine/engine_shims.d.ts +4 -4
  173. package/lib/engine/engine_shims.js +24 -24
  174. package/lib/engine/engine_test_utils.d.ts +39 -39
  175. package/lib/engine/engine_test_utils.js +83 -83
  176. package/lib/engine/engine_texture.d.ts +28 -28
  177. package/lib/engine/engine_texture.js +64 -64
  178. package/lib/engine/engine_three_utils.d.ts +201 -201
  179. package/lib/engine/engine_three_utils.js +731 -731
  180. package/lib/engine/engine_time.d.ts +51 -51
  181. package/lib/engine/engine_time.js +82 -82
  182. package/lib/engine/engine_time_utils.d.ts +88 -88
  183. package/lib/engine/engine_time_utils.js +215 -215
  184. package/lib/engine/engine_tonemapping.d.ts +2 -2
  185. package/lib/engine/engine_tonemapping.js +194 -194
  186. package/lib/engine/engine_types.d.ts +572 -572
  187. package/lib/engine/engine_types.js +88 -88
  188. package/lib/engine/engine_typestore.d.ts +28 -28
  189. package/lib/engine/engine_typestore.js +55 -55
  190. package/lib/engine/engine_util_decorator.d.ts +13 -13
  191. package/lib/engine/engine_util_decorator.js +116 -116
  192. package/lib/engine/engine_utils.d.ts +266 -266
  193. package/lib/engine/engine_utils.js +878 -878
  194. package/lib/engine/engine_utils_format.d.ts +21 -21
  195. package/lib/engine/engine_utils_format.js +193 -193
  196. package/lib/engine/engine_utils_screenshot.d.ts +159 -159
  197. package/lib/engine/engine_utils_screenshot.js +513 -513
  198. package/lib/engine/engine_utils_screenshot.xr.d.ts +5 -5
  199. package/lib/engine/engine_utils_screenshot.xr.js +90 -90
  200. package/lib/engine/engine_web_api.d.ts +12 -0
  201. package/lib/engine/engine_web_api.js +113 -0
  202. package/lib/engine/engine_web_api.js.map +1 -0
  203. package/lib/engine/engine_xr.d.ts +1 -1
  204. package/lib/engine/engine_xr.js +1 -1
  205. package/lib/engine/export/gltf/Writers.d.ts +19 -19
  206. package/lib/engine/export/gltf/Writers.js +24 -24
  207. package/lib/engine/export/gltf/index.d.ts +11 -11
  208. package/lib/engine/export/gltf/index.js +123 -123
  209. package/lib/engine/export/index.d.ts +2 -2
  210. package/lib/engine/export/index.js +2 -2
  211. package/lib/engine/export/state.d.ts +7 -7
  212. package/lib/engine/export/state.js +17 -17
  213. package/lib/engine/export/utils.d.ts +2 -2
  214. package/lib/engine/export/utils.js +7 -7
  215. package/lib/engine/extensions/EXT_texture_exr.d.ts +8 -8
  216. package/lib/engine/extensions/EXT_texture_exr.js +32 -32
  217. package/lib/engine/extensions/NEEDLE_animator_controller_model.d.ts +122 -122
  218. package/lib/engine/extensions/NEEDLE_animator_controller_model.js +95 -95
  219. package/lib/engine/extensions/NEEDLE_components.d.ts +35 -35
  220. package/lib/engine/extensions/NEEDLE_components.js +220 -220
  221. package/lib/engine/extensions/NEEDLE_gameobject_data.d.ts +10 -10
  222. package/lib/engine/extensions/NEEDLE_gameobject_data.js +57 -57
  223. package/lib/engine/extensions/NEEDLE_lighting_settings.d.ts +37 -37
  224. package/lib/engine/extensions/NEEDLE_lighting_settings.js +157 -157
  225. package/lib/engine/extensions/NEEDLE_lightmaps.d.ts +18 -18
  226. package/lib/engine/extensions/NEEDLE_lightmaps.js +99 -99
  227. package/lib/engine/extensions/NEEDLE_persistent_assets.d.ts +11 -11
  228. package/lib/engine/extensions/NEEDLE_persistent_assets.js +63 -63
  229. package/lib/engine/extensions/NEEDLE_progressive.d.ts +1 -1
  230. package/lib/engine/extensions/NEEDLE_progressive.js +1 -1
  231. package/lib/engine/extensions/NEEDLE_render_objects.d.ts +13 -13
  232. package/lib/engine/extensions/NEEDLE_render_objects.js +159 -159
  233. package/lib/engine/extensions/NEEDLE_techniques_webgl.d.ts +38 -38
  234. package/lib/engine/extensions/NEEDLE_techniques_webgl.js +564 -564
  235. package/lib/engine/extensions/extension_resolver.d.ts +4 -4
  236. package/lib/engine/extensions/extension_resolver.js +1 -1
  237. package/lib/engine/extensions/extension_utils.d.ts +12 -12
  238. package/lib/engine/extensions/extension_utils.js +152 -152
  239. package/lib/engine/extensions/extensions.d.ts +31 -31
  240. package/lib/engine/extensions/extensions.js +103 -103
  241. package/lib/engine/extensions/index.d.ts +6 -6
  242. package/lib/engine/extensions/index.js +6 -6
  243. package/lib/engine/extensions/usage_tracker.d.ts +13 -13
  244. package/lib/engine/extensions/usage_tracker.js +65 -65
  245. package/lib/engine/js-extensions/Camera.d.ts +1 -1
  246. package/lib/engine/js-extensions/Camera.js +39 -39
  247. package/lib/engine/js-extensions/ExtensionUtils.d.ts +9 -9
  248. package/lib/engine/js-extensions/ExtensionUtils.js +67 -67
  249. package/lib/engine/js-extensions/Layers.d.ts +6 -6
  250. package/lib/engine/js-extensions/Layers.js +22 -22
  251. package/lib/engine/js-extensions/Object3D.d.ts +120 -120
  252. package/lib/engine/js-extensions/Object3D.js +136 -136
  253. package/lib/engine/js-extensions/RGBAColor.d.ts +23 -23
  254. package/lib/engine/js-extensions/RGBAColor.js +110 -110
  255. package/lib/engine/js-extensions/Vector.d.ts +3 -3
  256. package/lib/engine/js-extensions/Vector.js +13 -13
  257. package/lib/engine/js-extensions/index.d.ts +5 -5
  258. package/lib/engine/js-extensions/index.js +5 -5
  259. package/lib/engine/physics/workers/mesh-bvh/GenerateMeshBVHWorker.d.ts +4 -4
  260. package/lib/engine/physics/workers/mesh-bvh/GenerateMeshBVHWorker.js +76 -76
  261. package/lib/engine/shaders/shaderData.d.ts +55 -55
  262. package/lib/engine/shaders/shaderData.js +58 -58
  263. package/lib/engine/tests/test_utils.d.ts +2 -2
  264. package/lib/engine/tests/test_utils.js +53 -53
  265. package/lib/engine/webcomponents/WebXRButtons.d.ts +56 -56
  266. package/lib/engine/webcomponents/WebXRButtons.js +230 -230
  267. package/lib/engine/webcomponents/api.d.ts +5 -5
  268. package/lib/engine/webcomponents/api.js +4 -4
  269. package/lib/engine/webcomponents/buttons.d.ts +39 -39
  270. package/lib/engine/webcomponents/buttons.js +237 -237
  271. package/lib/engine/webcomponents/fonts.d.ts +9 -9
  272. package/lib/engine/webcomponents/fonts.js +32 -32
  273. package/lib/engine/webcomponents/icons.d.ts +9 -9
  274. package/lib/engine/webcomponents/icons.js +52 -52
  275. package/lib/engine/webcomponents/index.d.ts +1 -1
  276. package/lib/engine/webcomponents/index.js +1 -1
  277. package/lib/engine/webcomponents/logo-element.d.ts +10 -10
  278. package/lib/engine/webcomponents/logo-element.js +67 -67
  279. package/lib/engine/webcomponents/needle menu/needle-menu-spatial.d.ts +37 -37
  280. package/lib/engine/webcomponents/needle menu/needle-menu-spatial.js +513 -513
  281. package/lib/engine/webcomponents/needle menu/needle-menu.d.ts +155 -151
  282. package/lib/engine/webcomponents/needle menu/needle-menu.js +1029 -1018
  283. package/lib/engine/webcomponents/needle menu/needle-menu.js.map +1 -1
  284. package/lib/engine/webcomponents/needle-button.d.ts +34 -34
  285. package/lib/engine/webcomponents/needle-button.js +161 -161
  286. package/lib/engine/xr/NeedleXRController.d.ts +313 -313
  287. package/lib/engine/xr/NeedleXRController.js +1007 -1007
  288. package/lib/engine/xr/NeedleXRSession.d.ts +339 -339
  289. package/lib/engine/xr/NeedleXRSession.js +1427 -1427
  290. package/lib/engine/xr/NeedleXRSync.d.ts +22 -22
  291. package/lib/engine/xr/NeedleXRSync.js +188 -188
  292. package/lib/engine/xr/SceneTransition.d.ts +18 -18
  293. package/lib/engine/xr/SceneTransition.js +69 -69
  294. package/lib/engine/xr/TempXRContext.d.ts +34 -34
  295. package/lib/engine/xr/TempXRContext.js +187 -187
  296. package/lib/engine/xr/XRRig.d.ts +7 -7
  297. package/lib/engine/xr/XRRig.js +1 -1
  298. package/lib/engine/xr/api.d.ts +6 -6
  299. package/lib/engine/xr/api.js +6 -6
  300. package/lib/engine/xr/events.d.ts +66 -66
  301. package/lib/engine/xr/events.js +93 -93
  302. package/lib/engine/xr/internal.d.ts +12 -12
  303. package/lib/engine/xr/internal.js +25 -25
  304. package/lib/engine/xr/usdz.d.ts +12 -12
  305. package/lib/engine/xr/usdz.js +29 -29
  306. package/lib/engine/xr/utils.d.ts +11 -11
  307. package/lib/engine/xr/utils.js +34 -34
  308. package/lib/engine-components/AlignmentConstraint.d.ts +10 -10
  309. package/lib/engine-components/AlignmentConstraint.js +39 -39
  310. package/lib/engine-components/Animation.d.ts +156 -156
  311. package/lib/engine-components/Animation.js +508 -508
  312. package/lib/engine-components/AnimationCurve.d.ts +40 -40
  313. package/lib/engine-components/AnimationCurve.js +159 -159
  314. package/lib/engine-components/AnimationUtils.d.ts +8 -8
  315. package/lib/engine-components/AnimationUtils.js +27 -27
  316. package/lib/engine-components/AnimationUtilsAutoplay.d.ts +1 -1
  317. package/lib/engine-components/AnimationUtilsAutoplay.js +39 -39
  318. package/lib/engine-components/Animator.d.ts +217 -217
  319. package/lib/engine-components/Animator.js +354 -354
  320. package/lib/engine-components/AnimatorController.d.ts +227 -227
  321. package/lib/engine-components/AnimatorController.js +1152 -1152
  322. package/lib/engine-components/AudioListener.d.ts +33 -33
  323. package/lib/engine-components/AudioListener.js +86 -86
  324. package/lib/engine-components/AudioSource.d.ts +217 -217
  325. package/lib/engine-components/AudioSource.js +627 -627
  326. package/lib/engine-components/AvatarLoader.d.ts +80 -80
  327. package/lib/engine-components/AvatarLoader.js +231 -231
  328. package/lib/engine-components/AxesHelper.d.ts +32 -32
  329. package/lib/engine-components/AxesHelper.js +67 -67
  330. package/lib/engine-components/BasicIKConstraint.d.ts +9 -9
  331. package/lib/engine-components/BasicIKConstraint.js +43 -43
  332. package/lib/engine-components/BoxCollider.d.ts +2 -2
  333. package/lib/engine-components/BoxCollider.js +2 -2
  334. package/lib/engine-components/BoxHelperComponent.d.ts +47 -47
  335. package/lib/engine-components/BoxHelperComponent.js +102 -102
  336. package/lib/engine-components/Camera.d.ts +231 -231
  337. package/lib/engine-components/Camera.js +700 -700
  338. package/lib/engine-components/CameraUtils.d.ts +1 -1
  339. package/lib/engine-components/CameraUtils.js +121 -121
  340. package/lib/engine-components/CharacterController.d.ts +55 -55
  341. package/lib/engine-components/CharacterController.js +236 -236
  342. package/lib/engine-components/Collider.d.ts +188 -188
  343. package/lib/engine-components/Collider.js +369 -369
  344. package/lib/engine-components/Component.d.ts +792 -792
  345. package/lib/engine-components/Component.js +915 -915
  346. package/lib/engine-components/ContactShadows.d.ts +82 -82
  347. package/lib/engine-components/ContactShadows.js +430 -430
  348. package/lib/engine-components/DeleteBox.d.ts +19 -19
  349. package/lib/engine-components/DeleteBox.js +58 -58
  350. package/lib/engine-components/DeviceFlag.d.ts +16 -16
  351. package/lib/engine-components/DeviceFlag.js +47 -47
  352. package/lib/engine-components/DragControls.d.ts +170 -170
  353. package/lib/engine-components/DragControls.js +1421 -1421
  354. package/lib/engine-components/DropListener.d.ts +215 -215
  355. package/lib/engine-components/DropListener.js +630 -630
  356. package/lib/engine-components/Duplicatable.d.ts +35 -35
  357. package/lib/engine-components/Duplicatable.js +202 -202
  358. package/lib/engine-components/EventList.d.ts +54 -54
  359. package/lib/engine-components/EventList.js +232 -232
  360. package/lib/engine-components/EventTrigger.d.ts +33 -33
  361. package/lib/engine-components/EventTrigger.js +75 -75
  362. package/lib/engine-components/EventType.d.ts +22 -22
  363. package/lib/engine-components/EventType.js +23 -23
  364. package/lib/engine-components/FlyControls.d.ts +10 -0
  365. package/lib/engine-components/FlyControls.js +29 -0
  366. package/lib/engine-components/FlyControls.js.map +1 -0
  367. package/lib/engine-components/Fog.d.ts +22 -22
  368. package/lib/engine-components/Fog.js +61 -61
  369. package/lib/engine-components/Gizmos.d.ts +17 -17
  370. package/lib/engine-components/Gizmos.js +64 -64
  371. package/lib/engine-components/GridHelper.d.ts +20 -20
  372. package/lib/engine-components/GridHelper.js +54 -54
  373. package/lib/engine-components/GroundProjection.d.ts +67 -67
  374. package/lib/engine-components/GroundProjection.js +343 -343
  375. package/lib/engine-components/Interactable.d.ts +12 -12
  376. package/lib/engine-components/Interactable.js +12 -12
  377. package/lib/engine-components/Joints.d.ts +19 -19
  378. package/lib/engine-components/Joints.js +51 -51
  379. package/lib/engine-components/LODGroup.d.ts +35 -35
  380. package/lib/engine-components/LODGroup.js +152 -152
  381. package/lib/engine-components/Light.d.ts +180 -180
  382. package/lib/engine-components/Light.js +535 -535
  383. package/lib/engine-components/LookAtConstraint.d.ts +19 -19
  384. package/lib/engine-components/LookAtConstraint.js +35 -35
  385. package/lib/engine-components/NeedleMenu.d.ts +50 -50
  386. package/lib/engine-components/NeedleMenu.js +92 -92
  387. package/lib/engine-components/NeedleMenu.js.map +1 -1
  388. package/lib/engine-components/NestedGltf.d.ts +25 -25
  389. package/lib/engine-components/NestedGltf.js +88 -88
  390. package/lib/engine-components/Networking.d.ts +54 -54
  391. package/lib/engine-components/Networking.js +112 -112
  392. package/lib/engine-components/OffsetConstraint.d.ts +14 -14
  393. package/lib/engine-components/OffsetConstraint.js +65 -65
  394. package/lib/engine-components/OrbitControls.d.ts +266 -266
  395. package/lib/engine-components/OrbitControls.js +1009 -1009
  396. package/lib/engine-components/PlayerColor.d.ts +19 -19
  397. package/lib/engine-components/PlayerColor.js +94 -94
  398. package/lib/engine-components/ReflectionProbe.d.ts +27 -27
  399. package/lib/engine-components/ReflectionProbe.js +201 -201
  400. package/lib/engine-components/ReflectionProbe.js.map +1 -1
  401. package/lib/engine-components/Renderer.d.ts +153 -153
  402. package/lib/engine-components/Renderer.js +830 -830
  403. package/lib/engine-components/RendererInstancing.d.ts +140 -140
  404. package/lib/engine-components/RendererInstancing.js +744 -744
  405. package/lib/engine-components/RendererLightmap.d.ts +24 -24
  406. package/lib/engine-components/RendererLightmap.js +182 -182
  407. package/lib/engine-components/RigidBody.d.ts +155 -155
  408. package/lib/engine-components/RigidBody.js +517 -517
  409. package/lib/engine-components/SceneSwitcher.d.ts +263 -263
  410. package/lib/engine-components/SceneSwitcher.js +951 -951
  411. package/lib/engine-components/ScreenCapture.d.ts +144 -144
  412. package/lib/engine-components/ScreenCapture.js +547 -547
  413. package/lib/engine-components/ShadowCatcher.d.ts +33 -33
  414. package/lib/engine-components/ShadowCatcher.js +166 -166
  415. package/lib/engine-components/Skybox.d.ts +82 -82
  416. package/lib/engine-components/Skybox.js +448 -448
  417. package/lib/engine-components/SmoothFollow.d.ts +34 -34
  418. package/lib/engine-components/SmoothFollow.js +82 -82
  419. package/lib/engine-components/SpatialTrigger.d.ts +102 -102
  420. package/lib/engine-components/SpatialTrigger.js +225 -225
  421. package/lib/engine-components/SpectatorCamera.d.ts +111 -111
  422. package/lib/engine-components/SpectatorCamera.js +715 -715
  423. package/lib/engine-components/SphereCollider.d.ts +2 -2
  424. package/lib/engine-components/SphereCollider.js +2 -2
  425. package/lib/engine-components/SpriteRenderer.d.ts +132 -132
  426. package/lib/engine-components/SpriteRenderer.js +472 -472
  427. package/lib/engine-components/SyncedCamera.d.ts +41 -41
  428. package/lib/engine-components/SyncedCamera.js +199 -199
  429. package/lib/engine-components/SyncedRoom.d.ts +106 -106
  430. package/lib/engine-components/SyncedRoom.js +371 -371
  431. package/lib/engine-components/SyncedTransform.d.ts +94 -94
  432. package/lib/engine-components/SyncedTransform.js +331 -331
  433. package/lib/engine-components/TestRunner.d.ts +16 -16
  434. package/lib/engine-components/TestRunner.js +102 -102
  435. package/lib/engine-components/TransformGizmo.d.ts +75 -75
  436. package/lib/engine-components/TransformGizmo.js +209 -209
  437. package/lib/engine-components/VideoPlayer.d.ts +184 -184
  438. package/lib/engine-components/VideoPlayer.js +978 -978
  439. package/lib/engine-components/Voip.d.ts +67 -67
  440. package/lib/engine-components/Voip.js +360 -360
  441. package/lib/engine-components/api.d.ts +51 -51
  442. package/lib/engine-components/api.js +50 -50
  443. package/lib/engine-components/avatar/AvatarBlink_Simple.d.ts +11 -11
  444. package/lib/engine-components/avatar/AvatarBlink_Simple.js +76 -76
  445. package/lib/engine-components/avatar/AvatarEyeLook_Rotation.d.ts +14 -14
  446. package/lib/engine-components/avatar/AvatarEyeLook_Rotation.js +68 -68
  447. package/lib/engine-components/avatar/Avatar_Brain_LookAt.d.ts +29 -29
  448. package/lib/engine-components/avatar/Avatar_Brain_LookAt.js +121 -121
  449. package/lib/engine-components/avatar/Avatar_MouthShapes.d.ts +15 -15
  450. package/lib/engine-components/avatar/Avatar_MouthShapes.js +79 -79
  451. package/lib/engine-components/avatar/Avatar_MustacheShake.d.ts +9 -9
  452. package/lib/engine-components/avatar/Avatar_MustacheShake.js +29 -29
  453. package/lib/engine-components/codegen/components.d.ts +216 -216
  454. package/lib/engine-components/codegen/components.js +218 -218
  455. package/lib/engine-components/debug/LogStats.d.ts +5 -5
  456. package/lib/engine-components/debug/LogStats.js +18 -18
  457. package/lib/engine-components/export/gltf/GltfExport.d.ts +30 -30
  458. package/lib/engine-components/export/gltf/GltfExport.js +246 -246
  459. package/lib/engine-components/export/gltf/index.d.ts +1 -1
  460. package/lib/engine-components/export/gltf/index.js +1 -1
  461. package/lib/engine-components/export/index.d.ts +1 -1
  462. package/lib/engine-components/export/index.js +1 -1
  463. package/lib/engine-components/export/usdz/Extension.d.ts +22 -22
  464. package/lib/engine-components/export/usdz/Extension.js +1 -1
  465. package/lib/engine-components/export/usdz/ThreeUSDZExporter.d.ts +160 -160
  466. package/lib/engine-components/export/usdz/ThreeUSDZExporter.js +1782 -1782
  467. package/lib/engine-components/export/usdz/USDZExporter.d.ts +130 -130
  468. package/lib/engine-components/export/usdz/USDZExporter.js +663 -663
  469. package/lib/engine-components/export/usdz/extensions/Animation.d.ts +106 -106
  470. package/lib/engine-components/export/usdz/extensions/Animation.js +1071 -1071
  471. package/lib/engine-components/export/usdz/extensions/DocumentExtension.d.ts +5 -5
  472. package/lib/engine-components/export/usdz/extensions/DocumentExtension.js +6 -6
  473. package/lib/engine-components/export/usdz/extensions/USDZText.d.ts +54 -54
  474. package/lib/engine-components/export/usdz/extensions/USDZText.js +203 -203
  475. package/lib/engine-components/export/usdz/extensions/USDZUI.d.ts +8 -8
  476. package/lib/engine-components/export/usdz/extensions/USDZUI.js +157 -157
  477. package/lib/engine-components/export/usdz/extensions/behavior/Actions.d.ts +30 -30
  478. package/lib/engine-components/export/usdz/extensions/behavior/Actions.js +88 -88
  479. package/lib/engine-components/export/usdz/extensions/behavior/AudioExtension.d.ts +10 -10
  480. package/lib/engine-components/export/usdz/extensions/behavior/AudioExtension.js +86 -86
  481. package/lib/engine-components/export/usdz/extensions/behavior/Behaviour.d.ts +28 -28
  482. package/lib/engine-components/export/usdz/extensions/behavior/Behaviour.js +290 -290
  483. package/lib/engine-components/export/usdz/extensions/behavior/BehaviourComponents.d.ts +190 -190
  484. package/lib/engine-components/export/usdz/extensions/behavior/BehaviourComponents.js +1060 -1060
  485. package/lib/engine-components/export/usdz/extensions/behavior/BehavioursBuilder.d.ts +135 -135
  486. package/lib/engine-components/export/usdz/extensions/behavior/BehavioursBuilder.js +548 -548
  487. package/lib/engine-components/export/usdz/extensions/behavior/PhysicsExtension.d.ts +7 -7
  488. package/lib/engine-components/export/usdz/extensions/behavior/PhysicsExtension.js +115 -115
  489. package/lib/engine-components/export/usdz/index.d.ts +3 -3
  490. package/lib/engine-components/export/usdz/index.js +2 -2
  491. package/lib/engine-components/export/usdz/utils/animationutils.d.ts +7 -7
  492. package/lib/engine-components/export/usdz/utils/animationutils.js +163 -163
  493. package/lib/engine-components/export/usdz/utils/quicklook.d.ts +2 -2
  494. package/lib/engine-components/export/usdz/utils/quicklook.js +43 -43
  495. package/lib/engine-components/particlesystem/ParticleSystem.d.ts +177 -177
  496. package/lib/engine-components/particlesystem/ParticleSystem.js +1176 -1176
  497. package/lib/engine-components/particlesystem/ParticleSystemModules.d.ts +526 -526
  498. package/lib/engine-components/particlesystem/ParticleSystemModules.js +1930 -1930
  499. package/lib/engine-components/particlesystem/ParticleSystemSubEmitter.d.ts +25 -25
  500. package/lib/engine-components/particlesystem/ParticleSystemSubEmitter.js +87 -87
  501. package/lib/engine-components/particlesystem/api.d.ts +2 -2
  502. package/lib/engine-components/particlesystem/api.js +2 -2
  503. package/lib/engine-components/postprocessing/Effects/Antialiasing.d.ts +17 -17
  504. package/lib/engine-components/postprocessing/Effects/Antialiasing.js +50 -50
  505. package/lib/engine-components/postprocessing/Effects/BloomEffect.d.ts +46 -46
  506. package/lib/engine-components/postprocessing/Effects/BloomEffect.js +113 -113
  507. package/lib/engine-components/postprocessing/Effects/ChromaticAberration.d.ts +11 -11
  508. package/lib/engine-components/postprocessing/Effects/ChromaticAberration.js +39 -39
  509. package/lib/engine-components/postprocessing/Effects/ColorAdjustments.d.ts +15 -15
  510. package/lib/engine-components/postprocessing/Effects/ColorAdjustments.js +92 -92
  511. package/lib/engine-components/postprocessing/Effects/DepthOfField.d.ts +25 -25
  512. package/lib/engine-components/postprocessing/Effects/DepthOfField.js +104 -104
  513. package/lib/engine-components/postprocessing/Effects/EffectWrapper.d.ts +12 -12
  514. package/lib/engine-components/postprocessing/Effects/EffectWrapper.js +18 -18
  515. package/lib/engine-components/postprocessing/Effects/Pixelation.d.ts +11 -11
  516. package/lib/engine-components/postprocessing/Effects/Pixelation.js +32 -32
  517. package/lib/engine-components/postprocessing/Effects/ScreenspaceAmbientOcclusion.d.ts +18 -18
  518. package/lib/engine-components/postprocessing/Effects/ScreenspaceAmbientOcclusion.js +91 -91
  519. package/lib/engine-components/postprocessing/Effects/ScreenspaceAmbientOcclusionN8.d.ts +70 -70
  520. package/lib/engine-components/postprocessing/Effects/ScreenspaceAmbientOcclusionN8.js +175 -175
  521. package/lib/engine-components/postprocessing/Effects/Sharpening.d.ts +17 -17
  522. package/lib/engine-components/postprocessing/Effects/Sharpening.js +123 -123
  523. package/lib/engine-components/postprocessing/Effects/TiltShiftEffect.d.ts +17 -17
  524. package/lib/engine-components/postprocessing/Effects/TiltShiftEffect.js +70 -70
  525. package/lib/engine-components/postprocessing/Effects/Tonemapping.d.ts +26 -26
  526. package/lib/engine-components/postprocessing/Effects/Tonemapping.js +138 -138
  527. package/lib/engine-components/postprocessing/Effects/Vignette.d.ts +15 -15
  528. package/lib/engine-components/postprocessing/Effects/Vignette.js +60 -60
  529. package/lib/engine-components/postprocessing/PostProcessingEffect.d.ts +72 -72
  530. package/lib/engine-components/postprocessing/PostProcessingEffect.js +149 -149
  531. package/lib/engine-components/postprocessing/PostProcessingHandler.d.ts +25 -25
  532. package/lib/engine-components/postprocessing/PostProcessingHandler.js +350 -350
  533. package/lib/engine-components/postprocessing/Volume.d.ts +89 -89
  534. package/lib/engine-components/postprocessing/Volume.js +367 -367
  535. package/lib/engine-components/postprocessing/VolumeParameter.d.ts +26 -26
  536. package/lib/engine-components/postprocessing/VolumeParameter.js +136 -136
  537. package/lib/engine-components/postprocessing/VolumeProfile.d.ts +15 -15
  538. package/lib/engine-components/postprocessing/VolumeProfile.js +60 -60
  539. package/lib/engine-components/postprocessing/index.d.ts +5 -5
  540. package/lib/engine-components/postprocessing/index.js +5 -5
  541. package/lib/engine-components/postprocessing/utils.d.ts +11 -11
  542. package/lib/engine-components/postprocessing/utils.js +37 -37
  543. package/lib/engine-components/timeline/PlayableDirector.d.ts +163 -163
  544. package/lib/engine-components/timeline/PlayableDirector.js +686 -686
  545. package/lib/engine-components/timeline/SignalAsset.d.ts +24 -24
  546. package/lib/engine-components/timeline/SignalAsset.js +130 -130
  547. package/lib/engine-components/timeline/TimelineModels.d.ts +89 -89
  548. package/lib/engine-components/timeline/TimelineModels.js +22 -22
  549. package/lib/engine-components/timeline/TimelineTracks.d.ts +110 -110
  550. package/lib/engine-components/timeline/TimelineTracks.js +879 -879
  551. package/lib/engine-components/timeline/index.d.ts +4 -4
  552. package/lib/engine-components/timeline/index.js +3 -3
  553. package/lib/engine-components/ui/BaseUIComponent.d.ts +49 -49
  554. package/lib/engine-components/ui/BaseUIComponent.js +170 -170
  555. package/lib/engine-components/ui/Button.d.ts +64 -64
  556. package/lib/engine-components/ui/Button.js +315 -315
  557. package/lib/engine-components/ui/Canvas.d.ts +74 -74
  558. package/lib/engine-components/ui/Canvas.js +407 -407
  559. package/lib/engine-components/ui/CanvasGroup.d.ts +19 -19
  560. package/lib/engine-components/ui/CanvasGroup.js +58 -58
  561. package/lib/engine-components/ui/EventSystem.d.ts +125 -125
  562. package/lib/engine-components/ui/EventSystem.js +764 -764
  563. package/lib/engine-components/ui/Graphic.d.ts +55 -55
  564. package/lib/engine-components/ui/Graphic.js +254 -254
  565. package/lib/engine-components/ui/Image.d.ts +35 -35
  566. package/lib/engine-components/ui/Image.js +116 -116
  567. package/lib/engine-components/ui/InputField.d.ts +42 -42
  568. package/lib/engine-components/ui/InputField.js +268 -268
  569. package/lib/engine-components/ui/Interfaces.d.ts +38 -38
  570. package/lib/engine-components/ui/Interfaces.js +12 -12
  571. package/lib/engine-components/ui/Layout.d.ts +84 -84
  572. package/lib/engine-components/ui/Layout.js +330 -330
  573. package/lib/engine-components/ui/Outline.d.ts +7 -7
  574. package/lib/engine-components/ui/Outline.js +20 -20
  575. package/lib/engine-components/ui/PointerEvents.d.ts +115 -115
  576. package/lib/engine-components/ui/PointerEvents.js +145 -145
  577. package/lib/engine-components/ui/RaycastUtils.d.ts +11 -11
  578. package/lib/engine-components/ui/RaycastUtils.js +67 -67
  579. package/lib/engine-components/ui/Raycaster.d.ts +30 -30
  580. package/lib/engine-components/ui/Raycaster.js +95 -95
  581. package/lib/engine-components/ui/RectTransform.d.ts +61 -61
  582. package/lib/engine-components/ui/RectTransform.js +353 -353
  583. package/lib/engine-components/ui/SpatialHtml.d.ts +8 -8
  584. package/lib/engine-components/ui/SpatialHtml.js +79 -79
  585. package/lib/engine-components/ui/Text.d.ts +78 -78
  586. package/lib/engine-components/ui/Text.js +539 -539
  587. package/lib/engine-components/ui/Utils.d.ts +24 -24
  588. package/lib/engine-components/ui/Utils.js +90 -90
  589. package/lib/engine-components/ui/index.d.ts +1 -1
  590. package/lib/engine-components/ui/index.js +1 -1
  591. package/lib/engine-components/utils/EnvironmentScene.d.ts +5 -5
  592. package/lib/engine-components/utils/EnvironmentScene.js +205 -205
  593. package/lib/engine-components/utils/LookAt.d.ts +31 -31
  594. package/lib/engine-components/utils/LookAt.js +82 -82
  595. package/lib/engine-components/utils/OpenURL.d.ts +42 -42
  596. package/lib/engine-components/utils/OpenURL.js +119 -119
  597. package/lib/engine-components/webxr/Avatar.d.ts +25 -25
  598. package/lib/engine-components/webxr/Avatar.js +255 -255
  599. package/lib/engine-components/webxr/TeleportTarget.d.ts +7 -7
  600. package/lib/engine-components/webxr/TeleportTarget.js +7 -7
  601. package/lib/engine-components/webxr/WebARCameraBackground.d.ts +30 -30
  602. package/lib/engine-components/webxr/WebARCameraBackground.js +155 -155
  603. package/lib/engine-components/webxr/WebARSessionRoot.d.ts +98 -98
  604. package/lib/engine-components/webxr/WebARSessionRoot.js +770 -770
  605. package/lib/engine-components/webxr/WebXR.d.ts +232 -232
  606. package/lib/engine-components/webxr/WebXR.js +561 -561
  607. package/lib/engine-components/webxr/WebXRAvatar.d.ts +27 -27
  608. package/lib/engine-components/webxr/WebXRAvatar.js +44 -44
  609. package/lib/engine-components/webxr/WebXRImageTracking.d.ts +86 -86
  610. package/lib/engine-components/webxr/WebXRImageTracking.js +470 -470
  611. package/lib/engine-components/webxr/WebXRPlaneTracking.d.ts +92 -92
  612. package/lib/engine-components/webxr/WebXRPlaneTracking.js +500 -500
  613. package/lib/engine-components/webxr/WebXRRig.d.ts +32 -32
  614. package/lib/engine-components/webxr/WebXRRig.js +72 -72
  615. package/lib/engine-components/webxr/XRFlag.d.ts +38 -38
  616. package/lib/engine-components/webxr/XRFlag.js +139 -139
  617. package/lib/engine-components/webxr/controllers/XRControllerFollow.d.ts +47 -47
  618. package/lib/engine-components/webxr/controllers/XRControllerFollow.js +120 -120
  619. package/lib/engine-components/webxr/controllers/XRControllerModel.d.ts +43 -43
  620. package/lib/engine-components/webxr/controllers/XRControllerModel.js +351 -351
  621. package/lib/engine-components/webxr/controllers/XRControllerMovement.d.ts +78 -78
  622. package/lib/engine-components/webxr/controllers/XRControllerMovement.js +506 -506
  623. package/lib/engine-components/webxr/index.d.ts +3 -3
  624. package/lib/engine-components/webxr/index.js +3 -3
  625. package/lib/engine-components/webxr/types.d.ts +3 -3
  626. package/lib/engine-components/webxr/types.js +1 -1
  627. package/lib/engine-components-experimental/Presentation.d.ts +6 -6
  628. package/lib/engine-components-experimental/Presentation.js +9 -9
  629. package/lib/engine-components-experimental/api.d.ts +4 -4
  630. package/lib/engine-components-experimental/api.js +4 -4
  631. package/lib/engine-components-experimental/networking/PlayerSync.d.ts +156 -156
  632. package/lib/engine-components-experimental/networking/PlayerSync.js +377 -377
  633. package/lib/engine-schemes/api.d.ts +12 -12
  634. package/lib/engine-schemes/api.js +12 -12
  635. package/lib/engine-schemes/schemes.d.ts +7 -7
  636. package/lib/engine-schemes/schemes.js +19 -19
  637. package/lib/engine-schemes/synced-camera-model.d.ts +25 -25
  638. package/lib/engine-schemes/synced-camera-model.js +67 -67
  639. package/lib/engine-schemes/synced-transform-model.d.ts +31 -31
  640. package/lib/engine-schemes/synced-transform-model.js +66 -66
  641. package/lib/engine-schemes/transform.d.ts +12 -12
  642. package/lib/engine-schemes/transform.js +39 -39
  643. package/lib/engine-schemes/vec2.d.ts +10 -10
  644. package/lib/engine-schemes/vec2.js +25 -25
  645. package/lib/engine-schemes/vec3.d.ts +11 -11
  646. package/lib/engine-schemes/vec3.js +29 -29
  647. package/lib/engine-schemes/vec4.d.ts +12 -12
  648. package/lib/engine-schemes/vec4.js +33 -33
  649. package/lib/engine-schemes/vr-user-state-buffer.d.ts +37 -37
  650. package/lib/engine-schemes/vr-user-state-buffer.js +110 -110
  651. package/lib/include/three/EXT_mesh_gpu_instancing_exporter.d.ts +6 -6
  652. package/lib/include/three/EXT_mesh_gpu_instancing_exporter.js +45 -45
  653. package/lib/needle-engine.d.ts +7 -7
  654. package/lib/needle-engine.js +64 -64
  655. package/package.json +2 -2
  656. package/plugins/common/buildinfo.js +64 -64
  657. package/plugins/common/cloud.js +1 -1
  658. package/plugins/common/config.cjs +31 -31
  659. package/plugins/common/config.js +35 -35
  660. package/plugins/common/files.js +31 -31
  661. package/plugins/common/generator.js +10 -10
  662. package/plugins/common/license.js +355 -341
  663. package/plugins/common/npm.js +15 -15
  664. package/plugins/common/timers.js +7 -7
  665. package/plugins/common/version.js +37 -37
  666. package/plugins/gltf-packer.mjs +1 -1
  667. package/plugins/next/alias.cjs +39 -39
  668. package/plugins/next/license.cjs +18 -18
  669. package/plugins/next/meshbvhworker.cjs +18 -18
  670. package/plugins/next/next.js +128 -128
  671. package/plugins/types/index.d.ts +2 -2
  672. package/plugins/types/license.d.ts +24 -24
  673. package/plugins/types/needleConfig.d.ts +27 -27
  674. package/plugins/types/userconfig.d.ts +108 -108
  675. package/plugins/types/webmanifest.d.ts +32 -32
  676. package/plugins/vite/alias.js +174 -174
  677. package/plugins/vite/asap.js +245 -245
  678. package/plugins/vite/build-pipeline.js +355 -355
  679. package/plugins/vite/build.js +19 -19
  680. package/plugins/vite/buildinfo.js +41 -41
  681. package/plugins/vite/config.js +106 -106
  682. package/plugins/vite/copyfiles.js +138 -138
  683. package/plugins/vite/defines.js +66 -66
  684. package/plugins/vite/dependencies.js +223 -223
  685. package/plugins/vite/dependency-watcher.js +231 -231
  686. package/plugins/vite/drop-client.js +76 -76
  687. package/plugins/vite/drop.js +87 -87
  688. package/plugins/vite/editor-connection.js +124 -124
  689. package/plugins/vite/facebook-instant-games.js +99 -99
  690. package/plugins/vite/gzip.js +5 -5
  691. package/plugins/vite/imports-logger.js +143 -143
  692. package/plugins/vite/index.js +139 -139
  693. package/plugins/vite/license.js +55 -55
  694. package/plugins/vite/meta.js +163 -163
  695. package/plugins/vite/npm.js +7 -7
  696. package/plugins/vite/peer.js +29 -29
  697. package/plugins/vite/poster-client.js +73 -73
  698. package/plugins/vite/poster.js +79 -79
  699. package/plugins/vite/pwa.js +604 -604
  700. package/plugins/vite/reload-client.js +15 -15
  701. package/plugins/vite/reload.js +363 -363
  702. package/plugins/vite/server.js +66 -66
  703. package/plugins/vite/transform-codegen.js +55 -55
  704. package/plugins/vite/transform.js +31 -31
  705. package/plugins/vite/vite-4.4-hack.js +31 -31
  706. package/src/asap/needle-asap.ts +111 -111
  707. package/src/asap/sessiongranted.ts +75 -75
  708. package/src/asap/utils.ts +4 -4
  709. package/src/engine/analytics/index.ts +10 -10
  710. package/src/engine/analytics/lcp.ts +35 -35
  711. package/src/engine/api.ts +81 -81
  712. package/src/engine/assets/index.ts +59 -59
  713. package/src/engine/assets/static.js +5 -5
  714. package/src/engine/codegen/register_types.ts +300 -300
  715. package/src/engine/debug/debug.ts +51 -51
  716. package/src/engine/debug/debug_console.ts +333 -333
  717. package/src/engine/debug/debug_overlay.ts +332 -332
  718. package/src/engine/debug/debug_spatial_console.ts +429 -429
  719. package/src/engine/debug/index.ts +1 -1
  720. package/src/engine/engine_addressables.ts +679 -679
  721. package/src/engine/engine_animation.ts +145 -145
  722. package/src/engine/engine_application.ts +113 -113
  723. package/src/engine/engine_assetdatabase.ts +387 -387
  724. package/src/engine/engine_audio.ts +24 -24
  725. package/src/engine/engine_camera.ts +39 -39
  726. package/src/engine/engine_components.ts +374 -374
  727. package/src/engine/engine_components_internal.ts +40 -40
  728. package/src/engine/engine_constants.ts +52 -52
  729. package/src/engine/engine_context.ts +1686 -1686
  730. package/src/engine/engine_context_registry.ts +129 -129
  731. package/src/engine/engine_coroutine.ts +54 -54
  732. package/src/engine/engine_create_objects.ts +398 -398
  733. package/src/engine/engine_default_parameters.ts +3 -3
  734. package/src/engine/engine_editor-sync.ts +28 -28
  735. package/src/engine/engine_element.ts +872 -869
  736. package/src/engine/engine_element_attributes.ts +85 -85
  737. package/src/engine/engine_element_extras.ts +16 -16
  738. package/src/engine/engine_element_loading.ts +381 -381
  739. package/src/engine/engine_element_overlay.ts +186 -186
  740. package/src/engine/engine_fileloader.js +9 -9
  741. package/src/engine/engine_gameobject.ts +684 -684
  742. package/src/engine/engine_generic_utils.js +13 -13
  743. package/src/engine/engine_gizmos.ts +577 -577
  744. package/src/engine/engine_gltf.ts +29 -29
  745. package/src/engine/engine_gltf_builtin_components.ts +403 -403
  746. package/src/engine/engine_hot_reload.ts +198 -198
  747. package/src/engine/engine_input.ts +1460 -1460
  748. package/src/engine/engine_input_utils.ts +23 -23
  749. package/src/engine/engine_instancing.ts +45 -45
  750. package/src/engine/engine_license.ts +378 -329
  751. package/src/engine/engine_lifecycle_api.ts +106 -106
  752. package/src/engine/engine_lifecycle_functions_internal.ts +193 -193
  753. package/src/engine/engine_lightdata.ts +117 -117
  754. package/src/engine/engine_loaders.ts +82 -82
  755. package/src/engine/engine_lods.ts +168 -168
  756. package/src/engine/engine_mainloop_utils.ts +472 -472
  757. package/src/engine/engine_math.ts +282 -282
  758. package/src/engine/engine_modules.ts +83 -83
  759. package/src/engine/engine_networking.ts +841 -841
  760. package/src/engine/engine_networking_auto.ts +352 -352
  761. package/src/engine/engine_networking_blob.ts +254 -254
  762. package/src/engine/engine_networking_files.ts +217 -217
  763. package/src/engine/engine_networking_files_default_components.ts +58 -58
  764. package/src/engine/engine_networking_instantiate.ts +419 -419
  765. package/src/engine/engine_networking_peer.ts +159 -159
  766. package/src/engine/engine_networking_streams.ts +713 -713
  767. package/src/engine/engine_networking_types.ts +24 -24
  768. package/src/engine/engine_networking_utils.ts +23 -23
  769. package/src/engine/engine_networking_websocket.ts +2 -2
  770. package/src/engine/engine_patcher.ts +199 -199
  771. package/src/engine/engine_physics.ts +783 -783
  772. package/src/engine/engine_physics.types.ts +46 -46
  773. package/src/engine/engine_physics_rapier.ts +1579 -1579
  774. package/src/engine/engine_playerview.ts +80 -80
  775. package/src/engine/engine_scenelighting.ts +294 -294
  776. package/src/engine/engine_scenetools.ts +365 -365
  777. package/src/engine/engine_serialization.ts +2 -2
  778. package/src/engine/engine_serialization_builtin_serializer.ts +473 -473
  779. package/src/engine/engine_serialization_core.ts +705 -705
  780. package/src/engine/engine_serialization_decorator.ts +80 -80
  781. package/src/engine/engine_setup.ts +1 -1
  782. package/src/engine/engine_shaders.ts +267 -267
  783. package/src/engine/engine_shims.ts +32 -32
  784. package/src/engine/engine_test_utils.ts +109 -109
  785. package/src/engine/engine_texture.ts +82 -82
  786. package/src/engine/engine_three_utils.ts +849 -849
  787. package/src/engine/engine_time.ts +94 -94
  788. package/src/engine/engine_time_utils.ts +237 -237
  789. package/src/engine/engine_tonemapping.ts +210 -210
  790. package/src/engine/engine_types.ts +714 -714
  791. package/src/engine/engine_typestore.ts +63 -63
  792. package/src/engine/engine_util_decorator.ts +136 -136
  793. package/src/engine/engine_utils.ts +972 -972
  794. package/src/engine/engine_utils_format.ts +212 -212
  795. package/src/engine/engine_utils_screenshot.ts +698 -698
  796. package/src/engine/engine_utils_screenshot.xr.ts +103 -103
  797. package/src/engine/export/gltf/Writers.ts +34 -34
  798. package/src/engine/export/gltf/index.ts +158 -158
  799. package/src/engine/export/index.ts +2 -2
  800. package/src/engine/export/state.ts +19 -19
  801. package/src/engine/export/utils.ts +9 -9
  802. package/src/engine/extensions/EXT_texture_exr.ts +50 -50
  803. package/src/engine/extensions/NEEDLE_animator_controller_model.ts +195 -195
  804. package/src/engine/extensions/NEEDLE_components.ts +268 -268
  805. package/src/engine/extensions/NEEDLE_gameobject_data.ts +81 -81
  806. package/src/engine/extensions/NEEDLE_lighting_settings.ts +185 -185
  807. package/src/engine/extensions/NEEDLE_lightmaps.ts +119 -119
  808. package/src/engine/extensions/NEEDLE_persistent_assets.ts +76 -76
  809. package/src/engine/extensions/NEEDLE_render_objects.ts +209 -209
  810. package/src/engine/extensions/NEEDLE_techniques_webgl.ts +640 -640
  811. package/src/engine/extensions/extension_resolver.ts +4 -4
  812. package/src/engine/extensions/extension_utils.ts +166 -166
  813. package/src/engine/extensions/extensions.ts +135 -135
  814. package/src/engine/extensions/index.ts +5 -5
  815. package/src/engine/extensions/usage_tracker.ts +100 -100
  816. package/src/engine/js-extensions/Camera.ts +37 -37
  817. package/src/engine/js-extensions/ExtensionUtils.ts +85 -85
  818. package/src/engine/js-extensions/Layers.ts +23 -23
  819. package/src/engine/js-extensions/Object3D.ts +296 -296
  820. package/src/engine/js-extensions/RGBAColor.ts +125 -125
  821. package/src/engine/js-extensions/Vector.ts +18 -18
  822. package/src/engine/js-extensions/index.ts +4 -4
  823. package/src/engine/physics/workers/mesh-bvh/GenerateMeshBVHWorker.js +122 -122
  824. package/src/engine/shaders/shaderData.ts +67 -67
  825. package/src/engine/tests/test_utils.ts +63 -63
  826. package/src/engine/webcomponents/WebXRButtons.ts +260 -260
  827. package/src/engine/webcomponents/api.ts +6 -6
  828. package/src/engine/webcomponents/buttons.ts +262 -262
  829. package/src/engine/webcomponents/fonts.ts +41 -41
  830. package/src/engine/webcomponents/icons.ts +57 -57
  831. package/src/engine/webcomponents/index.ts +1 -1
  832. package/src/engine/webcomponents/logo-element.ts +78 -78
  833. package/src/engine/webcomponents/needle menu/needle-menu-spatial.ts +573 -573
  834. package/src/engine/webcomponents/needle menu/needle-menu.ts +1118 -1107
  835. package/src/engine/webcomponents/needle-button.ts +181 -181
  836. package/src/engine/xr/NeedleXRController.ts +1125 -1125
  837. package/src/engine/xr/NeedleXRSession.ts +1585 -1585
  838. package/src/engine/xr/NeedleXRSync.ts +220 -220
  839. package/src/engine/xr/SceneTransition.ts +78 -78
  840. package/src/engine/xr/TempXRContext.ts +216 -216
  841. package/src/engine/xr/XRRig.ts +9 -9
  842. package/src/engine/xr/api.ts +5 -5
  843. package/src/engine/xr/events.ts +102 -102
  844. package/src/engine/xr/internal.ts +34 -34
  845. package/src/engine/xr/usdz.ts +30 -30
  846. package/src/engine/xr/utils.ts +39 -39
  847. package/src/engine-components/AlignmentConstraint.ts +36 -36
  848. package/src/engine-components/Animation.ts +557 -557
  849. package/src/engine-components/AnimationCurve.ts +150 -150
  850. package/src/engine-components/AnimationUtils.ts +28 -28
  851. package/src/engine-components/AnimationUtilsAutoplay.ts +43 -43
  852. package/src/engine-components/Animator.ts +397 -397
  853. package/src/engine-components/AnimatorController.ts +1293 -1293
  854. package/src/engine-components/AudioListener.ts +92 -92
  855. package/src/engine-components/AudioSource.ts +639 -639
  856. package/src/engine-components/AvatarLoader.ts +263 -263
  857. package/src/engine-components/AxesHelper.ts +59 -59
  858. package/src/engine-components/BasicIKConstraint.ts +54 -54
  859. package/src/engine-components/BoxCollider.ts +1 -1
  860. package/src/engine-components/BoxHelperComponent.ts +114 -114
  861. package/src/engine-components/Camera.ts +719 -719
  862. package/src/engine-components/CameraUtils.ts +136 -136
  863. package/src/engine-components/CharacterController.ts +253 -253
  864. package/src/engine-components/Collider.ts +374 -374
  865. package/src/engine-components/Component.ts +1294 -1294
  866. package/src/engine-components/ContactShadows.ts +482 -482
  867. package/src/engine-components/DeleteBox.ts +62 -62
  868. package/src/engine-components/DeviceFlag.ts +46 -46
  869. package/src/engine-components/DragControls.ts +1623 -1623
  870. package/src/engine-components/DropListener.ts +698 -698
  871. package/src/engine-components/Duplicatable.ts +198 -198
  872. package/src/engine-components/EventList.ts +266 -266
  873. package/src/engine-components/EventTrigger.ts +74 -74
  874. package/src/engine-components/EventType.ts +22 -22
  875. package/src/engine-components/Fog.ts +60 -60
  876. package/src/engine-components/Gizmos.ts +56 -56
  877. package/src/engine-components/GridHelper.ts +48 -48
  878. package/src/engine-components/GroundProjection.ts +356 -356
  879. package/src/engine-components/Interactable.ts +14 -14
  880. package/src/engine-components/Joints.ts +52 -52
  881. package/src/engine-components/LODGroup.ts +153 -153
  882. package/src/engine-components/Light.ts +558 -558
  883. package/src/engine-components/LookAtConstraint.ts +25 -25
  884. package/src/engine-components/NeedleMenu.ts +84 -84
  885. package/src/engine-components/NestedGltf.ts +86 -86
  886. package/src/engine-components/Networking.ts +114 -114
  887. package/src/engine-components/OffsetConstraint.ts +60 -60
  888. package/src/engine-components/OrbitControls.ts +1068 -1068
  889. package/src/engine-components/PlayerColor.ts +103 -103
  890. package/src/engine-components/ReflectionProbe.ts +216 -216
  891. package/src/engine-components/Renderer.ts +900 -900
  892. package/src/engine-components/RendererInstancing.ts +855 -855
  893. package/src/engine-components/RendererLightmap.ts +198 -198
  894. package/src/engine-components/RigidBody.ts +526 -526
  895. package/src/engine-components/SceneSwitcher.ts +1013 -1013
  896. package/src/engine-components/ScreenCapture.ts +592 -592
  897. package/src/engine-components/ShadowCatcher.ts +172 -172
  898. package/src/engine-components/Skybox.ts +455 -455
  899. package/src/engine-components/SmoothFollow.ts +76 -76
  900. package/src/engine-components/SpatialTrigger.ts +229 -229
  901. package/src/engine-components/SpectatorCamera.ts +787 -787
  902. package/src/engine-components/SphereCollider.ts +1 -1
  903. package/src/engine-components/SpriteRenderer.ts +468 -468
  904. package/src/engine-components/SyncedCamera.ts +220 -220
  905. package/src/engine-components/SyncedRoom.ts +380 -380
  906. package/src/engine-components/SyncedTransform.ts +383 -383
  907. package/src/engine-components/TestRunner.ts +118 -118
  908. package/src/engine-components/TransformGizmo.ts +219 -219
  909. package/src/engine-components/VideoPlayer.ts +1025 -1025
  910. package/src/engine-components/Voip.ts +363 -363
  911. package/src/engine-components/api.ts +60 -60
  912. package/src/engine-components/avatar/AvatarBlink_Simple.ts +69 -69
  913. package/src/engine-components/avatar/AvatarEyeLook_Rotation.ts +63 -63
  914. package/src/engine-components/avatar/Avatar_Brain_LookAt.ts +139 -139
  915. package/src/engine-components/avatar/Avatar_MouthShapes.ts +83 -83
  916. package/src/engine-components/avatar/Avatar_MustacheShake.ts +31 -31
  917. package/src/engine-components/codegen/components.ts +217 -217
  918. package/src/engine-components/debug/LogStats.ts +21 -21
  919. package/src/engine-components/export/gltf/GltfExport.ts +265 -265
  920. package/src/engine-components/export/usdz/Extension.ts +24 -24
  921. package/src/engine-components/export/usdz/ThreeUSDZExporter.ts +2413 -2413
  922. package/src/engine-components/export/usdz/USDZExporter.ts +705 -705
  923. package/src/engine-components/export/usdz/extensions/Animation.ts +1204 -1204
  924. package/src/engine-components/export/usdz/extensions/DocumentExtension.ts +9 -9
  925. package/src/engine-components/export/usdz/extensions/USDZText.ts +240 -240
  926. package/src/engine-components/export/usdz/extensions/USDZUI.ts +189 -189
  927. package/src/engine-components/export/usdz/extensions/behavior/Actions.ts +99 -99
  928. package/src/engine-components/export/usdz/extensions/behavior/AudioExtension.ts +102 -102
  929. package/src/engine-components/export/usdz/extensions/behavior/Behaviour.ts +320 -320
  930. package/src/engine-components/export/usdz/extensions/behavior/BehaviourComponents.ts +1225 -1225
  931. package/src/engine-components/export/usdz/extensions/behavior/BehavioursBuilder.ts +646 -646
  932. package/src/engine-components/export/usdz/extensions/behavior/PhysicsExtension.ts +132 -132
  933. package/src/engine-components/export/usdz/index.ts +2 -2
  934. package/src/engine-components/export/usdz/utils/animationutils.ts +191 -191
  935. package/src/engine-components/export/usdz/utils/quicklook.ts +50 -50
  936. package/src/engine-components/particlesystem/ParticleSystem.ts +1287 -1287
  937. package/src/engine-components/particlesystem/ParticleSystemModules.ts +1765 -1765
  938. package/src/engine-components/particlesystem/ParticleSystemSubEmitter.ts +111 -111
  939. package/src/engine-components/particlesystem/api.ts +1 -1
  940. package/src/engine-components/postprocessing/Effects/Antialiasing.ts +55 -55
  941. package/src/engine-components/postprocessing/Effects/BloomEffect.ts +116 -116
  942. package/src/engine-components/postprocessing/Effects/ChromaticAberration.ts +37 -37
  943. package/src/engine-components/postprocessing/Effects/ColorAdjustments.ts +95 -95
  944. package/src/engine-components/postprocessing/Effects/DepthOfField.ts +103 -103
  945. package/src/engine-components/postprocessing/Effects/EffectWrapper.ts +25 -25
  946. package/src/engine-components/postprocessing/Effects/Pixelation.ts +32 -32
  947. package/src/engine-components/postprocessing/Effects/ScreenspaceAmbientOcclusion.ts +90 -90
  948. package/src/engine-components/postprocessing/Effects/ScreenspaceAmbientOcclusionN8.ts +191 -191
  949. package/src/engine-components/postprocessing/Effects/Sharpening.ts +138 -138
  950. package/src/engine-components/postprocessing/Effects/TiltShiftEffect.ts +61 -61
  951. package/src/engine-components/postprocessing/Effects/Tonemapping.ts +155 -155
  952. package/src/engine-components/postprocessing/Effects/Vignette.ts +59 -59
  953. package/src/engine-components/postprocessing/PostProcessingEffect.ts +172 -172
  954. package/src/engine-components/postprocessing/PostProcessingHandler.ts +398 -398
  955. package/src/engine-components/postprocessing/Volume.ts +410 -410
  956. package/src/engine-components/postprocessing/VolumeParameter.ts +158 -158
  957. package/src/engine-components/postprocessing/VolumeProfile.ts +61 -61
  958. package/src/engine-components/postprocessing/index.ts +5 -5
  959. package/src/engine-components/postprocessing/utils.ts +52 -52
  960. package/src/engine-components/timeline/PlayableDirector.ts +722 -722
  961. package/src/engine-components/timeline/SignalAsset.ts +144 -144
  962. package/src/engine-components/timeline/TimelineModels.ts +92 -92
  963. package/src/engine-components/timeline/TimelineTracks.ts +967 -967
  964. package/src/engine-components/timeline/index.ts +3 -3
  965. package/src/engine-components/ui/BaseUIComponent.ts +203 -203
  966. package/src/engine-components/ui/Button.ts +307 -307
  967. package/src/engine-components/ui/Canvas.ts +419 -419
  968. package/src/engine-components/ui/CanvasGroup.ts +54 -54
  969. package/src/engine-components/ui/EventSystem.ts +853 -853
  970. package/src/engine-components/ui/Graphic.ts +275 -275
  971. package/src/engine-components/ui/Image.ts +112 -112
  972. package/src/engine-components/ui/InputField.ts +321 -321
  973. package/src/engine-components/ui/Interfaces.ts +57 -57
  974. package/src/engine-components/ui/Layout.ts +334 -334
  975. package/src/engine-components/ui/Outline.ts +13 -13
  976. package/src/engine-components/ui/PointerEvents.ts +206 -206
  977. package/src/engine-components/ui/RaycastUtils.ts +69 -69
  978. package/src/engine-components/ui/Raycaster.ts +102 -102
  979. package/src/engine-components/ui/RectTransform.ts +372 -372
  980. package/src/engine-components/ui/SpatialHtml.ts +79 -79
  981. package/src/engine-components/ui/Text.ts +578 -578
  982. package/src/engine-components/ui/Utils.ts +112 -112
  983. package/src/engine-components/utils/EnvironmentScene.ts +245 -245
  984. package/src/engine-components/utils/LookAt.ts +88 -88
  985. package/src/engine-components/utils/OpenURL.ts +114 -114
  986. package/src/engine-components/webxr/Avatar.ts +265 -265
  987. package/src/engine-components/webxr/TeleportTarget.ts +9 -9
  988. package/src/engine-components/webxr/WebARCameraBackground.ts +175 -175
  989. package/src/engine-components/webxr/WebARSessionRoot.ts +880 -880
  990. package/src/engine-components/webxr/WebXR.ts +585 -585
  991. package/src/engine-components/webxr/WebXRAvatar.ts +66 -66
  992. package/src/engine-components/webxr/WebXRImageTracking.ts +518 -518
  993. package/src/engine-components/webxr/WebXRPlaneTracking.ts +570 -570
  994. package/src/engine-components/webxr/WebXRRig.ts +77 -77
  995. package/src/engine-components/webxr/XRFlag.ts +147 -147
  996. package/src/engine-components/webxr/controllers/XRControllerFollow.ts +118 -118
  997. package/src/engine-components/webxr/controllers/XRControllerModel.ts +374 -374
  998. package/src/engine-components/webxr/controllers/XRControllerMovement.ts +550 -550
  999. package/src/engine-components/webxr/index.ts +2 -2
  1000. package/src/engine-components/webxr/types.ts +3 -3
  1001. package/src/engine-components-experimental/Presentation.ts +12 -12
  1002. package/src/engine-components-experimental/api.ts +4 -4
  1003. package/src/engine-components-experimental/networking/PlayerSync.ts +401 -401
  1004. package/src/engine-schemes/COMPILE_SCHEMES.bat +3 -3
  1005. package/src/engine-schemes/COMPILE_TS.bat +11 -11
  1006. package/src/engine-schemes/README.md +1 -1
  1007. package/src/engine-schemes/api.ts +12 -12
  1008. package/src/engine-schemes/dist/api.js +17 -0
  1009. package/src/engine-schemes/dist/api.js.meta +7 -0
  1010. package/src/engine-schemes/dist/schemes.js +25 -0
  1011. package/src/engine-schemes/dist/schemes.js.meta +7 -0
  1012. package/src/engine-schemes/dist/synced-camera-model.js +74 -0
  1013. package/src/engine-schemes/dist/synced-camera-model.js.meta +7 -0
  1014. package/src/engine-schemes/dist/synced-transform-model.js +73 -0
  1015. package/src/engine-schemes/dist/synced-transform-model.js.meta +7 -0
  1016. package/src/engine-schemes/dist/transform.js +46 -0
  1017. package/src/engine-schemes/dist/transform.js.meta +7 -0
  1018. package/src/engine-schemes/dist/vec2.js +32 -0
  1019. package/src/engine-schemes/dist/vec2.js.meta +7 -0
  1020. package/src/engine-schemes/dist/vec3.js +36 -0
  1021. package/src/engine-schemes/dist/vec3.js.meta +7 -0
  1022. package/src/engine-schemes/dist/vec4.js +40 -0
  1023. package/src/engine-schemes/dist/vec4.js.meta +7 -0
  1024. package/src/engine-schemes/dist/vr-user-state-buffer.js +110 -0
  1025. package/src/engine-schemes/dist/vr-user-state-buffer.js.meta +7 -0
  1026. package/src/engine-schemes/schemes.ts +28 -28
  1027. package/src/engine-schemes/synced-camera-model.ts +92 -92
  1028. package/src/engine-schemes/synced-transform-model.ts +90 -90
  1029. package/src/engine-schemes/syncedCamera.fbs +10 -10
  1030. package/src/engine-schemes/transform.ts +50 -50
  1031. package/src/engine-schemes/transforms.fbs +25 -25
  1032. package/src/engine-schemes/vec.fbs +19 -19
  1033. package/src/engine-schemes/vec2.ts +33 -33
  1034. package/src/engine-schemes/vec3.ts +38 -38
  1035. package/src/engine-schemes/vec4.ts +43 -43
  1036. package/src/engine-schemes/vr-user-state-buffer.ts +145 -145
  1037. package/src/engine-schemes/vrUserStateBuffer.fbs +17 -17
  1038. package/src/include/draco/draco_decoder.js +34 -34
  1039. package/src/include/ktx2/basis_transcoder.js +21 -21
  1040. package/src/include/needle/arial-msdf.json +1471 -1471
  1041. package/src/include/three/DragControls.js +231 -231
  1042. package/src/include/three/EXT_mesh_gpu_instancing_exporter.js +66 -66
  1043. package/src/needle-engine.ts +70 -70
@@ -1,1686 +1,1686 @@
1
- import 'three/examples/jsm/renderers/webgl-legacy/nodes/WebGLNodes.js';
2
-
3
- import type { EffectComposer } from "postprocessing";
4
- import {
5
- BufferGeometry, Camera, Color, DepthTexture, Group,
6
- Material, NearestFilter, NoToneMapping, Object3D, OrthographicCamera, PCFSoftShadowMap,
7
- PerspectiveCamera, RGBAFormat, Scene, SRGBColorSpace,
8
- Texture, WebGLRenderer, type WebGLRendererParameters, WebGLRenderTarget, type WebXRArrayCamera
9
- } from 'three';
10
- /** @ts-ignore (not yet in types?) */
11
- import { BasicNodeLibrary } from "three";
12
- import * as Stats from 'three/examples/jsm/libs/stats.module.js';
13
- import type { EffectComposer as ThreeEffectComposer } from "three/examples/jsm/postprocessing/EffectComposer.js";
14
- import { nodeFrame } from "three/examples/jsm/renderers/webgl-legacy/nodes/WebGLNodeBuilder.js";
15
-
16
- import { isDevEnvironment, LogType, showBalloonError, showBalloonMessage } from './debug/index.js';
17
- import { Addressables } from './engine_addressables.js';
18
- import { AnimationsRegistry } from './engine_animation.js';
19
- import { Application } from './engine_application.js';
20
- import { AssetDatabase } from './engine_assetdatabase.js';
21
- import { VERSION } from './engine_constants.js';
22
- import { ContextEvent, ContextRegistry } from './engine_context_registry.js';
23
- import { WaitForPromise } from './engine_coroutine.js';
24
- import { ObjectUtils } from "./engine_create_objects.js";
25
- import { destroy, foreachComponent } from './engine_gameobject.js';
26
- import { getLoader } from './engine_gltf.js';
27
- import { Input } from './engine_input.js';
28
- import { invokeLifecycleFunctions } from './engine_lifecycle_functions_internal.js';
29
- import { type ILightDataRegistry, LightDataRegistry } from './engine_lightdata.js';
30
- import { LODsManager } from "./engine_lods.js";
31
- import * as looputils from './engine_mainloop_utils.js';
32
- import { NetworkConnection } from './engine_networking.js';
33
- import { Physics } from './engine_physics.js';
34
- import { PlayerViewManager } from './engine_playerview.js';
35
- import { RendererData as SceneLighting } from './engine_scenelighting.js';
36
- import { logHierarchy } from './engine_three_utils.js';
37
- import { Time } from './engine_time.js';
38
- import { patchTonemapping } from './engine_tonemapping.js';
39
- import type { CoroutineData, ICamera, IComponent, IContext, ILight, LoadedModel, Model, Vec2 } from "./engine_types.js";
40
- import { deepClone, delay, DeviceUtilities, getParam } from './engine_utils.js';
41
- import type { INeedleXRSessionEventReceiver, NeedleXRSession } from './engine_xr.js';
42
- import { NeedleMenu } from './webcomponents/needle menu/needle-menu.js';
43
-
44
- const debug = getParam("debugcontext");
45
- const stats = getParam("stats");
46
- const debugActive = getParam("debugactive");
47
- const debugframerate = getParam("debugframerate");
48
- const debugCoroutine = getParam("debugcoroutine");
49
-
50
- // this is where functions that setup unity scenes will be pushed into
51
- // those will be accessed from our custom html element to load them into their context
52
- export const build_scene_functions: { [name: string]: (context: Context) => Promise<void> } = {};
53
-
54
-
55
- export declare class LoadingProgressArgs {
56
- /** the name or URL of the loaded file */
57
- name: string;
58
- /** the loading progress event from the loader */
59
- progress: ProgressEvent;
60
- /** the index of the loaded file */
61
- index: number;
62
- /** the total number of files to load */
63
- count: number;
64
- }
65
- export declare class ContextCreateArgs {
66
- /** list of glTF or GLB files to load */
67
- files: Array<string>;
68
- abortSignal?: AbortSignal;
69
- /** called when loading a provided glTF file started */
70
- onLoadingStart?: (index: number, file: string) => void;
71
- /** called on update for each loaded glTF file */
72
- onLoadingProgress?: (args: LoadingProgressArgs) => void;
73
- /** Called after a gLTF file has finished loading */
74
- onLoadingFinished?: (index: number, file: string, glTF: Model | null) => void;
75
- }
76
-
77
- export class ContextArgs {
78
- name?: string;
79
- /** for debugging only */
80
- alias?: string;
81
- /** the hash is used as a seed when initially loading the scene files */
82
- hash?: string;
83
-
84
- /** when true the context will not check if it's visible in the viewport and always update and render */
85
- runInBackground?: boolean;
86
- /** the DOM element the context belongs to or is inside of (this does not have to be the canvas. use renderer.domElement if you want to access the dom canvas) */
87
- domElement?: HTMLElement | null;
88
- /** externally owned renderer */
89
- renderer?: WebGLRenderer;
90
- /** externally owned camera */
91
- camera?: Camera;
92
- /** externally owned scene */
93
- scene?: Scene;
94
- }
95
-
96
- export enum FrameEvent {
97
- Start = -1,
98
- EarlyUpdate = 0,
99
- Update = 1,
100
- LateUpdate = 2,
101
- OnBeforeRender = 3,
102
- OnAfterRender = 4,
103
- PrePhysicsStep = 9,
104
- PostPhysicsStep = 10,
105
- Undefined = -1,
106
- }
107
-
108
- /** threejs callback event signature */
109
- export declare type OnRenderCallback = (renderer: WebGLRenderer, scene: Scene, camera: Camera, geometry: BufferGeometry, material: Material, group: Group) => void
110
-
111
-
112
- export function registerComponent(script: IComponent, context?: Context) {
113
- if (!script) return;
114
- if (!script.isComponent) {
115
- if (isDevEnvironment() || debug)
116
- console.error("Registered script is not a Needle Engine component. \nThe script will be ignored. Please make sure your component extends \"Behaviour\" imported from \"@needle-tools/engine\"\n", script);
117
- return;
118
- }
119
- if (!context) {
120
- context = Context.Current;
121
- if (debug) console.warn("> Registering component without context");
122
- }
123
- const new_scripts = context?.new_scripts;
124
- if (!new_scripts.includes(script)) {
125
- new_scripts.push(script);
126
- }
127
- }
128
-
129
- /**
130
- * The context is the main object that holds all the data and state of the Needle Engine.
131
- * It can be used to access the scene, renderer, camera, input, physics, networking, and more.
132
- * @example
133
- * ```typescript
134
- * import { Behaviour } from "@needle-tools/engine";
135
- * import { Mesh, BoxGeometry, MeshBasicMaterial } from "three";
136
- * export class MyScript extends Behaviour {
137
- * start() {
138
- * console.log("Hello from MyScript");
139
- * this.context.scene.add(new Mesh(new BoxGeometry(), new MeshBasicMaterial()));
140
- * }
141
- * }
142
- * ```
143
- */
144
- export class Context implements IContext {
145
-
146
- private static _defaultTargetFramerate: { value?: number, toString?() } = { value: 90, toString() { return this.value; } }
147
- /** When a new context is created this is the framerate that will be used by default */
148
- static get DefaultTargetFrameRate(): number | undefined {
149
- return Context._defaultTargetFramerate.value;
150
- }
151
- /** When a new context is created this is the framerate that will be used by default */
152
- static set DefaultTargetFrameRate(val: number | undefined) {
153
- Context._defaultTargetFramerate.value = val;
154
- }
155
-
156
- private static _defaultWebglRendererParameters: WebGLRendererParameters = {
157
- antialias: true,
158
- alpha: false,
159
- // Note: this is due to a bug on OSX devices. See NE-5370
160
- powerPreference: (DeviceUtilities.isiOS() || DeviceUtilities.isMacOS()) ? "default" : "high-performance",
161
- stencil: true,
162
- // logarithmicDepthBuffer: true,
163
- // reverseDepthBuffer: true, // https://github.com/mrdoob/three.js/issues/29770
164
- };
165
- /** The default parameters that will be used when creating a new WebGLRenderer.
166
- * Modify in global context to change the default parameters for all new contexts.
167
- * @example
168
- * ```typescript
169
- * import { Context } from "@needle-tools/engine";
170
- * Context.DefaultWebGLRendererParameters.antialias = false;
171
- * ```
172
- */
173
- static get DefaultWebGLRendererParameters(): WebGLRendererParameters {
174
- return Context._defaultWebglRendererParameters;
175
- }
176
-
177
- /** The needle engine version */
178
- get version() {
179
- return VERSION;
180
- }
181
-
182
- /** The currently active context. Only set during the update loops */
183
- static get Current(): Context {
184
- return ContextRegistry.Current as Context;
185
- }
186
-
187
- /** @internal this property should not be set by user code */
188
- static set Current(context: Context) {
189
- ContextRegistry.Current = context;
190
- }
191
-
192
- static get All(): Context[] {
193
- return ContextRegistry.All as Context[];
194
- }
195
-
196
- /** The name of the context */
197
- name: string;
198
- /** An alias for the context */
199
- alias: string | undefined | null;
200
- /** When the renderer or camera are managed by an external process (e.g. when running in r3f context).
201
- * When this is false you are responsible to call update(timestamp, xframe.
202
- * It is also currently assumed that rendering is handled performed by an external process
203
- * */
204
- isManagedExternally: boolean = false;
205
- /** set to true to pause the update loop. You can receive an event for it in your components.
206
- * Note that script updates will not be called when paused */
207
- isPaused: boolean = false;
208
- /** When enabled the application will run while not visible on the page */
209
- runInBackground: boolean = false;
210
- /**
211
- * Set to the target framerate you want your application to run in (you can use ?stats to check the fps)
212
- * Set to undefined if you want to run at the maximum framerate
213
- */
214
- targetFrameRate?: number | { value?: number };
215
-
216
- /** Use a higher number for more accurate physics simulation.
217
- * When undefined physics steps will be 1 for mobile devices and 5 for desktop devices
218
- * Set to 0 to disable physics updates
219
- * TODO: changing physics steps is currently not supported because then forces that we get from the character controller and rigidbody et al are not correct anymore - this needs to be properly tested before making this configureable
220
- */
221
- private physicsSteps?: number = 1;
222
-
223
- /** used to append to loaded assets */
224
- hash?: string;
225
-
226
- /** The `<needle-engine>` web component */
227
- domElement: HTMLElement;
228
-
229
- appendHTMLElement(element: HTMLElement) {
230
- if (this.domElement.shadowRoot)
231
- return this.domElement.shadowRoot.appendChild(element);
232
- else return this.domElement.appendChild(element);
233
- }
234
-
235
- get resolutionScaleFactor() { return this._resolutionScaleFactor; }
236
- /** use to scale the resolution up or down of the renderer. default is 1 */
237
- set resolutionScaleFactor(val: number) {
238
- if (val === this._resolutionScaleFactor) return;
239
- if (typeof val !== "number") return;
240
- if (val <= 0) {
241
- console.error("Invalid resolution scale factor", val);
242
- return;
243
- }
244
- this._resolutionScaleFactor = val;
245
- this.updateSize();
246
- }
247
- private _resolutionScaleFactor: number = 1;
248
-
249
- // domElement.clientLeft etc doesnt return absolute position
250
- private _boundingClientRectFrame: number = -1;
251
- private _boundingClientRect: DOMRect | null = null;
252
- private _domX; private _domY;
253
- /** update bounding rects + domX, domY */
254
- private calculateBoundingClientRect() {
255
- // workaround for mozilla webXR viewer
256
- if (this.xr) {
257
- this._domX = 0;
258
- this._domY = 0;
259
- return;
260
- }
261
- // TODO: cache this
262
- if (this._boundingClientRectFrame === this.time.frame) return;
263
- this._boundingClientRectFrame = this.time.frame;
264
- this._boundingClientRect = this.domElement.getBoundingClientRect();
265
- this._domX = this._boundingClientRect.x;
266
- this._domY = this._boundingClientRect.y;
267
- }
268
-
269
- /** The width of the `<needle-engine>` element on the website */
270
- get domWidth(): number {
271
- // for mozilla XR
272
- if (this.isInAR) return window.innerWidth;
273
- return this.domElement.clientWidth;
274
- }
275
- /** The height of the `<needle-engine>` element on the website */
276
- get domHeight(): number {
277
- // for mozilla XR
278
- if (this.isInAR) return window.innerHeight;
279
- return this.domElement.clientHeight;
280
- }
281
- /** the X position of the Needle Engine element on the website */
282
- get domX(): number {
283
- this.calculateBoundingClientRect();
284
- return this._domX;
285
- }
286
- /** the Y position of the Needlee Engine element on the website */
287
- get domY(): number {
288
- this.calculateBoundingClientRect();
289
- return this._domY;
290
- }
291
- get isInXR() { return this.renderer?.xr?.isPresenting || false; }
292
- /** shorthand for `NeedleXRSession.active`
293
- * Automatically set by NeedleXRSession when a XR session is active
294
- * @returns the active XR session or null if no session is active
295
- * */
296
- xr: NeedleXRSession | null = null;
297
- get xrSessionMode() { return this.xr?.mode; }
298
- get isInVR() { return this.xrSessionMode === "immersive-vr"; }
299
- get isInAR() { return this.xrSessionMode === "immersive-ar"; }
300
- /** If a XR session is active and in pass through mode (immersive-ar on e.g. Quest) */
301
- get isInPassThrough() { return this.xr ? this.xr.isPassThrough : false; }
302
- /** access the raw `XRSession` object (shorthand for `context.renderer.xr.getSession()`). For more control use `NeedleXRSession.active` */
303
- get xrSession() { return this.renderer?.xr?.getSession(); }
304
- /** @returns the latest XRFrame (if a XRSession is currently active)
305
- * @link https://developer.mozilla.org/en-US/docs/Web/API/XRFrame
306
- */
307
- get xrFrame() { return this._xrFrame }
308
- /** @returns the current WebXR camera while the WebXRManager is active (shorthand for `context.renderer.xr.getCamera()`) */
309
- get xrCamera(): WebXRArrayCamera | undefined { return this.renderer.xr.isPresenting ? this.renderer?.xr?.getCamera() : undefined }
310
- private _xrFrame: XRFrame | null = null;
311
- get arOverlayElement(): HTMLElement {
312
- const el = this.domElement as any;
313
- if (typeof el.getAROverlayContainer === "function")
314
- return el.getAROverlayContainer();
315
- return this.domElement;
316
- }
317
- /** Current event of the update cycle */
318
- get currentFrameEvent(): FrameEvent {
319
- return this._currentFrameEvent;
320
- }
321
- private _currentFrameEvent: FrameEvent = FrameEvent.Undefined;
322
-
323
- scene: Scene;
324
- renderer!: WebGLRenderer;
325
- composer: EffectComposer | ThreeEffectComposer | null = null;
326
-
327
- // all scripts
328
- readonly scripts: IComponent[] = [];
329
- readonly scripts_pausedChanged: IComponent[] = [];
330
- // scripts with update event
331
- readonly scripts_earlyUpdate: IComponent[] = [];
332
- readonly scripts_update: IComponent[] = [];
333
- readonly scripts_lateUpdate: IComponent[] = [];
334
- readonly scripts_onBeforeRender: IComponent[] = [];
335
- readonly scripts_onAfterRender: IComponent[] = [];
336
- readonly scripts_WithCorroutines: IComponent[] = [];
337
- readonly scripts_immersive_vr: INeedleXRSessionEventReceiver[] = [];
338
- readonly scripts_immersive_ar: INeedleXRSessionEventReceiver[] = [];
339
- readonly coroutines: { [FrameEvent: number]: Array<CoroutineData> } = {}
340
-
341
- /** callbacks called once after the context has been created */
342
- readonly post_setup_callbacks: Function[] = [];
343
- /** called every frame at the beginning of the frame (after component start events and before earlyUpdate) */
344
- readonly pre_update_callbacks: Function[] = [];
345
- /** called every frame before rendering (after all component events) */
346
- readonly pre_render_callbacks: Array<(frame: XRFrame | null) => void> = [];
347
- /** called every frame after rendering (after all component events) */
348
- readonly post_render_callbacks: Function[] = [];
349
-
350
- /** called every frame befroe update (this list is emptied every frame) */
351
- readonly pre_update_oneshot_callbacks: Function[] = [];
352
-
353
- readonly new_scripts: IComponent[] = [];
354
- readonly new_script_start: IComponent[] = [];
355
- readonly new_scripts_pre_setup_callbacks: Function[] = [];
356
- readonly new_scripts_post_setup_callbacks: Function[] = [];
357
- readonly new_scripts_xr: INeedleXRSessionEventReceiver[] = [];
358
-
359
- /** The main camera component of the scene - this camera is used for rendering */
360
- mainCameraComponent: ICamera | undefined = undefined;
361
-
362
- /** The main camera of the scene - this camera is used for rendering */
363
- get mainCamera(): Camera {
364
- if (this._mainCamera) {
365
- return this._mainCamera;
366
- }
367
- if (this.mainCameraComponent) {
368
- const cam = this.mainCameraComponent as ICamera;
369
- if (!cam.threeCamera)
370
- cam.buildCamera();
371
- return cam.threeCamera;
372
- }
373
- if (!this._fallbackCamera) {
374
- this._fallbackCamera = new PerspectiveCamera(75, this.domWidth / this.domHeight, 0.1, 1000);
375
- }
376
- return this._fallbackCamera;
377
- }
378
- /** Set the main camera of the scene. If set to null the camera of the {@link mainCameraComponent} will be used - this camera is used for rendering */
379
- set mainCamera(cam: Camera | null) {
380
- this._mainCamera = cam;
381
- }
382
- private _mainCamera: Camera | null = null;
383
- private _fallbackCamera: PerspectiveCamera | null = null;
384
-
385
- application: Application;
386
- /** access animation mixer used by components in the scene */
387
- animations: AnimationsRegistry;
388
- /** access timings (current frame number, deltaTime, timeScale, ...) */
389
- time: Time;
390
- input: Input;
391
- /** access physics related methods (e.g. raycasting). To access the phyiscs engine use `context.physics.engine` */
392
- physics: Physics;
393
- /** access networking methods (use it to send or listen to messages or join a networking backend) */
394
- connection: NetworkConnection;
395
- /**
396
- * @deprecated AssetDataBase is deprecated
397
- */
398
- assets: AssetDatabase;
399
- mainLight: ILight | null = null;
400
- /** @deprecated Use sceneLighting */
401
- get rendererData() { return this.sceneLighting }
402
- sceneLighting: SceneLighting;
403
- addressables: Addressables;
404
- lightmaps: ILightDataRegistry;
405
- players: PlayerViewManager;
406
- readonly lodsManager: LODsManager;
407
- readonly menu: NeedleMenu;
408
-
409
- get isCreated() { return this._isCreated; }
410
-
411
- private _needsUpdateSize: boolean = false;
412
- private _isCreated: boolean = false;
413
- private _isCreating: boolean = false;
414
- private _isVisible: boolean = false;
415
-
416
- private _stats = stats ? new Stats.default() : null;
417
-
418
- constructor(args?: ContextArgs) {
419
- this.name = args?.name || "";
420
- this.alias = args?.alias;
421
- this.domElement = args?.domElement || document.body;
422
- this.hash = args?.hash;
423
-
424
- if (args?.renderer) {
425
- this.renderer = args.renderer;
426
- this.isManagedExternally = true;
427
- }
428
- if (args?.runInBackground !== undefined) this.runInBackground = args.runInBackground;
429
- if (args?.scene) this.scene = args.scene;
430
- else this.scene = new Scene();
431
- if (args?.camera) this._mainCamera = args.camera;
432
-
433
- this.application = new Application(this);
434
- this.time = new Time();
435
- this.input = new Input(this);
436
- this.physics = new Physics(this);
437
- this.connection = new NetworkConnection(this);
438
- // eslint-disable-next-line deprecation/deprecation
439
- this.assets = new AssetDatabase();
440
- this.sceneLighting = new SceneLighting(this);
441
- this.addressables = new Addressables(this);
442
- this.lightmaps = new LightDataRegistry(this);
443
- this.players = new PlayerViewManager(this);
444
- this.menu = new NeedleMenu(this);
445
- this.lodsManager = new LODsManager(this);
446
- this.animations = new AnimationsRegistry(this);
447
-
448
-
449
- const resizeCallback = () => this._needsUpdateSize = true;
450
- window.addEventListener('resize', resizeCallback);
451
- this._disposeCallbacks.push(() => window.removeEventListener('resize', resizeCallback));
452
-
453
- const resizeObserver = new ResizeObserver(_ => this._needsUpdateSize = true);
454
- resizeObserver.observe(this.domElement);
455
- this._disposeCallbacks.push(() => resizeObserver.disconnect());
456
-
457
- this._intersectionObserver = new IntersectionObserver(entries => {
458
- this._isVisible = entries[0].isIntersecting;
459
- });
460
- this._disposeCallbacks.push(() => this._intersectionObserver?.disconnect());
461
-
462
- ContextRegistry.register(this);
463
- }
464
-
465
- /** calling this function will dispose the current renderer and create a new one */
466
- createNewRenderer(params?: WebGLRendererParameters) {
467
- this.renderer?.dispose();
468
-
469
- params = { ...Context.DefaultWebGLRendererParameters, ...params };
470
- if (!params.canvas) {
471
- // get canvas already configured in the Needle Engine Web Component
472
- const canvas = this.domElement?.shadowRoot?.querySelector("canvas");
473
- if (canvas) {
474
- params.canvas = canvas;
475
- if (debug) {
476
- console.log("Using canvas from shadow root", canvas);
477
- }
478
- }
479
- }
480
- if (debug) console.log("Using Renderer Parameters:", params, this.domElement)
481
-
482
- this.renderer = new WebGLRenderer(params);
483
-
484
- this.renderer.debug.checkShaderErrors = isDevEnvironment() || getParam("checkshadererrors") === true;
485
-
486
- // some tonemapping other than "NONE" is required for adjusting exposure with EXR environments
487
- this.renderer.toneMappingExposure = 1; // range [0...inf] instead of the usual -15..15
488
- this.renderer.toneMapping = NoToneMapping; // could also set to LinearToneMapping, ACESFilmicToneMapping
489
-
490
- this.renderer.setClearColor(new Color('lightgrey'), 0);
491
- // // @ts-ignore
492
- // this.renderer.alpha = false;
493
- this.renderer.shadowMap.enabled = true;
494
- this.renderer.shadowMap.type = PCFSoftShadowMap;
495
- this.renderer.setSize(this.domWidth, this.domHeight);
496
- this.renderer.outputColorSpace = SRGBColorSpace;
497
-
498
- // Injecting the core nodes library here, like WebGPURenderer backends do
499
- //@ts-ignore
500
- this.renderer.nodes = {
501
- library: new BasicNodeLibrary(),
502
- modelViewMatrix: null,
503
- modelNormalViewMatrix: null,
504
- };
505
- // this.renderer.toneMapping = AgXToneMapping;
506
- this.lodsManager.setRenderer(this.renderer);
507
-
508
- this.input.bindEvents();
509
- }
510
-
511
-
512
- private _intersectionObserver: IntersectionObserver | null = null;
513
- private internalOnUpdateVisible() {
514
- this._intersectionObserver?.disconnect();
515
- this._intersectionObserver?.observe(this.domElement);
516
- }
517
-
518
- private _disposeCallbacks: Function[] = [];
519
-
520
-
521
- /** will request a renderer size update the next render call (will call updateSize the next update) */
522
- requestSizeUpdate() { this._needsUpdateSize = true; }
523
-
524
- /** Clamps the renderer max resolution. If undefined the max resolution is not clamped. Default is undefined */
525
- maxRenderResolution?: Vec2;
526
-
527
- /** Control the renderer devicePixelRatio.
528
- * **Options**
529
- * - `auto` - Needle Engine automatically sets the pixel ratio to the current window.devicePixelRatio.
530
- * - `manual` - Needle Engine will not change the renderer pixel ratio. You can set it manually.
531
- * - `number` - Needle Engine will set the pixel ratio to the given number. The change will be applied to the renderer and the composer (if used) at the end of the current frame.
532
- */
533
- get devicePixelRatio() { return this._devicePixelRatio; }
534
- set devicePixelRatio(val: "auto" | "manual" | number) {
535
- if (val !== this._devicePixelRatio) {
536
- this._devicePixelRatio = val;
537
- this._needsUpdateSize = true;
538
- }
539
- }
540
- private _devicePixelRatio: "auto" | "manual" | number = "auto";
541
-
542
- /** update the renderer and canvas size */
543
- updateSize(force: boolean = false) {
544
- if (force || (!this.isManagedExternally && this.renderer.xr?.isPresenting === false)) {
545
- this._needsUpdateSize = false;
546
- const scaleFactor = this.resolutionScaleFactor;
547
- let width = this.domWidth * scaleFactor;
548
- let height = this.domHeight * scaleFactor;
549
- if (this.maxRenderResolution) {
550
- this.maxRenderResolution.x = Math.max(1, this.maxRenderResolution.x);
551
- width = Math.min(this.maxRenderResolution.x, width);
552
- this.maxRenderResolution.y = Math.max(1, this.maxRenderResolution.y);
553
- height = Math.min(this.maxRenderResolution.y, height);
554
- }
555
- const camera = this.mainCamera as PerspectiveCamera;
556
- this.updateAspect(camera);
557
- this.renderer.setSize(width, height, true);
558
- // avoid setting pixel values here since this can cause pingpong updates
559
- // e.g. when system scale is set to 125%
560
- // https://github.com/needle-tools/needle-engine-support/issues/69
561
- this.renderer.domElement.style.width = "100%";
562
- this.renderer.domElement.style.height = "100%";
563
-
564
- const devicePixelRatio = typeof this.devicePixelRatio === "number"
565
- ? this.devicePixelRatio
566
- : this.devicePixelRatio === "auto"
567
- ? window.devicePixelRatio
568
- : undefined;
569
- if (devicePixelRatio !== undefined) {
570
- this.renderer.setPixelRatio(devicePixelRatio);
571
- }
572
-
573
- if (this.composer) {
574
- this.composer.setSize?.call(this.composer, width, height);
575
- if (devicePixelRatio !== undefined && "setPixelRatio" in this.composer && typeof this.composer.setPixelRatio === "function")
576
- this.composer.setPixelRatio?.call(this.composer, window.devicePixelRatio);
577
- }
578
- }
579
- }
580
-
581
- updateAspect(camera: PerspectiveCamera | OrthographicCamera, width?: number, height?: number) {
582
- if (!camera) return;
583
- if (width === undefined)
584
- width = this.domWidth;
585
- if (height === undefined)
586
- height = this.domHeight;
587
- const aspectRatio = width / height;
588
- if ((camera as PerspectiveCamera).isPerspectiveCamera) {
589
- const cam = camera as PerspectiveCamera;
590
- const pa = cam.aspect;
591
- cam.aspect = aspectRatio;
592
- if (pa !== cam.aspect)
593
- camera.updateProjectionMatrix();
594
- }
595
- else if ((camera as OrthographicCamera).isOrthographicCamera) {
596
- const cam = camera as OrthographicCamera;
597
- // Maintain the camera's current vertical size (top - bottom)
598
- const verticalSize = cam.top - cam.bottom;
599
- // Calculate new horizontal size based on aspect ratio
600
- const horizontalSize = verticalSize * aspectRatio;
601
- // Update camera bounds while maintaining center position
602
- const halfWidth = horizontalSize / 2;
603
- const halfHeight = verticalSize / 2;
604
- if (cam.left != -halfWidth || cam.top != halfHeight) {
605
- cam.left = -halfWidth;
606
- cam.right = halfWidth;
607
- cam.top = halfHeight;
608
- cam.bottom = -halfHeight;
609
- camera.updateProjectionMatrix();
610
- }
611
- }
612
- }
613
-
614
- /** This will recreate the whole needle engine context and dispose the whole scene content
615
- * All content will be reloaded (loading times might be faster due to browser caches)
616
- * All scripts will be recreated */
617
- recreate() {
618
- this.clear();
619
- this.create(this._originalCreationArgs);
620
- }
621
-
622
- private _originalCreationArgs?: ContextCreateArgs;
623
-
624
- /** @deprecated use create. This method will be removed in a future version */
625
- async onCreate(opts?: ContextCreateArgs) {
626
- return this.create(opts);
627
- }
628
- async create(opts?: ContextCreateArgs) {
629
- try {
630
- this._isCreating = true;
631
- if (opts !== this._originalCreationArgs)
632
- this._originalCreationArgs = deepClone(opts);
633
- window.addEventListener("unhandledrejection", this.onUnhandledRejection)
634
- const res = await this.internalOnCreate(opts);
635
- this._isCreated = res;
636
- return res;
637
- }
638
- finally {
639
- window.removeEventListener("unhandledrejection", this.onUnhandledRejection)
640
- this._isCreating = false;
641
- }
642
- }
643
-
644
- private onUnhandledRejection = (event: PromiseRejectionEvent) => {
645
- this.onError(event.reason);
646
- };
647
-
648
- /** Dispatches an error */
649
- private onError(error: string) {
650
- this.domElement.dispatchEvent(new CustomEvent("error", { detail: error }));
651
- }
652
-
653
- /** Will destroy all scenes and objects in the scene
654
- */
655
- clear() {
656
- ContextRegistry.dispatchCallback(ContextEvent.ContextClearing, this);
657
- invokeLifecycleFunctions(this, ContextEvent.ContextClearing);
658
- // NOTE: this does dispose the environment/background image too
659
- // which is probably not desired if it is set via the skybox-image attribute
660
- destroy(this.scene, true, true);
661
- this.scene = new Scene();
662
- this.addressables?.dispose();
663
- this.lightmaps?.clear();
664
- this.physics?.engine?.clearCaches();
665
- this.lodsManager.disable();
666
-
667
- if (!this.isManagedExternally) {
668
- if (this.renderer) {
669
- this.renderer.renderLists.dispose();
670
- this.renderer.state.reset();
671
- this.renderer.resetState();
672
- }
673
- }
674
- // We do not want to clear the renderer here because when switching src we want to keep the last rendered frame in case the loading screen is not visible
675
- // if a user wants to see the background they can still call setClearAlpha(0) and clear manually
676
- ContextRegistry.dispatchCallback(ContextEvent.ContextCleared, this);
677
- }
678
-
679
- dispose() {
680
- this.internalOnDestroy();
681
- }
682
-
683
- /**@deprecated use dispose() */
684
- onDestroy() { this.internalOnDestroy(); }
685
- private internalOnDestroy() {
686
- Context.Current = this;
687
- ContextRegistry.dispatchCallback(ContextEvent.ContextDestroying, this);
688
- invokeLifecycleFunctions(this, ContextEvent.ContextDestroying);
689
- this.clear();
690
- this.renderer?.setAnimationLoop(null);
691
- if (this.renderer) {
692
- this.renderer.setClearAlpha(0);
693
- this.renderer.clear();
694
- if (!this.isManagedExternally) {
695
- if (debug) console.log("Disposing renderer");
696
- this.renderer.dispose();
697
- }
698
- }
699
- this.scene = null!;
700
- this.renderer = null!;
701
- this.input.dispose();
702
- this.menu.onDestroy();
703
- this.animations.onDestroy();
704
- for (const cb of this._disposeCallbacks) {
705
- try {
706
- cb();
707
- }
708
- catch (e) {
709
- console.error("Error in on dispose callback:", e, cb);
710
- }
711
- }
712
- if (this.domElement?.parentElement) {
713
- this.domElement.parentElement.removeChild(this.domElement);
714
- }
715
- this._isCreated = false;
716
- ContextRegistry.dispatchCallback(ContextEvent.ContextDestroyed, this);
717
- invokeLifecycleFunctions(this, ContextEvent.ContextDestroyed);
718
- ContextRegistry.unregister(this);
719
- if (Context.Current === this) {
720
- //@ts-ignore
721
- Context.Current = null;
722
- }
723
- }
724
-
725
- registerCoroutineUpdate(script: IComponent, coroutine: Generator, evt: FrameEvent): Generator {
726
- if (typeof coroutine?.next !== "function") {
727
- console.error("Registered invalid coroutine function from " + script.name + "\nCoroutine functions must be generators: \"*myCoroutine() {...}\"\nStart a coroutine from a component by calling \"this.startCoroutine(myCoroutine())\"")
728
- return coroutine;
729
- }
730
- if (!this.coroutines[evt]) this.coroutines[evt] = [];
731
- this.coroutines[evt].push({ comp: script, main: coroutine });
732
- return coroutine;
733
- }
734
-
735
- unregisterCoroutineUpdate(coroutine: Generator, evt: FrameEvent): void {
736
- if (!this.coroutines[evt]) return;
737
- const idx = this.coroutines[evt].findIndex(c => c.main === coroutine);
738
- if (idx >= 0) this.coroutines[evt].splice(idx, 1);
739
- }
740
-
741
- stopAllCoroutinesFrom(script: IComponent) {
742
- for (const evt in this.coroutines) {
743
- const rout: CoroutineData[] = this.coroutines[evt];
744
- for (let i = rout.length - 1; i >= 0; i--) {
745
- const r = rout[i];
746
- if (r.comp === script) {
747
- rout.splice(i, 1);
748
- }
749
- }
750
- }
751
- }
752
-
753
- private _cameraStack: ICamera[] = [];
754
-
755
- setCurrentCamera(cam: ICamera) {
756
- if (!cam) return;
757
- if (!cam.threeCamera) cam.buildCamera(); // < to build camera
758
- if (!cam.threeCamera) {
759
- console.warn("Camera component is missing camera", cam)
760
- return;
761
- }
762
- const index = this._cameraStack.indexOf(cam);
763
- if (index >= 0) this._cameraStack.splice(index, 1);
764
- this._cameraStack.push(cam);
765
- this.mainCameraComponent = cam;
766
- const camera = cam.threeCamera as PerspectiveCamera;
767
- if (camera.isPerspectiveCamera)
768
- this.updateAspect(camera);
769
- (this.mainCameraComponent as ICamera)?.applyClearFlagsIfIsActiveCamera();
770
- }
771
-
772
- removeCamera(cam?: ICamera | null) {
773
- if (!cam) return;
774
- const index = this._cameraStack.indexOf(cam);
775
- if (index >= 0) this._cameraStack.splice(index, 1);
776
-
777
- if (this.mainCameraComponent === cam) {
778
- this.mainCameraComponent = undefined;
779
-
780
- if (this._cameraStack.length > 0) {
781
- const last = this._cameraStack[this._cameraStack.length - 1];
782
- this.setCurrentCamera(last);
783
- }
784
- }
785
- }
786
-
787
-
788
-
789
- private _onBeforeRenderListeners = new Map<string, OnRenderCallback[]>();
790
- private _onAfterRenderListeners = new Map<string, OnRenderCallback[]>();
791
-
792
- /** use this to subscribe to onBeforeRender events on threejs objects */
793
- addBeforeRenderListener(target: Object3D, callback: OnRenderCallback) {
794
- if (!this._onBeforeRenderListeners.has(target.uuid)) {
795
- this._onBeforeRenderListeners.set(target.uuid, []);
796
- target.onBeforeRender = this._createRenderCallbackWrapper(target, this._onBeforeRenderListeners);
797
- }
798
- this._onBeforeRenderListeners.get(target.uuid)!.push(callback);
799
- }
800
- removeBeforeRenderListener(target: Object3D, callback: OnRenderCallback) {
801
- if (this._onBeforeRenderListeners.has(target.uuid)) {
802
- const arr = this._onBeforeRenderListeners.get(target.uuid)!;
803
- const idx = arr.indexOf(callback);
804
- if (idx >= 0) arr.splice(idx, 1);
805
- }
806
- }
807
-
808
- /** use this to subscribe to onAfterRender events on threejs objects */
809
- addAfterRenderListener(target: Object3D, callback: OnRenderCallback) {
810
- if (!this._onAfterRenderListeners.has(target.uuid)) {
811
- this._onAfterRenderListeners.set(target.uuid, []);
812
- target.onAfterRender = this._createRenderCallbackWrapper(target, this._onAfterRenderListeners);
813
- }
814
- this._onAfterRenderListeners.get(target.uuid)?.push(callback);
815
- }
816
- removeAfterRenderListener(target: Object3D, callback: OnRenderCallback) {
817
- if (this._onAfterRenderListeners.has(target.uuid)) {
818
- const arr = this._onAfterRenderListeners.get(target.uuid)!;
819
- const idx = arr.indexOf(callback);
820
- if (idx >= 0) arr.splice(idx, 1);
821
- }
822
- }
823
-
824
-
825
- private _createRenderCallbackWrapper(target: Object3D, array: Map<string, OnRenderCallback[]>): OnRenderCallback {
826
- return (renderer, scene, camera, geometry, material, group) => {
827
- const arr = array.get(target.uuid);
828
- if (!arr) return;
829
- for (let i = 0; i < arr.length; i++) {
830
- const fn = arr[i];
831
- fn(renderer, scene, camera, geometry, material, group);
832
- }
833
- }
834
- }
835
-
836
-
837
-
838
- private _requireDepthTexture: boolean = false;
839
- private _requireColorTexture: boolean = false;
840
- private _renderTarget?: WebGLRenderTarget;
841
- private _isRendering: boolean = false;
842
-
843
- get isRendering() { return this._isRendering; }
844
-
845
- setRequireDepth(val: boolean) {
846
- this._requireDepthTexture = val;
847
- }
848
-
849
- setRequireColor(val: boolean) {
850
- this._requireColorTexture = val;
851
- }
852
-
853
- get depthTexture(): DepthTexture | null {
854
- return this._renderTarget?.depthTexture || null;
855
- }
856
-
857
- get opaqueColorTexture(): Texture | null {
858
- return this._renderTarget?.texture || null;
859
- }
860
-
861
- /** returns true if the dom element is visible on screen */
862
- get isVisibleToUser() {
863
- if (this.isInXR) return true;
864
- if (!this._isVisible) return false;
865
- const style = getComputedStyle(this.domElement);
866
- return style.visibility !== "hidden" && style.display !== "none" && style.opacity !== "0";
867
- }
868
-
869
-
870
- private _createId: number = 0;
871
- private async internalOnCreate(opts?: ContextCreateArgs): Promise<boolean> {
872
- const createId = ++this._createId;
873
-
874
- if (debug) console.log("Creating context", this.name, opts);
875
-
876
- // wait for async imported dependencies to be loaded
877
- // see https://linear.app/needle/issue/NE-4445
878
- const dependenciesReady = globalThis["needle:dependencies:ready"];
879
- if (dependenciesReady instanceof Promise) {
880
- if (debug) console.log("Waiting for dependencies to be ready");
881
- await dependenciesReady
882
- .catch(err => {
883
- if (debug || isDevEnvironment()) {
884
- showBalloonError("Needle Engine dependencies failed to load. Please check the console for more details");
885
- const printedError = false;
886
- if (err instanceof ReferenceError) {
887
- let offendingComponentName = "YourComponentName";
888
- const offendingComponentStartIndex = err.message.indexOf("'");
889
- if (offendingComponentStartIndex > 0) {
890
- const offendingComponentEndIndex = err.message.indexOf("'", offendingComponentStartIndex + 1);
891
- if (offendingComponentEndIndex > 0) {
892
- const name = err.message.substring(offendingComponentStartIndex + 1, offendingComponentEndIndex);
893
- if (name.length > 3) offendingComponentName = name;
894
- }
895
- }
896
- console.error(`Needle Engine dependencies failed to load:\n\n# Make sure you don't have circular imports in your scripts!\n\nPossible solutions: \n→ Replace @serializable(${offendingComponentName}) in your script with @serializable(Behaviour)\n→ If you only need type information try importing the type only, e.g: import { type ${offendingComponentName} }\n\n---`, err)
897
- return;
898
- }
899
- if (!printedError) {
900
- console.error("Needle Engine dependencies failed to load", err);
901
- }
902
- }
903
- })
904
- .then(() => {
905
- if (debug) console.log("Needle Engine dependencies are ready");
906
- });
907
- }
908
-
909
- this.clear();
910
- // stop the animation loop if its running during creation
911
- // since we do not want to start enabling scripts etc before they are deserialized
912
- if (this.isManagedExternally === false) {
913
- this.createNewRenderer();
914
- this.renderer?.setAnimationLoop(null);
915
- }
916
-
917
- await delay(1);
918
-
919
- Context.Current = this;
920
- await ContextRegistry.dispatchCallback(ContextEvent.ContextCreationStart, this);
921
-
922
- // load and create scene
923
- let prepare_succeeded = true;
924
- let loadedFiles!: Array<LoadedModel | null>;
925
- try {
926
- Context.Current = this;
927
- if (opts) {
928
- loadedFiles = await this.internalLoadInitialContent(createId, opts);
929
- }
930
- else loadedFiles = [];
931
- }
932
- catch (err) {
933
- console.error(err);
934
- prepare_succeeded = false;
935
- }
936
- if (!prepare_succeeded) {
937
- this.onError("Failed to load initial content");
938
- return false;
939
- }
940
- if (createId !== this._createId || opts?.abortSignal?.aborted) {
941
- return false;
942
- }
943
-
944
- this.internalOnUpdateVisible();
945
-
946
- if (!this.renderer) {
947
- if (debug) console.warn("Context has no renderer (perhaps it was disconnected?", this.domElement.isConnected);
948
- return false;
949
- }
950
-
951
- if (!this.isManagedExternally && !this.domElement.shadowRoot) {
952
- this.domElement.prepend(this.renderer.domElement);
953
- }
954
-
955
- Context.Current = this;
956
-
957
- // TODO: we could configure if we need physics
958
- // await this.physics.engine?.initialize();
959
-
960
- // Setup
961
- Context.Current = this;
962
- for (let i = 0; i < this.new_scripts.length; i++) {
963
- const script = this.new_scripts[i];
964
- if (script.gameObject !== undefined && script.gameObject !== null) {
965
- if (script.gameObject.userData === undefined) script.gameObject.userData = {};
966
- if (script.gameObject.userData.components === undefined) script.gameObject.userData.components = [];
967
- const arr = script.gameObject.userData.components;
968
- if (!arr.includes(script)) arr.push(script);
969
- }
970
- // if (script.gameObject && !this.raycastTargets.includes(script.gameObject)) {
971
- // this.raycastTargets.push(script.gameObject);
972
- // }
973
- }
974
-
975
- // const context = new SerializationContext(this.scene);
976
- // for (let i = 0; i < this.new_scripts.length; i++) {
977
- // const script = this.new_scripts[i];
978
- // const ser = script as unknown as ISerializable;
979
- // if (ser.$serializedTypes === undefined) continue;
980
- // context.context = this;
981
- // context.object = script.gameObject;
982
- // deserializeObject(ser, script, context);
983
- // }
984
-
985
- // resolve post setup callbacks (things that rely on threejs objects having references to components)
986
- if (this.post_setup_callbacks) {
987
- for (let i = 0; i < this.post_setup_callbacks.length; i++) {
988
- Context.Current = this;
989
- await this.post_setup_callbacks[i](this);
990
- }
991
- }
992
-
993
- if (!this._mainCamera) {
994
- Context.Current = this;
995
- let camera: ICamera | null = null;
996
- foreachComponent(this.scene, comp => {
997
- const cam = comp as ICamera;
998
- if (cam?.isCamera) {
999
- looputils.updateActiveInHierarchyWithoutEventCall(cam.gameObject);
1000
- if (!cam.activeAndEnabled) return undefined;
1001
- if (cam.tag === "MainCamera") {
1002
- camera = cam;
1003
- return true;
1004
- }
1005
- else camera = cam;
1006
- }
1007
- return undefined;
1008
- });
1009
- if (camera) {
1010
- this.setCurrentCamera(camera);
1011
- }
1012
- else {
1013
- const res = ContextRegistry.dispatchCallback(ContextEvent.MissingCamera, this, { files: loadedFiles });
1014
- if (!res && !this.mainCamera && !this.isManagedExternally)
1015
- console.warn("Missing camera in main scene", this);
1016
- }
1017
- }
1018
-
1019
- this.input.bindEvents();
1020
-
1021
- Context.Current = this;
1022
- looputils.processNewScripts(this);
1023
-
1024
- // We have to step once so that colliders that have been created in onEnable can be raycasted in start
1025
- if (this.physics.engine) {
1026
- this.physics.engine?.step(0);
1027
- this.physics.engine?.postStep();
1028
- }
1029
-
1030
- // const mainCam = this.mainCameraComponent as Camera;
1031
- // if (mainCam) {
1032
- // mainCam.applyClearFlagsIfIsActiveCamera();
1033
- // }
1034
-
1035
- if (!this.isManagedExternally && this.composer && this.mainCamera) {
1036
- // TODO: import postprocessing async
1037
- // const renderPass = new RenderPass(this.scene, this.mainCamera);
1038
- // this.renderer.setSize(this.domWidth, this.domHeight);
1039
- // this.composer.addPass(renderPass);
1040
- // this.composer.setSize(this.domWidth, this.domHeight);
1041
- }
1042
-
1043
- this._needsUpdateSize = true;
1044
-
1045
- if (this._stats) {
1046
- this._stats.showPanel(0);
1047
- this._stats.dom.style.position = "absolute"; // (default is fixed)
1048
- this.domElement.shadowRoot?.appendChild(this._stats.dom);
1049
- }
1050
-
1051
- if (debug)
1052
- logHierarchy(this.scene, true);
1053
-
1054
- // If no target framerate was set we use the default
1055
- if (this.targetFrameRate === undefined) {
1056
- if (debug) console.warn("No target framerate set, using default", Context.DefaultTargetFrameRate);
1057
- // the _defaultTargetFramerate is intentionally an object so it can be changed at any time if not explictly set by the user
1058
- this.targetFrameRate = Context._defaultTargetFramerate;
1059
- }
1060
- else if (debug) console.log("Target framerate set to", this.targetFrameRate);
1061
-
1062
- this._dispatchReadyAfterFrame = true;
1063
- const res = ContextRegistry.dispatchCallback(ContextEvent.ContextCreated, this, { files: loadedFiles });
1064
- if (res) {
1065
- if ("internalSetLoadingMessage" in this.domElement && typeof this.domElement.internalSetLoadingMessage === "function")
1066
- this.domElement?.internalSetLoadingMessage("finish loading");
1067
- await res;
1068
- }
1069
- if (opts?.abortSignal?.aborted) {
1070
- return false;
1071
- }
1072
- invokeLifecycleFunctions(this, ContextEvent.ContextCreated);
1073
- if (debug) console.log("Context Created...", this.renderer, this.renderer.domElement)
1074
-
1075
- this._isCreating = false;
1076
- if (!this.isManagedExternally && !opts?.abortSignal?.aborted)
1077
- this.restartRenderLoop();
1078
- return true;
1079
- }
1080
-
1081
- private async internalLoadInitialContent(createId: number, args: ContextCreateArgs): Promise<Array<LoadedModel>> {
1082
- const results = new Array<LoadedModel>();
1083
- // early out if we dont have any files to load
1084
- if (args.files.length === 0) return results;
1085
-
1086
-
1087
- const files = [...args.files];
1088
- const progressArg: LoadingProgressArgs = {
1089
- name: "",
1090
- progress: null!,
1091
- index: 0,
1092
- count: files.length
1093
- }
1094
-
1095
- const loader = getLoader();
1096
- // this hash should be constant since it is used to initialize the UIDProvider per initially loaded scene
1097
- const loadingHash = 0;
1098
- for (let i = 0; i < files.length; i++) {
1099
- if (args.abortSignal?.aborted) {
1100
- if (debug) console.log("Aborting loading because of abort signal");
1101
- break;
1102
- }
1103
- // abort loading if the create id has changed
1104
- if (createId !== this._createId) {
1105
- if (debug) console.log("Aborting loading because create id changed", createId, this._createId);
1106
- break;
1107
- }
1108
- const file = files[i];
1109
- args?.onLoadingStart?.call(this, i, file);
1110
- if (debug) console.log("Context Load " + file);
1111
- const res = await loader.loadSync(this, file, file, loadingHash, prog => {
1112
- if (args.abortSignal?.aborted) return;
1113
- progressArg.name = file;
1114
- progressArg.progress = prog;
1115
- progressArg.index = i;
1116
- progressArg.count = files.length;
1117
- args.onLoadingProgress?.call(this, progressArg);
1118
- });
1119
- args?.onLoadingFinished?.call(this, i, file, res ?? null);
1120
- if (res) {
1121
- results.push({
1122
- src: file,
1123
- file: res
1124
- });
1125
- }
1126
- else {
1127
- // a file could not be loaded
1128
- console.warn("Could not load file: " + file);
1129
- }
1130
- }
1131
-
1132
- // if the id was changed while still loading
1133
- // then we want to cleanup/destroy previously loaded files
1134
- if (createId !== this._createId || args.abortSignal?.aborted) {
1135
- if (debug) console.log("Aborting loading because create id changed or abort signal was set", createId, this._createId);
1136
- for (const res of results) {
1137
- if (res && res.file) {
1138
- for (const scene of res.file.scenes)
1139
- destroy(scene, true, true);
1140
- }
1141
- }
1142
- }
1143
- // otherwise we want to add the loaded files to the current scene
1144
- else {
1145
- let anyModelFound = false;
1146
- for (const res of results) {
1147
- if (res && res.file) {
1148
- // TODO: should we load all scenes in a glTF here?
1149
- if (res.file.scene) {
1150
- anyModelFound = true;
1151
- this.scene.add(res.file.scene);
1152
- }
1153
- else {
1154
- console.warn("No scene found in loaded file");
1155
- }
1156
- }
1157
- }
1158
- // If the loaded files do not contain ANY model
1159
- // We then attempt to create a mesh from each material in the loaded files to visualize it
1160
- // It's ok to do this at this point because we know the context has been cleared because the whole `src` attribute has been set
1161
- if (!anyModelFound) {
1162
- for (const res of results) {
1163
- if (res && res.file && "parser" in res.file) {
1164
- let y = 0;
1165
- if (!Array.isArray(res.file.parser.json.materials)) continue;
1166
- for (let i = 0; i < res.file.parser.json.materials.length; i++) {
1167
- const mat = await res.file.parser.getDependency("material", i);
1168
- const parent = new Object3D();
1169
- parent.position.x = i * 1.1;
1170
- parent.position.y = y;
1171
- this.scene.add(parent);
1172
- ObjectUtils.createPrimitive("ShaderBall", {
1173
- parent,
1174
- material: mat
1175
- });
1176
- }
1177
- y += 1;
1178
- }
1179
- }
1180
- }
1181
- }
1182
-
1183
- return results;
1184
- }
1185
-
1186
-
1187
- /** Sets the animation loop.
1188
- * Can not be done while creating the context or when disposed
1189
- **/
1190
- public restartRenderLoop(): boolean {
1191
- if (!this.renderer) {
1192
- console.error("Can not start render loop without renderer");
1193
- return false;
1194
- }
1195
- if (this._isCreating) {
1196
- console.warn("Can not start render loop while creating context");
1197
- return false;
1198
- }
1199
- this.renderer.setAnimationLoop((timestamp, frame: XRFrame | null) => {
1200
- if (this.isManagedExternally) return;
1201
- this.update(timestamp, frame)
1202
- });
1203
- return true;
1204
- }
1205
-
1206
- private _renderlooperrors = 0;
1207
-
1208
- /** Performs a full update step including script callbacks, rendering (unless isManagedExternally is set to false) and post render callbacks */
1209
- public update(timestamp: DOMHighResTimeStamp, frame?: XRFrame | null) {
1210
- if (frame === undefined) frame = null;
1211
- if (isDevEnvironment() || debug || looputils.hasNewScripts()) {
1212
- try {
1213
- //performance.mark('update.start');
1214
- this.internalStep(timestamp, frame);
1215
- this._renderlooperrors = 0;
1216
- //performance.mark('update.end');
1217
- //performance.measure('NE Frame', 'update.start', 'update.end');
1218
- }
1219
- catch (err) {
1220
- this._renderlooperrors += 1;
1221
- if ((isDevEnvironment() || debug) && (err instanceof Error || err instanceof TypeError))
1222
- showBalloonMessage(`Caught unhandled exception during render-loop - see console for details.`, LogType.Error);
1223
- console.error("Frame #" + this.time.frame + "\n", err);
1224
- if (this._renderlooperrors >= 3) {
1225
- console.warn("Stopping render loop due to error")
1226
- this.renderer.setAnimationLoop(null);
1227
- }
1228
- this.domElement.dispatchEvent(new CustomEvent("error", { detail: err }));
1229
- }
1230
- }
1231
- else {
1232
- this.internalStep(timestamp, frame);
1233
- }
1234
- }
1235
-
1236
- /** Call to **manually** perform physics steps.
1237
- * By default the context uses the `physicsSteps` property to perform steps during the update loop
1238
- * If you just want to increase the accuracy of physics you can instead set the `physicsSteps` property to a higher value
1239
- * */
1240
- public updatePhysics(steps: number) {
1241
- this.internalUpdatePhysics(steps);
1242
- }
1243
-
1244
- private _lastTimestamp = 0;
1245
- private _accumulatedTime = 0;
1246
- private _dispatchReadyAfterFrame = false;
1247
-
1248
- // TODO: we need to skip after render callbacks if the render loop is managed externally. When changing this we also need to to update the r3f sample
1249
- private internalStep(timestamp: DOMHighResTimeStamp, frame: XRFrame | null) {
1250
- if (this.internalOnBeforeRender(timestamp, frame) === false) return;
1251
- this.internalOnRender();
1252
- this.internalOnAfterRender();
1253
- }
1254
-
1255
- private internalOnBeforeRender(timestamp: DOMHighResTimeStamp, frame: XRFrame | null) {
1256
-
1257
- // If we don't auto reset we get wrong stats in WebXR. AutoReset was turned off to support custom blits and count them too
1258
- this.renderer.info.autoReset = true;
1259
-
1260
-
1261
- const sessionStarted = frame !== null && this._xrFrame === null;
1262
- this._xrFrame = frame;
1263
- if (sessionStarted) {
1264
- this.domElement.dispatchEvent(new CustomEvent("xr-session-started", { detail: { context: this, session: this.xrSession, frame: frame } }));
1265
- }
1266
-
1267
- this._currentFrameEvent = FrameEvent.Undefined;
1268
-
1269
- if (this.isManagedExternally === false && this.isInXR === false && this.targetFrameRate !== undefined) {
1270
- if (this._lastTimestamp === 0) this._lastTimestamp = timestamp;
1271
- this._accumulatedTime += (timestamp - this._lastTimestamp) / 1000;
1272
- this._lastTimestamp = timestamp;
1273
- let targetFrameRate = this.targetFrameRate;
1274
- if (typeof targetFrameRate === "object") targetFrameRate = targetFrameRate.value!;
1275
- // if(debug) console.log(this._accumulatedTime, (1 / (targetFrameRate)))
1276
- if (this._accumulatedTime < (1 / (targetFrameRate + 1))) {
1277
- return false;
1278
- }
1279
- this._accumulatedTime = 0;
1280
- }
1281
-
1282
- this._stats?.begin();
1283
-
1284
- Context.Current = this;
1285
- if (this.onHandlePaused()) return false;
1286
-
1287
- Context.Current = this;
1288
- this.time.update();
1289
- if (debugframerate)
1290
- console.log("FPS", (this.time.smoothedFps).toFixed(0));
1291
-
1292
-
1293
- looputils.processNewScripts(this);
1294
- looputils.updateIsActive(this.scene);
1295
- looputils.processStart(this);
1296
- invokeLifecycleFunctions(this, FrameEvent.Start);
1297
-
1298
- while (this._cameraStack.length > 0 && (!this.mainCameraComponent || this.mainCameraComponent.destroyed)) {
1299
- this._cameraStack.splice(this._cameraStack.length - 1, 1);
1300
- const last = this._cameraStack[this._cameraStack.length - 1];
1301
- this.setCurrentCamera(last);
1302
- }
1303
-
1304
- if (this.pre_update_oneshot_callbacks) {
1305
- for (const i in this.pre_update_oneshot_callbacks) {
1306
- this.pre_update_oneshot_callbacks[i]();
1307
- }
1308
- this.pre_update_oneshot_callbacks.length = 0;
1309
- }
1310
-
1311
- if (this.pre_update_callbacks) {
1312
- for (const i in this.pre_update_callbacks) {
1313
- this.pre_update_callbacks[i]();
1314
- }
1315
- }
1316
-
1317
- this._currentFrameEvent = FrameEvent.EarlyUpdate;
1318
-
1319
- for (let i = 0; i < this.scripts_earlyUpdate.length; i++) {
1320
- const script = this.scripts_earlyUpdate[i];
1321
- if (!script.activeAndEnabled) continue;
1322
- if (script.earlyUpdate !== undefined) {
1323
- Context.Current = this;
1324
- script.earlyUpdate();
1325
- }
1326
- }
1327
- this.executeCoroutines(FrameEvent.EarlyUpdate);
1328
- invokeLifecycleFunctions(this, FrameEvent.EarlyUpdate);
1329
- if (this.onHandlePaused()) return false;
1330
-
1331
- this._currentFrameEvent = FrameEvent.Update;
1332
-
1333
- for (let i = 0; i < this.scripts_update.length; i++) {
1334
- const script = this.scripts_update[i];
1335
- if (!script.activeAndEnabled) continue;
1336
- if (script.update !== undefined) {
1337
- Context.Current = this;
1338
- script.update();
1339
- }
1340
- }
1341
- this.executeCoroutines(FrameEvent.Update);
1342
- invokeLifecycleFunctions(this, FrameEvent.Update);
1343
- if (this.onHandlePaused()) return false;
1344
-
1345
- this._currentFrameEvent = FrameEvent.LateUpdate;
1346
-
1347
- for (let i = 0; i < this.scripts_lateUpdate.length; i++) {
1348
- const script = this.scripts_lateUpdate[i];
1349
- if (!script.activeAndEnabled) continue;
1350
- if (script.lateUpdate !== undefined) {
1351
- Context.Current = this;
1352
- script.lateUpdate();
1353
- }
1354
- }
1355
-
1356
- // this.mainLight = null;
1357
- this.executeCoroutines(FrameEvent.LateUpdate);
1358
- invokeLifecycleFunctions(this, FrameEvent.LateUpdate);
1359
- if (this.onHandlePaused()) return false;
1360
-
1361
- if (this.physicsSteps === undefined) {
1362
- this.physicsSteps = 1;
1363
- }
1364
- if (this.physics.engine && this.physicsSteps > 0) {
1365
- this.internalUpdatePhysics(this.physicsSteps);
1366
- }
1367
-
1368
- if (this.onHandlePaused()) return false;
1369
-
1370
- if (this.isVisibleToUser || this.runInBackground) {
1371
-
1372
- this._currentFrameEvent = FrameEvent.OnBeforeRender;
1373
-
1374
- // should we move these callbacks in the regular three onBeforeRender events?
1375
- for (let i = 0; i < this.scripts_onBeforeRender.length; i++) {
1376
- const script = this.scripts_onBeforeRender[i];
1377
- if (!script.activeAndEnabled) continue;
1378
- // if(script.isActiveAndEnabled === false) continue;
1379
- if (script.onBeforeRender !== undefined) {
1380
- Context.Current = this;
1381
- script.onBeforeRender(frame);
1382
- }
1383
- }
1384
-
1385
- this.executeCoroutines(FrameEvent.OnBeforeRender);
1386
- invokeLifecycleFunctions(this, FrameEvent.OnBeforeRender);
1387
-
1388
- if (this._needsUpdateSize)
1389
- this.updateSize();
1390
-
1391
- if (this.pre_render_callbacks) {
1392
- for (const i in this.pre_render_callbacks) {
1393
- this.pre_render_callbacks[i](frame);
1394
- }
1395
- }
1396
-
1397
- }
1398
-
1399
- return true;
1400
- }
1401
-
1402
- private internalUpdatePhysics(steps: number) {
1403
- if (!this.physics.engine) return false;
1404
- const physicsSteps = steps;
1405
- const dt = this.time.deltaTime / physicsSteps;
1406
- for (let i = 0; i < physicsSteps; i++) {
1407
- this._currentFrameEvent = FrameEvent.PrePhysicsStep;
1408
- this.executeCoroutines(FrameEvent.PrePhysicsStep);
1409
- this.physics.engine.step(dt);
1410
- this._currentFrameEvent = FrameEvent.PostPhysicsStep;
1411
- this.executeCoroutines(FrameEvent.PostPhysicsStep);
1412
- }
1413
- this.physics.engine.postStep();
1414
- return true;
1415
- }
1416
-
1417
- private internalOnRender() {
1418
- if (!this.isManagedExternally) {
1419
- // when loading assets we compile them async after GLTFLoader is done
1420
- // but as a fallback we still register them (if e.g. there's no camera for compile async)
1421
- looputils.runPrewarm(this);
1422
- this._currentFrameEvent = FrameEvent.Undefined;
1423
- nodeFrame.update();
1424
- this.renderNow();
1425
- this._currentFrameEvent = FrameEvent.OnAfterRender;
1426
- }
1427
- }
1428
-
1429
- private internalOnAfterRender() {
1430
- if (this.isVisibleToUser || this.runInBackground) {
1431
- for (let i = 0; i < this.scripts_onAfterRender.length; i++) {
1432
- const script = this.scripts_onAfterRender[i];
1433
- if (!script.activeAndEnabled) continue;
1434
- if (script.onAfterRender !== undefined) {
1435
- Context.Current = this;
1436
- script.onAfterRender();
1437
- }
1438
- }
1439
-
1440
- this.executeCoroutines(FrameEvent.OnAfterRender);
1441
- invokeLifecycleFunctions(this, FrameEvent.OnAfterRender);
1442
-
1443
- if (this.post_render_callbacks) {
1444
- for (const i in this.post_render_callbacks) {
1445
- this.post_render_callbacks[i]();
1446
- }
1447
- }
1448
- }
1449
-
1450
- this._currentFrameEvent = -1;
1451
-
1452
- this.connection.sendBufferedMessagesNow();
1453
-
1454
- if (this._stats) {
1455
- this._stats.end();
1456
- if (this.time.frameCount % 150 === 0)
1457
- console.log(this.renderer.info.render.calls + " DrawCalls", "\nRender:", { ...this.renderer.info.render }, "\nMemory:", { ...this.renderer.info.memory }, "\nTarget Framerate: " + this.targetFrameRate);
1458
- }
1459
-
1460
- if (this._dispatchReadyAfterFrame) {
1461
- this._dispatchReadyAfterFrame = false;
1462
- this.domElement.dispatchEvent(new CustomEvent("ready"));
1463
- ContextRegistry.dispatchCallback(ContextEvent.ContextFirstFrameRendered, this);
1464
- }
1465
- }
1466
-
1467
- renderNow(camera?: Camera) {
1468
- if (!camera) {
1469
- camera = this.mainCamera as Camera;
1470
- if (!camera) return false;
1471
- }
1472
- this.handleRendererContextLost();
1473
-
1474
- this._isRendering = true;
1475
- this.renderRequiredTextures();
1476
-
1477
- if (this.renderer.toneMapping !== NoToneMapping)
1478
- patchTonemapping(this);
1479
-
1480
- if (this.composer && !this.isInXR) {
1481
- // if a camera is passed in we need to check if we need to update the composer's camera
1482
- if (camera && "setMainCamera" in this.composer) {
1483
- const currentPassesCamera = this.composer.passes[0]?.mainCamera;
1484
- if (currentPassesCamera != camera)
1485
- this.composer.setMainCamera(camera);
1486
- }
1487
- this.composer.render(this.time.deltaTime);
1488
- }
1489
- else if (camera) {
1490
- // Workaround for issue on Vision Pro –
1491
- // depth buffer is not cleared between eye draws, despite the spec...
1492
- if (this.isInXR && DeviceUtilities.isMacOS())
1493
- this.renderer.clearDepth();
1494
- this.renderer.render(this.scene, camera);
1495
- }
1496
- this._isRendering = false;
1497
- return true;
1498
- }
1499
-
1500
- private _contextRestoreTries = 0;
1501
- private handleRendererContextLost() {
1502
- // Try to restore the context every x frames
1503
- if (this.time.frame % 10 && this.renderer.getContext().isContextLost()) {
1504
- if (this._contextRestoreTries++ < 100) {
1505
- console.warn("Attempting to recover WebGL context...");
1506
- this.renderer.forceContextRestore();
1507
- }
1508
- }
1509
- }
1510
-
1511
- /** returns true if we should return out of the frame loop */
1512
- private _wasPaused: boolean = false;
1513
- private onHandlePaused(): boolean {
1514
- const paused = this.evaluatePaused();
1515
- if (this._wasPaused !== paused) {
1516
- if (debugActive) console.log("Paused?", paused, "context:" + this.alias);
1517
- for (let i = 0; i < this.scripts_pausedChanged.length; i++) {
1518
- const script = this.scripts_pausedChanged[i];
1519
- if (!script.activeAndEnabled) continue;
1520
- if (script.onPausedChanged !== undefined) {
1521
- Context.Current = this;
1522
- script.onPausedChanged(paused, this._wasPaused);
1523
- }
1524
- }
1525
- }
1526
- this._wasPaused = paused;
1527
- return paused;
1528
- }
1529
-
1530
- private evaluatePaused(): boolean {
1531
- if (this.isInXR) return false;
1532
- if (this.isPaused) return true;
1533
- // if the element is not visible use the runInBackground flag to determine if we should continue
1534
- if (this.runInBackground) {
1535
- return false;
1536
- }
1537
- const paused = !this.isVisibleToUser;
1538
- return paused;
1539
- }
1540
-
1541
- private renderRequiredTextures() {
1542
- if (!this.mainCamera) return;
1543
- if (!this._requireDepthTexture && !this._requireColorTexture) return;
1544
- if (!this._renderTarget) {
1545
- this._renderTarget = new WebGLRenderTarget(this.domWidth, this.domHeight);
1546
- if (this._requireDepthTexture) {
1547
- const dt = new DepthTexture(this.domWidth, this.domHeight);;
1548
- this._renderTarget.depthTexture = dt;
1549
- }
1550
- if (this._requireColorTexture) {
1551
- this._renderTarget.texture = new Texture();
1552
- this._renderTarget.texture.generateMipmaps = false;
1553
- this._renderTarget.texture.minFilter = NearestFilter;
1554
- this._renderTarget.texture.magFilter = NearestFilter;
1555
- this._renderTarget.texture.format = RGBAFormat;
1556
- }
1557
- }
1558
- const rt = this._renderTarget;
1559
- if (rt.texture) {
1560
- rt.texture.colorSpace = this.renderer.outputColorSpace;
1561
- }
1562
- const prevTarget = this.renderer.getRenderTarget();
1563
- this.renderer.setRenderTarget(rt);
1564
- this.renderer.render(this.scene, this.mainCamera);
1565
- this.renderer.setRenderTarget(prevTarget);
1566
- }
1567
-
1568
- private executeCoroutines(evt: FrameEvent) {
1569
- if (this.coroutines[evt]) {
1570
- const evts = this.coroutines[evt];
1571
- for (let i = 0; i < evts.length; i++) {
1572
- try {
1573
- const evt = evts[i];
1574
- // TODO we might want to keep coroutines playing even if the component is disabled or inactive
1575
- const remove = !evt.comp || evt.comp.destroyed || !evt.main || evt.comp["enabled"] === false;
1576
- if (remove) {
1577
- if (debugCoroutine) console.log("Removing coroutine", evt.comp, evt.comp["enabled"])
1578
- evts.splice(i, 1);
1579
- --i;
1580
- continue;
1581
- }
1582
- const iter = evt.chained;
1583
- if (iter && iter.length > 0) {
1584
- const last: Generator = iter[iter.length - 1];
1585
- const res = last.next();
1586
- if (res.done) {
1587
- iter.pop();
1588
- }
1589
- if (isGenerator(res)) {
1590
- if (!evt.chained) evt.chained = [];
1591
- evt.chained.push(res.value);
1592
- }
1593
- if (!res.done) continue;
1594
- }
1595
-
1596
- const res = evt.main.next();
1597
- if (res.done === true) {
1598
- evts.splice(i, 1);
1599
- --i;
1600
- continue;
1601
- }
1602
- const val = res.value;
1603
- if (isGenerator(val)) {
1604
- // invoke once if its a generator
1605
- // this means e.g. WaitForFrame(1) works and will capture
1606
- // the frame it was created
1607
- const gen = val as Generator;
1608
- const res = gen.next();
1609
- if (res.done) continue;
1610
- if (!evt.chained) evt.chained = [];
1611
- evt.chained.push(val as Generator);
1612
- }
1613
- else if (val instanceof Promise) {
1614
- // If its a promise we want to wait for it to resolve
1615
- const prom = val as Promise<any>;
1616
- if (!evt.chained) evt.chained = [];
1617
- const nested = WaitForPromise(prom);
1618
- evt.chained?.push(nested);
1619
- continue;
1620
- }
1621
- }
1622
- catch (e) {
1623
- console.error(e);
1624
- }
1625
- }
1626
- }
1627
-
1628
- function isGenerator(val: any): boolean {
1629
- if (val) {
1630
- if (val.next && val.return) {
1631
- return true;
1632
- }
1633
- }
1634
- return false;
1635
- }
1636
- }
1637
-
1638
- }
1639
-
1640
-
1641
- // const scene = new Scene();
1642
- // const useComposer = utils.getParam("postfx");
1643
- // const renderer = new WebGLRenderer({ antialias: true });
1644
- // const composer = useComposer ? new EffectComposer(renderer) : undefined;
1645
-
1646
- // renderer.setClearColor(new Color('lightgrey'), 0)
1647
- // renderer.antialias = true;
1648
- // renderer.alpha = false;
1649
- // renderer.shadowMap.enabled = true;
1650
- // renderer.shadowMap.type = PCFSoftShadowMap;
1651
- // renderer.setSize(window.innerWidth, window.innerHeight);
1652
- // renderer.outputEncoding = sRGBEncoding;
1653
- // renderer.physicallyCorrectLights = true;
1654
- // document.body.appendChild(renderer.domElement);
1655
-
1656
- // // generation pushes loading requests in this array
1657
- // const sceneData: {
1658
- // mainCamera: Camera | undefined
1659
- // } = {
1660
- // preparing: [],
1661
- // resolving: [],
1662
- // scripts: [],
1663
- // raycastTargets: [],
1664
- // mainCamera: undefined,
1665
- // mainCameraComponent: undefined,
1666
- // };
1667
-
1668
- // // contains a list of functions to be called after loading is done
1669
- // const post_setup_callbacks = [];
1670
-
1671
- // const pre_render_Callbacks = [];
1672
- // const post_render_callbacks = [];
1673
-
1674
- // const new_scripts = [];
1675
- // const new_scripts_post_setup_callbacks = [];
1676
- // const new_scripts_pre_setup_callbacks = [];
1677
-
1678
- // export {
1679
- // scene, renderer, composer,
1680
- // new_scripts,
1681
- // new_scripts_post_setup_callbacks, new_scripts_pre_setup_callbacks,
1682
- // sceneData,
1683
- // post_setup_callbacks,
1684
- // pre_render_Callbacks,
1685
- // post_render_callbacks
1686
- // }
1
+ import 'three/examples/jsm/renderers/webgl-legacy/nodes/WebGLNodes.js';
2
+
3
+ import type { EffectComposer } from "postprocessing";
4
+ import {
5
+ BufferGeometry, Camera, Color, DepthTexture, Group,
6
+ Material, NearestFilter, NoToneMapping, Object3D, OrthographicCamera, PCFSoftShadowMap,
7
+ PerspectiveCamera, RGBAFormat, Scene, SRGBColorSpace,
8
+ Texture, WebGLRenderer, type WebGLRendererParameters, WebGLRenderTarget, type WebXRArrayCamera
9
+ } from 'three';
10
+ /** @ts-ignore (not yet in types?) */
11
+ import { BasicNodeLibrary } from "three";
12
+ import * as Stats from 'three/examples/jsm/libs/stats.module.js';
13
+ import type { EffectComposer as ThreeEffectComposer } from "three/examples/jsm/postprocessing/EffectComposer.js";
14
+ import { nodeFrame } from "three/examples/jsm/renderers/webgl-legacy/nodes/WebGLNodeBuilder.js";
15
+
16
+ import { isDevEnvironment, LogType, showBalloonError, showBalloonMessage } from './debug/index.js';
17
+ import { Addressables } from './engine_addressables.js';
18
+ import { AnimationsRegistry } from './engine_animation.js';
19
+ import { Application } from './engine_application.js';
20
+ import { AssetDatabase } from './engine_assetdatabase.js';
21
+ import { VERSION } from './engine_constants.js';
22
+ import { ContextEvent, ContextRegistry } from './engine_context_registry.js';
23
+ import { WaitForPromise } from './engine_coroutine.js';
24
+ import { ObjectUtils } from "./engine_create_objects.js";
25
+ import { destroy, foreachComponent } from './engine_gameobject.js';
26
+ import { getLoader } from './engine_gltf.js';
27
+ import { Input } from './engine_input.js';
28
+ import { invokeLifecycleFunctions } from './engine_lifecycle_functions_internal.js';
29
+ import { type ILightDataRegistry, LightDataRegistry } from './engine_lightdata.js';
30
+ import { LODsManager } from "./engine_lods.js";
31
+ import * as looputils from './engine_mainloop_utils.js';
32
+ import { NetworkConnection } from './engine_networking.js';
33
+ import { Physics } from './engine_physics.js';
34
+ import { PlayerViewManager } from './engine_playerview.js';
35
+ import { RendererData as SceneLighting } from './engine_scenelighting.js';
36
+ import { logHierarchy } from './engine_three_utils.js';
37
+ import { Time } from './engine_time.js';
38
+ import { patchTonemapping } from './engine_tonemapping.js';
39
+ import type { CoroutineData, ICamera, IComponent, IContext, ILight, LoadedModel, Model, Vec2 } from "./engine_types.js";
40
+ import { deepClone, delay, DeviceUtilities, getParam } from './engine_utils.js';
41
+ import type { INeedleXRSessionEventReceiver, NeedleXRSession } from './engine_xr.js';
42
+ import { NeedleMenu } from './webcomponents/needle menu/needle-menu.js';
43
+
44
+ const debug = getParam("debugcontext");
45
+ const stats = getParam("stats");
46
+ const debugActive = getParam("debugactive");
47
+ const debugframerate = getParam("debugframerate");
48
+ const debugCoroutine = getParam("debugcoroutine");
49
+
50
+ // this is where functions that setup unity scenes will be pushed into
51
+ // those will be accessed from our custom html element to load them into their context
52
+ export const build_scene_functions: { [name: string]: (context: Context) => Promise<void> } = {};
53
+
54
+
55
+ export declare class LoadingProgressArgs {
56
+ /** the name or URL of the loaded file */
57
+ name: string;
58
+ /** the loading progress event from the loader */
59
+ progress: ProgressEvent;
60
+ /** the index of the loaded file */
61
+ index: number;
62
+ /** the total number of files to load */
63
+ count: number;
64
+ }
65
+ export declare class ContextCreateArgs {
66
+ /** list of glTF or GLB files to load */
67
+ files: Array<string>;
68
+ abortSignal?: AbortSignal;
69
+ /** called when loading a provided glTF file started */
70
+ onLoadingStart?: (index: number, file: string) => void;
71
+ /** called on update for each loaded glTF file */
72
+ onLoadingProgress?: (args: LoadingProgressArgs) => void;
73
+ /** Called after a gLTF file has finished loading */
74
+ onLoadingFinished?: (index: number, file: string, glTF: Model | null) => void;
75
+ }
76
+
77
+ export class ContextArgs {
78
+ name?: string;
79
+ /** for debugging only */
80
+ alias?: string;
81
+ /** the hash is used as a seed when initially loading the scene files */
82
+ hash?: string;
83
+
84
+ /** when true the context will not check if it's visible in the viewport and always update and render */
85
+ runInBackground?: boolean;
86
+ /** the DOM element the context belongs to or is inside of (this does not have to be the canvas. use renderer.domElement if you want to access the dom canvas) */
87
+ domElement?: HTMLElement | null;
88
+ /** externally owned renderer */
89
+ renderer?: WebGLRenderer;
90
+ /** externally owned camera */
91
+ camera?: Camera;
92
+ /** externally owned scene */
93
+ scene?: Scene;
94
+ }
95
+
96
+ export enum FrameEvent {
97
+ Start = -1,
98
+ EarlyUpdate = 0,
99
+ Update = 1,
100
+ LateUpdate = 2,
101
+ OnBeforeRender = 3,
102
+ OnAfterRender = 4,
103
+ PrePhysicsStep = 9,
104
+ PostPhysicsStep = 10,
105
+ Undefined = -1,
106
+ }
107
+
108
+ /** threejs callback event signature */
109
+ export declare type OnRenderCallback = (renderer: WebGLRenderer, scene: Scene, camera: Camera, geometry: BufferGeometry, material: Material, group: Group) => void
110
+
111
+
112
+ export function registerComponent(script: IComponent, context?: Context) {
113
+ if (!script) return;
114
+ if (!script.isComponent) {
115
+ if (isDevEnvironment() || debug)
116
+ console.error("Registered script is not a Needle Engine component. \nThe script will be ignored. Please make sure your component extends \"Behaviour\" imported from \"@needle-tools/engine\"\n", script);
117
+ return;
118
+ }
119
+ if (!context) {
120
+ context = Context.Current;
121
+ if (debug) console.warn("> Registering component without context");
122
+ }
123
+ const new_scripts = context?.new_scripts;
124
+ if (!new_scripts.includes(script)) {
125
+ new_scripts.push(script);
126
+ }
127
+ }
128
+
129
+ /**
130
+ * The context is the main object that holds all the data and state of the Needle Engine.
131
+ * It can be used to access the scene, renderer, camera, input, physics, networking, and more.
132
+ * @example
133
+ * ```typescript
134
+ * import { Behaviour } from "@needle-tools/engine";
135
+ * import { Mesh, BoxGeometry, MeshBasicMaterial } from "three";
136
+ * export class MyScript extends Behaviour {
137
+ * start() {
138
+ * console.log("Hello from MyScript");
139
+ * this.context.scene.add(new Mesh(new BoxGeometry(), new MeshBasicMaterial()));
140
+ * }
141
+ * }
142
+ * ```
143
+ */
144
+ export class Context implements IContext {
145
+
146
+ private static _defaultTargetFramerate: { value?: number, toString?() } = { value: 90, toString() { return this.value; } }
147
+ /** When a new context is created this is the framerate that will be used by default */
148
+ static get DefaultTargetFrameRate(): number | undefined {
149
+ return Context._defaultTargetFramerate.value;
150
+ }
151
+ /** When a new context is created this is the framerate that will be used by default */
152
+ static set DefaultTargetFrameRate(val: number | undefined) {
153
+ Context._defaultTargetFramerate.value = val;
154
+ }
155
+
156
+ private static _defaultWebglRendererParameters: WebGLRendererParameters = {
157
+ antialias: true,
158
+ alpha: false,
159
+ // Note: this is due to a bug on OSX devices. See NE-5370
160
+ powerPreference: (DeviceUtilities.isiOS() || DeviceUtilities.isMacOS()) ? "default" : "high-performance",
161
+ stencil: true,
162
+ // logarithmicDepthBuffer: true,
163
+ // reverseDepthBuffer: true, // https://github.com/mrdoob/three.js/issues/29770
164
+ };
165
+ /** The default parameters that will be used when creating a new WebGLRenderer.
166
+ * Modify in global context to change the default parameters for all new contexts.
167
+ * @example
168
+ * ```typescript
169
+ * import { Context } from "@needle-tools/engine";
170
+ * Context.DefaultWebGLRendererParameters.antialias = false;
171
+ * ```
172
+ */
173
+ static get DefaultWebGLRendererParameters(): WebGLRendererParameters {
174
+ return Context._defaultWebglRendererParameters;
175
+ }
176
+
177
+ /** The needle engine version */
178
+ get version() {
179
+ return VERSION;
180
+ }
181
+
182
+ /** The currently active context. Only set during the update loops */
183
+ static get Current(): Context {
184
+ return ContextRegistry.Current as Context;
185
+ }
186
+
187
+ /** @internal this property should not be set by user code */
188
+ static set Current(context: Context) {
189
+ ContextRegistry.Current = context;
190
+ }
191
+
192
+ static get All(): Context[] {
193
+ return ContextRegistry.All as Context[];
194
+ }
195
+
196
+ /** The name of the context */
197
+ name: string;
198
+ /** An alias for the context */
199
+ alias: string | undefined | null;
200
+ /** When the renderer or camera are managed by an external process (e.g. when running in r3f context).
201
+ * When this is false you are responsible to call update(timestamp, xframe.
202
+ * It is also currently assumed that rendering is handled performed by an external process
203
+ * */
204
+ isManagedExternally: boolean = false;
205
+ /** set to true to pause the update loop. You can receive an event for it in your components.
206
+ * Note that script updates will not be called when paused */
207
+ isPaused: boolean = false;
208
+ /** When enabled the application will run while not visible on the page */
209
+ runInBackground: boolean = false;
210
+ /**
211
+ * Set to the target framerate you want your application to run in (you can use ?stats to check the fps)
212
+ * Set to undefined if you want to run at the maximum framerate
213
+ */
214
+ targetFrameRate?: number | { value?: number };
215
+
216
+ /** Use a higher number for more accurate physics simulation.
217
+ * When undefined physics steps will be 1 for mobile devices and 5 for desktop devices
218
+ * Set to 0 to disable physics updates
219
+ * TODO: changing physics steps is currently not supported because then forces that we get from the character controller and rigidbody et al are not correct anymore - this needs to be properly tested before making this configureable
220
+ */
221
+ private physicsSteps?: number = 1;
222
+
223
+ /** used to append to loaded assets */
224
+ hash?: string;
225
+
226
+ /** The `<needle-engine>` web component */
227
+ domElement: HTMLElement;
228
+
229
+ appendHTMLElement(element: HTMLElement) {
230
+ if (this.domElement.shadowRoot)
231
+ return this.domElement.shadowRoot.appendChild(element);
232
+ else return this.domElement.appendChild(element);
233
+ }
234
+
235
+ get resolutionScaleFactor() { return this._resolutionScaleFactor; }
236
+ /** use to scale the resolution up or down of the renderer. default is 1 */
237
+ set resolutionScaleFactor(val: number) {
238
+ if (val === this._resolutionScaleFactor) return;
239
+ if (typeof val !== "number") return;
240
+ if (val <= 0) {
241
+ console.error("Invalid resolution scale factor", val);
242
+ return;
243
+ }
244
+ this._resolutionScaleFactor = val;
245
+ this.updateSize();
246
+ }
247
+ private _resolutionScaleFactor: number = 1;
248
+
249
+ // domElement.clientLeft etc doesnt return absolute position
250
+ private _boundingClientRectFrame: number = -1;
251
+ private _boundingClientRect: DOMRect | null = null;
252
+ private _domX; private _domY;
253
+ /** update bounding rects + domX, domY */
254
+ private calculateBoundingClientRect() {
255
+ // workaround for mozilla webXR viewer
256
+ if (this.xr) {
257
+ this._domX = 0;
258
+ this._domY = 0;
259
+ return;
260
+ }
261
+ // TODO: cache this
262
+ if (this._boundingClientRectFrame === this.time.frame) return;
263
+ this._boundingClientRectFrame = this.time.frame;
264
+ this._boundingClientRect = this.domElement.getBoundingClientRect();
265
+ this._domX = this._boundingClientRect.x;
266
+ this._domY = this._boundingClientRect.y;
267
+ }
268
+
269
+ /** The width of the `<needle-engine>` element on the website */
270
+ get domWidth(): number {
271
+ // for mozilla XR
272
+ if (this.isInAR) return window.innerWidth;
273
+ return this.domElement.clientWidth;
274
+ }
275
+ /** The height of the `<needle-engine>` element on the website */
276
+ get domHeight(): number {
277
+ // for mozilla XR
278
+ if (this.isInAR) return window.innerHeight;
279
+ return this.domElement.clientHeight;
280
+ }
281
+ /** the X position of the Needle Engine element on the website */
282
+ get domX(): number {
283
+ this.calculateBoundingClientRect();
284
+ return this._domX;
285
+ }
286
+ /** the Y position of the Needlee Engine element on the website */
287
+ get domY(): number {
288
+ this.calculateBoundingClientRect();
289
+ return this._domY;
290
+ }
291
+ get isInXR() { return this.renderer?.xr?.isPresenting || false; }
292
+ /** shorthand for `NeedleXRSession.active`
293
+ * Automatically set by NeedleXRSession when a XR session is active
294
+ * @returns the active XR session or null if no session is active
295
+ * */
296
+ xr: NeedleXRSession | null = null;
297
+ get xrSessionMode() { return this.xr?.mode; }
298
+ get isInVR() { return this.xrSessionMode === "immersive-vr"; }
299
+ get isInAR() { return this.xrSessionMode === "immersive-ar"; }
300
+ /** If a XR session is active and in pass through mode (immersive-ar on e.g. Quest) */
301
+ get isInPassThrough() { return this.xr ? this.xr.isPassThrough : false; }
302
+ /** access the raw `XRSession` object (shorthand for `context.renderer.xr.getSession()`). For more control use `NeedleXRSession.active` */
303
+ get xrSession() { return this.renderer?.xr?.getSession(); }
304
+ /** @returns the latest XRFrame (if a XRSession is currently active)
305
+ * @link https://developer.mozilla.org/en-US/docs/Web/API/XRFrame
306
+ */
307
+ get xrFrame() { return this._xrFrame }
308
+ /** @returns the current WebXR camera while the WebXRManager is active (shorthand for `context.renderer.xr.getCamera()`) */
309
+ get xrCamera(): WebXRArrayCamera | undefined { return this.renderer.xr.isPresenting ? this.renderer?.xr?.getCamera() : undefined }
310
+ private _xrFrame: XRFrame | null = null;
311
+ get arOverlayElement(): HTMLElement {
312
+ const el = this.domElement as any;
313
+ if (typeof el.getAROverlayContainer === "function")
314
+ return el.getAROverlayContainer();
315
+ return this.domElement;
316
+ }
317
+ /** Current event of the update cycle */
318
+ get currentFrameEvent(): FrameEvent {
319
+ return this._currentFrameEvent;
320
+ }
321
+ private _currentFrameEvent: FrameEvent = FrameEvent.Undefined;
322
+
323
+ scene: Scene;
324
+ renderer!: WebGLRenderer;
325
+ composer: EffectComposer | ThreeEffectComposer | null = null;
326
+
327
+ // all scripts
328
+ readonly scripts: IComponent[] = [];
329
+ readonly scripts_pausedChanged: IComponent[] = [];
330
+ // scripts with update event
331
+ readonly scripts_earlyUpdate: IComponent[] = [];
332
+ readonly scripts_update: IComponent[] = [];
333
+ readonly scripts_lateUpdate: IComponent[] = [];
334
+ readonly scripts_onBeforeRender: IComponent[] = [];
335
+ readonly scripts_onAfterRender: IComponent[] = [];
336
+ readonly scripts_WithCorroutines: IComponent[] = [];
337
+ readonly scripts_immersive_vr: INeedleXRSessionEventReceiver[] = [];
338
+ readonly scripts_immersive_ar: INeedleXRSessionEventReceiver[] = [];
339
+ readonly coroutines: { [FrameEvent: number]: Array<CoroutineData> } = {}
340
+
341
+ /** callbacks called once after the context has been created */
342
+ readonly post_setup_callbacks: Function[] = [];
343
+ /** called every frame at the beginning of the frame (after component start events and before earlyUpdate) */
344
+ readonly pre_update_callbacks: Function[] = [];
345
+ /** called every frame before rendering (after all component events) */
346
+ readonly pre_render_callbacks: Array<(frame: XRFrame | null) => void> = [];
347
+ /** called every frame after rendering (after all component events) */
348
+ readonly post_render_callbacks: Function[] = [];
349
+
350
+ /** called every frame befroe update (this list is emptied every frame) */
351
+ readonly pre_update_oneshot_callbacks: Function[] = [];
352
+
353
+ readonly new_scripts: IComponent[] = [];
354
+ readonly new_script_start: IComponent[] = [];
355
+ readonly new_scripts_pre_setup_callbacks: Function[] = [];
356
+ readonly new_scripts_post_setup_callbacks: Function[] = [];
357
+ readonly new_scripts_xr: INeedleXRSessionEventReceiver[] = [];
358
+
359
+ /** The main camera component of the scene - this camera is used for rendering */
360
+ mainCameraComponent: ICamera | undefined = undefined;
361
+
362
+ /** The main camera of the scene - this camera is used for rendering */
363
+ get mainCamera(): Camera {
364
+ if (this._mainCamera) {
365
+ return this._mainCamera;
366
+ }
367
+ if (this.mainCameraComponent) {
368
+ const cam = this.mainCameraComponent as ICamera;
369
+ if (!cam.threeCamera)
370
+ cam.buildCamera();
371
+ return cam.threeCamera;
372
+ }
373
+ if (!this._fallbackCamera) {
374
+ this._fallbackCamera = new PerspectiveCamera(75, this.domWidth / this.domHeight, 0.1, 1000);
375
+ }
376
+ return this._fallbackCamera;
377
+ }
378
+ /** Set the main camera of the scene. If set to null the camera of the {@link mainCameraComponent} will be used - this camera is used for rendering */
379
+ set mainCamera(cam: Camera | null) {
380
+ this._mainCamera = cam;
381
+ }
382
+ private _mainCamera: Camera | null = null;
383
+ private _fallbackCamera: PerspectiveCamera | null = null;
384
+
385
+ application: Application;
386
+ /** access animation mixer used by components in the scene */
387
+ animations: AnimationsRegistry;
388
+ /** access timings (current frame number, deltaTime, timeScale, ...) */
389
+ time: Time;
390
+ input: Input;
391
+ /** access physics related methods (e.g. raycasting). To access the phyiscs engine use `context.physics.engine` */
392
+ physics: Physics;
393
+ /** access networking methods (use it to send or listen to messages or join a networking backend) */
394
+ connection: NetworkConnection;
395
+ /**
396
+ * @deprecated AssetDataBase is deprecated
397
+ */
398
+ assets: AssetDatabase;
399
+ mainLight: ILight | null = null;
400
+ /** @deprecated Use sceneLighting */
401
+ get rendererData() { return this.sceneLighting }
402
+ sceneLighting: SceneLighting;
403
+ addressables: Addressables;
404
+ lightmaps: ILightDataRegistry;
405
+ players: PlayerViewManager;
406
+ readonly lodsManager: LODsManager;
407
+ readonly menu: NeedleMenu;
408
+
409
+ get isCreated() { return this._isCreated; }
410
+
411
+ private _needsUpdateSize: boolean = false;
412
+ private _isCreated: boolean = false;
413
+ private _isCreating: boolean = false;
414
+ private _isVisible: boolean = false;
415
+
416
+ private _stats = stats ? new Stats.default() : null;
417
+
418
+ constructor(args?: ContextArgs) {
419
+ this.name = args?.name || "";
420
+ this.alias = args?.alias;
421
+ this.domElement = args?.domElement || document.body;
422
+ this.hash = args?.hash;
423
+
424
+ if (args?.renderer) {
425
+ this.renderer = args.renderer;
426
+ this.isManagedExternally = true;
427
+ }
428
+ if (args?.runInBackground !== undefined) this.runInBackground = args.runInBackground;
429
+ if (args?.scene) this.scene = args.scene;
430
+ else this.scene = new Scene();
431
+ if (args?.camera) this._mainCamera = args.camera;
432
+
433
+ this.application = new Application(this);
434
+ this.time = new Time();
435
+ this.input = new Input(this);
436
+ this.physics = new Physics(this);
437
+ this.connection = new NetworkConnection(this);
438
+ // eslint-disable-next-line deprecation/deprecation
439
+ this.assets = new AssetDatabase();
440
+ this.sceneLighting = new SceneLighting(this);
441
+ this.addressables = new Addressables(this);
442
+ this.lightmaps = new LightDataRegistry(this);
443
+ this.players = new PlayerViewManager(this);
444
+ this.menu = new NeedleMenu(this);
445
+ this.lodsManager = new LODsManager(this);
446
+ this.animations = new AnimationsRegistry(this);
447
+
448
+
449
+ const resizeCallback = () => this._needsUpdateSize = true;
450
+ window.addEventListener('resize', resizeCallback);
451
+ this._disposeCallbacks.push(() => window.removeEventListener('resize', resizeCallback));
452
+
453
+ const resizeObserver = new ResizeObserver(_ => this._needsUpdateSize = true);
454
+ resizeObserver.observe(this.domElement);
455
+ this._disposeCallbacks.push(() => resizeObserver.disconnect());
456
+
457
+ this._intersectionObserver = new IntersectionObserver(entries => {
458
+ this._isVisible = entries[0].isIntersecting;
459
+ });
460
+ this._disposeCallbacks.push(() => this._intersectionObserver?.disconnect());
461
+
462
+ ContextRegistry.register(this);
463
+ }
464
+
465
+ /** calling this function will dispose the current renderer and create a new one */
466
+ createNewRenderer(params?: WebGLRendererParameters) {
467
+ this.renderer?.dispose();
468
+
469
+ params = { ...Context.DefaultWebGLRendererParameters, ...params };
470
+ if (!params.canvas) {
471
+ // get canvas already configured in the Needle Engine Web Component
472
+ const canvas = this.domElement?.shadowRoot?.querySelector("canvas");
473
+ if (canvas) {
474
+ params.canvas = canvas;
475
+ if (debug) {
476
+ console.log("Using canvas from shadow root", canvas);
477
+ }
478
+ }
479
+ }
480
+ if (debug) console.log("Using Renderer Parameters:", params, this.domElement)
481
+
482
+ this.renderer = new WebGLRenderer(params);
483
+
484
+ this.renderer.debug.checkShaderErrors = isDevEnvironment() || getParam("checkshadererrors") === true;
485
+
486
+ // some tonemapping other than "NONE" is required for adjusting exposure with EXR environments
487
+ this.renderer.toneMappingExposure = 1; // range [0...inf] instead of the usual -15..15
488
+ this.renderer.toneMapping = NoToneMapping; // could also set to LinearToneMapping, ACESFilmicToneMapping
489
+
490
+ this.renderer.setClearColor(new Color('lightgrey'), 0);
491
+ // // @ts-ignore
492
+ // this.renderer.alpha = false;
493
+ this.renderer.shadowMap.enabled = true;
494
+ this.renderer.shadowMap.type = PCFSoftShadowMap;
495
+ this.renderer.setSize(this.domWidth, this.domHeight);
496
+ this.renderer.outputColorSpace = SRGBColorSpace;
497
+
498
+ // Injecting the core nodes library here, like WebGPURenderer backends do
499
+ //@ts-ignore
500
+ this.renderer.nodes = {
501
+ library: new BasicNodeLibrary(),
502
+ modelViewMatrix: null,
503
+ modelNormalViewMatrix: null,
504
+ };
505
+ // this.renderer.toneMapping = AgXToneMapping;
506
+ this.lodsManager.setRenderer(this.renderer);
507
+
508
+ this.input.bindEvents();
509
+ }
510
+
511
+
512
+ private _intersectionObserver: IntersectionObserver | null = null;
513
+ private internalOnUpdateVisible() {
514
+ this._intersectionObserver?.disconnect();
515
+ this._intersectionObserver?.observe(this.domElement);
516
+ }
517
+
518
+ private _disposeCallbacks: Function[] = [];
519
+
520
+
521
+ /** will request a renderer size update the next render call (will call updateSize the next update) */
522
+ requestSizeUpdate() { this._needsUpdateSize = true; }
523
+
524
+ /** Clamps the renderer max resolution. If undefined the max resolution is not clamped. Default is undefined */
525
+ maxRenderResolution?: Vec2;
526
+
527
+ /** Control the renderer devicePixelRatio.
528
+ * **Options**
529
+ * - `auto` - Needle Engine automatically sets the pixel ratio to the current window.devicePixelRatio.
530
+ * - `manual` - Needle Engine will not change the renderer pixel ratio. You can set it manually.
531
+ * - `number` - Needle Engine will set the pixel ratio to the given number. The change will be applied to the renderer and the composer (if used) at the end of the current frame.
532
+ */
533
+ get devicePixelRatio() { return this._devicePixelRatio; }
534
+ set devicePixelRatio(val: "auto" | "manual" | number) {
535
+ if (val !== this._devicePixelRatio) {
536
+ this._devicePixelRatio = val;
537
+ this._needsUpdateSize = true;
538
+ }
539
+ }
540
+ private _devicePixelRatio: "auto" | "manual" | number = "auto";
541
+
542
+ /** update the renderer and canvas size */
543
+ updateSize(force: boolean = false) {
544
+ if (force || (!this.isManagedExternally && this.renderer.xr?.isPresenting === false)) {
545
+ this._needsUpdateSize = false;
546
+ const scaleFactor = this.resolutionScaleFactor;
547
+ let width = this.domWidth * scaleFactor;
548
+ let height = this.domHeight * scaleFactor;
549
+ if (this.maxRenderResolution) {
550
+ this.maxRenderResolution.x = Math.max(1, this.maxRenderResolution.x);
551
+ width = Math.min(this.maxRenderResolution.x, width);
552
+ this.maxRenderResolution.y = Math.max(1, this.maxRenderResolution.y);
553
+ height = Math.min(this.maxRenderResolution.y, height);
554
+ }
555
+ const camera = this.mainCamera as PerspectiveCamera;
556
+ this.updateAspect(camera);
557
+ this.renderer.setSize(width, height, true);
558
+ // avoid setting pixel values here since this can cause pingpong updates
559
+ // e.g. when system scale is set to 125%
560
+ // https://github.com/needle-tools/needle-engine-support/issues/69
561
+ this.renderer.domElement.style.width = "100%";
562
+ this.renderer.domElement.style.height = "100%";
563
+
564
+ const devicePixelRatio = typeof this.devicePixelRatio === "number"
565
+ ? this.devicePixelRatio
566
+ : this.devicePixelRatio === "auto"
567
+ ? window.devicePixelRatio
568
+ : undefined;
569
+ if (devicePixelRatio !== undefined) {
570
+ this.renderer.setPixelRatio(devicePixelRatio);
571
+ }
572
+
573
+ if (this.composer) {
574
+ this.composer.setSize?.call(this.composer, width, height);
575
+ if (devicePixelRatio !== undefined && "setPixelRatio" in this.composer && typeof this.composer.setPixelRatio === "function")
576
+ this.composer.setPixelRatio?.call(this.composer, window.devicePixelRatio);
577
+ }
578
+ }
579
+ }
580
+
581
+ updateAspect(camera: PerspectiveCamera | OrthographicCamera, width?: number, height?: number) {
582
+ if (!camera) return;
583
+ if (width === undefined)
584
+ width = this.domWidth;
585
+ if (height === undefined)
586
+ height = this.domHeight;
587
+ const aspectRatio = width / height;
588
+ if ((camera as PerspectiveCamera).isPerspectiveCamera) {
589
+ const cam = camera as PerspectiveCamera;
590
+ const pa = cam.aspect;
591
+ cam.aspect = aspectRatio;
592
+ if (pa !== cam.aspect)
593
+ camera.updateProjectionMatrix();
594
+ }
595
+ else if ((camera as OrthographicCamera).isOrthographicCamera) {
596
+ const cam = camera as OrthographicCamera;
597
+ // Maintain the camera's current vertical size (top - bottom)
598
+ const verticalSize = cam.top - cam.bottom;
599
+ // Calculate new horizontal size based on aspect ratio
600
+ const horizontalSize = verticalSize * aspectRatio;
601
+ // Update camera bounds while maintaining center position
602
+ const halfWidth = horizontalSize / 2;
603
+ const halfHeight = verticalSize / 2;
604
+ if (cam.left != -halfWidth || cam.top != halfHeight) {
605
+ cam.left = -halfWidth;
606
+ cam.right = halfWidth;
607
+ cam.top = halfHeight;
608
+ cam.bottom = -halfHeight;
609
+ camera.updateProjectionMatrix();
610
+ }
611
+ }
612
+ }
613
+
614
+ /** This will recreate the whole needle engine context and dispose the whole scene content
615
+ * All content will be reloaded (loading times might be faster due to browser caches)
616
+ * All scripts will be recreated */
617
+ recreate() {
618
+ this.clear();
619
+ this.create(this._originalCreationArgs);
620
+ }
621
+
622
+ private _originalCreationArgs?: ContextCreateArgs;
623
+
624
+ /** @deprecated use create. This method will be removed in a future version */
625
+ async onCreate(opts?: ContextCreateArgs) {
626
+ return this.create(opts);
627
+ }
628
+ async create(opts?: ContextCreateArgs) {
629
+ try {
630
+ this._isCreating = true;
631
+ if (opts !== this._originalCreationArgs)
632
+ this._originalCreationArgs = deepClone(opts);
633
+ window.addEventListener("unhandledrejection", this.onUnhandledRejection)
634
+ const res = await this.internalOnCreate(opts);
635
+ this._isCreated = res;
636
+ return res;
637
+ }
638
+ finally {
639
+ window.removeEventListener("unhandledrejection", this.onUnhandledRejection)
640
+ this._isCreating = false;
641
+ }
642
+ }
643
+
644
+ private onUnhandledRejection = (event: PromiseRejectionEvent) => {
645
+ this.onError(event.reason);
646
+ };
647
+
648
+ /** Dispatches an error */
649
+ private onError(error: string) {
650
+ this.domElement.dispatchEvent(new CustomEvent("error", { detail: error }));
651
+ }
652
+
653
+ /** Will destroy all scenes and objects in the scene
654
+ */
655
+ clear() {
656
+ ContextRegistry.dispatchCallback(ContextEvent.ContextClearing, this);
657
+ invokeLifecycleFunctions(this, ContextEvent.ContextClearing);
658
+ // NOTE: this does dispose the environment/background image too
659
+ // which is probably not desired if it is set via the skybox-image attribute
660
+ destroy(this.scene, true, true);
661
+ this.scene = new Scene();
662
+ this.addressables?.dispose();
663
+ this.lightmaps?.clear();
664
+ this.physics?.engine?.clearCaches();
665
+ this.lodsManager.disable();
666
+
667
+ if (!this.isManagedExternally) {
668
+ if (this.renderer) {
669
+ this.renderer.renderLists.dispose();
670
+ this.renderer.state.reset();
671
+ this.renderer.resetState();
672
+ }
673
+ }
674
+ // We do not want to clear the renderer here because when switching src we want to keep the last rendered frame in case the loading screen is not visible
675
+ // if a user wants to see the background they can still call setClearAlpha(0) and clear manually
676
+ ContextRegistry.dispatchCallback(ContextEvent.ContextCleared, this);
677
+ }
678
+
679
+ dispose() {
680
+ this.internalOnDestroy();
681
+ }
682
+
683
+ /**@deprecated use dispose() */
684
+ onDestroy() { this.internalOnDestroy(); }
685
+ private internalOnDestroy() {
686
+ Context.Current = this;
687
+ ContextRegistry.dispatchCallback(ContextEvent.ContextDestroying, this);
688
+ invokeLifecycleFunctions(this, ContextEvent.ContextDestroying);
689
+ this.clear();
690
+ this.renderer?.setAnimationLoop(null);
691
+ if (this.renderer) {
692
+ this.renderer.setClearAlpha(0);
693
+ this.renderer.clear();
694
+ if (!this.isManagedExternally) {
695
+ if (debug) console.log("Disposing renderer");
696
+ this.renderer.dispose();
697
+ }
698
+ }
699
+ this.scene = null!;
700
+ this.renderer = null!;
701
+ this.input.dispose();
702
+ this.menu.onDestroy();
703
+ this.animations.onDestroy();
704
+ for (const cb of this._disposeCallbacks) {
705
+ try {
706
+ cb();
707
+ }
708
+ catch (e) {
709
+ console.error("Error in on dispose callback:", e, cb);
710
+ }
711
+ }
712
+ if (this.domElement?.parentElement) {
713
+ this.domElement.parentElement.removeChild(this.domElement);
714
+ }
715
+ this._isCreated = false;
716
+ ContextRegistry.dispatchCallback(ContextEvent.ContextDestroyed, this);
717
+ invokeLifecycleFunctions(this, ContextEvent.ContextDestroyed);
718
+ ContextRegistry.unregister(this);
719
+ if (Context.Current === this) {
720
+ //@ts-ignore
721
+ Context.Current = null;
722
+ }
723
+ }
724
+
725
+ registerCoroutineUpdate(script: IComponent, coroutine: Generator, evt: FrameEvent): Generator {
726
+ if (typeof coroutine?.next !== "function") {
727
+ console.error("Registered invalid coroutine function from " + script.name + "\nCoroutine functions must be generators: \"*myCoroutine() {...}\"\nStart a coroutine from a component by calling \"this.startCoroutine(myCoroutine())\"")
728
+ return coroutine;
729
+ }
730
+ if (!this.coroutines[evt]) this.coroutines[evt] = [];
731
+ this.coroutines[evt].push({ comp: script, main: coroutine });
732
+ return coroutine;
733
+ }
734
+
735
+ unregisterCoroutineUpdate(coroutine: Generator, evt: FrameEvent): void {
736
+ if (!this.coroutines[evt]) return;
737
+ const idx = this.coroutines[evt].findIndex(c => c.main === coroutine);
738
+ if (idx >= 0) this.coroutines[evt].splice(idx, 1);
739
+ }
740
+
741
+ stopAllCoroutinesFrom(script: IComponent) {
742
+ for (const evt in this.coroutines) {
743
+ const rout: CoroutineData[] = this.coroutines[evt];
744
+ for (let i = rout.length - 1; i >= 0; i--) {
745
+ const r = rout[i];
746
+ if (r.comp === script) {
747
+ rout.splice(i, 1);
748
+ }
749
+ }
750
+ }
751
+ }
752
+
753
+ private _cameraStack: ICamera[] = [];
754
+
755
+ setCurrentCamera(cam: ICamera) {
756
+ if (!cam) return;
757
+ if (!cam.threeCamera) cam.buildCamera(); // < to build camera
758
+ if (!cam.threeCamera) {
759
+ console.warn("Camera component is missing camera", cam)
760
+ return;
761
+ }
762
+ const index = this._cameraStack.indexOf(cam);
763
+ if (index >= 0) this._cameraStack.splice(index, 1);
764
+ this._cameraStack.push(cam);
765
+ this.mainCameraComponent = cam;
766
+ const camera = cam.threeCamera as PerspectiveCamera;
767
+ if (camera.isPerspectiveCamera)
768
+ this.updateAspect(camera);
769
+ (this.mainCameraComponent as ICamera)?.applyClearFlagsIfIsActiveCamera();
770
+ }
771
+
772
+ removeCamera(cam?: ICamera | null) {
773
+ if (!cam) return;
774
+ const index = this._cameraStack.indexOf(cam);
775
+ if (index >= 0) this._cameraStack.splice(index, 1);
776
+
777
+ if (this.mainCameraComponent === cam) {
778
+ this.mainCameraComponent = undefined;
779
+
780
+ if (this._cameraStack.length > 0) {
781
+ const last = this._cameraStack[this._cameraStack.length - 1];
782
+ this.setCurrentCamera(last);
783
+ }
784
+ }
785
+ }
786
+
787
+
788
+
789
+ private _onBeforeRenderListeners = new Map<string, OnRenderCallback[]>();
790
+ private _onAfterRenderListeners = new Map<string, OnRenderCallback[]>();
791
+
792
+ /** use this to subscribe to onBeforeRender events on threejs objects */
793
+ addBeforeRenderListener(target: Object3D, callback: OnRenderCallback) {
794
+ if (!this._onBeforeRenderListeners.has(target.uuid)) {
795
+ this._onBeforeRenderListeners.set(target.uuid, []);
796
+ target.onBeforeRender = this._createRenderCallbackWrapper(target, this._onBeforeRenderListeners);
797
+ }
798
+ this._onBeforeRenderListeners.get(target.uuid)!.push(callback);
799
+ }
800
+ removeBeforeRenderListener(target: Object3D, callback: OnRenderCallback) {
801
+ if (this._onBeforeRenderListeners.has(target.uuid)) {
802
+ const arr = this._onBeforeRenderListeners.get(target.uuid)!;
803
+ const idx = arr.indexOf(callback);
804
+ if (idx >= 0) arr.splice(idx, 1);
805
+ }
806
+ }
807
+
808
+ /** use this to subscribe to onAfterRender events on threejs objects */
809
+ addAfterRenderListener(target: Object3D, callback: OnRenderCallback) {
810
+ if (!this._onAfterRenderListeners.has(target.uuid)) {
811
+ this._onAfterRenderListeners.set(target.uuid, []);
812
+ target.onAfterRender = this._createRenderCallbackWrapper(target, this._onAfterRenderListeners);
813
+ }
814
+ this._onAfterRenderListeners.get(target.uuid)?.push(callback);
815
+ }
816
+ removeAfterRenderListener(target: Object3D, callback: OnRenderCallback) {
817
+ if (this._onAfterRenderListeners.has(target.uuid)) {
818
+ const arr = this._onAfterRenderListeners.get(target.uuid)!;
819
+ const idx = arr.indexOf(callback);
820
+ if (idx >= 0) arr.splice(idx, 1);
821
+ }
822
+ }
823
+
824
+
825
+ private _createRenderCallbackWrapper(target: Object3D, array: Map<string, OnRenderCallback[]>): OnRenderCallback {
826
+ return (renderer, scene, camera, geometry, material, group) => {
827
+ const arr = array.get(target.uuid);
828
+ if (!arr) return;
829
+ for (let i = 0; i < arr.length; i++) {
830
+ const fn = arr[i];
831
+ fn(renderer, scene, camera, geometry, material, group);
832
+ }
833
+ }
834
+ }
835
+
836
+
837
+
838
+ private _requireDepthTexture: boolean = false;
839
+ private _requireColorTexture: boolean = false;
840
+ private _renderTarget?: WebGLRenderTarget;
841
+ private _isRendering: boolean = false;
842
+
843
+ get isRendering() { return this._isRendering; }
844
+
845
+ setRequireDepth(val: boolean) {
846
+ this._requireDepthTexture = val;
847
+ }
848
+
849
+ setRequireColor(val: boolean) {
850
+ this._requireColorTexture = val;
851
+ }
852
+
853
+ get depthTexture(): DepthTexture | null {
854
+ return this._renderTarget?.depthTexture || null;
855
+ }
856
+
857
+ get opaqueColorTexture(): Texture | null {
858
+ return this._renderTarget?.texture || null;
859
+ }
860
+
861
+ /** returns true if the dom element is visible on screen */
862
+ get isVisibleToUser() {
863
+ if (this.isInXR) return true;
864
+ if (!this._isVisible) return false;
865
+ const style = getComputedStyle(this.domElement);
866
+ return style.visibility !== "hidden" && style.display !== "none" && style.opacity !== "0";
867
+ }
868
+
869
+
870
+ private _createId: number = 0;
871
+ private async internalOnCreate(opts?: ContextCreateArgs): Promise<boolean> {
872
+ const createId = ++this._createId;
873
+
874
+ if (debug) console.log("Creating context", this.name, opts);
875
+
876
+ // wait for async imported dependencies to be loaded
877
+ // see https://linear.app/needle/issue/NE-4445
878
+ const dependenciesReady = globalThis["needle:dependencies:ready"];
879
+ if (dependenciesReady instanceof Promise) {
880
+ if (debug) console.log("Waiting for dependencies to be ready");
881
+ await dependenciesReady
882
+ .catch(err => {
883
+ if (debug || isDevEnvironment()) {
884
+ showBalloonError("Needle Engine dependencies failed to load. Please check the console for more details");
885
+ const printedError = false;
886
+ if (err instanceof ReferenceError) {
887
+ let offendingComponentName = "YourComponentName";
888
+ const offendingComponentStartIndex = err.message.indexOf("'");
889
+ if (offendingComponentStartIndex > 0) {
890
+ const offendingComponentEndIndex = err.message.indexOf("'", offendingComponentStartIndex + 1);
891
+ if (offendingComponentEndIndex > 0) {
892
+ const name = err.message.substring(offendingComponentStartIndex + 1, offendingComponentEndIndex);
893
+ if (name.length > 3) offendingComponentName = name;
894
+ }
895
+ }
896
+ console.error(`Needle Engine dependencies failed to load:\n\n# Make sure you don't have circular imports in your scripts!\n\nPossible solutions: \n→ Replace @serializable(${offendingComponentName}) in your script with @serializable(Behaviour)\n→ If you only need type information try importing the type only, e.g: import { type ${offendingComponentName} }\n\n---`, err)
897
+ return;
898
+ }
899
+ if (!printedError) {
900
+ console.error("Needle Engine dependencies failed to load", err);
901
+ }
902
+ }
903
+ })
904
+ .then(() => {
905
+ if (debug) console.log("Needle Engine dependencies are ready");
906
+ });
907
+ }
908
+
909
+ this.clear();
910
+ // stop the animation loop if its running during creation
911
+ // since we do not want to start enabling scripts etc before they are deserialized
912
+ if (this.isManagedExternally === false) {
913
+ this.createNewRenderer();
914
+ this.renderer?.setAnimationLoop(null);
915
+ }
916
+
917
+ await delay(1);
918
+
919
+ Context.Current = this;
920
+ await ContextRegistry.dispatchCallback(ContextEvent.ContextCreationStart, this);
921
+
922
+ // load and create scene
923
+ let prepare_succeeded = true;
924
+ let loadedFiles!: Array<LoadedModel | null>;
925
+ try {
926
+ Context.Current = this;
927
+ if (opts) {
928
+ loadedFiles = await this.internalLoadInitialContent(createId, opts);
929
+ }
930
+ else loadedFiles = [];
931
+ }
932
+ catch (err) {
933
+ console.error(err);
934
+ prepare_succeeded = false;
935
+ }
936
+ if (!prepare_succeeded) {
937
+ this.onError("Failed to load initial content");
938
+ return false;
939
+ }
940
+ if (createId !== this._createId || opts?.abortSignal?.aborted) {
941
+ return false;
942
+ }
943
+
944
+ this.internalOnUpdateVisible();
945
+
946
+ if (!this.renderer) {
947
+ if (debug) console.warn("Context has no renderer (perhaps it was disconnected?", this.domElement.isConnected);
948
+ return false;
949
+ }
950
+
951
+ if (!this.isManagedExternally && !this.domElement.shadowRoot) {
952
+ this.domElement.prepend(this.renderer.domElement);
953
+ }
954
+
955
+ Context.Current = this;
956
+
957
+ // TODO: we could configure if we need physics
958
+ // await this.physics.engine?.initialize();
959
+
960
+ // Setup
961
+ Context.Current = this;
962
+ for (let i = 0; i < this.new_scripts.length; i++) {
963
+ const script = this.new_scripts[i];
964
+ if (script.gameObject !== undefined && script.gameObject !== null) {
965
+ if (script.gameObject.userData === undefined) script.gameObject.userData = {};
966
+ if (script.gameObject.userData.components === undefined) script.gameObject.userData.components = [];
967
+ const arr = script.gameObject.userData.components;
968
+ if (!arr.includes(script)) arr.push(script);
969
+ }
970
+ // if (script.gameObject && !this.raycastTargets.includes(script.gameObject)) {
971
+ // this.raycastTargets.push(script.gameObject);
972
+ // }
973
+ }
974
+
975
+ // const context = new SerializationContext(this.scene);
976
+ // for (let i = 0; i < this.new_scripts.length; i++) {
977
+ // const script = this.new_scripts[i];
978
+ // const ser = script as unknown as ISerializable;
979
+ // if (ser.$serializedTypes === undefined) continue;
980
+ // context.context = this;
981
+ // context.object = script.gameObject;
982
+ // deserializeObject(ser, script, context);
983
+ // }
984
+
985
+ // resolve post setup callbacks (things that rely on threejs objects having references to components)
986
+ if (this.post_setup_callbacks) {
987
+ for (let i = 0; i < this.post_setup_callbacks.length; i++) {
988
+ Context.Current = this;
989
+ await this.post_setup_callbacks[i](this);
990
+ }
991
+ }
992
+
993
+ if (!this._mainCamera) {
994
+ Context.Current = this;
995
+ let camera: ICamera | null = null;
996
+ foreachComponent(this.scene, comp => {
997
+ const cam = comp as ICamera;
998
+ if (cam?.isCamera) {
999
+ looputils.updateActiveInHierarchyWithoutEventCall(cam.gameObject);
1000
+ if (!cam.activeAndEnabled) return undefined;
1001
+ if (cam.tag === "MainCamera") {
1002
+ camera = cam;
1003
+ return true;
1004
+ }
1005
+ else camera = cam;
1006
+ }
1007
+ return undefined;
1008
+ });
1009
+ if (camera) {
1010
+ this.setCurrentCamera(camera);
1011
+ }
1012
+ else {
1013
+ const res = ContextRegistry.dispatchCallback(ContextEvent.MissingCamera, this, { files: loadedFiles });
1014
+ if (!res && !this.mainCamera && !this.isManagedExternally)
1015
+ console.warn("Missing camera in main scene", this);
1016
+ }
1017
+ }
1018
+
1019
+ this.input.bindEvents();
1020
+
1021
+ Context.Current = this;
1022
+ looputils.processNewScripts(this);
1023
+
1024
+ // We have to step once so that colliders that have been created in onEnable can be raycasted in start
1025
+ if (this.physics.engine) {
1026
+ this.physics.engine?.step(0);
1027
+ this.physics.engine?.postStep();
1028
+ }
1029
+
1030
+ // const mainCam = this.mainCameraComponent as Camera;
1031
+ // if (mainCam) {
1032
+ // mainCam.applyClearFlagsIfIsActiveCamera();
1033
+ // }
1034
+
1035
+ if (!this.isManagedExternally && this.composer && this.mainCamera) {
1036
+ // TODO: import postprocessing async
1037
+ // const renderPass = new RenderPass(this.scene, this.mainCamera);
1038
+ // this.renderer.setSize(this.domWidth, this.domHeight);
1039
+ // this.composer.addPass(renderPass);
1040
+ // this.composer.setSize(this.domWidth, this.domHeight);
1041
+ }
1042
+
1043
+ this._needsUpdateSize = true;
1044
+
1045
+ if (this._stats) {
1046
+ this._stats.showPanel(0);
1047
+ this._stats.dom.style.position = "absolute"; // (default is fixed)
1048
+ this.domElement.shadowRoot?.appendChild(this._stats.dom);
1049
+ }
1050
+
1051
+ if (debug)
1052
+ logHierarchy(this.scene, true);
1053
+
1054
+ // If no target framerate was set we use the default
1055
+ if (this.targetFrameRate === undefined) {
1056
+ if (debug) console.warn("No target framerate set, using default", Context.DefaultTargetFrameRate);
1057
+ // the _defaultTargetFramerate is intentionally an object so it can be changed at any time if not explictly set by the user
1058
+ this.targetFrameRate = Context._defaultTargetFramerate;
1059
+ }
1060
+ else if (debug) console.log("Target framerate set to", this.targetFrameRate);
1061
+
1062
+ this._dispatchReadyAfterFrame = true;
1063
+ const res = ContextRegistry.dispatchCallback(ContextEvent.ContextCreated, this, { files: loadedFiles });
1064
+ if (res) {
1065
+ if ("internalSetLoadingMessage" in this.domElement && typeof this.domElement.internalSetLoadingMessage === "function")
1066
+ this.domElement?.internalSetLoadingMessage("finish loading");
1067
+ await res;
1068
+ }
1069
+ if (opts?.abortSignal?.aborted) {
1070
+ return false;
1071
+ }
1072
+ invokeLifecycleFunctions(this, ContextEvent.ContextCreated);
1073
+ if (debug) console.log("Context Created...", this.renderer, this.renderer.domElement)
1074
+
1075
+ this._isCreating = false;
1076
+ if (!this.isManagedExternally && !opts?.abortSignal?.aborted)
1077
+ this.restartRenderLoop();
1078
+ return true;
1079
+ }
1080
+
1081
+ private async internalLoadInitialContent(createId: number, args: ContextCreateArgs): Promise<Array<LoadedModel>> {
1082
+ const results = new Array<LoadedModel>();
1083
+ // early out if we dont have any files to load
1084
+ if (args.files.length === 0) return results;
1085
+
1086
+
1087
+ const files = [...args.files];
1088
+ const progressArg: LoadingProgressArgs = {
1089
+ name: "",
1090
+ progress: null!,
1091
+ index: 0,
1092
+ count: files.length
1093
+ }
1094
+
1095
+ const loader = getLoader();
1096
+ // this hash should be constant since it is used to initialize the UIDProvider per initially loaded scene
1097
+ const loadingHash = 0;
1098
+ for (let i = 0; i < files.length; i++) {
1099
+ if (args.abortSignal?.aborted) {
1100
+ if (debug) console.log("Aborting loading because of abort signal");
1101
+ break;
1102
+ }
1103
+ // abort loading if the create id has changed
1104
+ if (createId !== this._createId) {
1105
+ if (debug) console.log("Aborting loading because create id changed", createId, this._createId);
1106
+ break;
1107
+ }
1108
+ const file = files[i];
1109
+ args?.onLoadingStart?.call(this, i, file);
1110
+ if (debug) console.log("Context Load " + file);
1111
+ const res = await loader.loadSync(this, file, file, loadingHash, prog => {
1112
+ if (args.abortSignal?.aborted) return;
1113
+ progressArg.name = file;
1114
+ progressArg.progress = prog;
1115
+ progressArg.index = i;
1116
+ progressArg.count = files.length;
1117
+ args.onLoadingProgress?.call(this, progressArg);
1118
+ });
1119
+ args?.onLoadingFinished?.call(this, i, file, res ?? null);
1120
+ if (res) {
1121
+ results.push({
1122
+ src: file,
1123
+ file: res
1124
+ });
1125
+ }
1126
+ else {
1127
+ // a file could not be loaded
1128
+ console.warn("Could not load file: " + file);
1129
+ }
1130
+ }
1131
+
1132
+ // if the id was changed while still loading
1133
+ // then we want to cleanup/destroy previously loaded files
1134
+ if (createId !== this._createId || args.abortSignal?.aborted) {
1135
+ if (debug) console.log("Aborting loading because create id changed or abort signal was set", createId, this._createId);
1136
+ for (const res of results) {
1137
+ if (res && res.file) {
1138
+ for (const scene of res.file.scenes)
1139
+ destroy(scene, true, true);
1140
+ }
1141
+ }
1142
+ }
1143
+ // otherwise we want to add the loaded files to the current scene
1144
+ else {
1145
+ let anyModelFound = false;
1146
+ for (const res of results) {
1147
+ if (res && res.file) {
1148
+ // TODO: should we load all scenes in a glTF here?
1149
+ if (res.file.scene) {
1150
+ anyModelFound = true;
1151
+ this.scene.add(res.file.scene);
1152
+ }
1153
+ else {
1154
+ console.warn("No scene found in loaded file");
1155
+ }
1156
+ }
1157
+ }
1158
+ // If the loaded files do not contain ANY model
1159
+ // We then attempt to create a mesh from each material in the loaded files to visualize it
1160
+ // It's ok to do this at this point because we know the context has been cleared because the whole `src` attribute has been set
1161
+ if (!anyModelFound) {
1162
+ for (const res of results) {
1163
+ if (res && res.file && "parser" in res.file) {
1164
+ let y = 0;
1165
+ if (!Array.isArray(res.file.parser.json.materials)) continue;
1166
+ for (let i = 0; i < res.file.parser.json.materials.length; i++) {
1167
+ const mat = await res.file.parser.getDependency("material", i);
1168
+ const parent = new Object3D();
1169
+ parent.position.x = i * 1.1;
1170
+ parent.position.y = y;
1171
+ this.scene.add(parent);
1172
+ ObjectUtils.createPrimitive("ShaderBall", {
1173
+ parent,
1174
+ material: mat
1175
+ });
1176
+ }
1177
+ y += 1;
1178
+ }
1179
+ }
1180
+ }
1181
+ }
1182
+
1183
+ return results;
1184
+ }
1185
+
1186
+
1187
+ /** Sets the animation loop.
1188
+ * Can not be done while creating the context or when disposed
1189
+ **/
1190
+ public restartRenderLoop(): boolean {
1191
+ if (!this.renderer) {
1192
+ console.error("Can not start render loop without renderer");
1193
+ return false;
1194
+ }
1195
+ if (this._isCreating) {
1196
+ console.warn("Can not start render loop while creating context");
1197
+ return false;
1198
+ }
1199
+ this.renderer.setAnimationLoop((timestamp, frame: XRFrame | null) => {
1200
+ if (this.isManagedExternally) return;
1201
+ this.update(timestamp, frame)
1202
+ });
1203
+ return true;
1204
+ }
1205
+
1206
+ private _renderlooperrors = 0;
1207
+
1208
+ /** Performs a full update step including script callbacks, rendering (unless isManagedExternally is set to false) and post render callbacks */
1209
+ public update(timestamp: DOMHighResTimeStamp, frame?: XRFrame | null) {
1210
+ if (frame === undefined) frame = null;
1211
+ if (isDevEnvironment() || debug || looputils.hasNewScripts()) {
1212
+ try {
1213
+ //performance.mark('update.start');
1214
+ this.internalStep(timestamp, frame);
1215
+ this._renderlooperrors = 0;
1216
+ //performance.mark('update.end');
1217
+ //performance.measure('NE Frame', 'update.start', 'update.end');
1218
+ }
1219
+ catch (err) {
1220
+ this._renderlooperrors += 1;
1221
+ if ((isDevEnvironment() || debug) && (err instanceof Error || err instanceof TypeError))
1222
+ showBalloonMessage(`Caught unhandled exception during render-loop - see console for details.`, LogType.Error);
1223
+ console.error("Frame #" + this.time.frame + "\n", err);
1224
+ if (this._renderlooperrors >= 3) {
1225
+ console.warn("Stopping render loop due to error")
1226
+ this.renderer.setAnimationLoop(null);
1227
+ }
1228
+ this.domElement.dispatchEvent(new CustomEvent("error", { detail: err }));
1229
+ }
1230
+ }
1231
+ else {
1232
+ this.internalStep(timestamp, frame);
1233
+ }
1234
+ }
1235
+
1236
+ /** Call to **manually** perform physics steps.
1237
+ * By default the context uses the `physicsSteps` property to perform steps during the update loop
1238
+ * If you just want to increase the accuracy of physics you can instead set the `physicsSteps` property to a higher value
1239
+ * */
1240
+ public updatePhysics(steps: number) {
1241
+ this.internalUpdatePhysics(steps);
1242
+ }
1243
+
1244
+ private _lastTimestamp = 0;
1245
+ private _accumulatedTime = 0;
1246
+ private _dispatchReadyAfterFrame = false;
1247
+
1248
+ // TODO: we need to skip after render callbacks if the render loop is managed externally. When changing this we also need to to update the r3f sample
1249
+ private internalStep(timestamp: DOMHighResTimeStamp, frame: XRFrame | null) {
1250
+ if (this.internalOnBeforeRender(timestamp, frame) === false) return;
1251
+ this.internalOnRender();
1252
+ this.internalOnAfterRender();
1253
+ }
1254
+
1255
+ private internalOnBeforeRender(timestamp: DOMHighResTimeStamp, frame: XRFrame | null) {
1256
+
1257
+ // If we don't auto reset we get wrong stats in WebXR. AutoReset was turned off to support custom blits and count them too
1258
+ this.renderer.info.autoReset = true;
1259
+
1260
+
1261
+ const sessionStarted = frame !== null && this._xrFrame === null;
1262
+ this._xrFrame = frame;
1263
+ if (sessionStarted) {
1264
+ this.domElement.dispatchEvent(new CustomEvent("xr-session-started", { detail: { context: this, session: this.xrSession, frame: frame } }));
1265
+ }
1266
+
1267
+ this._currentFrameEvent = FrameEvent.Undefined;
1268
+
1269
+ if (this.isManagedExternally === false && this.isInXR === false && this.targetFrameRate !== undefined) {
1270
+ if (this._lastTimestamp === 0) this._lastTimestamp = timestamp;
1271
+ this._accumulatedTime += (timestamp - this._lastTimestamp) / 1000;
1272
+ this._lastTimestamp = timestamp;
1273
+ let targetFrameRate = this.targetFrameRate;
1274
+ if (typeof targetFrameRate === "object") targetFrameRate = targetFrameRate.value!;
1275
+ // if(debug) console.log(this._accumulatedTime, (1 / (targetFrameRate)))
1276
+ if (this._accumulatedTime < (1 / (targetFrameRate + 1))) {
1277
+ return false;
1278
+ }
1279
+ this._accumulatedTime = 0;
1280
+ }
1281
+
1282
+ this._stats?.begin();
1283
+
1284
+ Context.Current = this;
1285
+ if (this.onHandlePaused()) return false;
1286
+
1287
+ Context.Current = this;
1288
+ this.time.update();
1289
+ if (debugframerate)
1290
+ console.log("FPS", (this.time.smoothedFps).toFixed(0));
1291
+
1292
+
1293
+ looputils.processNewScripts(this);
1294
+ looputils.updateIsActive(this.scene);
1295
+ looputils.processStart(this);
1296
+ invokeLifecycleFunctions(this, FrameEvent.Start);
1297
+
1298
+ while (this._cameraStack.length > 0 && (!this.mainCameraComponent || this.mainCameraComponent.destroyed)) {
1299
+ this._cameraStack.splice(this._cameraStack.length - 1, 1);
1300
+ const last = this._cameraStack[this._cameraStack.length - 1];
1301
+ this.setCurrentCamera(last);
1302
+ }
1303
+
1304
+ if (this.pre_update_oneshot_callbacks) {
1305
+ for (const i in this.pre_update_oneshot_callbacks) {
1306
+ this.pre_update_oneshot_callbacks[i]();
1307
+ }
1308
+ this.pre_update_oneshot_callbacks.length = 0;
1309
+ }
1310
+
1311
+ if (this.pre_update_callbacks) {
1312
+ for (const i in this.pre_update_callbacks) {
1313
+ this.pre_update_callbacks[i]();
1314
+ }
1315
+ }
1316
+
1317
+ this._currentFrameEvent = FrameEvent.EarlyUpdate;
1318
+
1319
+ for (let i = 0; i < this.scripts_earlyUpdate.length; i++) {
1320
+ const script = this.scripts_earlyUpdate[i];
1321
+ if (!script.activeAndEnabled) continue;
1322
+ if (script.earlyUpdate !== undefined) {
1323
+ Context.Current = this;
1324
+ script.earlyUpdate();
1325
+ }
1326
+ }
1327
+ this.executeCoroutines(FrameEvent.EarlyUpdate);
1328
+ invokeLifecycleFunctions(this, FrameEvent.EarlyUpdate);
1329
+ if (this.onHandlePaused()) return false;
1330
+
1331
+ this._currentFrameEvent = FrameEvent.Update;
1332
+
1333
+ for (let i = 0; i < this.scripts_update.length; i++) {
1334
+ const script = this.scripts_update[i];
1335
+ if (!script.activeAndEnabled) continue;
1336
+ if (script.update !== undefined) {
1337
+ Context.Current = this;
1338
+ script.update();
1339
+ }
1340
+ }
1341
+ this.executeCoroutines(FrameEvent.Update);
1342
+ invokeLifecycleFunctions(this, FrameEvent.Update);
1343
+ if (this.onHandlePaused()) return false;
1344
+
1345
+ this._currentFrameEvent = FrameEvent.LateUpdate;
1346
+
1347
+ for (let i = 0; i < this.scripts_lateUpdate.length; i++) {
1348
+ const script = this.scripts_lateUpdate[i];
1349
+ if (!script.activeAndEnabled) continue;
1350
+ if (script.lateUpdate !== undefined) {
1351
+ Context.Current = this;
1352
+ script.lateUpdate();
1353
+ }
1354
+ }
1355
+
1356
+ // this.mainLight = null;
1357
+ this.executeCoroutines(FrameEvent.LateUpdate);
1358
+ invokeLifecycleFunctions(this, FrameEvent.LateUpdate);
1359
+ if (this.onHandlePaused()) return false;
1360
+
1361
+ if (this.physicsSteps === undefined) {
1362
+ this.physicsSteps = 1;
1363
+ }
1364
+ if (this.physics.engine && this.physicsSteps > 0) {
1365
+ this.internalUpdatePhysics(this.physicsSteps);
1366
+ }
1367
+
1368
+ if (this.onHandlePaused()) return false;
1369
+
1370
+ if (this.isVisibleToUser || this.runInBackground) {
1371
+
1372
+ this._currentFrameEvent = FrameEvent.OnBeforeRender;
1373
+
1374
+ // should we move these callbacks in the regular three onBeforeRender events?
1375
+ for (let i = 0; i < this.scripts_onBeforeRender.length; i++) {
1376
+ const script = this.scripts_onBeforeRender[i];
1377
+ if (!script.activeAndEnabled) continue;
1378
+ // if(script.isActiveAndEnabled === false) continue;
1379
+ if (script.onBeforeRender !== undefined) {
1380
+ Context.Current = this;
1381
+ script.onBeforeRender(frame);
1382
+ }
1383
+ }
1384
+
1385
+ this.executeCoroutines(FrameEvent.OnBeforeRender);
1386
+ invokeLifecycleFunctions(this, FrameEvent.OnBeforeRender);
1387
+
1388
+ if (this._needsUpdateSize)
1389
+ this.updateSize();
1390
+
1391
+ if (this.pre_render_callbacks) {
1392
+ for (const i in this.pre_render_callbacks) {
1393
+ this.pre_render_callbacks[i](frame);
1394
+ }
1395
+ }
1396
+
1397
+ }
1398
+
1399
+ return true;
1400
+ }
1401
+
1402
+ private internalUpdatePhysics(steps: number) {
1403
+ if (!this.physics.engine) return false;
1404
+ const physicsSteps = steps;
1405
+ const dt = this.time.deltaTime / physicsSteps;
1406
+ for (let i = 0; i < physicsSteps; i++) {
1407
+ this._currentFrameEvent = FrameEvent.PrePhysicsStep;
1408
+ this.executeCoroutines(FrameEvent.PrePhysicsStep);
1409
+ this.physics.engine.step(dt);
1410
+ this._currentFrameEvent = FrameEvent.PostPhysicsStep;
1411
+ this.executeCoroutines(FrameEvent.PostPhysicsStep);
1412
+ }
1413
+ this.physics.engine.postStep();
1414
+ return true;
1415
+ }
1416
+
1417
+ private internalOnRender() {
1418
+ if (!this.isManagedExternally) {
1419
+ // when loading assets we compile them async after GLTFLoader is done
1420
+ // but as a fallback we still register them (if e.g. there's no camera for compile async)
1421
+ looputils.runPrewarm(this);
1422
+ this._currentFrameEvent = FrameEvent.Undefined;
1423
+ nodeFrame.update();
1424
+ this.renderNow();
1425
+ this._currentFrameEvent = FrameEvent.OnAfterRender;
1426
+ }
1427
+ }
1428
+
1429
+ private internalOnAfterRender() {
1430
+ if (this.isVisibleToUser || this.runInBackground) {
1431
+ for (let i = 0; i < this.scripts_onAfterRender.length; i++) {
1432
+ const script = this.scripts_onAfterRender[i];
1433
+ if (!script.activeAndEnabled) continue;
1434
+ if (script.onAfterRender !== undefined) {
1435
+ Context.Current = this;
1436
+ script.onAfterRender();
1437
+ }
1438
+ }
1439
+
1440
+ this.executeCoroutines(FrameEvent.OnAfterRender);
1441
+ invokeLifecycleFunctions(this, FrameEvent.OnAfterRender);
1442
+
1443
+ if (this.post_render_callbacks) {
1444
+ for (const i in this.post_render_callbacks) {
1445
+ this.post_render_callbacks[i]();
1446
+ }
1447
+ }
1448
+ }
1449
+
1450
+ this._currentFrameEvent = -1;
1451
+
1452
+ this.connection.sendBufferedMessagesNow();
1453
+
1454
+ if (this._stats) {
1455
+ this._stats.end();
1456
+ if (this.time.frameCount % 150 === 0)
1457
+ console.log(this.renderer.info.render.calls + " DrawCalls", "\nRender:", { ...this.renderer.info.render }, "\nMemory:", { ...this.renderer.info.memory }, "\nTarget Framerate: " + this.targetFrameRate);
1458
+ }
1459
+
1460
+ if (this._dispatchReadyAfterFrame) {
1461
+ this._dispatchReadyAfterFrame = false;
1462
+ this.domElement.dispatchEvent(new CustomEvent("ready"));
1463
+ ContextRegistry.dispatchCallback(ContextEvent.ContextFirstFrameRendered, this);
1464
+ }
1465
+ }
1466
+
1467
+ renderNow(camera?: Camera) {
1468
+ if (!camera) {
1469
+ camera = this.mainCamera as Camera;
1470
+ if (!camera) return false;
1471
+ }
1472
+ this.handleRendererContextLost();
1473
+
1474
+ this._isRendering = true;
1475
+ this.renderRequiredTextures();
1476
+
1477
+ if (this.renderer.toneMapping !== NoToneMapping)
1478
+ patchTonemapping(this);
1479
+
1480
+ if (this.composer && !this.isInXR) {
1481
+ // if a camera is passed in we need to check if we need to update the composer's camera
1482
+ if (camera && "setMainCamera" in this.composer) {
1483
+ const currentPassesCamera = this.composer.passes[0]?.mainCamera;
1484
+ if (currentPassesCamera != camera)
1485
+ this.composer.setMainCamera(camera);
1486
+ }
1487
+ this.composer.render(this.time.deltaTime);
1488
+ }
1489
+ else if (camera) {
1490
+ // Workaround for issue on Vision Pro –
1491
+ // depth buffer is not cleared between eye draws, despite the spec...
1492
+ if (this.isInXR && DeviceUtilities.isMacOS())
1493
+ this.renderer.clearDepth();
1494
+ this.renderer.render(this.scene, camera);
1495
+ }
1496
+ this._isRendering = false;
1497
+ return true;
1498
+ }
1499
+
1500
+ private _contextRestoreTries = 0;
1501
+ private handleRendererContextLost() {
1502
+ // Try to restore the context every x frames
1503
+ if (this.time.frame % 10 && this.renderer.getContext().isContextLost()) {
1504
+ if (this._contextRestoreTries++ < 100) {
1505
+ console.warn("Attempting to recover WebGL context...");
1506
+ this.renderer.forceContextRestore();
1507
+ }
1508
+ }
1509
+ }
1510
+
1511
+ /** returns true if we should return out of the frame loop */
1512
+ private _wasPaused: boolean = false;
1513
+ private onHandlePaused(): boolean {
1514
+ const paused = this.evaluatePaused();
1515
+ if (this._wasPaused !== paused) {
1516
+ if (debugActive) console.log("Paused?", paused, "context:" + this.alias);
1517
+ for (let i = 0; i < this.scripts_pausedChanged.length; i++) {
1518
+ const script = this.scripts_pausedChanged[i];
1519
+ if (!script.activeAndEnabled) continue;
1520
+ if (script.onPausedChanged !== undefined) {
1521
+ Context.Current = this;
1522
+ script.onPausedChanged(paused, this._wasPaused);
1523
+ }
1524
+ }
1525
+ }
1526
+ this._wasPaused = paused;
1527
+ return paused;
1528
+ }
1529
+
1530
+ private evaluatePaused(): boolean {
1531
+ if (this.isInXR) return false;
1532
+ if (this.isPaused) return true;
1533
+ // if the element is not visible use the runInBackground flag to determine if we should continue
1534
+ if (this.runInBackground) {
1535
+ return false;
1536
+ }
1537
+ const paused = !this.isVisibleToUser;
1538
+ return paused;
1539
+ }
1540
+
1541
+ private renderRequiredTextures() {
1542
+ if (!this.mainCamera) return;
1543
+ if (!this._requireDepthTexture && !this._requireColorTexture) return;
1544
+ if (!this._renderTarget) {
1545
+ this._renderTarget = new WebGLRenderTarget(this.domWidth, this.domHeight);
1546
+ if (this._requireDepthTexture) {
1547
+ const dt = new DepthTexture(this.domWidth, this.domHeight);;
1548
+ this._renderTarget.depthTexture = dt;
1549
+ }
1550
+ if (this._requireColorTexture) {
1551
+ this._renderTarget.texture = new Texture();
1552
+ this._renderTarget.texture.generateMipmaps = false;
1553
+ this._renderTarget.texture.minFilter = NearestFilter;
1554
+ this._renderTarget.texture.magFilter = NearestFilter;
1555
+ this._renderTarget.texture.format = RGBAFormat;
1556
+ }
1557
+ }
1558
+ const rt = this._renderTarget;
1559
+ if (rt.texture) {
1560
+ rt.texture.colorSpace = this.renderer.outputColorSpace;
1561
+ }
1562
+ const prevTarget = this.renderer.getRenderTarget();
1563
+ this.renderer.setRenderTarget(rt);
1564
+ this.renderer.render(this.scene, this.mainCamera);
1565
+ this.renderer.setRenderTarget(prevTarget);
1566
+ }
1567
+
1568
+ private executeCoroutines(evt: FrameEvent) {
1569
+ if (this.coroutines[evt]) {
1570
+ const evts = this.coroutines[evt];
1571
+ for (let i = 0; i < evts.length; i++) {
1572
+ try {
1573
+ const evt = evts[i];
1574
+ // TODO we might want to keep coroutines playing even if the component is disabled or inactive
1575
+ const remove = !evt.comp || evt.comp.destroyed || !evt.main || evt.comp["enabled"] === false;
1576
+ if (remove) {
1577
+ if (debugCoroutine) console.log("Removing coroutine", evt.comp, evt.comp["enabled"])
1578
+ evts.splice(i, 1);
1579
+ --i;
1580
+ continue;
1581
+ }
1582
+ const iter = evt.chained;
1583
+ if (iter && iter.length > 0) {
1584
+ const last: Generator = iter[iter.length - 1];
1585
+ const res = last.next();
1586
+ if (res.done) {
1587
+ iter.pop();
1588
+ }
1589
+ if (isGenerator(res)) {
1590
+ if (!evt.chained) evt.chained = [];
1591
+ evt.chained.push(res.value);
1592
+ }
1593
+ if (!res.done) continue;
1594
+ }
1595
+
1596
+ const res = evt.main.next();
1597
+ if (res.done === true) {
1598
+ evts.splice(i, 1);
1599
+ --i;
1600
+ continue;
1601
+ }
1602
+ const val = res.value;
1603
+ if (isGenerator(val)) {
1604
+ // invoke once if its a generator
1605
+ // this means e.g. WaitForFrame(1) works and will capture
1606
+ // the frame it was created
1607
+ const gen = val as Generator;
1608
+ const res = gen.next();
1609
+ if (res.done) continue;
1610
+ if (!evt.chained) evt.chained = [];
1611
+ evt.chained.push(val as Generator);
1612
+ }
1613
+ else if (val instanceof Promise) {
1614
+ // If its a promise we want to wait for it to resolve
1615
+ const prom = val as Promise<any>;
1616
+ if (!evt.chained) evt.chained = [];
1617
+ const nested = WaitForPromise(prom);
1618
+ evt.chained?.push(nested);
1619
+ continue;
1620
+ }
1621
+ }
1622
+ catch (e) {
1623
+ console.error(e);
1624
+ }
1625
+ }
1626
+ }
1627
+
1628
+ function isGenerator(val: any): boolean {
1629
+ if (val) {
1630
+ if (val.next && val.return) {
1631
+ return true;
1632
+ }
1633
+ }
1634
+ return false;
1635
+ }
1636
+ }
1637
+
1638
+ }
1639
+
1640
+
1641
+ // const scene = new Scene();
1642
+ // const useComposer = utils.getParam("postfx");
1643
+ // const renderer = new WebGLRenderer({ antialias: true });
1644
+ // const composer = useComposer ? new EffectComposer(renderer) : undefined;
1645
+
1646
+ // renderer.setClearColor(new Color('lightgrey'), 0)
1647
+ // renderer.antialias = true;
1648
+ // renderer.alpha = false;
1649
+ // renderer.shadowMap.enabled = true;
1650
+ // renderer.shadowMap.type = PCFSoftShadowMap;
1651
+ // renderer.setSize(window.innerWidth, window.innerHeight);
1652
+ // renderer.outputEncoding = sRGBEncoding;
1653
+ // renderer.physicallyCorrectLights = true;
1654
+ // document.body.appendChild(renderer.domElement);
1655
+
1656
+ // // generation pushes loading requests in this array
1657
+ // const sceneData: {
1658
+ // mainCamera: Camera | undefined
1659
+ // } = {
1660
+ // preparing: [],
1661
+ // resolving: [],
1662
+ // scripts: [],
1663
+ // raycastTargets: [],
1664
+ // mainCamera: undefined,
1665
+ // mainCameraComponent: undefined,
1666
+ // };
1667
+
1668
+ // // contains a list of functions to be called after loading is done
1669
+ // const post_setup_callbacks = [];
1670
+
1671
+ // const pre_render_Callbacks = [];
1672
+ // const post_render_callbacks = [];
1673
+
1674
+ // const new_scripts = [];
1675
+ // const new_scripts_post_setup_callbacks = [];
1676
+ // const new_scripts_pre_setup_callbacks = [];
1677
+
1678
+ // export {
1679
+ // scene, renderer, composer,
1680
+ // new_scripts,
1681
+ // new_scripts_post_setup_callbacks, new_scripts_pre_setup_callbacks,
1682
+ // sceneData,
1683
+ // post_setup_callbacks,
1684
+ // pre_render_Callbacks,
1685
+ // post_render_callbacks
1686
+ // }