オペレータは適用すると、削除するまで「オペレータ スタック」と呼ばれるスタック上に置かれます(オペレータは一般にスタックのフリーズ操作で削除されます)。 このスタックはオブジェクトの履歴も追跡するので、「コンストラクション ヒストリ」とも呼ばれます。 オブジェクト モデルは Primitive.ConstructionHistory プロパティを介して ConstructionHistory オブジェクトにアクセスします。これはオペレータにアクセスするためにコンストラクション ヒストリを列挙するときに使用できます。 詳細については、「オペレータ スタック」を参照してください。
オペレータへのポインタを取得したら、以下のメソッドを使用してオペレータの入力ポート(オペレータのデータ変更を制御する値)と出力ポート(制御されているパラメータなど)にアクセスできます。
オブジェクト モデルの場合: Operator.InputPorts および Operator.OutputPorts
C++ API の場合: Operator::GetInputPorts および Operator::GetOutputPorts
ポートを元に、ポートが接続されているオブジェクトへのポインタを取得できます。これには Port.Target2(オブジェクト モデル)と Port::GetTarget(C++ API)を使用します。
SDK の場合、オペレータ スタックはコンストラクション ヒストリと呼ばれます。絶えず繰り返されるオブジェクへの変更をそれぞれ把握しているからです。つまり、オブジェクトをフリーズするまで、オブジェクトに適用した各オペレータを把握しているということです。 オペレータ スタックは以下の 4 つのコンストラクション モード領域に分類されます。
オペレータが適用されるとすぐにコンストラクション ヒストリが構築されます。このコンストラクション ヒストリには、上記の 4 つのマーカー以外に新しいオペレータも含まれます。 コンストラクション ヒストリ内のオペレータを列挙すると、これらの 4 つのマーカーはフルネームで報告されます(上の表の第 3 列目に記載している名前です)。したがって、希望のオペレータが実際に適用されているかどうかを確認するため、コンストラクション ヒストリの各アイテムをテストすることが可能です。
シーン オブジェクトに適用したオペレータを調べるには、オブジェクトの ConstructionHistory の内容を参照する必要があります。ConstructionHistory は Primitive.ConstructionHistory プロパティを通じてアクセスできます(コンストラクションモード領域の操作方法のスクリプト例については「JScript の例: 特定のコンストラクション領域からのオペレータ選択」を参照)。
現在、Primitive.ConstructionHistoryプロパティはオブジェクトモデルでのみ使用できます。ただし、CComAPIHandler を使用することにより、C++ API プラグインはプリミティブに接続されているオペレータにアクセスできます(例については、「C++ の例: CComAPIHandler を使ったコンストラクション ヒストリへのアクセス」を参照)。
JScript の例: 特定のコンストラクション領域からのオペレータ選択
この例では、立方体を作成し、いくつかのオペレータを異なるコンストラクション モードで適用しています。 その後に、オペレータ スタックが読み取られています。そのため、アニメーション コンストラクション モード領域に分類されるオペレータのみが対象となっています。
// Set up a scene with a cube and apply a variety of deform operators
// in a variety of construction modes
NewScene( null, false );
var obj = CreatePrim( "Cube", "MeshSurface" );
ApplyOp( "Bulge", "cube", 3, siPersistentOperation, null, 0 );
ApplyOp( "Bend", "cube", 3, siPersistentOperation, null, 0 );
SetValue( "Context.ConstructionMode", 2 );
ApplyOp( "Fold", "cube", 3, siPersistentOperation, null, 2 );
ApplyOp( "Shear", "cube", 3, siPersistentOperation, null, 2 );
SetValue( "Context.ConstructionMode", 3 );
ApplyOp( "Smooth", "cube", 3, siPersistentOperation, null, 3 );
// Get the cube's operator stack/construction history and browse it...
var opstack = new Enumerator( obj.ActivePrimitive.ConstructionHistory );
var getanimops = false;
for ( ; !opstack.atEnd(); opstack.moveNext() ) {
var op = opstack.item();
Application.LogMessage( "Current node: " + op.FullName );
// Use RegularExpression matching to identify the markers in the stack
var beginregion = false;
if ( op.FullName.match(/marker/i) != null ) {
beginregion = true;
} else {
beginregion = false;
}
// Grab only animation operators
if ( !beginregion && getanimops ) {
Application.LogMessage( "\tFound this animation operator: " + op.Name );
}
// Figures out when we're in the Animation region
if ( beginregion ) {
if ( op.FullName.match(/animationmarker/i) != null ) {
getanimops = true;
} else {
getanimops = false;
}
}
}
//INFO : Current node: cube.polymsh.secondaryshapemarker
//INFO : Current node: cube.polymsh.smoothop
//INFO : Current node: cube.polymsh.animationmarker
//INFO : Current node: cube.polymsh.shearop
//INFO : Found this animation operator: Shear Op
//INFO : Current node: cube.polymsh.foldop
//INFO : Found this animation operator: Fold Op
//INFO : Current node: cube.polymsh.shapemarker
//INFO : Current node: cube.polymsh.modelingmarker
//INFO : Current node: cube.polymsh.bendop
//INFO : Current node: cube.polymsh.bulgeop
//INFO : Current node: cube.polymsh.geom
C++ の例: CComAPIHandler を使ったコンストラクション ヒストリへのアクセス
この例では、コンストラクション ヒストリにアクセスするために CComAPIHandler オブジェクトを使用して、Primitive に接続されたオペレータの CRefArray を作成する方法を示します。
// Given an X3DObject (e.g. a mesh or nurbs), fills in an array with all the operators connected to its
// primitive. This function is suitable for re-use in any plug-in that wants to access construction history
void GetOperators( X3DObject in_ops, CRefArray & out_ops )
{
Primitive primitive = in_ops.GetActivePrimitive() ;
CComAPIHandler comPrimitive( primitive.GetRef() ) ;
CComAPIHandler constructionHistory = comPrimitive.GetProperty( L"ConstructionHistory" ) ;
// Currently there isn't a "Count" or "Item" property on the ConstructionHistory
// scripting object, so we use Filter to find all operators
CValue valOperatorCollection ;
CValueArray args(3) ;
args[1] = CValue( L"Operators" ) ; // We want all operators (siOperatorFamily)
constructionHistory.Call( L"Filter", valOperatorCollection, args ) ;
// Now convert from a OperatorCollection object to a C++ CRefArray
CComAPIHandler comOpColl = valOperatorCollection ;
CValue cnt = comOpColl.GetProperty( L"Count" ) ;
CRefArray ops( (LONG)cnt ) ;
for ( LONG i=0 ; i<(LONG)cnt; i++ )
{
CValue outOp;
CValueArray itemsArgs;
itemsArgs.Add( i );
comOpColl.Invoke(L"Item", CComAPIHandler::PropertyGet, outOp, itemsArgs);
ops[i] = outOp ;
}
out_ops = ops ;
}