@webspatial/core-sdk 1.7.0 → 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.
- package/CHANGELOG.md +61 -0
- package/README.md +10 -0
- package/dist/JSBCommand.d.ts +398 -0
- package/dist/JSBCommand.js +668 -0
- package/dist/JSBCommand.js.map +1 -0
- package/dist/Spatial.d.ts +63 -0
- package/dist/Spatial.js +60 -0
- package/dist/Spatial.js.map +1 -0
- package/dist/SpatialObject.d.ts +19 -0
- package/dist/SpatialObject.js +44 -0
- package/dist/SpatialObject.js.map +1 -0
- package/dist/SpatialScene.d.ts +51 -0
- package/dist/SpatialScene.js +74 -0
- package/dist/SpatialScene.js.map +1 -0
- package/dist/SpatialSession.d.ts +143 -0
- package/dist/SpatialSession.js +173 -0
- package/dist/SpatialSession.js.map +1 -0
- package/dist/SpatialWebEvent.d.ts +8 -0
- package/dist/SpatialWebEvent.js +18 -0
- package/dist/SpatialWebEvent.js.map +1 -0
- package/dist/SpatialWebEventCreator.d.ts +11 -0
- package/dist/SpatialWebEventCreator.js +11 -0
- package/dist/SpatialWebEventCreator.js.map +1 -0
- package/dist/Spatialized2DElement.d.ts +42 -0
- package/dist/Spatialized2DElement.js +47 -0
- package/dist/Spatialized2DElement.js.map +1 -0
- package/dist/SpatializedDynamic3DElement.d.ts +7 -0
- package/dist/SpatializedDynamic3DElement.js +43 -0
- package/dist/SpatializedDynamic3DElement.js.map +1 -0
- package/dist/SpatializedElement.d.ts +7 -0
- package/dist/SpatializedElement.js +206 -0
- package/dist/SpatializedElement.js.map +1 -0
- package/dist/SpatializedElementCreator.d.ts +15 -0
- package/dist/SpatializedElementCreator.js +47 -0
- package/dist/SpatializedElementCreator.js.map +1 -0
- package/dist/SpatializedStatic3DElement.d.ts +195 -0
- package/dist/SpatializedStatic3DElement.js +327 -0
- package/dist/SpatializedStatic3DElement.js.map +1 -0
- package/dist/WebMsgCommand.d.ts +7 -0
- package/dist/WebMsgCommand.js +23 -0
- package/dist/WebMsgCommand.js.map +1 -0
- package/dist/index.d.ts +35 -1251
- package/dist/index.js +21 -3650
- package/dist/index.js.map +1 -1
- package/dist/install-polyfills.d.ts +2 -0
- package/dist/install-polyfills.js +13 -0
- package/dist/install-polyfills.js.map +1 -0
- package/dist/isSSREnv.d.ts +3 -0
- package/dist/isSSREnv.js +6 -0
- package/dist/isSSREnv.js.map +1 -0
- package/dist/motion/AnimationObject.d.ts +7 -0
- package/dist/motion/AnimationObject.js +140 -0
- package/dist/motion/AnimationObject.js.map +1 -0
- package/dist/motion/compute/index.d.ts +10 -0
- package/dist/motion/compute/index.js +19 -0
- package/dist/motion/compute/index.js.map +1 -0
- package/dist/motion/compute/motionPropertyValues.d.ts +19 -0
- package/dist/motion/compute/motionPropertyValues.js +50 -0
- package/dist/motion/compute/motionPropertyValues.js.map +1 -0
- package/dist/motion/compute/normalize.d.ts +31 -0
- package/dist/motion/compute/normalize.js +201 -0
- package/dist/motion/compute/normalize.js.map +1 -0
- package/dist/motion/compute/validate.d.ts +22 -0
- package/dist/motion/compute/validate.js +103 -0
- package/dist/motion/compute/validate.js.map +1 -0
- package/dist/motion/index.d.ts +8 -0
- package/dist/motion/index.js +6 -0
- package/dist/motion/index.js.map +1 -0
- package/dist/motion/native/serializeMotionTimeline.d.ts +12 -0
- package/dist/motion/native/serializeMotionTimeline.js +21 -0
- package/dist/motion/native/serializeMotionTimeline.js.map +1 -0
- package/dist/physicalMetrics-W5uZ5xKb.d.ts +48 -0
- package/dist/physicalMetrics.d.ts +1 -0
- package/dist/physicalMetrics.js +58 -0
- package/dist/physicalMetrics.js.map +1 -0
- package/dist/platform-adapter/CommandResultUtils.d.ts +12 -0
- package/dist/platform-adapter/CommandResultUtils.js +21 -0
- package/dist/platform-adapter/CommandResultUtils.js.map +1 -0
- package/dist/platform-adapter/createPlatformSync.d.ts +16 -0
- package/dist/platform-adapter/createPlatformSync.js +30 -0
- package/dist/platform-adapter/createPlatformSync.js.map +1 -0
- package/dist/platform-adapter/index.d.ts +12 -0
- package/dist/platform-adapter/index.js +10 -0
- package/dist/platform-adapter/index.js.map +1 -0
- package/dist/platform-adapter/interface.d.ts +7 -0
- package/dist/platform-adapter/interface.js +1 -0
- package/dist/platform-adapter/interface.js.map +1 -0
- package/dist/platform-adapter/pico-os/PicoOSPlatform.d.ts +25 -0
- package/dist/platform-adapter/pico-os/PicoOSPlatform.js +168 -0
- package/dist/platform-adapter/pico-os/PicoOSPlatform.js.map +1 -0
- package/dist/platform-adapter/puppeteer/PuppeteerPlatform.d.ts +66 -0
- package/dist/platform-adapter/puppeteer/PuppeteerPlatform.js +372 -0
- package/dist/platform-adapter/puppeteer/PuppeteerPlatform.js.map +1 -0
- package/dist/platform-adapter/spatialRequestMetadata.d.ts +6 -0
- package/dist/platform-adapter/spatialRequestMetadata.js +39 -0
- package/dist/platform-adapter/spatialRequestMetadata.js.map +1 -0
- package/dist/platform-adapter/spatialSceneQuery.d.ts +12 -0
- package/dist/platform-adapter/spatialSceneQuery.js +12 -0
- package/dist/platform-adapter/spatialSceneQuery.js.map +1 -0
- package/dist/platform-adapter/vision-os/VisionOSPlatform.d.ts +19 -0
- package/dist/platform-adapter/vision-os/VisionOSPlatform.js +77 -0
- package/dist/platform-adapter/vision-os/VisionOSPlatform.js.map +1 -0
- package/dist/platform-runtime.d.ts +12 -0
- package/dist/platform-runtime.js +14 -0
- package/dist/platform-runtime.js.map +1 -0
- package/dist/reality/Attachment.d.ts +19 -0
- package/dist/reality/Attachment.js +39 -0
- package/dist/reality/Attachment.js.map +1 -0
- package/dist/reality/component/ModelComponent.d.ts +14 -0
- package/dist/reality/component/ModelComponent.js +11 -0
- package/dist/reality/component/ModelComponent.js.map +1 -0
- package/dist/reality/component/SpatialComponent.d.ts +8 -0
- package/dist/reality/component/SpatialComponent.js +19 -0
- package/dist/reality/component/SpatialComponent.js.map +1 -0
- package/dist/reality/component/index.d.ts +8 -0
- package/dist/reality/component/index.js +3 -0
- package/dist/reality/component/index.js.map +1 -0
- package/dist/reality/entity/SpatialEntity.d.ts +7 -0
- package/dist/reality/entity/SpatialEntity.js +291 -0
- package/dist/reality/entity/SpatialEntity.js.map +1 -0
- package/dist/reality/entity/SpatialModelEntity.d.ts +17 -0
- package/dist/reality/entity/SpatialModelEntity.js +17 -0
- package/dist/reality/entity/SpatialModelEntity.js.map +1 -0
- package/dist/reality/entity/index.d.ts +8 -0
- package/dist/reality/entity/index.js +3 -0
- package/dist/reality/entity/index.js.map +1 -0
- package/dist/reality/geometry/SpatialBoxGeometry.d.ts +16 -0
- package/dist/reality/geometry/SpatialBoxGeometry.js +13 -0
- package/dist/reality/geometry/SpatialBoxGeometry.js.map +1 -0
- package/dist/reality/geometry/SpatialConeGeometry.d.ts +16 -0
- package/dist/reality/geometry/SpatialConeGeometry.js +13 -0
- package/dist/reality/geometry/SpatialConeGeometry.js.map +1 -0
- package/dist/reality/geometry/SpatialCylinderGeometry.d.ts +16 -0
- package/dist/reality/geometry/SpatialCylinderGeometry.js +13 -0
- package/dist/reality/geometry/SpatialCylinderGeometry.js.map +1 -0
- package/dist/reality/geometry/SpatialGeometry.d.ts +7 -0
- package/dist/reality/geometry/SpatialGeometry.js +13 -0
- package/dist/reality/geometry/SpatialGeometry.js.map +1 -0
- package/dist/reality/geometry/SpatialPlaneGeometry.d.ts +16 -0
- package/dist/reality/geometry/SpatialPlaneGeometry.js +13 -0
- package/dist/reality/geometry/SpatialPlaneGeometry.js.map +1 -0
- package/dist/reality/geometry/SpatialSphereGeometry.d.ts +16 -0
- package/dist/reality/geometry/SpatialSphereGeometry.js +13 -0
- package/dist/reality/geometry/SpatialSphereGeometry.js.map +1 -0
- package/dist/reality/geometry/index.d.ts +12 -0
- package/dist/reality/geometry/index.js +7 -0
- package/dist/reality/geometry/index.js.map +1 -0
- package/dist/reality/index.d.ts +18 -0
- package/dist/reality/index.js +7 -0
- package/dist/reality/index.js.map +1 -0
- package/dist/reality/material/SpatialMaterial.d.ts +7 -0
- package/dist/reality/material/SpatialMaterial.js +13 -0
- package/dist/reality/material/SpatialMaterial.js.map +1 -0
- package/dist/reality/material/SpatialUnlitMaterial.d.ts +16 -0
- package/dist/reality/material/SpatialUnlitMaterial.js +16 -0
- package/dist/reality/material/SpatialUnlitMaterial.js.map +1 -0
- package/dist/reality/material/index.d.ts +8 -0
- package/dist/reality/material/index.js +3 -0
- package/dist/reality/material/index.js.map +1 -0
- package/dist/reality/realityCreator.d.ts +22 -0
- package/dist/reality/realityCreator.js +89 -0
- package/dist/reality/realityCreator.js.map +1 -0
- package/dist/reality/resource/SpatialModelAsset.d.ts +15 -0
- package/dist/reality/resource/SpatialModelAsset.js +12 -0
- package/dist/reality/resource/SpatialModelAsset.js.map +1 -0
- package/dist/reality/resource/SpatialTextureResource.d.ts +16 -0
- package/dist/reality/resource/SpatialTextureResource.js +16 -0
- package/dist/reality/resource/SpatialTextureResource.js.map +1 -0
- package/dist/reality/resource/index.d.ts +9 -0
- package/dist/reality/resource/index.js +3 -0
- package/dist/reality/resource/index.js.map +1 -0
- package/dist/runtime/WebSpatialRuntimeError.d.ts +10 -0
- package/dist/runtime/WebSpatialRuntimeError.js +14 -0
- package/dist/runtime/WebSpatialRuntimeError.js.map +1 -0
- package/dist/runtime/capability-data.d.ts +12 -0
- package/dist/runtime/capability-data.js +134 -0
- package/dist/runtime/capability-data.js.map +1 -0
- package/dist/runtime/index.d.ts +8 -0
- package/dist/runtime/index.js +27 -0
- package/dist/runtime/index.js.map +1 -0
- package/dist/runtime/jsbAdapterPlatform.d.ts +9 -0
- package/dist/runtime/jsbAdapterPlatform.js +38 -0
- package/dist/runtime/jsbAdapterPlatform.js.map +1 -0
- package/dist/runtime/keys.d.ts +34 -0
- package/dist/runtime/keys.js +122 -0
- package/dist/runtime/keys.js.map +1 -0
- package/dist/runtime/semver.d.ts +8 -0
- package/dist/runtime/semver.js +32 -0
- package/dist/runtime/semver.js.map +1 -0
- package/dist/runtime/supports.d.ts +22 -0
- package/dist/runtime/supports.js +78 -0
- package/dist/runtime/supports.js.map +1 -0
- package/dist/runtime/types.d.ts +12 -0
- package/dist/runtime/types.js +1 -0
- package/dist/runtime/types.js.map +1 -0
- package/dist/runtime/userAgent.d.ts +20 -0
- package/dist/runtime/userAgent.js +41 -0
- package/dist/runtime/userAgent.js.map +1 -0
- package/dist/scene-polyfill.d.ts +18 -0
- package/dist/scene-polyfill.js +480 -0
- package/dist/scene-polyfill.js.map +1 -0
- package/dist/spatial-host.d.ts +13 -0
- package/dist/spatial-host.js +18 -0
- package/dist/spatial-host.js.map +1 -0
- package/dist/spatial-window-polyfill.d.ts +3 -0
- package/dist/spatial-window-polyfill.js +155 -0
- package/dist/spatial-window-polyfill.js.map +1 -0
- package/dist/spatializedElementMotion-_0XWPQCE.d.ts +1009 -0
- package/dist/types/animation.d.ts +7 -0
- package/dist/types/animation.js +1 -0
- package/dist/types/animation.js.map +1 -0
- package/dist/types/global.d.ts +38 -0
- package/dist/types/global.js +1 -0
- package/dist/types/global.js.map +1 -0
- package/dist/types/internal.d.ts +7 -0
- package/dist/types/internal.js +12 -0
- package/dist/types/internal.js.map +1 -0
- package/dist/types/motion/index.d.ts +7 -0
- package/dist/types/motion/index.js +3 -0
- package/dist/types/motion/index.js.map +1 -0
- package/dist/types/motion/spatializedElementMotion.d.ts +7 -0
- package/dist/types/motion/spatializedElementMotion.js +1 -0
- package/dist/types/motion/spatializedElementMotion.js.map +1 -0
- package/dist/types/motion/spatializedMotion.d.ts +7 -0
- package/dist/types/motion/spatializedMotion.js +16 -0
- package/dist/types/motion/spatializedMotion.js.map +1 -0
- package/dist/types/motion/spatializedPlayback.d.ts +11 -0
- package/dist/types/motion/spatializedPlayback.js +1 -0
- package/dist/types/motion/spatializedPlayback.js.map +1 -0
- package/dist/types/motion/spatializedVisual.d.ts +35 -0
- package/dist/types/motion/spatializedVisual.js +1 -0
- package/dist/types/motion/spatializedVisual.js.map +1 -0
- package/dist/types/types.d.ts +7 -0
- package/dist/types/types.js +117 -0
- package/dist/types/types.js.map +1 -0
- package/dist/utils.d.ts +44 -0
- package/dist/utils.js +86 -0
- package/dist/utils.js.map +1 -0
- package/package.json +20 -4
- package/src/JSBCommand.ts +132 -5
- package/src/SpatialObject.ts +10 -0
- package/src/Spatialized2DElement.ts +5 -0
- package/src/SpatializedDynamic3DElement.ts +5 -0
- package/src/SpatializedElement.ts +29 -0
- package/src/SpatializedStatic3DElement.ts +42 -3
- package/src/WebMsgCommand.ts +40 -0
- package/src/coverage-boost.test.ts +239 -216
- package/src/index.ts +25 -11
- package/src/install-polyfills.ts +38 -0
- package/src/jsbcommand.coverage.test.ts +23 -0
- package/src/motion/AnimationObject.test.ts +421 -0
- package/src/motion/AnimationObject.ts +208 -0
- package/src/motion/compute/index.ts +10 -0
- package/src/motion/compute/motionPropertyValues.test.ts +55 -0
- package/src/motion/compute/motionPropertyValues.ts +70 -0
- package/src/motion/compute/normalize.test.ts +99 -0
- package/src/motion/compute/normalize.ts +289 -0
- package/src/motion/compute/validate.test.ts +229 -0
- package/src/motion/compute/validate.ts +156 -0
- package/src/motion/index.ts +2 -0
- package/src/motion/native/serializeMotionTimeline.test.ts +61 -0
- package/src/motion/native/serializeMotionTimeline.ts +27 -0
- package/src/platform-adapter/createPlatformSync.ts +5 -3
- package/src/platform-adapter/pico-os/PicoOSPlatform.ts +76 -11
- package/src/platform-adapter/spatialRequestMetadata.test.ts +175 -0
- package/src/platform-adapter/spatialRequestMetadata.ts +48 -0
- package/src/platform-adapter/vision-os/VisionOSPlatform.ts +6 -1
- package/src/reality/entity/SpatialEntity.ts +127 -0
- package/src/runtime/capability-data.ts +104 -4
- package/src/runtime/index.ts +0 -11
- package/src/runtime/keys.ts +12 -1
- package/src/runtime/supports.test.ts +143 -4
- package/src/runtime/supports.ts +3 -1
- package/src/runtime/useAnimation.capability.test.ts +275 -0
- package/src/scene-polyfill.manifest.test.ts +306 -5
- package/src/scene-polyfill.request-metadata.test.ts +39 -0
- package/src/scene-polyfill.test.ts +33 -94
- package/src/scene-polyfill.ts +117 -87
- package/src/spatial-window-polyfill.ts +18 -2
- package/src/transform-roundtrip.test.ts +90 -0
- package/src/types/animation.ts +224 -0
- package/src/types/global.ts +1 -8
- package/src/types/motion/index.ts +10 -0
- package/src/types/motion/spatializedElementMotion.ts +49 -0
- package/src/types/motion/spatializedMotion.ts +147 -0
- package/src/types/motion/spatializedPlayback.ts +17 -0
- package/src/types/motion/spatializedVisual.ts +24 -0
- package/src/types/types.ts +3 -0
- package/src/utils.ts +54 -0
- package/tsup.config.ts +61 -36
- package/vitest.config.ts +5 -1
- package/dist/iife/index.d.ts +0 -1251
- package/dist/iife/index.global.js +0 -75
- package/dist/iife/index.global.js.map +0 -1
- package/src/platform-adapter/ssr/SSRPlatform.ts +0 -52
- /package/src/{ssr-polyfill.ts → isSSREnv.ts} +0 -0
|
@@ -128,6 +128,7 @@ describe('JSBCommand', () => {
|
|
|
128
128
|
it('builds element commands payloads', async () => {
|
|
129
129
|
const mod = await import('./JSBCommand')
|
|
130
130
|
const {
|
|
131
|
+
CreateSpatializedElementAnimationJSBCommand,
|
|
131
132
|
UpdateSpatializedElementTransform,
|
|
132
133
|
UpdateSpatialized2DElementProperties,
|
|
133
134
|
UpdateSpatializedDynamic3DElementProperties,
|
|
@@ -185,6 +186,18 @@ describe('JSBCommand', () => {
|
|
|
185
186
|
JSON.stringify({ id: 'so-1', spatializedElementId: 'ele-1' }),
|
|
186
187
|
)
|
|
187
188
|
|
|
189
|
+
await new CreateSpatializedElementAnimationJSBCommand({
|
|
190
|
+
elementId: 'ele-1',
|
|
191
|
+
timeline: { duration: 1, tracks: [] },
|
|
192
|
+
} as any).execute()
|
|
193
|
+
expect(platformSpy.callJSB).toHaveBeenCalledWith(
|
|
194
|
+
'CreateSpatializedElementAnimation',
|
|
195
|
+
JSON.stringify({
|
|
196
|
+
elementId: 'ele-1',
|
|
197
|
+
timeline: { duration: 1, tracks: [] },
|
|
198
|
+
}),
|
|
199
|
+
)
|
|
200
|
+
|
|
188
201
|
await new UpdateUnlitMaterialProperties(obj, { color: '#fff' }).execute()
|
|
189
202
|
expect(platformSpy.callJSB).toHaveBeenCalledWith(
|
|
190
203
|
'UpdateUnlitMaterialProperties',
|
|
@@ -412,12 +425,17 @@ describe('SpatializedElement', () => {
|
|
|
412
425
|
SpatialWebEvent.init()
|
|
413
426
|
|
|
414
427
|
class TestElement extends SpatializedElement {
|
|
428
|
+
/** Identifies the supported motion target kind for this test element. */
|
|
429
|
+
readonly kind = 'spatialized2d' as const
|
|
430
|
+
|
|
415
431
|
updateProperties = vi.fn().mockResolvedValue({
|
|
416
432
|
success: true,
|
|
417
433
|
data: undefined,
|
|
418
434
|
errorCode: '',
|
|
419
435
|
errorMessage: '',
|
|
420
436
|
})
|
|
437
|
+
|
|
438
|
+
motion = vi.fn()
|
|
421
439
|
}
|
|
422
440
|
|
|
423
441
|
const e = new TestElement('el3')
|
|
@@ -440,12 +458,17 @@ describe('SpatializedElement', () => {
|
|
|
440
458
|
SpatialWebEvent.init()
|
|
441
459
|
|
|
442
460
|
class TestElement extends SpatializedElement {
|
|
461
|
+
/** Identifies the supported motion target kind for this test element. */
|
|
462
|
+
readonly kind = 'spatialized2d' as const
|
|
463
|
+
|
|
443
464
|
updateProperties = vi.fn().mockResolvedValue({
|
|
444
465
|
success: true,
|
|
445
466
|
data: undefined,
|
|
446
467
|
errorCode: '',
|
|
447
468
|
errorMessage: '',
|
|
448
469
|
})
|
|
470
|
+
|
|
471
|
+
motion = vi.fn()
|
|
449
472
|
}
|
|
450
473
|
|
|
451
474
|
const e = new TestElement('el4')
|
|
@@ -0,0 +1,421 @@
|
|
|
1
|
+
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
2
|
+
import { SpatialWebMsgType } from '../WebMsgCommand'
|
|
3
|
+
import { SpatialWebEvent } from '../SpatialWebEvent'
|
|
4
|
+
import type { SpatialAnimationStateChangedMsg } from '../types/motion/spatializedElementMotion'
|
|
5
|
+
|
|
6
|
+
const spatialAnimationStateChangedType: SpatialAnimationStateChangedMsg['type'] =
|
|
7
|
+
SpatialWebMsgType.animationstatechange
|
|
8
|
+
|
|
9
|
+
const spies = vi.hoisted(() => ({
|
|
10
|
+
createCommandSpy: vi.fn(),
|
|
11
|
+
controlCommandSpy: vi.fn(),
|
|
12
|
+
destroyCommandSpy: vi.fn(),
|
|
13
|
+
failNextControlType: undefined as string | undefined,
|
|
14
|
+
}))
|
|
15
|
+
|
|
16
|
+
vi.mock('../JSBCommand', () => {
|
|
17
|
+
const ok = (data: any = {}) => ({
|
|
18
|
+
success: true,
|
|
19
|
+
data,
|
|
20
|
+
errorCode: '',
|
|
21
|
+
errorMessage: '',
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
class CreateSpatializedElementAnimationJSBCommand {
|
|
25
|
+
constructor(public command: any) {
|
|
26
|
+
spies.createCommandSpy(command)
|
|
27
|
+
}
|
|
28
|
+
execute = vi.fn().mockResolvedValue(ok({ id: 'native-anim-1' }))
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
class ControlSpatializedElementAnimationJSBCommand {
|
|
32
|
+
constructor(public command: any) {
|
|
33
|
+
spies.controlCommandSpy(command)
|
|
34
|
+
}
|
|
35
|
+
execute = vi.fn().mockImplementation(() => {
|
|
36
|
+
if (spies.failNextControlType === this.command.type) {
|
|
37
|
+
spies.failNextControlType = undefined
|
|
38
|
+
return Promise.resolve({
|
|
39
|
+
success: false,
|
|
40
|
+
data: undefined,
|
|
41
|
+
errorCode: 'E_CONTROL',
|
|
42
|
+
errorMessage: `${this.command.type} failed`,
|
|
43
|
+
})
|
|
44
|
+
}
|
|
45
|
+
return Promise.resolve(ok())
|
|
46
|
+
})
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
class DestroyCommand {
|
|
50
|
+
constructor(public id: string) {
|
|
51
|
+
spies.destroyCommandSpy(id)
|
|
52
|
+
}
|
|
53
|
+
execute = vi.fn().mockResolvedValue(ok({ destroyed: true }))
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
class InspectCommand {
|
|
57
|
+
constructor(public id: string = '') {}
|
|
58
|
+
execute = vi.fn().mockResolvedValue(ok({ inspected: true }))
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return {
|
|
62
|
+
CreateSpatializedElementAnimationJSBCommand,
|
|
63
|
+
ControlSpatializedElementAnimationJSBCommand,
|
|
64
|
+
DestroyCommand,
|
|
65
|
+
InspectCommand,
|
|
66
|
+
}
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
describe('AnimationObject', () => {
|
|
70
|
+
beforeEach(() => {
|
|
71
|
+
spies.createCommandSpy.mockClear()
|
|
72
|
+
spies.controlCommandSpy.mockClear()
|
|
73
|
+
spies.destroyCommandSpy.mockClear()
|
|
74
|
+
spies.failNextControlType = undefined
|
|
75
|
+
SpatialWebEvent.eventReceiver = {}
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
async function createAnimation() {
|
|
79
|
+
const { SpatializedElement } = await import('../SpatializedElement')
|
|
80
|
+
|
|
81
|
+
class TestSpatializedElement extends SpatializedElement {
|
|
82
|
+
/** Identifies the supported motion target kind for this test element. */
|
|
83
|
+
readonly kind = 'static3d' as const
|
|
84
|
+
|
|
85
|
+
async updateProperties() {
|
|
86
|
+
return {
|
|
87
|
+
success: true,
|
|
88
|
+
data: undefined,
|
|
89
|
+
errorCode: '',
|
|
90
|
+
errorMessage: '',
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const element = new TestSpatializedElement('element-1')
|
|
96
|
+
return element.createAnimation({
|
|
97
|
+
duration: 1,
|
|
98
|
+
from: {
|
|
99
|
+
transform: { translate: { x: 0 } },
|
|
100
|
+
},
|
|
101
|
+
to: {
|
|
102
|
+
transform: { translate: { x: 10 } },
|
|
103
|
+
},
|
|
104
|
+
})
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
it('types native state events with the shared animationstatechange discriminant', () => {
|
|
108
|
+
expect(spatialAnimationStateChangedType).toBe(
|
|
109
|
+
SpatialWebMsgType.animationstatechange,
|
|
110
|
+
)
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
it('creates from the native create command and tracks native state directly', async () => {
|
|
114
|
+
const { AnimationObject } = await import('./AnimationObject')
|
|
115
|
+
|
|
116
|
+
const animation = await createAnimation()
|
|
117
|
+
|
|
118
|
+
expect(animation).toBeInstanceOf(AnimationObject)
|
|
119
|
+
expect(animation.id).toBe('native-anim-1')
|
|
120
|
+
expect('uuid' in animation).toBe(false)
|
|
121
|
+
expect(spies.createCommandSpy).toHaveBeenCalledWith(
|
|
122
|
+
expect.objectContaining({
|
|
123
|
+
elementId: 'element-1',
|
|
124
|
+
timeline: expect.any(Object),
|
|
125
|
+
}),
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
const receiver = SpatialWebEvent.eventReceiver[animation.id]
|
|
129
|
+
expect(receiver).toEqual(expect.any(Function))
|
|
130
|
+
|
|
131
|
+
const onValuesChange = vi.fn()
|
|
132
|
+
const onStateChange = vi.fn()
|
|
133
|
+
const onComplete = vi.fn()
|
|
134
|
+
animation.setCallbacks({
|
|
135
|
+
onValuesChange,
|
|
136
|
+
onStateChange,
|
|
137
|
+
onComplete,
|
|
138
|
+
})
|
|
139
|
+
|
|
140
|
+
receiver?.({
|
|
141
|
+
detail: {
|
|
142
|
+
animationId: 'other-animation',
|
|
143
|
+
action: 'play',
|
|
144
|
+
playState: 'running',
|
|
145
|
+
finished: false,
|
|
146
|
+
values: { transform: { translate: { x: 2.5 } } },
|
|
147
|
+
},
|
|
148
|
+
})
|
|
149
|
+
|
|
150
|
+
expect(animation.playState).toBe('idle')
|
|
151
|
+
expect(onValuesChange).not.toHaveBeenCalled()
|
|
152
|
+
expect(onStateChange).not.toHaveBeenCalled()
|
|
153
|
+
|
|
154
|
+
receiver?.({
|
|
155
|
+
detail: {
|
|
156
|
+
animationId: animation.id,
|
|
157
|
+
action: 'play',
|
|
158
|
+
playState: 'running',
|
|
159
|
+
finished: false,
|
|
160
|
+
values: { transform: { translate: { x: 5 } } },
|
|
161
|
+
},
|
|
162
|
+
})
|
|
163
|
+
|
|
164
|
+
expect(animation.playState).toBe('running')
|
|
165
|
+
expect(animation.isAnimating).toBe(true)
|
|
166
|
+
expect(animation.isPaused).toBe(false)
|
|
167
|
+
expect(animation.finished).toBe(false)
|
|
168
|
+
expect(onValuesChange).toHaveBeenCalledWith({
|
|
169
|
+
transform: { translate: { x: 5 } },
|
|
170
|
+
})
|
|
171
|
+
expect(onStateChange).toHaveBeenCalledTimes(1)
|
|
172
|
+
|
|
173
|
+
receiver?.({
|
|
174
|
+
detail: {
|
|
175
|
+
animationId: animation.id,
|
|
176
|
+
action: 'complete',
|
|
177
|
+
playState: 'finished',
|
|
178
|
+
finished: true,
|
|
179
|
+
values: { transform: { translate: { x: 10 } } },
|
|
180
|
+
},
|
|
181
|
+
})
|
|
182
|
+
|
|
183
|
+
expect(animation.playState).toBe('finished')
|
|
184
|
+
expect(animation.finished).toBe(true)
|
|
185
|
+
expect(onComplete).toHaveBeenCalledWith({
|
|
186
|
+
transform: { translate: { x: 10 } },
|
|
187
|
+
})
|
|
188
|
+
expect(onStateChange).toHaveBeenCalledTimes(2)
|
|
189
|
+
})
|
|
190
|
+
|
|
191
|
+
it('uses the inherited destroy path and unregisters its native WebMsg receiver', async () => {
|
|
192
|
+
const animation = await createAnimation()
|
|
193
|
+
|
|
194
|
+
expect(SpatialWebEvent.eventReceiver[animation.id]).toEqual(
|
|
195
|
+
expect.any(Function),
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
await animation.destroy()
|
|
199
|
+
|
|
200
|
+
expect(spies.destroyCommandSpy).toHaveBeenCalledWith(animation.id)
|
|
201
|
+
expect(spies.controlCommandSpy).not.toHaveBeenCalledWith(
|
|
202
|
+
expect.objectContaining({ type: 'destroy' }),
|
|
203
|
+
)
|
|
204
|
+
expect(animation.isDestroyed).toBe(true)
|
|
205
|
+
expect(SpatialWebEvent.eventReceiver[animation.id]).toBeUndefined()
|
|
206
|
+
})
|
|
207
|
+
|
|
208
|
+
it('cleans up local lifecycle when native reports destroy', async () => {
|
|
209
|
+
const animation = await createAnimation()
|
|
210
|
+
const receiver = SpatialWebEvent.eventReceiver[animation.id]
|
|
211
|
+
|
|
212
|
+
expect(receiver).toEqual(expect.any(Function))
|
|
213
|
+
|
|
214
|
+
receiver?.({
|
|
215
|
+
detail: {
|
|
216
|
+
animationId: animation.id,
|
|
217
|
+
action: 'destroy',
|
|
218
|
+
playState: 'idle',
|
|
219
|
+
finished: false,
|
|
220
|
+
},
|
|
221
|
+
})
|
|
222
|
+
|
|
223
|
+
expect(animation.isDestroyed).toBe(true)
|
|
224
|
+
expect(SpatialWebEvent.eventReceiver[animation.id]).toBeUndefined()
|
|
225
|
+
|
|
226
|
+
await animation.play()
|
|
227
|
+
expect(spies.controlCommandSpy).not.toHaveBeenCalled()
|
|
228
|
+
})
|
|
229
|
+
|
|
230
|
+
it('fires onStart only after the native start event arrives', async () => {
|
|
231
|
+
const animation = await createAnimation()
|
|
232
|
+
const onStart = vi.fn()
|
|
233
|
+
animation.setCallbacks({ onStart })
|
|
234
|
+
const receiver = SpatialWebEvent.eventReceiver[animation.id]
|
|
235
|
+
|
|
236
|
+
await animation.play()
|
|
237
|
+
expect(onStart).not.toHaveBeenCalled()
|
|
238
|
+
|
|
239
|
+
receiver?.({
|
|
240
|
+
detail: {
|
|
241
|
+
animationId: animation.id,
|
|
242
|
+
action: 'play',
|
|
243
|
+
playState: 'running',
|
|
244
|
+
finished: false,
|
|
245
|
+
values: { transform: { translate: { x: 1 } } },
|
|
246
|
+
},
|
|
247
|
+
})
|
|
248
|
+
expect(onStart).not.toHaveBeenCalled()
|
|
249
|
+
|
|
250
|
+
receiver?.({
|
|
251
|
+
detail: {
|
|
252
|
+
animationId: animation.id,
|
|
253
|
+
action: 'start',
|
|
254
|
+
playState: 'running',
|
|
255
|
+
finished: false,
|
|
256
|
+
values: { transform: { translate: { x: 1 } } },
|
|
257
|
+
},
|
|
258
|
+
})
|
|
259
|
+
expect(onStart).toHaveBeenCalledTimes(1)
|
|
260
|
+
})
|
|
261
|
+
|
|
262
|
+
it('does not fire onStart when play control fails and retries only start after native start', async () => {
|
|
263
|
+
const animation = await createAnimation()
|
|
264
|
+
const onStart = vi.fn()
|
|
265
|
+
const onError = vi.fn()
|
|
266
|
+
animation.setCallbacks({ onStart, onError })
|
|
267
|
+
const receiver = SpatialWebEvent.eventReceiver[animation.id]
|
|
268
|
+
|
|
269
|
+
spies.failNextControlType = 'play'
|
|
270
|
+
|
|
271
|
+
await expect(animation.play()).rejects.toThrow('play failed')
|
|
272
|
+
expect(onStart).not.toHaveBeenCalled()
|
|
273
|
+
expect(onError).not.toHaveBeenCalled()
|
|
274
|
+
|
|
275
|
+
await animation.play()
|
|
276
|
+
expect(onStart).not.toHaveBeenCalled()
|
|
277
|
+
|
|
278
|
+
receiver?.({
|
|
279
|
+
detail: {
|
|
280
|
+
animationId: animation.id,
|
|
281
|
+
action: 'start',
|
|
282
|
+
playState: 'running',
|
|
283
|
+
finished: false,
|
|
284
|
+
values: { transform: { translate: { x: 2 } } },
|
|
285
|
+
},
|
|
286
|
+
})
|
|
287
|
+
expect(onStart).toHaveBeenCalledTimes(1)
|
|
288
|
+
})
|
|
289
|
+
|
|
290
|
+
it('normalizes native playback errors without exposing animation id', async () => {
|
|
291
|
+
const animation = await createAnimation()
|
|
292
|
+
const onError = vi.fn()
|
|
293
|
+
animation.setCallbacks({ onError })
|
|
294
|
+
const receiver = SpatialWebEvent.eventReceiver[animation.id]
|
|
295
|
+
|
|
296
|
+
receiver?.({
|
|
297
|
+
detail: {
|
|
298
|
+
animationId: animation.id,
|
|
299
|
+
action: 'error',
|
|
300
|
+
playState: 'idle',
|
|
301
|
+
finished: false,
|
|
302
|
+
error: {
|
|
303
|
+
code: 'mask-conflict',
|
|
304
|
+
message: 'Another animation is already writing this target',
|
|
305
|
+
},
|
|
306
|
+
},
|
|
307
|
+
})
|
|
308
|
+
|
|
309
|
+
expect(onError).toHaveBeenCalledWith({
|
|
310
|
+
command: 'play',
|
|
311
|
+
code: 'mask-conflict',
|
|
312
|
+
reason: 'Another animation is already writing this target',
|
|
313
|
+
})
|
|
314
|
+
})
|
|
315
|
+
|
|
316
|
+
it.each(['stop', 'reset', 'finish'] as const)(
|
|
317
|
+
'does not re-fire onStart after %s until native terminal event arrives',
|
|
318
|
+
async controlType => {
|
|
319
|
+
const animation = await createAnimation()
|
|
320
|
+
const onStart = vi.fn()
|
|
321
|
+
animation.setCallbacks({ onStart })
|
|
322
|
+
const receiver = SpatialWebEvent.eventReceiver[animation.id]
|
|
323
|
+
|
|
324
|
+
receiver?.({
|
|
325
|
+
detail: {
|
|
326
|
+
animationId: animation.id,
|
|
327
|
+
action: 'start',
|
|
328
|
+
playState: 'running',
|
|
329
|
+
finished: false,
|
|
330
|
+
values: { transform: { translate: { x: 1 } } },
|
|
331
|
+
},
|
|
332
|
+
})
|
|
333
|
+
expect(onStart).toHaveBeenCalledTimes(1)
|
|
334
|
+
|
|
335
|
+
await animation[controlType]()
|
|
336
|
+
|
|
337
|
+
receiver?.({
|
|
338
|
+
detail: {
|
|
339
|
+
animationId: animation.id,
|
|
340
|
+
action: 'start',
|
|
341
|
+
playState: 'running',
|
|
342
|
+
finished: false,
|
|
343
|
+
values: { transform: { translate: { x: 2 } } },
|
|
344
|
+
},
|
|
345
|
+
})
|
|
346
|
+
expect(onStart).toHaveBeenCalledTimes(1)
|
|
347
|
+
|
|
348
|
+
receiver?.({
|
|
349
|
+
detail: {
|
|
350
|
+
animationId: animation.id,
|
|
351
|
+
action: controlType,
|
|
352
|
+
playState: controlType === 'finish' ? 'finished' : 'idle',
|
|
353
|
+
finished: controlType === 'finish',
|
|
354
|
+
values: { transform: { translate: { x: 3 } } },
|
|
355
|
+
},
|
|
356
|
+
})
|
|
357
|
+
|
|
358
|
+
receiver?.({
|
|
359
|
+
detail: {
|
|
360
|
+
animationId: animation.id,
|
|
361
|
+
action: 'start',
|
|
362
|
+
playState: 'running',
|
|
363
|
+
finished: false,
|
|
364
|
+
values: { transform: { translate: { x: 4 } } },
|
|
365
|
+
},
|
|
366
|
+
})
|
|
367
|
+
expect(onStart).toHaveBeenCalledTimes(2)
|
|
368
|
+
},
|
|
369
|
+
)
|
|
370
|
+
|
|
371
|
+
it('sends all playback controls to the same native animation id without recreating', async () => {
|
|
372
|
+
const animation = await createAnimation()
|
|
373
|
+
spies.createCommandSpy.mockClear()
|
|
374
|
+
|
|
375
|
+
await animation.play()
|
|
376
|
+
await animation.pause()
|
|
377
|
+
await animation.play()
|
|
378
|
+
await animation.stop()
|
|
379
|
+
await animation.reset()
|
|
380
|
+
await animation.finish()
|
|
381
|
+
|
|
382
|
+
expect(spies.createCommandSpy).not.toHaveBeenCalled()
|
|
383
|
+
expect(spies.controlCommandSpy.mock.calls.map(call => call[0])).toEqual([
|
|
384
|
+
{ animationId: animation.id, type: 'play' },
|
|
385
|
+
{ animationId: animation.id, type: 'pause' },
|
|
386
|
+
{ animationId: animation.id, type: 'play' },
|
|
387
|
+
{ animationId: animation.id, type: 'stop' },
|
|
388
|
+
{ animationId: animation.id, type: 'reset' },
|
|
389
|
+
{ animationId: animation.id, type: 'finish' },
|
|
390
|
+
])
|
|
391
|
+
})
|
|
392
|
+
})
|
|
393
|
+
|
|
394
|
+
describe('Core exports', () => {
|
|
395
|
+
it('keeps internal motion architecture objects out of the public Core export surface', async () => {
|
|
396
|
+
const mod = await import('../index')
|
|
397
|
+
|
|
398
|
+
expect((mod as any).AnimationObject).toBeUndefined()
|
|
399
|
+
expect((mod as any).AnimationObjectChannel).toBeUndefined()
|
|
400
|
+
expect((mod as any).AnimationObjectBridge).toBeUndefined()
|
|
401
|
+
expect((mod as any).SpatialObjectBridge).toBeUndefined()
|
|
402
|
+
})
|
|
403
|
+
|
|
404
|
+
it('exports AnimationObject from the motion entrypoint', async () => {
|
|
405
|
+
const mod = await import('./index')
|
|
406
|
+
|
|
407
|
+
expect(mod.AnimationObject).toBeDefined()
|
|
408
|
+
})
|
|
409
|
+
|
|
410
|
+
it('removes legacy animateMotion entry points from spatialized elements', async () => {
|
|
411
|
+
const mod = await import('../index')
|
|
412
|
+
|
|
413
|
+
expect('animateMotion' in mod.Spatialized2DElement.prototype).toBe(false)
|
|
414
|
+
expect('animateMotion' in mod.SpatializedStatic3DElement.prototype).toBe(
|
|
415
|
+
false,
|
|
416
|
+
)
|
|
417
|
+
expect('animateMotion' in mod.SpatializedDynamic3DElement.prototype).toBe(
|
|
418
|
+
false,
|
|
419
|
+
)
|
|
420
|
+
})
|
|
421
|
+
})
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ControlSpatializedElementAnimationJSBCommand,
|
|
3
|
+
CreateSpatializedElementAnimationJSBCommand,
|
|
4
|
+
} from '../JSBCommand'
|
|
5
|
+
import { SpatialObject } from '../SpatialObject'
|
|
6
|
+
import { SpatialWebEvent } from '../SpatialWebEvent'
|
|
7
|
+
import type {
|
|
8
|
+
ControlSpatializedElementAnimationCommand,
|
|
9
|
+
SpatialAnimationStateChangedDetail,
|
|
10
|
+
SpatialAnimationStateChangedMsg,
|
|
11
|
+
} from '../types/motion/spatializedElementMotion'
|
|
12
|
+
import type { SpatializedPlaybackError } from '../types/motion/spatializedPlayback'
|
|
13
|
+
import type { SpatializedVisualValues } from '../types/motion/spatializedVisual'
|
|
14
|
+
import type {
|
|
15
|
+
SpatializedMotionTimeline,
|
|
16
|
+
SpatializedPlaybackApi,
|
|
17
|
+
SpatializedMotionPlayState,
|
|
18
|
+
} from '../types/motion/spatializedMotion'
|
|
19
|
+
|
|
20
|
+
export interface AnimationObjectCreateOptions {
|
|
21
|
+
elementId: string
|
|
22
|
+
timeline: SpatializedMotionTimeline
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface AnimationObjectCallbacks {
|
|
26
|
+
onStart?: () => void
|
|
27
|
+
onComplete?: (values: SpatializedVisualValues) => void
|
|
28
|
+
onStop?: (values: SpatializedVisualValues) => void
|
|
29
|
+
onReset?: (values: SpatializedVisualValues) => void
|
|
30
|
+
onError?: (error: SpatializedPlaybackError) => void
|
|
31
|
+
onValuesChange?: (values: SpatializedVisualValues) => void
|
|
32
|
+
onStateChange?: () => void
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export class AnimationObject
|
|
36
|
+
extends SpatialObject
|
|
37
|
+
implements SpatializedPlaybackApi
|
|
38
|
+
{
|
|
39
|
+
readonly elementId: string
|
|
40
|
+
readonly timeline: SpatializedMotionTimeline
|
|
41
|
+
|
|
42
|
+
private callbacks: AnimationObjectCallbacks = {}
|
|
43
|
+
private _playState: SpatializedMotionPlayState = 'idle'
|
|
44
|
+
private _finished = false
|
|
45
|
+
private started = false
|
|
46
|
+
|
|
47
|
+
constructor(id: string, options: AnimationObjectCreateOptions) {
|
|
48
|
+
super(id)
|
|
49
|
+
this.elementId = options.elementId
|
|
50
|
+
this.timeline = options.timeline
|
|
51
|
+
|
|
52
|
+
SpatialWebEvent.addEventReceiver(id, data => this.onReceiveEvent(data))
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
static async create(options: AnimationObjectCreateOptions) {
|
|
56
|
+
const ret = await new CreateSpatializedElementAnimationJSBCommand({
|
|
57
|
+
elementId: options.elementId,
|
|
58
|
+
timeline: options.timeline,
|
|
59
|
+
}).execute()
|
|
60
|
+
if (!ret.success) {
|
|
61
|
+
throw new Error(
|
|
62
|
+
ret.errorMessage ?? 'CreateSpatializedElementAnimation command failed',
|
|
63
|
+
)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const data = ret.data as { id?: string } | undefined
|
|
67
|
+
const id = data?.id
|
|
68
|
+
if (!id) {
|
|
69
|
+
throw new Error('CreateSpatializedElementAnimation did not return an id')
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return new AnimationObject(id, options)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
setCallbacks(callbacks: AnimationObjectCallbacks): void {
|
|
76
|
+
this.callbacks = callbacks
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
get playState() {
|
|
80
|
+
return this._playState
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
get isAnimating() {
|
|
84
|
+
return this._playState === 'running' || this._playState === 'queued'
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
get isPaused() {
|
|
88
|
+
return this._playState === 'paused'
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
get finished() {
|
|
92
|
+
return this._finished
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
play(): Promise<void> {
|
|
96
|
+
return this.control('play')
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
pause(): Promise<void> {
|
|
100
|
+
return this.control('pause')
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
stop(): Promise<void> {
|
|
104
|
+
return this.control('stop')
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
reset(): Promise<void> {
|
|
108
|
+
return this.control('reset')
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
finish(): Promise<void> {
|
|
112
|
+
return this.control('finish')
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
protected override onDestroy(): void {
|
|
116
|
+
SpatialWebEvent.removeEventReceiver(this.id)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
private async control(
|
|
120
|
+
type: ControlSpatializedElementAnimationCommand['type'],
|
|
121
|
+
): Promise<void> {
|
|
122
|
+
if (this.isDestroyed) return
|
|
123
|
+
|
|
124
|
+
const ret = await new ControlSpatializedElementAnimationJSBCommand({
|
|
125
|
+
animationId: this.id,
|
|
126
|
+
type,
|
|
127
|
+
}).execute()
|
|
128
|
+
|
|
129
|
+
if (!ret.success) {
|
|
130
|
+
throw new Error(
|
|
131
|
+
ret.errorMessage ??
|
|
132
|
+
`ControlSpatializedElementAnimation(${type}) command failed`,
|
|
133
|
+
)
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
onReceiveEvent(data: SpatialAnimationStateChangedMsg | { detail?: unknown }) {
|
|
138
|
+
const detail = data?.detail ?? data
|
|
139
|
+
if (!this.isSpatialAnimationStateChangedDetail(detail)) return
|
|
140
|
+
if (detail.animationId !== this.id) return
|
|
141
|
+
|
|
142
|
+
this._playState = detail.playState
|
|
143
|
+
this._finished = detail.finished
|
|
144
|
+
|
|
145
|
+
if (detail.values) {
|
|
146
|
+
this.callbacks.onValuesChange?.(detail.values)
|
|
147
|
+
}
|
|
148
|
+
if (detail.action !== 'start') {
|
|
149
|
+
this.callbacks.onStateChange?.()
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
if (detail.error) {
|
|
153
|
+
this.started = false
|
|
154
|
+
// Native currently emits asynchronous errors only when play cannot acquire the ownership mask.
|
|
155
|
+
this.callbacks.onError?.({
|
|
156
|
+
command: 'play',
|
|
157
|
+
code: detail.error.code,
|
|
158
|
+
reason: detail.error.message,
|
|
159
|
+
})
|
|
160
|
+
return
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (detail.action === 'start') {
|
|
164
|
+
if (!this.started) {
|
|
165
|
+
this.started = true
|
|
166
|
+
this.callbacks.onStart?.()
|
|
167
|
+
}
|
|
168
|
+
return
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (detail.action === 'complete' || detail.action === 'finish') {
|
|
172
|
+
this.started = false
|
|
173
|
+
this.callbacks.onComplete?.(detail.values ?? {})
|
|
174
|
+
return
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (detail.action === 'stop') {
|
|
178
|
+
this.started = false
|
|
179
|
+
this.callbacks.onStop?.(detail.values ?? {})
|
|
180
|
+
return
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
if (detail.action === 'reset') {
|
|
184
|
+
this.started = false
|
|
185
|
+
this.callbacks.onReset?.(detail.values ?? {})
|
|
186
|
+
return
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
if (detail.action === 'destroy') {
|
|
190
|
+
this.started = false
|
|
191
|
+
this.isDestroyed = true
|
|
192
|
+
this.onDestroy()
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
private isSpatialAnimationStateChangedDetail(
|
|
197
|
+
detail: unknown,
|
|
198
|
+
): detail is SpatialAnimationStateChangedDetail {
|
|
199
|
+
if (!detail || typeof detail !== 'object') return false
|
|
200
|
+
const candidate = detail as Partial<SpatialAnimationStateChangedDetail>
|
|
201
|
+
return (
|
|
202
|
+
typeof candidate.animationId === 'string' &&
|
|
203
|
+
typeof candidate.action === 'string' &&
|
|
204
|
+
typeof candidate.playState === 'string' &&
|
|
205
|
+
typeof candidate.finished === 'boolean'
|
|
206
|
+
)
|
|
207
|
+
}
|
|
208
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { setMotionPropertyValue } from './motionPropertyValues'
|
|
2
|
+
export {
|
|
3
|
+
validateNormalizedMotionConfig,
|
|
4
|
+
validateSpatializedMotionConfig,
|
|
5
|
+
} from './validate'
|
|
6
|
+
export {
|
|
7
|
+
desugarTimelineConfig,
|
|
8
|
+
normalizeMotionConfig,
|
|
9
|
+
segmentConfigToMotionConfig,
|
|
10
|
+
} from './normalize'
|