// // ImmersiveView.swift // SampleOrbitAnimationApp // // Created by Andrew Hall on 7/4/24. // import SwiftUI import RealityKit import Starship struct ImmersiveView: View { @Environment(\.dismissImmersiveSpace) var dismissImmersiveSpace @Environment(\.dismissWindow) var dismissWindow @Environment(\.openWindow) var openWindow var body: some View { RealityView { content, attachments in //Skybox Entity guard let skyBoxEntity = createSkyBox() else { print("Error loading skyBoxEntity") return } //Get Starship model let starshipEntity = await createStarshipModel() // Retrieve the attachment with the "Exit Button" identifier as an entity. guard let exitButton = attachments.entity(for: "Exit Button") else { return } exitButton.setScale([4.0, 4.0, 4.0], relativeTo: starshipEntity) exitButton.setPosition([0.0, 0.5, -2.0], relativeTo: starshipEntity) //Add to RealityView content.add(skyBoxEntity) content.add(starshipEntity) content.add(exitButton) if let orbitingVessel = starshipEntity.findEntity(named: "Group") { //Playing an orbit transform animation let orbit = OrbitAnimation(name: "Orbit", duration: 180, axis: [0, 1, 0], startTransform: orbitingVessel.transform, orientToPath: true, bindTarget: .transform, repeatMode: .repeat) if let animation = try? AnimationResource.generate(with: orbit) { orbitingVessel.playAnimation(animation) } } } attachments: { Attachment(id: "Exit Button") { Button { Task { await dismissImmersiveSpace() } } label: { Label("Close Starship Orbit View", systemImage: "arrow.down.right.and.arrow.up.left") } } } .onAppear { dismissWindow(id: "ContentView") } .onDisappear { openWindow(id: "ContentView") } } private func createSkyBox () -> Entity? { //Mesh let largeSphere = MeshResource.generateSphere(radius: 1000) //Material var skyBoxMaterial = UnlitMaterial() do { let texture = try TextureResource.load(named: "Starfield") skyBoxMaterial.color = .init(texture: .init(texture)) } catch { print("Error loading texture \(error)") } //SkyBox Entity let skyBoxEntity = Entity() skyBoxEntity.components.set( ModelComponent( mesh: largeSphere, materials: [skyBoxMaterial]) ) //Map texture to inner sphere skyBoxEntity.scale *= .init(x: -1, y: 1, z: 1) return skyBoxEntity } private func createStarshipModel () async -> Entity { guard let starshipEntity = try? await Entity(named: "OrbitingVessel", in: starshipBundle) else { fatalError("Cannot load Starship model") } return starshipEntity } } #Preview(immersionStyle: .full) { ImmersiveView() .previewLayout(.sizeThatFits) }