I'm making a test program that allows the user to switch .allowCameraControl on and off with a button So I'm using observable objects that update the scene object whenever a variable changes. But every time the .allowCameraControl option is changed, the scene refreshes and objects goes back to its original orientation. How do I make it so that the object stays in its current orientation even when the .allowCameraControl changes
Here's a minimum reproducible example ContentView.swift:
import SwiftUI
import SceneKit
final class Lmao: ObservableObject {
@Published var yo: SceneView.Options = [.allowsCameraControl]
}
struct ContentView: View {
@EnvironmentObject var l: Lmao
var scene = SCNScene(named: "myScene.scn")
var body: some View {
VStack {
SceneView(scene: scene, options: l.yo)
.frame(width: UIScreen.main.bounds.width ,
height: UIScreen.main.bounds.height / 2)
Button("allow/disable camera controll") {
if l.yo == [] {
l.yo = [SceneView.Options.allowsCameraControl]
}
else {
l.yo = []
}
}
}
}
func updateLocation(_ location: CGPoint) {
print(location)
}
}
CameraTestApp.swift:
@main
struct CameraTestApp: App {
@StateObject private var ll = Lmao()
var body: some Scene {
WindowGroup {
ContentView()
.environmentObject(ll)
}
}
}
myScene.scn: put some random stuff in a scene file
In ContentView use @State property wrapper allowOrNot
for toggling states:
import SwiftUI
import SceneKit
struct ContentView : View {
@State private var text: String = "CamControl is On"
@State private var allowOrNot: Bool = true
var body: some View {
ZStack {
VRViewContainer(allowOrNot: $allowOrNot)
.ignoresSafeArea()
VStack {
Text(text)
.onTapGesture {
allowOrNot.toggle()
if !allowOrNot { text = "CamControl is OFF" }
else { text = "CamControl is On" }
}
Spacer()
}
}
}
}
In VRViewContainer use @Binding property wrapper.
struct VRViewContainer: UIViewRepresentable {
@Binding var allowOrNot: Bool
func makeUIView(context: Context) -> SCNView {
let sceneView = SCNView(frame: .zero)
let scene = SCNScene(named: "art.scnassets/ship.scn")
sceneView.scene = scene
return sceneView
}
func updateUIView(_ uiView: SCNView, context: Context) {
uiView.allowsCameraControl = allowOrNot
}
}
If you wanna control a camera's transform using your code, you have to retrieve all the sixteen values from the transform matrix (position, orientation and scale) of the scene's default camera node (or from transform of any other SCNCamera node). In both cases, you'll need the sceneView
instance.
sceneView.pointOfView?.transform // SCNMatrix4
In simplified SwiftUI's SceneView
init you've got the parameter called pointOfView
:
SceneView(scene: SCNScene?, pointOfView: SCNNode?, options: SceneView.Options)