@webspatial/core-sdk 1.0.4 → 1.0.5

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 (82) hide show
  1. package/CHANGELOG.md +2 -0
  2. package/README.md +112 -81
  3. package/dist/iife/index.d.ts +683 -561
  4. package/dist/iife/index.global.js +3 -4
  5. package/dist/iife/index.global.js.map +1 -1
  6. package/dist/index.d.ts +683 -561
  7. package/dist/index.js +2175 -1291
  8. package/dist/index.js.map +1 -1
  9. package/package.json +7 -4
  10. package/src/JSBCommand.ts +631 -0
  11. package/src/Spatial.ts +68 -0
  12. package/src/SpatialObject.ts +46 -0
  13. package/src/SpatialScene.ts +75 -0
  14. package/src/SpatialSession.ts +187 -0
  15. package/src/SpatialWebEvent.ts +23 -0
  16. package/src/SpatialWebEventCreator.ts +12 -0
  17. package/src/Spatialized2DElement.ts +51 -0
  18. package/src/SpatializedDynamic3DElement.ts +30 -0
  19. package/src/SpatializedElement.ts +331 -0
  20. package/src/SpatializedElementCreator.ts +45 -0
  21. package/src/SpatializedStatic3DElement.ts +111 -0
  22. package/src/WebMsgCommand.ts +88 -0
  23. package/src/index.ts +23 -1
  24. package/src/platform-adapter/CommandResultUtils.ts +22 -0
  25. package/src/platform-adapter/android/AndroidPlatform.ts +133 -0
  26. package/src/platform-adapter/index.ts +21 -0
  27. package/src/platform-adapter/interface.ts +36 -0
  28. package/src/platform-adapter/ssr/SSRPlatform.ts +43 -0
  29. package/src/platform-adapter/vision-os/VisionOSPlatform.ts +77 -0
  30. package/src/reality/component/ModelComponent.ts +11 -0
  31. package/src/reality/component/SpatialComponent.ts +17 -0
  32. package/src/reality/component/index.ts +2 -0
  33. package/src/reality/entity/SpatialEntity.ts +255 -0
  34. package/src/reality/entity/SpatialModelEntity.ts +15 -0
  35. package/src/reality/entity/index.ts +2 -0
  36. package/src/reality/geometry/SpatialBoxGeometry.ts +12 -0
  37. package/src/reality/geometry/SpatialConeGeometry.ts +15 -0
  38. package/src/reality/geometry/SpatialCylinderGeometry.ts +15 -0
  39. package/src/reality/geometry/SpatialGeometry.ts +12 -0
  40. package/src/reality/geometry/SpatialPlaneGeometry.ts +15 -0
  41. package/src/reality/geometry/SpatialSphereGeometry.ts +15 -0
  42. package/src/reality/geometry/index.ts +6 -0
  43. package/src/reality/index.ts +5 -0
  44. package/src/reality/material/SpatialMaterial.ts +14 -0
  45. package/src/reality/material/SpatialUnlitMaterial.ts +16 -0
  46. package/src/reality/material/index.ts +2 -0
  47. package/src/reality/realityCreator.ts +94 -0
  48. package/src/reality/resource/SpatialModelAsset.ts +11 -0
  49. package/src/reality/resource/index.ts +1 -0
  50. package/src/scene-polyfill.test.ts +376 -0
  51. package/src/scene-polyfill.ts +359 -0
  52. package/src/spatial-window-polyfill.ts +182 -0
  53. package/src/ssr-polyfill.ts +3 -0
  54. package/src/types/global.d.ts +33 -1
  55. package/src/types/internal.ts +13 -0
  56. package/src/types/types.ts +380 -0
  57. package/src/utils.ts +61 -0
  58. package/tsconfig.json +1 -1
  59. package/vitest.config.ts +8 -0
  60. package/src/core/Spatial.ts +0 -50
  61. package/src/core/SpatialEntity.ts +0 -147
  62. package/src/core/SpatialHelper.ts +0 -230
  63. package/src/core/SpatialObject.ts +0 -26
  64. package/src/core/SpatialSession.ts +0 -457
  65. package/src/core/SpatialTransform.ts +0 -26
  66. package/src/core/SpatialWindowContainer.ts +0 -59
  67. package/src/core/component/EventSpatialComponent.ts +0 -32
  68. package/src/core/component/SpatialComponent.ts +0 -26
  69. package/src/core/component/SpatialInputComponent.ts +0 -24
  70. package/src/core/component/SpatialModel3DComponent.ts +0 -223
  71. package/src/core/component/SpatialModelComponent.ts +0 -39
  72. package/src/core/component/SpatialViewComponent.ts +0 -32
  73. package/src/core/component/SpatialWindowComponent.ts +0 -177
  74. package/src/core/component/index.ts +0 -14
  75. package/src/core/index.ts +0 -10
  76. package/src/core/private/WebSpatial.ts +0 -383
  77. package/src/core/private/remote-command/RemoteCommand.ts +0 -15
  78. package/src/core/private/remote-command/index.ts +0 -1
  79. package/src/core/resource/SpatialMeshResource.ts +0 -6
  80. package/src/core/resource/SpatialPhysicallyBasedMaterialResource.ts +0 -42
  81. package/src/core/resource/index.ts +0 -2
  82. package/src/core/types.ts +0 -32
package/dist/index.js CHANGED
@@ -2,1521 +2,2405 @@
2
2
  (function(){
3
3
  if(typeof window === 'undefined') return;
4
4
  if(!window.__webspatialsdk__) window.__webspatialsdk__ = {}
5
- window.__webspatialsdk__['core-sdk-version'] = "1.0.4"
5
+ window.__webspatialsdk__['core-sdk-version'] = "1.0.5"
6
6
  })()
7
7
 
