From my question here, I would like to use the scene with notifications in Reality Composer like
Scene1.notifications.replay.post()
Therefore, I load the scene in ContentView and binding to the ARViewContainer for appending the scene, but it didn't work.
How can I do it?
Here's my code:
struct: ContentView: View {
@State private var arView = ARView(frame: .zero)
@State private var Scene1 = Experience.loadSceneAsync(completion: { result in
do {
let Scene = try result.get()
} catch {
print("Error")
}
})
var body: some View {
ZStack {
ARViewContainer(arView: $arView, Scene1: $Scene1)
.ignoresSafeArea()
Button("play") {
Scene1.notifications.replay.post()
}
}
}
}
struct ARViewContainer: UIViewRepresentable {
@Binding var arView: ARView
@Binding var Scene1: Experience1.Scene1
func makeUIView(context: Context) -> ARView {
arView.scene.anchors.append(Scene1)
return ARView
}
}
In order to implement the Combine's publisher/subscriber logics, we need to create a class with a @Published
property wrapper, in which we will place the RealityKit's asynchronous loading method.
@Published
and @ObservedObject
wrappers used here to manage state from external objects.
import SwiftUI
import RealityKit
class Catcher: ObservableObject {
@Published var scene = Experience.Box()
func sceneLoader() {
Experience.loadBoxAsync(completion: { result in
do {
self.scene = try result.get()
self.scene.steelBox?.scale *= 4
} catch {
print("Error: \(error.localizedDescription)")
}
})
}
func notificationLoader() {
if scene.notifications.allNotifications.count > 0 {
self.scene.notifications.replay.post()
}
}
}
struct ContentView : View {
@State private var boolean: Bool = false
var body: some View {
ZStack {
ARViewContainer(boolean: $boolean)
.ignoresSafeArea()
VStack {
Spacer()
Button("Play Animation") {
boolean = true
}
}
}
}
}
struct ARViewContainer : UIViewRepresentable {
@ObservedObject var catcher = Catcher()
@Binding var boolean: Bool
var arView = ARView(frame: .zero)
func makeUIView(context: Context) -> ARView {
catcher.sceneLoader()
return arView
}
func updateUIView(_ vue: ARView, context: Context) {
vue.scene.anchors.append(catcher.scene)
if boolean {
catcher.notificationLoader()
}
DispatchQueue.main.async {
if boolean {
boolean = false
}
}
}
}