David Rose 17 years ago
parent
commit
d8641b3fdc

+ 70 - 12
direct/src/showbase/MakeAppMF.py

@@ -1,18 +1,32 @@
-""" This module will pack a Panda application, consisting of a
+"""
+This module will pack a Panda application, consisting of a
 directory tree of .py files and models, into a multifile for
 distribution and running with RunAppMF.py.  To run it, use:
 
-python MakeAppMF.py app.mf [application_root]
+python MakeAppMF.py [opts] app.mf
+
+Options:
+
+  -r application_root
+
+     Specify the root directory of the application source; this is a
+     directory tree that contains all of your .py files and models.
+     If this is omitted, the default is the current directory.
+
+  -m main.py
+  
+     Names the Python file that begins the application.  This should
+     be a file within the root directory. If this is omitted, the
+     default is a file named "main.py", or if there is only one Python
+     file present, it is used.  If this file contains a function
+     called main(), that function will be called after importing it
+     (this is preferable to having the module start itself immediately
+     upon importing).
 
-where application_root is the root directory of the application.  If
-it is omitted, the default is the current directory.  The root
-directory should contain at a file named main.py, which is imported to
-start the application.  If main.py contains a function called main(),
-this function is called after importing it; otherwise, taskMgr.run()
-is called.
 """
 
 import sys
+import getopt
 import direct
 from pandac.PandaModules import *
 
@@ -52,13 +66,37 @@ class AppPacker:
         for type in PNMFileTypeRegistry.getGlobalPtr().getTypes():
             self.image_extensions += type.getExtensions()
 
-    def scan(self, root):
+    def scan(self, root, main):
         self.root = Filename(root)
         self.root.makeAbsolute(vfs.getCwd())
+
+        # Check if there is just one .py file.
+        pyFiles = self.findPyFiles(self.root)
+        if main == None:
+            if len(pyFiles) == 1:
+                main = pyFiles[0]
+            else:
+                main = 'main.py'
+        if main not in pyFiles:
+            raise StandardError, 'No file %s in root directory.' % (main)
+        self.main = Filename(self.root, main)
+        
         self._recurse(self.root)
 
         self.multifile.repack()
 
+    def findPyFiles(self, dirname):
+        """ Returns a list of Python filenames at the root directory
+        level. """
+        
+        dirList = vfs.scanDirectory(dirname)
+        pyFiles = []
+        for file in dirList:
+            if file.getFilename().getExtension() == 'py':
+                pyFiles.append(file.getFilename().getBasename())
+
+        return pyFiles
+
     def _recurse(self, filename):
         dirList = vfs.scanDirectory(filename)
         if dirList:
@@ -95,7 +133,12 @@ class AppPacker:
     def addPyFile(self, filename):
         # For now, just add it as an ordinary file.  Later we'll
         # precompile these to .pyo's.
-        self.addTextFile(filename)
+        if filename == self.main:
+            # This one is the "main.py"; the starter file.
+            self.multifile.addSubfile('main.py', filename, self.compression_level)
+        else:
+            # Any other Python file; add it normally.
+            self.addTextFile(filename)
 
     def addEggFile(self, filename, outFilename):
         # Precompile egg files to bam's.
@@ -140,7 +183,9 @@ class AppPacker:
         bamFile.getWriter().setFileTextureMode(BTMUnchanged)
         bamFile.writeObject(node)
         bamFile.close()
-        node = None
+
+        # Clean the node out of memory.
+        node.removeAllChildren()
 
         # Now we have an in-memory bam file.
         rel = self.makeRelFilename(filename)
@@ -223,6 +268,19 @@ class AppPacker:
 
 
 def makePackedApp(args):
+    opts, args = getopt.getopt(args, 'r:m:h')
+
+    root = '.'
+    main = None
+    for option, value in opts:
+        if option == '-r':
+            root = value
+        elif option == '-m':
+            main = value
+        elif option == '-h':
+            print __doc__
+            sys.exit(1)
+    
     if not args:
         raise ArgumentError, "No destination app specified.  Use:\npython MakeAppMF.py app.mf"
 
@@ -235,7 +293,7 @@ def makePackedApp(args):
         raise ArgumentError, "Too many arguments."
 
     p = AppPacker(multifile_name)
-    p.scan(root)
+    p.scan(root = root, main = main)
 
 if __name__ == '__main__':
     try:

+ 11 - 6
direct/src/showbase/RunAppMF.py

@@ -14,7 +14,8 @@ Also see MakeAppMF.py.
 import sys
 from direct.showbase import VFSImporter
 from pandac.PandaModules import VirtualFileSystem, Filename, Multifile, ConfigPageManager, getModelPath
-from direct.stdpy.file import file, open
+from direct.stdpy import file
+import os
 import __builtin__
 
 MultifileRoot = '/mf'
@@ -70,13 +71,17 @@ def runPackedApp(args):
     cpMgr.getSearchPath().prependDirectory(MultifileRoot)
     cpMgr.reloadImplicitPages()
 
-    # Replace the builtin open and file symbols so code will get our
-    # versions by default, which can open and read files out of the
-    # multifile.
-    __builtin__.file = file
-    __builtin__.open = open
+    # Replace the builtin open and file symbols so user code will get
+    # our versions by default, which can open and read files out of
+    # the multifile.
+    __builtin__.file = file.file
+    __builtin__.open = file.open
+    os.listdir = file.listdir
+    os.walk = file.walk
 
     import main
+    if hasattr(main, 'main') and callable(main.main):
+        main.main()
 
 if __name__ == '__main__':
     try:

+ 5 - 4
direct/src/showbase/VFSImporter.py

@@ -34,7 +34,7 @@ class VFSImporter:
 
     def find_module(self, fullname):
         basename = fullname.split('.')[-1]
-        path = Filename(self.dir_path, Filename(basename))
+        path = Filename(self.dir_path, basename)
 
         # First, look for Python files.
         filename = path
@@ -66,12 +66,12 @@ class VFSImporter:
 
         # Finally, consider a package, i.e. a directory containing
         # __init__.py.
-        filename = Filename(path, Filename('__init__.py'))
+        filename = Filename(path, '__init__.py')
         vfile = vfs.getFile(filename, True)
         if vfile:
             return VFSLoader(self, vfile, filename, FTPythonSource,
                              package = True)
-        filename = Filename(path, Filename('__init__.' + pycExtension))
+        filename = Filename(path, '__init__.' + pycExtension)
         vfile = vfs.getFile(filename, True)
         if vfile:
             return VFSLoader(self, vfile, filename, FTPythonCompiled,
@@ -158,7 +158,8 @@ class VFSLoader:
         else:
             # It's a virtual file.  Dump it.
             filename = Filename.temporary('', self.filename.getBasenameWoExtension(),
-                                          '.' + self.filename.getExtension())
+                                          '.' + self.filename.getExtension(),
+                                          type = Filename.TDso)
             filename.setExtension(self.filename.getExtension())
             fin = open(vfile, 'rb')
             fout = open(filename, 'wb')