WxPython hosting a Panda3D display

Those fragments and the Panda doc were useful for writing the code for keeping both frameworks running cooperatively.

In particular, I am looking for the Panda3D equivalent of wx.Panel (or similar).

class Frame(wx.Frame):
   
    def __init__(self):
        wx.Frame.__init__(self, None, -1, "Panda test");
        panel = wx.Panel(self, -1);

We haven’t gotten around to implementing that yet. Presently, you can only open toplevel windows with Panda.

Though we’re actually working on something like this at the moment, so it will be just a matter of time before this feature makes it into the official Panda release.

David

Depending on your operating system, you might be able to make some headway by writing a small library in C or C++ that binds to the Python layer. The Win32 API has functions that allow you to list all the windows owned by your process; you can use the Spy++ program (one of the components installed with Visual Studio 2005) to determine the window class of the Panda3D window and then write a DLL that conforms to the Python C/API standard, digs up the window’s handle, and feeds it back. If you import the DLL by name (similar to importing source files, DLL name without the ‘.DLL’ suffix) Python can load its contents and expose them as a standard Python module. If I recall correctly, wxPython can deal directly in window handles; once you have acquired the handle to the Panda window, operating on it via wx becomes simpler.

Note that there are still a few challenges if you go this road: wx and Panda will have to be taught to correctly pass keyboard and mouse messages between each other to make sure that both your 2D UI and your 3D space work correctly. I don’t know of a particularly clean path to correctly handle the concept of focus.

The Python C/API is documented here:
docs.python.org/api/api.html

Best of luck!
-Mark

Hello folks,

I would also like to see the feature added to panda3d standard: open a panda3d window as a MDI window frame in my wxpython application.

Right now, Ogre3D is capable of offering this feature and IMHO it should be a MUST for panda - if it is not that much coding to be done.

Regards
Sabrina

Maybe you want to add that as a feature request in the corresponding forum section? :slight_smile:

https://discourse.panda3d.org/viewtopic.php?t=3021

Regards, Bigfoot29

Note that, as I mentioned, support for this has already been added via the WindowProperties.setParentWindow() method. Here’s a simple example:

import wx
import time

import direct
from pandac.PandaModules import *
loadPrcFileData('startup', 'window-type none')
from direct.directbase.DirectStart import *
from direct.showbase import DirectObject

class App(wx.PySimpleApp, DirectObject.DirectObject):
    def __init__(self):
        wx.PySimpleApp.__init__(self)

        #Create a new event loop (to overide default wxEventLoop)
        self.evtloop = wx.EventLoop()
        self.old = wx.EventLoop.GetActive()
        wx.EventLoop.SetActive(self.evtloop)
        taskMgr.add(self.wx, "Custom wx Event Loop")

    # wxWindows calls this method to initialize the application
    def OnInit(self):
        self.SetAppName('My wx app')
        self.SetClassName('MyAppClass')

        self.parent = wx.MDIParentFrame(None, -1, 'My wx app')
        self.child = wx.MDIChildFrame(self.parent, -1, 'Panda window')

        self.parent.SetClientSize((600, 400))
        self.parent.Show(True)
        self.child.SetClientSize((400, 300))
        self.child.Show(True)

        base.windowType = 'onscreen'
        props = WindowProperties.getDefault()
        props.setParentWindow(self.child.GetHandle())
        base.openDefaultWindow(props = props)

        base.setFrameRateMeter(True)
        
        return True

    def wx(self, task):
        while self.evtloop.Pending():
            self.evtloop.Dispatch()
        #time.sleep(0.01)
        self.ProcessIdle()
        return task.cont

    def close(self):
        wx.EventLoop.SetActive(self.old)

app = App()
run()

I am trying the above code on linux. The wx main window and “panda window” child window show, but panda comes up in its own window. child.GetHandle() returns 0 as well as the following message:

(python:4634): Gdk-WARNING **: gdkdrawable-x11.c:878 drawable is not a pixmap or window

Googling the warning leads me to the OGRE forum where they may discuss the same problem, only they use a different kind of handle :
ogre3d.org/phpBB2addons/viewtopic.php?t=4739

Sorry, this feature is currently supported only on the Windows and OSX builds of Panda, not on Linux.

Aside from adding Panda supporting, getting the window handle from wx on Linux is a separate problem.

In general, this is a pretty nasty trick that you’re asking for: getting the low-level handle to a window and passing it around between two different windowing systems. Possible, but tricky to implement on all platforms.

David

Any idea how to get said window handle, or do you have a suggestion of a GUI system that actually does support such things on linux?
I’ve searched on the internet about the window handle, but can’t find it anywhere. Do you have any hints?

Could anybody tell me what sort of handle setParentWindow requires? An xid, or a pointer to a GtkWidget, or else? I’ve looked through the panda3d source code but couldn’t find it.

In the Windows case, it is the system window handle, converted to an integer. In the OSX case, it is the window pointer, converted to an integer. In the Linux case, it does nothing–this method is not yet implemented in Linux.

David

Thanks for your reply.

On Linux, I have found a workaround: The panda window is an undecorated window which is repositioned based on self.child.GetScreenPositionTuple().
I have set the ZOrder of the panda window to ZTop to avoid it disappearing below the wxWindow.
A screenshot:
i-imagehost.com/uploads/b0b33c801c.png
If anyone is interested in my code, let me know.

