Render a UIView in a SCNScene

I know this sounds weird but since it is possible to add a SKScene, why not?!

Since this work :

// Given a sceneSize we create a SKScene
let skScene = SKScene(size: sceneSize)
// And create a node, and assign skScene as the contents of our node geometry's material
let myNode = SCNNode(geometry: SCNPlane(width: sceneSize.width, height: sceneSize.height))
myNode.geometry!.firstMaterial!.diffuse.contents = skScene


I wanted to to this :

// Given a viewSize we create a UIView
let myUIView = UIView(frame: CGRect(origin: .zero, size: viewSize))
// And create a node, and assign myUIScene as the contents of our node geometry's material
let myNode = SCNNode(geometry: SCNPlane(width: sceneSize.width, height: sceneSize.height))
myNode.geometry!.firstMaterial!.diffuse.contents = myUIView


Surprisingly, this actually worked. According SCNMaterialProperty's documentation, contents doesn't take a UIView, but can take a CALayer. I am assuming this is what happens in this situation. However, where to go from there? You'll find out that touches don't work (nor UIGestureRecognizers) and auto-layout goes quite unstable (which we could expect...)


To solve the touches, I haven't figured so much but I am fine saying i'll just handle "taps". So in touchesEnded of my view controller I am using the hitTest method of my SCNSceneView this way :

  override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    guard let point = touches.first?.location(in: self.sceneView) else { return }
    if let result = self.sceneView.hitTest(point, options: nil) {
      let channel = result.node.geometry!geometry.firstMaterial!.diffuse.mappingChannel
      let texcoord = result.textureCoordinates(withMappingChannel: channel)
      myUIView.simulateTap(texcoord: texcoord)
    }
  }
// ...


To solve rendering... Yes, at this point, not only auto-layout doesn't work but updates to myUIView aren't reflected in my scene. Anyone would have an idea how to solve that?

Replies

Auto-layout and updates probably don't work because they rely on the UIKit event model to be running (and probably for the view to have a containment hierarchy ending in a window, so that frames and coordinates are well formed.)


What I'd try is creating a window, putting the window's layer on whatever your geometry or scene element is, and adding your views to that window. That might update properly.