@webspatial/platform-visionos 1.0.3 → 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 (74) hide show
  1. package/package.json +2 -2
  2. package/web-spatial/EventEmitter.swift +56 -0
  3. package/web-spatial/JSBCommand.swift +348 -0
  4. package/web-spatial/SpatialObject.swift +108 -0
  5. package/web-spatial/WebMsgCommand.swift +119 -0
  6. package/web-spatial/WebSpatialApp.swift +111 -0
  7. package/web-spatial/{libs/uiKitDelegate/Window.swift → Window.swift} +1 -0
  8. package/web-spatial/manager/Dynamic3DManager.swift +114 -0
  9. package/web-spatial/manager/JSBManager.swift +148 -0
  10. package/web-spatial/manager/WKWebViewManager.swift +39 -0
  11. package/web-spatial/{libs/webView/manifest.swift → manifest.swift} +16 -5
  12. package/web-spatial/model/SpatialApp.swift +190 -0
  13. package/web-spatial/model/SpatialScene.swift +1042 -0
  14. package/web-spatial/model/Spatialized2DElement.swift +128 -0
  15. package/web-spatial/model/SpatializedDynamic3DElement.swift +34 -0
  16. package/web-spatial/model/SpatializedElement.swift +95 -0
  17. package/web-spatial/model/SpatializedStatic3DElement.swift +19 -0
  18. package/web-spatial/model/dynamic3d/Geometry.swift +95 -0
  19. package/web-spatial/model/dynamic3d/SpatialComponent.swift +72 -0
  20. package/web-spatial/model/dynamic3d/SpatialEntity.swift +211 -0
  21. package/web-spatial/model/dynamic3d/SpatialMaterial.swift +39 -0
  22. package/web-spatial/model/dynamic3d/SpatialModelEntity.swift +39 -0
  23. package/web-spatial/model/dynamic3d/SpatialModelResource.swift +38 -0
  24. package/web-spatial/model/dynamic3d/SpatialTextureResource.swift +18 -0
  25. package/web-spatial/protocol/ScrollAbleSpatialElementContainer.swift +1 -0
  26. package/web-spatial/protocol/SpatialScrollAble.swift +8 -0
  27. package/web-spatial/protocol/SpatializedElementContainer.swift +8 -0
  28. package/web-spatial/protocol/WebMsgSender.swift +5 -0
  29. package/web-spatial/types/Vec2.swift +12 -0
  30. package/web-spatial/types/Vec3.swift +7 -0
  31. package/web-spatial/view/SceneHandlerUIView.swift +92 -0
  32. package/web-spatial/{views/ui/NavView.swift → view/SpatialNavView.swift} +149 -77
  33. package/web-spatial/view/SpatialSceneContentView.swift +218 -0
  34. package/web-spatial/view/SpatialSceneView.swift +53 -0
  35. package/web-spatial/view/Spatialized2DElementView.swift +96 -0
  36. package/web-spatial/view/SpatializedDynamic3DView.swift +104 -0
  37. package/web-spatial/view/SpatializedElementView.swift +178 -0
  38. package/web-spatial/view/SpatializedStatic3DView.swift +70 -0
  39. package/web-spatial/{views → view/view-modifier}/MaterialWithBorderCornerModifier.swift +28 -8
  40. package/web-spatial/webview/SpatialWebController.swift +300 -0
  41. package/web-spatial/webview/SpatialWebView.swift +34 -0
  42. package/web-spatial/webview/SpatialWebViewModel.swift +307 -0
  43. package/web-spatial.xcodeproj/project.pbxproj +126 -207
  44. package/web-spatial/libs/EventEmitter.swift +0 -25
  45. package/web-spatial/libs/SpatialComponent.swift +0 -24
  46. package/web-spatial/libs/SpatialEntity.swift +0 -172
  47. package/web-spatial/libs/SpatialInputComponent.swift +0 -19
  48. package/web-spatial/libs/SpatialMeshResource.swift +0 -12
  49. package/web-spatial/libs/SpatialModel3DComponent.swift +0 -51
  50. package/web-spatial/libs/SpatialModelComponent.swift +0 -25
  51. package/web-spatial/libs/SpatialObject.swift +0 -140
  52. package/web-spatial/libs/SpatialPhysicallyBasedMaterial.swift +0 -19
  53. package/web-spatial/libs/SpatialViewComponent.swift +0 -8
  54. package/web-spatial/libs/SpatialWindowComponent.swift +0 -454
  55. package/web-spatial/libs/SpatialWindowContainer.swift +0 -153
  56. package/web-spatial/libs/Utils/CommandManager.swift +0 -823
  57. package/web-spatial/libs/Utils/PerfClock.swift +0 -43
  58. package/web-spatial/libs/Utils/SceneManager.swift +0 -101
  59. package/web-spatial/libs/Utils/WindowContainerMgr.swift +0 -122
  60. package/web-spatial/libs/json/JsonParser.swift +0 -45
  61. package/web-spatial/libs/webView/UpdateSystem.swift +0 -26
  62. package/web-spatial/libs/webView/backend/NativeWebView.swift +0 -350
  63. package/web-spatial/views/ImmersiveView.swift +0 -17
  64. package/web-spatial/views/OpenDismissHandlerUI.swift +0 -45
  65. package/web-spatial/views/PlainWindowContainerView.swift +0 -132
  66. package/web-spatial/views/SpatialModel3DView.swift +0 -187
  67. package/web-spatial/views/SpatialViewUI.swift +0 -168
  68. package/web-spatial/views/SpatialWebViewUI.swift +0 -179
  69. package/web-spatial/views/VolumetricWindowContainerView.swift +0 -30
  70. package/web-spatial/web_spatialApp.swift +0 -141
  71. /package/web-spatial/{libs/Utils → Utils}/ColorExtension.swift +0 -0
  72. /package/web-spatial/{libs/Utils → Utils}/Logger.swift +0 -0
  73. /package/web-spatial/{views → view}/LoadingView.swift +0 -0
  74. /package/web-spatial/{views → view/view-modifier}/HideViewModifier.swift +0 -0
