@webspatial/builder 0.0.6 → 0.0.8
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.
- package/dist/index.js +1 -1
- package/dist/lib/Cli.js +1 -1
- package/dist/lib/cmds/build.js +1 -1
- package/dist/lib/cmds/check.js +1 -1
- package/dist/lib/cmds/help.js +1 -1
- package/dist/lib/cmds/version.js +1 -1
- package/dist/lib/pwa/config.js +1 -1
- package/dist/lib/pwa/index.js +1 -1
- package/dist/lib/pwa/validate.js +1 -1
- package/dist/lib/resource/file.js +1 -1
- package/dist/lib/resource/imageHelper.js +1 -1
- package/dist/lib/resource/index.js +1 -1
- package/dist/lib/resource/load.js +1 -1
- package/dist/lib/utils/CustomError.js +1 -1
- package/dist/lib/utils/FetchUtils-1.js +1 -1
- package/dist/lib/utils/Log.js +1 -1
- package/dist/lib/utils/fetch.js +1 -1
- package/dist/lib/utils/messages.js +1 -1
- package/dist/lib/utils/utils.js +1 -1
- package/dist/lib/xcode/index.js +1 -1
- package/dist/lib/xcode/manifestSwiftTemplate.d.ts +1 -1
- package/dist/lib/xcode/manifestSwiftTemplate.js +1 -1
- package/dist/lib/xcode/xcodebuild.js +1 -1
- package/dist/lib/xcode/xcodeproject.js +1 -1
- package/dist/lib/xcode/xcrun.js +1 -1
- package/package.json +1 -1
- package/template/visionOSApp/web-spatial/libs/SpatialWindowContainer.swift +20 -3
- package/template/visionOSApp/web-spatial/libs/webView/manifest.swift +3 -2
- package/template/visionOSApp/web-spatial/views/SpatialWebViewUI.swift +124 -125
- package/template/visionOSApp/web-spatial/views/VolumetricWindowContainerView.swift +5 -1
- package/template/visionOSApp/web-spatial/views/ui/NavView.swift +95 -58
- package/template/visionOSApp/web-spatial/web_spatialApp.swift +34 -10
- package/template/visionOSApp/web-spatial.xcodeproj/project.xcworkspace/xcuserdata/bytedance.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
|
@@ -34,108 +34,32 @@ struct SpatialWebViewUI: View {
|
|
|
34
34
|
let childEntities = ent.getEntities()
|
|
35
35
|
|
|
36
36
|
// Display child entities of the webview
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
ZStack {
|
|
45
|
-
ForEach(Array(childEntities.keys), id: \.self) { key in
|
|
46
|
-
if let e = childEntities[key] {
|
|
47
|
-
let _ = e.forceUpdate ? 0 : 0
|
|
48
|
-
if let childWindowcomponent = e.getComponent(SpatialWindowComponent.self) {
|
|
49
|
-
if e.coordinateSpace == .DOM {
|
|
50
|
-
let view = childWindowcomponent
|
|
51
|
-
let x = CGFloat(e.modelEntity.position.x)
|
|
52
|
-
let y = CGFloat(e.modelEntity.position.y - (view.scrollWithParent ? parentYOffset : 0))
|
|
53
|
-
let z = CGFloat(e.modelEntity.position.z)
|
|
54
|
-
let width = CGFloat(view.resolutionX)
|
|
55
|
-
let height = CGFloat(view.resolutionY)
|
|
56
|
-
let anchor = view.rotationAnchor
|
|
57
|
-
|
|
58
|
-
// Matrix = MTranslate X MRotate X MScale
|
|
59
|
-
SpatialWebViewUI().environment(e)
|
|
60
|
-
.frame(width: width, height: height)
|
|
61
|
-
// use .offset(smallVal) to workaround for glassEffect not working and small width/height spatialDiv not working
|
|
62
|
-
.offset(z: 0.0001)
|
|
63
|
-
.scaleEffect(
|
|
64
|
-
x: CGFloat(e.modelEntity.scale.x),
|
|
65
|
-
y: CGFloat(e.modelEntity.scale.y),
|
|
66
|
-
z: CGFloat(e.modelEntity.scale.z),
|
|
67
|
-
anchor: anchor
|
|
68
|
-
)
|
|
69
|
-
.rotation3DEffect(
|
|
70
|
-
Rotation3D(simd_quatf(
|
|
71
|
-
ix: e.modelEntity.orientation.vector.x,
|
|
72
|
-
iy: e.modelEntity.orientation.vector.y,
|
|
73
|
-
iz: e.modelEntity.orientation.vector.z,
|
|
74
|
-
r: e.modelEntity.orientation.vector.w
|
|
75
|
-
)),
|
|
76
|
-
anchor: anchor
|
|
77
|
-
)
|
|
78
|
-
|
|
79
|
-
.position(x: x, y: y)
|
|
80
|
-
.offset(z: z)
|
|
81
|
-
.zIndex(e.zIndex)
|
|
82
|
-
.gesture(
|
|
83
|
-
DragGesture()
|
|
84
|
-
.onChanged { gesture in
|
|
85
|
-
let scrollEnabled = view.isScrollEnabled()
|
|
86
|
-
if !scrollEnabled, wv.isScrollEnabled() {
|
|
87
|
-
if !view.dragStarted {
|
|
88
|
-
view.dragStarted = true
|
|
89
|
-
view.dragStart = (gesture.translation.height)
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
// TODO: this should have velocity
|
|
93
|
-
let delta = view.dragStart - gesture.translation.height
|
|
94
|
-
view.dragStart = gesture.translation.height
|
|
95
|
-
wv.updateScrollOffset(delta: delta)
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
.onEnded { _ in
|
|
99
|
-
let scrollEnabled = view.isScrollEnabled()
|
|
100
|
-
if !scrollEnabled, wv.isScrollEnabled() {
|
|
101
|
-
view.dragStarted = false
|
|
102
|
-
view.dragStart = 0
|
|
103
|
-
|
|
104
|
-
wv.stopScrolling()
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
)
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
// Model3D content
|
|
114
|
-
ForEach(Array(childEntities.keys), id: \.self) { key in
|
|
115
|
-
if let e = childEntities[key] {
|
|
116
|
-
let _ = e.forceUpdate ? 0 : 0
|
|
117
|
-
SpatialModel3DView(parentYOffset: parentYOffset)
|
|
118
|
-
.environment(e)
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
// SpatialView content
|
|
123
|
-
ForEach(Array(childEntities.keys), id: \.self) { key in
|
|
124
|
-
if let e = childEntities[key] {
|
|
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) {
|
|
125
44
|
if e.coordinateSpace == .DOM {
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
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(
|
|
136
59
|
x: CGFloat(e.modelEntity.scale.x),
|
|
137
60
|
y: CGFloat(e.modelEntity.scale.y),
|
|
138
|
-
z: CGFloat(e.modelEntity.scale.z)
|
|
61
|
+
z: CGFloat(e.modelEntity.scale.z),
|
|
62
|
+
anchor: anchor
|
|
139
63
|
)
|
|
140
64
|
.rotation3DEffect(
|
|
141
65
|
Rotation3D(simd_quatf(
|
|
@@ -143,44 +67,119 @@ struct SpatialWebViewUI: View {
|
|
|
143
67
|
iy: e.modelEntity.orientation.vector.y,
|
|
144
68
|
iz: e.modelEntity.orientation.vector.z,
|
|
145
69
|
r: e.modelEntity.orientation.vector.w
|
|
146
|
-
))
|
|
147
|
-
|
|
70
|
+
)),
|
|
71
|
+
anchor: anchor
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
.position(x: x, y: y)
|
|
148
75
|
.offset(z: z)
|
|
149
|
-
|
|
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
|
+
)
|
|
150
103
|
}
|
|
151
104
|
}
|
|
152
105
|
}
|
|
153
|
-
}
|
|
154
|
-
}
|
|
106
|
+
}
|
|
155
107
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
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
|
+
}
|
|
166
145
|
}
|
|
167
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?")
|
|
168
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
|
+
}
|
|
169
162
|
}
|
|
170
|
-
.
|
|
163
|
+
.foregroundColor(.white)
|
|
164
|
+
}
|
|
165
|
+
.frame(maxWidth: .infinity, maxHeight: .infinity).glassBackgroundEffect()
|
|
171
166
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
167
|
+
} else {
|
|
168
|
+
wv.getView()
|
|
169
|
+
.materialWithBorderCorner(
|
|
170
|
+
wv.backgroundMaterial,
|
|
171
|
+
wv.cornerRadius
|
|
172
|
+
)
|
|
178
173
|
|
|
179
|
-
|
|
180
|
-
|
|
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)
|
|
181
182
|
}
|
|
182
|
-
.opacity(wv.opacity)
|
|
183
|
-
.hidden(!ent.visible)
|
|
184
183
|
}
|
|
185
184
|
}
|
|
186
185
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
|
|
1
2
|
//
|
|
2
3
|
// VolumetricWindowContainerView.swift
|
|
3
4
|
// web-spatial
|
|
@@ -19,7 +20,10 @@ struct VolumetricWindowContainerView: View {
|
|
|
19
20
|
|
|
20
21
|
var body: some View {
|
|
21
22
|
OpenDismissHandlerUI().environment(windowContainerContent).onDisappear {
|
|
22
|
-
|
|
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
|
+
}
|
|
23
27
|
}
|
|
24
28
|
|
|
25
29
|
let entities = windowContainerContent.getEntities().filter { _, entity in
|
|
@@ -10,79 +10,116 @@ import WebKit
|
|
|
10
10
|
|
|
11
11
|
struct NavView: View {
|
|
12
12
|
@State var swc: SpatialWindowComponent?
|
|
13
|
-
@State var showUrl: Bool =
|
|
13
|
+
@State var showUrl: Bool = true
|
|
14
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
|
|
15
19
|
|
|
16
20
|
var body: some View {
|
|
17
21
|
ZStack(alignment: .bottomTrailing) {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
22
|
+
ZStack {}.frame(width: navWidth, height: navHeight)
|
|
23
|
+
VStack(alignment: .trailing, spacing: 5) {
|
|
24
|
+
if showUrl {
|
|
25
|
+
Text(pwaManager.name).padding(10)
|
|
21
26
|
if pwaManager.display == .minimal {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
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())
|
|
32
73
|
})
|
|
33
|
-
.
|
|
74
|
+
.frame(width: texWidth == 0 ? .infinity : texWidth)
|
|
34
75
|
Button(action: {
|
|
35
|
-
swc?.
|
|
76
|
+
UIPasteboard.general.string = swc?.getURL()?.absoluteString ?? ""
|
|
77
|
+
showCopyTip = true
|
|
78
|
+
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
|
|
79
|
+
showCopyTip = false
|
|
80
|
+
}
|
|
36
81
|
}, label: {
|
|
37
|
-
|
|
82
|
+
Text("copy")
|
|
38
83
|
})
|
|
39
|
-
Button(
|
|
40
|
-
action: {
|
|
41
|
-
swc?
|
|
42
|
-
.navigateToURL(
|
|
43
|
-
url: URL(string: pwaManager.start_url)!
|
|
44
|
-
)
|
|
45
|
-
},
|
|
46
|
-
label: {
|
|
47
|
-
Image(systemName: "house.fill")
|
|
48
|
-
}
|
|
49
|
-
)
|
|
50
84
|
}
|
|
85
|
+
|
|
51
86
|
Button(action: {
|
|
52
|
-
|
|
87
|
+
withAnimation(.easeInOut(duration: 0.5)) {
|
|
88
|
+
showUrl.toggle()
|
|
89
|
+
}
|
|
53
90
|
}, label: {
|
|
54
|
-
Image(systemName: "info
|
|
91
|
+
Image(systemName: showUrl ? "xmark" : "info")
|
|
55
92
|
})
|
|
56
93
|
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
)
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
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)
|
|
68
110
|
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
Button(action: {
|
|
74
|
-
showUrl = false
|
|
75
|
-
}, label: {
|
|
76
|
-
Text("X")
|
|
77
|
-
})
|
|
78
|
-
}.glassBackgroundEffect(in: .rect).cornerRadius(15).offset(y: 35).opacity(showUrl ? 1 : 0).animation(.easeOut, value: 0.2)
|
|
79
|
-
}
|
|
80
|
-
.zIndex(10) // closer to user
|
|
81
|
-
.popover(isPresented: $showCopyTip) {
|
|
82
|
-
Text("copied!")
|
|
83
|
-
.padding()
|
|
84
|
-
.background(.ultraThinMaterial)
|
|
85
|
-
.cornerRadius(10)
|
|
111
|
+
}
|
|
112
|
+
return AnyView(EmptyView())
|
|
113
|
+
})
|
|
114
|
+
.opacity(firstGetSize ? 0 : 1)
|
|
86
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()
|
|
87
124
|
}
|
|
88
125
|
}
|
|
@@ -92,24 +92,47 @@ struct web_spatialApp: App {
|
|
|
92
92
|
windowData.windowContainerID, windowData
|
|
93
93
|
)
|
|
94
94
|
PlainWindowContainerView().environment(wg)
|
|
95
|
-
|
|
96
|
-
|
|
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: [])
|
|
97
98
|
}
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
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
|
|
102
109
|
if oldPhase == .background && newPhase == .inactive {
|
|
103
110
|
if initialLaunch {
|
|
104
111
|
// App initial open
|
|
105
112
|
initialLaunch = false
|
|
106
113
|
} else {
|
|
107
114
|
// App reopened
|
|
115
|
+
|
|
108
116
|
let fileUrl = getFileUrl()
|
|
109
|
-
|
|
110
|
-
|
|
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
|
+
}
|
|
111
133
|
}
|
|
112
134
|
}
|
|
135
|
+
|
|
113
136
|
}.defaultSize(
|
|
114
137
|
getDefaultSize()
|
|
115
138
|
).windowResizability(
|
|
@@ -123,8 +146,9 @@ struct web_spatialApp: App {
|
|
|
123
146
|
}.windowStyle(.volumetric).defaultSize(width: 1, height: 1, depth: 1, in: .meters)
|
|
124
147
|
|
|
125
148
|
ImmersiveSpace(id: "ImmersiveSpace") {
|
|
126
|
-
let wg = SpatialWindowContainer.getImmersiveWindowContainer()
|
|
127
|
-
|
|
149
|
+
if let wg = SpatialWindowContainer.getImmersiveWindowContainer() {
|
|
150
|
+
VolumetricWindowContainerView().environment(wg).handlesExternalEvents(preferring: [], allowing: [])
|
|
151
|
+
}
|
|
128
152
|
}
|
|
129
153
|
|
|
130
154
|
WindowGroup(id: "loading") {
|