@webspatial/core-sdk 1.6.0 → 1.7.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 (54) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/dist/iife/index.d.ts +386 -236
  3. package/dist/iife/index.global.js +7 -7
  4. package/dist/iife/index.global.js.map +1 -1
  5. package/dist/index.d.ts +386 -236
  6. package/dist/index.js +1479 -1226
  7. package/dist/index.js.map +1 -1
  8. package/package.json +1 -1
  9. package/src/JSBCommand.ts +30 -100
  10. package/src/Spatial.ts +0 -21
  11. package/src/SpatialScene.ts +1 -5
  12. package/src/SpatialSession.ts +17 -3
  13. package/src/SpatializedDynamic3DElement.ts +0 -1
  14. package/src/SpatializedElementCreator.ts +6 -4
  15. package/src/SpatializedStatic3DElement.test.ts +99 -0
  16. package/src/SpatializedStatic3DElement.ts +99 -1
  17. package/src/WebMsgCommand.ts +10 -0
  18. package/src/coverage-boost.test.ts +38 -119
  19. package/src/index.ts +3 -1
  20. package/src/jsbcommand.coverage.test.ts +19 -48
  21. package/src/platform-adapter/CommandResultUtils.ts +2 -2
  22. package/src/platform-adapter/createPlatformSync.ts +34 -0
  23. package/src/platform-adapter/index.ts +5 -51
  24. package/src/platform-adapter/interface.ts +35 -23
  25. package/src/platform-adapter/pico-os/PicoOSPlatform.ts +84 -52
  26. package/src/platform-adapter/puppeteer/PuppeteerPlatform.ts +37 -11
  27. package/src/platform-adapter/spatialSceneQuery.ts +17 -0
  28. package/src/platform-adapter/ssr/SSRPlatform.ts +24 -15
  29. package/src/platform-adapter/vision-os/VisionOSPlatform.ts +55 -24
  30. package/src/platform-runtime.ts +13 -0
  31. package/src/reality/Attachment.ts +2 -2
  32. package/src/reality/entity/SpatialEntity.ts +0 -2
  33. package/src/reality/realityCreator.ts +15 -1
  34. package/src/reality/resource/SpatialTextureResource.ts +16 -0
  35. package/src/reality/resource/index.ts +1 -0
  36. package/src/runtime/WebSpatialRuntimeError.ts +16 -0
  37. package/src/runtime/capability-data.ts +113 -0
  38. package/src/runtime/contract-review.test.ts +44 -0
  39. package/src/runtime/index.ts +28 -0
  40. package/src/runtime/jsbAdapterPlatform.test.ts +36 -0
  41. package/src/runtime/jsbAdapterPlatform.ts +51 -0
  42. package/src/runtime/keys.ts +129 -0
  43. package/src/runtime/semver.ts +33 -0
  44. package/src/runtime/supports.test.ts +207 -0
  45. package/src/runtime/supports.ts +110 -0
  46. package/src/runtime/types.ts +11 -0
  47. package/src/runtime/userAgent.ts +64 -0
  48. package/src/scene-polyfill.manifest.test.ts +7 -5
  49. package/src/scene-polyfill.test.ts +60 -0
  50. package/src/scene-polyfill.ts +23 -22
  51. package/src/spatial-host.ts +25 -0
  52. package/src/types/{global.d.ts → global.ts} +10 -5
  53. package/src/types/types.ts +9 -0
  54. package/src/platform-adapter/android/AndroidPlatform.ts +0 -133
@@ -1,22 +1,31 @@
1
- import { PlatformAbility, CommandResult } from '../interface'
1
+ import {
2
+ PlatformAbility,
3
+ CommandResult,
4
+ WebSpatialProtocolResult,
5
+ } from '../interface'
2
6
  import {
3
7
  CommandResultFailure,
4
8
  CommandResultSuccess,
5
9
  } from '../CommandResultUtils'
10
+ import { buildSpatialSceneQuery } from '../spatialSceneQuery'
6
11
  import { SpatialWebEvent } from '../../SpatialWebEvent'
