SetValue() and the accompanying GetValue() are commands. Commands essentially
work from scratch every time they are invoked.
When using SetValue() to set the name of the cluster in your example,
SetValue() needs to parse the string of the cluster name and the '.Name'
parameter, then search the entire scene graph to see if that parameter exists.
If so, set the value as specified in your arguments (test). Actions performed
by commands are logged in the script editor and often invoke events or other
validations of the application before the task(s) are allowed to be performed
or completed. While functional and flexible, you can imagine this loop of
having to re-parse the entire scene graph to set a value can be rather
inefficient. Enter the Scripting object model.
The scripting object model is similar to working with a DOM in a web browser or
other application where the graph is exposed for direct manipulation. The
methodology of working in the object model is to get a reference to an object
(node) in the graph, then use the object's available methods and properties to
do work. Because you have a reference to an existing object, you don't have to
explicitly get names of things you want to manipulate. You can work in more
generic and abstracted terms to make your code more universal and bulletproof.
Although you'll often have to write more code to do the same work in the
scripting object model compared to commands, your code will be significantly
more efficient as it doesn't have re-parse the scene graph for every operation
you want to carry out, nor will it trigger many of the validations and events.
Actions performed using the object model are also not logged, so that overhead
is eliminated as well.
Rewriting your code using the scripting object model would look something like
the example below (Jscript). I added 'a lot' of verbosity and error checking
for learning purposes, so don't let the size of the code scare you away. The
name of the game is to get a reference to an object in the scene graph
(provided by the selection in this case), then traverse that graph using the
obtained object's properties and methods until you get what you want. Notice I
didn't use any commands in the entire code snippet. If you remove the
LogMessage() statements and run this on a large polygon selection you'll find
it runs much faster than anything using SetValue().
for ( var i = 0; i < Selection.Count; i++ ) {
var oItem = Selection(i);
if ( oItem.IsClassOf( siCollectionItemID ) ) {
// selected item is a collection item (eg; a
subset of something)
var oSubComponent = oItem.SubComponent;
var oObject =
oSubComponent.Parent3DObject;
// debug
LogMessage(
" Object: " +
oObject.FullName +
"\n Object Type: " +
oObject.Type +
"\n Object Class: " +
Application.ClassName( oObject ) +
"\n SubComponent Type: " +
oSubComponent.Type +
"\nSubComponent Class: " +
Application.ClassName( oSubComponent ),
siComment
);
if ( oSubComponent.Type == "polySubComponent" )
{
// subcomponent type is polygon
var oPolygons =
oSubComponent.ComponentCollection;
var oGeometry =
oObject.ActivePrimitive.Geometry;
// debug
LogMessage( "
NbPolygons: " + oPolygons.Count, siComment );
for ( var j = 0; j <
oPolygons.Count; j++ ) {
var oPolygon =
oPolygons(j);
// debug
LogMessage(
"------------------", siComment );
LogMessage(
"Polygon Index: " + oPolygon.Index, siComment );
var oCluster =
oGeometry.AddCluster( siPolygonCluster, "Test", oPolygon.Index );
if ( oCluster )
{
// debug
LogMessage( " Cluster: " + oCluster.FullName, siComment );
// create a null to constrain to the polygon cluster, then name it.
var oNull = ActiveSceneRoot.AddNull();
oNull.Name = "N_" + oObject.Name + "_" + oPolygon.Index;
// Apply the 'object to cluster' constraint
var oConstraintOperator = oNull.Kinematics.AddConstraint( "ObjectToCluster",
oCluster );
if ( oConstraintOperator ) {
LogMessage( "Constraint Operator: " +
oConstraintOperator.FullName, siComment );
LogMessage( "Constrained " +
oConstraintOperator.Constrained.FullName + " --> " +
oConstraintOperator.Constraining.GetAsText(), siComment );
}
}
}
}
}
}
Matt
From: [email protected]
[mailto:[email protected]] On Behalf Of Sergio Mucino
Sent: Friday, October 04, 2013 2:41 PM
To: [email protected]
Subject: Re: SetValue question...
Okay. I didn't know that existed. I will look into it (although it looks pretty
straightforward, and very similar to MAXScript). Thanks Alan!
(BTW, is the object model just more accessible, or are particular reasons why
we should avoid using SetValue?)
Sergio Mucino
Lead Rigger
Modus FX
On 04/10/2013 4:22 PM, Alan Fregtman wrote:
Avoid SetValue() when possible. Use the object model instead:
c.Name = "Test"
On Fri, Oct 4, 2013 at 3:43 PM, Sergio Mucino
<[email protected]<mailto:[email protected]>> wrote:
Never mind... found it. I found that SetValue expects strings for its
arguments, so changing cName to:
cName = str(c)+".Name"
did the trick.
Cheers!
Sergio Mucino
Lead Rigger
Modus FX
On 04/10/2013 3:40 PM, Sergio Mucino wrote:
Okay. I'm trying to write my first SI script (using Python)... and I actually
got kinda lucky, because I found what I need already scripted (ah, the joys of
Googleland). I need to create a cluster per each selected polygon on an object,
and then constraint Nulls to these clusters. This script works perfectly...
http://xsisupport.com/2012/03/17/python-example-constraining-nulls-to-components/
I'm now trying to extend the script snippet to be a little more friendly to my
needs. The first thing I'd like to do is specify the name for the clusters
created. So, I modified the loop to read like this...
for i in si.Selection(0).SubElements:
c = o.ActivePrimitive.Geometry.AddCluster( clusterType, "", [i] )
cName = c.Name
si.SetValue(cName, "Test", "")
n = si.ActiveSceneRoot.AddNull()
n.Kinematics.AddConstraint( "ObjectToCluster", c )
... but SI is barfing on the SetValue line. It claims that "the parameter is
incorrect". I know the problem is in the cName reference I'm using, but I can't
figure out how I need to feed it properly. I know that cName's type is
'instance', so I'm not sure how to reference it correctly. If anyone has any
pointers into how to get this working right, I'll be quite grateful.
The noob thanks you in advance.
--
Sergio Mucino
Lead Rigger
Modus FX
--------------------------
To unsubscribe: mail
[email protected]<mailto:[email protected]>
with subject "unsubscribe" and reply to the confirmation email.
--------------------------
To unsubscribe: mail
[email protected]<mailto:[email protected]>
with subject "unsubscribe" and reply to the confirmation email.
--------------------------
To unsubscribe: mail
[email protected]<mailto:[email protected]>
with subject "unsubscribe" and reply to the confirmation email.
--------------------------
To unsubscribe: mail [email protected] with subject
"unsubscribe" and reply to the confirmation email.