|
|
|
Return to Scripting Issues
by macromate » Wed Apr 18, 2012 9:59 am
Hi,
I recently started using panda 1.8 and I'm excited about the better wxpython support (especially for Mac OSX). However I can't figure out how to use it. I managed to set up wxpython and the direct.wxwidgets.WxPandaWindow class and the result looks like this:
But I can't move the camera and it seams as if the panda app receives no events at all. I guess I set it up wrong, but i can't find a offical way of doing it. Can you please help me?
This is my current code (some of it):
- Code: Select all
import wx import wx.aui
from direct.showbase.ShowBase import ShowBase from direct.wxwidgets.ViewPort import Viewport import panda3d.core as core
core.loadPrcFileData('startup', 'window-type none')
class Frame(wx.Frame): def __init__(self, *args, **kwargs): wx.Frame.__init__(self, *args, **kwargs)
self.auiManager = wx.aui.AuiManager(self) self.panda = Viewport.makeFront(self) self.outliner = scenegraph.Panel(self) outlinerInfo = wx.aui.AuiPaneInfo().Name("outliner") outlinerInfo.Left().CloseButton(False) outlinerInfo.Caption("Scenegraph").BestSize((300, 300)) self.auiManager.AddPane(self.outliner, outlinerInfo) pandaInfo = wx.aui.AuiPaneInfo().Name("panda") pandaInfo.Center().CloseButton(False).MaximizeButton(True) self.auiManager.AddPane(self.panda, pandaInfo) self.auiManager.Update() def onQuit(self, evt): self.auiManager.UnInit() self.Close()
class App(ShowBase): def __init__(self): ShowBase.__init__(self, fStartDirect=False, windowType=None) # setup application window self.startWx() self.wxApp.Bind(wx.EVT_CLOSE, self.quit) self.frame = Frame(None, wx.ID_ANY, 'Editor', size=(1024, 768)) self.frame.Show() # setup mouse/picking/selection system
# THIS DOES NOT WORK, # neither pressing the left/right mouse button # nor pressing t outputs "debug" def foo(): print "debug" self.accept("mouse1", foo) self.accept("mouse3", foo) self.accept("t", foo)
# load the scene (set up models and stuff) self.loadScene(self.args.map)
def quit(self, event=None): self.onDestroy(event) try: base except NameError: sys.exit() base.userExit()
app = App() app.run()
Thanks !
PS: I'm using Panda 1.8 and wxpython 2.9.3.1 on Windows 7.
Last edited by macromate on Fri Apr 20, 2012 5:52 pm, edited 1 time in total.
-
macromate
-
- Posts: 8
- Joined: Sun Jul 24, 2011 12:01 pm
by rdb » Wed Apr 18, 2012 1:42 pm
Hmm, if you put a print statement in ShowBase.py function __wxTimerCallback, does it show up? That would tell us if the timer that is supposed to run the Panda event loop is running properly at all.
-
rdb
-
- Posts: 8549
- Joined: Mon Dec 04, 2006 5:58 am
- Location: Netherlands
-
by macromate » Wed Apr 18, 2012 4:01 pm
I checked this and __wxTimerCallback gets called.
-
macromate
-
- Posts: 8
- Joined: Sun Jul 24, 2011 12:01 pm
by rdb » Fri Apr 20, 2012 3:14 am
If you put "base.messenger.toggleVerbose()", and try and send events to the Panda window, how do they appear (if at all) on the console?
-
rdb
-
- Posts: 8549
- Joined: Mon Dec 04, 2006 5:58 am
- Location: Netherlands
-
by macromate » Fri Apr 20, 2012 4:06 am
I enabled base.messenger.toggleVerbose() and there are numerous log messages printed as the app is loading:
- Code: Select all
C:\open-emergency>python editor Verbose mode true. quiet list = ['collisionLoopFinished', 'event-loop-done', 'NewFrame', 'avatarMoving'] C:\Panda3D-1.8.0\direct\showbase\ShowBase.py:2740: wxPyDeprecationWarning: Using deprecated class. self.wxApp = wx.PySimpleApp(redirect = False) Known pipe types: wglGraphicsPipe (all display modules loaded.) :display:windisplay(warning): SetActiveWindow() failed! :display:windisplay(warning): SetForegroundWindow() failed! :Messenger(debug): sent event: TaskManager-addTask sentArgs = [PythonTask resetPrevTransform], taskChain = None :Messenger(debug): sent event: TaskManager-addTask sentArgs = [PythonTask dataLoop], taskChain = None :Messenger(debug): sent event: TaskManager-addTask sentArgs = [PythonTask ivalLoop], taskChain = None :Messenger(debug): sent event: TaskManager-addTask sentArgs = [PythonTask collisionLoop], taskChain = None :Messenger(debug): sent event: TaskManager-addTask sentArgs = [PythonTask garbageCollectStates], taskChain = None :Messenger(debug): sent event: TaskManager-addTask sentArgs = [PythonTask igLoop], taskChain = None :Messenger(debug): sent event: TaskManager-addTask sentArgs = [PythonTask audioLoop], taskChain = None :Messenger(debug): sent event: TaskManager-addTask sentArgs = [PythonTask eventManager], taskChain = None :Messenger(debug): sent event: window-event sentArgs = [<libpanda.GraphicsWindow object at 0x064A5AD0>], taskChain = None :Messenger(debug): sent event: window-event sentArgs = [<libpanda.GraphicsWindow object at 0x064A5AB8>], taskChain = None :Messenger(debug): sent event: window-event sentArgs = [<libpanda.GraphicsWindow object at 0x064A5AD0>], taskChain = None :Messenger(debug): sent event: open_window sentArgs = [<libpanda.GraphicsWindow object at 0x064A5A70>, True], taskChain = None :Messenger(debug): sent event: open_main_window sentArgs = [], taskChain = None :Messenger(debug): object: <editor.scenegraph.Tree; proxy of <Swig Object of type 'wxPyTreeCtrl *' at 0x6195820> > (('Tree', 5)) accepting: tree-item-added method: <bound method Tree.onItemAdd of <editor.scenegraph.Tree; proxy of <Swig Object of type 'wxPyTreeCtrl *' at 0x6195820> >> extraArgs: [] persistent: 1 :Messenger(debug): object: <editor.scenegraph.Tree; proxy of <Swig Object of type 'wxPyTreeCtrl *' at 0x6195820> > (('Tree', 5)) accepting: tree-item-deleted method: <bound method Tree.onItemDelete of <editor.scenegraph.Tree; proxy of <Swig Object of type 'wxPyTreeCtrl *' at 0x6195820> >> extraArgs: [] persistent: 1 :Messenger(debug): object: <editor.scenegraph.Tree; proxy of <Swig Object of type 'wxPyTreeCtrl *' at 0x6195820> > (('Tree', 5)) accepting: tree-item-hidden method: <bound method Tree.onItemVisibilityChange of <editor.scenegraph.Tree; proxy of <Swig Object of type 'wxPyTreeCtrl *' at 0x6195820> >> extraArgs: [] persistent: 1 :Messenger(debug): object: <editor.scenegraph.Tree; proxy of <Swig Object of type 'wxPyTreeCtrl *' at 0x6195820> > (('Tree', 5)) accepting: tree-item-unhidden method: <bound method Tree.onItemVisibilityChange of <editor.scenegraph.Tree; proxy of <Swig Object of type 'wxPyTreeCtrl *' at 0x6195820> >> extraArgs: [] persistent: 1 :Messenger(debug): object: <editor.scenegraph.Tree; proxy of <Swig Object of type 'wxPyTreeCtrl *' at 0x6195820> > (('Tree', 5)) accepting: selection-empty method: <bound method Tree.UnselectAll of <editor.scenegraph.Tree; proxy of <Swig Object of type 'wxPyTreeCtrl *' at 0x6195820> >> extraArgs: [] persistent: 1 :Messenger(debug): object: <editor.scenegraph.Tree; proxy of <Swig Object of type 'wxPyTreeCtrl *' at 0x6195820> > (('Tree', 5)) accepting: selection-changed method: <bound method Tree.onSelectionChange of <editor.scenegraph.Tree; proxy of <Swig Object of type 'wxPyTreeCtrl *' at 0x6195820> >> extraArgs: [] persistent: 1 :Messenger(debug): object: <editor.scenegraph.Tree; proxy of <Swig Object of type 'wxPyTreeCtrl *' at 0x6195820> > (('Tree', 5)) accepting: map-loading-finished method: <function <lambda> at 0x064BF2F0> extraArgs: [] persistent: 1 :Messenger(debug): object: <editor.App instance at 0x019043F0> (('App', 1)) accepting: mouse1 method: <function foo at 0x066B2A70> extraArgs: [] persistent: 1 :Messenger(debug): object: <editor.App instance at 0x019043F0> (('App', 1)) accepting: mouse3 method: <function foo at 0x066B2A70> extraArgs: [] persistent: 1 :Messenger(debug): object: <editor.App instance at 0x019043F0> (('App', 1)) accepting: t method: <function foo at 0x066B2A70> extraArgs: [] persistent: 1 :Messenger(debug): sent event: map-loading-finished sentArgs = [], taskChain = None :Messenger(debug): sent event: window-event sentArgs = [<libpanda.GraphicsWindow object at 0x06BE48D8>], taskChain = None :Messenger(debug): sent event: aspectRatioChanged sentArgs = [], taskChain = None :Messenger(debug): sent event: TaskManager-addTask sentArgs = [PythonTask manager-update], taskChain = None :Messenger(debug): sent event: window-event sentArgs = [<libpanda.GraphicsWindow object at 0x06BE48C0>], taskChain = None :Messenger(debug): sent event: aspectRatioChanged sentArgs = [], taskChain = None :Messenger(debug): sent event: window-event sentArgs = [<libpanda.GraphicsWindow object at 0x064A5EF0>], taskChain = None :Messenger(debug): <direct.showbase.Loader.Loader instance at 0x06386D00> (('Loader', 0)) now ignoring: 'async_loader_0'
However, pressing left/right mouse or pressing "t" doesn't produce any log message. When I resize the window, "aspectRatioChanged" messages are sent. Then I added messenger.send("t") after self.LoadScene and this works. foo() gets called and debug is printed to the console, as well as this log message: - Code: Select all
:Messenger(debug): sent event: t sentArgs = [], taskChain = None
-
macromate
-
- Posts: 8
- Joined: Sun Jul 24, 2011 12:01 pm
by rdb » Sat Apr 21, 2012 9:25 am
That is strange. Something in wxPython must be preventing the events from being sent to the Panda window. I don't know enough about wxPython to say what, though.
-
rdb
-
- Posts: 8549
- Joined: Mon Dec 04, 2006 5:58 am
- Location: Netherlands
-
by macromate » Sat Apr 21, 2012 11:49 am
Are you sure? I managed to get it working after a few changes in EmbeddedPandaWindow. I found this somewhere in the forum and it works like a charm.
- Code: Select all
class EmbeddedPandaWindow(wx.Window): """ This class implements a Panda3D window that is directly embedded within the frame. It is fully supported on Windows, partially supported on Linux, and not at all on OSX. """
def __init__(self, *args, **kw): gsg = None if 'gsg' in kw: gsg = kw['gsg'] del kw['gsg']
base.startWx() wx.Window.__init__(self, *args, **kw)
wp = WindowProperties.getDefault() if platform.system() != 'Darwin': try: wp.setParentWindow(self.GetHandle()) except OverflowError: # Sheesh, a negative value from GetHandle(). This can # only happen on 32-bit Windows. wp.setParentWindow(self.GetHandle() & 0xffffffff)
# # CHANGE HERE # self.win = base.openWindow(props = wp, gsg = gsg, type = 'onscreen', unexposedDraw = False) base.openDefaultWindow(props=wp, gsg=None) self.win = base.win # self.Bind(wx.EVT_SIZE, self.onSize)
# This doesn't actually do anything, since wx won't call # EVT_CLOSE on a child window, only on the toplevel window # that contains it. self.Bind(wx.EVT_CLOSE, self.__closeEvent)
def __closeEvent(self, event): self.cleanup() event.Skip()
def cleanup(self): """ Parent windows should call cleanup() to clean up the wxPandaWindow explicitly (since we can't catch EVT_CLOSE directly). """ if self.win: base.closeWindow(self.win) self.win = None
def onSize(self, event): wp = WindowProperties() wp.setOrigin(0, 0) wp.setSize(*self.GetClientSize()) # CHANGE HERE self.win.requestProperties(wp) # event.Skip()
What do you think of this? Could it be that the issue is not caused by wxPython but by Panda? The rest of my code stayed the same, I just replaced - Code: Select all
self.panda = Viewport.makeFront(self)
with - Code: Select all
self.panda = WxPandaWindow(self)
-
macromate
-
- Posts: 8
- Joined: Sun Jul 24, 2011 12:01 pm
by drwr » Tue Apr 24, 2012 2:02 pm
Are you sure you needed to make the change to EmbeddedPandaWindow? I think it would work without that change, as long as you replaced your call to Viewport with a call to WxPandaWindow.
I think Viewport makes a lot of other assumptions that aren't true in your case, but WxPandaWindow is closer to your environment.
David
-
drwr
-
- Posts: 11253
- Joined: Fri Feb 13, 2004 12:42 pm
- Location: Glendale, CA
by Bradamante » Sat May 12, 2012 1:02 pm
When I try to run this as a test I get:
.../demo.py activate_osx_application This program needs access to the screen. Please run with 'pythonw', not 'python', and only when you are logged in on the main display of your Mac.
I have secondary display hooked up to my iMac, is that it? Not sure if I want to deactivate it and reboot the computer.
iMac (2009), Mac OS X.8.1 - MacBookPro (2007), Mac OS X.8.2
@ YouTube
-

