Softimage SDK Programmer's Guide > Working with the SDK > ICE Node Particles >

# Accessing the Components of a Simulated ICE Tree

Nodes are accessible in an ICE tree one level at a time: if a node contains subnodes, then that node is considered to be a node container. This means that you need to perform some kind of recursion to get all of the nested subnodes.

Because ports can have multiple instances, you need to specify not only the portgroup index and the port index, but also which portgroup instance a port belongs to.

## JScript Example: To access the components of a simulated ICE tree through scripting

This example demonstrates how to navigate from the scene graph to the ICE tree, then how to traverse the ICE tree graph to visit each node and each port in turn.

    NewScene(null, false);
    var obj = CreatePrim("Cylinder", "MeshSurface");
    var emitter = EmitPointsFromObject(obj);

    // Find ICE tree (operator)
    var ICEop = emitter.ActivePrimitive.ICETrees(0);

    // From the ICE tree you get the list of nodes one level at a time
    RecursivelyLogNodeInfo(ICEop, "- ");

    // Recursive function for traversing a node graph
    function RecursivelyLogNodeInfo( node, indent )
    {
    	Application.LogMessage( indent + "Node: " + node.FullName + " is a " + node.Type );

    	// Now log the node's ports with their portgroups
    	if ( node.Type != "ICETree" ) {
    		for ( var i=0; i<node.PortGroupCount; i++ ) {
    			Application.LogMessage( indent + " - PortGroup["+i+"]" );
    			for ( var j=0; j<node.GetGroupInstanceCount(i); j++ ) {
    				Application.LogMessage( indent + " - - PortGroupInstance["+j+"]" );
    				for ( var k=0; k<node.GetPortCount(i); k++ ) {
    					var port = node.GetPortFromIndex(k, i, j);
    					var direction = ( port.IsOutput ) ? "output" : "input";
    					Application.LogMessage( indent + " - - - Port " + port.FullName + " is an " + direction );
    				}
    			}
    		}
    	}

    	// Recursion: if node contains other nodes, log them as well
    	if ( node.IsClassOf(siICENodeContainerID) ) {
    		for ( var h=0; h<node.Nodes.Count; h++ ) {
    			RecursivelyLogNodeInfo(node.Nodes(h), indent+"- ");
    		}
    	}
    }

    // Expected results:
    // INFO : - Node: PointCloud.pointcloud.ICETree is a ICETree
    // INFO : - - Node: PointCloud.pointcloud.ICETree.SceneReferenceNode is a SceneReferenceNode
    // INFO : - -  - PortGroup[0]
    // INFO : - -  - - PortGroupInstance[0]
    // INFO : - -  - - - Port PointCloud.pointcloud.ICETree.SceneReferenceNode.value is an output
    // INFO : - -  - - - Port PointCloud.pointcloud.ICETree.SceneReferenceNode.outname is an output
    // INFO : - -  - PortGroup[1]
    // INFO : - -  - - PortGroupInstance[0]
    // INFO : - -  - - - Port PointCloud.pointcloud.ICETree.SceneReferenceNode.source is an input
    // INFO : - -  - PortGroup[2]
    // INFO : - -  - - PortGroupInstance[0]
    // INFO : - -  - - - Port PointCloud.pointcloud.ICETree.SceneReferenceNode.inname is an input
    // INFO : - - Node: PointCloud.pointcloud.ICETree.Emit_from_Surface is a Emit_from_Surface
    // INFO : - -  - PortGroup[0]
    // INFO : - -  - - PortGroupInstance[0]
    // INFO : - -  - - - Port PointCloud.pointcloud.ICETree.Emit_from_Surface.Seed is an input
    // INFO : - -  - - - Port PointCloud.pointcloud.ICETree.Emit_from_Surface.Emitter1 is an input
    // INFO : - -  - - - Port PointCloud.pointcloud.ICETree.Emit_from_Surface.Select_Rate_Type is an input
    // etc.