Softimage SDK Programmer's Guide > Customizing Softimage using the SDK > Custom ICENodes > Custom ICENode Categories >

# Regular Custom ICENode

Most custom ICENodes are regular ICENodes processed in multi-threading mode. Data and structure types define the port data type that gets propagated through other ICENodes and context types specify the connection compatibility of custom node ports with other ICENode ports. Mixing context types together is supported for both input and output ports but must follow this rule:

- siICENodeContextSingleton can be mixed with

  siICENodeContextComponent0D and/or

  siICENodeContextComponent1D and/or

  siICENodeContextComponent2D and/or

  siICENodeContextComponent0D2D. All ports defined with a mixed context type must be constrained with a context map ID.

Important

Softimage will log an error at registration time if the above rule is not met, in which case the ICENode registration will be aborted.

Tip

See the CustomVector3ToScalar Example for an example of how to create a regular ICENode.

## Example: Custom ICENode Using Mixed Context Types:

    enum IDs
    {
    	ID_IN_SINGLETON = 0,
    	ID_IN_COMPONENT0D = 1,
    	ID_IN_SINGLETON_OR_COMPONENT0D = 2,
    	ID_G_100 = 100,
    	ID_OUT_FLOAT_ARRAY = 200,
    	ID_OUT_VECTOR3F_ARRAY = 201,
    	ID_TYPE_CNS = 400,
    	ID_STRUCT_CNS,
    	ID_CTXT_CNS,
    	ID_UNDEF = ULONG_MAX
    };

    XSI::CStatus MixedContextSample_Register( XSI::PluginRegistrar& in_reg );

    XSIPLUGINCALLBACK CStatus XSILoadPlugin( PluginRegistrar& in_reg )
    {
    	in_reg.PutAuthor(L"Softimage");
    	in_reg.PutName(L"MixedContextSample Plugin");
    	in_reg.PutVersion(1,0);

    	MixedContextSample_Register( in_reg );

    	return CStatus::OK;
    }

    CStatus MixedContextSample_Register( PluginRegistrar& in_reg )
    {
    	ICENodeDef nodeDef;
    	nodeDef = Application().GetFactory().CreateICENodeDef(L"MixedContextSample");
    	CStatus st;

    	st = nodeDef.AddPortGroup( ID_G_100 );
    	st.AssertSucceeded();

    	// This port is a single integer.
    	st = nodeDef.AddInputPort( ID_IN_SINGLETON,
    		ID_G_100,
    		siICENodeDataLong,
    		siICENodeStructureSingle,
    		siICENodeContextSingleton,
    		L"int_singleton", L"int_singleton",
    		1L,
    		ID_UNDEF, ID_UNDEF, ID_UNDEF );
    	st.AssertSucceeded( ) ;

    	// Array of positions port.
    	st = nodeDef.AddInputPort( ID_IN_COMPONENT0D,
    		ID_G_100,
    		siICENodeDataVector3,
    		siICENodeStructureSingle,
    		siICENodeContextSingleton | siICENodeContextComponent0D,
    		L"C0D", L"C0D",
    		MATH::CVector3f(1.0,1.0,1.0),
    		ID_UNDEF, ID_UNDEF, ID_CTXT_CNS );
    	st.AssertSucceeded( ) ;

    	// A single float or an array of floats matching the positions array count above.
    	st = nodeDef.AddInputPort( ID_IN_SINGLETON_OR_COMPONENT0D,
    		ID_G_100,
    		siICENodeDataFloat,
    		siICENodeStructureSingle,
    		siICENodeContextSingleton | siICENodeContextComponent0D,
    		L"Singleton_or_C0D", L"Singleton_or_C0D",
    		1.0f,
    		ID_UNDEF, ID_UNDEF, ID_CTXT_CNS );
    	st.AssertSucceeded( ) ;

    	// Port to output an array of float values
    	st = nodeDef.AddOutputPort( ID_OUT_FLOAT_ARRAY,
    		siICENodeDataFloat,
    		siICENodeStructureArray,
    		siICENodeContextSingleton | siICENodeContextComponent0D,
    		L"OutFloatArray", L"OutFloatArray",
    		ID_UNDEF, ID_UNDEF, ID_CTXT_CNS );
    	st.AssertSucceeded( ) ;

    	// Port to output an array of CVector3f values
    	st = nodeDef.AddOutputPort( ID_OUT_VECTOR3F_ARRAY,
    		siICENodeDataVector3,
    		siICENodeStructureSingle,
    		siICENodeContextSingleton | siICENodeContextComponent0D,
    		L"OutVector3fArray", L"OutVector3fArray",
    		ID_UNDEF, ID_UNDEF, ID_CTXT_CNS );
    	st.AssertSucceeded( ) ;

    	PluginItem nodeItem = in_reg.RegisterICENode( nodeDef );
    	nodeItem.PutCategories( L"Custom ICENode" );

    	return CStatus::OK;
    }

    XSIPLUGINCALLBACK CStatus MixedContextSample_Evaluate( ICENodeContext& in_ctxt )
    {
    	switch( (ULONG)in_ctxt.GetEvaluatedOutputPortID() )
    	{
    		case ID_OUT_FLOAT_ARRAY :
    		{
    			CDataArrayLong a_count( in_ctxt, ID_IN_SINGLETON );
    			LONG count = a_count[0];
    			CDataArray2DFloat aa_out( in_ctxt );
    			CDataArray2DFloat::Accessor a_out = aa_out.Resize( 0, count );
    			for( ULONG i = 0; i < a_out.GetCount(); ++i )
    			{
    				a_out[i] = (float)i;
    			}
    		}
    		break;

    		case ID_OUT_VECTOR3F_ARRAY :
    		{
    			CIndexSet indexSet( in_ctxt );
    			CDataArrayVector3f v3fArray( in_ctxt, ID_IN_COMPONENT0D );
    			CDataArrayFloat fArray( in_ctxt, ID_IN_SINGLETON_OR_COMPONENT0D );
    			float fFact = fArray[0];
    			MATH::CVector3f v3f( fFact, fFact*2.0, -fFact );
    			CDataArrayVector3f outVector3f( in_ctxt );
    			for(CIndexSet::Iterator it = indexSet.Begin(); it.HasNext(); it.Next())
    			{
    				fFact *= 1.1;
    				v3f.ScaleInPlace( fFact );
    				outVector3f[it] = v3f;
    			}
    		}
    		break;
    	};

    	return CStatus::OK;
    }