Create a gist now

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 http://shaderop.com/contact/
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
in_reg.RegisterCommand("WxSceneInfo","WxSceneInfo")
in_reg.RegisterMenu(constants.siMenuMainWindowID,
"WxSceneInfo_Menu",
False,
False)
#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:
__queueCommand(runDialog)
else:
# It's probably a good idea to somehow notify the user that
# the dialog is already running.
pass
return True
def WxSceneInfo_Menu_Init( in_ctxt ):
oMenu = in_ctxt.Source
oMenu.AddCommandItem("WxSceneInfo","WxSceneInfo")
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):
wx.Frame.__init__(self,
None,
size=(400,300),
style=wx.DEFAULT_FRAME_STYLE,
title=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)
self.objectCountLabel.SetLabel(label)
def OnCreateCube(self, event):
Application.ActiveSceneRoot.AddGeometry('Cube', 'MeshSurface')
def OnClose(self, event):
self.Destroy()
# 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
is_dialog_running_event.clear()
app = __getApplication()
frame = MyFrame("Hello World")
frame.Show(True)
is_dialog_running_event.set()
app.MainLoop()
# Following code is copied almost verbatim from Houdini 9.5 sample
# code at http://www.sidefx.com/docs/houdini9.5/hom/cookbook/pyqt/
__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")
__wx_thread.start()
__command_queue_lock.acquire()
__command_queue.append((callable, arguments))
__command_queue_lock.release()
__command_queue_event.set()
def __wxThreadMain():
while True:
__command_queue_event.wait()
__command_queue_lock.acquire()
command = __command_queue.pop()
__command_queue_event.clear()
__command_queue_lock.release()
command[0].__call__(*command[1])
__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