@webspatial/platform-visionos 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 (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,454 +0,0 @@
1
- import Combine
2
- import Foundation
3
- import RealityKit
4
- import SwiftUI
5
- import WebKit
6
-
7
- let DefaultPlainWindowContainerSize = CGSize(width: 1280, height: 720)
8
-
9
- func getDocumentsDirectory() -> URL {
10
- let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
11
- let documentsDirectory = paths[0]
12
- return documentsDirectory
13
- }
14
-
15
- struct LoadingStyles {
16
- var cornerRadius: CornerRadius = .init()
17
- var windowContainerSize = DefaultPlainWindowContainerSize
18
- var backgroundMaterial: BackgroundMaterial = .None
19
- }
20
-
21
- class NavInfo: ObservableObject {
22
- @Published var url: String = ""
23
- }
24
-
25
- @Observable
26
- class SpatialWindowComponent: SpatialComponent {
27
- override func inspect() -> [String: Any] {
28
- let childEntitiesInfo = childResources.mapValues { spatialObject in
29
- spatialObject.inspect()
30
- }
31
-
32
- let encoder = JSONEncoder()
33
- encoder.outputFormatting = .prettyPrinted
34
-
35
- var inspectInfo: [String: Any] = [
36
- "scrollWithParent": scrollWithParent,
37
- "resolutionX": resolutionX,
38
- "resolutionY": resolutionY,
39
- "parentWebviewID": parentWebviewID,
40
- "parentWindowContainerID": parentWindowContainerID,
41
- "childWindowContainers": childWindowContainers,
42
- "spawnedNativeWebviewsCount": spawnedNativeWebviews.count,
43
- "childResources": childEntitiesInfo,
44
- "cornerRadius": cornerRadius.toJson(),
45
- "backgroundMaterial": backgroundMaterial.rawValue,
46
- "isOpaque": webViewNative!.webViewHolder.appleWebView!.isOpaque,
47
- "isScrollEnabled": isScrollEnabled(),
48
- ]
49
-
50
- let baseInspectInfo = super.inspect()
51
- for (key, value) in baseInspectInfo {
52
- inspectInfo[key] = value
53
- }
54
- return inspectInfo
55
- }
56
-
57
- var scrollOffset = CGPoint()
58
- private var webViewNative: WebViewNative?
59
- var resolutionX: Double = 0
60
- var resolutionY: Double = 0
61
- var scrollWithParent = false
62
-
63
- var rotationAnchor: UnitPoint3D = .center
64
-
65
- // Track the first load event of the webview so we don't see a flash of white before the page loads
66
- var didFinishFirstLoad = false
67
-
68
- // ID of the webview that created this or empty if its root
69
- var parentWebviewID: String = ""
70
- var parentWindowContainerID: String
71
- var childWindowContainers = [String: WindowContainerData]()
72
- var spawnedNativeWebviews = [String: WebViewNative]()
73
- var navInfo = NavInfo()
74
-
75
- // Resources that will be destroyed when this webpage is destoryed or if it is navigated away from
76
- private var childResources = [String: SpatialObject]()
77
- public func addChildSpatialObject(_ spatialObject: SpatialObject) {
78
- childResources[spatialObject.id] = spatialObject
79
- spatialObject
80
- .on(
81
- event: SpatialObject.Events.BeforeDestroyed.rawValue,
82
- listener: onSptatialObjectDestroyed
83
- )
84
- }
85
-
86
- public func removeChildSpatialObject(_ spatialObject: SpatialObject) {
87
- spatialObject
88
- .off(
89
- event: SpatialObject.Events.BeforeDestroyed.rawValue,
90
- listener: onSptatialObjectDestroyed
91
- )
92
- childResources.removeValue(forKey: spatialObject.id)
93
- }
94
-
95
- public func getChildSpatialObject(name: String) -> SpatialObject? {
96
- return childResources[name]
97
- }
98
-
99
- public func destroyChild(name: String) {
100
- childResources[name]?.destroy()
101
- }
102
-
103
- private func onSptatialObjectDestroyed(_ object: Any, _ data: Any) {
104
- let spatialObject = object as! SpatialObject
105
- removeChildSpatialObject(spatialObject)
106
- }
107
-
108
- private func onWindowContainerDestroyed(_ object: Any, _ data: Any) {
109
- if let spatialObject = object as? SpatialWindowContainer {
110
- spatialObject
111
- .off(
112
- event: SpatialObject.Events.BeforeDestroyed.rawValue,
113
- listener: onWindowContainerDestroyed
114
- )
115
- childWindowContainers.removeValue(forKey: spatialObject.id)
116
- }
117
- }
118
-
119
- /// Determines whether the current webview is a root webview.
120
- ///
121
- /// A root webview is created when the Scene is initialized.
122
- /// If the webview is created by another `SpatialWebview`, it is not considered a root webview.
123
- /// For example, a `SpatialDiv` is not a root webview.
124
- ///
125
- /// - Returns: `true` if the webview is a root webview (i.e., `parentWebviewID` is empty), otherwise `false`.
126
- public func isRootWebview() -> Bool {
127
- return parentWebviewID == ""
128
- }
129
-
130
- public func setWindowContainer(uuid: String, wgd: WindowContainerData) {
131
- childWindowContainers[uuid] = wgd
132
- SpatialWindowContainer.getSpatialWindowContainer(uuid)!.on(
133
- event: SpatialObject.Events.BeforeDestroyed.rawValue,
134
- listener: onWindowContainerDestroyed
135
- )
136
- }
137
-
138
- // Drag event handling
139
- var dragStarted = false
140
- var dragStart = 0.0
141
- var dragVelocity = 0.0
142
-
143
- var gotStyle = false
144
- var opacity = 1.0
145
- var cornerRadius: CornerRadius = .init()
146
-
147
- private var _backgroundMaterial = BackgroundMaterial.None
148
- var backgroundMaterial: BackgroundMaterial {
149
- get {
150
- return _backgroundMaterial
151
- }
152
- set(newValue) {
153
- _backgroundMaterial = newValue
154
- if isRootWebview() {
155
- webViewNative?.webViewHolder.appleWebView?.isOpaque = _backgroundMaterial == .None
156
- } else {
157
- // it's spatial div
158
- webViewNative?.webViewHolder.appleWebView?.isOpaque = false
159
- }
160
- }
161
- }
162
-
163
- var loadingStyles = LoadingStyles()
164
- var isLoading = true
165
-
166
- var didFailLoad = false
167
-
168
- private var cancellables = Set<AnyCancellable>() // save subscriptions
169
-
170
- init(parentWindowContainerID: String) {
171
- self.parentWindowContainerID = parentWindowContainerID
172
- super.init()
173
- webViewNative = WebViewNative()
174
- webViewNative?.webViewRef = self
175
- _ = webViewNative?.createResources()
176
- registerForceStyle()
177
- }
178
-
179
- init(parentWindowContainerID: String, url: URL) {
180
- self.parentWindowContainerID = parentWindowContainerID
181
- super.init()
182
-
183
- webViewNative = WebViewNative(url: url)
184
- webViewNative?.webViewRef = self
185
- _ = webViewNative?.createResources()
186
- registerForceStyle()
187
- }
188
-
189
- func initFromURL(url: URL) {
190
- webViewNative = WebViewNative(url: url)
191
- webViewNative?.webViewRef = self
192
- _ = webViewNative?.createResources()
193
- registerForceStyle()
194
- }
195
-
196
- // the url schema handler for forcestyle cannot bind seperately for every webview due to apple limitation. So this is a workaround like eventbus, webview will handle the message that has matched webview.
197
- func registerForceStyle() {
198
- webviewGetEarlyStyleData
199
- .filter { [weak self] event in
200
- self?.getView()?.webViewHolder.appleWebView == event.webview
201
- }
202
- .sink { [weak self] event in
203
- self?.didGetEarlyStyle(style: event.style)
204
- }
205
- .store(in: &cancellables)
206
- }
207
-
208
- func goBack() {
209
- webViewNative?.webViewHolder.appleWebView?.goBack()
210
- }
211
-
212
- func goForward() {
213
- webViewNative?.webViewHolder.appleWebView?.goForward()
214
- }
215
-
216
- func reload() {
217
- webViewNative?.webViewHolder.appleWebView?.reload()
218
- }
219
-
220
- var canGoBack: Bool = false
221
-
222
- var canGoForward: Bool = false
223
-
224
- func navigateToURL(url: URL) {
225
- webViewNative!.url = url
226
- webViewNative!.webViewHolder.needsUpdate = true
227
- webViewNative!.initialLoad()
228
- }
229
-
230
- /// Remove webview window.name
231
- ///
232
- /// The expectation is that when the app is reopened, the root page should not have a window.name. However, under the current scene mechanism, if the last closed scene had set a window.name, it will still exist the next time the app is opened.
233
- ///
234
- /// Currently, window.name is only deleted when non-main scenes are closed along with the destruction of the WebView.
235
- ///
236
- /// the root page should always have a blank name
237
-
238
- func removeWebviewName(completion: (() -> Void)? = nil) {
239
- webViewNative?.webViewHolder.appleWebView?.evaluateJavaScript("window.name = '';") { _, _ in
240
- completion?()
241
- }
242
- }
243
-
244
- func isScrollEnabled() -> Bool {
245
- return webViewNative!.webViewHolder.appleWebView!.scrollView.isScrollEnabled
246
- }
247
-
248
- /// Finds the nearest ancestor `SpatialWindowComponent` that has scrolling enabled.
249
- ///
250
- /// This method traverses the entity hierarchy upwards, starting from the current `SpatialWindowComponent`,
251
- /// and checks each ancestor `SpatialWindowComponent` to see if scrolling is enabled. If a suitable
252
- /// component is found, it is returned; otherwise, `nil` is returned.
253
- ///
254
- /// - Returns: The nearest ancestor `SpatialWindowComponent` with scrolling enabled, or `nil` if none is found.
255
- func findNearestScrollEnabledSpatialWindowComponent() -> SpatialWindowComponent? {
256
- var current: SpatialWindowComponent? = self
257
- while current != nil {
258
- if current!.isScrollEnabled() {
259
- return current!
260
- }
261
- if let parentEntity = current?.entity?.parent {
262
- current = parentEntity.getComponent(SpatialWindowComponent.self)
263
- } else {
264
- current = nil
265
- }
266
- }
267
- return current
268
- }
269
-
270
- func updateScrollOffset(delta: CGFloat) {
271
- webViewNative!.webViewHolder.appleWebView!.scrollView.contentOffset.y += delta
272
- }
273
-
274
- func stopScrolling() {
275
- webViewNative!.webViewHolder.appleWebView!.scrollView.stopScrollingAndZooming()
276
- }
277
-
278
- func getView() -> WebViewNative? {
279
- return webViewNative
280
- }
281
-
282
- func setView(wv: WebViewNative) {
283
- webViewNative = wv
284
- webViewNative!.webViewRef = self
285
- }
286
-
287
- func evaluateJS(js: String) {
288
- webViewNative!.webViewHolder.appleWebView!.evaluateJavaScript(js)
289
- }
290
-
291
- func getURL() -> URL? {
292
- return webViewNative?.url
293
- }
294
-
295
- func setURL(url: URL) {
296
- webViewNative!.url = url
297
- }
298
-
299
- func parseURL(url: String) -> String {
300
- // Compute target url depending if the url is relative or not
301
- var targetUrl = url
302
- if !pwaManager.isLocal {
303
- if url[...url.index(url.startIndex, offsetBy: 0)] == "/" {
304
- // Absolute path
305
- var port = ""
306
- if let p = webViewNative?.url.port {
307
- port = ":" + String(p)
308
- }
309
- let domain = webViewNative!.url.scheme! + "://" + webViewNative!.url.host()! + port + "/"
310
- targetUrl = domain + String(url[url.index(url.startIndex, offsetBy: 1)...])
311
- } else {
312
- // Full url eg. http://domain.com
313
- if let parsed = URL(string: url) {
314
- if parsed.scheme != nil {
315
- return url
316
- }
317
- }
318
- // Reletive path
319
- let localDir = NSString(string: webViewNative!.url.absoluteString)
320
- let relPath = String(localDir.deletingLastPathComponent) + "/" + targetUrl
321
- return relPath
322
- }
323
- } else {
324
- if !(targetUrl.starts(with: "http://") || targetUrl.starts(with: "https://")) {
325
- targetUrl = pwaManager.getLocalResourceURL(url: targetUrl)
326
- }
327
- }
328
- return targetUrl
329
- }
330
-
331
- func readWindowContainerID(id: String) -> String {
332
- if id == "current" {
333
- return parentWindowContainerID
334
- } else {
335
- return id
336
- }
337
- }
338
-
339
- deinit {
340
- webViewNative!.destroy()
341
- cancellables.removeAll()
342
- }
343
-
344
- func completeEvent(requestID: Int, data: String = "{}") {
345
- webViewNative?.webViewHolder.appleWebView?.evaluateJavaScript("window.__SpatialWebEvent({success: true, requestID:" + String(requestID) + ", data: " + data + "})")
346
- }
347
-
348
- func fireComponentEvent(componentId: String, data: String = "{}") {
349
- webViewNative?.webViewHolder.appleWebView?.evaluateJavaScript("window.__SpatialWebEvent({resourceId:'" + componentId + "', data: " + data + "})")
350
- }
351
-
352
- func failEvent(requestID: Int, data: String = "{}") {
353
- webViewNative?.webViewHolder.appleWebView?.evaluateJavaScript("window.__SpatialWebEvent({success: false, requestID:" + String(requestID) + ", data: " + data + "})")
354
- }
355
-
356
- // Request information of webview that request this webview to load
357
- weak var loadRequestWV: SpatialWindowComponent?
358
- var loadRequestID = -1
359
-
360
- // A load request of a child webview was loaded
361
- func didLoadChild(loadRequestID: Int, resourceID: String) {
362
- completeEvent(requestID: loadRequestID, data: "{createdID: '" + id + "'}")
363
- }
364
-
365
- func didFailLoadPage() {
366
- didFailLoad = true
367
- didFinishFirstLoad = true
368
- }
369
-
370
- func releaseChildResources() {
371
- let spatialObjects = childResources.map { $0.value }
372
- for spatialObject in spatialObjects {
373
- spatialObject.destroy()
374
- }
375
- childResources = [String: SpatialObject]()
376
- spawnedNativeWebviews = [String: WebViewNative]()
377
-
378
- let wgkeys = childWindowContainers.map { $0.key }
379
- for k in wgkeys {
380
- SpatialWindowContainer.getSpatialWindowContainer(k)!.closeWindowData.send(childWindowContainers[k]!)
381
- }
382
- }
383
-
384
- func didStartLoadPage() {
385
- if didFinishFirstLoad {
386
- webViewNative!.webViewHolder.appleWebView!.evaluateJavaScript("window.__WebSpatialUnloaded = true")
387
- }
388
-
389
- releaseChildResources()
390
- let url = webViewNative?.webViewHolder.appleWebView?.url
391
- webViewNative!.url = url!
392
-
393
- // Mark that we havn't gotten a style update
394
- gotStyle = false
395
- isLoading = true
396
- loadingStyles = LoadingStyles()
397
-
398
- // FIXME:
399
- // This is a workaround to force run UIViewRepresentable.update()
400
- // SwiftUI not trigger it when go back from example page.
401
- // Warning of `AttributeGraph: cycle detected through attribute` fired when goes to example page
402
- webViewNative?.initialLoad()
403
- }
404
-
405
- func didSpawnWebView(wv: WebViewNative) {
406
- let uuid = UUID().uuidString
407
- wv.webViewHolder.appleWebView!.evaluateJavaScript("window._webSpatialID = '" + uuid + "'")
408
- spawnedNativeWebviews[uuid] = wv
409
- }
410
-
411
- func didCloseWebView() {
412
- // if need
413
- if isRootWebview() {
414
- SceneManager.Instance.closeRoot(self)
415
- }
416
- }
417
-
418
- func didStartReceivePageContent() {}
419
-
420
- func didGetEarlyStyle(style: PreloadStyleSettings) {
421
- if let cornerRadius = style.cornerRadius {
422
- loadingStyles.cornerRadius = cornerRadius
423
- }
424
-
425
- if let backgroundMaterial = style.backgroundMaterial {
426
- loadingStyles.backgroundMaterial = backgroundMaterial
427
- }
428
- }
429
-
430
- func didFinishLoadPage() {
431
- didFinishFirstLoad = true
432
- didFailLoad = false
433
- cornerRadius = loadingStyles.cornerRadius
434
- backgroundMaterial = loadingStyles.backgroundMaterial
435
-
436
- isLoading = false
437
-
438
- // update navinfo
439
- if let wv = webViewNative?.webViewHolder.appleWebView {
440
- canGoBack = wv.canGoBack
441
- canGoForward = wv.canGoForward
442
- }
443
- }
444
-
445
- override func onDestroy() {
446
- releaseChildResources()
447
- didCloseWebView()
448
- }
449
-
450
- func didNavBackForward() {
451
- // in JS calling history.go(-1) we should set needUpdate=true
452
- webViewNative?.webViewHolder.needsUpdate = true
453
- }
454
- }
@@ -1,153 +0,0 @@
1
- import Combine
2
- import Foundation
3
- import RealityKit
4
- import typealias RealityKit.Entity
5
-
6
- @Observable
7
- class SpatialWindowContainer: SpatialObject {
8
- // save active plain windowContainer ids
9
- static var activePlainWindowContainerIds: Set<String> = []
10
- // get first active plain WindowContainerId
11
- static var firstActivePlainWindowContainerId: String? {
12
- return activePlainWindowContainerIds.first
13
- }
14
-
15
- // Resources that will be destroyed when this window group is removed
16
- private var childResources = [String: SpatialObject]()
17
- public func addChildResource(_ spatialObject: SpatialObject) {
18
- childResources[spatialObject.id] = spatialObject
19
- spatialObject
20
- .on(
21
- event: SpatialObject.Events.BeforeDestroyed.rawValue,
22
- listener: onSptatialObjectDestroyed
23
- )
24
- }
25
-
26
- private func onSptatialObjectDestroyed(_ object: Any, _ data: Any) {
27
- let spatialObject = object as! SpatialObject
28
- spatialObject
29
- .off(
30
- event: SpatialObject.Events.BeforeDestroyed.rawValue,
31
- listener: onSptatialObjectDestroyed
32
- )
33
- childResources.removeValue(forKey: spatialObject.id)
34
- }
35
-
36
- public var childContainers = [String: SpatialWindowContainer]()
37
-
38
- var wgd: WindowContainerData
39
- static func getSpatialWindowContainer(_ name: String) -> SpatialWindowContainer? {
40
- return SpatialObject.get(name) as? SpatialWindowContainer
41
- }
42
-
43
- static func getOrCreateSpatialWindowContainer(_ name: String, _ data: WindowContainerData) -> SpatialWindowContainer? {
44
- if let windowContainer = getSpatialWindowContainer(name) {
45
- return windowContainer
46
- }
47
- let newWindowContainer = SpatialWindowContainer(name, data)
48
- return newWindowContainer
49
- }
50
-
51
- init(_ name: String, _ data: WindowContainerData) {
52
- wgd = data
53
- if data.windowStyle == "Plain" {
54
- SpatialWindowContainer.activePlainWindowContainerIds.insert(data.windowContainerID)
55
- }
56
-
57
- super.init(name)
58
- }
59
-
60
- // Resources
61
- private var childEntities = [String: SpatialEntity]()
62
-
63
- public func getEntities() -> [String: SpatialEntity] {
64
- return childEntities
65
- }
66
-
67
- public func addEntity(_ spatialEntity: SpatialEntity) {
68
- childEntities[spatialEntity.id] = spatialEntity
69
- }
70
-
71
- public func removeEntity(_ spatialEntity: SpatialEntity) {
72
- childEntities.removeValue(forKey: spatialEntity.id)
73
- }
74
-
75
- // Global state
76
- var toggleImmersiveSpace = PassthroughSubject<Bool, Never>()
77
-
78
- var setSize = PassthroughSubject<CGSize, Never>()
79
- var setResizeRange = PassthroughSubject<ResizeRange, Never>()
80
-
81
- var updateFrame = false
82
- var openWindowData = PassthroughSubject<WindowContainerData, Never>()
83
- var closeWindowData = PassthroughSubject<WindowContainerData, Never>()
84
-
85
- var setLoadingWindowData = PassthroughSubject<LoadingWindowContainerData, Never>()
86
-
87
- override func onDestroy() {
88
- // Note that destroy wont be called on immersive window container
89
- // as there should only ever be one in existance
90
-
91
- childEntities.forEach { $0.value.destroy() }
92
- childEntities = [:]
93
-
94
- // Destroy resources
95
- let spatialObjects = childResources.map { $0.value }
96
- for spatialObject in spatialObjects {
97
- spatialObject.destroy()
98
- }
99
- childResources = [String: SpatialObject]()
100
-
101
- // Destroy spatial containers
102
- let spatialContainers = childContainers.map { $0.value }
103
- for spatialObject in spatialContainers {
104
- if spatialObject != self {
105
- spatialObject.destroy()
106
- }
107
- }
108
- childContainers = [String: SpatialWindowContainer]()
109
-
110
- // Close the window group when this object is destroyed
111
- SpatialWindowContainer.getSpatialWindowContainer(id)!.closeWindowData.send(wgd)
112
- if wgd.windowStyle == "Plain" {
113
- SpatialWindowContainer.activePlainWindowContainerIds.remove(wgd.windowContainerID)
114
- }
115
- }
116
-
117
- override func inspect() -> [String: Any] {
118
- let childEntitiesInfo = childEntities.mapValues { entity in
119
- entity.inspect()
120
- }
121
-
122
- let baseInspectInfo = super.inspect()
123
- var inspectInfo: [String: Any] = ["childEntities": childEntitiesInfo]
124
- for (key, value) in baseInspectInfo {
125
- inspectInfo[key] = value
126
- }
127
- return inspectInfo
128
- }
129
- }
130
-
131
- extension SpatialWindowContainer {
132
- private static let RootID = "root"
133
- static func getRootID() -> String {
134
- return RootID
135
- }
136
- }
137
-
138
- extension SpatialWindowContainer {
139
- static let ImmersiveID = "Immersive"
140
-
141
- static func getImmersiveWindowContainer() -> SpatialWindowContainer? {
142
- return getSpatialWindowContainer(ImmersiveID)
143
- }
144
-
145
- static func createImmersiveWindowContainer() -> SpatialWindowContainer {
146
- if let windowContainer = getSpatialWindowContainer(ImmersiveID) {
147
- logger.warning("Immersive already created! ")
148
- return windowContainer
149
- }
150
- let wgd = WindowContainerData(windowStyle: "ImmersiveSpace", windowContainerID: "ImmersiveSpace")
151
- return SpatialWindowContainer(ImmersiveID, wgd)
152
- }
153
- }