Tut-Glow-Basic, unable to start

I am on Windows XP, with my own version of Python 2.5.

I am able to run all tutorials well, except Tut-Glow-Basic.py

The error is:

:express(warning): Filename is incorrect case: /d/panda3D-1.5.4/direct/src/filter/filter-bloomi.sha instead of /d/Panda3D-1.5.4/direct/src/filter/filter-bloomi.
sha
:gobj(error): Could not read shader file: /d/panda3D-1.5.4/direct/src/filter/filter-bloomi.sha
Traceback (most recent call last):
  File "D:\Panda3D-1.5.4\samples\Glow-Filter\Tut-Glow-Basic.py", line 113, in <module>
    t=GlowDemo()
  File "D:\Panda3D-1.5.4\samples\Glow-Filter\Tut-Glow-Basic.py", line 47, in __init__
    filterok = self.filters.setBloom(blend=(0,0,0,1), desat=-0.5, intensity=3.0, size="small")
  File "D:\Panda3D-1.5.4\direct\src\filter\CommonFilters.py", line 233, in setBloom
    return self.reconfigure(fullrebuild, "Bloom")
  File "D:\Panda3D-1.5.4\direct\src\filter\CommonFilters.py", line 121, in reconfigure
    self.bloom[0].setShader(self.loadShader("filter-bloomi.sha"))
TypeError: NodePath.setShader() argument 1 must be Shader, not NoneType

It is work fine if I use the panda3D python. I would need to use my own version of python as I have quite a number of packages loaded there already.

I looked in CommonFilters.py => CommonFilters.loadShader
It creates the shader path by:
fn = os.path.join(os.path.abspath(os.path.dirname(file)), name)

Then I checked file variable, it is:
d:\panda3D-1.5.4\direct\src\filter\CommonFilters.py
instead of:
D:\Panda3D-1.5.4\direct\src\filter\CommonFilters.py

It is the main cause of the problem. Any idea on how to fix it ?

Hmm.
What happens if you replace the loadShader function with this one:

    def loadShader(self, name):
        fn = os.path.join(os.path.abspath(os.path.dirname(__file__)), name)
        fn = Filename.fromOsSpecific(fn)
        fn.makeTrueCase()
        return Shader.load(fn)

It works very well with your fix ! Thank you.

Good, then I’ll apply the fix for the upcoming 1.6.0.

Hi pro-rsoft
I encounter another problem on this area and it took me so long to track it down.

I am developing a wxPython container hosting some demos.
When I click the menu on wxPython app, it will launch the panda app on the Panda screen. If the panda app is calling:
filters = CommonFilters(base.win, base.cam)
filterok = filters.setBloom(blend=(1,0,0,1), desat=-0.5, intensity=3.0, size=1)

Then the app will crash.

To fix this, I tell panda to get the application focus first:
wp = WindowProperties()
wp.setForeground(True)
base.win.requestProperties(wp)
self.loadnext = demoinfo
taskMgr.doMethodLater(0.01, self.InitDemoLater, “initdemo”)

And initialize the application a bit later.

It looks like there are some assumptions in the CommonFilters implementation ?

Are you sure the window is already created when you create the CommonFilters? I believe base.win is None until that point, so it’s likely that caused the crash.
What kind of crash is it, by the way? If it’s a Python exception, could you give the traceback?

I am very sure the window is created. My app is like this:
hk.myblog.yahoo.com/clcheunghk/a … =1&mid=686

It starts with an empty panda. When I select an application, it load models, lights, …

The crash is a hard crash, not a python exception.

I just find that the YARR sample program with water shader shares the same problem. It is also fixed by delay calling. (i.e. make sure the panda windows get activated before creating the shaders).

Could you try to minimize the code to a few lines and post it here so I can take a look at it?

Would you mind if I post a link to a complete development source code for your test ? It is quite complicated to isolate that part as the whole thing is linked up together.

Hmm, you can’t reproduce the same thing (panda + wx window, call commonfilters, etc) in a very simple piece of code?

I can, just lazy.
I will make one and post when ready.

Here is the code:

import wx, wx.aui
from    wx.lib import masked
import sys
from pandac.PandaModules import *
import direct.directbase.DirectStart
from direct.filter.CommonFilters import CommonFilters
from direct.showbase.DirectObject import DirectObject


