How to check if an object exists with no error handling


Yes, this old chestnut…I thought I had posted this ages ago, but I don’t see in the archives, so:

If you want to check if an object exists, and you don’t want to deal with any error handling, then do it this way:

from sipyutils import disp		# win32com.client.Dispatch

def objExists( name ):
    c = disp( "XSI.Collection" )
    c.Items = name
    return not( c.Count == 0 )

print 'Object does exist' if objExists( "XSI_Man.geom" ) else 'Does not exist'

Finding materials used by a model


Here’s one way to get the materials used by model. Note that this will also get any materials applied to clusters.

si=Application

def get_mdl_materials( m ):
	from win32com.client import constants as c
	return m.FindObjects( c.siMaterialID )

Application.GetPresetModel("Man_Character", "Man_Character", "", "Character.Character_Designer")
for m in get_mdl_materials( si.Dictionary.GetObject( 'Man_Character' ) ):
	print m

And here’s an old-school way that uses a couple of string expressions:

si=Application
mdl = si.Dictionary.GetObject( 'Man_Character' )

import win32com.client
mats = win32com.client.Dispatch( "XSI.Collection" )
mats.Items = '{0}.{1},{0}.{2}'.format(mdl.Name, "*.cls.*.material", "*.material")

for m in mats:
	print (m)

Saturday snippet: Converting strings to objects


XSICollections know how to handle (aka parse) string expressions like ‘cube.pnt[2,4,LAST]’

si = Application
import win32com.client
c = win32com.client.Dispatch( "XSI.Collection" )

#c.SetAsText( 'cube.pnt[2,4,LAST]' )
c.Items = 'cube.pnt[2,4,LAST]'

print c.Count
print si.ClassName( c(0) )
print c(0).SubComponent.ComponentCollection.Count
print si.ClassName( c(0).SubComponent.ComponentCollection(0) )
print c(0).SubComponent.ComponentCollection(2).Index
# 1
# CollectionItem
# 3
# Vertex
# 7

Back in 1999, this code looked something like this:

CreatePrim "Cube", "MeshSurface"
set list = GetCollection( "cube.pnt[2,3,6,LAST]" )

if not typename(list) = "Nothing" then
	logmessage list
end if

function GetCollection( in_str )
	Dim l_myList 

	set GetCollection = CreateObject( "Sumatra.Collection" )

	On Error Resume Next
	GetCollection.items = in_str

	if GetCollection.Count = 0 then
		set GetCollection = Nothing
	end if

end function

Getting all visibility.viewvis parameters


From a discussion on the mailing list today, a few of the different ways to get every instance of a specific parameter, and some [crude] timing of the different methods.

I was also glad to see confirmation that using wildcards like “*.visibility” pick up everything (because I’ve never got any variation of “*#3dobject” to pick up all objects).

si = Application
import time
from win32com.client import Dispatch as disp
from win32com.client import constants as c


t = time.clock()
oObj = disp("XSI.Collection")
oObj.Items = "*.visibility"
for o in oObj:
	v = o.viewvis.Value
print 'XSICollection.Items  : count=%s, time=%s' % ( oObj.Count, time.clock() - t )


t = time.clock()
oObj.Items = "*.visibility.viewvis"
for o in oObj:
	v = o.Value
print 'XSICollection.Items  : count=%s, time=%s' % ( oObj.Count, time.clock() - t )



t = time.clock()
items = si.ActiveSceneRoot.FindChildren2()
for obj in items:
    vis = obj.GetPropertyFromName2("Visibility")
    v = vis.viewvis.value
print 'GetPropertyFromName2 : count=%s, time=%s' % ( items.Count, time.clock() - t )


t = time.clock()
items = si.ActiveSceneRoot.FindChildren2()
for obj in items:
    v = obj.Properties('visibility').Parameters('viewvis').Value   
print 'Properties.Parameters: count=%s, time=%s' % ( items.Count, time.clock() - t )


t = time.clock()
items = si.ActiveSceneRoot.FindChildren2()
for item in items:
    si.Tag(item.fullname + '.visibility.viewvis', c.siTag1)
print 'Tag()                : count=%s, time=%s' % ( items.Count, time.clock() - t )

t = time.clock()
items = si.ActiveSceneRoot.FindChildren2()
for item in items:
	p = item.Properties( "Visibility" ).Parameters( "viewvis" )
	p.Tags = c.siTag1
print 'Parameter.Tag        : count=%s, time=%s' % ( items.Count, time.clock() - t )


t = time.clock()
val = si.ActiveSceneRoot.TaggedParameters(c.siTag1, False)
for v in val:
    v = v.value
print 'TaggedParameters     : count=%s, time=%s' % ( items.Count, time.clock() - t )

Notice how turning off command logging speeds up those two commands:

# XSICollection.Items  : count=4367, time=1.18428964264
# XSICollection.Items  : count=4367, time=1.00415073153
# GetPropertyFromName2 : count=4367, time=2.07334397855
# Properties.Parameters: count=4367, time=4.38064481075
# Tag()                : count=4367, time=20.6681847681
# Parameter.Tag        : count=4367, time=5.11316244631
# TaggedParameters     : count=4367, time=0.705648810261
Application.SetValue("preferences.scripting.cmdlog", False, "")
# XSICollection.Items  : count=4367, time=1.16849869148
# XSICollection.Items  : count=4367, time=0.988541493731
# GetPropertyFromName2 : count=4367, time=2.03344763365
# Properties.Parameters: count=4367, time=4.33773781962
# Tag()                : count=4367, time=7.47015675041
# Parameter.Tag        : count=4367, time=4.99573667863
# TaggedParameters     : count=4367, time=0.687065751859