方法 `enumerateChildNodes` 没有找到节点
Method `enumerateChildNodes` is not finding nodes
我正在开发一个具有 2 个按钮的 ARKit 应用程序:“播放”和“重置”。当我点击播放时,会显示一个金字塔节点。当我点击重置时,所有的金字塔节点都应该从场景中删除:
另一个要求是我想在单击播放按钮时禁用它。
接下来是我的contentView代码:
import ARKit
struct ContentView: View {
@State var node = SCNNode()
@State var play: Bool = false
@State var reset: Bool = false
@State var isDisabled: Bool = false
@State var showBanner:Bool = true
var body: some View {
ZStack {
SceneKitView(node: $node, play: $play, reset: $reset, isDisabled: $isDisabled)
VStack {
Spacer()
HStack {
Button(action: {
play = true
}) {
Image("Play")
}.padding()
.disabled(isDisabled) /// <<<<< THIS DISABLES THE BUTTON
Spacer()
Button(action: {
play = false
reset = true
}) {
Image("Reset")
}.padding()
}
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
为了禁用“播放”按钮,我使用了 .disabled
和布尔值 isDisabled
。
我的代码在 Coordinator
中将 isDisabled
的值更改为 TRUE
:
import ARKit
import SwiftUI
struct SceneKitView: UIViewRepresentable {
let arView = ARSCNView(frame: .zero)
let config = ARWorldTrackingConfiguration()
@Binding var node: SCNNode
@Binding var play: Bool
@Binding var reset: Bool
@Binding var isDisabled: Bool
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
final class Coordinator: NSObject, ARSCNViewDelegate {
var control: SceneKitView
init(_ control: SceneKitView) {
self.control = control
}
func renderer(_ renderer: SCNSceneRenderer, willRenderScene scene: SCNScene, atTime time: TimeInterval) {
DispatchQueue.main.async {
if self.control.play {
self.control.addNode()
self.control.play = false
self.control.isDisabled = true // HERE I UPDATE THE VALUE !!!!!!!!
self.control.reset = false
}else{
}
}
}
}
func removeNode(){
self.arView.scene.rootNode.enumerateChildNodes { (node, _) in
print("existing nodes = \(node)")
node.removeFromParentNode()
}
}
func updateUIView(_ uiView: ARSCNView,
context: Context) {
if self.reset {
self.removeNode()
print("game reseted")
}
}
func makeUIView(context: Context) -> ARSCNView {
arView.scene = SCNScene()
arView.delegate = context.coordinator
arView.autoenablesDefaultLighting = true
//arView.debugOptions = [ARSCNDebugOptions.showFeaturePoints, ARSCNDebugOptions.showWorldOrigin]
arView.showsStatistics = true
arView.session.run(self.config)
return arView
}
func addNode(){
let pyramid = SCNNode(geometry: SCNPyramid(width: 0.1, height: 0.1, length: 0.1))
pyramid.geometry?.firstMaterial?.diffuse.contents = UIColor.red
pyramid.geometry?.firstMaterial?.specular.contents = UIColor.white
pyramid.position = SCNVector3(0,0,-0.5)
self.arView.scene.rootNode.addChildNode(pyramid)
}
}
问题:当应用程序处于运行并且我点击RESET时,方法removeNode
被调用并且该方法使用enumerateChildNodes
找到节点并使用 removeFromParentNode
删除它们,但金字塔节点没有被删除! :(
疯狂的事情(对我来说)是,如果我不更改 Coordinator
中 isDisabled
的值,即我注释那行,removeNode 工作,并且节点被删除!!!!!
欢迎任何评论、建议:)
这解决了问题:
func updateUIView(_ uiView: ARSCNView, context: Context) {
if self.reset {
DispatchQueue.main.async {
context.coordinator.control.removeNode()
context.coordinator.control.isDisabled = false
}
print("Game Reset")
}
}
我正在开发一个具有 2 个按钮的 ARKit 应用程序:“播放”和“重置”。当我点击播放时,会显示一个金字塔节点。当我点击重置时,所有的金字塔节点都应该从场景中删除:
另一个要求是我想在单击播放按钮时禁用它。
接下来是我的contentView代码:
import ARKit
struct ContentView: View {
@State var node = SCNNode()
@State var play: Bool = false
@State var reset: Bool = false
@State var isDisabled: Bool = false
@State var showBanner:Bool = true
var body: some View {
ZStack {
SceneKitView(node: $node, play: $play, reset: $reset, isDisabled: $isDisabled)
VStack {
Spacer()
HStack {
Button(action: {
play = true
}) {
Image("Play")
}.padding()
.disabled(isDisabled) /// <<<<< THIS DISABLES THE BUTTON
Spacer()
Button(action: {
play = false
reset = true
}) {
Image("Reset")
}.padding()
}
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
为了禁用“播放”按钮,我使用了 .disabled
和布尔值 isDisabled
。
我的代码在 Coordinator
中将 isDisabled
的值更改为 TRUE
:
import ARKit
import SwiftUI
struct SceneKitView: UIViewRepresentable {
let arView = ARSCNView(frame: .zero)
let config = ARWorldTrackingConfiguration()
@Binding var node: SCNNode
@Binding var play: Bool
@Binding var reset: Bool
@Binding var isDisabled: Bool
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
final class Coordinator: NSObject, ARSCNViewDelegate {
var control: SceneKitView
init(_ control: SceneKitView) {
self.control = control
}
func renderer(_ renderer: SCNSceneRenderer, willRenderScene scene: SCNScene, atTime time: TimeInterval) {
DispatchQueue.main.async {
if self.control.play {
self.control.addNode()
self.control.play = false
self.control.isDisabled = true // HERE I UPDATE THE VALUE !!!!!!!!
self.control.reset = false
}else{
}
}
}
}
func removeNode(){
self.arView.scene.rootNode.enumerateChildNodes { (node, _) in
print("existing nodes = \(node)")
node.removeFromParentNode()
}
}
func updateUIView(_ uiView: ARSCNView,
context: Context) {
if self.reset {
self.removeNode()
print("game reseted")
}
}
func makeUIView(context: Context) -> ARSCNView {
arView.scene = SCNScene()
arView.delegate = context.coordinator
arView.autoenablesDefaultLighting = true
//arView.debugOptions = [ARSCNDebugOptions.showFeaturePoints, ARSCNDebugOptions.showWorldOrigin]
arView.showsStatistics = true
arView.session.run(self.config)
return arView
}
func addNode(){
let pyramid = SCNNode(geometry: SCNPyramid(width: 0.1, height: 0.1, length: 0.1))
pyramid.geometry?.firstMaterial?.diffuse.contents = UIColor.red
pyramid.geometry?.firstMaterial?.specular.contents = UIColor.white
pyramid.position = SCNVector3(0,0,-0.5)
self.arView.scene.rootNode.addChildNode(pyramid)
}
}
问题:当应用程序处于运行并且我点击RESET时,方法removeNode
被调用并且该方法使用enumerateChildNodes
找到节点并使用 removeFromParentNode
删除它们,但金字塔节点没有被删除! :(
疯狂的事情(对我来说)是,如果我不更改 Coordinator
中 isDisabled
的值,即我注释那行,removeNode 工作,并且节点被删除!!!!!
欢迎任何评论、建议:)
这解决了问题:
func updateUIView(_ uiView: ARSCNView, context: Context) {
if self.reset {
DispatchQueue.main.async {
context.coordinator.control.removeNode()
context.coordinator.control.isDisabled = false
}
print("Game Reset")
}
}