mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-04 10:54:24 -04:00
108 lines
3.2 KiB
Python
108 lines
3.2 KiB
Python
""" This module can serve as a startup script to play a Panda
|
|
application packed within a .mf file. Run via:
|
|
|
|
python RunAppMF.py app.mf
|
|
|
|
This is currently experimental, but the intent is to work towards a
|
|
prepackaged Panda distributable, designed to run applications exactly
|
|
like this.
|
|
|
|
Also see MakeAppMF.py.
|
|
|
|
"""
|
|
|
|
import sys
|
|
from direct.showbase import VFSImporter
|
|
from pandac.PandaModules import VirtualFileSystem, Filename, Multifile, loadPrcFileData, getModelPath
|
|
from direct.stdpy import file
|
|
import os
|
|
import __builtin__
|
|
|
|
MultifileRoot = '/mf'
|
|
|
|
# This defines the default prc file that is implicitly loaded with an
|
|
# application.
|
|
AppPrcFilename = 'App.prc'
|
|
AppPrc = """
|
|
default-model-extension .bam
|
|
"""
|
|
|
|
class ArgumentError(AttributeError):
|
|
pass
|
|
|
|
def runPackedApp(args):
|
|
if not args:
|
|
raise ArgumentError, "No Panda app specified. Use:\npython RunAppMF.py app.mf"
|
|
|
|
vfs = VirtualFileSystem.getGlobalPtr()
|
|
|
|
fname = Filename.fromOsSpecific(args[0])
|
|
if not vfs.exists(fname):
|
|
raise ArgumentError, "No such file: %s" % (args[0])
|
|
|
|
mf = Multifile()
|
|
if not mf.openRead(fname):
|
|
raise ArgumentError, "Not a Panda Multifile: %s" % (args[0])
|
|
|
|
# Clear *all* the mount points, including "/", so that we no
|
|
# longer access the disk directly.
|
|
vfs.unmountAll()
|
|
|
|
# Mount the Multifile under /mf, by convention, and make that our
|
|
# "current directory".
|
|
vfs.mount(mf, MultifileRoot, vfs.MFReadOnly)
|
|
vfs.chdir(MultifileRoot)
|
|
|
|
# Make sure the directories on our standard Python path are mounted
|
|
# read-only, so we can still load Python.
|
|
for dirname in sys.path:
|
|
vfs.mount(dirname, dirname, vfs.MFReadOnly)
|
|
|
|
# Also mount some standard directories read-write (temporary and
|
|
# app-data directories).
|
|
tdir = Filename.temporary('', '')
|
|
for dirname in set([ tdir.getDirname(),
|
|
Filename.getTempDirectory().cStr(),
|
|
Filename.getUserAppdataDirectory().cStr(),
|
|
Filename.getCommonAppdataDirectory().cStr() ]):
|
|
vfs.mount(dirname, dirname, 0)
|
|
|
|
# Now set up Python to import this stuff.
|
|
VFSImporter.register()
|
|
sys.path = [ MultifileRoot ] + sys.path
|
|
|
|
# Put our root directory on the model-path and prc-path, too.
|
|
getModelPath().prependDirectory(MultifileRoot)
|
|
|
|
# Load the implicit App.prc file.
|
|
loadPrcFileData(AppPrcFilename, AppPrc)
|
|
|
|
# Load any prc files in the root. We have to load them
|
|
# explicitly, since the ConfigPageManager can't directly look
|
|
# inside the vfs.
|
|
for f in vfs.scanDirectory(MultifileRoot):
|
|
if f.getFilename().getExtension() == 'prc':
|
|
data = f.readFile(True)
|
|
loadPrcFileData(f.getFilename().cStr(), data)
|
|
|
|
# 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:
|
|
runPackedApp(sys.argv[1:])
|
|
except ArgumentError, e:
|
|
print e.args[0]
|
|
sys.exit(1)
|
|
|
|
|