EDIT: Just in case anyone reads this thread, setParentWindow on X11 is already supported and works great - no need for the workaround.

The example above works great, but the panda window doesn’t automatically match the size of the child wx mdi window. I’m working around this by destroying and recreating the window in the resize handler like this:

def OnSize(self, evt):
        if self.pandaWindow:
            base.graphicsEngine.removeWindow(self.pandaWindow)
        self.windowProperties.setSize(evt.Size[0], evt.Size[1])
        self.pandaWindow = base.openWindow(props = self.windowProperties)

Which works, but is a little slow. Does anyone know of a different way to resize a panda window?

Thx.

-Greg

wp = WindowProperties()
wp.setSize(evt.Size[0], evt.Size[1])
base.win.requestProperties(wp)

David

Oh okay, I was searching around for a set method instead. Works perfectly, thanks a lot!

I am new to Panda3D

While trying to embed a Panda3D window in a wxPython GUI all works fine except this: (I have used the same strategy as ‘drwr’ suggested)

When the program starts the events that are accepted by any DirectObject subclass from the keyboard work perfectly well, but once the focus is shifted to some other GUI element or the window is minimized and then maximized again…its never the same again…the DirectObject subclass doesn’t receive
any keyboard inputs!!

I tried verbose messenger and it turns out, the messenger itself doesn’t receive anything from the keyboard.

As was suggested somewhere on this forum, I tried to use windowProperties and request a SetForeground but this doesn’t help, although this request is not rejected (getRejectedProperties yields nothing)…

Is this a known issue or am I missing something obvious???
Please fire back if I couldn’t explain it properly

Shashank

So i had a stab at this using Panda3d on OSX. My set up is
Python 2.5.1 and panda 1.5.3

I installed Panda3d according to the install script generated by khakionion available at http://gamesketching.googlecode.com/files/pandaAutoInstall.py

When i run the program defined above (named embed.py) i get the following

juanchohome.local:[117] scratch|> python embed.py
:interrogatedb(warning): Classes Http_Request and Socket_TCP share the same TypeHandle value (42); check class definitions.
/usr/local/panda/lib/pandac/extension_native_helpers.py:65: DeprecationWarning: raising a string exception is deprecated
  raise message
DirectStart: Starting the game.
Warning: DirectNotify: category 'Interval' already exists
:audio: NullAudioManager
:audio: NullAudioManager
:audio: NullAudioManager
:audio: NullAudioManager
:util(warning): Adjusting global clock's real time by 0.986064 seconds.
:ShowBase:info: __dev__ == 0
:display: loading display module: libpandagl.dylib
Known pipe types:
  osxGraphicsPipe
(all display modules loaded.)
:ShowBase:info: Default graphics pipe is OpenGL (osxGraphicsPipe).
:display:osxdisplay: Creating child window
:display:osxdisplay: Child window created
2008-11-19 07:19:45.512 Python[66308:60b] *** -[NSHIObject windowNumber]: unrecognized selector sent to instance 0xe1d2880
2008-11-19 07:19:45.516 Python[66308:60b] An uncaught exception was raised
2008-11-19 07:19:45.517 Python[66308:60b] *** -[NSHIObject windowNumber]: unrecognized selector sent to instance 0xe1d2880
2008-11-19 07:19:45.519 Python[66308:60b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSHIObject windowNumber]: unrecognized selector sent to instance 0xe1d2880'
2008-11-19 07:19:45.520 Python[66308:60b] Stack: (
    2464936267,
    2461224507,
    2464965450,
    2464958796,
    2464958994,
    333329496,
    333334840,
    209984761,
    333331306,
    209926642,
    333313930,
    209666316,
    209666504,
    209696090,
    209726317,
    210200611,
    1628166,
    1635419,
    1285159,
    1178941,
    1630136,
    1635419,
    1285159,
    1178941,
    1630136,
    1635419,
    1628805,
    1635419,
    1285159,
    1178941,
    1213944,
    1178941,
    1608469,
    16813304,
    17092721,
    1178941,
    1630136,
    1635419,
    1628805,
    1635419,
    1285159,
    1178941,
    1213944,
    1178941,
    1628954,
    1635419,
    1285159,
    1178941,
    1213944,
    1178941,
    1628954,
    1635419,
    1285159,
    1178941,
    1213944,
    1178941,
    1452529,
    1428454,
    1178941,
    1628954,
    1635419,
    1635656,
    1731052,
    1732630,
    1739138,
    1784835
)
Trace/BPT trap

I do not know enough about the graphics layers on OSX to make sense of this report. Is there anyone here who can?

cheers

That is a known bug:
discourse.panda3d.org/viewtopic.php?t=4852
bugs.launchpad.net/panda3d/+bug/273608

Would you be interested in volunteering in debugging the issue?

I tried using this method, but when ever I exit the window created by wxPython, the application actually didn’t stop. I checked the Task Manager, there is still python.exe process running, and consuming quite a number of memory. Is there a new implementation for Panda 1.5.3 on using wxPython?

It has nothing to do with Panda.
If you want to shutdown Python when user closes wxPython-created window, you must respond to its close event.

self.parent.Bind(wx.EVT_CLOSE,sys.exit)

Import sys first.