Browse Source

panda3d.pdef

David Rose 16 years ago
parent
commit
8dac001268

+ 166 - 0
direct/src/configfiles/panda3d.pdef

@@ -0,0 +1,166 @@
+# This file defines a number of standard "packages" that correspond to
+# a Panda3D distribution.  These packages are built by passing this
+# file to the ppackage utility, either as a packaged application, or
+# as the module direct.showutil.ppackage.
+
+# These packages are then downloaded by the Panda3D plugin and
+# standalone runtime executable, and they contain the actual Panda3D
+# runtime libraries.
+
+# We divide the runtime into several smaller packages.  There is the
+# core Panda3D package, which is needed by all Panda3D applications,
+# and then a number of smaller, optional packages, which may or may
+# not be needed by any one particular application.
+
+
+begin_package panda3d
+
+# The core Panda3D package.  Contains Python and most of the graphics
+# code in Panda3D.
+
+config display_name="Panda3D"
+
+# This is the key Python module that is imported at runtime to start
+# an application running.
+module direct.showutil.runp3d
+
+# These are additional Python modules that are needed by most Panda3D
+# applications.  It doesn't matter too much if we miss one or two
+# here, since any module imported by any of this code will
+# automatically be included as well, and we end up with a pretty
+# complete list that way.
+module direct.directbase.DirectStart
+module direct.showbase.*
+module direct.actor.Actor
+module direct.fsm.FSM
+module direct.interval.IntervalGlobal
+module direct.particles.ParticleEffect
+module direct.directutil.Mopath
+
+# Exclude these GUI toolkits; they're big, and many applications don't
+# use them.  We define them as separate, optional packages, below.
+exclude_module wx
+exclude_module direct.showbase.WxGlobal
+
+exclude_module Tkinter
+exclude_module direct.showbase.TkGlobal
+exclude_module direct.tkpanels
+exclude_module direct.tkwidgets
+
+# Bind all of the above Python code into a frozen DLL.  This makes the
+# Python code available when the DLL is imported.  It is actually
+# preferable not to use freeze, but instead just to leave the Python
+# code directly within the Multifile; but in this case we have to use
+# freeze on this very first package, due to bootstrapping
+# requirements.  (Part of the code we're including here is the code
+# required to load Python code from a Multifile, so it can't be placed
+# within a Multifile itself.)
+freeze_dll runp3d_frozen
+
+# This is the main program that drives the plugin application.  It is
+# responsible for loading runp3d_frozen, above, and then importing
+# direct.showutil.runp3d, to start an application running.  Note that
+# the .exe extension is automatically replaced with the
+# platform-specific extension appropriate for an executable.
+file p3dpython.exe
+
+# Most of the core Panda3D DLL's will be included implicitly due to
+# being referenced by the above Python code.  Here we name a few more
+# that are also needed, but aren't referenced by any code.  Again,
+# note that the .dll extension is automatically replaced with the
+# platform-specific extension for an executable.
+file libpandagl.dll
+file libpandadx8.dll
+file libpandadx9.dll
+file libtinydisplay.dll
+
+# A basic config file is needed to lay some some fundamental runtime
+# variables.
+inline_file Config.prc extract=1 <<- <EOF>
+    plugin-path $PANDA3D_ROOT
+    aux-display pandagl
+    aux-display pandadx9
+    aux-display pandadx8
+    aux-display tinydisplay
+<EOF>
+
+end_package panda3d
+
+
+begin_package egg
+
+# This package contains the code for reading and operating on egg
+# files.  Since the Packager automatically converts egg files to bam
+# files, this is not needed for most Panda3D applications.
+
+config display_name="Panda3D egg loader"
+require panda3d
+
+file libpandaegg.dll
+
+inline_file egg.prc extract=1 <<- <EOF>
+    plugin-path $EGG_ROOT
+    load-file-type egg pandaegg
+<EOF>
+
+end_package egg
+
+
+begin_package wx
+config display_name="wxPython GUI Toolkit"
+require panda3d
+
+module direct.showbase.WxGlobal
+module wx
+module wx.*
+
+end_package wx
+
+
+
+begin_package tk
+config display_name="Tk GUI Toolkit"
+require panda3d
+
+module Tkinter
+module direct.showbase.TkGlobal
+module direct.tkpanels
+module direct.tkwidgets
+
+end_package tk
+
+
+begin_p3d packp3d
+
+# This application is a command-line convenience for building a p3d
+# application out of a directory hierarchy on disk.  We build it here
+# into its own p3d application, to allow end-users to easily build p3d
+# applications using the appropriate version of Python and Panda for
+# the targeted runtime.
+
+config display_name="Panda3D Application Packer"
+config full_disk_access=1
+config hidden=1
+require panda3d
+require egg
+
+main_module direct.showutil.packp3d
+
+end_p3d packp3d
+
+
+begin_p3d ppackage
+
+# As above, a packaging utility.  This is the fully-general ppackage
+# utility, which reads pdef files (like this one!) and creates one or
+# more packages or p3d applications.
+
+config display_name="Panda3D General Package Utility"
+config full_disk_access=1
+config hidden=1
+require panda3d
+require egg
+
+main_module direct.showutil.ppackage
+
+end_p3d ppackage

