diff --git a/direct/src/showbase/MakeAppMF.py b/direct/src/showbase/MakeAppMF.py index 1f4233a399..c1a534bc50 100644 --- a/direct/src/showbase/MakeAppMF.py +++ b/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: diff --git a/direct/src/showbase/RunAppMF.py b/direct/src/showbase/RunAppMF.py index 61273d255c..054e645fb6 100644 --- a/direct/src/showbase/RunAppMF.py +++ b/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: diff --git a/direct/src/showbase/VFSImporter.py b/direct/src/showbase/VFSImporter.py index aaed66ff41..ff47434083 100644 --- a/direct/src/showbase/VFSImporter.py +++ b/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')