As operators are applied, they are pushed onto a stack called the operator stack until they are removed (usually by freezing the stack). Because this stack keeps track of the object's history it is also known as the construction history. The object model provides access to the ConstructionHistory object through the Primitive.ConstructionHistory property. which you can use to enumerate over the construction history to access its operators. For more information, see The Operator Stack.
Once you have a pointer to an operator, you can access its input ports (the values that are driving the operator's data change) and its output ports (for example, the parameter being driven) using these methods:
Object Model: Operator.InputPorts and Operator.OutputPorts
C++ API: Operator::GetInputPorts and Operator::GetOutputPorts
From the ports you can get a pointer to the object to which the port is connected: Port.Target2 (object model) and Port::GetTarget (C++ API).
To see the input and output ports in the UI, you can use the SDK Explorer (available from the ViewScripting menu) by clicking on the operator and then clicking the Object Details link above the main content pane.
Note that the operator appears in the scene explorer according to which objects it is writing to (that is, it appears in the operator stack of the object it is creating or modifying) so it may appear in multiple places in the scene explorer at once.
In the SDK, the operator stack is called the construction history because it keeps track of each persistent change to the object; that is, each operator applied to an object until it is frozen. The operator stack is subdivided into four construction mode regions:
As soon as an operator is applied, a construction history is built containing the new operator in addition to these four markers. When you enumerate over the operators in the construction history, these four markers will report their full names (shown in the third column in the table above), so you can test each item in the construction history to make sure you have what you think you have.
To find an operator applied on a scene object, you need to browse through the contents of the object's ConstructionHistory, which is accessible through the Primitive.ConstructionHistory property (see JScript Example: Picking Operators from a Specific Construction Region for a script example of how to navigate through the construction mode regions).
Currently the Primitive.ConstructionHistory property is only available in the object model. However, by using the CComAPIHandler, a C++ API plug-in can reach the operators connected to a Primitive (see C++ Example: Accessing the Construction History via the CComAPIHandler for an example).
In this example, a cube is created and several operators applied in different construction modes. Then the operator stack is read so that only those operators under the Animation construction mode region are considered.
// 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
This example demonstrates how to create a CRefArray of the operators connected to a Primitive using the CComAPIHandler object to access the Construction History.
// 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 ; }
Except where otherwise noted, this work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License