Created
April 9, 2011 09:19
-
-
Save MhmmdAb/911265 to your computer and use it in GitHub Desktop.
An Autodesk Softiamge plug-in that shows how to use wxPython from inside a command.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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