@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
@@ -0,0 +1,128 @@
1
+ import Foundation
2
+ import RealityKit
3
+ import SwiftUI
4
+
5
+ @Observable
6
+ class Spatialized2DElement: SpatializedElement, ScrollAbleSpatialElementContainer {
7
+ var cornerRadius: CornerRadius = .init()
8
+
9
+ var backgroundMaterial = BackgroundMaterial.None
10
+
11
+ var scrollPageEnabled = false
12
+
13
+ var scrollEdgeInsetsMarginRight: CGFloat? {
14
+ get {
15
+ return spatialWebViewModel.getController().webview?.scrollView.contentInset.right
16
+ }
17
+ set(newValue) {
18
+ spatialWebViewModel.getController().webview?.scrollView.contentInset.right = newValue ?? 0
19
+ }
20
+ }
21
+
22
+ var _scrollOffset: Vec2 = .init(x: 0, y: 0)
23
+ var scrollOffset: Vec2 {
24
+ get {
25
+ return _scrollOffset
26
+ }
27
+ set(newValue) {
28
+ _scrollOffset = newValue
29
+ }
30
+ }
31
+
32
+ func updateDeltaScrollOffset(_ delta: Vec2) {
33
+ spatialWebViewModel.setScrollOffset(_scrollOffset + delta)
34
+ }
35
+
36
+ func stopScrolling() {
37
+ spatialWebViewModel.stopScrolling()
38
+ }
39
+
40
+ private var spatialWebViewModel: SpatialWebViewModel
41
+ func getWebViewModel() -> SpatialWebViewModel {
42
+ return spatialWebViewModel
43
+ }
44
+
45
+ override init() {
46
+ spatialWebViewModel = SpatialWebViewModel(url: nil)
47
+
48
+ super.init()
49
+
50
+ spatialWebViewModel.setBackgroundTransparent(true)
51
+ spatialWebViewModel.addScrollUpdateListener { _, point in
52
+ self._scrollOffset.x = point.x
53
+ self._scrollOffset.y = point.y
54
+ }
55
+ spatialWebViewModel.scrollEnabled = false
56
+ }
57
+
58
+ // Spatialized2DElement can hold a collection of SpatializedElement children
59
+ private var children = [String: SpatializedElement]()
60
+
61
+ // Called by SpatializedElement.setParent
62
+ func addChild(_ spatializedElement: SpatializedElement) {
63
+ children[spatializedElement.id] = spatializedElement
64
+ }
65
+
66
+ // Called by SpatializedElement.setParent
67
+ func removeChild(_ spatializedElement: SpatializedElement) {
68
+ children.removeValue(forKey: spatializedElement.id)
69
+ }
70
+
71
+ func getChildren() -> [String: SpatializedElement] {
72
+ return children
73
+ }
74
+
75
+ func getChildrenOfType(_ type: SpatializedElementType) -> [String: SpatializedElement] {
76
+ let typedChildren = children.filter {
77
+ switch type {
78
+ case .Spatialized2DElement:
79
+ return $0.value is Spatialized2DElement
80
+ case .SpatializedStatic3DElement:
81
+ return $0.value is SpatializedStatic3DElement
82
+ case .SpatializedDynamic3DElement:
83
+ return $0.value is SpatializedDynamic3DElement
84
+ }
85
+ }
86
+ return typedChildren
87
+ }
88
+
89
+ func loadHtml(_ html: String) {
90
+ spatialWebViewModel.loadHTML(html)
91
+ }
92
+
93
+ func load(_ url: String) {
94
+ spatialWebViewModel.load(url)
95
+ }
96
+
97
+ func getView() -> SpatialWebView {
98
+ return spatialWebViewModel.getView()
99
+ }
100
+
101
+ override func onDestroy() {
102
+ let spatializedElements = children.map { $0.value }
103
+ for spatializedElement in spatializedElements {
104
+ spatializedElement.destroy()
105
+ }
106
+ spatialWebViewModel.destroy()
107
+
108
+ super.onDestroy()
109
+ }
110
+
111
+ enum CodingKeys: String, CodingKey {
112
+ case cornerRadius, backgroundMaterial, children, type, scrollOffset, scrollPageEnabled, webviewIsOpaque
113
+ }
114
+
115
+ override func encode(to encoder: Encoder) throws {
116
+ try super.encode(to: encoder)
117
+ var container = encoder.container(keyedBy: CodingKeys.self)
118
+ try container.encode(cornerRadius, forKey: .cornerRadius)
119
+ try container.encode(backgroundMaterial, forKey: .backgroundMaterial)
120
+ try container.encode(children, forKey: .children)
121
+ try container.encode(SpatializedElementType.Spatialized2DElement, forKey: .type)
122
+ try container.encode(scrollOffset, forKey: .scrollOffset)
123
+ try container.encode(scrollPageEnabled, forKey: .scrollPageEnabled)
124
+
125
+ // for debug only
126
+ try container.encode(spatialWebViewModel.getController().webview?.isOpaque, forKey: .webviewIsOpaque)
127
+ }
128
+ }
@@ -0,0 +1,34 @@
1
+ import Foundation
2
+
3
+ @Observable
4
+ class SpatializedDynamic3DElement: SpatializedElement {
5
+ private var rootEntity = SpatialEntity()
6
+
7
+ func getRoot() -> SpatialEntity {
8
+ return rootEntity
9
+ }
10
+
11
+ func addEntity(_ entity: SpatialEntity) {
12
+ rootEntity.addChild(entity)
13
+ }
14
+
15
+ func removeEntity(_ entity: SpatialEntity) {
16
+ rootEntity.removeChild(entity)
17
+ }
18
+
19
+ enum CodingKeys: String, CodingKey {
20
+ case type, root
21
+ }
22
+
23
+ override func encode(to encoder: Encoder) throws {
24
+ try super.encode(to: encoder)
25
+ var container = encoder.container(keyedBy: CodingKeys.self)
26
+ try container.encode(SpatializedElementType.SpatializedDynamic3DElement, forKey: .type)
27
+ try container.encode(rootEntity, forKey: .root)
28
+ }
29
+
30
+ override func onDestroy() {
31
+ rootEntity.destroy()
32
+ super.onDestroy()
33
+ }
34
+ }
@@ -0,0 +1,95 @@
1
+ import Foundation
2
+ import RealityKit
3
+ import SwiftUI
4
+
5
+ enum SpatializedElementType: String, Codable {
6
+ case Spatialized2DElement
7
+ case SpatializedStatic3DElement
8
+ case SpatializedDynamic3DElement
9
+ }
10
+
11
+ @Observable
12
+ class SpatializedElement: SpatialObject {
13
+ var clientX: Double = 0.0
14
+ var clientY: Double = 0.0
15
+ var width: Double = 0.0
16
+ var height: Double = 0.0
17
+ var depth: Double = 0.0
18
+ var backOffset: Double = 0.0
19
+ var transform: AffineTransform3D = .identity
20
+ var rotationAnchor: UnitPoint3D = .center
21
+ var opacity: Double = 1.0
22
+ var visible = true
23
+ var scrollWithParent = true
24
+ var zIndex: Double = 0
25
+
26
+ var enableDragStartGesture: Bool = false
27
+ var enableDragGesture: Bool = false
28
+ var enableDragEndGesture: Bool = false
29
+ var enableRotateStartGesture: Bool = false
30
+ var enableRotateGesture: Bool = false
31
+ var enableRotateEndGesture: Bool = false
32
+ var enableMagnifyStartGesture: Bool = false
33
+ var enableMagnifyGesture: Bool = false
34
+ var enableMagnifyEndGesture: Bool = false
35
+ var enableTapGesture: Bool = false
36
+
37
+ var enableGesture: Bool {
38
+ return enableDragStartGesture || enableDragGesture || enableDragEndGesture || enableRotateStartGesture || enableRotateGesture || enableRotateEndGesture || enableMagnifyStartGesture || enableMagnifyGesture || enableMagnifyEndGesture || enableTapGesture
39
+ }
40
+
41
+ enum CodingKeys: String, CodingKey {
42
+ case clientX, clientY, width, height, depth, backOffset, transform, rotationAnchor, opacity, visible, scrollWithParent, zIndex, parent, enableGesture, enableTapGesture, enableDragGesture, enableDragEndGesture, enableRotateStartGesture, enableRotateGesture, enableRotateEndGesture, enableMagnifyStartGesture, enableMagnifyGesture, enableMagnifyEndGesture
43
+ }
44
+
45
+ override func encode(to encoder: Encoder) throws {
46
+ try super.encode(to: encoder)
47
+ var container = encoder.container(keyedBy: CodingKeys.self)
48
+ try container.encode(clientX, forKey: .clientX)
49
+ try container.encode(clientY, forKey: .clientY)
50
+ try container.encode(width, forKey: .width)
51
+ try container.encode(height, forKey: .height)
52
+ try container.encode(depth, forKey: .depth)
53
+ try container.encode(backOffset, forKey: .backOffset)
54
+ try container.encode(transform, forKey: .transform)
55
+ try container.encode(rotationAnchor, forKey: .rotationAnchor)
56
+ try container.encode(opacity, forKey: .opacity)
57
+ try container.encode(visible, forKey: .visible)
58
+ try container.encode(scrollWithParent, forKey: .scrollWithParent)
59
+ try container.encode(zIndex, forKey: .zIndex)
60
+ try container.encode(parent?.id, forKey: .parent)
61
+ try container.encode(enableGesture, forKey: .enableGesture)
62
+ try container.encode(enableTapGesture, forKey: .enableTapGesture)
63
+ try container.encode(enableDragGesture, forKey: .enableDragGesture)
64
+ try container.encode(enableDragEndGesture, forKey: .enableDragEndGesture)
65
+ try container.encode(enableRotateStartGesture, forKey: .enableRotateStartGesture)
66
+ try container.encode(enableRotateGesture, forKey: .enableRotateGesture)
67
+ try container.encode(enableRotateEndGesture, forKey: .enableRotateEndGesture)
68
+ try container.encode(enableMagnifyStartGesture, forKey: .enableMagnifyStartGesture)
69
+ try container.encode(enableMagnifyGesture, forKey: .enableMagnifyGesture)
70
+ try container.encode(enableMagnifyEndGesture, forKey: .enableMagnifyEndGesture)
71
+ }
72
+
73
+ private(set) var parent: ScrollAbleSpatialElementContainer?
74
+
75
+ func setParent(_ parent: ScrollAbleSpatialElementContainer?) {
76
+ if self.parent?.id == parent?.id {
77
+ return
78
+ }
79
+
80
+ if let prevParent = self.parent {
81
+ prevParent.removeChild(self)
82
+ }
83
+
84
+ parent?.addChild(self)
85
+ self.parent = parent
86
+ }
87
+
88
+ func getParent() -> ScrollAbleSpatialElementContainer? {
89
+ return parent
90
+ }
91
+
92
+ override func onDestroy() {
93
+ setParent(nil)
94
+ }
95
+ }
@@ -0,0 +1,19 @@
1
+ import Foundation
2
+ import SwiftUI
3
+
4
+ @Observable
5
+ class SpatializedStatic3DElement: SpatializedElement {
6
+ var modelURL: String = ""
7
+ var modelTransform: AffineTransform3D = AffineTransform3D.identity
8
+
9
+ enum CodingKeys: String, CodingKey {
10
+ case modelURL, type
11
+ }
12
+
13
+ override func encode(to encoder: Encoder) throws {
14
+ try super.encode(to: encoder)
15
+ var container = encoder.container(keyedBy: CodingKeys.self)
16
+ try container.encode(modelURL, forKey: .modelURL)
17
+ try container.encode(SpatializedElementType.SpatializedStatic3DElement, forKey: .type)
18
+ }
19
+ }
@@ -0,0 +1,95 @@
1
+ import RealityKit
2
+ import SwiftUI
3
+
4
+ @Observable
5
+ class Geometry: SpatialObject {
6
+ let type: GeometryType
7
+
8
+ var _resource: MeshResource?
9
+ var resource: MeshResource? {
10
+ _resource
11
+ }
12
+
13
+ init(_ _type: GeometryType) {
14
+ type = _type
15
+ super.init()
16
+ }
17
+
18
+ override func onDestroy() {
19
+ _resource = nil
20
+ }
21
+ }
22
+
23
+ @Observable
24
+ class BoxGeometry: Geometry {
25
+ let width: Float
26
+ let height: Float
27
+ let depth: Float
28
+ let cornerRadius: Float
29
+ let splitFaces: Bool
30
+ init(width: Float, height: Float, depth: Float, cornerRadius: Float = 0, splitFaces: Bool = false) {
31
+ self.width = width
32
+ self.height = height
33
+ self.depth = depth
34
+ self.cornerRadius = cornerRadius
35
+ self.splitFaces = splitFaces
36
+ super.init(.BoxGeometry)
37
+ _resource = MeshResource.generateBox(width: width, height: height, depth: depth, cornerRadius: cornerRadius, splitFaces: splitFaces)
38
+ }
39
+ }
40
+
41
+ @Observable
42
+ class PlaneGeometry: Geometry {
43
+ let width: Float
44
+ let height: Float
45
+ let cornerRadius: Float
46
+ init(width: Float, height: Float, cornerRadius: Float = 0) {
47
+ self.width = width
48
+ self.height = height
49
+ self.cornerRadius = cornerRadius
50
+ super.init(.PlaneGeometry)
51
+ _resource = MeshResource.generatePlane(width: width, height: height, cornerRadius: cornerRadius)
52
+ }
53
+ }
54
+
55
+ enum GeometryType: String {
56
+ case BoxGeometry
57
+ case PlaneGeometry
58
+ case SphereGeometry
59
+ case ConeGeometry
60
+ case CylinderGeometry
61
+ }
62
+
63
+ @Observable
64
+ class SphereGeometry: Geometry {
65
+ let radius: Float
66
+ init(radius: Float) {
67
+ self.radius = radius
68
+ super.init(.SphereGeometry)
69
+ _resource = MeshResource.generateSphere(radius: radius)
70
+ }
71
+ }
72
+
73
+ @Observable
74
+ class ConeGeometry: Geometry {
75
+ let radius: Float
76
+ let height: Float
77
+ init(radius: Float, height: Float) {
78
+ self.radius = radius
79
+ self.height = height
80
+ super.init(.ConeGeometry)
81
+ _resource = MeshResource.generateCone(height: height, radius: radius)
82
+ }
83
+ }
84
+
85
+ @Observable
86
+ class CylinderGeometry: Geometry {
87
+ let radius: Float
88
+ let height: Float
89
+ init(radius: Float, height: Float) {
90
+ self.radius = radius
91
+ self.height = height
92
+ super.init(.CylinderGeometry)
93
+ _resource = MeshResource.generateCylinder(height: height, radius: radius)
94
+ }
95
+ }
@@ -0,0 +1,72 @@
1
+ import SwiftUI
2
+ import RealityKit
3
+
4
+ @Observable
5
+ class SpatialComponent: SpatialObject {
6
+ let type: SpatialComponentType
7
+
8
+
9
+ internal var _resource:Component? = nil
10
+ var resource:Component? {
11
+ _resource
12
+ }
13
+
14
+ internal var _entity:SpatialEntity? = nil
15
+ var entity:SpatialEntity? {
16
+ _entity
17
+ }
18
+
19
+ init(_ _type:SpatialComponentType){
20
+ type = _type
21
+ super.init()
22
+ }
23
+
24
+ func addToEntity(entity:SpatialEntity){
25
+ if _entity != nil {
26
+ print("This component has already been added to another entity")
27
+ return
28
+ }
29
+ if let component = resource{
30
+ _entity = entity
31
+ entity.components.set(component)
32
+ }
33
+ }
34
+
35
+ func removeFromEntity(entity:SpatialEntity){
36
+ if let component = resource,
37
+ self.entity == entity{
38
+ entity.components.remove(Swift.type(of: component))
39
+ _entity = nil
40
+ }
41
+ }
42
+ }
43
+
44
+ @Observable
45
+ class SpatialModelComponent: SpatialComponent {
46
+ init(mesh:Geometry, mats:[SpatialMaterial]){
47
+ super.init(.ModelComponent)
48
+ var materials:[any RealityKit.Material] = []
49
+ mats.forEach{ item in
50
+ materials.append(item.resource!)
51
+ }
52
+ _resource = ModelComponent(mesh: mesh.resource!, materials: materials)
53
+ }
54
+
55
+ override func addToEntity(entity:SpatialEntity){
56
+ super.addToEntity(entity: entity)
57
+ entity.generateCollisionShapes(recursive: true)
58
+ }
59
+
60
+ override func removeFromEntity(entity:SpatialEntity){
61
+ super.removeFromEntity(entity: entity)
62
+ entity.generateCollisionShapes(recursive: true)
63
+ }
64
+
65
+ override internal func onDestroy() {
66
+ _resource = nil
67
+ }
68
+ }
69
+
70
+ enum SpatialComponentType:String {
71
+ case ModelComponent = "ModelComponent"
72
+ }
@@ -0,0 +1,211 @@
1
+ import SwiftUI
2
+ import RealityKit
3
+
4
+ @Observable
5
+ class SpatialEntity: Entity, SpatialObjectProtocol {
6
+ let spatialId: String
7
+
8
+ private var _isDestroyed: Bool = false
9
+ var isDestroyed: Bool {
10
+ return _isDestroyed
11
+ }
12
+ internal var listeners: [String: [(_ object: Any, _ data: Any) -> Void]] = [:]
13
+
14
+ private var _enableTap: Bool = false
15
+ private var _enableRotate: Bool = false
16
+ private var _enableRotateStart: Bool = false
17
+ private var _enableRotateEnd: Bool = false
18
+ private var _enableDrag: Bool = false
19
+ private var _enableDragStart: Bool = false
20
+ private var _enableDragEnd: Bool = false
21
+ private var _enableMagnify: Bool = false
22
+ private var _enableMagnifyStart: Bool = false
23
+ private var _enableMagnifyEnd: Bool = false
24
+
25
+ internal var rotation: simd_quatd = simd_quatd()
26
+ internal var spatialChildren: [String:SpatialEntity] = [:]
27
+ internal var spatialComponents: [String: SpatialComponent] = [:]
28
+
29
+ var enableTap: Bool {
30
+ return _enableTap
31
+ }
32
+ var enableRotate: Bool {
33
+ return _enableRotate || _enableRotateStart
34
+ }
35
+ var enableDrag: Bool {
36
+ return _enableDrag || _enableDragStart
37
+ }
38
+ var enableMagnify: Bool {
39
+ return _enableMagnify || _enableMagnifyStart
40
+ }
41
+
42
+ var enableRotateEnd: Bool {
43
+ return _enableRotateEnd
44
+ }
45
+ var enableDragEnd: Bool {
46
+ return _enableDragEnd
47
+ }
48
+ var enableMagnifyEnd: Bool {
49
+ return _enableMagnifyEnd
50
+ }
51
+
52
+ var enableInteractive: Bool {
53
+ return enableTap || enableRotate || enableDrag || enableMagnify || enableRotateEnd || enableDragEnd || enableMagnifyEnd
54
+ }
55
+
56
+ required init() {
57
+ self.spatialId = UUID().uuidString
58
+ super.init()
59
+ SpatialObject.objects[spatialId] = self
60
+ SpatialObjectWeakRefManager.setWeakRef(spatialId, self)
61
+ }
62
+
63
+ init(_ _name:String){
64
+ self.spatialId = UUID().uuidString
65
+ super.init()
66
+ self.name = _name
67
+ SpatialObject.objects[spatialId] = self
68
+ SpatialObjectWeakRefManager.setWeakRef(spatialId, self)
69
+ }
70
+
71
+ func addChild(entity:SpatialEntity){
72
+ spatialChildren[entity.spatialId] = entity
73
+ super.addChild(entity)
74
+ }
75
+
76
+ func removeChild(id:String){
77
+ if let entity = spatialChildren[id]{
78
+ super.removeChild(entity)
79
+ spatialChildren.removeValue(forKey: id)
80
+ }
81
+ else {
82
+ print("no child found")
83
+ }
84
+ }
85
+
86
+ func removeFromParent(){
87
+ if let parent = parent as? SpatialEntity{
88
+ parent.removeChild(self)
89
+ }
90
+ }
91
+
92
+ func addComponent(_ comp: SpatialComponent) {
93
+ spatialComponents[comp.type.rawValue] = comp
94
+ comp.addToEntity(entity: self)
95
+ }
96
+
97
+ func removeComponent(_ comp: SpatialComponent) {
98
+ if spatialComponents[comp.type.rawValue] != nil {
99
+ comp.removeFromEntity(entity: self)
100
+ spatialComponents.removeValue(forKey: comp.type.rawValue)
101
+ }
102
+ }
103
+
104
+ func updateTransform(_ matrix:[String:Float]){
105
+ transform.matrix = float4x4([matrix["0"]!, matrix["1"]!, matrix["2"]!, matrix["3"]!], [matrix["4"]!, matrix["5"]!, matrix["6"]!, matrix["7"]!], [matrix["8"]!, matrix["9"]!, matrix["10"]!, matrix["11"]!], [matrix["12"]!, matrix["13"]!, matrix["14"]!, matrix["15"]!])
106
+ }
107
+
108
+ func updateGesture(_ type:String, _ isEable:Bool){
109
+ switch WebSpatialGestureType(rawValue: type){
110
+ case .spatialtap:
111
+ _enableTap = isEable
112
+ case .spatialrotate:
113
+ _enableRotate = isEable
114
+ case .spatialrotatestart:
115
+ _enableRotateStart = isEable
116
+ case .spatialrotateend:
117
+ _enableRotateEnd = isEable
118
+ case .spatialdrag:
119
+ _enableDrag = isEable
120
+ case .spatialdragstart:
121
+ _enableDragStart = isEable
122
+ case .spatialdragend:
123
+ _enableDragEnd = isEable
124
+ case .spatialmagnify:
125
+ _enableMagnify = isEable
126
+ case .spatialmagnifystart:
127
+ _enableMagnifyStart = isEable
128
+ case .spatialmagnifyend:
129
+ _enableMagnifyEnd = isEable
130
+ default:
131
+ return
132
+ }
133
+
134
+ if enableInteractive {
135
+ if !components.has(InputTargetComponent.self){
136
+ components.set(InputTargetComponent())
137
+ }
138
+ }
139
+ else {
140
+ if components.has(InputTargetComponent.self){
141
+ components.remove(InputTargetComponent.self)
142
+ }
143
+ }
144
+ }
145
+
146
+ static func findNearestParent(entity: Entity) -> SpatialEntity?{
147
+ if let parent = entity.parent as? SpatialEntity{
148
+ return parent
149
+ }
150
+ else if entity.parent != nil {
151
+ return findNearestParent(entity: entity.parent!)
152
+ }
153
+ return nil
154
+ }
155
+
156
+ func setRotation(_ rotation: simd_quatd) {
157
+ self.rotation = rotation
158
+ self.transform.rotation = simd_quatf(ix: Float(rotation.imag.x), iy: Float(rotation.imag.y), iz: Float(rotation.imag.z), r: Float(rotation.real))
159
+ }
160
+
161
+ // Encodable
162
+ enum CodingKeys: String, CodingKey {
163
+ case id, name, isDestroyed, children, components
164
+ }
165
+
166
+ func encode(to encoder: any Encoder) throws {
167
+ var container = encoder.container(keyedBy: CodingKeys.self)
168
+ try container.encode(spatialId, forKey: .id)
169
+ try container.encode(name, forKey: .name)
170
+ try container.encode(isDestroyed, forKey: .isDestroyed)
171
+ try container.encode(spatialChildren, forKey: .children)
172
+ try container.encode(spatialComponents, forKey: .components)
173
+ }
174
+
175
+ // Equatable
176
+ static func == (lhs: SpatialEntity, rhs: SpatialEntity) -> Bool {
177
+ return lhs.spatialId == rhs.spatialId
178
+ }
179
+
180
+ func destroy() {
181
+ if _isDestroyed {
182
+ return
183
+ }
184
+ emit(event: SpatialObject.Events.BeforeDestroyed.rawValue, data: ["object": self])
185
+ onDestroy()
186
+ _isDestroyed = true
187
+
188
+ emit(event: SpatialObject.Events.Destroyed.rawValue, data: ["object": self])
189
+ listeners = [:]
190
+ SpatialObject.objects.removeValue(forKey: spatialId)
191
+ }
192
+
193
+ internal func onDestroy() {
194
+ if(parent != nil){
195
+ removeFromParent()
196
+ }
197
+ components.removeAll()
198
+ spatialChildren.forEach { id, child in
199
+ child.destroy()
200
+ }
201
+ spatialChildren = [:]
202
+ spatialComponents.forEach { id, components in
203
+ components.destroy()
204
+ }
205
+ spatialComponents = [:]
206
+ }
207
+
208
+ deinit {
209
+ SpatialObjectWeakRefManager.removeWeakRef(spatialId)
210
+ }
211
+ }
@@ -0,0 +1,39 @@
1
+ import SwiftUI
2
+ import RealityKit
3
+
4
+ @Observable
5
+ class SpatialMaterial: SpatialObject {
6
+ let type: SpatialMaterialType
7
+
8
+ internal var _resource:RealityKit.Material? = nil
9
+ var resource:RealityKit.Material? {
10
+ _resource
11
+ }
12
+
13
+ init(_ _type:SpatialMaterialType){
14
+ type = _type
15
+ super.init()
16
+ }
17
+
18
+ override func onDestroy() {
19
+ _resource = nil
20
+ }
21
+ }
22
+
23
+ @Observable
24
+ class SpatialUnlitMaterial: SpatialMaterial{
25
+ let color:UIColor
26
+
27
+ init(_ color:String, _ texture:TextureResource? = nil, _ transparent:Bool = true, _ opacity:Float = 1){
28
+ self.color = UIColor.init(Color(hex: color))
29
+ super.init(.UnlitMaterial)
30
+ var mat = UnlitMaterial()
31
+ mat.color = .init(tint:UIColor(Color.init(hex: color)), texture: texture != nil ? .init(texture!) : nil)
32
+ mat.blending = transparent ? .transparent(opacity: .init(scale: opacity)) : .opaque
33
+ _resource = mat
34
+ }
35
+ }
36
+
37
+ enum SpatialMaterialType: String{
38
+ case UnlitMaterial = "UnlitMaterial"
39
+ }