Softimage SDK Programmer's Guide > Customizing with the SDK > Custom ICENodes > Custom ICENode Processing >

# Iterating Over Port Data

Given the following ICENode ports:

    nodeOpDef.AddInputPort( ID_Port0, ID_Group0, siICENodePortDataLong, siICENodePortStructureSingle, siICENodeEvaluationContextAny, L"Port_0", L"Port_0" );
    nodeOpDef.AddInputPort( ID_Port1, ID_Group0, siICENodeDataVector3, siICENodePortStructureSingle, siICENodeEvaluationContextAny, L"Port_1", L"Port_1" );
    nodeOpDef.AddInputPort( ID_Port2, ID_Group0, siICENodePortDataFloat, siICENodePortStructureArray, siICENodeEvaluationContextAny, L"Port_2", L"Port_2" );
    nodeOpDef.AddOutputPort( ID_OutPort0, siICENodeDataVector3, siICENodePortStructureSingle, siICENodeEvaluationContextAny, L"OutPort_0", L"OutPort_0" );
    nodeOpDef.AddOutputPort( ID_OutPort1, siICENodePortDataFloat, siICENodePortStructureArray, siICENodeEvaluationContextAny, L"OutPort_1", L"OutPort_1" );
    nodeOpDef.AddOutputPort( ID_OutPort2, siICENodePortDataLong, siICENodePortStructureSingle, siICENodeEvaluationContextAny, L"OutPort_2", L"OutPort_2" );

The next block demonstrates how to iterate over the port data defined above and how to filter out elements:

    XSIPLUGINCALLBACK CStatus SampleNode_Evaluate( ICENodeContext& in_ctxt )
    {
    	// Switch over the output port being evaluated
    	ULONG outportID = in_ctxt.GetEvaluatedOutputPortID( );

    	// Create the index set
    	CIndexSet indexSet( in_ctxt );
    	switch ( outportID )
    	{
    		// This section demonstrates a regular array iteration
    		case ID_OutPort0:
    		{
    			// Get the data from port 0 and port 1
    			CDataArrayLong port0( in_ctxt, ID_Port0 );
    			CDataArrayVector3f port1( in_ctxt, ID_Port1 );

    			// Get the output array
    			CDataArrayVector3 outPort0( in_ctxt );

    			// Now fill the output array
    			for( CIndexSet::Iterator it = indexSet.Begin(); it.HasNext(); it.Next())
    			{
    				ULONG nIndex = it;
    				XSI::MATH::CVector3f v3f( port1[ nIndex ] );
    				outPort0[ nIndex ].Set( v3f.GetY(), port0[ nIndex ] * v3f.GetZ(), v3f.GetX() );
    			}
    		}
    		break;

    		// This section demonstrates how to iterate over a 2D array
    		case ID_OutPort1:
    		{
    			// Get the 2D array from port 2
    			CDataArray2DFloat port2( in_ctxt, ID_Port2 );

    			// Get the output 2D array
    			CDataArray2DFloat outPort1( in_ctxt );

    			// The first loop iterates normally on outPort1
    			for( CIndexSet::Iterator it = indexSet.Begin(); it.HasNext(); it.Next())
    			{
    				// Now we use the Accessor class to allocate the output buffer and to iterate over the sub-array of outPort1
    				CDataArray2DFloat::Accessor floatAccessor = port2[it];

    				CDataArray2DFloat::Accessor outAccessor = outPort1.Resize( it, floatAccessor.GetCount( ) );

    				for (ULONG i=0; i<floatAccessor.GetCount( ); i++)
    				{
    					// Set the output 2D array
    					outAccessor[i] = floatAccessor[i];
    				}
    			}
    		}
    		break;

    		// This section demonstrates how to filter out element items
    		case ID_OutPort2:
    		{
    			// Get the data from port 0
    			CDataArrayLong port0( in_ctxt, ID_Port0 );

    			// Get the output array
    			CDataArrayLong outPort2( in_ctxt );

    			for( CIndexSet::Iterator it = indexSet.Begin(); it.HasNext(); /* do not call it.Next() here as it could increment the iterator twice! */ )
    			{
    				outPort2[ it ] = port0[ it ];

    				if ( port0[ it ] < 10 )
    				{
    					// Filter out elements of port 0 below 10
    					it.Remove( );

    					// Important: Remove() will increment the iterator position by itself
    				}
    				else
    				{
    					// Nothing to filter out, go to next item
    					it.Next( );
    				}
    			}
    		}
    		break;
    	};

    	return CStatus::OK;
    }