Man*_*ero 1 xcode scenekit swift arkit swiftui
目标:使用 Scenekit 控制 SwiftUI 视图的 SwiftUI 切换按钮(UIViewRepresentable)
// 显示统计信息,例如 fps 和计时信息
我做了什么:这是 UIViewRepresentable ScenekitView
import SwiftUI
import SceneKit
struct ScenekitView : UIViewRepresentable {
let scene = SCNScene(named: "art.scnassets/ship.scn")!
func makeUIView(context: Context) -> SCNView {
// create and add a camera to the scene
let cameraNode = SCNNode()
cameraNode.camera = SCNCamera()
scene.rootNode.addChildNode(cameraNode)
// place the camera
cameraNode.position = SCNVector3(x: 0, y: 0, z: 15)
// create and add a light to the scene
let lightNode = SCNNode()
lightNode.light = SCNLight()
lightNode.light!.type = .omni
lightNode.position = SCNVector3(x: 0, y: 10, z: 10)
scene.rootNode.addChildNode(lightNode)
// create and add an ambient light to the scene
let ambientLightNode = SCNNode()
ambientLightNode.light = SCNLight()
ambientLightNode.light!.type = .ambient
ambientLightNode.light!.color = UIColor.darkGray
scene.rootNode.addChildNode(ambientLightNode)
// retrieve the ship node
let ship = scene.rootNode.childNode(withName: "ship", recursively: true)!
// animate the 3d object
ship.runAction(SCNAction.repeatForever(SCNAction.rotateBy(x: 0, y: 2, z: 0, duration: 1)))
// retrieve the SCNView
let scnView = SCNView()
return scnView
}
func updateUIView(_ scnView: SCNView, context: Context) {
scnView.scene = scene
// allows the user to manipulate the camera
scnView.allowsCameraControl = true
// show statistics such as fps and timing information
scnView.showsStatistics = true
// configure the view
scnView.backgroundColor = UIColor.black
}
}
struct ScenekitView_Previews: PreviewProvider {
static var previews: some View {
ScenekitView()
}
}
Run Code Online (Sandbox Code Playgroud)
这是控制Scenekit的菜单
import SwiftUI
struct Menu: View {
@State var showstats = false
var body: some View {
HStack {
Form {
Toggle(isOn:) {
Text("Stats")
}
}
.frame(width: 200.0)
Spacer()
}
}
}
struct Menu_Previews: PreviewProvider {
static var previews: some View {
Menu()
}
}
Run Code Online (Sandbox Code Playgroud)
这是主场景,菜单位于 Scenekit 之上:
import SwiftUI
struct MainView: View {
var body: some View {
ZStack {
ScenekitView()
Menu()
}
}
}
Run Code Online (Sandbox Code Playgroud)
问题:如何将数据从 ScenekitView 传递到菜单,以便我可以切换和显示/隐藏统计信息?
我尝试了 ObservableObject 但无法使其工作。还研究了其他 SO 线程,但没有一个对我有用。
任何帮助深表感谢!
更新日期:2023 年 2 月 5 日。
要将数据传递给updateNSView(_:context:)实例updateUIView(_:context:)方法,您需要创建@State属性@Binding。
使用以下代码了解如何操作(我为 macOS 编写了此代码,但您可以轻松地将其更改为 iOS):
import SwiftUI
import SceneKit
struct ContentView: View {
@State var stats: Bool = true
var body: some View {
HStack {
ScenekitView(showStats: $stats)
VStack {
Button(action: {
self.stats.toggle()
}, label: {
Text(self.stats ? "ON" : "OFF")
})
}.frame(width: 150.0)
}
}
}
struct ScenekitView: NSViewRepresentable {
@Binding var showStats: Bool
let sceneView = SCNView(frame: .zero)
let scene = SCNScene(named: "art.scnassets/ship.scn")!
func scnScene(stat: Bool, context: Context) -> SCNView {
sceneView.scene = scene
sceneView.showsStatistics = stat
return sceneView
}
func makeNSView(context: Context) -> SCNView {
scnScene(stat: true, context: context)
}
func updateNSView(_ uiView: SCNView, context: Context) {
uiView.allowsCameraControl = true
uiView.backgroundColor = NSColor.black
uiView.showsStatistics = showStats
}
}
Run Code Online (Sandbox Code Playgroud)
此外,您可以使用
Coordinator对象和delegate此协调器来使用control属性切换对象以及在方法内以 60 fps 更新任何内容renderer()(例如)。
在这种情况下,您不需要使用updateNSView()或updateUIView()方法:
struct ScenekitView: NSViewRepresentable {
@Binding var showStats: Bool
let sceneView = SCNView(frame: .zero)
let scene = SCNScene(named: "art.scnassets/ship.scn")!
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
final class Coordinator: NSObject, SCNSceneRendererDelegate {
var control: ScenekitView
init(_ control: ScenekitView) {
self.control = control
}
func renderer(_ renderer: SCNSceneRenderer,
updateAtTime time: TimeInterval) {
control.sceneView.showsStatistics = control.showStats
control.sceneView.backgroundColor = NSColor(
red: CGFloat(arc4random_uniform(256)) / 255.0,
green: CGFloat(arc4random_uniform(256)) / 255.0,
blue: CGFloat(arc4random_uniform(256)) / 255.0,
alpha: 1.0)
}
}
func scnScene(stat: Bool, context: Context) -> SCNView {
sceneView.scene = scene
sceneView.showsStatistics = stat
sceneView.delegate = context.coordinator
return sceneView
}
func makeNSView(context: Context) -> SCNView {
scnScene(stat: true, context: context)
}
func updateNSView(_ uiView: SCNView, context: Context) { }
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2546 次 |
| 最近记录: |