A brief history of the Python multi-dispatch issue


For the most part, this is no longer a problem, although there may be a few cases where you have to use win32com.client.dynamic.Dispatch. A huge effort was put in to XSI 6.0 to get rid of this “dispatch” issue.

The main problem was that XSI used a technique called “Multi-Dispatch” rather than normal inheritance to organize the interfaces supported by each object in the Scripting Object Model. In the original SDK, this was designed to maintain binary ompatibility for the now-obsolete COM C++ API.

The problem was that because Python used optimizations to read and compile the contents of typelibs rather than communicating with XSI directly via IDispatch, objects did not always appear to have all the methods and properties that they are supposed to.

For XSI 6.0, the OM hierarchy was overhauled to use derivation and inheritance instead of the multi-dispatch mechanism.

Prior to XSI 6.0, the workaround was the __init__.py file hack, as described in this 2005 post to the XSI Mailing List by Jerry Gamache:

—–Original Message—–
From: owner-xsi@Softimage.COM [mailto:owner-xsi@Softimage.COM] On Behalf Of Jerry Gamache
Sent: March-17-05 2:23 PM
To: XSI@Softimage.COM
Subject: RE: avoiding using get value with python

XSI sometimes return objects with an incorrectly set (as per PythonWin standards) multi-dispatch interface.

The way to work around that is to re-wrap the object in a dynamic dispatch. This allows you to skip the Application.GetValue:

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

# Let's see if this works:
Application.CreatePrim("Sphere", "MeshSurface", "", "")
Application.ApplyHairOp("sphere", "")
oHair = Application.GetValue("hair").ActivePrimitive.ConstructionHistory.Find("HairGenOp")
try:
	Application.LogMessage(oHair.Parameters['EmitterMeshSubdlevel'].Value)
except:
	Application.LogMessage("Incorrect dispatch pointer")
oHair = dispFix(oHair)
Application.LogMessage(oHair.Parameters['EmitterMeshSubdlevel'].Value)

# or, as a single long line:

dispFix(Application.GetValue("hair")  
	   .ActivePrimitive.ConstructionHistory 
	   .Find("HairGenOp")
	 ).Parameters['EmitterMeshSubdlevel'].Value = 1

If that really really annoys you and you don’t want to dispFix at all, there is a way to make sure everything works, but you need to modify a Python file to always return dynamic dispatches:

Change %PYTHONPATH%\Lib\site-packages\win32com\client\__init__.py

Look for the function called __WrapDispatch

And comment all lines except the last one that begins with “return dynamic.Dispatch( … ”

Of course it is always a good idea to backup files you are about to modify.

Using ICE color attributes to render instance geometry


This issue came across my desk several times recently:

I have a point cloud of instanced geometry, and I do a Color Attribute lookup in my point cloud material.
But the colors don’t show up in the render.

When you use instance geometry, you have to use the Color Attribute node in the material applied to the instance geometry, not the material applied to the point cloud.

Getting the selected ICE nodes


The context for custom menu callbacks gives you access to the current view instance, so you can use the selection view attribute to get the selected ICE nodes. See line 35 in the example.

import win32com.client
from win32com.client import constants

null = None
false = 0
true = 1

def XSILoadPlugin( in_reg ):
	in_reg.Author = "blairs"
	in_reg.Name = "My_ICETreeUserTool_Plugin"
	in_reg.Major = 1
	in_reg.Minor = 0

	in_reg.RegisterMenu(constants.siMenuICEViewToolsID,"My_ICETreeUserTool_Menu",false,false)
	#RegistrationInsertionPoint - do not remove this line

	return true

def XSIUnloadPlugin( in_reg ):
	strPluginName = in_reg.Name
	Application.LogMessage(str(strPluginName) + str(" has been unloaded."),constants.siVerbose)
	return true

def My_ICETreeUserTool_Menu_Init( in_ctxt ):
	oMenu = in_ctxt.Source
	oMenu.AddCallbackItem("My ICE Tree User Tool","OnMyICETreeUserTool")
	return true

def OnMyICETreeUserTool( in_ctxt ):
	itv = in_ctxt.GetAttribute("Target")
	
	LogMessage( 'View: ' + itv.Name )
	
	# get the selected nodes
	nodes = itv.GetAttributeValue('selection')
	LogMessage( 'Selected nodes: ' + nodes )
		

Installing Python modules in the Softimage Python site-packages


To get a Python module like PIL to work with the Python installed with Softimage, you will need to edit the registry. I tested this on my system, where I do not have any Python installed, except the Python installed with Softimage.

The PIL installer is looking in the registry for that Python install path, so we must edit the registry to put in the path to the Softimage Python.

You can use regedit to add the registry entry

HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.6\InstallPath

Then set the “(Default)” value to

C:\Program Files\Autodesk\Softimage 2011 Subscription Advantage Pack\Application\python

If you do have an external Python installed, you can just temporarily change the “(Default)” value to point to the Softimage install of Python.

Hat Tip: leendert68

Also: mabxsi suggests an alternative approach that avoids editing the registry

Friday Flashback #10


Splash screens through the years…

I couldn’t find anything older than these:

SOFTIMAGE|3D 4.0

SOFTIMAGE|SDK 3.9.2

Not much changed from 1.5 to 3.5:

SOFTIMAGE|XSI v1.5

SOFTIMAGE|XSI v2.0

SOFTIMAGE|XSI v3.5

4.2 and 5.11 were pretty much the same too:

SOFTIMAGE|XSI v4.2

SOFTIMAGE|XSI v5.11

It was Mr Hoodie for 6.x

SOFTIMAGE|XSI 6.02

7.0 was the last version of SOFTIMAGE|XSI.
After that, it was “Autodesk Softimage”.

SOFTIMAGE|XSI v7.01

SOFTIMAGE|XSI v7.5

And then the corporate branding…

Softimage 2010

Autodesk Softimage 2011


Autodesk Softimage 2012

ERROR : 2000 – Unable to create object [CLSID\{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}], Cleanup will be performed.


If you get an error that looks like this when you load a scene or import a model

ERROR : 2000 - Unable to create object [CLSID\{XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}],  Cleanup will be performed.

it’s often because you’re missing a shader or plugin (usually an older version that used spdl for registration).

Softimage prints this error message when it cannot create an instance of some object that was persisted in the scene file. In some cases, Softimage will know which DLL it was looking for, and you’ll get a message like this:

ERROR : 2000 - Unable to create object [CLSID\{A8BF89CA-1025-11D2-B5FD-006094EB029C}] : %SUMATRAPATH%\moaudio.dll,  Cleanup will be performed.

In the moaudio.dll case, you can run runonce.bat to fix the problem. Otherwise, the error may indicate a corruption of the object.