Python Custom Modules (XSISDK)

Python has powerful ability to let you organize your code into modules (http://www.python.org/doc/current/tut/node8.html). It is an interesting way to organize your code into multiple script files. Modules are a Python feature, not a Softimage feature, but there are some tricks to make them work more succesfully inside of Softimage.

Since this article has been written, there have been some optimizations for working with custom python modules in Softimage.

Table of contents

Example Module Code

Imagine you have a Self-installed plugin and want to move some of the code into a Python Module. You don't want to hardcode the location of the module into your python environmental variables because the code needs to be placed on a workgroup and accessed by many users.

Here is an example self-installed plugin called ModuleDemo.py.

# Demonstration of a Self-installed plug-in
# which uses a custom Python Module
#
# It shows how the python module could be
# stored in the same workgroup or addon location
# without the need to hardcode the PYTHONPATH
# environmental variable for each user on the workgroup

import win32com.client
from win32com.client import constants

null = None
false = 0
true = 1

import sys


def XSILoadPlugin( in_reg ):
	in_reg.Author = "askowron"
	in_reg.Name = "Python Module Demo"
	in_reg.Major = 1
	in_reg.Minor = 0

	in_reg.RegisterCommand("UsePythonModule","UsePythonModule")
	#RegistrationInsertionPoint - do not remove this line

	#Make sure that the location of our workgroup
	#based Python modules are part of the Python path,
	
	#This makes sure that the import statements doesn't fail

	pluginLocation = in_reg.OriginPath

	#in this case we assume the modules are stored a
	#Modules directory as a sibling to the plugin path,
	#e.g. \Application\Modules
		
	workgroupLibFolder = XSIUtils.BuildPath( pluginLocation, "..", "Modules" )
	

	if workgroupLibFolder not in sys.path :
		sys.path.append( workgroupLibFolder )

	Application.LogMessage( sys.path )
	
	return true


def UsePythonModule_Execute(  ):

	#Import a file called Foo.py

	#We can't do the import at the top of the file
	#because we need to make sure the path has been
	#patched already by XSILoadPlugin
	import Foo

	#During development of Foo you will need to 
	#call reload to force the module to reload itself
	#after you change its contents.  Otherwise it is 
	#cached in memory	
	reload( Foo )

	#Demonstrate that the methods are available
	Application.LogMessage(Foo.Foo())	
	Foo.PrintPropsOfSelectedObj()
	
	return true

It relies on this file, Foo.py, which should be stored in the \Application\Modules directory of your Workgroup or Addon.

#
# Example python module for use by XSI
# 
#The module doesn't automatically have access to
#the global XSI objects, so this call would fail:
#Application.LogMessage( "Loading Foo Module" ) 


#Instead we can create our own global
#variables for XSIApplication and any other XSI intrinsic
#objects we might want

import win32com
ap = win32com.client.Dispatch( 'XSI.Application' ).Application

#Uncomment these lines if you want them
#XSIFactory = win32com.client.Dispatch( 'XSI.Factory' )
#XSIMath = win32com.client.Dispatch( 'XSI.Math' )
#from win32com.client import constants as c

#Basic Python routine
def Foo():
	return 7

#More interesting routine that is using the XSI Object Model
#via our "ap" variable		
def PrintPropsOfSelectedObj():
	for i in range(0,ap.Selection.Count):
		oObj = ap.Selection(i)
		ap.LogMessage( "%s has %s properties" % \
			( oObj.Name, oObj.Properties.Count ) )


Issues

Should Modules be Avoided?

Before decided to write your own modules you can also consider keeping all your code with-in self-installed plug-ins. You can have multiple plugins as a way of modularizing your code. By avoiding modules you won't have to do the special import and reload fixes and other workflow challenges described in this article.

Modules are clearly good if the code is not XSI specific and you want to access the same code from other scripts outside of XSI. Modules can also be great if you want to distribute the code once it is completely finished - you can send just the .pyc file and other people won't be able to see your code.

Explicitly Reload During Development

Python will cache your module script in memory even after you change it on disk, so you may need to call "Reload" as shown in the example above.

Accessing XSIApplication object inside the Module

The example above shows a workaround recreating an instance of the XSIApplication object as a global variable of your module. This lets you access the XSI scene within the Module.

import win32com
ap = win32com.client.Dispatch( 'XSI.Application' ).Application


Location of the Module files

Normally you need to store your Module files inside your python installation. You can also update the PYTHONPATH environmental variable to extend the module search path.

However the example above shows how this path can be build "on-the-fly" via sys.path to give maximum location independence to your code. Location independence is most important when you want to distribute your code onto a XSI workgroup or inside an .xsiaddon because the module path could be different on each machine.

This page was last modified 02:42, 13 Dec 2010.
This page has been accessed 11637 times.

© Copyright 2009 Autodesk Inc. All Rights Reserved. Privacy Policy | Legal Notices and Trademarks | Report Piracy