Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
An Autodesk Softiamge plug-in that shows how to use wxPython from inside a command.
# By Mohammad "ShaderOp" Abdulfatah
# This little sample demonstrates how to use wxPython to display
# a dialog box inside Autodesk Softimage. It attached an item
# to the "Window" menu named "WxSceneInfo", which executes a
# a command that shows a wxPython dialog box with a labed and
# two buttons. One button adpats the label with the number
# of top-level objects in the current scne, and the other creates
# a polygonal cube.
# Modifying this code to work wiht PyQT should be trivial.
# For questions, comments, and feedback, you can reach me
# through my website at
import win32com.client
from win32com.client import constants
import threading
# This will be used to ensure that only one copy of the dialog
# is running.
is_dialog_running_event = threading.Event()
def XSILoadPlugin(in_reg):
in_reg.Author = "Mohammad Abdulfatah"
in_reg.Name = "WxSceneInfoPlugin"
in_reg.Major = 1
in_reg.Minor = 0
#RegistrationInsertionPoint - do not remove this line
return True
def XSIUnloadPlugin(in_reg):
strPluginName = in_reg.Name
return True
def WxSceneInfo_Init(in_ctxt):
oCmd = in_ctxt.Source
oCmd.Description = "Wx Scene Info"
oCmd.ReturnValue = True
return True
def WxSceneInfo_Execute():
# only launch the dialog if it's not already running.
if is_dialog_running_event.is_set() == False:
# It's probably a good idea to somehow notify the user that
# the dialog is already running.
return True
def WxSceneInfo_Menu_Init( in_ctxt ):
oMenu = in_ctxt.Source
return True
def runDialog():
# Any attempt to import the wx module on the main application thread
# will cause Softiamge to crash and burn, but since this method runs
# on a separate thread and has its own message loop, importing wx
# will work here.
import wx
# Now go to town
class MyFrame(wx.Frame):
def __init__(self, title):
# set background color to SI's signature desert gray.
self.SetBackgroundColour(wx.Color(171, 168, 166))
self.Bind(wx.EVT_CLOSE, self.OnClose)
self.objectCountLabel = wx.StaticText(self,
label="Number of objects in scene:",
pos = (10, 10),
size = (300, -1))
self.refreshButton = wx.Button(self, label = "Refresh", pos = (310, 10))
self.Bind(wx.EVT_BUTTON, self.OnRefresh, self.refreshButton)
self.createCubeButton = wx.Button(self,
label="Create cube",
pos=(310, 50))
self.Bind(wx.EVT_BUTTON, self.OnCreateCube, self.createCubeButton)
def OnRefresh(self, event):
count = Application.ActiveSceneRoot.Children.Count
label = "Number of objects in scene: {0}".format(count)
def OnCreateCube(self, event):
Application.ActiveSceneRoot.AddGeometry('Cube', 'MeshSurface')
def OnClose(self, event):
# IMPORTANT: Must release the event once the windows is closed,
# else the dialog won't launch again until after SI is restarted
global is_dialog_running_event
app = __getApplication()
frame = MyFrame("Hello World")
# Following code is copied almost verbatim from Houdini 9.5 sample
# code at
__command_queue = []
__command_queue_lock = threading.RLock()
__command_queue_event = threading.Event()
__wx_thread = None
def __queueCommand(callable, arguments=()):
global __wx_thread
if __wx_thread is None:
__wx_thread = threading.Thread(target=__wxThreadMain, name="wxThread")
__command_queue.append((callable, arguments))
def __wxThreadMain():
while True:
command = __command_queue.pop()
__wx_app = None
def __getApplication():
import wx
global __wx_app
if __wx_app is None:
__wx_app = wx.App(False)
return __wx_app
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.