oliver
oliver

Reputation: 355

SceneKit material blinking

I want to make a node blinking (loop from input color to current firstMaterial for example). The node has a material which is shared with many others nodes but I don't want all the nodes blinking (only selected nodes).

I succeeded to do that without SCNAction/SCNTransaction but the code is dirty, very hard to maintain and must be called in Update()... I was wondering if SCNAction/SCNTransaction could help me but I don't know how to do this the right way.

Upvotes: 0

Views: 1197

Answers (1)

PongBongoSaurus
PongBongoSaurus

Reputation: 7385

I believe something like this will point you in the right direction.

First we will create an extension of SCNNode so that we can make use of our function on any SCNNode:

//-----------------------
//MARK: SCNNode Extension
//-----------------------

extension SCNNode{

    /// Creates A Pulsing Animation On An Infinite Loop
    ///
    /// - Parameter duration: TimeInterval
    func highlightNodeWithDurarion(_ duration: TimeInterval){

        //1. Create An SCNAction Which Emmits A Red Colour Over The Passed Duration Parameter
        let highlightAction = SCNAction.customAction(duration: duration) { (node, elapsedTime) in

            let color = UIColor(red: elapsedTime/CGFloat(duration), green: 0, blue: 0, alpha: 1)
            let currentMaterial = self.geometry?.firstMaterial
            currentMaterial?.emission.contents = color

        }

        //2. Create An SCNAction Which Removes The Red Emissio Colour Over The Passed Duration Parameter
        let unHighlightAction = SCNAction.customAction(duration: duration) { (node, elapsedTime) in
            let color = UIColor(red: CGFloat(1) - elapsedTime/CGFloat(duration), green: 0, blue: 0, alpha: 1)
            let currentMaterial = self.geometry?.firstMaterial
            currentMaterial?.emission.contents = color

        }

        //3. Create An SCNAction Sequence Which Runs The Actions
        let pulseSequence = SCNAction.sequence([highlightAction, unHighlightAction])

        //4. Set The Loop As Infinitie
        let infiniteLoop = SCNAction.repeatForever(pulseSequence)

        //5. Run The Action
        self.runAction(infiniteLoop)
    }

}

Lets say that we then create an SCNNode with an SCNSphereGeometry like so:

let blueNode = SCNNode()
let blueGeometry = SCNSphere(radius: 0.2)
blueGeometry.firstMaterial?.diffuse.contents = UIColor.blue
blueNode.geometry = blueGeometry
blueNode.position = SCNVector3(1.5, 0, -1.5)
blueNode.name = "BlueNode"
augmentedRealityView.scene.rootNode.addChildNode(redNode)

We can then call the highlight function on this (or any SCNNode) like so:

blueNode.highlightNodeWithDurarion(5)

Upvotes: 4

Related Questions