Hi all
After hours of frustrated digging in the forum on how to combine wx with panda, and after I finaly did the job, i post the full solution here.
The terrain is real terrain of the small crater (=machtesh) in Israel, one of the most beautifuls…
Copy attached files to your “/tmp” directory
I’m working on ubuntu 14.04, python 2.7.6, wxpython 2.8.12.1, panda 1.9.1
import wx
from panda3d.core import loadPrcFileData
from direct.showbase.ShowBase import ShowBase # import the bits of panda
from direct.wxwidgets.WxPandaWindow import WxPandaWindow
from panda3d.core import *
from direct.wxwidgets.WxPandaWindow import WxPandaWindow
from direct.task import Task
class PandaPanel(wx.Panel):
def __init__(self, parent, id, style):
wx.Panel.__init__(self, parent, id)
self.SetBackgroundColour("BLUE")
def OnKeyDown(self, event):
keycode = event.GetKeyCode()
print "PandaPanel OnKeyDown " + str(keycode)
def OnKeyUp(self, event):
keycode = event.GetKeyCode()
print "PandaPanel OnKeyUp " + str(keycode)
class pandaApp(ShowBase): # our 'class'
def __init__(self):
ShowBase.__init__(self) # initialise
base.startWx()
# add ambient light
ambient = Vec4(0.34, 0.3, 0.3, 1)
alight = AmbientLight('alight')
alight.setColor(ambient)
alnp = render.attachNewNode(alight)
dlight = DirectionalLight('dlight')
dlight.setColor(VBase4(0.8, 0.8, 0.5, 1))
dlnp = render.attachNewNode(dlight)
dlnp.setHpr(0, -60, 0)
terrain = GeoMipTerrain("genTerrain")
terrain.setHeightfield("/tmp/small_crater.hm.jpg")
terrain.setBlockSize(64)
terrain.setBruteforce(1)
self.ter = terrain
# Store the root NodePath for convenience
self.root = terrain.getRoot()
# self.root = base.loader.loadModel('/tmp/crater.4.bam')
self.root.reparentTo(base.render)
self.root.setScale(4)
self.hm_size=512
self.root.setPos(-1*self.hm_size*self.root.getSx()/2,
-1*self.hm_size*self.root.getSy()/2,0)
self.root.setHpr(0, 0, 0)
self.root.setSz(200)
terrain.generate()
###### Load textures and alpha maps
tex0 = loader.loadTexture('/tmp/small_crater.txt.2.jpg')
render.setLight(alnp)
render.setLight(dlnp)
self.blendtex(tex0, "finalstage", 200)
self.taskMgr.add(self.spinCameraTask, "SpinCameraTask")
base.disableMouse()
self.camera.setPos(0, 0, 3)
def blendtex(self, texture, stage, SORT):
ts = TextureStage(stage)
ts.setSort(SORT)
# ts.setCombineRgb(TextureStage.CMModulate, TextureStage.CSPrevious, TextureStage.COSrcColor,
# TextureStage.CSTexture, TextureStage.COSrcColor)
ts.setRgbScale(2)
self.root.setTexture(ts, texture)
ts.setSavedResult(True)
# Define a procedure to move the camera.
def spinCameraTask(self, task):
dt = globalClock.getDt()
if wx.GetKeyState(wx.WXK_LEFT):
self.camera.setH(self.camera.getH() + 20 * dt)
elif wx.GetKeyState(wx.WXK_RIGHT):
self.camera.setH(self.camera.getH() - 20 * dt)
if wx.GetKeyState(wx.WXK_UP):
self.camera.setY(self.camera, +20 * dt)
elif wx.GetKeyState(wx.WXK_DOWN):
self.camera.setY(self.camera, -20 * dt)
(hmx,hmy) = (self.hm_size/2+self.camera.getX()/self.root.getSx(),
self.hm_size/2+(self.camera.getY()+base.camLens.getNear())/self.root.getSy())
self.camera.setZ(self.ter.getElevation(hmx, hmy)*self.root.getSz()+3)
return Task.cont
class MainWindow(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, parent, -1, 'Test', size=(800, 600))
pandaPanel = PandaPanel(self, -1, style=wx.SUNKEN_BORDER)
panel2 = wx.Panel(self, -1, style=wx.SUNKEN_BORDER)
panel2.SetBackgroundColour("RED")
panel2.Bind(wx.EVT_LEFT_DOWN, self.OnMouseEvent2)
panel2.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown2)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(pandaPanel, 2, wx.EXPAND)
sizer.Add(panel2, 1, wx.EXPAND)
self.SetSizer(sizer)
panelSizer = wx.BoxSizer(wx.VERTICAL)
self.window1 = WxPandaWindow(parent=pandaPanel)
panelSizer.Add(self.window1, 1, wx.EXPAND)
pandaPanel.SetSizer(panelSizer)
self.window1.Bind(wx.EVT_LEFT_DOWN, self.OnMouseEvent)
self.window1.Bind(wx.EVT_LEFT_UP, self.OnMouseEvent)
self.window1.Bind(wx.EVT_KEY_DOWN, pandaPanel.OnKeyDown)
self.window1.Bind(wx.EVT_KEY_UP, pandaPanel.OnKeyUp)
self.Layout()
self.Show(True)
self.panel2 = panel2
def OnMouseEvent(self, event):
print "OnMouseEvent " + str(event.Id)
# print str(self.FindFocus())
self.window1.SetFocus()
def OnKeyDown(self, event):
keycode = event.GetKeyCode()
print "main OnKeyDown " + str(keycode)
def OnKeyUp(self, event):
keycode = event.GetKeyCode()
print "main OnKeyUp " + str(keycode)
def OnMouseEvent2(self, event):
print "OnMouseEvent2 " + str(event.Id)
self.panel2.SetFocus()
def OnKeyDown2(self, event):
keycode = event.GetKeyCode()
print "OnKeyDown2 " + str(keycode)
self.panel2.SetFocus()
# loadPrcFileData('startup', 'window-type none')
# window-type none is for where you don't need window, for
# example when you generate files. There is no camera in
# such situation. Here we need camera, so window is
# offscreen, not none
loadPrcFileData('startup', 'window-type offscreen')
app = pandaApp() # our 'object'
mw = MainWindow(None)
run()