@webspatial/core-sdk 1.6.1 → 2.0.0

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 (320) hide show
  1. package/CHANGELOG.md +84 -0
  2. package/README.md +10 -0
  3. package/dist/JSBCommand.d.ts +398 -0
  4. package/dist/JSBCommand.js +668 -0
  5. package/dist/JSBCommand.js.map +1 -0
  6. package/dist/Spatial.d.ts +63 -0
  7. package/dist/Spatial.js +60 -0
  8. package/dist/Spatial.js.map +1 -0
  9. package/dist/SpatialObject.d.ts +19 -0
  10. package/dist/SpatialObject.js +44 -0
  11. package/dist/SpatialObject.js.map +1 -0
  12. package/dist/SpatialScene.d.ts +51 -0
  13. package/dist/SpatialScene.js +74 -0
  14. package/dist/SpatialScene.js.map +1 -0
  15. package/dist/SpatialSession.d.ts +143 -0
  16. package/dist/SpatialSession.js +173 -0
  17. package/dist/SpatialSession.js.map +1 -0
  18. package/dist/SpatialWebEvent.d.ts +8 -0
  19. package/dist/SpatialWebEvent.js +18 -0
  20. package/dist/SpatialWebEvent.js.map +1 -0
  21. package/dist/SpatialWebEventCreator.d.ts +11 -0
  22. package/dist/SpatialWebEventCreator.js +11 -0
  23. package/dist/SpatialWebEventCreator.js.map +1 -0
  24. package/dist/Spatialized2DElement.d.ts +42 -0
  25. package/dist/Spatialized2DElement.js +47 -0
  26. package/dist/Spatialized2DElement.js.map +1 -0
  27. package/dist/SpatializedDynamic3DElement.d.ts +7 -0
  28. package/dist/SpatializedDynamic3DElement.js +43 -0
  29. package/dist/SpatializedDynamic3DElement.js.map +1 -0
  30. package/dist/SpatializedElement.d.ts +7 -0
  31. package/dist/SpatializedElement.js +206 -0
  32. package/dist/SpatializedElement.js.map +1 -0
  33. package/dist/SpatializedElementCreator.d.ts +15 -0
  34. package/dist/SpatializedElementCreator.js +47 -0
  35. package/dist/SpatializedElementCreator.js.map +1 -0
  36. package/dist/SpatializedStatic3DElement.d.ts +195 -0
  37. package/dist/SpatializedStatic3DElement.js +327 -0
  38. package/dist/SpatializedStatic3DElement.js.map +1 -0
  39. package/dist/WebMsgCommand.d.ts +7 -0
  40. package/dist/WebMsgCommand.js +23 -0
  41. package/dist/WebMsgCommand.js.map +1 -0
  42. package/dist/index.d.ts +35 -1101
  43. package/dist/index.js +21 -3393
  44. package/dist/index.js.map +1 -1
  45. package/dist/install-polyfills.d.ts +2 -0
  46. package/dist/install-polyfills.js +13 -0
  47. package/dist/install-polyfills.js.map +1 -0
  48. package/dist/isSSREnv.d.ts +3 -0
  49. package/dist/isSSREnv.js +6 -0
  50. package/dist/isSSREnv.js.map +1 -0
  51. package/dist/motion/AnimationObject.d.ts +7 -0
  52. package/dist/motion/AnimationObject.js +140 -0
  53. package/dist/motion/AnimationObject.js.map +1 -0
  54. package/dist/motion/compute/index.d.ts +10 -0
  55. package/dist/motion/compute/index.js +19 -0
  56. package/dist/motion/compute/index.js.map +1 -0
  57. package/dist/motion/compute/motionPropertyValues.d.ts +19 -0
  58. package/dist/motion/compute/motionPropertyValues.js +50 -0
  59. package/dist/motion/compute/motionPropertyValues.js.map +1 -0
  60. package/dist/motion/compute/normalize.d.ts +31 -0
  61. package/dist/motion/compute/normalize.js +201 -0
  62. package/dist/motion/compute/normalize.js.map +1 -0
  63. package/dist/motion/compute/validate.d.ts +22 -0
  64. package/dist/motion/compute/validate.js +103 -0
  65. package/dist/motion/compute/validate.js.map +1 -0
  66. package/dist/motion/index.d.ts +8 -0
  67. package/dist/motion/index.js +6 -0
  68. package/dist/motion/index.js.map +1 -0
  69. package/dist/motion/native/serializeMotionTimeline.d.ts +12 -0
  70. package/dist/motion/native/serializeMotionTimeline.js +21 -0
  71. package/dist/motion/native/serializeMotionTimeline.js.map +1 -0
  72. package/dist/physicalMetrics-W5uZ5xKb.d.ts +48 -0
  73. package/dist/physicalMetrics.d.ts +1 -0
  74. package/dist/physicalMetrics.js +58 -0
  75. package/dist/physicalMetrics.js.map +1 -0
  76. package/dist/platform-adapter/CommandResultUtils.d.ts +12 -0
  77. package/dist/platform-adapter/CommandResultUtils.js +21 -0
  78. package/dist/platform-adapter/CommandResultUtils.js.map +1 -0
  79. package/dist/platform-adapter/createPlatformSync.d.ts +16 -0
  80. package/dist/platform-adapter/createPlatformSync.js +30 -0
  81. package/dist/platform-adapter/createPlatformSync.js.map +1 -0
  82. package/dist/platform-adapter/index.d.ts +12 -0
  83. package/dist/platform-adapter/index.js +10 -0
  84. package/dist/platform-adapter/index.js.map +1 -0
  85. package/dist/platform-adapter/interface.d.ts +7 -0
  86. package/dist/platform-adapter/interface.js +1 -0
  87. package/dist/platform-adapter/interface.js.map +1 -0
  88. package/dist/platform-adapter/pico-os/PicoOSPlatform.d.ts +25 -0
  89. package/dist/platform-adapter/pico-os/PicoOSPlatform.js +168 -0
  90. package/dist/platform-adapter/pico-os/PicoOSPlatform.js.map +1 -0
  91. package/dist/platform-adapter/puppeteer/PuppeteerPlatform.d.ts +66 -0
  92. package/dist/platform-adapter/puppeteer/PuppeteerPlatform.js +372 -0
  93. package/dist/platform-adapter/puppeteer/PuppeteerPlatform.js.map +1 -0
  94. package/dist/platform-adapter/spatialRequestMetadata.d.ts +6 -0
  95. package/dist/platform-adapter/spatialRequestMetadata.js +39 -0
  96. package/dist/platform-adapter/spatialRequestMetadata.js.map +1 -0
  97. package/dist/platform-adapter/spatialSceneQuery.d.ts +12 -0
  98. package/dist/platform-adapter/spatialSceneQuery.js +12 -0
  99. package/dist/platform-adapter/spatialSceneQuery.js.map +1 -0
  100. package/dist/platform-adapter/vision-os/VisionOSPlatform.d.ts +19 -0
  101. package/dist/platform-adapter/vision-os/VisionOSPlatform.js +77 -0
  102. package/dist/platform-adapter/vision-os/VisionOSPlatform.js.map +1 -0
  103. package/dist/platform-runtime.d.ts +12 -0
  104. package/dist/platform-runtime.js +14 -0
  105. package/dist/platform-runtime.js.map +1 -0
  106. package/dist/reality/Attachment.d.ts +19 -0
  107. package/dist/reality/Attachment.js +39 -0
  108. package/dist/reality/Attachment.js.map +1 -0
  109. package/dist/reality/component/ModelComponent.d.ts +14 -0
  110. package/dist/reality/component/ModelComponent.js +11 -0
  111. package/dist/reality/component/ModelComponent.js.map +1 -0
  112. package/dist/reality/component/SpatialComponent.d.ts +8 -0
  113. package/dist/reality/component/SpatialComponent.js +19 -0
  114. package/dist/reality/component/SpatialComponent.js.map +1 -0
  115. package/dist/reality/component/index.d.ts +8 -0
  116. package/dist/reality/component/index.js +3 -0
  117. package/dist/reality/component/index.js.map +1 -0
  118. package/dist/reality/entity/SpatialEntity.d.ts +7 -0
  119. package/dist/reality/entity/SpatialEntity.js +291 -0
  120. package/dist/reality/entity/SpatialEntity.js.map +1 -0
  121. package/dist/reality/entity/SpatialModelEntity.d.ts +17 -0
  122. package/dist/reality/entity/SpatialModelEntity.js +17 -0
  123. package/dist/reality/entity/SpatialModelEntity.js.map +1 -0
  124. package/dist/reality/entity/index.d.ts +8 -0
  125. package/dist/reality/entity/index.js +3 -0
  126. package/dist/reality/entity/index.js.map +1 -0
  127. package/dist/reality/geometry/SpatialBoxGeometry.d.ts +16 -0
  128. package/dist/reality/geometry/SpatialBoxGeometry.js +13 -0
  129. package/dist/reality/geometry/SpatialBoxGeometry.js.map +1 -0
  130. package/dist/reality/geometry/SpatialConeGeometry.d.ts +16 -0
  131. package/dist/reality/geometry/SpatialConeGeometry.js +13 -0
  132. package/dist/reality/geometry/SpatialConeGeometry.js.map +1 -0
  133. package/dist/reality/geometry/SpatialCylinderGeometry.d.ts +16 -0
  134. package/dist/reality/geometry/SpatialCylinderGeometry.js +13 -0
  135. package/dist/reality/geometry/SpatialCylinderGeometry.js.map +1 -0
  136. package/dist/reality/geometry/SpatialGeometry.d.ts +7 -0
  137. package/dist/reality/geometry/SpatialGeometry.js +13 -0
  138. package/dist/reality/geometry/SpatialGeometry.js.map +1 -0
  139. package/dist/reality/geometry/SpatialPlaneGeometry.d.ts +16 -0
  140. package/dist/reality/geometry/SpatialPlaneGeometry.js +13 -0
  141. package/dist/reality/geometry/SpatialPlaneGeometry.js.map +1 -0
  142. package/dist/reality/geometry/SpatialSphereGeometry.d.ts +16 -0
  143. package/dist/reality/geometry/SpatialSphereGeometry.js +13 -0
  144. package/dist/reality/geometry/SpatialSphereGeometry.js.map +1 -0
  145. package/dist/reality/geometry/index.d.ts +12 -0
  146. package/dist/reality/geometry/index.js +7 -0
  147. package/dist/reality/geometry/index.js.map +1 -0
  148. package/dist/reality/index.d.ts +18 -0
  149. package/dist/reality/index.js +7 -0
  150. package/dist/reality/index.js.map +1 -0
  151. package/dist/reality/material/SpatialMaterial.d.ts +7 -0
  152. package/dist/reality/material/SpatialMaterial.js +13 -0
  153. package/dist/reality/material/SpatialMaterial.js.map +1 -0
  154. package/dist/reality/material/SpatialUnlitMaterial.d.ts +16 -0
  155. package/dist/reality/material/SpatialUnlitMaterial.js +16 -0
  156. package/dist/reality/material/SpatialUnlitMaterial.js.map +1 -0
  157. package/dist/reality/material/index.d.ts +8 -0
  158. package/dist/reality/material/index.js +3 -0
  159. package/dist/reality/material/index.js.map +1 -0
  160. package/dist/reality/realityCreator.d.ts +22 -0
  161. package/dist/reality/realityCreator.js +89 -0
  162. package/dist/reality/realityCreator.js.map +1 -0
  163. package/dist/reality/resource/SpatialModelAsset.d.ts +15 -0
  164. package/dist/reality/resource/SpatialModelAsset.js +12 -0
  165. package/dist/reality/resource/SpatialModelAsset.js.map +1 -0
  166. package/dist/reality/resource/SpatialTextureResource.d.ts +16 -0
  167. package/dist/reality/resource/SpatialTextureResource.js +16 -0
  168. package/dist/reality/resource/SpatialTextureResource.js.map +1 -0
  169. package/dist/reality/resource/index.d.ts +9 -0
  170. package/dist/reality/resource/index.js +3 -0
  171. package/dist/reality/resource/index.js.map +1 -0
  172. package/dist/runtime/WebSpatialRuntimeError.d.ts +10 -0
  173. package/dist/runtime/WebSpatialRuntimeError.js +14 -0
  174. package/dist/runtime/WebSpatialRuntimeError.js.map +1 -0
  175. package/dist/runtime/capability-data.d.ts +12 -0
  176. package/dist/runtime/capability-data.js +134 -0
  177. package/dist/runtime/capability-data.js.map +1 -0
  178. package/dist/runtime/index.d.ts +8 -0
  179. package/dist/runtime/index.js +27 -0
  180. package/dist/runtime/index.js.map +1 -0
  181. package/dist/runtime/jsbAdapterPlatform.d.ts +9 -0
  182. package/dist/runtime/jsbAdapterPlatform.js +38 -0
  183. package/dist/runtime/jsbAdapterPlatform.js.map +1 -0
  184. package/dist/runtime/keys.d.ts +34 -0
  185. package/dist/runtime/keys.js +122 -0
  186. package/dist/runtime/keys.js.map +1 -0
  187. package/dist/runtime/semver.d.ts +8 -0
  188. package/dist/runtime/semver.js +32 -0
  189. package/dist/runtime/semver.js.map +1 -0
  190. package/dist/runtime/supports.d.ts +22 -0
  191. package/dist/runtime/supports.js +78 -0
  192. package/dist/runtime/supports.js.map +1 -0
  193. package/dist/runtime/types.d.ts +12 -0
  194. package/dist/runtime/types.js +1 -0
  195. package/dist/runtime/types.js.map +1 -0
  196. package/dist/runtime/userAgent.d.ts +20 -0
  197. package/dist/runtime/userAgent.js +41 -0
  198. package/dist/runtime/userAgent.js.map +1 -0
  199. package/dist/scene-polyfill.d.ts +18 -0
  200. package/dist/scene-polyfill.js +480 -0
  201. package/dist/scene-polyfill.js.map +1 -0
  202. package/dist/spatial-host.d.ts +13 -0
  203. package/dist/spatial-host.js +18 -0
  204. package/dist/spatial-host.js.map +1 -0
  205. package/dist/spatial-window-polyfill.d.ts +3 -0
  206. package/dist/spatial-window-polyfill.js +155 -0
  207. package/dist/spatial-window-polyfill.js.map +1 -0
  208. package/dist/spatializedElementMotion-_0XWPQCE.d.ts +1009 -0
  209. package/dist/types/animation.d.ts +7 -0
  210. package/dist/types/animation.js +1 -0
  211. package/dist/types/animation.js.map +1 -0
  212. package/dist/types/global.d.ts +38 -0
  213. package/dist/types/global.js +1 -0
  214. package/dist/types/global.js.map +1 -0
  215. package/dist/types/internal.d.ts +7 -0
  216. package/dist/types/internal.js +12 -0
  217. package/dist/types/internal.js.map +1 -0
  218. package/dist/types/motion/index.d.ts +7 -0
  219. package/dist/types/motion/index.js +3 -0
  220. package/dist/types/motion/index.js.map +1 -0
  221. package/dist/types/motion/spatializedElementMotion.d.ts +7 -0
  222. package/dist/types/motion/spatializedElementMotion.js +1 -0
  223. package/dist/types/motion/spatializedElementMotion.js.map +1 -0
  224. package/dist/types/motion/spatializedMotion.d.ts +7 -0
  225. package/dist/types/motion/spatializedMotion.js +16 -0
  226. package/dist/types/motion/spatializedMotion.js.map +1 -0
  227. package/dist/types/motion/spatializedPlayback.d.ts +11 -0
  228. package/dist/types/motion/spatializedPlayback.js +1 -0
  229. package/dist/types/motion/spatializedPlayback.js.map +1 -0
  230. package/dist/types/motion/spatializedVisual.d.ts +35 -0
  231. package/dist/types/motion/spatializedVisual.js +1 -0
  232. package/dist/types/motion/spatializedVisual.js.map +1 -0
  233. package/dist/types/types.d.ts +7 -0
  234. package/dist/types/types.js +117 -0
  235. package/dist/types/types.js.map +1 -0
  236. package/dist/utils.d.ts +44 -0
  237. package/dist/utils.js +86 -0
  238. package/dist/utils.js.map +1 -0
  239. package/package.json +20 -4
  240. package/src/JSBCommand.ts +148 -91
  241. package/src/Spatial.ts +0 -21
  242. package/src/SpatialObject.ts +10 -0
  243. package/src/SpatialScene.ts +1 -5
  244. package/src/SpatialSession.ts +17 -3
  245. package/src/Spatialized2DElement.ts +5 -0
  246. package/src/SpatializedDynamic3DElement.ts +5 -1
  247. package/src/SpatializedElement.ts +29 -0
  248. package/src/SpatializedElementCreator.ts +6 -4
  249. package/src/SpatializedStatic3DElement.test.ts +99 -0
  250. package/src/SpatializedStatic3DElement.ts +141 -4
  251. package/src/WebMsgCommand.ts +50 -0
  252. package/src/coverage-boost.test.ts +258 -316
  253. package/src/index.ts +28 -12
  254. package/src/install-polyfills.ts +38 -0
  255. package/src/jsbcommand.coverage.test.ts +42 -48
  256. package/src/motion/AnimationObject.test.ts +421 -0
  257. package/src/motion/AnimationObject.ts +208 -0
  258. package/src/motion/compute/index.ts +10 -0
  259. package/src/motion/compute/motionPropertyValues.test.ts +55 -0
  260. package/src/motion/compute/motionPropertyValues.ts +70 -0
  261. package/src/motion/compute/normalize.test.ts +99 -0
  262. package/src/motion/compute/normalize.ts +289 -0
  263. package/src/motion/compute/validate.test.ts +229 -0
  264. package/src/motion/compute/validate.ts +156 -0
  265. package/src/motion/index.ts +2 -0
  266. package/src/motion/native/serializeMotionTimeline.test.ts +61 -0
  267. package/src/motion/native/serializeMotionTimeline.ts +27 -0
  268. package/src/platform-adapter/CommandResultUtils.ts +2 -2
  269. package/src/platform-adapter/createPlatformSync.ts +36 -0
  270. package/src/platform-adapter/index.ts +5 -51
  271. package/src/platform-adapter/interface.ts +35 -23
  272. package/src/platform-adapter/pico-os/PicoOSPlatform.ts +156 -59
  273. package/src/platform-adapter/puppeteer/PuppeteerPlatform.ts +37 -11
  274. package/src/platform-adapter/spatialRequestMetadata.test.ts +175 -0
  275. package/src/platform-adapter/spatialRequestMetadata.ts +48 -0
  276. package/src/platform-adapter/spatialSceneQuery.ts +17 -0
  277. package/src/platform-adapter/vision-os/VisionOSPlatform.ts +60 -24
  278. package/src/platform-runtime.ts +13 -0
  279. package/src/reality/Attachment.ts +2 -2
  280. package/src/reality/entity/SpatialEntity.ts +127 -2
  281. package/src/reality/realityCreator.ts +15 -1
  282. package/src/reality/resource/SpatialTextureResource.ts +16 -0
  283. package/src/reality/resource/index.ts +1 -0
  284. package/src/runtime/WebSpatialRuntimeError.ts +16 -0
  285. package/src/runtime/capability-data.ts +213 -0
  286. package/src/runtime/contract-review.test.ts +44 -0
  287. package/src/runtime/index.ts +17 -0
  288. package/src/runtime/jsbAdapterPlatform.test.ts +36 -0
  289. package/src/runtime/jsbAdapterPlatform.ts +51 -0
  290. package/src/runtime/keys.ts +140 -0
  291. package/src/runtime/semver.ts +33 -0
  292. package/src/runtime/supports.test.ts +346 -0
  293. package/src/runtime/supports.ts +112 -0
  294. package/src/runtime/types.ts +11 -0
  295. package/src/runtime/useAnimation.capability.test.ts +275 -0
  296. package/src/runtime/userAgent.ts +64 -0
  297. package/src/scene-polyfill.manifest.test.ts +312 -9
  298. package/src/scene-polyfill.request-metadata.test.ts +39 -0
  299. package/src/scene-polyfill.test.ts +33 -94
  300. package/src/scene-polyfill.ts +125 -92
  301. package/src/spatial-host.ts +25 -0
  302. package/src/spatial-window-polyfill.ts +18 -2
  303. package/src/transform-roundtrip.test.ts +90 -0
  304. package/src/types/animation.ts +224 -0
  305. package/src/types/{global.d.ts → global.ts} +10 -12
  306. package/src/types/motion/index.ts +10 -0
  307. package/src/types/motion/spatializedElementMotion.ts +49 -0
  308. package/src/types/motion/spatializedMotion.ts +147 -0
  309. package/src/types/motion/spatializedPlayback.ts +17 -0
  310. package/src/types/motion/spatializedVisual.ts +24 -0
  311. package/src/types/types.ts +12 -0
  312. package/src/utils.ts +54 -0
  313. package/tsup.config.ts +61 -36
  314. package/vitest.config.ts +5 -1
  315. package/dist/iife/index.d.ts +0 -1101
  316. package/dist/iife/index.global.js +0 -75
  317. package/dist/iife/index.global.js.map +0 -1
  318. package/src/platform-adapter/android/AndroidPlatform.ts +0 -133
  319. package/src/platform-adapter/ssr/SSRPlatform.ts +0 -43
  320. /package/src/{ssr-polyfill.ts → isSSREnv.ts} +0 -0
