0

My renderer function is not being called when the delegate is set to the SCNView in a Swift playground.

I already looked at this question: SceneKit SCNSceneRendererDelegate - renderer function not called

None of the solutions on that page seemed to solve my problem. I've already tried adding a meaningless animation, enabling isLooping, enabling isPlaying, and made sure the rendering function syntax is correct.

I'm entirely lost as to what's missing, as seemingly identical code was used as a part of a PlaygroundBook and works. Thanks ahead of time.

import UIKit
import SceneKit
import PlaygroundSupport
import Foundation

class TestingRenderer: NSObject, SCNSceneRendererDelegate
{
    var tornadoCenter: SCNNode!
    let gameScene = SCNScene()
    var cameraNode: SCNNode!

    public func awakening()
    {
        cameraNode = SCNNode()
        cameraNode.camera = SCNCamera()

        // place the camera
        cameraNode.position = SCNVector3(x: 0, y: 0, z: 0)
        cameraNode.camera?.zFar = 200
        gameScene.rootNode.addChildNode(cameraNode)

        tornadoCenter = SCNNode()
        tornadoCenter.position = SCNVector3(x: 0, y: 0, z: 0)
        gameScene.rootNode.addChildNode(tornadoCenter)

// meaningless animation
        let animation = CABasicAnimation(keyPath: "rotation")
        animation.toValue = NSValue(scnVector4: SCNVector4(x: Float(0), y: Float(1), z: Float(0), w: Float.pi * 2))
        animation.duration = 30000
        animation.repeatCount = MAXFLOAT //repeat forever
        tornadoCenter.addAnimation(animation, forKey: nil)
    }

    func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval)
    {
        print("eeee")
    }

    func getScene() -> SCNScene
    {
        return gameScene
    }
}

class TestingView: SCNView
{
    public func setup()
    {
        let renderer = TestingRenderer()
        renderer.awakening()

        self.scene = renderer.getScene()
        self.backgroundColor = UIColor.black
        self.autoenablesDefaultLighting = true
        self.allowsCameraControl = true
        self.delegate = renderer
    }
}

class MyViewController : UIViewController
{
    var sceneView: TestingView!

    override func loadView()
    {
        let view = UIView()

        sceneView = TestingView()
        sceneView.setup()

        view.addSubview(sceneView)
        self.view = view
    }

    override func viewDidLayoutSubviews()
    {
        sceneView.frame = self.view.frame
    }
}

PlaygroundPage.current.liveView = MyViewController()

2 Answers2

0

You need to make the delegate method visible by SceneKit by using the @objc attribute.

The objc attribute tells the compiler that a declaration is available to use in Objective-C code.

@objc func renderer(_ renderer: SCNSceneRenderer, updateAtTime time: TimeInterval)
{
    print("eeee")
}
mnuages
  • 13,049
  • 2
  • 23
  • 40
0

You need to keep a reference to your renderer, at the moment it's getting deallocated as soon as the setup function returns.

e.g.

class TestingView: SCNView
{
    let renderer = TestingRenderer()

    public func setup()
    {
        renderer.awakening()

        self.scene = renderer.getScene()
        self.backgroundColor = UIColor.black
        self.autoenablesDefaultLighting = true
        self.allowsCameraControl = true
        self.delegate = renderer
    }
}
James P
  • 4,786
  • 2
  • 35
  • 52