Applying Operators in Softimage

 
 
 

Applying operators is a three-part process that includes:

There are several ways to apply custom operators, depending on what kind of operator you are building (static vs. dynamic) and how much control you need over the connection process.

If you are building an operator with the wizard, it can generate the code to instantiate the operator and make the port connections (the Generate Command to Apply the Operator option is selected by default).

Automatic Static

This is the simplest case, a static operator with a fixed number of port connections and includes cases where the objects to be connected are not yet created. You can use the AddCustomOp method or command, which takes care of instantiating the operator, specifying the ports to hook up, and making the connections.

Manual Static

If you want to break the application process into its component parts you can also use specific object model and C++ API functions to perform each part. This is the way that the wizard generates the code.

Instantiating the Operator

You can use the CreateObject function to instantiate the operator by specifying the PluginItem name used to register the operator with PluginRegistrar.RegisterOperator or PluginRegistrar::RegisterOperator. The CreateObject function returns a pointer to the instantiated operator which you need in order to define the port connections and connect the objects to ports.

// JScript
var op = XSIFactory.CreateObject( "MyCustomOperator" );

// C++
Factory factory = Application().GetFactory();
CustomOperator op( factory.CreateObject(L"MyCustomOperator") );

Related Links

Defining Port Connections

For static operators you can define the port connections with a set of methods and functions that require the objects to be connected to exist. You can define an input port (AddInputPort), an output port (AddOutputPort), or both at the same time (AddIOPort, for example, for deformer operators).

// JScript
op.AddInputPort( "sphere.polymsh.cls.Point" );

// C++ API
CRef obj;
obj.Set( "sphere.polymsh.cls.Point" );
op.AddIOPort( obj );

Connecting Objects to Ports

You can use the Connect method to finish the port connections. In the case of static operators, it is usually not necessary to pass in any arguments for the connection specification (such as an object or a connection set) because the explicit object needed was specified when the port connections were defined.

Related Links

Dynamic

Applying dynamic operator is very similar to applying static operators manually, but you also have to add port groups before declaring port connections. In addition, you need to add ports by specifying the class ID instead of explicit objects since your connection objects may not exist yet. Finally, the ConnectToGroup method allows you to add instances of port objects to groups, thereby allowing you to connect in a truly dynamic way.

Adding Port Groups

The AddPortGroup method allows you to specify how many objects can be connected to within this port group. By default, there is only one port connection allowed, but you can specify a valid range, as in the case of an operator that averages between at least two and no more than ten inputs:

myOp.AddPortGroup( "Inputs", 2, 10, "MyPolygonFilter" );

This method also allows you to specify a filter to validate any input object to connect to the group.

Related Links

Declaring Potential Port Connections

The methods used to define static port connections manually need an explicit path to an object that already exists, whereas dynamic connections need to declared in a more hypothetical manner. For this reason, the CustomOperator or CustomOperator also provides methods that allow you to add ports by class ID:

myOp.AddInputPortByClassID( siPrimitiveID, "inputprim", 1 /* index of input port group */ );

Dynamically Connecting To Groups

The ConnectToGroup method allows you to add objects to a port group at any time after it is defined. However, this method can only be used on a port group containing a single port, and the object passed in the Object argument must be a specific node (that is, a KinematicState or KinematicState or Primitive or Primitive rather than an X3DObject or X3DObject):

newOp.ConnectToGroup( 0, mySphere.Kinematics.Local );

Related Links

Examples of Applying Custom Operators

These examples demonstrate a number of approaches for applying custom operators:

JScript Example: Applying a Static Operator (Manual)

This example is extracted from the code generated by the SDK Operator Wizard. Note that because the ports are specified explicitly, no parameters need to be passed to the Operator.Connect or Operator::Connect method (see C++ Example: Applying a Static Operator (Automatic) for an automatic version of this example).

// Instantiate the operator
var newOp = XSIFactory.CreateObject("MyOp");

// Specify the ports to hook up
newOp.AddOutputPort("sphere.polymsh");
newOp.AddInputPort("sphere.polymsh");

// Connect the operator
newOp.Connect();

C++ Example: Applying a Static Operator (Automatic)

This snippet is similar to the wizard-generated code in JScript Example: Applying a Static Operator (Manual) but uses the AddCustomOp function which combines the three steps (instantiate, declare ports, connect) into one. The JScript version and this one are examples of static operators, so the port connections must already exist.

// Output of the operator will be this mesh
CRef obj;
obj.Set(L"sphere.polymsh");
Primitive prim(obj);

// AddCustomOp takes an array of inputs
CRefArray inputs(3);

// Get the objects to which the operator will be connected
inputs[0].Set(L"grid.polymsh");
inputs[1].Set(L"null.kine.global");
inputs[2].Set(L"null2.kine.global");

// Apply the custom operator
prim.AddCustomOp("MyOp", inputs);

Check out how the equivalent code in JScript using the AddCustomOp command takes only one line:

AddCustomOp("MyOp", "sphere.polymsh", 
"grid.polymsh,null.kine.global,null2.kine.global");

JScript Example: Applying an Operator Before Port Targets Exist

In this example the operator ports are declared before any matching objects actually exist in the scene, thanks to the AddIOPortByClassID method, which simply declares what kind of object to expect to connect to the port, rather than the exact object.

// Instantiate the operator
var newOp = XSIFactory.CreateObject( "MyOp" );

// Specify the ports to hook up, this time using AddXXXPortByClassID which
// allows you to add the port without specifying an existing object to connect
newOp.AddIOPortByClassID( siKinematicStateID );

// ...

// The operator connections are set up before the target object exists
var sph = Application.ActiveSceneRoot.AddGeometry( "Sphere", "MeshSurface" );
newOp.ConnectToGroup( 0, sph.Kinematics.Local );

C++ Example: Applying a Dynamic Operator

This example demonstrates how to apply an operator with a variable number of objects connected by adding a port group that can accept between 2 and 10 connections and defining the ports using only a class ID.

// Instantiate the operator
CustomOperator newOp = Application().GetFactory().CreateObject( L"MyOp" );

// Define an input port group that can accept at least 2 and up to 10 connections
newOp.AddPortGroup( L"Output" );
newOp.AddPortGroup( L"Inputs", 2, 10 );

// Specify the ports to hook up, using AddXXXPortByClassID which allows you to
// add the port without specifying an existing object to connect
newOp.AddOutputPortByClassID( siClusterPropertyID, L"", 0 /* output port group */ );
newOp.AddInputPortByClassID( siClusterPropertyID, L"", 1 /* input port group */ );

// ...
// When it's time to connect a new port instance to the operator
CRef wp; CRef out_instance;
wp.Set( L"sphere.polymsh.cls.Point.Weight_Map" );
newOp.ConnectToGroup( 1, wp, out_instance );

// etc.