Bradamante
-
- Posts: 303
- Joined: Tue Nov 25, 2008 10:58 am
- Location: Leipzig, Germany
by drwr » Thu May 17, 2012 11:21 am
Did you try running it with pythonw instead of python, as it suggests? E.g. "pythonw demo.py"?
David
-
drwr
-
- Posts: 11253
- Joined: Fri Feb 13, 2004 12:42 pm
- Location: Glendale, CA
by Bradamante » Thu Jun 14, 2012 3:34 pm
That gives:
- Code: Select all
Traceback (most recent call last): File "/Applications/Panda3D_Mare_Ceti/samples/WXPython/demo1.py", line 3, in <module> import wx File "/var/tmp/wxWidgets/wxWidgets-13~231/2.6/DSTROOT/System/Library/Frameworks/Python.framework/Versions/2.6/Extras/lib/python/wx-2.8-mac-unicode/wx/__init__.py", line 45, in <module> File "/var/tmp/wxWidgets/wxWidgets-13~231/2.6/DSTROOT/System/Library/Frameworks/Python.framework/Versions/2.6/Extras/lib/python/wx-2.8-mac-unicode/wx/_core.py", line 4, in <module> ImportError: /System/Library/Frameworks/Python.framework/Versions/2.6/Extras/lib/python/wx-2.8-mac-unicode/wx/_core_.so: no appropriate 64-bit architecture (see "man python" for running in 32-bit mode)
python? ppython? pythonw? Oh man ... 
iMac (2009), Mac OS X.8.1 - MacBookPro (2007), Mac OS X.8.2
@ YouTube
-

