XSIFactory.CreateScriptedOp

Introduced

v4.0

Description

Creates a blank "runtime" scripted operator with the code specified. This makes it possible to create an operator on-the-fly rather than using the the script operator editor. These operators will have their code embedded in the scene file and have a different Callback convention than Self-Installed CustomOperators.

Scripted operators define the following callbacks. If the operator has a user-specified name then the name must prefix the Init, Term and Update callbacks:

CustomOperator_Init( ctx )

CustomOperator_Term( ctx )

CustomOperator_Update( ctx, out, in1, inN )

The Update function has 1 argument per input port. If the operator defines 2 groups with 2 input ports each there must be 4 input arguments to the update method. The names of the input ports must be unique as this will be used as the argument's name. The name 'in' is not considered a valid port name because it is also a reserved word in some scripting langauges such as VBScript.

As of version 3.51, Init and Term are considered reserved function names. Softimage will check the helper code of scripted operators created using the scripted operator editor or the SPDL file for Init(ctx) and Term(ctx) callbacks. If the function names are found but specify the wrong number of arguments, Softimage will issue a warning message. It is possible that a scripted operator created prior to version 3.51 defined Init or Term helper functions with a signature that matches the callbacks, which may cause a runtime error when the callback is executed. The only remedy is to modify the code of the operator and rename these helper functions to something else.

Scripting Syntax

oReturn = XSIFactory.CreateScriptedOp( Name, [ScriptCode], [Language] );

Return Value

CustomOperator

Parameters

Parameter Type Description
Name String The name for the new scripted operator.

Default Value: ""

ScriptCode String The logic that implements the scripted operator

Default Value: ""

Language String The scripting language to use for the logic; for example "JScript"

Default Value: The current scripting language user preference

Examples

1. JScript Example

/*
        This example illustrates how to use the XSIFactory to create a multi-output operator 
        which constrains the posx position of a number of objects to a single object. 
*/
NewScene( null, false );
var null1 = GetPrim( "Null" );
var null2 = GetPrim( "Null" );
var polymsh1 = CreatePrim( "sphere", "MeshSurface" );
var op = XSIFactory.CreateScriptedOp( "myCns", myCns_Update.toString(), "JScript" );
// Allow a maximum of 2 nulls to be connected to the main group
var group1 = op.AddPortGroup( "mainoutputgroup", 1, 2, siNullFilter );
// You only need to add 1 port to control 2 objects since the portgroup definition takes 
// care of that. The only thing you need to do here is to define what type of object/parameter 
// you would like to be connected to.
op.AddOutputPort( null1.posx, "", group1.Index );
// Define the second input group that will accept only 1 polygon mesh as input
var group2 = op.AddPortGroup( "inputgroup", 1, 1, siPolyMeshFilter );
op.AddInputPort( polymsh1.posx, "", group2.Index );
// Create a connection string. Use the semi-colon to delimit where the first group ends and 
// the second port group begins.
var cnxstr = null1 + "," + null2 + ";" + polymsh1;
// connect operator
op.Connect( cnxstr );
function myCns_Update( ctx, out, inposx )
{
        out.Value = inposx.Value;
}

2. JScript Example

// The following code illustrates how to create a scripted operator
// entirely from the COM API
NewScene( null, false );
var oObject = ActiveSceneRoot.AddGeometry("Sphere","MeshSurface");
apply_splatter( oObject );
var oSplatterOperator = oObject.ActivePrimitive.ConstructionHistory.Find( "MySplatter" );
var oPort = oSplatterOperator.Port( "InGeom", "MainGroup", 0 );
var oInputGeometry = oPort.Target2;
Application.LogMessage( "splatter is reading from the " + oInputGeometry.Parent.Name );
function apply_splatter( oObject )
{
        var op = XSIFactory.CreateScriptedOp( "MySplatter", MySplatter_Update.toString(), "JScript" );
        // Define connections
        var group = op.AddPortGroup( "MainGroup" );
        var ioport = op.AddIOPort( oObject.ActivePrimitive, "Geom", group.Index );
        var inport = op.AddInputPort( oObject.kinematics.global.posy, "InGPosY", group.Index );
        // Define parameters
        var pdef = XSIFactory.CreateParamDef2( "SquishFactor", siDouble, 0.5, 0, 1 );
        op.AddParameter( pdef );
        // Connect operator
        op.Connect(oObject);
}
function MySplatter_Update( ctx, out, InGeom, InGPosY )
{
        // Declare variables.
        var dSquishPnt,  i;
        // Get the squish factor.
        var dSquish = ctx.Parameters("SquishFactor").Value
        // Get the array of point positions.
        var aPnts = InGeom.Value.Geometry.Points.PositionArray.toArray();
        // Get the object//s global Y position.
        var dGPosYObj = InGPosY.Value;
        // For each point...
        for ( var i = 0; i < aPnts.length / 3; i++ )
        {
                // Compute the point's global Y position.
                var dGPosYPnt = aPnts[1 + (i*3)] + dGPosYObj;
                // If the point is below the Y=0 plane...
                if ( dGPosYPnt < 0 ) 
                {
                        // Compute the squish factor for the point.
                        var dSquishPnt = 1.0 - dGPosYPnt * dSquish;
                        // Squish the point.
                        aPnts[0 + (i*3)] = aPnts[0 + (i*3)] * dSquishPnt;
                        aPnts[1 + (i*3)] = - dGPosYObj;
                        aPnts[2 + (i*3)] = aPnts[2 + (i*3)] * dSquishPnt;
                }
        }
        // Update the object//s point positions.
        out.Value.Geometry.Points.PositionArray = aPnts;
        return;
}
//

See Also

ConvertScriptedOp UpdateContext ProjectItem.AddScriptedOp ProjectItem.AddScriptedOpFromFile XSIFactory.CreateScriptedOpFromFile XSIFactory.CreateParamDef