Hey all,
I’m having a problem getting my editor to work on Linux as I’m coming up against the GetHandle() returning 0 issue with wxPython. Nemesis has kindly offered a solution - showing the frame before initialising the viewports. This seems to work with the snippet attached below, but it doesn’t work with my editor source (here: github.com/Derfies/panda3d-editor) even though they’re doing pretty much the same thing.
I don’t have Linux so I can’t debug the issue. Is there anyone with a Linux machine who can take a look for me? I’d really appreciate it!
from panda3d.core import loadPrcFileData
loadPrcFileData( 'startup', 'window-type none' )
import wx
from pandac.PandaModules import WindowProperties
from direct.showbase.ShowBase import ShowBase
from direct.showbase.DirectObject import DirectObject
class Viewport( wx.Panel ):
def __init__( self, *args, **kwargs ):
"""
Initialise the wx panel. You must complete the other part of the
init process by calling Initialize() once the wx-window has been
built.
"""
wx.Panel.__init__( self, *args, **kwargs )
self._win = None
def GetWindow( self ):
return self._win
def SetWindow( self, win ):
self._win = win
def Initialize( self, useMainWin=True ):
"""
The panda3d window must be put into the wx-window after it has been
shown, or it will not size correctly.
"""
assert self.GetHandle() != 0
wp = WindowProperties()
wp.setOrigin( 0, 0 )
wp.setSize( self.ClientSize.GetWidth(), self.ClientSize.GetHeight() )
wp.setParentWindow( self.GetHandle() )
if self._win is None:
if useMainWin:
base.openDefaultWindow( props=wp, gsg=None )
self._win = base.win
else:
self._win = base.openWindow( props=wp, makeCamera=0 )
self.Bind( wx.EVT_SIZE, self.OnResize )
def OnResize( self, event ):
"""When the wx-panel is resized, fit the panda3d window into it."""
frame_size = event.GetSize()
wp = WindowProperties()
wp.setOrigin( 0, 0 )
wp.setSize( frame_size.GetWidth(), frame_size.GetHeight() )
self._win.requestProperties( wp )
class App( wx.App, DirectObject ):
"""
Don't forget to bind your frame's wx.EVT_CLOSE event to the app's
self.Quit method, or the application will not close properly.
"""
def ReplaceEventLoop( self ):
self.evtLoop = wx.EventLoop()
self.oldLoop = wx.EventLoop.GetActive()
wx.EventLoop.SetActive( self.evtLoop )
taskMgr.add( self.WxStep, 'evtLoopTask' )
self.WxStep()
def OnDestroy( self, event=None ):
self.WxStep()
wx.EventLoop.SetActive( self.oldLoop )
def Quit( self, event=None ):
self.OnDestroy( event )
try:
base
except NameError:
sys.exit()
base.userExit()
def WxStep( self, task=None ):
while self.evtLoop.Pending():
self.evtLoop.Dispatch()
self.ProcessIdle()
if task != None:
return task.cont
class MainFrame( wx.Frame ):
"""Panda Editor user interface."""
def __init__( self, *args, **kwargs ):
wx.Frame.__init__( self, *args, **kwargs )
self.vp = Viewport( self )
self.SetTitle( 'wxWindow' )
self.Bind( wx.EVT_CLOSE, self.OnClose )
self.bs1 = wx.BoxSizer( wx.VERTICAL )
self.bs1.Add( self.vp, 1, wx.EXPAND )
self.SetSizer( self.bs1 )
def OnClose( self, evt ):
self.Show( False )
wx.GetApp().Quit()
class App( App ):
"""Base editor class."""
def OnInit( self ):
self.frame = MainFrame( None, size=(800, 600) )
ShowBase()
self.ReplaceEventLoop()
self.frame.Show()
wx.CallAfter( self.FinishInit )
return True
def FinishInit( self ):
self.frame.vp.Initialize()
app = App( redirect=False )
run()