Bradamante
-
- Posts: 303
- Joined: Tue Nov 25, 2008 10:58 am
- Location: Leipzig, Germany
by doublereedkurt » Mon Aug 13, 2012 3:20 am
I am having the same problem in windows.
I noticed that the ShowBase object's mouseWatchNode is set to None.
Maybe there is some critical initialization which is not happening? Maybe there is a way to do it manually?
EDIT:
Is this necessary?
core.loadPrcFileData('startup', 'window-type none')
I'll bet the initialization of some of the input handlers doesn't happen until the window exists.
Hmm... Further investigation:
The bottom of this page http://www.panda3d.org/manual/index.php/SPE
recommends that if the window-type is set to none, the window can be started later with this function:
base.openMainWindow(type = 'onscreen')
The docs for that function (ShowBase.openMainWindow) say:
Creates the initial, main window for the application, and sets up the mouse and render2d structures appropriately for it.
So, maybe input handlers are not being properly initialized because the window is not started?
EDIT 2:
If I omit the line
core.loadPrcFileData('startup', 'window-type none')
then two windows show: the wxPython window, and the regular Panda3D window.
Input works in the Panda window, but not in the wxPython window.
class MainWindow(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1, 'Test', size=(640, 480))
self.panda_panel = WxPandaWindow(parent=self)
self.Show(True)
EDIT 3:
Source code here: http://panda3d.cvs.sourceforge.net/view ... xt%2Fplain
I need to read and understand what is going on there to track it down... looks like suppressing the window-open is the correct thing to do, since ther eis a call to base.openWindow inside the EmbeddedPandaWindow.
-
doublereedkurt
-
- Posts: 10
- Joined: Sun Jul 15, 2012 11:39 pm
by rdb » Wed Aug 15, 2012 5:01 am
@Bradamante: it looks like there's a mismatch between the architecture of your wx installation and the version of Python you're running.
@doublereedkurt: on some platforms, wx wants control over the main loop in order for events to work properly. In 1.8.0 and above, this is done by Panda if you put "want-wx #t" in Config.prc (or use base.startWx()). Does that help?
-
rdb
-
- Posts: 8549
- Joined: Mon Dec 04, 2006 5:58 am
- Location: Netherlands
-
by doublereedkurt » Wed Aug 15, 2012 12:44 pm
@rdb: thanks, I didn't know what startWx() did; it is being called so that probably isn't the problem.
That is an interesting avenue though, I'll try adding some wxPython widgets to the frame as well, and see if they are getting keyboard/mouse events.
I notice looking at the source code of WxPandaWindow that the windows class is much, much smaller than the OpenGL class. I wonder if some of that extra code is for passing through mouse/keyboard events when the panda window has focus.
Edit:
Ok, clearly the extra code has to do with passing through input events. The real question is, is that necessary for non-OpenGL windows? I'll try Bind()'ing mouse and keyboard handlers on the window through wxPython's normal mechanisms. Actually, it wouldn't be too much code to have a pass-through binding. The only tricky part will be getting accurate screen coordinates for mouse clicks.
Also, I notice the aspect ratio doesn't change when the window is re-sized.
-
doublereedkurt
-
- Posts: 10
- Joined: Sun Jul 15, 2012 11:39 pm
by ynjh_jo » Wed Aug 15, 2012 8:25 pm
You haven't created any panda window at all, that's what.
Stripped down version, beware :
- Code: Select all
import wx import wx.aui
from direct.showbase.ShowBase import ShowBase from direct.wxwidgets.ViewPort import Viewport import panda3d.core as core
core.loadPrcFileData('startup', 'window-type none')
class Frame(wx.Frame): def __init__(self, *args, **kwargs): wx.Frame.__init__(self, *args, **kwargs)
self.auiManager = wx.aui.AuiManager(self) self.panda = Viewport.makeFront(self) pandaInfo = wx.aui.AuiPaneInfo().Name("panda") pandaInfo.Center().CloseButton(False).MaximizeButton(True) self.auiManager.AddPane(self.panda, pandaInfo) self.auiManager.Update() def onQuit(self, evt): self.auiManager.UnInit() self.Close()
class App(ShowBase): def __init__(self): ShowBase.__init__(self, fStartDirect=False, windowType=None) # setup application window self.startWx() self.wxApp.Bind(wx.EVT_CLOSE, self.quit) self.frame = Frame(None, wx.ID_ANY, 'Editor', size=(800, 600))
# YNJH : create P3D window wp = core.WindowProperties() wp.setOrigin(20,20) wp.setSize(400,300) wp.setParentWindow(self.frame.panda.GetHandle()) base.openMainWindow(type = 'onscreen', props=wp)
self.frame.Show() # setup mouse/picking/selection system
def foo(): print "debug" self.accept("mouse1", foo) self.accept("mouse3", foo) self.accept("t", foo)
def quit(self, event=None): self.onDestroy(event) try: base except NameError: sys.exit() base.userExit()
app = App() app.run()
-

ynjh_jo
-
- Posts: 1795
- Joined: Tue Apr 18, 2006 12:41 am
- Location: Malang, Indonesia
-
by doublereedkurt » Wed Aug 15, 2012 10:09 pm
@ynjh_jo
That makes a lot of sense!
Thank you so much 
-
doublereedkurt
-
- Posts: 10
- Joined: Sun Jul 15, 2012 11:39 pm
by doublereedkurt » Thu Aug 16, 2012 11:44 pm
Alright, so apparently WxPandaWindow / EmbeddedPandaWindow calls base.openWindow(). When you call openWindow() you get something without input handlers.
So, basically TLDR; if you want to enclose your game inside a wxWindows frame, it is totally doable, but you'll have to do it manually and just use WxPandaWindow as a starting point.
-
doublereedkurt
-
- Posts: 10
- Joined: Sun Jul 15, 2012 11:39 pm
by gyedo » Wed Mar 20, 2013 6:17 pm
@Bradamante
Try to use /usr/bin/pythonw2.5
-

gyedo
-
- Posts: 29
- Joined: Fri Jun 22, 2007 12:46 pm
- Location: Glendale, CA
Return to Scripting Issues
Who is online
Users browsing this forum: enn0x and 0 guests
| | |