0

I'm loading a node from a .dae file with the following code:

func newNode() -> SCNNode {
var node = SCNNode()
let scene = SCNScene(named: "circle.dae")
var nodeArray = scene!.rootNode.childNodes

for childNode in nodeArray {
    node.addChildNode(childNode as! SCNNode)
    }
return node
}

I would now like to add some properties and methods to this specific node so that when I load it in a scene it gets a random color that I can then modify whenever I want. I had done something similar with a subclass of a SCNSphere (which is a geometry and not a node, though) using:

let NumberOfColors: UInt32 = 4

enum EllipsoidColor: Int, Printable {
case Red = 0, Blue, Green, White

var ellipsoidName: String {
    switch self {
    case .Red:
        return "red"
    case .Blue:
        return "blue"
    case .Green:
        return "green"
    case .White:
        return "white"
    }
}

var description: String {
    return self.ellipsoidName
}

static func random() -> EllipsoidColor {
    return EllipsoidColor(rawValue: Int(arc4random_uniform(NumberOfColors - 1)))!
    }
}


class Ellipsoid: SCNNode {

func setMaterialColor(ellipsoidColor: EllipsoidColor) {
    let color: UIColor

    switch ellipsoidColor {
    case .Red:
        color = UIColor.redColor()
    case .Blue:
        color = UIColor.blueColor()
    case .Green:
        color = UIColor.greenColor()
    case .White:
        color = UIColor.whiteColor()
    }

    self.geometry?.firstMaterial!.diffuse.contents = color
}

var color : EllipsoidColor {
    didSet {
        self.setMaterialColor(color)
    }
}

init(color: EllipsoidColor) {
    self.color = color
    super.init()
    self.setMaterialColor(color)
    }

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

How can I "link" this subclass to the node that I obtain using newNode() ? I naively thought that using something like

let ellipsoid = newNode() as! Ellipsoid

would work, but it doesn't. Thanks for your time and help.

Hari Seldon
  • 141
  • 10

1 Answers1

0

Well, your code cannot work.

In newNode you create a SCNNode:

func newNode() -> SCNNode {
   var node = SCNNode()
   //...
   return node
}

And later on you tell the compiler that this SCNNode is a Ellipsoid

let ellipsoid = newNode() as! Ellipsoid

But it isn't! It’s a SCNNode. Of course your program will crash.

If you want an Ellipsoid create one:

func newEllipsoid() -> Ellipsoid {
   var node = Ellipsoid()
   //...
   return node
}

(or wherever you need to create it)

idmean
  • 14,540
  • 9
  • 54
  • 83
  • That fixed it, but it looks like my code for assigning and changing a color doesn't work. Is it because it's a node and I need a geometry object to do that? I thought that nodes loaded from .dae files already had geometries in them. – Hari Seldon Jul 30 '15 at 10:00
  • @HariSeldon changing the color of what? Of the ellipsoid? – idmean Jul 30 '15 at 10:35
  • Yes, according to my Ellipsoid subclass code initializing an ellipsoid with newNode() should give me an object with a random color, but that doesn't happen because self.geometry? returns nil. Does that mean the node I load from the .dae file has no geometry property? Thanks a lot for your help – Hari Seldon Jul 30 '15 at 10:40
  • @HariSeldon Your Ellipsoid is not loaded from a file. You load a scene from a file and add the nodes of that scene to your Ellipsoid. So your ellipsoid has many child nodes but not a geometry. You will need to explicitely create one and it to the Ellipsoid. (You can verify this by changing the question mark in `self.geometry?.firstMaterial!.d...` to a exclamation mark. Your program should crash if I'm right) – idmean Jul 30 '15 at 10:56
  • That's what I thought, so how should I modify my program in order to be able to change the ellipsoid's color? – Hari Seldon Jul 30 '15 at 11:01
  • @HariSeldon In your initializer create and assign a geometry. Something like `self.geometry = SCNSphere(radius: 5)` – idmean Jul 30 '15 at 11:10