Scripting Tips and Tricks (XSISDK)


Location for general tips and tricks. If any particular topic becomes very extensive it can be moved into its own page.


Table of contents

Scripting Primer

All new XSI SDK users should start with this document XSI Scripting Primer

Script Debugging

See Script Debugging (XSISDK)

Dictionary


VBScript and JScript coders may find the scripting Dictionary (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/script56/html/jsobjdictionary.asp) object interesting. This is a built-in object (not part of XSI) and builds a table mapping between "keys" and "values". The keys are often strings.

To create a dictionary use this syntax (JScript):

var oDictionary = new ActiveXObject("Scripting.Dictionary");

For a demonstration of its use check out the implementation of the SetGlobal (http://softimage.wiki.avid.com/sdkdocs/SetGlobal.htm) and GetGlobal (http://softimage.wiki.avid.com/sdkdocs/GetGlobal.htm) commands (XSI 5.0). Hint: Look at C:\Softimage\XSI_5.0\Application\Commands\GlobalVarPlugin.js.

Python has a structure like this available as a native type but could potentially use this object as well.

Mixing Scripting Languages

Normally it might be best to work primarily in a single scripting language, for example JScript. However in some cases certain actions are only available (or easier to achieve) in other languages, including the C++ API.

The solution is to write certain functionality as custom commands in the other language. It is straightfoward to call a custom command and arguments and the return value can be used to pass values between the different environments.

An example is the InputBox function which is part of VBScript and an easy way to get simple input from a user. It has been exposed as a command for XSI v5.0 called XSIInputBox (see SDKVBHelpers.vbs), so now it is available from any scripting language and even C++.

By this same approach it is easier to re-use script code written by external sources - even if you are not extensively familiar with the particular scripting language it is written in you may find it easier to invoke it "as is" rather than to try to rewrite it in a language you are more comfortable with.

For simple scripts that do not need to pass and return values you may prefer to use Application.ExecuteScript. This lets you execute any script in any supported language. However this requires that you can determine the exact full path to the scripts location.

How to Find

If you cannot find something directly through the Object Model (OM), there are generally two alternatives:

  • Use a string expression (http://softimage.wiki.avid.com/sdkdocs/StringExpression.htm) to populate an XSICollection (http://softimage.wiki.avid.com/sdkdocs/XSICollection.htm).
  • Use the Object Model and NestedObjects (http://softimage.wiki.avid.com/sdkdocs/NestedObjects.htm) property.

Some things, such as the PlayControl parameters, are accessible through the OM but it is not obvious how to do it.

Partitions

Using an XSICollection:

// Get a collection of partitions from a pass
var partColl = new ActiveXObject('XSI.Collection');
partColl.SetAsText( passname + '.Partitions.*' );

Using NestedObjects property:

// The NestedObjects for a Pass includes a Parameter object named "Partitions".
// The NestedObjects for this Parameter object are the partitions (Group objects).

var oPartitions = oPass.NestedObjects.Item("Partitions").NestedObjects;

Render Options

Using an XSICollection:

var oPass = ActiveProject.ActiveScene.ActivePass;

// Get the RenderOptions Property object
var oColl = XSIFactory.CreateObject( "XSI.Collection" );

oColl.SetAsText( oPass.fullname + ".RenderOptions" );
var oRenderOptions = oColl(0);	// oRenderOptions is a Property (http://softimage.wiki.avid.com/sdkdocs/Property.htm)

Using the NestedObjects property:

var oPass = ActiveProject.ActiveScene.ActivePass;

// Get the RenderOptions Property (http://softimage.wiki.avid.com/sdkdocs/Property.htm)
var oRenderOptions = oPass.NestedObjects.Item("Render Options");

PlayControl

The PlayControl property is located under the ActiveProject (http://softimage.wiki.avid.com/sdkdocs/ActiveProject.htm).

// Get the PlayControl property
// "Play Control" is the property Name
var oPlayControl = ActiveProject.Properties.Item("Play Control");

// Set a PlayControl parameter
// "Current" is the ScriptName
oPlayControl.Parameters.Item("Current").Value = 32;

See Playback Controls for a detailed discussion.

FxTrees

FxTrees are a type of property, so you can get FxTree (http://softimage.wiki.avid.com/sdkdocs/FxTree.htm) objects from the Properties (http://softimage.wiki.avid.com/sdkdocs/SceneItem_Properties.htm) collection of the scene root

// Get the FxTrees under the scene root
var oFxTrees = ActiveSceneRoot.Properties.Filter("FxTree");

FxTrees can also be found under models:

// Get the FxTrees located under models
// Note that ActiveSceneRoot.Models does not include the scene root.

var oEnum = new Enumerator( ActiveSceneRoot.Models ) ;
for (;!oEnum.atEnd();oEnum.moveNext() )
{
	var oModel = oEnum.item() ;
	var oFxTrees = oModel.Properties.Filter("FxTree");
	
	// Enumerate the FxTrees under the current model
	var oFxTreesEnum = new Enumerator( oFxTrees ) ;
	for (;!oFxTreesEnum.atEnd();oFxTreesEnum.moveNext() )
	{
		oFxTree = oFxTreesEnum.item();
	}
}

You can use to an XSICollection (http://softimage.wiki.avid.com/sdkdocs/XSICollection.htm) to hold all the FxTree objects found under the scene root or any other model.

var oFxTrees = new ActiveXObject('XSI.Collection');

// Add the FxTree nodes found under the scene root
// AddItems does not raise an error if you pass an empty string
oFxTrees.AddItems( ActiveSceneRoot.Properties.Filter("FxTree") );

// Get the FxTrees located under models
oEnum = new Enumerator( ActiveSceneRoot.Models ) ;
for (;!oEnum.atEnd();oEnum.moveNext() )
{
	var oModel = oEnum.item() ;
	oFxTrees.AddItems( oModel.Properties.Filter("FxTree") );
}

FxTree nodes may also be located under 3D objects (for example, under Model.null). The above techniques would not find these FxTrees. To make sure you got all FxTrees no matter where they are in the scene, you'd have to do something like this:

var oFxTrees = new ActiveXObject('XSI.Collection');

// "FxTree" gets all the FxTree nodes under the scene root
// "*.FxTree" gets the first FxTree under the scene root and 
// all the other FxTree nodes under models and 3D objects
oFxTrees.Items = "FxTree, *.FxTree";

// Make sure the first FxTree node under the scene root
// is not listed twice
oFxTrees.Unique = true;

You could also use SetAsText, but note that it raises an error if the string does not evaluate to one or more valid objects:

try {
	oFxTrees.SetAsText( "FxTree, *.FxTree" );
	oFxTrees.Unique = true;
} catch (e) {
	// do nothing, or log a message
	LogMessage( "No FxTrees found", siWarning );
}


Just About Anything

Use FindObjects (http://softimage.wiki.avid.com/sdkdocs/FindObjects.htm).

For example, see Custom_Properties_(XSISDK)#Find_Custom_Properties.


Name Collisions

One of the most perplexity bugs to figure out in scripting happens when you have a conflict in your variable naming.

For example

// JScript
var in = 4 ;

Gives this perplexing error message:

//ERROR : Expected identifier - [line 1]

It turns out that "in" is not a valid variable name, so you just need to rename it.

Similarily if you have variables that have the same name as XSI commands (or methods of the Application) object you will get similar strange error messages.

As an example someone at Softimage recently added a command called "Frame", but this was found to cause scripts containing the variable name "frame" to start mysteriously failing. The command was renamed to something that is much less likely to cause conflict.

Each language has its own particular list of reserved words and built-in objects or constants.

So if you become really stumped by a mysterious script error try making sure your variables, functions and other elements have clear names that are not likely to conflict with anything in the system. Sometimes naming conventions, like standard prefixes in your code can help avoid this problem entirely.

This page was last modified 12:34, 30 Aug 2007.
This page has been accessed 11298 times.