@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
@@ -0,0 +1,140 @@
1
+ import {
2
+ ControlSpatializedElementAnimationJSBCommand,
3
+ CreateSpatializedElementAnimationJSBCommand
4
+ } from "../JSBCommand";
5
+ import { SpatialObject } from "../SpatialObject";
6
+ import { SpatialWebEvent } from "../SpatialWebEvent";
7
+ class AnimationObject extends SpatialObject {
8
+ elementId;
9
+ timeline;
10
+ callbacks = {};
11
+ _playState = "idle";
12
+ _finished = false;
13
+ started = false;
14
+ constructor(id, options) {
15
+ super(id);
16
+ this.elementId = options.elementId;
17
+ this.timeline = options.timeline;
18
+ SpatialWebEvent.addEventReceiver(id, (data) => this.onReceiveEvent(data));
19
+ }
20
+ static async create(options) {
21
+ const ret = await new CreateSpatializedElementAnimationJSBCommand({
22
+ elementId: options.elementId,
23
+ timeline: options.timeline
24
+ }).execute();
25
+ if (!ret.success) {
26
+ throw new Error(
27
+ ret.errorMessage ?? "CreateSpatializedElementAnimation command failed"
28
+ );
29
+ }
30
+ const data = ret.data;
31
+ const id = data?.id;
32
+ if (!id) {
33
+ throw new Error("CreateSpatializedElementAnimation did not return an id");
34
+ }
35
+ return new AnimationObject(id, options);
36
+ }
37
+ setCallbacks(callbacks) {
38
+ this.callbacks = callbacks;
39
+ }
40
+ get playState() {
41
+ return this._playState;
42
+ }
43
+ get isAnimating() {
44
+ return this._playState === "running" || this._playState === "queued";
45
+ }
46
+ get isPaused() {
47
+ return this._playState === "paused";
48
+ }
49
+ get finished() {
50
+ return this._finished;
51
+ }
52
+ play() {
53
+ return this.control("play");
54
+ }
55
+ pause() {
56
+ return this.control("pause");
57
+ }
58
+ stop() {
59
+ return this.control("stop");
60
+ }
61
+ reset() {
62
+ return this.control("reset");
63
+ }
64
+ finish() {
65
+ return this.control("finish");
66
+ }
67
+ onDestroy() {
68
+ SpatialWebEvent.removeEventReceiver(this.id);
69
+ }
70
+ async control(type) {
71
+ if (this.isDestroyed) return;
72
+ const ret = await new ControlSpatializedElementAnimationJSBCommand({
73
+ animationId: this.id,
74
+ type
75
+ }).execute();
76
+ if (!ret.success) {
77
+ throw new Error(
78
+ ret.errorMessage ?? `ControlSpatializedElementAnimation(${type}) command failed`
79
+ );
80
+ }
81
+ }
82
+ onReceiveEvent(data) {
83
+ const detail = data?.detail ?? data;
84
+ if (!this.isSpatialAnimationStateChangedDetail(detail)) return;
85
+ if (detail.animationId !== this.id) return;
86
+ this._playState = detail.playState;
87
+ this._finished = detail.finished;
88
+ if (detail.values) {
89
+ this.callbacks.onValuesChange?.(detail.values);
90
+ }
91
+ if (detail.action !== "start") {
92
+ this.callbacks.onStateChange?.();
93
+ }
94
+ if (detail.error) {
95
+ this.started = false;
96
+ this.callbacks.onError?.({
97
+ command: "play",
98
+ code: detail.error.code,
99
+ reason: detail.error.message
100
+ });
101
+ return;
102
+ }
103
+ if (detail.action === "start") {
104
+ if (!this.started) {
105
+ this.started = true;
106
+ this.callbacks.onStart?.();
107
+ }
108
+ return;
109
+ }
110
+ if (detail.action === "complete" || detail.action === "finish") {
111
+ this.started = false;
112
+ this.callbacks.onComplete?.(detail.values ?? {});
113
+ return;
114
+ }
115
+ if (detail.action === "stop") {
116
+ this.started = false;
117
+ this.callbacks.onStop?.(detail.values ?? {});
118
+ return;
119
+ }
120
+ if (detail.action === "reset") {
121
+ this.started = false;
122
+ this.callbacks.onReset?.(detail.values ?? {});
123
+ return;
124
+ }
125
+ if (detail.action === "destroy") {
126
+ this.started = false;
127
+ this.isDestroyed = true;
128
+ this.onDestroy();
129
+ }
130
+ }
131
+ isSpatialAnimationStateChangedDetail(detail) {
132
+ if (!detail || typeof detail !== "object") return false;
133
+ const candidate = detail;
134
+ return typeof candidate.animationId === "string" && typeof candidate.action === "string" && typeof candidate.playState === "string" && typeof candidate.finished === "boolean";
135
+ }
136
+ }
137
+ export {
138
+ AnimationObject
139
+ };
140
+ //# sourceMappingURL=AnimationObject.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/motion/AnimationObject.ts"],"sourcesContent":["import {\n ControlSpatializedElementAnimationJSBCommand,\n CreateSpatializedElementAnimationJSBCommand,\n} from '../JSBCommand'\nimport { SpatialObject } from '../SpatialObject'\nimport { SpatialWebEvent } from '../SpatialWebEvent'\nimport type {\n ControlSpatializedElementAnimationCommand,\n SpatialAnimationStateChangedDetail,\n SpatialAnimationStateChangedMsg,\n} from '../types/motion/spatializedElementMotion'\nimport type { SpatializedPlaybackError } from '../types/motion/spatializedPlayback'\nimport type { SpatializedVisualValues } from '../types/motion/spatializedVisual'\nimport type {\n SpatializedMotionTimeline,\n SpatializedPlaybackApi,\n SpatializedMotionPlayState,\n} from '../types/motion/spatializedMotion'\n\nexport interface AnimationObjectCreateOptions {\n elementId: string\n timeline: SpatializedMotionTimeline\n}\n\nexport interface AnimationObjectCallbacks {\n onStart?: () => void\n onComplete?: (values: SpatializedVisualValues) => void\n onStop?: (values: SpatializedVisualValues) => void\n onReset?: (values: SpatializedVisualValues) => void\n onError?: (error: SpatializedPlaybackError) => void\n onValuesChange?: (values: SpatializedVisualValues) => void\n onStateChange?: () => void\n}\n\nexport class AnimationObject\n extends SpatialObject\n implements SpatializedPlaybackApi\n{\n readonly elementId: string\n readonly timeline: SpatializedMotionTimeline\n\n private callbacks: AnimationObjectCallbacks = {}\n private _playState: SpatializedMotionPlayState = 'idle'\n private _finished = false\n private started = false\n\n constructor(id: string, options: AnimationObjectCreateOptions) {\n super(id)\n this.elementId = options.elementId\n this.timeline = options.timeline\n\n SpatialWebEvent.addEventReceiver(id, data => this.onReceiveEvent(data))\n }\n\n static async create(options: AnimationObjectCreateOptions) {\n const ret = await new CreateSpatializedElementAnimationJSBCommand({\n elementId: options.elementId,\n timeline: options.timeline,\n }).execute()\n if (!ret.success) {\n throw new Error(\n ret.errorMessage ?? 'CreateSpatializedElementAnimation command failed',\n )\n }\n\n const data = ret.data as { id?: string } | undefined\n const id = data?.id\n if (!id) {\n throw new Error('CreateSpatializedElementAnimation did not return an id')\n }\n\n return new AnimationObject(id, options)\n }\n\n setCallbacks(callbacks: AnimationObjectCallbacks): void {\n this.callbacks = callbacks\n }\n\n get playState() {\n return this._playState\n }\n\n get isAnimating() {\n return this._playState === 'running' || this._playState === 'queued'\n }\n\n get isPaused() {\n return this._playState === 'paused'\n }\n\n get finished() {\n return this._finished\n }\n\n play(): Promise<void> {\n return this.control('play')\n }\n\n pause(): Promise<void> {\n return this.control('pause')\n }\n\n stop(): Promise<void> {\n return this.control('stop')\n }\n\n reset(): Promise<void> {\n return this.control('reset')\n }\n\n finish(): Promise<void> {\n return this.control('finish')\n }\n\n protected override onDestroy(): void {\n SpatialWebEvent.removeEventReceiver(this.id)\n }\n\n private async control(\n type: ControlSpatializedElementAnimationCommand['type'],\n ): Promise<void> {\n if (this.isDestroyed) return\n\n const ret = await new ControlSpatializedElementAnimationJSBCommand({\n animationId: this.id,\n type,\n }).execute()\n\n if (!ret.success) {\n throw new Error(\n ret.errorMessage ??\n `ControlSpatializedElementAnimation(${type}) command failed`,\n )\n }\n }\n\n onReceiveEvent(data: SpatialAnimationStateChangedMsg | { detail?: unknown }) {\n const detail = data?.detail ?? data\n if (!this.isSpatialAnimationStateChangedDetail(detail)) return\n if (detail.animationId !== this.id) return\n\n this._playState = detail.playState\n this._finished = detail.finished\n\n if (detail.values) {\n this.callbacks.onValuesChange?.(detail.values)\n }\n if (detail.action !== 'start') {\n this.callbacks.onStateChange?.()\n }\n\n if (detail.error) {\n this.started = false\n // Native currently emits asynchronous errors only when play cannot acquire the ownership mask.\n this.callbacks.onError?.({\n command: 'play',\n code: detail.error.code,\n reason: detail.error.message,\n })\n return\n }\n\n if (detail.action === 'start') {\n if (!this.started) {\n this.started = true\n this.callbacks.onStart?.()\n }\n return\n }\n\n if (detail.action === 'complete' || detail.action === 'finish') {\n this.started = false\n this.callbacks.onComplete?.(detail.values ?? {})\n return\n }\n\n if (detail.action === 'stop') {\n this.started = false\n this.callbacks.onStop?.(detail.values ?? {})\n return\n }\n\n if (detail.action === 'reset') {\n this.started = false\n this.callbacks.onReset?.(detail.values ?? {})\n return\n }\n\n if (detail.action === 'destroy') {\n this.started = false\n this.isDestroyed = true\n this.onDestroy()\n }\n }\n\n private isSpatialAnimationStateChangedDetail(\n detail: unknown,\n ): detail is SpatialAnimationStateChangedDetail {\n if (!detail || typeof detail !== 'object') return false\n const candidate = detail as Partial<SpatialAnimationStateChangedDetail>\n return (\n typeof candidate.animationId === 'string' &&\n typeof candidate.action === 'string' &&\n typeof candidate.playState === 'string' &&\n typeof candidate.finished === 'boolean'\n )\n }\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,10 @@
1
+ export { setMotionPropertyValue } from './motionPropertyValues.js';
2
+ export { validateNormalizedMotionConfig, validateSpatializedMotionConfig } from './validate.js';
3
+ export { desugarTimelineConfig, normalizeMotionConfig, segmentConfigToMotionConfig } from './normalize.js';
4
+ import '../../types/motion/spatializedVisual.js';
5
+ import '../../spatializedElementMotion-_0XWPQCE.js';
6
+ import '../../types/motion/spatializedPlayback.js';
7
+ import '../../types/global.js';
8
+ import '../../physicalMetrics-W5uZ5xKb.js';
9
+ import '../../SpatialObject.js';
10
+ import '../../reality/component/SpatialComponent.js';
@@ -0,0 +1,19 @@
1
+ import { setMotionPropertyValue } from "./motionPropertyValues";
2
+ import {
3
+ validateNormalizedMotionConfig,
4
+ validateSpatializedMotionConfig
5
+ } from "./validate";
6
+ import {
7
+ desugarTimelineConfig,
8
+ normalizeMotionConfig,
9
+ segmentConfigToMotionConfig
10
+ } from "./normalize";
11
+ export {
12
+ desugarTimelineConfig,
13
+ normalizeMotionConfig,
14
+ segmentConfigToMotionConfig,
15
+ setMotionPropertyValue,
16
+ validateNormalizedMotionConfig,
17
+ validateSpatializedMotionConfig
18
+ };
19
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/motion/compute/index.ts"],"sourcesContent":["export { setMotionPropertyValue } from './motionPropertyValues'\nexport {\n validateNormalizedMotionConfig,\n validateSpatializedMotionConfig,\n} from './validate'\nexport {\n desugarTimelineConfig,\n normalizeMotionConfig,\n segmentConfigToMotionConfig,\n} from './normalize'\n"],"mappings":"AAAA,SAAS,8BAA8B;AACvC;AAAA,EACE;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;","names":[]}
@@ -0,0 +1,19 @@
1
+ import { SpatializedVisualValues } from '../../types/motion/spatializedVisual.js';
2
+ import { a_ as SpatializedMotionProperty } from '../../spatializedElementMotion-_0XWPQCE.js';
3
+ import '../../types/motion/spatializedPlayback.js';
4
+ import '../../types/global.js';
5
+ import '../../physicalMetrics-W5uZ5xKb.js';
6
+ import '../../SpatialObject.js';
7
+ import '../../reality/component/SpatialComponent.js';
8
+
9
+ /**
10
+ * Writes a sampled numeric track value into the corresponding
11
+ * SpatializedVisualValues field.
12
+ *
13
+ * @param visualValues Visual value object being populated for the sampled time.
14
+ * @param motionProperty Motion property path for the sampled track.
15
+ * @param sampledValue Numeric value sampled from the track at the current time.
16
+ */
17
+ declare function setMotionPropertyValue(visualValues: SpatializedVisualValues, motionProperty: SpatializedMotionProperty, sampledValue: number): void;
18
+
19
+ export { setMotionPropertyValue };
@@ -0,0 +1,50 @@
1
+ function getTranslate(visualValues) {
2
+ const transform = visualValues.transform ??= {};
3
+ return transform.translate ??= {};
4
+ }
5
+ function getRotate(visualValues) {
6
+ const transform = visualValues.transform ??= {};
7
+ return transform.rotate ??= {};
8
+ }
9
+ function getScale(visualValues) {
10
+ const transform = visualValues.transform ??= {};
11
+ return transform.scale ??= {};
12
+ }
13
+ function setMotionPropertyValue(visualValues, motionProperty, sampledValue) {
14
+ switch (motionProperty) {
15
+ case "opacity":
16
+ visualValues.opacity = sampledValue;
17
+ return;
18
+ case "transform.translate.x":
19
+ getTranslate(visualValues).x = sampledValue;
20
+ return;
21
+ case "transform.translate.y":
22
+ getTranslate(visualValues).y = sampledValue;
23
+ return;
24
+ case "transform.translate.z":
25
+ getTranslate(visualValues).z = sampledValue;
26
+ return;
27
+ case "transform.rotate.x":
28
+ getRotate(visualValues).x = sampledValue;
29
+ return;
30
+ case "transform.rotate.y":
31
+ getRotate(visualValues).y = sampledValue;
32
+ return;
33
+ case "transform.rotate.z":
34
+ getRotate(visualValues).z = sampledValue;
35
+ return;
36
+ case "transform.scale.x":
37
+ getScale(visualValues).x = sampledValue;
38
+ return;
39
+ case "transform.scale.y":
40
+ getScale(visualValues).y = sampledValue;
41
+ return;
42
+ case "transform.scale.z":
43
+ getScale(visualValues).z = sampledValue;
44
+ return;
45
+ }
46
+ }
47
+ export {
48
+ setMotionPropertyValue
49
+ };
50
+ //# sourceMappingURL=motionPropertyValues.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/motion/compute/motionPropertyValues.ts"],"sourcesContent":["import type { SpatializedVisualValues } from '../../types/motion/spatializedVisual'\nimport type { SpatializedMotionProperty } from '../../types/motion/spatializedMotion'\n\nfunction getTranslate(\n visualValues: SpatializedVisualValues,\n): NonNullable<NonNullable<SpatializedVisualValues['transform']>['translate']> {\n const transform = (visualValues.transform ??= {})\n return (transform.translate ??= {})\n}\n\nfunction getRotate(\n visualValues: SpatializedVisualValues,\n): NonNullable<NonNullable<SpatializedVisualValues['transform']>['rotate']> {\n const transform = (visualValues.transform ??= {})\n return (transform.rotate ??= {})\n}\n\nfunction getScale(\n visualValues: SpatializedVisualValues,\n): NonNullable<NonNullable<SpatializedVisualValues['transform']>['scale']> {\n const transform = (visualValues.transform ??= {})\n return (transform.scale ??= {})\n}\n\n/**\n * Writes a sampled numeric track value into the corresponding\n * SpatializedVisualValues field.\n *\n * @param visualValues Visual value object being populated for the sampled time.\n * @param motionProperty Motion property path for the sampled track.\n * @param sampledValue Numeric value sampled from the track at the current time.\n */\nexport function setMotionPropertyValue(\n visualValues: SpatializedVisualValues,\n motionProperty: SpatializedMotionProperty,\n sampledValue: number,\n): void {\n switch (motionProperty) {\n case 'opacity':\n visualValues.opacity = sampledValue\n return\n case 'transform.translate.x':\n getTranslate(visualValues).x = sampledValue\n return\n case 'transform.translate.y':\n getTranslate(visualValues).y = sampledValue\n return\n case 'transform.translate.z':\n getTranslate(visualValues).z = sampledValue\n return\n case 'transform.rotate.x':\n getRotate(visualValues).x = sampledValue\n return\n case 'transform.rotate.y':\n getRotate(visualValues).y = sampledValue\n return\n case 'transform.rotate.z':\n getRotate(visualValues).z = sampledValue\n return\n case 'transform.scale.x':\n getScale(visualValues).x = sampledValue\n return\n case 'transform.scale.y':\n getScale(visualValues).y = sampledValue\n return\n case 'transform.scale.z':\n getScale(visualValues).z = sampledValue\n return\n }\n}\n"],"mappings":"AAGA,SAAS,aACP,cAC6E;AAC7E,QAAM,YAAa,aAAa,cAAc,CAAC;AAC/C,SAAQ,UAAU,cAAc,CAAC;AACnC;AAEA,SAAS,UACP,cAC0E;AAC1E,QAAM,YAAa,aAAa,cAAc,CAAC;AAC/C,SAAQ,UAAU,WAAW,CAAC;AAChC;AAEA,SAAS,SACP,cACyE;AACzE,QAAM,YAAa,aAAa,cAAc,CAAC;AAC/C,SAAQ,UAAU,UAAU,CAAC;AAC/B;AAUO,SAAS,uBACd,cACA,gBACA,cACM;AACN,UAAQ,gBAAgB;AAAA,IACtB,KAAK;AACH,mBAAa,UAAU;AACvB;AAAA,IACF,KAAK;AACH,mBAAa,YAAY,EAAE,IAAI;AAC/B;AAAA,IACF,KAAK;AACH,mBAAa,YAAY,EAAE,IAAI;AAC/B;AAAA,IACF,KAAK;AACH,mBAAa,YAAY,EAAE,IAAI;AAC/B;AAAA,IACF,KAAK;AACH,gBAAU,YAAY,EAAE,IAAI;AAC5B;AAAA,IACF,KAAK;AACH,gBAAU,YAAY,EAAE,IAAI;AAC5B;AAAA,IACF,KAAK;AACH,gBAAU,YAAY,EAAE,IAAI;AAC5B;AAAA,IACF,KAAK;AACH,eAAS,YAAY,EAAE,IAAI;AAC3B;AAAA,IACF,KAAK;AACH,eAAS,YAAY,EAAE,IAAI;AAC3B;AAAA,IACF,KAAK;AACH,eAAS,YAAY,EAAE,IAAI;AAC3B;AAAA,EACJ;AACF;","names":[]}
@@ -0,0 +1,31 @@
1
+ import { an as SpatializedMotionTimelineConfig, a$ as NormalizedSpatializedMotionConfig, aj as SpatializedMotionConfig, am as SpatializedMotionSegmentConfig } from '../../spatializedElementMotion-_0XWPQCE.js';
2
+ import '../../types/motion/spatializedVisual.js';
3
+ import '../../types/motion/spatializedPlayback.js';
4
+ import '../../types/global.js';
5
+ import '../../physicalMetrics-W5uZ5xKb.js';
6
+ import '../../SpatialObject.js';
7
+ import '../../reality/component/SpatialComponent.js';
8
+
9
+ /**
10
+ * Desugars shorthand from/to motion config into canonical tracks.
11
+ *
12
+ * @param simple Shorthand segment config.
13
+ * @returns Canonical track-based motion config.
14
+ */
15
+ declare function segmentConfigToMotionConfig(simple: SpatializedMotionSegmentConfig): NormalizedSpatializedMotionConfig;
16
+ /**
17
+ * Desugars percentage-key timeline config into canonical tracks.
18
+ *
19
+ * @param config Timeline config using percentage keys.
20
+ * @returns Canonical track-based motion config.
21
+ */
22
+ declare function desugarTimelineConfig(config: SpatializedMotionTimelineConfig): NormalizedSpatializedMotionConfig;
23
+ /**
24
+ * Normalizes any supported motion config shape into canonical tracks.
25
+ *
26
+ * @param config Motion config in shorthand, timeline, or canonical form.
27
+ * @returns Canonical track-based motion config.
28
+ */
29
+ declare function normalizeMotionConfig(config: SpatializedMotionConfig): NormalizedSpatializedMotionConfig;
30
+
31
+ export { desugarTimelineConfig, normalizeMotionConfig, segmentConfigToMotionConfig };
@@ -0,0 +1,201 @@
1
+ function collectScalars(values, out) {
2
+ if (values.opacity !== void 0) {
3
+ out.push({ property: "opacity", value: values.opacity });
4
+ }
5
+ const tr = values.transform;
6
+ if (!tr) return;
7
+ for (const group of ["translate", "rotate", "scale"]) {
8
+ const part = tr[group];
9
+ if (!part) continue;
10
+ for (const axis of ["x", "y", "z"]) {
11
+ const v = part[axis];
12
+ if (v !== void 0) {
13
+ out.push({
14
+ property: `transform.${group}.${axis}`,
15
+ value: v
16
+ });
17
+ }
18
+ }
19
+ }
20
+ }
21
+ function parsePercentageKey(key) {
22
+ if (!/^\d+(\.\d+)?%$/.test(key)) {
23
+ throw new Error(`[SpatializedMotion] invalid timeline key "${key}"`);
24
+ }
25
+ const ratio = Number(key.slice(0, -1));
26
+ if (!Number.isFinite(ratio) || ratio < 0 || ratio > 100) {
27
+ throw new Error(`[SpatializedMotion] invalid timeline key "${key}"`);
28
+ }
29
+ return ratio / 100;
30
+ }
31
+ function segmentConfigToMotionConfig(simple) {
32
+ if (!simple.from || !simple.to) {
33
+ throw new Error(
34
+ "[SpatializedMotion] top-level from and to are both required"
35
+ );
36
+ }
37
+ const duration = simple.duration ?? 0.3;
38
+ const fromScalars = [];
39
+ const toScalars = [];
40
+ collectScalars(simple.from, fromScalars);
41
+ collectScalars(simple.to, toScalars);
42
+ const trackMap = /* @__PURE__ */ new Map();
43
+ const properties = /* @__PURE__ */ new Set([
44
+ ...fromScalars.map((entry) => entry.property),
45
+ ...toScalars.map((entry) => entry.property)
46
+ ]);
47
+ for (const property of properties) {
48
+ const fromEntry = fromScalars.find((f) => f.property === property);
49
+ const toEntry = toScalars.find((f) => f.property === property);
50
+ if (!fromEntry) {
51
+ throw new Error(
52
+ `[SpatializedMotion] missing start boundary for "${property}"`
53
+ );
54
+ }
55
+ if (!toEntry) {
56
+ throw new Error(
57
+ `[SpatializedMotion] missing end boundary for "${property}"`
58
+ );
59
+ }
60
+ trackMap.set(property, {
61
+ property,
62
+ timingFunction: simple.timingFunction,
63
+ keyframes: [
64
+ { at: 0, value: fromEntry.value },
65
+ { at: duration, value: toEntry.value }
66
+ ]
67
+ });
68
+ }
69
+ const tracks = [...trackMap.values()];
70
+ if (tracks.length === 0) {
71
+ throw new Error(
72
+ "[SpatializedMotion.simple] to must include at least one animatable field"
73
+ );
74
+ }
75
+ return {
76
+ duration,
77
+ tracks,
78
+ timingFunction: simple.timingFunction,
79
+ delay: simple.delay,
80
+ autoStart: simple.autoStart,
81
+ loop: simple.loop,
82
+ playbackRate: simple.playbackRate,
83
+ onStart: simple.onStart,
84
+ onComplete: simple.onComplete,
85
+ onStop: simple.onStop,
86
+ onReset: simple.onReset,
87
+ onError: simple.onError
88
+ };
89
+ }
90
+ function desugarTimelineConfig(config) {
91
+ if (Array.isArray(config.timeline) || !config.timeline) {
92
+ throw new Error("[SpatializedMotion] timeline must be an object");
93
+ }
94
+ const entries = Object.entries(config.timeline);
95
+ let hasPercentageKey = false;
96
+ const frames = entries.map(([key, values]) => {
97
+ if (!values || typeof values !== "object" || Array.isArray(values)) {
98
+ throw new Error(`[SpatializedMotion] invalid timeline frame "${key}"`);
99
+ }
100
+ if (key === "from") return { key, atRatio: 0, values };
101
+ if (key === "to") return { key, atRatio: 1, values };
102
+ hasPercentageKey = true;
103
+ return { key, atRatio: parsePercentageKey(key), values };
104
+ }).sort((a, b) => a.atRatio - b.atRatio);
105
+ if (config.from !== void 0 || config.to !== void 0) {
106
+ console.warn(
107
+ "[SpatializedMotion] top-level from/to are ignored because timeline is present"
108
+ );
109
+ }
110
+ const hasStartFrame = frames.some((frame) => frame.atRatio === 0);
111
+ const hasEndFrame = frames.some((frame) => frame.atRatio === 1);
112
+ if (!hasStartFrame) {
113
+ throw new Error(
114
+ "[SpatializedMotion] timeline must define a start frame (from or 0%)"
115
+ );
116
+ }
117
+ if (!hasEndFrame) {
118
+ throw new Error(
119
+ "[SpatializedMotion] timeline must define an end frame (to or 100%)"
120
+ );
121
+ }
122
+ if (hasPercentageKey && config.duration === void 0) {
123
+ throw new Error(
124
+ "[SpatializedMotion] duration is required when timeline uses percentage keys"
125
+ );
126
+ }
127
+ const duration = config.duration ?? 0.3;
128
+ const trackMap = /* @__PURE__ */ new Map();
129
+ const fromProperties = /* @__PURE__ */ new Set();
130
+ const zeroProperties = /* @__PURE__ */ new Set();
131
+ const toProperties = /* @__PURE__ */ new Set();
132
+ const hundredProperties = /* @__PURE__ */ new Set();
133
+ for (const frame of frames) {
134
+ const at = frame.atRatio * duration;
135
+ const scalars = [];
136
+ collectScalars(frame.values, scalars);
137
+ for (const scalar of scalars) {
138
+ if (frame.key === "from") fromProperties.add(scalar.property);
139
+ if (frame.key !== "from" && frame.atRatio === 0) {
140
+ zeroProperties.add(scalar.property);
141
+ }
142
+ if (frame.key === "to") toProperties.add(scalar.property);
143
+ if (frame.key !== "to" && frame.atRatio === 1) {
144
+ hundredProperties.add(scalar.property);
145
+ }
146
+ const keyframes = trackMap.get(scalar.property) ?? [];
147
+ const keyframe = {
148
+ at,
149
+ value: scalar.value,
150
+ ...frame.values.timingFunction !== void 0 ? { timingFunction: frame.values.timingFunction } : {}
151
+ };
152
+ keyframes.push(keyframe);
153
+ trackMap.set(scalar.property, keyframes);
154
+ }
155
+ }
156
+ const tracks = [...trackMap.entries()].map(([property, keyframes]) => {
157
+ const startCount = Number(fromProperties.has(property)) + Number(zeroProperties.has(property));
158
+ const endCount = Number(toProperties.has(property)) + Number(hundredProperties.has(property));
159
+ if (startCount > 1) {
160
+ throw new Error(
161
+ `[SpatializedMotion] duplicate start boundary for "${property}"`
162
+ );
163
+ }
164
+ if (endCount > 1) {
165
+ throw new Error(
166
+ `[SpatializedMotion] duplicate end boundary for "${property}"`
167
+ );
168
+ }
169
+ return {
170
+ property,
171
+ timingFunction: config.timingFunction,
172
+ keyframes
173
+ };
174
+ });
175
+ return {
176
+ duration,
177
+ tracks,
178
+ timingFunction: config.timingFunction,
179
+ delay: config.delay,
180
+ autoStart: config.autoStart,
181
+ loop: config.loop,
182
+ playbackRate: config.playbackRate,
183
+ onStart: config.onStart,
184
+ onComplete: config.onComplete,
185
+ onStop: config.onStop,
186
+ onReset: config.onReset,
187
+ onError: config.onError
188
+ };
189
+ }
190
+ function normalizeMotionConfig(config) {
191
+ if (config.timeline !== void 0) {
192
+ return desugarTimelineConfig(config);
193
+ }
194
+ return segmentConfigToMotionConfig(config);
195
+ }
196
+ export {
197
+ desugarTimelineConfig,
198
+ normalizeMotionConfig,
199
+ segmentConfigToMotionConfig
200
+ };
201
+ //# sourceMappingURL=normalize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/motion/compute/normalize.ts"],"sourcesContent":["import type { SpatializedVisualValues } from '../../types/motion/spatializedVisual'\nimport type { TimingFunction } from '../../types/animation'\nimport type {\n NormalizedSpatializedMotionConfig,\n SpatializedMotionConfig,\n SpatializedMotionProperty,\n SpatializedMotionSegmentConfig,\n SpatializedMotionTrack,\n SpatializedMotionTimelineConfig,\n} from '../../types/motion/spatializedMotion'\n\n/**\n * Flattens visual values into motion-property/value pairs.\n *\n * @param values Visual values to inspect.\n * @param out Collector for discovered motion property samples.\n */\nfunction collectScalars(\n values: SpatializedVisualValues,\n out: Array<{ property: SpatializedMotionProperty; value: number }>,\n): void {\n if (values.opacity !== undefined) {\n out.push({ property: 'opacity', value: values.opacity })\n }\n const tr = values.transform\n if (!tr) return\n for (const group of ['translate', 'rotate', 'scale'] as const) {\n const part = tr[group]\n if (!part) continue\n for (const axis of ['x', 'y', 'z'] as const) {\n const v = part[axis]\n if (v !== undefined) {\n out.push({\n property: `transform.${group}.${axis}` as SpatializedMotionProperty,\n value: v,\n })\n }\n }\n }\n}\n\n/**\n * Converts `0%`-style timeline keys into [0, 1] ratios.\n *\n * @param key Percentage key from the timeline config.\n * @returns The normalized ratio represented by the key.\n */\nfunction parsePercentageKey(key: string): number {\n if (!/^\\d+(\\.\\d+)?%$/.test(key)) {\n throw new Error(`[SpatializedMotion] invalid timeline key \"${key}\"`)\n }\n const ratio = Number(key.slice(0, -1))\n if (!Number.isFinite(ratio) || ratio < 0 || ratio > 100) {\n throw new Error(`[SpatializedMotion] invalid timeline key \"${key}\"`)\n }\n return ratio / 100\n}\n\n/**\n * Desugars shorthand from/to motion config into canonical tracks.\n *\n * @param simple Shorthand segment config.\n * @returns Canonical track-based motion config.\n */\nexport function segmentConfigToMotionConfig(\n simple: SpatializedMotionSegmentConfig,\n): NormalizedSpatializedMotionConfig {\n if (!simple.from || !simple.to) {\n throw new Error(\n '[SpatializedMotion] top-level from and to are both required',\n )\n }\n const duration = simple.duration ?? 0.3\n const fromScalars: Array<{\n property: SpatializedMotionProperty\n value: number\n }> = []\n const toScalars: Array<{\n property: SpatializedMotionProperty\n value: number\n }> = []\n\n collectScalars(simple.from, fromScalars)\n collectScalars(simple.to, toScalars)\n\n const trackMap = new Map<SpatializedMotionProperty, SpatializedMotionTrack>()\n const properties = new Set([\n ...fromScalars.map(entry => entry.property),\n ...toScalars.map(entry => entry.property),\n ])\n\n for (const property of properties) {\n const fromEntry = fromScalars.find(f => f.property === property)\n const toEntry = toScalars.find(f => f.property === property)\n if (!fromEntry) {\n throw new Error(\n `[SpatializedMotion] missing start boundary for \"${property}\"`,\n )\n }\n if (!toEntry) {\n throw new Error(\n `[SpatializedMotion] missing end boundary for \"${property}\"`,\n )\n }\n trackMap.set(property, {\n property,\n timingFunction: simple.timingFunction,\n keyframes: [\n { at: 0, value: fromEntry.value },\n { at: duration, value: toEntry.value },\n ],\n })\n }\n\n const tracks = [...trackMap.values()]\n if (tracks.length === 0) {\n throw new Error(\n '[SpatializedMotion.simple] to must include at least one animatable field',\n )\n }\n\n return {\n duration,\n tracks,\n timingFunction: simple.timingFunction,\n delay: simple.delay,\n autoStart: simple.autoStart,\n loop: simple.loop,\n playbackRate: simple.playbackRate,\n onStart: simple.onStart,\n onComplete: simple.onComplete,\n onStop: simple.onStop,\n onReset: simple.onReset,\n onError: simple.onError,\n }\n}\n\n/**\n * Desugars percentage-key timeline config into canonical tracks.\n *\n * @param config Timeline config using percentage keys.\n * @returns Canonical track-based motion config.\n */\nexport function desugarTimelineConfig(\n config: SpatializedMotionTimelineConfig,\n): NormalizedSpatializedMotionConfig {\n if (Array.isArray(config.timeline) || !config.timeline) {\n throw new Error('[SpatializedMotion] timeline must be an object')\n }\n\n const entries = Object.entries(config.timeline)\n let hasPercentageKey = false\n const frames = entries\n .map(([key, values]) => {\n if (!values || typeof values !== 'object' || Array.isArray(values)) {\n throw new Error(`[SpatializedMotion] invalid timeline frame \"${key}\"`)\n }\n if (key === 'from') return { key, atRatio: 0, values }\n if (key === 'to') return { key, atRatio: 1, values }\n hasPercentageKey = true\n return { key, atRatio: parsePercentageKey(key), values }\n })\n .sort((a, b) => a.atRatio - b.atRatio)\n\n // Dev warn: top-level from/to are ignored once a timeline is present.\n if (config.from !== undefined || config.to !== undefined) {\n console.warn(\n '[SpatializedMotion] top-level from/to are ignored because timeline is present',\n )\n }\n\n // Start/end boundary frames are required; this change does not fill missing\n // boundaries from underlying element style.\n const hasStartFrame = frames.some(frame => frame.atRatio === 0)\n const hasEndFrame = frames.some(frame => frame.atRatio === 1)\n if (!hasStartFrame) {\n throw new Error(\n '[SpatializedMotion] timeline must define a start frame (from or 0%)',\n )\n }\n if (!hasEndFrame) {\n throw new Error(\n '[SpatializedMotion] timeline must define an end frame (to or 100%)',\n )\n }\n\n if (hasPercentageKey && config.duration === undefined) {\n throw new Error(\n '[SpatializedMotion] duration is required when timeline uses percentage keys',\n )\n }\n const duration = config.duration ?? 0.3\n\n const trackMap = new Map<\n SpatializedMotionProperty,\n Array<{\n at: number\n value: number\n timingFunction?: TimingFunction\n }>\n >()\n const fromProperties = new Set<SpatializedMotionProperty>()\n const zeroProperties = new Set<SpatializedMotionProperty>()\n const toProperties = new Set<SpatializedMotionProperty>()\n const hundredProperties = new Set<SpatializedMotionProperty>()\n\n for (const frame of frames) {\n const at = frame.atRatio * duration\n const scalars: Array<{\n property: SpatializedMotionProperty\n value: number\n }> = []\n collectScalars(frame.values, scalars)\n for (const scalar of scalars) {\n if (frame.key === 'from') fromProperties.add(scalar.property)\n if (frame.key !== 'from' && frame.atRatio === 0) {\n zeroProperties.add(scalar.property)\n }\n if (frame.key === 'to') toProperties.add(scalar.property)\n if (frame.key !== 'to' && frame.atRatio === 1) {\n hundredProperties.add(scalar.property)\n }\n const keyframes = trackMap.get(scalar.property) ?? []\n const keyframe = {\n at,\n value: scalar.value,\n ...(frame.values.timingFunction !== undefined\n ? { timingFunction: frame.values.timingFunction }\n : {}),\n }\n keyframes.push(keyframe)\n trackMap.set(scalar.property, keyframes)\n }\n }\n\n const tracks = [...trackMap.entries()].map(([property, keyframes]) => {\n const startCount =\n Number(fromProperties.has(property)) +\n Number(zeroProperties.has(property))\n const endCount =\n Number(toProperties.has(property)) +\n Number(hundredProperties.has(property))\n if (startCount > 1) {\n throw new Error(\n `[SpatializedMotion] duplicate start boundary for \"${property}\"`,\n )\n }\n if (endCount > 1) {\n throw new Error(\n `[SpatializedMotion] duplicate end boundary for \"${property}\"`,\n )\n }\n return {\n property,\n timingFunction: config.timingFunction,\n keyframes,\n }\n })\n\n return {\n duration,\n tracks,\n timingFunction: config.timingFunction,\n delay: config.delay,\n autoStart: config.autoStart,\n loop: config.loop,\n playbackRate: config.playbackRate,\n onStart: config.onStart,\n onComplete: config.onComplete,\n onStop: config.onStop,\n onReset: config.onReset,\n onError: config.onError,\n }\n}\n\n/**\n * Normalizes any supported motion config shape into canonical tracks.\n *\n * @param config Motion config in shorthand, timeline, or canonical form.\n * @returns Canonical track-based motion config.\n */\nexport function normalizeMotionConfig(\n config: SpatializedMotionConfig,\n): NormalizedSpatializedMotionConfig {\n if (config.timeline !== undefined) {\n return desugarTimelineConfig(config as SpatializedMotionTimelineConfig)\n }\n return segmentConfigToMotionConfig(config as SpatializedMotionSegmentConfig)\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,22 @@
1
+ import { aj as SpatializedMotionConfig, a$ as NormalizedSpatializedMotionConfig } from '../../spatializedElementMotion-_0XWPQCE.js';
2
+ import '../../types/motion/spatializedVisual.js';
3
+ import '../../types/motion/spatializedPlayback.js';
4
+ import '../../types/global.js';
5
+ import '../../physicalMetrics-W5uZ5xKb.js';
6
+ import '../../SpatialObject.js';
7
+ import '../../reality/component/SpatialComponent.js';
8
+
9
+ /**
10
+ * Validates any supported motion config shape before playback or serialization.
11
+ *
12
+ * @param config Motion config in any supported input shape.
13
+ */
14
+ declare function validateSpatializedMotionConfig(config: SpatializedMotionConfig): void;
15
+ /**
16
+ * Validates the canonical track-based motion config form.
17
+ *
18
+ * @param config Canonical motion config to validate.
19
+ */
20
+ declare function validateNormalizedMotionConfig(config: NormalizedSpatializedMotionConfig): void;
21
+
22
+ export { validateNormalizedMotionConfig, validateSpatializedMotionConfig };
@@ -0,0 +1,103 @@
1
+ import { SPATIALIZED_MOTION_PROPERTIES } from "../../types/motion/spatializedMotion";
2
+ import { normalizeMotionConfig } from "./normalize";
3
+ const ALLOWED_PROPERTIES = new Set(
4
+ SPATIALIZED_MOTION_PROPERTIES
5
+ );
6
+ const FORBIDDEN_PREFIXES = [
7
+ "width",
8
+ "height",
9
+ "back",
10
+ "backOffset",
11
+ "depth"
12
+ ];
13
+ function validateSpatializedMotionConfig(config) {
14
+ if (config.tracks !== void 0) {
15
+ throw new Error("[SpatializedMotion] tracks authoring is internal");
16
+ }
17
+ const normalized = normalizeMotionConfig(config);
18
+ validateNormalizedMotionConfig(normalized);
19
+ }
20
+ function validateNormalizedMotionConfig(config) {
21
+ const { duration, tracks } = config;
22
+ if (typeof duration !== "number" || !Number.isFinite(duration) || duration <= 0) {
23
+ throw new Error("[SpatializedMotion] duration must be a finite number > 0");
24
+ }
25
+ if (!Array.isArray(tracks) || tracks.length === 0) {
26
+ throw new Error("[SpatializedMotion] tracks must be a non-empty array");
27
+ }
28
+ const seen = /* @__PURE__ */ new Set();
29
+ for (const track of tracks) {
30
+ validateTrack(track, duration, seen);
31
+ }
32
+ if (config.delay !== void 0) {
33
+ const d = config.delay;
34
+ if (typeof d !== "number" || !Number.isFinite(d) || d < 0) {
35
+ throw new Error("[SpatializedMotion] delay must be >= 0 and finite");
36
+ }
37
+ }
38
+ if (config.playbackRate !== void 0) {
39
+ const r = config.playbackRate;
40
+ if (typeof r !== "number" || !Number.isFinite(r) || r <= 0) {
41
+ throw new Error("[SpatializedMotion] playbackRate must be > 0 and finite");
42
+ }
43
+ }
44
+ }
45
+ function validateTrack(track, duration, seen) {
46
+ const prop = track.property;
47
+ for (const forbidden of FORBIDDEN_PREFIXES) {
48
+ if (prop === forbidden || prop.startsWith(`${forbidden}.`)) {
49
+ throw new Error(
50
+ `[SpatializedMotion] property "${prop}" is not animatable`
51
+ );
52
+ }
53
+ }
54
+ if (!ALLOWED_PROPERTIES.has(track.property)) {
55
+ throw new Error(`[SpatializedMotion] unknown property "${prop}"`);
56
+ }
57
+ if (seen.has(prop)) {
58
+ throw new Error(`[SpatializedMotion] duplicate track for "${prop}"`);
59
+ }
60
+ seen.add(prop);
61
+ const kf = track.keyframes;
62
+ if (!Array.isArray(kf) || kf.length < 2) {
63
+ throw new Error(
64
+ `[SpatializedMotion] track "${prop}" needs at least 2 keyframes`
65
+ );
66
+ }
67
+ let prevAt = -Infinity;
68
+ for (const frame of kf) {
69
+ if (typeof frame.at !== "number" || !Number.isFinite(frame.at)) {
70
+ throw new Error(
71
+ `[SpatializedMotion] keyframe.at must be finite for "${prop}"`
72
+ );
73
+ }
74
+ if (frame.at < 0 || frame.at > duration) {
75
+ throw new Error(
76
+ `[SpatializedMotion] keyframe.at must be within [0, duration] for "${prop}"`
77
+ );
78
+ }
79
+ if (frame.at <= prevAt) {
80
+ throw new Error(
81
+ `[SpatializedMotion] keyframe times must be strictly increasing for "${prop}"`
82
+ );
83
+ }
84
+ prevAt = frame.at;
85
+ validateScalar(frame.value, track.property);
86
+ }
87
+ }
88
+ function validateScalar(value, property) {
89
+ if (typeof value !== "number" || !Number.isFinite(value)) {
90
+ throw new Error(`[SpatializedMotion] invalid value for ${property}`);
91
+ }
92
+ if (property === "opacity" && (value < 0 || value > 1)) {
93
+ throw new Error("[SpatializedMotion] opacity must be in [0, 1]");
94
+ }
95
+ if (property.startsWith("transform.scale.") && value < 0) {
96
+ throw new Error("[SpatializedMotion] scale must be >= 0");
97
+ }
98
+ }
99
+ export {
100
+ validateNormalizedMotionConfig,
101
+ validateSpatializedMotionConfig
102
+ };
103
+ //# sourceMappingURL=validate.js.map