TUT: Scripting 101


Note This is a work in progress.

In this tutorial, we'll write a little script that figures out whether an object has a position constraint. While this is a fairly straight-forward task, it will give us a chance to cover some important points about scripting in XSI.

So start XSI and switch to the Tools Development Environment layout. This layout is a great workspace for scripting. You can quickly switch between the XSI viewports, the Plug-in Manager, and the SDK Explorer, you get six script editors windows, and the scripting History log is always visible.

Table of contents

Lesson 1: Hello World

The traditional starting point for programming tutorials is the "Hello World" program. So here’s a "Hello World" script (in JScript):

LogMessage ("Hello World" );

Pretty simple, eh? To run this script, all you have to do is type this one line into the Script Editor and click Run. The message "Hello World" is logged in the History window of the Script Editor, and on the XSI status bar.

Description

If you want to know more about LogMessage, click "LogMessage" in the script editor and press F1. This opens the reference page for LogMessage.

LogMessage is actually a method of the Application object.

The Application object is a global object that is always available, that's why you can write

LogMessage( "Hello World" );

instead of

Application.LogMessage( "Hello World" );

Lesson 2 Getting Objects

Now create a sphere and a null, and then position constrain the sphere to the null:

CreatePrim("Sphere", "MeshSurface", null, null);
GetPrim("Null", null, null, null);
SelectObj("sphere", null, null);
ApplyCns("Position", "sphere", "null", null);

Switch to the SDK Explorer, and in the explorer tree, expand sphere > Kinematics > Constraints. See the Position Cns node? We need to figure how to check if that node is there.

Position Constraint in the Explorer

Now click Position Cns and look at the history log. See that SelectObj command that was logged?

SelectObj("sphere.kine.poscns", null, null);

That tells us that the position constraint is some sort of object, and it is named "sphere.kine.poscns". Also notice all the information displayed in the SDK Explorer. Don't worry about understanding all that right now, we'll come back to it later. For now, it's enough to understand that the SDK Explorer shows you all the information you can get with the SDK.

So far, all we know are the names of some objects: "sphere" is the name of a polygon mesh and "sphere.kine.poscns" is the name of a position constraint. But names are just strings. We need to get an actual object. Let's look at some common ways to get objects (note that is not an exhaustive list, there are other ways like FindObjects).

GetValue()

One of the oldest known ways to get an object is with the GetValue() command:

var o = GetValue( "sphere" );
LogMessage( ClassName(o) );

GetValue() gets the X3DObject that represents the polygon mesh named "sphere". An X3DObject is a type of XSI object that represents a 3D object such as a polygon mesh.

GetValue() is a command. Commands are logged to the scripting history. Commands are slower.

GetValue() fails if there is no object with the specified name, so you have to add error-handling to your script, or it will just stop dead when GetValue() fails.


Dictionary.GetObject()

An Object Model way to get an object is Dictionary.GetObject.

var o = Application.Dictionary.GetObject( "sphere" );
LogMessage( classname(o) );

The Object Model does not log. But like GetValue, GetObject fails if no object exists.

Children

Another way to get objects is by traversing the data hierarchy. The data hierarchy is basically just what you see in the explorer.

For example, you can get a child object that is directly under the scene root (Scene_Root):

var o = ActiveSceneRoot.Children( "sphere" );

Or you can find all objects named "sphere" that are anywhere under the scene root:

var oSpheres = ActiveSceneRoot.FindChildren( "sphere" );
LogMessage( oSpheres.Count );

Children are X3DObjects, which are the OM representations of the objects that appear in the XSI viewports. X3DObjects are what you see when you set the Scene Explorer to display Objects Only.

FindChildren finds only X3DObjects, so you cannot do this:

var oPosCnss = ActiveSceneRoot.FindChildren( "sphere.kine.poscns" );

because a poscns is not an X3DObject (what is poscns? Use the SDK explorer and find out).

XSICollection

Yet another way to get objects is to use an XSICollection:

var oColl = new ActiveXObject( "XSI.Collection" );
oColl.Items = "sphere";
LogMessage( oColl.Item(0) );

This is a very powerful, efficient technique for getting objects. Items does not fail, even if the object does not exist. We'll come back to XSICollections later.


Selection

So far, we've been getting objects by name, which is not the way to write reusable scripts.

A better approach is to process the objects selected by a user.

// Get the first selected object
var o = Selection(0);

The above is shorthand for

var oSelection = Application.Selection;
var o = oSelection.Item(0)

Lesson 3 Checking if You Got the Right Object

Class

While you're writing a script, it's common to use LogMessage to print information to the history log. For example, you may want to confirm that you have the right kind of object:

var o = Application.Selection.Item(0);
Application.LogMessage( Application.ClassName(o) );

LogMessage is helpful when you're writing little code snippets to figure out how XSI works, but you don't want to be logging messages in your final script.

For debugging purposes, you could make the messages verbose. By default, verbose messages are not logged unless the user changes a scripting preference.

var o = Selection(0);
LogMessage( ClassName(o), siVerbose );

In a real script, you want to make sure you have the right kind of object. Otherwise your script is going to fail with an error (unless you add error handling). So you could do this:

var o = Selection(0);
if ( ClassName(o) != "X3DObject" )
{
        LogMessage( "Please select a 3D object" );
}

Even better, you could get rid of the string comparison and do this:

var o = Selection(0);
if ( !o.IsClassOf( siX3DObjectID ) )
{
	LogMessage( "Please select a 3D object" );
}

IsClassOf is a method of the SIObject class, and pretty much anything you can select in the explorer is an SIObject. Try it in the SDK Explorer, and check that SIObject is a supported object model interface.

And if the selected object is not an X3DObject, you can always do this:

if ( !o.IsClassOf( siX3DObjectID ) )
{
        o = o.Parent3DObject;
}

Now, for example, even if a user selects something underneath a X3DObject (like "sphere.polymsh" or "sphere.kine.local") you can be sure that you have an X3DObject.

Lesson 4 Traversing the Data Hierarchy with the Object Model


Description
// cube
SelectObj("sphere", null, null);
var oX3DObject = Selection(0);
// cube > Polygon Mesh
var oPrimitive = oX3DObject.ActivePrimitive;
// cube > Polygon Mesh > Geometry
var oGeometryOp = oPrimitive.NestedObjects("Geometry");
// cube > Polygon Mesh > Geometry > U Subdivisions
var oSubdivu = oGeometryOp.Parameters( "subdivu" );
var oSubdivu1 = oX3DObject.Parameters( "subdivu" );
// cube > Polygon Mesh > Geometry > Cube
// "cube.polymsh.geom.cube" aka "cube.cube"
var o = oX3DObject.Primitives(0);

This page was last modified 20:38, 14 Dec 2010.
This page has been accessed 19792 times.

© Copyright 2009 Autodesk Inc. All Rights Reserved. Privacy Policy | Legal Notices and Trademarks | Report Piracy