@webspatial/core-sdk 0.0.1-alpha

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 (99) hide show
  1. package/README.md +112 -0
  2. package/dist/core/Spatial.d.ts +27 -0
  3. package/dist/core/Spatial.d.ts.map +1 -0
  4. package/dist/core/Spatial.js +41 -0
  5. package/dist/core/SpatialEntity.d.ts +92 -0
  6. package/dist/core/SpatialEntity.d.ts.map +1 -0
  7. package/dist/core/SpatialEntity.js +121 -0
  8. package/dist/core/SpatialHelper.d.ts +39 -0
  9. package/dist/core/SpatialHelper.d.ts.map +1 -0
  10. package/dist/core/SpatialHelper.js +169 -0
  11. package/dist/core/SpatialObject.d.ts +19 -0
  12. package/dist/core/SpatialObject.d.ts.map +1 -0
  13. package/dist/core/SpatialObject.js +22 -0
  14. package/dist/core/SpatialSession.d.ts +166 -0
  15. package/dist/core/SpatialSession.d.ts.map +1 -0
  16. package/dist/core/SpatialSession.js +310 -0
  17. package/dist/core/SpatialTransform.d.ts +23 -0
  18. package/dist/core/SpatialTransform.d.ts.map +1 -0
  19. package/dist/core/SpatialTransform.js +31 -0
  20. package/dist/core/SpatialWindowContainer.d.ts +31 -0
  21. package/dist/core/SpatialWindowContainer.d.ts.map +1 -0
  22. package/dist/core/SpatialWindowContainer.js +48 -0
  23. package/dist/core/component/EventSpatialComponent.d.ts +22 -0
  24. package/dist/core/component/EventSpatialComponent.d.ts.map +1 -0
  25. package/dist/core/component/EventSpatialComponent.js +23 -0
  26. package/dist/core/component/SpatialComponent.d.ts +11 -0
  27. package/dist/core/component/SpatialComponent.d.ts.map +1 -0
  28. package/dist/core/component/SpatialComponent.js +23 -0
  29. package/dist/core/component/SpatialInputComponent.d.ts +22 -0
  30. package/dist/core/component/SpatialInputComponent.d.ts.map +1 -0
  31. package/dist/core/component/SpatialInputComponent.js +14 -0
  32. package/dist/core/component/SpatialModel3DComponent.d.ts +86 -0
  33. package/dist/core/component/SpatialModel3DComponent.d.ts.map +1 -0
  34. package/dist/core/component/SpatialModel3DComponent.js +176 -0
  35. package/dist/core/component/SpatialModelComponent.d.ts +22 -0
  36. package/dist/core/component/SpatialModelComponent.d.ts.map +1 -0
  37. package/dist/core/component/SpatialModelComponent.js +34 -0
  38. package/dist/core/component/SpatialViewComponent.d.ts +22 -0
  39. package/dist/core/component/SpatialViewComponent.d.ts.map +1 -0
  40. package/dist/core/component/SpatialViewComponent.js +30 -0
  41. package/dist/core/component/SpatialWindowComponent.d.ts +86 -0
  42. package/dist/core/component/SpatialWindowComponent.d.ts.map +1 -0
  43. package/dist/core/component/SpatialWindowComponent.js +114 -0
  44. package/dist/core/component/index.d.ts +7 -0
  45. package/dist/core/component/index.d.ts.map +1 -0
  46. package/dist/core/component/index.js +6 -0
  47. package/dist/core/index.d.ts +11 -0
  48. package/dist/core/index.d.ts.map +1 -0
  49. package/dist/core/index.js +9 -0
  50. package/dist/core/private/WebSpatial.d.ts +46 -0
  51. package/dist/core/private/WebSpatial.d.ts.map +1 -0
  52. package/dist/core/private/WebSpatial.js +282 -0
  53. package/dist/core/private/remote-command/RemoteCommand.d.ts +8 -0
  54. package/dist/core/private/remote-command/RemoteCommand.d.ts.map +1 -0
  55. package/dist/core/private/remote-command/RemoteCommand.js +11 -0
  56. package/dist/core/private/remote-command/index.d.ts +2 -0
  57. package/dist/core/private/remote-command/index.d.ts.map +1 -0
  58. package/dist/core/private/remote-command/index.js +1 -0
  59. package/dist/core/resource/SpatialMeshResource.d.ts +7 -0
  60. package/dist/core/resource/SpatialMeshResource.d.ts.map +1 -0
  61. package/dist/core/resource/SpatialMeshResource.js +6 -0
  62. package/dist/core/resource/SpatialPhysicallyBasedMaterialResource.d.ts +37 -0
  63. package/dist/core/resource/SpatialPhysicallyBasedMaterialResource.d.ts.map +1 -0
  64. package/dist/core/resource/SpatialPhysicallyBasedMaterialResource.js +37 -0
  65. package/dist/core/resource/index.d.ts +3 -0
  66. package/dist/core/resource/index.d.ts.map +1 -0
  67. package/dist/core/resource/index.js +2 -0
  68. package/dist/core/types.d.ts +23 -0
  69. package/dist/core/types.d.ts.map +1 -0
  70. package/dist/core/types.js +1 -0
  71. package/dist/index.d.ts +2 -0
  72. package/dist/index.d.ts.map +1 -0
  73. package/dist/index.js +1 -0
  74. package/package.json +35 -0
  75. package/src/core/Spatial.ts +48 -0
  76. package/src/core/SpatialEntity.ts +146 -0
  77. package/src/core/SpatialHelper.ts +197 -0
  78. package/src/core/SpatialObject.ts +24 -0
  79. package/src/core/SpatialSession.ts +434 -0
  80. package/src/core/SpatialTransform.ts +26 -0
  81. package/src/core/SpatialWindowContainer.ts +51 -0
  82. package/src/core/component/EventSpatialComponent.ts +32 -0
  83. package/src/core/component/SpatialComponent.ts +26 -0
  84. package/src/core/component/SpatialInputComponent.ts +24 -0
  85. package/src/core/component/SpatialModel3DComponent.ts +213 -0
  86. package/src/core/component/SpatialModelComponent.ts +39 -0
  87. package/src/core/component/SpatialViewComponent.ts +32 -0
  88. package/src/core/component/SpatialWindowComponent.ts +168 -0
  89. package/src/core/component/index.ts +14 -0
  90. package/src/core/index.ts +10 -0
  91. package/src/core/private/WebSpatial.ts +356 -0
  92. package/src/core/private/remote-command/RemoteCommand.ts +15 -0
  93. package/src/core/private/remote-command/index.ts +1 -0
  94. package/src/core/resource/SpatialMeshResource.ts +6 -0
  95. package/src/core/resource/SpatialPhysicallyBasedMaterialResource.ts +42 -0
  96. package/src/core/resource/index.ts +2 -0
  97. package/src/core/types.ts +27 -0
  98. package/src/index.ts +1 -0
  99. package/tsconfig.json +26 -0