@@ -1,8 +1,10 @@
1
1
  import { UpdateSpatializedStatic3DElementProperties } from './JSBCommand'
2
2
  import { ReceiveEventData, SpatializedElement } from './SpatializedElement'
3
3
  import {
4
+ ModelLoadingMode,
4
5
  ModelSource,
5
6
  SpatializedStatic3DElementProperties,
7
+ StageMode,
6
8
  } from './types/types'
7
9
  import {
8
10
  ModelLoadSuccess,
@@ -10,6 +12,7 @@ import {
10
12
  SpatialWebMsgType,
11
13
  AnimationStateChangeDetail,
12
14
  AnimationStateChangeMsg,
15
+ EntityTransformChangeMsg,
13
16
  } from './WebMsgCommand'
14
17
 
15
18
  /**
@@ -18,17 +21,29 @@ import {
18
21
  * and provides events for load success and failure.
19
22
  */
20
23
  export class SpatializedStatic3DElement extends SpatializedElement {
24
+ /**
25
+ * Identifies the motion target kind supported by this element.
26
+ */
27
+ override readonly kind = 'static3d' as const
28
+
21
29
  /**
22
30
  * Creates a new spatialized static 3D element with the specified ID and URL.
23
31
  * Registers the element to receive spatial events.
24
32
  * @param id Unique identifier for this element
25
33
  * @param modelURL URL of the 3D model
26
34
  * @param sources Optional fallback model sources
35
+ * @param loading Initial loading mode (`'eager'` by default)
27
36
  */
28
- constructor(id: string, modelURL?: string, sources?: ModelSource[]) {
37
+ constructor(
38
+ id: string,
39
+ modelURL?: string,
40
+ sources?: ModelSource[],
41
+ loading: ModelLoadingMode = 'eager',
42
+ ) {
29
43
  super(id)
30
44
  this.modelURL = modelURL
31
45
  this.sources = sources
46
+ this._loading = loading
32
47
  }
33
48
 
34
49
  /**
@@ -42,6 +57,10 @@ export class SpatializedStatic3DElement extends SpatializedElement {
42
57
  * Used to reset the ready promise when the model URL changes.
43
58
  */
44
59
  private modelURL?: string
60
+ // @TODO: Deprecate modelURL property from Web and Swift code
61
+ get modelUrl(): string | undefined {
62
+ return this.modelURL
63
+ }
45
64
 
46
65
  /**
47
66
  * Caches the last sources array to detect changes.
@@ -109,8 +128,26 @@ export class SpatializedStatic3DElement extends SpatializedElement {
109
128
  this._loop = properties.loop
110
129
  }
111
130
  if (properties.playbackRate !== undefined) {
131
+ // Re-anchor so extrapolation uses the new rate only for future elapsed
132
+ // time, not the window between the last sample and this change.
133
+ if (!this._paused) {
134
+ this._currentTime = this.currentTime
135
+ this._anchorTimestamp = Date.now()
136
+ }
112
137
  this._playbackRate = properties.playbackRate
113
138
  }
139
+ if (properties.currentTime !== undefined) {
140
+ // Optimistically update the local anchor so subsequent reads reflect
141
+ // the requested seek without waiting for the next native sample.
142
+ this._currentTime = properties.currentTime
143
+ this._anchorTimestamp = Date.now()
144
+ }
145
+ if (properties.loading !== undefined) {
146
+ this._loading = properties.loading
147
+ }
148
+ if (properties.stagemode !== undefined) {
149
+ this._stagemode = properties.stagemode
150
+ }
114
151
  return new UpdateSpatializedStatic3DElementProperties(
115
152
  this,
116
153
  properties,
@@ -148,6 +185,49 @@ export class SpatializedStatic3DElement extends SpatializedElement {
148
185
  this.updateProperties({ playbackRate: value })
149
186
  }
150
187
 
188
+ /**
189
+ * Last playback position sampled from native (seconds).
190
+ */
191
+ private _currentTime: number = 0
192
+
193
+ /**
194
+ * Unix epoch time (ms) corresponding to `_currentTime`. Sourced from the
195
+ * native `timestamp` on samples, or `Date.now()` on local seeks/transitions.
196
+ */
197
+ private _anchorTimestamp: number = 0
198
+
199
+ private clampTime(time: number): number {
200
+ if (!Number.isFinite(time) || time < 0) return 0
201
+ // When looping the current time is modulo the duration
202
+ if (time > this._duration) {
203
+ return this.loop && this.duration > 0
204
+ ? time % this._duration
205
+ : this.duration
206
+ }
207
+ return time
208
+ }
209
+
210
+ /**
211
+ * Returns the current (un-scaled) playback position in seconds. While
212
+ * playing, the value is extrapolated from the last anchor using
213
+ * `playbackRate` and clamped to `[0, duration]`; while paused it returns
214
+ * the anchor directly.
215
+ */
216
+ get currentTime(): number {
217
+ if (this._paused) return this._currentTime
218
+ const elapsed = (Date.now() - this._anchorTimestamp) / 1000
219
+ return this.clampTime(this._currentTime + elapsed * this._playbackRate)
220
+ }
221
+
222
+ /**
223
+ * Seeks the animation to `value` seconds (clamped to `[0, duration]`) and
224
+ * forwards the request to native.
225
+ */
226
+ set currentTime(value: number) {
227
+ const time = Number.isNaN(value) ? 0 : clamp(value, 0, this.duration)
228
+ this.updateProperties({ currentTime: time })
229
+ }
230
+
151
231
  /**
152
232
  * Whether the animation is currently paused.
153
233
  */
@@ -181,6 +261,10 @@ export class SpatializedStatic3DElement extends SpatializedElement {
181
261
  * @returns Promise resolving when the command is sent
182
262
  */
183
263
  async play(): Promise<void> {
264
+ if (this._paused) {
265
+ // Start extrapolating from the last known position on resume.
266
+ this._anchorTimestamp = Date.now()
267
+ }
184
268
  this._paused = false
185
269
  await this.updateProperties({ animationPaused: false })
186
270
  }
@@ -190,6 +274,12 @@ export class SpatializedStatic3DElement extends SpatializedElement {
190
274
  * @returns Promise resolving when the command is sent
191
275
  */
192
276
  async pause(): Promise<void> {
277
+ if (!this._paused) {
278
+ // Freeze the extrapolated position so reads remain stable until the
279
+ // next native sample arrives.
280
+ this._currentTime = this.currentTime
281
+ this._anchorTimestamp = Date.now()
282
+ }
193
283
  this._paused = true
194
284
  await this.updateProperties({ animationPaused: true })
195
285
  }
@@ -213,7 +303,12 @@ export class SpatializedStatic3DElement extends SpatializedElement {
213
303
  } else if (data.type === SpatialWebMsgType.animationstatechange) {
214
304
  this._paused = data.detail.paused
215
305
  this._duration = data.detail.duration
306
+ // In unsupported environments currentTime is invalid
307
+ this._currentTime = data.detail.currentTime ?? 0
308
+ this._anchorTimestamp = data.detail.timestamp ?? Date.now()
216
309
  this._onAnimationStateChangeCallback?.(data.detail)
310
+ } else if (data.type === SpatialWebMsgType.entitytransformchange) {
311
+ this._entityTransform = new DOMMatrixReadOnly(data.detail.transform)
217
312
  } else {
218
313
  // Handle other spatial events using the base class implementation
219
314
  super.onReceiveEvent(data)
@@ -232,6 +327,16 @@ export class SpatializedStatic3DElement extends SpatializedElement {
232
327
  return this._autoplay
233
328
  }
234
329
 
330
+ /**
331
+ * Asset fetch policy. `'lazy'` defers fetching until the host signals the
332
+ * element is in view; `'eager'` fetches immediately.
333
+ */
334
+ private _loading: ModelLoadingMode = 'eager'
335
+
336
+ get loading(): ModelLoadingMode {
337
+ return this._loading
338
+ }
339
+
235
340
  /**
236
341
  * Whether the model animation should loop continuously.
237
342
  */
@@ -270,10 +375,41 @@ export class SpatializedStatic3DElement extends SpatializedElement {
270
375
  this._onLoadFailureCallback = callback
271
376
  }
272
377
 
273
- updateModelTransform(transform: DOMMatrixReadOnly) {
274
- const modelTransform = Array.from(transform.toFloat64Array())
275
- this.updateProperties({ modelTransform })
378
+ /**
379
+ * Built-in interaction mode. In `'orbit'` the native layer drives the
380
+ * transform and `entityTransform` is read-only.
381
+ */
382
+ private _stagemode: StageMode = 'none'
383
+
384
+ get stagemode(): StageMode {
385
+ return this._stagemode
386
+ }
387
+
388
+ /**
389
+ * Latest transform of the model, including native-driven manipulations such
390
+ * as orbit interaction.
391
+ */
392
+ private _entityTransform: DOMMatrixReadOnly = new DOMMatrixReadOnly()
393
+
394
+ get entityTransform(): DOMMatrixReadOnly {
395
+ return this._entityTransform
276
396
  }
397
+
398
+ set entityTransform(transform: DOMMatrixReadOnly) {
399
+ // In orbit mode the native layer owns the transform, so ignore writes.
400
+ if (this._stagemode === 'orbit') return
401
+ this._entityTransform = transform
402
+ // The public API is `entityTransform`, but the JSB property stays
403
+ // `modelTransform` so the native side remains backward compatible.
404
+ this.updateProperties({
405
+ modelTransform: Array.from(transform.toFloat64Array()),
406
+ })
407
+ }
408
+ }
409
+
410
+ // Equivalent of proposed Math.clamp
411
+ function clamp(num: number, min: number, max: number) {
412
+ return num <= min ? min : num >= max ? max : num
277
413
  }
278
414
 
279
415
  type Static3DReceiveEventData =
@@ -281,3 +417,4 @@ type Static3DReceiveEventData =
281
417
  | ModelLoadFailure
282
418
  | ReceiveEventData
283
419
  | AnimationStateChangeMsg
420
+ | EntityTransformChangeMsg
@@ -21,6 +21,14 @@ export enum SpatialWebMsgType {
21
21
 
22
22
  animationstatechange = 'animationstatechange',
23
23
 
24
+ // Native-driven transform updates (e.g. while in `stagemode="orbit"`)
25
+ entitytransformchange = 'entitytransformchange',
26
+
27
+ // Animation terminal events (keyed by animationId, not by this enum)
28
+ animationcompleted = 'animationcompleted',
29
+ animationstopped = 'animationstopped',
30
+ animationfailed = 'animationfailed',
31
+
24
32
  objectdestroy = 'objectdestroy',
25
33
  }
26
34
 
@@ -81,9 +89,51 @@ export interface ModelLoadFailure {
81
89
  export interface AnimationStateChangeDetail {
82
90
  paused: boolean
83
91
  duration: number
92
+ /**
93
+ * Sampled animation playback position in seconds at `timestamp`.
94
+ * Optional for compatibility with older native runtimes.
95
+ */
96
+ currentTime?: number
97
+ /**
98
+ * Unix epoch time in milliseconds at which `currentTime` was sampled.
99
+ * Used to extrapolate `currentTime` between samples while playing.
100
+ */
101
+ timestamp?: number
84
102
  }
85
103
 
86
104
  export interface AnimationStateChangeMsg {
87
105
  type: SpatialWebMsgType.animationstatechange
88
106
  detail: AnimationStateChangeDetail
89
107
  }
108
+
109
+ export interface EntityTransformChangeDetail {
110
+ /** Column-major 4x4 matrix (16 numbers) representing the manipulated transform. */
111
+ transform: number[]
112
+ }
113
+
114
+ export interface EntityTransformChangeMsg {
115
+ type: SpatialWebMsgType.entitytransformchange
116
+ detail: EntityTransformChangeDetail
117
+ }
118
+
119
+ // Animation terminal event payloads (delivered via SpatialWebEvent keyed by animationId)
120
+
121
+ export interface AnimationCompletedEventPayload {
122
+ type: 'completed'
123
+ /** Column-major 4x4 matrix (16 numbers) representing the final native transform. */
124
+ transform: number[]
125
+ }
126
+
127
+ export interface AnimationCanceledEventPayload {
128
+ type: 'canceled'
129
+ /** Column-major 4x4 matrix (16 numbers) representing the restored transform after cancel. */
130
+ transform: number[]
131
+ }
132
+
133
+ export interface AnimationFailedEventPayload {
134
+ type: 'failed'
135
+ animationId: string
136
+ command: 'play' | 'pause' | 'resume' | 'cancel'
137
+ code?: string
138
+ reason: string
139
+ }