快速添加按钮到SCNNode [英] Swift Add Button to SCNNode

查看:130
本文介绍了快速添加按钮到SCNNode的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在玩ARKit和图像检测. 现在,我有一个应用程序,该应用程序可以检测图像并在屏幕上将检测到的对象放置在平面上.

I'm playing around with the ARKit and image detection. Now I have an app that detects images an places planes on the screen where the detected objects are.

如何在飞机上添加可点击元素,例如按钮.我想对每个检测到的对象都单击事件.

How can I add a clickable element like a button on the planes. I want to have a click event on each detected object.

这是我的渲染器函数的外观:

This is what my renderer function looks:

func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {
        guard let imageAnchor = anchor as? ARImageAnchor else { return }
        let referenceImage = imageAnchor.referenceImage
        updateQueue.async {
            let plane = SCNPlane(width: referenceImage.physicalSize.width,
                                 height: referenceImage.physicalSize.height)
            let planeNode = SCNNode(geometry: plane)

            planeNode.opacity = 0.25
            planeNode.eulerAngles.x = -.pi / 2
            planeNode.runAction(self.imageHighlightAction)
            node.addChildNode(planeNode)
        }

        DispatchQueue.main.async {
            let imageName = referenceImage.name ?? ""
            self.statusViewController.cancelAllScheduledMessages()
            // self.statusViewController.showMessage("Detected image "\(imageName)"")
            let storyboard = UIStoryboard(name: "Main", bundle: nil)
            let second = storyboard.instantiateViewController(withIdentifier: "InfoViewController")as! InfoViewController
            second.myStringValue = imageName
            // self.navigationController?.pushViewController(second, animated: true)
        }
    }

推荐答案

有几种方法可以解决此问题:

There are a few ways you can approach this:

1:标准方法:

在您的delegate方法中,按以下方式为每个节点分配一个名称(显然,如果您有很多节点,您将根据需要将它们存储在数组或字典中):

In your delegate method, assign each node a name as per below (clearly if you have lots of nodes you would want to store them in an Array or Dictionary depending upon your needs):

 func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {

    //1. Check We Have The Image Anchor
    guard let imageAnchor = anchor as? ARImageAnchor else { return }

    //2. Get The Reference Image
    let referenceImage = imageAnchor.referenceImage

    //1. Create The Plane Geometry With Our Width & Height Parameters
    let planeGeometry = SCNPlane(width: referenceImage.physicalSize.width,
                         height: referenceImage.physicalSize.height)

    //2. Create A New Material
    let material = SCNMaterial()

    material.diffuse.contents = UIColor.red

    //3. Create The Plane Node
    let planeNode = SCNNode(geometry: planeGeometry)

    planeNode.geometry?.firstMaterial = material

    planeNode.opacity = 0.25

    planeNode.eulerAngles.x = -.pi / 2

    //4. Add A Name To The Node
    planeNode.name = "I Was Clicked"

    //5. Add It To The Scene
    node.addChildNode(planeNode)

}

然后使用touchesBegan进行一次hitTest并相应地处理触摸:

Then using touchesBegan, perform a hitTest and handle your touch accordingly:

   override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {

    /*
     1. Get The Current Touch Location
     2. Check That We Have Touched A Valid Node
     3. Check If The Node Has A Name
     4. Handle The Touch
     */

    guard let touchLocation = touches.first?.location(in: augmentedRealityView),
        let hitNode = augmentedRealityView?.hitTest(touchLocation, options: nil).first?.node,
        let nodeName = hitNode.name
        else {
            //No Node Has Been Tapped
            return

    }
    //Handle Event Here e.g. PerformSegue
    print(nodeName)

}

2:一种有趣的方法:

UIKit元素实际上可以作为SCNGeometry's Material添加.我个人没有见过很多人使用这种方法,但是对于想将UIKitARKit结合的人来说,它可能很有用.

UIKit elements can actually be added as an SCNGeometry's Material. I personally haven't seen many people use this approach, but it may prove useful to anyone who wants to incorporate UIKit with ARKit.

创建自定义UIButton,例如:

Create A Custom UIButton e.g:

/// Clickable View
class ClickableView: UIButton{

    override init(frame: CGRect) {

    super.init(frame: frame)

    self.addTarget(self, action:  #selector(objectTapped(_:)), for: .touchUpInside)

    self.backgroundColor = .red

}

required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

/// Detects Which Object Was Tapped
///
/// - Parameter sender: UIButton
@objc func objectTapped(_ sender: UIButton){

    print("Object With Tag \(tag)")

   }

}

然后在您的委托方法中执行以下操作:

And in your delegate method do the following:

  func renderer(_ renderer: SCNSceneRenderer, didAdd node: SCNNode, for anchor: ARAnchor) {

    //1. Check We Have The Image Anchor
    guard let imageAnchor = anchor as? ARImageAnchor else { return }

    //2. Get The Reference Image
    let referenceImage = imageAnchor.referenceImage

    //1. Create The Plane Geometry With Our Width & Height Parameters
    let planeGeometry = SCNPlane(width: referenceImage.physicalSize.width,
                         height: referenceImage.physicalSize.height)

    //2. Create A New Material
    let material = SCNMaterial()

    DispatchQueue.main.async {
        //3. Create The New Clickable View
        let clickableElement = ClickableView(frame: CGRect(x: 0, y: 0,
                                                           width: 300,
                                                           height: 300))
        clickableElement.tag = 1

        //4. Add The Clickable View As A Materil
        material.diffuse.contents = clickableElement
    }

    //5. Create The Plane Node
    let planeNode = SCNNode(geometry: planeGeometry)

    planeNode.geometry?.firstMaterial = material

    planeNode.opacity = 0.25

    planeNode.eulerAngles.x = -.pi / 2

    //6. Add It To The Scene
    node.addChildNode(planeNode)
}

这应该让您入门...

This should get you started...

这篇关于快速添加按钮到SCNNode的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