+ 65 - 13
direct/src/showutil/Packager.py

@@ -252,7 +252,7 @@ class Packager:
                     xmodule.SetAttribute('forbid', '1')
                     xmodule.SetAttribute('forbid', '1')
                 if mdef.exclude and mdef.allowChildren:
                 if mdef.exclude and mdef.allowChildren:
                     xmodule.SetAttribute('allowChildren', '1')
                     xmodule.SetAttribute('allowChildren', '1')
-                self.components.append(xmodule)
+                self.components.append((newName.lower(), xmodule))
 
 
             # Now look for implicit shared-library dependencies.
             # Now look for implicit shared-library dependencies.
             if PandaSystem.getPlatform().startswith('win'):
             if PandaSystem.getPlatform().startswith('win'):
@@ -727,7 +727,8 @@ class Packager:
             xpackage.InsertEndChild(xuncompressedArchive)
             xpackage.InsertEndChild(xuncompressedArchive)
             xpackage.InsertEndChild(xcompressedArchive)
             xpackage.InsertEndChild(xcompressedArchive)
 
 
-            for xextract in self.extracts:
+            self.extracts.sort()
+            for name, xextract in self.extracts:
                 xpackage.InsertEndChild(xextract)
                 xpackage.InsertEndChild(xextract)
 
 
             doc.InsertEndChild(xpackage)
             doc.InsertEndChild(xpackage)
@@ -755,7 +756,8 @@ class Packager:
                     xrequires.SetAttribute('version', package.version)
                     xrequires.SetAttribute('version', package.version)
                 xpackage.InsertEndChild(xrequires)
                 xpackage.InsertEndChild(xrequires)
 
 
-            for xcomponent in self.components:
+            self.components.sort()
+            for name, xcomponent in self.components:
                 xpackage.InsertEndChild(xcomponent)
                 xpackage.InsertEndChild(xcomponent)
 
 
             doc.InsertEndChild(xpackage)
             doc.InsertEndChild(xpackage)
@@ -933,7 +935,7 @@ class Packager:
             
             
             xcomponent = TiXmlElement('component')
             xcomponent = TiXmlElement('component')
             xcomponent.SetAttribute('filename', newName)
             xcomponent.SetAttribute('filename', newName)
-            self.components.append(xcomponent)
+            self.components.append((newName.lower(), xcomponent))
 
 
         def addFoundTexture(self, filename):
         def addFoundTexture(self, filename):
             """ Adds the newly-discovered texture to the output, if it has
             """ Adds the newly-discovered texture to the output, if it has
@@ -973,11 +975,11 @@ class Packager:
             self.multifile.addSubfile(file.newName, file.filename, compressionLevel)
             self.multifile.addSubfile(file.newName, file.filename, compressionLevel)
             if file.extract:
             if file.extract:
                 xextract = self.getFileSpec('extract', file.filename, file.newName)
                 xextract = self.getFileSpec('extract', file.filename, file.newName)
