@needle-tools/engine 5.1.0-canary.fbdfce3 → 5.1.0-experimental.03e8105

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 (311) hide show
  1. package/CHANGELOG.md +86 -0
  2. package/SKILL.md +4 -1
  3. package/components.needle.json +1 -1
  4. package/dist/{needle-engine.bundle-BFSj2Fz8.js → needle-engine.bundle-BNqUjnSQ.js} +19180 -18386
  5. package/dist/needle-engine.bundle-Bt8ULD7E.umd.cjs +1733 -0
  6. package/dist/needle-engine.bundle-DF6ovbwD.min.js +1733 -0
  7. package/dist/needle-engine.d.ts +1487 -356
  8. package/dist/needle-engine.js +544 -542
  9. package/dist/needle-engine.min.js +1 -1
  10. package/dist/needle-engine.umd.cjs +1 -1
  11. package/dist/three.js +1 -0
  12. package/dist/three.min.js +21 -21
  13. package/dist/three.umd.cjs +16 -16
  14. package/lib/engine/api.d.ts +8 -1
  15. package/lib/engine/api.js +7 -1
  16. package/lib/engine/api.js.map +1 -1
  17. package/lib/engine/codegen/register_types.js +10 -18
  18. package/lib/engine/codegen/register_types.js.map +1 -1
  19. package/lib/engine/engine_audio.d.ts +68 -0
  20. package/lib/engine/engine_audio.js +172 -0
  21. package/lib/engine/engine_audio.js.map +1 -1
  22. package/lib/engine/engine_camera.fit.js +16 -4
  23. package/lib/engine/engine_camera.fit.js.map +1 -1
  24. package/lib/engine/engine_components.js +1 -1
  25. package/lib/engine/engine_components.js.map +1 -1
  26. package/lib/engine/engine_context.d.ts +21 -8
  27. package/lib/engine/engine_context.js +32 -16
  28. package/lib/engine/engine_context.js.map +1 -1
  29. package/lib/engine/engine_context_eventbus.d.ts +47 -0
  30. package/lib/engine/engine_context_eventbus.js +47 -0
  31. package/lib/engine/engine_context_eventbus.js.map +1 -0
  32. package/lib/engine/engine_disposable.d.ts +172 -0
  33. package/lib/engine/engine_disposable.js +136 -0
  34. package/lib/engine/engine_disposable.js.map +1 -0
  35. package/lib/engine/engine_gameobject.d.ts +1 -10
  36. package/lib/engine/engine_gameobject.js +22 -120
  37. package/lib/engine/engine_gameobject.js.map +1 -1
  38. package/lib/engine/engine_gltf_builtin_components.js +7 -69
  39. package/lib/engine/engine_gltf_builtin_components.js.map +1 -1
  40. package/lib/engine/engine_init.js +7 -7
  41. package/lib/engine/engine_init.js.map +1 -1
  42. package/lib/engine/engine_input.d.ts +24 -5
  43. package/lib/engine/engine_input.js +3 -2
  44. package/lib/engine/engine_input.js.map +1 -1
  45. package/lib/engine/engine_instantiate_resolve.d.ts +42 -0
  46. package/lib/engine/engine_instantiate_resolve.js +372 -0
  47. package/lib/engine/engine_instantiate_resolve.js.map +1 -0
  48. package/lib/engine/engine_license.d.ts +7 -7
  49. package/lib/engine/engine_license.js +183 -57
  50. package/lib/engine/engine_license.js.map +1 -1
  51. package/lib/engine/engine_mainloop_utils.js +7 -4
  52. package/lib/engine/engine_mainloop_utils.js.map +1 -1
  53. package/lib/engine/engine_networking.d.ts +51 -37
  54. package/lib/engine/engine_networking.js +132 -82
  55. package/lib/engine/engine_networking.js.map +1 -1
  56. package/lib/engine/engine_networking.transport.websocket.d.ts +15 -0
  57. package/lib/engine/engine_networking.transport.websocket.js +38 -0
  58. package/lib/engine/engine_networking.transport.websocket.js.map +1 -0
  59. package/lib/engine/engine_networking_blob.js +4 -4
  60. package/lib/engine/engine_networking_blob.js.map +1 -1
  61. package/lib/engine/engine_networking_instantiate.js +2 -2
  62. package/lib/engine/engine_networking_instantiate.js.map +1 -1
  63. package/lib/engine/engine_networking_types.d.ts +39 -1
  64. package/lib/engine/engine_networking_types.js +7 -0
  65. package/lib/engine/engine_networking_types.js.map +1 -1
  66. package/lib/engine/engine_physics_rapier.d.ts +21 -3
  67. package/lib/engine/engine_physics_rapier.js +94 -25
  68. package/lib/engine/engine_physics_rapier.js.map +1 -1
  69. package/lib/engine/engine_scenedata.js +2 -2
  70. package/lib/engine/engine_scenedata.js.map +1 -1
  71. package/lib/engine/engine_serialization_builtin_serializer.js +28 -5
  72. package/lib/engine/engine_serialization_builtin_serializer.js.map +1 -1
  73. package/lib/engine/engine_serialization_core.d.ts +1 -0
  74. package/lib/engine/engine_serialization_core.js +7 -0
  75. package/lib/engine/engine_serialization_core.js.map +1 -1
  76. package/lib/engine/engine_types.d.ts +29 -11
  77. package/lib/engine/engine_types.js +1 -1
  78. package/lib/engine/engine_types.js.map +1 -1
  79. package/lib/engine/engine_util_decorator.js +7 -2
  80. package/lib/engine/engine_util_decorator.js.map +1 -1
  81. package/lib/engine/engine_utils.d.ts +1 -1
  82. package/lib/engine/engine_utils.js +19 -5
  83. package/lib/engine/engine_utils.js.map +1 -1
  84. package/lib/engine/engine_utils_qrcode.js +2 -2
  85. package/lib/engine/engine_utils_qrcode.js.map +1 -1
  86. package/lib/engine/physics/workers/mesh-bvh/GenerateMeshBVHWorker.js +1 -1
  87. package/lib/engine/physics/workers/mesh-bvh/GenerateMeshBVHWorker.js.map +1 -1
  88. package/lib/engine/webcomponents/needle menu/needle-menu-spatial.js +2 -2
  89. package/lib/engine/webcomponents/needle menu/needle-menu-spatial.js.map +1 -1
  90. package/lib/engine/webcomponents/needle menu/needle-menu.d.ts +1 -1
  91. package/lib/engine/webcomponents/needle menu/needle-menu.js +6 -6
  92. package/lib/engine/webcomponents/needle menu/needle-menu.js.map +1 -1
  93. package/lib/engine/webcomponents/needle-engine.d.ts +10 -4
  94. package/lib/engine/webcomponents/needle-engine.js +3 -3
  95. package/lib/engine/webcomponents/needle-engine.js.map +1 -1
  96. package/lib/engine/webcomponents/needle-engine.loading.js +2 -2
  97. package/lib/engine/webcomponents/needle-engine.loading.js.map +1 -1
  98. package/lib/engine/xr/NeedleXRSession.d.ts +3 -2
  99. package/lib/engine/xr/NeedleXRSession.js +50 -14
  100. package/lib/engine/xr/NeedleXRSession.js.map +1 -1
  101. package/lib/engine/xr/TempXRContext.js +2 -2
  102. package/lib/engine/xr/TempXRContext.js.map +1 -1
  103. package/lib/engine/xr/events.d.ts +1 -1
  104. package/lib/engine/xr/events.js.map +1 -1
  105. package/lib/engine-components/Animation.js +17 -16
  106. package/lib/engine-components/Animation.js.map +1 -1
  107. package/lib/engine-components/AnimationBuilder.d.ts +158 -0
  108. package/lib/engine-components/AnimationBuilder.js +305 -0
  109. package/lib/engine-components/AnimationBuilder.js.map +1 -0
  110. package/lib/engine-components/Animator.d.ts +6 -0
  111. package/lib/engine-components/Animator.js +23 -13
  112. package/lib/engine-components/Animator.js.map +1 -1
  113. package/lib/engine-components/AnimatorController.builder.d.ts +191 -0
  114. package/lib/engine-components/AnimatorController.builder.js +263 -0
  115. package/lib/engine-components/AnimatorController.builder.js.map +1 -0
  116. package/lib/engine-components/AnimatorController.d.ts +2 -119
  117. package/lib/engine-components/AnimatorController.js +33 -232
  118. package/lib/engine-components/AnimatorController.js.map +1 -1
  119. package/lib/engine-components/AudioSource.d.ts +19 -3
  120. package/lib/engine-components/AudioSource.js +121 -68
  121. package/lib/engine-components/AudioSource.js.map +1 -1
  122. package/lib/engine-components/Collider.d.ts +18 -9
  123. package/lib/engine-components/Collider.js +61 -14
  124. package/lib/engine-components/Collider.js.map +1 -1
  125. package/lib/engine-components/Component.d.ts +72 -9
  126. package/lib/engine-components/Component.js +114 -10
  127. package/lib/engine-components/Component.js.map +1 -1
  128. package/lib/engine-components/ContactShadows.d.ts +1 -0
  129. package/lib/engine-components/ContactShadows.js +14 -1
  130. package/lib/engine-components/ContactShadows.js.map +1 -1
  131. package/lib/engine-components/DragControls.d.ts +7 -0
  132. package/lib/engine-components/DragControls.js +19 -7
  133. package/lib/engine-components/DragControls.js.map +1 -1
  134. package/lib/engine-components/DropListener.js +3 -0
  135. package/lib/engine-components/DropListener.js.map +1 -1
  136. package/lib/engine-components/EventList.d.ts +31 -9
  137. package/lib/engine-components/EventList.js +37 -76
  138. package/lib/engine-components/EventList.js.map +1 -1
  139. package/lib/engine-components/Joints.d.ts +4 -2
  140. package/lib/engine-components/Joints.js +19 -3
  141. package/lib/engine-components/Joints.js.map +1 -1
  142. package/lib/engine-components/Light.js +9 -1
  143. package/lib/engine-components/Light.js.map +1 -1
  144. package/lib/engine-components/Networking.d.ts +1 -1
  145. package/lib/engine-components/Networking.js +1 -1
  146. package/lib/engine-components/OrbitControls.d.ts +0 -2
  147. package/lib/engine-components/OrbitControls.js +30 -12
  148. package/lib/engine-components/OrbitControls.js.map +1 -1
  149. package/lib/engine-components/RigidBody.d.ts +12 -4
  150. package/lib/engine-components/RigidBody.js +18 -4
  151. package/lib/engine-components/RigidBody.js.map +1 -1
  152. package/lib/engine-components/SceneSwitcher.js +3 -0
  153. package/lib/engine-components/SceneSwitcher.js.map +1 -1
  154. package/lib/engine-components/SeeThrough.js +2 -2
  155. package/lib/engine-components/SeeThrough.js.map +1 -1
  156. package/lib/engine-components/api.d.ts +2 -1
  157. package/lib/engine-components/api.js +2 -1
  158. package/lib/engine-components/api.js.map +1 -1
  159. package/lib/engine-components/codegen/components.d.ts +7 -13
  160. package/lib/engine-components/codegen/components.js +7 -13
  161. package/lib/engine-components/codegen/components.js.map +1 -1
  162. package/lib/engine-components/export/usdz/USDZExporter.js +4 -4
  163. package/lib/engine-components/export/usdz/USDZExporter.js.map +1 -1
  164. package/lib/engine-components/postprocessing/Effects/Tonemapping.utils.d.ts +1 -1
  165. package/lib/engine-components/timeline/PlayableDirector.d.ts +21 -11
  166. package/lib/engine-components/timeline/PlayableDirector.js +75 -67
  167. package/lib/engine-components/timeline/PlayableDirector.js.map +1 -1
  168. package/lib/engine-components/timeline/SignalAsset.d.ts +3 -1
  169. package/lib/engine-components/timeline/SignalAsset.js +1 -0
  170. package/lib/engine-components/timeline/SignalAsset.js.map +1 -1
  171. package/lib/engine-components/timeline/TimelineBuilder.d.ts +413 -0
  172. package/lib/engine-components/timeline/TimelineBuilder.js +506 -0
  173. package/lib/engine-components/timeline/TimelineBuilder.js.map +1 -0
  174. package/lib/engine-components/timeline/TimelineModels.d.ts +2 -1
  175. package/lib/engine-components/timeline/TimelineModels.js +3 -0
  176. package/lib/engine-components/timeline/TimelineModels.js.map +1 -1
  177. package/lib/engine-components/timeline/TimelineTracks.d.ts +37 -6
  178. package/lib/engine-components/timeline/TimelineTracks.js +92 -26
  179. package/lib/engine-components/timeline/TimelineTracks.js.map +1 -1
  180. package/lib/engine-components/timeline/index.d.ts +2 -1
  181. package/lib/engine-components/timeline/index.js +2 -0
  182. package/lib/engine-components/timeline/index.js.map +1 -1
  183. package/lib/engine-components/ui/Canvas.d.ts +1 -1
  184. package/lib/engine-components/ui/Canvas.js +2 -8
  185. package/lib/engine-components/ui/Canvas.js.map +1 -1
  186. package/lib/engine-components/ui/Text.d.ts +1 -0
  187. package/lib/engine-components/ui/Text.js +10 -7
  188. package/lib/engine-components/ui/Text.js.map +1 -1
  189. package/lib/engine-components/web/CursorFollow.d.ts +0 -1
  190. package/lib/engine-components/web/CursorFollow.js +21 -13
  191. package/lib/engine-components/web/CursorFollow.js.map +1 -1
  192. package/lib/engine-components/webxr/WebXRImageTracking.js +4 -0
  193. package/lib/engine-components/webxr/WebXRImageTracking.js.map +1 -1
  194. package/package.json +2 -83
  195. package/plugins/common/cloud.js +6 -1
  196. package/plugins/common/license.js +31 -10
  197. package/plugins/common/worker.js +9 -4
  198. package/plugins/vite/asap.js +17 -8
  199. package/plugins/vite/dependencies.js +29 -10
  200. package/plugins/vite/dependency-watcher.js +2 -2
  201. package/plugins/vite/editor-connection.js +3 -3
  202. package/plugins/vite/license.js +46 -7
  203. package/plugins/vite/local-files-core.js +3 -3
  204. package/plugins/vite/local-files-utils.d.ts +3 -1
  205. package/plugins/vite/local-files-utils.js +29 -5
  206. package/plugins/vite/reload.js +1 -1
  207. package/plugins/vite/server.js +2 -1
  208. package/src/engine/api.ts +11 -1
  209. package/src/engine/codegen/register_types.ts +10 -18
  210. package/src/engine/engine_audio.ts +184 -0
  211. package/src/engine/engine_camera.fit.ts +15 -4
  212. package/src/engine/engine_components.ts +1 -1
  213. package/src/engine/engine_context.ts +34 -18
  214. package/src/engine/engine_context_eventbus.ts +73 -0
  215. package/src/engine/engine_disposable.ts +214 -0
  216. package/src/engine/engine_gameobject.ts +54 -159
  217. package/src/engine/engine_gltf_builtin_components.ts +7 -76
  218. package/src/engine/engine_init.ts +7 -7
  219. package/src/engine/engine_input.ts +28 -7
  220. package/src/engine/engine_instantiate_resolve.ts +407 -0
  221. package/src/engine/engine_license.ts +197 -55
  222. package/src/engine/engine_mainloop_utils.ts +7 -4
  223. package/src/engine/engine_networking.transport.websocket.ts +45 -0
  224. package/src/engine/engine_networking.ts +161 -137
  225. package/src/engine/engine_networking_blob.ts +4 -4
  226. package/src/engine/engine_networking_instantiate.ts +2 -2
  227. package/src/engine/engine_networking_types.ts +41 -1
  228. package/src/engine/engine_physics_rapier.ts +102 -33
  229. package/src/engine/engine_scenedata.ts +3 -3
  230. package/src/engine/engine_serialization_builtin_serializer.ts +32 -9
  231. package/src/engine/engine_serialization_core.ts +9 -0
  232. package/src/engine/engine_types.ts +46 -27
  233. package/src/engine/engine_util_decorator.ts +7 -2
  234. package/src/engine/engine_utils.ts +16 -5
  235. package/src/engine/engine_utils_qrcode.ts +2 -2
  236. package/src/engine/physics/workers/mesh-bvh/GenerateMeshBVHWorker.js +1 -1
  237. package/src/engine/webcomponents/needle menu/needle-menu-spatial.ts +2 -2
  238. package/src/engine/webcomponents/needle menu/needle-menu.ts +6 -6
  239. package/src/engine/webcomponents/needle-engine.loading.ts +6 -6
  240. package/src/engine/webcomponents/needle-engine.ts +12 -6
  241. package/src/engine/xr/NeedleXRSession.ts +48 -13
  242. package/src/engine/xr/TempXRContext.ts +2 -2
  243. package/src/engine/xr/events.ts +1 -1
  244. package/src/engine-components/Animation.ts +19 -16
  245. package/src/engine-components/AnimationBuilder.ts +472 -0
  246. package/src/engine-components/Animator.ts +24 -12
  247. package/src/engine-components/AnimatorController.builder.ts +387 -0
  248. package/src/engine-components/AnimatorController.ts +20 -291
  249. package/src/engine-components/AudioSource.ts +130 -79
  250. package/src/engine-components/Collider.ts +66 -18
  251. package/src/engine-components/Component.ts +118 -20
  252. package/src/engine-components/ContactShadows.ts +15 -1
  253. package/src/engine-components/DragControls.ts +18 -11
  254. package/src/engine-components/DropListener.ts +3 -0
  255. package/src/engine-components/EventList.ts +45 -83
  256. package/src/engine-components/Joints.ts +20 -4
  257. package/src/engine-components/Light.ts +10 -2
  258. package/src/engine-components/Networking.ts +1 -1
  259. package/src/engine-components/OrbitControls.ts +34 -14
  260. package/src/engine-components/RigidBody.ts +18 -4
  261. package/src/engine-components/SceneSwitcher.ts +3 -0
  262. package/src/engine-components/SeeThrough.ts +2 -2
  263. package/src/engine-components/api.ts +2 -1
  264. package/src/engine-components/codegen/components.ts +7 -13
  265. package/src/engine-components/export/usdz/USDZExporter.ts +4 -4
  266. package/src/engine-components/timeline/PlayableDirector.ts +83 -81
  267. package/src/engine-components/timeline/SignalAsset.ts +4 -1
  268. package/src/engine-components/timeline/TimelineBuilder.ts +824 -0
  269. package/src/engine-components/timeline/TimelineModels.ts +5 -1
  270. package/src/engine-components/timeline/TimelineTracks.ts +96 -27
  271. package/src/engine-components/timeline/index.ts +2 -1
  272. package/src/engine-components/ui/Canvas.ts +2 -8
  273. package/src/engine-components/ui/Text.ts +12 -8
  274. package/src/engine-components/web/CursorFollow.ts +21 -14
  275. package/src/engine-components/webxr/WebXRImageTracking.ts +2 -0
  276. package/dist/needle-engine.bundle-CmxIO5uH.min.js +0 -1732
  277. package/dist/needle-engine.bundle-tJIZukCz.umd.cjs +0 -1732
  278. package/lib/engine-components/AvatarLoader.d.ts +0 -80
  279. package/lib/engine-components/AvatarLoader.js +0 -232
  280. package/lib/engine-components/AvatarLoader.js.map +0 -1
  281. package/lib/engine-components/avatar/AvatarBlink_Simple.d.ts +0 -11
  282. package/lib/engine-components/avatar/AvatarBlink_Simple.js +0 -77
  283. package/lib/engine-components/avatar/AvatarBlink_Simple.js.map +0 -1
  284. package/lib/engine-components/avatar/AvatarEyeLook_Rotation.d.ts +0 -14
  285. package/lib/engine-components/avatar/AvatarEyeLook_Rotation.js +0 -69
  286. package/lib/engine-components/avatar/AvatarEyeLook_Rotation.js.map +0 -1
  287. package/lib/engine-components/avatar/Avatar_Brain_LookAt.d.ts +0 -29
  288. package/lib/engine-components/avatar/Avatar_Brain_LookAt.js +0 -122
  289. package/lib/engine-components/avatar/Avatar_Brain_LookAt.js.map +0 -1
  290. package/lib/engine-components/avatar/Avatar_MouthShapes.d.ts +0 -15
  291. package/lib/engine-components/avatar/Avatar_MouthShapes.js +0 -80
  292. package/lib/engine-components/avatar/Avatar_MouthShapes.js.map +0 -1
  293. package/lib/engine-components/avatar/Avatar_MustacheShake.d.ts +0 -9
  294. package/lib/engine-components/avatar/Avatar_MustacheShake.js +0 -30
  295. package/lib/engine-components/avatar/Avatar_MustacheShake.js.map +0 -1
  296. package/plugins/dts-generator/dts.codegen.js +0 -334
  297. package/plugins/dts-generator/dts.scan.js +0 -99
  298. package/plugins/dts-generator/dts.writer.js +0 -59
  299. package/plugins/dts-generator/glb.discovery.js +0 -279
  300. package/plugins/dts-generator/glb.extractor.js +0 -215
  301. package/plugins/dts-generator/glb.reader.js +0 -167
  302. package/plugins/dts-generator/index.js +0 -36
  303. package/plugins/dts-generator/manifest.types.js +0 -174
  304. package/plugins/gltf-packer.mjs +0 -1
  305. package/src/engine-components/AvatarLoader.ts +0 -264
  306. package/src/engine-components/avatar/AvatarBlink_Simple.ts +0 -70
  307. package/src/engine-components/avatar/AvatarEyeLook_Rotation.ts +0 -64
  308. package/src/engine-components/avatar/Avatar_Brain_LookAt.ts +0 -140
  309. package/src/engine-components/avatar/Avatar_MouthShapes.ts +0 -84
  310. package/src/engine-components/avatar/Avatar_MustacheShake.ts +0 -32
  311. package/src/vite-env.d.ts +0 -16
