Skip to content

Commit

Permalink
Support building for iOS 18
Browse files Browse the repository at this point in the history
  • Loading branch information
carson-katri committed Jul 25, 2024
1 parent 579423d commit 403ed16
Show file tree
Hide file tree
Showing 10 changed files with 129 additions and 0 deletions.
1 change: 1 addition & 0 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import PackageDescription

let package = Package(
name: "LiveViewNativeRealityKit",
platforms: [.visionOS(.v1), .iOS("18.0")],
products: [
// Products define the executables and libraries a package produces, making them visible to other packages.
.library(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,15 @@ extension AnchoringComponent.Target: AttributeDecodable {
guard let value = attribute?.value
else { throw AttributeDecodingError.missingAttribute(Self.self) }
switch value {
#if os(visionOS)
case "hand":
self = .hand(
try element.attributeValue(Chirality.self, for: "chirality"),
location: try element.attributeValue(HandLocation.self, for: "location")
)
case "head":
self = .head
#endif
case "image":
self = .image(
group: try element.attributeValue(String.self, for: "group"),
Expand All @@ -64,6 +66,7 @@ extension AnchoringComponent.Target: AttributeDecodable {
}
}

#if os(visionOS)
extension AnchoringComponent.Target.Chirality: AttributeDecodable {
public init(from attribute: Attribute?, on element: ElementNode) throws {
guard let value = attribute?.value
Expand Down Expand Up @@ -99,6 +102,7 @@ extension AnchoringComponent.Target.HandLocation: AttributeDecodable {
}
}
}
#endif

extension AnchoringComponent.Target.Alignment: AttributeDecodable {
public init(from attribute: Attribute?, on element: ElementNode) throws {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,12 @@ public struct EntityContentBuilder<Entities: EntityRegistry, Components: Compone
case modelEntity = "ModelEntity"
case anchorEntity = "AnchorEntity"

#if os(visionOS)
case sceneReconstructionProvider = "SceneReconstructionProvider"
case handTrackingProvider = "HandTrackingProvider"

case viewAttachmentEntity = "ViewAttachmentEntity"
#endif
}

public init?(rawValue: RawValue) {
Expand Down Expand Up @@ -71,12 +73,14 @@ public struct EntityContentBuilder<Entities: EntityRegistry, Components: Compone
entity = try ModelEntity(from: element, in: context)
case .anchorEntity:
entity = try AnchorEntity(from: element, in: context)
#if os(visionOS)
case .sceneReconstructionProvider:
entity = try SceneReconstructionEntity(from: element, in: context)
case .handTrackingProvider:
entity = HandTrackingEntity(from: element, in: context)
case .viewAttachmentEntity:
entity = try _ViewAttachmentEntity(from: element, in: context)
#endif
}
case .custom:
guard let customEntity = (try Self.build([element.node], with: Entities.self, in: context)).first
Expand Down Expand Up @@ -217,7 +221,9 @@ extension Entity {
self.components.set(elementNodeComponent)
}

#if os(visionOS)
guard !(self is SceneReconstructionEntity) else { return } // scene reconstruction creates its own child meshes
#endif

/// The list of children previously part of this element.
///
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
// Created by Carson.Katri on 5/30/24.
//

#if os(visionOS)
import ARKit

enum SharedARKitSessionStore {
Expand All @@ -19,3 +20,4 @@ enum SharedARKitSessionStore {
}
}
}
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
// Created by Carson Katri on 5/23/24.
//

#if os(visionOS)
import LiveViewNative
import LiveViewNativeCore
import ARKit
Expand Down Expand Up @@ -152,3 +153,4 @@ class HandTrackingEntity: Entity {
session.stop()
}
}
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
// Created by Carson Katri on 5/23/24.
//

#if os(visionOS)
import LiveViewNative
import ARKit
import RealityKit
Expand Down Expand Up @@ -128,3 +129,4 @@ extension GeometrySource {
return asArray(ofType: (T, T, T).self).map { .init($0.0, $0.1, $0.2) }
}
}
#endif
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
//
// RealityViewCameraControlsModifier.swift
//
//
// Created by Carson.Katri on 7/25/24.
//

#if os(iOS) || os(macOS)
import LiveViewNative
import LiveViewNativeStylesheet
import SwiftUI
import RealityKit

@ParseableExpression
struct _RealityViewCameraControlsModifier: ViewModifier {
public static var name: String { "realityViewCameraControls" }

let controls: CameraControls

init(_ controls: CameraControls) {
self.controls = controls
}

func body(content: Content) -> some View {
content.realityViewCameraControls(controls)
}
}

extension CameraControls: ParseableModifierValue {
public static func parser(in context: ParseableModifierContext) -> some Parser<Substring.UTF8View, Self> {
ImplicitStaticMember([
"dolly": .dolly,
"none": .none,
"orbit": .orbit,
"pan": .pan,
"tilt": .tilt,
])
}
}
#endif
31 changes: 31 additions & 0 deletions Sources/LiveViewNativeRealityKit/RealityKit.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import LiveViewNative
import LiveViewNativeStylesheet
import SwiftUI
import RealityKit

public struct CustomizableRealityKitRegistry<
Entities: EntityRegistry,
Expand All @@ -17,6 +18,36 @@ public struct CustomizableRealityKitRegistry<
_RealityView<Root, Entities, _ComponentContentBuilder<Components>>()
}
}

#if os(iOS) || os(macOS)
public static func parseModifier(
_ input: inout Substring.UTF8View,
in context: ParseableModifierContext
) throws -> CustomModifier {
try CustomModifier.parser(in: context).parse(&input)
}

public struct CustomModifier: ViewModifier, ParseableModifierValue {
enum Storage {
case realityViewCameraControls(_RealityViewCameraControlsModifier)
}

let storage: Storage

public static func parser(in context: ParseableModifierContext) -> some Parser<Substring.UTF8View, Self> {
CustomModifierGroupParser(output: Self.self) {
_RealityViewCameraControlsModifier.parser(in: context).map({ Self(storage: .realityViewCameraControls($0)) })
}
}

public func body(content: Content) -> some View {
switch storage {
case .realityViewCameraControls(let modifier):
content.modifier(modifier)
}
}
}
#endif
}
}

