Object model methods are quite straightforward to use in C# with only a few things to be aware of.
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.
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 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");
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.
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.
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:
|
|