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.

Reply via email to