@webspatial/platform-visionos 1.0.5 → 1.1.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webspatial/platform-visionos",
3
- "version": "1.0.5",
3
+ "version": "1.1.0",
4
4
  "description": "Used to publish WebSpatial projects to Apple Vision Pro",
5
5
  "type": "commonjs",
6
6
  "engines": {
@@ -21,13 +21,16 @@ enum SpatialWebMsgType: String, Encodable {
21
21
  case modelloaded = "modelloaded"
22
22
  case modelloadfailed = "modelloadfailed"
23
23
  case spatialtap = "spatialtap"
24
+ case spatialdragstart = "spatialdragstart"
24
25
  case spatialdrag = "spatialdrag"
25
26
  case spatialdragend = "spatialdragend"
27
+ case spatialrotatestart = "spatialrotatestart"
26
28
  case spatialrotate = "spatialrotate"
27
29
  case spatialrotateend = "spatialrotateend"
30
+ case spatialmagnifystart = "spatialmagnifystart"
28
31
  case spatialmagnify = "spatialmagnify"
29
32
  case spatialmagnifyend = "spatialmagnifyend"
30
-
33
+
31
34
  case objectdestroy = "objectdestroy"
32
35
  }
33
36
 
@@ -68,6 +71,11 @@ struct WebSpatialDragGuestureEvent: Encodable {
68
71
  let detail: WebSpatialDragGuestureEventDetail
69
72
  }
70
73
 
74
+ struct WebSpatialDragStartGuestureEvent: Encodable {
75
+ let type: SpatialWebMsgType = SpatialWebMsgType.spatialdragstart
76
+ let detail: WebSpatialDragGuestureEventDetail
77
+ }
78
+
71
79
  struct WebSpatialDragEndGuestureEvent: Encodable {
72
80
  let type: SpatialWebMsgType = SpatialWebMsgType.spatialdragend
73
81
  let detail: WebSpatialDragGuestureEventDetail
@@ -77,13 +85,18 @@ struct WebSpatialRotateGuestureEventDetail: Encodable {
77
85
  let rotation: Rotation3D
78
86
  let startAnchor3D: UnitPoint3D
79
87
  let startLocation3D: Point3D
80
-
81
88
  }
89
+
82
90
  struct WebSpatialRotateGuestureEvent: Encodable {
83
91
  let type: SpatialWebMsgType = SpatialWebMsgType.spatialrotate
84
92
  let detail: WebSpatialRotateGuestureEventDetail
85
93
  }
86
94
 
95
+ struct WebSpatialRotateStartGuestureEvent: Encodable {
96
+ let type: SpatialWebMsgType = SpatialWebMsgType.spatialrotatestart
97
+ let detail: WebSpatialRotateGuestureEventDetail
98
+ }
99
+
87
100
  struct WebSpatialRotateEndGuestureEvent: Encodable {
88
101
  let type: SpatialWebMsgType = SpatialWebMsgType.spatialrotateend
89
102
  let detail: WebSpatialRotateGuestureEventDetail
@@ -101,6 +114,11 @@ struct WebSpatialMagnifyGuestureEvent: Encodable {
101
114
  let detail: WebSpatialMagnifyGuestureEventDetail
102
115
  }
103
116
 
117
+ struct WebSpatialMagnifyStartGuestureEvent: Encodable {
118
+ let type: SpatialWebMsgType = SpatialWebMsgType.spatialmagnifystart
119
+ let detail: WebSpatialMagnifyGuestureEventDetail
120
+ }
121
+
104
122
  struct WebSpatialMagnifyEndGuestureEvent: Encodable {
105
123
  let type: SpatialWebMsgType = SpatialWebMsgType.spatialmagnifyend
106
124
  let detail: WebSpatialMagnifyGuestureEventDetail
@@ -5,7 +5,7 @@ var pwaManager = PWAManager()
5
5
 
6
6
  struct PWAManager: Codable {
7
7
  var isLocal: Bool = false
8
- var start_url: String = "http://localhost:5173/src/reality/gestures"
8
+ var start_url: String = "http://localhost:5173/src/static-3d-model"
9
9
 
10
10
  var scope: String = ""
11
11
  var id: String = "com.webspatial.pico"
@@ -116,6 +116,35 @@ class SpatialScene: SpatialObject, ScrollAbleSpatialElementContainer, WebMsgSend
116
116
  return true
117
117
  }
118
118
 
119
+ private func handleNavigationCheckCustom(_ url: URL) -> Bool {
120
+ /*
121
+ because full url is webspatial://createSpatialScene?url=xxx
122
+ we need to get the real url.
123
+ we do 2 things:
124
+
125
+ 1. let curUrl = parse url
126
+ 2. if url is in scope do webviewModel.load(curUrl)
127
+ else open in safari
128
+ */
129
+ guard let components = URLComponents(string: url.absoluteString),
130
+ let queryItems = components.queryItems
131
+ else {
132
+ print("❌ fail to parse URL")
133
+ return false
134
+ }
135
+ guard let encodedUrl = queryItems.first(where: { $0.name == "url" })?.value,
136
+ let decodedUrl = encodedUrl.removingPercentEncoding
137
+ else {
138
+ return false
139
+ }
140
+ if pwaManager.checkInScope(url: decodedUrl) {
141
+ spatialWebViewModel.load(decodedUrl)
142
+ return false
143
+ }
144
+ UIApplication.shared.open(URL(string: decodedUrl)!, options: [:], completionHandler: nil)
145
+ return false
146
+ }
147
+
119
148
  private func handleWindowOpenCustom(_ url: URL) -> WebViewElementInfo? {
120
149
  // get config from url
121
150
  guard let components = URLComponents(string: url.absoluteString),
@@ -132,6 +161,11 @@ class SpatialScene: SpatialObject, ScrollAbleSpatialElementContainer, WebMsgSend
132
161
  return nil
133
162
  }
134
163
 
164
+ if !pwaManager.checkInScope(url: decodedUrl) {
165
+ UIApplication.shared.open(URL(string: decodedUrl)!, options: [:], completionHandler: nil)
166
+ return nil
167
+ }
168
+
135
169
  if let encodedConfig = queryItems.first(where: { $0.name == "config" })?.value,
136
170
  let decodedConfig = encodedConfig.removingPercentEncoding
137
171
  {
@@ -269,6 +303,8 @@ class SpatialScene: SpatialObject, ScrollAbleSpatialElementContainer, WebMsgSend
269
303
 
270
304
  spatialWebViewModel
271
305
  .addNavigationListener(protocal: SpatialApp.Instance.scope, event: handleNavigationCheck)
306
+ spatialWebViewModel
307
+ .addNavigationListener(protocal: "webspatial://createSpatialScene", event: handleNavigationCheckCustom)
272
308
  }
273
309
 
274
310
  var width: Double = 0
@@ -7,90 +7,159 @@ struct SpatializedDynamic3DView: View {
7
7
  @State private var isDrag = false
8
8
  @State private var isRotate = false
9
9
  @State private var isScale = false
10
-
10
+
11
11
  private var spatializedDynamic3DElement: SpatializedDynamic3DElement {
12
12
  return spatializedElement as! SpatializedDynamic3DElement
13
13
  }
14
-
15
- var spatialTapEvent: some Gesture{
14
+
15
+ var spatialTapEvent: some Gesture {
16
16
  SpatialTapGesture(count: 1).targetedToAnyEntity()
17
- .onEnded{ value in
18
- if let entity = value.entity as? SpatialEntity{
17
+ .onEnded { value in
18
+ if let entity = value.entity as? SpatialEntity {
19
19
  spatialScene.sendWebMsg(entity.spatialId, WebSpatialTapGuestureEvent(detail: WebSpatialTapGuestureEventDetail(location3D: value.location3D)))
20
- }
21
- else {
22
- if let spatialEntity = SpatialEntity.findNearestParent(entity: value.entity){
20
+ } else {
21
+ if let spatialEntity = SpatialEntity.findNearestParent(entity: value.entity) {
23
22
  spatialScene.sendWebMsg(spatialEntity.spatialId, WebSpatialTapGuestureEvent(detail: WebSpatialTapGuestureEventDetail(location3D: value.location3D)))
24
23
  }
25
24
  }
26
- }
25
+ }
27
26
  }
28
-
29
- var rotate3dEvent: some Gesture{
30
- RotateGesture3D().targetedToAnyEntity().onChanged{ value in
31
- print(value.gestureValue)
32
- if let entity = value.entity as? SpatialEntity{
33
- if entity.enableTap == true {
34
- // if(isRotate == false){
35
- // print("start rotate")
36
- // }
37
- // else{
38
- // print("rotating")
39
- // }
40
- // isRotate = true
41
- return
27
+
28
+ var rotate3dEvent: some Gesture {
29
+ RotateGesture3D().targetedToAnyEntity().onChanged { value in
30
+ // Always forward rotate gesture events to JS
31
+ if let entity = value.entity as? SpatialEntity {
32
+ if !isRotate {
33
+ let startEvent = WebSpatialRotateStartGuestureEvent(
34
+ detail: .init(
35
+ rotation: value.rotation,
36
+ startAnchor3D: value.startAnchor3D,
37
+ startLocation3D: value.startLocation3D
38
+ )
39
+ )
40
+ spatialScene.sendWebMsg(entity.spatialId, startEvent)
41
+ isRotate = true
42
+ } else {
43
+ let gestureEvent = WebSpatialRotateGuestureEvent(
44
+ detail: .init(
45
+ rotation: value.rotation,
46
+ startAnchor3D: value.startAnchor3D,
47
+ startLocation3D: value.startLocation3D
48
+ )
49
+ )
50
+ spatialScene.sendWebMsg(entity.spatialId, gestureEvent)
42
51
  }
43
52
  }
53
+ }.onEnded { value in
54
+ // Always forward rotate end event to JS
55
+ if let entity = value.entity as? SpatialEntity {
56
+ let gestureEvent = WebSpatialRotateEndGuestureEvent(
57
+ detail: .init(
58
+ rotation: value.rotation,
59
+ startAnchor3D: value.startAnchor3D,
60
+ startLocation3D: value.startLocation3D
61
+ )
62
+ )
63
+ spatialScene.sendWebMsg(entity.spatialId, gestureEvent)
64
+ }
44
65
  isRotate = false
45
- }.onEnded{ value in
46
- print(value.rotation)
47
- print("rotate end")
48
- // isRotate = false
49
66
  }
50
67
  }
51
-
52
- var magnifyEvent: some Gesture{
53
- MagnifyGesture().targetedToAnyEntity().onChanged{ value in
54
- print(value)
55
- if let entity = value.entity as? SpatialEntity{
56
- if entity.enableTap == true {
57
- // if(isScale == false){
58
- // print("start scale")
59
- // }
60
- // else{
61
- // print("scaling")
62
- // }
63
- // isScale = true
64
- return
68
+
69
+ var magnifyEvent: some Gesture {
70
+ MagnifyGesture().targetedToAnyEntity().onChanged { value in
71
+ // Always forward magnify gesture events to JS
72
+ if let entity = value.entity as? SpatialEntity {
73
+ if !isScale {
74
+ let startEvent = WebSpatialMagnifyStartGuestureEvent(
75
+ detail: .init(
76
+ magnification: value.magnification,
77
+ velocity: value.velocity,
78
+ startLocation3D: value.startLocation3D,
79
+ startAnchor3D: value.startAnchor3D
80
+ )
81
+ )
82
+ spatialScene.sendWebMsg(entity.spatialId, startEvent)
83
+ isScale = true
84
+ } else {
85
+ let gestureEvent = WebSpatialMagnifyGuestureEvent(
86
+ detail: .init(
87
+ magnification: value.magnification,
88
+ velocity: value.velocity,
89
+ startLocation3D: value.startLocation3D,
90
+ startAnchor3D: value.startAnchor3D
91
+ )
92
+ )
93
+ spatialScene.sendWebMsg(entity.spatialId, gestureEvent)
65
94
  }
66
95
  }
67
- }.onEnded{ value in
68
- print("scale end")
69
- // isScale = false
96
+ }.onEnded { value in
97
+ // Always forward magnify end event to JS
98
+ if let entity = value.entity as? SpatialEntity {
99
+ let gestureEvent = WebSpatialMagnifyEndGuestureEvent(
100
+ detail: .init(
101
+ magnification: value.magnification,
102
+ velocity: value.velocity,
103
+ startLocation3D: value.startLocation3D,
104
+ startAnchor3D: value.startAnchor3D
105
+ )
106
+ )
107
+ spatialScene.sendWebMsg(entity.spatialId, gestureEvent)
108
+ }
109
+ isScale = false
70
110
  }
71
111
  }
72
-
73
- var dragEvent: some Gesture{
74
- DragGesture().targetedToAnyEntity().onChanged{ value in
75
- if let entity = value.entity as? SpatialEntity{
76
- if entity.enableTap == true {
77
- // if(isDrag == false){
78
- // print("start drag")
79
- // }
80
- // else{
81
- // print("dragging")
82
- // }
83
- // isDrag = true
84
- return
112
+
113
+ var dragEvent: some Gesture {
114
+ DragGesture().targetedToAnyEntity().onChanged { value in
115
+ // Always forward drag gesture events to JS
116
+ if let entity = value.entity as? SpatialEntity {
117
+ if !isDrag {
118
+ let startEvent = WebSpatialDragStartGuestureEvent(
119
+ detail: .init(
120
+ location3D: value.location3D,
121
+ startLocation3D: value.startLocation3D,
122
+ translation3D: value.translation3D,
123
+ predictedEndTranslation3D: value.predictedEndTranslation3D,
124
+ predictedEndLocation3D: value.predictedEndLocation3D,
125
+ velocity: value.velocity
126
+ )
127
+ )
128
+ spatialScene.sendWebMsg(entity.spatialId, startEvent)
129
+ isDrag = true
130
+ } else {
131
+ let gestureEvent = WebSpatialDragGuestureEvent(
132
+ detail: .init(
133
+ location3D: value.location3D,
134
+ startLocation3D: value.startLocation3D,
135
+ translation3D: value.translation3D,
136
+ predictedEndTranslation3D: value.predictedEndTranslation3D,
137
+ predictedEndLocation3D: value.predictedEndLocation3D,
138
+ velocity: value.velocity
139
+ )
140
+ )
141
+ spatialScene.sendWebMsg(entity.spatialId, gestureEvent)
85
142
  }
86
143
  }
87
-
88
- }.onEnded{ value in
89
- print("drag end")
90
- // isDrag = false
144
+ }.onEnded { value in
145
+ // Always forward drag end event to JS
146
+ if let entity = value.entity as? SpatialEntity {
147
+ let gestureEvent = WebSpatialDragEndGuestureEvent(
148
+ detail: .init(
149
+ location3D: value.location3D,
150
+ startLocation3D: value.startLocation3D,
151
+ translation3D: value.translation3D,
152
+ predictedEndTranslation3D: value.predictedEndTranslation3D,
153
+ predictedEndLocation3D: value.predictedEndLocation3D,
154
+ velocity: value.velocity
155
+ )
156
+ )
157
+ spatialScene.sendWebMsg(entity.spatialId, gestureEvent)
158
+ }
159
+ isDrag = false
91
160
  }
92
161
  }
93
-
162
+
94
163
  var body: some View {
95
164
  RealityView(make: { content in
96
165
  let rootEntity = spatializedDynamic3DElement.getRoot()
@@ -19,6 +19,7 @@ struct SpatializedStatic3DView: View {
19
19
 
20
20
  @ViewBuilder
21
21
  var body: some View {
22
+ let depth = spatializedElement.depth
22
23
  let transform = spatializedStatic3DElement.modelTransform
23
24
  let translation = transform.translation
24
25
  let scale = transform.scale
@@ -41,6 +42,7 @@ struct SpatializedStatic3DView: View {
41
42
  nil,
42
43
  contentMode: .fit
43
44
  )
45
+ .if(!depth.isZero){ view in view.scaledToFit3D()}
44
46
  .onAppear {
45
47
  self.onLoadSuccess()
46
48
  }