class ControlWindow(wx.Frame):
    def __init__(self, title, pos, size, panda, docking):
        self.panda = panda
        self.docking = docking
        if not docking:
            size=(224,size[1])
            pos = (800,0)

        wx.Frame.__init__(self, None, -1, title, pos, size=size)
        if self.docking:
            self.setDocking()

        self.setupWindows()

    def setupWindows(self):
        box = wx.BoxSizer(wx.VERTICAL)
        btn = wx.Button(self, -1, "Test 1")
        btn.Bind(wx.EVT_BUTTON, self.test1)
        box.Add(btn)
        btn = wx.Button(self, -1, "Test 2")
        btn.Bind(wx.EVT_BUTTON, self.test2)
        box.Add(btn)
        self.SetSizerAndFit (box)

    def test1(self, evt):
        self.panda.test1()

    def test2(self, evt):
        self.panda.test2()

class myApp(wx.App):
    WIDTH = 1024
    HEIGHT = 740
    def __init__(self, panda=None):
        self.panda = panda
        wx.App.__init__(self, 0)
        self.running = True

    def OnInit(self):
        self.evtLoop = wx.EventLoop()
        self.oldLoop = wx.EventLoop.GetActive()
        wx.EventLoop.SetActive(self.evtLoop)

        self.win = ControlWindow("Demo Master", (0,0), wx.Size(self.WIDTH, self.HEIGHT), self.panda, docking=False)
        self.SetTopWindow(self.win)
        #self.win.CenterOnScreen()
        self.win.Show(True)
        self.win.Bind(wx.EVT_CLOSE, self.onClose)

        #print "main loop is running" , self.IsMainLoopRunning()
        return True

    def Cleanup(self):
        self.running = False
        if self.panda != None:
            self.panda.Destroy()
            self.setPandaWorld(None)
#        self.win.SaveOnClose()
        self.win.Destroy()

    def onClose(self, event):
        self.Cleanup()
        #while self.evtLoop.Pending(): self.evtLoop.Dispatch()
        try: base.userExit()
        except: sys.exit()
        sys.exit()
        #base.disableAllAudio()
        #base.closeWindow( base.win )
        #base.userExit()
        #base.shutdown()
        #base.destroy()

    def setPandaWorld(self, panda):
        self.panda = panda
        self.win.panda = panda

class Container(DirectObject):
    def __init__(self, wxApp):
        #DirectObject.__init__(self)
        self.wxApp = wxApp

    def test1(self, task=None):
        self.filters = CommonFilters(base.win, base.cam)
        filterok = self.filters.setBloom(blend=(0,0,0,1), desat=-0.5, intensity=3.0, size="small")

    def test2(self):
        wp = WindowProperties()
        wp.setForeground(True)
        base.win.requestProperties(wp)
        taskMgr.doMethodLater(0.01, self.test1, "initdemo")

def handleWxEvents(wxApp, task):
    while wxApp.evtLoop.Pending(): wxApp.evtLoop.Dispatch()
    wxApp.ProcessIdle()
    if task != None and wxApp.running:
        return task.cont

def Start():
    wxApp = myApp(None)
    container = Container(wxApp)
    wxApp.setPandaWorld(container)
    taskMgr.add(handleWxEvents, 'handleWxEvents', extraArgs=[wxApp], appendTask=True)
    run()

Start()

If you click test1, it will crash.
click test2 is ok.

That’s weird. I’m not getting any crash at all. The common filters gets turned on fine with 1, too. It only crashes if I have clicked both (quite understandably, because I’d have 2 commonfilters instances)

That’s interesting.

Are you also testing on Windows XP ?

It is a hard crash, but what can I do to get more traces/debugging information from Panda to track down this problem ?

No, Linux here. I’ll try it later on windows if I get the chance.

I see. As far as I know it shall only happen on Windows.

Problem is here:

  for (wi = wlist.begin(); wi != wlist.end(); ++wi) {
    GraphicsOutput *win = (*wi);
    win->process_events();
  }

The problem is an “Access violation reading location 0x00000023.”
This sounds like a window was added to the window list while the loop was still running, invalidating the iterator. drwr, could I fix this by changing the code to something like this?

  for (int i = 0; i < wlist.size(); ++i) {
    wlist[i]->process_events();
  }

Ah, I see–the problem is caused because some Python code attached to a wx event caused a Panda buffer to be created. Since the wx event is handled in that loop, which doesn’t expect any buffers to be created during that loop, it caused a crash.

Changing the loop as you describe may be a reasonable solution. Please put an appropriate comment in the code to explain why it is necessary. I hope there aren’t any other issues to be discovered with Python callouts enabled during this loop.

David

Done, and also on the 1.6 branch.

Hmm, indeed. This is the second time I’ve ran into this issue, but just in a different loop. There are quite a number of functions in graphicsEngine that iterate through the windows using an iterator.

hi,

I am not sure if it is related problem. Panda also crash if called
base.graphicsEngine.makeOutput from wx.

Can your patch fix this one also ? Is it already in the downloadable version 1.6.0 ?