8
-
9
- // src/core/private/remote-command/RemoteCommand.ts
10
- var RemoteCommand = class _RemoteCommand {
11
- static requestCounter = 0;
12
- command;
13
- data;
14
- requestID;
15
- constructor(cmd, data) {
16
- this.command = cmd;
17
- this.data = data;
18
- this.requestID = ++_RemoteCommand.requestCounter;
19
- }
8
+ var __defProp = Object.defineProperty;
9
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
10
+ var __getOwnPropNames = Object.getOwnPropertyNames;
11
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
12
+ var __esm = (fn, res) => function __init() {
13
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
20
14
  };
21
-
22
- // src/core/private/WebSpatial.ts
23
- var WindowContainer = class {
24
- id = "";
15
+ var __export = (target, all) => {
16
+ for (var name in all)
17
+ __defProp(target, name, { get: all[name], enumerable: true });
25
18
  };
26
- var WebSpatialResource = class {
27
- id = "";
28
- windowContainerId = "";
29
- data = {};
30
- receiveEvent() {
19
+ var __copyProps = (to, from, except, desc) => {
20
+ if (from && typeof from === "object" || typeof from === "function") {
21
+ for (let key of __getOwnPropNames(from))
22
+ if (!__hasOwnProp.call(to, key) && key !== except)
23
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
31
24
  }
25
+ return to;
32
26
  };
33
- var WebSpatial = class _WebSpatial {
34
- static eventPromises = {};
35
- static transactionStarted = false;
36
- static transactionCommands = Array();
37
- // store event receivers
38
- static eventReceivers = {};
39
- static registerEventReceiver(resourceId, callback) {
40
- this.eventReceivers[resourceId] = callback;
41
- }
42
- static unregisterEventReceiver(resourceId) {
43
- delete this.eventReceivers[resourceId];
44
- }
45
- static init() {
46
- window.__SpatialWebEvent = (e) => {
47
- if (e.resourceId) {
48
- var callback = _WebSpatial.eventReceivers[e.resourceId];
49
- callback(e.data);
50
- } else {
51
- var p = _WebSpatial.eventPromises[e.requestID];
52
- if (p) {
53
- if (e.success) {
54
- p.res(e);
55
- } else {
56
- p.rej(e);
57
- }
58
- }
27
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
+
29
+ // src/ssr-polyfill.ts
30
+ var isSSR, isSSREnv;
31
+ var init_ssr_polyfill = __esm({
32
+ "src/ssr-polyfill.ts"() {
33
+ "use strict";
34
+ isSSR = typeof window === "undefined";
35
+ isSSREnv = () => isSSR;
36
+ }
37
+ });
38
+
39
+ // src/platform-adapter/ssr/SSRPlatform.ts
40
+ var SSRPlatform;
41
+ var init_SSRPlatform = __esm({
42
+ "src/platform-adapter/ssr/SSRPlatform.ts"() {
43
+ "use strict";
44
+ SSRPlatform = class {
45
+ callJSB(cmd, msg) {
46
+ return Promise.resolve({
47
+ success: true,
48
+ data: void 0,
49
+ errorCode: void 0,
50
+ errorMessage: void 0
51
+ });
52
+ }
53
+ callWebSpatialProtocol(schema, query, target, features) {
54
+ return Promise.resolve({
55
+ success: true,
56
+ data: void 0,
57
+ errorCode: void 0,
58
+ errorMessage: void 0
59
+ });
60
+ }
61
+ callWebSpatialProtocolSync(schema, query, target, features, resultCallback) {
62
+ return {
63
+ success: true,
64
+ data: void 0,
65
+ errorCode: void 0,
66
+ errorMessage: void 0
67
+ };
59
68
  }
60
69
  };
61
70
  }
62
- static startTransaction() {
63
- _WebSpatial.transactionStarted = true;
64
- _WebSpatial.transactionCommands = [];
65
- }
66
- static async sendTransaction() {
67
- _WebSpatial.transactionStarted = false;
68
- var cmd = new RemoteCommand("multiCommand", {
69
- commandList: _WebSpatial.transactionCommands
70
- });
71
- var result = await new Promise((res, rej) => {
72
- _WebSpatial.eventPromises[cmd.requestID] = { res, rej };
73
- _WebSpatial.sendCommand(cmd);
74
- });
75
- return result;
76
- }
77
- static getBackend() {
78
- if (window.webkit) {
79
- return "AVP";
80
- } else {
81
- return "UNKNOWN";
82
- }
83
- }
84
- static async sendCommand(cmd) {
85
- if (window.__WebSpatialUnloaded) {
86
- return;
87
- }
88
- if (_WebSpatial.transactionStarted) {
89
- _WebSpatial.transactionCommands.push(cmd);
90
- return;
91
- }
92
- var msg = JSON.stringify(cmd);
93
- if (_WebSpatial.getBackend() == "AVP") {
94
- window.webkit.messageHandlers.bridge.postMessage(msg);
95
- return;
96
- } else {
97
- window.__WebSpatialData.androidNativeMessage(msg);
98
- return;
99
- }
71
+ });
72
+
73
+ // src/platform-adapter/CommandResultUtils.ts
74
+ function CommandResultSuccess(data) {
75
+ return {
76
+ success: true,
77
+ data,
78
+ errorCode: "",
79
+ errorMessage: ""
80
+ };
81
+ }
82
+ function CommandResultFailure(errorCode, errorMessage = "") {
83
+ return {
84
+ success: false,
85
+ data: void 0,
86
+ errorCode,
87
+ errorMessage
88
+ };
89
+ }
90
+ var init_CommandResultUtils = __esm({
91
+ "src/platform-adapter/CommandResultUtils.ts"() {
92
+ "use strict";
100
93
  }
101
- static getImmersiveWindowContainer() {
102
- var wg = new WindowContainer();
103
- wg.id = "Immersive";
104
- return wg;
105
- }
106
- static getCurrentWindowContainer() {
107
- var wg = new WindowContainer();
108
- wg.id = "current";
109
- return wg;
110
- }
111
- static getCurrentWebPanel() {
112
- var wg = new WebSpatialResource();
113
- wg.id = "current";
114
- wg.windowContainerId = _WebSpatial.getCurrentWindowContainer().id;
115
- return wg;
116
- }
117
- static async createScene(style = "Plain", cfg) {
118
- const { window: newWindow, ...sceneData } = cfg.sceneData;
119
- const jsbSceneData = {
120
- ...sceneData,
121
- windowID: newWindow._webSpatialID,
122
- windowContainerID: newWindow._webSpatialGroupID
94
+ });
95
+
96
+ // src/SpatialWebEvent.ts
97
+ var SpatialWebEvent;
98
+ var init_SpatialWebEvent = __esm({
99
+ "src/SpatialWebEvent.ts"() {
100
+ "use strict";
101
+ SpatialWebEvent = class _SpatialWebEvent {
102
+ static eventReceiver = {};
103
+ static init() {
104
+ window.__SpatialWebEvent = ({ id, data }) => {
105
+ _SpatialWebEvent.eventReceiver[id]?.(data);
106
+ };
107
+ }
108
+ static addEventReceiver(id, callback) {
109
+ _SpatialWebEvent.eventReceiver[id] = callback;
110
+ }
111
+ static removeEventReceiver(id) {
112
+ delete _SpatialWebEvent.eventReceiver[id];
113
+ }
123
114
  };
124
- var cmd = new RemoteCommand("createScene", {
125
- windowStyle: style,
126
- sceneData: jsbSceneData,
127
- windowContainerID: window._webSpatialParentGroupID
128
- // parent WindowContainerID
129
- });
130
- try {
131
- await new Promise((res, rej) => {
132
- _WebSpatial.eventPromises[cmd.requestID] = { res, rej };
133
- _WebSpatial.sendCommand(cmd);
134
- });
135
- return true;
136
- } catch (error) {
137
- return false;
138
- }
139
- }
140
- static async createWindowContainer(style = "Plain", windowContainer, parentWebView) {
141
- var cmd = new RemoteCommand("createWindowContainer", {
142
- windowStyle: style,
143
- windowContainerID: windowContainer ? windowContainer.id : void 0,
144
- resourceID: parentWebView ? parentWebView.id : void 0
145
- });
146
- var result = await new Promise((res2, rej) => {
147
- _WebSpatial.eventPromises[cmd.requestID] = { res: res2, rej };
148
- _WebSpatial.sendCommand(cmd);
149
- });
150
- var res = new WindowContainer();
151
- res.id = result.data.createdID;
152
- return res;
153
- }
154
- static async destroyResource(resource) {
155
- const data = {};
156
- var cmd = new RemoteCommand("destroyResource", {
157
- windowContainerID: resource.windowContainerId,
158
- resourceID: resource.id
159
- });
160
- _WebSpatial.sendCommand(cmd);
161
115
  }
162
- static async ping(msg) {
163
- var cmd = new RemoteCommand("ping", {
164
- windowContainerID: this.getCurrentWindowContainer().id,
165
- resourceID: this.getCurrentWebPanel().id,
166
- message: msg
167
- });
168
- if (_WebSpatial.transactionStarted) {
169
- _WebSpatial.sendCommand(cmd);
170
- return null;
171
- } else {
172
- var result = await new Promise((res, rej) => {
173
- _WebSpatial.eventPromises[cmd.requestID] = { res, rej };
174
- _WebSpatial.sendCommand(cmd);
175
- });
176
- return result;
177
- }
116
+ });
117
+
118
+ // src/platform-adapter/android/AndroidPlatform.ts
119
+ var AndroidPlatform_exports = {};
120
+ __export(AndroidPlatform_exports, {
121
+ AndroidPlatform: () => AndroidPlatform
122
+ });
123
+ function nextRequestId() {
124
+ requestId = (requestId + 1) % MAX_ID;
125
+ return `rId_${requestId}`;
126
+ }
127
+ var creatingElementCount, requestId, MAX_ID, AndroidPlatform;
128
+ var init_AndroidPlatform = __esm({
129
+ "src/platform-adapter/android/AndroidPlatform.ts"() {
130
+ "use strict";
131
+ init_CommandResultUtils();
132
+ init_JSBCommand();
133
+ init_SpatialWebEvent();
134
+ creatingElementCount = 0;
135
+ requestId = 0;
136
+ MAX_ID = 1e5;
137
+ AndroidPlatform = class {
138
+ async callJSB(cmd, msg) {
139
+ return new Promise((resolve, reject) => {
140
+ try {
141
+ const rId = nextRequestId();
142
+ SpatialWebEvent.addEventReceiver(rId, (result) => {
143
+ SpatialWebEvent.removeEventReceiver(rId);
144
+ if (result.success) {
145
+ resolve(CommandResultSuccess(result.data));
146
+ } else {
147
+ const { code, message } = result.data;
148
+ resolve(CommandResultFailure(code, message));
149
+ }
150
+ });
151
+ const ans = window.webspatialBridge.postMessage(rId, cmd, msg);
152
+ if (ans !== "") {
153
+ SpatialWebEvent.removeEventReceiver(rId);
154
+ const result = JSON.parse(ans);
155
+ if (result.success) {
156
+ resolve(CommandResultSuccess(result.data));
157
+ } else {
158
+ const { code, message } = result.data;
159
+ resolve(CommandResultFailure(code, message));
160
+ }
161
+ }
162
+ } catch (error) {
163
+ console.error(
164
+ `AndroidPlatform cmd: ${cmd}, msg: ${msg} error: ${error}`
165
+ );
166
+ const { code, message } = error;
167
+ resolve(CommandResultFailure(code, message));
168
+ }
169
+ });
170
+ }
171
+ async callWebSpatialProtocol(command, query, target, features) {
172
+ await new Promise((resolve) => setTimeout(resolve, 16 * creatingElementCount));
173
+ creatingElementCount++;
174
+ let canCreate = await new CheckWebViewCanCreateCommand().execute();
175
+ while (!canCreate.data.can) {
176
+ await new Promise((resolve) => setTimeout(resolve, 16));
177
+ canCreate = await new CheckWebViewCanCreateCommand().execute();
178
+ }
179
+ const { windowProxy } = this.openWindow(command, query, target, features);
180
+ while (!windowProxy?.open) {
181
+ await new Promise((resolve) => setTimeout(resolve, 16));
182
+ }
183
+ windowProxy?.open("about:blank", "_self");
184
+ while (!windowProxy?.SpatialId) {
185
+ await new Promise((resolve) => setTimeout(resolve, 16));
186
+ }
187
+ let spatialId = windowProxy?.SpatialId;
188
+ creatingElementCount--;
189
+ return Promise.resolve(
190
+ CommandResultSuccess({ windowProxy, id: spatialId })
191
+ );
192
+ }
193
+ callWebSpatialProtocolSync(command, query, target, features) {
194
+ const { spatialId: id = "", windowProxy } = this.openWindow(
195
+ command,
196
+ query,
197
+ target,
198
+ features
199
+ );
200
+ return CommandResultSuccess({ windowProxy, id });
201
+ }
202
+ openWindow(command, query, target, features) {
203
+ const windowProxy = window.open(
204
+ `webspatial://${command}?${query || ""}`,
205
+ target,
206
+ features
207
+ );
208
+ return { spatialId: "", windowProxy };
209
+ }
210
+ };
178
211
  }
179
- static async getStats() {
180
- var cmd = new RemoteCommand("getStats", {
181
- windowContainerID: this.getCurrentWindowContainer().id,
182
- resourceID: this.getCurrentWebPanel().id
183
- });
184
- var result = await new Promise((res, rej) => {
185
- _WebSpatial.eventPromises[cmd.requestID] = { res, rej };
186
- _WebSpatial.sendCommand(cmd);
187
- });
188
- return result.data;
212
+ });
213
+
214
+ // src/platform-adapter/vision-os/VisionOSPlatform.ts
215
+ var VisionOSPlatform_exports = {};
216
+ __export(VisionOSPlatform_exports, {
217
+ VisionOSPlatform: () => VisionOSPlatform
218
+ });
219
+ var VisionOSPlatform;
220
+ var init_VisionOSPlatform = __esm({
221
+ "src/platform-adapter/vision-os/VisionOSPlatform.ts"() {
222
+ "use strict";
223
+ init_CommandResultUtils();
224
+ VisionOSPlatform = class {
225
+ async callJSB(cmd, msg) {
226
+ try {
227
+ const result = await window.webkit.messageHandlers.bridge.postMessage(
228
+ `${cmd}::${msg}`
229
+ );
230
+ return CommandResultSuccess(result);
231
+ } catch (error) {
232
+ const { code, message } = JSON.parse(error.message);
233
+ return CommandResultFailure(code, message);
234
+ }
235
+ }
236
+ callWebSpatialProtocol(command, query, target, features) {
237
+ const { spatialId: id, windowProxy } = this.openWindow(
238
+ command,
239
+ query,
240
+ target,
241
+ features
242
+ );
243
+ return Promise.resolve(
244
+ CommandResultSuccess({ windowProxy, id })
245
+ );
246
+ }
247
+ callWebSpatialProtocolSync(command, query, target, features) {
248
+ const { spatialId: id = "", windowProxy } = this.openWindow(
249
+ command,
250
+ query,
251
+ target,
252
+ features
253
+ );
254
+ return CommandResultSuccess({ windowProxy, id });
255
+ }
256
+ openWindow(command, query, target, features) {
257
+ const windowProxy = window.open(
258
+ `webspatial://${command}?${query || ""}`,
259
+ target,
260
+ features
261
+ );
262
+ const ua = windowProxy?.navigator.userAgent;
263
+ const spatialId = ua?.match(
264
+ /\b([0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12})\b/gi
265
+ )?.[0];
266
+ return { spatialId, windowProxy };
267
+ }
268
+ };
189
269
  }
190
- static async inspect(spatialObjectId) {
191
- var cmd = new RemoteCommand("inspect", {
192
- resourceID: spatialObjectId
193
- });
194
- var result = await new Promise((res, rej) => {
195
- _WebSpatial.eventPromises[cmd.requestID] = { res, rej };
196
- _WebSpatial.sendCommand(cmd);
197
- });
198
- return result.data;
270
+ });
271
+
272
+ // src/platform-adapter/index.ts
273
+ function createPlatform() {
274
+ if (isSSREnv()) {
275
+ return new SSRPlatform();
276
+ }
277
+ if (window.navigator.userAgent.includes("Android") || window.navigator.userAgent.includes("Linux")) {
278
+ const AndroidPlatform2 = (init_AndroidPlatform(), __toCommonJS(AndroidPlatform_exports)).AndroidPlatform;
279
+ return new AndroidPlatform2();
280
+ } else {
281
+ const VisionOSPlatform2 = (init_VisionOSPlatform(), __toCommonJS(VisionOSPlatform_exports)).VisionOSPlatform;
282
+ return new VisionOSPlatform2();
199
283
  }
200
- static async inspectRootWindowContainer() {
201
- return this.inspect("root");
284
+ }
285
+ var init_platform_adapter = __esm({
286
+ "src/platform-adapter/index.ts"() {
287
+ "use strict";
288
+ init_ssr_polyfill();
289
+ init_SSRPlatform();
202
290
  }
203
- static async setComponent(entity, resource) {
204
- var cmd = new RemoteCommand("setComponent", {
205
- windowContainerID: entity.windowContainerId,
206
- resourceID: resource.id,
207
- entityID: entity.id
208
- });
209
- _WebSpatial.sendCommand(cmd);
291
+ });
292
+
293
+ // src/utils.ts
294
+ function parseBorderRadius(borderProperty, width) {
295
+ if (borderProperty === "") {
296
+ return 0;
210
297
  }
211
- static async removeComponent(entity, resource) {
212
- var cmd = new RemoteCommand("removeComponent", {
213
- windowContainerID: entity.windowContainerId,
214
- resourceID: resource.id,
215
- entityID: entity.id
216
- });
217
- _WebSpatial.sendCommand(cmd);
218
- }
219
- // windowContainer is the group the resource will be tied to (if not provided it will use the current window grou)
220
- // 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)
221
- static async createResource(type, windowContainer, parentWebView, params = {}) {
222
- var cmd = new RemoteCommand("createResource", {
223
- windowContainerID: windowContainer ? windowContainer.id : void 0,
224
- resourceID: parentWebView ? parentWebView.id : void 0,
225
- type,
226
- params
227
- });
228
- var result = await new Promise((res2, rej) => {
229
- _WebSpatial.eventPromises[cmd.requestID] = { res: res2, rej };
230
- _WebSpatial.sendCommand(cmd);
231
- });
232
- var res = new WebSpatialResource();
233
- res.id = result.data.createdID;
234
- res.windowContainerId = cmd.data.windowContainerID;
235
- return res;
236
- }
237
- static async updateWindowContainer(wg, data) {
238
- var cmd = new RemoteCommand("updateWindowContainer", {
239
- windowContainerID: wg.id,
240
- update: data
241
- });
242
- var result = await new Promise((res, rej) => {
243
- _WebSpatial.eventPromises[cmd.requestID] = { res, rej };
244
- _WebSpatial.sendCommand(cmd);
245
- });
246
- return result;
298
+ if (borderProperty.endsWith("%")) {
299
+ return width * parseFloat(borderProperty) / 100;
247
300
  }
248
- static async updateResource(resource, data = null) {
249
- var cmd = new RemoteCommand("updateResource", {
250
- windowContainerID: resource.windowContainerId,
251
- resourceID: resource.id,
252
- update: data || resource.data
253
- });
254
- var result = await new Promise((res, rej) => {
255
- _WebSpatial.eventPromises[cmd.requestID] = { res, rej };
256
- _WebSpatial.sendCommand(cmd);
257
- });
258
- return result;
301
+ return parseFloat(borderProperty);
302
+ }
303
+ function parseCornerRadius(computedStyle) {
304
+ const width = parseFloat(computedStyle.getPropertyValue("width"));
305
+ const topLeftPropertyValue = computedStyle.getPropertyValue(
306
+ "border-top-left-radius"
307
+ );
308
+ const topRightPropertyValue = computedStyle.getPropertyValue(
309
+ "border-top-right-radius"
310
+ );
311
+ const bottomLeftPropertyValue = computedStyle.getPropertyValue(
312
+ "border-bottom-left-radius"
313
+ );
314
+ const bottomRightPropertyValue = computedStyle.getPropertyValue(
315
+ "border-bottom-right-radius"
316
+ );
317
+ const cornerRadius = {
318
+ topLeading: parseBorderRadius(topLeftPropertyValue, width),
319
+ bottomLeading: parseBorderRadius(bottomLeftPropertyValue, width),
320
+ topTrailing: parseBorderRadius(topRightPropertyValue, width),
321
+ bottomTrailing: parseBorderRadius(bottomRightPropertyValue, width)
322
+ };
323
+ return cornerRadius;
324
+ }
325
+ function composeSRT(position, rotation, scale) {
326
+ const { x: px, y: py, z: pz } = position;
327
+ const { x: rx, y: ry, z: rz } = rotation;
328
+ const { x: sx, y: sy, z: sz } = scale;
329
+ let m = new DOMMatrix();
330
+ m = m.translate(px, py, pz);
331
+ m = m.rotate(rx, ry, rz);
332
+ m = m.scale(sx, sy, sz);
333
+ return m;
334
+ }
335
+ var init_utils = __esm({
336
+ "src/utils.ts"() {
337
+ "use strict";
259
338
  }
260
- static async setLoading(method, style) {
261
- var cmd = new RemoteCommand("setLoading", {
262
- windowContainerID: window._webSpatialParentGroupID,
263
- // parent WindowContainerID
264
- loading: {
265
- method,
266
- style
339
+ });
340
+
341
+ // src/JSBCommand.ts
342
+ var platform, JSBCommand, UpdateEntityPropertiesCommand, UpdateEntityEventCommand, UpdateSpatialSceneProperties, UpdateSceneConfig, FocusScene, GetSpatialSceneState, SpatializedElementCommand, UpdateSpatialized2DElementProperties, UpdateSpatializedDynamic3DElementProperties, UpdateUnlitMaterialProperties, UpdateSpatializedElementTransform, UpdateSpatializedStatic3DElementProperties, AddSpatializedElementToSpatialized2DElement, AddSpatializedElementToSpatialScene, CreateSpatializedStatic3DElementCommand, CreateSpatializedDynamic3DElementCommand, CreateSpatialEntityCommand, CreateModelComponentCommand, CreateSpatialModelEntityCommand, CreateModelAssetCommand, CreateSpatialGeometryCommand, CreateSpatialUnlitMaterialCommand, AddComponentToEntityCommand, SetParentForEntityCommand, ConvertFromEntityToEntityCommand, ConvertFromEntityToSceneCommand, ConvertFromSceneToEntityCommand, InspectCommand, DestroyCommand, CheckWebViewCanCreateCommand, WebSpatialProtocolCommand, createSpatialized2DElementCommand, createSpatialSceneCommand;
343
+ var init_JSBCommand = __esm({
344
+ "src/JSBCommand.ts"() {
345
+ "use strict";
346
+ init_platform_adapter();
347
+ init_utils();
348
+ platform = createPlatform();
349
+ JSBCommand = class {
350
+ commandType = "";
351
+ async execute() {
352
+ const param = this.getParams();
353
+ const msg = param ? JSON.stringify(param) : "";
354
+ return platform.callJSB(this.commandType, msg);
355
+ }
356
+ };
357
+ UpdateEntityPropertiesCommand = class extends JSBCommand {
358
+ constructor(entity, properties) {
359
+ super();
360
+ this.entity = entity;
361
+ this.properties = properties;
362
+ }
363
+ commandType = "UpdateEntityProperties";
364
+ getParams() {
365
+ const transform = composeSRT(
366
+ this.properties.position ?? this.entity.position,
367
+ this.properties.rotation ?? this.entity.rotation,
368
+ this.properties.scale ?? this.entity.scale
369
+ ).toFloat64Array();
370
+ return {
371
+ entityId: this.entity.id,
372
+ transform
373
+ };
374
+ }
375
+ };
376
+ UpdateEntityEventCommand = class extends JSBCommand {
377
+ constructor(entity, type, isEnable) {
378
+ super();
379
+ this.entity = entity;
380
+ this.type = type;
381
+ this.isEnable = isEnable;
382
+ }
383
+ commandType = "UpdateEntityEvent";
384
+ getParams() {
385
+ return {
386
+ type: this.type,
387
+ entityId: this.entity.id,
388
+ isEnable: this.isEnable
389
+ };
390
+ }
391
+ };
392
+ UpdateSpatialSceneProperties = class extends JSBCommand {
393
+ properties;
394
+ commandType = "UpdateSpatialSceneProperties";
395
+ constructor(properties) {
396
+ super();
397
+ this.properties = properties;
398
+ }
399
+ getParams() {
400
+ return this.properties;
401
+ }
402
+ };
403
+ UpdateSceneConfig = class extends JSBCommand {
404
+ config;
405
+ commandType = "UpdateSceneConfig";
406
+ constructor(config) {
407
+ super();
408
+ this.config = config;
409
+ }
410
+ getParams() {
411
+ return { config: this.config };
412
+ }
413
+ };
414
+ FocusScene = class extends JSBCommand {
415
+ constructor(id) {
416
+ super();
417
+ this.id = id;
418
+ }
419
+ commandType = "FocusScene";
420
+ getParams() {
421
+ return { id: this.id };
422
+ }
423
+ };
424
+ GetSpatialSceneState = class extends JSBCommand {
425
+ commandType = "GetSpatialSceneState";
426
+ constructor() {
427
+ super();
428
+ }
429
+ getParams() {
430
+ return {};
431
+ }
432
+ };
433
+ SpatializedElementCommand = class extends JSBCommand {
434
+ constructor(spatialObject) {
435
+ super();
436
+ this.spatialObject = spatialObject;
437
+ }
438
+ getParams() {
439
+ const extraParams = this.getExtraParams();
440
+ return { id: this.spatialObject.id, ...extraParams };
441
+ }
442
+ };
443
+ UpdateSpatialized2DElementProperties = class extends SpatializedElementCommand {
444
+ properties;
445
+ commandType = "UpdateSpatialized2DElementProperties";
446
+ constructor(spatialObject, properties) {
447
+ super(spatialObject);
448
+ this.properties = properties;
449
+ }
450
+ getExtraParams() {
451
+ return this.properties;
452
+ }
453
+ };
454
+ UpdateSpatializedDynamic3DElementProperties = class extends SpatializedElementCommand {
455
+ properties;
456
+ commandType = "UpdateSpatializedDynamic3DElementProperties";
457
+ constructor(spatialObject, properties) {
458
+ super(spatialObject);
459
+ this.properties = properties;
460
+ }
461
+ getExtraParams() {
462
+ return {
463
+ id: this.spatialObject.id,
464
+ ...this.properties
465
+ };
466
+ }
467
+ };
468
+ UpdateUnlitMaterialProperties = class extends SpatializedElementCommand {
469
+ properties;
470
+ commandType = "UpdateUnlitMaterialProperties";
471
+ constructor(spatialObject, properties) {
472
+ super(spatialObject);
473
+ this.properties = properties;
474
+ }
475
+ getExtraParams() {
476
+ return this.properties;
477
+ }
478
+ };
479
+ UpdateSpatializedElementTransform = class extends SpatializedElementCommand {
480
+ matrix;
481
+ commandType = "UpdateSpatializedElementTransform";
482
+ constructor(spatialObject, matrix) {
483
+ super(spatialObject);
484
+ this.matrix = matrix;
485
+ }
486
+ getExtraParams() {
487
+ return { matrix: Array.from(this.matrix.toFloat64Array()) };
488
+ }
489
+ };
490
+ UpdateSpatializedStatic3DElementProperties = class extends SpatializedElementCommand {
491
+ properties;
492
+ commandType = "UpdateSpatializedStatic3DElementProperties";
493
+ constructor(spatialObject, properties) {
494
+ super(spatialObject);
495
+ this.properties = properties;
496
+ }
497
+ getExtraParams() {
498
+ return this.properties;
499
+ }
500
+ };
501
+ AddSpatializedElementToSpatialized2DElement = class extends SpatializedElementCommand {
502
+ commandType = "AddSpatializedElementToSpatialized2DElement";
503
+ spatializedElement;
504
+ constructor(spatialObject, spatializedElement) {
505
+ super(spatialObject);
506
+ this.spatializedElement = spatializedElement;
507
+ }
508
+ getExtraParams() {
509
+ return { spatializedElementId: this.spatializedElement.id };
510
+ }
511
+ };
512
+ AddSpatializedElementToSpatialScene = class extends JSBCommand {
513
+ commandType = "AddSpatializedElementToSpatialScene";
514
+ spatializedElement;
515
+ constructor(spatializedElement) {
516
+ super();
517
+ this.spatializedElement = spatializedElement;
518
+ }
519
+ getParams() {
520
+ return {
521
+ spatializedElementId: this.spatializedElement.id
522
+ };
523
+ }
524
+ };
525
+ CreateSpatializedStatic3DElementCommand = class extends JSBCommand {
526
+ constructor(modelURL) {
527
+ super();
528
+ this.modelURL = modelURL;
529
+ this.modelURL = modelURL;
530
+ }
531
+ commandType = "CreateSpatializedStatic3DElement";
532
+ getParams() {
533
+ return { modelURL: this.modelURL };
534
+ }
535
+ };
536
+ CreateSpatializedDynamic3DElementCommand = class extends JSBCommand {
537
+ getParams() {
538
+ return { test: true };
539
+ }
540
+ commandType = "CreateSpatializedDynamic3DElement";
541
+ };
542
+ CreateSpatialEntityCommand = class extends JSBCommand {
543
+ constructor(name) {
544
+ super();
545
+ this.name = name;
546
+ }
547
+ getParams() {
548
+ return { name: this.name };
549
+ }
550
+ commandType = "CreateSpatialEntity";
551
+ };
552
+ CreateModelComponentCommand = class extends JSBCommand {
553
+ constructor(options) {
554
+ super();
555
+ this.options = options;
556
+ }
557
+ getParams() {
558
+ let geometryId = this.options.mesh.id;
559
+ let materialIds = this.options.materials.map((material) => material.id);
560
+ return { geometryId, materialIds };
561
+ }
562
+ commandType = "CreateModelComponent";
563
+ };
564
+ CreateSpatialModelEntityCommand = class extends JSBCommand {
565
+ constructor(options) {
566
+ super();
567
+ this.options = options;
568
+ }
569
+ getParams() {
570
+ return this.options;
571
+ }
572
+ commandType = "CreateSpatialModelEntity";
573
+ };
574
+ CreateModelAssetCommand = class extends JSBCommand {
575
+ constructor(options) {
576
+ super();
577
+ this.options = options;
578
+ }
579
+ getParams() {
580
+ return { url: this.options.url };
581
+ }
582
+ commandType = "CreateModelAsset";
583
+ };
584
+ CreateSpatialGeometryCommand = class extends JSBCommand {
585
+ constructor(type, options = {}) {
586
+ super();
587
+ this.type = type;
588
+ this.options = options;
589
+ }
590
+ getParams() {
591
+ return { type: this.type, ...this.options };
592
+ }
593
+ commandType = "CreateGeometry";
594
+ };
595
+ CreateSpatialUnlitMaterialCommand = class extends JSBCommand {
596
+ constructor(options) {
597
+ super();
598
+ this.options = options;
599
+ }
600
+ getParams() {
601
+ return this.options;
602
+ }
603
+ commandType = "CreateUnlitMaterial";
604
+ };
605
+ AddComponentToEntityCommand = class extends JSBCommand {
606
+ constructor(entity, comp) {
607
+ super();
608
+ this.entity = entity;
609
+ this.comp = comp;
610
+ }
611
+ getParams() {
612
+ return {
613
+ entityId: this.entity.id,
614
+ componentId: this.comp.id
615
+ };
616
+ }
617
+ commandType = "AddComponentToEntity";
618
+ };
619
+ SetParentForEntityCommand = class extends JSBCommand {
620
+ // childId, parentId
621
+ constructor(childId, parentId) {
622
+ super();
623
+ this.childId = childId;
624
+ this.parentId = parentId;
625
+ }
626
+ getParams() {
627
+ return {
628
+ childId: this.childId,
629
+ parentId: this.parentId
630
+ };
631
+ }
632
+ commandType = "SetParentToEntity";
633
+ };
634
+ ConvertFromEntityToEntityCommand = class extends JSBCommand {
635
+ constructor(fromEntityId, toEntityId, fromPosition) {
636
+ super();
637
+ this.fromEntityId = fromEntityId;
638
+ this.toEntityId = toEntityId;
639
+ this.fromPosition = fromPosition;
640
+ }
641
+ getParams() {
642
+ return {
643
+ fromEntityId: this.fromEntityId,
644
+ toEntityId: this.toEntityId,
645
+ position: this.fromPosition
646
+ };
647
+ }
648
+ commandType = "ConvertFromEntityToEntity";
649
+ };
650
+ ConvertFromEntityToSceneCommand = class extends JSBCommand {
651
+ constructor(fromEntityId, position) {
652
+ super();
653
+ this.fromEntityId = fromEntityId;
654
+ this.position = position;
655
+ }
656
+ getParams() {
657
+ return {
658
+ fromEntityId: this.fromEntityId,
659
+ position: this.position
660
+ };
661
+ }
662
+ commandType = "ConvertFromEntityToScene";
663
+ };
664
+ ConvertFromSceneToEntityCommand = class extends JSBCommand {
665
+ // let entityId: String
666
+ // let position:Vec3
667
+ constructor(entityId, position) {
668
+ super();
669
+ this.entityId = entityId;
670
+ this.position = position;
671
+ }
672
+ getParams() {
673
+ return {
674
+ entityId: this.entityId,
675
+ position: this.position
676
+ };
677
+ }
678
+ commandType = "ConvertFromSceneToEntity";
679
+ };
680
+ InspectCommand = class extends JSBCommand {
681
+ constructor(id = "") {
682
+ super();
683
+ this.id = id;
684
+ }
685
+ commandType = "Inspect";
686
+ getParams() {
687
+ return this.id ? { id: this.id } : { id: "" };
688
+ }
689
+ };
690
+ DestroyCommand = class extends JSBCommand {
691
+ constructor(id) {
692
+ super();
693
+ this.id = id;
694
+ }
695
+ commandType = "Destroy";
696
+ getParams() {
697
+ return { id: this.id };
698
+ }
699
+ };
700
+ CheckWebViewCanCreateCommand = class extends JSBCommand {
701
+ constructor(id = "") {
702
+ super();
703
+ this.id = id;
704
+ }
705
+ commandType = "CheckWebViewCanCreate";
706
+ getParams() {
707
+ return { id: this.id };
708
+ }
709
+ };
710
+ WebSpatialProtocolCommand = class extends JSBCommand {
711
+ target;
712
+ features;
713
+ async execute() {
714
+ const query = this.getQuery();
715
+ return platform.callWebSpatialProtocol(
716
+ this.commandType,
717
+ query,
718
+ this.target,
719
+ this.features
720
+ );
721
+ }
722
+ executeSync() {
723
+ const query = this.getQuery();
724
+ return platform.callWebSpatialProtocolSync(
725
+ this.commandType,
726
+ query,
727
+ this.target,
728
+ this.features
729
+ );
730
+ }
731
+ getQuery() {
732
+ let query = void 0;
733
+ const params = this.getParams();
734
+ if (params) {
735
+ query = Object.keys(params).map((key) => {
736
+ const value = params[key];
737
+ const finalValue = typeof value === "object" ? JSON.stringify(value) : value;
738
+ return `${key}=${encodeURIComponent(finalValue)}`;
739
+ }).join("&");
740
+ }
741
+ return query;
742
+ }
743
+ };
744
+ createSpatialized2DElementCommand = class extends WebSpatialProtocolCommand {
745
+ commandType = "createSpatialized2DElement";
746
+ constructor() {
747
+ super();
748
+ }
749
+ getParams() {
750
+ return {};
751
+ }
752
+ };
753
+ createSpatialSceneCommand = class extends WebSpatialProtocolCommand {
754
+ constructor(url, config, target, features) {
755
+ super();
756
+ this.url = url;
757
+ this.config = config;
758
+ this.target = target;
759
+ this.features = features;
760
+ }
761
+ commandType = "createSpatialScene";
762
+ getParams() {
763
+ return {
764
+ url: this.url,
765
+ config: this.config
766
+ };
267
767
  }
268
- });
269
- var result = await new Promise((res, rej) => {
270
- _WebSpatial.eventPromises[cmd.requestID] = { res, rej };
271
- _WebSpatial.sendCommand(cmd);
272
- });
273
- return result;
274
- }
275
- static async openImmersiveSpace() {
276
- var cmd = new RemoteCommand("openImmersiveSpace");
277
- await _WebSpatial.sendCommand(cmd);
278
- }
279
- static async dismissImmersiveSpace() {
280
- var cmd = new RemoteCommand("dismissImmersiveSpace");
281
- await _WebSpatial.sendCommand(cmd);
282
- }
283
- static onFrame(fn) {
284
- var dt = 0;
285
- var loop = async () => {
286
- var curTime = window.performance.now();
287
- await fn(curTime);
288
- var updateTime = window.performance.now() - curTime;
289
- setTimeout(
290
- () => {
291
- loop();
292
- },
293
- Math.max(1e3 / 60 - updateTime, 0)
294
- );
295
768
  };
296
- loop();
297
769
  }
298
- };
299
- WebSpatial.init();
770
+ });
300
771
 
301
- // src/core/SpatialObject.ts
772
+ // src/SpatialObject.ts
773
+ init_JSBCommand();
302
774
  var SpatialObject = class {
303
775
  /** @hidden */
304
- constructor(_resource) {
305
- this._resource = _resource;
776
+ constructor(id) {
777
+ this.id = id;
778
+ }
779
+ name;
780
+ isDestroyed = false;
781
+ async inspect() {
782
+ const ret = await new InspectCommand(this.id).execute();
783
+ if (ret.success) {
784
+ return ret.data;
785
+ }
786
+ throw new Error(ret.errorMessage);
306
787
  }
307
- /**
308
- * Marks resource to be released (it should no longer be used)
309
- */
310
788
  async destroy() {
311
- await WebSpatial.destroyResource(this._resource);
312
- await this.onDestroy();
789
+ if (this.isDestroyed) {
790
+ return;
791
+ }
792
+ const ret = await new DestroyCommand(this.id).execute();
793
+ if (ret.success) {
794
+ this.onDestroy();
795
+ this.isDestroyed = true;
796
+ return ret.data;
797
+ } else if (this.isDestroyed) {
798
+ return;
799
+ }
800
+ throw new Error(ret.errorMessage);
313
801
  }
314
- name = "";
315
- async onDestroy() {
802
+ // override this method to do some cleanup
803
+ onDestroy() {
316
804
  }
317
805
  };
318
806
 
319
- // src/core/SpatialTransform.ts
320
- var Vec3 = class {
321
- constructor(x = 0, y = 0, z = 0) {
322
- this.x = x;
323
- this.y = y;
324
- this.z = z;
325
- }
326
- };
327
- var Vec4 = class {
328
- constructor(x = 0, y = 0, z = 0, w = 1) {
329
- this.x = x;
330
- this.y = y;
331
- this.z = z;
332
- this.w = w;
333
- }
334
- };
335
- var SpatialTransform = class {
336
- position = new Vec3(0, 0, 0);
337
- /** Quaternion value for x,y,z,w */
338
- orientation = new Vec4(0, 0, 0, 1);
339
- scale = new Vec3(1, 1, 1);
340
- };
807
+ // src/scene-polyfill.ts
808
+ init_JSBCommand();
341
809
 
342
- // src/core/SpatialEntity.ts
343
- var SpatialEntity = class extends SpatialObject {
344
- /**
345
- * Transform corresponding to the entity
346
- * note: updateTransform must be called for transform to be synced to rendering
347
- */
348
- transform = new SpatialTransform();
349
- /** @hidden */
350
- _destroyed = false;
351
- /** @hidden */
352
- get _entity() {
353
- return this._resource;
810
+ // src/SpatialScene.ts
811
+ init_JSBCommand();
812
+ var instance;
813
+ var SpatialScene = class _SpatialScene extends SpatialObject {
814
+ /**
815
+ * Gets the singleton instance of the SpatialScene.
816
+ * Creates a new instance if one doesn't exist yet.
817
+ * @returns The singleton SpatialScene instance
818
+ */
819
+ static getInstance() {
820
+ if (!instance) {
821
+ instance = new _SpatialScene("");
822
+ }
823
+ return instance;
354
824
  }
355
825
  /**
356
- * Syncs the transform with the renderer, must be called to observe updates
826
+ * Updates the properties of the spatial scene.
827
+ * This can include background settings, lighting, and other scene-wide properties.
828
+ * @param properties Partial set of properties to update
829
+ * @returns Promise resolving when the update is complete
357
830
  */
358
- async updateTransform() {
359
- await WebSpatial.updateResource(this._entity, this.transform);
831
+ async updateSpatialProperties(properties) {
832
+ return new UpdateSpatialSceneProperties(properties).execute();
360
833
  }
361
834
  /**
362
- * Syncs the zIndex with the renderer
835
+ * Adds a spatialized element to the scene.
836
+ * This makes the element visible and interactive in the spatial environment.
837
+ * @param element The SpatializedElement to add to the scene
838
+ * @returns Promise resolving when the element is added
363
839
  */
364
- async updateZIndex(zIndex) {
365
- await WebSpatial.updateResource(this._entity, { zIndex });
840
+ async addSpatializedElement(element) {
841
+ return new AddSpatializedElementToSpatialScene(element).execute();
366
842
  }
367
- components = /* @__PURE__ */ new Map();
368
843
  /**
369
- * Attaches a component to the entity to be displayed
370
- * [TODO] review pass by value vs ref and ownership model for this
844
+ * Updates the scene creation configuration.
845
+ * This allows changing scene parameters after initial creation.
846
+ * @param config The new scene creation configuration
847
+ * @returns Promise resolving when the update is complete
371
848
  */
372
- async setComponent(component) {
373
- await WebSpatial.setComponent(this._entity, component._resource);
374
- this.components.set(component.constructor, component);
849
+ async updateSceneCreationConfig(config) {
850
+ return new UpdateSceneConfig(config).execute();
375
851
  }
376
852
  /**
377
- * Removes a component from the entity
853
+ * Gets the current state of the spatial scene.
854
+ * This includes information about active elements and scene configuration.
855
+ * @returns Promise resolving to the current SpatialSceneState
378
856
  */
379
- async removeComponent(type) {
380
- var c = this.getComponent(type);
381
- if (c != void 0) {
382
- await WebSpatial.removeComponent(this._entity, c._resource);
383
- this.components.delete(c.constructor);
857
+ async getState() {
858
+ return (await new GetSpatialSceneState().execute()).data.name;
859
+ }
860
+ };
861
+
862
+ // src/types/types.ts
863
+ var SpatializedElementType = /* @__PURE__ */ ((SpatializedElementType2) => {
864
+ SpatializedElementType2[SpatializedElementType2["Spatialized2DElement"] = 0] = "Spatialized2DElement";
865
+ SpatializedElementType2[SpatializedElementType2["SpatializedStatic3DElement"] = 1] = "SpatializedStatic3DElement";
866
+ SpatializedElementType2[SpatializedElementType2["SpatializedDynamic3DElement"] = 2] = "SpatializedDynamic3DElement";
867
+ return SpatializedElementType2;
868
+ })(SpatializedElementType || {});
869
+ var BaseplateVisibilityValues = [
870
+ "automatic",
871
+ "visible",
872
+ "hidden"
873
+ ];
874
+ function isValidBaseplateVisibilityType(type) {
875
+ return BaseplateVisibilityValues.includes(type);
876
+ }
877
+ var WorldScalingValues = ["automatic", "dynamic"];
878
+ function isValidWorldScalingType(type) {
879
+ return WorldScalingValues.includes(type);
880
+ }
881
+ var WorldAlignmentValues = [
882
+ "adaptive",
883
+ "automatic",
884
+ "gravityAligned"
885
+ ];
886
+ function isValidWorldAlignmentType(type) {
887
+ return WorldAlignmentValues.includes(type);
888
+ }
889
+ var SpatialSceneValues = ["window", "volume"];
890
+ function isValidSpatialSceneType(type) {
891
+ return SpatialSceneValues.includes(type);
892
+ }
893
+ function isValidSceneUnit(val) {
894
+ if (typeof val === "number") {
895
+ return val >= 0;
896
+ }
897
+ if (typeof val === "string") {
898
+ if (val.endsWith("px")) {
899
+ if (isNaN(Number(val.slice(0, -2)))) {
900
+ return false;
901
+ }
902
+ return Number(val.slice(0, -2)) >= 0;
903
+ }
904
+ if (val.endsWith("m")) {
905
+ if (isNaN(Number(val.slice(0, -1)))) {
906
+ return false;
907
+ }
908
+ return Number(val.slice(0, -1)) >= 0;
384
909
  }
385
910
  }
386
- /**
387
- * Gets a component from the entity
388
- */
389
- getComponent(type) {
390
- return this.components.get(type);
911
+ return false;
912
+ }
913
+ var SpatialSceneState = /* @__PURE__ */ ((SpatialSceneState2) => {
914
+ SpatialSceneState2["idle"] = "idle";
915
+ SpatialSceneState2["pending"] = "pending";
916
+ SpatialSceneState2["willVisible"] = "willVisible";
917
+ SpatialSceneState2["visible"] = "visible";
918
+ SpatialSceneState2["fail"] = "fail";
919
+ return SpatialSceneState2;
920
+ })(SpatialSceneState || {});
921
+ var CubeInfo = class {
922
+ constructor(size, origin) {
923
+ this.size = size;
924
+ this.origin = origin;
925
+ this.size = size;
926
+ this.origin = origin;
391
927
  }
392
- /**
393
- * @hidden
394
- * Sets the window container that this entity should be rendered by (this does not effect resource ownership)
395
- * @param wg the window container that should render this entity
396
- */
397
- async _setParentWindowContainer(wg) {
398
- await WebSpatial.updateResource(this._entity, {
399
- setParentWindowContainerID: wg._wg.id
400
- });
928
+ get x() {
929
+ return this.origin.x;
401
930
  }
402
- /**
403
- * Sets a parent entity, if that entity or its parents are attached to a window container, this entity will be displayed
404
- * @param e parent entity or null to remove current parent
405
- */
406
- async setParent(e) {
407
- await WebSpatial.updateResource(this._entity, {
408
- setParent: e ? e._entity.id : ""
409
- });
931
+ get y() {
932
+ return this.origin.y;
410
933
  }
411
- /**
412
- * Sets the coordinate space of this entity (Default: App)
413
- * "App" = game engine style coordinates in meters
414
- * "Dom" = Windowing coordinates in dom units (eg. 0,0,0 is top left of window)
415
- * "Root" = Coordinate space is ignored and content is displayed and updated as window container's root object, window containers can only have one root entity
416
- * [TODO] review this api
417
- * @param space coordinate space mode
418
- */
419
- async setCoordinateSpace(space) {
420
- await WebSpatial.updateResource(this._entity, { setCoordinateSpace: space });
934
+ get z() {
935
+ return this.origin.z;
421
936
  }
422
- /**
423
- * Query the 3d boudning box of the entity
424
- * @returns The bounding box of the entity
425
- */
426
- async getBoundingBox() {
427
- var res = await WebSpatial.updateResource(this._entity, {
428
- getBoundingBox: true
429
- });
430
- return res.data;
937
+ get width() {
938
+ return this.size.width;
431
939
  }
432
- /**
433
- * Sets if the entity should be visible (default: True)
434
- * @param visible
435
- */
436
- async setVisible(visible) {
437
- await WebSpatial.updateResource(this._entity, { visible });
940
+ get height() {
941
+ return this.size.height;
438
942
  }
439
- /**
440
- * Removes a reference to the entity by the renderer and this object should no longer be used. [TODO] Attached components will not be destroyed
441
- */
442
- async destroy() {
443
- this._destroyed = true;
444
- await WebSpatial.destroyResource(this._entity);
943
+ get depth() {
944
+ return this.size.depth;
445
945
  }
446
- /**
447
- * Check if destroy has been called
448
- */
449
- isDestroyed() {
450
- return this._destroyed;
946
+ get left() {
947
+ return this.x;
451
948
  }
452
- // Set Entity name. Currently for debugging only.
453
- /** @hidden */
454
- async _setName(name) {
455
- this.name = name;
456
- return WebSpatial.updateResource(this._entity, { name });
949
+ get top() {
950
+ return this.y;
951
+ }
952
+ get right() {
953
+ return this.x + this.width;
954
+ }
955
+ get bottom() {
956
+ return this.y + this.height;
957
+ }
958
+ get back() {
959
+ return this.z;
960
+ }
961
+ get front() {
962
+ return this.z + this.depth;
457
963
  }
458
964
  };
459
965
 
460
- // src/core/component/SpatialComponent.ts
461
- var SpatialComponent = class extends SpatialObject {
462
- /**
463
- * Gets the entity this component is attached to
464
- * @returns entity or null
465
- */
466
- async getEntity() {
467
- let reqResp = await WebSpatial.updateResource(
468
- WebSpatial.getCurrentWebPanel(),
469
- { getEntityID: "" }
470
- );
471
- if (reqResp.data.parentID === "") {
472
- return new Promise((res2, rej) => {
473
- res2(null);
474
- });
475
- } else {
476
- var res = new WebSpatialResource();
477
- res.id = reqResp.data.parentID;
478
- return new SpatialEntity(res);
479
- }
966
+ // src/scene-polyfill.ts
967
+ var defaultSceneConfig = {
968
+ defaultSize: {
969
+ width: 1280,
970
+ height: 720
480
971
  }
481
972
  };
482
-
483
- // src/core/SpatialWindowContainer.ts
484
- var SpatialWindowContainer = class {
485
- /** @hidden */
486
- constructor(_wg) {
487
- this._wg = _wg;
973
+ var defaultSceneConfigVolume = {
974
+ defaultSize: {
975
+ width: 0.94,
976
+ height: 0.94,
977
+ depth: 0.94
488
978
  }
489
- /**
490
- * @hidden
491
- * Sets sets the open configuration for opening new window containers
492
- * @param options style options
493
- */
494
- async _setOpenSettings(options) {
495
- await WebSpatial.updateWindowContainer(this._wg, {
496
- nextOpenSettings: options
497
- });
979
+ };
980
+ var INTERNAL_SCHEMA_PREFIX = "webspatial://";
981
+ var SceneManager = class _SceneManager {
982
+ originalOpen;
983
+ static instance;
984
+ static getInstance() {
985
+ if (!_SceneManager.instance) {
986
+ _SceneManager.instance = new _SceneManager();
987
+ }
988
+ return _SceneManager.instance;
498
989
  }
499
- /**
500
- * Retrieves the root entity of the windowContainer
501
- * @returns the root entity of the windowContainer if one exists
502
- */
503
- async getRootEntity() {
504
- let reqResp = await WebSpatial.updateWindowContainer(this._wg, {
505
- getRootEntityID: ""
506
- });
507
- if (reqResp.data.rootEntId === "") {
508
- return null;
990
+ init(window2) {
991
+ this.originalOpen = window2.open.bind(window2);
992
+ window2.open = this.open;
993
+ }
994
+ configMap = {};
995
+ // name=>config
996
+ getConfig(name) {
997
+ if (name === void 0 || !this.configMap[name]) return void 0;
998
+ return this.configMap[name];
999
+ }
1000
+ open = (url, target, features) => {
1001
+ if (url?.startsWith(INTERNAL_SCHEMA_PREFIX)) {
1002
+ return this.originalOpen(url, target, features);
1003
+ }
1004
+ const prefix = `${window.location.protocol}//${window.location.host}`;
1005
+ if (!url?.startsWith(prefix)) {
1006
+ url = prefix + url;
1007
+ }
1008
+ if (target === "_self" || target === "_parent" || target === "_top") {
1009
+ const newWindow = this.originalOpen(url, target, features);
1010
+ return newWindow;
1011
+ }
1012
+ const cfg = target ? this.getConfig(target) : void 0;
1013
+ const cmd = new createSpatialSceneCommand(url, cfg, target, features);
1014
+ const result = cmd.executeSync();
1015
+ if (typeof target === "string" && this.configMap[target]) {
1016
+ delete this.configMap[target];
1017
+ }
1018
+ const id = result.data?.id;
1019
+ if (id) {
1020
+ let focusCmd = new FocusScene(id);
1021
+ focusCmd.execute();
1022
+ }
1023
+ return result.data?.windowProxy;
1024
+ };
1025
+ initScene(name, callback, options) {
1026
+ const sceneType = options?.type ?? "window";
1027
+ const defaultConfig = getSceneDefaultConfig(sceneType);
1028
+ const rawReturnVal = callback({ ...defaultConfig });
1029
+ const [formattedConfig, errors] = formatSceneConfig(rawReturnVal, sceneType);
1030
+ if (errors.length > 0) {
1031
+ console.warn(`initScene ${name} with errors: ${errors.join(", ")}`);
1032
+ }
1033
+ this.configMap[name] = {
1034
+ ...formattedConfig,
1035
+ type: sceneType
1036
+ };
1037
+ }
1038
+ };
1039
+ function pxToMeter(px) {
1040
+ return px / 1360;
1041
+ }
1042
+ function meterToPx(meter) {
1043
+ return meter * 1360;
1044
+ }
1045
+ function formatToNumber(str, targetUnit, defaultUnit) {
1046
+ if (typeof str === "number") {
1047
+ if (defaultUnit === "px" && targetUnit === "px" || defaultUnit === "m" && targetUnit === "m") {
1048
+ return str;
1049
+ }
1050
+ if (defaultUnit === "px" && targetUnit === "m") {
1051
+ return pxToMeter(str);
1052
+ } else if (defaultUnit === "m" && targetUnit === "px") {
1053
+ return meterToPx(str);
1054
+ }
1055
+ return str;
1056
+ }
1057
+ if (targetUnit === "m") {
1058
+ if (str.endsWith("m")) {
1059
+ return Number(str.slice(0, -1));
1060
+ } else if (str.endsWith("px")) {
1061
+ return pxToMeter(Number(str.slice(0, -2)));
1062
+ } else {
1063
+ throw new Error("formatToNumber: invalid str");
1064
+ }
1065
+ } else if (targetUnit === "px") {
1066
+ if (str.endsWith("px")) {
1067
+ return Number(str.slice(0, -2));
1068
+ } else if (str.endsWith("m")) {
1069
+ return meterToPx(Number(str.slice(0, -1)));
509
1070
  } else {
510
- var res = new WebSpatialResource();
511
- res.id = reqResp.data.rootEntId;
512
- return new SpatialEntity(res);
1071
+ throw new Error("formatToNumber: invalid str");
513
1072
  }
1073
+ } else {
1074
+ throw new Error("formatToNumber: invalid targetUnit");
514
1075
  }
515
- /*
516
- * Sets the root entity that this windowContainer will display (this does not effect resource ownership)
517
- * @param entity to display
518
- */
519
- async setRootEntity(entity) {
520
- await entity._setParentWindowContainer(this);
1076
+ }
1077
+ function formatSceneConfig(config, sceneType) {
1078
+ const defaultSceneConfig2 = getSceneDefaultConfig(sceneType);
1079
+ const errors = [];
1080
+ const isWindow = sceneType === "window";
1081
+ if (!isValidSpatialSceneType(sceneType)) {
1082
+ errors.push(`sceneType`);
1083
+ }
1084
+ if (config.defaultSize) {
1085
+ const iterKeys = ["width", "height", "depth"];
1086
+ for (let k of iterKeys) {
1087
+ if (!(k in config.defaultSize)) continue;
1088
+ if (isValidSceneUnit(config.defaultSize[k])) {
1089
+ ;
1090
+ config.defaultSize[k] = formatToNumber(
1091
+ config.defaultSize[k],
1092
+ isWindow ? "px" : "m",
1093
+ isWindow ? "px" : "m"
1094
+ );
1095
+ } else {
1096
+ ;
1097
+ config.defaultSize[k] = defaultSceneConfig2.defaultSize[k];
1098
+ errors.push(`defaultSize.${k}`);
1099
+ }
1100
+ }
521
1101
  }
522
- async close() {
523
- await WebSpatial.updateWindowContainer(this._wg, {
524
- close: true
525
- });
1102
+ if (config.resizability) {
1103
+ const iterKeys = ["minWidth", "minHeight", "maxWidth", "maxHeight"];
1104
+ for (let k of iterKeys) {
1105
+ if (!(k in config.resizability)) continue;
1106
+ if (isValidSceneUnit(config.resizability[k])) {
1107
+ ;
1108
+ config.resizability[k] = formatToNumber(
1109
+ config.resizability[k],
1110
+ "px",
1111
+ isWindow ? "px" : "m"
1112
+ );
1113
+ } else {
1114
+ ;
1115
+ config.resizability[k] = void 0;
1116
+ errors.push(`resizability.${k}`);
1117
+ }
1118
+ }
526
1119
  }
527
- };
528
-
529
- // src/core/resource/SpatialMeshResource.ts
530
- var SpatialMeshResource = class extends SpatialObject {
531
- };
532
-
533
- // src/core/resource/SpatialPhysicallyBasedMaterialResource.ts
534
- var SpatialPhysicallyBasedMaterialResource = class extends SpatialObject {
535
- /**
536
- * Base color of the material containing rgba between 0 and 1
537
- */
538
- baseColor = { r: 0, g: 0.7, b: 0.7, a: 1 };
539
- /**
540
- * PBR metalic value between 0 and 1
541
- */
542
- metallic = { value: 0.5 };
543
- /**
544
- * PBR roughness value between 0 and 1
545
- */
546
- roughness = { value: 0.5 };
547
- _modelComponentAttachedTo = {};
548
- _addToComponent(c) {
549
- this._modelComponentAttachedTo[c._resource.id] = c;
1120
+ if (config.worldScaling) {
1121
+ if (!isValidWorldScalingType(config.worldScaling)) {
1122
+ config.worldScaling = "automatic";
1123
+ errors.push("worldScaling");
1124
+ }
550
1125
  }
551
- /**
552
- * Syncs state of color, metallic, roupghness to the renderer
553
- */
554
- async update() {
555
- await WebSpatial.updateResource(this._resource, {
556
- baseColor: this.baseColor,
557
- metallic: this.metallic,
558
- roughness: this.roughness
559
- });
560
- for (var key in this._modelComponentAttachedTo) {
561
- await this._modelComponentAttachedTo[key]._syncMaterials();
1126
+ if (config.worldAlignment) {
1127
+ if (!isValidWorldAlignmentType(config.worldAlignment)) {
1128
+ config.worldAlignment = "automatic";
1129
+ errors.push("worldAlignment");
562
1130
  }
563
1131
  }
564
- };
565
-
566
- // src/core/SpatialSession.ts
567
- function _parseParentResources(options) {
568
- var parentWindowContainer = null;
569
- if (options?.windowContainer !== null) {
570
- parentWindowContainer = options?.windowContainer ? options?.windowContainer._wg : WebSpatial.getCurrentWindowContainer();
1132
+ if (config.baseplateVisibility) {
1133
+ if (!isValidBaseplateVisibilityType(config.baseplateVisibility)) {
1134
+ config.baseplateVisibility = "automatic";
1135
+ errors.push("baseplateVisibility");
1136
+ }
571
1137
  }
572
- var parentWindow = null;
573
- if (options?.windowComponent !== null) {
574
- parentWindow = options?.windowComponent ? options?.windowComponent._resource : WebSpatial.getCurrentWebPanel();
1138
+ return [config, errors];
1139
+ }
1140
+ function initScene(name, callback, options) {
1141
+ return SceneManager.getInstance().initScene(name, callback, options);
1142
+ }
1143
+ function hijackWindowOpen(window2) {
1144
+ SceneManager.getInstance().init(window2);
1145
+ }
1146
+ function hijackWindowATag(openedWindow) {
1147
+ openedWindow.document.onclick = function(e) {
1148
+ let element = e.target;
1149
+ let found = false;
1150
+ while (!found) {
1151
+ if (element && element.tagName == "A") {
1152
+ if (handleATag(e)) {
1153
+ return false;
1154
+ }
1155
+ return true;
1156
+ }
1157
+ if (element && element.parentElement) {
1158
+ element = element.parentElement;
1159
+ } else {
1160
+ break;
1161
+ }
1162
+ }
1163
+ };
1164
+ }
1165
+ function handleATag(event) {
1166
+ const targetElement = event.target;
1167
+ if (targetElement.tagName === "A") {
1168
+ const link = targetElement;
1169
+ const target = link.target;
1170
+ const url = link.href;
1171
+ if (target && target !== "_self") {
1172
+ event.preventDefault();
1173
+ window.open(url, target);
1174
+ return true;
1175
+ }
575
1176
  }
576
- return [parentWindowContainer, parentWindow];
577
1177
  }
578
- var SpatialSession = class _SpatialSession {
579
- /** @hidden */
580
- _engineUpdateListeners = Array();
581
- /** @hidden */
582
- _frameLoopStarted = false;
583
- /**
584
- * Add event listener callback to be called each frame
585
- * @param callback callback to be called each update
586
- */
587
- addOnEngineUpdateEventListener(callback) {
588
- this._engineUpdateListeners.push(callback);
589
- if (!this._frameLoopStarted) {
590
- this._frameLoopStarted = true;
591
- WebSpatial.onFrame(async (time) => {
592
- await Promise.all(
593
- this._engineUpdateListeners.map((cb) => {
594
- return cb(time);
595
- })
596
- );
597
- });
1178
+ function getSceneDefaultConfig(sceneType) {
1179
+ return sceneType === "window" ? defaultSceneConfig : defaultSceneConfigVolume;
1180
+ }
1181
+ async function injectScenePolyfill() {
1182
+ if (!window.opener) return;
1183
+ const state = await SpatialScene.getInstance().getState();
1184
+ if (state !== "pending" /* pending */) return;
1185
+ function onContentLoaded(callback) {
1186
+ if (document.readyState === "interactive" || document.readyState === "complete") {
1187
+ callback();
1188
+ } else {
1189
+ document.addEventListener("DOMContentLoaded", callback);
598
1190
  }
599
1191
  }
1192
+ onContentLoaded(async () => {
1193
+ let provideDefaultSceneConfig = getSceneDefaultConfig(
1194
+ window.xrCurrentSceneType ?? "window"
1195
+ );
1196
+ let cfg = provideDefaultSceneConfig;
1197
+ if (typeof window.xrCurrentSceneDefaults === "function") {
1198
+ try {
1199
+ cfg = await window.xrCurrentSceneDefaults?.(provideDefaultSceneConfig);
1200
+ } catch (error) {
1201
+ console.error(error);
1202
+ }
1203
+ }
1204
+ await new Promise((resolve, reject) => {
1205
+ setTimeout(() => {
1206
+ resolve(null);
1207
+ }, 1e3);
1208
+ });
1209
+ const sceneType = window.xrCurrentSceneType ?? "window";
1210
+ const [formattedConfig, errors] = formatSceneConfig(cfg, sceneType);
1211
+ if (errors.length > 0) {
1212
+ console.warn(
1213
+ `window.xrCurrentSceneDefaults with errors: ${errors.join(", ")}`
1214
+ );
1215
+ }
1216
+ await SpatialScene.getInstance().updateSceneCreationConfig({
1217
+ ...formattedConfig,
1218
+ type: sceneType
1219
+ });
1220
+ });
1221
+ }
1222
+ function injectSceneHook() {
1223
+ hijackWindowOpen(window);
1224
+ hijackWindowATag(window);
1225
+ injectScenePolyfill();
1226
+ }
1227
+
1228
+ // src/SpatializedElementCreator.ts
1229
+ init_JSBCommand();
1230
+
1231
+ // src/Spatialized2DElement.ts
1232
+ init_JSBCommand();
1233
+
1234
+ // src/SpatializedElement.ts
1235
+ init_JSBCommand();
1236
+ init_SpatialWebEvent();
1237
+
1238
+ // src/SpatialWebEventCreator.ts
1239
+ function createSpatialEvent(type, detail) {
1240
+ return new CustomEvent(type, {
1241
+ bubbles: true,
1242
+ cancelable: false,
1243
+ detail
1244
+ });
1245
+ }
1246
+
1247
+ // src/SpatializedElement.ts
1248
+ var SpatializedElement = class extends SpatialObject {
600
1249
  /**
601
- * Creates a Entity
602
- * @returns Entity
1250
+ * Creates a new spatialized element with the specified ID.
1251
+ * Registers the element to receive spatial events.
1252
+ * @param id Unique identifier for this element
603
1253
  */
604
- async createEntity(options) {
605
- var [parentWindowContainer, parentWindow] = _parseParentResources(options);
606
- let entity = await WebSpatial.createResource(
607
- "Entity",
608
- parentWindowContainer,
609
- parentWindow
610
- );
611
- return new SpatialEntity(entity);
1254
+ constructor(id) {
1255
+ super(id);
1256
+ this.id = id;
1257
+ SpatialWebEvent.addEventReceiver(id, this.onReceiveEvent.bind(this));
612
1258
  }
613
1259
  /**
614
- * Creates a WindowComponent
615
- * [TODO] should creation of components be moved to entity? and these made private?
616
- * @returns WindowComponent
1260
+ * Updates the transformation matrix of this element in 3D space.
1261
+ * This affects the position, rotation, and scale of the element.
1262
+ * @param matrix The new transformation matrix
1263
+ * @returns Promise resolving when the transform is updated
617
1264
  */
618
- async createWindowComponent(options) {
619
- var [parentWindowContainer, parentWindow] = _parseParentResources(options);
620
- let entity = await WebSpatial.createResource(
621
- "SpatialWebView",
622
- parentWindowContainer,
623
- parentWindow
624
- );
625
- return new SpatialWindowComponent(entity);
1265
+ async updateTransform(matrix) {
1266
+ return new UpdateSpatializedElementTransform(this, matrix).execute();
626
1267
  }
627
1268
  /**
628
- * Creates a ViewComponent used to display 3D content within the entity
629
- * @returns SpatialViewComponent
1269
+ * Information about the element's bounding cube.
1270
+ * Used for spatial calculations and hit testing.
630
1271
  */
631
- async createViewComponent(options) {
632
- var [parentWindowContainer, parentWindow] = _parseParentResources(options);
633
- let entity = await WebSpatial.createResource(
634
- "SpatialView",
635
- parentWindowContainer,
636
- parentWindow
637
- );
638
- return new SpatialViewComponent(entity);
639
- }
1272
+ _cubeInfo;
640
1273
  /**
641
- * Creates a ModelComponent used to display geometry + material of a 3D model
642
- * @returns ModelComponent
1274
+ * Gets the current cube information for this element.
1275
+ * @returns The current CubeInfo or undefined if not set
643
1276
  */
644
- async createModelComponent(options) {
645
- var [parentWindowContainer, parentWindow] = _parseParentResources(options);
646
- var opts = void 0;
647
- if (options) {
648
- opts = { modelURL: options.url };
649
- }
650
- let entity = await WebSpatial.createResource(
651
- "ModelComponent",
652
- parentWindowContainer,
653
- parentWindow,
654
- opts
655
- );
656
- return new SpatialModelComponent(entity);
1277
+ get cubeInfo() {
1278
+ return this._cubeInfo;
657
1279
  }
658
1280
  /**
659
- * Creates a Model3DComponent
660
- * @returns Model3DComponent
1281
+ * The current transformation matrix of this element.
661
1282
  */
662
- async createModel3DComponent(options) {
663
- var [parentWindowContainer, parentWindow] = _parseParentResources(options);
664
- var opts = void 0;
665
- if (options) {
666
- opts = { modelURL: options.url };
667
- }
668
- let entity = await WebSpatial.createResource(
669
- "Model3DComponent",
670
- parentWindowContainer,
671
- parentWindow,
672
- opts
673
- );
674
- return new SpatialModel3DComponent(entity);
675
- }
1283
+ _transform;
676
1284
  /**
677
- * Creates a InputComponent
678
- * [Experimental] Creates a InputComponent used to handle click and drag events of the entity containing a model
679
- * @returns InputComponent
1285
+ * The inverse of the current transformation matrix.
1286
+ * Used for converting world coordinates to local coordinates.
680
1287
  */
681
- async createInputComponent(options) {
682
- var [parentWindowContainer, parentWindow] = _parseParentResources(options);
683
- let entity = await WebSpatial.createResource(
684
- "InputComponent",
685
- parentWindowContainer,
686
- parentWindow
687
- );
688
- return new SpatialInputComponent(entity);
1288
+ _transformInv;
1289
+ /**
1290
+ * Gets the current transformation matrix.
1291
+ * @returns The current transformation matrix or undefined if not set
1292
+ */
1293
+ get transform() {
1294
+ return this._transform;
689
1295
  }
690
1296
  /**
691
- * Creates a MeshResource containing geometry data
692
- * @returns MeshResource
1297
+ * Gets the inverse of the current transformation matrix.
1298
+ * @returns The inverse transformation matrix or undefined if not set
693
1299
  */
694
- async createMeshResource(options) {
695
- var [parentWindowContainer, parentWindow] = _parseParentResources(options);
696
- let entity = await WebSpatial.createResource(
697
- "MeshResource",
698
- parentWindowContainer,
699
- parentWindow,
700
- options
701
- );
702
- return new SpatialMeshResource(entity);
1300
+ get transformInv() {
1301
+ return this._transformInv;
703
1302
  }
704
1303
  /**
705
- * Creates a PhysicallyBasedMaterial containing PBR material data
706
- * @returns PhysicallyBasedMaterial
1304
+ * Processes events received from the WebSpatial environment.
1305
+ * Handles various spatial events like transforms, gestures, and interactions.
1306
+ * @param data The event data received from the WebSpatial system
707
1307
  */
708
- async createPhysicallyBasedMaterialResource(options) {
709
- var [parentWindowContainer, parentWindow] = _parseParentResources(options);
710
- let entity = await WebSpatial.createResource(
711
- "PhysicallyBasedMaterial",
712
- parentWindowContainer,
713
- parentWindow,
714
- options
715
- );
716
- return new SpatialPhysicallyBasedMaterialResource(entity);
1308
+ onReceiveEvent(data) {
1309
+ const { type } = data;
1310
+ if (type === "objectdestroy" /* objectdestroy */) {
1311
+ this.isDestroyed = true;
1312
+ } else if (type === "cubeInfo" /* cubeInfo */) {
1313
+ const cubeInfoMsg = data;
1314
+ this._cubeInfo = new CubeInfo(cubeInfoMsg.size, cubeInfoMsg.origin);
1315
+ } else if (type === "transform" /* transform */) {
1316
+ this._transform = new DOMMatrix([
1317
+ data.detail.column0[0],
1318
+ data.detail.column0[1],
1319
+ data.detail.column0[2],
1320
+ 0,
1321
+ data.detail.column1[0],
1322
+ data.detail.column1[1],
1323
+ data.detail.column1[2],
1324
+ 0,
1325
+ data.detail.column2[0],
1326
+ data.detail.column2[1],
1327
+ data.detail.column2[2],
1328
+ 0,
1329
+ data.detail.column3[0],
1330
+ data.detail.column3[1],
1331
+ data.detail.column3[2],
1332
+ 1
1333
+ ]);
1334
+ this._transformInv = this._transform.inverse();
1335
+ } else if (type === "spatialtap" /* spatialtap */) {
1336
+ const event = createSpatialEvent(
1337
+ "spatialtap" /* spatialtap */,
1338
+ data.detail
1339
+ );
1340
+ this._onSpatialTap?.(event);
1341
+ } else if (type === "spatialdrag" /* spatialdrag */) {
1342
+ if (!this._isDragging) {
1343
+ const dragStartEvent = createSpatialEvent(
1344
+ "spatialdragstart" /* spatialdragstart */,
1345
+ data.detail
1346
+ );
1347
+ this._onSpatialDragStart?.(dragStartEvent);
1348
+ }
1349
+ this._isDragging = true;
1350
+ const event = createSpatialEvent(
1351
+ "spatialdrag" /* spatialdrag */,
1352
+ data.detail
1353
+ );
1354
+ this._onSpatialDrag?.(event);
1355
+ } else if (type === "spatialdragend" /* spatialdragend */) {
1356
+ this._isDragging = false;
1357
+ const event = createSpatialEvent(
1358
+ "spatialdragend" /* spatialdragend */,
1359
+ data.detail
1360
+ );
1361
+ this._onSpatialDragEnd?.(event);
1362
+ } else if (type === "spatialrotate" /* spatialrotate */) {
1363
+ if (!this._isRotating) {
1364
+ const rotationStartEvent = createSpatialEvent(
1365
+ "spatialrotatestart" /* spatialrotatestart */,
1366
+ data.detail
1367
+ );
1368
+ this._onSpatialRotateStart?.(rotationStartEvent);
1369
+ }
1370
+ this._isRotating = true;
1371
+ const event = createSpatialEvent(
1372
+ "spatialrotate" /* spatialrotate */,
1373
+ data.detail
1374
+ );
1375
+ this._onSpatialRotate?.(event);
1376
+ } else if (type === "spatialrotateend" /* spatialrotateend */) {
1377
+ this._isRotating = false;
1378
+ const event = createSpatialEvent(
1379
+ "spatialrotateend" /* spatialrotateend */,
1380
+ data.detail
1381
+ );
1382
+ this._onSpatialRotateEnd?.(event);
1383
+ } else if (type === "spatialmagnify" /* spatialmagnify */) {
1384
+ if (!this._isMagnify) {
1385
+ const magnifyStartEvent = createSpatialEvent(
1386
+ "spatialmagnifystart" /* spatialmagnifystart */,
1387
+ data.detail
1388
+ );
1389
+ this._onSpatialMagnifyStart?.(magnifyStartEvent);
1390
+ }
1391
+ this._isMagnify = true;
1392
+ const event = createSpatialEvent(
1393
+ "spatialmagnify" /* spatialmagnify */,
1394
+ data.detail
1395
+ );
1396
+ this._onSpatialMagnify?.(event);
1397
+ } else if (type === "spatialmagnifyend" /* spatialmagnifyend */) {
1398
+ this._isMagnify = false;
1399
+ const event = createSpatialEvent(
1400
+ "spatialmagnifyend" /* spatialmagnifyend */,
1401
+ data.detail
1402
+ );
1403
+ this._onSpatialMagnifyEnd?.(event);
1404
+ }
1405
+ }
1406
+ _onSpatialTap;
1407
+ set onSpatialTap(value) {
1408
+ this._onSpatialTap = value;
1409
+ this.updateProperties({
1410
+ enableTapGesture: value !== void 0
1411
+ });
1412
+ }
1413
+ _isDragging = false;
1414
+ _onSpatialDragStart;
1415
+ set onSpatialDragStart(value) {
1416
+ this._onSpatialDragStart = value;
1417
+ this.updateProperties({
1418
+ enableDragStartGesture: this._onSpatialDragStart !== void 0
1419
+ });
1420
+ }
1421
+ _onSpatialDrag;
1422
+ set onSpatialDrag(value) {
1423
+ this._onSpatialDrag = value;
1424
+ this.updateProperties({
1425
+ enableDragGesture: this._onSpatialDrag !== void 0
1426
+ });
1427
+ }
1428
+ _onSpatialDragEnd;
1429
+ set onSpatialDragEnd(value) {
1430
+ this._onSpatialDragEnd = value;
1431
+ this.updateProperties({
1432
+ enableDragEndGesture: value !== void 0
1433
+ });
1434
+ }
1435
+ _isRotating = false;
1436
+ _onSpatialRotateStart;
1437
+ set onSpatialRotateStart(value) {
1438
+ this._onSpatialRotateStart = value;
1439
+ this.updateProperties({
1440
+ enableRotateStartGesture: this._onSpatialRotateStart !== void 0
1441
+ });
1442
+ }
1443
+ _onSpatialRotate;
1444
+ set onSpatialRotate(value) {
1445
+ this._onSpatialRotate = value;
1446
+ this.updateProperties({
1447
+ enableRotateGesture: this._onSpatialRotate !== void 0
1448
+ });
1449
+ }
1450
+ _onSpatialRotateEnd;
1451
+ set onSpatialRotateEnd(value) {
1452
+ this._onSpatialRotateEnd = value;
1453
+ this.updateProperties({
1454
+ enableRotateEndGesture: value !== void 0
1455
+ });
1456
+ }
1457
+ _isMagnify = false;
1458
+ _onSpatialMagnifyStart;
1459
+ set onSpatialMagnifyStart(value) {
1460
+ this._onSpatialMagnifyStart = value;
1461
+ this.updateProperties({
1462
+ enableMagnifyStartGesture: value !== void 0
1463
+ });
717
1464
  }
718
- /**
719
- * Creates a WindowContainer
720
- * @returns SpatialWindowContainer
721
- * */
722
- async createWindowContainer(options) {
723
- var style = options?.style ? options?.style : "Plain";
724
- var [parentWindowContainer, parentWindow] = _parseParentResources(options);
725
- return new SpatialWindowContainer(
726
- await WebSpatial.createWindowContainer(
727
- style,
728
- parentWindowContainer,
729
- parentWindow
730
- )
731
- );
1465
+ _onSpatialMagnify;
1466
+ set onSpatialMagnify(value) {
1467
+ this._onSpatialMagnify = value;
1468
+ this.updateProperties({
1469
+ enableMagnifyGesture: value !== void 0
1470
+ });
1471
+ }
1472
+ _onSpatialMagnifyEnd;
1473
+ set onSpatialMagnifyEnd(value) {
1474
+ this._onSpatialMagnifyEnd = value;
1475
+ this.updateProperties({
1476
+ enableMagnifyEndGesture: value !== void 0
1477
+ });
732
1478
  }
733
1479
  /**
734
- * Creates a Scene to display content within an anchored area managed by the OS
735
- * @hidden
736
- * @param {WindowStyle} [style='Plain'] - The style of the Scene container to be created with. Defaults to 'Plain'.
737
- * @param {Object} [cfg={}] - Configuration object for the Scene.
738
- * @returns Boolean
1480
+ * Cleans up resources when this element is destroyed.
1481
+ * Removes event receivers to prevent memory leaks.
739
1482
  */
740
- async _createScene(style = "Plain", cfg) {
741
- return await WebSpatial.createScene(style, cfg);
1483
+ onDestroy() {
1484
+ SpatialWebEvent.removeEventReceiver(this.id);
742
1485
  }
1486
+ };
1487
+
1488
+ // src/Spatialized2DElement.ts
1489
+ var Spatialized2DElement = class extends SpatializedElement {
743
1490
  /**
744
- * Retrieves the window for this page
745
- * @returns the window component corresponding to the js running on this page
746
- * [TODO] discuss implications of this not being async
1491
+ * Creates a new spatialized 2D element.
1492
+ * @param id Unique identifier for this element
1493
+ * @param windowProxy Reference to the window object containing the 2D content
747
1494
  */
748
- getCurrentWindowComponent() {
749
- return new SpatialWindowComponent(WebSpatial.getCurrentWebPanel());
1495
+ constructor(id, windowProxy) {
1496
+ super(id);
1497
+ this.windowProxy = windowProxy;
1498
+ hijackWindowATag(windowProxy);
750
1499
  }
751
1500
  /**
752
- * Retrieves the parent window for this page or null if this is the root page
753
- * @returns the window component or null
1501
+ * Updates the properties of this 2D element.
1502
+ * This can include size, position, background, and other visual properties.
1503
+ * @param properties Partial set of properties to update
1504
+ * @returns Promise resolving when the update is complete
754
1505
  */
755
- async getParentWindowComponent() {
756
- let parentResp = await WebSpatial.updateResource(
757
- WebSpatial.getCurrentWebPanel(),
758
- { getParentID: "" }
759
- );
760
- if (parentResp.data.parentID === "") {
761
- return new Promise((res2, rej) => {
762
- res2(null);
763
- });
764
- } else {
765
- var res = new WebSpatialResource();
766
- res.id = parentResp.data.parentID;
767
- return new SpatialWindowComponent(res);
768
- }
1506
+ async updateProperties(properties) {
1507
+ return new UpdateSpatialized2DElementProperties(this, properties).execute();
769
1508
  }
770
1509
  /**
771
- * Logs a message to the native apps console
772
- * @param msg mesage to log
1510
+ * Adds a child spatialized element to this 2D element.
1511
+ * This allows for creating hierarchical structures of spatial elements.
1512
+ * @param element The child element to add
1513
+ * @returns Promise resolving when the element is added
773
1514
  */
774
- async log(...msg) {
775
- await WebSpatial.sendCommand(
776
- new RemoteCommand("log", {
777
- logString: msg.map((x) => {
778
- return JSON.stringify(x);
779
- })
780
- })
781
- );
1515
+ async addSpatializedElement(element) {
1516
+ return new AddSpatializedElementToSpatialized2DElement(
1517
+ this,
1518
+ element
1519
+ ).execute();
782
1520
  }
1521
+ };
1522
+
1523
+ // src/SpatializedStatic3DElement.ts
1524
+ init_JSBCommand();
1525
+ var SpatializedStatic3DElement = class extends SpatializedElement {
783
1526
  /**
784
- * @hidden
785
- * Debugging only, used to ping the native renderer
1527
+ * Promise resolver for the ready state.
1528
+ * Used to resolve the ready promise when the model is loaded.
786
1529
  */
787
- async _ping(msg) {
788
- return await WebSpatial.ping(msg);
789
- }
1530
+ _readyResolve;
790
1531
  /**
791
- * @hidden
792
- * Debugging to get internal state from native code
793
- * @returns stats from native code. Objects tracks number of native objects that were created but not yet explicitly destroyed. RefObjects tracks bjects that still have references. After an object is destroyed, we should be cleaning up all of the native references. Expect objects.count == refObjects.count , if not, there is likely a leak.
1532
+ * Caches the last model URL to detect changes.
1533
+ * Used to reset the ready promise when the model URL changes.
794
1534
  */
795
- async _getStats() {
796
- return await WebSpatial.getStats();
797
- }
1535
+ modelURL = "";
798
1536
  /**
799
- * @hidden
1537
+ * Creates a new promise for tracking the ready state of the model.
1538
+ * @returns Promise that resolves when the model is loaded (true) or fails to load (false)
800
1539
  */
801
- async _inspect(spatialObjectId = WebSpatial.getCurrentWebPanel().id) {
802
- return WebSpatial.inspect(spatialObjectId);
1540
+ createReadyPromise() {
1541
+ return new Promise((resolve) => {
1542
+ this._readyResolve = resolve;
1543
+ });
803
1544
  }
804
1545
  /**
805
- * @hidden
1546
+ * Promise that resolves when the model is loaded.
1547
+ * Resolves to true on successful load, false on failure.
806
1548
  */
807
- async _inspectRootWindowContainer() {
808
- return WebSpatial.inspectRootWindowContainer();
809
- }
810
- /** Opens the immersive space */
811
- async openImmersiveSpace() {
812
- return await WebSpatial.openImmersiveSpace();
813
- }
814
- /** Closes the immersive space */
815
- async dismissImmersiveSpace() {
816
- return await WebSpatial.dismissImmersiveSpace();
817
- }
818
- static _immersiveWindowContainer = null;
1549
+ ready = this.createReadyPromise();
819
1550
  /**
820
- * Retreives the window container corresponding to the Immersive space
821
- * @returns the immersive window container
1551
+ * Updates the properties of this static 3D element.
1552
+ * Handles special case for modelURL changes by resetting the ready promise.
1553
+ * @param properties Partial set of properties to update
1554
+ * @returns Promise resolving when the update is complete
822
1555
  */
823
- async getImmersiveWindowContainer() {
824
- if (_SpatialSession._immersiveWindowContainer) {
825
- return _SpatialSession._immersiveWindowContainer;
1556
+ async updateProperties(properties) {
1557
+ if (properties.modelURL !== void 0) {
1558
+ if (this.modelURL !== properties.modelURL) {
1559
+ this.modelURL = properties.modelURL;
1560
+ this.ready = this.createReadyPromise();
1561
+ }
1562
+ }
1563
+ return new UpdateSpatializedStatic3DElementProperties(
1564
+ this,
1565
+ properties
1566
+ ).execute();
1567
+ }
1568
+ /**
1569
+ * Processes events received from the WebSpatial environment.
1570
+ * Handles model loading events in addition to base spatial events.
1571
+ * @param data The event data received from the WebSpatial system
1572
+ */
1573
+ onReceiveEvent(data) {
1574
+ if (data.type === "modelloaded" /* modelloaded */) {
1575
+ this._onLoadCallback?.();
1576
+ this._readyResolve?.(true);
1577
+ } else if (data.type === "modelloadfailed" /* modelloadfailed */) {
1578
+ this._onLoadFailureCallback?.();
1579
+ this._readyResolve?.(false);
826
1580
  } else {
827
- _SpatialSession._immersiveWindowContainer = new SpatialWindowContainer(
828
- WebSpatial.getImmersiveWindowContainer()
829
- );
830
- return _SpatialSession._immersiveWindowContainer;
1581
+ super.onReceiveEvent(data);
831
1582
  }
832
1583
  }
833
- // Retreives the window container that is the parent to this spatial web page
834
- static _currentWindowContainer = null;
835
1584
  /**
836
- * Gets the current window container for the window
837
- * [TODO] discuss what happens if it doesnt yet have a window container
838
- * @returns the current window container for the window
1585
+ * Callback function for successful model loading.
839
1586
  */
840
- getCurrentWindowContainer() {
841
- if (_SpatialSession._currentWindowContainer) {
842
- return _SpatialSession._currentWindowContainer;
843
- } else {
844
- _SpatialSession._currentWindowContainer = new SpatialWindowContainer(
845
- WebSpatial.getCurrentWindowContainer()
846
- );
847
- return _SpatialSession._currentWindowContainer;
848
- }
849
- }
1587
+ _onLoadCallback;
850
1588
  /**
851
- * Start a transaction that queues up commands to submit them all at once to reduce ipc overhead
852
- * @param fn function to be run, within this function, promises will not resolve
853
- * @returns promise for the entire transaction completion
1589
+ * Sets the callback function for successful model loading.
1590
+ * @param callback Function to call when the model is loaded successfully
854
1591
  */
855
- transaction(fn) {
856
- WebSpatial.startTransaction();
857
- fn();
858
- return WebSpatial.sendTransaction();
1592
+ set onLoadCallback(callback) {
1593
+ this._onLoadCallback = callback;
859
1594
  }
860
1595
  /**
861
- * Creates a window context object that is compatable with SpatialWindowComponent's setFromWindow API
862
- * @returns window context
1596
+ * Callback function for model loading failure.
863
1597
  */
864
- async createWindowContext() {
865
- let openedWindow = window.open("webspatial://createWindowContext");
866
- if (WebSpatial.getBackend() != "AVP") {
867
- var counter = 0;
868
- while (openedWindow.window.testAPI == null) {
869
- if (counter > 15) {
870
- openedWindow?.close();
871
- openedWindow = window.open("about:blank");
872
- counter = 0;
873
- this.log("unexpected error when trying to open new window, retrying.");
874
- }
875
- var locName = "about:blank?x" + counter;
876
- openedWindow.location.href = locName;
877
- counter++;
878
- await new Promise((resolve) => setTimeout(resolve, 10));
879
- }
880
- ;
881
- openedWindow._webSpatialID = openedWindow.window.testAPI.getWindowID();
882
- } else {
883
- while (openedWindow.window._webSpatialID == void 0) {
884
- await new Promise((resolve) => setTimeout(resolve, 10));
885
- }
886
- }
887
- openedWindow.document.head.innerHTML = `<meta name="viewport" content="width=device-width, initial-scale=1">
888
- <base href="${document.baseURI}">
889
- `;
890
- return openedWindow;
1598
+ _onLoadFailureCallback;
1599
+ /**
1600
+ * Sets the callback function for model loading failure.
1601
+ * @param callback Function to call when the model fails to load
1602
+ */
1603
+ set onLoadFailureCallback(callback) {
1604
+ this._onLoadFailureCallback = callback;
891
1605
  }
892
- // Get Entity by id. Currently for debugging only.
893
- /** @hidden */
894
- async _getEntity(id) {
895
- const entityInfo = await WebSpatial.inspect(id);
896
- const [_, x, y, z] = entityInfo.position.match(/(\d+\.?\d*)/g);
897
- const [__, sx, sy, sz] = entityInfo.scale.match(/(\d+\.?\d*)/g);
898
- var res = new WebSpatialResource();
899
- res.id = id;
900
- res.windowContainerId = WebSpatial.getCurrentWindowContainer().id;
901
- const entity = new SpatialEntity(res);
902
- entity.transform.position.x = parseFloat(x);
903
- entity.transform.position.y = parseFloat(y);
904
- entity.transform.position.z = parseFloat(z);
905
- entity.transform.scale.x = parseFloat(sx);
906
- entity.transform.scale.y = parseFloat(sy);
907
- entity.transform.scale.z = parseFloat(sz);
908
- return entity;
909
- }
910
- // set loading view.
911
- /** @hidden */
912
- async setLoading(method, style) {
913
- return WebSpatial.setLoading(method, style);
1606
+ updateModelTransform(transform) {
1607
+ const modelTransform = Array.from(transform.toFloat64Array());
1608
+ this.updateProperties({ modelTransform });
914
1609
  }
915
1610
  };
916
1611
 
917
- // src/core/Spatial.ts
918
- var Spatial = class {
919
- /**
920
- * Requests a session object from the browser
921
- * @returns The session or null if not availible in the current browser
922
- * [TODO] discuss implications of this not being async
923
- */
924
- requestSession() {
925
- if (this.isSupported() && this.getNativeVersion() === this.getClientVersion()) {
926
- return new SpatialSession();
927
- } else {
928
- return null;
929
- }
1612
+ // src/SpatializedDynamic3DElement.ts
1613
+ init_JSBCommand();
1614
+ var SpatializedDynamic3DElement = class extends SpatializedElement {
1615
+ children = [];
1616
+ constructor(id) {
1617
+ super(id);
1618
+ }
1619
+ async addEntity(entity) {
1620
+ const ans = new SetParentForEntityCommand(entity.id, this.id).execute();
1621
+ this.children.push(entity);
1622
+ entity.parent = this;
1623
+ return ans;
1624
+ }
1625
+ async updateProperties(properties) {
1626
+ return new UpdateSpatializedDynamic3DElementProperties(
1627
+ this,
1628
+ properties
1629
+ ).execute();
930
1630
  }
931
- /**
932
- * @returns true if web spatial is supported by this webpage
933
- */
934
- isSupported() {
935
- return this.getNativeVersion() === this.getClientVersion();
1631
+ };
1632
+
1633
+ // src/SpatializedElementCreator.ts
1634
+ async function createSpatialized2DElement() {
1635
+ const result = await new createSpatialized2DElementCommand().execute();
1636
+ if (!result.success) {
1637
+ throw new Error("createSpatialized2DElement failed");
1638
+ } else {
1639
+ const { id, windowProxy } = result.data;
1640
+ windowProxy.document.head.innerHTML = `<meta name="viewport" content="width=device-width, initial-scale=1">
1641
+ <base href="${document.baseURI}">`;
1642
+ return new Spatialized2DElement(id, windowProxy);
936
1643
  }
937
- /**
938
- * Gets the native version, format is "x.x.x"
939
- * @returns native version string
940
- */
941
- getNativeVersion() {
942
- if (window.__WebSpatialData && window.__WebSpatialData.getNativeVersion) {
943
- return window.__WebSpatialData.getNativeVersion();
944
- }
945
- return window.WebSpatailNativeVersion === "PACKAGE_VERSION" ? this.getClientVersion() : window.WebSpatailNativeVersion;
1644
+ }
1645
+ async function createSpatializedStatic3DElement(modelURL) {
1646
+ const result = await new CreateSpatializedStatic3DElementCommand(
1647
+ modelURL
1648
+ ).execute();
1649
+ if (!result.success) {
1650
+ throw new Error("createSpatializedStatic3DElement failed");
1651
+ } else {
1652
+ const { id } = result.data;
1653
+ return new SpatializedStatic3DElement(id);
946
1654
  }
947
- /**
948
- * Gets the client version, format is "x.x.x"
949
- * @returns client version string
950
- */
951
- getClientVersion() {
952
- return "1.0.4";
1655
+ }
1656
+ async function createSpatializedDynamic3DElement() {
1657
+ const result = await new CreateSpatializedDynamic3DElementCommand().execute();
1658
+ if (!result.success) {
1659
+ throw new Error("createSpatializedDynamic3DElement failed");
1660
+ } else {
1661
+ const { id } = result.data;
1662
+ return new SpatializedDynamic3DElement(id);
953
1663
  }
954
- };
1664
+ }
955
1665
 
956
- // src/core/SpatialHelper.ts
957
- var SpatialHelper = class _SpatialHelper {
958
- constructor(session) {
959
- this.session = session;
960
- }
961
- static _instance = null;
962
- static get instance() {
963
- if (this._instance) {
964
- return this._instance;
1666
+ // src/reality/realityCreator.ts
1667
+ init_JSBCommand();
1668
+
1669
+ // src/reality/entity/SpatialEntity.ts
1670
+ init_JSBCommand();
1671
+ init_JSBCommand();
1672
+ init_SpatialWebEvent();
1673
+ var SpatialEntity = class _SpatialEntity extends SpatialObject {
1674
+ constructor(id, userData) {
1675
+ super(id);
1676
+ this.userData = userData;
1677
+ SpatialWebEvent.addEventReceiver(id, this.onReceiveEvent);
1678
+ }
1679
+ position = { x: 0, y: 0, z: 0 };
1680
+ rotation = { x: 0, y: 0, z: 0 };
1681
+ scale = { x: 1, y: 1, z: 1 };
1682
+ events = {};
1683
+ children = [];
1684
+ parent = null;
1685
+ async addComponent(component) {
1686
+ return new AddComponentToEntityCommand(this, component).execute();
1687
+ }
1688
+ async setPosition(position) {
1689
+ return this.updateTransform({ position });
1690
+ }
1691
+ async setRotation(rotation) {
1692
+ return this.updateTransform({ rotation });
1693
+ }
1694
+ async setScale(scale) {
1695
+ return this.updateTransform({ scale });
1696
+ }
1697
+ async addEntity(ent) {
1698
+ const ans = await new SetParentForEntityCommand(ent.id, this.id).execute();
1699
+ this.children.push(ent);
1700
+ ent.parent = this;
1701
+ return ans;
1702
+ }
1703
+ async removeFromParent() {
1704
+ const ans = await new SetParentForEntityCommand(
1705
+ this.id,
1706
+ void 0
1707
+ ).execute();
1708
+ if (this.parent) {
1709
+ this.parent.children = this.parent.children.filter(
1710
+ (child) => child.id !== this.id
1711
+ );
1712
+ this.parent = null;
1713
+ }
1714
+ return ans;
1715
+ }
1716
+ async updateTransform(properties) {
1717
+ this.position = properties.position ?? this.position;
1718
+ this.rotation = properties.rotation ?? this.rotation;
1719
+ this.scale = properties.scale ?? this.scale;
1720
+ return new UpdateEntityPropertiesCommand(this, properties).execute();
1721
+ }
1722
+ async addEvent(type, callback) {
1723
+ if (this.events[type]) {
1724
+ this.events[type] = callback;
965
1725
  } else {
966
- let spatial = new Spatial();
967
- if (spatial.isSupported()) {
968
- let session = spatial.requestSession();
969
- if (session) {
970
- this._instance = new _SpatialHelper(session);
971
- return this._instance;
972
- }
1726
+ try {
1727
+ await this.updateEntityEvent(type, true);
1728
+ this.events[type] = callback;
1729
+ } catch (error) {
1730
+ console.error("addEvent failed", type);
973
1731
  }
974
1732
  }
975
- return null;
976
- }
977
- shape = {
978
- createShapeEntity: async (shape = "box") => {
979
- var box = await this.session.createMeshResource({ shape });
980
- var mat = await this.session.createPhysicallyBasedMaterialResource();
981
- await mat.update();
982
- var customModel = await this.session.createModelComponent();
983
- customModel.setMaterials([mat]);
984
- customModel.setMesh(box);
985
- var boxEntity = await this.session.createEntity();
986
- await boxEntity.setComponent(customModel);
987
- boxEntity.transform.position.z = 0;
988
- boxEntity.transform.scale = new Vec3(0.5, 0.5, 0.5);
989
- await boxEntity.updateTransform();
990
- return boxEntity;
991
- },
992
- createModelEntity: async (url) => {
993
- var customModel = await this.session.createModelComponent({ url });
994
- var boxEntity = await this.session.createEntity();
995
- await boxEntity.setComponent(customModel);
996
- await boxEntity.updateTransform();
997
- return boxEntity;
998
- },
999
- wrapInBoundingBoxEntity: async (entityToWrap) => {
1000
- var bb = await entityToWrap.getBoundingBox();
1001
- var targetSize = 1;
1002
- var scale = targetSize / Math.max(bb.extents.x, bb.extents.y, bb.extents.z);
1003
- entityToWrap.transform.scale.x = scale;
1004
- entityToWrap.transform.scale.y = scale;
1005
- entityToWrap.transform.scale.z = scale;
1006
- entityToWrap.transform.position.x = -bb.center.x * scale;
1007
- entityToWrap.transform.position.y = -bb.center.y * scale;
1008
- entityToWrap.transform.position.z = -bb.center.z * scale;
1009
- await entityToWrap.updateTransform();
1010
- var boudningEntity = await _SpatialHelper.instance?.session.createEntity();
1011
- await entityToWrap.setParent(boudningEntity);
1012
- return boudningEntity;
1733
+ }
1734
+ async removeEvent(eventName) {
1735
+ if (this.events[eventName]) {
1736
+ delete this.events[eventName];
1737
+ try {
1738
+ await this.updateEntityEvent(eventName, false);
1739
+ } catch (error) {
1740
+ console.error("removeEvent failed", eventName);
1741
+ }
1013
1742
  }
1014
- };
1015
- navigation = {
1016
- openPanel: async (url, options) => {
1017
- if (options?.resolution) {
1018
- await this.session.getCurrentWindowContainer()._setOpenSettings({ resolution: options.resolution });
1019
- }
1020
- var wg = await this.session.createWindowContainer({
1021
- style: "Plain",
1022
- windowComponent: null,
1023
- windowContainer: null
1024
- });
1025
- var ent = await this.session.createEntity({
1026
- windowComponent: null,
1027
- windowContainer: wg
1028
- });
1029
- var i = await this.session.createWindowComponent({
1030
- windowComponent: null,
1031
- windowContainer: wg
1032
- });
1033
- await i.loadURL(url);
1034
- await ent.setCoordinateSpace("Root");
1035
- await ent.setComponent(i);
1036
- await wg.setRootEntity(ent);
1037
- await this.session.getCurrentWindowContainer()._setOpenSettings({ resolution: { width: 900, height: 700 } });
1038
- return {
1039
- windowContainer: wg
1040
- };
1041
- },
1042
- openVolume: async (url, options) => {
1043
- var wg = await this.session.createWindowContainer({
1044
- style: "Volumetric",
1045
- windowComponent: null,
1046
- windowContainer: null
1047
- });
1048
- var rootEnt = await this.session.createEntity({
1049
- windowComponent: null,
1050
- windowContainer: wg
1051
- });
1052
- await rootEnt.setComponent(
1053
- await this.session.createViewComponent({
1054
- windowComponent: null,
1055
- windowContainer: wg
1056
- })
1743
+ }
1744
+ async updateEntityEvent(eventName, isEnable) {
1745
+ return new UpdateEntityEventCommand(this, eventName, isEnable).execute();
1746
+ }
1747
+ onReceiveEvent = (data) => {
1748
+ const { type } = data;
1749
+ if (type === "objectdestroy" /* objectdestroy */) {
1750
+ this.isDestroyed = true;
1751
+ } else if (type === "spatialtap" /* spatialtap */) {
1752
+ const evt = createSpatialEvent(
1753
+ "spatialtap" /* spatialtap */,
1754
+ data.detail
1057
1755
  );
1058
- await rootEnt.setCoordinateSpace("Root");
1059
- await wg.setRootEntity(rootEnt);
1060
- var ent = await this.session.createEntity({
1061
- windowComponent: null,
1062
- windowContainer: wg
1063
- });
1064
- var i = await this.session.createWindowComponent({
1065
- windowComponent: null,
1066
- windowContainer: wg
1067
- });
1068
- await i.loadURL(url);
1069
- if (options?.resolution) {
1070
- await i.setResolution(
1071
- options.resolution.width,
1072
- options.resolution.height
1073
- );
1074
- } else {
1075
- await i.setResolution(1e3, 1e3);
1076
- }
1077
- ent.transform.position.z = -0.49;
1078
- await ent.updateTransform();
1079
- await ent.setCoordinateSpace("App");
1080
- await ent.setComponent(i);
1081
- await ent.setParent(rootEnt);
1756
+ this.dispatchEvent(evt);
1757
+ } else if (type === "spatialdragstart" /* spatialdragstart */) {
1758
+ const evt = createSpatialEvent(
1759
+ "spatialdragstart" /* spatialdragstart */,
1760
+ data.detail
1761
+ );
1762
+ this.dispatchEvent(evt);
1763
+ } else if (type === "spatialdrag" /* spatialdrag */) {
1764
+ const evt = createSpatialEvent(
1765
+ "spatialdrag" /* spatialdrag */,
1766
+ data.detail
1767
+ );
1768
+ this.dispatchEvent(evt);
1769
+ } else if (type === "spatialdragend" /* spatialdragend */) {
1770
+ const evt = createSpatialEvent(
1771
+ "spatialdragend" /* spatialdragend */,
1772
+ data.detail
1773
+ );
1774
+ this.dispatchEvent(evt);
1775
+ } else if (type === "spatialrotatestart" /* spatialrotatestart */) {
1776
+ const evt = createSpatialEvent(
1777
+ "spatialrotatestart" /* spatialrotatestart */,
1778
+ data.detail
1779
+ );
1780
+ this.dispatchEvent(evt);
1781
+ } else if (type === "spatialrotate" /* spatialrotate */) {
1782
+ const evt = createSpatialEvent(
1783
+ "spatialrotate" /* spatialrotate */,
1784
+ data.detail
1785
+ );
1786
+ this.dispatchEvent(evt);
1787
+ } else if (type === "spatialrotateend" /* spatialrotateend */) {
1788
+ const evt = createSpatialEvent(
1789
+ "spatialrotateend" /* spatialrotateend */,
1790
+ data.detail
1791
+ );
1792
+ this.dispatchEvent(evt);
1793
+ } else if (type === "spatialmagnifystart" /* spatialmagnifystart */) {
1794
+ const evt = createSpatialEvent(
1795
+ "spatialmagnifystart" /* spatialmagnifystart */,
1796
+ data.detail
1797
+ );
1798
+ this.dispatchEvent(evt);
1799
+ } else if (type === "spatialmagnify" /* spatialmagnify */) {
1800
+ const evt = createSpatialEvent(
1801
+ "spatialmagnify" /* spatialmagnify */,
1802
+ data.detail
1803
+ );
1804
+ this.dispatchEvent(evt);
1805
+ } else if (type === "spatialmagnifyend" /* spatialmagnifyend */) {
1806
+ const evt = createSpatialEvent(
1807
+ "spatialmagnifyend" /* spatialmagnifyend */,
1808
+ data.detail
1809
+ );
1810
+ this.dispatchEvent(evt);
1082
1811
  }
1083
1812
  };
1084
- dom = {
1085
- attachSpatialView: async (divOnPage) => {
1086
- var viewEnt = await this.session.createEntity();
1087
- await viewEnt.setCoordinateSpace("Dom");
1088
- await viewEnt.setComponent(await this.session.createViewComponent());
1089
- var wc = await this.session.getCurrentWindowComponent();
1090
- var ent = await wc.getEntity();
1091
- await viewEnt.setParent(ent);
1092
- var update = () => {
1093
- var rect = divOnPage.getBoundingClientRect();
1094
- viewEnt.transform.position.x = rect.x + rect.width / 2;
1095
- viewEnt.transform.position.y = rect.y + rect.height / 2 + window.scrollY;
1096
- viewEnt.updateTransform();
1097
- viewEnt.getComponent(SpatialViewComponent).setResolution(rect.width, rect.height);
1098
- };
1099
- var mo = new MutationObserver(update);
1100
- mo.observe(divOnPage, { attributes: true });
1101
- var ro = new ResizeObserver(update);
1102
- ro.observe(divOnPage);
1103
- const addRemoveObserver = new MutationObserver((mutations) => {
1104
- mutations.forEach((mutation) => {
1105
- mutation.removedNodes.forEach((node) => {
1106
- if (node instanceof HTMLElement) {
1107
- update();
1108
- }
1109
- });
1110
- mutation.addedNodes.forEach((node) => {
1111
- if (node instanceof HTMLElement) {
1112
- update();
1113
- }
1114
- });
1115
- });
1116
- });
1117
- addRemoveObserver.observe(document.body, {
1118
- childList: true,
1119
- subtree: true
1120
- });
1121
- update();
1122
- return {
1123
- entity: viewEnt
1124
- };
1813
+ dispatchEvent(evt) {
1814
+ this.events[evt.type]?.(evt);
1815
+ if (evt.bubbles && !evt.cancelBubble) {
1816
+ if (this.parent && this.parent instanceof _SpatialEntity) {
1817
+ this.parent.dispatchEvent(evt);
1818
+ }
1125
1819
  }
1126
- };
1127
- setBackgroundStyle = async (style, backgroundColor = "#00000000") => {
1128
- document.documentElement.style.backgroundColor = backgroundColor;
1129
- await this.session.getCurrentWindowComponent().setStyle(style);
1130
- };
1131
- };
1132
-
1133
- // src/core/component/SpatialWindowComponent.ts
1134
- var SpatialWindowComponent = class extends SpatialComponent {
1135
- /**
1136
- * Loads a url page in the window
1137
- * @param url url to load
1138
- */
1139
- async loadURL(url) {
1140
- await WebSpatial.updateResource(this._resource, { url });
1141
- }
1142
- async setFromWindow(window2) {
1143
- if (window2._webSpatialID) {
1144
- await WebSpatial.updateResource(this._resource, {
1145
- windowID: window2._webSpatialID
1146
- });
1147
- } else {
1148
- await console.warn(
1149
- "failed to call setFromWindow, window provided is not valid"
1820
+ }
1821
+ onDestroy() {
1822
+ SpatialWebEvent.removeEventReceiver(this.id);
1823
+ this.children.forEach((child) => {
1824
+ child.parent = null;
1825
+ });
1826
+ this.children = [];
1827
+ if (this.parent) {
1828
+ this.parent.children = this.parent.children.filter(
1829
+ (child) => child.id !== this.id
1150
1830
  );
1831
+ this.parent = null;
1151
1832
  }
1152
1833
  }
1153
- /**
1154
- * Sets the resolution of the window, the resulting dimensions when rendered will be equal to 1/1360 units
1155
- * eg. if the resolution is set to 1360x1360 it will be a 1x1 plane
1156
- * See 1360 in spatialViewUI.swift for how this ratio works
1157
- * @param width width in pixels
1158
- * @param height height in pixels
1159
- */
1160
- async setResolution(width, height) {
1161
- await WebSpatial.updateResource(this._resource, {
1162
- resolution: { x: width, y: height }
1163
- });
1834
+ // onUpdate(properties: SpatialEntityProperties) {
1835
+ // this.position = properties.position
1836
+ // this.rotation = properties.rotation
1837
+ // this.scale = properties.scale
1838
+ // }
1839
+ async convertFromEntityToEntity(fromEntityId, toEntityId, position) {
1840
+ return new ConvertFromEntityToEntityCommand(
1841
+ fromEntityId,
1842
+ toEntityId,
1843
+ position
1844
+ ).execute();
1164
1845
  }
1165
- /**
1166
- * [Experimental] Sets the anchor which the entity this is attached to will rotate around
1167
- * @param rotationAnchor
1168
- */
1169
- async setRotationAnchor(rotationAnchor) {
1170
- await WebSpatial.updateResource(this._resource, {
1171
- rotationAnchor
1172
- });
1846
+ async convertFromEntityToScene(fromEntityId, position) {
1847
+ return new ConvertFromEntityToSceneCommand(fromEntityId, position).execute();
1173
1848
  }
1174
- /**
1175
- * [Experimental] Sets the opacity of the window after apply material
1176
- * @param opacity
1177
- */
1178
- async setOpacity(opacity) {
1179
- await WebSpatial.updateResource(this._resource, {
1180
- opacity
1181
- });
1849
+ async convertFromSceneToEntity(entityId, position) {
1850
+ return new ConvertFromSceneToEntityCommand(entityId, position).execute();
1182
1851
  }
1183
- /**
1184
- * Sets the style that should be applied to the window
1185
- * @param options style options
1186
- */
1187
- async setStyle(styleParam) {
1188
- const currentWindowComponent = SpatialHelper.instance?.session.getCurrentWindowComponent();
1189
- const isSettingSelfStyle = currentWindowComponent?._resource.id == this._resource.id;
1190
- const { material, cornerRadius } = styleParam;
1191
- const options = {};
1192
- if (material?.type) {
1193
- options.backgroundMaterial = material.type;
1194
- }
1195
- if (cornerRadius !== void 0) {
1196
- if (typeof cornerRadius === "number") {
1197
- options.cornerRadius = {
1198
- topLeading: cornerRadius,
1199
- bottomLeading: cornerRadius,
1200
- topTrailing: cornerRadius,
1201
- bottomTrailing: cornerRadius
1202
- };
1203
- } else {
1204
- options.cornerRadius = { ...cornerRadius };
1205
- }
1206
- }
1207
- if (isSettingSelfStyle && document && document.readyState == "loading") {
1208
- var encoded = encodeURIComponent(JSON.stringify(options));
1209
- const a = document.createElement(`a`);
1210
- a.href = "forcestyle://mystyle.css?style=" + encoded;
1211
- document.body.appendChild(a);
1212
- a.click();
1213
- a.remove();
1214
- } else {
1215
- await WebSpatial.updateResource(this._resource, { style: options });
1852
+ };
1853
+
1854
+ // src/reality/entity/SpatialModelEntity.ts
1855
+ var SpatialModelEntity = class extends SpatialEntity {
1856
+ constructor(id, options, userData) {
1857
+ super(id, userData);
1858
+ this.id = id;
1859
+ this.options = options;
1860
+ this.userData = userData;
1861
+ }
1862
+ };
1863
+
1864
+ // src/reality/component/SpatialComponent.ts
1865
+ init_SpatialWebEvent();
1866
+ var SpatialComponent = class extends SpatialObject {
1867
+ constructor(id) {
1868
+ super(id);
1869
+ SpatialWebEvent.addEventReceiver(id, this.onReceiveEvent);
1870
+ }
1871
+ onReceiveEvent = (data) => {
1872
+ const { type } = data;
1873
+ if (type === "objectdestroy" /* objectdestroy */) {
1874
+ this.isDestroyed = true;
1216
1875
  }
1876
+ };
1877
+ };
1878
+
1879
+ // src/reality/component/ModelComponent.ts
1880
+ var ModelComponent = class extends SpatialComponent {
1881
+ constructor(id, options) {
1882
+ super(id);
1883
+ this.options = options;
1217
1884
  }
1218
- /**
1219
- * Modifies the amount the spatial window can be scrolled
1220
- * Should only be used internally
1221
- * See https://developer.apple.com/documentation/uikit/1624475-uiedgeinsetsmake?language=objc
1222
- * @param insets margin to modify scroll distances by
1223
- */
1224
- async setScrollEdgeInsets(insets) {
1225
- await WebSpatial.updateResource(this._resource, {
1226
- setScrollEdgeInsets: insets
1227
- });
1885
+ };
1886
+
1887
+ // src/reality/material/SpatialUnlitMaterial.ts
1888
+ init_JSBCommand();
1889
+
1890
+ // src/reality/material/SpatialMaterial.ts
1891
+ var SpatialMaterial = class extends SpatialObject {
1892
+ constructor(id, type) {
1893
+ super(id);
1894
+ this.id = id;
1895
+ this.type = type;
1896
+ this.type = type;
1228
1897
  }
1229
- /**
1230
- * Enable/Disable scrolling in the window (defaults to enabled), if disabled, scrolling will be applied to the root page
1231
- * @param enabled value to set
1232
- */
1233
- async setScrollEnabled(enabled) {
1234
- await WebSpatial.updateResource(this._resource, { scrollEnabled: enabled });
1898
+ };
1899
+
1900
+ // src/reality/material/SpatialUnlitMaterial.ts
1901
+ var SpatialUnlitMaterial = class extends SpatialMaterial {
1902
+ constructor(id, options) {
1903
+ super(id, "unlit");
1904
+ this.id = id;
1905
+ this.options = options;
1235
1906
  }
1236
- /**
1237
- * Defaults to false. If set to true, scrolling the parent page will also scroll this window with it like other dom elements
1238
- * @param scrollWithParent value to set
1239
- */
1240
- async setScrollWithParent(scrollWithParent) {
1241
- await WebSpatial.updateResource(this._resource, {
1242
- scrollWithParent
1243
- });
1907
+ updateProperties(properties) {
1908
+ return new UpdateUnlitMaterialProperties(this, properties).execute();
1244
1909
  }
1245
1910
  };
1246
1911
 
1247
- // src/core/component/EventSpatialComponent.ts
1248
- var EventSpatialComponent = class extends SpatialComponent {
1249
- // Class implementation goes here
1250
- constructor(_resource) {
1251
- super(_resource);
1252
- WebSpatial.registerEventReceiver(_resource.id, (data) => {
1253
- this.onRecvEvent(data);
1254
- });
1255
- }
1256
- async onDestroy() {
1257
- WebSpatial.unregisterEventReceiver(this._resource.id);
1912
+ // src/reality/resource/SpatialModelAsset.ts
1913
+ var SpatialModelAsset = class extends SpatialObject {
1914
+ constructor(id, options) {
1915
+ super(id);
1916
+ this.id = id;
1917
+ this.options = options;
1258
1918
  }
1259
1919
  };
1260
1920
 
1261
- // src/core/component/SpatialInputComponent.ts
1262
- var SpatialInputComponent = class extends EventSpatialComponent {
1263
- onRecvEvent(data) {
1264
- this.onTranslate(data);
1921
+ // src/reality/realityCreator.ts
1922
+ async function createSpatialEntity(userData) {
1923
+ const result = await new CreateSpatialEntityCommand(userData?.name).execute();
1924
+ if (!result.success) {
1925
+ throw new Error("createSpatialEntity failed:" + result?.errorMessage);
1926
+ } else {
1927
+ const { id } = result.data;
1928
+ return new SpatialEntity(id, userData);
1265
1929
  }
1266
- /**
1267
- * Callback fired when a translate event occurs
1268
- * @param data translate event data
1269
- */
1270
- onTranslate(data) {
1930
+ }
1931
+ async function createSpatialGeometry(ctor, options) {
1932
+ const result = await new CreateSpatialGeometryCommand(
1933
+ ctor.type,
1934
+ options
1935
+ ).execute();
1936
+ if (!result.success) {
1937
+ throw new Error("createSpatialGeometry failed:" + result?.errorMessage);
1938
+ } else {
1939
+ const { id } = result.data;
1940
+ return new ctor(id, options);
1941
+ }
1942
+ }
1943
+ async function createSpatialUnlitMaterial(options) {
1944
+ const result = await new CreateSpatialUnlitMaterialCommand(options).execute();
1945
+ if (!result.success) {
1946
+ throw new Error("createSpatialUnlitMaterial failed:" + result?.errorMessage);
1947
+ } else {
1948
+ const { id } = result.data;
1949
+ return new SpatialUnlitMaterial(id, options);
1950
+ }
1951
+ }
1952
+ async function createModelComponent(options) {
1953
+ const result = await new CreateModelComponentCommand(options).execute();
1954
+ if (!result.success) {
1955
+ throw new Error("createModelComponent failed:" + result?.errorMessage);
1956
+ } else {
1957
+ const { id } = result.data;
1958
+ return new ModelComponent(id, options);
1959
+ }
1960
+ }
1961
+ async function createSpatialModelEntity(options, userData) {
1962
+ const result = await new CreateSpatialModelEntityCommand(options).execute();
1963
+ if (!result.success) {
1964
+ throw new Error("createSpatialModelEntity failed:" + result?.errorMessage);
1965
+ } else {
1966
+ const { id } = result.data;
1967
+ return new SpatialModelEntity(id, options, userData);
1271
1968
  }
1969
+ }
1970
+ async function createModelAsset(options) {
1971
+ const result = await new CreateModelAssetCommand(options).execute();
1972
+ if (!result.success) {
1973
+ throw new Error("createModelAsset failed:" + result?.errorMessage);
1974
+ } else {
1975
+ const { id } = result.data;
1976
+ return new SpatialModelAsset(id, options);
1977
+ }
1978
+ }
1979
+
1980
+ // src/reality/geometry/SpatialGeometry.ts
1981
+ var SpatialGeometry = class extends SpatialObject {
1982
+ constructor(id, options) {
1983
+ super(id);
1984
+ this.id = id;
1985
+ this.options = options;
1986
+ }
1987
+ static type;
1988
+ };
1989
+
1990
+ // src/reality/geometry/SpatialBoxGeometry.ts
1991
+ var SpatialBoxGeometry = class extends SpatialGeometry {
1992
+ constructor(id, options) {
1993
+ super(id, options);
1994
+ this.id = id;
1995
+ this.options = options;
1996
+ }
1997
+ static type = "BoxGeometry";
1998
+ };
1999
+
2000
+ // src/reality/geometry/SpatialSphereGeometry.ts
2001
+ var SpatialSphereGeometry = class extends SpatialGeometry {
2002
+ constructor(id, options) {
2003
+ super(id, options);
2004
+ this.id = id;
2005
+ this.options = options;
2006
+ }
2007
+ static type = "SphereGeometry";
1272
2008
  };
1273
2009
 
1274
- // src/core/component/SpatialModelComponent.ts
1275
- var SpatialModelComponent = class extends SpatialComponent {
1276
- cachedMaterials = new Array();
2010
+ // src/reality/geometry/SpatialCylinderGeometry.ts
2011
+ var SpatialCylinderGeometry = class extends SpatialGeometry {
2012
+ constructor(id, options) {
2013
+ super(id, options);
2014
+ this.id = id;
2015
+ this.options = options;
2016
+ }
2017
+ static type = "CylinderGeometry";
2018
+ };
2019
+
2020
+ // src/reality/geometry/SpatialPlaneGeometry.ts
2021
+ var SpatialPlaneGeometry = class extends SpatialGeometry {
2022
+ constructor(id, options) {
2023
+ super(id, options);
2024
+ this.id = id;
2025
+ this.options = options;
2026
+ }
2027
+ static type = "PlaneGeometry";
2028
+ };
2029
+
2030
+ // src/reality/geometry/SpatialConeGeometry.ts
2031
+ var SpatialConeGeometry = class extends SpatialGeometry {
2032
+ constructor(id, options) {
2033
+ super(id, options);
2034
+ this.id = id;
2035
+ this.options = options;
2036
+ }
2037
+ static type = "ConeGeometry";
2038
+ };
2039
+
2040
+ // src/SpatialSession.ts
2041
+ var SpatialSession = class {
1277
2042
  /**
1278
- * Sets the mesh to be displayed by the component
1279
- * @param mesh mesh to set
2043
+ * Gets the singleton instance of the spatial scene.
2044
+ * The spatial scene is the root container for all spatial elements.
2045
+ * @returns The SpatialScene singleton instance
1280
2046
  */
1281
- async setMesh(mesh) {
1282
- await WebSpatial.updateResource(this._resource, {
1283
- meshResource: mesh._resource.id
1284
- });
2047
+ getSpatialScene() {
2048
+ return SpatialScene.getInstance();
1285
2049
  }
1286
2050
  /**
1287
- * Sets the materials that should be applied to the mesh
1288
- * @param materials array of materials to set
2051
+ * Creates a new 2D element that can be spatialized in the 3D environment.
2052
+ * 2D elements represent HTML content that can be positioned in 3D space.
2053
+ * @returns Promise resolving to a new Spatialized2DElement instance
1289
2054
  */
1290
- async setMaterials(materials) {
1291
- this.cachedMaterials = materials;
1292
- await WebSpatial.updateResource(this._resource, {
1293
- materials: materials.map((m) => {
1294
- m._addToComponent(this);
1295
- return m._resource.id;
1296
- })
1297
- });
2055
+ createSpatialized2DElement() {
2056
+ return createSpatialized2DElement();
1298
2057
  }
1299
- /** @hidden */
1300
- async _syncMaterials() {
1301
- await this.setMaterials(this.cachedMaterials);
1302
- }
1303
- };
1304
-
1305
- // src/core/component/SpatialViewComponent.ts
1306
- var SpatialViewComponent = class extends SpatialComponent {
1307
2058
  /**
1308
- * Sets the resolution of the spatial view in dom pixels
2059
+ * Creates a new static 3D element with an optional model URL.
2060
+ * Static 3D elements represent pre-built 3D models that can be loaded from a URL.
2061
+ * @param modelURL Optional URL to the 3D model to load
2062
+ * @returns Promise resolving to a new SpatializedStatic3DElement instance
1309
2063
  */
1310
- async setResolution(width, height) {
1311
- await WebSpatial.updateResource(this._resource, {
1312
- resolution: { x: width, y: height }
1313
- });
2064
+ createSpatializedStatic3DElement(modelURL = "") {
2065
+ return createSpatializedStatic3DElement(modelURL);
1314
2066
  }
1315
2067
  /**
1316
- * Sets if content of the spatialView should be within a portal
1317
- * If true, volume will be behind the page, if false, it will be in front of the page
2068
+ * Initializes the spatial scene with custom configuration.
2069
+ * This is a reference to the initScene function from scene-polyfill.
1318
2070
  */
1319
- async setIsPortal(isPortal) {
1320
- await WebSpatial.updateResource(this._resource, {
1321
- isPortal
1322
- });
1323
- }
1324
- };
1325
-
1326
- // src/core/component/SpatialModel3DComponent.ts
1327
- var SpatialModel3DComponent = class extends EventSpatialComponent {
1328
- onRecvEvent(data) {
1329
- const { eventType, value, error } = data;
1330
- switch (eventType) {
1331
- case "phase":
1332
- if (value === "success") {
1333
- this.onSuccess?.();
1334
- } else {
1335
- this.onFailure?.(error);
1336
- }
1337
- break;
1338
- case "dragstart":
1339
- this._onDragStart?.(value);
1340
- break;
1341
- case "dragend":
1342
- this._onDragEnd?.(value);
1343
- break;
1344
- case "drag":
1345
- this._onDrag?.(value);
1346
- break;
1347
- case "tap":
1348
- this._onTap?.();
1349
- break;
1350
- case "doubletap":
1351
- this._onDoubleTap?.();
1352
- break;
1353
- case "longpress":
1354
- this._onLongPress?.();
1355
- break;
1356
- default:
1357
- break;
1358
- }
2071
+ initScene = initScene;
2072
+ /**
2073
+ * Creates a new dynamic 3D element that can be manipulated at runtime.
2074
+ * Dynamic 3D elements allow for programmatic creation and modification of 3D content.
2075
+ * @returns Promise resolving to a new SpatializedDynamic3DElement instance
2076
+ */
2077
+ createSpatializedDynamic3DElement() {
2078
+ return createSpatializedDynamic3DElement();
1359
2079
  }
1360
2080
  /**
1361
- * Sets the resolution of the spatial view in dom pixels
2081
+ * Creates a new spatial entity with an optional name.
2082
+ * Entities are the basic building blocks for creating custom 3D content.
2083
+ * @param name Optional name for the entity
2084
+ * @returns Promise resolving to a new SpatialEntity instance
1362
2085
  */
1363
- async setResolution(width, height) {
1364
- await WebSpatial.updateResource(this._resource, {
1365
- resolution: { x: width, y: height }
1366
- });
2086
+ createEntity(userData) {
2087
+ return createSpatialEntity(userData);
1367
2088
  }
1368
- async setRotationAnchor(rotationAnchor) {
1369
- await WebSpatial.updateResource(this._resource, {
1370
- rotationAnchor
1371
- });
2089
+ /**
2090
+ * Creates a box geometry with optional configuration.
2091
+ * @param options Configuration options for the box geometry
2092
+ * @returns Promise resolving to a new SpatialBoxGeometry instance
2093
+ */
2094
+ createBoxGeometry(options = {}) {
2095
+ return createSpatialGeometry(SpatialBoxGeometry, options);
1372
2096
  }
1373
2097
  /**
1374
- * Sets the opacity of the model
1375
- * @param opacity
2098
+ * Creates a plane geometry with optional configuration.
2099
+ * @param options Configuration options for the plane geometry
2100
+ * @returns Promise resolving to a new SpatialPlaneGeometry instance
1376
2101
  */
1377
- async setOpacity(opacity) {
1378
- await WebSpatial.updateResource(this._resource, {
1379
- opacity
1380
- });
2102
+ createPlaneGeometry(options = {}) {
2103
+ return createSpatialGeometry(SpatialPlaneGeometry, options);
1381
2104
  }
1382
2105
  /**
1383
- * Sets how the model fill the rect
1384
- * @param contentMode
2106
+ * Creates a sphere geometry with optional configuration.
2107
+ * @param options Configuration options for the sphere geometry
2108
+ * @returns Promise resolving to a new SpatialSphereGeometry instance
1385
2109
  */
1386
- async setContentMode(contentMode) {
1387
- await WebSpatial.updateResource(this._resource, {
1388
- contentMode
1389
- });
2110
+ createSphereGeometry(options = {}) {
2111
+ return createSpatialGeometry(SpatialSphereGeometry, options);
1390
2112
  }
1391
2113
  /**
1392
- * Constrains this model dimensions to the specified aspect ratio.
1393
- * with a value of 0, the model will use the original aspect ratio.
1394
- *
1395
- * @param aspectRatio number
2114
+ * Creates a cone geometry with the specified configuration.
2115
+ * @param options Configuration options for the cone geometry
2116
+ * @returns Promise resolving to a new SpatialConeGeometry instance
1396
2117
  */
1397
- async setAspectRatio(aspectRatio) {
1398
- await WebSpatial.updateResource(this._resource, {
1399
- aspectRatio
1400
- });
2118
+ createConeGeometry(options) {
2119
+ return createSpatialGeometry(SpatialConeGeometry, options);
1401
2120
  }
1402
2121
  /**
1403
- * Defaults to false. If set to true, scrolling the parent page will also scroll this window with it like other dom elements
1404
- * @param scrollWithParent value to set
2122
+ * Creates a cylinder geometry with the specified configuration.
2123
+ * @param options Configuration options for the cylinder geometry
2124
+ * @returns Promise resolving to a new SpatialCylinderGeometry instance
1405
2125
  */
1406
- async setScrollWithParent(scrollWithParent) {
1407
- await WebSpatial.updateResource(this._resource, {
1408
- scrollWithParent
1409
- });
2126
+ createCylinderGeometry(options) {
2127
+ return createSpatialGeometry(SpatialCylinderGeometry, options);
1410
2128
  }
1411
2129
  /**
1412
- * Sets whether the model appear in original size or fit the rect
1413
- * @param resizable
2130
+ * Creates a model component with the specified configuration.
2131
+ * Model components are used to add 3D model rendering capabilities to entities.
2132
+ * @param options Configuration options for the model component
2133
+ * @returns Promise resolving to a new ModelComponent instance
1414
2134
  */
1415
- async setResizable(resizable) {
1416
- await WebSpatial.updateResource(this._resource, {
1417
- resizable
1418
- });
2135
+ createModelComponent(options) {
2136
+ return createModelComponent(options);
1419
2137
  }
1420
2138
  /**
1421
- * Callback fired when model load success
2139
+ * Creates an unlit material with the specified configuration.
2140
+ * Unlit materials don't respond to lighting in the scene.
2141
+ * @param options Configuration options for the unlit material
2142
+ * @returns Promise resolving to a new SpatialUnlitMaterial instance
1422
2143
  */
1423
- onSuccess;
2144
+ createUnlitMaterial(options) {
2145
+ return createSpatialUnlitMaterial(options);
2146
+ }
1424
2147
  /**
1425
- * Callback fired when model load failure
1426
- * @param errorReason
2148
+ * Creates a model asset with the specified configuration.
2149
+ * Model assets represent 3D model resources that can be used by entities.
2150
+ * @param options Configuration options for the model asset
2151
+ * @returns Promise resolving to a new SpatialModelAsset instance
1427
2152
  */
1428
- onFailure;
2153
+ createModelAsset(options) {
2154
+ return createModelAsset(options);
2155
+ }
1429
2156
  /**
1430
- * Callback fired when model was dragged at the beginning
1431
- * @param dragEvent
2157
+ * Creates a spatial model entity with the specified configuration.
2158
+ * This is a convenience method for creating an entity with a model component.
2159
+ * @param options Configuration options for the spatial model entity
2160
+ * @returns Promise resolving to a new SpatialModelEntity instance
1432
2161
  */
1433
- _onDragStart;
1434
- set onDragStart(callback) {
1435
- if (this._onDragStart !== callback) {
1436
- this._onDragStart = callback;
1437
- WebSpatial.updateResource(this._resource, {
1438
- enableDragEvent: this.enableDragEvent
1439
- });
1440
- }
2162
+ createSpatialModelEntity(options, userData) {
2163
+ return createSpatialModelEntity(options, userData);
1441
2164
  }
2165
+ };
2166
+
2167
+ // src/Spatial.ts
2168
+ init_SpatialWebEvent();
2169
+ var Spatial = class {
1442
2170
  /**
1443
- * Callback fired when model was dragged
1444
- * @param dragEvent
2171
+ * Requests a spatial session object from the browser.
2172
+ * This is the primary method to initialize spatial functionality.
2173
+ * @returns The SpatialSession instance or null if not available in the current browser
2174
+ * [TODO] discuss implications of this not being async
1445
2175
  */
1446
- _onDrag;
1447
- set onDrag(callback) {
1448
- if (this._onDrag !== callback) {
1449
- this._onDrag = callback;
1450
- WebSpatial.updateResource(this._resource, {
1451
- enableDragEvent: this.enableDragEvent
1452
- });
2176
+ requestSession() {
2177
+ if (this.runInSpatialWeb()) {
2178
+ SpatialWebEvent.init();
2179
+ return new SpatialSession();
2180
+ } else {
2181
+ return null;
1453
2182
  }
1454
2183
  }
1455
2184
  /**
1456
- * Callback fired when model was dragged at the ending
1457
- * @param dragEvent
2185
+ * Checks if the current page is running in a spatial web environment.
2186
+ * This method detects if the application is running in a WebSpatial-compatible browser.
2187
+ * @returns True if running in a spatial web environment, false otherwise
1458
2188
  */
1459
- _onDragEnd;
1460
- set onDragEnd(callback) {
1461
- if (this._onDragEnd !== callback) {
1462
- this._onDragEnd = callback;
1463
- WebSpatial.updateResource(this._resource, {
1464
- enableDragEvent: this.enableDragEvent
1465
- });
2189
+ runInSpatialWeb() {
2190
+ if (navigator.userAgent.indexOf("WebSpatial/") > 0) {
2191
+ return true;
1466
2192
  }
2193
+ return false;
1467
2194
  }
1468
- get enableDragEvent() {
1469
- return void 0 !== this._onDrag || void 0 !== this._onDragStart || void 0 !== this._onDragEnd;
2195
+ /** @deprecated
2196
+ * Checks if WebSpatial is supported in the current environment.
2197
+ * Verifies compatibility between native and client versions.
2198
+ * @returns True if web spatial is supported by this webpage
2199
+ */
2200
+ isSupported() {
2201
+ return true;
1470
2202
  }
1471
- /**
1472
- * Callback fired when model was tapped
2203
+ /** @deprecated
2204
+ * Gets the native WebSpatial version from the browser environment.
2205
+ * The version format follows semantic versioning (x.x.x).
2206
+ * @returns Native version string in format "x.x.x"
1473
2207
  */
1474
- _onTap;
1475
- set onTap(callback) {
1476
- if (this._onTap !== callback) {
1477
- this._onTap = callback;
1478
- WebSpatial.updateResource(this._resource, {
1479
- enableTapEvent: void 0 !== callback
1480
- });
2208
+ getNativeVersion() {
2209
+ if (window.__WebSpatialData && window.__WebSpatialData.getNativeVersion) {
2210
+ return window.__WebSpatialData.getNativeVersion();
1481
2211
  }
2212
+ return window.WebSpatailNativeVersion === "PACKAGE_VERSION" ? this.getClientVersion() : window.WebSpatailNativeVersion;
1482
2213
  }
1483
- /** Callback fired when model was double tapped */
1484
- _onDoubleTap;
1485
- set onDoubleTap(callback) {
1486
- if (this._onDoubleTap !== callback) {
1487
- this._onDoubleTap = callback;
1488
- WebSpatial.updateResource(this._resource, {
1489
- enableDoubleTapEvent: void 0 !== callback
1490
- });
1491
- }
2214
+ /** @deprecated
2215
+ * Gets the client SDK version.
2216
+ * The version format follows semantic versioning (x.x.x).
2217
+ * @returns Client SDK version string in format "x.x.x"
2218
+ */
2219
+ getClientVersion() {
2220
+ return "1.0.5";
1492
2221
  }
1493
- /** Callback fired when model was long pressed */
1494
- _onLongPress;
1495
- set onLongPress(callback) {
1496
- if (this._onLongPress !== callback) {
1497
- this._onLongPress = callback;
1498
- WebSpatial.updateResource(this._resource, {
1499
- enableLongPressEvent: void 0 !== callback
1500
- });
1501
- }
2222
+ };
2223
+
2224
+ // src/index.ts
2225
+ init_ssr_polyfill();
2226
+
2227
+ // src/spatial-window-polyfill.ts
2228
+ init_utils();
2229
+ var spatial = new Spatial();
2230
+ var session = void 0;
2231
+ var SpatialGlobalCustomVars = {
2232
+ backgroundMaterial: "--xr-background-material"
2233
+ };
2234
+ var htmlBackgroundMaterial = "";
2235
+ function setCurrentWindowStyle(backgroundMaterial) {
2236
+ if (backgroundMaterial !== htmlBackgroundMaterial) {
2237
+ session?.getSpatialScene()?.updateSpatialProperties({
2238
+ material: backgroundMaterial
2239
+ });
2240
+ htmlBackgroundMaterial = backgroundMaterial;
1502
2241
  }
2242
+ }
2243
+ function checkHtmlBackgroundMaterial() {
2244
+ const computedStyle = getComputedStyle(document.documentElement);
2245
+ const backgroundMaterial = computedStyle.getPropertyValue(
2246
+ SpatialGlobalCustomVars.backgroundMaterial
2247
+ );
2248
+ setCurrentWindowStyle(backgroundMaterial || "none");
2249
+ }
2250
+ var htmlCornerRadius = {
2251
+ topLeading: 0,
2252
+ bottomLeading: 0,
2253
+ topTrailing: 0,
2254
+ bottomTrailing: 0
1503
2255
  };
2256
+ function checkCornerRadius() {
2257
+ const computedStyle = getComputedStyle(document.documentElement);
2258
+ const cornerRadius = parseCornerRadius(computedStyle);
2259
+ setCornerRadius(cornerRadius);
2260
+ }
2261
+ function setCornerRadius(cornerRadius) {
2262
+ if (htmlCornerRadius.topLeading !== cornerRadius.topLeading || htmlCornerRadius.bottomLeading !== cornerRadius.bottomLeading || htmlCornerRadius.topTrailing !== cornerRadius.topTrailing || htmlCornerRadius.bottomTrailing !== cornerRadius.bottomTrailing) {
2263
+ session?.getSpatialScene()?.updateSpatialProperties({
2264
+ cornerRadius
2265
+ });
2266
+ htmlCornerRadius.topLeading = cornerRadius.topLeading;
2267
+ htmlCornerRadius.bottomLeading = cornerRadius.bottomLeading;
2268
+ htmlCornerRadius.topTrailing = cornerRadius.topTrailing;
2269
+ htmlCornerRadius.bottomTrailing = cornerRadius.bottomTrailing;
2270
+ }
2271
+ }
2272
+ function setOpacity(opacity) {
2273
+ session?.getSpatialScene().updateSpatialProperties({
2274
+ opacity
2275
+ });
2276
+ }
2277
+ function checkOpacity() {
2278
+ const computedStyle = getComputedStyle(document.documentElement);
2279
+ const opacity = parseFloat(computedStyle.getPropertyValue("opacity"));
2280
+ setOpacity(opacity);
2281
+ }
2282
+ function hijackDocumentElementStyle() {
2283
+ const rawDocumentStyle = document.documentElement.style;
2284
+ const styleProxy = new Proxy(rawDocumentStyle, {
2285
+ set: function(target, key, value) {
2286
+ const ret = Reflect.set(target, key, value);
2287
+ if (key === SpatialGlobalCustomVars.backgroundMaterial) {
2288
+ setCurrentWindowStyle(value);
2289
+ }
2290
+ if (key === "border-radius" || key === "borderRadius" || key === "border-top-left-radius" || key === "borderTopLeftRadius" || key === "border-top-right-radius" || key === "borderTopRightRadius" || key === "border-bottom-left-radius" || key === "borderBottomLeftRadius" || key === "border-bottom-right-radius" || key === "borderBottomRightRadius") {
2291
+ checkCornerRadius();
2292
+ }
2293
+ if (key === "opacity") {
2294
+ checkOpacity();
2295
+ }
2296
+ return ret;
2297
+ },
2298
+ get: function(target, prop) {
2299
+ if (typeof target[prop] === "function") {
2300
+ return function(...args) {
2301
+ if (prop === "setProperty") {
2302
+ const [property, value] = args;
2303
+ if (property === SpatialGlobalCustomVars.backgroundMaterial) {
2304
+ setCurrentWindowStyle(value);
2305
+ }
2306
+ } else if (prop === "removeProperty") {
2307
+ const [property] = args;
2308
+ if (property === SpatialGlobalCustomVars.backgroundMaterial) {
2309
+ setCurrentWindowStyle("none");
2310
+ }
2311
+ }
2312
+ return target[prop](
2313
+ ...args
2314
+ );
2315
+ };
2316
+ }
2317
+ return Reflect.get(target, prop);
2318
+ }
2319
+ });
2320
+ Object.defineProperty(document.documentElement, "style", {
2321
+ get: function() {
2322
+ return styleProxy;
2323
+ }
2324
+ });
2325
+ }
2326
+ function monitorExternalStyleChange() {
2327
+ const headObserver = new MutationObserver(checkCSSProperties);
2328
+ headObserver.observe(document.head, { childList: true, subtree: true });
2329
+ }
2330
+ function checkCSSProperties() {
2331
+ checkHtmlBackgroundMaterial();
2332
+ checkCornerRadius();
2333
+ checkOpacity();
2334
+ }
2335
+ function monitorHTMLAttributeChange() {
2336
+ const observer = new MutationObserver((mutations) => {
2337
+ mutations.forEach((mutation) => {
2338
+ if (mutation.type === "attributes" && mutation.attributeName) {
2339
+ checkCSSProperties();
2340
+ }
2341
+ });
2342
+ });
2343
+ observer.observe(document.documentElement, {
2344
+ attributes: true,
2345
+ attributeFilter: ["style", "class"]
2346
+ });
2347
+ }
2348
+ async function spatialWindowPolyfill() {
2349
+ if (!spatial.runInSpatialWeb()) {
2350
+ return;
2351
+ }
2352
+ session = await spatial.requestSession();
2353
+ if (document.readyState === "complete") {
2354
+ checkCSSProperties();
2355
+ } else {
2356
+ window.addEventListener("load", () => {
2357
+ checkCSSProperties();
2358
+ });
2359
+ }
2360
+ hijackDocumentElementStyle();
2361
+ monitorExternalStyleChange();
2362
+ monitorHTMLAttributeChange();
2363
+ }
2364
+
2365
+ // src/index.ts
2366
+ if (!isSSREnv() && navigator.userAgent.indexOf("WebSpatial/") > 0) {
2367
+ injectSceneHook();
2368
+ spatialWindowPolyfill();
2369
+ }
1504
2370
  export {
2371
+ BaseplateVisibilityValues,
2372
+ CubeInfo,
2373
+ ModelComponent,
1505
2374
  Spatial,
2375
+ SpatialBoxGeometry,
1506
2376
  SpatialComponent,
2377
+ SpatialConeGeometry,
2378
+ SpatialCylinderGeometry,
1507
2379
  SpatialEntity,
1508
- SpatialHelper,
1509
- SpatialInputComponent,
1510
- SpatialMeshResource,
1511
- SpatialModel3DComponent,
1512
- SpatialModelComponent,
1513
- SpatialPhysicallyBasedMaterialResource,
2380
+ SpatialGeometry,
2381
+ SpatialMaterial,
2382
+ SpatialModelAsset,
2383
+ SpatialModelEntity,
2384
+ SpatialObject,
2385
+ SpatialPlaneGeometry,
2386
+ SpatialScene,
2387
+ SpatialSceneState,
2388
+ SpatialSceneValues,
1514
2389
  SpatialSession,
1515
- SpatialTransform,
1516
- SpatialViewComponent,
1517
- SpatialWindowComponent,
1518
- SpatialWindowContainer,
1519
- Vec3,
1520
- Vec4
2390
+ SpatialSphereGeometry,
2391
+ SpatialUnlitMaterial,
2392
+ Spatialized2DElement,
2393
+ SpatializedDynamic3DElement,
2394
+ SpatializedElement,
2395
+ SpatializedElementType,
2396
+ SpatializedStatic3DElement,
2397
+ WorldAlignmentValues,
2398
+ WorldScalingValues,
2399
+ isSSREnv,
2400
+ isValidBaseplateVisibilityType,
2401
+ isValidSceneUnit,
2402
+ isValidSpatialSceneType,
2403
+ isValidWorldAlignmentType,
2404
+ isValidWorldScalingType
1521
2405
  };
1522
2406
  //# sourceMappingURL=index.js.map