@@ -0,0 +1,407 @@
1
+ import type { Color, Euler, Matrix2, Matrix3, Matrix4, Object3D, Quaternion, Vector2, Vector3, Vector4 } from "three";
2
+
3
+ import { InstantiateIdProvider } from "./engine_networking_instantiate.js";
4
+ import { isSerializable } from "./engine_serialization_core.js";
5
+ import { type GuidsMap, type IComponent, type UIDProvider, isComponent } from "./engine_types.js";
6
+ import { getParam } from "./engine_utils.js";
7
+
8
+ const debug = getParam("debuginstantiate");
9
+
10
+ // ————————————————————————————————————————————————————————
11
+ // Types
12
+ // ————————————————————————————————————————————————————————
13
+
14
+ export type ObjectCloneReference = {
15
+ readonly original: object;
16
+ readonly clone: object;
17
+ }
18
+
19
+ /** Maps uuid/guid → { original, clone } for Object3D and Component instances */
20
+ export type InstantiateReferenceMap = Record<string, ObjectCloneReference>;
21
+
22
+ /**
23
+ * Provides access to the instantiated object map (used by EventList etc.)
24
+ */
25
+ export type InstantiateContext = Readonly<InstantiateReferenceMap>;
26
+
27
+
28
+ // ————————————————————————————————————————————————————————
29
+ // ID Provider Cache (moved from engine_gltf_builtin_components.ts)
30
+ // ————————————————————————————————————————————————————————
31
+
32
+ /**
33
+ * Cache of id providers per component/object guid.
34
+ * Ensures deterministic guid generation regardless of scene order.
35
+ */
36
+ const idProviderCache = new Map<string, InstantiateIdProvider>();
37
+
38
+ /** Clear the id provider cache (e.g. when reloading a context) */
39
+ export function clearIdProviderCache() {
40
+ idProviderCache.clear();
41
+ }
42
+
43
+ // ————————————————————————————————————————————————————————
44
+ // Guid Generation (moved from engine_gltf_builtin_components.ts)
45
+ // ————————————————————————————————————————————————————————
46
+
47
+ export const originalComponentNameKey = Symbol("original-component-name");
48
+
49
+ // #region hierarchy guids
50
+ /**
51
+ * Recursively generates new deterministic guids for all objects and components in a hierarchy.
52
+ * Uses the idProviderCache so that the same source guid always produces the same output guid
53
+ * (needed for networking: all clients must agree on the guids of instantiated objects).
54
+ * Populates guidsMap (oldGuid → newGuid) so string references can be remapped afterwards.
55
+ */
56
+ export function generateGuidsForHierarchy(
57
+ obj: Object3D,
58
+ idProvider: UIDProvider | null,
59
+ guidsMap: GuidsMap,
60
+ ): void {
61
+ if (idProvider === null) return;
62
+ if (!obj) return;
63
+ const prev = (obj as any).guid;
64
+
65
+ // Use a cached id provider per object to ensure stable guids regardless of hierarchy order
66
+ const idProviderKey = (obj as any).guid;
67
+ if (idProviderKey?.length) {
68
+ if (!idProviderCache.has(idProviderKey)) {
69
+ if (debug) console.log("Creating InstanceIdProvider with key \"" + idProviderKey + "\" for object " + obj.name);
70
+ idProviderCache.set(idProviderKey, new InstantiateIdProvider(idProviderKey));
71
+ }
72
+ }
73
+ const objectIdProvider = idProviderKey && idProviderCache.get(idProviderKey) || idProvider;
74
+
75
+ (obj as any).guid = objectIdProvider.generateUUID();
76
+ if (prev && prev !== "invalid")
77
+ guidsMap[prev] = (obj as any).guid;
78
+
79
+ if (obj && obj.userData && obj.userData.components) {
80
+ for (const comp of obj.userData.components) {
81
+ if (comp === null) continue;
82
+
83
+ const compIdProviderKey = comp.guid;
84
+ if (compIdProviderKey) {
85
+ if (!idProviderCache.has(compIdProviderKey)) {
86
+ if (debug) console.log("Creating InstanceIdProvider with key \"" + compIdProviderKey + "\" for component " + comp[originalComponentNameKey]);
87
+ idProviderCache.set(compIdProviderKey, new InstantiateIdProvider(compIdProviderKey));
88
+ }
89
+ }
90
+ else if (debug) console.warn("Can not create IdProvider: component " + comp[originalComponentNameKey] + " has no guid", comp.guid);
91
+ const componentIdProvider = idProviderCache.get(compIdProviderKey) || idProvider;
92
+
93
+ const compPrev = comp.guid;
94
+ comp.guid = componentIdProvider.generateUUID();
95
+ if (compPrev && compPrev !== "invalid")
96
+ guidsMap[compPrev] = comp.guid;
97
+ }
98
+ }
99
+ if (obj.children) {
100
+ for (const child of obj.children) {
101
+ generateGuidsForHierarchy(child as Object3D, idProvider, guidsMap);
102
+ }
103
+ }
104
+ }
105
+
106
+ // ————————————————————————————————————————————————————————
107
+ // #region reference resolution
108
+ // ————————————————————————————————————————————————————————
109
+
110
+ /**
111
+ * The unified reference resolution function.
112
+ * Iterates all cloned components in the objectMap and remaps their properties
113
+ * to point at cloned counterparts where appropriate.
114
+ *
115
+ * Handles: Component, Object3D, Array, Map, Set, Record/plain objects,
116
+ * EventList, Vector/Color/Quaternion, and @serializable nested objects.
117
+ */
118
+ export function resolveInstanceReferences(objectMap: InstantiateReferenceMap): void {
119
+ for (const key in objectMap) {
120
+ const val = objectMap[key];
121
+ const clone = val.clone as Object3D | null;
122
+ if (!clone?.isObject3D || !clone?.userData?.components) continue;
123
+
124
+ for (let i = 0; i < clone.userData.components.length; i++) {
125
+ const component = clone.userData.components[i];
126
+ const entries = Object.entries(component);
127
+ for (const [propKey, propValue] of entries) {
128
+ if (propValue === null || propValue === undefined) continue;
129
+ // Skip primitives that can't be remapped, but allow strings for guid resolution
130
+ if (typeof propValue !== "object" && typeof propValue !== "string") continue;
131
+ const resolved = resolveValue(propKey, propValue, objectMap);
132
+ if (resolved !== undefined) {
133
+ component[propKey] = resolved;
134
+ }
135
+ }
136
+ }
137
+ }
138
+ }
139
+
140
+ /**
141
+ * Resolves string-based guid references in all components of a hierarchy using a GuidsMap.
142
+ * Used by the glTF loading path where objects get new guids assigned and string references
143
+ * (e.g. PlayableDirector track.outputs) need to be updated.
144
+ */
145
+ export function resolveStringGuidsInHierarchy(root: Object3D, guidsMap: GuidsMap): void {
146
+ resolveStringGuidsRecursive(root, guidsMap);
147
+ }
148
+
149
+ function resolveStringGuidsRecursive(obj: Object3D, guidsMap: GuidsMap): void {
150
+ if (obj.userData?.components) {
151
+ for (const component of obj.userData.components) {
152
+ if (component === null) continue;
153
+ resolveStringGuidsInObject(component, guidsMap);
154
+ }
155
+ }
156
+ if (obj.children) {
157
+ for (const child of obj.children) {
158
+ resolveStringGuidsRecursive(child as Object3D, guidsMap);
159
+ }
160
+ }
161
+ }
162
+
163
+ function resolveStringGuidsInObject(obj: any, guidsMap: GuidsMap, visited?: WeakSet<object>): void {
164
+ if (!visited) visited = new WeakSet();
165
+ if (visited.has(obj)) return;
166
+ visited.add(obj);
167
+
168
+ for (const key of Object.keys(obj)) {
169
+ const value = obj[key];
170
+ if (value === null || value === undefined) continue;
171
+ if (typeof value === "string") {
172
+ if (guidsMap[value]) {
173
+ obj[key] = guidsMap[value];
174
+ }
175
+ }
176
+ else if (Array.isArray(value)) {
177
+ for (let i = 0; i < value.length; i++) {
178
+ if (typeof value[i] === "string" && guidsMap[value[i]]) {
179
+ value[i] = guidsMap[value[i]];
180
+ }
181
+ else if (typeof value[i] === "object" && value[i] !== null) {
182
+ resolveStringGuidsInObject(value[i], guidsMap, visited);
183
+ }
184
+ }
185
+ }
186
+ else if (typeof value === "object") {
187
+ // Skip known non-data objects
188
+ if (value.isObject3D || value.isComponent) continue;
189
+ resolveStringGuidsInObject(value, guidsMap, visited);
190
+ }
191
+ }
192
+ }
193
+
194
+ // #region resolveValue
195
+ /**
196
+ * Resolve a single value, returning the remapped value or undefined if no remap needed.
197
+ * This is the core remapping logic called recursively for nested structures.
198
+ */
199
+ export function resolveValue(key: string, value: unknown, objectMap: InstantiateReferenceMap): any | undefined {
200
+
201
+ // Handle null/undefined early to avoid unnecessary processing
202
+ if (value === undefined) return undefined;
203
+ if (value === null) return null;
204
+
205
+ // String guid resolution: if this string is a known guid/uuid in the objectMap,
206
+ // resolve it directly to the clone object. This handles e.g. PlayableDirector track.outputs.
207
+ if (typeof value === "string") {
208
+ const ref = objectMap[value];
209
+ if (ref) {
210
+ return ref.clone;
211
+ }
212
+ return undefined;
213
+ }
214
+
215
+ // Primitives: no remapping needed
216
+ if (typeof value !== "object") return undefined;
217
+
218
+ // 1. Component → find cloned counterpart by gameObject.uuid + component index
219
+ if (isComponent(value)) {
220
+ return resolveComponentReference(value, objectMap);
221
+ }
222
+
223
+ // 2. Object3D → uuid lookup, return clone if found (otherwise external, keep as-is)
224
+ if ((value as Object3D).isObject3D === true) {
225
+ if (key === "gameObject") return undefined;
226
+ const id = (value as Object3D).uuid;
227
+ const cloneRef = objectMap[id]?.clone;
228
+ if (cloneRef) {
229
+ if (debug) console.log(key, "old", value, "new", cloneRef);
230
+ return cloneRef;
231
+ }
232
+ return undefined;
233
+ }
234
+
235
+ // 3. Cloneable value types (Vector3, Quaternion, Euler, Color)
236
+ if (isCloneableValueType(value)) {
237
+ return value.clone();
238
+ }
239
+
240
+ // 4. Array → create new array, recursively resolve each element
241
+ if (Array.isArray(value)) {
242
+ return resolveArray(key, value, objectMap);
243
+ }
244
+
245
+ // 5. Map → create new Map, resolve keys and values
246
+ if (value instanceof Map) {
247
+ return resolveMap(value, objectMap);
248
+ }
249
+
250
+ // 6. Set → create new Set, resolve values
251
+ if (value instanceof Set) {
252
+ return resolveSet(value, objectMap);
253
+ }
254
+
255
+ // 7. WeakMap / WeakSet → NOT iterable, cannot remap. Keep as-is.
256
+ if (value instanceof WeakMap || value instanceof WeakSet) {
257
+ return undefined;
258
+ }
259
+
260
+ // 8. @serializable objects (incl. EventList, CallInfo) → shallow clone + recursively resolve $serializedTypes fields
261
+ if (isSerializable(value) && value.$serializedTypes) {
262
+ return resolveSerializableObject(value, objectMap);
263
+ }
264
+
265
+ // 9. Plain objects / Records → shallow clone, resolve each value
266
+ if (isPlainObject(value)) {
267
+ return resolvePlainObject(key, value, objectMap);
268
+ }
269
+
270
+ return undefined;
271
+ }
272
+
273
+ // ————————————————————————————————————————————————————————
274
+ // Internal Helpers
275
+ // ————————————————————————————————————————————————————————
276
+
277
+ function resolveComponentReference(value: IComponent, objectMap: InstantiateReferenceMap): object | undefined {
278
+ const originalGameObject = value["gameObject"] as Object3D | undefined;
279
+ if (!originalGameObject) return undefined;
280
+
281
+ const id = originalGameObject.uuid;
282
+ const newGameObject = objectMap[id]?.clone as Object3D | undefined;
283
+ if (!newGameObject) {
284
+ // Reference points to an object not in the cloned hierarchy (external)
285
+ if (debug) console.log("Component reference did not change (external)", value);
286
+ return undefined;
287
+ }
288
+
289
+ const index = originalGameObject.userData.components.indexOf(value);
290
+ if (index >= 0 && newGameObject.isObject3D) {
291
+ if (debug) console.log("Resolved component", id, "at index", index);
292
+ return newGameObject.userData.components[index];
293
+ }
294
+ else {
295
+ console.warn("Could not find component at expected index", value);
296
+ }
297
+ return undefined;
298
+ }
299
+
300
+ function resolveArray(key: string, arr: unknown[], objectMap: InstantiateReferenceMap): unknown[] {
301
+ const result: unknown[] = [];
302
+ for (let i = 0; i < arr.length; i++) {
303
+ const entry = arr[i];
304
+ if (entry === null || entry === undefined) {
305
+ result.push(entry);
306
+ continue;
307
+ }
308
+ // Skip primitives that can't be remapped (numbers, booleans)
309
+ // but allow strings through for guid resolution
310
+ if (typeof entry !== "object" && typeof entry !== "string") {
311
+ result.push(entry);
312
+ continue;
313
+ }
314
+ const resolved = resolveValue(key, entry, objectMap);
315
+ result.push(resolved !== undefined ? resolved : entry);
316
+ }
317
+ return result;
318
+ }
319
+
320
+ function resolveMap(map: Map<unknown, unknown>, objectMap: InstantiateReferenceMap): Map<any, any> {
321
+ const result = new Map();
322
+ let didChange = false;
323
+ for (const [mapKey, mapValue] of map) {
324
+ let resolvedKey = mapKey;
325
+ let resolvedValue = mapValue;
326
+
327
+ if (typeof mapKey === "object" && mapKey !== null) {
328
+ const rk = resolveValue("", mapKey, objectMap);
329
+ if (rk !== undefined) { resolvedKey = rk; didChange = true; }
330
+ }
331
+ if (typeof mapValue === "object" && mapValue !== null) {
332
+ const rv = resolveValue("", mapValue, objectMap);
333
+ if (rv !== undefined) { resolvedValue = rv; didChange = true; }
334
+ }
335
+ result.set(resolvedKey, resolvedValue);
336
+ }
337
+ return didChange ? result : result; // always return new Map to prevent shared mutation
338
+ }
339
+
340
+ function resolveSet(set: Set<unknown>, objectMap: InstantiateReferenceMap): Set<any> {
341
+ const result = new Set();
342
+ for (const entry of set) {
343
+ if (typeof entry === "object" && entry !== null) {
344
+ const resolved = resolveValue("", entry, objectMap);
345
+ result.add(resolved !== undefined ? resolved : entry);
346
+ } else {
347
+ result.add(entry);
348
+ }
349
+ }
350
+ return result;
351
+ }
352
+
353
+ function resolveSerializableObject(value: unknown, objectMap: InstantiateReferenceMap): any | undefined {
354
+ // Clone the serializable object to avoid mutating the original (which may be shared with source)
355
+ const cloned = Object.assign(Object.create(Object.getPrototypeOf(value)), value);
356
+ let didChange = false;
357
+ for (const key in cloned.$serializedTypes) {
358
+ const val = cloned[key];
359
+ if (val === null || val === undefined) continue;
360
+ if (typeof val === "object") {
361
+ if (debug) console.log("Recursively resolve references for", key, val);
362
+ const resolved = resolveValue(key, val, objectMap);
363
+ if (resolved !== undefined) {
364
+ cloned[key] = resolved;
365
+ didChange = true;
366
+ }
367
+ }
368
+ }
369
+ return didChange ? cloned : undefined;
370
+ }
371
+
372
+ function resolvePlainObject(_parentKey: string, obj: Record<string, unknown>, objectMap: InstantiateReferenceMap): Record<string, unknown> | undefined {
373
+ let didChange = false;
374
+ const clone = { ...obj };
375
+ for (const key of Object.keys(clone)) {
376
+ const val = clone[key];
377
+ if (val === null || val === undefined) continue;
378
+ // Skip primitives that can't be remapped, but allow strings for guid resolution
379
+ if (typeof val !== "object" && typeof val !== "string") continue;
380
+ const resolved = resolveValue(key, val, objectMap);
381
+ if (resolved !== undefined) {
382
+ clone[key] = resolved;
383
+ didChange = true;
384
+ }
385
+ }
386
+ return didChange ? clone : undefined;
387
+ }
388
+
389
+ function isPlainObject(obj: unknown): obj is Record<string, unknown> {
390
+ if (typeof obj !== "object" || obj === null) return false;
391
+ const proto = Object.getPrototypeOf(obj);
392
+ return proto === Object.prototype || proto === null;
393
+ }
394
+
395
+ /** Returns true if the object is a three.js value type that should be cloned (not remapped) */
396
+ function isCloneableValueType(value: object): value is { clone(): object } {
397
+ return (value as Vector2).isVector2 === true ||
398
+ (value as Vector3).isVector3 === true ||
399
+ (value as Vector4).isVector4 === true ||
400
+ (value as Quaternion).isQuaternion === true ||
401
+ (value as Euler).isEuler === true ||
402
+ (value as Color).isColor === true ||
403
+ (value as Matrix2).isMatrix2 === true ||
404
+ (value as Matrix3).isMatrix3 === true ||
405
+ (value as Matrix4).isMatrix4 === true;
406
+ }
407
+