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
 directory tree of .py files and models, into a multifile for
 distribution and running with RunAppMF.py.  To run it, use:
 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 sys
+import getopt
 import direct
 import direct
 from pandac.PandaModules import *
 from pandac.PandaModules import *
 
 
@@ -52,13 +66,37 @@ class AppPacker:
         for type in PNMFileTypeRegistry.getGlobalPtr().getTypes():
         for type in PNMFileTypeRegistry.getGlobalPtr().getTypes():
             self.image_extensions += type.getExtensions()
             self.image_extensions += type.getExtensions()
 
 
-    def scan(self, root):
+    def scan(self, root, main):
         self.root = Filename(root)
         self.root = Filename(root)
         self.root.makeAbsolute(vfs.getCwd())
         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._recurse(self.root)
 
 
         self.multifile.repack()
         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):
     def _recurse(self, filename):
         dirList = vfs.scanDirectory(filename)
         dirList = vfs.scanDirectory(filename)
         if dirList:
         if dirList:
@@ -95,7 +133,12 @@ class AppPacker:
     def addPyFile(self, filename):
     def addPyFile(self, filename):
         # For now, just add it as an ordinary file.  Later we'll
         # For now, just add it as an ordinary file.  Later we'll
         # precompile these to .pyo's.
         # 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):
     def addEggFile(self, filename, outFilename):
         # Precompile egg files to bam's.
         # Precompile egg files to bam's.
@@ -140,7 +183,9 @@ class AppPacker:
         bamFile.getWriter().setFileTextureMode(BTMUnchanged)
         bamFile.getWriter().setFileTextureMode(BTMUnchanged)
         bamFile.writeObject(node)
         bamFile.writeObject(node)
         bamFile.close()
         bamFile.close()
-        node = None
+
+        # Clean the node out of memory.
+        node.removeAllChildren()
 
 
         # Now we have an in-memory bam file.
         # Now we have an in-memory bam file.
         rel = self.makeRelFilename(filename)
         rel = self.makeRelFilename(filename)
@@ -223,6 +268,19 @@ class AppPacker:
 
 
 
 
 def makePackedApp(args):
 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:
     if not args:
         raise ArgumentError, "No destination app specified.  Use:\npython MakeAppMF.py app.mf"
         raise ArgumentError, "No destination app specified.  Use:\npython MakeAppMF.py app.mf"
 
 
@@ -235,7 +293,7 @@ def makePackedApp(args):
         raise ArgumentError, "Too many arguments."
         raise ArgumentError, "Too many arguments."
 
 
     p = AppPacker(multifile_name)
     p = AppPacker(multifile_name)
-    p.scan(root)
+    p.scan(root = root, main = main)
 
 
 if __name__ == '__main__':
 if __name__ == '__main__':
     try:
     try:

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

@@ -14,7 +14,8 @@ Also see MakeAppMF.py.
 import sys
 import sys
 from direct.showbase import VFSImporter
 from direct.showbase import VFSImporter
 from pandac.PandaModules import VirtualFileSystem, Filename, Multifile, ConfigPageManager, getModelPath
 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__
 import __builtin__
 
 
 MultifileRoot = '/mf'
 MultifileRoot = '/mf'
@@ -70,13 +71,17 @@ def runPackedApp(args):
     cpMgr.getSearchPath().prependDirectory(MultifileRoot)
     cpMgr.getSearchPath().prependDirectory(MultifileRoot)
     cpMgr.reloadImplicitPages()
     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
     import main
+    if hasattr(main, 'main') and callable(main.main):
+        main.main()
 
 
 if __name__ == '__main__':
 if __name__ == '__main__':
     try:
     try:

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

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