@webspatial/builder 0.0.9 → 0.0.11

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 (92) hide show
  1. package/dist/index.js +1 -1
  2. package/dist/lib/Cli.js +1 -1
  3. package/dist/lib/cmds/build.d.ts +1 -1
  4. package/dist/lib/cmds/build.js +1 -1
  5. package/dist/lib/cmds/check.js +1 -1
  6. package/dist/lib/cmds/help.js +1 -1
  7. package/dist/lib/cmds/version.js +1 -1
  8. package/dist/lib/pwa/config.js +1 -1
  9. package/dist/lib/pwa/index.js +1 -1
  10. package/dist/lib/pwa/validate.js +1 -1
  11. package/dist/lib/resource/file.js +1 -1
  12. package/dist/lib/resource/imageHelper.js +1 -1
  13. package/dist/lib/resource/index.d.ts +10 -3
  14. package/dist/lib/resource/index.js +1 -1
  15. package/dist/lib/resource/load.js +1 -1
  16. package/dist/lib/utils/CustomError.js +1 -1
  17. package/dist/lib/utils/FetchUtils-1.js +1 -1
  18. package/dist/lib/utils/Log.js +1 -1
  19. package/dist/lib/utils/fetch.js +1 -1
  20. package/dist/lib/utils/messages.js +1 -1
  21. package/dist/lib/utils/utils.d.ts +9 -0
  22. package/dist/lib/utils/utils.js +1 -1
  23. package/dist/lib/xcode/index.js +1 -1
  24. package/dist/lib/xcode/manifestSwiftTemplate.d.ts +1 -1
  25. package/dist/lib/xcode/manifestSwiftTemplate.js +1 -1
  26. package/dist/lib/xcode/xcodebuild.js +1 -1
  27. package/dist/lib/xcode/xcodeproject.js +1 -1
  28. package/dist/lib/xcode/xcrun.js +1 -1
  29. package/package.json +3 -2
  30. package/template/visionOSApp/Packages/RealityKitContent/.build/workspace-state.json +0 -7
  31. package/template/visionOSApp/Packages/RealityKitContent/.swiftpm/xcode/xcuserdata/bytedance.xcuserdatad/xcschemes/xcschememanagement.plist +0 -14
  32. package/template/visionOSApp/Packages/RealityKitContent/Package.realitycomposerpro/ProjectData/main.json +0 -11
  33. package/template/visionOSApp/Packages/RealityKitContent/Package.realitycomposerpro/WorkspaceData/SceneMetadataList.json +0 -112
  34. package/template/visionOSApp/Packages/RealityKitContent/Package.realitycomposerpro/WorkspaceData/Settings.rcprojectdata +0 -17
  35. package/template/visionOSApp/Packages/RealityKitContent/Package.swift +0 -27
  36. package/template/visionOSApp/Packages/RealityKitContent/README.md +0 -3
  37. package/template/visionOSApp/Packages/RealityKitContent/Sources/RealityKitContent/RealityKitContent.rkassets/Immersive.usda +0 -50
  38. package/template/visionOSApp/Packages/RealityKitContent/Sources/RealityKitContent/RealityKitContent.rkassets/Materials/GridMaterial.usda +0 -216
  39. package/template/visionOSApp/Packages/RealityKitContent/Sources/RealityKitContent/RealityKitContent.rkassets/Scene.usda +0 -59
  40. package/template/visionOSApp/Packages/RealityKitContent/Sources/RealityKitContent/RealityKitContent.swift +0 -4
  41. package/template/visionOSApp/web-spatial/Assets.xcassets/AppIcon.solidimagestack/Back.solidimagestacklayer/Content.imageset/Contents.json +0 -12
  42. package/template/visionOSApp/web-spatial/Assets.xcassets/AppIcon.solidimagestack/Back.solidimagestacklayer/Contents.json +0 -6
  43. package/template/visionOSApp/web-spatial/Assets.xcassets/AppIcon.solidimagestack/Contents.json +0 -17
  44. package/template/visionOSApp/web-spatial/Assets.xcassets/AppIcon.solidimagestack/Front.solidimagestacklayer/Content.imageset/Contents.json +0 -12
  45. package/template/visionOSApp/web-spatial/Assets.xcassets/AppIcon.solidimagestack/Front.solidimagestacklayer/Contents.json +0 -6
  46. package/template/visionOSApp/web-spatial/Assets.xcassets/AppIcon.solidimagestack/Middle.solidimagestacklayer/Content.imageset/Contents.json +0 -12
  47. package/template/visionOSApp/web-spatial/Assets.xcassets/AppIcon.solidimagestack/Middle.solidimagestacklayer/Contents.json +0 -6
  48. package/template/visionOSApp/web-spatial/Assets.xcassets/Contents.json +0 -6
  49. package/template/visionOSApp/web-spatial/Info.plist +0 -33
  50. package/template/visionOSApp/web-spatial/Preview Content/Preview Assets.xcassets/Contents.json +0 -6
  51. package/template/visionOSApp/web-spatial/libs/EventEmitter.swift +0 -32
  52. package/template/visionOSApp/web-spatial/libs/SpatialComponent.swift +0 -31
  53. package/template/visionOSApp/web-spatial/libs/SpatialEntity.swift +0 -179
  54. package/template/visionOSApp/web-spatial/libs/SpatialInputComponent.swift +0 -26
  55. package/template/visionOSApp/web-spatial/libs/SpatialMeshResource.swift +0 -19
  56. package/template/visionOSApp/web-spatial/libs/SpatialModel3DComponent.swift +0 -51
  57. package/template/visionOSApp/web-spatial/libs/SpatialModelComponent.swift +0 -32
  58. package/template/visionOSApp/web-spatial/libs/SpatialObject.swift +0 -144
  59. package/template/visionOSApp/web-spatial/libs/SpatialPhysicallyBasedMaterial.swift +0 -19
  60. package/template/visionOSApp/web-spatial/libs/SpatialViewComponent.swift +0 -15
  61. package/template/visionOSApp/web-spatial/libs/SpatialWindowComponent.swift +0 -420
  62. package/template/visionOSApp/web-spatial/libs/SpatialWindowContainer.swift +0 -149
  63. package/template/visionOSApp/web-spatial/libs/Utils/CommandManager.swift +0 -800
  64. package/template/visionOSApp/web-spatial/libs/Utils/Logger.swift +0 -36
  65. package/template/visionOSApp/web-spatial/libs/Utils/SceneManager.swift +0 -108
  66. package/template/visionOSApp/web-spatial/libs/Utils/WindowContainerMgr.swift +0 -113
  67. package/template/visionOSApp/web-spatial/libs/json/JsonParser.swift +0 -52
  68. package/template/visionOSApp/web-spatial/libs/uiKitDelegate/Window.swift +0 -34
  69. package/template/visionOSApp/web-spatial/libs/webView/UpdateSystem.swift +0 -33
  70. package/template/visionOSApp/web-spatial/libs/webView/backend/NativeWebView.swift +0 -319
  71. package/template/visionOSApp/web-spatial/libs/webView/manifest.swift +0 -92
  72. package/template/visionOSApp/web-spatial/static-web/index.html +0 -9
  73. package/template/visionOSApp/web-spatial/views/HideViewModifier.swift +0 -17
  74. package/template/visionOSApp/web-spatial/views/ImmersiveView.swift +0 -24
  75. package/template/visionOSApp/web-spatial/views/LoadingView.swift +0 -25
  76. package/template/visionOSApp/web-spatial/views/MaterialWithBorderCornerModifier.swift +0 -82
  77. package/template/visionOSApp/web-spatial/views/OpenDismissHandlerUI.swift +0 -52
  78. package/template/visionOSApp/web-spatial/views/PlainWindowContainerView.swift +0 -84
  79. package/template/visionOSApp/web-spatial/views/SpatialModel3DView.swift +0 -193
  80. package/template/visionOSApp/web-spatial/views/SpatialViewUI.swift +0 -168
  81. package/template/visionOSApp/web-spatial/views/SpatialWebViewUI.swift +0 -186
  82. package/template/visionOSApp/web-spatial/views/VolumetricWindowContainerView.swift +0 -38
  83. package/template/visionOSApp/web-spatial/views/ui/NavView.swift +0 -125
  84. package/template/visionOSApp/web-spatial/web_spatialApp.swift +0 -158
  85. package/template/visionOSApp/web-spatial.xcodeproj/project.pbxproj +0 -686
  86. package/template/visionOSApp/web-spatial.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -7
  87. package/template/visionOSApp/web-spatial.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +0 -8
  88. package/template/visionOSApp/web-spatial.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings +0 -5
  89. package/template/visionOSApp/web-spatial.xcodeproj/project.xcworkspace/xcuserdata/bytedance.xcuserdatad/WorkspaceSettings.xcsettings +0 -14
  90. package/template/visionOSApp/web-spatial.xcodeproj/xcshareddata/xcschemes/web-spatial.xcscheme +0 -115
  91. package/template/visionOSApp/web-spatial.xcodeproj/xcuserdata/bytedance.xcuserdatad/xcschemes/xcschememanagement.plist +0 -27
  92. package/template/visionOSApp/web-spatialTests/web_spatialTests.swift +0 -34
