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.
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; }