David Rose 16 年 前
コミット
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')
                 if mdef.exclude and mdef.allowChildren:
                     xmodule.SetAttribute('allowChildren', '1')
-                self.components.append(xmodule)
+                self.components.append((newName.lower(), xmodule))
 
             # Now look for implicit shared-library dependencies.
             if PandaSystem.getPlatform().startswith('win'):
@@ -727,7 +727,8 @@ class Packager:
             xpackage.InsertEndChild(xuncompressedArchive)
             xpackage.InsertEndChild(xcompressedArchive)
 
-            for xextract in self.extracts:
+            self.extracts.sort()
+            for name, xextract in self.extracts:
                 xpackage.InsertEndChild(xextract)
 
             doc.InsertEndChild(xpackage)
@@ -755,7 +756,8 @@ class Packager:
                     xrequires.SetAttribute('version', package.version)
                 xpackage.InsertEndChild(xrequires)
 
-            for xcomponent in self.components:
+            self.components.sort()
+            for name, xcomponent in self.components:
                 xpackage.InsertEndChild(xcomponent)
 
             doc.InsertEndChild(xpackage)
@@ -933,7 +935,7 @@ class Packager:
             
             xcomponent = TiXmlElement('component')
             xcomponent.SetAttribute('filename', newName)
-            self.components.append(xcomponent)
+            self.components.append((newName.lower(), xcomponent))
 
         def addFoundTexture(self, filename):
             """ 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)
             if file.extract:
                 xextract = self.getFileSpec('extract', file.filename, file.newName)
-                self.extracts.append(xextract)
+                self.extracts.append((file.newName.lower(), xextract))
 
             xcomponent = TiXmlElement('component')
             xcomponent.SetAttribute('filename', file.newName)
-            self.components.append(xcomponent)
+            self.components.append((file.newName.lower(), xcomponent))
 
         def requirePackage(self, package):
             """ Indicates a dependency on the given package.  This
@@ -1076,7 +1078,29 @@ class Packager:
         self.binaryExtensions = [ 'ttf', 'wav', 'mid' ]
 
         # 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.
         self.extractExtensions = self.executableExtensions[:]
@@ -1596,10 +1620,10 @@ class Packager:
 
     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
 
@@ -1619,9 +1643,13 @@ class Packager:
         if executable is not None:
             executable = int(executable)
 
+        literal = args.get('literal', None)
+        if literal is not None:
+            literal = int(literal)
+
         self.file(Filename.fromOsSpecific(filename),
                   newNameOrDir = newNameOrDir, extract = extract,
-                  executable = executable)
+                  executable = executable, literal = literal)
 
     def parse_inline_file(self, words):
         """
@@ -2133,7 +2161,8 @@ class Packager:
         package.mainModule = 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.
 
         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
         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
 
         filename = Filename(filename)
-        files = glob.glob(filename.toOsSpecific())
-        if not files:
+
+        if literal:
             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)
 
         newName = None

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

@@ -1,15 +1,22 @@
 #! /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.
 

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

@@ -222,8 +222,11 @@ class AppRunner(DirectObject):
                 mainName = self.p3dPackage.Attribute('main_module')
                 if 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)
             if not loader:
                 message = "No %s found in application." % (moduleName)
@@ -264,6 +267,10 @@ class AppRunner(DirectObject):
         self.tokenDict = dict(tokens)
         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
         # respond to queries.
         self.notifyRequest('onpythonload')