Browse Source

Merge branch 'master' into interrogate-overhaul

rdb 11 years ago
parent
commit
b2f73d0877
100 changed files with 2476 additions and 3529 deletions
  1. 4 9
      direct/src/directnotify/Notifier.py
  2. 5 5
      direct/src/ffi/DoGenPyCode.py
  3. 2 2
      direct/src/filter/CommonFilters.py
  4. 0 0
      direct/src/http/HTMLTree.py
  5. 69 60
      direct/src/p3d/AppRunner.py
  6. 7 7
      direct/src/p3d/DeploymentTools.py
  7. 10 10
      direct/src/p3d/FileSpec.py
  8. 18 19
      direct/src/p3d/HostInfo.py
  9. 2 2
      direct/src/p3d/InstalledHostData.py
  10. 55 56
      direct/src/p3d/PackageInfo.py
  11. 19 19
      direct/src/p3d/PackageInstaller.py
  12. 11 11
      direct/src/p3d/PackageMerger.py
  13. 144 41
      direct/src/p3d/Packager.py
  14. 30 30
      direct/src/p3d/PatchMaker.py
  15. 6 6
      direct/src/p3d/ScanDirectoryNode.py
  16. 4 4
      direct/src/p3d/coreapi.pdef
  17. 6 10
      direct/src/p3d/packp3d.py
  18. 26 2
      direct/src/p3d/panda3d.pdef
  19. 2 2
      direct/src/p3d/pdeploy.py
  20. 3 3
      direct/src/p3d/pmerge.py
  21. 1 1
      direct/src/p3d/ppackage.py
  22. 2 2
      direct/src/p3d/ppatcher.py
  23. 1 1
      direct/src/p3d/runp3d.py
  24. 2 2
      direct/src/p3d/thirdparty.pdef
  25. 2 2
      direct/src/particles/ForceGroup.py
  26. 1 1
      direct/src/particles/ParticleManagerGlobal.py
  27. 29 30
      direct/src/particles/Particles.py
  28. 1 2
      direct/src/particles/SpriteParticleRendererExt.py
  29. 36 77
      direct/src/plugin/p3dPythonRun.cxx
  30. 46 43
      direct/src/plugin/p3dX11SplashWindow.cxx
  31. 0 557
      direct/src/showbase/BpDb.py
  32. 1 1
      direct/src/showbase/BufferViewer.py
  33. 0 4
      direct/src/showbase/DirectObject.py
  34. 8 36
      direct/src/showbase/EventManager.py
  35. 3 3
      direct/src/showbase/ExceptionVarDump.py
  36. 1 1
      direct/src/showbase/Job.py
  37. 5 75
      direct/src/showbase/Messenger.py
  38. 0 12
      direct/src/showbase/PandaObject.py
  39. 1 1
      direct/src/showbase/PhysicsManagerGlobal.py
  40. 18 966
      direct/src/showbase/PythonUtil.py
  41. 71 64
      direct/src/showbase/ShowBase.py
  42. 24 23
      direct/src/showbase/VFSImporter.py
  43. 11 22
      direct/src/showutil/FreezeTool.py
  44. 28 28
      direct/src/stdpy/file.py
  45. 3 3
      direct/src/stdpy/pickle.py
  46. 30 31
      direct/src/stdpy/thread.py
  47. 48 51
      direct/src/stdpy/threading.py
  48. 2 2
      direct/src/stdpy/threading2.py
  49. 15 15
      direct/src/task/Task.py
  50. 445 438
      dtool/src/cppparser/cppBison.cxx.prebuilt
  51. 58 56
      dtool/src/cppparser/cppBison.h.prebuilt
  52. 2 27
      dtool/src/dtoolbase/deletedBufferChain.I
  53. 11 13
      dtool/src/dtoolbase/deletedBufferChain.cxx
  54. 13 2
      dtool/src/dtoolbase/deletedBufferChain.h
  55. 24 1
      dtool/src/dtoolbase/dtoolbase_cc.h
  56. 31 11
      dtool/src/dtoolutil/executionEnvironment.cxx
  57. 3 0
      dtool/src/prc/configFlags.cxx
  58. 1 1
      dtool/src/prc/configFlags.h
  59. 2 0
      dtool/src/pystub/pystub.cxx
  60. 5 0
      makepanda/installpanda.py
  61. 42 19
      makepanda/makepanda.py
  62. 4 5
      panda/src/bullet/bulletContactCallbacks.h
  63. 21 25
      panda/src/collide/collisionVisualizer.cxx
  64. 4 4
      panda/src/cull/cullBinBackToFront.cxx
  65. 4 4
      panda/src/cull/cullBinFrontToBack.cxx
  66. 2 2
      panda/src/cull/cullBinStateSorted.I
  67. 2 2
      panda/src/display/config_display.cxx
  68. 2 1
      panda/src/display/config_display.h
  69. 55 6
      panda/src/display/graphicsEngine.cxx
  70. 7 6
      panda/src/display/graphicsEngine.h
  71. 19 41
      panda/src/display/graphicsOutput.cxx
  72. 2 2
      panda/src/display/graphicsOutput.h
  73. 16 16
      panda/src/display/graphicsPipe.cxx
  74. 6 5
      panda/src/display/graphicsPipe.h
  75. 23 1
      panda/src/display/graphicsStateGuardian.I
  76. 210 13
      panda/src/display/graphicsStateGuardian.cxx
  77. 6 2
      panda/src/display/graphicsStateGuardian.h
  78. 35 6
      panda/src/display/standardMunger.cxx
  79. 1 0
      panda/src/display/standardMunger.h
  80. 17 17
      panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx
  81. 3 0
      panda/src/dxgsg9/dxGraphicsStateGuardian9.h
  82. 5 6
      panda/src/dxgsg9/dxShaderContext9.I
  83. 28 113
      panda/src/dxgsg9/dxShaderContext9.cxx
  84. 6 18
      panda/src/dxgsg9/dxShaderContext9.h
  85. 36 0
      panda/src/express/openSSLWrapper.I
  86. 4 1
      panda/src/express/openSSLWrapper.h
  87. 9 32
      panda/src/framework/pandaFramework.cxx
  88. 12 1
      panda/src/framework/windowFramework.I
  89. 29 14
      panda/src/framework/windowFramework.cxx
  90. 7 5
      panda/src/framework/windowFramework.h
  91. 1 2
      panda/src/glstuff/glCgShaderContext_src.I
  92. 117 95
      panda/src/glstuff/glCgShaderContext_src.cxx
  93. 5 10
      panda/src/glstuff/glCgShaderContext_src.h
  94. 13 14
      panda/src/glstuff/glGraphicsBuffer_src.cxx
  95. 19 0
      panda/src/glstuff/glGraphicsStateGuardian_src.I
  96. 105 85
      panda/src/glstuff/glGraphicsStateGuardian_src.cxx
  97. 12 3
      panda/src/glstuff/glGraphicsStateGuardian_src.h
  98. 170 46
      panda/src/glstuff/glShaderContext_src.cxx
  99. 1 1
      panda/src/glstuff/glShaderContext_src.h
  100. 8 3
      panda/src/glstuff/glTimerQueryContext_src.cxx

+ 4 - 9
direct/src/directnotify/Notifier.py

@@ -4,7 +4,7 @@ for the programmer/user
 """
 from LoggerGlobal import defaultLogger
 from direct.showbase import PythonUtil
-from panda3d.core import ConfigVariableBool
+from panda3d.core import ConfigVariableBool, NotifyCategory, StreamWriter, Notify
 import time
 import types
 import sys
@@ -18,9 +18,8 @@ class Notifier:
     # with the C++ notify system.
     streamWriter = None
     if ConfigVariableBool('notify-integrate', True):
-        from panda3d.core import StreamWriter, Notify
         streamWriter = StreamWriter(Notify.out(), False)
-        
+
     showTime = ConfigVariableBool('notify-timestamp', False)
 
     def __init__(self, name, logger=None):
@@ -44,9 +43,6 @@ class Notifier:
         self.__warning = 1
         self.__debug = 0
         self.__logging = 0
-        
-        
-
 
     def setServerDelta(self, delta, timezone):
         """
@@ -62,7 +58,6 @@ class Notifier:
         # The following call is necessary to make the output from C++
         # notify messages show the same timestamp as those generated
         # from Python-level notify messages.
-        from pandac.PandaModules import NotifyCategory
         NotifyCategory.setServerDelta(self.serverDelta)
 
         self.info("Notify clock adjusted by %s (and timezone adjusted by %s hours) to synchronize with server." % (PythonUtil.formatElapsedSeconds(delta), (time.timezone - timezone) / 3600))
@@ -92,7 +87,7 @@ class Notifier:
 
     # Severity funcs
     def setSeverity(self, severity):
-        from pandac.PandaModules import NSDebug, NSInfo, NSWarning, NSError
+        from panda3d.core import NSDebug, NSInfo, NSWarning, NSError
         if severity >= NSError:
             self.setWarning(0)
             self.setInfo(0)
@@ -111,7 +106,7 @@ class Notifier:
             self.setDebug(1)
 
     def getSeverity(self):
-        from pandac.PandaModules import NSDebug, NSInfo, NSWarning, NSError
+        from panda3d.core import NSDebug, NSInfo, NSWarning, NSError
         if self.getDebug():
             return NSDebug
         elif self.getInfo():

+ 5 - 5
direct/src/ffi/DoGenPyCode.py

@@ -143,7 +143,7 @@ def doGetopts():
             doSqueeze = False
         elif (flag == '-s'):
             deleteSourceAfterSqueeze = False
-            
+
         else:
             FFIConstants.notify.error('illegal option: ' + flag)
 
@@ -168,7 +168,7 @@ def doGetopts():
         if codeLib not in newLibs:
             newLibs.append(codeLib)
     codeLibs = newLibs
-        
+
 
 def doErrorCheck():
     global outputCodeDir
@@ -278,9 +278,9 @@ def generateNativeWrappers():
         # in the runtime (plugin) environment, where all libraries are
         # not necessarily downloaded.
         if sys.version_info >= (3, 0):
-            pandaModules.write('try:\n  from .%s import *\nexcept ImportError as err:\n  if "DLL loader cannot find" not in str(err):\n    raise\n' % (metaModuleName))
+            pandaModules.write('try:\n    from .%s import *\nexcept ImportError as err:\n    if "DLL loader cannot find" not in str(err):\n        raise\n' % (metaModuleName))
         else:
-            pandaModules.write('try:\n  from %s import *\nexcept ImportError, err:\n  if "DLL loader cannot find" not in str(err):\n    raise\n' % (metaModuleName))
+            pandaModules.write('try:\n    from %s import *\nexcept ImportError, err:\n    if "DLL loader cannot find" not in str(err):\n        raise\n' % (metaModuleName))
 
         # Not sure if this message is helpful or annoying.
         #pandaModules.write('  print("Failed to import %s")\n' % (moduleName))
@@ -306,7 +306,7 @@ def generateNativeWrappers():
                     extension = open(extensionFilename, 'r')
                     moduleModules.write(extension.read())
                     moduleModules.write('\n')
-        
+
 
 def run():
     global outputCodeDir

+ 2 - 2
direct/src/filter/CommonFilters.py

@@ -199,7 +199,7 @@ class CommonFilters:
                 self.ssao[0].setShaderInput("depth", self.textures["depth"])
                 self.ssao[0].setShaderInput("normal", self.textures["aux"])
                 self.ssao[0].setShaderInput("random", loader.loadTexture("maps/random.rgb"))
-                self.ssao[0].setShader(Shader.make(SSAO_BODY % configuration["AmbientOcclusion"].numsamples))
+                self.ssao[0].setShader(Shader.make(SSAO_BODY % configuration["AmbientOcclusion"].numsamples, Shader.SL_Cg))
                 self.ssao[1].setShaderInput("src", ssao0)
                 self.ssao[1].setShader(self.loadShader("filter-blurx.sha"))
                 self.ssao[2].setShaderInput("src", ssao1)
@@ -339,7 +339,7 @@ class CommonFilters:
                 text += "  o_color = float4(1, 1, 1, 1) - o_color;\n"
             text += "}\n"
             
-            self.finalQuad.setShader(Shader.make(text))
+            self.finalQuad.setShader(Shader.make(text, Shader.SL_Cg))
             for tex in self.textures:
                 self.finalQuad.setShaderInput("tx"+tex, self.textures[tex])
             

+ 0 - 0
direct/src/showbase/HTMLTree.py → direct/src/http/HTMLTree.py


+ 69 - 60
direct/src/p3d/AppRunner.py

@@ -25,16 +25,13 @@ if 'VFSImporter' in sys.modules:
     direct.showbase.VFSImporter = VFSImporter
     sys.modules['direct.showbase.VFSImporter'] = VFSImporter
 else:
-    # Otherwise, we can import the VFSImporter normally.  We have to
-    # import PandaModules first, to get the funny renaming with
-    # pandaexpress.
-    import direct
-    from pandac import PandaModules
+    # Otherwise, we can import the VFSImporter normally.
     from direct.showbase import VFSImporter
 
 from direct.showbase.DirectObject import DirectObject
-from pandac.PandaModules import VirtualFileSystem, Filename, Multifile, loadPrcFileData, unloadPrcFile, getModelPath, Thread, WindowProperties, ExecutionEnvironment, PandaSystem, Notify, StreamWriter, ConfigVariableString, ConfigPageManager, initAppForGui
-from pandac import PandaModules
+from panda3d.core import VirtualFileSystem, Filename, Multifile, loadPrcFileData, unloadPrcFile, getModelPath, Thread, WindowProperties, ExecutionEnvironment, PandaSystem, Notify, StreamWriter, ConfigVariableString, ConfigPageManager
+from panda3d.direct import init_app_for_gui
+from panda3d import core
 from direct.stdpy import file, glob
 from direct.task.TaskManagerGlobal import taskMgr
 from direct.showbase.MessengerGlobal import messenger
@@ -83,7 +80,7 @@ class AppRunner(DirectObject):
 
     # Also from p3d_plugin.h
     P3D_CONTENTS_DEFAULT_MAX_AGE = 5
-    
+
     def __init__(self):
         DirectObject.__init__(self)
 
@@ -119,8 +116,8 @@ class AppRunner(DirectObject):
         self.windowPrc = None
 
         self.http = None
-        if hasattr(PandaModules, 'HTTPClient'):
-            self.http = PandaModules.HTTPClient.getGlobalPtr()
+        if hasattr(core, 'HTTPClient'):
+            self.http = core.HTTPClient.getGlobalPtr()
 
         self.Undefined = Undefined
         self.ConcreteStruct = ConcreteStruct
@@ -213,7 +210,7 @@ class AppRunner(DirectObject):
         # this instance, e.g. the WindowProperties necessary to
         # re-embed a window in the browser frame.
         self.windowProperties = None
-        
+
         # Store our pointer so DirectStart-based apps can find us.
         if AppRunnerGlobal.appRunner is None:
             AppRunnerGlobal.appRunner = self
@@ -263,7 +260,7 @@ class AppRunner(DirectObject):
             value = bool(value)
         return value
 
-        
+
 
     def installPackage(self, packageName, version = None, hostUrl = None):
 
@@ -353,7 +350,7 @@ class AppRunner(DirectObject):
 
         # No shenanigans, just return the requested host.
         return host
-        
+
     def getHost(self, hostUrl, hostDir = None):
         """ Returns a new HostInfo object corresponding to the
         indicated host URL.  If we have already seen this URL
@@ -419,7 +416,7 @@ class AppRunner(DirectObject):
                 # the host directory too.
                 del self.hosts[hostUrl]
                 self.__deleteHostFiles(host)
-                
+
         return packages
 
     def __deleteHostFiles(self, host):
@@ -431,7 +428,7 @@ class AppRunner(DirectObject):
         self.rmtree(host.hostDir)
 
         self.sendRequest('forget_package', host.hostUrl, '', '')
-        
+
 
     def freshenFile(self, host, fileSpec, localPathname):
         """ Ensures that the localPathname is the most current version
@@ -449,18 +446,18 @@ class AppRunner(DirectObject):
         doc = None
         if self.superMirrorUrl:
             # Use the "super mirror" first.
-            url = PandaModules.URLSpec(self.superMirrorUrl + fileSpec.filename)
+            url = core.URLSpec(self.superMirrorUrl + fileSpec.filename)
             self.notify.info("Freshening %s" % (url))
             doc = self.http.getDocument(url)
-            
+
         if not doc or not doc.isValid():
             # Failing the super mirror, contact the actual host.
-            url = PandaModules.URLSpec(host.hostUrlPrefix + fileSpec.filename)
+            url = core.URLSpec(host.hostUrlPrefix + fileSpec.filename)
             self.notify.info("Freshening %s" % (url))
             doc = self.http.getDocument(url)
             if not doc.isValid():
                 return False
-        
+
         file = Filename.temporary('', 'p3d_')
         if not doc.downloadToFile(file):
             # Failed to download.
@@ -522,12 +519,11 @@ class AppRunner(DirectObject):
         """ Reads the config.xml file that may be present in the root
         directory. """
 
-        if not hasattr(PandaModules, 'TiXmlDocument'):
+        if not hasattr(core, 'TiXmlDocument'):
             return
-        from pandac.PandaModules import TiXmlDocument
 
         filename = Filename(self.rootDir, self.ConfigBasename)
-        doc = TiXmlDocument(filename.toOsSpecific())
+        doc = core.TiXmlDocument(filename.toOsSpecific())
         if not doc.LoadFile():
             return
 
@@ -544,7 +540,7 @@ class AppRunner(DirectObject):
         called automatically; an application may call this after
         adjusting some parameters (such as self.maxDiskUsage). """
 
-        from pandac.PandaModules import TiXmlDocument, TiXmlDeclaration, TiXmlElement
+        from panda3d.core import TiXmlDocument, TiXmlDeclaration, TiXmlElement
 
         filename = Filename(self.rootDir, self.ConfigBasename)
         doc = TiXmlDocument(filename.toOsSpecific())
@@ -561,7 +557,7 @@ class AppRunner(DirectObject):
         tfile = Filename.temporary(self.rootDir.cStr(), '.xml')
         if doc.SaveFile(tfile.toOsSpecific()):
             tfile.renameTo(filename)
-        
+
 
     def checkDiskUsage(self):
         """ Checks the total disk space used by all packages, and
@@ -574,11 +570,11 @@ class AppRunner(DirectObject):
                 totalSize += packageData.totalSize
         self.notify.info("Total Panda3D disk space used: %s MB" % (
             (totalSize + 524288) / 1048576))
-        
+
         if self.verifyContents == self.P3DVCNever:
             # We're not allowed to delete anything anyway.
             return
-        
+
         self.notify.info("Configured max usage is: %s MB" % (
             (self.maxDiskUsage + 524288) / 1048576))
         if totalSize <= self.maxDiskUsage:
@@ -592,7 +588,7 @@ class AppRunner(DirectObject):
                 if packageData.package and packageData.package.installed:
                     # Don't uninstall any packages we're currently using.
                     continue
-                
+
                 usedPackages.append((packageData.lastUse, packageData))
 
         # Sort the packages into oldest-first order.
@@ -609,13 +605,13 @@ class AppRunner(DirectObject):
                 packages.append(packageData.package)
             else:
                 # If it's an unknown package, just delete it directly.
-                print "Deleting unknown package %s" % (packageData.pathname)
+                print("Deleting unknown package %s" % (packageData.pathname))
                 self.rmtree(packageData.pathname)
 
         packages = self.deletePackages(packages)
         if packages:
-            print "Unable to delete %s packages" % (len(packages))
-        
+            print("Unable to delete %s packages" % (len(packages)))
+
         return
 
     def stop(self):
@@ -663,10 +659,10 @@ class AppRunner(DirectObject):
             for child in filename.scanDirectory():
                 self.rmtree(Filename(filename, child))
             if not filename.rmdir():
-                print "could not remove directory %s" % (filename)
+                print("could not remove directory %s" % (filename))
         else:
             if not filename.unlink():
-                print "could not delete %s" % (filename)
+                print("could not delete %s" % (filename))
 
     def setSessionId(self, sessionId):
         """ This message should come in at startup. """
@@ -747,10 +743,23 @@ class AppRunner(DirectObject):
             # will properly get ignored by ShowBase.
             self.initialAppImport = True
 
-            __import__(moduleName)
-            main = sys.modules[moduleName]
-            if hasattr(main, 'main') and hasattr(main.main, '__call__'):
-                main.main(self)
+            # Python won't let us import a module named __main__.  So,
+            # we have to do that manually, via the VFSImporter.
+            if moduleName == '__main__':
+                dirName = Filename(self.multifileRoot).toOsSpecific()
+                importer = VFSImporter.VFSImporter(dirName)
+                loader = importer.find_module('__main__')
+                if loader is None:
+                    raise ImportError('No module named __main__')
+
+                mainModule = loader.load_module('__main__')
+            else:
+                __import__(moduleName)
+                mainModule = sys.modules[moduleName]
+
+            # Check if it has a main() function.  If so, call it.
+            if hasattr(mainModule, 'main') and hasattr(mainModule.main, '__call__'):
+                mainModule.main(self)
 
             # Now clear this flag.
             self.initialAppImport = False
@@ -814,7 +823,7 @@ class AppRunner(DirectObject):
 
         # Now that we have rootDir, we can read the config file.
         self.readConfigXml()
-        
+
 
     def addPackageInfo(self, name, platform, version, hostUrl, hostDir = None,
                        recurse = False):
@@ -858,7 +867,7 @@ class AppRunner(DirectObject):
                 # Maybe the contents.xml file isn't current.  Re-fetch it.
                 if host.redownloadContentsFile(self.http):
                     return self.addPackageInfo(name, platform, version, hostUrl, hostDir = hostDir, recurse = True)
-            
+
             message = "Couldn't find %s %s on %s" % (name, version, hostUrl)
             raise OSError, message
 
@@ -866,18 +875,18 @@ class AppRunner(DirectObject):
         if not package.downloadDescFile(self.http):
             message = "Couldn't get desc file for %s" % (name)
             raise OSError, message
-        
+
         if not package.downloadPackage(self.http):
             message = "Couldn't download %s" % (name)
             raise OSError, message
-        
+
         if not package.installPackage(self):
             message = "Couldn't install %s" % (name)
             raise OSError, message
 
         if package.guiApp:
             self.guiApp = True
-            initAppForGui()
+            init_app_for_gui()
 
     def setP3DFilename(self, p3dFilename, tokens, argv, instanceId,
                        interactiveConsole, p3dOffset = 0, p3dUrl = None):
@@ -885,7 +894,7 @@ class AppRunner(DirectObject):
         contains the application itself, along with the web tokens
         and/or command-line arguments.  Once this method has been
         called, the application is effectively started. """
-        
+
         # One day we will have support for multiple instances within a
         # Python session.  Against that day, we save the instance ID
         # for this instance.
@@ -937,9 +946,9 @@ class AppRunner(DirectObject):
         self.allowPythonDev = False
 
         i = mf.findSubfile('p3d_info.xml')
-        if i >= 0 and hasattr(PandaModules, 'readXmlStream'):
+        if i >= 0 and hasattr(core, 'readXmlStream'):
             stream = mf.openReadSubfile(i)
-            self.p3dInfo = PandaModules.readXmlStream(stream)
+            self.p3dInfo = core.readXmlStream(stream)
             mf.closeReadSubfile(stream)
         if self.p3dInfo:
             self.p3dPackage = self.p3dInfo.FirstChildElement('package')
@@ -975,7 +984,7 @@ class AppRunner(DirectObject):
             ConfigVariableString('frame-rate-meter-text-pattern').setValue('allow_python_dev %0.1f fps')
 
         if self.guiApp:
-            initAppForGui()
+            init_app_for_gui()
 
         self.initPackedAppEnvironment()
 
@@ -992,7 +1001,7 @@ class AppRunner(DirectObject):
             # provided if available.  It is only for documentation
             # purposes; the actual p3d file has already been
             # downloaded to p3dFilename.
-            self.p3dUrl = PandaModules.URLSpec(p3dUrl)
+            self.p3dUrl = core.URLSpec(p3dUrl)
 
         # Send this call to the main thread; don't call it directly.
         messenger.send('AppRunner_startIfReady', taskChain = 'default')
@@ -1015,14 +1024,14 @@ class AppRunner(DirectObject):
                     newUrl = xalthost.Attribute('url')
                     self.altHostMap[origUrl] = newUrl
                     break
-                
+
                 xalthost = xalthost.NextSiblingElement('alt_host')
-    
+
     def loadMultifilePrcFiles(self, mf, root):
         """ Loads any prc files in the root of the indicated
         Multifile, which is presumed to have been mounted already
         under root. """
-        
+
         # We have to load these prc files explicitly, since the
         # ConfigPageManager can't directly look inside the vfs.  Use
         # the Multifile interface to find the prc files, rather than
@@ -1046,12 +1055,12 @@ class AppRunner(DirectObject):
                     cp = loadPrcFileData(pathname, data)
                     # Set it to sort value 20, behind the implicit pages.
                     cp.setSort(20)
-        
-    
+
+
     def __clearWindowProperties(self):
         """ Clears the windowPrc file that was created in a previous
         call to setupWindow(), if any. """
-        
+
         if self.windowPrc:
             unloadPrcFile(self.windowPrc)
             self.windowPrc = None
@@ -1127,12 +1136,12 @@ class AppRunner(DirectObject):
         function that can be used to deliver requests upstream, to the
         core API, and thereby to the browser. """
         self.requestFunc = func
-        
+
     def sendRequest(self, request, *args):
         """ Delivers a request to the browser via self.requestFunc.
         This low-level function is not intended to be called directly
         by user code. """
-        
+
         assert self.requestFunc
         return self.requestFunc(self.instanceId, request, args)
 
@@ -1176,7 +1185,7 @@ class AppRunner(DirectObject):
             # Evaluate it now.
             return self.scriptRequest('eval', self.dom, value = expression,
                                       needsResponse = needsResponse)
-        
+
     def scriptRequest(self, operation, object, propertyName = '',
                       value = None, needsResponse = True):
         """ Issues a new script request to the browser.  This queries
@@ -1184,7 +1193,7 @@ class AppRunner(DirectObject):
         low-level method that user code should not call directly;
         instead, just operate on the Python wrapper objects that
         shadow the DOM objects, beginning with appRunner.dom.
-        
+
         operation may be one of [ 'get_property', 'set_property',
         'call', 'evaluate' ].
 
@@ -1233,7 +1242,7 @@ def dummyAppRunner(tokens = [], argv = None):
     first-look sanity check. """
 
     if AppRunnerGlobal.appRunner:
-        print "Already have AppRunner, not creating a new one."
+        print("Already have AppRunner, not creating a new one.")
         return AppRunnerGlobal.appRunner
 
     appRunner = AppRunner()
@@ -1243,7 +1252,7 @@ def dummyAppRunner(tokens = [], argv = None):
     platform = PandaSystem.getPlatform()
     version = PandaSystem.getPackageVersionString()
     hostUrl = PandaSystem.getPackageHostUrl()
-    
+
     if platform.startswith('win'):
         rootDir = Filename(Filename.getUserAppdataDirectory(), 'Panda3D')
     elif platform.startswith('osx'):
@@ -1256,7 +1265,7 @@ def dummyAppRunner(tokens = [], argv = None):
 
     # Of course we will have the panda3d application loaded.
     appRunner.addPackageInfo('panda3d', platform, version, hostUrl)
-        
+
     appRunner.tokens = tokens
     appRunner.tokenDict = dict(tokens)
     if argv is None:
@@ -1274,6 +1283,6 @@ def dummyAppRunner(tokens = [], argv = None):
     vfs.mount(cwd, appRunner.multifileRoot, vfs.MFReadOnly)
 
     appRunner.initPackedAppEnvironment()
-    
+
     return appRunner
 

+ 7 - 7
direct/src/p3d/DeploymentTools.py

@@ -8,9 +8,9 @@ import os, sys, subprocess, tarfile, shutil, time, zipfile, glob, socket, getpas
 from cStringIO import StringIO
 from direct.directnotify.DirectNotifyGlobal import *
 from direct.showbase.AppRunnerGlobal import appRunner
-from pandac.PandaModules import PandaSystem, HTTPClient, Filename, VirtualFileSystem, Multifile
-from pandac.PandaModules import TiXmlDocument, TiXmlDeclaration, TiXmlElement, readXmlStream
-from pandac.PandaModules import PNMImage, PNMFileTypeRegistry
+from panda3d.core import PandaSystem, HTTPClient, Filename, VirtualFileSystem, Multifile
+from panda3d.core import TiXmlDocument, TiXmlDeclaration, TiXmlElement, readXmlStream
+from panda3d.core import PNMImage, PNMFileTypeRegistry
 from direct.stdpy.file import *
 from direct.p3d.HostInfo import HostInfo
 # This is important for some reason
@@ -296,7 +296,7 @@ class Icon:
 
     def __init__(self):
         self.images = {}
-    
+
     def addImage(self, image):
         """ Adds an image to the icon.  Returns False on failure, True on success.
         Only one image per size can be loaded, and the image size must be square. """
@@ -1097,7 +1097,7 @@ class Installer:
 
         # Tell Vista that we require admin rights
         print >>nsi, 'RequestExecutionLevel admin'
-        print >>nsi 
+        print >>nsi
         if self.offerRun:
             print >>nsi, 'Function launch'
             print >>nsi, '  ExecShell "open" "$INSTDIR\\%s.exe"' % self.shortname
@@ -1112,7 +1112,7 @@ class Installer:
                 print >>nsi, '  CreateShortcut "$DESKTOP\\%s.lnk" "$INSTDIR\\%s.exe" "" "$INSTDIR\\%s.ico"' % (self.fullname, self.shortname, self.shortname)
             print >>nsi, 'FunctionEnd'
             print >>nsi
-            
+
         print >>nsi, '!include "MUI2.nsh"'
         print >>nsi, '!define MUI_ABORTWARNING'
         if self.offerRun:
@@ -1213,7 +1213,7 @@ class Installer:
 
         if icofile is not None:
             icofile.unlink()
-        
+
         return output
 
     def os_walk(self, top):

+ 10 - 10
direct/src/p3d/FileSpec.py

@@ -1,6 +1,6 @@
 import os
 import time
-from pandac.PandaModules import Filename, HashVal, VirtualFileSystem
+from panda3d.core import Filename, HashVal, VirtualFileSystem
 
 class FileSpec:
     """ This class represents a disk file whose hash and size
@@ -18,13 +18,13 @@ class FileSpec:
     def fromFile(self, packageDir, filename, pathname = None, st = None):
         """ Reads the file information from the indicated file.  If st
         is supplied, it is the result of os.stat on the filename. """
-        
+
         vfs = VirtualFileSystem.getGlobalPtr()
 
         filename = Filename(filename)
         if pathname is None:
             pathname = Filename(packageDir, filename)
-        
+
         self.filename = filename.cStr()
         self.basename = filename.getBasename()
 
@@ -41,17 +41,17 @@ class FileSpec:
         hv = HashVal()
         hv.hashFile(pathname)
         self.hash = hv.asHex()
-                 
+
 
     def loadXml(self, xelement):
         """ Reads the file information from the indicated XML
         element. """
-        
+
         self.filename = xelement.Attribute('filename')
         self.basename = None
         if self.filename:
             self.basename = Filename(self.filename).getBasename()
-            
+
         size = xelement.Attribute('size')
         try:
             self.size = int(size)
@@ -87,7 +87,7 @@ class FileSpec:
             xelement.SetAttribute('size', str(self.size))
         if self.hash:
             xelement.SetAttribute('hash', self.hash)
-            
+
     def quickVerify(self, packageDir = None, pathname = None,
                     notify = None, correctSelf = False):
         """ Performs a quick test to ensure the file has not been
@@ -157,8 +157,8 @@ class FileSpec:
             self.__updateTimestamp(pathname, st)
 
         return True
-        
-            
+
+
     def fullVerify(self, packageDir = None, pathname = None, notify = None):
         """ Performs a more thorough test to ensure the file has not
         been modified.  This test is less vulnerable to malicious
@@ -235,7 +235,7 @@ class FileSpec:
         """ Corrects the internal hash to match the one on disk. """
         if not self.actualFile:
             self.checkHash(packageDir, pathname, st)
-            
+
         if notify:
             notify.info("Correcting hash %s to %s" % (
                 self.filename, self.actualFile.hash))

+ 18 - 19
direct/src/p3d/HostInfo.py

@@ -1,7 +1,6 @@
-from pandac.PandaModules import HashVal, Filename, PandaSystem, DocumentSpec, Ramfile
-from pandac.PandaModules import HTTPChannel
-from pandac import PandaModules
-from libpandaexpress import ConfigVariableInt
+from panda3d.core import HashVal, Filename, PandaSystem, DocumentSpec, Ramfile
+from panda3d.core import HTTPChannel, ConfigVariableInt
+from panda3d import core
 from direct.p3d.PackageInfo import PackageInfo
 from direct.p3d.FileSpec import FileSpec
 from direct.directnotify.DirectNotifyGlobal import directNotify
@@ -49,7 +48,7 @@ class HostInfo:
 
         if hostDir and not isinstance(hostDir, Filename):
             hostDir = Filename.fromOsSpecific(hostDir)
-            
+
         self.hostDir = hostDir
         self.asMirror = asMirror
         self.perPlatform = perPlatform
@@ -175,7 +174,7 @@ class HostInfo:
                         statusString = channel.getStatusString()
                         self.notify.warning("Could not contact download server at %s" % (url,))
                         self.notify.warning("Status code = %s %s" % (statusCode, statusString))
-                                    
+
                 if not rf:
                     self.notify.warning("Unable to download %s" % (url,))
                     try:
@@ -206,7 +205,7 @@ class HostInfo:
                         self.notify.warning("%s" % (str(e),))
                         pass
                     return False
-                    
+
         tempFilename = Filename.temporary('', 'p3d_', '.xml')
         if rf:
             f = open(tempFilename.toOsSpecific(), 'wb')
@@ -278,7 +277,7 @@ class HostInfo:
 
         now = int(time.time())
         return now < self.contentsExpiration and self.hasContentsFile
-        
+
     def readContentsFile(self, tempFilename = None, freshDownload = False):
         """ Reads the contents.xml file for this particular host, once
         it has been downloaded into the indicated temporary file.
@@ -290,7 +289,7 @@ class HostInfo:
         there already.  If tempFilename is not specified, the standard
         filename is read if it is known. """
 
-        if not hasattr(PandaModules, 'TiXmlDocument'):
+        if not hasattr(core, 'TiXmlDocument'):
             return False
 
         if not tempFilename:
@@ -304,7 +303,7 @@ class HostInfo:
 
             tempFilename = Filename(hostDir, 'contents.xml')
 
-        doc = PandaModules.TiXmlDocument(tempFilename.toOsSpecific())
+        doc = core.TiXmlDocument(tempFilename.toOsSpecific())
         if not doc.LoadFile():
             return False
 
@@ -337,12 +336,12 @@ class HostInfo:
                 xcontents.RemoveChild(xorig)
                 xorig = xcontents.FirstChildElement('orig')
 
-            xorig = PandaModules.TiXmlElement('orig')
+            xorig = core.TiXmlElement('orig')
             self.contentsSpec.storeXml(xorig)
             xorig.SetAttribute('expiration', str(self.contentsExpiration))
 
             xcontents.InsertEndChild(xorig)
-            
+
         else:
             # Read the download hash and expiration time from the XML.
             expiration = None
@@ -385,7 +384,7 @@ class HostInfo:
                 perPlatform = int(xpackage.Attribute('per_platform') or '')
             except ValueError:
                 perPlatform = False
-                
+
             package = self.__makePackage(name, platform, version, solo, perPlatform)
             package.descFile = FileSpec()
             package.descFile.loadXml(xpackage)
@@ -418,7 +417,7 @@ class HostInfo:
         """ Looks for the <host> or <alt_host> entry in the
         contents.xml that corresponds to the URL that we actually
         downloaded from. """
-        
+
         xhost = xcontents.FirstChildElement('host')
         while xhost:
             url = xhost.Attribute('url')
@@ -433,7 +432,7 @@ class HostInfo:
                     self.readHostXml(xalthost)
                     return
                 xalthost = xalthost.NextSiblingElement('alt_host')
-            
+
             xhost = xhost.NextSiblingElement('host')
 
     def __findHostXmlForHostDir(self, xcontents):
@@ -442,7 +441,7 @@ class HostInfo:
         contents.xml from.  This is used when reading a contents.xml
         file found on disk, as opposed to downloading it from a
         site. """
-        
+
         xhost = xcontents.FirstChildElement('host')
         while xhost:
             url = xhost.Attribute('url')
@@ -463,7 +462,7 @@ class HostInfo:
                     self.readHostXml(xalthost)
                     return
                 xalthost = xalthost.NextSiblingElement('alt_host')
-            
+
             xhost = xhost.NextSiblingElement('host')
 
     def readHostXml(self, xhost):
@@ -487,7 +486,7 @@ class HostInfo:
                 self.downloadUrlPrefix += '/'
         else:
             self.downloadUrlPrefix = self.hostUrlPrefix
-            
+
         xmirror = xhost.FirstChildElement('mirror')
         while xmirror:
             url = xmirror.Attribute('url')
@@ -611,7 +610,7 @@ class HostInfo:
         the list of packages that were NOT found. """
 
         packages = packages[:]
-        
+
         for key, platforms in self.packages.items():
             for platform, package in platforms.items():
                 if package in packages:

+ 2 - 2
direct/src/p3d/InstalledHostData.py

@@ -1,11 +1,11 @@
-from pandac.PandaModules import URLSpec
+from panda3d.core import URLSpec
 
 class InstalledHostData:
     """ A list of instances of this class is returned by
     AppRunner.scanInstalledPackages().  Each of these corresponds to a
     particular host that has provided packages that have been
     installed on the local client. """
-    
+
     def __init__(self, host, dirnode):
         self.host = host
         self.pathname = dirnode.pathname

+ 55 - 56
direct/src/p3d/PackageInfo.py

@@ -1,6 +1,5 @@
-from pandac.PandaModules import Filename, URLSpec, DocumentSpec, Ramfile, Multifile, Decompressor, EUOk, EUSuccess, VirtualFileSystem, Thread, getModelPath, ExecutionEnvironment, PStatCollector, TiXmlDocument, TiXmlDeclaration, TiXmlElement
-from pandac import PandaModules
-from libpandaexpress import ConfigVariableInt
+from panda3d.core import Filename, URLSpec, DocumentSpec, Ramfile, Multifile, Decompressor, EUOk, EUSuccess, VirtualFileSystem, Thread, getModelPath, ExecutionEnvironment, PStatCollector, TiXmlDocument, TiXmlDeclaration, TiXmlElement
+import panda3d.core as core
 from direct.p3d.FileSpec import FileSpec
 from direct.p3d.ScanDirectoryNode import ScanDirectoryNode
 from direct.showbase import VFSImporter
@@ -55,7 +54,7 @@ class PackageInfo:
             tokens.  This function defines a new generator that yields
             each of those tokens, but wraps each call into the nested
             generator within a pair of start/stop collector calls. """
-            
+
             self.pStatCol.start()
             for token in self.__funcPtr(self):
                 self.pStatCol.stop()
@@ -76,7 +75,7 @@ class PackageInfo:
             if self.bytesNeeded == 0:
                 return 1
             return min(float(self.bytesDone) / float(self.bytesNeeded), 1)
-    
+
     def __init__(self, host, packageName, packageVersion, platform = None,
                  solo = False, asMirror = False, perPlatform = False):
         self.host = host
@@ -94,7 +93,7 @@ class PackageInfo:
         # This will be filled in when the host's contents.xml file is
         # read.
         self.packageDir = None
-            
+
         # These will be filled in by HostInfo when the package is read
         # from contents.xml.
         self.descFile = None
@@ -110,11 +109,11 @@ class PackageInfo:
         self.extracts = []
         self.requires = []
         self.installPlans = None
- 
+
         # This is updated during downloadPackage().  It is in the
         # range 0..1.
         self.downloadProgress = 0
-        
+
         # This is set true when the package file has been fully
         # downloaded and unpacked.
         self.hasPackage = False
@@ -133,12 +132,12 @@ class PackageInfo:
         This may not be known until the host's contents.xml file has
         been downloaded, which informs us of the host's own install
         directory. """
-        
+
         if not self.packageDir:
             if not self.host.hasContentsFile:
                 if not self.host.readContentsFile():
                     self.host.downloadContentsFile(self.http)
-            
+
             # Derive the packageDir from the hostDir.
             self.packageDir = Filename(self.host.hostDir, self.packageName)
             if self.packageVersion:
@@ -159,7 +158,7 @@ class PackageInfo:
                 # plugin--and we therefore shouldn't include the
                 # platform in the directory hierarchy.
                 includePlatform = False
-                
+
             if includePlatform and self.platform:
                 self.packageDir = Filename(self.packageDir, self.platform)
 
@@ -176,7 +175,7 @@ class PackageInfo:
         # Return the size of plan A, assuming it will work.
         plan = self.installPlans[0]
         size = sum([step.getEffort() for step in plan])
-        
+
         return size
 
     def getPrevDownloadedEffort(self):
@@ -209,13 +208,13 @@ class PackageInfo:
             name += ' rev %s' % (self.patchVersion)
 
         return name
-        
+
 
     def setupFilenames(self):
         """ This is called by the HostInfo when the package is read
         from contents.xml, to set up the internal filenames and such
         that rely on some of the information from contents.xml. """
-        
+
         dirname, basename = self.descFile.filename.rsplit('/', 1)
         self.descFileDirname = dirname
         self.descFileBasename = basename
@@ -264,7 +263,7 @@ class PackageInfo:
             Thread.considerYield()
 
         return (token == self.stepComplete)
-    
+
     def downloadDescFileGenerator(self, http):
         """ A generator function that implements downloadDescFile()
         one piece at a time.  It yields one of stepComplete,
@@ -343,9 +342,9 @@ class PackageInfo:
 
         filename = Filename(self.getPackageDir(), self.descFileBasename)
 
-        if not hasattr(PandaModules, 'TiXmlDocument'):
+        if not hasattr(core, 'TiXmlDocument'):
             return False
-        doc = PandaModules.TiXmlDocument(filename.toOsSpecific())
+        doc = core.TiXmlDocument(filename.toOsSpecific())
         if not doc.LoadFile():
             return False
 
@@ -432,7 +431,7 @@ class PackageInfo:
         pc.start()
 
         self.hasPackage = False
-        
+
         if self.host.appRunner and self.host.appRunner.verifyContents == self.host.appRunner.P3DVCNever:
             # We're not allowed to download anything.
             self.installPlans = []
@@ -447,12 +446,12 @@ class PackageInfo:
             # archive.
             downloadSize = self.compressedArchive.size
             func = lambda step, fileSpec = self.compressedArchive: self.__downloadFile(step, fileSpec, allowPartial = True)
-            
+
             step = self.InstallStep(func, downloadSize, self.downloadFactor, 'download')
             installPlan = [step]
             self.installPlans = [installPlan]
             pc.stop()
-            return 
+            return
 
         # The normal download process.  Determine what we will need to
         # download, and build a plan (or two) to download it all.
@@ -520,9 +519,9 @@ class PackageInfo:
             # plan B as the only plan.
             self.installPlans = [planB]
 
-        # In case of unexpected failures on the internet, we will retry 
+        # In case of unexpected failures on the internet, we will retry
         # the full download instead of just giving up.
-        for retry in range(ConfigVariableInt('package-full-dl-retries', 1)):
+        for retry in range(core.ConfigVariableInt('package-full-dl-retries', 1)):
             self.installPlans.append(planB[:])
 
         pc.stop()
@@ -530,7 +529,7 @@ class PackageInfo:
     def __scanDirectoryRecursively(self, dirname):
         """ Generates a list of Filename objects: all of the files
         (not directories) within and below the indicated dirname. """
-        
+
         contents = []
         for dirpath, dirnames, filenames in os.walk(dirname.toOsSpecific()):
             dirpath = Filename.fromOsSpecific(dirpath)
@@ -560,7 +559,7 @@ class PackageInfo:
 
         # Get a list of all of the files in the directory, so we can
         # remove files that don't belong.
-        contents = self.__scanDirectoryRecursively(self.getPackageDir()) 
+        contents = self.__scanDirectoryRecursively(self.getPackageDir())
         self.__removeFileFromList(contents, self.descFileBasename)
         self.__removeFileFromList(contents, self.compressedArchive.filename)
         self.__removeFileFromList(contents, self.UsageBasename)
@@ -582,7 +581,7 @@ class PackageInfo:
 
         if self.asMirror:
             return self.compressedArchive.quickVerify(self.getPackageDir(), notify = self.notify)
-            
+
         allExtractsOk = True
         if not self.uncompressedArchive.quickVerify(self.getPackageDir(), notify = self.notify):
             self.notify.debug("File is incorrect: %s" % (self.uncompressedArchive.filename))
@@ -593,7 +592,7 @@ class PackageInfo:
             # shouldn't be a compressed archive file here.
             pathname = Filename(self.getPackageDir(), self.compressedArchive.filename)
             pathname.unlink()
-            
+
             for file in self.extracts:
                 if not file.quickVerify(self.getPackageDir(), notify = self.notify):
                     self.notify.debug("File is incorrect: %s" % (file.filename))
@@ -614,7 +613,7 @@ class PackageInfo:
 
         size = self.totalPlanCompleted + self.currentStepEffort * step.getProgress()
         self.downloadProgress = min(float(size) / float(self.totalPlanSize), 1)
-    
+
     def downloadPackage(self, http):
         """ Downloads the package file, synchronously, then
         uncompresses and unpacks it.  Returns true on success, false
@@ -630,7 +629,7 @@ class PackageInfo:
             Thread.considerYield()
 
         return (token == self.stepComplete)
-    
+
     def downloadPackageGenerator(self, http):
         """ A generator function that implements downloadPackage() one
         piece at a time.  It yields one of stepComplete, stepFailed,
@@ -655,7 +654,7 @@ class PackageInfo:
                 yield token
             else:
                 break
-            
+
         while token == self.restartDownload:
             # Try again.
             for token in self.downloadDescFileGenerator(http):
@@ -675,7 +674,7 @@ class PackageInfo:
 
         assert token == self.stepComplete
         yield self.stepComplete; return
-            
+
 
     def __followInstallPlans(self):
         """ Performs all of the steps in self.installPlans.  Yields
@@ -701,16 +700,16 @@ class PackageInfo:
                         yield token
                     else:
                         break
-                    
+
                 if token == self.restartDownload:
                     yield token
                 if token == self.stepFailed:
                     planFailed = True
                     break
                 assert token == self.stepComplete
-                
+
                 self.totalPlanCompleted += self.currentStepEffort
-                
+
             if not planFailed:
                 # Successfully downloaded!
                 yield self.stepComplete; return
@@ -754,7 +753,7 @@ class PackageInfo:
     def __downloadFile(self, step, fileSpec, urlbase = None, filename = None,
                        allowPartial = False):
         """ Downloads the indicated file from the host into
-        packageDir.  Yields one of stepComplete, stepFailed, 
+        packageDir.  Yields one of stepComplete, stepFailed,
         restartDownload, or stepContinue. """
 
         if self.host.appRunner and self.host.appRunner.verifyContents == self.host.appRunner.P3DVCNever:
@@ -806,7 +805,7 @@ class PackageInfo:
                 url += '?' + str(int(time.time()))
                 request = DocumentSpec(url)
                 request.setCacheControl(DocumentSpec.CCNoCache)
-             
+
             self.notify.info("%s downloading %s" % (self.packageName, url))
 
             if not filename:
@@ -839,7 +838,7 @@ class PackageInfo:
                 targetPathname.makeDir()
                 targetPathname.unlink()
                 channel.beginGetDocument(request)
-                
+
             channel.downloadToFile(targetPathname)
             while channel.run():
                 if step:
@@ -849,7 +848,7 @@ class PackageInfo:
                         # it's the wrong file.
                         self.notify.warning("Got more data than expected for download %s" % (url))
                         break
-                    
+
                     self.__updateStepProgress(step)
 
                 if taskMgr.destroyed:
@@ -857,9 +856,9 @@ class PackageInfo:
                     # be shutting down.  Get out of here.
                     self.notify.warning("Task Manager destroyed, aborting %s" % (url))
                     yield self.stepFailed; return
-                    
+
                 yield self.stepContinue
-                
+
             if step:
                 step.bytesDone = channel.getBytesDownloaded() + channel.getFirstByteDelivered()
                 self.__updateStepProgress(step)
@@ -897,7 +896,7 @@ class PackageInfo:
     def __applyPatch(self, step, patchfile):
         """ Applies the indicated patching in-place to the current
         uncompressed archive.  The patchfile is removed after the
-        operation.  Yields one of stepComplete, stepFailed, 
+        operation.  Yields one of stepComplete, stepFailed,
         restartDownload, or stepContinue. """
 
         self.updated = True
@@ -907,7 +906,7 @@ class PackageInfo:
         result = Filename.temporary('', 'patch_')
         self.notify.info("Patching %s with %s" % (origPathname, patchPathname))
 
-        p = PandaModules.Patchfile()  # The C++ class
+        p = core.Patchfile()  # The C++ class
 
         ret = p.initiate(patchPathname, origPathname, result)
         if ret == EUSuccess:
@@ -925,7 +924,7 @@ class PackageInfo:
             ret = p.run()
         del p
         patchPathname.unlink()
-        
+
         if ret < 0:
             self.notify.warning("Patching of %s failed." % (origPathname))
             result.unlink()
@@ -934,12 +933,12 @@ class PackageInfo:
         if not result.renameTo(origPathname):
             self.notify.warning("Couldn't rename %s to %s" % (result, origPathname))
             yield self.stepFailed; return
-            
+
         yield self.stepComplete; return
 
     def __uncompressArchive(self, step):
         """ Turns the compressed archive into the uncompressed
-        archive.  Yields one of stepComplete, stepFailed, 
+        archive.  Yields one of stepComplete, stepFailed,
         restartDownload, or stepContinue. """
 
         if self.host.appRunner and self.host.appRunner.verifyContents == self.host.appRunner.P3DVCNever:
@@ -970,7 +969,7 @@ class PackageInfo:
 
         if result != EUSuccess:
             yield self.stepFailed; return
-            
+
         step.bytesDone = totalBytes
         self.__updateStepProgress(step)
 
@@ -985,10 +984,10 @@ class PackageInfo:
         # Now we can safely remove the compressed archive.
         sourcePathname.unlink()
         yield self.stepComplete; return
-    
+
     def __unpackArchive(self, step):
         """ Unpacks any files in the archive that want to be unpacked
-        to disk.  Yields one of stepComplete, stepFailed, 
+        to disk.  Yields one of stepComplete, stepFailed,
         restartDownload, or stepContinue. """
 
         if not self.extracts:
@@ -1008,7 +1007,7 @@ class PackageInfo:
         if not mf.openRead(mfPathname):
             self.notify.warning("Couldn't open %s" % (mfPathname))
             yield self.stepFailed; return
-        
+
         allExtractsOk = True
         step.bytesDone = 0
         for file in self.extracts:
@@ -1025,7 +1024,7 @@ class PackageInfo:
                 self.notify.warning("Couldn't extract: %s" % (file.filename))
                 allExtractsOk = False
                 continue
-            
+
             if not file.quickVerify(self.getPackageDir(), notify = self.notify):
                 self.notify.warning("After extracting, still incorrect: %s" % (file.filename))
                 allExtractsOk = False
@@ -1157,7 +1156,7 @@ class PackageInfo:
         """ Marks the package as having been used.  This is normally
         called automatically by installPackage(). """
 
-        if not hasattr(PandaModules, 'TiXmlDocument'):
+        if not hasattr(core, 'TiXmlDocument'):
             return
 
         if self.host.appRunner and self.host.appRunner.verifyContents == self.host.appRunner.P3DVCNever:
@@ -1174,14 +1173,14 @@ class PackageInfo:
         if not doc.LoadFile():
             decl = TiXmlDeclaration("1.0", "utf-8", "")
             doc.InsertEndChild(decl)
-            
+
         xusage = doc.FirstChildElement('usage')
         if not xusage:
             doc.InsertEndChild(TiXmlElement('usage'))
             xusage = doc.FirstChildElement('usage')
 
         now = int(time.time())
-        
+
         count = xusage.Attribute('count_app')
         try:
             count = int(count or '')
@@ -1214,22 +1213,22 @@ class PackageInfo:
         tfile = Filename.temporary(self.getPackageDir().cStr(), '.xml')
         if doc.SaveFile(tfile.toOsSpecific()):
             tfile.renameTo(filename)
-        
+
     def getUsage(self):
         """ Returns the xusage element that is read from the usage.xml
         file, or None if there is no usage.xml file. """
 
-        if not hasattr(PandaModules, 'TiXmlDocument'):
+        if not hasattr(core, 'TiXmlDocument'):
             return None
 
         filename = Filename(self.getPackageDir(), self.UsageBasename)
         doc = TiXmlDocument(filename.toOsSpecific())
         if not doc.LoadFile():
             return None
-            
+
         xusage = doc.FirstChildElement('usage')
         if not xusage:
             return None
 
         return copy.copy(xusage)
-    
+

+ 19 - 19
direct/src/p3d/PackageInstaller.py

@@ -3,7 +3,7 @@ from direct.stdpy.threading import Lock, RLock
 from direct.showbase.MessengerGlobal import messenger
 from direct.task.TaskManagerGlobal import taskMgr
 from direct.p3d.PackageInfo import PackageInfo
-from pandac.PandaModules import TPLow, PStatCollector
+from panda3d.core import TPLow, PStatCollector
 from direct.directnotify.DirectNotifyGlobal import directNotify
 
 class PackageInstaller(DirectObject):
@@ -33,7 +33,7 @@ class PackageInstaller(DirectObject):
     S_ready = 1      # donePackages() has been called
     S_started = 2    # download has started
     S_done = 3       # download is over
-    
+
     class PendingPackage:
         """ This class describes a package added to the installer for
         download. """
@@ -121,12 +121,12 @@ class PackageInstaller(DirectObject):
                 self.prevDownloadedEffort = self.package.getPrevDownloadedEffort()
 
             return True
-            
+
 
         def getDescFile(self, http):
             """ Synchronously downloads the desc files required for
             the package. """
-            
+
             if not self.host.downloadContentsFile(http):
                 return False
 
@@ -156,10 +156,10 @@ class PackageInstaller(DirectObject):
             PackageInstaller.nextUniqueId += 1
         finally:
             self.globalLock.release()
-        
+
         self.appRunner = appRunner
         self.taskChain = taskChain
-        
+
         # If we're to be running on an asynchronous task chain, and
         # the task chain hasn't yet been set up already, create the
         # default parameters now.
@@ -180,7 +180,7 @@ class PackageInstaller(DirectObject):
         # A list of packages that are waiting for their desc files.
         self.needsDescFile = []
         self.descFileTask = None
-        
+
         # A list of packages that are waiting to be downloaded and
         # installed.
         self.needsDownload = []
@@ -198,7 +198,7 @@ class PackageInstaller(DirectObject):
         # This task is spawned on the default task chain, to update
         # the status during the download.
         self.progressTask = None
-        
+
         self.accept('PackageInstaller-%s-allHaveDesc' % self.uniqueId,
                     self.__allHaveDesc)
         self.accept('PackageInstaller-%s-packageStarted' % self.uniqueId,
@@ -231,7 +231,7 @@ class PackageInstaller(DirectObject):
             self.progressTask = None
 
         self.ignoreAll()
-        
+
     def addPackage(self, packageName, version = None, hostUrl = None):
         """ Adds the named package to the list of packages to be
         downloaded.  Call donePackages() to finish the list. """
@@ -256,7 +256,7 @@ class PackageInstaller(DirectObject):
         if pp in self.packages:
             # Already added.
             return
-        
+
         self.packages.append(pp)
 
         # We always add the package to needsDescFile, even if we
@@ -323,7 +323,7 @@ class PackageInstaller(DirectObject):
         (beginning) to 1 (complete). """
 
         self.notify.debug("packageProgress: %s %s" % (package.packageName, progress))
-        
+
     def downloadProgress(self, overallProgress):
         """ This callback is made repeatedly between downloadStarted()
         and downloadFinished() to update the current progress through
@@ -384,7 +384,7 @@ class PackageInstaller(DirectObject):
         """ This method is called internally when all of the pending
         packages have their desc info. """
         working = True
-        
+
         self.packageLock.acquire()
         try:
             if self.state == self.S_ready:
@@ -489,7 +489,7 @@ class PackageInstaller(DirectObject):
         it extracts one package from self.needsDescFile and downloads
         its desc file.  On success, it adds the package to
         self.needsDownload. """
-        
+
         self.packageLock.acquire()
         try:
             # If we've finished all of the packages that need desc
@@ -515,7 +515,7 @@ class PackageInstaller(DirectObject):
         # This package is now ready to be downloaded.  We always add
         # it to needsDownload, even if it's already downloaded, to
         # guarantee ordering of packages.
-        
+
         self.packageLock.acquire()
         try:
             # Also add any packages required by this one.
@@ -527,7 +527,7 @@ class PackageInstaller(DirectObject):
             self.packageLock.release()
 
         return task.cont
-        
+
     def __downloadPackageTask(self, task):
 
         """ This task runs on the aysynchronous task chain; each pass,
@@ -543,7 +543,7 @@ class PackageInstaller(DirectObject):
                     self.packageLock.release()
                     yield task.done; return
 
-                assert self.state == self.S_started        
+                assert self.state == self.S_started
                 pp = self.needsDownload[0]
                 del self.needsDownload[0]
             except:
@@ -578,7 +578,7 @@ class PackageInstaller(DirectObject):
 
             # Continue the loop without yielding, so we pick up the
             # next package within this same frame.
-        
+
     def __donePackage(self, pp, success):
         """ Marks the indicated package as done, either successfully
         or otherwise. """
@@ -630,9 +630,9 @@ class PackageInstaller(DirectObject):
             else:
                 progress = float(currentDownloadSize) / float(downloadEffort)
             self.downloadProgress(progress)
-            
+
         finally:
             self.callbackLock.release()
 
         return task.cont
-    
+

+ 11 - 11
direct/src/p3d/PackageMerger.py

@@ -1,7 +1,7 @@
 from direct.p3d.FileSpec import FileSpec
 from direct.p3d.SeqValue import SeqValue
 from direct.directnotify.DirectNotifyGlobal import *
-from pandac.PandaModules import *
+from panda3d.core import *
 import copy
 import shutil
 import os
@@ -18,11 +18,11 @@ class PackageMerger:
     always the most current version of the file. """
 
     notify = directNotify.newCategory("PackageMerger")
- 
+
     class PackageEntry:
         """ This corresponds to a <package> entry in the contents.xml
         file. """
-        
+
         def __init__(self, xpackage, sourceDir):
             self.sourceDir = sourceDir
             self.loadXml(xpackage)
@@ -48,7 +48,7 @@ class PackageMerger:
             self.descFile.loadXml(xpackage)
 
             self.validatePackageContents()
-            
+
             self.descFile.quickVerify(packageDir = self.sourceDir, notify = PackageMerger.notify, correctSelf = True)
 
             self.packageSeq = SeqValue()
@@ -84,7 +84,7 @@ class PackageMerger:
                 ximport = TiXmlElement('import')
                 self.importDescFile.storeXml(ximport)
                 xpackage.InsertEndChild(ximport)
-            
+
             return xpackage
 
         def validatePackageContents(self):
@@ -170,7 +170,7 @@ class PackageMerger:
             xhost = xcontents.FirstChildElement('host')
             if xhost:
                 self.xhost = xhost.Clone()
-                
+
             xpackage = xcontents.FirstChildElement('package')
             while xpackage:
                 pe = self.PackageEntry(xpackage, sourceDir)
@@ -183,7 +183,7 @@ class PackageMerger:
                     if not other or pe.isNewer(other):
                         # Store this package in the resulting output.
                         self.contents[pe.getKey()] = pe
-                    
+
                 xpackage = xpackage.NextSiblingElement('package')
 
         self.contentsDoc = doc
@@ -247,7 +247,7 @@ class PackageMerger:
             else:
                 # Both the source file and target file are
                 # directories.
-                
+
                 # We have to clean out the target directory first.
                 # Instead of using shutil.rmtree(), remove the files in
                 # this directory one at a time, so we don't inadvertently
@@ -282,10 +282,10 @@ class PackageMerger:
         the current pool.  If packageNames is not None, it is a list
         of package names that we wish to include from the source;
         packages not named in this list will be unchanged. """
-        
+
         if not self.__readContentsFile(sourceDir, packageNames):
             message = "Couldn't read %s" % (sourceDir)
-            raise PackageMergerError, message            
+            raise PackageMergerError, message
 
     def close(self):
         """ Finalizes the results of all of the previous calls to
@@ -302,4 +302,4 @@ class PackageMerger:
 
         self.contentsSeq += 1
         self.__writeContentsFile()
-        
+

+ 144 - 41
direct/src/p3d/Packager.py

@@ -15,6 +15,7 @@ import types
 import getpass
 import platform
 import struct
+import subprocess
 from direct.p3d.FileSpec import FileSpec
 from direct.p3d.SeqValue import SeqValue
 from direct.showbase import Loader
@@ -58,7 +59,7 @@ class Packager:
             self.required = required
 
             if not self.newName:
-                self.newName = self.filename.cStr()
+                self.newName = str(self.filename)
 
             ext = Filename(self.newName).getExtension()
             if ext == 'pz':
@@ -66,7 +67,7 @@ class Packager:
                 # within the Multifile without it.
                 filename = Filename(self.newName)
                 filename.setExtension('')
-                self.newName = filename.cStr()
+                self.newName = str(filename)
                 ext = Filename(self.newName).getExtension()
                 if self.compress is None:
                     self.compress = True
@@ -80,8 +81,8 @@ class Packager:
 
             if self.executable and self.dependencyDir is None:
                 # By default, install executable dependencies in the
-                # same directory with the executable itself.
-                self.dependencyDir = Filename(self.newName).getDirname()
+                # root directory, which is the one that's added to PATH.
+                self.dependencyDir = ''
 
             if self.extract is None:
                 self.extract = self.executable or (ext in packager.extractExtensions)
@@ -93,13 +94,13 @@ class Packager:
 
             if self.executable:
                 # Look up the filename along the system PATH, if necessary.
-                if not self.filename.resolveFilename(packager.executablePath):
+                if not packager.resolveLibrary(self.filename):
                     # If it wasn't found, try looking it up under its
                     # basename only.  Sometimes a Mac user will copy
                     # the library file out of a framework and put that
                     # along the PATH, instead of the framework itself.
                     basename = Filename(self.filename.getBasename())
-                    if basename.resolveFilename(packager.executablePath):
+                    if packager.resolveLibrary(basename):
                         self.filename = basename
 
             if ext in packager.textExtensions and not self.executable:
@@ -156,7 +157,7 @@ class Packager:
             if not self.localOnly:
                 filename = Filename(filename)
                 filename.makeCanonical()
-            self.glob = GlobPattern(filename.cStr())
+            self.glob = GlobPattern(str(filename))
 
             if self.packager.platform.startswith('win'):
                 self.glob.setCaseSensitive(False)
@@ -167,7 +168,7 @@ class Packager:
             if self.localOnly:
                 return self.glob.matches(filename.getBasename())
             else:
-                return self.glob.matches(filename.cStr())
+                return self.glob.matches(str(filename))
 
     class PackageEntry:
         """ This corresponds to a <package> entry in the contents.xml
@@ -586,9 +587,9 @@ class Packager:
                     # (i.e. missing) modules.
                     continue
 
-                if newName == '__main__':
-                    # Ignore this special case.
-                    continue
+                #if newName == '__main__':
+                #    # Ignore this special case.
+                #    continue
 
                 self.moduleNames[newName] = mdef
 
@@ -937,7 +938,7 @@ class Packager:
                         # means we should include the manifest
                         # file itself in the package.
                         newName = Filename(file.dependencyDir, mfile.getBasename())
-                        self.addFile(mfile, newName = newName.cStr(),
+                        self.addFile(mfile, newName = str(newName),
                                      explicit = False, executable = True)
 
                     if afilenames is None and out != 31:
@@ -957,7 +958,7 @@ class Packager:
                     filename.makeTrueCase()
 
                     newName = Filename(file.dependencyDir, filename.getBasename())
-                    self.addFile(filename, newName = newName.cStr(),
+                    self.addFile(filename, newName = str(newName),
                                  explicit = False, executable = True)
 
         def __parseDependenciesWindows(self, tempFile):
@@ -1172,7 +1173,7 @@ class Packager:
                             # It's a fully-specified filename; look
                             # for it under the system root first.
                             if self.packager.systemRoot:
-                                f2 = Filename(self.packager.systemRoot + filename.cStr())
+                                f2 = Filename(self.packager.systemRoot, filename)
                                 if f2.exists():
                                     filename = f2
 
@@ -1181,7 +1182,7 @@ class Packager:
                         continue
 
                     newName = Filename(file.dependencyDir, filename.getBasename())
-                    self.addFile(filename, newName = newName.cStr(),
+                    self.addFile(filename, newName = str(newName),
                                  explicit = False, executable = True)
 
         def __parseDependenciesOSX(self, tempFile):
@@ -1346,6 +1347,7 @@ class Packager:
 
                 # If that failed, perhaps ldd will help us.
                 if filenames is None:
+                    self.notify.warning("Reading ELF library %s failed, using ldd instead" % (file.filename))
                     tempFile = Filename.temporary('', 'p3d_', '.txt')
                     command = 'ldd "%s" >"%s"' % (
                         file.filename.toOsSpecific(),
@@ -1379,7 +1381,7 @@ class Packager:
                     filename.setBinary()
 
                     newName = Filename(file.dependencyDir, filename.getBasename())
-                    self.addFile(filename, newName = newName.cStr(),
+                    self.addFile(filename, newName = str(newName),
                                  explicit = False, executable = True)
 
         def __parseDependenciesPosix(self, tempFile):
@@ -1470,7 +1472,7 @@ class Packager:
             # compatible with older versions of the core API that
             # didn't understand the SF_text flag.
             filename.setBinary()
-            
+
             doc.SaveFile(filename.toOsSpecific())
 
             # It's important not to compress this file: the core API
@@ -1772,8 +1774,6 @@ class Packager:
 
             return xspec
 
-
-
         def addPyFile(self, file):
             """ Adds the indicated python file, identified by filename
             instead of by module name, to the package. """
@@ -1793,6 +1793,18 @@ class Packager:
                 # deal with it again.
                 return
 
+            # Make sure that it is actually in a package.
+            parentName = moduleName
+            while '.' in parentName:
+                parentName = parentName.rsplit('.', 1)[0]
+                if parentName not in self.freezer.modules:
+                    message = 'Cannot add Python file %s; not in package' % (file.newName)
+                    if file.required or file.explicit:
+                        raise StandardError, message
+                    else:
+                        self.notify.warning(message)
+                    return
+
             self.freezer.addModule(moduleName, filename = file.filename)
 
         def addEggFile(self, file):
@@ -1803,7 +1815,7 @@ class Packager:
 
             bamName = Filename(file.newName)
             bamName.setExtension('bam')
-            self.addNode(np.node(), file.filename, bamName.cStr())
+            self.addNode(np.node(), file.filename, str(bamName))
 
         def addBamFile(self, file):
             # Load the bam file so we can massage its textures.
@@ -2207,6 +2219,9 @@ class Packager:
         cvar = ConfigVariableSearchPath('pdef-path')
         self.installSearch = list(map(Filename, cvar.getDirectories()))
 
+        # This is where we cache the location of libraries.
+        self.libraryCache = {}
+
         # The system PATH, for searching dll's and exe's.
         self.executablePath = DSearchPath()
 
@@ -2219,22 +2234,36 @@ class Packager:
         # Now add the actual system search path.
         if self.platform.startswith('win'):
             self.addWindowsSearchPath(self.executablePath, "PATH")
-        elif self.platform.startswith('osx'):
-            self.addPosixSearchPath(self.executablePath, "DYLD_LIBRARY_PATH")
-            self.addPosixSearchPath(self.executablePath, "LD_LIBRARY_PATH")
-            self.addPosixSearchPath(self.executablePath, "PATH")
-            self.executablePath.appendDirectory('/lib')
-            self.executablePath.appendDirectory('/usr/lib')
-            self.executablePath.appendDirectory('/usr/local/lib')
+
         else:
+            if self.platform.startswith('osx'):
+                self.addPosixSearchPath(self.executablePath, "DYLD_LIBRARY_PATH")
+
             self.addPosixSearchPath(self.executablePath, "LD_LIBRARY_PATH")
             self.addPosixSearchPath(self.executablePath, "PATH")
-            self.executablePath.appendDirectory('/lib')
-            self.executablePath.appendDirectory('/usr/lib')
-            self.executablePath.appendDirectory('/usr/local/lib')
 
-        import platform
-        if platform.uname()[1]=="pcbsd":
+            if self.platform.startswith('linux'):
+                # It used to be okay to just add some common paths on Linux.
+                # But nowadays, each distribution has their own convention for
+                # where they put their libraries.  Instead, we query the ldconfig
+                # cache, which contains the location of all libraries.
+
+                if not self.loadLdconfigCache():
+                    # Ugh, failure.  All that remains is to guess.  This should
+                    # work for the most common Debian configurations.
+                    multiarchDir = "/lib/%s-linux-gnu" % (os.uname()[4])
+                    if os.path.isdir(multiarchDir):
+                        self.executablePath.appendDirectory(multiarchDir)
+                    if os.path.isdir("/usr/" + multiarchDir):
+                        self.executablePath.appendDirectory("/usr/" + multiarchDir)
+
+            else:
+                # FreeBSD, or some other system that still makes sense.
+                self.executablePath.appendDirectory('/lib')
+                self.executablePath.appendDirectory('/usr/lib')
+                self.executablePath.appendDirectory('/usr/local/lib')
+
+        if os.uname()[1] == "pcbsd":
             self.executablePath.appendDirectory('/usr/PCBSD/local/lib')
 
         # Set this flag true to automatically add allow_python_dev to
@@ -2388,6 +2417,7 @@ class Packager:
             GlobPattern('libpthread.so*'),
             GlobPattern('libthr.so*'),
             GlobPattern('ld-linux.so*'),
+            GlobPattern('ld-linux-*.so*'),
             ]
 
         # A Loader for loading models.
@@ -2405,6 +2435,60 @@ class Packager:
         # file.
         self.contents = {}
 
+    def loadLdconfigCache(self):
+        """ On GNU/Linux, runs ldconfig -p to find out where all the
+        libraries on the system are located.  Assumes that the platform
+        has already been set. """
+
+        if not os.path.isfile('/sbin/ldconfig'):
+            return False
+
+        handle = subprocess.Popen(['/sbin/ldconfig', '-p'], stdout=subprocess.PIPE)
+        out, err = handle.communicate()
+
+        if handle.returncode != 0:
+            self.notify.warning("/sbin/ldconfig -p returned code %d" %(handle.returncode))
+            return False
+
+        for line in out.splitlines():
+            if '=>' not in line:
+                continue
+
+            prefix, location = line.rsplit('=>', 1)
+            prefix = prefix.strip()
+            location = location.strip()
+
+            if not location or not prefix or ' ' not in prefix:
+                self.notify.warning("Ignoring malformed ldconfig -p line: " + line)
+                continue
+
+            lib, opts = prefix.split(' ', 1)
+            if ('x86-64' in opts) != self.platform.endswith('_amd64'):
+                # This entry isn't meant for our architecture.  I think
+                # x86-64 is the only platform where ldconfig supplies
+                # this extra arch string.
+                continue
+
+            self.libraryCache[lib] = Filename.fromOsSpecific(location)
+
+        return True
+
+    def resolveLibrary(self, filename):
+        """ Resolves the given shared library filename along the executable path,
+        or by cross-referencing it with the library cache. """
+
+        path = str(filename)
+
+        if path in self.libraryCache:
+            filename.setFullpath(self.libraryCache[path].getFullpath())
+            return True
+
+        if filename.resolveFilename(self.executablePath):
+            self.libraryCache[path] = Filename(filename)
+            return True
+
+        return False
+
     def setPlatform(self, platform = None):
         """ Sets the platform that this Packager will compute for.  On
         OSX, this can be used to specify the particular architecture
@@ -3143,9 +3227,17 @@ class Packager:
         for moduleName in args:
             self.currentPackage.freezer.excludeModule(moduleName)
 
+    def do_main(self, filename):
+        """ Includes the indicated file as __main__ module of the application.
+        Also updates mainModule to point to this module. """
+
+        self.addModule(['__main__'], '__main__', filename, required = True)
+        self.currentPackage.mainModule = ('__main__', '__main__')
+
     def do_mainModule(self, moduleName, newName = None, filename = None):
         """ Names the indicated module as the "main" module of the
-        application or exe. """
+        application or exe.  In most cases, you will want to use main()
+        instead. """
 
         if not self.currentPackage:
             raise OutsideOfPackageError
@@ -3162,7 +3254,7 @@ class Packager:
             newFilename = Filename('/'.join(moduleName.split('.')))
             newFilename.setExtension(filename.getExtension())
             self.currentPackage.addFile(
-                filename, newName = newFilename.cStr(),
+                filename, newName = str(newFilename),
                 explicit = True, extract = True, required = True)
 
         self.currentPackage.mainModule = (moduleName, newName)
@@ -3194,7 +3286,9 @@ class Packager:
         # Multifile, so this file can't itself be in the Multifile.
 
         # This requires a bit of care, because we only want to freeze
-        # VFSImporter.py, and not any other part of direct.
+        # VFSImporter.py, and not any other part of direct.  We do
+        # also want panda3d/__init__.py, though, since it would
+        # otherwise be part of the multifile.
         self.do_excludeModule('direct')
 
         # Import the actual VFSImporter module to get its filename on
@@ -3205,7 +3299,7 @@ class Packager:
         self.do_module('VFSImporter', filename = filename)
         self.do_freeze('_vfsimporter', compileToExe = False)
 
-        self.do_file('libpandaexpress.dll');
+        self.do_file('panda3d/core.pyd');
 
         # Now that we're done freezing, explicitly add 'direct' to
         # counteract the previous explicit excludeModule().
@@ -3438,13 +3532,13 @@ class Packager:
                     # build.
                     dllFilename = Filename(filename)
                     dllFilename.setExtension('so')
-                    dllFilename = Filename.dsoFilename(dllFilename.cStr())
+                    dllFilename = Filename.dsoFilename(str(dllFilename))
                     if dllFilename != filename:
                         thisFiles = glob.glob(filename.toOsSpecific())
                         if not thisFiles:
                             # We have to resolve this filename to
                             # determine if it's a _d or not.
-                            if dllFilename.resolveFilename(self.executablePath):
+                            if self.resolveLibrary(dllFilename):
                                 thisFiles = [dllFilename.toOsSpecific()]
                             else:
                                 thisFiles = [filename.toOsSpecific()]
@@ -3455,7 +3549,7 @@ class Packager:
 
         prefix = ''
         if newDir is not None:
-            prefix = Filename(newDir).cStr()
+            prefix = str(Filename(newDir))
             if prefix and prefix[-1] != '/':
                 prefix += '/'
 
@@ -3527,13 +3621,22 @@ class Packager:
         sys.path.append(dirname.toOsSpecific())
         self.__recurseDir(dirname, newDir, unprocessed = unprocessed)
 
-    def __recurseDir(self, filename, newName, unprocessed = None):
+    def __recurseDir(self, filename, newName, unprocessed = None, packageTree = None):
         dirList = vfs.scanDirectory(filename)
         if dirList:
             # It's a directory name.  Recurse.
             prefix = newName
             if prefix and prefix[-1] != '/':
                 prefix += '/'
+
+            # First check if this is a Python package tree.  If so, add it
+            # implicitly as a module.
+            for subfile in dirList:
+                filename = subfile.getFilename()
+                if filename.getBasename() == '__init__.py':
+                    moduleName = newName.replace("/", ".")
+                    self.addModule([moduleName], filename=filename)
+
             for subfile in dirList:
                 filename = subfile.getFilename()
                 self.__recurseDir(filename, prefix + filename.getBasename(),
@@ -3550,7 +3653,7 @@ class Packager:
                 # Strip off an implicit .pz extension.
                 newFilename = Filename(filename)
                 newFilename.setExtension('')
-                newFilename = Filename(newFilename.cStr())
+                newFilename = Filename(str(newFilename))
                 ext = newFilename.getExtension()
 
             if ext in self.knownExtensions:

+ 30 - 30
direct/src/p3d/PatchMaker.py

@@ -1,6 +1,6 @@
 from direct.p3d.FileSpec import FileSpec
 from direct.p3d.SeqValue import SeqValue
-from pandac.PandaModules import *
+from panda3d.core import *
 import copy
 
 class PatchMaker:
@@ -14,7 +14,7 @@ class PatchMaker:
         the package's "version" string; it also corresponds to the
         particular patch version, which increments independently of
         the "version". """
-        
+
         def __init__(self, packageName, platform, version, hostUrl, file):
             self.packageName = packageName
             self.platform = platform
@@ -84,7 +84,7 @@ class PatchMaker:
             apply in sequence, and the packageVersion object
             associated with each patch.  Returns (None, None, None) if
             there is no way to recreate this archive file.  """
-            
+
             if self.tempFile:
                 return (self.tempFile, self, [])
 
@@ -101,7 +101,7 @@ class PatchMaker:
                 # version of some package.
                 package = self.packageCurrent
                 return (Filename(package.packageDir, package.compressedFilename), self, [])
-            
+
             if self.packageBase:
                 # This PackageVersion instance represents the base
                 # (oldest) version of some package.
@@ -144,7 +144,7 @@ class PatchMaker:
                     # Failure trying to decompress the file.
                     return None
                 startFile = startPv.tempFile
-            
+
             if not plan:
                 # If plan is a zero-length list, we're already
                 # here--return startFile.  If plan is None, there's no
@@ -162,7 +162,7 @@ class PatchMaker:
                 if not result:
                     # Failure trying to re-create the file.
                     return None
-                
+
                 pv.tempFile = result
                 prevFile = result
 
@@ -194,10 +194,10 @@ class PatchMaker:
                     return patch.toPv
 
             return None
-        
+
     class Patchfile:
         """ A single patchfile for a package. """
-        
+
         def __init__(self, package):
             self.package = package
             self.packageName = package.packageName
@@ -233,7 +233,7 @@ class PatchMaker:
         def fromFile(self, packageDir, patchFilename, sourceFile, targetFile):
             """ Creates the data structures from an existing patchfile
             on disk. """
-            
+
             self.file = FileSpec()
             self.file.fromFile(packageDir, patchFilename)
             self.sourceFile = sourceFile
@@ -241,7 +241,7 @@ class PatchMaker:
 
         def loadXml(self, xpatch):
             """ Reads the data structures from an xml file. """
-            
+
             self.packageName = xpatch.Attribute('name') or self.packageName
             self.platform = xpatch.Attribute('platform') or self.platform
             self.version = xpatch.Attribute('version') or self.version
@@ -287,7 +287,7 @@ class PatchMaker:
     class Package:
         """ This is a particular package.  This contains all of the
         information needed to reconstruct the package's desc file. """
-        
+
         def __init__(self, packageDesc, patchMaker, xpackage = None):
             self.packageDir = Filename(patchMaker.installDir, packageDesc.getDirname())
             self.packageDesc = packageDesc
@@ -312,19 +312,19 @@ class PatchMaker:
         def getCurrentKey(self):
             """ Returns the key to locate the current version of this
             package. """
-            
+
             return (self.packageName, self.platform, self.version, self.hostUrl, self.currentFile)
 
         def getBaseKey(self):
             """ Returns the key to locate the "base" or oldest version
             of this package. """
-            
+
             return (self.packageName, self.platform, self.version, self.hostUrl, self.baseFile)
 
         def getTopKey(self):
             """ Returns the key to locate the "top" or newest version
             of this package. """
-            
+
             return (self.packageName, self.platform, self.version, self.hostUrl, self.topFile)
 
         def getGenericKey(self, fileSpec):
@@ -345,7 +345,7 @@ class PatchMaker:
             if not self.doc.LoadFile():
                 print "Couldn't read %s" % (packageDescFullpath)
                 return False
-            
+
             xpackage = self.doc.FirstChildElement('package')
             if not xpackage:
                 return False
@@ -358,7 +358,7 @@ class PatchMaker:
             # other hosts, which means we'll need to fill in a value
             # here for those hosts.
             self.hostUrl = None
-        
+
             self.currentFile = None
             self.baseFile = None
             self.topFile = None
@@ -388,7 +388,7 @@ class PatchMaker:
                 else:
                     # There's a new version this pass.  Update it.
                     self.anyChanges = True
-                
+
             else:
                 # If there isn't a top_version yet, we have to make
                 # one, by duplicating the currentFile.
@@ -516,7 +516,7 @@ class PatchMaker:
             xarchive = TiXmlElement('top_version')
             self.currentFile.storeXml(xarchive)
             xpackage.InsertEndChild(xarchive)
-            
+
             for patchfile in self.patches:
                 xpatch = patchfile.makeXml(self)
                 xpackage.InsertEndChild(xpatch)
@@ -571,7 +571,7 @@ class PatchMaker:
         patches for all packages; otherwise, it should be a list of
         package name strings, limiting the set of packages that are
         processed. """
-        
+
         if not self.readContentsFile():
             return False
         self.buildPatchChains()
@@ -587,7 +587,7 @@ class PatchMaker:
     def cleanup(self):
         """ Should be called on exit to remove temporary files and
         such created during processing. """
-        
+
         for pv in self.packageVersions.values():
             pv.cleanup()
 
@@ -596,11 +596,11 @@ class PatchMaker:
         constructs a patch chain from the version represented by
         fileSpec to the current version of this package, if possible.
         Returns the patch chain if successful, or None otherwise. """
-        
+
         package = self.readPackageDescFile(descFilename)
         if not package:
             return None
-        
+
         self.buildPatchChains()
         fromPv = self.getPackageVersion(package.getGenericKey(fileSpec))
         toPv = package.currentPv
@@ -619,7 +619,7 @@ class PatchMaker:
         package = self.Package(Filename(descFilename), self)
         if not package.readDescFile(doProcessing = False):
             return None
-        
+
         self.packages.append(package)
         return package
 
@@ -640,7 +640,7 @@ class PatchMaker:
             contentsSeq.loadXml(xcontents)
             contentsSeq += 1
             contentsSeq.storeXml(xcontents)
-            
+
             xpackage = xcontents.FirstChildElement('package')
             while xpackage:
                 solo = xpackage.Attribute('solo')
@@ -651,7 +651,7 @@ class PatchMaker:
                     package = self.Package(filename, self, xpackage)
                     package.readDescFile(doProcessing = True)
                     self.packages.append(package)
-                    
+
                 xpackage = xpackage.NextSiblingElement('package')
 
         self.contentsDoc = doc
@@ -685,7 +685,7 @@ class PatchMaker:
             pv = self.PackageVersion(*key)
             self.packageVersions[k] = pv
         return pv
-    
+
     def buildPatchChains(self):
         """ Builds up the chains of PackageVersions and the patchfiles
         that connect them. """
@@ -696,7 +696,7 @@ class PatchMaker:
             if not package.baseFile:
                 # This package doesn't have any versions yet.
                 continue
-            
+
             currentPv = self.getPackageVersion(package.getCurrentKey())
             package.currentPv = currentPv
             currentPv.packageCurrent = package
@@ -710,7 +710,7 @@ class PatchMaker:
             topPv = self.getPackageVersion(package.getTopKey())
             package.topPv = topPv
             topPv.packageTop = package
-            
+
             for patchfile in package.patches:
                 self.recordPatchfile(patchfile)
 
@@ -757,7 +757,7 @@ class PatchMaker:
         # What's the current version on the top of the tree?
         topPv = package.topPv
         currentPv = package.currentPv
-        
+
         if topPv != currentPv:
             # They're different, so build a new patch.
             filename = Filename(package.currentFile.filename + '.%s.patch' % (package.patchVersion))
@@ -786,7 +786,7 @@ class PatchMaker:
                            v1.file, v2.file)
         package.patches.append(patchfile)
         package.anyChanges = True
-        
+
         self.recordPatchfile(patchfile)
 
         return True

+ 6 - 6
direct/src/p3d/ScanDirectoryNode.py

@@ -1,9 +1,9 @@
-from pandac.PandaModules import VirtualFileSystem, VirtualFileMountSystem, Filename, TiXmlDocument
+from panda3d.core import VirtualFileSystem, VirtualFileMountSystem, Filename, TiXmlDocument
 vfs = VirtualFileSystem.getGlobalPtr()
 
 class ScanDirectoryNode:
     """ This class is used to scan a list of files on disk. """
-    
+
     def __init__(self, pathname, ignoreUsageXml = False):
         self.pathname = pathname
         self.filenames = []
@@ -38,7 +38,7 @@ class ScanDirectoryNode:
                 if not isinstance(vfile.getMount(), VirtualFileMountSystem):
                     # Not a real file; ignore it.
                     continue
-                
+
             if vfile.isDirectory():
                 # A nested directory.
                 subdir = ScanDirectoryNode(vfile.getFilename(), ignoreUsageXml = ignoreUsageXml)
@@ -49,7 +49,7 @@ class ScanDirectoryNode:
                 # A nested file.
                 self.filenames.append(vfile.getFilename())
                 self.fileSize += vfile.getFileSize()
-                
+
             else:
                 # Some other wacky file thing.
                 self.filenames.append(vfile.getFilename())
@@ -78,7 +78,7 @@ class ScanDirectoryNode:
                 self.nested.remove(subdir)
                 self.nestedSize -= subdir.getTotalSize()
                 return subdir
-            
+
             result = subdir.extractSubdir(pathname)
             if result:
                 self.nestedSize -= result.getTotalSize()
@@ -89,5 +89,5 @@ class ScanDirectoryNode:
                 return result
 
         return None
-    
+
 

+ 4 - 4
direct/src/p3d/coreapi.pdef

@@ -1,4 +1,4 @@
-from pandac.PandaModules import getModelPath, Filename, ConfigVariableFilename, DSearchPath, ExecutionEnvironment, PandaSystem
+from panda3d.core import getModelPath, Filename, ConfigVariableFilename, DSearchPath, ExecutionEnvironment, PandaSystem
 
 # This file defines a number of standard "packages" that correspond to
 # a Panda3D distribution.  These packages are built by passing this
@@ -57,7 +57,7 @@ class images(package):
             basename = '%s.jpg' % (name)
             filename = Filename(basename)
             found = filename.resolveFilename(search)
-            
+
         if found:
             # Add the image file to the package
             file(filename, newName = basename, extract = True)
@@ -91,7 +91,7 @@ class certlist(package):
     # ".pem" or ".crt" extension, and they should be added with the
     # extract = True flag so they will be extracted to disk.
     pass
-    
+
 
 class p3dcert(package):
     # This special application, used to pop up a dialog to prompt the
@@ -102,7 +102,7 @@ class p3dcert(package):
         # On Mac, we package up a P3DCert.app bundle.  This includes
         # specifications in the plist file to avoid creating a dock
         # icon and stuff.
-        
+
         # Find p3dcert.plist in the direct source tree.
         import direct
         plist = Filename(direct.__path__[0], 'plugin/p3dcert.plist')

+ 6 - 10
direct/src/p3d/packp3d.py

@@ -93,8 +93,8 @@ import os
 import getopt
 import glob
 import direct
-from direct.p3d import Packager 
-from pandac.PandaModules import *
+from direct.p3d import Packager
+from panda3d.core import *
 
 # Temp hack for debugging.
 #from direct.p3d.AppRunner import dummyAppRunner; dummyAppRunner()
@@ -113,7 +113,7 @@ def makePackedApp(args):
     configFlags = []
     requires = []
     allowPythonDev = False
-    
+
     for option, value in opts:
         if option == '-o':
             appFilename = Filename.fromOsSpecific(value)
@@ -183,11 +183,7 @@ def makePackedApp(args):
             main = os.path.split(main[0])[1]
 
     main = Filename.fromOsSpecific(main)
-    mainModule = Filename(main)
-    mainModule.setExtension('')
 
-    mainModule = mainModule.cStr().replace('/', '.')
-    
     packager.installDir = appDir
     packager.allowPythonDev = allowPythonDev
 
@@ -206,7 +202,7 @@ def makePackedApp(args):
         # panda3d.
         if 'panda3d' not in [t[0] for t in requires]:
             packager.do_require('panda3d')
-        
+
         for name, version, host in requires:
             packager.do_require(name, version = version, host = host)
 
@@ -214,10 +210,10 @@ def makePackedApp(args):
             packager.do_config(**dict(configFlags))
 
         packager.do_dir(root)
-        packager.do_mainModule(mainModule)
+        packager.do_main(main)
         packager.endPackage()
         packager.close()
-        
+
     except Packager.PackagerError:
         # Just print the error message and exit gracefully.
         inst = sys.exc_info()[1]

+ 26 - 2
direct/src/p3d/panda3d.pdef

@@ -1,4 +1,4 @@
-from pandac.PandaModules import Filename, PandaSystem, getModelPath
+from panda3d.core import Filename, PandaSystem, getModelPath
 
 # This file defines a number of standard "packages" that correspond to
 # a Panda3D distribution.  These packages are built by passing this
@@ -54,7 +54,11 @@ class panda3d(package):
            'direct.showutil.*',
            'direct.stdpy.*',
            'direct.task.*')
-    module('panda3d')
+
+    module('panda3d.core',
+           'panda3d.direct',
+           'panda3d.fx',
+           'panda3d.physics')
 
     # Include various standard Python encodings.  The rest is in morepy.
     module('encodings', 'encodings.aliases', 'encodings.undefined,'
@@ -65,9 +69,19 @@ class panda3d(package):
     import direct
     file(Filename(direct.__path__[0], 'filter/*.sha'), newDir = 'direct/filter')
 
+    # pandac.PandaModules pulls in other Panda3D libs automatically.
     # Exclude these Panda3D libs; they are big and many applications don't
     # use them.  We define them as separate, optional packages, below,
     # except for skel - this is useless in a shipped game anyways.
+    excludeModule('panda3d.egg')
+    excludeModule('panda3d.ode')
+    excludeModule('panda3d.bullet')
+    excludeModule('panda3d.vision')
+    excludeModule('panda3d.skel')
+    excludeModule('panda3d.physx')
+    excludeModule('panda3d.ai')
+    excludeModule('panda3d.vrpn')
+
     excludeModule('libpandaegg')
     excludeModule('libpandaode')
     excludeModule('libpandabullet')
@@ -89,6 +103,8 @@ class panda3d(package):
 
     excludeModule('MySQLdb', '_mysql')
 
+    excludeModule('xml', 'xml.parsers.expat', 'xml.sax')
+
     # Most of the core Panda3D DLL's will be included implicitly due to
     # being referenced by the above Python code.  Here we name a few more
     # that are also needed, but aren't referenced by any code.  Again,
@@ -269,6 +285,7 @@ class egg(package):
     config(display_name = "Panda3D egg loader")
     require('panda3d')
 
+    module('panda3d.egg', required = True)
     file('libpandaegg.dll', required = True)
     file('libp3ptloader.dll', required = True)
 
@@ -286,6 +303,7 @@ class ode(package):
     config(display_name = "Panda3D Open Dynamics Engine integration")
     require('panda3d')
 
+    module('panda3d.ode', required = True)
     file('libpandaode.dll', required = True)
 
 class bullet(package):
@@ -296,6 +314,7 @@ class bullet(package):
     config(display_name = "Panda3D Bullet integration")
     require('panda3d')
 
+    module('panda3d.bullet', required = True)
     file('libpandabullet.dll', required = True)
 
 class physx(package):
@@ -306,6 +325,7 @@ class physx(package):
     config(display_name = "Panda3D PhysX integration")
     require('panda3d')
 
+    module('panda3d.physx', required = True)
     file('libpandaphysx.dll', required = True)
     file('physxcudart_20.dll')
     file('PhysXDevice.dll')
@@ -319,6 +339,7 @@ class ai(package):
     config(display_name = "Panda3D AI modules")
     require('panda3d')
 
+    module('panda3d.ai', required = True)
     file('libpandaai.dll', required = True)
 
 class vision(package):
@@ -330,6 +351,7 @@ class vision(package):
     config(display_name = "Panda3D vision modules")
     require('panda3d')
 
+    module('panda3d.vision', required = True)
     file('libp3vision.dll', required = True)
 
 class rocket(package):
@@ -340,6 +362,7 @@ class rocket(package):
     config(display_name = "Panda3D libRocket support")
     require('panda3d')
 
+    module('panda3d.rocket', required = True)
     module('_rocketcore', '_rocketcontrols')
     file('libp3rocket.dll', required = True)
 
@@ -350,6 +373,7 @@ class vrpn(package):
     config(display_name = "Panda3D VRPN support")
     require('panda3d')
 
+    module('panda3d.vrpn', required = True)
     file('libp3vrpn.dll', required = True)
 
 

+ 2 - 2
direct/src/p3d/pdeploy.py

@@ -102,7 +102,7 @@ Options:
      is licensed under.
      Only relevant when generating a graphical installer.
 
-  -O 
+  -O
      Specify this option when generating a graphical installer to omit
      the default checkboxes for "run this program" and "install a
      desktop shortcut" on completion.
@@ -147,7 +147,7 @@ import sys
 import os
 import getopt
 from direct.p3d.DeploymentTools import Standalone, Installer, Icon
-from pandac.PandaModules import Filename, PandaSystem
+from panda3d.core import Filename, PandaSystem
 
 def usage(code, msg = ''):
     if not msg:

+ 3 - 3
direct/src/p3d/pmerge.py

@@ -47,7 +47,7 @@ import getopt
 import os
 
 from direct.p3d import PackageMerger
-from pandac.PandaModules import *
+from panda3d.core import *
 
 def usage(code, msg = ''):
     print >> sys.stderr, usageText % {'prog' : os.path.split(sys.argv[0])[1]}
@@ -66,7 +66,7 @@ for opt, arg in opts:
         installDir = Filename.fromOsSpecific(arg)
     elif opt == '-p':
         packageNames += arg.split(',')
-        
+
     elif opt == '-h':
         usage(0)
     else:
@@ -92,7 +92,7 @@ try:
     for dir in inputDirs:
         pm.merge(dir, packageNames = packageNames)
     pm.close()
-        
+
 except PackageMerger.PackageMergerError:
     # Just print the error message and exit gracefully.
     inst = sys.exc_info()[1]

+ 1 - 1
direct/src/p3d/ppackage.py

@@ -132,7 +132,7 @@ import getopt
 import os
 
 from direct.p3d import Packager
-from pandac.PandaModules import *
+from panda3d.core import *
 
 def usage(code, msg = ''):
     print >> sys.stderr, usageText % {

+ 2 - 2
direct/src/p3d/ppatcher.py

@@ -60,7 +60,7 @@ import getopt
 import os
 
 from direct.p3d.PatchMaker import PatchMaker
-from pandac.PandaModules import *
+from panda3d.core import *
 
 def usage(code, msg = ''):
     print >> sys.stderr, usageText % {'prog' : os.path.split(sys.argv[0])[1]}
@@ -76,7 +76,7 @@ installDir = None
 for opt, arg in opts:
     if opt == '-i':
         installDir = Filename.fromOsSpecific(arg)
-        
+
     elif opt == '-h':
         usage(0)
     else:

+ 1 - 1
direct/src/p3d/runp3d.py

@@ -28,7 +28,7 @@ import sys
 import getopt
 from AppRunner import AppRunner, ArgumentError
 from direct.task.TaskManagerGlobal import taskMgr
-from pandac.PandaModules import Filename
+from panda3d.core import Filename
 
 def parseSysArgs():
     """ Handles sys.argv, if there are any local arguments, and

+ 2 - 2
direct/src/p3d/thirdparty.pdef

@@ -13,7 +13,7 @@
 
 # Also see panda3d.pdef.
 
-from pandac.PandaModules import Filename
+from panda3d.core import Filename
 import sys
 
 class wx(package):
@@ -95,7 +95,7 @@ class twisted(package):
            'twisted.runner', 'twisted.scripts', 'twisted.spread',
            'twisted.tap', 'twisted.trial', 'twisted.vfs',
            'twisted.web', 'twisted.web2', 'twisted.words')
-           
+
     module('twisted.*', 'twisted.*.*')
 
 class pil(package):

+ 2 - 2
direct/src/particles/ForceGroup.py

@@ -12,7 +12,7 @@ class ForceGroup(DirectObject):
 
     def __init__(self, name=None):
         if (name == None):
-            self.name = 'ForceGroup-%d' % ForceGroup.id 
+            self.name = 'ForceGroup-%d' % ForceGroup.id
             ForceGroup.id += 1
         else:
             self.name = name
@@ -65,7 +65,7 @@ class ForceGroup(DirectObject):
     def getNodePath(self):
         return self.nodePath
 
-    # Utility functions 
+    # Utility functions
     def __getitem__(self, index):
         numForces = self.node.getNumForces()
         if ((index < 0) or (index >= numForces)):

+ 1 - 1
direct/src/particles/ParticleManagerGlobal.py

@@ -1,6 +1,6 @@
 """
 Contains the global particle system manager
 """
-from pandac.PandaModules import ParticleSystemManager
+from panda3d.physics import ParticleSystemManager
 
 particleMgr = ParticleSystemManager()

+ 29 - 30
direct/src/particles/Particles.py

@@ -1,27 +1,27 @@
 from pandac.PandaModules import *
 
-from pandac.PandaModules import ParticleSystem
-from pandac.PandaModules import BaseParticleFactory
-from pandac.PandaModules import PointParticleFactory
-from pandac.PandaModules import ZSpinParticleFactory
-#from pandac.PandaModules import OrientedParticleFactory
-from pandac.PandaModules import BaseParticleRenderer
-from pandac.PandaModules import PointParticleRenderer
-from pandac.PandaModules import LineParticleRenderer
-from pandac.PandaModules import GeomParticleRenderer
-from pandac.PandaModules import SparkleParticleRenderer
-#from pandac.PandaModules import SpriteParticleRenderer
-from pandac.PandaModules import BaseParticleEmitter
-from pandac.PandaModules import ArcEmitter
-from pandac.PandaModules import BoxEmitter
-from pandac.PandaModules import DiscEmitter
-from pandac.PandaModules import LineEmitter
-from pandac.PandaModules import PointEmitter
-from pandac.PandaModules import RectangleEmitter
-from pandac.PandaModules import RingEmitter
-from pandac.PandaModules import SphereSurfaceEmitter
-from pandac.PandaModules import SphereVolumeEmitter
-from pandac.PandaModules import TangentRingEmitter
+from panda3d.physics import ParticleSystem
+from panda3d.physics import BaseParticleFactory
+from panda3d.physics import PointParticleFactory
+from panda3d.physics import ZSpinParticleFactory
+#from panda3d.physics import OrientedParticleFactory
+from panda3d.physics import BaseParticleRenderer
+from panda3d.physics import PointParticleRenderer
+from panda3d.physics import LineParticleRenderer
+from panda3d.physics import GeomParticleRenderer
+from panda3d.physics import SparkleParticleRenderer
+#from panda3d.physics import SpriteParticleRenderer
+from panda3d.physics import BaseParticleEmitter
+from panda3d.physics import ArcEmitter
+from panda3d.physics import BoxEmitter
+from panda3d.physics import DiscEmitter
+from panda3d.physics import LineEmitter
+from panda3d.physics import PointEmitter
+from panda3d.physics import RectangleEmitter
+from panda3d.physics import RingEmitter
+from panda3d.physics import SphereSurfaceEmitter
+from panda3d.physics import SphereVolumeEmitter
+from panda3d.physics import TangentRingEmitter
 
 import SpriteParticleRendererExt
 
@@ -464,7 +464,7 @@ class Particles(ParticleSystem):
                     t_b = seg.getTimeBegin()
                     t_e = seg.getTimeEnd()
                     mod = seg.isModulated()
-                    fun = seg.getFunction()                    
+                    fun = seg.getFunction()
                     typ = type(fun).__name__
                     if typ == 'ColorInterpolationFunctionConstant':
                         c_a = fun.getColorA()
@@ -560,7 +560,7 @@ class Particles(ParticleSystem):
             file.write('# Tangent Ring parameters\n')
             file.write(targ + '.emitter.setRadius(%.4f)\n' % self.emitter.getRadius())
             file.write(targ + '.emitter.setRadiusSpread(%.4f)\n' % self.emitter.getRadiusSpread())
-            
+
     def getPoolSizeRanges(self):
         litterRange = [max(1,self.getLitterSize()-self.getLitterSpread()),
                        self.getLitterSize(),
@@ -573,9 +573,9 @@ class Particles(ParticleSystem):
         print 'Litter Ranges:    ',litterRange
         print 'LifeSpan Ranges:  ',lifespanRange
         print 'BirthRate Ranges: ',birthRateRange
-        
+
         return dict(zip(('min','median','max'),[l*s/b for l,s,b in zip(litterRange,lifespanRange,birthRateRange)]))
-            
+
 
     def accelerate(self,time,stepCount = 1,stepTime=0.0):
         if time > 0.0:
@@ -585,14 +585,13 @@ class Particles(ParticleSystem):
             else:
                 stepCount = int(float(time)/stepTime)
                 remainder = time-stepCount*stepTime
-                
+
             for step in range(stepCount):
                 base.particleMgr.doParticles(stepTime,self,False)
                 base.physicsMgr.doPhysics(stepTime,self)
-                
+
             if(remainder):
                 base.particleMgr.doParticles(remainder,self,False)
                 base.physicsMgr.doPhysics(remainder,self)
-                
+
             self.render()
-        

+ 1 - 2
direct/src/particles/SpriteParticleRendererExt.py

@@ -1,4 +1,4 @@
-from pandac.PandaModules import SpriteParticleRenderer
+from panda3d.physics import SpriteParticleRenderer
 
 
 class SpriteParticleRendererExt(SpriteParticleRenderer):
@@ -126,4 +126,3 @@ class SpriteParticleRendererExt(SpriteParticleRenderer):
         m.removeNode()
 
         return True
-

+ 36 - 77
direct/src/plugin/p3dPythonRun.cxx

@@ -34,11 +34,11 @@ TypeHandle P3DPythonRun::P3DWindowHandle::_type_handle;
 ////////////////////////////////////////////////////////////////////
 //     Function: P3DPythonRun::Constructor
 //       Access: Public
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 P3DPythonRun::
 P3DPythonRun(const char *program_name, const char *archive_file,
-             FHandle input_handle, FHandle output_handle, 
+             FHandle input_handle, FHandle output_handle,
              const char *log_pathname, bool interactive_console) {
   P3DWindowHandle::init_type();
   init_xml();
@@ -115,7 +115,7 @@ P3DPythonRun(const char *program_name, const char *archive_file,
 ////////////////////////////////////////////////////////////////////
 //     Function: P3DPythonRun::Destructor
 //       Access: Public
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 P3DPythonRun::
 ~P3DPythonRun() {
@@ -150,72 +150,32 @@ run_python() {
   PyRun_SimpleString("import sys; sys.dll_suffix = '_d'");
 #endif
 
-  // We'll need libpandaexpress to be imported before we can load
-  // _vfsimporter.  So, find it and load it.
-  Filename libpandaexpress;
-
-#ifdef _WIN32
-  // Of course it's already resident, so use that version.
-  wstring basename = Filename::dso_filename("libpandaexpress.so").to_os_specific_w();
-  HMODULE h = GetModuleHandleW(basename.c_str());
-
-  if (h == NULL) {
-    nout << "Can't find libpandaexpress in memory.\n";
-  } else {
-    static const int buffer_size = 4096;
-    wchar_t buffer[buffer_size];
-    GetModuleFileNameW(h, buffer, buffer_size);
-    libpandaexpress = Filename::from_os_specific_w(buffer);
-  }
-#endif  // _WIN32
-
-  if (libpandaexpress.empty()) {
-    // Go look for it on disk.
-    libpandaexpress = Filename(_archive_file.get_dirname(), 
-                               Filename::dso_filename("libpandaexpress.so"));
-#if defined(__APPLE__) && PY_VERSION_HEX < 0x02050000
-    // On OSX, for Python versions 2.4 and before, we have to load the
-    // .so file, not the .dylib file.
-    libpandaexpress.set_type(Filename::T_general);
-#endif
-  }
-
-  if (!libpandaexpress.exists()) {
-    nout << "Can't find " << libpandaexpress << "\n";
-    return false;
-  }
+  Filename dir = _archive_file.get_dirname();
 
-  // We need the "imp" built-in module for that.
-  PyObject *imp_module = PyImport_ImportModule("imp");
-  if (imp_module == NULL) {
-    nout << "Failed to import module imp\n";
+  // We'll need to synthesize a 'panda3d' module before loading
+  // VFSImporter.  We could simply freeze it, but Python has a bug
+  // setting __path__ of frozen modules properly.
+  PyObject *panda3d_module = PyImport_AddModule("panda3d");
+  if (panda3d_module == NULL) {
+    nout << "Failed to create panda3d module:\n";
     PyErr_Print();
     return false;
   }
 
-  // And here's where we run into a brick wall attempting to make the
-  // whole plugin system Unicode-safe for Windows.  It turns out that
-  // this Python call, imp.load_dynamic(), will not accept a Unicode
-  // pathname.  So if the DLL in question is in a location that
-  // contains non-ASCII characters, it can't be loaded.
-  string os_specific = libpandaexpress.to_os_specific();
-  PyObject *result = PyObject_CallMethod
-    (imp_module, (char *)"load_dynamic", (char *)"ss", 
-     "libpandaexpress", os_specific.c_str());
-  if (result == NULL) {
-    nout << "Failed to import libpandaexpress as a module\n";
-    PyErr_Print();
-    return false;
-  }
-  Py_DECREF(result);
-  Py_DECREF(imp_module);
+  // Set the __path__ such that it can find panda3d/core.pyd, etc.
+  Filename panda3d_dir(dir, "panda3d");
+  string dir_str = panda3d_dir.to_os_specific();
+  PyObject *panda3d_dict = PyModule_GetDict(panda3d_module);
+  PyObject *panda3d_path = Py_BuildValue("[s#]", dir_str.data(), dir_str.length());
+  PyDict_SetItemString(panda3d_dict, "__path__", panda3d_path);
+  Py_DECREF(panda3d_path);
 
   // Now we can load _vfsimporter.pyd.  Since this is a magic frozen
   // pyd, importing it automatically makes all of its frozen contents
   // available to import as well.
   PyObject *vfsimporter = PyImport_ImportModule("_vfsimporter");
   if (vfsimporter == NULL) {
-    nout << "Failed to import _vfsimporter\n";
+    nout << "Failed to import _vfsimporter:\n";
     PyErr_Print();
     return false;
   }
@@ -224,15 +184,15 @@ run_python() {
   // And now we can import the VFSImporter module that was so defined.
   PyObject *vfsimporter_module = PyImport_ImportModule("VFSImporter");
   if (vfsimporter_module == NULL) {
-    nout << "Failed to import VFSImporter\n";
+    nout << "Failed to import VFSImporter:\n";
     PyErr_Print();
     return false;
   }
 
   // And register the VFSImporter.
-  result = PyObject_CallMethod(vfsimporter_module, (char *)"register", (char *)"");
+  PyObject *result = PyObject_CallMethod(vfsimporter_module, (char *)"register", (char *)"");
   if (result == NULL) {
-    nout << "Failed to call VFSImporter.register()\n";
+    nout << "Failed to call VFSImporter.register():\n";
     PyErr_Print();
     return false;
   }
@@ -248,7 +208,6 @@ run_python() {
     nout << "Could not read " << _archive_file << "\n";
     return false;
   }
-  Filename dir = _archive_file.get_dirname();
   VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
   if (!vfs->mount(mf, dir, VirtualFileSystem::MF_read_only)) {
     nout << "Could not mount " << _archive_file << "\n";
@@ -346,7 +305,7 @@ run_python() {
   }
   Py_DECREF(result);
   Py_DECREF(request_func);
- 
+
 
   // Now add check_comm() as a task.  It can be a threaded task, but
   // this does mean that application programmers will have to be alert
@@ -545,7 +504,7 @@ handle_command(TiXmlDocument *doc) {
         assert(!needs_response);
         int instance_id;
         TiXmlElement *xwparams = xcommand->FirstChildElement("wparams");
-        if (xwparams != (TiXmlElement *)NULL && 
+        if (xwparams != (TiXmlElement *)NULL &&
             xcommand->QueryIntAttribute("instance_id", &instance_id) == TIXML_SUCCESS) {
           setup_window(instance_id, xwparams);
         }
@@ -591,7 +550,7 @@ handle_command(TiXmlDocument *doc) {
             _sent_objects.erase(si);
           }
         }
-        
+
       } else {
         nout << "Unhandled command " << cmd << "\n";
         if (needs_response) {
@@ -678,7 +637,7 @@ handle_pyobj_command(TiXmlElement *xcommand, bool needs_response,
         if (method_name == NULL) {
           // No method name; call the object directly.
           result = PyObject_CallObject(obj, params);
-          
+
           // Several special-case "method" names.
         } else if (strcmp(method_name, "__bool__") == 0) {
           result = PyBool_FromLong(PyObject_IsTrue(obj));
@@ -713,7 +672,7 @@ handle_pyobj_command(TiXmlElement *xcommand, bool needs_response,
                 PyErr_Clear();
               }
             }
-            
+
             // If the object supports the mapping protocol, store it
             // in the object's dictionary.
             if (!success && PyMapping_Check(obj)) {
@@ -761,7 +720,7 @@ handle_pyobj_command(TiXmlElement *xcommand, bool needs_response,
                 PyErr_Clear();
               }
             }
-            
+
             if (success) {
               result = Py_True;
             } else {
@@ -1066,8 +1025,8 @@ py_request_func(PyObject *args) {
     PyObject *value;
     int needs_response;
     int unique_id;
-    if (!PyArg_ParseTuple(extra_args, "sOsOii", 
-                          &operation, &object, &property_name, &value, 
+    if (!PyArg_ParseTuple(extra_args, "sOsOii",
+                          &operation, &object, &property_name, &value,
                           &needs_response, &unique_id)) {
       return NULL;
     }
@@ -1256,7 +1215,7 @@ set_instance_info(P3DCInstance *inst, TiXmlElement *xinstance) {
   xinstance->Attribute("respect_per_platform", &respect_per_platform);
 
   PyObject *result = PyObject_CallMethod
-    (_runner, (char *)"setInstanceInfo", (char *)"sssiOi", root_dir, 
+    (_runner, (char *)"setInstanceInfo", (char *)"sssiOi", root_dir,
      log_directory, super_mirror, verify_contents, main, respect_per_platform);
   Py_DECREF(main);
 
@@ -1347,7 +1306,7 @@ set_p3d_filename(P3DCInstance *inst, TiXmlElement *xfparams) {
       value = value_c;
     }
 
-    PyObject *tuple = Py_BuildValue("(ss)", keyword.c_str(), 
+    PyObject *tuple = Py_BuildValue("(ss)", keyword.c_str(),
                                     value.c_str());
     PyList_Append(token_list, tuple);
     Py_DECREF(tuple);
@@ -1419,7 +1378,7 @@ setup_window(P3DCInstance *inst, TiXmlElement *xwparams) {
   }
 
   int win_x, win_y, win_width, win_height;
-  
+
   xwparams->Attribute("win_x", &win_x);
   xwparams->Attribute("win_y", &win_y);
   xwparams->Attribute("win_width", &win_width);
@@ -1531,7 +1490,7 @@ terminate_session() {
         Py_DECREF(result);
       }
     }
-    
+
     _session_terminated = true;
   }
 }
@@ -1772,7 +1731,7 @@ xml_to_pyobj(TiXmlElement *xvalue) {
     int object_id;
     if (xvalue->QueryIntAttribute("object_id", &object_id) == TIXML_SUCCESS) {
       // Construct a new BrowserObject wrapper around this object.
-      return PyObject_CallFunction(_browser_object_class, (char *)"Oi", 
+      return PyObject_CallFunction(_browser_object_class, (char *)"Oi",
                                    _runner, object_id);
     }
 
@@ -1852,7 +1811,7 @@ rt_thread_run() {
     }
 
     // Successfully read an XML document.
-    
+
     // Check for one special case: the "exit" command means we shut
     // down the read thread along with everything else.
     TiXmlElement *xcommand = doc->FirstChildElement("command");
@@ -1875,7 +1834,7 @@ rt_thread_run() {
 ////////////////////////////////////////////////////////////////////
 //     Function: P3DPythonRun::P3DWindowHandle::Constructor
 //       Access: Public
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 P3DPythonRun::P3DWindowHandle::
 P3DWindowHandle(P3DPythonRun *p3dpython, P3DCInstance *inst,

+ 46 - 43
direct/src/plugin/p3dX11SplashWindow.cxx

@@ -28,10 +28,10 @@
 ////////////////////////////////////////////////////////////////////
 //     Function: P3DX11SplashWindow::Constructor
 //       Access: Public
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 P3DX11SplashWindow::
-P3DX11SplashWindow(P3DInstance *inst, bool make_visible) : 
+P3DX11SplashWindow(P3DInstance *inst, bool make_visible) :
   P3DSplashWindow(inst, make_visible)
 {
   // Init for parent process
@@ -61,7 +61,7 @@ P3DX11SplashWindow(P3DInstance *inst, bool make_visible) :
 ////////////////////////////////////////////////////////////////////
 //     Function: P3DX11SplashWindow::Destructor
 //       Access: Public, Virtual
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 P3DX11SplashWindow::
 ~P3DX11SplashWindow() {
@@ -312,13 +312,13 @@ stop_subprocess() {
   _pipe_write.close();
 
   static const int max_wait_ms = 2000;
-  
+
   // Wait for a certain amount of time for the process to stop by
   // itself.
   struct timeval start;
   gettimeofday(&start, NULL);
   int start_ms = start.tv_sec * 1000 + start.tv_usec / 1000;
-  
+
   int status;
   pid_t result = waitpid(_subprocess_pid, &status, WNOHANG);
   while (result != _subprocess_pid) {
@@ -326,20 +326,20 @@ stop_subprocess() {
       perror("waitpid");
       break;
     }
-    
+
     struct timeval now;
     gettimeofday(&now, NULL);
     int now_ms = now.tv_sec * 1000 + now.tv_usec / 1000;
     int elapsed = now_ms - start_ms;
-    
+
     if (elapsed > max_wait_ms) {
       // Tired of waiting.  Kill the process.
-      nout << "Force-killing splash window process, pid " << _subprocess_pid 
+      nout << "Force-killing splash window process, pid " << _subprocess_pid
            << "\n";
       kill(_subprocess_pid, SIGKILL);
       start_ms = now_ms;
     }
-    
+
     // Yield the timeslice and wait some more.
     struct timeval tv;
     tv.tv_sec = 0;
@@ -353,7 +353,7 @@ stop_subprocess() {
     nout << "  exited normally, status = "
          << WEXITSTATUS(status) << "\n";
   } else if (WIFSIGNALED(status)) {
-    nout << "  signalled by " << WTERMSIG(status) << ", core = " 
+    nout << "  signalled by " << WTERMSIG(status) << ", core = "
          << WCOREDUMP(status) << "\n";
   } else if (WIFSTOPPED(status)) {
     nout << "  stopped by " << WSTOPSIG(status) << "\n";
@@ -396,7 +396,7 @@ check_stopped() {
     nout << "  exited normally, status = "
          << WEXITSTATUS(status) << "\n";
   } else if (WIFSIGNALED(status)) {
-    nout << "  signalled by " << WTERMSIG(status) << ", core = " 
+    nout << "  signalled by " << WTERMSIG(status) << ", core = "
          << WCOREDUMP(status) << "\n";
   } else if (WIFSTOPPED(status)) {
     nout << "  stopped by " << WSTOPSIG(status) << "\n";
@@ -522,14 +522,14 @@ subprocess_run() {
           _win_height = event.xconfigure.height;
 
           set_button_range(_button_ready_image);
-          
+
           // If the window changes size, we need to recompute the
           // composed image.
           _needs_new_composite = true;
         }
         needs_redraw = true;
         break;
-        
+
       case MotionNotify:
         set_mouse_data(event.xmotion.x, event.xmotion.y, _mouse_down);
         break;
@@ -537,7 +537,7 @@ subprocess_run() {
       case ButtonPress:
         set_mouse_data(_mouse_x, _mouse_y, true);
         break;
-        
+
       case ButtonRelease:
         set_mouse_data(_mouse_x, _mouse_y, false);
         break;
@@ -563,7 +563,7 @@ subprocess_run() {
       needs_redraw = true;
       prev_label = _install_label;
     }
-    
+
     if (_progress_known != prev_progress_known) {
       needs_update_progress = true;
       needs_redraw_progress = true;
@@ -592,7 +592,7 @@ subprocess_run() {
         needs_redraw = true;
       }
     }
-    
+
     if (needs_redraw) {
       redraw();
       XFlush(_display);
@@ -619,23 +619,23 @@ subprocess_run() {
                    text_width + 4, text_height + 4, false);
         XDrawString(_display, _window, _graphics_context, text_x, text_y,
                     _install_label.c_str(), _install_label.size());
-        
+
         needs_draw_label = false;
       }
-      
+
       if (needs_redraw_progress) {
-        XClearArea(_display, _window, 
+        XClearArea(_display, _window,
                    bar_x, bar_y, bar_width, bar_height, false);
-        XDrawRectangle(_display, _window, _graphics_context, 
+        XDrawRectangle(_display, _window, _graphics_context,
                        bar_x, bar_y, bar_width, bar_height);
         needs_update_progress = true;
         needs_redraw_progress = false;
       }
-      
+
       if (needs_update_progress) {
         if (_progress_known) {
           int progress_width = (int)((bar_width - 2) * _install_progress + 0.5);
-          XFillRectangle(_display, _window, _bar_context, 
+          XFillRectangle(_display, _window, _bar_context,
                          bar_x + 1, bar_y + 1,
                          progress_width + 1, bar_height - 1);
         } else {
@@ -649,7 +649,7 @@ subprocess_run() {
             progress = block_travel * 2 - progress;
           }
 
-          XFillRectangle(_display, _window, _bar_context, 
+          XFillRectangle(_display, _window, _bar_context,
                          bar_x + 1 + progress, bar_y + 1,
                          block_width + 1, bar_height - 1);
         }
@@ -665,7 +665,7 @@ subprocess_run() {
       fd_set fds;
       FD_ZERO(&fds);
       FD_SET(read_fd, &fds);
-      
+
       // Sleep a bit to yield the timeslice if there's nothing new.
       struct timeval tv;
       tv.tv_sec = 0;
@@ -729,27 +729,30 @@ receive_command() {
       } else if (strcmp(cmd, "set_image_filename") == 0) {
         const string *image_filename = xcommand->Attribute(string("image_filename"));
         int image_placement;
-        if (image_filename != NULL && 
+        if (image_filename != NULL &&
             xcommand->QueryIntAttribute("image_placement", &image_placement) == TIXML_SUCCESS) {
-          
+
           X11ImageData *image = NULL;
           switch ((ImagePlacement)image_placement) {
           case IP_background:
             image = &_background_image;
             break;
-            
+
           case IP_button_ready:
             image = &_button_ready_image;
             set_button_range(_button_ready_image);
             break;
-            
+
           case IP_button_rollover:
             image = &_button_rollover_image;
             break;
-            
+
           case IP_button_click:
             image = &_button_click_image;
             break;
+
+          case IP_none:
+            break;
           }
           if (image != NULL) {
             if (image->_filename != *image_filename) {
@@ -804,7 +807,7 @@ redraw() {
     // If we have an image, draw it.
     int xo = (_win_width - _composite_width) / 2;
     int yo = (_win_height - _composite_height) / 2;
-    XPutImage(_display, _window, _graphics_context, _composite_image, 0, 0, 
+    XPutImage(_display, _window, _graphics_context, _composite_image, 0, 0,
               xo, yo, _composite_width, _composite_height);
 
     // Then clear the rectangles around it carefully (rather than just
@@ -840,12 +843,12 @@ make_window() {
   }
 
   X11_Window parent = 0;
-  
+
   // Hum, if we use the display provided by the browser,
   // it causes a crash in some browsers when you make an Xlib
   // call with the plugin window minimized.
   // So I kept XOpenDisplay until we have a better workaround.
-  
+
   //_display = (X11_Display*) _wparams.get_parent_window()._xdisplay;
   //_own_display = false;
   //if (_display == 0) {
@@ -871,7 +874,7 @@ make_window() {
     // Create a toplevel window.
     parent = XRootWindow(_display, _screen);
   }
-  
+
   assert(parent != None);
 
   int depth = DefaultDepth(_display, _screen);
@@ -955,7 +958,7 @@ setup_gc() {
   XFontStruct* fs = XLoadQueryFont(_display, "6x13");
 
   XGCValues gcval;
-  gcval.font = fs->fid; 
+  gcval.font = fs->fid;
   gcval.function = GXcopy;
   gcval.plane_mask = AllPlanes;
   gcval.foreground = BlackPixel(_display, _screen);
@@ -966,8 +969,8 @@ setup_gc() {
   if (_bg_pixel != -1) {
     gcval.background = _bg_pixel;
   }
-  _graphics_context = XCreateGC(_display, _window, 
-    GCFont | GCFunction | GCPlaneMask | GCForeground | GCBackground, &gcval); 
+  _graphics_context = XCreateGC(_display, _window,
+    GCFont | GCFunction | GCPlaneMask | GCForeground | GCBackground, &gcval);
 
   // Also create a gc for filling in the interior of the progress bar
   // in a pleasant blue color (or whatever color the user requested).
@@ -983,7 +986,7 @@ setup_gc() {
     gcval.foreground = bar.pixel;
   }
 
-  _bar_context = XCreateGC(_display, _window, 
+  _bar_context = XCreateGC(_display, _window,
     GCFont | GCFunction | GCPlaneMask | GCForeground | GCBackground, &gcval);
 }
 
@@ -998,7 +1001,7 @@ close_window() {
     XDestroyImage(_composite_image);
     _composite_image = NULL;
   }
-  
+
   if (_bar_context != None) {
     if (_bar_context != _graphics_context) {
       XFreeGC(_display, _bar_context);
@@ -1009,22 +1012,22 @@ close_window() {
     Colormap colormap = DefaultColormap(_display, _screen);
     XFreeColors(_display, colormap, &_bar_pixel, 1, 0);
   }
-  
+
   if (_fg_pixel != -1) {
     Colormap colormap = DefaultColormap(_display, _screen);
     XFreeColors(_display, colormap, &_fg_pixel, 1, 0);
   }
-  
+
   if (_bg_pixel != -1) {
     Colormap colormap = DefaultColormap(_display, _screen);
     XFreeColors(_display, colormap, &_bg_pixel, 1, 0);
   }
-  
+
   if (_graphics_context != None) {
     XFreeGC(_display, _graphics_context);
     _graphics_context = None;
   }
-  
+
   if (_window != None) {
     XDestroyWindow(_display, _window);
     _window = None;
@@ -1150,7 +1153,7 @@ compose_image() {
   }
 
   // Now load the image.
-  _composite_image = XCreateImage(_display, CopyFromParent, DefaultDepth(_display, _screen), 
+  _composite_image = XCreateImage(_display, CopyFromParent, DefaultDepth(_display, _screen),
                                   ZPixmap, 0, (char *)new_data, image1_width, image1_height, 32, 0);
   _composite_width = image1_width;
   _composite_height = image1_height;

+ 0 - 557
direct/src/showbase/BpDb.py

@@ -1,557 +0,0 @@
-
-import inspect
-import sys
-
-#Bpdb - breakpoint debugging system (kanpatel - 04/2010)
-class BpMan:
-    def __init__(self):
-        self.bpInfos = {}
-    
-    def partsToPath(self, parts):
-        cfg = parts.get('cfg')
-        grp = parts.get('grp')
-        id = parts.get('id','*')
-        path = ''
-        if cfg:
-            path += '%s'%(cfg,)
-            if grp or id:
-                path += '::'
-        if grp:
-            path += '%s'%(grp,)
-        if isinstance(id, int):
-            path += '(%s)'%(id,)
-        elif grp:
-            path += '.%s'%(id,)
-        else:
-            path += '%s'%(id,)
-        return path
-
-    def pathToParts(self, path=None):
-        parts = {'cfg':None, 'grp':None, 'id':None}
-
-        #verify input        
-        if not isinstance(path, type('')):
-            assert not "error: argument must be string of form '[cfg::][grp.]id'"
-            return parts
-
-        #parse cfg                
-        tokens = path.split('::')
-        if (len(tokens) > 1) and (len(tokens[0]) > 0):
-            parts['cfg'] = tokens[0]
-            path = tokens[1]
-            
-        #parse grp
-        tokens = path.split('.')
-        if (len(tokens) == 1):
-            tokens = path.rsplit(')', 1)
-            if (len(tokens) > 1) and (tokens[-1] == ''):
-                tokens = tokens[-2].rsplit('(', 1)
-                if (len(tokens) > 1):
-                    try:
-                        verifyInt = int(tokens[-1])
-                        parts['grp'] = tokens[0]
-                        path = tokens[-1]
-                    except:
-                        pass
-        elif (len(tokens) > 1) and (len(tokens[0]) > 0):
-            parts['grp'] = tokens[0]
-            path = tokens[1]
-
-        #parse id
-        if (len(path) > 0):
-            parts['id'] = path
-        if parts['id'] == '*':
-            parts['id'] = None
-
-        #done
-        return parts
-
-    def bpToPath(self, bp):
-        if type(bp) is type(''):
-            bp = self.pathToParts(bp)
-        return self.partsToPath(bp)
-        
-    def bpToParts(self, bp):
-        if type(bp) is type({}):
-            bp = self.partsToPath(bp)
-        return self.pathToParts(bp)
-        
-    def makeBpInfo(self, grp, id):
-        self.bpInfos.setdefault(grp, {None:{},})
-        self.bpInfos[grp].setdefault(id, {})
-
-    def getEnabled(self, bp):
-        parts = self.bpToParts(bp)
-        grp, id = parts['grp'], parts['id']
-        self.makeBpInfo(parts['grp'], parts['id'])
-        if not self.bpInfos[grp][None].get('enabled', True):
-            return False
-        if not self.bpInfos[grp][id].get('enabled', True):
-            return False
-        return True
-
-    def setEnabled(self, bp, enabled=True):
-        parts = self.bpToParts(bp)
-        grp, id = parts['grp'], parts['id']
-        self.makeBpInfo(grp, id)
-        self.bpInfos[grp][id]['enabled'] = enabled
-        return enabled
-
-    def toggleEnabled(self, bp):
-        parts = self.bpToParts(bp)
-        grp, id = parts['grp'], parts['id']
-        self.makeBpInfo(grp, id)
-        newEnabled = not self.bpInfos[grp][id].get('enabled', True)
-        self.bpInfos[grp][id]['enabled'] = newEnabled
-        return newEnabled
-
-    def getIgnoreCount(self, bp, decrement=False):
-        parts = self.bpToParts(bp)
-        grp, id = parts['grp'], parts['id']
-        self.makeBpInfo(grp, id)
-        ignoreCount = self.bpInfos[grp][id].get('ignoreCount', 0)
-        if ignoreCount > 0 and decrement:
-            self.bpInfos[grp][id]['ignoreCount'] = ignoreCount - 1
-        return ignoreCount
-
-    def setIgnoreCount(self, bp, ignoreCount=0):
-        if not isinstance(ignoreCount, int):
-            print 'error: first argument should be integer ignoreCount'
-            return
-            
-        parts = self.bpToParts(bp)
-        grp, id = parts['grp'], parts['id']
-        self.makeBpInfo(grp, id)
-        self.bpInfos[grp][id]['ignoreCount'] = ignoreCount
-        return ignoreCount
-
-    def getLifetime(self, bp):
-        parts = self.bpToParts(bp)
-        grp, id = parts['grp'], parts['id']
-        self.makeBpInfo(grp, id)
-        lifetime = self.bpInfos[grp][id].get('lifetime', -1)
-        return lifetime
-        
-    def setLifetime(self, bp, newLifetime):
-        parts = self.bpToParts(bp)
-        grp, id = parts['grp'], parts['id']
-        self.makeBpInfo(grp, id)
-        self.bpInfos[grp][id]['lifetime'] = newLifetime
-        return lifetime
-        
-    def decLifetime(self, bp):
-        parts = self.bpToParts(bp)
-        grp, id = parts['grp'], parts['id']
-        self.makeBpInfo(grp, id)
-        lifetime = self.bpInfos[grp][id].get('lifetime', -1)
-        if lifetime > 0:
-            lifetime = lifetime - 1
-        self.bpInfos[grp][id]['lifetime'] = lifetime
-        return lifetime
-
-    def getHitCount(self, bp):
-        parts = self.bpToParts(bp)
-        grp, id = parts['grp'], parts['id']
-        self.makeBpInfo(grp, id)
-        return self.bpInfos[grp][id].get('count', 0)
-        
-    def setHitCount(self, bp, newHitCount):
-        parts = self.bpToParts(bp)
-        grp, id = parts['grp'], parts['id']
-        self.makeBpInfo(grp, id)
-        self.bpInfos[grp][id]['count'] = newHitCount
-        
-    def incHitCount(self, bp):
-        parts = self.bpToParts(bp)
-        grp, id = parts['grp'], parts['id']
-        self.makeBpInfo(grp, id)
-        self.bpInfos[grp][id]['count'] = self.bpInfos[grp][id].get('count', 0) + 1
-        
-    def resetBp(self, bp):
-        parts = self.bpToParts(bp)
-        grp, id = parts['grp'], parts['id']
-        self.makeBpInfo(grp, id)
-        self.bpInfos[grp][id] = {}
-        if id is None:
-            del self.bpInfos[grp]
-    
-class BpDb:
-    def __init__(self):
-        self.enabled = True
-        self.cfgInfos = { None:True }
-        self.codeInfoCache = {}
-        self.bpMan = BpMan()
-        self.lastBp = None
-        self.pdbAliases = {}
-        self.configCallback = None
-
-    def setEnabledCallback(self, callback):
-        self.enabledCallback = callback
-
-    def verifyEnabled(self):
-        if self.enabledCallback:
-            return self.enabledCallback()
-        return True
-
-    def setConfigCallback(self, callback):
-        self.configCallback = callback
-                
-    def verifySingleConfig(self, cfg):
-        if cfg in self.cfgInfos:
-            return self.cfgInfos[cfg]
-        return not self.configCallback or self.configCallback(cfg)
-
-    def verifyConfig(self, cfg):
-        cfgList = choice(isinstance(cfg, tuple), cfg, (cfg,))
-        passedCfgs = [c for c in cfgList if self.verifySingleConfig(c)]
-        return (len(passedCfgs) > 0)
-
-    def toggleConfig(self, cfg):
-        self.cfgInfos[cfg] = not self.verifyConfig(cfg)
-        return self.cfgInfos[cfg]
-
-    def resetConfig(self, cfg):
-        self.cfgInfos.pop(cfg, None)
-
-    #setup bpdb prompt commands
-    def displayHelp(self):
-        print 'You may use normal pdb commands plus the following:'
-        #print '    cmd  [param <def>]  [cmd] does )this( with [param] (default is def)'
-        #print '    -----------------------------------------------------------------------'
-        print '    _i   [n <0> [, path=<curr>]] set ignore count for bp [path] to [n]'
-        print '    _t   [path <curr>]   toggle bp [path]'
-        print '    _tg  [grp <curr>]    toggle grp'
-        print '    _tc  [cfg <curr>]    toggle cfg'
-        print '    _z   [path <curr>]   clear all settings for bp [path]'
-        print '    _zg  [grp <curr>]    clear all settings for grp'
-        print '    _zc  [cfg <curr>]    clear all settings for cfg (restore .prc setting)'
-        print '    _h                   displays this usage help'
-        print '    _ua                  unalias these commands from pdb'
-
-    def addPdbAliases(self):
-        self.makePdbAlias('_i', 'bpdb._i(%*)')
-        self.makePdbAlias('_t', 'bpdb._t(%*)')
-        self.makePdbAlias('_tg', 'bpdb._tg(%*)')
-        self.makePdbAlias('_tc', 'bpdb._tc(%*)')
-        self.makePdbAlias('_z', 'bpdb._z(%*)')
-        self.makePdbAlias('_zg', 'bpdb._zg(%*)')
-        self.makePdbAlias('_zc', 'bpdb._zc(%*)')
-        self.makePdbAlias('_h', 'bpdb.displayHelp()')
-        self.makePdbAlias('_ua', 'bpdb.removePdbAliases()')
-
-    def makePdbAlias(self, aliasName, aliasCmd):
-        self.pdbAliases[aliasName] = aliasCmd
-        self.pdb.do_alias('%s %s'%(aliasName,aliasCmd))
-
-    def removePdbAliases(self):
-        for aliasName in self.pdbAliases.iterkeys():
-            self.pdb.do_unalias(aliasName)
-        self.pdbAliases = {}
-        print '(bpdb aliases removed)'
-
-    #handle bpdb prompt commands by forwarding to bpMan
-    def _e(self, *args, **kwargs):
-        bp = self._getArg(args, [type(''),type({}),], kwargs, ['path','bp','name',], self.lastBp)
-        enabled = self._getArg(args, [type(True),type(1),], kwargs, ['enabled','on',], True)
-        newEnabled = self.bpMan.setEnabled(bp, enabled)
-        print "'%s' is now %s."%(self.bpMan.bpToPath(bp),choice(newEnabled,'enabled','disabled'),)
-        
-    def _i(self, *args, **kwargs):
-        bp = self._getArg(args, [type(''),type({}),], kwargs, ['path','bp','name',], self.lastBp)
-        count = self._getArg(args, [type(1),], kwargs, ['ignoreCount','count','n',], 0)
-        newCount = self.bpMan.setIgnoreCount(bp, count)
-        print "'%s' will ignored %s times."%(self.bpMan.bpToPath(bp),newCount,)
-
-    def _t(self, *args, **kwargs):
-        bp = self._getArg(args, [type(''),type({}),], kwargs, ['path','bp','name',], self.lastBp)
-        newEnabled = self.bpMan.toggleEnabled(bp)
-        print "'%s' is now %s."%(self.bpMan.bpToPath(bp),choice(newEnabled,'enabled','disabled'),)
-        
-    def _tg(self, *args, **kwargs):
-        bp = self._getArg(args, [type(''),type({}),], kwargs, ['grp',], self.lastBp)
-        if type(bp) == type(''):
-            bp = {'grp':bp}
-        bp = {'grp':bp.get('grp')}
-        newEnabled = self.bpMan.toggleEnabled(bp)
-        print "'%s' is now %s."%(self.bpMan.bpToPath(bp),choice(newEnabled,'enabled','disabled'),)
-        
-    def _tc(self, *args, **kwargs):
-        bp = self._getArg(args, [type(''),type({}),], kwargs, ['cfg',], self.lastBp)
-        if type(bp) == type(''):
-            bp = {'cfg':bp}
-        bp = {'cfg':bp.get('cfg')}
-        newEnabled = self.toggleConfig(bp['cfg'])
-        print "'%s' is now %s."%(self.bpMan.bpToPath(bp),choice(newEnabled,'enabled','disabled'),)
-        
-    def _z(self, *args, **kwargs):
-        bp = self._getArg(args, [type(''),type({}),], kwargs, ['path','bp','name',], self.lastBp)
-        self.bpMan.resetBp(bp)
-        print "'%s' has been reset."%(self.bpMan.partsToPath(bp),)
-
-    def _zg(self, *args, **kwargs):
-        bp = self._getArg(args, [type(''),type({}),], kwargs, ['grp',], self.lastBp)
-        if type(bp) == type(''):
-            bp = {'grp':bp}
-        bp = {'grp':bp.get('grp')}
-        self.bpMan.resetBp(bp)
-        print "'%s' has been reset."%(self.bpMan.partsToPath(bp),)
-
-    def _zc(self, *args, **kwargs):
-        bp = self._getArg(args, [type(''),type({}),], kwargs, ['cfg',], self.lastBp)
-        if type(bp) == type(''):
-            bp = {'cfg':bp}
-        bp = {'cfg':bp.get('cfg')}
-        self.resetConfig(bp['cfg'])
-        print "'%s' has been reset."%(self.bpMan.bpToPath(bp),)
- 
-    def _getArg(self, args, goodTypes, kwargs, goodKeys, default = None):
-        #look for desired arg in args and kwargs lists
-        argVal = default
-        for val in args:
-            if type(val) in goodTypes:
-                argVal = val
-        for key in goodKeys:
-            if key in kwargs:
-                argVal = kwargs[key]
-        return argVal
-                
-    #code for automatically determining param vals
-    def getFrameCodeInfo(self, frameCount=1):
-        #get main bits
-        stack = inspect.stack()
-        try:
-            primaryFrame = stack[frameCount][0]
-        except:
-            return ('<stdin>', None, -1)
-
-        #todo: 
-        #frameInfo is inadequate as a unique marker for this code location
-        #caching disabled until suitable replacement is found
-        #
-        #frameInfo = inspect.getframeinfo(primaryFrame)
-        #frameInfo = (frameInfo[0], frameInfo[1])
-        #check cache
-        #codeInfo = self.codeInfoCache.get(frameInfo)
-        #if codeInfo:
-        #    return codeInfo
-        
-        #look for module name
-        moduleName = None
-        callingModule = inspect.getmodule(primaryFrame)
-        if callingModule and callingModule.__name__ != '__main__':
-            moduleName = callingModule.__name__
-
-        #look for class name
-        className = None
-        for i in range(frameCount, len(stack)):
-            callingContexts = stack[i][4]
-            if callingContexts:
-                contextTokens = callingContexts[0].split()
-                if contextTokens[0] in ['class','def'] and len(contextTokens) > 1:
-                    callingContexts[0] = callingContexts[0].replace('(',' ').replace(':',' ')
-                    contextTokens = callingContexts[0].split()
-                    className = contextTokens[1]
-                    break
-        if className is None:
-            #look for self (this functions inappropriately for inherited classes)
-            slf = primaryFrame.f_locals.get('self')
-            try:
-                if slf:
-                    className = slf.__class__.__name__
-            except:
-                #in __init__ 'self' exists but 'if slf' will crash
-                pass
-
-        #get line number
-        def byteOffsetToLineno(code, byte):
-            # Returns the source line number corresponding to the given byte
-            # offset into the indicated Python code module.
-            import array
-            lnotab = array.array('B', code.co_lnotab)
-            line   = code.co_firstlineno
-            for i in range(0, len(lnotab), 2):
-                byte -= lnotab[i]
-                if byte <= 0:
-                    return line
-                line += lnotab[i+1]
-            return line
-
-        lineNumber = byteOffsetToLineno(primaryFrame.f_code, primaryFrame.f_lasti)
-        #frame = inspect.stack()[frameCount][0]
-        #lineno = byteOffsetToLineno(frame.f_code, frame.f_lasti)
-
-        codeInfo = (moduleName, className, lineNumber)
-        #self.codeInfoCache[frameInfo] = codeInfo
-        return codeInfo
-    
-    #actually deliver the user a prompt
-    def set_trace(self, bp, frameCount=1):
-        #find useful frame
-        self.currFrame = sys._getframe()
-        interactFrame = self.currFrame
-        while frameCount > 0:
-            interactFrame = interactFrame.f_back
-            frameCount -= 1
-
-        #cache this as the latest bp
-        self.lastBp = bp.getParts()
-        #set up and start debuggger
-        import pdb
-        self.pdb = pdb.Pdb()
-        #self.pdb.do_alias('aa bpdb.addPdbAliases()')        
-        self.addPdbAliases()
-        self.pdb.set_trace(interactFrame);
-        
-    #bp invoke methods
-    def bp(self, id=None, grp=None, cfg=None, iff=True, enabled=True, test=None, frameCount=1):
-        if not (self.enabled and self.verifyEnabled()):
-            return
-        if not (enabled and iff):
-            return
-            
-        bpi = bp(id=id, grp=grp, cfg=cfg, frameCount=frameCount+1)
-        bpi.maybeBreak(test=test, frameCount=frameCount+1)
-
-    def bpCall(self,id=None,grp=None,cfg=None,iff=True,enabled=True,test=None,frameCount=1,onEnter=1,onExit=0):
-        def decorator(f):
-            return f
-
-        if not (self.enabled and self.verifyEnabled()):
-            return decorator
-        if not (enabled and iff):
-            return decorator
-        
-        bpi = bp(id=id, grp=grp, cfg=cfg, frameCount=frameCount+1)
-        if bpi.disabled:
-            return decorator
-
-        def decorator(f):
-            def wrap(*args, **kwds):
-                #create our bp object
-                dbp = bp(id=id or f.__name__, grp=bpi.grp, cfg=bpi.cfg, frameCount=frameCount+1)
-                if onEnter:
-                    dbp.maybeBreak(test=test,frameCount=frameCount+1,displayPrefix='Calling ')
-                f_result = f(*args, **kwds)
-                if onExit:
-                    dbp.maybeBreak(test=test,frameCount=frameCount+1,displayPrefix='Exited ')
-                return f_result
-                
-            wrap.func_name = f.func_name
-            wrap.func_dict = f.func_dict
-            wrap.func_doc = f.func_doc
-            wrap.__module__ = f.__module__
-            return wrap
-            
-        return decorator
-        
-    def bpPreset(self, *args, **kArgs):
-        def functor(*cArgs, **ckArgs):
-            return
-        if kArgs.get('call', None):
-            def functor(*cArgs, **ckArgs):
-                def decorator(f):
-                    return f
-                return decorator
-
-        if self.enabled and self.verifyEnabled():
-            argsCopy = args[:]
-            def functor(*cArgs, **ckArgs):
-                kwArgs = {}
-                kwArgs.update(kArgs)
-                kwArgs.update(ckArgs)
-                kwArgs.pop('static', None)
-                kwArgs['frameCount'] = ckArgs.get('frameCount',1)+1
-                if kwArgs.pop('call', None):
-                    return self.bpCall(*(cArgs), **kwArgs)
-                else:
-                    return self.bp(*(cArgs), **kwArgs)
-
-        if kArgs.get('static', None):
-            return staticmethod(functor)
-        else:
-            return functor
-
-    #deprecated:
-    @staticmethod
-    def bpGroup(*args, **kArgs):
-        print "BpDb.bpGroup is deprecated, use bpdb.bpPreset instead"
-        kwArgs = {}
-        kwArgs.update(kArgs)
-        kwArgs['frameCount'] = kArgs.get('frameCount', 1) + 1
-        return bpdb.bpPreset(*(args), **(kwArgs))
-
-
-class bp:
-    def __init__(self, id=None, grp=None, cfg=None, frameCount=1):
-        #check early out conditions 
-        self.disabled = False
-        if not bpdb.enabled:
-            self.disabled = True
-            return
-        
-        #default cfg, grp, id from calling code info
-        moduleName, className, lineNumber = bpdb.getFrameCodeInfo(frameCount=frameCount+1)
-        if moduleName:  #use only leaf module name
-            moduleName = moduleName.split('.')[-1]
-        self.grp = grp or className or moduleName
-        self.id = id or lineNumber
-
-        #default cfg to stripped module name
-        if cfg is None and moduleName:
-            cfg = moduleName.lower()
-            if cfg.find("distributed") == 0:        #prune leading 'Distributed'
-                cfg = cfg[len("distributed"):]
-
-        # check cfgs
-        self.cfg = cfg
-        if not bpdb.verifyConfig(self.cfg):
-            self.disabled = True
-            return
-
-    def getParts(self):
-        return {'id':self.id,'grp':self.grp,'cfg':self.cfg}
-        
-    def displayContextHint(self, displayPrefix=''):
-        contextString = displayPrefix + bpdb.bpMan.partsToPath({'id':self.id,'grp':self.grp,'cfg':self.cfg})
-        dashes = '-'*max(0, (80 - len(contextString) - 4) / 2)
-        print '<%s %s %s>'%(dashes,contextString,dashes)
-    
-    def maybeBreak(self, test=None, frameCount=1, displayPrefix=''):
-        if self.shouldBreak(test=test):
-            self.doBreak(frameCount=frameCount+1,displayPrefix=displayPrefix)
-    
-    def shouldBreak(self, test=None):
-        #check easy early out
-        if self.disabled:
-            return False
-        if test:
-            if not isinstance(test, (list, tuple)):
-                test = (test,)
-            for atest in test:
-                if not atest():
-                    return False
-
-        #check disabled conditions
-        if not bpdb.bpMan.getEnabled({'grp':self.grp,'id':self.id}):
-            return False
-        if not bpdb.verifyConfig(self.cfg):
-            return False
-
-        #check skip conditions
-        if bpdb.bpMan.getIgnoreCount({'grp':self.grp,'id':self.id},decrement=True):
-            return False
-        if bpdb.bpMan.getLifetime({'grp':self.grp,'id':self.id}) == 0:
-            return False
-
-        #all conditions go
-        return True
-        
-    def doBreak(self, frameCount=1,displayPrefix=''):
-        #accumulate hit count
-        bpdb.bpMan.decLifetime({'grp':self.grp,'id':self.id})
-        bpdb.bpMan.incHitCount({'grp':self.grp,'id':self.id})
-        
-        #setup debugger
-        self.displayContextHint(displayPrefix=displayPrefix)
-        bpdb.set_trace(self, frameCount=frameCount+1)
-

+ 1 - 1
direct/src/showbase/BufferViewer.py

@@ -2,7 +2,7 @@
 
 __all__ = ['BufferViewer']
 
-from pandac.PandaModules import *
+from panda3d.core import *
 from direct.task import Task
 from direct.directnotify.DirectNotifyGlobal import *
 from direct.showbase.DirectObject import DirectObject

+ 0 - 4
direct/src/showbase/DirectObject.py

@@ -5,7 +5,6 @@ __all__ = ['DirectObject']
 
 from direct.directnotify.DirectNotifyGlobal import directNotify
 from MessengerGlobal import messenger
-from direct.showbase.PythonUtil import ClassTree
 
 class DirectObject:
     """
@@ -42,9 +41,6 @@ class DirectObject:
     def isIgnoring(self, event):
         return messenger.isIgnoring(event, self)
 
-    def classTree(self):
-        return ClassTree(self)
-
     #This function must be used if you want a managed task
     def addTask(self, *args, **kwargs):
         if(not hasattr(self,"_taskList")):

+ 8 - 36
direct/src/showbase/EventManager.py

@@ -5,11 +5,8 @@ __all__ = ['EventManager']
 
 from MessengerGlobal import *
 from direct.directnotify.DirectNotifyGlobal import *
-
-# This module may not import pandac.PandaModules, since it is imported
-# by the Toontown Launcher before the complete PandaModules have been
-# downloaded.
-#from pandac.PandaModules import *
+from direct.task.TaskManagerGlobal import taskMgr
+from panda3d.core import PStatCollector, EventQueue, EventHandler
 
 class EventManager:
 
@@ -18,11 +15,6 @@ class EventManager:
     # delayed import, since this is imported by the Toontown Launcher
     # before the complete PandaModules have been downloaded.
     PStatCollector = None
-
-    # for efficiency, only call import once per module
-    EventStorePandaNode = None
-    EventQueue = None
-    EventHandler = None
     
     def __init__(self, eventQueue = None):
         """
@@ -43,7 +35,6 @@ class EventManager:
         """
         if self._wantPstats is None:
             self._wantPstats = config.GetBool('pstats-eventmanager', 0)
-            from pandac.PandaModules import PStatCollector
             EventManager.PStatCollector = PStatCollector
         # use different methods for handling events with and without pstats tracking
         # for efficiency
@@ -80,18 +71,8 @@ class EventManager:
             return None
         else:
             # Must be some user defined type, return the ptr
-            # which will be downcast to that type
-            ptr = eventParameter.getPtr()
-
-            if EventManager.EventStorePandaNode is None:
-                from pandac.PandaModules import EventStorePandaNode
-                EventManager.EventStorePandaNode = EventStorePandaNode
-            if isinstance(ptr, EventManager.EventStorePandaNode):
-                # Actually, it's a kludgey wrapper around a PandaNode
-                # pointer.  Return the node.
-                ptr = ptr.getValue()
-
-            return ptr
+            # which will be downcast to that type.
+            return eventParameter.getPtr()
         
     def processEvent(self, event):
         """
@@ -190,28 +171,19 @@ class EventManager:
 
 
     def restart(self):
-        if None in (EventManager.EventQueue, EventManager.EventHandler):
-            from pandac.PandaModules import EventQueue, EventHandler
-            EventManager.EventQueue = EventQueue
-            EventManager.EventHandler = EventHandler
-        
         if self.eventQueue == None:
-            self.eventQueue = EventManager.EventQueue.getGlobalEventQueue()
+            self.eventQueue = EventQueue.getGlobalEventQueue()
 
         if self.eventHandler == None:
-            if self.eventQueue == EventManager.EventQueue.getGlobalEventQueue():
+            if self.eventQueue == EventQueue.getGlobalEventQueue():
                 # If we are using the global event queue, then we also
                 # want to use the global event handler.
-                self.eventHandler = EventManager.EventHandler.getGlobalEventHandler()
+                self.eventHandler = EventHandler.getGlobalEventHandler()
             else:
                 # Otherwise, we need our own event handler.
-                self.eventHandler = EventManager.EventHandler(self.eventQueue)
+                self.eventHandler = EventHandler(self.eventQueue)
 
-        # Should be safe to import the global taskMgr by now.
-        from direct.task.TaskManagerGlobal import taskMgr
         taskMgr.add(self.eventLoopTask, 'eventManager')
 
     def shutdown(self):
-        # Should be safe to import the global taskMgr by now.
-        from direct.task.TaskManagerGlobal import taskMgr
         taskMgr.remove('eventManager')

+ 3 - 3
direct/src/showbase/ExceptionVarDump.py

@@ -1,4 +1,4 @@
-from pandac.PandaModules import getConfigShowbase
+from panda3d.direct import get_config_showbase
 from direct.directnotify.DirectNotifyGlobal import directNotify
 from direct.showbase.PythonUtil import fastRepr
 import sys
@@ -6,7 +6,7 @@ import types
 import traceback
 
 notify = directNotify.newCategory("ExceptionVarDump")
-config = getConfigShowbase()
+config = get_config_showbase()
 
 reentry = 0
 
@@ -154,7 +154,7 @@ def _excepthookDumpVars(eType, eValue, tb):
                     for attrName in attrNames:
                         obj = attrName2obj[attrName]
                         stateStack.push(['%s.%s' % (name, attrName), obj, ids])
-                
+
         tb = tb.tb_next
 
     if foundRun:

+ 1 - 1
direct/src/showbase/Job.py

@@ -1,7 +1,7 @@
 from direct.showbase.DirectObject import DirectObject
 
 if __debug__:
-    from pandac.PandaModules import PStatCollector
+    from panda3d.core import PStatCollector
 
 class Job(DirectObject):
     # Base class for cpu-intensive or non-time-critical operations that

+ 5 - 75
direct/src/showbase/Messenger.py

@@ -7,78 +7,8 @@ from PythonUtil import *
 from direct.directnotify import DirectNotifyGlobal
 import types
 
-from panda3d.core import ConfigVariableBool
-
-# If using the Toontown ActiveX launcher, this must be set true.
-# Also, Panda must be compiled with SIMPLE_THREADS or no HAVE_THREADS
-# at all.  In the normal Panda case, this should be set false.
-if ConfigVariableBool('delay-messenger-lock', False).getValue():
-    class Lock:
-        """ This is a cheesy delayed implementation of Lock, designed to
-        support the Toontown ActiveX launch, which must import Messenger
-        before it has downloaded the rest of Panda.  Note that this
-        cheesy lock isn't thread-safe if the application starts any
-        threads before acquiring the Messenger lock the first time.
-        (However, it's mostly thread-safe if Panda is compiled with
-        SIMPLE_THREADS.) """
-
-        notify = DirectNotifyGlobal.directNotify.newCategory("Messenger.Lock")
-
-        def __init__(self):
-            self.locked = 0
-
-        def acquire(self):
-            # Before we download Panda, we can't use any threading
-            # interfaces.  So don't, until we observe that we have some
-            # actual contention on the lock.
-
-            if self.locked:
-                # We have contention.
-                return self.__getLock()
-
-            # This relies on the fact that any individual Python statement
-            # is atomic.
-            self.locked += 1
-            if self.locked > 1:
-                # Whoops, we have contention.
-                self.locked -= 1
-                return self.__getLock()
-
-        def release(self):
-            if self.locked:
-                # Still using the old, cheesy lock.
-                self.locked -= 1
-                return
-
-            # The new lock must have been put in place.
-            self.release = self.lock.release
-            return self.lock.release()
-
-        def __getLock(self):
-            # Now that we've started Panda, it's safe to import the Mutex
-            # class, which becomes our actual lock.
-            # From now on, this lock will be used.
-
-            self.notify.info("Acquiring Panda lock for the first time.")
-
-            from pandac.PandaModules import Thread, Mutex
-            self.__dict__.setdefault('lock', Mutex('Messenger'))
-            self.lock.acquire()
-
-            self.acquire = self.lock.acquire
-
-            # Wait for the cheesy lock to be released before we return.
-            self.notify.info("Waiting for cheesy lock to be released.")
-            while self.locked:
-                Thread.forceYield()
-            self.notify.info("Got cheesy lock.")
-
-            # We return with the lock acquired.
-else:            
-    # In the normal case, there's no reason not to import all of
-    # libpanda right away, and so we can just use Lock directly.  This
-    # is perfectly thread-safe.
-    from direct.stdpy.threading import Lock
+from panda3d.core import ConfigVariableBool, Thread, Mutex
+from direct.stdpy.threading import Lock
 
 class Messenger:
 
@@ -215,7 +145,7 @@ class Messenger:
             # on this particular object.
             if id in acceptorDict:
                 # TODO: we're replacing the existing callback. should this be an error?
-                if notifyDebug:        
+                if notifyDebug:
                     oldMethod = acceptorDict[id][0]
                     if oldMethod == method:
                         self.notify.warning(
@@ -420,7 +350,7 @@ class Messenger:
                 if not eventTuple:
                     # No event; we're done.
                     return task.done
-                
+
                 self.__dispatch(*eventTuple)
             finally:
                 self.lock.release()
@@ -450,7 +380,7 @@ class Messenger:
                         if (len(eventDict) == 0):
                             del self.__objectEvents[id]
                         self._releaseObject(self._getObject(id))
-                        
+
                     del acceptorDict[id]
                     # If the dictionary at this event is now empty, remove
                     # the event entry from the Messenger altogether

+ 0 - 12
direct/src/showbase/PandaObject.py

@@ -1,12 +0,0 @@
-"""Undocumented Module"""
-
-__all__ = []
-
-## from DirectObject import *
-## from pandac.PandaModules import *
-## 
-## class PandaObject(DirectObject):
-##     """
-##     This is the class that all Panda/Show classes should inherit from
-##     """
-##     pass

+ 1 - 1
direct/src/showbase/PhysicsManagerGlobal.py

@@ -2,6 +2,6 @@
 
 __all__ = ['physicsMgr']
 
-from pandac.PandaModules import PhysicsManager
+from panda3d.physics import PhysicsManager
 
 physicsMgr = PhysicsManager()

File diff suppressed because it is too large
+ 18 - 966
direct/src/showbase/PythonUtil.py


+ 71 - 64
direct/src/showbase/ShowBase.py

@@ -8,11 +8,11 @@ __all__ = ['ShowBase', 'WindowControls']
 #import VerboseImport
 
 from panda3d.core import *
-from panda3d.direct import *
+from panda3d.direct import get_config_showbase, throw_new_frame, init_app_for_gui
 
 # This needs to be available early for DirectGUI imports
 import __builtin__
-__builtin__.config = getConfigShowbase()
+__builtin__.config = get_config_showbase()
 
 from direct.directnotify.DirectNotifyGlobal import *
 from MessengerGlobal import *
@@ -46,7 +46,7 @@ import AppRunnerGlobal
 
 __builtin__.FADE_SORT_INDEX = 1000
 __builtin__.NO_FADE_SORT_INDEX = 2000
-    
+
 
 # Now ShowBase is a DirectObject.  We need this so ShowBase can hang
 # hooks on messages, particularly on window-event.  This doesn't
@@ -58,7 +58,7 @@ class ShowBase(DirectObject.DirectObject):
     def __init__(self, fStartDirect = True, windowType = None):
         self.__dev__ = config.GetBool('want-dev', __debug__)
         __builtin__.__dev__ = self.__dev__
-        
+
         logStackDump = (config.GetBool('log-stack-dump', False) or
                         config.GetBool('client-log-stack-dump', False))
         uploadStackDump = config.GetBool('upload-stack-dump', False)
@@ -74,7 +74,7 @@ class ShowBase(DirectObject.DirectObject):
 
         #debug running multiplier
         self.debugRunningMultiplier = 4
-        
+
         # Get the dconfig object
         self.config = config
         # Setup wantVerifyPdb as soon as reasonable:
@@ -91,7 +91,7 @@ class ShowBase(DirectObject.DirectObject):
         self.nextWindowIndex = 1
         self.__directStarted = False
         self.__deadInputs = 0
-        
+
         # Store dconfig variables
         self.sfxActive = self.config.GetBool('audio-sfx-active', 1)
         self.musicActive = self.config.GetBool('audio-music-active', 1)
@@ -253,7 +253,7 @@ class ShowBase(DirectObject.DirectObject):
 
         self.loader = Loader.Loader(self)
         self.graphicsEngine.setDefaultLoader(self.loader.loader)
-            
+
         self.eventMgr = eventMgr
         self.messenger = messenger
         self.bboard = bulletinBoard
@@ -315,7 +315,7 @@ class ShowBase(DirectObject.DirectObject):
         # Make sure we're not making more than one ShowBase.
         if 'base' in __builtin__.__dict__:
             raise StandardError, "Attempt to spawn multiple ShowBase instances!"
-        
+
         __builtin__.base = self
         __builtin__.render2d = self.render2d
         __builtin__.aspect2d = self.aspect2d
@@ -357,7 +357,7 @@ class ShowBase(DirectObject.DirectObject):
 
         # set up recording of Functor creation stacks in __dev__
         PythonUtil.recordFunctorCreationStacks()
-        
+
         if __dev__ or self.config.GetBool('want-e3-hacks', False):
             if self.config.GetBool('track-gui-items', True):
                 # dict of guiId to gui item, for tracking down leaks
@@ -372,6 +372,7 @@ class ShowBase(DirectObject.DirectObject):
         # Now hang a hook on the window-event from Panda.  This allows
         # us to detect when the user resizes, minimizes, or closes the
         # main window.
+        self.__prevWindowProperties = None
         self.accept('window-event', self.windowEvent)
 
         # Transition effects (fade, iris, etc)
@@ -386,7 +387,7 @@ class ShowBase(DirectObject.DirectObject):
         sleepTime = self.config.GetFloat('client-sleep', 0.0)
         self.clientSleep = 0.0
         self.setSleep(sleepTime)
-        
+
         # Extra sleep for running 4+ clients on a single machine
         # adds a sleep right after the main render in igloop
         # tends to even out the frame rate and keeps it from going
@@ -414,7 +415,7 @@ class ShowBase(DirectObject.DirectObject):
 
         # Start IGLOOP
         self.restart()
-        
+
     # add a collision traverser via pushCTrav and remove it via popCTrav
     # that way the owner of the new cTrav doesn't need to hold onto the
     # previous one in order to put it back
@@ -427,7 +428,7 @@ class ShowBase(DirectObject.DirectObject):
     def __setupProfile(self):
         """ Sets up the Python profiler, if avaialable, according to
         some Panda config settings. """
-        
+
         try:
             import profile, pstats
         except ImportError:
@@ -499,7 +500,7 @@ class ShowBase(DirectObject.DirectObject):
 
         vfs = VirtualFileSystem.getGlobalPtr()
         vfs.unmountAll()
-        
+
 
     def exitfunc(self):
         """
@@ -609,7 +610,7 @@ class ShowBase(DirectObject.DirectObject):
 
         If requireWindow is true, it means that the function should
         raise an exception if the window fails to open correctly.
-        
+
         """
 
         # Save this lambda here for convenience; we'll use it to call
@@ -622,19 +623,19 @@ class ShowBase(DirectObject.DirectObject):
             keepCamera = keepCamera, scene = scene, stereo = stereo,
             unexposedDraw = unexposedDraw,
             callbackWindowDict = callbackWindowDict)
-        
+
         if self.win:
             # If we've already opened a window before, this is just a
             # pass-through to _doOpenWindow().
             win = func()
             self.graphicsEngine.openWindows()
             return win
-        
+
         if type is None:
             type = self.windowType
         if requireWindow is None:
             requireWindow = self.requireWindow
-            
+
         win = func()
 
         # Give the window a chance to truly open.
@@ -699,7 +700,7 @@ class ShowBase(DirectObject.DirectObject):
             # GSG from that buffer.
             host = gsg
             gsg = gsg.getGsg()
-            
+
         # If we are using DirectX, force a new GSG to be created,
         # since at the moment DirectX seems to misbehave if we do
         # not do this.  This will cause a delay while all textures
@@ -764,7 +765,7 @@ class ShowBase(DirectObject.DirectObject):
                 func = callbackWindowDict.get(callbackName, None)
                 if not func:
                     continue
-                
+
                 setCallbackName = 'set%sCallback' % (callbackName)
                 setCallback = getattr(win, setCallbackName)
                 setCallback(PythonCallbackObject(func))
@@ -804,10 +805,10 @@ class ShowBase(DirectObject.DirectObject):
         pointer to None.
         """
         win.setActive(False)
-        
+
         # First, remove all of the cameras associated with display
         # regions on the window.
-        numRegions = win.getNumDisplayRegions()        
+        numRegions = win.getNumDisplayRegions()
         for i in range(numRegions):
             dr = win.getDisplayRegion(i)
             # [gjeon] remove drc in base.direct.drList
@@ -816,9 +817,9 @@ class ShowBase(DirectObject.DirectObject):
                     if drc.cam == dr.getCamera():
                         base.direct.drList.displayRegionList.remove(drc)
                         break
-                    
+
             cam = NodePath(dr.getCamera())
-            
+
             dr.setCamera(NodePath())
 
             if not cam.isEmpty() and \
@@ -905,7 +906,7 @@ class ShowBase(DirectObject.DirectObject):
         closed window).
         """
         keepCamera = kw.get('keepCamera', False)
-        
+
         success = 1
         oldWin = self.win
         oldLens = self.camLens
@@ -1066,7 +1067,7 @@ class ShowBase(DirectObject.DirectObject):
         self.aspect2d = self.render2d.attachNewNode(PGTop("aspect2d"))
         self.aspect2d.setScale(1.0 / aspectRatio, 1.0, 1.0)
 
-        self.a2dBackground = self.aspect2d.attachNewNode("a2dBackground") 
+        self.a2dBackground = self.aspect2d.attachNewNode("a2dBackground")
 
         # It's important to know the bounds of the aspect2d screen.
         self.a2dTop = 1.0
@@ -1110,7 +1111,7 @@ class ShowBase(DirectObject.DirectObject):
         self.a2dBottomLeftNs.setPos(self.a2dLeft, 0, self.a2dBottom)
         self.a2dBottomRight.setPos(self.a2dRight, 0, self.a2dBottom)
         self.a2dBottomRightNs.setPos(self.a2dRight, 0, self.a2dBottom)
-        
+
         # This special root, pixel2d, uses units in pixels that are relative
         # to the window. The upperleft corner of the window is (0, 0),
         # the lowerleft corner is (xsize, -ysize), in this coordinate system.
@@ -1182,7 +1183,7 @@ class ShowBase(DirectObject.DirectObject):
         self.a2dpTopRight.setPos(self.a2dpRight, 0, self.a2dpTop)
         self.a2dpBottomLeft.setPos(self.a2dpLeft, 0, self.a2dpBottom)
         self.a2dpBottomRight.setPos(self.a2dpRight, 0, self.a2dpBottom)
-        
+
         # This special root, pixel2d, uses units in pixels that are relative
         # to the window. The upperleft corner of the window is (0, 0),
         # the lowerleft corner is (xsize, -ysize), in this coordinate system.
@@ -1229,7 +1230,7 @@ class ShowBase(DirectObject.DirectObject):
 
         if aspectRatio == 0:
             return 1
-        
+
         return aspectRatio
 
     def getSize(self, win = None):
@@ -1337,7 +1338,7 @@ class ShowBase(DirectObject.DirectObject):
         # we will if clearDepth is specified.
         if clearDepth:
             dr.setClearDepthActive(1)
-            
+
         if clearColor:
             dr.setClearColorActive(1)
             dr.setClearColor(clearColor)
@@ -1370,7 +1371,7 @@ class ShowBase(DirectObject.DirectObject):
             cam2dNode = Camera('cam2d_' + cameraName)
         else:
             cam2dNode = Camera('cam2d')
-            
+
         if lens == None:
             lens = OrthographicLens()
             lens.setFilmSize(right - left, top - bottom)
@@ -1480,12 +1481,12 @@ class ShowBase(DirectObject.DirectObject):
 
         if fMultiWin:
             return bts[0]
-        
+
         self.buttonThrowers = bts[:]
         self.pointerWatcherNodes = pws[:]
 
         self.mouseWatcher = self.buttonThrowers[0].getParent()
-        self.mouseWatcherNode = self.mouseWatcher.node()  
+        self.mouseWatcherNode = self.mouseWatcher.node()
 
         if self.mouseInterface:
             self.mouseInterface.reparentTo(self.mouseWatcher)
@@ -1553,7 +1554,7 @@ class ShowBase(DirectObject.DirectObject):
                 # track the left and right halves of the screen
                 # individually.
                 mw.node().setDisplayRegion(win.getOverlayDisplayRegion())
-                
+
             mb = mw.node().getModifierButtons()
             mb.addButton(KeyboardButton.shift())
             mb.addButton(KeyboardButton.control())
@@ -1675,7 +1676,7 @@ class ShowBase(DirectObject.DirectObject):
             port = -1
         PStatClient.connect(hostname, port)
         return PStatClient.isConnected()
-                
+
 
     def addSfxManager(self, extraSfxManager):
         # keep a list of sfx manager objects to apply settings to,
@@ -1841,11 +1842,11 @@ class ShowBase(DirectObject.DirectObject):
         case we're responsible for taking out Panda's garbage from
         time to time.  This is not to be confused with Python's
         garbage collection.  """
-        
+
         TransformState.garbageCollect()
         RenderState.garbageCollect()
         return Task.cont
-        
+
     def __igLoop(self, state):
         # We render the watch variables for the onScreenDebug as soon
         # as we reasonably can before the renderFrame().
@@ -1881,7 +1882,7 @@ class ShowBase(DirectObject.DirectObject):
 
         # Lerp stuff needs this event, and it must be generated in
         # C++, not in Python.
-        throwNewFrame()
+        throw_new_frame()
         return Task.cont
 
 
@@ -1927,8 +1928,8 @@ class ShowBase(DirectObject.DirectObject):
 
         # Lerp stuff needs this event, and it must be generated in
         # C++, not in Python.
-        throwNewFrame()
-        return Task.cont    
+        throw_new_frame()
+        return Task.cont
 
     def restart(self,clusterSync=False,cluster=None):
         self.shutdown()
@@ -2196,7 +2197,7 @@ class ShowBase(DirectObject.DirectObject):
 
         self.showVertices = self.cam.attachNewNode(cam)
         dr.setCamera(self.showVertices)
-        
+
 
     def oobe(self, cam = None):
         """
@@ -2221,7 +2222,7 @@ class ShowBase(DirectObject.DirectObject):
         """
         if cam is None:
             cam = self.cam
-            
+
         # If oobeMode was never set, set it to false and create the
         # structures we need to implement OOBE.
         if not hasattr(self, 'oobeMode'):
@@ -2614,9 +2615,15 @@ class ShowBase(DirectObject.DirectObject):
             return Task.cont
 
     def windowEvent(self, win):
-        if win == self.win:
-            properties = win.getProperties()
-            self.notify.info("Got window event: %s" % (repr(properties)))
+        if win != self.win:
+            # This event isn't about our window.
+            return
+
+        properties = win.getProperties()
+        if properties != self.__prevWindowProperties:
+            self.__prevWindowProperties = properties
+
+            self.notify.debug("Got window event: %s" % (repr(properties)))
             if not properties.getOpen():
                 # If the user closes the main window, we should exit.
                 self.notify.info("User closed main window.")
@@ -2645,7 +2652,7 @@ class ShowBase(DirectObject.DirectObject):
             # If we have not forced the aspect ratio, let's see if it has
             # changed and update the camera lenses and aspect2d parameters
             self.adjustWindowAspectRatio(self.getAspectRatio())
-            
+
             # Temporary hasattr for old Pandas
             if not hasattr(win, 'getSbsLeftXSize'):
                 self.pixel2d.setScale(2.0 / win.getXSize(), 1.0, 2.0 / win.getYSize())
@@ -2659,7 +2666,7 @@ class ShowBase(DirectObject.DirectObject):
         windowEvent(), but it may also be called to explicitly adjust
         the aspect ratio of the render/render2d DisplayRegion, by a
         class that has redefined these. """
-        
+
         if self.__configAspectRatio:
             aspectRatio = self.__configAspectRatio
 
@@ -2694,13 +2701,13 @@ class ShowBase(DirectObject.DirectObject):
                 self.a2dpTop = 1.0
                 self.a2dpBottom = -1.0
                 self.a2dpLeft = -aspectRatio
-                self.a2dpRight = aspectRatio                        
+                self.a2dpRight = aspectRatio
 
             # Reposition the aspect2d marker nodes
             self.a2dTopCenter.setPos(0, self.a2dTop, self.a2dTop)
             self.a2dBottomCenter.setPos(0, self.a2dBottom, self.a2dBottom)
             self.a2dLeftCenter.setPos(self.a2dLeft, 0, 0)
-            self.a2dRightCenter.setPos(self.a2dRight, 0, 0)                    
+            self.a2dRightCenter.setPos(self.a2dRight, 0, 0)
             self.a2dTopLeft.setPos(self.a2dLeft, self.a2dTop, self.a2dTop)
             self.a2dTopRight.setPos(self.a2dRight, self.a2dTop, self.a2dTop)
             self.a2dBottomLeft.setPos(self.a2dLeft, self.a2dBottom, self.a2dBottom)
@@ -2710,17 +2717,17 @@ class ShowBase(DirectObject.DirectObject):
             self.a2dTopCenterNs.setPos(0, self.a2dTop, self.a2dTop)
             self.a2dBottomCenterNs.setPos(0, self.a2dBottom, self.a2dBottom)
             self.a2dLeftCenterNs.setPos(self.a2dLeft, 0, 0)
-            self.a2dRightCenterNs.setPos(self.a2dRight, 0, 0)                    
+            self.a2dRightCenterNs.setPos(self.a2dRight, 0, 0)
             self.a2dTopLeftNs.setPos(self.a2dLeft, self.a2dTop, self.a2dTop)
             self.a2dTopRightNs.setPos(self.a2dRight, self.a2dTop, self.a2dTop)
             self.a2dBottomLeftNs.setPos(self.a2dLeft, self.a2dBottom, self.a2dBottom)
-            self.a2dBottomRightNs.setPos(self.a2dRight, self.a2dBottom, self.a2dBottom)                    
+            self.a2dBottomRightNs.setPos(self.a2dRight, self.a2dBottom, self.a2dBottom)
 
             # Reposition the aspect2dp marker nodes
             self.a2dpTopCenter.setPos(0, self.a2dpTop, self.a2dpTop)
             self.a2dpBottomCenter.setPos(0, self.a2dpBottom, self.a2dpBottom)
             self.a2dpLeftCenter.setPos(self.a2dpLeft, 0, 0)
-            self.a2dpRightCenter.setPos(self.a2dpRight, 0, 0)                  
+            self.a2dpRightCenter.setPos(self.a2dpRight, 0, 0)
             self.a2dpTopLeft.setPos(self.a2dpLeft, self.a2dpTop, self.a2dpTop)
             self.a2dpTopRight.setPos(self.a2dpRight, self.a2dpTop, self.a2dpTop)
             self.a2dpBottomLeft.setPos(self.a2dpLeft, self.a2dpBottom, self.a2dpBottom)
@@ -2728,7 +2735,7 @@ class ShowBase(DirectObject.DirectObject):
 
             # If anybody needs to update their GUI, put a callback on this event
             messenger.send("aspectRatioChanged")
-        
+
     def userExit(self):
         # The user has requested we exit the program.  Deal with this.
         if self.exitFunc:
@@ -2752,12 +2759,12 @@ class ShowBase(DirectObject.DirectObject):
         This sets up a wxTimer callback so that Panda still gets
         updated, but wxPython owns the main loop (which seems to make
         it happier than the other way around). """
-        
+
         if self.wxApp:
             # Don't do this twice.
             return
 
-        initAppForGui()
+        init_app_for_gui()
 
         import wx
         # Create a new base.wxApp.
@@ -2767,7 +2774,7 @@ class ShowBase(DirectObject.DirectObject):
             # Put wxPython in charge of the main loop.  It really
             # seems to like this better; some features of wx don't
             # work properly unless this is true.
-            
+
             # Set a timer to run the Panda frame 60 times per second.
             wxFrameRate = ConfigVariableDouble('wx-frame-rate', 60.0)
             self.wxTimer = wx.Timer(self.wxApp)
@@ -2802,19 +2809,19 @@ class ShowBase(DirectObject.DirectObject):
             # This happens when the wxTimer expires while igLoop is
             # rendering.  Ignore it.
             return
-        
+
         self.taskMgr.step()
 
     def wxRun(self):
         """ This method replaces base.run() after we have called
         spawnWxLoop().  Since at this point wxPython now owns the main
         loop, this method is a call to wxApp.MainLoop(). """
-        
+
         if Thread.getCurrentThread().getCurrentTask():
             # This happens in the p3d environment during startup.
             # Ignore it.
             return
-        
+
         self.wxApp.MainLoop()
 
     def startTk(self, fWantTk = True):
@@ -2829,7 +2836,7 @@ class ShowBase(DirectObject.DirectObject):
         This sets up a timer callback so that Panda still gets
         updated, but Tkinter owns the main loop (which seems to make
         it happier than the other way around). """
-        
+
         if self.tkRoot:
             # Don't do this twice.
             return
@@ -2841,13 +2848,13 @@ class ShowBase(DirectObject.DirectObject):
         self.tkRoot = Pmw.initialise()
         __builtin__.tkroot = self.tkRoot
 
-        initAppForGui()
+        init_app_for_gui()
 
         if ConfigVariableBool('tk-main-loop', True):
             # Put Tkinter in charge of the main loop.  It really
             # seems to like this better; the GUI otherwise becomes
             # largely unresponsive on Mac OS X unless this is true.
-            
+
             # Set a timer to run the Panda frame 60 times per second.
             tkFrameRate = ConfigVariableDouble('tk-frame-rate', 60.0)
             self.tkDelay = int(1000.0 / tkFrameRate.getValue())
@@ -2885,12 +2892,12 @@ class ShowBase(DirectObject.DirectObject):
         """ This method replaces base.run() after we have called
         spawnTkLoop().  Since at this point Tkinter now owns the main
         loop, this method is a call to tkRoot.mainloop(). """
-        
+
         if Thread.getCurrentThread().getCurrentTask():
             # This happens in the p3d environment during startup.
             # Ignore it.
             return
-        
+
         self.tkRoot.mainloop()
 
     def startDirect(self, fWantDirect = 1, fWantTk = 1, fWantWx = 0):
@@ -2913,7 +2920,7 @@ class ShowBase(DirectObject.DirectObject):
         if self.__directStarted:
             return
         self.__directStarted = False
-        
+
         # Start Tk, Wx and DIRECT if specified by Config.prc
         fTk = self.config.GetBool('want-tk', 0)
         fWx = self.config.GetBool('want-wx', 0)

+ 24 - 23
direct/src/showbase/VFSImporter.py

@@ -1,14 +1,13 @@
+__all__ = ['register', 'sharedPackages',
+           'reloadSharedPackage', 'reloadSharedPackages']
+
 from panda3d.core import Filename, VirtualFileSystem, VirtualFileMountSystem, OFileStream, copyStream
 import sys
-import os
 import marshal
 import imp
 import types
 import __builtin__
 
-__all__ = ['register', 'sharedPackages',
-           'reloadSharedPackage', 'reloadSharedPackages']
-
 # The sharedPackages dictionary lists all of the "shared packages",
 # special Python packages that automatically span multiple directories
 # via magic in the VFSImporter.  You can make a package "shared"
@@ -76,14 +75,13 @@ class VFSImporter:
         for desc in imp.get_suffixes():
             if desc[2] != imp.C_EXTENSION:
                 continue
-            
+
             filename = Filename(path)
             filename.setExtension(desc[0][1:])
             vfile = vfs.getFile(filename, True)
             if vfile:
                 return VFSLoader(dir_path, vfile, filename, FTExtensionModule,
                                  desc = desc)
-        
 
         # Finally, consider a package, i.e. a directory containing
         # __init__.py.
@@ -105,7 +103,7 @@ class VFSImporter:
 class VFSLoader:
     """ The second part of VFSImporter, this is created for a
     particular .py file or directory. """
-    
+
     def __init__(self, dir_path, vfile, filename, fileType,
                  desc = None, packagePath = None):
         self.dir_path = dir_path
@@ -116,7 +114,7 @@ class VFSLoader:
         self.fileType = fileType
         self.desc = desc
         self.packagePath = packagePath
-    
+
     def load_module(self, fullname, loadingShared = False):
         #print >>sys.stderr, "load_module(%s), dir_path = %s, filename = %s" % (fullname, self.dir_path, self.filename)
         if self.fileType == FTFrozenModule:
@@ -136,11 +134,11 @@ class VFSLoader:
                 loader = importer.find_module(fullname, path = path)
                 assert loader
                 return loader.load_module(fullname)
-        
+
         code = self._read_code()
         if not code:
             raise ImportError, 'No Python code in %s' % (fullname)
-        
+
         mod = sys.modules.setdefault(fullname, imp.new_module(fullname))
         mod.__file__ = self.filename.toOsSpecific()
         mod.__loader__ = self
@@ -169,15 +167,15 @@ class VFSLoader:
 
     def get_filename(self, fullname):
         return self.filename.toOsSpecific()
-        
+
     def _read_source(self):
         """ Returns the Python source for this file, if it is
         available, or None if it is not.  May raise IOError. """
-        
+
         if self.fileType == FTPythonCompiled or \
            self.fileType == FTExtensionModule:
             return None
-        
+
         filename = Filename(self.filename)
         filename.setExtension('py')
         filename.setText()
@@ -281,7 +279,7 @@ class VFSLoader:
     def _loadPyc(self, vfile, timestamp):
         """ Reads and returns the marshal data from a .pyc file.
         Raises ValueError if there is a problem. """
-        
+
         code = None
         data = vfile.readFile(True)
         if data[:4] == imp.get_magic():
@@ -294,13 +292,13 @@ class VFSLoader:
         else:
             raise ValueError, 'Bad magic number in %s' % (vfile)
         return code
-        
+
 
     def _compile(self, filename, source):
         """ Compiles the Python source code to a code object and
         attempts to write it to an appropriate .pyc file.  May raise
         SyntaxError or other errors generated by the compiler. """
-        
+
         if source and source[-1] != '\n':
             source = source + '\n'
         code = __builtin__.compile(source, filename.toOsSpecific(), 'exec')
@@ -335,7 +333,7 @@ class VFSSharedImporter:
 
     def __init__(self):
         pass
-    
+
     def find_module(self, fullname, path = None, reload = False):
         #print >>sys.stderr, "shared find_module(%s), path = %s" % (fullname, path)
 
@@ -364,14 +362,14 @@ class VFSSharedImporter:
         for dir in path:
             if dir in excludePaths:
                 continue
-            
+
             importer = sys.path_importer_cache.get(dir, None)
             if importer is None:
                 try:
                     importer = VFSImporter(dir)
                 except ImportError:
                     continue
-                
+
                 sys.path_importer_cache[dir] = importer
 
             try:
@@ -391,6 +389,9 @@ class VFSSharedImporter:
         """ Returns the directory name that the indicated
         conventionally-loaded module must have been loaded from. """
 
+        if not hasattr(mod, __file__) or mod.__file__ is None:
+            return None
+
         fullname = mod.__name__
         dirname = Filename.fromOsSpecific(mod.__file__).getDirname()
 
@@ -414,15 +415,15 @@ class VFSSharedImporter:
 
         # Couldn't figure it out.
         return None
-        
+
 class VFSSharedLoader:
     """ The second part of VFSSharedImporter, this imports a list of
     packages and combines them. """
-    
+
     def __init__(self, loaders, reload):
         self.loaders = loaders
         self.reload = reload
-    
+
     def load_module(self, fullname):
         #print >>sys.stderr, "shared load_module(%s), loaders = %s" % (fullname, map(lambda l: l.dir_path, self.loaders))
 
@@ -475,7 +476,7 @@ def register():
         _registered = True
         sys.path_hooks.insert(0, VFSImporter)
         sys.meta_path.insert(0, VFSSharedImporter())
-        
+
         # Blow away the importer cache, so we'll come back through the
         # VFSImporter for every folder in the future, even those
         # folders that previously were loaded directly.

+ 11 - 22
direct/src/showutil/FreezeTool.py

@@ -17,9 +17,8 @@ except ImportError:
     p3extend_frozen = None
 
 import direct
-from pandac.PandaModules import *
+from panda3d.core import *
 from pandac.extension_native_helpers import dll_suffix, dll_ext
-import panda3d
 
 # Check to see if we are running python_d, which implies we have a
 # debug build, and we have to build the module with debug options.
@@ -578,6 +577,8 @@ class Freezer:
         if self.platform.startswith('win'):
             self.objectExtension = '.obj'
 
+        self.keepTemporaryFiles = True
+
         # Change any of these to change the generated startup and glue
         # code.
         self.frozenMainCode = frozenMainCode
@@ -912,7 +913,7 @@ class Freezer:
                 continue
             if origName in self.modules:
                 continue
-                
+
             # This module is missing.  Let it be missing in the
             # runtime also.
             self.modules[origName] = self.ModuleDef(origName, exclude = True,
@@ -1110,7 +1111,7 @@ class Freezer:
             # The "module" may end in __init__, but that really means
             # the parent directory.
             dirnames = dirnames[:-1]
-            
+
         self.__addPythonDirs(multifile, moduleDirs, dirnames[:-1], compressionLevel)
 
         filename = '/'.join(dirnames)
@@ -1328,10 +1329,11 @@ class Freezer:
         try:
             compileFunc(filename, basename)
         finally:
-            if (os.path.exists(filename)):
-                os.unlink(filename)
-            if (os.path.exists(basename + self.objectExtension)):
-                os.unlink(basename + self.objectExtension)
+            if not self.keepTemporaryFiles:
+                if os.path.exists(filename):
+                    os.unlink(filename)
+                if os.path.exists(basename + self.objectExtension):
+                    os.unlink(basename + self.objectExtension)
 
         return target
 
@@ -1378,19 +1380,6 @@ class PandaModuleFinder(modulefinder.ModuleFinder):
     def __init__(self, *args, **kw):
         modulefinder.ModuleFinder.__init__(self, *args, **kw)
 
-    def import_module(self, partname, fqname, parent):
-        if parent and parent.__name__ == 'panda3d':
-            # A special case: map a reference to the "panda3d.blah"
-            # module into the appropriate Panda3D dll.
-            m = getattr(panda3d, partname, None)
-            if m and hasattr(m, '__libraries__'):
-                libname = m.__libraries__[-1]
-                partname = libname
-                fqname = libname
-                parent = None
-
-        return modulefinder.ModuleFinder.import_module(self, partname, fqname, parent)
-
     def find_module(self, name, path, parent=None):
         try:
             return modulefinder.ModuleFinder.find_module(self, name, path, parent = parent)
@@ -1425,7 +1414,7 @@ class PandaModuleFinder(modulefinder.ModuleFinder):
             m = self.add_module(fqname)
             m.__file__ = '<frozen>'
             if isPackage:
-                m.__path__ = pathname
+                m.__path__ = [pathname]
             co = marshal.loads(co)
             if self.replace_paths:
                 co = self.replace_paths_in_code(co)

+ 28 - 28
direct/src/stdpy/file.py

@@ -10,10 +10,10 @@ __all__ = [
     'execfile',
     ]
 
-from pandac import PandaModules as pm
+from panda3d import core
 import types
 
-_vfs = pm.VirtualFileSystem.getGlobalPtr()
+_vfs = core.VirtualFileSystem.getGlobalPtr()
 
 class file:
     def __init__(self, filename, mode = 'r', bufsize = None,
@@ -36,14 +36,14 @@ class file:
         readMode = False
         writeMode = False
 
-        if isinstance(filename, pm.Istream) or isinstance(filename, pm.Ostream):
+        if isinstance(filename, core.Istream) or isinstance(filename, core.Ostream):
             # If we were given a stream instead of a filename, assign
             # it directly.
             self.__stream = filename
-            readMode = isinstance(filename, pm.Istream)
-            writeMode = isinstance(filename, pm.Ostream)
+            readMode = isinstance(filename, core.Istream)
+            writeMode = isinstance(filename, core.Ostream)
 
-        elif isinstance(filename, pm.VirtualFile):
+        elif isinstance(filename, core.VirtualFile):
             # We can also "open" a VirtualFile object for reading.
             self.__stream = filename.openReadFile(autoUnwrap)
             if not self.__stream:
@@ -57,10 +57,10 @@ class file:
             if isinstance(filename, types.StringTypes):
                 # If a raw string is given, assume it's an os-specific
                 # filename.
-                filename = pm.Filename.fromOsSpecific(filename)
+                filename = core.Filename.fromOsSpecific(filename)
             else:
                 # If a Filename is given, make a writable copy anyway.
-                filename = pm.Filename(filename)
+                filename = core.Filename(filename)
 
             self.filename = filename
             self.name = filename.toOsSpecific()
@@ -97,7 +97,7 @@ class file:
                     message = 'Could not open %s for writing' % (filename)
                     raise IOError, message
                 writeMode = True
-                
+
             elif mode == 'a':
                 self.__stream = _vfs.openAppendFile(filename)
                 if not self.__stream:
@@ -142,14 +142,14 @@ class file:
             self.__needsVfsClose = True
 
         if readMode:
-            self.__reader = pm.StreamReader(self.__stream, False)
+            self.__reader = core.StreamReader(self.__stream, False)
         if writeMode:
-            self.__writer = pm.StreamWriter(self.__stream, False)
+            self.__writer = core.StreamWriter(self.__stream, False)
             self.__lastWrite = True
 
     def __del__(self):
         self.close()
-        
+
     def close(self):
         if self.__needsVfsClose:
             if self.__reader and self.__writer:
@@ -158,13 +158,13 @@ class file:
                 _vfs.closeReadFile(self.__stream)
             else:  # self.__writer:
                 _vfs.closeWriteFile(self.__stream)
-                
+
             self.__needsVfsClose = False
         self.__stream = None
         self.__needsVfsClose = False
         self.__reader = None
         self.__writer = None
-        
+
     def flush(self):
         if self.__stream:
             self.__stream.clear()  # clear eof flag
@@ -188,7 +188,7 @@ class file:
             # The stream is open only in write mode.
             message = 'Attempt to read from write-only stream'
             raise IOError, message
-        
+
         self.__stream.clear()  # clear eof flag
         self.__lastWrite = False
         if size >= 0:
@@ -199,7 +199,7 @@ class file:
             while not self.__stream.eof():
                 result += self.__reader.extractBytes(1024)
         return result
-        
+
     def readline(self, size = -1):
         if not self.__reader:
             if not self.__writer:
@@ -213,7 +213,7 @@ class file:
         self.__stream.clear()  # clear eof flag
         self.__lastWrite = False
         return self.__reader.readline()
-        
+
     def readlines(self, sizehint = -1):
         lines = []
         line = self.readline()
@@ -241,7 +241,7 @@ class file:
                 return self.__stream.tellg()
         message = 'I/O operation on closed file'
         raise ValueError, message
-    
+
     def truncate(self):
         """ Sorry, this isn't supported by Panda's low-level I/O,
         because it isn't supported by the standard C++ library. """
@@ -287,7 +287,7 @@ open = file
 def listdir(path):
     """ Implements os.listdir over vfs. """
     files = []
-    dirlist = _vfs.scanDirectory(pm.Filename.fromOsSpecific(path))
+    dirlist = _vfs.scanDirectory(core.Filename.fromOsSpecific(path))
     if dirlist is None:
         message = 'No such file or directory: %s' % (path)
         raise OSError, message
@@ -338,31 +338,31 @@ def join(path, *args):
     return path
 
 def isfile(path):
-    return _vfs.isRegularFile(pm.Filename.fromOsSpecific(path))
+    return _vfs.isRegularFile(core.Filename.fromOsSpecific(path))
 
 def isdir(path):
-    return _vfs.isDirectory(pm.Filename.fromOsSpecific(path))
+    return _vfs.isDirectory(core.Filename.fromOsSpecific(path))
 
 def exists(path):
-    return _vfs.exists(pm.Filename.fromOsSpecific(path))
+    return _vfs.exists(core.Filename.fromOsSpecific(path))
 
 def lexists(path):
-    return _vfs.exists(pm.Filename.fromOsSpecific(path))
-    
+    return _vfs.exists(core.Filename.fromOsSpecific(path))
+
 def getmtime(path):
-    file = _vfs.getFile(pm.Filename.fromOsSpecific(path), True)
+    file = _vfs.getFile(core.Filename.fromOsSpecific(path), True)
     if not file:
         raise os.error
     return file.getTimestamp()
-    
+
 def getsize(path):
-    file = _vfs.getFile(pm.Filename.fromOsSpecific(path), True)
+    file = _vfs.getFile(core.Filename.fromOsSpecific(path), True)
     if not file:
         raise os.error
     return file.getFileSize()
 
 def execfile(path, globals=None, locals=None):
-    file = _vfs.getFile(pm.Filename.fromOsSpecific(path), True)
+    file = _vfs.getFile(core.Filename.fromOsSpecific(path), True)
     if not file:
         raise os.error
 

+ 3 - 3
direct/src/stdpy/pickle.py

@@ -23,7 +23,7 @@ support extensions of this nature. """
 
 from types import *
 from copy_reg import dispatch_table
-from pandac.PandaModules import BamWriter, BamReader
+from panda3d.core import BamWriter, BamReader
 
 # A funny replacement for "import pickle" so we don't get confused
 # with the local pickle.py.
@@ -37,7 +37,7 @@ class Pickler(pickle.Pickler):
 
     # We have to duplicate most of the save() method, so we can add
     # support for __reduce_persist__().
-    
+
     def save(self, obj):
         # Check for persistent id (defined by a subclass)
         pid = self.persistent_id(obj)
@@ -116,7 +116,7 @@ class Unpickler(pickle.Unpickler):
 
     # Duplicate the load_reduce() function, to provide a special case
     # for the reduction function.
-    
+
     def load_reduce(self):
         stack = self.stack
         args = stack.pop()

+ 30 - 31
direct/src/stdpy/thread.py

@@ -14,13 +14,12 @@ __all__ = [
     'forceYield', 'considerYield',
     ]
 
-# Import PandaModules as pm, so we don't have any namespace collisions.
-from pandac import PandaModules as pm
+from panda3d import core
 
 # These methods are defined in Panda, and are particularly useful if
 # you may be running in Panda's SIMPLE_THREADS compilation mode.
-forceYield = pm.Thread.forceYield
-considerYield = pm.Thread.considerYield
+forceYield = core.Thread.forceYield
+considerYield = core.Thread.considerYield
 
 class error(StandardError):
     pass
@@ -31,10 +30,10 @@ class LockType:
     provide the described Python lock semantics.  In particular, this
     allows a different thread to release the lock than the one that
     acquired it. """
-    
+
     def __init__(self):
-        self.__lock = pm.Mutex('PythonLock')
-        self.__cvar = pm.ConditionVar(self.__lock)
+        self.__lock = core.Mutex('PythonLock')
+        self.__cvar = core.ConditionVar(self.__lock)
         self.__locked = False
 
     def acquire(self, waitflag = 1):
@@ -44,7 +43,7 @@ class LockType:
                 return False
             while self.__locked:
                 self.__cvar.wait()
-                
+
             self.__locked = True
             return True
 
@@ -56,16 +55,16 @@ class LockType:
         try:
             if not self.__locked:
                 raise error, 'Releasing unheld lock.'
-                
+
             self.__locked = False
             self.__cvar.notify()
 
         finally:
             self.__lock.release()
-        
+
     def locked(self):
         return self.__locked
-    
+
     __enter__ = acquire
 
     def __exit__(self, t, v, tb):
@@ -73,7 +72,7 @@ class LockType:
 
 _threads = {}
 _nextThreadId = 0
-_threadsLock = pm.Mutex('thread._threadsLock')
+_threadsLock = core.Mutex('thread._threadsLock')
 
 def start_new_thread(function, args, kwargs = {}, name = None):
     def threadFunc(threadId, function = function, args = args, kwargs = kwargs):
@@ -94,31 +93,31 @@ def start_new_thread(function, args, kwargs = {}, name = None):
 
         if name is None:
             name = 'PythonThread-%s' % (threadId)
-            
-        thread = pm.PythonThread(threadFunc, [threadId], name, name)
+
+        thread = core.PythonThread(threadFunc, [threadId], name, name)
         thread.setPythonData(threadId)
         _threads[threadId] = (thread, {}, None)
-        
-        thread.start(pm.TPNormal, False)
+
+        thread.start(core.TPNormal, False)
         return threadId
 
     finally:
         _threadsLock.release()
 
 def _add_thread(thread, wrapper):
-    """ Adds the indicated pm.Thread object, with the indicated Python
+    """ Adds the indicated core.Thread object, with the indicated Python
     wrapper, to the thread list.  Returns the new thread ID. """
-    
+
     global _nextThreadId
     _threadsLock.acquire()
     try:
         threadId = _nextThreadId
         _nextThreadId += 1
-            
+
         thread.setPythonData(threadId)
         _threads[threadId] = (thread, {}, wrapper)
         return threadId
-        
+
     finally:
         _threadsLock.release()
 
@@ -130,7 +129,7 @@ def _get_thread_wrapper(thread, wrapperClass):
     threadId = thread.getPythonData()
     if threadId is None:
         # The thread has never been assigned a threadId.  Go assign one.
-        
+
         global _nextThreadId
         _threadsLock.acquire()
         try:
@@ -166,7 +165,7 @@ def _get_thread_locals(thread, i):
     threadId = thread.getPythonData()
     if threadId is None:
         # The thread has never been assigned a threadId.  Go assign one.
-        
+
         global _nextThreadId
         _threadsLock.acquire()
         try:
@@ -195,14 +194,14 @@ def _get_thread_locals(thread, i):
 
 def _remove_thread_id(threadId):
     """ Removes the thread with the indicated ID from the thread list. """
-    
+
     _threadsLock.acquire()
     try:
         thread, locals, wrapper = _threads[threadId]
         assert thread.getPythonData() == threadId
         del _threads[threadId]
         thread.setPythonData(None)
-        
+
     finally:
         _threadsLock.release()
 
@@ -218,7 +217,7 @@ def allocate_lock():
     return LockType()
 
 def get_ident():
-    return pm.Thread.getCurrentThread().this
+    return core.Thread.getCurrentThread().this
 
 def stack_size(size = 0):
     raise error
@@ -244,18 +243,18 @@ class _local(object):
             _threadsLock.release()
 
     def __setattr__(self, key, value):
-        d = _get_thread_locals(pm.Thread.getCurrentThread(), id(self))
+        d = _get_thread_locals(core.Thread.getCurrentThread(), id(self))
         d[key] = value
-        
+
 ##     def __getattr__(self, key):
-##         d = _get_thread_locals(pm.Thread.getCurrentThread(), id(self))
+##         d = _get_thread_locals(core.Thread.getCurrentThread(), id(self))
 ##         try:
 ##             return d[key]
 ##         except KeyError:
 ##             raise AttributeError
 
     def __getattribute__(self, key):
-        d = _get_thread_locals(pm.Thread.getCurrentThread(), id(self))
+        d = _get_thread_locals(core.Thread.getCurrentThread(), id(self))
         if key == '__dict__':
             return d
         try:
@@ -263,5 +262,5 @@ class _local(object):
         except KeyError:
             return object.__getattribute__(self, key)
 
-        
-        
+
+

+ 48 - 51
direct/src/stdpy/threading.py

@@ -21,11 +21,8 @@ easier to use and understand.
 It is permissible to mix-and-match both threading and threading2
 within the same application. """
 
-# We import PandaModules as the name pm, so we can avoid namespace
-# collisions between native Panda objects, and our own class
-# definitions in this module. """
 import direct
-from pandac import PandaModules as pm
+from panda3d import core
 from direct.stdpy import thread as _thread
 import sys as _sys
 
@@ -55,10 +52,10 @@ class ThreadBase:
 
     def getName(self):
         return self.name
-    
+
     def is_alive(self):
         return self.__thread.isStarted()
-    
+
     def isAlive(self):
         return self.__thread.isStarted()
 
@@ -68,9 +65,9 @@ class ThreadBase:
     def setDaemon(self, daemon):
         if self.is_alive():
             raise RuntimeError
-        
+
         self.__dict__['daemon'] = daemon
-        
+
     def __setattr__(self, key, value):
         if key == 'name':
             self.setName(value)
@@ -84,8 +81,8 @@ class ThreadBase:
 # Copy these static methods from Panda's Thread object.  These are
 # useful if you may be running in Panda's SIMPLE_THREADS compilation
 # mode.
-ThreadBase.forceYield = pm.Thread.forceYield
-ThreadBase.considerYield = pm.Thread.considerYield
+ThreadBase.forceYield = core.Thread.forceYield
+ThreadBase.considerYield = core.Thread.considerYield
 
 class Thread(ThreadBase):
     """ This class provides a wrapper around Panda's PythonThread
@@ -108,21 +105,21 @@ class Thread(ThreadBase):
         self.__dict__['daemon'] = current.daemon
         self.__dict__['name'] = name
 
-        self.__thread = pm.PythonThread(self.run, None, name, name)
+        self.__thread = core.PythonThread(self.run, None, name, name)
         threadId = _thread._add_thread(self.__thread, weakref.proxy(self))
         self.__dict__['ident'] = threadId
 
     def __del__(self):
         # On interpreter shutdown, the _thread module might have
         # already been cleaned up.
-        if _thread and _thread._remove_thread_id: 
+        if _thread and _thread._remove_thread_id:
             _thread._remove_thread_id(self.ident)
 
     def start(self):
         if self.__thread.isStarted():
             raise RuntimeError
-        
-        if not self.__thread.start(pm.TPNormal, True):
+
+        if not self.__thread.start(core.TPNormal, True):
             raise RuntimeError
 
     def run(self):
@@ -132,7 +129,7 @@ class Thread(ThreadBase):
             _sys.setprofile(_setprofile_func)
 
         self.__target(*self.__args, **self.__kwargs)
-        
+
     def join(self, timeout = None):
         # We don't support a timed join here, sorry.
         assert timeout is None
@@ -146,10 +143,10 @@ class Thread(ThreadBase):
 class ExternalThread(ThreadBase):
     """ Returned for a Thread object that wasn't created by this
     interface. """
-    
+
     def __init__(self, extThread, threadId):
         ThreadBase.__init__(self)
-        
+
         self.__thread = extThread
         self.__dict__['daemon'] = True
         self.__dict__['name'] = self.__thread.getName()
@@ -157,10 +154,10 @@ class ExternalThread(ThreadBase):
 
     def start(self):
         raise RuntimeError
-    
+
     def run(self):
         raise RuntimeError
-        
+
     def join(self, timeout = None):
         raise RuntimeError
 
@@ -169,53 +166,53 @@ class ExternalThread(ThreadBase):
 
 class MainThread(ExternalThread):
     """ Returned for the MainThread object. """
-    
+
     def __init__(self, extThread, threadId):
         ExternalThread.__init__(self, extThread, threadId)
         self.__dict__['daemon'] = False
 
-class Lock(pm.Mutex):
+class Lock(core.Mutex):
     """ This class provides a wrapper around Panda's Mutex object.
     The wrapper is designed to emulate Python's own threading.Lock
     object. """
 
     def __init__(self, name = "PythonLock"):
-        pm.Mutex.__init__(self, name)
+        core.Mutex.__init__(self, name)
 
     def acquire(self, blocking = True):
         if blocking:
-            pm.Mutex.acquire(self)
+            core.Mutex.acquire(self)
             return True
         else:
-            return pm.Mutex.tryAcquire(self)
-    
+            return core.Mutex.tryAcquire(self)
+
     __enter__ = acquire
 
     def __exit__(self, t, v, tb):
         self.release()
 
-class RLock(pm.ReMutex):
+class RLock(core.ReMutex):
     """ This class provides a wrapper around Panda's ReMutex object.
     The wrapper is designed to emulate Python's own threading.RLock
     object. """
 
     def __init__(self, name = "PythonRLock"):
-        pm.ReMutex.__init__(self, name)
+        core.ReMutex.__init__(self, name)
 
     def acquire(self, blocking = True):
         if blocking:
-            pm.ReMutex.acquire(self)
+            core.ReMutex.acquire(self)
             return True
         else:
-            return pm.ReMutex.tryAcquire(self)
-    
+            return core.ReMutex.tryAcquire(self)
+
     __enter__ = acquire
 
     def __exit__(self, t, v, tb):
         self.release()
 
 
-class Condition(pm.ConditionVarFull):
+class Condition(core.ConditionVarFull):
     """ This class provides a wrapper around Panda's ConditionVarFull
     object.  The wrapper is designed to emulate Python's own
     threading.Condition object. """
@@ -229,7 +226,7 @@ class Condition(pm.ConditionVarFull):
         assert isinstance(lock, Lock)
 
         self.__lock = lock
-        pm.ConditionVarFull.__init__(self, self.__lock)
+        core.ConditionVarFull.__init__(self, self.__lock)
 
     def acquire(self, *args, **kw):
         return self.__lock.acquire(*args, **kw)
@@ -239,35 +236,35 @@ class Condition(pm.ConditionVarFull):
 
     def wait(self, timeout = None):
         if timeout is None:
-            pm.ConditionVarFull.wait(self)
+            core.ConditionVarFull.wait(self)
         else:
-            pm.ConditionVarFull.wait(self, timeout)
+            core.ConditionVarFull.wait(self, timeout)
 
     def notifyAll(self):
-        pm.ConditionVarFull.notifyAll(self)
+        core.ConditionVarFull.notifyAll(self)
 
     notify_all = notifyAll
-    
+
     __enter__ = acquire
 
     def __exit__(self, t, v, tb):
         self.release()
 
-class Semaphore(pm.Semaphore):
+class Semaphore(core.Semaphore):
     """ This class provides a wrapper around Panda's Semaphore
     object.  The wrapper is designed to emulate Python's own
     threading.Semaphore object. """
 
     def __init__(self, value = 1):
-        pm.Semaphore.__init__(self, value)
+        core.Semaphore.__init__(self, value)
 
     def acquire(self, blocking = True):
         if blocking:
-            pm.Semaphore.acquire(self)
+            core.Semaphore.acquire(self)
             return True
         else:
-            return pm.Semaphore.tryAcquire(self)
-    
+            return core.Semaphore.tryAcquire(self)
+
     __enter__ = acquire
 
     def __exit__(self, t, v, tb):
@@ -293,8 +290,8 @@ class Event:
     object. """
 
     def __init__(self):
-        self.__lock = pm.Lock("Python Event")
-        self.__cvar = pm.ConditionVarFull(self.__lock)
+        self.__lock = core.Lock("Python Event")
+        self.__cvar = core.ConditionVarFull(self.__lock)
         self.__flag = False
 
     def is_set(self):
@@ -310,7 +307,7 @@ class Event:
 
         finally:
             self.__lock.release()
-            
+
     def clear(self):
         self.__lock.acquire()
         try:
@@ -318,7 +315,7 @@ class Event:
 
         finally:
             self.__lock.release()
-            
+
     def wait(self, timeout = None):
         self.__lock.acquire()
         try:
@@ -326,15 +323,15 @@ class Event:
                 while not self.__flag:
                     self.__cvar.wait()
             else:
-                clock = pm.TrueClock.getGlobalPtr()
+                clock = core.TrueClock.getGlobalPtr()
                 expires = clock.getShortTime() + timeout
                 while not self.__flag:
                     wait = expires - clock.getShortTime()
                     if wait < 0:
                         return
-                    
+
                     self.__cvar.wait(wait)
-                
+
         finally:
             self.__lock.release()
 
@@ -366,7 +363,7 @@ class Timer(Thread):
 
 def _create_thread_wrapper(t, threadId):
     """ Creates a thread wrapper for the indicated external thread. """
-    if isinstance(t, pm.MainThread):
+    if isinstance(t, core.MainThread):
         pyt = MainThread(t, threadId)
     else:
         pyt = ExternalThread(t, threadId)
@@ -374,7 +371,7 @@ def _create_thread_wrapper(t, threadId):
     return pyt
 
 def current_thread():
-    t = pm.Thread.getCurrentThread()
+    t = core.Thread.getCurrentThread()
     return _thread._get_thread_wrapper(t, _create_thread_wrapper)
 
 currentThread = current_thread
@@ -410,7 +407,7 @@ def stack_size(size = None):
 def _test():
 
     from collections import deque
-    _sleep = pm.Thread.sleep
+    _sleep = core.Thread.sleep
 
     _VERBOSE = False
 

+ 2 - 2
direct/src/stdpy/threading2.py

@@ -17,8 +17,8 @@ import sys as _sys
 
 from direct.stdpy import thread
 from direct.stdpy.thread import stack_size, _local as local
-from pandac import PandaModules as pm
-_sleep = pm.Thread.sleep
+from panda3d import core
+_sleep = core.Thread.sleep
 
 from time import time as _time
 from traceback import format_exc as _format_exc

+ 15 - 15
direct/src/task/Task.py

@@ -16,7 +16,7 @@ import time
 import random
 import string
 
-from pandac.PandaModules import *
+from panda3d.core import *
 
 def print_exc_plus():
     """
@@ -114,7 +114,7 @@ class TaskManager:
 
         self._frameProfileQueue = Queue()
 
-        # this will be set when it's safe to import StateVar 
+        # this will be set when it's safe to import StateVar
         self._profileFrames = None
         self._frameProfiler = None
         self._profileTasks = None
@@ -231,7 +231,7 @@ class TaskManager:
         in proportion to their time used and to their priority value.
         See AsyncTaskManager.setTimeslicePriority() for more.
         """
-        
+
         chain = self.mgr.makeTaskChain(chainName)
         if numThreads is not None:
             chain.setNumThreads(numThreads)
@@ -249,7 +249,7 @@ class TaskManager:
     def hasTaskNamed(self, taskName):
         """Returns true if there is at least one task, active or
         sleeping, with the indicated name. """
-        
+
         return bool(self.mgr.findTask(taskName))
 
     def getTasksNamed(self, taskName):
@@ -261,7 +261,7 @@ class TaskManager:
         """Returns a list of all tasks, active or sleeping, with a
         name that matches the pattern, which can include standard
         shell globbing characters like *, ?, and []. """
-        
+
         return self.__makeTaskList(self.mgr.findTasksMatching(GlobPattern(taskPattern)))
 
     def getAllTasks(self):
@@ -298,7 +298,7 @@ class TaskManager:
         wish to specify a task that will run in the next frame, use a
         delayTime of 0.
         """
-        
+
         if delayTime < 0:
             assert self.notify.warning('doMethodLater: added task: %s with negative delay: %s' % (name, delayTime))
 
@@ -310,7 +310,7 @@ class TaskManager:
     def add(self, funcOrTask, name = None, sort = None, extraArgs = None,
             priority = None, uponDeath = None, appendTask = False,
             taskChain = None, owner = None):
-        
+
         """
         Add a new task to the taskMgr.  The task will begin executing
         immediately, or next frame if its sort value has already
@@ -363,7 +363,7 @@ class TaskManager:
         added, or the original Task object that was passed in.
 
         """
-        
+
         task = self.__setupTask(funcOrTask, name, priority, sort, extraArgs, taskChain, appendTask, owner, uponDeath)
         self.mgr.add(task)
         return task
@@ -412,7 +412,7 @@ class TaskManager:
             task.setUponDeath(uponDeath)
 
         return task
-        
+
     def remove(self, taskOrName):
         """Removes a task from the task manager.  The task is stopped,
         almost as if it had returned task.done.  (But if the task is
@@ -421,7 +421,7 @@ class TaskManager:
         Task object, or the name of a task.  If you specify a name,
         all tasks with the indicated name are removed.  Returns the
         number of tasks removed. """
-        
+
         if isinstance(taskOrName, types.StringTypes):
             tasks = self.mgr.findTasks(taskOrName)
             return self.mgr.remove(tasks)
@@ -463,7 +463,7 @@ class TaskManager:
         # This is the spot for an internal yield function
         nextTaskTime = self.mgr.getNextWakeTime()
         self.doYield(startFrameTime, nextTaskTime)
-        
+
         # Restore default interrupt handler
         signal.signal(signal.SIGINT, signal.default_int_handler)
         if self.fKeyboardInterrupt:
@@ -472,7 +472,7 @@ class TaskManager:
     def run(self):
         """Starts the task manager running.  Does not return until an
         exception is encountered (including KeyboardInterrupt). """
-        
+
         # Set the clock to have last frame's time in case we were
         # Paused at the prompt for a long time
         t = self.globalClock.getFrameTime()
@@ -554,7 +554,7 @@ class TaskManager:
     def __tryReplaceTaskMethod(self, task, oldMethod, newFunction):
         if not isinstance(task, PythonTask):
             return 0
-        
+
         method = task.getFunction()
         if (type(method) == types.MethodType):
             function = method.im_func
@@ -730,10 +730,10 @@ class TaskManager:
         delta = minFinTime - self.globalClock.getRealTime()
         while(delta > 0.002):
             print ' sleep %s'% (delta)
-            time.sleep(delta)           
+            time.sleep(delta)
             delta = minFinTime - self.globalClock.getRealTime()
     """
-    
+
     if __debug__:
         # to catch memory leaks during the tests at the bottom of the file
         def _startTrackingMemLeaks(self):

File diff suppressed because it is too large
+ 445 - 438
dtool/src/cppparser/cppBison.cxx.prebuilt


+ 58 - 56
dtool/src/cppparser/cppBison.h.prebuilt

@@ -119,34 +119,35 @@ extern int cppyydebug;
      KW_MUTABLE = 328,
      KW_NAMESPACE = 329,
      KW_NEW = 330,
-     KW_OPERATOR = 331,
-     KW_PRIVATE = 332,
-     KW_PROTECTED = 333,
-     KW_PUBLIC = 334,
-     KW_REGISTER = 335,
-     KW_RETURN = 336,
-     KW_SHORT = 337,
-     KW_SIGNED = 338,
-     KW_SIZEOF = 339,
-     KW_STATIC = 340,
-     KW_STATIC_CAST = 341,
-     KW_STRUCT = 342,
-     KW_TEMPLATE = 343,
-     KW_THROW = 344,
-     KW_TRUE = 345,
-     KW_TRY = 346,
-     KW_TYPEDEF = 347,
-     KW_TYPENAME = 348,
-     KW_UNION = 349,
-     KW_UNSIGNED = 350,
-     KW_USING = 351,
-     KW_VIRTUAL = 352,
-     KW_VOID = 353,
-     KW_VOLATILE = 354,
-     KW_WHILE = 355,
-     START_CPP = 356,
-     START_CONST_EXPR = 357,
-     START_TYPE = 358
+     KW_NOEXCEPT = 331,
+     KW_OPERATOR = 332,
+     KW_PRIVATE = 333,
+     KW_PROTECTED = 334,
+     KW_PUBLIC = 335,
+     KW_REGISTER = 336,
+     KW_RETURN = 337,
+     KW_SHORT = 338,
+     KW_SIGNED = 339,
+     KW_SIZEOF = 340,
+     KW_STATIC = 341,
+     KW_STATIC_CAST = 342,
+     KW_STRUCT = 343,
+     KW_TEMPLATE = 344,
+     KW_THROW = 345,
+     KW_TRUE = 346,
+     KW_TRY = 347,
+     KW_TYPEDEF = 348,
+     KW_TYPENAME = 349,
+     KW_UNION = 350,
+     KW_UNSIGNED = 351,
+     KW_USING = 352,
+     KW_VIRTUAL = 353,
+     KW_VOID = 354,
+     KW_VOLATILE = 355,
+     KW_WHILE = 356,
+     START_CPP = 357,
+     START_CONST_EXPR = 358,
+     START_TYPE = 359
    };
 #endif
 /* Tokens.  */
@@ -223,34 +224,35 @@ extern int cppyydebug;
 #define KW_MUTABLE 328
 #define KW_NAMESPACE 329
 #define KW_NEW 330
-#define KW_OPERATOR 331
-#define KW_PRIVATE 332
-#define KW_PROTECTED 333
-#define KW_PUBLIC 334
-#define KW_REGISTER 335
-#define KW_RETURN 336
-#define KW_SHORT 337
-#define KW_SIGNED 338
-#define KW_SIZEOF 339
-#define KW_STATIC 340
-#define KW_STATIC_CAST 341
-#define KW_STRUCT 342
-#define KW_TEMPLATE 343
-#define KW_THROW 344
-#define KW_TRUE 345
-#define KW_TRY 346
-#define KW_TYPEDEF 347
-#define KW_TYPENAME 348
-#define KW_UNION 349
-#define KW_UNSIGNED 350
-#define KW_USING 351
-#define KW_VIRTUAL 352
-#define KW_VOID 353
-#define KW_VOLATILE 354
-#define KW_WHILE 355
-#define START_CPP 356
-#define START_CONST_EXPR 357
-#define START_TYPE 358
+#define KW_NOEXCEPT 331
+#define KW_OPERATOR 332
+#define KW_PRIVATE 333
+#define KW_PROTECTED 334
+#define KW_PUBLIC 335
+#define KW_REGISTER 336
+#define KW_RETURN 337
+#define KW_SHORT 338
+#define KW_SIGNED 339
+#define KW_SIZEOF 340
+#define KW_STATIC 341
+#define KW_STATIC_CAST 342
+#define KW_STRUCT 343
+#define KW_TEMPLATE 344
+#define KW_THROW 345
+#define KW_TRUE 346
+#define KW_TRY 347
+#define KW_TYPEDEF 348
+#define KW_TYPENAME 349
+#define KW_UNION 350
+#define KW_UNSIGNED 351
+#define KW_USING 352
+#define KW_VIRTUAL 353
+#define KW_VOID 354
+#define KW_VOLATILE 355
+#define KW_WHILE 356
+#define START_CPP 357
+#define START_CONST_EXPR 358
+#define START_TYPE 359
 
 
 

+ 2 - 27
dtool/src/dtoolbase/deletedBufferChain.I

@@ -59,7 +59,7 @@ node_to_buffer(DeletedBufferChain::ObjectNode *node) {
 #if defined(USE_DELETEDCHAINFLAG) && defined(USE_DELETED_CHAIN)
   // In development mode, we increment the pointer so that the
   // returned data does not overlap our _flag member.
-  return (void *)(((char *)node) + get_flag_reserved_bytes());
+  return (void *)(((char *)node) + flag_reserved_bytes);
 #else
   return (void *)node;
 #endif  // NDEBUG
@@ -75,33 +75,8 @@ buffer_to_node(void *ptr) {
 #if defined(USE_DELETEDCHAINFLAG) && defined(USE_DELETED_CHAIN)
   // In development mode, we decrement the pointer to undo the
   // increment we did above.
-  return (ObjectNode *)(((char *)ptr) - get_flag_reserved_bytes());
+  return (ObjectNode *)(((char *)ptr) - flag_reserved_bytes);
 #else
   return (ObjectNode *)ptr;
 #endif  // NDEBUG
 }
-
-////////////////////////////////////////////////////////////////////
-//     Function: DeletedBufferChain::get_flag_reserved_bytes
-//       Access: Private, Static
-//  Description: Returns the number of extra bytes reserved at the
-//               beginning of each buffer for the _flag member.
-////////////////////////////////////////////////////////////////////
-INLINE size_t DeletedBufferChain::
-get_flag_reserved_bytes() {
-#ifndef USE_DELETEDCHAINFLAG
-  // Without DELETEDCHAINFLAG, we don't even store the _flag member at
-  // all, and this method is never called.
-  static const size_t flag_reserved_bytes = 0;
-
-#elif defined(LINMATH_ALIGN)
-  // With SSE2 alignment, we need all 16 bytes to preserve alignment.
-  static const size_t flag_reserved_bytes = 16;
-
-#else
-  // Otherwise, we only need enough space for the Integer itself.
-  static const size_t flag_reserved_bytes = sizeof(AtomicAdjust::Integer);
-#endif  // USE_DELETEDCHAINFLAG
-
-  return flag_reserved_bytes;
-}

+ 11 - 13
dtool/src/dtoolbase/deletedBufferChain.cxx

@@ -25,17 +25,10 @@ DeletedBufferChain::
 DeletedBufferChain(size_t buffer_size) {
   _deleted_chain = NULL;
   _buffer_size = buffer_size;
-  _alloc_size = _buffer_size;
-
-#ifdef USE_DELETEDCHAINFLAG
-  // In development mode, we also need to reserve space for _flag.
-  _alloc_size += get_flag_reserved_bytes();
-#endif  // USE_DELETEDCHAINFLAG
 
   // We must allocate at least this much space for bookkeeping
   // reasons.
   _buffer_size = max(_buffer_size, sizeof(ObjectNode));
-  _alloc_size = max(_alloc_size, sizeof(ObjectNode));
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -51,6 +44,9 @@ allocate(size_t size, TypeHandle type_handle) {
   //TAU_PROFILE("void *DeletedBufferChain::allocate(size_t, TypeHandle)", " ", TAU_USER);
   assert(size <= _buffer_size);
 
+  // Determine how much space to allocate.
+  const size_t alloc_size = _buffer_size + flag_reserved_bytes;
+
   ObjectNode *obj;
 
   _lock.acquire();
@@ -67,8 +63,8 @@ allocate(size_t size, TypeHandle type_handle) {
     void *ptr = node_to_buffer(obj);
 
 #ifdef DO_MEMORY_USAGE
-    //    type_handle.dec_memory_usage(TypeHandle::MC_deleted_chain_inactive, _alloc_size);
-    type_handle.inc_memory_usage(TypeHandle::MC_deleted_chain_active, _alloc_size);
+    //    type_handle.dec_memory_usage(TypeHandle::MC_deleted_chain_inactive, alloc_size);
+    type_handle.inc_memory_usage(TypeHandle::MC_deleted_chain_active, alloc_size);
 #endif  // DO_MEMORY_USAGE
 
     return ptr;
@@ -78,7 +74,7 @@ allocate(size_t size, TypeHandle type_handle) {
   // If we get here, the deleted_chain is empty; we have to allocate a
   // new object from the system pool.
 
-  obj = (ObjectNode *)NeverFreeMemory::alloc(_alloc_size);
+  obj = (ObjectNode *)NeverFreeMemory::alloc(alloc_size);
 
 #ifdef USE_DELETEDCHAINFLAG
   obj->_flag = DCF_alive;
@@ -87,7 +83,7 @@ allocate(size_t size, TypeHandle type_handle) {
   void *ptr = node_to_buffer(obj);
 
 #ifdef DO_MEMORY_USAGE
-  type_handle.inc_memory_usage(TypeHandle::MC_deleted_chain_active, _alloc_size);
+  type_handle.inc_memory_usage(TypeHandle::MC_deleted_chain_active, alloc_size);
 #endif  // DO_MEMORY_USAGE
 
   return ptr;
@@ -110,8 +106,10 @@ deallocate(void *ptr, TypeHandle type_handle) {
   assert(ptr != (void *)NULL);
 
 #ifdef DO_MEMORY_USAGE
-  type_handle.dec_memory_usage(TypeHandle::MC_deleted_chain_active, _alloc_size);
-  //  type_handle.inc_memory_usage(TypeHandle::MC_deleted_chain_inactive, _alloc_size);
+  type_handle.dec_memory_usage(TypeHandle::MC_deleted_chain_active,
+                               _buffer_size + flag_reserved_bytes);
+  //  type_handle.inc_memory_usage(TypeHandle::MC_deleted_chain_inactive,
+  //                               _buffer_size + flag_reserved_bytes);
 
 #endif  // DO_MEMORY_USAGE
 

+ 13 - 2
dtool/src/dtoolbase/deletedBufferChain.h

@@ -93,13 +93,24 @@ private:
 
   static INLINE void *node_to_buffer(ObjectNode *node);
   static INLINE ObjectNode *buffer_to_node(void *buffer);
-  static INLINE size_t get_flag_reserved_bytes();
 
   ObjectNode *_deleted_chain;
   
   MutexImpl _lock;
   size_t _buffer_size;
-  size_t _alloc_size;
+
+#ifndef USE_DELETEDCHAINFLAG
+  // Without DELETEDCHAINFLAG, we don't even store the _flag member at all.
+  static const size_t flag_reserved_bytes = 0;
+
+#elif defined(LINMATH_ALIGN)
+  // With SSE2 alignment, we need all 16 bytes to preserve alignment.
+  static const size_t flag_reserved_bytes = 16;
+
+#else
+  // Otherwise, we only need enough space for the Integer itself.
+  static const size_t flag_reserved_bytes = sizeof(AtomicAdjust::Integer);
+#endif  // USE_DELETEDCHAINFLAG
 
   friend class MemoryHook;
 };

+ 24 - 1
dtool/src/dtoolbase/dtoolbase_cc.h

@@ -35,6 +35,9 @@ using namespace std;
 #define TYPENAME typename
 #define CONSTEXPR
 #define NOEXCEPT noexcept
+#define FINAL
+#define OVERRIDE
+#define MOVE(x) x
 
 #define EXPORT_TEMPLATE_CLASS(expcl, exptp, classname)
 
@@ -121,6 +124,7 @@ typedef ios::seekdir ios_seekdir;
 #define INLINE inline
 #endif
 
+// Determine the availability of C++11 features.
 #if defined(__has_extension) // Clang magic.
 #  if __has_extension(cxx_constexpr)
 #    define CONSTEXPR constexpr
@@ -134,6 +138,16 @@ typedef ios::seekdir ios_seekdir;
 #  endif
 #  if __has_extension(cxx_rvalue_references) && (__cplusplus >= 201103L)
 #    define USE_MOVE_SEMANTICS
+#    define MOVE(x) move(x)
+#  else
+#    define MOVE(x) x
+#  endif
+#  if __has_extension(cxx_override_control) && (__cplusplus >= 201103L)
+#    define FINAL final
+#    define OVERRIDE override
+#  else
+#    define FINAL
+#    define OVERRIDE
 #  endif
 #elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)) && (__cplusplus >= 201103L)
 // noexcept was introduced in GCC 4.6, constexpr in GCC 4.7, rvalue refs in
@@ -141,14 +155,23 @@ typedef ios::seekdir ios_seekdir;
 #  define CONSTEXPR constexpr
 #  define NOEXCEPT noexcept
 #  define USE_MOVE_SEMANTICS
+#  define FINAL final
+#  define OVERRIDE override
+#  define MOVE(x) move(x)
 #elif defined(_MSC_VER) && _MSC_VER >= 1600
-// MSVC 2010 has move semantics.
+// MSVC 2010 has move semantics.  Not much else.
 #  define CONSTEXPR INLINE
 #  define NOEXCEPT throw()
 #  define USE_MOVE_SEMANTICS
+#  define FINAL
+#  define OVERRIDE
+#  define MOVE(x) move(x)
 #else
 #  define CONSTEXPR INLINE
 #  define NOEXCEPT
+#  define FINAL
+#  define OVERRIDE
+#  define MOVE(x) x
 #endif
 
 #if defined(WIN32_VC) && !defined(LINK_ALL_STATIC) && defined(EXPORT_TEMPLATES)

+ 31 - 11
dtool/src/dtoolutil/executionEnvironment.cxx

@@ -55,15 +55,17 @@
 #ifdef IS_FREEBSD
 extern char **environ;
 
-// For Link_map and dlinfo.
-#include <link.h>
-#include <dlfcn.h>
-
 // This is for sysctl.
 #include <sys/types.h>
 #include <sys/sysctl.h>
 #endif
 
+#if defined(IS_LINUX) || defined(IS_OSX)
+// For link_map and dlinfo.
+#include <link.h>
+#include <dlfcn.h>
+#endif
+
 #ifdef HAVE_PYTHON
 #include "Python.h"
 #endif
@@ -507,7 +509,7 @@ ns_get_binary_name() const {
 ////////////////////////////////////////////////////////////////////
 //     Function: ExecutionEnvironment::ns_get_dtool_name
 //       Access: Private
-//  Description: Returns the name of the libdtool DLL that
+//  Description: Returns the name of the libp3dtool DLL that
 //               is used in this program, if it can be determined.  The
 //               nonstatic implementation.
 ////////////////////////////////////////////////////////////////////
@@ -646,14 +648,34 @@ read_args() {
       const char *buffer = _dyld_get_image_name(i);
       const char *tail = strrchr(buffer, '/');
       if (tail && (strcmp(tail, "/libp3dtool." PANDA_ABI_VERSION_STR ".dylib") == 0
-                || strcmp(tail, "/libp3dtool.dylib") == 0
-                || strcmp(tail, "/libdtool.dylib") == 0)) {
+                || strcmp(tail, "/libp3dtool.dylib") == 0)) {
         _dtool_name = buffer;
       }
     }
   }
 #endif
 
+#if defined(IS_FREEBSD) || defined(IS_LINUX)
+  // FreeBSD and Linux have a function to get the origin of a loaded library.
+
+  char origin[PATH_MAX + 1];
+
+  if (_dtool_name.empty()) {
+    void *dtool_handle = dlopen("libp3dtool.so." PANDA_ABI_VERSION_STR, RTLD_NOW | RTLD_NOLOAD);
+    if (dtool_handle != NULL && dlinfo(dtool_handle, RTLD_DI_ORIGIN, origin) != -1) {
+      _dtool_name = origin;
+      _dtool_name += "/libp3dtool.so." PANDA_ABI_VERSION_STR;
+    } else {
+      // Try the version of libp3dtool.so without ABI suffix.
+      dtool_handle = dlopen("libp3dtool.so", RTLD_NOW | RTLD_NOLOAD);
+      if (dtool_handle != NULL && dlinfo(dtool_handle, RTLD_DI_ORIGIN, origin) != -1) {
+        _dtool_name = origin;
+        _dtool_name += "/libp3dtool.so";
+      }
+    }
+  }
+#endif
+
 #if defined(IS_FREEBSD)
   // On FreeBSD, we can use dlinfo to get the linked libraries.
 
@@ -665,8 +687,7 @@ read_args() {
       char *tail = strrchr(map->l_name, '/');
       char *head = strchr(map->l_name, '/');
       if (tail && head && (strcmp(tail, "/libp3dtool.so." PANDA_ABI_VERSION_STR) == 0
-                        || strcmp(tail, "/libp3dtool.so") == 0
-                        || strcmp(tail, "/libdtool.so") == 0)) {
+                        || strcmp(tail, "/libp3dtool.so") == 0)) {
         _dtool_name = head;
       }
       map = map->l_next;
@@ -690,8 +711,7 @@ read_args() {
       char *tail = strrchr(buffer, '/');
       char *head = strchr(buffer, '/');
       if (tail && head && (strcmp(tail, "/libp3dtool.so." PANDA_ABI_VERSION_STR) == 0
-                        || strcmp(tail, "/libp3dtool.so") == 0
-                        || strcmp(tail, "/libdtool.so") == 0)) {
+                        || strcmp(tail, "/libp3dtool.so") == 0)) {
         _dtool_name = head;
       }
     }

+ 3 - 0
dtool/src/prc/configFlags.cxx

@@ -52,6 +52,9 @@ operator << (ostream &out, ConfigFlags::ValueType type) {
 
   case ConfigFlags::VT_int64:
     return out << "int64";
+
+  case ConfigFlags::VT_color:
+    return out << "color";
   }
 
   return out << "**invalid(" << (int)type << ")**";

+ 1 - 1
dtool/src/prc/configFlags.h

@@ -39,6 +39,7 @@ PUBLISHED:
     VT_enum,
     VT_search_path,
     VT_int64,
+    VT_color,
   };
 
   enum VariableFlags {
@@ -75,4 +76,3 @@ ostream &operator << (ostream &out, ConfigFlags::ValueType type);
 #include "configFlags.I"
 
 #endif
-

+ 2 - 0
dtool/src/pystub/pystub.cxx

@@ -194,6 +194,7 @@ extern "C" {
   EXPCL_PYSTUB extern void *PyExc_SystemExit;
   EXPCL_PYSTUB extern void *PyExc_TypeError;
   EXPCL_PYSTUB extern void *PyExc_ValueError;
+  EXPCL_PYSTUB extern void *_Py_FalseStruct;
   EXPCL_PYSTUB extern void *_Py_NoneStruct;
   EXPCL_PYSTUB extern void *_Py_NotImplementedStruct;
   EXPCL_PYSTUB extern void *_Py_TrueStruct;
@@ -385,6 +386,7 @@ void *PyExc_StopIteration = (void *)NULL;
 void *PyExc_SystemExit = (void *)NULL;
 void *PyExc_TypeError = (void *)NULL;
 void *PyExc_ValueError = (void *)NULL;
+void *_Py_FalseStruct = (void *)NULL;
 void *_Py_NoneStruct = (void *)NULL;
 void *_Py_NotImplementedStruct = (void *)NULL;
 void *_Py_TrueStruct = (void *)NULL;

+ 5 - 0
makepanda/installpanda.py

@@ -17,6 +17,11 @@ from distutils.sysconfig import get_python_lib
 from optparse import OptionParser
 from makepandacore import *
 
+def python_sitepackages_path():
+    from distutils.sysconfig import get_python_lib
+    return get_python_lib(1)
+PYTHON_SITEPACKAGES=python_sitepackages_path()
+
 MIME_INFO = (
   ("egg", "model/x-egg", "EGG model file", "pview"),
   ("bam", "model/x-bam", "Panda3D binary model file", "pview"),

+ 42 - 19
makepanda/makepanda.py

@@ -68,7 +68,7 @@ COREAPI_VERSION=None
 PLUGIN_VERSION=None
 OSXTARGET=None
 UNIVERSAL=False
-HOST_URL="https://runtime.panda3d.org/"
+HOST_URL=None
 global STRDXSDKVERSION, STRMSPLATFORMVERSION, BOOUSEINTELCOMPILER
 STRDXSDKVERSION = 'default'
 STRMSPLATFORMVERSION = 'default'
@@ -429,11 +429,16 @@ SdkAutoDisablePhysX()
 SdkAutoDisableSpeedTree()
 
 if (RTDIST and DISTRIBUTOR == "cmu"):
+    HOST_URL = "https://runtime.panda3d.org/"
+
     if (RTDIST_VERSION == "cmu_1.7" and SDK["PYTHONVERSION"] != "python2.6"):
         exit("The CMU 1.7 runtime distribution must be built against Python 2.6!")
     elif (RTDIST_VERSION == "cmu_1.8" and SDK["PYTHONVERSION"] != "python2.7"):
         exit("The CMU 1.8 runtime distribution must be built against Python 2.7!")
 
+elif RTDIST and not HOST_URL:
+    exit("You must specify a host URL when building the rtdist!")
+
 ########################################################################
 ##
 ## Choose a Compiler.
@@ -970,7 +975,12 @@ def CompileCxx(obj,src,opts):
             if ("BIGOBJ" in opts) or GetTargetArch() == 'x64':
                 cmd += " /bigobj"
 
-            cmd += " /EHa /Zm300 /DWIN32_VC /DWIN32"
+            cmd += " /Zm300 /DWIN32_VC /DWIN32"
+            if 'EXCEPTIONS' in opts:
+                cmd += " /EHsc"
+            else:
+                cmd += " -D_HAS_EXCEPTIONS=0"
+
             if GetTargetArch() == 'x64':
                 cmd += " /DWIN64_VC /DWIN64"
 
@@ -1134,8 +1144,10 @@ def CompileCxx(obj,src,opts):
             cmd += " -pthread"
 
         if not src.endswith(".c"):
-            # We don't use exceptions.
-            if 'EXCEPTIONS' not in opts:
+            # We don't use exceptions for most modules.
+            if 'EXCEPTIONS' in opts:
+                cmd += " -fexceptions"
+            else:
                 cmd += " -fno-exceptions"
 
             if 'RTTI' not in opts:
@@ -1562,8 +1574,8 @@ def CompileLink(dll, obj, opts):
             CopyFile(new_path, dll)
             oscmd('%s --strip-unneeded %s' % (GetStrip(), BracketNameWithQuotes(new_path)))
 
-        elif (GetOrigExt(dll)==".exe" and GetOptimizeOption(opts)==4 and "NOSTRIP" not in opts):
-            oscmd(GetStrip() + " -x " + BracketNameWithQuotes(dll))
+        elif (GetOptimizeOption(opts)==4 and GetTarget() == 'linux'):
+            oscmd(GetStrip() + " --strip-unneeded " + BracketNameWithQuotes(dll))
 
         os.system("chmod +x " + BracketNameWithQuotes(dll))
 
@@ -2201,7 +2213,8 @@ def WriteConfigSettings():
 
     if (RTDIST or RUNTIME):
         prc_parameters["DEFAULT_PRC_DIR"] = '""'
-        plugin_config["PANDA_PACKAGE_HOST_URL"] = HOST_URL
+        if HOST_URL:
+            plugin_config["PANDA_PACKAGE_HOST_URL"] = HOST_URL
         #plugin_config["P3D_PLUGIN_LOG_DIRECTORY"] = ""
         plugin_config["P3D_PLUGIN_LOG_BASENAME1"] = ""
         plugin_config["P3D_PLUGIN_LOG_BASENAME2"] = ""
@@ -2411,7 +2424,7 @@ def CreatePandaVersionFiles():
     pandaversion_h = pandaversion_h.replace("$DISTRIBUTOR",DISTRIBUTOR)
     pandaversion_h = pandaversion_h.replace("$RTDIST_VERSION",RTDIST_VERSION)
     pandaversion_h = pandaversion_h.replace("$COREAPI_VERSION",COREAPI_VERSION)
-    pandaversion_h = pandaversion_h.replace("$HOST_URL",HOST_URL)
+    pandaversion_h = pandaversion_h.replace("$HOST_URL",(HOST_URL or ""))
     if (DISTRIBUTOR == "cmu"):
         pandaversion_h += "\n#define PANDA_OFFICIAL_VERSION\n"
     else:
@@ -3640,14 +3653,14 @@ if (not RUNTIME):
 #
 
 if (PkgSkip("VISION") == 0) and (not RUNTIME):
-  OPTS=['DIR:panda/src/vision', 'BUILDING:VISION', 'ARTOOLKIT', 'OPENCV', 'DX9', 'DIRECTCAM', 'JPEG']
+  OPTS=['DIR:panda/src/vision', 'BUILDING:VISION', 'ARTOOLKIT', 'OPENCV', 'DX9', 'DIRECTCAM', 'JPEG', 'EXCEPTIONS']
   TargetAdd('p3vision_composite1.obj', opts=OPTS, input='p3vision_composite1.cxx')
 
   TargetAdd('libp3vision.dll', input='p3vision_composite1.obj')
   TargetAdd('libp3vision.dll', input=COMMON_PANDA_LIBS)
   TargetAdd('libp3vision.dll', opts=OPTS)
 
-  OPTS=['DIR:panda/src/vision', 'ARTOOLKIT', 'OPENCV', 'DX9', 'DIRECTCAM', 'JPEG']
+  OPTS=['DIR:panda/src/vision', 'ARTOOLKIT', 'OPENCV', 'DX9', 'DIRECTCAM', 'JPEG', 'EXCEPTIONS']
   IGATEFILES=GetDirectoryContents('panda/src/vision', ["*.h", "*_composite*.cxx"])
   TargetAdd('libp3vision.in', opts=OPTS, input=IGATEFILES)
   TargetAdd('libp3vision.in', opts=['IMOD:panda3d.vision', 'ILIB:libp3vision', 'SRCDIR:panda/src/vision'])
@@ -4681,7 +4694,7 @@ if (RTDIST or RUNTIME):
     TargetAdd('p3dpython.exe', input='p3dpython_p3dPythonMain.obj')
     TargetAdd('p3dpython.exe', input=COMMON_PANDA_LIBS)
     TargetAdd('p3dpython.exe', input='libp3tinyxml.ilb')
-    TargetAdd('p3dpython.exe', opts=['NOSTRIP', 'PYTHON', 'WINUSER'])
+    TargetAdd('p3dpython.exe', opts=['PYTHON', 'WINUSER'])
 
     TargetAdd('libp3dpython.dll', input='p3dpython_p3dpython_composite1.obj')
     TargetAdd('libp3dpython.dll', input=COMMON_PANDA_LIBS)
@@ -4719,7 +4732,7 @@ if (RTDIST or RUNTIME):
       TargetAdd('p3dcert.exe', input='plugin_mkdir_complete.obj')
       TargetAdd('p3dcert.exe', input='plugin_wstring_encode.obj')
       TargetAdd('p3dcert.exe', input='plugin_p3dCert.obj')
-      OPTS=['NOSTRIP', 'OPENSSL', 'WX', 'CARBON', 'WINOLE', 'WINOLEAUT', 'WINUSER', 'ADVAPI', 'WINSHELL', 'WINCOMCTL', 'WINGDI', 'WINCOMDLG']
+      OPTS=['OPENSSL', 'WX', 'CARBON', 'WINOLE', 'WINOLEAUT', 'WINUSER', 'ADVAPI', 'WINSHELL', 'WINCOMCTL', 'WINGDI', 'WINCOMDLG']
       if GetTarget() == "darwin":
           OPTS += ['GL', 'OPT:2']
       TargetAdd('p3dcert.exe', opts=OPTS)
@@ -4836,7 +4849,7 @@ if (RUNTIME):
     TargetAdd('Panda3D.app', input='libp3tinyxml.ilb')
     TargetAdd('Panda3D.app', input='panda3d_mac.plist', ipath=OPTS)
     TargetAdd('Panda3D.app', input='models/plugin_images/panda3d.icns')
-    TargetAdd('Panda3D.app', opts=['NOSTRIP', 'OPENSSL', 'ZLIB', 'WINGDI', 'WINUSER', 'WINSHELL', 'ADVAPI', 'WINSOCK2', 'WINOLE', 'CARBON'])
+    TargetAdd('Panda3D.app', opts=['OPENSSL', 'ZLIB', 'WINGDI', 'WINUSER', 'WINSHELL', 'ADVAPI', 'WINSOCK2', 'WINOLE', 'CARBON'])
   elif (GetTarget() == 'windows'):
     TargetAdd('plugin_standalone_panda3dWinMain.obj', opts=OPTS, input='panda3dWinMain.cxx')
     TargetAdd('panda3dw.exe', input='plugin_standalone_panda3d.obj')
@@ -4899,7 +4912,7 @@ if (RTDIST):
     TargetAdd('p3dembed.exe', input='libp3subprocbuffer.ilb')
   TargetAdd('p3dembed.exe', input='libp3tinyxml.ilb')
   TargetAdd('p3dembed.exe', input='libp3d_plugin_static.ilb')
-  TargetAdd('p3dembed.exe', opts=['NOICON', 'NOSTRIP', 'WINGDI', 'WINSOCK2', 'ZLIB', 'WINUSER', 'OPENSSL', 'JPEG', 'WINOLE', 'CARBON', 'MSIMG', 'WINCOMCTL', 'ADVAPI', 'WINSHELL', 'X11', 'PNG'])
+  TargetAdd('p3dembed.exe', opts=['NOICON', 'WINGDI', 'WINSOCK2', 'ZLIB', 'WINUSER', 'OPENSSL', 'JPEG', 'WINOLE', 'CARBON', 'MSIMG', 'WINCOMCTL', 'ADVAPI', 'WINSHELL', 'X11', 'PNG'])
 
   if GetTarget() == 'windows':
     OPTS.append("P3DEMBEDW")
@@ -4925,7 +4938,7 @@ if (RTDIST):
     TargetAdd('p3dembedw.exe', input='plugin_common.obj')
     TargetAdd('p3dembedw.exe', input='libp3tinyxml.ilb')
     TargetAdd('p3dembedw.exe', input='libp3d_plugin_static.ilb')
-    TargetAdd('p3dembedw.exe', opts=['NOICON', 'NOSTRIP', 'WINGDI', 'WINSOCK2', 'ZLIB', 'WINUSER', 'OPENSSL', 'JPEG', 'WINOLE', 'MSIMG', 'WINCOMCTL', 'ADVAPI', 'WINSHELL', 'PNG'])
+    TargetAdd('p3dembedw.exe', opts=['NOICON', 'WINGDI', 'WINSOCK2', 'ZLIB', 'WINUSER', 'OPENSSL', 'JPEG', 'WINOLE', 'MSIMG', 'WINCOMCTL', 'ADVAPI', 'WINSHELL', 'PNG'])
 
 #
 # DIRECTORY: pandatool/src/pandatoolbase/
@@ -6171,11 +6184,11 @@ Description: Runtime binary and browser plugin for the Panda3D Game Engine
 
 """
 
+
 # We're not putting "python" in the "Requires" field,
 # since the rpm-based distros don't have a common
 # naming for the Python package.
 INSTALLER_SPEC_FILE="""
-%{!?python_sitearch: %global python_sitearch %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib(1)")}
 Summary: The Panda3D free 3D engine SDK
 Name: panda3d
 Version: VERSION
@@ -6204,7 +6217,7 @@ This package contains the SDK for development with Panda3D, install panda3d-runt
 /usr/share/applications/*.desktop
 /etc/ld.so.conf.d/panda3d.conf
 /usr/%_lib/panda3d
-%{python_sitearch}
+""" + PYTHON_SITEPACKAGES + """
 /usr/include/panda3d
 """
 
@@ -6272,7 +6285,17 @@ def MakeInstallerLinux():
     oscmd("rm -rf targetroot data.tar.gz control.tar.gz panda3d.spec")
     oscmd("mkdir --mode=0755 targetroot")
 
-    if os.path.exists("/usr/bin/dpkg-deb"):
+    dpkg_present = False
+    if os.path.exists("/usr/bin/dpkg-architecture") and os.path.exists("/usr/bin/dpkg-deb"):
+        dpkg_present = True
+    rpmbuild_present = False
+    if os.path.exists("/usr/bin/rpmbuild"):
+        rpmbuild_present = True
+
+    if dpkg_present and rpmbuild_present:
+        print("Warning: both dpkg and rpmbuild present.")
+
+    if dpkg_present:
         # Invoke installpanda.py to install it into a temporary dir
         lib_dir = GetDebLibDir()
         if RUNTIME:
@@ -6359,7 +6382,7 @@ def MakeInstallerLinux():
             oscmd("chmod 644 targetroot/DEBIAN/conffiles targetroot/DEBIAN/symbols")
         oscmd("fakeroot dpkg-deb -b targetroot %s_%s_%s.deb" % (pkg_name, pkg_version, pkg_arch))
 
-    elif os.path.exists("/usr/bin/rpmbuild"):
+    elif rpmbuild_present:
         # Invoke installpanda.py to install it into a temporary dir
         if RUNTIME:
             InstallRuntime(destdir="targetroot", prefix="/usr", outputdir=GetOutputDir(), libdir=GetRPMLibDir())

+ 4 - 5
panda/src/bullet/bulletContactCallbacks.h

@@ -25,7 +25,6 @@
 #include "event.h"
 #include "eventQueue.h"
 #include "eventParameter.h"
-#include "eventStorePandaNode.h"
 #include "pandaNode.h"
 
 struct UserPersitentData {
@@ -77,8 +76,8 @@ contact_added_callback(btManifoldPoint &cp,
     if (bullet_enable_contact_events) {
 
       Event *event = new Event("bullet-contact-added");
-      event->add_parameter(EventParameter(new EventStorePandaNode(node0)));
-      event->add_parameter(EventParameter(new EventStorePandaNode(node1)));
+      event->add_parameter(EventParameter(node0));
+      event->add_parameter(EventParameter(node1));
 
       EventQueue::get_global_event_queue()->queue_event(event);
     }
@@ -137,8 +136,8 @@ contact_destroyed_callback(void *userPersistentData) {
   if (bullet_enable_contact_events) {
 
     Event *event = new Event("bullet-contact-destroyed");
-    event->add_parameter(EventParameter(new EventStorePandaNode(data->node0)));
-    event->add_parameter(EventParameter(new EventStorePandaNode(data->node1)));
+    event->add_parameter(EventParameter(data->node0));
+    event->add_parameter(EventParameter(data->node1));
 
     EventQueue::get_global_event_queue()->queue_event(event);
   }

+ 21 - 25
panda/src/collide/collisionVisualizer.cxx

@@ -122,14 +122,14 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) {
     const VizInfo &viz_info = (*di).second;
 
     CullTraverserData xform_data(data);
-    
+
     // We don't want to inherit the transform from above!  We ignore
     // whatever transforms were above the CollisionVisualizer node; it
     // always renders its objects according to their appropriate net
     // transform.
     xform_data._net_transform = TransformState::make_identity();
     xform_data._view_frustum = trav->get_view_frustum();
-    xform_data.apply_transform_and_state(trav, net_transform, 
+    xform_data.apply_transform_and_state(trav, net_transform,
                                          RenderState::make_empty(),
                                          RenderEffects::make_empty(),
                                          ClipPlaneAttrib::make());
@@ -148,7 +148,7 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) {
       PT(PandaNode) node = solid->get_viz(trav, xform_data, !was_detected);
       if (node != (PandaNode *)NULL) {
         CullTraverserData next_data(xform_data, node);
-        
+
         // We don't want to inherit the render state from above for
         // these guys.
         next_data._state = get_viz_state();
@@ -161,16 +161,16 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) {
       CPT(RenderState) empty_state = RenderState::make_empty();
       CPT(RenderState) point_state = RenderState::make(RenderModeAttrib::make(RenderModeAttrib::M_unchanged, 1.0f, false));
 
-      PT(GeomVertexArrayFormat) point_array_format = 
+      PT(GeomVertexArrayFormat) point_array_format =
         new GeomVertexArrayFormat(InternalName::get_vertex(), 3,
                                   Geom::NT_stdfloat, Geom::C_point,
                                   InternalName::get_color(), 1,
                                   Geom::NT_packed_dabc, Geom::C_color,
-                                  InternalName::get_size(), 1, 
+                                  InternalName::get_size(), 1,
                                   Geom::NT_stdfloat, Geom::C_other);
-      CPT(GeomVertexFormat) point_format = 
+      CPT(GeomVertexFormat) point_format =
         GeomVertexFormat::register_format(point_array_format);
-        
+
       Points::const_iterator pi;
       for (pi = viz_info._points.begin(); pi != viz_info._points.end(); ++pi) {
         const CollisionPoint &point = (*pi);
@@ -178,9 +178,9 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) {
         // Draw a small red point at the surface point, and a smaller
         // white point at the interior point.
         {
-          PT(GeomVertexData) point_vdata = 
+          PT(GeomVertexData) point_vdata =
             new GeomVertexData("viz", point_format, Geom::UH_stream);
-          
+
           PT(GeomPoints) points = new GeomPoints(Geom::UH_stream);
 
           GeomVertexWriter vertex(point_vdata, InternalName::get_vertex());
@@ -203,19 +203,17 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) {
 
           PT(Geom) geom = new Geom(point_vdata);
           geom->add_primitive(points);
-            
-          CullableObject *object = 
-            new CullableObject(geom, point_state, 
-                               xform_data.get_net_transform(trav),
-                               xform_data.get_modelview_transform(trav),
-                               trav->get_scene());
-          
+
+          CullableObject *object =
+            new CullableObject(geom, point_state,
+                               xform_data.get_internal_transform(trav));
+
           trav->get_cull_handler()->record_object(object, trav);
         }
 
         // Draw the normal vector at the surface point.
         if (!point._surface_normal.almost_equal(LVector3::zero())) {
-          PT(GeomVertexData) line_vdata = 
+          PT(GeomVertexData) line_vdata =
             new GeomVertexData("viz", GeomVertexFormat::get_v3cp(),
                                Geom::UH_stream);
 
@@ -225,7 +223,7 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) {
           GeomVertexWriter color(line_vdata, InternalName::get_color());
 
           vertex.add_data3(point._surface_point);
-          vertex.add_data3(point._surface_point + 
+          vertex.add_data3(point._surface_point +
                             point._surface_normal * _normal_scale);
           color.add_data4(1.0f, 0.0f, 0.0f, 1.0f);
           color.add_data4(1.0f, 1.0f, 1.0f, 1.0f);
@@ -234,13 +232,11 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) {
 
           PT(Geom) geom = new Geom(line_vdata);
           geom->add_primitive(lines);
-          
-          CullableObject *object = 
-            new CullableObject(geom, empty_state, 
-                               xform_data.get_net_transform(trav),
-                               xform_data.get_modelview_transform(trav),
-                               trav->get_scene());
-          
+
+          CullableObject *object =
+            new CullableObject(geom, empty_state,
+                               xform_data.get_internal_transform(trav));
+
           trav->get_cull_handler()->record_object(object, trav);
         }
       }

+ 4 - 4
panda/src/cull/cullBinBackToFront.cxx

@@ -66,11 +66,11 @@ add_object(CullableObject *object, Thread *current_thread) {
 
   const GeometricBoundingVolume *gbv;
   DCAST_INTO_V(gbv, volume);
-  
+
   LPoint3 center = gbv->get_approx_center();
-  nassertv(object->_modelview_transform != (const TransformState *)NULL);
-  center = center * object->_modelview_transform->get_mat();
-  
+  nassertv(object->_internal_transform != (const TransformState *)NULL);
+  center = center * object->_internal_transform->get_mat();
+
   PN_stdfloat distance = _gsg->compute_distance_to(center);
   _objects.push_back(ObjectData(object, distance));
 }

+ 4 - 4
panda/src/cull/cullBinFrontToBack.cxx

@@ -66,11 +66,11 @@ add_object(CullableObject *object, Thread *current_thread) {
 
   const GeometricBoundingVolume *gbv;
   DCAST_INTO_V(gbv, volume);
-  
+
   LPoint3 center = gbv->get_approx_center();
-  nassertv(object->_modelview_transform != (const TransformState *)NULL);
-  center = center * object->_modelview_transform->get_mat();
-  
+  nassertv(object->_internal_transform != (const TransformState *)NULL);
+  center = center * object->_internal_transform->get_mat();
+
   PN_stdfloat distance = _gsg->compute_distance_to(center);
   _objects.push_back(ObjectData(object, distance));
 }

+ 2 - 2
panda/src/cull/cullBinStateSorted.I

@@ -47,8 +47,8 @@ INLINE bool CullBinStateSorted::ObjectData::
 operator < (const ObjectData &other) const {
   // First group objects by transform, since transform changes are
   // supposed to be expensive.
-  if (_object->_modelview_transform != other._object->_modelview_transform) {
-    return _object->_modelview_transform < other._object->_modelview_transform;
+  if (_object->_internal_transform != other._object->_internal_transform) {
+    return _object->_internal_transform < other._object->_internal_transform;
   }
 
   // Then group by other state changes, in approximate order from

+ 2 - 2
panda/src/display/config_display.cxx

@@ -451,8 +451,8 @@ ConfigVariableDouble pixel_zoom
 ("pixel-zoom", 1.0,
  PRC_DESC("The default pixel_zoom factor for new windows."));
 
-ConfigVariableDouble background_color
-("background-color", "0.41 0.41 0.41",
+ConfigVariableColor background_color
+("background-color", "0.41 0.41 0.41 0.0",
  PRC_DESC("Specifies the rgb(a) value of the default background color for a "
           "new window or offscreen buffer."));
 

+ 2 - 1
panda/src/display/config_display.h

@@ -24,6 +24,7 @@
 #include "configVariableInt.h"
 #include "configVariableEnum.h"
 #include "configVariableFilename.h"
+#include "configVariableColor.h"
 #include "coordinateSystem.h"
 #include "dconfig.h"
 
@@ -107,7 +108,7 @@ extern EXPCL_PANDA_DISPLAY ConfigVariableInt back_buffers;
 
 extern EXPCL_PANDA_DISPLAY ConfigVariableDouble pixel_zoom;
 
-extern EXPCL_PANDA_DISPLAY ConfigVariableDouble background_color;
+extern EXPCL_PANDA_DISPLAY ConfigVariableColor background_color;
 extern EXPCL_PANDA_DISPLAY ConfigVariableBool sync_video;
 extern EXPCL_PANDA_DISPLAY ConfigVariableBool basic_shaders_only;
 

+ 55 - 6
panda/src/display/graphicsEngine.cxx

@@ -476,6 +476,42 @@ make_output(GraphicsPipe *pipe,
   return NULL;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsEngine::add_window
+//       Access: Published
+//  Description: This can be used to add a newly-created
+//               GraphicsOutput object (and its GSG) to the engine's
+//               list of windows, and requests that it be opened.
+//               This shouldn't be called by user code as
+//               make_output normally does this under the hood; it
+//               may be useful in esoteric cases in which a custom
+//               window object is used.
+////////////////////////////////////////////////////////////////////
+bool GraphicsEngine::
+add_window(GraphicsOutput *window, int sort) {
+  nassertr(window != NULL, false);
+
+  GraphicsThreadingModel threading_model = get_threading_model();
+  nassertr(this == window->get_engine(), false);
+
+  window->_sort = sort;
+  do_add_window(window, threading_model);
+
+  open_windows();
+  if (window->is_valid()) {
+    do_add_gsg(window->get_gsg(), window->get_pipe(), threading_model);
+
+    display_cat.info()
+      << "Added output of type " << window->get_type() << "\n";
+
+    return true;
+
+  } else {
+    remove_window(window);
+    return false;
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsEngine::remove_window
 //       Access: Published
@@ -1324,9 +1360,9 @@ cull_and_draw_together(const GraphicsEngine::Windows &wlist,
                        Thread *current_thread) {
   PStatTimer timer(_cull_pcollector, current_thread);
 
-  Windows::const_iterator wi;
-  for (wi = wlist.begin(); wi != wlist.end(); ++wi) {
-    GraphicsOutput *win = (*wi);
+  size_t wlist_size = wlist.size();
+  for (size_t wi = 0; wi < wlist_size; ++wi) {
+    GraphicsOutput *win = wlist[wi];
     if (win->is_active() && win->get_gsg()->is_active()) {
       if (win->flip_ready()) {
         {
@@ -1450,9 +1486,9 @@ cull_to_bins(const GraphicsEngine::Windows &wlist, Thread *current_thread) {
   typedef pmap<NodePath, DisplayRegion *> AlreadyCulled;
   AlreadyCulled already_culled;
 
-  Windows::const_iterator wi;
-  for (wi = wlist.begin(); wi != wlist.end(); ++wi) {
-    GraphicsOutput *win = (*wi);
+  size_t wlist_size = wlist.size();
+  for (size_t wi = 0; wi < wlist_size; ++wi) {
+    GraphicsOutput *win = wlist[wi];
     if (win->is_active() && win->get_gsg()->is_active()) {
       PStatTimer timer(win->get_cull_window_pcollector(), current_thread);
       int num_display_regions = win->get_num_active_display_regions();
@@ -1958,6 +1994,17 @@ setup_scene(GraphicsStateGuardian *gsg, DisplayRegionPipelineReader *dr) {
   CPT(TransformState) cs_transform = gsg->get_cs_transform_for(lens->get_coordinate_system());
   scene_setup->set_cs_transform(cs_transform);
 
+  CPT(TransformState) cs_world_transform = cs_transform->compose(world_transform);
+  scene_setup->set_cs_world_transform(cs_world_transform);
+
+  // Make sure that the GSG has a ShaderGenerator for the munger
+  // to use.  We have to do this here because the ShaderGenerator
+  // needs a host window pointer.  Hopefully we'll be able to
+  // eliminate that requirement in the future.
+  if (gsg->get_shader_generator() == NULL) {
+    gsg->set_shader_generator(new ShaderGenerator(gsg, window));
+  }
+
   return scene_setup;
 }
 
@@ -2107,6 +2154,8 @@ do_add_window(GraphicsOutput *window,
 void GraphicsEngine::
 do_add_gsg(GraphicsStateGuardian *gsg, GraphicsPipe *pipe,
            const GraphicsThreadingModel &threading_model) {
+  nassertv(gsg != NULL);
+
   ReMutexHolder holder(_lock);
   nassertv(gsg->get_pipe() == pipe && gsg->get_engine() == this);
   gsg->_threading_model = threading_model;

+ 7 - 6
panda/src/display/graphicsEngine.h

@@ -80,7 +80,7 @@ PUBLISHED:
                               const WindowProperties &win_prop,
                               int flags, GraphicsStateGuardian *gsg = NULL,
                               GraphicsOutput *host = NULL);
-  
+
   // Syntactic shorthand versions of make_output
   INLINE GraphicsOutput *make_buffer(GraphicsOutput *host,
                                      const string &name, int sort,
@@ -91,7 +91,8 @@ PUBLISHED:
   INLINE GraphicsOutput *make_parasite(GraphicsOutput *host,
                                        const string &name, int sort,
                                        int x_size, int y_size);
-  
+
+  bool add_window(GraphicsOutput *window, int sort);
   bool remove_window(GraphicsOutput *window);
   void remove_all_windows();
   void reset_all_windows(bool swapchain);
@@ -104,7 +105,7 @@ PUBLISHED:
   BLOCKING void render_frame();
   BLOCKING void open_windows();
   BLOCKING void sync_frame();
-  BLOCKING void ready_flip();  
+  BLOCKING void ready_flip();
   BLOCKING void flip_frame();
 
   bool extract_texture_data(Texture *tex, GraphicsStateGuardian *gsg);
@@ -130,7 +131,7 @@ public:
 public:
   static void do_cull(CullHandler *cull_handler, SceneSetup *scene_setup,
                       GraphicsStateGuardian *gsg, Thread *current_thread);
-  
+
 private:
   typedef ov_set< PT(GraphicsOutput), IndirectLess<GraphicsOutput> > Windows;
   typedef pset< PT(GraphicsStateGuardian) > GSGs;
@@ -158,7 +159,7 @@ private:
   void do_flip_frame(Thread *current_thread);
   INLINE void close_gsg(GraphicsPipe *pipe, GraphicsStateGuardian *gsg);
 
-  PT(SceneSetup) setup_scene(GraphicsStateGuardian *gsg, 
+  PT(SceneSetup) setup_scene(GraphicsStateGuardian *gsg,
                              DisplayRegionPipelineReader *dr);
   void do_draw(CullResult *cull_result, SceneSetup *scene_setup,
                GraphicsOutput *win, DisplayRegion *dr, Thread *current_thread);
@@ -281,7 +282,7 @@ private:
     Windows _cull;    // cull stage
     Windows _cdraw;   // cull-and-draw-together stage
     Windows _draw;    // draw stage
-    Windows _window;  // window stage, i.e. process windowing events 
+    Windows _window;  // window stage, i.e. process windowing events
 
     // These are not kept sorted.
     Windows _pending_close;    // moved from _window, pending close.

+ 19 - 41
panda/src/display/graphicsOutput.cxx

@@ -120,7 +120,6 @@ GraphicsOutput(GraphicsEngine *engine, GraphicsPipe *pipe,
   _sbs_left_dimensions.set(0.0f, 1.0f, 0.0f, 1.0f);
   _sbs_right_dimensions.set(0.0f, 1.0f, 0.0f, 1.0f);
   _delete_flag = false;
-  _texture_card = 0;
   _trigger_copy = false;
 
   if (_fb_properties.is_single_buffered()) {
@@ -139,9 +138,9 @@ GraphicsOutput(GraphicsEngine *engine, GraphicsPipe *pipe,
     }
     _side_by_side_stereo = side_by_side_stereo && !fb_prop.is_stereo();
     if (_side_by_side_stereo) {
-      _sbs_left_dimensions.set(sbs_left_dimensions[0], sbs_left_dimensions[1], 
+      _sbs_left_dimensions.set(sbs_left_dimensions[0], sbs_left_dimensions[1],
                                sbs_left_dimensions[2], sbs_left_dimensions[3]);
-      _sbs_right_dimensions.set(sbs_right_dimensions[0], sbs_right_dimensions[1], 
+      _sbs_right_dimensions.set(sbs_right_dimensions[0], sbs_right_dimensions[1],
                                 sbs_right_dimensions[2], sbs_right_dimensions[3]);
     }
   }
@@ -164,29 +163,7 @@ GraphicsOutput(GraphicsEngine *engine, GraphicsPipe *pipe,
   set_clear_color_active(true);
   set_clear_depth_active(true);
   set_clear_stencil_active(true);
-
-  switch (background_color.get_num_words()) {
-  case 1:
-    set_clear_color(LColor(background_color[0], background_color[0], background_color[0], 0.0f));
-    break;
-
-  case 2:
-    set_clear_color(LColor(background_color[0], background_color[0], background_color[0], background_color[1]));
-    break;
-
-  case 3:
-    set_clear_color(LColor(background_color[0], background_color[1], background_color[2], 0.0f));
-    break;
-
-  case 4:
-    set_clear_color(LColor(background_color[0], background_color[1], background_color[2], background_color[3]));
-    break;
-
-  default:
-    display_cat.warning()
-      << "Invalid background-color specification: "
-      << background_color.get_string_value() << "\n";
-  }
+  set_clear_color(background_color.get_value());
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -579,9 +556,9 @@ set_inverted(bool inverted) {
 void GraphicsOutput::
 set_side_by_side_stereo(bool side_by_side_stereo) {
   LVecBase4 left, right;
-  left.set(sbs_left_dimensions[0], sbs_left_dimensions[1], 
+  left.set(sbs_left_dimensions[0], sbs_left_dimensions[1],
            sbs_left_dimensions[2], sbs_left_dimensions[3]);
-  right.set(sbs_right_dimensions[0], sbs_right_dimensions[1], 
+  right.set(sbs_right_dimensions[0], sbs_right_dimensions[1],
             sbs_right_dimensions[2], sbs_right_dimensions[3]);
   set_side_by_side_stereo(side_by_side_stereo, left, right);
 }
@@ -984,7 +961,7 @@ make_texture_buffer(const string &name, int x_size, int y_size,
                 flags, get_gsg(), get_host());
 
   if (buffer != (GraphicsOutput *)NULL) {
-    if (buffer->get_gsg() == (GraphicsStateGuardian *)NULL || 
+    if (buffer->get_gsg() == (GraphicsStateGuardian *)NULL ||
         buffer->get_gsg()->get_prepared_objects() != get_gsg()->get_prepared_objects()) {
       // If the newly-created buffer doesn't share texture objects
       // with the current GSG, then we will have to force the texture
@@ -1101,19 +1078,20 @@ make_cube_map(const string &name, int size, NodePath &camera_rig,
 ////////////////////////////////////////////////////////////////////
 NodePath GraphicsOutput::
 get_texture_card() {
-  if (_texture_card == 0) {
+  if (_texture_card == NULL) {
     PT(GeomVertexData) vdata = create_texture_card_vdata(get_x_size(), get_y_size());
     PT(GeomTristrips) strip = new GeomTristrips(Geom::UH_static);
     strip->set_shade_model(Geom::SM_uniform);
     strip->add_next_vertices(4);
     strip->close_primitive();
-    _texture_card = new Geom(vdata);
-    _texture_card->add_primitive(strip);
+    PT(Geom) geom = new Geom(vdata);
+    geom->add_primitive(strip);
+    _texture_card = new GeomNode("texture card");
+    _texture_card->add_geom(geom);
   }
 
-  PT(GeomNode) gnode = new GeomNode("texture card");
-  gnode->add_geom(_texture_card);
-  NodePath path(gnode);
+  NodePath path("texture card");
+  path.node()->add_child(_texture_card);
 
   // The texture card, by default, is textured with the first
   // render-to-texture output texture.  Depth and stencil
@@ -1277,8 +1255,8 @@ set_size_and_recalc(int x, int y) {
     (*dri)->compute_pixels_all_stages(fb_x_size, fb_y_size);
   }
 
-  if (_texture_card != 0) {
-    _texture_card->set_vertex_data(create_texture_card_vdata(x, y));
+  if (_texture_card != NULL && _texture_card->get_num_geoms() > 0) {
+    _texture_card->modify_geom(0)->set_vertex_data(create_texture_card_vdata(x, y));
   }
 }
 
@@ -1701,7 +1679,7 @@ add_display_region(DisplayRegion *display_region) {
   LightMutexHolder holder(_lock);
   CDWriter cdata(_cycler, true);
   cdata->_active_display_regions_stale = true;
-  
+
   _total_display_regions.push_back(display_region);
 
   return display_region;
@@ -1806,7 +1784,7 @@ parse_color_mask(const string &word) {
       result |= 0x008;
 
     } else if (w == "off") {
-      
+
     } else {
       display_cat.warning()
         << "Invalid color in red-blue-stereo-colors: " << (*ci) << "\n";
@@ -1819,7 +1797,7 @@ parse_color_mask(const string &word) {
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsOutput::CData::Constructor
 //       Access: Public
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 GraphicsOutput::CData::
 CData() {
@@ -1834,7 +1812,7 @@ CData() {
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsOutput::CData::Constructor
 //       Access: Public
-//  Description: 
+//  Description:
 ////////////////////////////////////////////////////////////////////
 GraphicsOutput::CData::
 CData(const GraphicsOutput::CData &copy) :

+ 2 - 2
panda/src/display/graphicsOutput.h

@@ -68,7 +68,7 @@ class GraphicsEngine;
 class EXPCL_PANDA_DISPLAY GraphicsOutput : public GraphicsOutputBase, public DrawableRegion {
 protected:
   GraphicsOutput(GraphicsEngine *engine,
-                 GraphicsPipe *pipe, 
+                 GraphicsPipe *pipe,
                  const string &name,
                  const FrameBufferProperties &fb_prop,
                  const WindowProperties &win_prop, int flags,
@@ -314,7 +314,7 @@ protected:
   int _target_tex_page;
   int _target_tex_view;
   DisplayRegion *_prev_page_dr;
-  PT(Geom) _texture_card;
+  PT(GeomNode) _texture_card;
   bool _trigger_copy;
 
   class RenderTexture {

+ 16 - 16
panda/src/display/graphicsPipe.cxx

@@ -82,11 +82,25 @@ GraphicsPipe::
 //               performed: typically either the app thread (e.g. X)
 //               or the draw thread (Windows).
 ////////////////////////////////////////////////////////////////////
-GraphicsPipe::PreferredWindowThread 
+GraphicsPipe::PreferredWindowThread
 GraphicsPipe::get_preferred_window_thread() const {
   return PWT_draw;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsPipe::make_callback_gsg
+//       Access: Public, Virtual
+//  Description: This is called when make_output() is used to create a
+//               CallbackGraphicsWindow.  If the GraphicsPipe can
+//               construct a GSG that's not associated with any
+//               particular window object, do so now, assuming the
+//               correct graphics context has been set up externally.
+////////////////////////////////////////////////////////////////////
+PT(GraphicsStateGuardian) GraphicsPipe::
+make_callback_gsg(GraphicsEngine *engine) {
+  return NULL;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsPipe::make_device
 //       Access: Public, Virtual
@@ -95,7 +109,7 @@ GraphicsPipe::get_preferred_window_thread() const {
 ////////////////////////////////////////////////////////////////////
 PT(GraphicsDevice) GraphicsPipe::
 make_device(void *scrn) {
-  display_cat.error() 
+  display_cat.error()
     << "make_device() unimplemented by " << get_type() << "\n";
   return NULL;
 }
@@ -138,20 +152,6 @@ make_output(const string &name,
   return NULL;
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: GraphicsPipe::make_callback_gsg
-//       Access: Protected, Virtual
-//  Description: This is called when make_output() is used to create a
-//               CallbackGraphicsWindow.  If the GraphicsPipe can
-//               construct a GSG that's not associated with any
-//               particular window object, do so now, assuming the
-//               correct graphics context has been set up externally.
-////////////////////////////////////////////////////////////////////
-PT(GraphicsStateGuardian) GraphicsPipe::
-make_callback_gsg(GraphicsEngine *engine) {
-  return NULL;
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsPipe::get_display_information
 //       Access: Published

+ 6 - 5
panda/src/display/graphicsPipe.h

@@ -101,7 +101,7 @@ PUBLISHED:
 
   DisplayInformation *get_display_information();
   virtual void lookup_cpu_data();
-  
+
   virtual string get_interface_name() const=0;
 
 public:
@@ -114,9 +114,11 @@ public:
   INLINE GraphicsDevice *get_device() const;
   virtual PT(GraphicsDevice) make_device(void *scrn = NULL);
 
+  virtual PT(GraphicsStateGuardian) make_callback_gsg(GraphicsEngine *engine);
+
 protected:
   virtual void close_gsg(GraphicsStateGuardian *gsg);
-  
+
   virtual PT(GraphicsOutput) make_output(const string &name,
                                          const FrameBufferProperties &fb_prop,
                                          const WindowProperties &win_prop,
@@ -126,8 +128,7 @@ protected:
                                          GraphicsOutput *host,
                                          int retry,
                                          bool &precertify);
-  virtual PT(GraphicsStateGuardian) make_callback_gsg(GraphicsEngine *engine);
-  
+
   LightMutex _lock;
 
   bool _is_valid;
@@ -135,7 +136,7 @@ protected:
   int _display_width;
   int _display_height;
   PT(GraphicsDevice) _device;
-  
+
   DisplayInformation *_display_information;
 
   static const int strip_properties[];

+ 23 - 1
panda/src/display/graphicsStateGuardian.I

@@ -204,7 +204,7 @@ set_loader(Loader *loader) {
 
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsStateGuardian::get_loader
-//       Access: Public, Virtual
+//       Access: Public
 //  Description: Returns the Loader object that will be used by this
 //               GSG to load textures when necessary, if
 //               get_incomplete_render() is true.
@@ -214,6 +214,28 @@ get_loader() const {
   return _loader;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsStateGuardian::set_shader_generator
+//       Access: Public
+//  Description: Sets the ShaderGenerator object that will be used
+//               by this GSG to generate shaders when necessary.
+////////////////////////////////////////////////////////////////////
+INLINE void GraphicsStateGuardian::
+set_shader_generator(ShaderGenerator *shader_generator) {
+  _shader_generator = shader_generator;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsStateGuardian::get_shader_generator
+//       Access: Public
+//  Description: Returns the ShaderGenerator object that will be used
+//               by this GSG to generate shaders when necessary.
+////////////////////////////////////////////////////////////////////
+INLINE ShaderGenerator *GraphicsStateGuardian::
+get_shader_generator() const {
+  return _shader_generator;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsStateGuardian::get_pipe
 //       Access: Published

+ 210 - 13
panda/src/display/graphicsStateGuardian.cxx

@@ -266,8 +266,6 @@ GraphicsStateGuardian(CoordinateSystem internal_coordinate_system,
 
   _gamma = 1.0f;
   _texture_quality_override = Texture::QL_default;
-
-  _shader_generator = NULL;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -278,12 +276,6 @@ GraphicsStateGuardian(CoordinateSystem internal_coordinate_system,
 GraphicsStateGuardian::
 ~GraphicsStateGuardian() {
   remove_gsg(this);
-
-  if (_shader_generator) {
-    delete _shader_generator;
-    _shader_generator = 0;
-  }
-
   GeomMunger::unregister_mungers_for_gsg(this);
 }
 
@@ -878,14 +870,14 @@ make_geom_munger(const RenderState *state, Thread *current_thread) {
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsStateGuardian::compute_distance_to
 //       Access: Public, Virtual
-//  Description: This function may only be called during a render
-//               traversal; it will compute the distance to the
+//  Description: This function will compute the distance to the
 //               indicated point, assumed to be in eye coordinates,
-//               from the camera plane.
+//               from the camera plane.  The point is assumed to be
+//               in the GSG's internal coordinate system.
 ////////////////////////////////////////////////////////////////////
 PN_stdfloat GraphicsStateGuardian::
 compute_distance_to(const LPoint3 &point) const {
-  switch (_coordinate_system) {
+  switch (_internal_coordinate_system) {
   case CS_zup_right:
     return point[1];
 
@@ -901,7 +893,7 @@ compute_distance_to(const LPoint3 &point) const {
   default:
     gsg_cat.error()
       << "Invalid coordinate system in compute_distance_to: "
-      << (int)_coordinate_system << "\n";
+      << (int)_internal_coordinate_system << "\n";
     return 0.0f;
   }
 }
@@ -1175,6 +1167,31 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name, LMatrix4 &
     t = LMatrix4(c[0],c[1],c[2],c[3],s[0],s[1],s[2],s[3],p[0],p[1],p[2],0,d[0],d[1],d[2],cutoff);
     return &t;
   }
+  case Shader::SMO_light_ambient: {
+    LColor cur_ambient_light(0.0f, 0.0f, 0.0f, 0.0f);
+    const LightAttrib *target_light = (const LightAttrib *)
+      _target_rs->get_attrib_def(LightAttrib::get_class_slot());
+
+    int num_on_lights = target_light->get_num_on_lights();
+    if (num_on_lights == 0) {
+      // There are no lights at all.  This means, to follow the fixed-
+      // function model, we pretend there is an all-white ambient light.
+      t.set_row(3, LVecBase4(1, 1, 1, 1));
+    } else {
+      for (int li = 0; li < num_on_lights; li++) {
+        NodePath light = target_light->get_on_light(li);
+        nassertr(!light.is_empty(), &LMatrix4::zeros_mat());
+        Light *light_obj = light.node()->as_light();
+        nassertr(light_obj != (Light *)NULL, &LMatrix4::zeros_mat());
+
+        if (light_obj->get_type() == AmbientLight::get_class_type()) {
+          cur_ambient_light += light_obj->get_color();
+        }
+      }
+      t.set_row(3, cur_ambient_light);
+    }
+    return &t;
+  }
   case Shader::SMO_texmat_x: {
     const TexMatrixAttrib *tma = DCAST(TexMatrixAttrib, _target_rs->get_attrib_def(TexMatrixAttrib::get_class_slot()));
     const TextureAttrib *ta = DCAST(TextureAttrib, _target_rs->get_attrib_def(TextureAttrib::get_class_slot()));
@@ -1338,6 +1355,167 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name, LMatrix4 &
       calc_projection_mat(lens)->get_mat();
     return &t;
   }
+  case Shader::SMO_vec_constant_x_attrib: {
+    // This system is not ideal.  It will be improved in the future.
+    if (_target_shader->has_shader_input(name)) {
+      // There is an input specifying precisely this whole thing, with
+      // dot and all.  Support this, even if only for backward compatibility.
+      const LVecBase4 &data = _target_shader->get_shader_input_vector(name);
+      t = LMatrix4(data[0],data[1],data[2],data[3],
+                   data[0],data[1],data[2],data[3],
+                   data[0],data[1],data[2],data[3],
+                   data[0],data[1],data[2],data[3]);
+      return &t;
+    }
+
+    const NodePath &np = _target_shader->get_shader_input_nodepath(name->get_parent());
+    nassertr(!np.is_empty(), &LMatrix4::ident_mat());
+
+    CPT_InternalName attrib = name->get_basename();
+
+    static const CPT_InternalName IN_ambient("ambient");
+    static const CPT_InternalName IN_diffuse("diffuse");
+    static const CPT_InternalName IN_specular("specular");
+    static const CPT_InternalName IN_position("position");
+    static const CPT_InternalName IN_spotDirection("spotDirection");
+    static const CPT_InternalName IN_spotCutoff("spotCutoff");
+    static const CPT_InternalName IN_spotCosCutoff("spotCosCutoff");
+    static const CPT_InternalName IN_spotExponent("spotExponent");
+    static const CPT_InternalName IN_constantAttenuation("constantAttenuation");
+    static const CPT_InternalName IN_linearAttenuation("linearAttenuation");
+    static const CPT_InternalName IN_quadraticAttenuation("quadraticAttenuation");
+
+    if (attrib == IN_ambient) {
+#ifndef NDEBUG
+      Light *light = np.node()->as_light();
+      nassertr(light != (Light *)NULL, &LMatrix4::ident_mat());
+#endif
+      // Lights don't currently have an ambient color in Panda3D.
+      // We still have to support the attribute.
+      t.set_row(3, LColor(0.0f, 0.0f, 0.0f, 1.0f));
+      return &t;
+
+    } else if (attrib == IN_diffuse) {
+      Light *light = np.node()->as_light();
+      nassertr(light != (Light *)NULL, &LMatrix4::ones_mat());
+
+      LColor c = light->get_color();
+      c.componentwise_mult(_light_color_scale);
+      t.set_row(3, c);
+      return &t;
+
+    } else if (attrib == IN_specular) {
+      Light *light = np.node()->as_light();
+      nassertr(light != (Light *)NULL, &LMatrix4::ones_mat());
+      t.set_row(3, light->get_specular_color());
+      return &t;
+
+    } else if (attrib == IN_position) {
+      if (np.node()->is_of_type(DirectionalLight::get_class_type())) {
+        DirectionalLight *light;
+        DCAST_INTO_R(light, np.node(), &LMatrix4::ident_mat());
+
+        CPT(TransformState) transform = np.get_transform(_scene_setup->get_scene_root().get_parent());
+        LVector3 dir = -(light->get_direction() * transform->get_mat());
+        dir *= get_scene()->get_cs_world_transform()->get_mat();
+        t = LMatrix4(0,0,0,0,0,0,0,0,0,0,0,0,dir[0],dir[1],dir[2],0);
+        return &t;
+      } else {
+        LightLensNode *light;
+        DCAST_INTO_R(light, np.node(), &LMatrix4::ident_mat());
+        Lens *lens = light->get_lens();
+        nassertr(lens != (Lens *)NULL, &LMatrix4::ident_mat());
+
+        CPT(TransformState) transform =
+          get_scene()->get_cs_world_transform()->compose(
+            np.get_transform(_scene_setup->get_scene_root().get_parent()));
+
+        const LMatrix4 &light_mat = transform->get_mat();
+        LPoint3 pos = lens->get_nodal_point() * light_mat;
+        t = LMatrix4::translate_mat(pos);
+        return &t;
+      }
+    } else if (attrib == IN_spotDirection) {
+      LightLensNode *light;
+      DCAST_INTO_R(light, np.node(), &LMatrix4::ident_mat());
+      Lens *lens = light->get_lens();
+      nassertr(lens != (Lens *)NULL, &LMatrix4::ident_mat());
+
+      CPT(TransformState) transform =
+        get_scene()->get_cs_world_transform()->compose(
+          np.get_transform(_scene_setup->get_scene_root().get_parent()));
+
+      const LMatrix4 &light_mat = transform->get_mat();
+      LVector3 dir = lens->get_view_vector() * light_mat;
+      t.set_row(3, dir);
+      return &t;
+
+    } else if (attrib == IN_spotCutoff) {
+      if (np.node()->is_of_type(Spotlight::get_class_type())) {
+        LightLensNode *light;
+        DCAST_INTO_R(light, np.node(), &LMatrix4::ident_mat());
+        Lens *lens = light->get_lens();
+        nassertr(lens != (Lens *)NULL, &LMatrix4::ident_mat());
+
+        float cutoff = lens->get_hfov() * 0.5f;
+        t.set_row(3, LVecBase4(cutoff));
+        return &t;
+      } else {
+        // Other lights have no cut-off.
+        t.set_row(3, LVecBase4(180));
+        return &t;
+      }
+
+    } else if (attrib == IN_spotCosCutoff) {
+      if (np.node()->is_of_type(Spotlight::get_class_type())) {
+        LightLensNode *light;
+        DCAST_INTO_R(light, np.node(), &LMatrix4::ident_mat());
+        Lens *lens = light->get_lens();
+        nassertr(lens != (Lens *)NULL, &LMatrix4::ident_mat());
+
+        float cutoff = lens->get_hfov() * 0.5f;
+        t.set_row(3, LVecBase4(ccos(deg_2_rad(cutoff))));
+        return &t;
+      } else {
+        // Other lights have no cut-off.
+        t.set_row(3, LVecBase4(-1));
+        return &t;
+      }
+    } else if (attrib == IN_spotExponent) {
+      Light *light = np.node()->as_light();
+      nassertr(light != (Light *)NULL, &LMatrix4::ident_mat());
+
+      t.set_row(3, LVecBase4(light->get_exponent()));
+      return &t;
+
+    } else if (attrib == IN_constantAttenuation) {
+      Light *light = np.node()->as_light();
+      nassertr(light != (Light *)NULL, &LMatrix4::ones_mat());
+
+      t.set_row(3, LVecBase4(light->get_attenuation()[0]));
+      return &t;
+
+    } else if (attrib == IN_linearAttenuation) {
+      Light *light = np.node()->as_light();
+      nassertr(light != (Light *)NULL, &LMatrix4::ident_mat());
+
+      t.set_row(3, LVecBase4(light->get_attenuation()[1]));
+      return &t;
+
+    } else if (attrib == IN_quadraticAttenuation) {
+      Light *light = np.node()->as_light();
+      nassertr(light != (Light *)NULL, &LMatrix4::ident_mat());
+
+      t.set_row(3, LVecBase4(light->get_attenuation()[2]));
+      return &t;
+
+    } else {
+      display_cat.error()
+        << "Shader input requests invalid attribute " << *name
+        << " from node " << np << "\n";
+      return &LMatrix4::ident_mat();
+    }
+  }
   default:
     nassertr(false /*should never get here*/, &LMatrix4::ident_mat());
     return &LMatrix4::ident_mat();
@@ -2732,6 +2910,13 @@ close_gsg() {
   Thread *current_thread = Thread::get_current_thread();
   _prepared_objects->begin_frame(this, current_thread);
   _prepared_objects->end_frame(current_thread);
+
+  // We have to clear the list of timer queries, though, otherwise
+  // their destructors will cause a crash when they try to access
+  // the GSG object.
+#ifdef DO_PSTATS
+  _pending_timer_queries.clear();
+#endif
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -2973,6 +3158,18 @@ make_shadow_buffer(const NodePath &light_np, GraphicsOutputBase *host) {
   return tex;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: GraphicsStateGuardian::has_extension
+//       Access: Public, Virtual
+//  Description: Returns true if the GSG implements the extension
+//               identified by the given string.  This currently
+//               is only implemented by the OpenGL back-end.
+////////////////////////////////////////////////////////////////////
+bool GraphicsStateGuardian::
+has_extension(const string &extension) const {
+  return false;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: GraphicsStateGuardian::get_driver_vendor
 //       Access: Public, Virtual

+ 6 - 2
panda/src/display/graphicsStateGuardian.h

@@ -49,10 +49,10 @@
 #include "shaderAttrib.h"
 #include "texGenAttrib.h"
 #include "textureAttrib.h"
+#include "shaderGenerator.h"
 
 class DrawableRegion;
 class GraphicsEngine;
-class ShaderGenerator;
 
 ////////////////////////////////////////////////////////////////////
 //       Class : GraphicsStateGuardian
@@ -104,6 +104,9 @@ PUBLISHED:
   INLINE void set_loader(Loader *loader);
   INLINE Loader *get_loader() const;
 
+  INLINE void set_shader_generator(ShaderGenerator *shader_generator);
+  INLINE ShaderGenerator *get_shader_generator() const;
+
   INLINE GraphicsPipe *get_pipe() const;
   GraphicsEngine *get_engine() const;
   INLINE const GraphicsThreadingModel &get_threading_model() const;
@@ -198,6 +201,7 @@ PUBLISHED:
 #endif
 
 PUBLISHED:
+  virtual bool has_extension(const string &extension) const;
 
   virtual string get_driver_vendor();
   virtual string get_driver_renderer();
@@ -546,7 +550,7 @@ protected:
   PN_stdfloat _gamma;
   Texture::QualityLevel _texture_quality_override;
 
-  ShaderGenerator* _shader_generator;
+  PT(ShaderGenerator) _shader_generator;
 
 #ifndef NDEBUG
   PT(Texture) _flash_texture;

+ 35 - 6
panda/src/display/standardMunger.cxx

@@ -43,15 +43,18 @@ StandardMunger(GraphicsStateGuardianBase *gsg, const RenderState *state,
 
   _munge_color = false;
   _munge_color_scale = false;
+  _auto_shader = false;
 
   if (!get_gsg()->get_runtime_color_scale()) {
     // We might need to munge the colors.
-    CPT(ColorAttrib) color_attrib = DCAST(ColorAttrib, state->get_attrib(ColorAttrib::get_class_slot()));
-    CPT(ColorScaleAttrib) color_scale_attrib = DCAST(ColorScaleAttrib, state->get_attrib(ColorScaleAttrib::get_class_slot()));
+    const ColorAttrib *color_attrib = (const ColorAttrib *)
+      state->get_attrib(ColorAttrib::get_class_slot());
+    const ColorScaleAttrib *color_scale_attrib = (const ColorScaleAttrib *)
+      state->get_attrib(ColorScaleAttrib::get_class_slot());
 
     if (color_attrib != (ColorAttrib *)NULL && 
         color_attrib->get_color_type() == ColorAttrib::T_flat) {
-      
+
       if (!get_gsg()->get_color_scale_via_lighting()) {
         // We only need to munge the color directly if the GSG says it
         // can't cheat the color via lighting (presumably, in this case,
@@ -72,15 +75,16 @@ StandardMunger(GraphicsStateGuardianBase *gsg, const RenderState *state,
                color_scale_attrib->has_scale()) {
       _color_scale = color_scale_attrib->get_scale();
       
-      CPT(TextureAttrib) tex_attrib = DCAST(TextureAttrib, state->get_attrib(TextureAttrib::get_class_slot()));
-      
+      const TextureAttrib *tex_attrib = (const TextureAttrib *)
+        state->get_attrib(TextureAttrib::get_class_slot());
+
       // If the GSG says it can't cheat this RGB or alpha scale, we have
       // to apply the color scale directly.
       if ((color_scale_attrib->has_rgb_scale() && !get_gsg()->get_color_scale_via_lighting()) ||
           (color_scale_attrib->has_alpha_scale() && !get_gsg()->get_alpha_scale_via_texture(tex_attrib))) {
         _munge_color_scale = true;
       }
-      
+
       // Known bug: if there is a material on an object that would
       // obscure the effect of color_scale, we scale the lighting
       // anyway, thus applying the effect even if it should be obscured.
@@ -88,6 +92,12 @@ StandardMunger(GraphicsStateGuardianBase *gsg, const RenderState *state,
       // situation and handle it correctly.
     }
   }
+
+  const ShaderAttrib *shader_attrib = (const ShaderAttrib *)
+    state->get_attrib_def(ShaderAttrib::get_class_slot());
+  if (shader_attrib->auto_shader()) {
+    _auto_shader = true;
+  }
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -297,6 +307,10 @@ compare_to_impl(const GeomMunger *other) const {
     }
   }
 
+  if (_auto_shader != om->_auto_shader) {
+    return (int)_auto_shader - (int)om->_auto_shader;
+  }
+
   return StateMunger::compare_to_impl(other);
 }
 
@@ -351,5 +365,20 @@ munge_state_impl(const RenderState *state) {
     munged_state = munged_state->remove_attrib(ColorScaleAttrib::get_class_slot());
   }
 
+  if (_auto_shader) {
+    CPT(RenderState) shader_state = munged_state->get_auto_shader_state();
+    ShaderGenerator *shader_generator = get_gsg()->get_shader_generator();
+    if (shader_generator == NULL) {
+      pgraph_cat.error()
+        << "auto_shader enabled, but GSG has no shader generator assigned!\n";
+      return munged_state;
+    }
+    if (shader_state->_generated_shader == NULL) {
+      // Cache the generated ShaderAttrib on the shader state.
+      shader_state->_generated_shader = shader_generator->synthesize_shader(shader_state);
+    }
+    munged_state = munged_state->set_attrib(shader_state->_generated_shader);
+  }
+
   return munged_state;
 }

+ 1 - 0
panda/src/display/standardMunger.h

@@ -57,6 +57,7 @@ private:
 
   bool _munge_color;
   bool _munge_color_scale;
+  bool _auto_shader;
 
   LColor _color;
   LVecBase4 _color_scale;

+ 17 - 17
panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx

@@ -84,7 +84,9 @@ D3DMATRIX DXGraphicsStateGuardian9::_d3d_ident_mat;
 unsigned char *DXGraphicsStateGuardian9::_temp_buffer = NULL;
 unsigned char *DXGraphicsStateGuardian9::_safe_buffer_start = NULL;
 
+#ifdef HAVE_CG
 LPDIRECT3DDEVICE9 DXGraphicsStateGuardian9::_cg_device = NULL;
+#endif
 
 #define __D3DLIGHT_RANGE_MAX ((PN_stdfloat)sqrt(FLT_MAX))  //for some reason this is missing in dx9 hdrs
 
@@ -150,6 +152,10 @@ DXGraphicsStateGuardian9(GraphicsEngine *engine, GraphicsPipe *pipe) :
 
   _supports_stream_offset = false;
 
+#ifdef HAVE_CG
+  _cg_context = 0;
+#endif
+
   get_gamma_table();
   atexit (atexit_function);
 }
@@ -2372,6 +2378,8 @@ reset() {
 #ifdef HAVE_CG
   set_cg_device(_d3d_device);
 
+  _cg_context = cgCreateContext();
+
   if (cgD3D9IsProfileSupported(CG_PROFILE_PS_2_0) &&
       cgD3D9IsProfileSupported(CG_PROFILE_VS_2_0)) {
     _supports_basic_shaders = true;
@@ -2388,7 +2396,6 @@ reset() {
   }
 
   if (dxgsg9_cat.is_debug()) {
-
     CGprofile vertex_profile;
     CGprofile pixel_profile;
 
@@ -2408,8 +2415,8 @@ reset() {
     }
 
     dxgsg9_cat.debug()
-      << "\nCg vertex profile = " << vertex_profile_str << "  id = " << vertex_profile
-      << "\nCg pixel profile = " << pixel_profile_str << "  id = " << pixel_profile
+      << "\nCg latest vertex profile = " << vertex_profile_str << "  id = " << vertex_profile
+      << "\nCg latest pixel profile = " << pixel_profile_str << "  id = " << pixel_profile
       << "\nshader model = " << _shader_model
       << "\n";
   }
@@ -3194,16 +3201,6 @@ set_state_and_transform(const RenderState *target,
   _target_rs = target;
 
   _target_shader = DCAST(ShaderAttrib, _target_rs->get_attrib_def(ShaderAttrib::get_class_slot()));
-  if (_target_shader->auto_shader()) {
-    // If we don't have a generated shader, make sure we have a ShaderGenerator, then generate the shader.
-    if (_target_rs->_generated_shader == NULL) {
-      if (_shader_generator == NULL) {
-        _shader_generator = new ShaderGenerator(this, _scene_setup->get_display_region()->get_window());
-      }
-      const_cast<RenderState*>(_target_rs.p())->_generated_shader = DCAST(ShaderAttrib, _shader_generator->synthesize_shader(_target_rs));
-    }
-    _target_shader = DCAST(ShaderAttrib, _target_rs->_generated_shader);
-  }
 
   int alpha_test_slot = AlphaTestAttrib::get_class_slot();
   if (_target_rs->get_attrib(alpha_test_slot) != _state_rs->get_attrib(alpha_test_slot) ||
@@ -3751,7 +3748,7 @@ update_standard_texture_bindings() {
 
     switch (mode) {
     case TexGenAttrib::M_off:
-    case TexGenAttrib::M_light_vector:
+    case TexGenAttrib::M_unused2:
       set_texture_stage_state(si, D3DTSS_TEXCOORDINDEX, texcoord_index);
       break;
 
@@ -4162,6 +4159,12 @@ close_gsg() {
 ////////////////////////////////////////////////////////////////////
 void DXGraphicsStateGuardian9::
 free_nondx_resources() {
+#ifdef HAVE_CG
+  if (_cg_context) {
+    cgDestroyContext(_cg_context);
+    _cg_context = 0;
+  }
+#endif
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -5638,9 +5641,6 @@ set_cg_device(LPDIRECT3DDEVICE9 cg_device) {
 #endif // HAVE_CG
 }
 
-
-
-
 typedef string KEY;
 
 typedef struct _KEY_ELEMENT

+ 3 - 0
panda/src/dxgsg9/dxGraphicsStateGuardian9.h

@@ -377,7 +377,10 @@ protected:
 
   int _supports_gamma_calibration;
 
+#ifdef HAVE_CG
+  CGcontext _cg_context;
   static LPDIRECT3DDEVICE9 _cg_device;
+#endif
 
 public:
   virtual TypeHandle get_type() const {

+ 5 - 6
panda/src/dxgsg9/dxShaderContext9.I

@@ -12,6 +12,7 @@
 //
 ////////////////////////////////////////////////////////////////////
 
+
 ////////////////////////////////////////////////////////////////////
 //     Function: DXShaderContext9::valid
 //       Access: Public
@@ -22,12 +23,10 @@
 //               or if no shader languages are compiled into panda.
 ////////////////////////////////////////////////////////////////////
 INLINE bool CLP(ShaderContext)::
-valid (GSG *gsg) {
+valid(GSG *gsg) {
 #ifdef HAVE_CG
-  if (_cg_context) {
-    return true;
-  }
-#endif
+  return (_cg_program != 0);
+#else
   return false;
+#endif
 }
-

+ 28 - 113
panda/src/dxgsg9/dxShaderContext9.cxx

@@ -22,8 +22,9 @@
 #include <fcntl.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+
 #ifdef HAVE_CG
-#include "Cg/cgD3D9.h"
+#include <Cg/cgD3D9.h>
 #endif
 
 #define DEBUG_SHADER 0
@@ -37,89 +38,42 @@ TypeHandle CLP(ShaderContext)::_type_handle;
 ////////////////////////////////////////////////////////////////////
 CLP(ShaderContext)::
 CLP(ShaderContext)(Shader *s, GSG *gsg) : ShaderContext(s) {
-
   _vertex_element_array = NULL;
   _vertex_declaration = NULL;
 
   _num_bound_streams = 0;
 
-  _name = s->get_filename ( );
+  _name = s->get_filename();
 
 #ifdef HAVE_CG
-  _cg_context = 0;
+  CGcontext context = DCAST(DXGraphicsStateGuardian9, gsg)->_cg_context;
+
   if (s->get_language() == Shader::SL_Cg) {
 
     // Ask the shader to compile itself for us and
     // to give us the resulting Cg program objects.
-
-    if (!s->cg_compile_for(gsg->_shader_caps,
-                           _cg_context,
-                           _cg_vprogram,
-                           _cg_fprogram,
-                           _cg_gprogram,        // CG2 CHANGE
-                           _cg_parameter_map)) {
+    if (!s->cg_compile_for(gsg->_shader_caps, context,
+                           _cg_program, _cg_parameter_map)) {
       return;
     }
 
     // Load the program.
-
-    BOOL paramater_shadowing;
-    DWORD assembly_flags;
-
-    paramater_shadowing = FALSE;
-    assembly_flags = 0;
-
+    DWORD assembly_flags = 0;
 #if DEBUG_SHADER
     assembly_flags |= D3DXSHADER_DEBUG;
 #endif
 
     HRESULT hr;
     bool success = true;
-    hr = cgD3D9LoadProgram(_cg_vprogram, paramater_shadowing, assembly_flags);
-    if (FAILED (hr)) {
-      dxgsg9_cat.error()
-        << "vertex shader cgD3D9LoadProgram failed "
-        << D3DERRORSTRING(hr);
-
-      CGerror error = cgGetError();
-      if (error != CG_NO_ERROR) {
-        dxgsg9_cat.error() << "  CG ERROR: " << cgGetErrorString(error) << "\n";
-      }
-      success = false;
-    }
-
-    hr = cgD3D9LoadProgram(_cg_fprogram, paramater_shadowing, assembly_flags);
+    hr = cgD3D9LoadProgram(_cg_program, FALSE, assembly_flags);
     if (FAILED (hr)) {
       dxgsg9_cat.error()
-        << "pixel shader cgD3D9LoadProgram failed "
-        << D3DERRORSTRING(hr);
+        << "cgD3D9LoadProgram failed " << D3DERRORSTRING(hr);
 
       CGerror error = cgGetError();
       if (error != CG_NO_ERROR) {
         dxgsg9_cat.error() << "  CG ERROR: " << cgGetErrorString(error) << "\n";
       }
-      success = false;
-    }
-
-    // BEGIN CG2 CHANGE
-    if (_cg_gprogram != 0)
-    {
-        hr = cgD3D9LoadProgram(_cg_gprogram, paramater_shadowing, assembly_flags);
-        if (FAILED (hr)) {
-          dxgsg9_cat.error()
-            << "geometry shader cgD3D9LoadProgram failed "
-            << D3DERRORSTRING(hr);
-
-          CGerror error = cgGetError();
-          if (error != CG_NO_ERROR) {
-            dxgsg9_cat.error() << "  CG ERROR: " << cgGetErrorString(error) << "\n";
-          }
-          success = false;
-        }
-    }
-    // END CG2 CHANGE
-
-    if (!success) {
       release_resources();
     }
   }
@@ -203,12 +157,9 @@ CLP(ShaderContext)::
 void CLP(ShaderContext)::
 release_resources() {
 #ifdef HAVE_CG
-  if (_cg_context) {
-    cgDestroyContext(_cg_context);
-    _cg_context = 0;
-    _cg_vprogram = 0;
-    _cg_fprogram = 0;
-    _cg_gprogram = 0;   // CG2 CHANGE
+  if (_cg_program) {
+    cgDestroyProgram(_cg_program);
+    _cg_program = 0;
     _cg_parameter_map.clear();
   }
 #endif
@@ -228,11 +179,10 @@ release_resources() {
 bool CLP(ShaderContext)::
 bind(GSG *gsg) {
 
-  bool bind_state;
+  bool bind_state = false;
 
-  bind_state = false;
 #ifdef HAVE_CG
-  if (_cg_context) {
+  if (_cg_program) {
     // clear the last cached FVF to make sure the next SetFVF call goes through
 
     gsg -> _last_fvf = 0;
@@ -244,20 +194,9 @@ bind(GSG *gsg) {
 
     // Bind the shaders.
     bind_state = true;
-    hr = cgD3D9BindProgram(_cg_vprogram);
-    if (FAILED (hr)) {
-      dxgsg9_cat.error() << "cgD3D9BindProgram vertex shader failed " << D3DERRORSTRING(hr);
-
-      CGerror error = cgGetError();
-      if (error != CG_NO_ERROR) {
-        dxgsg9_cat.error() << "  CG ERROR: " << cgGetErrorString(error) << "\n";
-      }
-
-      bind_state = false;
-    }
-    hr = cgD3D9BindProgram(_cg_fprogram);
+    hr = cgD3D9BindProgram(_cg_program);
     if (FAILED (hr)) {
-      dxgsg9_cat.error() << "cgD3D9BindProgram pixel shader failed " << D3DERRORSTRING(hr);
+      dxgsg9_cat.error() << "cgD3D9BindProgram failed " << D3DERRORSTRING(hr);
 
       CGerror error = cgGetError();
       if (error != CG_NO_ERROR) {
@@ -266,23 +205,6 @@ bind(GSG *gsg) {
 
       bind_state = false;
     }
-
-    // BEGIN CG2 CHANGE
-    if (_cg_gprogram != 0)
-    {
-        hr = cgD3D9BindProgram(_cg_gprogram);
-        if (FAILED (hr)) {
-          dxgsg9_cat.error() << "cgD3D9BindProgram geometry shader failed " << D3DERRORSTRING(hr);
-
-          CGerror error = cgGetError();
-          if (error != CG_NO_ERROR) {
-            dxgsg9_cat.error() << "  CG ERROR: " << cgGetErrorString(error) << "\n";
-          }
-
-          bind_state = false;
-        }
-    }
-    // END CG2 CHANGE
   }
 #endif
 
@@ -298,18 +220,12 @@ void CLP(ShaderContext)::
 unbind(GSG *gsg) {
 
 #ifdef HAVE_CG
-  if (_cg_context) {
+  if (_cg_program) {
     HRESULT hr;
-
-    hr = gsg -> _d3d_device -> SetVertexShader (NULL);
-    if (FAILED (hr)) {
+    hr = cgD3D9UnbindProgram(_cg_program);
+    if (FAILED(hr)) {
       dxgsg9_cat.error()
-        << "SetVertexShader (NULL) failed " << D3DERRORSTRING(hr);
-    }
-    hr = gsg -> _d3d_device -> SetPixelShader (NULL);
-    if (FAILED (hr)) {
-      dxgsg9_cat.error()
-        << "SetPixelShader (NULL) failed " << D3DERRORSTRING(hr);
+        << "cgD3D9UnbindProgram failed " << D3DERRORSTRING(hr);
     }
   }
 #endif
@@ -339,10 +255,9 @@ InternalName *global_internal_name_1 = 0;
 #endif
 
 void CLP(ShaderContext)::
-issue_parameters(GSG *gsg, int altered)
-{
+issue_parameters(GSG *gsg, int altered) {
 #ifdef HAVE_CG
-  if (_cg_context) {
+  if (_cg_program) {
 
   // Iterate through _ptr parameters
     for (int i=0; i<(int)_shader->_ptr_spec.size(); i++) {
@@ -510,7 +425,7 @@ bool CLP(ShaderContext)::
 update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg, bool force) {
   if (prev) prev->disable_shader_vertex_arrays(gsg);
 #ifdef HAVE_CG
-  if (!_cg_context) {
+  if (!_cg_program) {
     return true;
   }
 
@@ -717,11 +632,11 @@ update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg, bool force) {
 
     if (( _vertex_element_array != NULL ) &&
         ( _vertex_element_array->add_end_vertex_element() != false )) {
-      if ( dxgsg9_cat.is_debug() ) {
+      if (dxgsg9_cat.is_debug()) {
         // Note that the currently generated vertex declaration works but never validates.
         // My theory is that this is due to the shader programs always using float4 whereas
         // the vertex declaration correctly sets the number of inputs (float2, float3, etc.).
-        if (cgD3D9ValidateVertexDeclaration(_cg_vprogram,
+        if (cgD3D9ValidateVertexDeclaration(_cg_program,
                                             _vertex_element_array->_vertex_element_array) == CG_TRUE) {
           dxgsg9_cat.debug() << "cgD3D9ValidateVertexDeclaration succeeded\n";
         } else {
@@ -763,7 +678,7 @@ void CLP(ShaderContext)::
 disable_shader_texture_bindings(GSG *gsg)
 {
 #ifdef HAVE_CG
-  if (_cg_context) {
+  if (_cg_program) {
     for (int i=0; i<(int)_shader->_tex_spec.size(); i++) {
       CGparameter p = _cg_parameter_map[_shader->_tex_spec[i]._id._seqno];
       if (p == NULL) {
@@ -803,7 +718,7 @@ update_shader_texture_bindings(CLP(ShaderContext) *prev, GSG *gsg)
   if (prev) prev->disable_shader_texture_bindings(gsg);
 
 #ifdef HAVE_CG
-  if (_cg_context) {
+  if (_cg_program) {
 
     for (int i=0; i<(int)_shader->_tex_spec.size(); i++) {
       CGparameter p = _cg_parameter_map[_shader->_tex_spec[i]._id._seqno];

+ 6 - 18
panda/src/dxgsg9/dxShaderContext9.h

@@ -22,11 +22,9 @@
 #include "shader.h"
 #include "shaderContext.h"
 
-
 #define CLP(name) DX##name##9
 #define CLASSPREFIX_QUOTED "DX"
 
-
 class VertexElementArray;
 class CLP(GraphicsStateGuardian);
 
@@ -41,7 +39,7 @@ class CLP(GraphicsStateGuardian);
 //   D3DXCONSTANT_DESC *constant_description_array;
 // }
 // DX_PARAMETER;
-// 
+//
 // typedef struct
 // {
 //   int state;
@@ -52,7 +50,7 @@ class CLP(GraphicsStateGuardian);
 //   };
 //   LPD3DXCONSTANTTABLE constant_table;
 //   D3DXCONSTANTTABLE_DESC constant_table_description;
-// 
+//
 //   int total_semantics;
 //   D3DXSEMANTIC *semantic_array;
 // }
@@ -62,11 +60,10 @@ class CLP(GraphicsStateGuardian);
 //       Class : DXShaderContext9
 // Description : xyz
 ////////////////////////////////////////////////////////////////////
-
-class EXPCL_PANDADX CLP(ShaderContext): public ShaderContext {
+class EXPCL_PANDADX CLP(ShaderContext) : public ShaderContext {
 public:
   typedef CLP(GraphicsStateGuardian) GSG;
-  
+
   CLP(ShaderContext)(Shader *s, GSG *gsg);
   ~CLP(ShaderContext)();
 
@@ -88,23 +85,14 @@ public:
 
   // FOR DEBUGGING
   string _name;
-  
-private:
 
+private:
 #ifdef HAVE_CG
-  CGcontext _cg_context;
-  CGprogram _cg_vprogram;
-  CGprogram _cg_fprogram;
-
-  // BEGIN CG2 CHANGE
-  CGprogram _cg_gprogram;   // Geometry program
-  // END CG2 CHANGE
-
+  CGprogram _cg_program;
   pvector <CGparameter> _cg_parameter_map;
 #endif
 
 private:
-
   void release_resources(void);
 
 public:

+ 36 - 0
panda/src/express/openSSLWrapper.I

@@ -12,3 +12,39 @@
 //
 ////////////////////////////////////////////////////////////////////
 
+
+////////////////////////////////////////////////////////////////////
+//     Function: OpenSSLWrapper::load_certificates_from_pem_ram
+//       Access: Public
+//  Description: Reads a chain of trusted certificates from the
+//               indicated data buffer and adds them to the X509_STORE
+//               object.  The data buffer should be PEM-formatted.
+//               Returns the number of certificates read on success,
+//               or 0 on failure.
+//
+//               You should call this only with trusted,
+//               locally-stored certificates; not with certificates
+//               received from an untrusted source.
+////////////////////////////////////////////////////////////////////
+INLINE int OpenSSLWrapper::
+load_certificates_from_pem_ram(const string &data) {
+  return load_certificates_from_pem_ram(data.data(), data.size());
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: OpenSSLWrapper::load_certificates_from_der_ram
+//       Access: Public
+//  Description: Reads a chain of trusted certificates from the
+//               indicated data buffer and adds them to the X509_STORE
+//               object.  The data buffer should be DER-formatted.
+//               Returns the number of certificates read on success,
+//               or 0 on failure.
+//
+//               You should call this only with trusted,
+//               locally-stored certificates; not with certificates
+//               received from an untrusted source.
+////////////////////////////////////////////////////////////////////
+INLINE int OpenSSLWrapper::
+load_certificates_from_der_ram(const string &data) {
+  return load_certificates_from_der_ram(data.data(), data.size());
+}

+ 4 - 1
panda/src/express/openSSLWrapper.h

@@ -48,12 +48,15 @@ private:
   OpenSSLWrapper();
   ~OpenSSLWrapper();
 
-public:
+PUBLISHED:
   void clear_certificates();
   int load_certificates(const Filename &filename);
   int load_certificates_from_pem_ram(const char *data, size_t data_size);
   int load_certificates_from_der_ram(const char *data, size_t data_size);
 
+  INLINE int load_certificates_from_pem_ram(const string &data);
+  INLINE int load_certificates_from_der_ram(const string &data);
+
   X509_STORE *get_x509_store();
 
   void notify_ssl_errors();

+ 9 - 32
panda/src/framework/pandaFramework.cxx

@@ -140,12 +140,6 @@ open_framework(int &argc, char **&argv) {
     _task_mgr.add(task);
   }
 
-  _highlight_wireframe = NodePath("wireframe");
-  _highlight_wireframe.set_render_mode_wireframe(1);
-  _highlight_wireframe.set_texture_off(1);
-  _highlight_wireframe.set_color(1.0f, 0.0f, 0.0f, 1.0f, 1);
-  _highlight_wireframe.set_attrib(DepthOffsetAttrib::make());
-
   if (!playback_session.empty()) {
     // If the config file so indicates, create a recorder and start it
     // playing.
@@ -784,13 +778,7 @@ set_highlight(const NodePath &node) {
   if (!_highlight.is_empty()) {
     framework_cat.info(false) << _highlight << "\n";
     _highlight.show_bounds();
-
-    // Also create a new instance of the highlighted geometry, as a
-    // sibling of itself, under the special highlight property.
-    if (_highlight.has_parent()) {
-      _highlight_wireframe.reparent_to(_highlight.get_parent());
-      _highlight.instance_to(_highlight_wireframe);
-    }
+    _highlight.set_render_mode_filled_wireframe(LColor(1.0f, 0.0f, 0.0f, 1.0f), 200);
   }
 }
 
@@ -803,11 +791,8 @@ void PandaFramework::
 clear_highlight() {
   if (!_highlight.is_empty()) {
     _highlight.hide_bounds();
+    _highlight.clear_render_mode();
     _highlight = NodePath();
-
-    // Clean up the special highlight instance.
-    _highlight_wireframe.detach_node();
-    _highlight_wireframe.get_children().detach();
   }
 }
 
@@ -1012,7 +997,13 @@ event_w(const Event *event, void *) {
     WindowFramework *wf;
     DCAST_INTO_V(wf, param.get_ptr());
 
-    wf->set_wireframe(!wf->get_wireframe());
+    if (!wf->get_wireframe()) {
+      wf->set_wireframe(true, true);
+    } else if (wf->get_wireframe_filled()) {
+      wf->set_wireframe(true, false);
+    } else {
+      wf->set_wireframe(false, false);
+    }
   }
 }
 
@@ -1286,13 +1277,6 @@ event_arrow_left(const Event *, void *data) {
       int index = parent.node()->find_child(node.node());
       nassertv(index >= 0);
       int sibling = index - 1;
-
-      if (sibling >= 0 &&
-          parent.node()->get_child(sibling) == self->_highlight_wireframe.node()) {
-        // Skip over the special highlight node.
-        sibling--;
-      }
-
       if (sibling >= 0) {
         self->set_highlight(NodePath(parent, parent.node()->get_child(sibling)));
       }
@@ -1319,13 +1303,6 @@ event_arrow_right(const Event *, void *data) {
       nassertv(index >= 0);
       int num_children = parent.node()->get_num_children();
       int sibling = index + 1;
-
-      if (sibling < num_children &&
-          parent.node()->get_child(sibling) == self->_highlight_wireframe.node()) {
-        // Skip over the special highlight node.
-        sibling++;
-      }
-
       if (sibling < num_children) {
         self->set_highlight(NodePath(parent, parent.node()->get_child(sibling)));
       }

+ 12 - 1
panda/src/framework/windowFramework.I

@@ -33,7 +33,7 @@ get_panda_framework() const {
 ////////////////////////////////////////////////////////////////////
 INLINE GraphicsWindow *WindowFramework::
 get_graphics_window() const {
-  if (_window != (GraphicsOutput *)NULL && 
+  if (_window != (GraphicsOutput *)NULL &&
       _window->is_of_type(GraphicsWindow::get_class_type())) {
     return DCAST(GraphicsWindow, _window);
   }
@@ -117,6 +117,17 @@ get_wireframe() const {
   return _wireframe_enabled;
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: WindowFramework::get_wireframe_filled
+//       Access: Public
+//  Description: Returns the current state of the wireframe_filled
+//               flag.
+////////////////////////////////////////////////////////////////////
+INLINE bool WindowFramework::
+get_wireframe_filled() const {
+  return _wireframe_filled;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: WindowFramework::get_texture
 //       Access: Public

+ 29 - 14
panda/src/framework/windowFramework.cxx

@@ -85,6 +85,7 @@ WindowFramework(PandaFramework *panda_framework) :
   _anim_controls_enabled = false;
   _anim_index = 0;
   _wireframe_enabled = false;
+  _wireframe_filled = false;
   _texture_enabled = true;
   _two_sided_enabled = false;
   _one_sided_reverse_enabled = false;
@@ -358,7 +359,7 @@ get_pixel_2d() {
     PGTop *top = new PGTop("pixel_2d");
     _pixel_2d = get_render_2d().attach_new_node(top);
     _pixel_2d.set_pos(-1, 0, 1);
-  
+
     if (_window->has_size()) {
       int x_size = _window->get_sbs_left_x_size();
       int y_size = _window->get_sbs_left_y_size();
@@ -649,7 +650,7 @@ load_model(const NodePath &parent, Filename filename) {
         // A texture object.  Not exactly an image, but certainly a
         // texture.
         is_image = true;
-        
+
       } else {
         TexturePool *texture_pool = TexturePool::get_global_ptr();
         if (texture_pool->get_texture_type(extension) != NULL) {
@@ -841,7 +842,7 @@ adjust_dimensions() {
     x_size = _window->get_sbs_left_x_size();
     y_size = _window->get_sbs_left_y_size();
   }
-  
+
   if (this_aspect_ratio == 0.0f) {
     // An aspect ratio of 0.0 means to try to infer it.
     this_aspect_ratio = 1.0f;
@@ -938,28 +939,42 @@ split_window(SplitType split_type) {
 //               rendering (false).
 ////////////////////////////////////////////////////////////////////
 void WindowFramework::
-set_wireframe(bool enable) {
-  if (enable == _wireframe_enabled) {
+set_wireframe(bool enable, bool filled) {
+  if (enable == _wireframe_enabled && filled == _wireframe_filled) {
     return;
   }
 
   NodePath render = get_render();
 
+  if (!_two_sided_enabled) {
+    render.clear_two_sided();
+  }
+
   if (enable) {
-    render.set_render_mode_wireframe(override_priority);
-    render.set_two_sided(true, override_priority);
+    if (filled) {
+      render.set_attrib(RenderModeAttrib::make(
+        RenderModeAttrib::M_filled_wireframe,
+        1.4f, false, LColor(1, 1, 1, .5f)),
+        override_priority);
+      // Darken the scene so that the wireframe is clearly visible,
+      // even when the scene is completely white.
+      render.set_color_scale(LColor(0.7f, 0.7f, 0.7f, 1), override_priority);
+    } else {
+      render.set_render_mode_wireframe(override_priority);
+      render.set_two_sided(true, override_priority);
+      render.clear_color_scale();
+    }
   } else {
     render.clear_render_mode();
-    if (!_two_sided_enabled) {
-      render.clear_two_sided();
-    }
     if (_one_sided_reverse_enabled) {
       CPT(RenderAttrib) attrib = CullFaceAttrib::make_reverse();
       render.node()->set_attrib(attrib);
     }
+    render.clear_color_scale();
   }
 
   _wireframe_enabled = enable;
+  _wireframe_filled = filled;
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -1281,7 +1296,7 @@ load_image_as_model(const Filename &filename) {
   } else {
     framework_cat.warning()
       << "Texture size is 0 0: " << *tex << "\n";
-    
+
     left   = -scale;
     right  =  scale;
     top    =  scale;
@@ -1310,9 +1325,9 @@ load_image_as_model(const Filename &filename) {
     // Vertices and 3-d texture coordinates.
     vformat = GeomVertexFormat::register_format
       (new GeomVertexArrayFormat
-       (InternalName::get_vertex(), 3, 
+       (InternalName::get_vertex(), 3,
         GeomEnums::NT_stdfloat, GeomEnums::C_point,
-        InternalName::get_texcoord(), 3, 
+        InternalName::get_texcoord(), 3,
         GeomEnums::NT_stdfloat, GeomEnums::C_texcoord));
   }
 
@@ -1327,7 +1342,7 @@ load_image_as_model(const Filename &filename) {
     vertex.add_data3(LVertex::rfu(left, 0.02, bottom));
     vertex.add_data3(LVertex::rfu(right, 0.02, top));
     vertex.add_data3(LVertex::rfu(right, 0.02, bottom));
-    
+
     texcoord.add_data2(0.0f, tex_scale[1]);
     texcoord.add_data2(0.0f, 0.0f);
     texcoord.add_data2(tex_scale[0], tex_scale[1]);

+ 7 - 5
panda/src/framework/windowFramework.h

@@ -97,7 +97,7 @@ public:
                    const pvector<Filename> &files);
   NodePath load_model(const NodePath &parent, Filename filename);
   NodePath load_default_model(const NodePath &parent);
-  void loop_animations(int hierarchy_match_flags = 
+  void loop_animations(int hierarchy_match_flags =
                        PartGroup::HMF_ok_part_extra |
                        PartGroup::HMF_ok_anim_extra);
   void stagger_animations();
@@ -122,7 +122,7 @@ public:
   };
   WindowFramework *split_window(SplitType split_type = ST_default);
 
-  void set_wireframe(bool enable);
+  void set_wireframe(bool enable, bool filled=false);
   void set_texture(bool enable);
   void set_two_sided(bool enable);
   void set_one_sided_reverse(bool enable);
@@ -131,6 +131,7 @@ public:
   void set_background_type(BackgroundType type);
 
   INLINE bool get_wireframe() const;
+  INLINE bool get_wireframe_filled() const;
   INLINE bool get_texture() const;
   INLINE bool get_two_sided() const;
   INLINE bool get_one_sided_reverse() const;
@@ -150,7 +151,7 @@ private:
   void destroy_anim_controls();
   void update_anim_controls();
 
-  void setup_shuttle_button(const string &label, int index, 
+  void setup_shuttle_button(const string &label, int index,
                             EventHandler::EventCallbackFunction *func);
   void back_button();
   void pause_button();
@@ -194,12 +195,13 @@ private:
 
   NodePath _alight;
   NodePath _dlight;
-  
+
   bool _got_keyboard;
   bool _got_trackball;
   bool _got_lights;
 
   bool _wireframe_enabled;
+  bool _wireframe_filled;
   bool _texture_enabled;
   bool _two_sided_enabled;
   bool _one_sided_reverse_enabled;
@@ -210,7 +212,7 @@ private:
   PT(SceneGraphAnalyzerMeter) _scene_graph_analyzer_meter;
 
   BackgroundType _background_type;
-  
+
   static PT(TextFont) _shuttle_controls_font;
 
 public:

+ 1 - 2
panda/src/glstuff/glCgShaderContext_src.I

@@ -27,8 +27,7 @@ INLINE bool CLP(CgShaderContext)::
 valid() {
   if (_shader->get_error_flag()) return false;
   if (_shader->get_language() != Shader::SL_Cg) return false;
-  if (_cg_context) return true;
-  return false;
+  return (_cg_program != 0);
 }
 
 ////////////////////////////////////////////////////////////////////

+ 117 - 95
panda/src/glstuff/glCgShaderContext_src.cxx

@@ -40,63 +40,40 @@ TypeHandle CLP(CgShaderContext)::_type_handle;
 CLP(CgShaderContext)::
 CLP(CgShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext(s) {
   _glgsg = glgsg;
-  _cg_context = 0;
-  _cg_vprogram = 0;
-  _cg_fprogram = 0;
-  _cg_gprogram = 0;
-  _cg_vprofile = CG_PROFILE_UNKNOWN;
-  _cg_fprofile = CG_PROFILE_UNKNOWN;
-  _cg_gprofile = CG_PROFILE_UNKNOWN;
+  _cg_program = 0;
+  _glsl_profile = false;
 
   nassertv(s->get_language() == Shader::SL_Cg);
 
+  CGcontext context = _glgsg->_cg_context;
+
   // Ask the shader to compile itself for us and
   // to give us the resulting Cg program objects.
-  if (!s->cg_compile_for(_glgsg->_shader_caps,
-                         _cg_context,
-                         _cg_vprogram,
-                         _cg_fprogram,
-                         _cg_gprogram,
-                         _cg_parameter_map)) {
+  if (!s->cg_compile_for(_glgsg->_shader_caps, context,
+                         _cg_program, _cg_parameter_map)) {
     return;
   }
 
   // Load the program.
-  if (_cg_vprogram != 0) {
-    _cg_vprofile = cgGetProgramProfile(_cg_vprogram);
-    cgGLLoadProgram(_cg_vprogram);
-    CGerror verror = cgGetError();
-    if (verror != CG_NO_ERROR) {
-      const char *str = cgGetErrorString(verror);
-      GLCAT.error()
-        << "Could not load Cg vertex program: " << s->get_filename(Shader::ST_vertex)
-        << " (" << cgGetProfileString(_cg_vprofile) << " " << str << ")\n";
-      release_resources();
+  if (_cg_program == 0) {
+    const char *str = cgGetErrorString(cgGetError());
+    GLCAT.error()
+      << "Could not combine Cg program: " << s->get_filename()
+      << " (" << str << ")\n";
+    release_resources();
+
+  } else {
+    if (cgGetProgramProfile(_cg_program) == CG_PROFILE_GLSLC) {
+      _glsl_profile = true;
     }
-  }
 
-  if (_cg_fprogram != 0) {
-    _cg_fprofile = cgGetProgramProfile(_cg_fprogram);
-    cgGLLoadProgram(_cg_fprogram);
-    CGerror ferror = cgGetError();
-    if (ferror != CG_NO_ERROR) {
-      const char *str = cgGetErrorString(ferror);
+    cgGLLoadProgram(_cg_program);
+    CGerror error = cgGetError();
+    if (error != CG_NO_ERROR) {
+      const char *str = cgGetErrorString(error);
       GLCAT.error()
-        << "Could not load Cg fragment program: " << s->get_filename(Shader::ST_fragment)
-        << " (" << cgGetProfileString(_cg_fprofile) << " " << str << ")\n";
-      release_resources();
-    }
-  }
-
-  if (_cg_gprogram != 0) {
-    _cg_gprofile = cgGetProgramProfile(_cg_gprogram);
-    cgGLLoadProgram(_cg_gprogram);
-    CGerror gerror = cgGetError();
-    if (gerror != CG_NO_ERROR) {
-      const char *str = cgGetErrorString(gerror);
-      GLCAT.error()
-        << "Could not load Cg geometry program: " << s->get_filename(Shader::ST_geometry)
-        << " (" << cgGetProfileString(_cg_gprofile) << " " << str << ")\n";
+        << "Could not load program: " << s->get_filename()
+        << " (" << str << ")\n";
       release_resources();
     }
   }
@@ -122,20 +99,14 @@ CLP(CgShaderContext)::
 ////////////////////////////////////////////////////////////////////
 void CLP(CgShaderContext)::
 release_resources() {
-  if (_cg_context) {
-    cgDestroyContext(_cg_context);
-    _cg_context  = 0;
-    // Do *NOT* destroy the programs here! It causes problems.
-//  if (_cg_vprogram != 0) cgDestroyProgram(_cg_vprogram);
-//  if (_cg_fprogram != 0) cgDestroyProgram(_cg_fprogram);
-//  if (_cg_gprogram != 0) cgDestroyProgram(_cg_gprogram);
-    _cg_vprogram = 0;
-    _cg_fprogram = 0;
-    _cg_gprogram = 0;
-    _cg_parameter_map.clear();
+  if (_cg_program != 0) {
+    cgDestroyProgram(_cg_program);
+    _cg_program = 0;
   }
+  _cg_parameter_map.clear();
   if (_glgsg) {
     _glgsg->report_my_gl_errors();
+
   } else if (glGetError() != GL_NO_ERROR) {
     GLCAT.error() << "GL error in ShaderContext destructor\n";
   }
@@ -155,25 +126,15 @@ release_resources() {
 ////////////////////////////////////////////////////////////////////
 void CLP(CgShaderContext)::
 bind(bool reissue_parameters) {
-  if (reissue_parameters) {
-    // Pass in k-parameters and transform-parameters
-    issue_parameters(Shader::SSD_general);
-  }
+  if (_cg_program != 0) {
+    if (reissue_parameters) {
+      // Pass in k-parameters and transform-parameters
+      issue_parameters(Shader::SSD_general);
+    }
 
-  if (_cg_context != 0) {
     // Bind the shaders.
-    if (_cg_vprogram != 0) {
-      cgGLEnableProfile(_cg_vprofile);
-      cgGLBindProgram(_cg_vprogram);
-    }
-    if (_cg_fprogram != 0) {
-      cgGLEnableProfile(_cg_fprofile);
-      cgGLBindProgram(_cg_fprogram);
-    }
-    if (_cg_gprogram != 0) {
-      cgGLEnableProfile(_cg_gprofile);
-      cgGLBindProgram(_cg_gprogram);
-    }
+    cgGLEnableProgramProfiles(_cg_program);
+    cgGLBindProgram(_cg_program);
 
     cg_report_errors();
     _glgsg->report_my_gl_errors();
@@ -187,18 +148,12 @@ bind(bool reissue_parameters) {
 ////////////////////////////////////////////////////////////////////
 void CLP(CgShaderContext)::
 unbind() {
-  if (_cg_context != 0) {
-    if (_cg_vprogram != 0) {
-      cgGLUnbindProgram(_cg_vprofile);
-      cgGLDisableProfile(_cg_vprofile);
-    }
-    if (_cg_fprogram != 0) {
-      cgGLUnbindProgram(_cg_fprofile);
-      cgGLDisableProfile(_cg_fprofile);
-    }
-    if (_cg_gprogram != 0) {
-      cgGLUnbindProgram(_cg_gprofile);
-      cgGLDisableProfile(_cg_gprofile);
+  if (_cg_program != 0) {
+    int num_domains = cgGetNumProgramDomains(_cg_program);
+    for (int i = 0; i < num_domains; ++i) {
+      CGprofile profile = cgGetProgramDomainProfile(_cg_program, i);
+      cgGLUnbindProgram(profile);
+      cgGLDisableProfile(profile);
     }
 
     cg_report_errors();
@@ -396,7 +351,25 @@ disable_shader_vertex_arrays() {
   for (int i=0; i<(int)_shader->_var_spec.size(); i++) {
     CGparameter p = _cg_parameter_map[_shader->_var_spec[i]._id._seqno];
     if (p == 0) continue;
-    cgGLDisableClientState(p);
+
+    if (_glsl_profile && cgGetParameterBaseResource(p) == CG_ATTR0) {
+      int index = cgGetParameterResourceIndex(p);
+      if (index >= 8) {
+        _glgsg->_glClientActiveTexture(GL_TEXTURE0 + (index - 8));
+        glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+
+      } else if (index == 0) {
+        glDisableClientState(GL_VERTEX_ARRAY);
+
+      } else if (index == 2) {
+        glDisableClientState(GL_NORMAL_ARRAY);
+
+      } else if (index == 3) {
+        glDisableClientState(GL_COLOR_ARRAY);
+      }
+    } else {
+      cgGLDisableClientState(p);
+    }
   }
 
   cg_report_errors();
@@ -464,20 +437,68 @@ update_shader_vertex_arrays(ShaderContext *prev, bool force) {
         CGparameter p = _cg_parameter_map[_shader->_var_spec[i]._id._seqno];
 
         if (numeric_type == GeomEnums::NT_packed_dabc) {
-          cgGLSetParameterPointer(p, GL_BGRA, GL_UNSIGNED_BYTE,
-                                  stride, client_pointer + start);
+          // Yes, this is a thing.
+          num_values = GL_BGRA;
+        }
+
+        // This is truly the most preposterous hack.  When using the GLSL
+        // profiles, cgGLSetParameterPointer relies on the the driver mapping
+        // standard attributes to fixed indices (and breaking the spec doing
+        // so), which only the NVIDIA drivers do.  Unbelievable.
+        if (_glsl_profile && cgGetParameterBaseResource(p) == CG_ATTR0) {
+          int index = cgGetParameterResourceIndex(p);
+          switch (index) {
+          case 0:  // gl_Vertex
+            glVertexPointer(num_values, _glgsg->get_numeric_type(numeric_type),
+                            stride, client_pointer + start);
+            glEnableClientState(GL_VERTEX_ARRAY);
+            break;
+
+          case 2:  // gl_Normal
+            glNormalPointer(_glgsg->get_numeric_type(numeric_type),
+                            stride, client_pointer + start);
+            glEnableClientState(GL_NORMAL_ARRAY);
+            break;
+
+          case 3:  // gl_Color
+            glColorPointer(num_values, _glgsg->get_numeric_type(numeric_type),
+                           stride, client_pointer + start);
+            glEnableClientState(GL_COLOR_ARRAY);
+            break;
+
+          case 4:  // gl_SecondaryColor
+            //glSecondaryColorPointer(num_values, _glgsg->get_numeric_type(numeric_type),
+            //                        stride, client_pointer + start);
+            //glEnableClientState(GL_SECONDARY_COLOR_ARRAY);
+            //break;
+          case 5:  // gl_FogCoord
+          case 6:  // PSIZE?
+          case 7:  // BLENDINDICES?
+          case 1:  // glWeightPointerARB?
+            GLCAT.error()
+              << "Unable to bind " << *name << " to "
+              << cgGetParameterResourceName(p) << "\n";
+            break;
+
+          default:
+            _glgsg->_glClientActiveTexture(GL_TEXTURE0 + (index - 8));
+            glTexCoordPointer(num_values, _glgsg->get_numeric_type(numeric_type),
+                              stride, client_pointer + start);
+            glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+            break;
+          }
         } else {
           if (name == InternalName::get_normal() && num_values == 4) {
-            // In some cases, the normals are aligned to 4 values.
-            // This would cause an error on some rivers, so we tell it
-            // to use the first three values only.
+            // In some cases, the normals are aligned to 4 values.  We tell
+            // it to use three values exactly, otherwise we get the error:
+            // An unsupported GL extension was required to perform this operation.
             num_values = 3;
           }
-          cgGLSetParameterPointer(p,
-                                  num_values, _glgsg->get_numeric_type(numeric_type),
+          cgGLSetParameterPointer(p, num_values,
+                                  _glgsg->get_numeric_type(numeric_type),
                                   stride, client_pointer + start);
+          cgGLEnableClientState(p);
         }
-        cgGLEnableClientState(p);
       } else {
         CGparameter p = _cg_parameter_map[_shader->_var_spec[i]._id._seqno];
         cgGLDisableClientState(p);
@@ -506,6 +527,7 @@ disable_shader_texture_bindings() {
   for (int i=0; i<(int)_shader->_tex_spec.size(); i++) {
     CGparameter p = _cg_parameter_map[_shader->_tex_spec[i]._id._seqno];
     if (p == 0) continue;
+
     int texunit = cgGetParameterResourceIndex(p);
     _glgsg->_glActiveTexture(GL_TEXTURE0 + texunit);
 
@@ -527,7 +549,7 @@ disable_shader_texture_bindings() {
       glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
     }
     // This is probably faster - but maybe not as safe?
-    // cgGLDisableTextureParameter(p);
+    //cgGLDisableTextureParameter(p);
   }
 #endif  // OPENGLES_2
 

+ 5 - 10
panda/src/glstuff/glCgShaderContext_src.h

@@ -1,4 +1,4 @@
-// Filename: glShaderContext_src.h
+// Filename: glCgShaderContext_src.h
 // Created by: jyelon (01Sep05)
 //
 ////////////////////////////////////////////////////////////////////
@@ -51,15 +51,10 @@ public:
   INLINE bool uses_custom_texture_bindings(void);
 
 private:
-  CGcontext _cg_context;
-  CGprogram _cg_vprogram;
-  CGprogram _cg_fprogram;
-  CGprogram _cg_gprogram;
-  CGprofile _cg_vprofile;
-  CGprofile _cg_fprofile;
-  CGprofile _cg_gprofile;
-
-  pvector <CGparameter> _cg_parameter_map;
+  CGprogram _cg_program;
+  bool _glsl_profile;
+
+  pvector<CGparameter> _cg_parameter_map;
 
   CLP(GraphicsStateGuardian) *_glgsg;
 

+ 13 - 14
panda/src/glstuff/glGraphicsBuffer_src.cxx

@@ -445,18 +445,6 @@ rebuild_bitplanes() {
     if (_fbo[layer] == 0) {
       glgsg->_glGenFramebuffers(1, &_fbo[layer]);
 
-#ifndef OPENGLES
-      if (glgsg->_use_object_labels) {
-        if (num_fbos > 1) {
-          GLchar name[128];
-          GLsizei len = snprintf(name, 128, "%s[%d]", _name.c_str(), layer);
-          glgsg->_glObjectLabel(GL_FRAMEBUFFER, _fbo[layer], len, name);
-        } else {
-          glgsg->_glObjectLabel(GL_FRAMEBUFFER, _fbo[layer], _name.size(), _name.data());
-        }
-      }
-#endif
-
       if (_fbo[layer] == 0) {
         report_my_gl_errors();
         return;
@@ -464,6 +452,19 @@ rebuild_bitplanes() {
     }
     glgsg->bind_fbo(_fbo[layer]);
 
+#ifndef OPENGLES
+    if (glgsg->_use_object_labels) {
+      // Assign a label for OpenGL to use when displaying debug messages.
+      if (num_fbos > 1) {
+        GLchar name[128];
+        GLsizei len = snprintf(name, 128, "%s[%d]", _name.c_str(), layer);
+        glgsg->_glObjectLabel(GL_FRAMEBUFFER, _fbo[layer], len, name);
+      } else {
+        glgsg->_glObjectLabel(GL_FRAMEBUFFER, _fbo[layer], _name.size(), _name.data());
+      }
+    }
+#endif
+
     // For all slots, update the slot.
     if (_use_depth_stencil) {
       bind_slot(layer, rb_resize, attach, RTP_depth_stencil, GL_DEPTH_ATTACHMENT_EXT);
@@ -1393,9 +1394,7 @@ open_buffer() {
 ////////////////////////////////////////////////////////////////////
 void CLP(GraphicsBuffer)::
 close_buffer() {
-
   check_host_valid();
-  report_my_gl_errors();
 
   if (_gsg == 0) {
     return;

+ 19 - 0
panda/src/glstuff/glGraphicsStateGuardian_src.I

@@ -171,6 +171,25 @@ maybe_gl_finish() const {
 #endif
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: GLGraphicsStateGuardian::has_extension
+//       Access: Published, Final
+//  Description: Returns true if the indicated extension is reported
+//               by the GL system, false otherwise.  The extension
+//               name is case-sensitive.
+////////////////////////////////////////////////////////////////////
+INLINE bool CLP(GraphicsStateGuardian)::
+has_extension(const string &extension) const {
+  bool has_ext = (_extensions.find(extension) != _extensions.end());
+#ifndef NDEBUG
+  if (GLCAT.is_debug()) {
+    GLCAT.debug()
+      << "HAS EXT " << extension << " " << has_ext << "\n";
+  }
+#endif
+  return has_ext;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: GLGraphicsStateGuardian::is_at_least_gl_version
 //       Access: Public

+ 105 - 85
panda/src/glstuff/glGraphicsStateGuardian_src.cxx

@@ -318,6 +318,10 @@ CLP(GraphicsStateGuardian)(GraphicsEngine *engine, GraphicsPipe *pipe) :
   _scissor_enabled = false;
   _scissor_attrib_active = false;
 
+#ifdef HAVE_CG
+  _cg_context = 0;
+#endif
+
 #ifdef DO_PSTATS
   if (gl_finish) {
     GLCAT.warning()
@@ -550,8 +554,7 @@ reset() {
   }
 
 #ifndef OPENGLES
-  _primitive_restart_gl3 = false;
-  _primitive_restart_nv = false;
+  _explicit_primitive_restart = false;
   _glPrimitiveRestartIndex = NULL;
 
   if (gl_support_primitive_restart_index) {
@@ -563,19 +566,16 @@ reset() {
       _supported_geom_rendering |= Geom::GR_strip_cut_index;
 
     } else if (is_at_least_gl_version(3, 1)) {
-      _primitive_restart_gl3 = true;
+      // We have to use an explicit primitive restart enable/index.
+      _explicit_primitive_restart = true;
       _supported_geom_rendering |= Geom::GR_strip_cut_index;
 
       _glPrimitiveRestartIndex = (PFNGLPRIMITIVERESTARTINDEXPROC)
         get_extension_func("glPrimitiveRestartIndex");
 
-    } else if (has_extension("GL_NV_primitive_restart")) {
-      _primitive_restart_nv = true;
-      _supported_geom_rendering |= Geom::GR_strip_cut_index;
-
-      _glPrimitiveRestartIndex = (PFNGLPRIMITIVERESTARTINDEXPROC)
-        get_extension_func("glPrimitiveRestartIndexNV");
     }
+    // We used to have a case here for GL_NV_primitive_restart, but it
+    // seems to cause garbled geometry bugs on some drivers.
   }
 #endif
 
@@ -1087,15 +1087,19 @@ reset() {
     _supports_depth_texture = true;
   }
 
-  if (_supports_depth_texture &&
+  if (gl_support_shadow_filter &&
+      _supports_depth_texture &&
       has_extension("GL_ARB_shadow") &&
       has_extension("GL_ARB_fragment_program_shadow")) {
     _supports_shadow_filter = true;
   }
-  if (_gl_vendor.substr(0,3)=="ATI") {
+  // Actually, we can't keep forever disabling ARB_shadow on ATI cards,
+  // since they do work correctly now.  Maybe there is some feature
+  // level we can check somewhere?
+  /*if (_gl_vendor.substr(0,3)=="ATI") {
     // ATI drivers have never provided correct shadow support.
     _supports_shadow_filter = false;
-  }
+  }*/
 
   _supports_texture_combine =
     has_extension("GL_ARB_texture_env_combine") || is_at_least_gl_version(1, 3) || is_at_least_gles_version(1, 1);
@@ -1160,30 +1164,37 @@ reset() {
 
       // cgGLGetLatestProfile doesn't seem to return anything other
       // arbvp1/arbfp1 on non-NVIDIA cards, which is severely limiting.
-      // Actually, it seems that these profiles are horribly broken on these
-      // cards.  Let's not do this.
-      //if ((_shader_caps._active_vprofile == CG_PROFILE_ARBVP1 ||
-      //     _shader_caps._active_fprofile == CG_PROFILE_ARBFP1) &&
-      //    cgGLIsProfileSupported(CG_PROFILE_GLSLV) &&
-      //    cgGLIsProfileSupported(CG_PROFILE_GLSLF)) {
-
-      //  // So, if this happens, we set it to GLSL, which is
-      //  // usually supported on all cards.
-      //  _shader_caps._active_vprofile = (int)CG_PROFILE_GLSLV;
-      //  _shader_caps._active_fprofile = (int)CG_PROFILE_GLSLF;
+      // So, if this happens, we set it to GLSL, which is
+      // usually supported on all cards.
+      // The GLSL profiles are horribly broken on non-NVIDIA cards, but
+      // I think I've worked around the issues sufficiently.
+      if ((_shader_caps._active_vprofile == CG_PROFILE_ARBVP1 ||
+           _shader_caps._active_fprofile == CG_PROFILE_ARBFP1) &&
+          cgGLIsProfileSupported(CG_PROFILE_GLSLV) &&
+          cgGLIsProfileSupported(CG_PROFILE_GLSLF)) {
+
+        _shader_caps._active_vprofile = (int)CG_PROFILE_GLSLV;
+        _shader_caps._active_fprofile = (int)CG_PROFILE_GLSLF;
 #if CG_VERSION_NUM >= 2200
-      //  if (cgGLIsProfileSupported(CG_PROFILE_GLSLG)) {
-      //    _shader_caps._active_gprofile = (int)CG_PROFILE_GLSLG;
-      //  }
+        if (cgGLIsProfileSupported(CG_PROFILE_GLSLG)) {
+          _shader_caps._active_gprofile = (int)CG_PROFILE_GLSLG;
+        }
 #endif
-      //}
+      }
     }
     _shader_caps._ultimate_vprofile = (int)CG_PROFILE_VP40;
     _shader_caps._ultimate_fprofile = (int)CG_PROFILE_FP40;
     _shader_caps._ultimate_gprofile = (int)CG_PROFILE_GPU_GP;
 
-    _glBindProgram = (PFNGLBINDPROGRAMARBPROC)
-      get_extension_func("glBindProgramARB");
+    _cg_context = cgCreateContext();
+
+#if CG_VERSION_NUM >= 3100
+    // This just sounds like a good thing to do.
+    cgGLSetContextGLSLVersion(_cg_context, cgGLDetectGLSLVersion());
+    if (_shader_caps._active_vprofile == CG_PROFILE_GLSLV) {
+      cgGLSetContextOptimalOptions(_cg_context, CG_PROFILE_GLSLC);
+    }
+#endif
 
     // Bug workaround for radeons.
     if (_shader_caps._active_fprofile == CG_PROFILE_ARBFP1) {
@@ -1363,6 +1374,22 @@ reset() {
   }
 #endif
 
+  _supports_vertex_attrib_divisor = false;
+#ifndef OPENGLES
+  if (is_at_least_gl_version(3, 3)) {
+    _glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISORPROC)
+      get_extension_func("glVertexAttribDivisor");
+
+    _supports_vertex_attrib_divisor = true;
+
+  } else if (has_extension("GL_ARB_instanced_arrays")) {
+    _glVertexAttribDivisor = (PFNGLVERTEXATTRIBDIVISORPROC)
+      get_extension_func("glVertexAttribDivisorARB");
+
+    _supports_vertex_attrib_divisor = true;
+  }
+#endif
+
 #ifdef OPENGLES_2
   // In OpenGL ES 2.x, FBO's are supported in the core.
   _supports_framebuffer_object = true;
@@ -2232,9 +2259,17 @@ reset() {
     }
 #endif  // CG_VERSION_NUM >= 2200
 
+#if CG_VERSION_NUM >= 3100
+    if (GLCAT.is_debug()) {
+      CGGLglslversion ver = cgGLGetContextGLSLVersion(_cg_context);
+      GLCAT.debug()
+        << "Cg GLSL version: " << cgGLGetGLSLVersionString(ver) << "\n";
+    }
+#endif
+
     GLCAT.debug()
-      << "\nCg vertex profile = " << cgGetProfileString(vertex_profile) << "  id = " << vertex_profile
-      << "\nCg pixel profile = " << cgGetProfileString(pixel_profile) << "  id = " << pixel_profile
+      << "\nCg latest vertex profile = " << cgGetProfileString(vertex_profile) << "  id = " << vertex_profile
+      << "\nCg latest pixel profile = " << cgGetProfileString(pixel_profile) << "  id = " << pixel_profile
       << "\nshader model = " << _shader_model
       << "\n";
   }
@@ -2416,6 +2451,7 @@ clear(DrawableRegion *clearable) {
   }
 
   if (clearable->get_clear_stencil_active()) {
+    glStencilMask(~0);
     glClearStencil(clearable->get_clear_stencil());
     mask |= GL_STENCIL_BUFFER_BIT;
   }
@@ -2578,6 +2614,7 @@ clear_before_callback() {
   // texture stage is still set to stage 0.  CEGUI, in particular,
   // makes this assumption.
   _glActiveTexture(GL_TEXTURE0);
+  _glClientActiveTexture(GL_TEXTURE0);
 
   // Clear the bound sampler object, so that we do not inadvertently
   // override the callback's desired sampler settings.
@@ -3954,13 +3991,9 @@ draw_linestrips(const GeomPrimitivePipelineReader *reader, bool force) {
         (_supported_geom_rendering & GeomEnums::GR_strip_cut_index) != 0) {
       // One long triangle strip, connected by strip cut indices.
 #ifndef OPENGLES
-      if (_primitive_restart_gl3) {
+      if (_explicit_primitive_restart) {
         glEnable(GL_PRIMITIVE_RESTART);
         _glPrimitiveRestartIndex(reader->get_strip_cut_index());
-
-      } else if (_primitive_restart_nv) {
-        glEnableClientState(GL_PRIMITIVE_RESTART_NV);
-        _glPrimitiveRestartIndex(reader->get_strip_cut_index());
       }
 #endif  // !OPENGLES
 
@@ -3989,11 +4022,8 @@ draw_linestrips(const GeomPrimitivePipelineReader *reader, bool force) {
       }
 
 #ifndef OPENGLES
-      if (_primitive_restart_gl3) {
+      if (_explicit_primitive_restart) {
         glDisable(GL_PRIMITIVE_RESTART);
-
-      } else if (_primitive_restart_nv) {
-        glDisableClientState(GL_PRIMITIVE_RESTART_NV);
       }
 #endif  // !OPENGLES
     } else {
@@ -4190,8 +4220,8 @@ issue_memory_barrier(GLbitfield barriers) {
 
   PStatGPUTimer timer(this, _memory_barrier_pcollector);
 
-  if (GLCAT.is_debug()) {
-    GLCAT.debug() << "Issuing memory barriers:";
+  if (GLCAT.is_spam()) {
+    GLCAT.spam() << "Issuing memory barriers:";
   }
 
   _glMemoryBarrier(barriers);
@@ -4200,25 +4230,25 @@ issue_memory_barrier(GLbitfield barriers) {
   // the relevant lists of textures.
   if (barriers & GL_TEXTURE_FETCH_BARRIER_BIT) {
     _textures_needing_fetch_barrier.clear();
-    GLCAT.debug(false) << " texture_fetch";
+    GLCAT.spam(false) << " texture_fetch";
   }
 
   if (barriers & GL_SHADER_IMAGE_ACCESS_BARRIER_BIT) {
     _textures_needing_image_access_barrier.clear();
-    GLCAT.debug(false) << " shader_image_access";
+    GLCAT.spam(false) << " shader_image_access";
   }
 
   if (barriers & GL_TEXTURE_UPDATE_BARRIER_BIT) {
     _textures_needing_update_barrier.clear();
-    GLCAT.debug(false) << " texture_update";
+    GLCAT.spam(false) << " texture_update";
   }
 
   if (barriers & GL_FRAMEBUFFER_BARRIER_BIT) {
     _textures_needing_framebuffer_barrier.clear();
-    GLCAT.debug(false) << " framebuffer";
+    GLCAT.spam(false) << " framebuffer";
   }
 
-  GLCAT.debug(false) << "\n";
+  GLCAT.spam(false) << "\n";
 
   report_my_gl_errors();
 #endif  // OPENGLES
@@ -5116,6 +5146,9 @@ issue_timer_query(int pstats_index) {
     }
   }
 
+  // Issue the timestamp query.
+  _glQueryCounter(query->_index, GL_TIMESTAMP);
+
   if (_use_object_labels) {
     // Assign a label to it based on the PStatCollector name.
     const PStatClient *client = PStatClient::get_global_pstats();
@@ -5123,9 +5156,6 @@ issue_timer_query(int pstats_index) {
     _glObjectLabel(GL_QUERY, query->_index, name.size(), name.data());
   }
 
-  // Issue the timestamp query.
-  _glQueryCounter(query->_index, GL_TIMESTAMP);
-
   _pending_timer_queries.push_back((TimerQueryContext *)query);
 
   return (TimerQueryContext *)query;
@@ -5167,6 +5197,19 @@ make_geom_munger(const RenderState *state, Thread *current_thread) {
   return GeomMunger::register_munger(munger, current_thread);
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: GLGraphicsStateGuardian::compute_distance_to
+//       Access: Public, Virtual
+//  Description: This function will compute the distance to the
+//               indicated point, assumed to be in eye coordinates,
+//               from the camera plane.  The point is assumed to be
+//               in the GSG's internal coordinate system.
+////////////////////////////////////////////////////////////////////
+PN_stdfloat GLGraphicsStateGuardian::
+compute_distance_to(const LPoint3 &point) const {
+  return -point[2];
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: GLGraphicsStateGuardian::framebuffer_copy_to_texture
 //       Access: Public, Virtual
@@ -6762,27 +6805,6 @@ report_extensions() const {
   }
 }
 
-////////////////////////////////////////////////////////////////////
-//     Function: GLGraphicsStateGuardian::has_extension
-//       Access: Protected
-//  Description: Returns true if the indicated extension is reported
-//               by the GL system, false otherwise.  The extension
-//               name is case-sensitive.
-////////////////////////////////////////////////////////////////////
-bool CLP(GraphicsStateGuardian)::
-has_extension(const string &extension) const {
-
-  bool state;
-
-  state = _extensions.find(extension) != _extensions.end();
-  if (GLCAT.is_debug()) {
-    GLCAT.debug()
-      << "HAS EXT " << extension << " " << state << "\n";
-  }
-
-  return state;
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: GLGraphicsStateGuardian::get_extension_func
 //       Access: Public
@@ -8764,19 +8786,6 @@ set_state_and_transform(const RenderState *target,
 #ifndef OPENGLES
   _instance_count = _target_shader->get_instance_count();
 #endif
-#ifndef OPENGLES_1
-  if (_target_shader->auto_shader()) {
-    // If we don't have a generated shader, make sure we have a ShaderGenerator, then generate the shader.
-    CPT(RenderState) shader = _target_rs->get_auto_shader_state();
-    if (shader->_generated_shader == NULL) {
-      if (_shader_generator == NULL) {
-        _shader_generator = new ShaderGenerator(this, _scene_setup->get_display_region()->get_window());
-      }
-      const_cast<RenderState*>(shader.p())->_generated_shader = DCAST(ShaderAttrib, _shader_generator->synthesize_shader(shader));
-    }
-    _target_shader = DCAST(ShaderAttrib, shader->_generated_shader);
-  }
-#endif
 
   int alpha_test_slot = AlphaTestAttrib::get_class_slot();
   if (_target_rs->get_attrib(alpha_test_slot) != _state_rs->get_attrib(alpha_test_slot) ||
@@ -8980,6 +8989,11 @@ set_state_and_transform(const RenderState *target,
     //PStatGPUTimer timer(this, _draw_set_state_light_pcollector);
     do_issue_light();
     _state_mask.set_bit(light_slot);
+#ifndef OPENGLES_1
+    if (_current_shader_context) {
+      _current_shader_context->issue_parameters(Shader::SSD_light);
+    }
+#endif
   }
 
   int stencil_slot = StencilAttrib::get_class_slot();
@@ -9024,6 +9038,12 @@ set_state_and_transform(const RenderState *target,
 ////////////////////////////////////////////////////////////////////
 void CLP(GraphicsStateGuardian)::
 free_pointers() {
+#ifdef HAVE_CG
+  if (_cg_context != 0) {
+    cgDestroyContext(_cg_context);
+    _cg_context = 0;
+  }
+#endif
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -9655,7 +9675,7 @@ do_issue_tex_gen() {
     TexGenAttrib::Mode mode = _target_tex_gen->get_mode(stage);
     switch (mode) {
     case TexGenAttrib::M_off:
-    case TexGenAttrib::M_light_vector:
+    case TexGenAttrib::M_unused2:
       break;
 
     case TexGenAttrib::M_eye_sphere_map:

+ 12 - 3
panda/src/glstuff/glGraphicsStateGuardian_src.h

@@ -182,6 +182,7 @@ typedef void (APIENTRYP PFNGLVALIDATEPROGRAMPROC) (GLuint program);
 typedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer);
 typedef void (APIENTRYP PFNGLVERTEXATTRIBIPOINTERPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
 typedef void (APIENTRYP PFNGLVERTEXATTRIBLPOINTERPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+typedef void (APIENTRYP PFNGLVERTEXATTRIBDIVISORPROC) (GLuint index, GLuint divisor);
 #endif  // OPENGLES_1
 #ifndef OPENGLES
 typedef void (APIENTRYP PFNGLGENSAMPLERSPROC) (GLsizei count, GLuint *samplers);
@@ -326,6 +327,8 @@ public:
   virtual PT(GeomMunger) make_geom_munger(const RenderState *state,
                                           Thread *current_thread);
 
+  virtual PN_stdfloat compute_distance_to(const LPoint3 &point) const;
+
   virtual void clear(DrawableRegion *region);
 
   virtual bool framebuffer_copy_to_texture
@@ -403,7 +406,7 @@ protected:
   void save_extensions(const char *extensions);
   virtual void get_extra_extensions();
   void report_extensions() const;
-  bool has_extension(const string &extension) const;
+  INLINE virtual bool has_extension(const string &extension) const FINAL;
   INLINE bool is_at_least_gl_version(int major_version, int minor_version) const;
   INLINE bool is_at_least_gles_version(int major_version, int minor_version) const;
   void *get_extension_func(const char *name);
@@ -565,11 +568,17 @@ protected:
   static PT(Shader)  _default_shader;
 #endif
 
+#ifdef HAVE_CG
+  CGcontext _cg_context;
+#endif
+
 #ifdef SUPPORT_IMMEDIATE_MODE
   CLP(ImmediateModeSender) _sender;
   bool _use_sender;
 #endif  // SUPPORT_IMMEDIATE_MODE
 
+  bool _supports_vertex_attrib_divisor;
+
   // Cache the data necessary to bind each particular light each
   // frame, so if we bind a given light multiple times, we only have
   // to compute its data once.
@@ -616,8 +625,7 @@ public:
 
 #ifndef OPENGLES
   PFNGLPRIMITIVERESTARTINDEXPROC _glPrimitiveRestartIndex;
-  bool _primitive_restart_gl3;
-  bool _primitive_restart_nv;
+  bool _explicit_primitive_restart;
 #endif
 
   bool _supports_vertex_blend;
@@ -784,6 +792,7 @@ public:
   PFNGLVERTEXATTRIBPOINTERPROC _glVertexAttribPointer;
   PFNGLVERTEXATTRIBIPOINTERPROC _glVertexAttribIPointer;
   PFNGLVERTEXATTRIBLPOINTERPROC _glVertexAttribLPointer;
+  PFNGLVERTEXATTRIBDIVISORPROC _glVertexAttribDivisor;
 #endif  // OPENGLES_1
 #ifndef OPENGLES
   PFNGLGENSAMPLERSPROC _glGenSamplers;

+ 170 - 46
panda/src/glstuff/glShaderContext_src.cxx

@@ -412,6 +412,20 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext
             s->_mat_spec.push_back(bind);
             continue;
           }
+          if (noprefix == "LightModel.ambient") {
+            Shader::ShaderMatSpec bind;
+            bind._id = arg_id;
+            bind._piece = Shader::SMP_row3;
+            bind._func = Shader::SMF_first;
+            bind._part[0] = Shader::SMO_light_ambient;
+            bind._arg[0] = NULL;
+            bind._dep[0] = Shader::SSD_general | Shader::SSD_light;
+            bind._part[1] = Shader::SMO_identity;
+            bind._arg[1] = NULL;
+            bind._dep[1] = Shader::SSD_NONE;
+            s->_mat_spec.push_back(bind);
+            continue;
+          }
           GLCAT.error() << "Unrecognized uniform name '" << param_name_cstr << "'!\n";
           continue;
 
@@ -565,7 +579,8 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext
               bind._arg[1] = NULL;
               bind._dep[1] = Shader::SSD_NONE;
               s->_mat_spec.push_back(bind);
-              continue; }
+              continue;
+            }
             case GL_FLOAT_MAT4: {
               Shader::ShaderMatSpec bind;
               bind._id = arg_id;
@@ -578,7 +593,43 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext
               bind._arg[1] = NULL;
               bind._dep[1] = Shader::SSD_NONE;
               s->_mat_spec.push_back(bind);
-              continue; }
+              continue;
+            }
+            case GL_FLOAT:
+            case GL_FLOAT_VEC2:
+            case GL_FLOAT_VEC3:
+            case GL_FLOAT_VEC4: {
+              PT(InternalName) iname = InternalName::make(param_name);
+              if (iname->get_parent() != InternalName::get_root()) {
+                // It might be something like an attribute of a shader
+                // input, like a light parameter.  It might also just be
+                // a custom struct parameter.  We can't know yet, sadly.
+                Shader::ShaderMatSpec bind;
+                bind._id = arg_id;
+                switch (param_type) {
+                case GL_FLOAT:
+                  bind._piece = Shader::SMP_row3x1;
+                  break;
+                case GL_FLOAT_VEC2:
+                  bind._piece = Shader::SMP_row3x2;
+                  break;
+                case GL_FLOAT_VEC3:
+                  bind._piece = Shader::SMP_row3x3;
+                  break;
+                default:
+                  bind._piece = Shader::SMP_row3;
+                }
+                bind._func = Shader::SMF_first;
+                bind._part[0] = Shader::SMO_vec_constant_x_attrib;
+                bind._arg[0] = iname;
+                bind._dep[0] = Shader::SSD_general | Shader::SSD_shaderinputs;
+                bind._part[1] = Shader::SMO_identity;
+                bind._arg[1] = NULL;
+                bind._dep[1] = Shader::SSD_NONE;
+                s->_mat_spec.push_back(bind);
+                continue;
+              } // else fall through
+            }
             case GL_BOOL:
             case GL_BOOL_VEC2:
             case GL_BOOL_VEC3:
@@ -586,11 +637,7 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext
             case GL_INT:
             case GL_INT_VEC2:
             case GL_INT_VEC3:
-            case GL_INT_VEC4:
-            case GL_FLOAT:
-            case GL_FLOAT_VEC2:
-            case GL_FLOAT_VEC3:
-            case GL_FLOAT_VEC4: {
+            case GL_INT_VEC4: {
               Shader::ShaderPtrSpec bind;
               bind._id = arg_id;
               switch (param_type) {
@@ -734,6 +781,7 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext
       bind._id = arg_id;
       bind._name = NULL;
       bind._append_uv = -1;
+      bind._elements = 1;
 
       if (param_name.substr(0, 3) == "gl_") {
         // Not all drivers return -1 in glGetAttribLocation
@@ -792,6 +840,24 @@ CLP(ShaderContext)(CLP(GraphicsStateGuardian) *glgsg, Shader *s) : ShaderContext
         GLCAT.error() << "Unrecognized vertex attrib '" << param_name << "'!\n";
         continue;
       }
+
+      // Get the number of bind points.
+      switch (param_type) {
+      case GL_FLOAT_MAT3:
+      case GL_DOUBLE_MAT3:
+        bind._elements = 3 * param_size;
+        break;
+
+      case GL_FLOAT_MAT4:
+      case GL_DOUBLE_MAT4:
+        bind._elements = 4 * param_size;
+        break;
+
+      default:
+        bind._elements = param_size;
+        break;
+      }
+
       s->_var_spec.push_back(bind);
     }
   }
@@ -998,7 +1064,12 @@ disable_shader_vertex_arrays() {
   for (int i=0; i<(int)_shader->_var_spec.size(); i++) {
     const Shader::ShaderVarSpec &bind = _shader->_var_spec[i];
     const GLint p = _glsl_parameter_map[bind._id._seqno];
-    _glgsg->_glDisableVertexAttribArray(p);
+    if (_glgsg->_supports_vertex_attrib_divisor) {
+      _glgsg->_glVertexAttribDivisor(p, 0);
+    }
+    for (int i = 0; i < bind._elements; ++i) {
+      _glgsg->_glDisableVertexAttribArray(p + i);
+    }
   }
 
   _glgsg->report_my_gl_errors();
@@ -1050,33 +1121,47 @@ update_shader_vertex_arrays(ShaderContext *prev, bool force) {
           name = name->append(texname->get_basename());
         }
       }
-      const GLint p = _glsl_parameter_map[bind._id._seqno];
+      GLint p = _glsl_parameter_map[bind._id._seqno];
 
-      if (_glgsg->_data_reader->get_array_info(name,
-                                               array_reader, num_values, numeric_type,
-                                               start, stride)) {
+      int num_elements, element_stride, divisor;
+      if (_glgsg->_data_reader->get_array_info(name, array_reader,
+                                               num_values, numeric_type,
+                                               start, stride, divisor,
+                                               num_elements, element_stride)) {
         const unsigned char *client_pointer;
         if (!_glgsg->setup_array_data(client_pointer, array_reader, force)) {
           return false;
         }
+        client_pointer += start;
 
-        _glgsg->_glEnableVertexAttribArray(p);
+        for (int i = 0; i < num_elements; ++i) {
+          _glgsg->_glEnableVertexAttribArray(p);
 
 #ifndef OPENGLES
-        if (bind._integer) {
-          _glgsg->_glVertexAttribIPointer(p, num_values, _glgsg->get_numeric_type(numeric_type),
-                                          stride, client_pointer + start);
-        } else
+          if (bind._integer) {
+            _glgsg->_glVertexAttribIPointer(p, num_values, _glgsg->get_numeric_type(numeric_type),
+                                            stride, client_pointer);
+          } else
 #endif
-        if (numeric_type == GeomEnums::NT_packed_dabc) {
-          _glgsg->_glVertexAttribPointer(p, GL_BGRA, GL_UNSIGNED_BYTE,
-                                         GL_TRUE, stride, client_pointer + start);
-        } else {
-          _glgsg->_glVertexAttribPointer(p, num_values, _glgsg->get_numeric_type(numeric_type),
-                                         GL_TRUE, stride, client_pointer + start);
+          if (numeric_type == GeomEnums::NT_packed_dabc) {
+            _glgsg->_glVertexAttribPointer(p, GL_BGRA, GL_UNSIGNED_BYTE,
+                                           GL_TRUE, stride, client_pointer);
+          } else {
+            _glgsg->_glVertexAttribPointer(p, num_values, _glgsg->get_numeric_type(numeric_type),
+                                           GL_TRUE, stride, client_pointer);
+          }
+
+          if (_glgsg->_supports_vertex_attrib_divisor) {
+            _glgsg->_glVertexAttribDivisor(p, divisor);
+          }
+
+          ++p;
+          client_pointer += element_stride;
         }
       } else {
-        _glgsg->_glDisableVertexAttribArray(p);
+        for (int i = 0; i < bind._elements; ++i) {
+          _glgsg->_glDisableVertexAttribArray(p + i);
+        }
       }
     }
   }
@@ -1290,14 +1375,7 @@ update_shader_texture_bindings(ShaderContext *prev) {
       view += stage->get_tex_view_offset();
     }
 
-    if (_shader->_tex_spec[i]._suffix != 0) {
-      // The suffix feature is inefficient. It is a temporary hack.
-      if (tex == 0) {
-        continue;
-      }
-      tex = tex->load_related(_shader->_tex_spec[i]._suffix);
-    }
-    if ((tex == 0) || (tex->get_texture_type() != _shader->_tex_spec[i]._desired_type)) {
+    if (tex == NULL || tex->get_texture_type() != _shader->_tex_spec[i]._desired_type) {
       continue;
     }
 
@@ -1369,18 +1447,57 @@ update_shader_texture_bindings(ShaderContext *prev) {
 //  Description: This subroutine prints the infolog for a shader.
 ////////////////////////////////////////////////////////////////////
 void CLP(ShaderContext)::
-glsl_report_shader_errors(GLuint shader) {
+glsl_report_shader_errors(GLuint shader, Shader::ShaderType type) {
   char *info_log;
   GLint length = 0;
   GLint num_chars  = 0;
 
   _glgsg->_glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &length);
 
-  if (length > 1) {
-    info_log = (char *) alloca(length);
-    _glgsg->_glGetShaderInfoLog(shader, length, &num_chars, info_log);
-    if (strcmp(info_log, "Success.\n") != 0 && strcmp(info_log, "No errors.\n") != 0) {
-      GLCAT.error(false) << info_log << "\n";
+  if (length <= 1) {
+    return;
+  }
+
+  info_log = (char *) alloca(length);
+  _glgsg->_glGetShaderInfoLog(shader, length, &num_chars, info_log);
+  if (strcmp(info_log, "Success.\n") == 0 ||
+      strcmp(info_log, "No errors.\n") == 0) {
+    return;
+  }
+
+  // Parse the errors so that we can substitute in actual file
+  // locations instead of source indices.
+  istringstream log(info_log);
+  string line;
+  while (getline(log, line)) {
+    int fileno, lineno;
+    int prefixlen = 0;
+
+    // First is AMD/Intel driver syntax, second is NVIDIA syntax.
+    if (sscanf(line.c_str(), "ERROR: %d:%d: %n", &fileno, &lineno, &prefixlen) == 2
+        && prefixlen > 0) {
+
+      Filename fn = _shader->get_filename_from_index(fileno, type);
+      GLCAT.error(false)
+        << "ERROR: " << fn << ":" << lineno << ": " << (line.c_str() + prefixlen) << "\n";
+
+    } else if (sscanf(line.c_str(), "WARNING: %d:%d: %n", &fileno, &lineno, &prefixlen) == 2
+        && prefixlen > 0) {
+
+      Filename fn = _shader->get_filename_from_index(fileno, type);
+      GLCAT.warning(false)
+        << "WARNING: " << fn << ":" << lineno << ": " << (line.c_str() + prefixlen) << "\n";
+
+
+    } else if (sscanf(line.c_str(), "%d(%d) : %n", &fileno, &lineno, &prefixlen) == 2
+               && prefixlen > 0) {
+
+      Filename fn = _shader->get_filename_from_index(fileno, type);
+      GLCAT.error(false)
+        << fn << "(" << lineno << ") : " << (line.c_str() + prefixlen) << "\n";
+
+    } else {
+      GLCAT.error(false) << line << "\n";
     }
   }
 }
@@ -1468,9 +1585,9 @@ glsl_compile_shader(Shader::ShaderType type) {
 
   if (status != GL_TRUE) {
     GLCAT.error()
-      << "An error occurred while compiling shader "
-      << _shader->get_filename(type) << "\n";
-    glsl_report_shader_errors(handle);
+      << "An error occurred while compiling GLSL shader "
+      << _shader->get_filename(type) << ":\n";
+    glsl_report_shader_errors(handle, type);
     _glgsg->_glDeleteShader(handle);
     _glgsg->report_my_gl_errors();
     return false;
@@ -1478,6 +1595,10 @@ glsl_compile_shader(Shader::ShaderType type) {
 
   _glgsg->_glAttachShader(_glsl_program, handle);
   _glsl_shaders.push_back(handle);
+
+  // There might be warnings, so report those.
+  glsl_report_shader_errors(handle, type);
+
   return true;
 }
 
@@ -1538,10 +1659,10 @@ glsl_compile_and_link() {
   }
 
   // There might be warnings, so report those.
-  GLSLShaders::const_iterator it;
-  for (it = _glsl_shaders.begin(); it != _glsl_shaders.end(); ++it) {
-    glsl_report_shader_errors(*it);
-  }
+  //GLSLShaders::const_iterator it;
+  //for (it = _glsl_shaders.begin(); it != _glsl_shaders.end(); ++it) {
+  //  glsl_report_shader_errors(*it);
+  //}
 
   // If we requested to retrieve the shader, we should indicate that before linking.
 #if !defined(NDEBUG) && !defined(OPENGLES)
@@ -1555,11 +1676,14 @@ glsl_compile_and_link() {
   GLint status;
   _glgsg->_glGetProgramiv(_glsl_program, GL_LINK_STATUS, &status);
   if (status != GL_TRUE) {
-    GLCAT.error() << "An error occurred while linking shader program!\n";
+    GLCAT.error() << "An error occurred while linking GLSL shader program!\n";
     glsl_report_program_errors(_glsl_program);
     return false;
   }
 
+  // Report any warnings.
+  glsl_report_program_errors(_glsl_program);
+
   // Dump the binary if requested.
 #if !defined(NDEBUG) && !defined(OPENGLES)
   if (gl_dump_compiled_shaders && _glgsg->_supports_get_program_binary) {

+ 1 - 1
panda/src/glstuff/glShaderContext_src.h

@@ -73,7 +73,7 @@ private:
 
   bool _uses_standard_vertex_arrays;
 
-  void glsl_report_shader_errors(GLuint shader);
+  void glsl_report_shader_errors(GLuint shader, Shader::ShaderType type);
   void glsl_report_program_errors(GLuint program);
   bool glsl_compile_shader(Shader::ShaderType type);
   bool glsl_compile_and_link();

+ 8 - 3
panda/src/glstuff/glTimerQueryContext_src.cxx

@@ -30,9 +30,14 @@ CLP(TimerQueryContext)::
 ~CLP(TimerQueryContext)() {
   if (_index != 0) {
     // Tell the GSG to recycle this index when it gets around to it.
-    LightMutexHolder holder(_glgsg->_lock);
-    _glgsg->_deleted_queries.push_back(_index);
-    _index = 0;
+    // If it has already shut down, though, too bad.  This means we
+    // never get to free this index, but presumably the app is
+    // already shutting down anyway.
+    if (!_glgsg.was_deleted()) {
+      LightMutexHolder holder(_glgsg->_lock);
+      _glgsg->_deleted_queries.push_back(_index);
+      _index = 0;
+    }
   }
 }
 

Some files were not shown because too many files changed in this diff