首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >SwiftUI: HitTest on Scenekit

SwiftUI: HitTest on Scenekit
EN

Stack Overflow用户
提问于 2020-06-16 00:09:34
回答 1查看 489关注 0票数 2

目标:使用SwiftUI (而不是UIKit)进行SceneKit命中测试

问题:当我在SwiftUI "UIViewRepresentable“上嵌入默认的船舶场景时,示例handleTap函数不起作用。我明白他的错误:

“'#selector‘的参数引用未公开给Objective-C的实例方法'handleTap’”

如何创建命中测试,并将数据传递到另一个SwiftUI视图?

代码语言:javascript
复制
import SwiftUI
import SceneKit

 var handleTap: (() -> Void)

struct ScenekitView : UIViewRepresentable {
    let scene = SCNScene(named: "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)



        // retrieve the ship node
        let ship = scene.rootNode.childNode(withName: "ship", recursively: true)!



        // 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

        // add a tap gesture recognizer
      let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTap(_:)))
      scnView.addGestureRecognizer(tapGesture)
    }



    func handleTap(_ gestureRecognize: UIGestureRecognizer) {
        // retrieve the SCNView
        let scnView = SCNView()


        // check what nodes are tapped
        let p = gestureRecognize.location(in: scnView)
        let hitResults = scnView.hitTest(p, options: [:])
        // check that we clicked on at least one object
        if hitResults.count > 0 {
            // retrieved the first clicked object
            let result = hitResults[0]

            // get material for selected geometry element
            let material = result.node.geometry!.firstMaterial




            // highlight it
            SCNTransaction.begin()
           SCNTransaction.animationDuration = 0.5

            // on completion - unhighlight
            SCNTransaction.completionBlock = {
                SCNTransaction.begin()
                SCNTransaction.animationDuration = 0.5

                material?.emission.contents = UIColor.black

                SCNTransaction.commit()
            }

            material?.emission.contents = UIColor.green

            SCNTransaction.commit()
        }
    }
}

#if DEBUG
struct ScenekitView_Previews : PreviewProvider {
    static var previews: some View {
        ScenekitView()
    }
}
#endif
EN

回答 1

Stack Overflow用户

发布于 2020-08-18 11:58:21

我自己解决了这个问题,并最终找到了一个解决方案:创建一个从实际包含SCNView的类中提取的虚拟结构。

这对我来说很有效:

代码语言:javascript
复制
struct ScenekitView : UIViewRepresentable {
    let scenekitClass = ScenekitClass()

    func makeUIView(context: Context) -> SCNView {
        return scenekitClass.view
    }

    func updateUIView(_ scnView: SCNView, context: Context) {
        // your update UI view contents look like they can all be done in the initial creation
    }
}

class ScenekitClass {
    let view = SCNView()
    let scene = SCNScene(named: "ship.scn")!
    
    init() {
        // 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)
        
        // attach the scene
        view.scene = scene

        // allows the user to manipulate the camera
        view.allowsCameraControl = true

        // show statistics such as fps and timing information
        view.showsStatistics = true

        // configure the view
        view.backgroundColor = UIColor.black

        // add a tap gesture recognizer
        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTap(_:)))
        view.addGestureRecognizer(tapGesture)
    }
    
    @objc func handleTap(_ gestureRecognize: UIGestureRecognizer) {
        // check what nodes are tapped
        let p = gestureRecognize.location(in: view)
        let hitResults = view.hitTest(p, options: [:])
        // check that we clicked on at least one object
        if hitResults.count > 0 {
            // retrieved the first clicked object
            let result = hitResults[0]

            // get material for selected geometry element
            let material = result.node.geometry!.firstMaterial
            
            // highlight it
            SCNTransaction.begin()
            SCNTransaction.animationDuration = 0.5

            // on completion - unhighlight
            SCNTransaction.completionBlock = {
                SCNTransaction.begin()
                SCNTransaction.animationDuration = 0.5

                material?.emission.contents = UIColor.black

                SCNTransaction.commit()
            }

            material?.emission.contents = UIColor.green

            SCNTransaction.commit()
        }
    }
}

Based on this question.

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62392363

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档