Browse Source

Merge branch 'master' of https://github.com/panda3d/panda3d

David Rose 9 years ago
parent
commit
0b224a320a
69 changed files with 752 additions and 283 deletions
  1. 5 3
      .travis.yml
  2. 1 1
      direct/src/directscripts/eggcacher.py
  3. 1 1
      direct/src/directscripts/packpanda.py
  4. 2 2
      direct/src/p3d/Packager.py
  5. 1 1
      direct/src/p3d/PatchMaker.py
  6. 3 2
      direct/src/plugin/p3dPackage.cxx
  7. 221 83
      direct/src/showutil/FreezeTool.py
  8. 19 4
      direct/src/showutil/pfreeze.py
  9. 2 2
      dtool/src/parser-inc/zlib.h
  10. 8 3
      makepanda/makepanda.py
  11. 1 1
      panda/metalibs/pandaegg/pandaegg.h
  12. 29 10
      panda/src/audio/audioManager.cxx
  13. 2 0
      panda/src/audiotraits/config_openalAudio.cxx
  14. 1 1
      panda/src/audiotraits/config_openalAudio.h
  15. 1 1
      panda/src/audiotraits/milesAudioManager.cxx
  16. 1 1
      panda/src/collada/loaderFileTypeDae.cxx
  17. 1 1
      panda/src/downloader/decompressor.cxx
  18. 1 1
      panda/src/egg2pg/loaderFileTypeEgg.cxx
  19. 7 3
      panda/src/express/virtualFileSimple.cxx
  20. 3 3
      panda/src/express/virtualFileSystem.I
  21. 2 2
      panda/src/express/zStreamBuf.cxx
  22. 6 2
      panda/src/framework/pandaFramework.cxx
  23. 1 1
      panda/src/framework/windowFramework.cxx
  24. 19 0
      panda/src/glstuff/glGraphicsStateGuardian_src.cxx
  25. 11 2
      panda/src/glstuff/glShaderContext_src.cxx
  26. 4 1
      panda/src/gobj/geomVertexArrayFormat.cxx
  27. 12 2
      panda/src/gobj/geomVertexColumn.cxx
  28. 23 14
      panda/src/gobj/material.cxx
  29. 11 7
      panda/src/gobj/matrixLens.cxx
  30. 32 0
      panda/src/gobj/shader.I
  31. 1 0
      panda/src/gobj/shader.h
  32. 2 2
      panda/src/gobj/texture.I
  33. 46 8
      panda/src/gobj/texture.cxx
  34. 1 0
      panda/src/gobj/texture.h
  35. 4 1
      panda/src/gobj/textureStage.cxx
  36. 4 1
      panda/src/grutil/movieTexture.cxx
  37. 11 9
      panda/src/grutil/shaderTerrainMesh.I
  38. 28 34
      panda/src/grutil/shaderTerrainMesh.cxx
  39. 5 6
      panda/src/grutil/shaderTerrainMesh.h
  40. 3 3
      panda/src/movies/dr_flac.h
  41. 18 4
      panda/src/pgraph/clipPlaneAttrib.cxx
  42. 4 2
      panda/src/pgraph/depthOffsetAttrib.cxx
  43. 7 3
      panda/src/pgraph/light.cxx
  44. 17 4
      panda/src/pgraph/lightAttrib.cxx
  45. 8 8
      panda/src/pgraph/loader.cxx
  46. 1 1
      panda/src/pgraph/loaderFileType.cxx
  47. 1 1
      panda/src/pgraph/loaderFileTypeBam.cxx
  48. 9 2
      panda/src/pgraph/occluderEffect.cxx
  49. 12 1
      panda/src/pgraph/paramNodePath.cxx
  50. 3 1
      panda/src/pgraph/scissorAttrib.cxx
  51. 20 2
      panda/src/pgraph/stencilAttrib.cxx
  52. 4 1
      panda/src/pgraph/texMatrixAttrib.cxx
  53. 10 4
      panda/src/pgraph/textureAttrib.cxx
  54. 3 1
      panda/src/pgraphnodes/directionalLight.cxx
  55. 3 1
      panda/src/pgraphnodes/pointLight.cxx
  56. 3 1
      panda/src/pgraphnodes/spotlight.cxx
  57. 6 2
      panda/src/pgraphnodes/uvScrollNode.cxx
  58. 1 1
      panda/src/pnmimage/pnmFileTypeRegistry.cxx
  59. 3 2
      panda/src/pnmimage/pnmImageHeader.cxx
  60. 10 0
      panda/src/putil/bamWriter.I
  61. 48 7
      panda/src/putil/bamWriter.cxx
  62. 1 0
      panda/src/putil/bamWriter.h
  63. 6 0
      panda/src/putil/config_util.cxx
  64. 1 0
      panda/src/putil/config_util.h
  65. 1 1
      panda/src/speedtree/loaderFileTypeSrt.cxx
  66. 1 1
      panda/src/speedtree/loaderFileTypeStf.cxx
  67. 1 1
      pandatool/src/assimp/loaderFileTypeAssimp.cxx
  68. 1 1
      pandatool/src/ptloader/loaderFileTypePandatool.cxx
  69. 13 11
      samples/shader-terrain/main.py

+ 5 - 3
.travis.yml

@@ -3,9 +3,11 @@ sudo: false
 matrix:
 matrix:
   include:
   include:
     - compiler: gcc
     - compiler: gcc
-      env: PYTHONV=python2.7
+      env: PYTHONV=python2.7 FLAGS=
     - compiler: clang
     - compiler: clang
-      env: PYTHONV=python3
+      env: PYTHONV=python3 FLAGS=--installer
+    - compiler: clang
+      env: PYTHONV=python2.7 FLAGS=--override=STDFLOAT_DOUBLE=1
 addons:
 addons:
   apt:
   apt:
     packages:
     packages:
@@ -26,7 +28,7 @@ addons:
     - python-dev
     - python-dev
     - python3-dev
     - python3-dev
     - zlib1g-dev
     - zlib1g-dev
-script: $PYTHONV makepanda/makepanda.py --everything --git-commit $TRAVIS_COMMIT --installer --threads 4 && LD_LIBRARY_PATH=built/lib PYTHONPATH=built $PYTHONV makepanda/test_imports.py
+script: $PYTHONV makepanda/makepanda.py --everything --git-commit $TRAVIS_COMMIT $FLAGS --threads 4 && LD_LIBRARY_PATH=built/lib PYTHONPATH=built $PYTHONV makepanda/test_imports.py
 notifications:
 notifications:
   irc:
   irc:
     channels:
     channels:

+ 1 - 1
direct/src/directscripts/eggcacher.py

@@ -55,7 +55,7 @@ class EggCacher:
             size = os.path.getsize(path)
             size = os.path.getsize(path)
             eggs.append((path,size))
             eggs.append((path,size))
             return
             return
-        if (path.endswith(".egg.pz")):
+        if (path.endswith(".egg.pz") or path.endswith(".egg.gz")):
             size = os.path.getsize(path)
             size = os.path.getsize(path)
             if (self.pzkeep): eggs.append((path,size))
             if (self.pzkeep): eggs.append((path,size))
             else: eggs.append((path[:-3],size))
             else: eggs.append((path[:-3],size))

+ 1 - 1
direct/src/directscripts/packpanda.py

@@ -274,7 +274,7 @@ def CompileFiles(file):
     if (os.path.isfile(file)):
     if (os.path.isfile(file)):
         if (file.endswith(".egg")):
         if (file.endswith(".egg")):
             egg2bam(file, file[:-4]+'.bam')
             egg2bam(file, file[:-4]+'.bam')
-        elif (file.endswith(".egg.pz")):
+        elif (file.endswith(".egg.pz") or file.endswith(".egg.gz")):
             egg2bam(file, file[:-7]+'.bam')
             egg2bam(file, file[:-7]+'.bam')
         elif (file.endswith(".py")):
         elif (file.endswith(".py")):
             py2pyc(file)
             py2pyc(file)

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

@@ -61,7 +61,7 @@ class Packager:
                 self.newName = str(self.filename)
                 self.newName = str(self.filename)
 
 
             ext = Filename(self.newName).getExtension()
             ext = Filename(self.newName).getExtension()
-            if ext == 'pz':
+            if ext == 'pz' or ext == 'gz':
                 # Strip off a .pz extension; we can compress files
                 # Strip off a .pz extension; we can compress files
                 # within the Multifile without it.
                 # within the Multifile without it.
                 filename = Filename(self.newName)
                 filename = Filename(self.newName)
@@ -3772,7 +3772,7 @@ class Packager:
             self.currentPackage.addFile(filename, newName = newName,
             self.currentPackage.addFile(filename, newName = newName,
                                         explicit = False, unprocessed = unprocessed)
                                         explicit = False, unprocessed = unprocessed)
         else:
         else:
-            if ext == 'pz':
+            if ext == 'pz' or ext == 'gz':
                 # Strip off an implicit .pz extension.
                 # Strip off an implicit .pz extension.
                 newFilename = Filename(filename)
                 newFilename = Filename(filename)
                 newFilename.setExtension('')
                 newFilename.setExtension('')

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

@@ -137,7 +137,7 @@ class PatchMaker:
 
 
             startFile, startPv, plan = self.getRecreateFilePlan()
             startFile, startPv, plan = self.getRecreateFilePlan()
 
 
-            if startFile.getExtension() == 'pz':
+            if startFile.getExtension() in ('pz', 'gz'):
                 # If the starting file is compressed, we have to
                 # If the starting file is compressed, we have to
                 # decompress it first.
                 # decompress it first.
                 assert startPv.tempFile is None
                 assert startPv.tempFile is None

+ 3 - 2
direct/src/plugin/p3dPackage.cxx