-                self.extracts.append(xextract)
+                self.extracts.append((file.newName.lower(), xextract))
 
 
             xcomponent = TiXmlElement('component')
             xcomponent = TiXmlElement('component')
             xcomponent.SetAttribute('filename', file.newName)
             xcomponent.SetAttribute('filename', file.newName)
-            self.components.append(xcomponent)
+            self.components.append((file.newName.lower(), xcomponent))
 
 
         def requirePackage(self, package):
         def requirePackage(self, package):
             """ Indicates a dependency on the given package.  This
             """ Indicates a dependency on the given package.  This
@@ -1076,7 +1078,29 @@ class Packager:
         self.binaryExtensions = [ 'ttf', 'wav', 'mid' ]
         self.binaryExtensions = [ 'ttf', 'wav', 'mid' ]
 
 
         # Files that represent an executable or shared library.
         # Files that represent an executable or shared library.
-        self.executableExtensions = [ 'dll', 'pyd', 'so', 'dylib', 'exe' ]
+        if self.platform.startswith('win'):
+            self.executableExtensions = [ 'dll', 'pyd', 'exe' ]
+        elif self.platform.startswith('osx'):
+            self.executableExtensions = [ 'so', 'dylib' ]
+        else:
+            self.executableExtensions = [ 'so' ]
+
+        # Extensions that are automatically remapped by convention.
+        self.remapExtensions = {}
+        if self.platform.startswith('win'):
+            pass
+        elif self.platform.startswith('osx'):
+            self.remapExtensions = {
+                'dll' : 'dylib',
+                'pyd' : 'dylib',
+                'exe' : ''
+                }
+        else:
+            self.remapExtensions = {
+                'dll' : 'so',
+                'pyd' : 'so',
+                'exe' : ''
+                }
 
 
         # Files that should be extracted to disk.
         # Files that should be extracted to disk.
         self.extractExtensions = self.executableExtensions[:]
         self.extractExtensions = self.executableExtensions[:]
@@ -1596,10 +1620,10 @@ class Packager:
 
 
     def parse_file(self, words):
     def parse_file(self, words):
         """
         """
-        file filename [newNameOrDir] [extract=1] [executable=1]
+        file filename [newNameOrDir] [extract=1] [executable=1] [literal=1]
         """
         """
 
 
-        args = self.__parseArgs(words, ['extract', 'executable'])
+        args = self.__parseArgs(words, ['extract', 'executable', 'literal'])
 
 
         newNameOrDir = None
         newNameOrDir = None
 
 
@@ -1619,9 +1643,13 @@ class Packager:
         if executable is not None:
         if executable is not None:
             executable = int(executable)
             executable = int(executable)
 
 
+        literal = args.get('literal', None)
+        if literal is not None:
+            literal = int(literal)
+
         self.file(Filename.fromOsSpecific(filename),
         self.file(Filename.fromOsSpecific(filename),
                   newNameOrDir = newNameOrDir, extract = extract,
                   newNameOrDir = newNameOrDir, extract = extract,
-                  executable = executable)
+                  executable = executable, literal = literal)
 
 
     def parse_inline_file(self, words):
     def parse_inline_file(self, words):
         """
         """
@@ -2133,7 +2161,8 @@ class Packager:
         package.mainModule = None
         package.mainModule = None
 
 
     def file(self, filename, source = None, newNameOrDir = None,
     def file(self, filename, source = None, newNameOrDir = None,
-             extract = None, executable = None, deleteTemp = False):
+             extract = None, executable = None, deleteTemp = False,
+             literal = False):
         """ Adds the indicated arbitrary file to the current package.
         """ Adds the indicated arbitrary file to the current package.
 
 
         The file is placed in the named directory, or the toplevel
         The file is placed in the named directory, or the toplevel
@@ -2162,6 +2191,12 @@ class Packager:
 
 
         If deleteTemp is true, the file is a temporary file and will
         If deleteTemp is true, the file is a temporary file and will
         be deleted after its contents are copied to the package.
         be deleted after its contents are copied to the package.