@@ -1,823 +0,0 @@
1
- import Foundation
2
- import RealityKit
3
- import SwiftUI
4
-
5
- struct CommandInfo {
6
- var windowContainerID = "notFound"
7
- var entityID = "notFound"
8
- var resourceID = "notFound"
9
- var requestID = -1
10
- var cmd: JSBCommand
11
- }
12
-
13
- class CommandManager {
14
- static let Instance = CommandManager()
15
-
16
- private let decoder = JSONDecoder()
17
- private var commandList: [String: (_ target: SpatialWindowComponent, _ info: CommandInfo) -> Void] = [:]
18
- private init() {
19
- _ = registerCommand(name: "multiCommand", action: multiCommand)
20
- _ = registerCommand(name: "ping", action: ping)
21
- _ = registerCommand(name: "inspect", action: inspect)
22
- _ = registerCommand(name: "getStats", action: getStats)
23
- _ = registerCommand(name: "setComponent", action: setComponent)
24
- _ = registerCommand(name: "removeComponent", action: removeComponent)
25
- _ = registerCommand(name: "createResource", action: createResource)
26
- _ = registerCommand(name: "destroyResource", action: destroyResource)
27
- _ = registerCommand(name: "updateResource", action: updateResource)
28
- _ = registerCommand(name: "createWindowContainer", action: createWindowContainer)
29
- _ = registerCommand(name: "updateWindowContainer", action: updateWindowContainer)
30
- _ = registerCommand(name: "openImmersiveSpace", action: openImmersiveSpace)
31
- _ = registerCommand(name: "dismissImmersiveSpace", action: dismissImmersiveSpace)
32
- _ = registerCommand(name: "log", action: log)
33
- _ = registerCommand(name: "createScene", action: createScene)
34
- _ = registerCommand(name: "setLoading", action: setLoading)
35
- }
36
-
37
- private func getInfo(_ target: SpatialWindowComponent, _ jsb: RawJSBCommand) -> CommandInfo? {
38
- var ret = CommandInfo(cmd: JSBCommand(command: jsb.command, data: jsb.data, requestID: jsb.requestID))
39
- ret.requestID = jsb.requestID
40
- if let windowContainerID = jsb.data?.windowContainerID {
41
- ret.windowContainerID = target.readWindowContainerID(id: windowContainerID)
42
- }
43
- if let entityID = jsb.data?.entityID {
44
- ret.entityID = entityID
45
- }
46
- if let resourceID = jsb.data?.resourceID {
47
- ret.resourceID = resourceID
48
- }
49
- if ret.resourceID == "current" {
50
- ret.resourceID = target.id
51
- }
52
- return ret
53
- }
54
-
55
- private func registerCommand(name: String, action: @escaping (_ target: SpatialWindowComponent, _ info: CommandInfo) -> Void) -> Bool {
56
- if commandList[name] == nil {
57
- commandList[name] = action
58
- return true
59
- }
60
- return false
61
- }
62
-
63
- public func decode(jsonData: String) -> RawJSBCommand {
64
- var jsbCommand = RawJSBCommand(command: "", data: RawJSData(), requestID: 0)
65
- do {
66
- jsbCommand = try decoder.decode(RawJSBCommand.self, from: jsonData.data(using: .utf8)!)
67
- } catch {
68
- logger.error("\(error)")
69
- }
70
- return jsbCommand
71
- }
72
-
73
- public func doCommand(target: SpatialWindowComponent, jsb: RawJSBCommand) {
74
- if let action = commandList[jsb.command] {
75
- if let info = getInfo(target, jsb) {
76
- action(target, info)
77
- }
78
- }
79
- }
80
-
81
- private func multiCommand(target: SpatialWindowComponent, info: CommandInfo) {
82
- for subCommand in info.cmd.data!.commandList! {
83
- doCommand(target: target, jsb: subCommand)
84
- }
85
- target.completeEvent(requestID: info.requestID)
86
- }
87
-
88
- private func ping(target: SpatialWindowComponent, info: CommandInfo) {
89
- target.completeEvent(requestID: info.requestID, data: "{ping: 'Complete'}")
90
- }
91
-
92
- private func inspect(target: SpatialWindowComponent, info: CommandInfo) {
93
- if let spatialObject = SpatialObject.getRefObject(info.resourceID) {
94
- let inspectInfo = spatialObject.inspect()
95
- let isValidJSON = JSONSerialization.isValidJSONObject(inspectInfo)
96
- if isValidJSON {
97
- do {
98
- let jsonData = try JSONSerialization.data(withJSONObject: inspectInfo, options: [])
99
- let jsonString = String(data: jsonData, encoding: .utf8)
100
- target.completeEvent(requestID: info.requestID, data: jsonString ?? "Conver failed")
101
- } catch {
102
- logger.error("Error: \(error.localizedDescription)")
103
- target.completeEvent(requestID: info.requestID, data: """
104
- error: \(error.localizedDescription)
105
- """)
106
- }
107
- } else {
108
- logger.warning("\(inspectInfo)")
109
- }
110
- } else {
111
- logger.warning("Missing spatialObject resource")
112
- return
113
- }
114
- }
115
-
116
- private func getStats(target: SpatialWindowComponent, info: CommandInfo) {
117
- let statsInfo = SpatialObject.stats()
118
- do {
119
- let jsonData = try JSONEncoder().encode(statsInfo)
120
- let jsonString = String(data: jsonData, encoding: .utf8)
121
- target.completeEvent(requestID: info.requestID, data: jsonString ?? "Conver failed")
122
- } catch {
123
- logger.error("Error: \(error.localizedDescription)")
124
- target.completeEvent(requestID: info.requestID, data: """
125
- error: \(error.localizedDescription)
126
- """)
127
- }
128
- }
129
-
130
- private func setComponent(target: SpatialWindowComponent, info: CommandInfo) {
131
- if let component = SpatialObject.get(info.resourceID) as? SpatialComponent,
132
- let entity = SpatialObject.get(info.entityID) as? SpatialEntity
133
- {
134
- entity.addComponent(component)
135
- } else {
136
- logger.warning("missing resource, setComponent not processed")
137
- }
138
- }
139
-
140
- private func removeComponent(target: SpatialWindowComponent, info: CommandInfo) {
141
- if let component = target.getChildSpatialObject(name: info.resourceID) as? SpatialComponent,
142
- let entity = target.getChildSpatialObject(name: info.entityID) as? SpatialEntity
143
- {
144
- entity.removeComponent(component)
145
- } else {
146
- logger.warning("missing resource, removeComponent not processed")
147
- }
148
- }
149
-
150
- private static func setParentResourceDependencies(object: SpatialObject, info: CommandInfo) {
151
- if let parentWindowComponent = SpatialObject.get(info.resourceID) as? SpatialWindowComponent {
152
- parentWindowComponent.addChildSpatialObject(object)
153
- }
154
- if let parentWindowContainer = SpatialWindowContainer.getSpatialWindowContainer(info.windowContainerID) {
155
- parentWindowContainer.addChildResource(object)
156
- }
157
- }
158
-
159
- private func createResource(target: SpatialWindowComponent, info: CommandInfo) {
160
- let data = info.cmd.data!
161
- if let type = data.type {
162
- var sr: SpatialObject?
163
- switch type {
164
- case "Entity":
165
- sr = SpatialEntity()
166
- case "InputComponent":
167
- sr = SpatialInputComponent()
168
- (sr as! SpatialInputComponent).wv = target
169
- case "MeshResource":
170
- if let shape = data.params?.shape {
171
- let meshResource: MeshResource = shape == "sphere" ? .generateSphere(radius: 0.5) : .generateBox(size: 1.0)
172
- sr = SpatialMeshResource(meshResource)
173
- }
174
- case "PhysicallyBasedMaterial":
175
- sr = SpatialPhysicallyBasedMaterial(PhysicallyBasedMaterial())
176
- case "SpatialWebView":
177
- if let parentWindowContainer = SpatialWindowContainer.getSpatialWindowContainer(info.windowContainerID) {
178
- sr = SpatialWindowComponent(parentWindowContainerID: parentWindowContainer.id)
179
- let spatialWindowComponent = sr as! SpatialWindowComponent
180
- spatialWindowComponent.parentWebviewID = target.id
181
- }
182
- case "SpatialView":
183
- sr = SpatialViewComponent()
184
- case "Model3DComponent":
185
- let spatialModel3DComponent = SpatialModel3DComponent()
186
- if let modelURL: String = data.params?.modelURL {
187
- spatialModel3DComponent.setURL(modelURL)
188
- }
189
- sr = spatialModel3DComponent
190
- spatialModel3DComponent.wv = target
191
- case "ModelComponent":
192
- if var modelURL: String = data.params?.modelURL {
193
- modelURL = target.parseURL(url: modelURL)
194
- // Create download task for the url
195
- let url = URL(string: modelURL)!
196
- let downloadSession = URLSession(configuration: URLSession.shared.configuration, delegate: nil, delegateQueue: nil)
197
- let downloadTask = downloadSession.downloadTask(with: url, completionHandler: { a, _, _ in
198
- var fileURL = url
199
- if !pwaManager.isLocal {
200
- // Copy temp file to documentes directory
201
- let fileStr = modelURL.replacingOccurrences(of: ":", with: "__").replacingOccurrences(of: "/", with: "_x_")
202
- do {
203
- fileURL = getDocumentsDirectory().appendingPathComponent(fileStr)
204
- try FileManager.default.copyItem(at: a!, to: fileURL)
205
- logger.debug("Downloaded and copied model")
206
- } catch {
207
- logger.warning("Model already exists")
208
- }
209
- }
210
-
211
- Task {
212
- do {
213
- let m = try await ModelEntity(contentsOf: fileURL)
214
-
215
- let modelComponent = await m.model!
216
- let spatialModelComponent = SpatialModelComponent(modelComponent)
217
-
218
- Task.detached { @MainActor in
219
- // Update state on main thread
220
- CommandManager.setParentResourceDependencies(object: spatialModelComponent, info: info)
221
- target.completeEvent(requestID: info.requestID, data: "{createdID: '" + spatialModelComponent.id + "'}")
222
- logger.debug("Model load success!")
223
- }
224
- } catch {
225
- logger.warning("failed to load model: " + error.localizedDescription)
226
- }
227
- }
228
- })
229
- downloadTask.resume()
230
- return
231
- } else {
232
- let modelComponent = ModelComponent(mesh: .generateBox(size: 0.0), materials: [])
233
- sr = SpatialModelComponent(modelComponent)
234
- }
235
- default: logger.warning("failed to create sr of type \(type)")
236
- }
237
- if let srObject = sr {
238
- CommandManager.setParentResourceDependencies(object: srObject, info: info)
239
- target.completeEvent(requestID: info.requestID, data: "{createdID: '" + srObject.id + "'}")
240
- } else {
241
- logger.warning("failed to create sr of type: \(type)")
242
- }
243
- }
244
- }
245
-
246
- private func destroyResource(target: SpatialWindowComponent, info: CommandInfo) {
247
- let resourceID = info.resourceID
248
- target.destroyChild(name: resourceID)
249
- }
250
-
251
- private func updateResource(target: SpatialWindowComponent, info: CommandInfo) {
252
- let data = info.cmd.data!
253
- var delayComplete = false
254
- if SpatialObject.get(info.resourceID) == nil {
255
- logger.warning("Missing resource:" + info.resourceID)
256
- return
257
- }
258
- let sr = SpatialObject.get(info.resourceID)!
259
- if let entity = sr as? SpatialEntity {
260
- if let setParentID: String = data.update?.setParent {
261
- if setParentID.isEmpty {
262
- entity.setParent(parentEnt: nil)
263
- } else {
264
- if let parentEntity = SpatialObject.get(setParentID) as? SpatialEntity {
265
- entity.setParent(parentEnt: parentEntity)
266
- } else {
267
- logger.warning("Invalid setParentID: \(setParentID)")
268
- }
269
- }
270
- }
271
-
272
- if let _ = data.update?.getBoundingBox {
273
- let b = entity.modelEntity.visualBounds(relativeTo: nil)
274
- let exts = "x:" + String(b.extents.x) + "," + "y:" + String(b.extents.y) + "," + "z:" + String(b.extents.z)
275
- let center = "x:" + String(b.center.x) + "," + "y:" + String(b.center.y) + "," + "z:" + String(b.center.z)
276
- target.completeEvent(requestID: info.requestID, data: "{center: {" + center + "}, extents: {" + exts + "}}")
277
- return
278
- }
279
-
280
- if let name = data.update?.name {
281
- entity.name = name
282
- }
283
-
284
- if let space: String = data.update?.setCoordinateSpace {
285
- entity.coordinateSpace = .APP
286
- if space == "Root" {
287
- entity.coordinateSpace = .ROOT
288
- }
289
-
290
- if space == "Dom" {
291
- entity.coordinateSpace = .DOM
292
- }
293
- }
294
-
295
- if let zIndex: Double = data.update?.zIndex {
296
- entity.zIndex = zIndex
297
- }
298
-
299
- if let visible: Bool = data.update?.visible {
300
- entity.visible = visible
301
- }
302
-
303
- if var newParentID: String = data.update?.setParentWindowContainerID {
304
- newParentID = target.readWindowContainerID(id: newParentID)
305
- let wg = SpatialWindowContainer.getSpatialWindowContainer(newParentID)
306
- entity.setParentWindowContainer(wg: wg)
307
- }
308
-
309
- if let position: JSVector3F = data.update?.position,
310
- let scale: JSVector3F = data.update?.scale,
311
- let orientation: JSVector4 = data.update?.orientation
312
- {
313
- entity.modelEntity.position = SIMD3<Float>(position.x, position.y, position.z)
314
- entity.modelEntity.scale = SIMD3<Float>(scale.x, scale.y, scale.z)
315
- entity.modelEntity.orientation.vector = SIMD4<Float>(orientation.x, orientation.y, orientation.z, orientation.w)
316
- entity.forceUpdate = !entity.forceUpdate
317
- }
318
- } else if sr is SpatialMeshResource {
319
- } else if let spatialPhysicallyBasedMaterial = sr as? SpatialPhysicallyBasedMaterial {
320
- if let baseColor: JSColor = data.update?.baseColor {
321
- spatialPhysicallyBasedMaterial.physicallyBasedMaterial.baseColor = PhysicallyBasedMaterial.BaseColor(tint: UIColor(red: baseColor.r, green: baseColor.g, blue: baseColor.b, alpha: baseColor.a))
322
- spatialPhysicallyBasedMaterial.physicallyBasedMaterial.opacityThreshold = 0.0
323
- }
324
-
325
- if let roughness: Double = data.update?.roughness?.value {
326
- spatialPhysicallyBasedMaterial.physicallyBasedMaterial.roughness = PhysicallyBasedMaterial.Roughness(floatLiteral: Float(roughness))
327
- }
328
-
329
- if let metallic: Double = data.update?.metallic?.value {
330
- spatialPhysicallyBasedMaterial.physicallyBasedMaterial.metallic = PhysicallyBasedMaterial.Metallic(floatLiteral: Float(metallic))
331
- }
332
-
333
- } else if let spatialViewComponent = sr as? SpatialViewComponent {
334
- if let resolution = data.update?.resolution {
335
- spatialViewComponent.resolutionX = resolution.x
336
- spatialViewComponent.resolutionY = resolution.y
337
- }
338
-
339
- if let isPortal = data.update?.isPortal {
340
- spatialViewComponent.isPortal = isPortal
341
- }
342
-
343
- } else if let spatialModelComponent = sr as? SpatialModelComponent {
344
- if let meshResourceId: String = data.update?.meshResource {
345
- if let spatialMeshResource = target.getChildSpatialObject(name: meshResourceId) as? SpatialMeshResource {
346
- spatialModelComponent.modelComponent.mesh = spatialMeshResource.meshResource
347
- } else {
348
- logger.warning("invalid meshResource")
349
- }
350
- }
351
-
352
- if let materials: [String] = data.update?.materials {
353
- spatialModelComponent.modelComponent.materials = []
354
- for matID in materials {
355
- if let spatialMaterialComponent = target.getChildSpatialObject(name: matID) as? SpatialPhysicallyBasedMaterial {
356
- spatialModelComponent.modelComponent.materials.append(spatialMaterialComponent.physicallyBasedMaterial)
357
- }
358
- }
359
- }
360
- spatialModelComponent.onUpdate()
361
- } else if let spatialModel3DComponent = sr as? SpatialModel3DComponent {
362
- if let resolution: JSVector2 = data.update?.resolution {
363
- spatialModel3DComponent.resolutionX = resolution.x
364
- spatialModel3DComponent.resolutionY = resolution.y
365
- }
366
-
367
- if let rotationAnchor = data.update?.rotationAnchor {
368
- spatialModel3DComponent.rotationAnchor = UnitPoint3D(
369
- x: rotationAnchor.x,
370
- y: rotationAnchor.y,
371
- z: rotationAnchor.z
372
- )
373
- }
374
-
375
- if let opacity = data.update?.opacity {
376
- spatialModel3DComponent.opacity = opacity
377
- }
378
-
379
- if let contentMode: String = data.update?.contentMode {
380
- if contentMode == "fill" {
381
- spatialModel3DComponent.contentMode = .fill
382
-
383
- } else if contentMode == "fit" {
384
- spatialModel3DComponent.contentMode = .fit
385
- }
386
- }
387
-
388
- if let resizable: Bool = data.update?.resizable {
389
- spatialModel3DComponent.resizable = resizable
390
- }
391
-
392
- if let aspectRatio: Double = data.update?.aspectRatio {
393
- if aspectRatio > 0 {
394
- spatialModel3DComponent.aspectRatio = aspectRatio
395
-
396
- } else if aspectRatio == 0 {
397
- spatialModel3DComponent.aspectRatio = nil
398
- }
399
- }
400
-
401
- if let enableTapEvent: Bool = data.update?.enableTapEvent {
402
- spatialModel3DComponent.enableTapEvent = enableTapEvent
403
- }
404
-
405
- if let enableDoubleTapEvent: Bool = data.update?.enableDoubleTapEvent {
406
- spatialModel3DComponent.enableDoubleTapEvent = enableDoubleTapEvent
407
- }
408
-
409
- if let enableDragEvent: Bool = data.update?.enableDragEvent {
410
- spatialModel3DComponent.enableDragEvent = enableDragEvent
411
- }
412
-
413
- if let enableLongPressEvent: Bool = data.update?.enableLongPressEvent {
414
- spatialModel3DComponent.enableLongPressEvent = enableLongPressEvent
415
- }
416
-
417
- if let scrollWithParent: Bool = data.update?.scrollWithParent {
418
- spatialModel3DComponent.scrollWithParent = scrollWithParent
419
- }
420
-
421
- } else if let spatialWindowComponent = sr as? SpatialWindowComponent {
422
- if let _: String = data.update?.getEntityID {
423
- if let entity: SpatialEntity = spatialWindowComponent.entity {
424
- target.completeEvent(requestID: info.requestID, data: "{parentID:'" + entity.id + "'}")
425
-
426
- } else {
427
- target.completeEvent(requestID: info.requestID, data: "{parentID:''}")
428
- }
429
- return
430
- }
431
-
432
- if let _: String = data.update?.getParentID {
433
- target.completeEvent(requestID: info.requestID, data: "{parentID:'" + spatialWindowComponent.parentWebviewID + "'}")
434
- return
435
- }
436
-
437
- if let scrollEnabled: Bool = data.update?.scrollEnabled {
438
- if !scrollEnabled {
439
- spatialWindowComponent.getView()!.webViewHolder.appleWebView!.scrollView.contentOffset.y = 0
440
- spatialWindowComponent.getView()!.webViewHolder.appleWebView!.scrollView.isScrollEnabled = false
441
- } else {
442
- spatialWindowComponent.getView()!.webViewHolder.appleWebView!.scrollView.isScrollEnabled = true
443
- }
444
- }
445
-
446
- if let rect: JSRect = data.update?.setScrollEdgeInsets {
447
- spatialWindowComponent.getView()!.webViewHolder.appleWebView!.scrollView.contentInset = UIEdgeInsets(top: rect.top, left: rect.left, bottom: rect.bottom, right: rect.right)
448
- }
449
-
450
- if let scrollWithParent: Bool = data.update?.scrollWithParent {
451
- spatialWindowComponent.scrollWithParent = scrollWithParent
452
- }
453
-
454
- if let windowID: String = data.update?.windowID {
455
- if let spawnedWebView = target.spawnedNativeWebviews.removeValue(forKey: windowID) {
456
- spatialWindowComponent.getView()!.destroy()
457
- spatialWindowComponent.setView(wv: spawnedWebView)
458
- spatialWindowComponent.getView()!.webViewHolder.webViewCoordinator!.webViewRef = spatialWindowComponent
459
- spatialWindowComponent.didFinishFirstLoad = true
460
- }
461
- }
462
-
463
- if let url: String = data.update?.url {
464
- // Compute target url depending if the url is relative or not
465
- let targetUrl = target.parseURL(url: url)
466
-
467
- delayComplete = true
468
- if spatialWindowComponent.loadRequestID == -1 {
469
- spatialWindowComponent.loadRequestID = info.requestID
470
- spatialWindowComponent.loadRequestWV = target
471
- spatialWindowComponent.setURL(url: URL(string: targetUrl)!)
472
- spatialWindowComponent.getView()!.initialLoad()
473
- } else {
474
- target.failEvent(requestID: info.requestID)
475
- }
476
- }
477
-
478
- if let resolution: JSVector2 = data.update?.resolution {
479
- spatialWindowComponent.resolutionX = resolution.x
480
- spatialWindowComponent.resolutionY = resolution.y
481
- }
482
-
483
- if let rotationAnchor = data.update?.rotationAnchor {
484
- spatialWindowComponent.rotationAnchor = UnitPoint3D(
485
- x: rotationAnchor.x,
486
- y: rotationAnchor.y,
487
- z: rotationAnchor.z
488
- )
489
- }
490
-
491
- if let opacity = data.update?.opacity {
492
- spatialWindowComponent.opacity = opacity
493
- }
494
-
495
- if let backgroundMaterial: BackgroundMaterial = data.update?.style?.backgroundMaterial {
496
- clock.backgroundSet()
497
-
498
- if spatialWindowComponent.isLoading {
499
- spatialWindowComponent.loadingStyles.backgroundMaterial = backgroundMaterial
500
- }
501
- spatialWindowComponent.backgroundMaterial = backgroundMaterial
502
- }
503
- if let cornerRadius: CornerRadius = data.update?.style?.cornerRadius {
504
- if spatialWindowComponent.isLoading {
505
- spatialWindowComponent.loadingStyles.cornerRadius = cornerRadius
506
- }
507
- spatialWindowComponent.cornerRadius = cornerRadius
508
- }
509
- spatialWindowComponent.gotStyle = true
510
- }
511
- if !delayComplete {
512
- target.completeEvent(requestID: info.requestID)
513
- }
514
- }
515
-
516
- private func createWindowContainer(target: SpatialWindowComponent, info: CommandInfo) {
517
- if let windowStyle: String = info.cmd.data!.windowStyle {
518
- let uuid = UUID().uuidString
519
- let wgd = WindowContainerData(windowStyle: windowStyle, windowContainerID: uuid)
520
-
521
- // Force window container creation to happen now so it can be accessed after complete event returns
522
- _ = SpatialWindowContainer.getOrCreateSpatialWindowContainer(uuid, wgd)
523
-
524
- if let wg = SpatialWindowContainer.getOrCreateSpatialWindowContainer(target.parentWindowContainerID, wgd) {
525
- wg.openWindowData.send(wgd)
526
-
527
- // If the parent window component isn't set, the new container can continue to exist even after other window is closed
528
- if info.resourceID != "notFound" {
529
- let rid = info.resourceID
530
- let so = SpatialObject.get(rid)
531
- if let parentWindowComponent = so as? SpatialWindowComponent {
532
- parentWindowComponent.setWindowContainer(uuid: uuid, wgd: wgd)
533
- }
534
- }
535
-
536
- if info.windowContainerID != "notFound" {
537
- if let parentContainer = SpatialWindowContainer.getSpatialWindowContainer(info.windowContainerID) {
538
- parentContainer.childContainers[uuid] = wg
539
- }
540
- }
541
-
542
- target.completeEvent(requestID: info.requestID, data: "{createdID: '" + uuid + "'}")
543
- }
544
- }
545
- }
546
-
547
- private func createScene(target: SpatialWindowComponent, info: CommandInfo) {
548
- let data = info.cmd.data!
549
- if let _: String = data.windowStyle {
550
- // windowID exist in SWC
551
-
552
- // TODO: check url scope
553
- // in scope: the url is configured in manifest
554
- // if not in scope, open in safari
555
-
556
- if data.sceneData?.method == "createRoot" {
557
- if let windowID = data.sceneData?.windowID {
558
- // if windowID in spawned uuid, createRoot
559
-
560
- if target.spawnedNativeWebviews[windowID] != nil {
561
- // setup windowContainer defaultValues
562
- if let config = data.sceneData?.sceneConfig {
563
- SceneManager.Instance
564
- .createRoot(target: target, windowID: windowID, config: config)
565
- } else {
566
- SceneManager.Instance
567
- .createRoot(target: target, windowID: windowID)
568
- }
569
-
570
- } else {
571
- if let windowContainerID = data.sceneData?.windowContainerID {
572
- SceneManager.Instance.focusRoot(target: target, windowContainerID: windowContainerID)
573
- } else {
574
- logger.error("error: no windowContainerID")
575
- }
576
- }
577
-
578
- target.completeEvent(requestID: info.requestID, data: "{}")
579
- }
580
- } else if data.sceneData?.method == "showRoot" {
581
- if let config = data.sceneData?.sceneConfig {
582
- let parentWindowContainerID = info.windowContainerID
583
- SceneManager.Instance.showRoot(target: target, config: config, parentWindowContainerID: parentWindowContainerID)
584
- }
585
- target.completeEvent(requestID: info.requestID, data: "{}")
586
-
587
- } else {
588
- target.failEvent(requestID: info.requestID, data: "method not supported")
589
- }
590
- }
591
- }
592
-
593
- private func updateWindowContainer(target: SpatialWindowComponent, info: CommandInfo) {
594
- let data = info.cmd.data!
595
- if let _ = data.update?.getRootEntityID,
596
- let wg = SpatialWindowContainer.getSpatialWindowContainer(target.readWindowContainerID(id: info.windowContainerID))
597
- {
598
- let rootEntity = wg.getEntities().filter {
599
- $0.value.coordinateSpace == .ROOT
600
- }.first?.value
601
- if rootEntity != nil {
602
- target.completeEvent(requestID: info.requestID, data: "{rootEntId:'" + rootEntity!
603
- .id + "'}")
604
- } else {
605
- target.completeEvent(requestID: info.requestID, data: "{rootEntId:''}")
606
- }
607
- return
608
- }
609
-
610
- if let resolution = data.update?.nextOpenSettings?.resolution {
611
- sceneStateChangedCB = { _ in
612
- // Complete event after scene state change is completed
613
- target.completeEvent(requestID: info.requestID)
614
- sceneStateChangedCB = { _ in }
615
- }
616
-
617
- // Update scene state
618
- var cfg = WindowContainerPlainDefaultValues()
619
- cfg.defaultSize = CGSize(width: resolution.width, height: resolution.height)
620
- // TODO: need set resizeRange?
621
- WindowContainerMgr.Instance.updateWindowContainerPlainDefaultValues(cfg)
622
- return
623
- }
624
-
625
- if let shouldClose = data.update?.close,
626
- let wg = SpatialWindowContainer.getSpatialWindowContainer(target.readWindowContainerID(id: info.windowContainerID))
627
- {
628
- if shouldClose {
629
- wg.destroy()
630
- }
631
- }
632
-
633
- target.completeEvent(requestID: info.requestID)
634
- }
635
-
636
- private func openImmersiveSpace(target: SpatialWindowComponent, info: CommandInfo) {
637
- let wg = SpatialWindowContainer.getSpatialWindowContainer(target.parentWindowContainerID)
638
- wg?.toggleImmersiveSpace.send(true)
639
- }
640
-
641
- private func dismissImmersiveSpace(target: SpatialWindowComponent, info: CommandInfo) {
642
- let wg = SpatialWindowContainer.getSpatialWindowContainer(target.parentWindowContainerID)
643
- wg?.toggleImmersiveSpace.send(false)
644
- }
645
-
646
- private func log(target: SpatialWindowComponent, info: CommandInfo) {
647
- if let logStringArr: [String] = info.cmd.data!.logString {
648
- let logString = logStringArr.joined()
649
- logger.debug(logString)
650
- }
651
- }
652
-
653
- private func setLoading(target: SpatialWindowComponent, info: CommandInfo) {
654
- let data = info.cmd.data!
655
- switch data.loading?.method {
656
- case "show":
657
- SceneManager.Instance.setLoading(.show, windowContainerID: info.windowContainerID)
658
- case "hide":
659
- SceneManager.Instance.setLoading(.hide, windowContainerID: info.windowContainerID)
660
- case _:
661
- break
662
- }
663
- target.completeEvent(requestID: info.requestID)
664
- }
665
- }
666
-
667
- struct RawJSBCommand: Codable {
668
- var command: String
669
- var data: RawJSData?
670
- var requestID: Int
671
- }
672
-
673
- struct JSBCommand {
674
- var command: String
675
- var data: JSData?
676
- var requestID: Int
677
- }
678
-
679
- protocol JSData {
680
- var commandList: [RawJSBCommand]? { get } // multiCommand
681
- var type: String? { get } // createResource
682
- var params: JSParams? { get } // createResource
683
- var update: JSResourceData? { get }
684
- var windowStyle: String? { get }
685
- var windowContainerOptions: WindowContainerOptions? { get }
686
- var sceneData: SceneJSBData? { get }
687
- var logString: [String]? { get }
688
- var logLevel: String? { get }
689
- var loading: LoadingJSBData? { get }
690
- }
691
-
692
- struct RawJSData: Codable, JSData {
693
- var commandList: [RawJSBCommand]? // multiCommand
694
- var resourceID: String?
695
- var windowContainerID: String?
696
- var entityID: String? // setComponent
697
- var type: String? // createResource
698
- var params: JSParams? // createResource
699
- var update: JSResourceData?
700
- var windowStyle: String?
701
- var windowContainerOptions: WindowContainerOptions?
702
- var sceneData: SceneJSBData?
703
- var logString: [String]?
704
- var logLevel: String?
705
- var loading: LoadingJSBData?
706
- }
707
-
708
- struct JSParams: Codable {
709
- var shape: String?
710
- var modelURL: String?
711
- }
712
-
713
- struct JSResourceData: Codable {
714
- var setParent: String?
715
- var setCoordinateSpace: String?
716
- var setParentWindowContainerID: String?
717
- var position: JSVector3F?
718
- var orientation: JSVector4?
719
- var scale: JSVector3F?
720
- var baseColor: JSColor?
721
- var roughness: JSValue?
722
- var metallic: JSValue?
723
- var url: String?
724
- var aspectRatio: Double?
725
- var opacity: Double?
726
- var contentMode: String?
727
- var resizable: Bool?
728
- var resolution: JSVector2?
729
- var isPortal: Bool?
730
- var rotationAnchor: JSVector3?
731
- var meshResource: String?
732
- var materials: [String]?
733
- var getEntityID: String?
734
- var getParentID: String?
735
- var getRootEntityID: String?
736
- var scrollEnabled: Bool?
737
- var scrollWithParent: Bool?
738
- var setScrollEdgeInsets: JSRect?
739
- var windowID: String?
740
- var style: JSEntityStyle?
741
- var nextOpenSettings: JSNextOpen?
742
- var close: Bool?
743
- var getBoundingBox: Bool?
744
- var zIndex: Double?
745
- var visible: Bool?
746
- var name: String?
747
-
748
- var enableTapEvent: Bool?
749
- var enableDoubleTapEvent: Bool?
750
- var enableDragEvent: Bool?
751
- var enableLongPressEvent: Bool?
752
- }
753
-
754
- struct JSColor: Codable {
755
- var r: Double
756
- var g: Double
757
- var b: Double
758
- var a: Double
759
- }
760
-
761
- struct JSVector2: Codable {
762
- var x: Double
763
- var y: Double
764
- }
765
-
766
- struct JSResolution: Codable {
767
- var width: Double
768
- var height: Double
769
- }
770
-
771
- struct JSVector3: Codable {
772
- var x: Double
773
- var y: Double
774
- var z: Double
775
- }
776
-
777
- struct JSVector3F: Codable {
778
- var x: Float
779
- var y: Float
780
- var z: Float
781
- }
782
-
783
- struct JSVector4: Codable {
784
- var x: Float
785
- var y: Float
786
- var z: Float
787
- var w: Float
788
- }
789
-
790
- struct JSValue: Codable {
791
- var value: Double
792
- }
793
-
794
- struct JSRect: Codable {
795
- var top: Double
796
- var bottom: Double
797
- var left: Double
798
- var right: Double
799
- }
800
-
801
- struct JSEntityStyle: Codable {
802
- var cornerRadius: CornerRadius?
803
- var backgroundMaterial: BackgroundMaterial?
804
- var dimensions: JSVector2?
805
- }
806
-
807
- struct JSNextOpen: Codable {
808
- var resolution: JSResolution?
809
- }
810
-
811
- struct SceneJSBData: Codable {
812
- var method: String?
813
- var sceneName: String?
814
- var sceneConfig: WindowContainerOptions?
815
- var url: String?
816
- var windowID: String?
817
- var windowContainerID: String?
818
- }
819
-
820
- struct LoadingJSBData: Codable {
821
- var method: String?
822
- var style: String?
823
- }