@@ -998,7 +998,8 @@ build_install_plans(TiXmlDocument *doc) {
           FileSpec new_file = patchfile->_file;
           FileSpec new_file = patchfile->_file;
           string new_filename = new_file.get_filename();
           string new_filename = new_file.get_filename();
           size_t dot = new_filename.rfind('.');
           size_t dot = new_filename.rfind('.');
-          assert(new_filename.substr(dot) == ".pz");
+          string extension = new_filename.substr(dot);
+          assert(extension == ".pz" || extension == ".gz");
           new_filename = new_filename.substr(0, dot);
           new_filename = new_filename.substr(0, dot);
           new_file.set_filename(new_filename);
           new_file.set_filename(new_filename);
           step = new InstallStepUncompressFile
           step = new InstallStepUncompressFile
@@ -1834,7 +1835,7 @@ thread_step() {
   z.next_in = (Bytef *)decompress_buffer;
   z.next_in = (Bytef *)decompress_buffer;
   z.avail_in = (size_t)read_count;
   z.avail_in = (size_t)read_count;
 
 
-  int result = inflateInit(&z);
+  int result = inflateInit2(&z, 32 + 15);
   if (result < 0) {
   if (result < 0) {
     nout << z.msg << "\n";
     nout << z.msg << "\n";
     return IT_step_failed;
     return IT_step_failed;

+ 221 - 83
direct/src/showutil/FreezeTool.py

@@ -8,7 +8,7 @@ import marshal
 import imp
 import imp
 import platform
 import platform
 from io import StringIO
 from io import StringIO
-from distutils.sysconfig import PREFIX, get_python_inc, get_python_version, get_config_var
+import distutils.sysconfig as sysconf
 
 
 # Temporary (?) try..except to protect against unbuilt p3extend_frozen.
 # Temporary (?) try..except to protect against unbuilt p3extend_frozen.
 try:
 try:
@@ -29,9 +29,23 @@ isDebugBuild = (python.lower().endswith('_d'))
 # These are modules that Python always tries to import up-front.  They
 # These are modules that Python always tries to import up-front.  They
 # must be frozen in any main.exe.
 # must be frozen in any main.exe.
 startupModules = [
 startupModules = [
-    'os', 'encodings.cp1252',
-    'encodings.latin_1', 'encodings.utf_8', 'io',
+    'encodings.cp1252', 'encodings.latin_1', 'encodings.utf_8',
     ]
     ]
+if sys.version_info >= (3, 0):
+    startupModules += ['io', 'marshal', 'importlib.machinery', 'importlib.util']
+
+# These are some special init functions for some built-in Python modules that
+# deviate from the standard naming convention.  A value of None means that a
+# dummy entry should be written to the inittab.
+builtinInitFuncs = {
+    'builtins': None,
+    '__builtin__': None,
+    'sys': None,
+    'exceptions': None,
+    '_imp': 'PyInit_imp',
+    '_warnings': '_PyWarnings_Init',
+    'marshal': 'PyMarshal_Init',
+}
 
 
 # These are missing modules that we've reported already this session.
 # These are missing modules that we've reported already this session.
 reportedMissing = {}
 reportedMissing = {}
@@ -60,8 +74,8 @@ class CompilationEnvironment:
 
 
         # Paths to Python stuff.
         # Paths to Python stuff.
         self.Python = None
         self.Python = None
-        self.PythonIPath = get_python_inc()
-        self.PythonVersion = get_config_var("LDVERSION") or get_python_version()
+        self.PythonIPath = sysconf.get_python_inc()
+        self.PythonVersion = sysconf.get_config_var("LDVERSION") or sysconf.get_python_version()
 
 
         # The VC directory of Microsoft Visual Studio (if relevant)
         # The VC directory of Microsoft Visual Studio (if relevant)
         self.MSVC = None
         self.MSVC = None
@@ -85,7 +99,7 @@ class CompilationEnvironment:
 
 
     def determineStandardSetup(self):
     def determineStandardSetup(self):
         if self.platform.startswith('win'):
         if self.platform.startswith('win'):
-            self.Python = PREFIX
+            self.Python = sysconf.PREFIX
 
 
             if ('VCINSTALLDIR' in os.environ):
             if ('VCINSTALLDIR' in os.environ):
                 self.MSVC = os.environ['VCINSTALLDIR']
                 self.MSVC = os.environ['VCINSTALLDIR']
@@ -122,13 +136,15 @@ class CompilationEnvironment:
 
 
             # If it is run by makepanda, it handles the MSVC and PlatformSDK paths itself.
             # If it is run by makepanda, it handles the MSVC and PlatformSDK paths itself.
             if ('MAKEPANDA' in os.environ):
             if ('MAKEPANDA' in os.environ):
-                self.compileObj = 'cl /wd4996 /Fo%(basename)s.obj /nologo /c %(MD)s /Zi /O2 /Ob2 /EHsc /Zm300 /W3 /I"%(pythonIPath)s" %(filename)s'
+                self.compileObjExe = 'cl /wd4996 /Fo%(basename)s.obj /nologo /c %(MD)s /Zi /O2 /Ob2 /EHsc /Zm300 /W3 /I"%(pythonIPath)s" %(filename)s'
+                self.compileObjDll = self.compileObjExe
                 self.linkExe = 'link /nologo /MAP:NUL /FIXED:NO /OPT:REF /STACK:4194304 /INCREMENTAL:NO /LIBPATH:"%(python)s\libs"  /out:%(basename)s.exe %(basename)s.obj'
                 self.linkExe = 'link /nologo /MAP:NUL /FIXED:NO /OPT:REF /STACK:4194304 /INCREMENTAL:NO /LIBPATH:"%(python)s\libs"  /out:%(basename)s.exe %(basename)s.obj'
                 self.linkDll = 'link /nologo /DLL /MAP:NUL /FIXED:NO /OPT:REF /INCREMENTAL:NO /LIBPATH:"%(python)s\libs"  /out:%(basename)s%(dllext)s.pyd %(basename)s.obj'
                 self.linkDll = 'link /nologo /DLL /MAP:NUL /FIXED:NO /OPT:REF /INCREMENTAL:NO /LIBPATH:"%(python)s\libs"  /out:%(basename)s%(dllext)s.pyd %(basename)s.obj'
             else:
             else:
                 os.environ['PATH'] += ';' + self.MSVC + '\\bin' + self.suffix64 + ';' + self.MSVC + '\\Common7\\IDE;' + self.PSDK + '\\bin'
                 os.environ['PATH'] += ';' + self.MSVC + '\\bin' + self.suffix64 + ';' + self.MSVC + '\\Common7\\IDE;' + self.PSDK + '\\bin'
 
 
-                self.compileObj = 'cl /wd4996 /Fo%(basename)s.obj /nologo /c %(MD)s /Zi /O2 /Ob2 /EHsc /Zm300 /W3 /I"%(pythonIPath)s" /I"%(PSDK)s\include" /I"%(MSVC)s\include" %(filename)s'
+                self.compileObjExe = 'cl /wd4996 /Fo%(basename)s.obj /nologo /c %(MD)s /Zi /O2 /Ob2 /EHsc /Zm300 /W3 /I"%(pythonIPath)s" /I"%(PSDK)s\include" /I"%(MSVC)s\include" %(filename)s'
+                self.compileObjDll = self.compileObjExe
                 self.linkExe = 'link /nologo /MAP:NUL /FIXED:NO /OPT:REF /STACK:4194304 /INCREMENTAL:NO /LIBPATH:"%(PSDK)s\lib" /LIBPATH:"%(MSVC)s\\lib%(suffix64)s" /LIBPATH:"%(python)s\libs"  /out:%(basename)s.exe %(basename)s.obj'
                 self.linkExe = 'link /nologo /MAP:NUL /FIXED:NO /OPT:REF /STACK:4194304 /INCREMENTAL:NO /LIBPATH:"%(PSDK)s\lib" /LIBPATH:"%(MSVC)s\\lib%(suffix64)s" /LIBPATH:"%(python)s\libs"  /out:%(basename)s.exe %(basename)s.obj'
                 self.linkDll = 'link /nologo /DLL /MAP:NUL /FIXED:NO /OPT:REF /INCREMENTAL:NO /LIBPATH:"%(PSDK)s\lib" /LIBPATH:"%(MSVC)s\\lib%(suffix64)s" /LIBPATH:"%(python)s\libs"  /out:%(basename)s%(dllext)s.pyd %(basename)s.obj'
                 self.linkDll = 'link /nologo /DLL /MAP:NUL /FIXED:NO /OPT:REF /INCREMENTAL:NO /LIBPATH:"%(PSDK)s\lib" /LIBPATH:"%(MSVC)s\\lib%(suffix64)s" /LIBPATH:"%(python)s\libs"  /out:%(basename)s%(dllext)s.pyd %(basename)s.obj'
 
 
@@ -141,22 +157,26 @@ class CompilationEnvironment:
                 self.arch = '-arch ppc'
                 self.arch = '-arch ppc'
             elif proc == 'amd64':
             elif proc == 'amd64':
                 self.arch = '-arch x86_64'
                 self.arch = '-arch x86_64'
-            self.compileObj = "gcc -fPIC -c %(arch)s -o %(basename)s.o -O2 -I%(pythonIPath)s %(filename)s"
+            self.compileObjExe = "gcc -c %(arch)s -o %(basename)s.o -O2 -I%(pythonIPath)s %(filename)s"
+            self.compileObjDll = "gcc -fPIC -c %(arch)s -o %(basename)s.o -O2 -I%(pythonIPath)s %(filename)s"
             self.linkExe = "gcc %(arch)s -o %(basename)s %(basename)s.o -framework Python"
             self.linkExe = "gcc %(arch)s -o %(basename)s %(basename)s.o -framework Python"
             self.linkDll = "gcc %(arch)s -undefined dynamic_lookup -bundle -o %(basename)s.so %(basename)s.o"
             self.linkDll = "gcc %(arch)s -undefined dynamic_lookup -bundle -o %(basename)s.so %(basename)s.o"
 
 
         else:
         else:
             # Unix
             # Unix
-            self.compileObj = "gcc -fPIC -c -o %(basename)s.o -O2 %(filename)s -I%(pythonIPath)s"
-            self.linkExe = "gcc -o %(basename)s %(basename)s.o -L/usr/local/lib -lpython%(pythonVersion)s"
-            self.linkDll = "gcc -shared -o %(basename)s.so %(basename)s.o -L/usr/local/lib -lpython%(pythonVersion)s"
+            lib_dir = sysconf.get_python_lib(plat_specific=1, standard_lib=1)
+            #python_a = os.path.join(lib_dir, "config", "libpython%(pythonVersion)s.a")
+            self.compileObjExe = "%(CC)s %(CFLAGS)s -c -o %(basename)s.o -pthread -O2 %(filename)s -I%(pythonIPath)s"
+            self.compileObjDll = "%(CC)s %(CFLAGS)s %(CCSHARED)s -c -o %(basename)s.o -O2 %(filename)s -I%(pythonIPath)s"
+            self.linkExe = "%(CC)s -o %(basename)s %(basename)s.o -L/usr/local/lib -lpython%(pythonVersion)s"
+            self.linkDll = "%(LDSHARED)s -o %(basename)s.so %(basename)s.o -L/usr/local/lib -lpython%(pythonVersion)s"
 
 
             if (os.path.isdir("/usr/PCBSD/local/lib")):
             if (os.path.isdir("/usr/PCBSD/local/lib")):
                 self.linkExe += " -L/usr/PCBSD/local/lib"
                 self.linkExe += " -L/usr/PCBSD/local/lib"
                 self.linkDll += " -L/usr/PCBSD/local/lib"
                 self.linkDll += " -L/usr/PCBSD/local/lib"
 
 
-    def compileExe(self, filename, basename):
-        compile = self.compileObj % {
+    def compileExe(self, filename, basename, extraLink=[]):
+        compile = self.compileObjExe % dict({
             'python' : self.Python,
             'python' : self.Python,
             'MSVC' : self.MSVC,
             'MSVC' : self.MSVC,
             'PSDK' : self.PSDK,
             'PSDK' : self.PSDK,
@@ -167,12 +187,12 @@ class CompilationEnvironment:
             'arch' : self.arch,
             'arch' : self.arch,
             'filename' : filename,
             'filename' : filename,
             'basename' : basename,
             'basename' : basename,
-            }
+            }, **sysconf.get_config_vars())
         sys.stderr.write(compile + '\n')
         sys.stderr.write(compile + '\n')
         if os.system(compile) != 0:
         if os.system(compile) != 0:
             raise Exception('failed to compile %s.' % basename)
             raise Exception('failed to compile %s.' % basename)
 
 
-        link = self.linkExe % {
+        link = self.linkExe % dict({
             'python' : self.Python,
             'python' : self.Python,
             'MSVC' : self.MSVC,
             'MSVC' : self.MSVC,
             'PSDK' : self.PSDK,
             'PSDK' : self.PSDK,
@@ -182,13 +202,14 @@ class CompilationEnvironment:
             'arch' : self.arch,
             'arch' : self.arch,
             'filename' : filename,
             'filename' : filename,
             'basename' : basename,
             'basename' : basename,
-            }
+            }, **sysconf.get_config_vars())
+        link += ' ' + ' '.join(extraLink)
         sys.stderr.write(link + '\n')
         sys.stderr.write(link + '\n')
         if os.system(link) != 0:
         if os.system(link) != 0:
             raise Exception('failed to link %s.' % basename)
             raise Exception('failed to link %s.' % basename)
 
 
-    def compileDll(self, filename, basename):
-        compile = self.compileObj % {
+    def compileDll(self, filename, basename, extraLink=[]):
+        compile = self.compileObjDll % dict({
             'python' : self.Python,
             'python' : self.Python,
             'MSVC' : self.MSVC,
             'MSVC' : self.MSVC,
             'PSDK' : self.PSDK,
             'PSDK' : self.PSDK,
@@ -199,12 +220,12 @@ class CompilationEnvironment:
             'arch' : self.arch,
             'arch' : self.arch,
             'filename' : filename,
             'filename' : filename,
             'basename' : basename,
             'basename' : basename,
-            }
+            }, **sysconf.get_config_vars())
         sys.stderr.write(compile + '\n')
         sys.stderr.write(compile + '\n')
         if os.system(compile) != 0:
         if os.system(compile) != 0:
             raise Exception('failed to compile %s.' % basename)
             raise Exception('failed to compile %s.' % basename)
 
 
-        link = self.linkDll % {
+        link = self.linkDll % dict({
             'python' : self.Python,
             'python' : self.Python,
             'MSVC' : self.MSVC,
             'MSVC' : self.MSVC,
             'PSDK' : self.PSDK,
             'PSDK' : self.PSDK,
@@ -215,7 +236,8 @@ class CompilationEnvironment:
             'filename' : filename,
             'filename' : filename,
             'basename' : basename,
             'basename' : basename,
             'dllext' : self.dllext,
             'dllext' : self.dllext,
-            }
+            }, **sysconf.get_config_vars())
+        link += ' ' + ' '.join(extraLink)
         sys.stderr.write(link + '\n')
         sys.stderr.write(link + '\n')
         if os.system(link) != 0:
         if os.system(link) != 0:
             raise Exception('failed to link %s.' % basename)
             raise Exception('failed to link %s.' % basename)
@@ -233,7 +255,8 @@ frozenMainCode = """
 #ifdef MS_WINDOWS
 #ifdef MS_WINDOWS
 extern void PyWinFreeze_ExeInit(void);
 extern void PyWinFreeze_ExeInit(void);
 extern void PyWinFreeze_ExeTerm(void);
 extern void PyWinFreeze_ExeTerm(void);
-extern int PyInitFrozenExtensions(void);
+
+extern DL_IMPORT(int) PyImport_ExtendInittab(struct _inittab *newtab);
 #endif
 #endif
 
 
 /* Main program */
 /* Main program */
@@ -264,6 +287,8 @@ Py_FrozenMain(int argc, char **argv)
 #endif
 #endif
 
 
     Py_FrozenFlag = 1; /* Suppress errors from getpath.c */
     Py_FrozenFlag = 1; /* Suppress errors from getpath.c */
+    Py_NoSiteFlag = 1;
+    Py_NoUserSiteDirectory = 1;
 
 
     if ((p = Py_GETENV("PYTHONINSPECT")) && *p != '\\0')
     if ((p = Py_GETENV("PYTHONINSPECT")) && *p != '\\0')
         inspect = 1;
         inspect = 1;
@@ -300,7 +325,7 @@ Py_FrozenMain(int argc, char **argv)
 #endif
 #endif
 
 
 #ifdef MS_WINDOWS
 #ifdef MS_WINDOWS
-    PyInitFrozenExtensions();
+    PyImport_ExtendInittab(extensions);
 #endif /* MS_WINDOWS */
 #endif /* MS_WINDOWS */
 
 
     if (argc >= 1) {
     if (argc >= 1) {
@@ -344,8 +369,8 @@ Py_FrozenMain(int argc, char **argv)
 #endif
 #endif
     Py_Finalize();
     Py_Finalize();
 
 
-error:
 #if PY_MAJOR_VERSION >= 3
 #if PY_MAJOR_VERSION >= 3
+error:
     PyMem_RawFree(argv_copy);
     PyMem_RawFree(argv_copy);
     if (argv_copy2) {
     if (argv_copy2) {
         for (i = 0; i < argc; i++)
         for (i = 0; i < argc; i++)
@@ -463,10 +488,6 @@ main(int argc, char *argv[]) {
 
 
 # Our own glue code to start up a Python shared library.
 # Our own glue code to start up a Python shared library.
 dllInitCode = """
 dllInitCode = """
-static PyMethodDef nullMethods[] = {
-  {NULL, NULL}
-};
-
 /*
 /*
  * Call this function to extend the frozen modules array with a new
  * Call this function to extend the frozen modules array with a new
  * array of frozen modules, provided in a C-style array, at runtime.
  * array of frozen modules, provided in a C-style array, at runtime.
@@ -508,10 +529,29 @@ extend_frozen_modules(const struct _frozen *new_modules, int new_count) {
   return orig_count + new_count;
   return orig_count + new_count;
 }
 }
 
 
-%(dllexport)svoid init%(moduleName)s() {
+#if PY_MAJOR_VERSION >= 3
+static PyModuleDef mdef = {
+  PyModuleDef_HEAD_INIT,
+  "%(moduleName)s",
+  "",
+  -1,
+  NULL, NULL, NULL, NULL, NULL
+};
+
+%(dllexport)sPyObject *PyInit_%(moduleName)s(void) {
+  extend_frozen_modules(_PyImport_FrozenModules, sizeof(_PyImport_FrozenModules) / sizeof(struct _frozen));
+  return PyModule_Create(&mdef);
+}
+#else
+static PyMethodDef nullMethods[] = {
+  {NULL, NULL}
+};
+
+%(dllexport)svoid init%(moduleName)s(void) {
   extend_frozen_modules(_PyImport_FrozenModules, sizeof(_PyImport_FrozenModules) / sizeof(struct _frozen));
   extend_frozen_modules(_PyImport_FrozenModules, sizeof(_PyImport_FrozenModules) / sizeof(struct _frozen));
   Py_InitModule("%(moduleName)s", nullMethods);
   Py_InitModule("%(moduleName)s", nullMethods);
 }
 }
+#endif
 """
 """
 
 
 programFile = """
 programFile = """
@@ -526,24 +566,8 @@ struct _frozen _PyImport_FrozenModules[] = {
 %(moduleList)s
 %(moduleList)s
   {NULL, NULL, 0}
   {NULL, NULL, 0}
 };
 };
-
-%(initCode)s
 """
 """
 
 
-# Windows needs this bit.
-frozenExtensions = """
-
-static struct _inittab extensions[] = {
-        /* Sentinel */
-        {0, 0}
-};
-extern DL_IMPORT(int) PyImport_ExtendInittab(struct _inittab *newtab);
-
-int PyInitFrozenExtensions()
-{
-        return PyImport_ExtendInittab(extensions);
-}
-"""
 
 
 okMissing = [
 okMissing = [
     '__main__', '_dummy_threading', 'Carbon', 'Carbon.Files',
     '__main__', '_dummy_threading', 'Carbon', 'Carbon.Files',
@@ -645,14 +669,13 @@ class Freezer:
         if self.platform.startswith('win'):
         if self.platform.startswith('win'):
             self.objectExtension = '.obj'
             self.objectExtension = '.obj'
 
 
-        self.keepTemporaryFiles = True
+        self.keepTemporaryFiles = False
 
 
         # Change any of these to change the generated startup and glue
         # Change any of these to change the generated startup and glue
         # code.
         # code.
         self.frozenMainCode = frozenMainCode
         self.frozenMainCode = frozenMainCode
         self.frozenDllMainCode = frozenDllMainCode
         self.frozenDllMainCode = frozenDllMainCode
         self.mainInitCode = mainInitCode
         self.mainInitCode = mainInitCode
-        self.frozenExtensions = frozenExtensions
 
 
         # Set this true to encode Python files in a Multifile as their
         # Set this true to encode Python files in a Multifile as their
         # original source if possible, or false to encode them as
         # original source if possible, or false to encode them as
@@ -664,9 +687,14 @@ class Freezer:
         # addToMultifile().  It contains a list of all the extension
         # addToMultifile().  It contains a list of all the extension
         # modules that were discovered, which have not been added to
         # modules that were discovered, which have not been added to
         # the output.  The list is a list of tuples of the form
         # the output.  The list is a list of tuples of the form
-        # (moduleName, filename).
+        # (moduleName, filename).  filename will be None for built-in
+        # modules.
         self.extras = []
         self.extras = []
 
 
+        # Set this to true if extension modules should be linked in to
+        # the resulting executable.
+        self.linkExtensionModules = False
+
         # End of public interface.  These remaining members should not
         # End of public interface.  These remaining members should not
         # be directly manipulated by callers.
         # be directly manipulated by callers.
         self.previousModules = {}
         self.previousModules = {}
@@ -676,6 +704,10 @@ class Freezer:
             self.previousModules = dict(previous.modules)
             self.previousModules = dict(previous.modules)
             self.modules = dict(previous.modules)
             self.modules = dict(previous.modules)
 
 
+        # Exclude doctest by default; it is not very useful in production
+        # builds.  It can be explicitly included if desired.
+        self.modules['doctest'] = self.ModuleDef('doctest', exclude = True)
+
         self.mf = None
         self.mf = None
 
 
         # Actually, make sure we know how to find all of the
         # Actually, make sure we know how to find all of the
@@ -951,8 +983,8 @@ class Freezer:
         for mdef in includes:
         for mdef in includes:
             try:
             try:
                 self.__loadModule(mdef)
                 self.__loadModule(mdef)
-            except ImportError:
-                print("Unknown module: %s" % (mdef.moduleName))
+            except ImportError as ex:
+                print("Unknown module: %s (%s)" % (mdef.moduleName, str(ex)))
 
 
         # Also attempt to import any implicit modules.  If any of
         # Also attempt to import any implicit modules.  If any of
         # these fail to import, we don't really care.
         # these fail to import, we don't really care.
@@ -1296,41 +1328,116 @@ class Freezer:
             if mdef.forbid:
             if mdef.forbid:
                 # Explicitly disallow importing this module.
                 # Explicitly disallow importing this module.
                 moduleList.append(self.makeForbiddenModuleListEntry(moduleName))
                 moduleList.append(self.makeForbiddenModuleListEntry(moduleName))
-            else:
-                assert not mdef.exclude
-                # Allow importing this module.
-                module = self.mf.modules.get(origName, None)
-                code = getattr(module, "__code__", None)
-                if code:
-                    code = marshal.dumps(code)
+                continue
 
 
-                    mangledName = self.mangleName(moduleName)
-                    moduleDefs.append(self.makeModuleDef(mangledName, code))
-                    moduleList.append(self.makeModuleListEntry(mangledName, code, moduleName, module))
+            assert not mdef.exclude
+            # Allow importing this module.
+            module = self.mf.modules.get(origName, None)
+            code = getattr(module, "__code__", None)
+            if code:
+                code = marshal.dumps(code)
 
 
-                elif moduleName in startupModules:
-                    # Forbid the loading of this startup module.
-                    moduleList.append(self.makeForbiddenModuleListEntry(moduleName))
+                mangledName = self.mangleName(moduleName)
+                moduleDefs.append(self.makeModuleDef(mangledName, code))
+                moduleList.append(self.makeModuleListEntry(mangledName, code, moduleName, module))
+                continue
 
 
-                else:
-                    # This is a module with no associated Python
-                    # code.  It must be an extension module.  Get the
-                    # filename.
-                    extensionFilename = getattr(module, '__file__', None)
-                    if extensionFilename:
-                        self.extras.append((moduleName, extensionFilename))
-                    else:
-                        # It doesn't even have a filename; it must
-                        # be a built-in module.  No worries about
-                        # this one, then.
-                        pass
+            #if moduleName in startupModules:
+            #    # Forbid the loading of this startup module.
+            #    moduleList.append(self.makeForbiddenModuleListEntry(moduleName))
+            #    continue
+
+            # This is a module with no associated Python code.  It is either
+            # an extension module or a builtin module.  Get the filename, if
+            # it is the former.
+            extensionFilename = getattr(module, '__file__', None)
+
+            if extensionFilename or self.linkExtensionModules:
+                self.extras.append((moduleName, extensionFilename))
+
+            # If it is a submodule of a frozen module, Python will have
+            # trouble importing it as a builtin module.  Synthesize a frozen
+            # module that loads it as builtin.
+            if '.' in moduleName and self.linkExtensionModules:
+                code = compile('import sys;del sys.modules["%s"];import imp;imp.init_builtin("%s")' % (moduleName, moduleName), moduleName, 'exec')
+                code = marshal.dumps(code)
+                mangledName = self.mangleName(moduleName)
+                moduleDefs.append(self.makeModuleDef(mangledName, code))
+                moduleList.append(self.makeModuleListEntry(mangledName, code, moduleName, None))
+            elif '.' in moduleName:
+                # Nothing we can do about this case except warn the user they
+                # are in for some trouble.
+                print('WARNING: Python cannot import extension modules under '
+                      'frozen Python packages; %s will be inaccessible.  '
+                      'passing either -l to link in extension modules or use '
+                      '-x %s to exclude the entire package.' % (moduleName, moduleName.split('.')[0]))
 
 
         text = programFile % {
         text = programFile % {
             'moduleDefs': '\n'.join(moduleDefs),
             'moduleDefs': '\n'.join(moduleDefs),
             'moduleList': '\n'.join(moduleList),
             'moduleList': '\n'.join(moduleList),
-            'initCode': initCode
             }
             }
 
 
+        if self.linkExtensionModules and self.extras:
+            # Should we link in extension modules?  If so, we write out a new
+            # built-in module table that directly hooks up with the init
+            # functions.  On Linux, we completely override Python's own
+            # built-in module table; on Windows, we can't do this, so we
+            # instead use PyImport_ExtendInittab to add to it.
+
+            # Python 3 case.
+            text += '#if PY_MAJOR_VERSION >= 3\n'
+            for module, fn in self.extras:
+                if sys.platform != "win32" or fn:
+                    libName = module.split('.')[-1]
+                    initFunc = builtinInitFuncs.get(module, 'PyInit_' + libName)
+                    if initFunc:
+                        text += 'extern DL_IMPORT(PyObject) *%s(void);\n' % (initFunc)
+            text += '\n'
+
+            if sys.platform == "win32":
+                text += 'static struct _inittab extensions[] = {\n'
+            else:
+                text += 'struct _inittab _PyImport_Inittab[] = {\n'
+
+            for module, fn in self.extras:
+                if sys.platform != "win32" or fn:
+                    libName = module.split('.')[-1]
+                    initFunc = builtinInitFuncs.get(module, 'PyInit_' + libName) or 'NULL'
+                    text += '  {"%s", %s},\n' % (module, initFunc)
+            text += '  {0, 0},\n'
+            text += '};\n\n'
+
+            # Python 2 case.
+            text += '#else\n'
+            for module, fn in self.extras:
+                if sys.platform != "win32" or fn:
+                    libName = module.split('.')[-1]
+                    initFunc = builtinInitFuncs.get(module, 'init' + libName)
+                    if initFunc:
+                        text += 'extern DL_IMPORT(void) %s(void);\n' % (initFunc)
+            text += '\n'
+
+            if sys.platform == "win32":
+                text += 'static struct _inittab extensions[] = {\n'
+            else:
+                text += 'struct _inittab _PyImport_Inittab[] = {\n'
+
+            for module, fn in self.extras:
+                if sys.platform != "win32" or fn:
+                    libName = module.split('.')[-1]
+                    initFunc = builtinInitFuncs.get(module, 'init' + libName) or 'NULL'
+                    text += '  {"%s", %s},\n' % (module, initFunc)
+            text += '  {0, 0},\n'
+            text += '};\n'
+            text += '#endif\n\n'
+
+        elif sys.platform == "win32":
+            text += 'static struct _inittab extensions[] = {\n'
+            text += '  {0, 0},\n'
+            text += '};\n\n'
+
+        text += initCode
+
         if filename is not None:
         if filename is not None:
             file = open(filename, 'w')
             file = open(filename, 'w')
             file.write(text)
             file.write(text)
@@ -1375,7 +1482,6 @@ class Freezer:
                 'dllimport' : dllimport,
                 'dllimport' : dllimport,
                 }
                 }
             if self.platform.startswith('win'):
             if self.platform.startswith('win'):
-                initCode += self.frozenExtensions
                 target = basename + '.exe'
                 target = basename + '.exe'
             else:
             else:
                 target = basename
                 target = basename
@@ -1397,14 +1503,46 @@ class Freezer:
 
 
         self.writeCode(filename, initCode=initCode)
         self.writeCode(filename, initCode=initCode)
 
 
+        # Keep track of the files we should clean up after use.
+        cleanFiles = [filename, basename + self.objectExtension]
+
+        extraLink = []
+        if self.linkExtensionModules:
+            for mod, fn in self.extras:
+                if not fn:
+                    continue
+                if sys.platform == 'win32':
+                    # We can't link with a .pyd directly on Windows.  Check
+                    # if there is a corresponding .lib file in the Python libs
+                    # directory.
+                    libsdir = os.path.join(sys.exec_prefix, 'libs')
+                    libfile = os.path.join(libsdir, mod + '.lib')
+                    if os.path.isfile(libfile):
+                        extraLink.append(mod + '.lib')
+                        continue
+
+                    # No, so we have to generate a .lib file.  This is pretty
+                    # easy given that we know the only symbol we need is a
+                    # initmodule or PyInit_module function.
+                    modname = mod.split('.')[-1]
+                    libfile = modname + '.lib'
+                    if sys.version_info >= (3, 0):
+                        symbolName = 'PyInit_' + modname
+                    else:
+                        symbolName = 'init' + modname
+                    os.system('lib /nologo /def /export:%s /name:%s.pyd /out:%s' % (symbolName, modname, libfile))
+                    extraLink.append(libfile)
+                    cleanFiles += [libfile, modname + '.exp']
+                else:
+                    extraLink.append(fn)
+
         try:
         try:
-            compileFunc(filename, basename)
+            compileFunc(filename, basename, extraLink=extraLink)
         finally:
         finally:
             if not self.keepTemporaryFiles:
             if not self.keepTemporaryFiles:
-                if os.path.exists(filename):
-                    os.unlink(filename)
-                if os.path.exists(basename + self.objectExtension):
-                    os.unlink(basename + self.objectExtension)
+                for file in cleanFiles:
+                    if os.path.exists(file):
+                        os.unlink(file)
 
 
         return target
         return target
 
 

+ 19 - 4
direct/src/showutil/pfreeze.py

@@ -15,7 +15,7 @@ imported directly or indirectly by the original startfile.py.
 
 
 Usage:
 Usage:
 
 
-  pfreeze.py [opts] startfile
+  pfreeze.py [opts] [startfile]
 
 
 Options:
 Options:
 
 
@@ -40,11 +40,20 @@ Options:
      of the __path__ variable, and thus must be actually imported to
      of the __path__ variable, and thus must be actually imported to
      determine the true value of __path__.
      determine the true value of __path__.
 
 
+  -P path
+     Specifies an additional directory in which we should search for
+     Python modules.  This is equivalent to setting the PYTHONPATH
+     environment variable.  May be repeated.
+
   -s
   -s
      Adds the standard set of modules that are necessary for embedding
      Adds the standard set of modules that are necessary for embedding
      the Python interpreter.  Implicitly set if an executable is
      the Python interpreter.  Implicitly set if an executable is
      generated.
      generated.
 
 
+  -k
+     Keeps temporary files generated by pfreeze.  Useful when debugging
+     FreezeTool itself.
+
 """
 """
 
 
 import getopt
 import getopt
@@ -55,7 +64,7 @@ from direct.showutil import FreezeTool
 def usage(code, msg = ''):
 def usage(code, msg = ''):
     if __doc__:
     if __doc__:
         sys.stderr.write(__doc__ + '\n')
         sys.stderr.write(__doc__ + '\n')
-    sys.stderr.write(msg + '\n')
+    sys.stderr.write(str(msg) + '\n')
     sys.exit(code)
     sys.exit(code)
 
 
 # We're not protecting the next part under a __name__ == __main__
 # We're not protecting the next part under a __name__ == __main__
@@ -67,7 +76,7 @@ basename = None
 addStartupModules = False
 addStartupModules = False
 
 
 try:
 try:
-    opts, args = getopt.getopt(sys.argv[1:], 'o:i:x:p:sh')
+    opts, args = getopt.getopt(sys.argv[1:], 'o:i:x:p:P:slkh')
 except getopt.error as msg:
 except getopt.error as msg:
     usage(1, msg)
     usage(1, msg)
 
 
@@ -83,8 +92,14 @@ for opt, arg in opts:
     elif opt == '-p':
     elif opt == '-p':
         for module in arg.split(','):
         for module in arg.split(','):
             freezer.handleCustomPath(module)
             freezer.handleCustomPath(module)
+    elif opt == '-P':
+        sys.path.append(arg)
     elif opt == '-s':
     elif opt == '-s':
         addStartupModules = True
         addStartupModules = True
+    elif opt == '-l':
+        freezer.linkExtensionModules = True
+    elif opt == '-k':
+        freezer.keepTemporaryFiles = True
     elif opt == '-h':
     elif opt == '-h':
         usage(0)
         usage(0)
     else:
     else:
@@ -126,7 +141,7 @@ if args:
 
 
 elif outputType == 'exe':
 elif outputType == 'exe':
     # We must have a main module when making an executable.
     # We must have a main module when making an executable.
-    usage(0)
+    usage(1, 'A main file needs to be specified when creating an executable.')
 
 
 freezer.done(addStartupModules = addStartupModules)
 freezer.done(addStartupModules = addStartupModules)
 
 

+ 2 - 2
dtool/src/parser-inc/zlib.h

@@ -21,8 +21,8 @@
 
 
 #include "zconf.h"
 #include "zconf.h"
 
 
-class z_stream {
-};
+typedef struct z_stream_s z_stream;
+typedef struct gz_header_s gz_header;
 
 
 #endif
 #endif
 
 

+ 8 - 3
makepanda/makepanda.py

@@ -592,8 +592,12 @@ if (COMPILER == "MSVC"):
     if (PkgSkip("DIRECTCAM")==0): LibName("DIRECTCAM", "odbc32.lib")
     if (PkgSkip("DIRECTCAM")==0): LibName("DIRECTCAM", "odbc32.lib")
     if (PkgSkip("DIRECTCAM")==0): LibName("DIRECTCAM", "odbccp32.lib")
     if (PkgSkip("DIRECTCAM")==0): LibName("DIRECTCAM", "odbccp32.lib")
     if (PkgSkip("OPENSSL")==0):
     if (PkgSkip("OPENSSL")==0):
-        LibName("OPENSSL", GetThirdpartyDir() + "openssl/lib/libpandassl.lib")
-        LibName("OPENSSL", GetThirdpartyDir() + "openssl/lib/libpandaeay.lib")
+        if os.path.isfile(GetThirdpartyDir() + "openssl/lib/libpandassl.lib"):
+            LibName("OPENSSL", GetThirdpartyDir() + "openssl/lib/libpandassl.lib")
+            LibName("OPENSSL", GetThirdpartyDir() + "openssl/lib/libpandaeay.lib")
+        else:
+            LibName("OPENSSL", GetThirdpartyDir() + "openssl/lib/libeay32.lib")
+            LibName("OPENSSL", GetThirdpartyDir() + "openssl/lib/ssleay32.lib")
     if (PkgSkip("PNG")==0):
     if (PkgSkip("PNG")==0):
         if os.path.isfile(GetThirdpartyDir() + "png/lib/libpng16_static.lib"):
         if os.path.isfile(GetThirdpartyDir() + "png/lib/libpng16_static.lib"):
             LibName("PNG", GetThirdpartyDir() + "png/lib/libpng16_static.lib")
             LibName("PNG", GetThirdpartyDir() + "png/lib/libpng16_static.lib")
@@ -4039,7 +4043,8 @@ if (not RUNTIME):
   TargetAdd('core.pyd', input='p3display_pythonGraphicsWindowProc.obj')
   TargetAdd('core.pyd', input='p3display_pythonGraphicsWindowProc.obj')
 
 
   TargetAdd('core.pyd', input='core_module.obj')
   TargetAdd('core.pyd', input='core_module.obj')
-  TargetAdd('core.pyd', input='libp3tinyxml.ilb')
+  if not GetLinkAllStatic() and GetTarget() != 'emscripten':
+     TargetAdd('core.pyd', input='libp3tinyxml.ilb')
   TargetAdd('core.pyd', input='libp3interrogatedb.dll')
   TargetAdd('core.pyd', input='libp3interrogatedb.dll')
   TargetAdd('core.pyd', input=COMMON_PANDA_LIBS)
   TargetAdd('core.pyd', input=COMMON_PANDA_LIBS)
   TargetAdd('core.pyd', opts=['PYTHON', 'WINSOCK2'])
   TargetAdd('core.pyd', opts=['PYTHON', 'WINSOCK2'])

+ 1 - 1
panda/metalibs/pandaegg/pandaegg.h

@@ -9,6 +9,6 @@
 
 
 #include "pandabase.h"
 #include "pandabase.h"
 
 
-EXPCL_PANDAEGG void init_libpandaegg();
+extern "C" EXPCL_PANDAEGG void init_libpandaegg();
 
 
 #endif
 #endif

+ 29 - 10
panda/src/audio/audioManager.cxx

@@ -36,25 +36,35 @@ namespace {
   }
   }
 }
 }
 
 
-Create_AudioManager_proc* AudioManager::_create_AudioManager
-    =create_NullAudioManager;
+Create_AudioManager_proc *AudioManager::_create_AudioManager = NULL;
 
 
-void AudioManager::register_AudioManager_creator(Create_AudioManager_proc* proc) {
-  nassertv(_create_AudioManager==create_NullAudioManager);
-  _create_AudioManager=proc;
+void AudioManager::
+register_AudioManager_creator(Create_AudioManager_proc* proc) {
+  nassertv(_create_AudioManager == NULL);
+  _create_AudioManager = proc;
 }
 }
 
 
-
-
 // Factory method for getting a platform specific AudioManager:
 // Factory method for getting a platform specific AudioManager:
 PT(AudioManager) AudioManager::create_AudioManager() {
 PT(AudioManager) AudioManager::create_AudioManager() {
   audio_debug("create_AudioManager()\n  audio_library_name=\""<<audio_library_name<<"\"");
   audio_debug("create_AudioManager()\n  audio_library_name=\""<<audio_library_name<<"\"");
+
+  if (_create_AudioManager != NULL) {
+    // Someone was already so good as to register an audio manager creation function,
+    // perhaps by statically linking the requested library.  Let's use that, then.
+    PT(AudioManager) am = (*_create_AudioManager)();
+    if (!am->is_exact_type(NullAudioManager::get_class_type()) && !am->is_valid()) {
+      audio_error("  " << am->get_type() << " is not valid, will use NullAudioManager");
+      am = create_NullAudioManager();
+    }
+    return am;
+  }
+
   static bool lib_load = false;
   static bool lib_load = false;
   if (!lib_load) {
   if (!lib_load) {
     lib_load = true;
     lib_load = true;
-    if (!audio_library_name.empty() && !(audio_library_name == "null")) {
+    if (!audio_library_name.empty() && audio_library_name != "null") {
       Filename dl_name = Filename::dso_filename(
       Filename dl_name = Filename::dso_filename(
-          "lib"+string(audio_library_name)+".so");
+          "lib" + string(audio_library_name) + ".so");
       dl_name.to_os_specific();
       dl_name.to_os_specific();
       audio_debug("  dl_name=\""<<dl_name<<"\"");
       audio_debug("  dl_name=\""<<dl_name<<"\"");
       void *handle = load_dso(get_plugin_path().get_value(), dl_name);
       void *handle = load_dso(get_plugin_path().get_value(), dl_name);
@@ -84,11 +94,20 @@ PT(AudioManager) AudioManager::create_AudioManager() {
         } else {
         } else {
           typedef Create_AudioManager_proc *FuncType();
           typedef Create_AudioManager_proc *FuncType();
           Create_AudioManager_proc *factory_func = (*(FuncType *)dso_symbol)();
           Create_AudioManager_proc *factory_func = (*(FuncType *)dso_symbol)();
-          AudioManager::register_AudioManager_creator(factory_func);
+
+          // Note that the audio manager module may register itself upon load.
+          if (_create_AudioManager == NULL) {
+            AudioManager::register_AudioManager_creator(factory_func);
+          }
         }
         }
       }
       }
     }
     }
   }
   }
+
+  if (_create_AudioManager == NULL) {
+    _create_AudioManager = create_NullAudioManager;
+  }
+
   PT(AudioManager) am = (*_create_AudioManager)();
   PT(AudioManager) am = (*_create_AudioManager)();
   if (!am->is_exact_type(NullAudioManager::get_class_type()) && !am->is_valid()) {
   if (!am->is_exact_type(NullAudioManager::get_class_type()) && !am->is_valid()) {
     audio_error("  " << am->get_type() << " is not valid, will use NullAudioManager");
     audio_error("  " << am->get_type() << " is not valid, will use NullAudioManager");

+ 2 - 0
panda/src/audiotraits/config_openalAudio.cxx

@@ -48,6 +48,8 @@ init_libOpenALAudio() {
   OpenALAudioManager::init_type();
   OpenALAudioManager::init_type();
   OpenALAudioSound::init_type();
   OpenALAudioSound::init_type();
 
 
+  AudioManager::register_AudioManager_creator(&Create_OpenALAudioManager);
+
   PandaSystem *ps = PandaSystem::get_global_ptr();
   PandaSystem *ps = PandaSystem::get_global_ptr();
   ps->add_system("OpenAL");
   ps->add_system("OpenAL");
   ps->add_system("audio");
   ps->add_system("audio");

+ 1 - 1
panda/src/audiotraits/config_openalAudio.h

@@ -22,7 +22,7 @@
 ConfigureDecl(config_openalAudio, EXPCL_OPENAL_AUDIO, EXPTP_OPENAL_AUDIO);
 ConfigureDecl(config_openalAudio, EXPCL_OPENAL_AUDIO, EXPTP_OPENAL_AUDIO);
 NotifyCategoryDecl(openalAudio, EXPCL_OPENAL_AUDIO, EXPTP_OPENAL_AUDIO);
 NotifyCategoryDecl(openalAudio, EXPCL_OPENAL_AUDIO, EXPTP_OPENAL_AUDIO);
 
 
-extern EXPCL_OPENAL_AUDIO void init_libOpenALAudio();
+extern "C" EXPCL_OPENAL_AUDIO void init_libOpenALAudio();
 extern "C" EXPCL_OPENAL_AUDIO Create_AudioManager_proc *get_audio_manager_func_openal_audio();
 extern "C" EXPCL_OPENAL_AUDIO Create_AudioManager_proc *get_audio_manager_func_openal_audio();
 
 
 extern ConfigVariableString openal_device;
 extern ConfigVariableString openal_device;

+ 1 - 1
panda/src/audiotraits/milesAudioManager.cxx

@@ -893,7 +893,7 @@ load(const Filename &file_name) {
   sd->_basename = file_name.get_basename();
   sd->_basename = file_name.get_basename();
 
 
   string extension = sd->_basename.get_extension();
   string extension = sd->_basename.get_extension();
-  if (extension == "pz") {
+  if (extension == "pz" || extension == "gz") {
     extension = Filename(sd->_basename.get_basename_wo_extension()).get_extension();
     extension = Filename(sd->_basename.get_basename_wo_extension()).get_extension();
   }
   }
 
 

+ 1 - 1
panda/src/collada/loaderFileTypeDae.cxx

@@ -56,7 +56,7 @@ get_additional_extensions() const {
 
 
 /**
 /**
  * Returns true if this file type can transparently load compressed files
  * Returns true if this file type can transparently load compressed files
- * (with a .pz extension), false otherwise.
+ * (with a .pz or .gz extension), false otherwise.
  */
  */
 bool LoaderFileTypeDae::
 bool LoaderFileTypeDae::
 supports_compressed() const {
 supports_compressed() const {

+ 1 - 1
panda/src/downloader/decompressor.cxx

@@ -55,7 +55,7 @@ Decompressor::
 int Decompressor::
 int Decompressor::
 initiate(const Filename &source_file) {
 initiate(const Filename &source_file) {
   string extension = source_file.get_extension();
   string extension = source_file.get_extension();
-  if (extension == "pz") {
+  if (extension == "pz" || extension == "gz") {
     Filename dest_file = source_file;
     Filename dest_file = source_file;
     dest_file = source_file.get_fullpath_wo_extension();
     dest_file = source_file.get_fullpath_wo_extension();
     return initiate(source_file, dest_file);
     return initiate(source_file, dest_file);

+ 1 - 1
panda/src/egg2pg/loaderFileTypeEgg.cxx

@@ -44,7 +44,7 @@ get_extension() const {
 
 
 /**
 /**
  * Returns true if this file type can transparently load compressed files
  * Returns true if this file type can transparently load compressed files
- * (with a .pz extension), false otherwise.
+ * (with a .pz or .gz extension), false otherwise.
  */
  */
 bool LoaderFileTypeEgg::
 bool LoaderFileTypeEgg::
 supports_compressed() const {
 supports_compressed() const {

+ 7 - 3
panda/src/express/virtualFileSimple.cxx

@@ -186,7 +186,7 @@ copy_file(VirtualFile *new_file) {
  * (which you should eventually delete when you are done reading). Returns
  * (which you should eventually delete when you are done reading). Returns
  * NULL on failure.
  * NULL on failure.
  *
  *
- * If auto_unwrap is true, an explicitly-named .pz file is automatically
+ * If auto_unwrap is true, an explicitly-named .pz/.gz file is automatically
  * decompressed and the decompressed contents are returned.  This is different
  * decompressed and the decompressed contents are returned.  This is different
  * than vfs-implicit-pz, which will automatically decompress a file if the
  * than vfs-implicit-pz, which will automatically decompress a file if the
  * extension .pz is *not* given.
  * extension .pz is *not* given.
@@ -195,7 +195,9 @@ istream *VirtualFileSimple::
 open_read_file(bool auto_unwrap) const {
 open_read_file(bool auto_unwrap) const {
 
 
   // Will we be automatically unwrapping a .pz file?
   // Will we be automatically unwrapping a .pz file?
-  bool do_uncompress = (_implicit_pz_file || (auto_unwrap && _local_filename.get_extension() == "pz"));
+  bool do_uncompress = (_implicit_pz_file ||
+    (auto_unwrap && (_local_filename.get_extension() == "pz" ||
+                     _local_filename.get_extension() == "gz")));
 
 
   Filename local_filename(_local_filename);
   Filename local_filename(_local_filename);
   if (do_uncompress) {
   if (do_uncompress) {
@@ -364,7 +366,9 @@ bool VirtualFileSimple::
 read_file(pvector<unsigned char> &result, bool auto_unwrap) const {
 read_file(pvector<unsigned char> &result, bool auto_unwrap) const {
 
 
   // Will we be automatically unwrapping a .pz file?
   // Will we be automatically unwrapping a .pz file?
-  bool do_uncompress = (_implicit_pz_file || (auto_unwrap && _local_filename.get_extension() == "pz"));
+  bool do_uncompress = (_implicit_pz_file ||
+    (auto_unwrap && (_local_filename.get_extension() == "pz" ||
+                     _local_filename.get_extension() == "gz")));
 
 
   Filename local_filename(_local_filename);
   Filename local_filename(_local_filename);
   if (do_uncompress) {
   if (do_uncompress) {

+ 3 - 3
panda/src/express/virtualFileSystem.I

@@ -88,7 +88,7 @@ ls_all(const Filename &filename) const {
  * Convenience function; returns the entire contents of the indicated file as
  * Convenience function; returns the entire contents of the indicated file as
  * a string.
  * a string.
  *
  *
- * If auto_unwrap is true, an explicitly-named .pz file is automatically
+ * If auto_unwrap is true, an explicitly-named .pz/.gz file is automatically
  * decompressed and the decompressed contents are returned.  This is different
  * decompressed and the decompressed contents are returned.  This is different
  * than vfs-implicit-pz, which will automatically decompress a file if the
  * than vfs-implicit-pz, which will automatically decompress a file if the
  * extension .pz is *not* given.
  * extension .pz is *not* given.
@@ -118,7 +118,7 @@ write_file(const Filename &filename, const string &data, bool auto_wrap) {
  * file, if it exists and can be read.  Returns true on success, false
  * file, if it exists and can be read.  Returns true on success, false
  * otherwise.
  * otherwise.
  *
  *
- * If auto_unwrap is true, an explicitly-named .pz file is automatically
+ * If auto_unwrap is true, an explicitly-named .pz/.gz file is automatically
  * decompressed and the decompressed contents are returned.  This is different
  * decompressed and the decompressed contents are returned.  This is different
  * than vfs-implicit-pz, which will automatically decompress a file if the
  * than vfs-implicit-pz, which will automatically decompress a file if the
  * extension .pz is *not* given.
  * extension .pz is *not* given.
@@ -134,7 +134,7 @@ read_file(const Filename &filename, string &result, bool auto_unwrap) const {
  * file, if it exists and can be read.  Returns true on success, false
  * file, if it exists and can be read.  Returns true on success, false
  * otherwise.
  * otherwise.
  *
  *
- * If auto_unwrap is true, an explicitly-named .pz file is automatically
+ * If auto_unwrap is true, an explicitly-named .pz/.gz file is automatically
  * decompressed and the decompressed contents are returned.  This is different
  * decompressed and the decompressed contents are returned.  This is different
  * than vfs-implicit-pz, which will automatically decompress a file if the
  * than vfs-implicit-pz, which will automatically decompress a file if the
  * extension .pz is *not* given.
  * extension .pz is *not* given.

+ 2 - 2
panda/src/express/zStreamBuf.cxx

@@ -87,9 +87,9 @@ open_read(istream *source, bool owns_source) {
   _z_source.opaque = Z_NULL;
   _z_source.opaque = Z_NULL;
   _z_source.msg = (char *)"no error message";
   _z_source.msg = (char *)"no error message";
 
 
-  int result = inflateInit(&_z_source);
+  int result = inflateInit2(&_z_source, 32 + 15);
   if (result < 0) {
   if (result < 0) {
-    show_zlib_error("inflateInit", result, _z_source);
+    show_zlib_error("inflateInit2", result, _z_source);
     close_read();
     close_read();
   }
   }
   thread_consider_yield();
   thread_consider_yield();

+ 6 - 2
panda/src/framework/pandaFramework.cxx

@@ -31,6 +31,12 @@
 #include "transformState.h"
 #include "transformState.h"
 #include "renderState.h"
 #include "renderState.h"
 
 
+#ifdef LINK_ALL_STATIC
+#ifdef HAVE_EGG
+#include "pandaegg.h"
+#endif
+#endif
+
 LoaderOptions PandaFramework::_loader_options;
 LoaderOptions PandaFramework::_loader_options;
 
 
 /**
 /**
@@ -101,10 +107,8 @@ open_framework(int &argc, char **&argv) {
 
 
   // We also want the egg loader.
   // We also want the egg loader.
   #ifdef HAVE_EGG
   #ifdef HAVE_EGG
-  extern EXPCL_PANDAEGG void init_libpandaegg();
   init_libpandaegg();
   init_libpandaegg();
   #endif
   #endif
-
 #endif
 #endif
 
 
   // Let's explicitly make a call to the image type library to ensure it gets
   // Let's explicitly make a call to the image type library to ensure it gets

+ 1 - 1
panda/src/framework/windowFramework.cxx

@@ -591,7 +591,7 @@ load_model(const NodePath &parent, Filename filename) {
   bool is_image = false;
   bool is_image = false;
   string extension = filename.get_extension();
   string extension = filename.get_extension();
 #ifdef HAVE_ZLIB
 #ifdef HAVE_ZLIB
-  if (extension == "pz") {
+  if (extension == "pz" || extension == "gz") {
     extension = Filename(filename.get_basename_wo_extension()).get_extension();
     extension = Filename(filename.get_basename_wo_extension()).get_extension();
   }
   }
 #endif  // HAVE_ZLIB
 #endif  // HAVE_ZLIB

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

@@ -8334,6 +8334,7 @@ get_external_image_format(Texture *tex) const {
       case Texture::F_blue:
       case Texture::F_blue:
       case Texture::F_r8i:
       case Texture::F_r8i:
       case Texture::F_r16:
       case Texture::F_r16:
+      case Texture::F_r16i:
       case Texture::F_r32:
       case Texture::F_r32:
       case Texture::F_r32i:
       case Texture::F_r32i:
         return GL_COMPRESSED_RED;
         return GL_COMPRESSED_RED;
@@ -8539,6 +8540,7 @@ get_external_image_format(Texture *tex) const {
 
 
 #ifndef OPENGLES_1
 #ifndef OPENGLES_1
   case Texture::F_r8i:
   case Texture::F_r8i:
+  case Texture::F_r16i:
   case Texture::F_r32i:
   case Texture::F_r32i:
     return GL_RED_INTEGER;
     return GL_RED_INTEGER;
   case Texture::F_rg8i:
   case Texture::F_rg8i:
@@ -8596,6 +8598,7 @@ get_internal_image_format(Texture *tex, bool force_sized) const {
       case Texture::F_rg8i:
       case Texture::F_rg8i:
       case Texture::F_rgb8i:
       case Texture::F_rgb8i:
       case Texture::F_rgba8i:
       case Texture::F_rgba8i:
+      case Texture::F_r16i:
       case Texture::F_r32i:
       case Texture::F_r32i:
       case Texture::F_r11_g11_b10:
       case Texture::F_r11_g11_b10:
       case Texture::F_rgb9_e5:
       case Texture::F_rgb9_e5:
@@ -9072,6 +9075,12 @@ get_internal_image_format(Texture *tex, bool force_sized) const {
     } else {
     } else {
       return GL_R16_SNORM;
       return GL_R16_SNORM;
     }
     }
+  case Texture::F_r16i:
+    if (Texture::is_unsigned(tex->get_component_type())) {
+      return GL_R16UI;
+    } else {
+      return GL_R16I;
+    }
   case Texture::F_rg16:
   case Texture::F_rg16:
     if (tex->get_component_type() == Texture::T_float) {
     if (tex->get_component_type() == Texture::T_float) {
       return GL_RG16F;
       return GL_RG16F;
@@ -12662,6 +12671,16 @@ do_extract_texture_data(CLP(TextureContext) *gtc) {
     type = Texture::T_unsigned_byte;
     type = Texture::T_unsigned_byte;
     format = Texture::F_rgba8i;
     format = Texture::F_rgba8i;
     break;
     break;
+
+  case GL_R16I:
+    type = Texture::T_short;
+    format = Texture::F_r16i;
+    break;
+  case GL_R16UI:
+    type = Texture::T_unsigned_short;
+    format = Texture::F_r16i;
+    break;
+
 #endif
 #endif
 
 
 #ifndef OPENGLES_1
 #ifndef OPENGLES_1

+ 11 - 2
panda/src/glstuff/glShaderContext_src.cxx

@@ -2666,10 +2666,10 @@ glsl_report_shader_errors(GLuint shader, Shader::ShaderType type, bool fatal) {
   istringstream log(info_log);
   istringstream log(info_log);
   string line;
   string line;
   while (getline(log, line)) {
   while (getline(log, line)) {
-    int fileno, lineno;
+    int fileno, lineno, colno;
     int prefixlen = 0;
     int prefixlen = 0;
 
 
-    // First is AMDIntel driver syntax, second is NVIDIA syntax.
+    // This first format is used by the majority of compilers.
     if (sscanf(line.c_str(), "ERROR: %d:%d: %n", &fileno, &lineno, &prefixlen) == 2
     if (sscanf(line.c_str(), "ERROR: %d:%d: %n", &fileno, &lineno, &prefixlen) == 2
         && prefixlen > 0) {
         && prefixlen > 0) {
 
 
@@ -2688,10 +2688,19 @@ glsl_report_shader_errors(GLuint shader, Shader::ShaderType type, bool fatal) {
     } else if (sscanf(line.c_str(), "%d(%d) : %n", &fileno, &lineno, &prefixlen) == 2
     } else if (sscanf(line.c_str(), "%d(%d) : %n", &fileno, &lineno, &prefixlen) == 2
                && prefixlen > 0) {
                && prefixlen > 0) {
 
 
+      // This is the format NVIDIA uses.
       Filename fn = _shader->get_filename_from_index(fileno, type);
       Filename fn = _shader->get_filename_from_index(fileno, type);
       GLCAT.error(false)
       GLCAT.error(false)
         << fn << "(" << lineno << ") : " << (line.c_str() + prefixlen) << "\n";
         << fn << "(" << lineno << ") : " << (line.c_str() + prefixlen) << "\n";
 
 
+    } else if (sscanf(line.c_str(), "%d:%d(%d): %n", &fileno, &lineno, &colno, &prefixlen) == 3
+               && prefixlen > 0) {
+
+      // This is the format for Mesa's OpenGL ES 2 implementation.
+      Filename fn = _shader->get_filename_from_index(fileno, type);
+      GLCAT.error(false)
+        << fn << ":" << lineno << "(" << colno << "): " << (line.c_str() + prefixlen) << "\n";
+
     } else if (!fatal) {
     } else if (!fatal) {
       GLCAT.warning(false) << line << "\n";
       GLCAT.warning(false) << line << "\n";
 
 

+ 4 - 1
panda/src/gobj/geomVertexArrayFormat.cxx

@@ -708,7 +708,10 @@ write_datagram(BamWriter *manager, Datagram &dg) {
   dg.add_uint16(_stride);
   dg.add_uint16(_stride);
   dg.add_uint16(_total_bytes);
   dg.add_uint16(_total_bytes);
   dg.add_uint8(_pad_to);
   dg.add_uint8(_pad_to);
-  dg.add_uint16(_divisor);
+
+  if (manager->get_file_minor_ver() > 36) {
+    dg.add_uint16(_divisor);
+  }
 
 
   consider_sort_columns();
   consider_sort_columns();
 
 

+ 12 - 2
panda/src/gobj/geomVertexColumn.cxx

@@ -378,9 +378,19 @@ write_datagram(BamWriter *manager, Datagram &dg) {
   manager->write_pointer(dg, _name);
   manager->write_pointer(dg, _name);
   dg.add_uint8(_num_components);
   dg.add_uint8(_num_components);
   dg.add_uint8(_numeric_type);
   dg.add_uint8(_numeric_type);
-  dg.add_uint8(_contents);
+
+  if (_contents == C_normal && manager->get_file_minor_ver() < 38) {
+    // Panda 1.9 did not have C_normal.
+    dg.add_uint8(C_vector);
+  } else {
+    dg.add_uint8(_contents);
+  }
+
   dg.add_uint16(_start);
   dg.add_uint16(_start);
-  dg.add_uint8(_column_alignment);
+
+  if (manager->get_file_minor_ver() >= 29) {
+    dg.add_uint8(_column_alignment);
+  }
 }
 }
 
 
 /**
 /**

+ 23 - 14
panda/src/gobj/material.cxx

@@ -257,7 +257,7 @@ set_roughness(PN_stdfloat roughness) {
   // Calculate the specular exponent from the roughness as it is used in
   // Calculate the specular exponent from the roughness as it is used in
   // Blinn-Phong shading model.  We use the popular Disney method of squaring
   // Blinn-Phong shading model.  We use the popular Disney method of squaring
   // the roughness to get a more perceptually linear scale.  From:
   // the roughness to get a more perceptually linear scale.  From:
-  // http:graphicrants.blogspot.de201308specular-brdf-reference.html
+  // http://graphicrants.blogspot.de/2013/08/specular-brdf-reference.html
   if (roughness <= 0 || IS_NEARLY_ZERO(roughness)) {
   if (roughness <= 0 || IS_NEARLY_ZERO(roughness)) {
     _shininess = make_inf((PN_stdfloat)0);
     _shininess = make_inf((PN_stdfloat)0);
   } else {
   } else {
@@ -481,26 +481,35 @@ void Material::
 write_datagram(BamWriter *manager, Datagram &me) {
 write_datagram(BamWriter *manager, Datagram &me) {
   me.add_string(get_name());
   me.add_string(get_name());
 
 
-  me.add_int32(_flags);
+  if (manager->get_file_minor_ver() >= 39) {
+    me.add_int32(_flags);
 
 
-  if (_flags & F_metallic) {
-    // Metalness workflow.
-    _base_color.write_datagram(me);
-    me.add_stdfloat(_metallic);
+    if (_flags & F_metallic) {
+      // Metalness workflow.
+      _base_color.write_datagram(me);
+      me.add_stdfloat(_metallic);
+    } else {
+      _ambient.write_datagram(me);
+      _diffuse.write_datagram(me);
+      _specular.write_datagram(me);
+    }
+    _emission.write_datagram(me);
+
+    if (_flags & F_roughness) {
+      me.add_stdfloat(_roughness);
+    } else {
+      me.add_stdfloat(_shininess);
+    }
+
+    me.add_stdfloat(_refractive_index);
   } else {
   } else {
     _ambient.write_datagram(me);
     _ambient.write_datagram(me);
     _diffuse.write_datagram(me);
     _diffuse.write_datagram(me);
     _specular.write_datagram(me);
     _specular.write_datagram(me);
-  }
-  _emission.write_datagram(me);
-
-  if (_flags & F_roughness) {
-    me.add_stdfloat(_roughness);
-  } else {
+    _emission.write_datagram(me);
     me.add_stdfloat(_shininess);
     me.add_stdfloat(_shininess);
+    me.add_int32(_flags & 0x7f);
   }
   }
-
-  me.add_stdfloat(_refractive_index);
 }
 }
 
 
 /**
 /**

+ 11 - 7
panda/src/gobj/matrixLens.cxx

@@ -83,14 +83,18 @@ register_with_read_factory() {
  */
  */
 void MatrixLens::
 void MatrixLens::
 write_datagram(BamWriter *manager, Datagram &dg) {
 write_datagram(BamWriter *manager, Datagram &dg) {
-  dg.add_uint8(_ml_flags);
-  _user_mat.write_datagram(dg);
+  Lens::write_datagram(manager, dg);
 
 
-  if (_ml_flags & MF_has_left_eye) {
-    _left_eye_mat.write_datagram(dg);
-  }
-  if (_ml_flags & MF_has_right_eye) {
-    _left_eye_mat.write_datagram(dg);
+  if (manager->get_file_minor_ver() >= 41) {
+    dg.add_uint8(_ml_flags);
+    _user_mat.write_datagram(dg);
+
+    if (_ml_flags & MF_has_left_eye) {
+      _left_eye_mat.write_datagram(dg);
+    }
+    if (_ml_flags & MF_has_right_eye) {
+      _left_eye_mat.write_datagram(dg);
+    }
   }
   }
 }
 }
 
 

+ 32 - 0
panda/src/gobj/shader.I

@@ -50,6 +50,38 @@ get_filename(ShaderType type) const {
   }
   }
 }
 }
 
 
+/**
+ * Sets the Shader's filename for the given shader type.  Useful for
+ * associating a shader created with Shader.make with a name for diagnostics.
+ */
+INLINE void Shader::
+set_filename(ShaderType type, const Filename &filename) {
+  _filename._separate = true;
+  switch (type) {
+  case ST_vertex:
+    _filename._vertex = filename;
+    break;
+  case ST_fragment:
+    _filename._fragment = filename;
+    break;
+  case ST_geometry:
+    _filename._geometry = filename;
+    break;
+  case ST_tess_control:
+    _filename._tess_control = filename;
+    break;
+  case ST_tess_evaluation:
+    _filename._tess_evaluation = filename;
+    break;
+  case ST_compute:
+    _filename._compute = filename;
+    break;
+  default:
+    _filename._shared = filename;
+    _filename._separate = false;
+  }
+}
+
 /**
 /**
  * Return the Shader's text for the given shader type.
  * Return the Shader's text for the given shader type.
  */
  */

+ 1 - 0
panda/src/gobj/shader.h

@@ -98,6 +98,7 @@ PUBLISHED:
   static PT(Shader) make_compute(ShaderLanguage lang, const string &body);
   static PT(Shader) make_compute(ShaderLanguage lang, const string &body);
 
 
   INLINE Filename get_filename(ShaderType type = ST_none) const;
   INLINE Filename get_filename(ShaderType type = ST_none) const;
+  INLINE void set_filename(ShaderType type, const Filename &filename);
   INLINE const string &get_text(ShaderType type = ST_none) const;
   INLINE const string &get_text(ShaderType type = ST_none) const;
   INLINE bool get_error_flag() const;
   INLINE bool get_error_flag() const;
   INLINE ShaderLanguage get_language() const;
   INLINE ShaderLanguage get_language() const;

+ 2 - 2
panda/src/gobj/texture.I

@@ -2325,7 +2325,7 @@ INLINE bool Texture::
 is_txo_filename(const Filename &fullpath) {
 is_txo_filename(const Filename &fullpath) {
   string extension = fullpath.get_extension();
   string extension = fullpath.get_extension();
 #ifdef HAVE_ZLIB
 #ifdef HAVE_ZLIB
-  if (extension == "pz") {
+  if (extension == "pz" || extension == "gz") {
     extension = Filename(fullpath.get_basename_wo_extension()).get_extension();
     extension = Filename(fullpath.get_basename_wo_extension()).get_extension();
   }
   }
 #endif  // HAVE_ZLIB
 #endif  // HAVE_ZLIB
@@ -2340,7 +2340,7 @@ INLINE bool Texture::
 is_dds_filename(const Filename &fullpath) {
 is_dds_filename(const Filename &fullpath) {
   string extension = fullpath.get_extension();
   string extension = fullpath.get_extension();
 #ifdef HAVE_ZLIB
 #ifdef HAVE_ZLIB
-  if (extension == "pz") {
+  if (extension == "pz" || extension == "gz") {
     extension = Filename(fullpath.get_basename_wo_extension()).get_extension();
     extension = Filename(fullpath.get_basename_wo_extension()).get_extension();
   }
   }
 #endif  // HAVE_ZLIB
 #endif  // HAVE_ZLIB

+ 46 - 8
panda/src/gobj/texture.cxx

@@ -514,6 +514,7 @@ estimate_texture_memory() const {
     break;
     break;
 
 
   case Texture::F_r16:
   case Texture::F_r16:
+  case Texture::F_r16i:
   case Texture::F_rg8i:
   case Texture::F_rg8i:
     bpp = 2;
     bpp = 2;
     break;
     break;
@@ -1532,6 +1533,10 @@ write(ostream &out, int indent_level) const {
   case F_r16:
   case F_r16:
     out << "r16";
     out << "r16";
     break;
     break;
+  case F_r16i:
+    out << "r16i";
+    break;
+
   case F_rg16:
   case F_rg16:
     out << "rg16";
     out << "rg16";
     break;
     break;
@@ -1950,6 +1955,8 @@ format_format(Format format) {
     return "rgba32";
     return "rgba32";
   case F_r16:
   case F_r16:
     return "r16";
     return "r16";
+  case F_r16i:
+    return "r16i";  
   case F_rg16:
   case F_rg16:
     return "rg16";
     return "rg16";
   case F_rgb16:
   case F_rgb16:
@@ -2049,6 +2056,8 @@ string_format(const string &str) {
     return F_rgba32;
     return F_rgba32;
   } else if (cmp_nocase(str, "r16") == 0 || cmp_nocase(str, "red16") == 0) {
   } else if (cmp_nocase(str, "r16") == 0 || cmp_nocase(str, "red16") == 0) {
     return F_r16;
     return F_r16;
+  } else if (cmp_nocase(str, "r16i") == 0) {
+    return F_r16i;
   } else if (cmp_nocase(str, "rg16") == 0 || cmp_nocase(str, "r16g16") == 0) {
   } else if (cmp_nocase(str, "rg16") == 0 || cmp_nocase(str, "r16g16") == 0) {
     return F_rg16;
     return F_rg16;
   } else if (cmp_nocase(str, "rgb16") == 0 || cmp_nocase(str, "r16g16b16") == 0) {
   } else if (cmp_nocase(str, "rgb16") == 0 || cmp_nocase(str, "r16g16b16") == 0) {
@@ -5745,6 +5754,7 @@ do_set_format(CData *cdata, Texture::Format format) {
   case F_alpha:
   case F_alpha:
   case F_luminance:
   case F_luminance:
   case F_r16:
   case F_r16:
+  case F_r16i:
   case F_sluminance:
   case F_sluminance:
   case F_r32i:
   case F_r32i:
   case F_r32:
   case F_r32:
@@ -8663,8 +8673,19 @@ do_write_datagram_header(CData *cdata, BamWriter *manager, Datagram &me, bool &h
   me.add_uint8(cdata->_primary_file_num_channels);
   me.add_uint8(cdata->_primary_file_num_channels);
   me.add_uint8(cdata->_alpha_file_channel);
   me.add_uint8(cdata->_alpha_file_channel);
   me.add_bool(has_rawdata);
   me.add_bool(has_rawdata);
-  me.add_uint8(cdata->_texture_type);
-  me.add_bool(cdata->_has_read_mipmaps);
+
+  if (manager->get_file_minor_ver() < 25 &&
+      cdata->_texture_type == TT_cube_map) {
+    // Between Panda3D releases 1.7.2 and 1.8.0 (bam versions 6.24 and 6.25),
+    // we added TT_2d_texture_array, shifting the definition for TT_cube_map.
+    me.add_uint8(TT_2d_texture_array);
+  } else {
+    me.add_uint8(cdata->_texture_type);
+  }
+
+  if (manager->get_file_minor_ver() >= 32) {
+    me.add_bool(cdata->_has_read_mipmaps);
+  }
 }
 }
 
 
 /**
 /**
@@ -8673,7 +8694,18 @@ do_write_datagram_header(CData *cdata, BamWriter *manager, Datagram &me, bool &h
  */
  */
 void Texture::
 void Texture::
 do_write_datagram_body(CData *cdata, BamWriter *manager, Datagram &me) {
 do_write_datagram_body(CData *cdata, BamWriter *manager, Datagram &me) {
-  cdata->_default_sampler.write_datagram(me);
+  if (manager->get_file_minor_ver() >= 36) {
+    cdata->_default_sampler.write_datagram(me);
+  } else {
+    const SamplerState &s = cdata->_default_sampler;
+    me.add_uint8(s.get_wrap_u());
+    me.add_uint8(s.get_wrap_v());
+    me.add_uint8(s.get_wrap_w());
+    me.add_uint8(s.get_minfilter());
+    me.add_uint8(s.get_magfilter());
+    me.add_int16(s.get_anisotropic_degree());
+    s.get_border_color().write_datagram(me);
+  }
 
 
   me.add_uint8(cdata->_compression);
   me.add_uint8(cdata->_compression);
   me.add_uint8(cdata->_quality_level);
   me.add_uint8(cdata->_quality_level);
@@ -8685,7 +8717,9 @@ do_write_datagram_body(CData *cdata, BamWriter *manager, Datagram &me) {
     me.add_uint8(cdata->_usage_hint);
     me.add_uint8(cdata->_usage_hint);
   }
   }
 
 
-  me.add_uint8(cdata->_auto_texture_scale);
+  if (manager->get_file_minor_ver() >= 28) {
+    me.add_uint8(cdata->_auto_texture_scale);
+  }
   me.add_uint32(cdata->_orig_file_x_size);
   me.add_uint32(cdata->_orig_file_x_size);
   me.add_uint32(cdata->_orig_file_y_size);
   me.add_uint32(cdata->_orig_file_y_size);
 
 
@@ -8711,11 +8745,15 @@ do_write_datagram_rawdata(CData *cdata, BamWriter *manager, Datagram &me) {
   me.add_uint32(cdata->_y_size);
   me.add_uint32(cdata->_y_size);
   me.add_uint32(cdata->_z_size);
   me.add_uint32(cdata->_z_size);
 
 
-  me.add_uint32(cdata->_pad_x_size);
-  me.add_uint32(cdata->_pad_y_size);
-  me.add_uint32(cdata->_pad_z_size);
+  if (manager->get_file_minor_ver() >= 30) {
+    me.add_uint32(cdata->_pad_x_size);
+    me.add_uint32(cdata->_pad_y_size);
+    me.add_uint32(cdata->_pad_z_size);
+  }
 
 
-  me.add_uint32(cdata->_num_views);
+  if (manager->get_file_minor_ver() >= 26) {
+    me.add_uint32(cdata->_num_views);
+  }
   me.add_uint8(cdata->_component_type);
   me.add_uint8(cdata->_component_type);
   me.add_uint8(cdata->_component_width);
   me.add_uint8(cdata->_component_width);
   me.add_uint8(cdata->_ram_image_compression);
   me.add_uint8(cdata->_ram_image_compression);

+ 1 - 0
panda/src/gobj/texture.h

@@ -159,6 +159,7 @@ PUBLISHED:
     F_rgb10_a2,
     F_rgb10_a2,
 
 
     F_rg,
     F_rg,
+    F_r16i
   };
   };
 
 
   // Deprecated.  See SamplerState.FilterType.
   // Deprecated.  See SamplerState.FilterType.

+ 4 - 1
panda/src/gobj/textureStage.cxx

@@ -438,7 +438,10 @@ write_datagram(BamWriter *manager, Datagram &me) {
     me.add_uint8(_rgb_scale);
     me.add_uint8(_rgb_scale);
     me.add_uint8(_alpha_scale);
     me.add_uint8(_alpha_scale);
     me.add_bool(_saved_result);
     me.add_bool(_saved_result);
-    me.add_int32(_tex_view_offset);
+
+    if (manager->get_file_minor_ver() >= 26) {
+      me.add_int32(_tex_view_offset);
+    }
 
 
     me.add_uint8(_combine_rgb_mode);
     me.add_uint8(_combine_rgb_mode);
     me.add_uint8(_num_combine_rgb_operands);
     me.add_uint8(_num_combine_rgb_operands);

+ 4 - 1
panda/src/grutil/movieTexture.cxx

@@ -816,7 +816,10 @@ do_write_datagram_rawdata(Texture::CData *cdata_tex, BamWriter *manager, Datagra
   CDReader cdata(_cycler);
   CDReader cdata(_cycler);
 
 
   dg.add_uint16(cdata_tex->_z_size);
   dg.add_uint16(cdata_tex->_z_size);
-  dg.add_uint16(cdata_tex->_num_views);
+  if (manager->get_file_minor_ver() >= 26) {
+    dg.add_uint16(cdata_tex->_num_views);
+  }
+
   nassertv(cdata->_pages.size() == (size_t)(cdata_tex->_z_size * cdata_tex->_num_views));
   nassertv(cdata->_pages.size() == (size_t)(cdata_tex->_z_size * cdata_tex->_num_views));
   for (size_t n = 0; n < cdata->_pages.size(); ++n) {
   for (size_t n = 0; n < cdata->_pages.size(); ++n) {
     const VideoPage &page = cdata->_pages[n];
     const VideoPage &page = cdata->_pages[n];

+ 11 - 9
panda/src/grutil/shaderTerrainMesh.I

@@ -12,26 +12,28 @@
  */
  */
 
 
 /**
 /**
- * @brief Sets the path to the heightfield
- * @details This sets the path to the terrain heightfield. It should be 16bit
+ * @brief Sets the heightfield texture
+ * @details This sets the heightfield texture. It should be 16bit
  *   single channel, and have a power-of-two resolution greater than 32.
  *   single channel, and have a power-of-two resolution greater than 32.
  *   Common sizes are 2048x2048 or 4096x4096.
  *   Common sizes are 2048x2048 or 4096x4096.
  *
  *
- * @param filename Path to the heightfield
+ *   You should call generate() after setting the heightfield.
+ *
+ * @param filename Heightfield texture
  */
  */
-INLINE void ShaderTerrainMesh::set_heightfield_filename(const Filename& filename) {
-  _heightfield_source = filename;
+INLINE void ShaderTerrainMesh::set_heightfield(Texture* heightfield) {
+  _heightfield_tex = heightfield;
 }
 }
 
 
 /**
 /**
- * @brief Returns the heightfield path
- * @details This returns the path of the terrain heightfield, previously set with
+ * @brief Returns the heightfield
+ * @details This returns the terrain heightfield, previously set with
  *   set_heightfield()
  *   set_heightfield()
  *
  *
  * @return Path to the heightfield
  * @return Path to the heightfield
  */
  */
-INLINE const Filename& ShaderTerrainMesh::get_heightfield_filename() const {
-  return _heightfield_source;
+INLINE Texture* ShaderTerrainMesh::get_heightfield() const {
+  return _heightfield_tex;
 }
 }
 
 
 /**
 /**

+ 28 - 34
panda/src/grutil/shaderTerrainMesh.cxx

@@ -35,7 +35,7 @@
 #include "typeHandle.h"
 #include "typeHandle.h"
 
 
 ConfigVariableBool stm_use_hexagonal_layout
 ConfigVariableBool stm_use_hexagonal_layout
-("stm-use-hexagonal-layout", true,
+("stm-use-hexagonal-layout", false,
  PRC_DESC("Set this to true to use a hexagonal vertex layout. This approximates "
  PRC_DESC("Set this to true to use a hexagonal vertex layout. This approximates "
           "the heightfield in a better way, however the CLOD transitions might be "
           "the heightfield in a better way, however the CLOD transitions might be "
           "visible due to the vertices not matching exactly."));
           "visible due to the vertices not matching exactly."));
@@ -81,7 +81,6 @@ ShaderTerrainMesh::ShaderTerrainMesh() :
   PandaNode("ShaderTerrainMesh"),
   PandaNode("ShaderTerrainMesh"),
   _size(0),
   _size(0),
   _chunk_size(32),
   _chunk_size(32),
-  _heightfield_source(""),
   _generate_patches(false),
   _generate_patches(false),
   _data_texture(NULL),
   _data_texture(NULL),
   _chunk_geom(NULL),
   _chunk_geom(NULL),
@@ -107,7 +106,7 @@ ShaderTerrainMesh::ShaderTerrainMesh() :
  * @return true if the terrain was initialized, false if an error occured
  * @return true if the terrain was initialized, false if an error occured
  */
  */
 bool ShaderTerrainMesh::generate() {
 bool ShaderTerrainMesh::generate() {
-  if (!do_load_heightfield())
+  if (!do_check_heightfield())
     return false;
     return false;
 
 
   if (_chunk_size < 8 || !check_power_of_two(_chunk_size)) {
   if (_chunk_size < 8 || !check_power_of_two(_chunk_size)) {
@@ -120,28 +119,29 @@ bool ShaderTerrainMesh::generate() {
     return false;
     return false;
   }
   }
 
 
+  do_extract_heightfield();
   do_create_chunks();
   do_create_chunks();
   do_compute_bounds(&_base_chunk);
   do_compute_bounds(&_base_chunk);
   do_create_chunk_geom();
   do_create_chunk_geom();
   do_init_data_texture();
   do_init_data_texture();
-  do_convert_heightfield();
+
+  // Clear image after using it, otherwise we have two copies of the heightfield
+  // in memory.
+  _heightfield.clear();
 
 
   return true;
   return true;
 }
 }
 
 
 /**
 /**
- * @brief Converts the internal used PNMImage to a Texture
- * @details This converts the internal used PNMImage to a texture object. The
- *   reason for this is, that we need the PNMimage for computing the chunk
- *   bounds, but don't need it afterwards. However, since we have it in ram,
- *   we can just put its contents into a Texture object, which enables the
- *   user to call get_heightfield() instead of manually loading the texture
- *   from disk again to set it as shader input (Panda does not cache PNMImages)
+ * @brief Converts the internal used Texture to a PNMImage
+ * @details This converts the texture passed with set_heightfield to a PNMImage,
+ *   so we can read the pixels in a fast way. This is only used while generating
+ *   the chunks, and the PNMImage is destroyed afterwards.
  */
  */
-void ShaderTerrainMesh::do_convert_heightfield() {
-  _heightfield_tex = new Texture();
-  _heightfield_tex->load(_heightfield);
-  _heightfield_tex->set_keep_ram_image(true);
+void ShaderTerrainMesh::do_extract_heightfield() {
+  nassertv(_heightfield_tex->has_ram_image()); // Heightfield not in RAM, extract ram image first
+
+  _heightfield_tex->store(_heightfield);
 
 
   if (_heightfield.get_maxval() != 65535) {
   if (_heightfield.get_maxval() != 65535) {
     shader_terrain_cat.warning() << "Using non 16-bit heightfield!" << endl;
     shader_terrain_cat.warning() << "Using non 16-bit heightfield!" << endl;
@@ -150,31 +150,23 @@ void ShaderTerrainMesh::do_convert_heightfield() {
   }
   }
   _heightfield_tex->set_minfilter(SamplerState::FT_linear);
   _heightfield_tex->set_minfilter(SamplerState::FT_linear);
   _heightfield_tex->set_magfilter(SamplerState::FT_linear);
   _heightfield_tex->set_magfilter(SamplerState::FT_linear);
-  _heightfield.clear();
 }
 }
 
 
 /**
 /**
- * @brief Intermal method to load the heightfield
- * @details This method loads the heightfield from the heightfield path,
+ * @brief Intermal method to check the heightfield
+ * @details This method cecks the heightfield generated from the heightfield texture,
  *   and performs some basic checks, including a check for a power of two,
  *   and performs some basic checks, including a check for a power of two,
  *   and same width and height.
  *   and same width and height.
  *
  *
- * @return true if the heightfield was loaded and meets the requirements
+ * @return true if the heightfield meets the requirements
  */
  */
-bool ShaderTerrainMesh::do_load_heightfield() {
-
-  if(!_heightfield.read(_heightfield_source)) {
-    shader_terrain_cat.error() << "Could not load heightfield from " << _heightfield_source << endl;
-    return false;
-  }
-
-  if (_heightfield.get_x_size() != _heightfield.get_y_size()) {
+bool ShaderTerrainMesh::do_check_heightfield() {
+  if (_heightfield_tex->get_x_size() != _heightfield_tex->get_y_size()) {
     shader_terrain_cat.error() << "Only square heightfields are supported!";
     shader_terrain_cat.error() << "Only square heightfields are supported!";
     return false;
     return false;
   }
   }
 
 
-  _size = _heightfield.get_x_size();
-
+  _size = _heightfield_tex->get_x_size();
   if (_size < 32 || !check_power_of_two(_size)) {
   if (_size < 32 || !check_power_of_two(_size)) {
     shader_terrain_cat.error() << "Invalid heightfield! Needs to be >= 32 and a power of two (was: "
     shader_terrain_cat.error() << "Invalid heightfield! Needs to be >= 32 and a power of two (was: "
          << _size << ")!" << endl;
          << _size << ")!" << endl;
@@ -383,8 +375,8 @@ void ShaderTerrainMesh::do_create_chunk_geom() {
       // Stitched vertices at the cornders
       // Stitched vertices at the cornders
       if (x == -1 || y == -1 || x == size + 1 || y == size + 1) {
       if (x == -1 || y == -1 || x == size + 1 || y == size + 1) {
         vtx_pos.set_z(-1.0f / (PN_stdfloat)size);
         vtx_pos.set_z(-1.0f / (PN_stdfloat)size);
-        vtx_pos.set_x(max(0.0f, min(1.0f, vtx_pos.get_x())));
-        vtx_pos.set_y(max(0.0f, min(1.0f, vtx_pos.get_y())));
+        vtx_pos.set_x(max((PN_stdfloat)0, min((PN_stdfloat)1, vtx_pos.get_x())));
+        vtx_pos.set_y(max((PN_stdfloat)0, min((PN_stdfloat)1, vtx_pos.get_y())));
       }
       }
       vertex_writer.add_data3(vtx_pos);
       vertex_writer.add_data3(vtx_pos);
     }
     }
@@ -687,8 +679,8 @@ void ShaderTerrainMesh::do_emit_chunk(Chunk* chunk, TraversalData* data) {
   data_entry.size = chunk->size / _chunk_size;
   data_entry.size = chunk->size / _chunk_size;
   data_entry.clod = chunk->last_clod;
   data_entry.clod = chunk->last_clod;
 
 
-  data->emitted_chunks ++;
-  data->storage_ptr ++;
+  data->emitted_chunks++;
+  data->storage_ptr++;
 }
 }
 
 
 /**
 /**
@@ -701,7 +693,9 @@ void ShaderTerrainMesh::do_emit_chunk(Chunk* chunk, TraversalData* data) {
  * @return World-Space point
  * @return World-Space point
  */
  */
 LPoint3 ShaderTerrainMesh::uv_to_world(const LTexCoord& coord) const {
 LPoint3 ShaderTerrainMesh::uv_to_world(const LTexCoord& coord) const {
-  nassertr(_heightfield_tex != NULL, LPoint3(0));
+  nassertr(_heightfield_tex != NULL, LPoint3(0)); // Heightfield not set yet
+  nassertr(_heightfield_tex->has_ram_image(), LPoint3(0)); // Heightfield not in memory
+
   PT(TexturePeeker) peeker = _heightfield_tex->peek();
   PT(TexturePeeker) peeker = _heightfield_tex->peek();
   nassertr(peeker != NULL, LPoint3(0));
   nassertr(peeker != NULL, LPoint3(0));
 
 

+ 5 - 6
panda/src/grutil/shaderTerrainMesh.h

@@ -55,9 +55,9 @@ PUBLISHED:
 
 
   ShaderTerrainMesh();
   ShaderTerrainMesh();
 
 
-  INLINE void set_heightfield_filename(const Filename& filename);
-  INLINE const Filename& get_heightfield_filename() const;
-  MAKE_PROPERTY(heightfield_filename, get_heightfield_filename, set_heightfield_filename);
+  INLINE void set_heightfield(Texture* heightfield);
+  INLINE Texture* get_heightfield() const;
+  MAKE_PROPERTY(heightfield, get_heightfield, set_heightfield);
 
 
   INLINE void set_chunk_size(size_t chunk_size);
   INLINE void set_chunk_size(size_t chunk_size);
   INLINE size_t get_chunk_size() const;
   INLINE size_t get_chunk_size() const;
@@ -152,8 +152,8 @@ private:
     ChunkDataEntry* storage_ptr;
     ChunkDataEntry* storage_ptr;
   };
   };
 
 
-  bool do_load_heightfield();
-  void do_convert_heightfield();
+  bool do_check_heightfield();
+  void do_extract_heightfield();
   void do_init_data_texture();
   void do_init_data_texture();
   void do_create_chunks();
   void do_create_chunks();
   void do_init_chunk(Chunk* chunk);
   void do_init_chunk(Chunk* chunk);
@@ -164,7 +164,6 @@ private:
   bool do_check_lod_matches(Chunk* chunk, TraversalData* data);
   bool do_check_lod_matches(Chunk* chunk, TraversalData* data);
 
 
   Chunk _base_chunk;
   Chunk _base_chunk;
-  Filename _heightfield_source;
   size_t _size;
   size_t _size;
   size_t _chunk_size;
   size_t _chunk_size;
   bool _generate_patches;
   bool _generate_patches;

+ 3 - 3
panda/src/movies/dr_flac.h

@@ -92,7 +92,7 @@
 
 
 #include <stddef.h>
 #include <stddef.h>
 #include <stdint.h>
 #include <stdint.h>
-#include <stdbool.h>
+//#include <stdbool.h>
 
 
 // As data is read from the client it is placed into an internal buffer for fast access. This controls the
 // As data is read from the client it is placed into an internal buffer for fast access. This controls the
 // size of that buffer. Larger values means more speed, but also more memory. In my testing there is diminishing
 // size of that buffer. Larger values means more speed, but also more memory. In my testing there is diminishing
@@ -2244,7 +2244,7 @@ done_reading_block_header:
     }
     }
 
 
     if (pIsLastBlockOut) {
     if (pIsLastBlockOut) {
-        *pIsLastBlockOut = isLastBlock;
+        *pIsLastBlockOut = (isLastBlock != 0);
     }
     }
 
 
     return blockType;
     return blockType;
@@ -2350,7 +2350,7 @@ static bool drflac__seek_to_sample__brute_force(drflac* pFlac, uint64_t sampleIn
         return false;
         return false;
     }
     }
 
 
-    return drflac_read_s16(pFlac, samplesToDecode, NULL);
+    return (drflac_read_s16(pFlac, samplesToDecode, NULL) != 0);
 }
 }
 
 
 static bool drflac__seek_to_sample__seek_table(drflac* pFlac, uint64_t sampleIndex)
 static bool drflac__seek_to_sample__seek_table(drflac* pFlac, uint64_t sampleIndex)

+ 18 - 4
panda/src/pgraph/clipPlaneAttrib.cxx

@@ -872,18 +872,32 @@ write_datagram(BamWriter *manager, Datagram &dg) {
 
 
   // write the number of off_planes
   // write the number of off_planes
   dg.add_uint16(get_num_off_planes());
   dg.add_uint16(get_num_off_planes());
+
   // write the off planes pointers if any
   // write the off planes pointers if any
   Planes::const_iterator fi;
   Planes::const_iterator fi;
-  for (fi = _off_planes.begin(); fi != _off_planes.end(); ++fi) {
-    (*fi).write_datagram(manager, dg);
+  if (manager->get_file_minor_ver() < 40) {
+    for (fi = _off_planes.begin(); fi != _off_planes.end(); ++fi) {
+      manager->write_pointer(dg, fi->node());
+    }
+  } else {
+    for (fi = _off_planes.begin(); fi != _off_planes.end(); ++fi) {
+      (*fi).write_datagram(manager, dg);
+    }
   }
   }
 
 
   // write the number of on planes
   // write the number of on planes
   dg.add_uint16(get_num_on_planes());
   dg.add_uint16(get_num_on_planes());
+
   // write the on planes pointers if any
   // write the on planes pointers if any
   Planes::const_iterator nti;
   Planes::const_iterator nti;
-  for (nti = _on_planes.begin(); nti != _on_planes.end(); ++nti) {
-    (*nti).write_datagram(manager, dg);
+  if (manager->get_file_minor_ver() < 40) {
+    for (nti = _on_planes.begin(); nti != _on_planes.end(); ++nti) {
+      manager->write_pointer(dg, nti->node());
+    }
+  } else {
+    for (nti = _on_planes.begin(); nti != _on_planes.end(); ++nti) {
+      (*nti).write_datagram(manager, dg);
+    }
   }
   }
 }
 }
 
 

+ 4 - 2
panda/src/pgraph/depthOffsetAttrib.cxx

@@ -162,8 +162,10 @@ write_datagram(BamWriter *manager, Datagram &dg) {
   RenderAttrib::write_datagram(manager, dg);
   RenderAttrib::write_datagram(manager, dg);
 
 
   dg.add_int32(_offset);
   dg.add_int32(_offset);
-  dg.add_stdfloat(_min_value);
-  dg.add_stdfloat(_max_value);
+  if (manager->get_file_minor_ver() >= 31) {
+    dg.add_stdfloat(_min_value);
+    dg.add_stdfloat(_max_value);
+  }
 }
 }
 
 
 /**
 /**

+ 7 - 3
panda/src/pgraph/light.cxx

@@ -206,9 +206,13 @@ fill_viz_geom(GeomNode *) {
  */
  */
 void Light::
 void Light::
 write_datagram(BamWriter *manager, Datagram &dg) {
 write_datagram(BamWriter *manager, Datagram &dg) {
-  dg.add_bool(_has_color_temperature);
-  if (_has_color_temperature) {
-    dg.add_stdfloat(_color_temperature);
+  if (manager->get_file_minor_ver() >= 39) {
+    dg.add_bool(_has_color_temperature);
+    if (_has_color_temperature) {
+      dg.add_stdfloat(_color_temperature);
+    } else {
+      manager->write_cdata(dg, _cycler);
+    }
   } else {
   } else {
     manager->write_cdata(dg, _cycler);
     manager->write_cdata(dg, _cycler);
   }
   }

+ 17 - 4
panda/src/pgraph/lightAttrib.cxx

@@ -898,18 +898,31 @@ write_datagram(BamWriter *manager, Datagram &dg) {
 
 
   // write the number of off_lights
   // write the number of off_lights
   dg.add_uint16(get_num_off_lights());
   dg.add_uint16(get_num_off_lights());
+
   // write the off lights pointers if any
   // write the off lights pointers if any
   Lights::const_iterator fi;
   Lights::const_iterator fi;
-  for (fi = _off_lights.begin(); fi != _off_lights.end(); ++fi) {
-    (*fi).write_datagram(manager, dg);
+  if (manager->get_file_minor_ver() < 40) {
+    for (fi = _off_lights.begin(); fi != _off_lights.end(); ++fi) {
+      manager->write_pointer(dg, fi->node());
+    }
+  } else {
+    for (fi = _off_lights.begin(); fi != _off_lights.end(); ++fi) {
+      (*fi).write_datagram(manager, dg);
+    }
   }
   }
 
 
   // write the number of on lights
   // write the number of on lights
   dg.add_uint16(get_num_on_lights());
   dg.add_uint16(get_num_on_lights());
   // write the on lights pointers if any
   // write the on lights pointers if any
   Lights::const_iterator nti;
   Lights::const_iterator nti;
-  for (nti = _on_lights.begin(); nti != _on_lights.end(); ++nti) {
-    (*nti).write_datagram(manager, dg);
+  if (manager->get_file_minor_ver() < 40) {
+    for (nti = _on_lights.begin(); nti != _on_lights.end(); ++nti) {
+      manager->write_pointer(dg, nti->node());
+    }
+  } else {
+    for (nti = _on_lights.begin(); nti != _on_lights.end(); ++nti) {
+      (*nti).write_datagram(manager, dg);
+    }
   }
   }
 }
 }
 
 

+ 8 - 8
panda/src/pgraph/loader.cxx

@@ -140,10 +140,10 @@ load_file(const Filename &filename, const LoaderOptions &options) const {
     extension = this_filename.get_extension();
     extension = this_filename.get_extension();
   }
   }
 
 
-  bool pz_file = false;
+  bool compressed = false;
 #ifdef HAVE_ZLIB
 #ifdef HAVE_ZLIB
-  if (extension == "pz") {
-    pz_file = true;
+  if (extension == "pz" || extension == "gz") {
+    compressed = true;
     extension = Filename(this_filename.get_basename_wo_extension()).get_extension();
     extension = Filename(this_filename.get_basename_wo_extension()).get_extension();
   }
   }
 #endif  // HAVE_ZLIB
 #endif  // HAVE_ZLIB
@@ -182,7 +182,7 @@ load_file(const Filename &filename, const LoaderOptions &options) const {
         << extension << ") does not support loading.\n";
         << extension << ") does not support loading.\n";
     }
     }
     return NULL;
     return NULL;
-  } else if (pz_file && !requested_type->supports_compressed()) {
+  } else if (compressed && !requested_type->supports_compressed()) {
     if (report_errors) {
     if (report_errors) {
       loader_cat.error()
       loader_cat.error()
         << requested_type->get_name() << " file type (."
         << requested_type->get_name() << " file type (."
@@ -382,10 +382,10 @@ save_file(const Filename &filename, const LoaderOptions &options,
     extension = this_filename.get_extension();
     extension = this_filename.get_extension();
   }
   }
 
 
-  bool pz_file = false;
+  bool compressed = false;
 #ifdef HAVE_ZLIB
 #ifdef HAVE_ZLIB
-  if (extension == "pz") {
-    pz_file = true;
+  if (extension == "pz" || extension == "gz") {
+    compressed = true;
     extension = Filename(this_filename.get_basename_wo_extension()).get_extension();
     extension = Filename(this_filename.get_basename_wo_extension()).get_extension();
   }
   }
 #endif  // HAVE_ZLIB
 #endif  // HAVE_ZLIB
@@ -422,7 +422,7 @@ save_file(const Filename &filename, const LoaderOptions &options,
     }
     }
     return false;
     return false;
 
 
-  } else if (pz_file && !requested_type->supports_compressed()) {
+  } else if (compressed && !requested_type->supports_compressed()) {
     if (report_errors) {
     if (report_errors) {
       loader_cat.error()
       loader_cat.error()
         << requested_type->get_name() << " file type (."
         << requested_type->get_name() << " file type (."

+ 1 - 1
panda/src/pgraph/loaderFileType.cxx

@@ -48,7 +48,7 @@ get_additional_extensions() const {
 
 
 /**
 /**
  * Returns true if this file type can transparently load compressed files
  * Returns true if this file type can transparently load compressed files
- * (with a .pz extension), false otherwise.
+ * (with a .pz or .gz extension), false otherwise.
  */
  */
 bool LoaderFileType::
 bool LoaderFileType::
 supports_compressed() const {
 supports_compressed() const {

+ 1 - 1
panda/src/pgraph/loaderFileTypeBam.cxx

@@ -47,7 +47,7 @@ get_extension() const {
 
 
 /**
 /**
  * Returns true if this file type can transparently load compressed files
  * Returns true if this file type can transparently load compressed files
- * (with a .pz extension), false otherwise.
+ * (with a .pz or .gz extension), false otherwise.
  */
  */
 bool LoaderFileTypeBam::
 bool LoaderFileTypeBam::
 supports_compressed() const {
 supports_compressed() const {

+ 9 - 2
panda/src/pgraph/occluderEffect.cxx

@@ -146,10 +146,17 @@ write_datagram(BamWriter *manager, Datagram &dg) {
 
 
   // write the number of on occluders
   // write the number of on occluders
   dg.add_uint16(get_num_on_occluders());
   dg.add_uint16(get_num_on_occluders());
+
   // write the on occluders pointers if any
   // write the on occluders pointers if any
   Occluders::const_iterator nti;
   Occluders::const_iterator nti;
-  for (nti = _on_occluders.begin(); nti != _on_occluders.end(); ++nti) {
-    (*nti).write_datagram(manager, dg);
+  if (manager->get_file_minor_ver() < 40) {
+    for (nti = _on_occluders.begin(); nti != _on_occluders.end(); ++nti) {
+      manager->write_pointer(dg, nti->node());
+    }
+  } else {
+    for (nti = _on_occluders.begin(); nti != _on_occluders.end(); ++nti) {
+      (*nti).write_datagram(manager, dg);
+    }
   }
   }
 }
 }
 
 

+ 12 - 1
panda/src/pgraph/paramNodePath.cxx

@@ -40,7 +40,18 @@ register_with_read_factory() {
 void ParamNodePath::
 void ParamNodePath::
 write_datagram(BamWriter *manager, Datagram &dg) {
 write_datagram(BamWriter *manager, Datagram &dg) {
   ParamValueBase::write_datagram(manager, dg);
   ParamValueBase::write_datagram(manager, dg);
-  _node_path.write_datagram(manager, dg);
+
+  if (manager->get_file_minor_ver() < 40) {
+    // Before bam 6.40, we did not support writing NodePaths.  Instaed, we
+    // write the PandaNode pointer and pray there is an unambiguous path.
+    if (_node_path.is_empty()) {
+      manager->write_pointer(dg, NULL);
+    } else {
+      manager->write_pointer(dg, _node_path.node());
+    }
+  } else {
+    _node_path.write_datagram(manager, dg);
+  }
 }
 }
 
 
 /**
 /**

+ 3 - 1
panda/src/pgraph/scissorAttrib.cxx

@@ -177,7 +177,9 @@ write_datagram(BamWriter *manager, Datagram &dg) {
   RenderAttrib::write_datagram(manager, dg);
   RenderAttrib::write_datagram(manager, dg);
 
 
   _frame.write_datagram(dg);
   _frame.write_datagram(dg);
-  dg.add_bool(_off);
+  if (manager->get_file_minor_ver() >= 34) {
+    dg.add_bool(_off);
+  }
 }
 }
 
 
 /**
 /**

+ 20 - 2
panda/src/pgraph/stencilAttrib.cxx

@@ -338,8 +338,26 @@ void StencilAttrib::
 write_datagram(BamWriter *manager, Datagram &dg) {
 write_datagram(BamWriter *manager, Datagram &dg) {
   RenderAttrib::write_datagram(manager, dg);
   RenderAttrib::write_datagram(manager, dg);
 
 
-  for (int index = 0; index < SRS_total; ++index) {
-    dg.add_uint32(_stencil_render_states[index]);
+  if (manager->get_file_minor_ver() < 35) {
+    dg.add_int32(_stencil_render_states[SRS_front_comparison_function] != M_none);
+    dg.add_int32(_stencil_render_states[SRS_back_comparison_function] != M_none);
+
+    for (int index = 0; index < SRS_total; ++index) {
+      if (index == SRS_front_comparison_function ||
+          index == SRS_back_comparison_function) {
+        if (_stencil_render_states[index] == M_none) {
+          dg.add_uint32(7);
+        } else {
+          dg.add_uint32(_stencil_render_states[index] - 1);
+        }
+      } else {
+        dg.add_uint32(_stencil_render_states[index]);
+      }
+    }
+  } else {
+    for (int index = 0; index < SRS_total; ++index) {
+      dg.add_uint32(_stencil_render_states[index]);
+    }
   }
   }
 }
 }
 
 

+ 4 - 1
panda/src/pgraph/texMatrixAttrib.cxx

@@ -461,7 +461,10 @@ write_datagram(BamWriter *manager, Datagram &dg) {
 
 
     manager->write_pointer(dg, sn._stage);
     manager->write_pointer(dg, sn._stage);
     manager->write_pointer(dg, sn._transform);
     manager->write_pointer(dg, sn._transform);
-    dg.add_int32(sn._override);
+
+    if (manager->get_file_minor_ver() >= 24) {
+      dg.add_int32(sn._override);
+    }
   }
   }
 }
 }
 
 

+ 10 - 4
panda/src/pgraph/textureAttrib.cxx

@@ -778,10 +778,16 @@ write_datagram(BamWriter *manager, Datagram &dg) {
     manager->write_pointer(dg, stage);
     manager->write_pointer(dg, stage);
     manager->write_pointer(dg, tex);
     manager->write_pointer(dg, tex);
     dg.add_uint16((*si)._implicit_sort);
     dg.add_uint16((*si)._implicit_sort);
-    dg.add_int32((*si)._override);
-    dg.add_bool((*si)._has_sampler);
-    if ((*si)._has_sampler) {
-      (*si)._sampler.write_datagram(dg);
+
+    if (manager->get_file_minor_ver() >= 23) {
+      dg.add_int32((*si)._override);
+    }
+
+    if (manager->get_file_minor_ver() >= 36) {
+      dg.add_bool((*si)._has_sampler);
+      if ((*si)._has_sampler) {
+        (*si)._sampler.write_datagram(dg);
+      }
     }
     }
   }
   }
 }
 }

+ 3 - 1
panda/src/pgraphnodes/directionalLight.cxx

@@ -167,7 +167,9 @@ register_with_read_factory() {
 void DirectionalLight::
 void DirectionalLight::
 write_datagram(BamWriter *manager, Datagram &dg) {
 write_datagram(BamWriter *manager, Datagram &dg) {
   LightLensNode::write_datagram(manager, dg);
   LightLensNode::write_datagram(manager, dg);
-  dg.add_bool(_has_specular_color);
+  if (manager->get_file_minor_ver() >= 39) {
+    dg.add_bool(_has_specular_color);
+  }
   manager->write_cdata(dg, _cycler);
   manager->write_cdata(dg, _cycler);
 }
 }
 
 

+ 3 - 1
panda/src/pgraphnodes/pointLight.cxx

@@ -196,7 +196,9 @@ register_with_read_factory() {
 void PointLight::
 void PointLight::
 write_datagram(BamWriter *manager, Datagram &dg) {
 write_datagram(BamWriter *manager, Datagram &dg) {
   LightLensNode::write_datagram(manager, dg);
   LightLensNode::write_datagram(manager, dg);
-  dg.add_bool(_has_specular_color);
+  if (manager->get_file_minor_ver() >= 39) {
+    dg.add_bool(_has_specular_color);
+  }
   manager->write_cdata(dg, _cycler);
   manager->write_cdata(dg, _cycler);
 }
 }
 
 

+ 3 - 1
panda/src/pgraphnodes/spotlight.cxx

@@ -252,7 +252,9 @@ register_with_read_factory() {
 void Spotlight::
 void Spotlight::
 write_datagram(BamWriter *manager, Datagram &dg) {
 write_datagram(BamWriter *manager, Datagram &dg) {
   LightLensNode::write_datagram(manager, dg);
   LightLensNode::write_datagram(manager, dg);
-  dg.add_bool(_has_specular_color);
+  if (manager->get_file_minor_ver() >= 39) {
+    dg.add_bool(_has_specular_color);
+  }
   manager->write_cdata(dg, _cycler);
   manager->write_cdata(dg, _cycler);
 }
 }
 
 

+ 6 - 2
panda/src/pgraphnodes/uvScrollNode.cxx

@@ -53,8 +53,12 @@ write_datagram(BamWriter *manager, Datagram &dg) {
   PandaNode::write_datagram(manager, dg);
   PandaNode::write_datagram(manager, dg);
   dg.add_stdfloat(_u_speed);
   dg.add_stdfloat(_u_speed);
   dg.add_stdfloat(_v_speed);
   dg.add_stdfloat(_v_speed);
-  dg.add_stdfloat(_w_speed);
-  dg.add_stdfloat(_r_speed);
+  if (manager->get_file_minor_ver() >= 33) {
+    dg.add_stdfloat(_w_speed);
+  }
+  if (manager->get_file_minor_ver() >= 22) {
+    dg.add_stdfloat(_r_speed);
+  }
 }
 }
 
 
 /**
 /**

+ 1 - 1
panda/src/pnmimage/pnmFileTypeRegistry.cxx

@@ -127,7 +127,7 @@ get_type_from_extension(const string &filename) const {
   }
   }
 
 
 #ifdef HAVE_ZLIB
 #ifdef HAVE_ZLIB
-  if (extension == "pz") {
+  if (extension == "pz" || extension == "gz") {
     // If the extension is .pz, then we've got a Panda-compressed image file.
     // If the extension is .pz, then we've got a Panda-compressed image file.
     // Back up some more and get the extension before that.
     // Back up some more and get the extension before that.
     size_t prev_dot = filename.rfind('.', dot - 1);
     size_t prev_dot = filename.rfind('.', dot - 1);

+ 3 - 2
panda/src/pnmimage/pnmImageHeader.cxx

@@ -181,7 +181,8 @@ make_reader(istream *file, bool owns_file, const Filename &filename,
           << type->get_name() << ".\n";
           << type->get_name() << ".\n";
       } else {
       } else {
         pnmimage_cat.debug()
         pnmimage_cat.debug()
-          << "Unable to guess image file type from its extension.\n";
+          << "Unable to guess image file type from its extension ("
+          << filename.get_extension() << ").\n";
       }
       }
     }
     }
   }
   }
@@ -342,7 +343,7 @@ make_writer(ostream *file, bool owns_file, const Filename &filename,
     delete file;
     delete file;
   }
   }
 
 
-  if (!writer->is_valid()) {
+  if (writer != NULL && !writer->is_valid()) {
     delete writer;
     delete writer;
     writer = NULL;
     writer = NULL;
   }
   }

+ 10 - 0
panda/src/putil/bamWriter.I

@@ -42,6 +42,16 @@ get_file_major_ver() const {
   return _file_major;
   return _file_major;
 }
 }
 
 
+/**
+ * Changes the minor .bam version to write.  This should be called before
+ * init().  Each Panda version has only a fairly narrow range of versions it
+ * is able to write; consult the .bam documentation for more information.
+ */
+INLINE void BamWriter::
+set_file_minor_ver(int minor_ver) {
+  _file_minor = minor_ver;
+}
+
 /**
 /**
  * Returns the minor version number of the Bam file currently being written.
  * Returns the minor version number of the Bam file currently being written.
  */
  */

+ 48 - 7
panda/src/putil/bamWriter.cxx

@@ -41,8 +41,43 @@ BamWriter(DatagramSink *target) :
   _next_pta_id = 1;
   _next_pta_id = 1;
   _long_pta_id = false;
   _long_pta_id = false;
 
 
-  _file_major = _bam_major_ver;
-  _file_minor = _bam_minor_ver;
+  // Check which version .bam files we should write.
+  if (bam_version.get_num_words() > 0) {
+    if (bam_version.get_num_words() != 2) {
+      util_cat.error()
+        << "bam-version configuration variable requires two arguments.\n";
+    }
+    _file_major = bam_version[0];
+    _file_minor = bam_version[1];
+
+    if (_file_major < _bam_major_ver || _file_minor < 21) {
+      util_cat.error()
+        << "bam-version is set to " << bam_version << ", but this version of "
+           "Panda3D cannot produce .bam files older than 6.21.  Set "
+           "bam-version to 6 21 in Config.prc to suppress this error, or "
+           "leave it blank to write version " << _bam_major_ver << "."
+           << _bam_minor_ver << " files.\n";
+      _file_major = 6;
+      _file_minor = 21;
+      bam_version.set_string_value("6 21");
+
+    } else if (_file_major > _bam_major_ver || _file_minor > _bam_minor_ver) {
+      util_cat.error()
+        << "bam-version is set to " << bam_version << ", but this version of "
+           "Panda3D cannot produce .bam files newer than " << _bam_major_ver
+        << "." << _bam_minor_ver << ".  Set bam-version to a supported "
+           "version or leave it blank to write version " << _bam_major_ver
+        << "." << _bam_minor_ver << " files.\n";
+
+      _file_major = _bam_major_ver;
+      _file_minor = _bam_minor_ver;
+      bam_version.set_word(0, _bam_major_ver);
+      bam_version.set_word(1, _bam_minor_ver);
+    }
+  } else {
+    _file_major = _bam_major_ver;
+    _file_minor = _bam_minor_ver;
+  }
   _file_endian = bam_endian;
   _file_endian = bam_endian;
   _file_stdfloat_double = bam_stdfloat_double;
   _file_stdfloat_double = bam_stdfloat_double;
   _file_texture_mode = bam_texture_mode;
   _file_texture_mode = bam_texture_mode;
@@ -98,18 +133,24 @@ init() {
   _next_pta_id = 1;
   _next_pta_id = 1;
   _long_pta_id = false;
   _long_pta_id = false;
 
 
-  _file_major = _bam_major_ver;
-  _file_minor = _bam_minor_ver;
+  nassertr_always(_file_major == _bam_major_ver, false);
+  nassertr_always(_file_minor <= _bam_minor_ver && _file_minor >= 21, false);
+
   _file_endian = bam_endian;
   _file_endian = bam_endian;
   _file_texture_mode = bam_texture_mode;
   _file_texture_mode = bam_texture_mode;
 
 
   // Write out the current major and minor BAM file version numbers.
   // Write out the current major and minor BAM file version numbers.
   Datagram header;
   Datagram header;
 
 
-  header.add_uint16(_bam_major_ver);
-  header.add_uint16(_bam_minor_ver);
+  header.add_uint16(_file_major);
+  header.add_uint16(_file_minor);
   header.add_uint8(_file_endian);
   header.add_uint8(_file_endian);
-  header.add_bool(_file_stdfloat_double);
+
+  if (_file_major >= 6 || _file_minor >= 27) {
+    header.add_bool(_file_stdfloat_double);
+  } else {
+    _file_stdfloat_double = false;
+  }
 
 
   if (!_target->put_datagram(header)) {
   if (!_target->put_datagram(header)) {
     util_cat.error()
     util_cat.error()

+ 1 - 0
panda/src/putil/bamWriter.h

@@ -76,6 +76,7 @@ PUBLISHED:
 
 
   INLINE int get_file_major_ver() const;
   INLINE int get_file_major_ver() const;
   INLINE int get_file_minor_ver() const;
   INLINE int get_file_minor_ver() const;
+  INLINE void set_file_minor_ver(int minor_ver);
 
 
   INLINE BamEndian get_file_endian() const;
   INLINE BamEndian get_file_endian() const;
   INLINE bool get_file_stdfloat_double() const;
   INLINE bool get_file_stdfloat_double() const;

+ 6 - 0
panda/src/putil/config_util.cxx

@@ -51,6 +51,12 @@ ConfigureDef(config_util);
 NotifyCategoryDef(util, "");
 NotifyCategoryDef(util, "");
 NotifyCategoryDef(bam, util_cat);
 NotifyCategoryDef(bam, util_cat);
 
 
+ConfigVariableInt bam_version
+("bam-version", "",
+ PRC_DESC("Set this to specify which version .bam files to generate.  Each "
+          "Panda version only supports outputting a limited number of .bam "
+          "versions.  The default is to use the latest supported version."));
+
 ConfigVariableEnum<BamEnums::BamEndian> bam_endian
 ConfigVariableEnum<BamEnums::BamEndian> bam_endian
 ("bam-endian", BamEnums::BE_native,
 ("bam-endian", BamEnums::BE_native,
  PRC_DESC("The default endianness to use for writing major numeric data "
  PRC_DESC("The default endianness to use for writing major numeric data "

+ 1 - 0
panda/src/putil/config_util.h

@@ -33,6 +33,7 @@ NotifyCategoryDecl(bam, EXPCL_PANDA_PUTIL, EXPTP_PANDA_PUTIL);
 // a global constant, we'll make it a member of MemoryUsage.  extern
 // a global constant, we'll make it a member of MemoryUsage.  extern
 // EXPCL_PANDA_PUTIL const bool track_memory_usage;
 // EXPCL_PANDA_PUTIL const bool track_memory_usage;
 
 
+extern EXPCL_PANDA_PUTIL ConfigVariableInt bam_version;
 extern EXPCL_PANDA_PUTIL ConfigVariableEnum<BamEnums::BamEndian> bam_endian;
 extern EXPCL_PANDA_PUTIL ConfigVariableEnum<BamEnums::BamEndian> bam_endian;
 extern EXPCL_PANDA_PUTIL ConfigVariableBool bam_stdfloat_double;
 extern EXPCL_PANDA_PUTIL ConfigVariableBool bam_stdfloat_double;
 extern EXPCL_PANDA_PUTIL ConfigVariableEnum<BamEnums::BamTextureMode> bam_texture_mode;
 extern EXPCL_PANDA_PUTIL ConfigVariableEnum<BamEnums::BamTextureMode> bam_texture_mode;

+ 1 - 1
panda/src/speedtree/loaderFileTypeSrt.cxx

@@ -42,7 +42,7 @@ get_extension() const {
 
 
 /**
 /**
  * Returns true if this file type can transparently load compressed files
  * Returns true if this file type can transparently load compressed files
- * (with a .pz extension), false otherwise.
+ * (with a .pz or .gz extension), false otherwise.
  */
  */
 bool LoaderFileTypeSrt::
 bool LoaderFileTypeSrt::
 supports_compressed() const {
 supports_compressed() const {

+ 1 - 1
panda/src/speedtree/loaderFileTypeStf.cxx

@@ -41,7 +41,7 @@ get_extension() const {
 
 
 /**
 /**
  * Returns true if this file type can transparently load compressed files
  * Returns true if this file type can transparently load compressed files
- * (with a .pz extension), false otherwise.
+ * (with a .pz or .gz extension), false otherwise.
  */
  */
 bool LoaderFileTypeStf::
 bool LoaderFileTypeStf::
 supports_compressed() const {
 supports_compressed() const {

+ 1 - 1
pandatool/src/assimp/loaderFileTypeAssimp.cxx

@@ -63,7 +63,7 @@ get_additional_extensions() const {
 
 
 /**
 /**
  * Returns true if this file type can transparently load compressed files
  * Returns true if this file type can transparently load compressed files
- * (with a .pz extension), false otherwise.
+ * (with a .pz or .gz extension), false otherwise.
  */
  */
 bool LoaderFileTypeAssimp::
 bool LoaderFileTypeAssimp::
 supports_compressed() const {
 supports_compressed() const {

+ 1 - 1
pandatool/src/ptloader/loaderFileTypePandatool.cxx

@@ -80,7 +80,7 @@ get_additional_extensions() const {
 
 
 /**
 /**
  * Returns true if this file type can transparently load compressed files
  * Returns true if this file type can transparently load compressed files
- * (with a .pz extension), false otherwise.
+ * (with a .pz or .gz extension), false otherwise.
  */
  */
 bool LoaderFileTypePandatool::
 bool LoaderFileTypePandatool::
 supports_compressed() const {
 supports_compressed() const {

+ 13 - 11
samples/shader-terrain/main.py

@@ -2,16 +2,15 @@
 
 
 # Author: tobspr
 # Author: tobspr
 #
 #
-# Last Updated: 2016-02-13
+# Last Updated: 2016-04-30
 #
 #
 # This tutorial provides an example of using the ShaderTerrainMesh class
 # This tutorial provides an example of using the ShaderTerrainMesh class
 
 
-import os, sys, math, random
-
 from direct.showbase.ShowBase import ShowBase
 from direct.showbase.ShowBase import ShowBase
 from panda3d.core import ShaderTerrainMesh, Shader, load_prc_file_data
 from panda3d.core import ShaderTerrainMesh, Shader, load_prc_file_data
 from panda3d.core import SamplerState
 from panda3d.core import SamplerState
 
 
+
 class ShaderTerrainDemo(ShowBase):
 class ShaderTerrainDemo(ShowBase):
     def __init__(self):
     def __init__(self):
 
 
@@ -19,14 +18,14 @@ class ShaderTerrainDemo(ShowBase):
         # before the ShowBase is initialized
         # before the ShowBase is initialized
         load_prc_file_data("", """
         load_prc_file_data("", """
             textures-power-2 none
             textures-power-2 none
-            window-title Panda3D Shader Terrain Demo
             gl-coordinate-system default
             gl-coordinate-system default
+            window-title Panda3D ShaderTerrainMesh Demo
         """)
         """)
 
 
         # Initialize the showbase
         # Initialize the showbase
         ShowBase.__init__(self)
         ShowBase.__init__(self)
 
 
-        # Increase camera FOV aswell as the far plane
+        # Increase camera FOV as well as the far plane
         self.camLens.set_fov(90)
         self.camLens.set_fov(90)
         self.camLens.set_near_far(0.1, 50000)
         self.camLens.set_near_far(0.1, 50000)
 
 
@@ -35,7 +34,7 @@ class ShaderTerrainDemo(ShowBase):
 
 
         # Set a heightfield, the heightfield should be a 16-bit png and
         # Set a heightfield, the heightfield should be a 16-bit png and
         # have a quadratic size of a power of two.
         # have a quadratic size of a power of two.
-        self.terrain_node.heightfield_filename = "heightfield.png"
+        self.terrain_node.heightfield = self.loader.loadTexture("heightfield.png")
 
 
         # Set the target triangle width. For a value of 10.0 for example,
         # Set the target triangle width. For a value of 10.0 for example,
         # the terrain will attempt to make every triangle 10 pixels wide on screen.
         # the terrain will attempt to make every triangle 10 pixels wide on screen.
@@ -44,24 +43,28 @@ class ShaderTerrainDemo(ShowBase):
         # Generate the terrain
         # Generate the terrain
         self.terrain_node.generate()
         self.terrain_node.generate()
 
 
-        # Attach the terrain to the main scene and set its scale
+        # Attach the terrain to the main scene and set its scale. With no scale
+        # set, the terrain ranges from (0, 0, 0) to (1, 1, 1)
         self.terrain = self.render.attach_new_node(self.terrain_node)
         self.terrain = self.render.attach_new_node(self.terrain_node)
         self.terrain.set_scale(1024, 1024, 100)
         self.terrain.set_scale(1024, 1024, 100)
         self.terrain.set_pos(-512, -512, -70.0)
         self.terrain.set_pos(-512, -512, -70.0)
 
 
         # Set a shader on the terrain. The ShaderTerrainMesh only works with
         # Set a shader on the terrain. The ShaderTerrainMesh only works with
-        # an applied shader. You can use the shaders used here in your own shaders
+        # an applied shader. You can use the shaders used here in your own application
         terrain_shader = Shader.load(Shader.SL_GLSL, "terrain.vert.glsl", "terrain.frag.glsl")
         terrain_shader = Shader.load(Shader.SL_GLSL, "terrain.vert.glsl", "terrain.frag.glsl")
         self.terrain.set_shader(terrain_shader)
         self.terrain.set_shader(terrain_shader)
         self.terrain.set_shader_input("camera", self.camera)
         self.terrain.set_shader_input("camera", self.camera)
 
 
+        # Shortcut to view the wireframe mesh
+        self.accept("f3", self.toggleWireframe)
+
         # Set some texture on the terrain
         # Set some texture on the terrain
         grass_tex = self.loader.loadTexture("textures/grass.png")
         grass_tex = self.loader.loadTexture("textures/grass.png")
         grass_tex.set_minfilter(SamplerState.FT_linear_mipmap_linear)
         grass_tex.set_minfilter(SamplerState.FT_linear_mipmap_linear)
         grass_tex.set_anisotropic_degree(16)
         grass_tex.set_anisotropic_degree(16)
         self.terrain.set_texture(grass_tex)
         self.terrain.set_texture(grass_tex)
 
 
-        # Load some skybox - you can safely ignore this code
+        # Load a skybox - you can safely ignore this code
         skybox = self.loader.loadModel("models/skybox.bam")
         skybox = self.loader.loadModel("models/skybox.bam")
         skybox.reparent_to(self.render)
         skybox.reparent_to(self.render)
         skybox.set_scale(20000)
         skybox.set_scale(20000)
@@ -77,5 +80,4 @@ class ShaderTerrainDemo(ShowBase):
         skybox_shader = Shader.load(Shader.SL_GLSL, "skybox.vert.glsl", "skybox.frag.glsl")
         skybox_shader = Shader.load(Shader.SL_GLSL, "skybox.vert.glsl", "skybox.frag.glsl")
         skybox.set_shader(skybox_shader)
         skybox.set_shader(skybox_shader)
 
 
-demo = ShaderTerrainDemo()
-demo.run()
+ShaderTerrainDemo().run()