@@ -1,168 +0,0 @@
1
- //
2
- // SpatialViewUI.swift
3
- // web-spatial
4
- //
5
- // Created by ByteDance on 11/6/24.
6
- //
7
- import RealityKit
8
- import SwiftUI
9
-
10
- extension View {
11
- @ViewBuilder
12
- func `if`<Content: View>(_ condition: Bool, transform: (Self) -> Content) -> some View {
13
- if condition {
14
- transform(self)
15
- } else {
16
- self
17
- }
18
- }
19
- }
20
-
21
- struct SpatialViewUI: View {
22
- @Environment(SpatialEntity.self) var ent: SpatialEntity
23
- @State var isRoot = false
24
-
25
- // Entity which will contain all the content of this realityView and scale to fit frame
26
- @State var world = Entity()
27
- @State var portal = Entity()
28
- @State var light = PointLight()
29
- @State var portalModel = ModelComponent(
30
- mesh: .generatePlane(width: 1.0, height: 1.0, cornerRadius: 0.0),
31
- materials: [PortalMaterial()]
32
- )
33
- @State var worldComponent = WorldComponent()
34
-
35
- private func toJson(val: SIMD3<Float>) -> String {
36
- return "{x: " + String(val.x) + ",y: " + String(val.y) + ",z: " + String(val.z) + "}"
37
- }
38
-
39
- var dragGesture: some Gesture {
40
- DragGesture(minimumDistance: 0).handActivationBehavior(.automatic)
41
- .targetedToAnyEntity()
42
- .onChanged { value in
43
- let startPos = value.convert(value.startLocation3D, from: .local, to: .scene)
44
- let translate = value.convert(value.location3D, from: .local, to: .scene)
45
- let spatialEntity = value.entity.components[SpatialBridgeComponent.self]!.spatialEntity
46
- let ic = spatialEntity.getComponent(SpatialInputComponent.self)!
47
-
48
- if !ic.isDragging {
49
- ic.isDragging = true
50
- ic.trackedPosition = startPos
51
- let delta = translate - ic.trackedPosition
52
- ic.trackedPosition = translate
53
-
54
- ic.wv!.fireComponentEvent(componentId: ic.id, data: "{eventType: 'dragstart', translate: " + toJson(val: delta) + "}")
55
- } else {
56
- let delta = translate - ic.trackedPosition
57
- ic.trackedPosition = translate
58
- ic.wv!.fireComponentEvent(componentId: ic.id, data: "{eventType: 'drag', translate: " + toJson(val: delta) + "}")
59
- }
60
- }
61
- .onEnded { value in
62
- let spatialEntity = value.entity.components[SpatialBridgeComponent.self]!.spatialEntity
63
- let ic = spatialEntity.getComponent(SpatialInputComponent.self)!
64
- ic.wv!.fireComponentEvent(componentId: ic.id, data: "{eventType: 'dragend'}")
65
- ic.isDragging = false
66
- }
67
- }
68
-
69
- var body: some View {
70
- if let viewComponent = ent.getComponent(SpatialViewComponent.self) {
71
- GeometryReader3D { proxy in
72
- // Get dimensions of the frame
73
- let proxySize3d = proxy.frame(in: .local)
74
-
75
- RealityView { _, _ in
76
- } update: { content, attachments in
77
- // Scale content so it will be a 1x1x1 space and not exceed the frame
78
- let viewSpaceDimensions = content.convert(proxySize3d, from: .local, to: content)
79
- let newScale = min(viewSpaceDimensions.extents.x, viewSpaceDimensions.extents.y)
80
-
81
- world.transform.scale.x = newScale
82
- world.transform.scale.y = newScale
83
- world.transform.scale.z = newScale
84
- portal.transform.scale.x = newScale
85
- portal.transform.scale.y = newScale
86
- portal.transform.scale.z = newScale
87
-
88
- if !isRoot {
89
- // Pull out content so volume sits in front of the page
90
- world.transform.translation.z = world.transform.scale.z / 2
91
- }
92
-
93
- for (_, entity) in ent.getEntities() {
94
- world.addChild(entity.modelEntity)
95
- }
96
-
97
- // Add attachments for window entities
98
- let entities = ent.getEntities().filter { _, entity in
99
- entity.coordinateSpace == .APP && entity.hasComponent(SpatialWindowComponent.self)
100
- }
101
- for key in Array(entities.keys) {
102
- let e = entities[key]!
103
- let windowComponent = e.getComponent(SpatialWindowComponent.self)
104
- if windowComponent != nil && e.coordinateSpace == .APP {
105
- if let windowAttachment = attachments.entity(for: key) {
106
- if e.modelEntity.children.count == 0 {
107
- e.modelEntity.addChild(windowAttachment, preservingWorldTransform: false)
108
-
109
- // Scale the window to fit the resolution to unit ratio as defined by setResolution API
110
- let b = windowAttachment.attachment.bounds
111
- let wv = e.getComponent(SpatialWindowComponent.self)!
112
- let scaleFact = (Float(wv.resolutionX) / 1360.0) / (b.max.x - b.min.x)
113
- windowAttachment.scale.x = scaleFact
114
- windowAttachment.scale.y = scaleFact
115
- windowAttachment.scale.z = scaleFact
116
- }
117
- }
118
- }
119
- }
120
- if viewComponent.isPortal {
121
- // Setup portal
122
- portal.components.set(portalModel)
123
- portal.transform.translation.z = 0.0001 // avoid z fighting
124
- if !portal.components.has(PortalComponent.self) {
125
- portal.components.set(PortalComponent(target: world))
126
- }
127
-
128
- // Setup default light
129
- light.light.intensity = 5000
130
- light.position.z = 2
131
- light.position.y = 1
132
- light.position.x = 0.5
133
- world.addChild(light)
134
-
135
- // Position volume behind portal instead of in front
136
- world.transform.translation.z *= -1
137
-
138
- // Add portal to scene
139
- world.components.set(worldComponent)
140
- content.add(portal)
141
- } else {
142
- // Remove portal elements/components
143
- content.remove(portal)
144
- world.components.remove(WorldComponent.self)
145
- world.removeChild(light)
146
- }
147
-
148
- content.add(world)
149
- }
150
- attachments: {
151
- // Create an attachment for each window component
152
- let entities = ent.getEntities().filter { _, entity in
153
- entity.coordinateSpace == .APP && entity.hasComponent(SpatialWindowComponent.self)
154
- }
155
- ForEach(Array(entities.keys), id: \.self) { key in
156
- let entity = entities[key]!
157
- let wv = entity.getComponent(SpatialWindowComponent.self)!
158
- Attachment(id: key) {
159
- SpatialWebViewUI().environment(entity).frame(width: wv.resolutionX, height: wv.resolutionY)
160
- }
161
- }
162
- }.gesture(dragGesture).if(!isRoot) { view in
163
- view.clipped()
164
- }
165
- }
166
- }
167
- }
168
- }
@@ -1,186 +0,0 @@
1
- //
2
- // SpatialWebViewUI.swift
3
- // web-spatial
4
- //
5
- // Created by ByteDance on 5/9/24.
6
- //
7
-
8
- import RealityKit
9
- import SwiftUI
10
-
11
- // Using scrollview has some side effects so only use it on elements we want to clip the edges of
12
- // Seems only scrollview has this clipping property so far on visionOS otherwise we would use ZStack
13
- struct OptionalClip<Content: View>: View {
14
- var clipEnabled = true
15
- let viewBuilder: () -> Content
16
-
17
- var body: some View {
18
- if clipEnabled {
19
- ScrollView {
20
- viewBuilder()
21
- }.offset(z: CGFloat(0)).frame(maxWidth: .infinity, maxHeight: .infinity).scrollDisabled(true)
22
- } else {
23
- viewBuilder()
24
- }
25
- }
26
- }
27
-
28
- struct SpatialWebViewUI: View {
29
- @Environment(SpatialEntity.self) var ent: SpatialEntity
30
- var body: some View {
31
- if let wv = ent.getComponent(SpatialWindowComponent.self) {
32
- let parentYOffset = Float(wv.scrollOffset.y)
33
-
34
- let childEntities = ent.getEntities()
35
-
36
- // Display child entities of the webview
37
- ZStack {
38
- OptionalClip(clipEnabled: ent.coordinateSpace != .ROOT && wv.isScrollEnabled()) {
39
- ZStack {
40
- ForEach(Array(childEntities.keys), id: \.self) { key in
41
- if let e = childEntities[key] {
42
- let _ = e.forceUpdate ? 0 : 0
43
- if let childWindowcomponent = e.getComponent(SpatialWindowComponent.self) {
44
- if e.coordinateSpace == .DOM {
45
- let view = childWindowcomponent
46
- let x = CGFloat(e.modelEntity.position.x)
47
- let y = CGFloat(e.modelEntity.position.y - (view.scrollWithParent ? parentYOffset : 0))
48
- let z = CGFloat(e.modelEntity.position.z)
49
- let width = CGFloat(view.resolutionX)
50
- let height = CGFloat(view.resolutionY)
51
- let anchor = view.rotationAnchor
52
-
53
- // Matrix = MTranslate X MRotate X MScale
54
- SpatialWebViewUI().environment(e)
55
- .frame(width: width, height: height)
56
- // use .offset(smallVal) to workaround for glassEffect not working and small width/height spatialDiv not working
57
- .offset(z: 0.0001)
58
- .scaleEffect(
59
- x: CGFloat(e.modelEntity.scale.x),
60
- y: CGFloat(e.modelEntity.scale.y),
61
- z: CGFloat(e.modelEntity.scale.z),
62
- anchor: anchor
63
- )
64
- .rotation3DEffect(
65
- Rotation3D(simd_quatf(
66
- ix: e.modelEntity.orientation.vector.x,
67
- iy: e.modelEntity.orientation.vector.y,
68
- iz: e.modelEntity.orientation.vector.z,
69
- r: e.modelEntity.orientation.vector.w
70
- )),
71
- anchor: anchor
72
- )
73
-
74
- .position(x: x, y: y)
75
- .offset(z: z)
76
- .zIndex(e.zIndex)
77
- .gesture(
78
- DragGesture()
79
- .onChanged { gesture in
80
- let scrollEnabled = view.isScrollEnabled()
81
- if !scrollEnabled, wv.isScrollEnabled() {
82
- if !view.dragStarted {
83
- view.dragStarted = true
84
- view.dragStart = (gesture.translation.height)
85
- }
86
-
87
- // TODO: this should have velocity
88
- let delta = view.dragStart - gesture.translation.height
89
- view.dragStart = gesture.translation.height
90
- wv.updateScrollOffset(delta: delta)
91
- }
92
- }
93
- .onEnded { _ in
94
- let scrollEnabled = view.isScrollEnabled()
95
- if !scrollEnabled, wv.isScrollEnabled() {
96
- view.dragStarted = false
97
- view.dragStart = 0
98
-
99
- wv.stopScrolling()
100
- }
101
- }
102
- )
103
- }
104
- }
105
- }
106
- }
107
-
108
- // Model3D content
109
- ForEach(Array(childEntities.keys), id: \.self) { key in
110
- if let e = childEntities[key] {
111
- let _ = e.forceUpdate ? 0 : 0
112
- SpatialModel3DView(parentYOffset: parentYOffset)
113
- .environment(e)
114
- }
115
- }
116
-
117
- // SpatialView content
118
- ForEach(Array(childEntities.keys), id: \.self) { key in
119
- if let e = childEntities[key] {
120
- if e.coordinateSpace == .DOM {
121
- if let viewComponent = e.getComponent(SpatialViewComponent.self) {
122
- let _ = e.forceUpdate ? 0 : 0
123
- let x = CGFloat(e.modelEntity.position.x)
124
- let y = CGFloat(e.modelEntity.position.y - parentYOffset)
125
- let z = CGFloat(e.modelEntity.position.z)
126
-
127
- let width = CGFloat(viewComponent.resolutionX)
128
- let height = CGFloat(viewComponent.resolutionY)
129
-
130
- SpatialViewUI().environment(e).frame(width: width, height: height).scaleEffect(
131
- x: CGFloat(e.modelEntity.scale.x),
132
- y: CGFloat(e.modelEntity.scale.y),
133
- z: CGFloat(e.modelEntity.scale.z)
134
- )
135
- .rotation3DEffect(
136
- Rotation3D(simd_quatf(
137
- ix: e.modelEntity.orientation.vector.x,
138
- iy: e.modelEntity.orientation.vector.y,
139
- iz: e.modelEntity.orientation.vector.z,
140
- r: e.modelEntity.orientation.vector.w
141
- ))
142
- ).position(x: x, y: y)
143
- .offset(z: z)
144
- }
145
- }
146
- }
147
- }
148
- }.frame(maxWidth: .infinity, maxHeight: .infinity).frame(maxDepth: 0, alignment: .back).offset(z: 0)
149
- }
150
-
151
- // Display the main webview
152
- if wv.didFailLoad {
153
- VStack {
154
- Text("Failed to load webpage. Is the server running?")
155
- .foregroundColor(.white)
156
- Button("Reload") {
157
- if let url = wv.getURL() {
158
- wv.navigateToURL(url: url)
159
- } else {
160
- logger.warning("Unable to reload URL")
161
- }
162
- }
163
- .foregroundColor(.white)
164
- }
165
- .frame(maxWidth: .infinity, maxHeight: .infinity).glassBackgroundEffect()
166
-
167
- } else {
168
- wv.getView()
169
- .materialWithBorderCorner(
170
- wv.backgroundMaterial,
171
- wv.cornerRadius
172
- )
173
-
174
- .frame(maxWidth: .infinity, maxHeight: .infinity)
175
- }
176
- }
177
- .opacity(wv.opacity)
178
- .hidden(!ent.visible)
179
- .ornament(attachmentAnchor: .scene(.bottomTrailing), contentAlignment: .bottomTrailing) {
180
- if wv.isRootWebview() {
181
- NavView(swc: wv)
182
- }
183
- }
184
- }
185
- }
186
- }
@@ -1,38 +0,0 @@
1
-
2
- //
3
- // VolumetricWindowContainerView.swift
4
- // web-spatial
5
- //
6
- // Created by ByteDance on 5/9/24.
7
- //
8
-
9
- import typealias RealityKit.Attachment
10
- import typealias RealityKit.Entity
11
- import typealias RealityKit.MeshResource
12
- import typealias RealityKit.Model3D
13
- import typealias RealityKit.ModelEntity
14
- import typealias RealityKit.RealityView
15
- import typealias RealityKit.SimpleMaterial
16
- import SwiftUI
17
-
18
- struct VolumetricWindowContainerView: View {
19
- @Environment(SpatialWindowContainer.self) var windowContainerContent: SpatialWindowContainer
20
-
21
- var body: some View {
22
- OpenDismissHandlerUI().environment(windowContainerContent).onDisappear {
23
- // Don't destroy immersive space content as it is reused next time its opened
24
- if windowContainerContent.id != SpatialWindowContainer.ImmersiveID {
25
- windowContainerContent.destroy()
26
- }
27
- }
28
-
29
- let entities = windowContainerContent.getEntities().filter { _, entity in
30
- entity.coordinateSpace == .ROOT && entity.hasComponent(SpatialViewComponent.self)
31
- }
32
-
33
- ForEach(Array(entities.keys), id: \.self) { key in
34
- let entity = entities[key]!
35
- SpatialViewUI(isRoot: true).environment(entity)
36
- }
37
- }
38
- }
@@ -1,125 +0,0 @@
1
- //
2
- // NavView.swift
3
- // web-spatial
4
- //
5
- // Created by ByteDance on 2025/1/8.
6
- //
7
-
8
- import SwiftUI
9
- import WebKit
10
-
11
- struct NavView: View {
12
- @State var swc: SpatialWindowComponent?
13
- @State var showUrl: Bool = true
14
- @State private var showCopyTip = false
15
- @State private var navWidth: CGFloat = 0
16
- @State private var navHeight: CGFloat = 0
17
- @State private var texWidth: CGFloat = 0
18
- @State private var firstGetSize: Bool = true
19
-
20
- var body: some View {
21
- ZStack(alignment: .bottomTrailing) {
22
- ZStack {}.frame(width: navWidth, height: navHeight)
23
- VStack(alignment: .trailing, spacing: 5) {
24
- if showUrl {
25
- Text(pwaManager.name).padding(10)
26
- if pwaManager.display == .minimal {
27
- HStack(spacing: 5) {
28
- Button(action: {
29
- swc?.goBack()
30
- }, label: {
31
- Image(systemName: "arrow.left")
32
- })
33
- .disabled(!(swc?.canGoBack ?? false))
34
- Button(action: {
35
- swc?.goForward()
36
- }, label: {
37
- Image(systemName: "arrow.right")
38
- })
39
- .disabled(!(swc?.canGoBack ?? false))
40
- Button(action: {
41
- swc?.reload()
42
- }, label: {
43
- Image(systemName: "arrow.clockwise")
44
- })
45
- Button(
46
- action: {
47
- swc?
48
- .navigateToURL(
49
- url: URL(string: pwaManager.start_url)!
50
- )
51
- },
52
- label: {
53
- Image(systemName: "house.fill")
54
- }
55
- )
56
- }
57
- }
58
- }
59
- HStack(spacing: 5) {
60
- if showUrl {
61
- Text(
62
- swc?.getURL()?.absoluteString ?? "http://localhost:5173/"
63
- )
64
- .padding()
65
- .lineLimit(1)
66
- .overlay(GeometryReader { geo -> AnyView in
67
- DispatchQueue.main.async {
68
- if geo.size.width > 0 {
69
- texWidth = .minimum(300, geo.size.width)
70
- }
71
- }
72
- return AnyView(EmptyView())
73
- })
74
- .frame(width: texWidth == 0 ? .infinity : texWidth)
75
- Button(action: {
76
- UIPasteboard.general.string = swc?.getURL()?.absoluteString ?? ""
77
- showCopyTip = true
78
- DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
79
- showCopyTip = false
80
- }
81
- }, label: {
82
- Text("copy")
83
- })
84
- }
85
-
86
- Button(action: {
87
- withAnimation(.easeInOut(duration: 0.5)) {
88
- showUrl.toggle()
89
- }
90
- }, label: {
91
- Image(systemName: showUrl ? "xmark" : "info")
92
- })
93
- }
94
- }
95
- .padding()
96
- .glassBackgroundEffect(in: RoundedRectangle(cornerRadius: 15))
97
- .popover(isPresented: $showCopyTip) {
98
- Text("copied!")
99
- .padding()
100
- .cornerRadius(10)
101
- }
102
- .overlay(GeometryReader { geo -> AnyView in
103
- DispatchQueue.main.async {
104
- if firstGetSize {
105
- navWidth = geo.size.width
106
- navHeight = geo.size.height
107
- firstGetSize.toggle()
108
- showUrl.toggle()
109
- print(navWidth)
110
- }
111
- }
112
- return AnyView(EmptyView())
113
- })
114
- .opacity(firstGetSize ? 0 : 1)
115
- }
116
- .frame(width: firstGetSize ? .infinity : navWidth, height: firstGetSize ? .infinity : navHeight)
117
- .offset(z: 30)
118
- }
119
- }
120
-
121
- struct NavView_Previews: PreviewProvider {
122
- static var previews: some View {
123
- NavView()
124
- }
125
- }
@@ -1,158 +0,0 @@
1
- //
2
- // web_spatialApp.swift
3
- // web-spatial
4
- //
5
- // Created by ByteDance on 5/8/24.
6
- //
7
-
8
- import typealias RealityKit.Attachment
9
- import typealias RealityKit.Entity
10
- import typealias RealityKit.MeshResource
11
- import typealias RealityKit.Model3D
12
- import typealias RealityKit.ModelEntity
13
- import typealias RealityKit.RealityView
14
- import typealias RealityKit.SimpleMaterial
15
- import SwiftUI
16
-
17
- let logger = Logger()
18
-
19
- // To load a local path, remove http:// eg. "static-web/"
20
- let nativeAPIVersion = "0.0.1"
21
-
22
- // detect when app properties like defaultSize change so we can avoid race condition of setting default values and then opening window container
23
- var sceneStateChangedCB: ((Any) -> Void) = { _ in
24
- }
25
-
26
- @main
27
- struct web_spatialApp: App {
28
- @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
29
- @State var root: SpatialWindowComponent? = nil
30
- @State var rootWGD: SpatialWindowContainer
31
- @State var initialLaunch = true
32
-
33
- @ObservedObject var wgm = WindowContainerMgr.Instance
34
-
35
- @Environment(\.scenePhase) private var scenePhase
36
-
37
- init() {
38
- logger.debug("WebSpatial App Started --------")
39
-
40
- // init global logger
41
- Logger.initLogger()
42
-
43
- // init pwa manager
44
- pwaManager._init()
45
-
46
- // create root SpatialWindowContainer and Immersive SpatialWindowContainer
47
- rootWGD = SpatialWindowContainer.createRootWindowContainer()
48
- let _ = SpatialWindowContainer.createImmersiveWindowContainer()
49
- }
50
-
51
- func getFileUrl() -> URL {
52
- return URL(string: pwaManager.start_url)!
53
- }
54
-
55
- // There seems to be a bug in WKWebView where it needs to be initialized after the app has loaded so we do this here instead of init()
56
- // https://forums.developer.apple.com/forums/thread/61432
57
- func initAppOnViewMount() {
58
- if root == nil {
59
- let fileUrl = getFileUrl()
60
-
61
- // Create a default entity with webview resource
62
- let rootEntity = SpatialEntity()
63
- rootEntity.coordinateSpace = CoordinateSpaceMode.ROOT
64
- let windowComponent = SpatialWindowComponent(parentWindowContainerID: rootWGD.id, url: fileUrl)
65
- rootEntity.addComponent(windowComponent)
66
- rootEntity.setParentWindowContainer(wg: rootWGD)
67
-
68
- root = windowComponent
69
- }
70
- }
71
-
72
- func getDefaultSize() -> CGSize {
73
- sceneStateChangedCB("")
74
- return wgm.getValue().defaultSize!
75
- }
76
-
77
- var body: some Scene {
78
- WindowGroup(id: "Plain", for: WindowContainerData.self) { $windowData in
79
- if windowData.windowContainerID == SpatialWindowContainer.getRootID() {
80
- VStack {}.onAppear { initAppOnViewMount() }
81
-
82
- PlainWindowContainerView().environment(rootWGD).background(Color.clear.opacity(0)).onOpenURL { myURL in
83
- initAppOnViewMount()
84
- let urlToLoad = pwaManager.checkInDeeplink(url: myURL.absoluteString)
85
-
86
- if let url = URL(string: urlToLoad) {
87
- root!.navigateToURL(url: url)
88
- }
89
- }
90
- } else {
91
- let wg = SpatialWindowContainer.getOrCreateSpatialWindowContainer(
92
- windowData.windowContainerID, windowData
93
- )
94
- PlainWindowContainerView().environment(wg)
95
- // we no longer need the initial windowGroup to live all the time
96
- // https://stackoverflow.com/questions/78567737/how-to-get-initial-windowgroup-to-reopen-on-launch-visionos
97
- // .handlesExternalEvents(preferring: [], allowing: [])
98
- }
99
- }
100
- defaultValue: {
101
- WindowContainerData(
102
- windowStyle: "Plain",
103
- windowContainerID: SpatialWindowContainer.getRootID()
104
- )
105
- }
106
- .windowStyle(.plain).onChange(of: scenePhase) {
107
- oldPhase,
108
- newPhase in
109
- if oldPhase == .background && newPhase == .inactive {
110
- if initialLaunch {
111
- // App initial open
112
- initialLaunch = false
113
- } else {
114
- // App reopened
115
-
116
- let fileUrl = getFileUrl()
117
- if let awid = SpatialWindowContainer.firstActivePlainWindowContainerId,
118
- let wc = SpatialWindowContainer.getSpatialWindowContainer(
119
- awid
120
- )
121
- {
122
- let rootEntity = wc.getEntities().filter {
123
- $0.value.getComponent(SpatialWindowComponent.self) != nil && $0.value.coordinateSpace == .ROOT
124
- }.first?.value
125
-
126
- if let wv = rootEntity?.getComponent(SpatialWindowComponent.self) {
127
- wv.navigateToURL(url: fileUrl)
128
- }
129
- // reset to mainScene size
130
- wgm.setToMainSceneCfg()
131
- wc.setSize.send(getDefaultSize())
132
- }
133
- }
134
- }
135
-
136
- }.defaultSize(
137
- getDefaultSize()
138
- ).windowResizability(
139
- wgm.getValue().windowResizability!
140
- )
141
-
142
- WindowGroup(id: "Volumetric", for: WindowContainerData.self) { $windowData in
143
- let wg = SpatialWindowContainer.getOrCreateSpatialWindowContainer(windowData!.windowContainerID, windowData!)
144
- VolumetricWindowContainerView().environment(wg).handlesExternalEvents(preferring: [], allowing: [])
145
-
146
- }.windowStyle(.volumetric).defaultSize(width: 1, height: 1, depth: 1, in: .meters)
147
-
148
- ImmersiveSpace(id: "ImmersiveSpace") {
149
- if let wg = SpatialWindowContainer.getImmersiveWindowContainer() {
150
- VolumetricWindowContainerView().environment(wg).handlesExternalEvents(preferring: [], allowing: [])
151
- }
152
- }
153
-
154
- WindowGroup(id: "loading") {
155
- LoadingView()
156
- }
157
- }
158
- }