12
+ import type { SpatialSceneCreationOptionsInternal } from '../../types/internal'
13
+ import type { AttachmentEntityOptions } from '../../types/types'
7
14
 
8
15
  interface JSBResponse {
9
16
  success: boolean
10
17
  data: any
11
18
  }
12
19
  type JSBError = {
13
- code: string
20
+ code?: string
14
21
  message: string
15
22
  }
16
23
 
17
24
  let requestId = 0
18
25
 
19
26
  const MAX_ID = 100000
27
+ const DEFAULT_JSB_ERROR_CODE = 'E_PICO_JSB'
28
+ const DEFAULT_JSB_ERROR_MESSAGE = 'Pico JSB execution failed'
20
29
 
21
30
  function nextRequestId() {
22
31
  requestId = (requestId + 1) % MAX_ID
@@ -28,51 +37,67 @@ export class PicoOSPlatform implements PlatformAbility {
28
37
  async callJSB(cmd: string, msg: string): Promise<CommandResult> {
29
38
  // swan JS Bridge interface only support sync invoking
30
39
  // in order to implement promise API, register every request by requestId and remove when resolve/reject.
31
- return new Promise((resolve, reject) => {
40
+ return new Promise(resolve => {
32
41
  try {
33
42
  const rId = nextRequestId()
34
43
 
35
44
  SpatialWebEvent.addEventReceiver(rId, (result: JSBResponse) => {
36
45
  SpatialWebEvent.removeEventReceiver(rId)
37
- if (result.success) {
38
- resolve(CommandResultSuccess(result.data))
39
- } else {
40
- const { code, message } = result.data as JSBError
41
- resolve(CommandResultFailure(code, message))
42
- }
46
+ resolve(this.toCommandResult(result))
43
47
  })
44
48
 
45
49
  const ans = window.webspatialBridge.postMessage(rId, cmd, msg)
46
50
  if (ans !== '') {
47
51
  SpatialWebEvent.removeEventReceiver(rId)
48
52
  // sync call
49
- const result = JSON.parse(ans) as JSBResponse
50
- if (result.success) {
51
- resolve(CommandResultSuccess(result.data))
52
- } else {
53
- const { code, message } = result.data as JSBError
54
- resolve(CommandResultFailure(code, message))
55
- }
53
+ resolve(this.parseBridgeResponse(ans))
56
54
  }
57
55
  } catch (error: unknown) {
58
56
  console.error(`SwanPlatform cmd: ${cmd}, msg: ${msg} error: ${error}`)
59
- const { code, message } = error as JSBError
57
+ const { code, message } = this.parseJSBError(error)
60
58
  resolve(CommandResultFailure(code, message))
61
59
  }
62
60
  })
63
61
  }
64
62
 
65
- async callWebSpatialProtocol(
66
- command: string,
67
- query?: string,
63
+ openSpatialSceneSync(
64
+ url: string,
65
+ config: SpatialSceneCreationOptionsInternal | undefined,
68
66
  target?: string,
69
67
  features?: string,
70
- ): Promise<CommandResult> {
71
- // Waiting for request to create spatial div
72
- return new Promise((resolve, reject) => {
68
+ ): WebSpatialProtocolResult {
69
+ const query = buildSpatialSceneQuery(url, config)
70
+ const { spatialId: id = '', windowProxy } = this.openWindow(
71
+ 'createSpatialScene',
72
+ query,
73
+ target,
74
+ features,
75
+ )
76
+
77
+ return CommandResultSuccess({ windowProxy, id })
78
+ }
79
+
80
+ createNativeSpatialDiv(): Promise<WebSpatialProtocolResult> {
81
+ return this.waitForRidProtocolAsync('createSpatialized2DElement')
82
+ }
83
+
84
+ createNativeAttachment(
85
+ _options?: AttachmentEntityOptions,
86
+ ): Promise<WebSpatialProtocolResult> {
87
+ return this.waitForRidProtocolAsync('createAttachment')
88
+ }
89
+
90
+ /**
91
+ * Async path for createNativeSpatialDiv / createNativeAttachment: open webspatial URL
92
+ * with rid= correlation (Pico OS 6).
93
+ */
94
+ private waitForRidProtocolAsync(
95
+ command: string,
96
+ ): Promise<WebSpatialProtocolResult> {
97
+ return new Promise(resolve => {
73
98
  const createdId = nextRequestId()
74
99
  try {
75
- let windowProxy: any = null
100
+ let windowProxy: WindowProxy | null = null
76
101
  SpatialWebEvent.addEventReceiver(
77
102
  createdId,
78
103
  (result: { spatialId: string }) => {
@@ -85,47 +110,54 @@ export class PicoOSPlatform implements PlatformAbility {
85
110
  SpatialWebEvent.removeEventReceiver(createdId)
86
111
  },
87
112
  )
88
- windowProxy = this.openWindow(
89
- command,
90
- 'rid=' + createdId,
91
- target,
92
- features,
93
- ).windowProxy
113
+ windowProxy = this.openWindow(command, 'rid=' + createdId).windowProxy
94
114
  } catch (error: unknown) {
95
- const { code, message } = error as JSBError
115
+ const { code, message } = this.parseJSBError(error)
96
116
  SpatialWebEvent.removeEventReceiver(createdId)
97
117
  resolve(CommandResultFailure(code, message))
98
118
  }
99
119
  })
100
120
  }
101
121
 
102
- callWebSpatialProtocolSync(
122
+ private openWindow(
103
123
  command: string,
104
124
  query?: string,
105
125
  target?: string,
106
126
  features?: string,
107
- ): CommandResult {
108
- const { spatialId: id = '', windowProxy } = this.openWindow(
109
- command,
110
- query,
111
- target,
112
- features,
113
- )
127
+ ): { spatialId: string; windowProxy: WindowProxy | null } {
128
+ const url = query
129
+ ? `webspatial://${command}?${query}`
130
+ : `webspatial://${command}`
131
+ const windowProxy = window.open(url, target, features)
132
+ return { spatialId: '', windowProxy }
133
+ }
114
134
 
115
- return CommandResultSuccess({ windowProxy, id })
135
+ private parseBridgeResponse(ans: string): CommandResult {
136
+ try {
137
+ const result = JSON.parse(ans) as JSBResponse
138
+ return this.toCommandResult(result)
139
+ } catch {
140
+ return CommandResultFailure(
141
+ DEFAULT_JSB_ERROR_CODE,
142
+ 'Invalid Pico JSB response payload',
143
+ )
144
+ }
116
145
  }
117
146
 
118
- private openWindow(
119
- command: string,
120
- query?: string,
121
- target?: string,
122
- features?: string,
123
- ) {
124
- const windowProxy = window.open(
125
- `webspatial://${command}?${query || ''}`,
126
- target,
127
- features,
128
- )
129
- return { spatialId: '', windowProxy }
147
+ private toCommandResult(result: JSBResponse): CommandResult {
148
+ if (result.success) {
149
+ return CommandResultSuccess(result.data)
150
+ }
151
+ const { code, message } = this.parseJSBError(result.data)
152
+ return CommandResultFailure(code, message)
153
+ }
154
+
155
+ private parseJSBError(error: unknown): { code: string; message: string } {
156
+ return {
157
+ code: (error as JSBError)?.code ?? DEFAULT_JSB_ERROR_CODE,
158
+ message:
159
+ (error as JSBError)?.message ??
160
+ (typeof error === 'string' ? error : DEFAULT_JSB_ERROR_MESSAGE),
161
+ }
130
162
  }
131
163
  }
@@ -1,4 +1,11 @@
1
- import { PlatformAbility, CommandResult } from '../interface'
1
+ import {
2
+ PlatformAbility,
3
+ CommandResult,
4
+ WebSpatialProtocolResult,
5
+ } from '../interface'
6
+ import { buildSpatialSceneQuery } from '../spatialSceneQuery'
7
+ import type { SpatialSceneCreationOptionsInternal } from '../../types/internal'
8
+ import type { AttachmentEntityOptions } from '../../types/types'
2
9
  import {
3
10
  CommandResultFailure,
4
11
  CommandResultSuccess,
@@ -17,12 +24,6 @@ declare global {
17
24
  }
18
25
  }
19
26
 
20
- type JSBError = {
21
- message: string
22
- }
23
-
24
- console.log('PuppeteerPlatform')
25
-
26
27
  export class PuppeteerPlatform implements PlatformAbility {
27
28
  // store iframe instance
28
29
  private iframeRegistry: Map<string, HTMLIFrameElement> = new Map()
@@ -85,12 +86,37 @@ export class PuppeteerPlatform implements PlatformAbility {
85
86
  }
86
87
  }
87
88
 
88
- callWebSpatialProtocol(
89
+ openSpatialSceneSync(
90
+ url: string,
91
+ config: SpatialSceneCreationOptionsInternal | undefined,
92
+ target?: string,
93
+ features?: string,
94
+ ): WebSpatialProtocolResult {
95
+ const query = buildSpatialSceneQuery(url, config)
96
+ return this.runProtocolSync('createSpatialScene', query, target, features)
97
+ }
98
+
99
+ createNativeSpatialDiv(): Promise<WebSpatialProtocolResult> {
100
+ return this.runProtocolAsync(
101
+ 'createSpatialized2DElement',
102
+ '',
103
+ undefined,
104
+ undefined,
105
+ )
106
+ }
107
+
108
+ createNativeAttachment(
109
+ _options?: AttachmentEntityOptions,
110
+ ): Promise<WebSpatialProtocolResult> {
111
+ return this.runProtocolAsync('createAttachment', '', undefined, undefined)
112
+ }
113
+
114
+ private runProtocolAsync(
89
115
  command: string,
90
116
  query?: string,
91
117
  target?: string,
92
118
  features?: string,
93
- ): Promise<CommandResult> {
119
+ ): Promise<WebSpatialProtocolResult> {
94
120
  console.log(
95
121
  `PuppeteerPlatform: Calling webspatial protocol: webspatial://${command}${query ? `?${query}` : ''}`,
96
122
  )
@@ -124,12 +150,12 @@ export class PuppeteerPlatform implements PlatformAbility {
124
150
  })
125
151
  }
126
152
 
127
- callWebSpatialProtocolSync(
153
+ private runProtocolSync(
128
154
  command: string,
129
155
  query?: string,
130
156
  target?: string,
131
157
  features?: string,
132
- ): CommandResult {
158
+ ): WebSpatialProtocolResult {
133
159
  try {
134
160
  // create complete webspatial URL
135
161
  const webspatialUrl = `webspatial://${command}${query ? `?${query}` : ''}`
@@ -0,0 +1,17 @@
1
+ import type { SpatialSceneCreationOptionsInternal } from '../types/internal'
2
+
3
+ /** Build query string for webspatial://createSpatialScene (url + config). */
4
+ export function buildSpatialSceneQuery(
5
+ url: string,
6
+ config: SpatialSceneCreationOptionsInternal | undefined,
7
+ ): string {
8
+ const params: Record<string, any> = { url, config }
9
+ return Object.keys(params)
10
+ .map(key => {
11
+ const value = params[key]
12
+ const finalValue =
13
+ typeof value === 'object' ? JSON.stringify(value) : value
14
+ return `${key}=${encodeURIComponent(finalValue)}`
15
+ })
16
+ .join('&')
17
+ }
@@ -3,6 +3,8 @@ import {
3
3
  PlatformAbility,
4
4
  WebSpatialProtocolResult,
5
5
  } from '../interface'
6
+ import type { SpatialSceneCreationOptionsInternal } from '../../types/internal'
7
+ import type { AttachmentEntityOptions } from '../../types/types'
6
8
 
7
9
  export class SSRPlatform implements PlatformAbility {
8
10
  callJSB(cmd: string, msg: string): Promise<CommandResult> {
@@ -13,12 +15,22 @@ export class SSRPlatform implements PlatformAbility {
13
15
  errorMessage: undefined,
14
16
  })
15
17
  }
16
- callWebSpatialProtocol(
17
- schema: string,
18
- query?: string,
19
- target?: string,
20
- features?: string,
21
- ): Promise<WebSpatialProtocolResult> {
18
+
19
+ openSpatialSceneSync(
20
+ _url: string,
21
+ _config: SpatialSceneCreationOptionsInternal | undefined,
22
+ _target?: string,
23
+ _features?: string,
24
+ ): WebSpatialProtocolResult {
25
+ return {
26
+ success: true,
27
+ data: undefined,
28
+ errorCode: undefined,
29
+ errorMessage: undefined,
30
+ }
31
+ }
32
+
33
+ createNativeSpatialDiv(): Promise<WebSpatialProtocolResult> {
22
34
  return Promise.resolve({
23
35
  success: true,
24
36
  data: undefined,
@@ -26,18 +38,15 @@ export class SSRPlatform implements PlatformAbility {
26
38
  errorMessage: undefined,
27
39
  })
28
40
  }
29
- callWebSpatialProtocolSync(
30
- schema: string,
31
- query?: string,
32
- target?: string,
33
- features?: string,
34
- resultCallback?: (result: CommandResult) => void,
35
- ): WebSpatialProtocolResult {
36
- return {
41
+
42
+ createNativeAttachment(
43
+ _options?: AttachmentEntityOptions,
44
+ ): Promise<WebSpatialProtocolResult> {
45
+ return Promise.resolve({
37
46
  success: true,
38
47
  data: undefined,
39
48
  errorCode: undefined,
40
49
  errorMessage: undefined,
41
- }
50
+ })
42
51
  }
43
52
  }
@@ -1,13 +1,24 @@
1
- import { PlatformAbility, CommandResult } from '../interface'
1
+ import {
2
+ PlatformAbility,
3
+ CommandResult,
4
+ WebSpatialProtocolResult,
5
+ } from '../interface'
2
6
  import {
3
7
  CommandResultFailure,
4
8
  CommandResultSuccess,
5
9
  } from '../CommandResultUtils'
10
+ import { buildSpatialSceneQuery } from '../spatialSceneQuery'
11
+ import type { SpatialSceneCreationOptionsInternal } from '../../types/internal'
12
+ import type { AttachmentEntityOptions } from '../../types/types'
6
13
 
7
14
  type JSBError = {
15
+ code?: string
8
16
  message: string
9
17
  }
10
18
 
19
+ const UUID_RE =
20
+ /\b([0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12})\b/gi
21
+
11
22
  export class VisionOSPlatform implements PlatformAbility {
12
23
  async callJSB(cmd: string, msg: string): Promise<CommandResult> {
13
24
  try {
@@ -17,41 +28,47 @@ export class VisionOSPlatform implements PlatformAbility {
17
28
  return CommandResultSuccess(result)
18
29
  } catch (error: unknown) {
19
30
  // console.error(`VisionOSPlatform cmd: ${cmd}, msg: ${msg} error: ${error}`)
20
- const { code, message } = JSON.parse((error as JSBError).message)
31
+ const { code, message } = this.parseJSBError(error)
21
32
  return CommandResultFailure(code, message)
22
33
  }
23
34
  }
24
35
 
25
- callWebSpatialProtocol(
26
- command: string,
27
- query?: string,
36
+ openSpatialSceneSync(
37
+ url: string,
38
+ config: SpatialSceneCreationOptionsInternal | undefined,
28
39
  target?: string,
29
40
  features?: string,
30
- ): Promise<CommandResult> {
31
- const { spatialId: id, windowProxy } = this.openWindow(
32
- command,
41
+ ): WebSpatialProtocolResult {
42
+ const query = buildSpatialSceneQuery(url, config)
43
+ const { spatialId: id = '', windowProxy } = this.openWindow(
44
+ 'createSpatialScene',
33
45
  query,
34
46
  target,
35
47
  features,
36
48
  )
37
- return Promise.resolve(
38
- CommandResultSuccess({ windowProxy: windowProxy, id }),
39
- )
49
+
50
+ return CommandResultSuccess({ windowProxy, id })
51
+ }
52
+
53
+ createNativeSpatialDiv(): Promise<WebSpatialProtocolResult> {
54
+ return this.openProtocolAsync('createSpatialized2DElement')
55
+ }
56
+
57
+ createNativeAttachment(
58
+ _options?: AttachmentEntityOptions,
59
+ ): Promise<WebSpatialProtocolResult> {
60
+ return this.openProtocolAsync('createAttachment')
40
61
  }
41
62
 
42
- callWebSpatialProtocolSync(
63
+ private async openProtocolAsync(
43
64
  command: string,
44
- query?: string,
45
- target?: string,
46
- features?: string,
47
- ): CommandResult {
65
+ ): Promise<WebSpatialProtocolResult> {
48
66
  const { spatialId: id = '', windowProxy } = this.openWindow(
49
67
  command,
50
- query,
51
- target,
52
- features,
68
+ '',
69
+ undefined,
70
+ undefined,
53
71
  )
54
-
55
72
  return CommandResultSuccess({ windowProxy, id })
56
73
  }
57
74
 
@@ -60,17 +77,31 @@ export class VisionOSPlatform implements PlatformAbility {
60
77
  query?: string,
61
78
  target?: string,
62
79
  features?: string,
63
- ) {
80
+ ): { spatialId?: string; windowProxy: WindowProxy | null } {
64
81
  const windowProxy = window.open(
65
82
  `webspatial://${command}?${query || ''}`,
66
83
  target,
67
84
  features,
68
85
  )
69
86
  const ua = windowProxy?.navigator.userAgent
70
- const spatialId = ua?.match(
71
- /\b([0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12})\b/gi,
72
- )?.[0]
87
+ const spatialId = ua?.match(UUID_RE)?.[0]
73
88
 
74
89
  return { spatialId, windowProxy }
75
90
  }
91
+
92
+ private parseJSBError(error: unknown): { code: string; message: string } {
93
+ try {
94
+ const parsed = JSON.parse((error as JSBError).message ?? '')
95
+ return {
96
+ code: parsed.code ?? 'E_VISIONOS_JSB',
97
+ message: parsed.message ?? 'VisionOS JSB execution failed',
98
+ }
99
+ } catch {
100
+ return {
101
+ code: 'E_VISIONOS_JSB',
102
+ message:
103
+ (error as JSBError)?.message ?? 'VisionOS JSB execution failed',
104
+ }
105
+ }
106
+ }
76
107
  }
@@ -0,0 +1,13 @@
1
+ import { createPlatformSync } from './platform-adapter'
2
+ import type { PlatformAbility } from './platform-adapter/interface'
3
+
4
+ let platformResolved: PlatformAbility | undefined
5
+
6
+ export function getPlatformSync(): PlatformAbility {
7
+ platformResolved ??= createPlatformSync()
8
+ return platformResolved
9
+ }
10
+
11
+ export async function getPlatform(): Promise<PlatformAbility> {
12
+ return getPlatformSync()
13
+ }
@@ -1,9 +1,9 @@
1
1
  import { SpatialObject } from '../SpatialObject'
2
2
  import {
3
- CreateAttachmentEntityCommand,
4
3
  UpdateAttachmentEntityCommand,
5
4
  InitializeAttachmentCommand,
6
5
  } from '../JSBCommand'
6
+ import { createNativeAttachment } from '../spatial-host'
7
7
  import {
8
8
  AttachmentEntityOptions,
9
9
  AttachmentEntityUpdateOptions,
@@ -37,7 +37,7 @@ export class Attachment extends SpatialObject {
37
37
  export async function createAttachmentEntity(
38
38
  options: AttachmentEntityOptions,
39
39
  ): Promise<Attachment> {
40
- const result = await new CreateAttachmentEntityCommand(options).execute()
40
+ const result = await createNativeAttachment(options)
41
41
  if (!result.success) {
42
42
  throw new Error('createAttachmentEntity failed: ' + result?.errorMessage)
43
43
  }
@@ -12,9 +12,7 @@ import {
12
12
  } from '../../types/types'
13
13
  import {
14
14
  AddComponentToEntityCommand,
15
- AddEntityToEntityCommand,
16
15
  RemoveComponentFromEntityCommand,
17
- RemoveEntityFromParentCommand,
18
16
  UpdateEntityEventCommand,
19
17
  UpdateEntityPropertiesCommand,
20
18
  } from '../../JSBCommand'
@@ -5,6 +5,7 @@ import {
5
5
  CreateSpatialGeometryCommand,
6
6
  CreateSpatialModelEntityCommand,
7
7
  CreateSpatialUnlitMaterialCommand,
8
+ CreateTextureCommand,
8
9
  } from '../JSBCommand'
9
10
  import {
10
11
  ModelComponentOptions,
@@ -13,12 +14,13 @@ import {
13
14
  SpatialModelEntityCreationOptions,
14
15
  SpatialUnlitMaterialOptions,
15
16
  SpatialEntityUserData,
17
+ SpatialTextureResourceOptions,
16
18
  } from '../types/types'
17
19
  import { SpatialEntity, SpatialModelEntity } from './entity'
18
20
  import { ModelComponent } from './component'
19
21
  import { SpatialGeometry } from './geometry'
20
22
  import { SpatialUnlitMaterial } from './material'
21
- import { SpatialModelAsset } from './resource'
23
+ import { SpatialModelAsset, SpatialTextureResource } from './resource'
22
24
 
23
25
  export async function createSpatialEntity(
24
26
  userData?: SpatialEntityUserData,
@@ -92,3 +94,15 @@ export async function createModelAsset(options: ModelAssetOptions) {
92
94
  return new SpatialModelAsset(id, options)
93
95
  }
94
96
  }
97
+
98
+ export async function createSpatialTexture(
99
+ options: SpatialTextureResourceOptions,
100
+ ) {
101
+ const result = await new CreateTextureCommand(options.url).execute()
102
+ if (!result.success) {
103
+ throw new Error('createSpatialTexture failed:' + result?.errorMessage)
104
+ } else {
105
+ const { id } = result.data
106
+ return new SpatialTextureResource(id, options)
107
+ }
108
+ }
@@ -0,0 +1,16 @@
1
+ import { SpatialObject } from '../../SpatialObject'
2
+ import { SpatialTextureResourceOptions } from '../../types/types'
3
+ import { UpdateTexturePropertiesCommand } from '../../JSBCommand'
4
+
5
+ export class SpatialTextureResource extends SpatialObject {
6
+ constructor(
7
+ public id: string,
8
+ public options: SpatialTextureResourceOptions,
9
+ ) {
10
+ super(id)
11
+ }
12
+
13
+ updateProperties(properties: Partial<SpatialTextureResourceOptions>) {
14
+ return new UpdateTexturePropertiesCommand(this, properties).execute()
15
+ }
16
+ }
@@ -1 +1,2 @@
1
1
  export * from './SpatialModelAsset'
2
+ export * from './SpatialTextureResource'
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Thrown when a runtime-gated JS API is invoked but `supports('<name>')` is false.
3
+ * See OpenSpec `runtime-capabilities/spec.md` (Unsupported behavior contracts).
4
+ */
5
+ export class WebSpatialRuntimeError extends Error {
6
+ public readonly capability: string
7
+
8
+ constructor(capability: string, message?: string) {
9
+ super(
10
+ message ??
11
+ `Capability "${capability}" is not supported in this WebSpatial runtime`,
12
+ )
13
+ this.name = 'WebSpatialRuntimeError'
14
+ this.capability = capability
15
+ }
16
+ }