Get Closest Location and position coordinate systems


When you’re using Get Closest Locations, positions are local. That is, they are relative to the local coordinate system of the object that “owns” the ICE tree. The input Position is in local coordinates, so in most cases, (0, 0, 0) will do fine. And if you use the output locations to get positions, those positions will be in the local coordinate system of the ICE tree owner.
https://vimeo.com/85486760
Hat tip: Gray, who has posted this several (many?) times over the years.

Getting all shaders under a light


Given something like this:
light_disconnected shaders
Here’s how you get all shaders under a light, even the disconnected ones:

from sipyutils import si		# win32com.client.Dispatch('XSI.Application')
from sipyutils import log		# LogMessage
from sipyutils import C			# win32com.client.constants
from sipyutils import disp		# win32com.client.Dispatch

si = si()

def dispFix( badDispatch ):
    import win32com.client.dynamic
    # Re-Wraps a bad dispatch into a working one:
    return win32com.client.dynamic.Dispatch(badDispatch)

oLight = si.Selection(0)


#import win32com.client
oDisconnected = disp( "XSI.Collection" )

if oLight.IsClassOf( C.siLightID ):
	for oShader in oLight.GetAllShaders():
		oOut = dispFix( oShader.Parameters( "out" ) )
		if oOut.Targets.Count == 0:
			oDisconnected.Add( oShader )
			
log( oDisconnected.GetAsText() )

Hat tip: Matt Lind, who provided the GetAllShaders answer to the question “how to get all shaders in a light, even the disconnected ones”

Integer division in ICE


Dividing an integer N by itself doesn’t always give you 1.
IntegerDivision1
I think it’s a problem in the Divide by Scalar node (the division is probably returning a scalar like 0.99999999, and then that is truncated to zero when it is converted to an integer).

A workaround is to do all your division with scalars, and then use modulo to determine whether you Round or Floor the result. Here’s an example compound by Guillaume Laforge:
IntegerDivisionCompound

IntegerDivision3

Getting the texture support created by CreateProjection


Here’s the question: How do you get the texture support created by CreateProjection?

You’re supposed to be able to get the support name from an output argument, but that doesn’t work.

from sipyutils import si		# win32com.client.Dispatch('XSI.Application')
from sipyutils import log		# LogMessage
from sipyutils import C			# win32com.client.constants

si = si()

x = si.CreateProjection("sphere", C.siTxtSpherical, "", "SupportName", "Texture_Projection", "", "", "")

log( x.Value("SupportName") == None )

log( x.Count );
log( x(0) == "" );
log( x(1) );

So instead, I get the PropertyName and from CreateProjection and work my way over to the texture support, via the TextureOp.

import win32com.client

from sipyutils import si		# win32com.client.Dispatch('XSI.Application')
from sipyutils import log		# LogMessage
from sipyutils import C			# win32com.client.constants

si = si()

def dispFix( badDispatch ):
    import win32com.client.dynamic
    # Re-Wraps a bad dispatch into a working one:
    return win32com.client.dynamic.Dispatch(badDispatch)

o = si.Selection(0)

x = si.CreateProjection(o, C.siTxtSpherical, "", "Texture_Support", "Texture_Projection", "", "", "")
#CreateProjection( [InputObjs], [Type], [UVDefaultType], [SupportName], [PropertyName], [Parenting], [Fitting], [Camera] );

y = win32com.client.Dispatch( "XSI.Collection" )
y.Items = "%s.polymsh.cls.*.%s" % (o.FullName, x.Value("PropertyName") )

log( y.Items )

txtprop = si.Dictionary.GetObject( y(0).FullName )
op = txtprop.NestedObjects( "TextureOp" )

# re-dispatch it to avoid "object has no attribute 'InputPorts'" error
op = dispFix(op)

txtsupp = op.InputPorts(2).Target2.Parent3DObject

log( si.ClassName(txtsupp) )
si.SelectObj( txtsupp )

The SDK Explorer is good for finding these kinds of port connections:
texture_support_sdk_explorer

PS: Here’s a JScript version.

x = CreateProjection("cylinder", siTxtPlanarXY, siTxtDefaultSpherical, "Texture_Support", "Texture_Projection", null, siRelDefault, null);

var y = new ActiveXObject( "XSI.Collection" );
y.Items = "cylinder.polymsh.cls.*." + x.Value("PropertyName")

txtprop = Dictionary.GetObject( y(0).FullName );
op = txtprop.NestedObjects( "TextureOp" );

txtsupp = op.InputPorts(2).Target2.Parent3DObject

LogMessage( ClassName(txtsupp) );
SelectObj( txtsupp )