+
+        If literal is true, then the file extension will be respected
+        exactly as it appears, and glob characters will not be
+        expanded.  If this is false, then .dll or .exe files will be
+        renamed to .dylib and no extension on OSX (or .so on Linux);
+        and glob characters will be expanded.
         
         
         """
         """
 
 
@@ -2169,9 +2204,26 @@ class Packager:
             raise OutsideOfPackageError
             raise OutsideOfPackageError
 
 
         filename = Filename(filename)
         filename = Filename(filename)
-        files = glob.glob(filename.toOsSpecific())
-        if not files:
+
+        if literal:
             files = [filename.toOsSpecific()]
             files = [filename.toOsSpecific()]
+
+        else:
+            ext = filename.getExtension()
+
+            # A special case, since OSX and Linux don't have a
+            # standard extension for program files.
+            if executable is None and ext == 'exe':
+                executable = True
+
+            newExt = self.remapExtensions.get(ext, None)
+            if newExt is not None:
+                filename.setExtension(newExt)
+
+            files = glob.glob(filename.toOsSpecific())
+            if not files:
+                files = [filename.toOsSpecific()]
+
         explicit = (len(files) == 1)
         explicit = (len(files) == 1)
 
 
         newName = None
         newName = None

+ 16 - 9
direct/src/showutil/ppackage.py

@@ -1,15 +1,22 @@
 #! /usr/bin/env python
 #! /usr/bin/env python
 
 
 """
 """
-This script can be used to produce a downloadable "Package", which may
-contain arbitrary files--for instance, Python code, bam files, and/or
-compiled DLL's--and which may be downloaded by application code to
-extend an application at runtime.
-
-In addition to building the package in the first place, this script
-can also be used to generate downloadable patches of the package
-against previous versions, and manage the whole tree of patches in a
-directory structure suitable for hosting on a web server somewhere.
+This script can be used to produce a Panda3D downloadable "package",
+which may contain arbitrary files--for instance, Python code, bam
+files, and/or compiled DLL's--and which may be downloaded by
+application code to extend an application at runtime.
+
+In addition to packages, this script can also be used to build
+standalone p3d applications, that is, packaged Python code in a p3d
+file, for execution by the Panda3D plugin or runtime.  (But also see
+packp3d, which is designed to be a simpler interface for building
+applications.)
+
+In addition to building a package in the first place, this script will
+also generate downloadable patches of the package against previous
+versions, and manage the whole tree of patches in a directory
+structure suitable for hosting on a web server somewhere.  (This part
+is not yet completed.)
 
 
 This script is actually a wrapper around Panda's Packager.py.
 This script is actually a wrapper around Panda's Packager.py.
 
 

+ 9 - 2
direct/src/showutil/runp3d.py

@@ -222,8 +222,11 @@ class AppRunner(DirectObject):
                 mainName = self.p3dPackage.Attribute('main_module')
                 mainName = self.p3dPackage.Attribute('main_module')
                 if mainName:
                 if mainName:
                     moduleName = mainName
                     moduleName = mainName
-            
-            v = VFSImporter.VFSImporter(MultifileRoot)
+
+            root = MultifileRoot
+            if '.' in moduleName:
+                root += '/' + '/'.join(moduleName.split('.')[:-1])
+            v = VFSImporter.VFSImporter(root)
             loader = v.find_module(moduleName)
             loader = v.find_module(moduleName)
             if not loader:
             if not loader:
                 message = "No %s found in application." % (moduleName)
                 message = "No %s found in application." % (moduleName)
@@ -264,6 +267,10 @@ class AppRunner(DirectObject):
         self.tokenDict = dict(tokens)
         self.tokenDict = dict(tokens)
         self.argv = argv
         self.argv = argv
 
 
+        # Also store the arguments on sys, for applications that
+        # aren't instance-ready.
+        sys.argv = argv
+
         # Tell the browser that Python is up and running, and ready to
         # Tell the browser that Python is up and running, and ready to
         # respond to queries.
         # respond to queries.
         self.notifyRequest('onpythonload')
         self.notifyRequest('onpythonload')