2017-08-27 4 views
1

J'écris une application iOS en utilisant ARKit et SceneKit sur iOS 11 (beta).Comment stocker des informations supplémentaires dans SCNNode?

Cette application ajoute de nombreux éléments sur une scène de réalité augmentée. Afin d'identifier chacun de ces numéros, je SCNNode comme sous-classé MySCNNode et mettre un champ id en elle:

MySCNNode: SCNNode { 
    var id: Int 
    ...some initializer to assign value to the id 
} 

I a également mis en œuvre une méthode déléguée touchesBegan. Lorsque l'utilisateur touche un élément, je souhaite récupérer son id correspondant. J'ai donc essayé jeté cet élément de correspondant SCNNode Retour à MySCNNode:

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

    // hitTest to retrieve item's id 
    if let touchLocation = touches.first?.location(in: sceneLocationView) { 
     DDLogDebug("received touch location") 
     if let hit = sceneLocationView.hitTest(touchLocation, options: nil).first { 
      DDLogDebug("received a hit") 
      if let scnNode = hit.node as? SCNNode { 
       DDLogDebug("received a scnNode)") 
        if let mySCNNode = scnNode as? MySCNNode { 
         DDLogDebug("received a MySCNNode") // ====> Never reaches here 
        } 

      } 


      return 
     } 


    } 


} 

Cependant, l'étape de coulée SCNNode-MySCNNode ne se produit jamais

Ai-je écrit un endroit mal en essayant de jeter le SCNNode retour à MySCNNode dans le test de succès ci-dessus? Existe-t-il un autre moyen de stocker des informations supplémentaires dans un SCNNode et de le récupérer plus tard?

Merci

+0

« Afin d'identifier chacun de ces numéros » Utilisez la propriété du nom dans la vue de la scène. –

Répondre

0

je pense que vous êtes sur la bonne voie, mais vous n'avez pas besoin de tant de moulages et il est plus facile si vous « pile » les if let s. Essayez ceci:

if let touchLocation = touches.first?.location(in: sceneLocationView), 
    let hit = sceneLocationView.hitTest(touchLocation, options: nil).first, 
    let myNode = hit.node as? MySCNNode { 
    DDLogDebug("received a MySCNNode") 
} 
2

Tout d'abord, vous n'avez pas besoin de id. Au lieu de cela, vous pouvez utiliser l'attribut name existant. Mais si vous voulez vérifier le type de noeud, vous devez également vérifier ses parents, car le noeud de résultat hitTest démarre à partir de l'enfant. Vous pouvez ajouter l'extension SCNNode:

extension SCNNode { 
    /// Returns parent node of specified type. 
    /// 
    /// - Returns: An optional `SCNNode` of specified `T` class type. 
    func parentOfType<T: SCNNode>() -> T? { 
     var node: SCNNode! = self 
     repeat { 
      if let node = node as? T { return node } 
      node = node?.parent 
     } while node != nil 
     return nil 
    } 
} 

Et puis utilisez:

if let myNode = node.parentOfType() as? MySCNNode { 
    // do something 
}