ポリモーフィズムは、複数のデータ タイプを外部公開するポートの機能です。 カスタム ICENode の評価時にポートのポリモーフィズムを処理するには、さらに高度な実装テクニックが必要です。タイプ解決は接続時に実行されるので、複数のデータタイプをサポートするために、ICENode のコーディングは汎用的に行われる必要があります。推奨するのは、現在の出力ポート タイプを ICENodeContext オブジェクトに問い合わせ、テンプレート クラスを使用して評価を委任する方法です。
次のコードの断片は SDK サンプルの一部であり、1D および 2D の両方の配列に対してこのテクニックを使用しています。
// CEvaluator class is handling the most common types. The data is copied by reference,
// this is the most optimal way of setting output ports with input ports.
template < class T >
class CEvaluator
{
public:
static void Do( ICENodeContext& in_ctxt, ULONG in_nInPortID, XSI::siICENodeStructureType in_outStruct )
{
if ( in_outStruct == XSI::siICENodeStructureSingle )
{
CDataArray<T> outData( in_ctxt );
outData.CopyFrom( in_nInPortID );
}
else if ( in_outStruct == XSI::siICENodeStructureArray )
{
CDataArray2D<T> outData( in_ctxt );
outData.CopyFrom( in_nInPortID );
}
}
};
// Special case for the custom data type
template <>
class CEvaluator< CDataArrayCustomType::TData >
{
public:
static void Do( ICENodeContext& in_ctxt, ULONG in_nInPortID, XSI::siICENodeStructureType in_outStruct )
{
if ( in_outStruct == XSI::siICENodeStructureSingle )
{
CDataArrayCustomType outData( in_ctxt );
outData.CopyFrom( in_nInPortID );
}
else if ( in_outStruct == XSI::siICENodeStructureArray )
{
CDataArray2DCustomType outData( in_ctxt );
outData.CopyFrom( in_nInPortID );
}
}
};
SICALLBACK CustomPassThrough_Evaluate( ICENodeContext& in_ctxt )
{
ULONG out_portID = in_ctxt.GetEvaluatedOutputPortID( );
switch( out_portID )
{
case ID_OUT :
{
XSI::siICENodeDataType outPortType;
XSI::siICENodeStructureType outPortStruct;
XSI::siICENodeContextType outPortContext;
in_ctxt.GetPortInfo( ID_OUT, outPortType, outPortStruct, outPortContext );
switch( outPortType )
{
case siICENodeDataFloat: CEvaluator<float>::Do( in_ctxt, ID_IN, outPortStruct ); break;
case siICENodeDataLong: CEvaluator<LONG>::Do( in_ctxt, ID_IN, outPortStruct ); break;
case siICENodeDataBool: CEvaluator<bool>::Do( in_ctxt, ID_IN, outPortStruct ); break;
case siICENodeDataVector2: CEvaluator<MATH::CVector2f>::Do( in_ctxt, ID_IN, outPortStruct ); break;
case siICENodeDataVector3: CEvaluator<MATH::CVector3f>::Do( in_ctxt, ID_IN, outPortStruct ); break;
case siICENodeDataVector4: CEvaluator<MATH::CVector4f>::Do( in_ctxt, ID_IN, outPortStruct ); break;
case siICENodeDataQuaternion: CEvaluator<MATH::CQuaternionf>::Do( in_ctxt, ID_IN, outPortStruct ); break;
case siICENodeDataRotation: CEvaluator<MATH::CRotationf>::Do( in_ctxt, ID_IN, outPortStruct ); break;
case siICENodeDataMatrix33: CEvaluator<MATH::CMatrix3f>::Do( in_ctxt, ID_IN, outPortStruct ); break;
case siICENodeDataMatrix44: CEvaluator<MATH::CMatrix4f>::Do( in_ctxt, ID_IN, outPortStruct ); break;
case siICENodeDataColor4: CEvaluator<MATH::CColor4f>::Do( in_ctxt, ID_IN, outPortStruct ); break;
case siICENodeDataShape: CEvaluator<MATH::CShape>::Do( in_ctxt, ID_IN, outPortStruct ); break;
case siICENodeDataCustomType: CEvaluator<CDataArrayCustomType::TData>::Do( in_ctxt, ID_IN, outPortStruct ); break;
};
}
break;
};
return CStatus::OK;
}
The next example shows another approach to handle port polymorphism when output arrays need to be set by index (memory allocation is required):
// Another version of the CEvaluator class that copies data by allocating memory.
template < class T >
class CCopyEvaluator
{
public:
static void Do( ICENodeContext& in_ctxt, ULONG in_nInPortID, XSI::siICENodeStructureType in_outStruct )
{
CIndexSet indexSet( in_ctxt );
if ( in_outStruct == XSI::siICENodeStructureSingle )
{
CDataArray<T> outData( in_ctxt );
CDataArray<T> inData( in_ctxt, in_nInPortID );
for(CIndexSet::Iterator it = indexSet.Begin(); it.HasNext(); it.Next())
{
outData[it] = inData[it];
}
}
else if ( in_outStruct == XSI::siICENodeStructureArray )
{
CDataArray2D<T> outData( in_ctxt );
CDataArray2D<T> inData( in_ctxt, in_nInPortID );
for(CIndexSet::Iterator it = indexSet.Begin(); it.HasNext(); it.Next())
{
typename CDataArray2D<T>::Accessor inAccess = inData[it];
typename CDataArray2D<T>::Accessor outAccess = outData.Resize( it, inAccess.GetCount() );
memcpy( &outAccess[0], &inAccess[0], outAccess.GetCount() );
}
}
}
};
// Special case for the bool type
template <>
class CCopyEvaluator< bool >
{
public:
static void Do( ICENodeContext& in_ctxt, ULONG in_nInPortID, XSI::siICENodeStructureType in_outStruct )
{
CIndexSet indexSet( in_ctxt );
if ( in_outStruct == XSI::siICENodeStructureSingle )
{
CDataArray<bool> outData( in_ctxt );
CDataArray<bool> inData( in_ctxt, in_nInPortID );
for(CIndexSet::Iterator it = indexSet.Begin(); it.HasNext(); it.Next())
{
outData.Set( it, inData[it] );
}
}
else if ( in_outStruct == XSI::siICENodeStructureArray )
{
CDataArray2D<bool> outData( in_ctxt );
CDataArray2D<bool> inData( in_ctxt, in_nInPortID );
for(CIndexSet::Iterator it = indexSet.Begin(); it.HasNext(); it.Next())
{
CDataArray2D<bool>::Accessor inAccess = inData[it];
CDataArray2D<bool>::Accessor outAccess = outData.Resize( it, inAccess.GetCount() );
for ( ULONG i=0; i<outAccess.GetCount(); i++ )
{
outAccess.Set( i, inAccess[i] );
}
}
}
}
};
// Special case for the custom data type
template <>
class CCopyEvaluator< CDataArrayCustomType::TData >
{
public:
static void Do( ICENodeContext& in_ctxt, ULONG in_nInPortID, XSI::siICENodeStructureType in_outStruct )
{
if ( in_outStruct == XSI::siICENodeStructureSingle )
{
CDataArrayCustomType outData( in_ctxt );
CDataArrayCustomType inData( in_ctxt, in_nInPortID );
CIndexSet indexSet( in_ctxt );
for(CIndexSet::Iterator it = indexSet.Begin(); it.HasNext(); it.Next())
{
ULONG nSize;
const XSI::CDataArrayCustomType::TData* pInData;
inData.GetData(it, &pInData, nSize);
XSI::CDataArrayCustomType::TData* pOutData = outData.Resize(it, nSize);
::memcpy( pOutData, pInData, nSize );
}
}
else if ( in_outStruct == XSI::siICENodeStructureArray )
{
CDataArray2DCustomType outData( in_ctxt );
CDataArray2DCustomType inData( in_ctxt, in_nInPortID );
CIndexSet indexSet( in_ctxt );
for (CIndexSet::Iterator it = indexSet.Begin(); it.HasNext(); it.Next())
{
CDataArray2DCustomType::Accessor inAccess = inData[ it ];
CDataArray2DCustomType::Accessor outAccess = outData.Resize( it, inAccess.GetCount( ) );
for ( ULONG i=0; i<outAccess.GetCount(); i++ )
{
CDataArray2DCustomType::TData* pInData = NULL;
ULONG nSize;
inAccess.GetData( i, &pInData, nSize );
CDataArray2DCustomType::TData* pOutData = outAccess.Resize( i, nSize );
::memcpy( pOutData, pInData, nSize );
}
}
}
}
};