Calling Object Model Members

 
 
 

Calling Object Model Methods

Object model methods are quite straightforward to use in C# with only a few things to be aware of.

Default Arguments

C# doesn't support default args, so all args must be supplied when calling OM methods from C#. For example:

app.LogMessage(str, siSeverity.siInfo);

In scripting, the siInfo value is the default, but in C# it must be explicitly specified.

Output Arguments

You can access output arguments from methods as long as you pass a variable that was declared with the generic C# Object class (equivalent to Variant) along with the out keyword (which flags it as an output vairable). After the method has executed, you simply cast the object to the correct Softimage class, as this example demonstrates:

// Set up the scene
CXSIApplicationClass app = new CXSIApplicationClass();
object[] args = new object[2] { "", false };
app.ExecuteCommand("NewScene", args);
Model root = app.ActiveSceneRoot;
X3DObject cube = root.AddGeometry("Cube", "MeshSurface", "MyCube");

// Start with a Phong, then reconnect a Lambert using Parameter.ConnectFromFile
Material mat = cube.AddMaterial("Phong", false, "MyPhong");
Parameter surface = mat.Parameters["Surface"];
app.LogMessage("currently connected shader: " + surface.Source.FullName, siSeverity.siInfo);

// Declare output arguments as a generic object and use the 'out' keyword
Object oldone;
DataSource lambert = surface.ConnectFromFile("$SI_HOME\\Data\\DSPresets\\Shaders\\Material\\Lambert.Preset", out oldone);
app.LogMessage("currently connected shader: " + surface.Source.FullName, siSeverity.siInfo);

// To successfully retrieve output arguments, cast the generic object back to the correct class 
DataSource oldsrc = (DataSource)oldone;
app.LogMessage("displaced shader: " + oldsrc.FullName, siSeverity.siInfo);

// Output:
// INFO : currently connected shader: MyCube.Material.MyPhong
// INFO : currently connected shader: MyCube.Material.Lambert
// INFO : displaced shader: Sources.Materials.DefaultLib.Material.MyPhong

Generic Methods

Generic methods in the object model are converted to generic methods in C#:

// GetAttribute returns a string Variant in the OM which maps to the generic Object class in C#
Object obj = in_ctxt.GetAttribute("Button");

// To access the string value, a type cast must be performed to String
String str = (String)obj;

// Everything in C# is an Object type, so if a method returns a long you still need to typecast
long n = (long)in_ctxt.GetAttribute("LongAttribute");

Geometry Interfaces

With most interfaces in the object model, you can access any method on an instance directly without having to cast. However, for geometry collection interfaces (for example, PolygonFaceCollection, NurbsSampleCollection, etc.), you need to explicitly cast the interface before calling methods:

PolygonFaceCollection polygons = (PolygonFaceCollection)subcomp.ComponentCollection;
Array aNodeIndexArray = (Array)polygons.PolygonNodePolygonFaceIndexArray;

// Type cast a gain to access FacetCollection.IndexArray
FacetCollection polyFacets = (FacetCollection)polygons;
Array aPolyIndexArray = (Array)polyFacets.IndexArray;

Calling Object Model Properties

The syntax to call properties in C# works is very similar to using JScript, besides the obvious difference in type declaration:

//JScript
var params = oObject.Kinematics.Global.Parameters;

// C#
ParameterCollection params = oObject.Kinematics.Global.Parameters;

However, there are some syntactic differences when dealing with collections and special workarounds for when you have to use the get- or set-accessors.

Tip

Each object model member displays a syntax section for C# which you can use to verify your code. In addition, the Visual C# ObjectBrowser and Visual Studio .NET's auto-complete are excellent tools to help understand some of the issues covered in this section.

Accessing Collection Items

Collection items can be accessed with the [] syntax:

Parameter posy = oObject.Kinematics.Global.Parameters["posy"];
Parameter posx = oObject.Kinematics.Global.Parameters[0];

For iterating over a collection, the easiest and most reliable approach is to use the C# foreach loop:

ParameterCollection params = oObject.Kinematics.Global.Parameters;
foreach (Parameter p in params) 
{
	app.LogMessage( p.Name + " is a " + p.ValueType.ToString() );
}

Implementation Differences for Properties

Some properties defined in the object model use different data types or classes for getting vs. setting. For example, the XSIApplication.ActiveProject property takes a String for setting and returns a Project object while getting:

// Won't compile
Project p = xsi.ActiveProject; 

// Last line causes a compiler error
Preferences pref = xsi.Preferences;
ProjectItemCollection proj_itms = pref.Categories;

In some cases, an alternative method or property exists that resolves the problem; for example, XSIApplication.ActiveProject2 is an alternative property which returns and sets a Property object:

// Alternate version of above snippet:
Project p = xsi.ActiveProject2;

If there is no alternative method or property, you can use special syntax where you prefix get_ or set_ to the name of the property and then treat it like a method:

// Special syntax as a workaround 
ProjectItemCollection proj_itms = pref.get_Categories;
pref.set_Categories( proj_itms );

When you use this special syntax you are actually using the get- and set-accessor methods which you can find by browsing the methods of the object in the Visual C# ObjectBrowser.

Tip

On each property page in the Commands and Scripting Reference, there is a special C# Syntax section which provides a basic C# syntax string for the get and set accessors. The data or class type is provided so you can see how to use the specific accessor. For example, here is the section on the Preferences.Categories page:

// get accessor
Object Preferences.get_Categories();

// set accessor
Preferences.set_Categories( [String pArrayVal] );

Compare this with the C# Syntax section on the GridData.ColumnCount page, which sets and returns an Int32 value:

// get accessor
Int32 GridData.ColumnCount();

// set accessor
GridData.ColumnCount( [Int32 out_Columns] );

Properties with Input Arguments

Some object model properties take one or more input arguments, such as Primitive.Geometry, which allows you to get the geometry at a specific frame, or FCurveKey.Constraint, which tests whether the specified constraint is active on the FCurveKey or not. Many of these properties have C#-friendly method counterparts which you can find in the reference documentation by looking for Get prefixed to the name of the property and 2 suffixed to it (for example, Primitive.GetGeometry2 and FCurveKey.GetConstraint2).

In a few cases there is no corresponding C#-friendly method counterpart to use, so you can use the get- or set-accessor instead:

// Get the geometry at the current frame
Geometry geo = obj.ActivePrimitive.get_Geometry((int)-1);

These are the object model properties that take input arguments: