@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,179 +0,0 @@
1
- import RealityKit
2
- import SwiftUI
3
-
4
- // Using scrollview has some side effects so only use it on elements we want to clip the edges of
5
- // Seems only scrollview has this clipping property so far on visionOS otherwise we would use ZStack
6
- struct OptionalClip<Content: View>: View {
7
- var clipEnabled = true
8
- let viewBuilder: () -> Content
9
-
10
- var body: some View {
11
- if clipEnabled {
12
- ScrollView {
13
- viewBuilder()
14
- }.offset(z: CGFloat(0)).frame(maxWidth: .infinity, maxHeight: .infinity).scrollDisabled(true)
15
- } else {
16
- viewBuilder()
17
- }
18
- }
19
- }
20
-
21
- // zIndex() have some bug, so use zOrderBias to simulate zIndex effect
22
- let zOrderBias = 0.001
23
-
24
- struct SpatialWebViewUI: View {
25
- @Environment(SpatialEntity.self) var ent: SpatialEntity
26
- var body: some View {
27
- if let wv = ent.getComponent(SpatialWindowComponent.self) {
28
- let parentYOffset = Float(wv.scrollOffset.y)
29
-
30
- let childEntities = ent.getEntities()
31
- // Display child entities of the webview
32
- ZStack {
33
- OptionalClip(clipEnabled: ent.coordinateSpace != .ROOT && wv.isScrollEnabled()) {
34
- ZStack {
35
- ForEach(Array(childEntities.keys), id: \.self) { key in
36
- if let e = childEntities[key] {
37
- let _ = e.forceUpdate ? 0 : 0
38
- if let childWindowcomponent = e.getComponent(SpatialWindowComponent.self) {
39
- if e.coordinateSpace == .DOM {
40
- let view = childWindowcomponent
41
- let x = CGFloat(e.modelEntity.position.x)
42
- let y = CGFloat(e.modelEntity.position.y - (view.scrollWithParent ? parentYOffset : 0))
43
- let z = CGFloat(e.modelEntity.position.z) + (e.zIndex * zOrderBias)
44
- let width = CGFloat(view.resolutionX)
45
- let height = CGFloat(view.resolutionY)
46
- let anchor = view.rotationAnchor
47
-
48
- // Matrix = MTranslate X MRotate X MScale
49
- SpatialWebViewUI().environment(e)
50
- .frame(width: width, height: height)
51
- // use .offset(smallVal) to workaround for glassEffect not working and small width/height spatialDiv not working
52
- .offset(z: 0.0001)
53
- .scaleEffect(
54
- x: CGFloat(e.modelEntity.scale.x),
55
- y: CGFloat(e.modelEntity.scale.y),
56
- z: CGFloat(e.modelEntity.scale.z),
57
- anchor: anchor
58
- )
59
- .rotation3DEffect(
60
- Rotation3D(simd_quatf(
61
- ix: e.modelEntity.orientation.vector.x,
62
- iy: e.modelEntity.orientation.vector.y,
63
- iz: e.modelEntity.orientation.vector.z,
64
- r: e.modelEntity.orientation.vector.w
65
- )),
66
- anchor: anchor
67
- )
68
-
69
- .position(x: x, y: y)
70
- .offset(z: z)
71
- .gesture(
72
- DragGesture()
73
- .onChanged { gesture in
74
- let scrollEnabled = view.isScrollEnabled()
75
- if !scrollEnabled {
76
- // Check if there is a nearest scroll-enabled SpatialWindowComponent in the current SpatialEntity
77
- // and scroll it if it exists
78
- if let targetScrollWV = wv.findNearestScrollEnabledSpatialWindowComponent() {
79
- if !view.dragStarted {
80
- view.dragStarted = true
81
- view.dragStart = (gesture.translation.height)
82
- }
83
-
84
- // TODO: this should have velocity
85
- let delta = view.dragStart - gesture.translation.height
86
- view.dragStart = gesture.translation.height
87
- targetScrollWV.updateScrollOffset(delta: delta)
88
- }
89
- }
90
- }
91
- .onEnded { _ in
92
- let scrollEnabled = view.isScrollEnabled()
93
- if !scrollEnabled {
94
- if let targetScrollWV = wv.findNearestScrollEnabledSpatialWindowComponent() {
95
- view.dragStarted = false
96
- view.dragStart = 0
97
- targetScrollWV.stopScrolling()
98
- }
99
- }
100
- }
101
- )
102
- }
103
- }
104
- }
105
- }
106
-
107
- // Model3D content
108
- ForEach(Array(childEntities.keys), id: \.self) { key in
109
- if let e = childEntities[key] {
110
- let _ = e.forceUpdate ? 0 : 0
111
- SpatialModel3DView(parentYOffset: parentYOffset)
112
- .environment(e)
113
- }
114
- }
115
-
116
- // SpatialView content
117
- ForEach(Array(childEntities.keys), id: \.self) { key in
118
- if let e = childEntities[key] {
119
- if e.coordinateSpace == .DOM {
120
- if let viewComponent = e.getComponent(SpatialViewComponent.self) {
121
- let _ = e.forceUpdate ? 0 : 0
122
- let x = CGFloat(e.modelEntity.position.x)
123
- let y = CGFloat(e.modelEntity.position.y - parentYOffset)
124
- let z = CGFloat(e.modelEntity.position.z)
125
-
126
- let width = CGFloat(viewComponent.resolutionX)
127
- let height = CGFloat(viewComponent.resolutionY)
128
-
129
- SpatialViewUI().environment(e).frame(width: width, height: height).scaleEffect(
130
- x: CGFloat(e.modelEntity.scale.x),
131
- y: CGFloat(e.modelEntity.scale.y),
132
- z: CGFloat(e.modelEntity.scale.z)
133
- )
134
- .rotation3DEffect(
135
- Rotation3D(simd_quatf(
136
- ix: e.modelEntity.orientation.vector.x,
137
- iy: e.modelEntity.orientation.vector.y,
138
- iz: e.modelEntity.orientation.vector.z,
139
- r: e.modelEntity.orientation.vector.w
140
- ))
141
- ).position(x: x, y: y)
142
- .offset(z: z)
143
- }
144
- }
145
- }
146
- }
147
- }.frame(maxWidth: .infinity, maxHeight: .infinity).frame(maxDepth: 0, alignment: .back).offset(z: 0)
148
- }
149
-
150
- // Display the main webview
151
- if wv.didFailLoad {
152
- VStack {
153
- Text("Failed to load webpage. Is the server running?")
154
- .foregroundColor(.white)
155
- Button("Reload") {
156
- if let url = wv.getURL() {
157
- wv.navigateToURL(url: url)
158
- } else {
159
- logger.warning("Unable to reload URL")
160
- }
161
- }
162
- .foregroundColor(.white)
163
- }
164
- .frame(maxWidth: .infinity, maxHeight: .infinity).glassBackgroundEffect()
165
-
166
- } else {
167
- wv.getView()
168
- .materialWithBorderCorner(
169
- wv.backgroundMaterial,
170
- wv.cornerRadius
171
- )
172
- .frame(maxWidth: .infinity, maxHeight: .infinity)
173
- }
174
- }
175
- .opacity(wv.opacity)
176
- .hidden(!ent.visible)
177
- }
178
- }
179
- }
@@ -1,30 +0,0 @@
1
- import typealias RealityKit.Attachment
2
- import typealias RealityKit.Entity
3
- import typealias RealityKit.MeshResource
4
- import typealias RealityKit.Model3D
5
- import typealias RealityKit.ModelEntity
6
- import typealias RealityKit.RealityView
7
- import typealias RealityKit.SimpleMaterial
8
- import SwiftUI
9
-
10
- struct VolumetricWindowContainerView: View {
11
- @Environment(SpatialWindowContainer.self) var windowContainerContent: SpatialWindowContainer
12
-
13
- var body: some View {
14
- OpenDismissHandlerUI().environment(windowContainerContent).onDisappear {
15
- // Don't destroy immersive space content as it is reused next time its opened
16
- if windowContainerContent.id != SpatialWindowContainer.ImmersiveID {
17
- windowContainerContent.destroy()
18
- }
19
- }
20
-
21
- let entities = windowContainerContent.getEntities().filter { _, entity in
22
- entity.coordinateSpace == .ROOT && entity.hasComponent(SpatialViewComponent.self)
23
- }
24
-
25
- ForEach(Array(entities.keys), id: \.self) { key in
26
- let entity = entities[key]!
27
- SpatialViewUI(isRoot: true).environment(entity)
28
- }
29
- }
30
- }
@@ -1,141 +0,0 @@
1
- import typealias RealityKit.Attachment
2
- import typealias RealityKit.Entity
3
- import typealias RealityKit.MeshResource
4
- import typealias RealityKit.Model3D
5
- import typealias RealityKit.ModelEntity
6
- import typealias RealityKit.RealityView
7
- import typealias RealityKit.SimpleMaterial
8
- import SwiftUI
9
-
10
- let clock = PerfClock()
11
- let logger = Logger()
12
-
13
- // To load a local path, remove http:// eg. "static-web/"
14
- let nativeAPIVersion = pwaManager.getVersion()
15
-
16
- // start URL
17
- let startURL = pwaManager.start_url
18
-
19
- // detect when app properties like defaultSize change so we can avoid race condition of setting default values and then opening window container
20
- var sceneStateChangedCB: ((Any) -> Void) = { _ in
21
- }
22
-
23
- @main
24
- struct web_spatialApp: App {
25
- @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
26
- @State var initialLaunch = true
27
-
28
- @ObservedObject var wgm = WindowContainerMgr.Instance
29
-
30
- @Environment(\.scenePhase) private var scenePhase
31
-
32
- init() {
33
- logger.debug("WebSpatial App Started -------- rootURL: " + startURL)
34
-
35
- // init global logger
36
- Logger.initLogger()
37
-
38
- // init pwa manager
39
- pwaManager._init()
40
-
41
- // create Immersive SpatialWindowContainer
42
- let _ = SpatialWindowContainer.createImmersiveWindowContainer()
43
- }
44
-
45
- func getFileUrl() -> URL {
46
- return URL(string: pwaManager.start_url)!
47
- }
48
-
49
- func getDefaultSize() -> CGSize {
50
- sceneStateChangedCB("")
51
- return wgm.getValue().defaultSize!
52
- }
53
-
54
- var body: some Scene {
55
- WindowGroup(id: "Plain", for: WindowContainerData.self) { $windowData in
56
- let wg = SpatialWindowContainer.getOrCreateSpatialWindowContainer(
57
- windowData.windowContainerID, windowData
58
- )
59
- PlainWindowContainerView().environment(wg)
60
- // https://stackoverflow.com/questions/78567737/how-to-get-initial-windowgroup-to-reopen-on-launch-visionos
61
- // .handlesExternalEvents(preferring: [], allowing: [])
62
- }
63
- defaultValue: {
64
- let windowData = WindowContainerData(
65
- windowStyle: "Plain",
66
- windowContainerID: SpatialWindowContainer.getRootID()
67
- )
68
-
69
- // Initialize entity and webview for deafult value
70
- let fileUrl = getFileUrl()
71
- let wc = SpatialWindowContainer.getOrCreateSpatialWindowContainer(
72
- windowData.windowContainerID, windowData
73
- )!
74
- let rootEntity = SpatialEntity()
75
- rootEntity.coordinateSpace = CoordinateSpaceMode.ROOT
76
- let windowComponent = SpatialWindowComponent(parentWindowContainerID: wc.id, url: fileUrl)
77
- rootEntity.addComponent(windowComponent)
78
- rootEntity.setParentWindowContainer(wg: wc)
79
- return windowData
80
- }
81
- .windowStyle(.plain).onChange(of: scenePhase) {
82
- oldPhase,
83
- newPhase in
84
- if oldPhase == .background && newPhase == .inactive {
85
- if initialLaunch {
86
- // App initial open
87
- initialLaunch = false
88
- } else {
89
- // App reopened
90
-
91
- let fileUrl = getFileUrl()
92
- if let awid = SpatialWindowContainer.firstActivePlainWindowContainerId,
93
- let wc = SpatialWindowContainer.getSpatialWindowContainer(
94
- awid
95
- )
96
- {
97
- let rootEntity = wc.getEntities().filter {
98
- $0.value.getComponent(SpatialWindowComponent.self) != nil && $0.value.coordinateSpace == .ROOT
99
- }.first?.value
100
-
101
- if let wv = rootEntity?.getComponent(SpatialWindowComponent.self) {
102
- // remove the webview's name to behave like new opened root scene
103
- if wv.getURL() != fileUrl {
104
- wv.removeWebviewName {
105
- wv.navigateToURL(url: fileUrl)
106
- }
107
- }
108
- }
109
- // reset to mainScene size
110
- wgm.setToMainSceneCfg()
111
- if let resizeRange = wgm.getValue().resizeRange {
112
- wc.setResizeRange.send(resizeRange)
113
- }
114
- wc.setSize.send(getDefaultSize())
115
- }
116
- }
117
- }
118
-
119
- }.defaultSize(
120
- getDefaultSize()
121
- ).windowResizability(
122
- wgm.getValue().windowResizability!
123
- )
124
-
125
- WindowGroup(id: "Volumetric", for: WindowContainerData.self) { $windowData in
126
- let wg = SpatialWindowContainer.getOrCreateSpatialWindowContainer(windowData!.windowContainerID, windowData!)
127
- VolumetricWindowContainerView().environment(wg).handlesExternalEvents(preferring: [], allowing: [])
128
-
129
- }.windowStyle(.volumetric).defaultSize(width: 1, height: 1, depth: 1, in: .meters)
130
-
131
- ImmersiveSpace(id: "ImmersiveSpace") {
132
- if let wg = SpatialWindowContainer.getImmersiveWindowContainer() {
133
- VolumetricWindowContainerView().environment(wg).handlesExternalEvents(preferring: [], allowing: [])
134
- }
135
- }
136
-
137
- WindowGroup(id: "loading") {
138
- LoadingView()
139
- }
140
- }
141
- }
File without changes
File without changes