from direct.showbase.ShowBase import ShowBase
from direct.task import Task
from math import pi, sin, cos
import sys, time, wx
import threading
class wxThread(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.messages = []
def run(self):
# setup wxPython window
self.wxApp = wx.App(False)
wxMainApp(None, self, "wxpython and Panda3d")
self.wxApp.MainLoop()
def shutdown(self):
self.wxApp.Destroy()
sys.exit()
def putMessage(self, msg):
self.messages.append(msg)
def getMessage(self):
try:
return self.messages.pop()
except:
return None
# wxPython Window
class wxMainApp(wx.Frame):
def __init__(self, parent, instance, title):
wx.Frame.__init__(self, parent, wx.ID_ANY, title=title, pos=(860,20), size=(200,638))
self.PandaApp = instance
# Status Bar, just because
self.CreateStatusBar()
# add a panel and sizer for the frame so we can stick controls into it
panel = wx.Panel(self)
box = wx.BoxSizer(wx.VERTICAL)
# add a button
self.button1 = wx.Button(panel, id=1000, label='Button', pos=(8, 8), size=(60,60))
self.button1.Bind(wx.EVT_BUTTON, self.SendPandaMessage)
box.Add(self.button1, 0, wx.ALL, 10)
# a text control
self.control = wx.TextCtrl(panel, pos=(8, 100), size=(176,200), style=wx.TE_MULTILINE)
box.Add(self.control, 0, wx.ALL, 10)
# and finally, bind the close event
self.Bind(wx.EVT_CLOSE, self.OnClose)
# and show everything
self.Show(True)
def OnClose(self, evt):
msg = 'CLOSE', evt.GetId()
self.PandaApp.putMessage(msg)
def SendPandaMessage(self, evt):
msg = 'CLICK', evt.GetId()
self.PandaApp.putMessage(msg)
# Panda Render Window
class PandaApp(ShowBase):
def __init__(self):
ShowBase.__init__(self)
# start wx control window in it's own thread
self.wxApplication = wxThread()
self.wxApplication.start()
# load demo environment model, scale and position, from Hello World
self.environ = self.loader.loadModel("models/environment")
self.environ.reparentTo(self.render)
self.environ.setScale(0.25, 0.25, 0.25)
self.environ.setPos(-8, 42, 0)
self.angle = 6.0
# add spin camera task
self.taskMgr.add(self.spinCameraTask, "SpinCameraTask")
# add message pump task - Panda runs this every frame
self.taskMgr.add(self.getAppMessage, "getAppMessage")
# Panda Task - query wxApplication message que
def getAppMessage(self, task):
self.processMessage(self.wxApplication.getMessage())
return Task.cont
# and do whatever here
def processMessage(self, message):
if message != None:
print message
if message[0] == 'CLICK':
self.angle = self.angle + 1.0 #mod this from button click in wxpython
if message[0] == 'CLOSE':
self.wxApplication.shutdown() #our wxpython is closing, kill everything
# procedure to spin the camera.
def spinCameraTask(self, task):
angleDegrees = task.time * self.angle #and use it here
angleRadians = angleDegrees * (pi / 180.0)
self.camera.setPos(20 * sin(angleRadians), -20.0 * cos(angleRadians), 3)
self.camera.setHpr(angleDegrees, 0, 0)
return Task.cont
# start everything
panda = PandaApp()
run()