Expand Down
10 changes: 10 additions & 0 deletions Sources/LiveViewNativeRealityKit/RealityView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ struct _RealityView<Root: RootRegistry, Entities: EntityRegistry, Components: Co

private var audibleClicks: Bool = false

private var camera: RealityViewCamera = .worldTracking

@LiveElementIgnored
@State
private var updateStorage = UpdateContextComponent<Root, Entities, Components>.Storage()
Expand Down Expand Up @@ -146,6 +148,10 @@ struct _RealityView<Root: RootRegistry, Entities: EntityRegistry, Components: Co

var body: some View {
RealityView { content, attachments in
#if os(iOS) || os(macOS)
content.camera = self.camera
#endif

self.subscriptions = [
content.subscribe(to: CollisionEvents.Began.self, componentType: PhysicsBodyChangeEventComponent.self) { collision in
for entity in [collision.entityA, collision.entityB] {
Expand Down Expand Up @@ -259,7 +265,11 @@ struct _RealityView<Root: RootRegistry, Entities: EntityRegistry, Components: Co
partialResult[String(attr.name.name.dropFirst(prefix.count))] = attr.value
}

#if os(visionOS)
let tapLocation = value.convert(value.location3D, from: .local, to: .scene)
#else
let tapLocation = value.hitTest(point: value.location, in: .local).first?.position ?? value.entity.position
#endif

payload["_location"] = [tapLocation.x, tapLocation.y, tapLocation.z]

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
//
// RealityViewCamera+AttributeDecodable.swift
//
//
// Created by Carson.Katri on 7/25/24.
//

#if os(iOS) || os(macOS)
import LiveViewNative
import LiveViewNativeCore
import RealityKit
import SwiftUI

extension RealityViewCamera: AttributeDecodable {
public init(from attribute: Attribute?, on element: ElementNode) throws {
guard let value = attribute?.value
else { throw AttributeDecodingError.missingAttribute(Self.self) }

switch value {
case "virtual":
self = .virtual
case "worldTracking":
self = .worldTracking
default:
throw AttributeDecodingError.badValue(Self.self)
}
}
}
#else
typealias RealityViewCamera = String
#endif

0 comments on commit 403ed16

Please sign in to comment.