@@ -0,0 +1,356 @@
1
+ import { RemoteCommand } from './remote-command'
2
+ import {
3
+ WindowStyle,
4
+ WindowContainerOptions,
5
+ LoadingMethodKind,
6
+ sceneDataShape,
7
+ sceneDataJSBShape,
8
+ } from '../types'
9
+
10
+ export class WindowContainer {
11
+ id = ''
12
+ }
13
+
14
+ export class WebSpatialResource {
15
+ id = ''
16
+ windowContainerId = ''
17
+ data = {} as any
18
+
19
+ receiveEvent() {}
20
+ }
21
+
22
+ export class WebSpatial {
23
+ public static eventPromises: any = {}
24
+
25
+ public static transactionStarted = false
26
+ public static transactionCommands = Array<RemoteCommand>()
27
+
28
+ // store event receivers
29
+ private static eventReceivers: { [resourceId: string]: (data: any) => void } =
30
+ {}
31
+
32
+ public static registerEventReceiver(
33
+ resourceId: string,
34
+ callback: (data: any) => void,
35
+ ) {
36
+ this.eventReceivers[resourceId] = callback
37
+ }
38
+
39
+ public static unregisterEventReceiver(resourceId: string) {
40
+ delete this.eventReceivers[resourceId]
41
+ }
42
+
43
+ static init() {
44
+ ;(window as any).__SpatialWebEvent = (e: any) => {
45
+ if (e.resourceId) {
46
+ var callback = WebSpatial.eventReceivers[e.resourceId]
47
+ callback(e.data)
48
+ } else {
49
+ var p = WebSpatial.eventPromises[e.requestID]
50
+ if (p) {
51
+ if (e.success) {
52
+ p.res(e)
53
+ } else {
54
+ p.rej(e)
55
+ }
56
+ }
57
+ }
58
+ }
59
+ }
60
+
61
+ static startTransaction() {
62
+ WebSpatial.transactionStarted = true
63
+ WebSpatial.transactionCommands = []
64
+ }
65
+
66
+ static async sendTransaction() {
67
+ WebSpatial.transactionStarted = false
68
+ var cmd = new RemoteCommand('multiCommand', {
69
+ commandList: WebSpatial.transactionCommands,
70
+ })
71
+
72
+ var result = await new Promise((res, rej) => {
73
+ WebSpatial.eventPromises[cmd.requestID] = { res: res, rej: rej }
74
+ WebSpatial.sendCommand(cmd)
75
+ })
76
+ return result
77
+ }
78
+
79
+ static getBackend() {
80
+ if ((window as any).webkit) {
81
+ return 'AVP'
82
+ } else {
83
+ return 'UNKNOWN'
84
+ }
85
+ }
86
+
87
+ static async sendCommand(cmd: RemoteCommand) {
88
+ if ((window as any).__WebSpatialUnloaded) {
89
+ return
90
+ }
91
+ if (WebSpatial.transactionStarted) {
92
+ WebSpatial.transactionCommands.push(cmd as any)
93
+ return
94
+ }
95
+
96
+ var msg = JSON.stringify(cmd)
97
+
98
+ if (WebSpatial.getBackend() == 'AVP') {
99
+ ;(window as any).webkit.messageHandlers.bridge.postMessage(msg)
100
+ return
101
+ } else {
102
+ ;(window as any).bridge.nativeMessage(msg)
103
+ return
104
+ }
105
+ }
106
+
107
+ static getImmersiveWindowContainer() {
108
+ var wg = new WindowContainer()
109
+ wg.id = 'Immersive'
110
+ return wg
111
+ }
112
+
113
+ static getCurrentWindowContainer() {
114
+ var wg = new WindowContainer()
115
+ wg.id = 'current'
116
+ return wg
117
+ }
118
+
119
+ static getCurrentWebPanel() {
120
+ var wg = new WebSpatialResource()
121
+ wg.id = 'current'
122
+ wg.windowContainerId = WebSpatial.getCurrentWindowContainer().id
123
+ return wg
124
+ }
125
+
126
+ static async createScene(
127
+ style: WindowStyle = 'Plain',
128
+ cfg: {
129
+ sceneData: sceneDataShape
130
+ },
131
+ ) {
132
+ const { window: newWindow, ...sceneData } = cfg.sceneData
133
+ const jsbSceneData: sceneDataJSBShape = {
134
+ ...sceneData,
135
+ windowID: (newWindow as any)._webSpatialID,
136
+ windowContainerID: (newWindow as any)._webSpatialGroupID,
137
+ }
138
+ var cmd = new RemoteCommand('createScene', {
139
+ windowStyle: style,
140
+ sceneData: jsbSceneData,
141
+ windowContainerID: (window as any)._webSpatialParentGroupID, // parent WindowContainerID
142
+ })
143
+
144
+ try {
145
+ await new Promise((res, rej) => {
146
+ WebSpatial.eventPromises[cmd.requestID] = { res: res, rej: rej }
147
+ WebSpatial.sendCommand(cmd)
148
+ })
149
+ return true
150
+ } catch (error) {
151
+ return false
152
+ }
153
+ }
154
+
155
+ static async createWindowContainer(
156
+ style: WindowStyle = 'Plain',
157
+ windowContainer: WindowContainer | null,
158
+ parentWebView: WebSpatialResource | null,
159
+ ) {
160
+ var cmd = new RemoteCommand('createWindowContainer', {
161
+ windowStyle: style,
162
+ windowContainerID: windowContainer ? windowContainer.id : undefined,
163
+ resourceID: parentWebView ? parentWebView.id : undefined,
164
+ })
165
+
166
+ var result = await new Promise((res, rej) => {
167
+ WebSpatial.eventPromises[cmd.requestID] = { res: res, rej: rej }
168
+ WebSpatial.sendCommand(cmd)
169
+ })
170
+ var res = new WindowContainer()
171
+ res.id = (result as any).data.createdID
172
+ return res
173
+ }
174
+
175
+ static async destroyResource(resource: WebSpatialResource) {
176
+ const data = {}
177
+ var cmd = new RemoteCommand('destroyResource', {
178
+ windowContainerID: resource.windowContainerId,
179
+ resourceID: resource.id,
180
+ })
181
+
182
+ WebSpatial.sendCommand(cmd)
183
+ }
184
+
185
+ static async ping(msg: string) {
186
+ var cmd = new RemoteCommand('ping', {
187
+ windowContainerID: this.getCurrentWindowContainer().id,
188
+ resourceID: this.getCurrentWebPanel().id,
189
+ message: msg,
190
+ })
191
+
192
+ if (WebSpatial.transactionStarted) {
193
+ WebSpatial.sendCommand(cmd)
194
+ return null
195
+ } else {
196
+ var result = await new Promise((res, rej) => {
197
+ WebSpatial.eventPromises[cmd.requestID] = { res: res, rej: rej }
198
+ WebSpatial.sendCommand(cmd)
199
+ })
200
+ return result
201
+ }
202
+ }
203
+
204
+ static async getStats() {
205
+ var cmd = new RemoteCommand('getStats', {
206
+ windowContainerID: this.getCurrentWindowContainer().id,
207
+ resourceID: this.getCurrentWebPanel().id,
208
+ })
209
+
210
+ var result = await new Promise((res, rej) => {
211
+ WebSpatial.eventPromises[cmd.requestID] = { res: res, rej: rej }
212
+ WebSpatial.sendCommand(cmd)
213
+ })
214
+ return (result as any).data
215
+ }
216
+
217
+ static async inspect(spatialObjectId: string) {
218
+ var cmd = new RemoteCommand('inspect', {
219
+ resourceID: spatialObjectId,
220
+ })
221
+
222
+ var result = await new Promise((res, rej) => {
223
+ WebSpatial.eventPromises[cmd.requestID] = { res: res, rej: rej }
224
+ WebSpatial.sendCommand(cmd)
225
+ })
226
+
227
+ return (result as any).data
228
+ }
229
+
230
+ static async inspectRootWindowContainer() {
231
+ return this.inspect('root')
232
+ }
233
+
234
+ static async setComponent(
235
+ entity: WebSpatialResource,
236
+ resource: WebSpatialResource,
237
+ ) {
238
+ var cmd = new RemoteCommand('setComponent', {
239
+ windowContainerID: entity.windowContainerId,
240
+ resourceID: resource.id,
241
+ entityID: entity.id,
242
+ })
243
+
244
+ WebSpatial.sendCommand(cmd)
245
+ }
246
+
247
+ static async removeComponent(
248
+ entity: WebSpatialResource,
249
+ resource: WebSpatialResource,
250
+ ) {
251
+ var cmd = new RemoteCommand('removeComponent', {
252
+ windowContainerID: entity.windowContainerId,
253
+ resourceID: resource.id,
254
+ entityID: entity.id,
255
+ })
256
+
257
+ WebSpatial.sendCommand(cmd)
258
+ }
259
+
260
+ // windowContainer is the group the resource will be tied to (if not provided it will use the current window grou)
261
+ // parentWebView is the SpatialWebView that the resource will be tied to (if not provided, resource will continue to exist even if this page is unloaded)
262
+ static async createResource(
263
+ type: string,
264
+ windowContainer: WindowContainer,
265
+ parentWebView: WebSpatialResource,
266
+ params = {} as any,
267
+ ) {
268
+ var cmd = new RemoteCommand('createResource', {
269
+ windowContainerID: windowContainer.id,
270
+ resourceID: parentWebView.id,
271
+ type: type,
272
+ params: params,
273
+ })
274
+
275
+ var result = await new Promise((res, rej) => {
276
+ WebSpatial.eventPromises[cmd.requestID] = { res: res, rej: rej }
277
+ WebSpatial.sendCommand(cmd)
278
+ })
279
+ var res = new WebSpatialResource()
280
+ res.id = (result as any).data.createdID
281
+ res.windowContainerId = cmd.data.windowContainerID
282
+ return res
283
+ }
284
+
285
+ static async updateWindowContainer(wg: WindowContainer, data: any) {
286
+ var cmd = new RemoteCommand('updateWindowContainer', {
287
+ windowContainerID: wg.id,
288
+ update: data,
289
+ })
290
+
291
+ var result = await new Promise((res, rej) => {
292
+ WebSpatial.eventPromises[cmd.requestID] = { res: res, rej: rej }
293
+ WebSpatial.sendCommand(cmd)
294
+ })
295
+ return result
296
+ }
297
+
298
+ static async updateResource(resource: WebSpatialResource, data: any = null) {
299
+ var cmd = new RemoteCommand('updateResource', {
300
+ windowContainerID: resource.windowContainerId,
301
+ resourceID: resource.id,
302
+ update: data || resource.data,
303
+ })
304
+
305
+ var result = await new Promise((res, rej) => {
306
+ WebSpatial.eventPromises[cmd.requestID] = { res: res, rej: rej }
307
+ WebSpatial.sendCommand(cmd)
308
+ })
309
+ return result
310
+ }
311
+
312
+ static async setLoading(method: LoadingMethodKind, style?: string) {
313
+ var cmd = new RemoteCommand('setLoading', {
314
+ windowContainerID: (window as any)._webSpatialParentGroupID, // parent WindowContainerID
315
+ loading: {
316
+ method,
317
+ style,
318
+ },
319
+ })
320
+
321
+ var result = await new Promise((res, rej) => {
322
+ WebSpatial.eventPromises[cmd.requestID] = { res: res, rej: rej }
323
+ WebSpatial.sendCommand(cmd)
324
+ })
325
+ return result
326
+ }
327
+
328
+ static async openImmersiveSpace() {
329
+ var cmd = new RemoteCommand('openImmersiveSpace')
330
+ await WebSpatial.sendCommand(cmd)
331
+ }
332
+
333
+ static async dismissImmersiveSpace() {
334
+ var cmd = new RemoteCommand('dismissImmersiveSpace')
335
+ await WebSpatial.sendCommand(cmd)
336
+ }
337
+
338
+ static onFrame(fn: (curTime: number) => Promise<any>) {
339
+ var dt = 0
340
+ var loop = async () => {
341
+ var curTime = window.performance.now()
342
+ await fn(curTime)
343
+ var updateTime = window.performance.now() - curTime
344
+
345
+ // Call update loop targetting 60 fps
346
+ setTimeout(
347
+ () => {
348
+ loop()
349
+ },
350
+ Math.max(1000 / 60 - updateTime, 0),
351
+ )
352
+ }
353
+ loop()
354
+ }
355
+ }
356
+ WebSpatial.init()
@@ -0,0 +1,15 @@
1
+ export class RemoteCommand {
2
+ private static requestCounter = 0
3
+
4
+ command: string
5
+
6
+ data: any
7
+
8
+ requestID: number
9
+
10
+ constructor(cmd: string, data?: any) {
11
+ this.command = cmd
12
+ this.data = data
13
+ this.requestID = ++RemoteCommand.requestCounter
14
+ }
15
+ }
@@ -0,0 +1 @@
1
+ export { RemoteCommand } from './RemoteCommand'
@@ -0,0 +1,6 @@
1
+ import { SpatialObject } from '../SpatialObject'
2
+
3
+ /**
4
+ * Mesh asset containing geometry
5
+ */
6
+ export class SpatialMeshResource extends SpatialObject {}
@@ -0,0 +1,42 @@
1
+ import { SpatialModelComponent } from '../component'
2
+ import { WebSpatial } from '../private/WebSpatial'
3
+ import { SpatialObject } from '../SpatialObject'
4
+
5
+ /**
6
+ * PBR material which can be set on a SpatialModelComponent
7
+ */
8
+ export class SpatialPhysicallyBasedMaterialResource extends SpatialObject {
9
+ /**
10
+ * Base color of the material containing rgba between 0 and 1
11
+ */
12
+ baseColor = { r: 0.0, g: 0.7, b: 0.7, a: 1.0 }
13
+ /**
14
+ * PBR metalic value between 0 and 1
15
+ */
16
+ metallic = { value: 0.5 }
17
+ /**
18
+ * PBR roughness value between 0 and 1
19
+ */
20
+ roughness = { value: 0.5 }
21
+
22
+ _modelComponentAttachedTo: { [key: string]: SpatialModelComponent } = {}
23
+ _addToComponent(c: SpatialModelComponent) {
24
+ this._modelComponentAttachedTo[c._resource.id] = c
25
+ }
26
+
27
+ /**
28
+ * Syncs state of color, metallic, roupghness to the renderer
29
+ */
30
+ async update() {
31
+ await WebSpatial.updateResource(this._resource, {
32
+ baseColor: this.baseColor,
33
+ metallic: this.metallic,
34
+ roughness: this.roughness,
35
+ })
36
+
37
+ // Since realitykit's materials are structs and not references, every time we change a material, we must copy it to all of the components its attached to to observe the update
38
+ for (var key in this._modelComponentAttachedTo) {
39
+ await this._modelComponentAttachedTo[key]._syncMaterials()
40
+ }
41
+ }
42
+ }
@@ -0,0 +1,2 @@
1
+ export { SpatialMeshResource } from './SpatialMeshResource'
2
+ export { SpatialPhysicallyBasedMaterialResource } from './SpatialPhysicallyBasedMaterialResource'
@@ -0,0 +1,27 @@
1
+ export type WindowStyle = 'Plain' | 'Volumetric'
2
+
3
+ export interface WindowContainerOptions {
4
+ defaultSize?: {
5
+ width: number // Initial width of the window
6
+ height: number // Initial height of the window
7
+ }
8
+
9
+ resizability?: 'automatic' | 'contentSize' | 'contentMinSize'
10
+ }
11
+
12
+ export type LoadingMethodKind = 'show' | 'hide'
13
+
14
+ export interface sceneDataShape {
15
+ method?: 'createRoot' | 'showRoot'
16
+ sceneConfig?: WindowContainerOptions
17
+ url?: string
18
+ window: Window
19
+ }
20
+
21
+ export interface sceneDataJSBShape {
22
+ method?: 'createRoot' | 'showRoot'
23
+ sceneConfig?: WindowContainerOptions
24
+ url?: string
25
+ windowID?: string
26
+ windowContainerID?: string
27
+ }
package/src/index.ts ADDED
@@ -0,0 +1 @@
1
+ export * from './core/index'
package/tsconfig.json ADDED
@@ -0,0 +1,26 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2023",
4
+ "useDefineForClassFields": true,
5
+ "lib": ["ES2023", "DOM", "DOM.Iterable"],
6
+ "module": "ESNext",
7
+ "skipLibCheck": true,
8
+ "allowJs": false,
9
+ /* Bundler mode */
10
+ "moduleResolution": "node",
11
+ "resolveJsonModule": true,
12
+ "isolatedModules": true,
13
+ "noEmit": false,
14
+ "declaration": true,
15
+ "declarationMap": true,
16
+ /* Linting */
17
+ "strict": true,
18
+ "noUnusedLocals": false,
19
+ "noUnusedParameters": false,
20
+ "noFallthroughCasesInSwitch": true,
21
+ "outDir": "./dist",
22
+ "allowSyntheticDefaultImports": true
23
+ },
24
+ "include": ["src/index.ts"],
25
+ "references": []
26
+ }