better splash image management

This commit is contained in:
David Rose 2009-08-24 03:29:10 +00:00
parent f94479e13b
commit 29345bbc38
14 changed files with 335 additions and 196 deletions

View File

@ -138,6 +138,7 @@ class Packager:
self.version = None self.version = None
self.host = None self.host = None
self.p3dApplication = False self.p3dApplication = False
self.solo = False
self.compressionLevel = 0 self.compressionLevel = 0
self.importedMapsDir = 'imported_maps' self.importedMapsDir = 'imported_maps'
self.mainModule = None self.mainModule = None
@ -166,10 +167,6 @@ class Packager:
# far. # far.
self.freezer = FreezeTool.Freezer() self.freezer = FreezeTool.Freezer()
# Set this true to parse and build up the internal
# filelist, but not generate any output.
self.dryRun = False
def close(self): def close(self):
""" Writes out the contents of the current package. """ """ Writes out the contents of the current package. """
@ -198,18 +195,46 @@ class Packager:
# Every p3dapp requires panda3d. # Every p3dapp requires panda3d.
self.packager.do_require('panda3d') self.packager.do_require('panda3d')
if self.dryRun: # Check to see if any of the files are platform-specific.
self.multifile = None platformSpecific = False
for file in self.files:
if file.isExcluded(self):
# Skip this file.
continue
if file.platformSpecific:
platformSpecific = True
if platformSpecific and not self.platform:
self.platform = PandaSystem.getPlatform()
if not self.p3dApplication and self.platform and not self.version:
# We must have a version string for platform-specific
# packages. Use the first versioned string on our
# require list.
self.version = 'base'
for p2 in self.requires:
if p2.version:
self.version = p2.version
break
if self.solo:
self.installSolo()
else: else:
self.multifile = Multifile() self.installMultifile()
if self.p3dApplication: def installMultifile(self):
self.multifile.setHeaderPrefix('#! /usr/bin/env panda3d\n') """ Installs the package, either as a p3d application, or
as a true package. Either is implemented with a
Multifile. """
self.multifile = Multifile()
# Write the multifile to a temporary filename until we if self.p3dApplication:
# know enough to determine the output filename. self.multifile.setHeaderPrefix('#! /usr/bin/env panda3d\n')
multifileFilename = Filename.temporary('', self.packageName)
self.multifile.openReadWrite(multifileFilename) # Write the multifile to a temporary filename until we
# know enough to determine the output filename.
multifileFilename = Filename.temporary('', self.packageName)
self.multifile.openReadWrite(multifileFilename)
self.extracts = [] self.extracts = []
self.components = [] self.components = []
@ -306,13 +331,12 @@ class Packager:
# Skip this file. # Skip this file.
continue continue
if not self.dryRun: if ext == 'egg' or ext == 'bam':
if ext == 'egg' or ext == 'bam': # Skip model files this pass.
# Skip model files this pass. pass
pass else:
else: # Any other file.
# Any other file. self.addComponent(file)
self.addComponent(file)
# Finally, now add the model files. It's important to add # Finally, now add the model files. It's important to add
# these after we have added all of the texture files, so # these after we have added all of the texture files, so
@ -331,27 +355,17 @@ class Packager:
# Skip this file. # Skip this file.
continue continue
if not self.dryRun: if ext == 'egg':
if ext == 'egg': self.addEggFile(file)
self.addEggFile(file) elif ext == 'bam':
elif ext == 'bam': self.addBamFile(file)
self.addBamFile(file) else:
else: # Handled above.
# Handled above. pass
pass
# Now that we've processed all of the component files, # Now that we've processed all of the component files,
# (and set our platform if necessary), we can generate the # (and set our platform if necessary), we can generate the
# output filename and write the output files. # output filename and write the output files.
if not self.p3dApplication and not self.version:
# We must have a version string for packages. Use the
# first versioned string on our require list.
self.version = '0.0'
for p2 in self.requires:
if p2.version:
self.version = p2.version
break
self.packageBasename = self.packageName self.packageBasename = self.packageName
packageDir = self.packageName packageDir = self.packageName
@ -379,23 +393,63 @@ class Packager:
self.packageFullpath.makeDir() self.packageFullpath.makeDir()
self.packageFullpath.unlink() self.packageFullpath.unlink()
if not self.dryRun: if self.p3dApplication:
if self.p3dApplication: self.makeP3dInfo()
self.makeP3dInfo() self.multifile.repack()
self.multifile.repack() self.multifile.close()
self.multifile.close()
multifileFilename.renameTo(self.packageFullpath) multifileFilename.renameTo(self.packageFullpath)
if self.p3dApplication: if self.p3dApplication:
# Make the application file executable. # Make the application file executable.
os.chmod(self.packageFullpath.toOsSpecific(), 0755) os.chmod(self.packageFullpath.toOsSpecific(), 0755)
else: else:
self.compressMultifile() self.compressMultifile()
self.writeDescFile() self.writeDescFile()
self.writeImportDescFile() self.writeImportDescFile()
self.cleanup()
def installSolo(self):
""" Installs the package as a "solo", which means we
simply copy all files into the install directory. This is
primarily intended for the "coreapi" plugin, which is just
a single dll and a jpg file; but it can support other
kinds of similar "solo" packages as well. """
packageDir = self.packageName
if self.platform:
packageDir += '/' + self.platform
if self.version:
packageDir += '/' + self.version
installPath = Filename(self.packager.installDir, packageDir)
# Remove any files already in the installPath.
origFiles = vfs.scanDirectory(installPath)
if origFiles:
for origFile in origFiles:
origFile.getFilename().unlink()
if not self.files:
# No files, never mind.
return
Filename(installPath, '').makeDir()
for file in self.files:
if file.isExcluded(self):
# Skip this file.
continue
targetPath = Filename(installPath, file.newName)
targetPath.setBinary()
file.filename.setBinary()
if not file.filename.copyTo(targetPath):
print "Could not copy %s to %s" % (
file.filename, targetPath)
self.cleanup()
def cleanup(self):
# Now that all the files have been packed, we can delete # Now that all the files have been packed, we can delete
# the temporary files. # the temporary files.
for file in self.files: for file in self.files:
@ -1214,8 +1268,6 @@ class Packager:
# A table of all known packages by name. # A table of all known packages by name.
self.packages = {} self.packages = {}
self.dryRun = False
def addWindowsSearchPath(self, searchPath, varname): def addWindowsSearchPath(self, searchPath, varname):
""" Expands $varname, interpreting as a Windows-style search """ Expands $varname, interpreting as a Windows-style search
path, and adds its contents to the indicated DSearchPath. """ path, and adds its contents to the indicated DSearchPath. """
@ -1390,18 +1442,13 @@ class Packager:
# side-effect that the user can put arbitrary Python code in # side-effect that the user can put arbitrary Python code in
# there to control conditional execution, and such. # there to control conditional execution, and such.
# Set up the global and local dictionaries for exec. # Set up the namespace dictionary for exec.
globals = {} globals = {}
globals['__name__'] = packageDef.getBasenameWoExtension() globals['__name__'] = packageDef.getBasenameWoExtension()
globals['platform'] = PandaSystem.getPlatform() globals['platform'] = PandaSystem.getPlatform()
# The local dictionary is initially empty, but it will be # We'll stuff all of the predefined functions, and the
# filled with all the definitions at the module scope when we
# parse the pdef file.
locals = {}
# We'll stuff all of the predefined functions, and both of the
# predefined classes, in the global dictionary, so the pdef # predefined classes, in the global dictionary, so the pdef
# file can reference them. # file can reference them.
@ -1416,23 +1463,36 @@ class Packager:
globals['p3d'] = class_p3d globals['p3d'] = class_p3d
globals['package'] = class_package globals['package'] = class_package
globals['solo'] = class_solo
# Now exec the pdef file. Assuming there are no syntax # Now exec the pdef file. Assuming there are no syntax
# errors, and that the pdef file doesn't contain any really # errors, and that the pdef file doesn't contain any really
# crazy Python code, all this will do is fill in the # crazy Python code, all this will do is fill in the
# '__statements' list in the module scope. # '__statements' list in the module scope.
execfile(packageDef.toOsSpecific(), globals, locals)
# It appears that having a separate globals and locals
# dictionary causes problems with resolving symbols within a
# class scope. So, we just use one dictionary, the globals.
execfile(packageDef.toOsSpecific(), globals)
packages = [] packages = []
# Now iterate through the statements and operate on them. # Now iterate through the statements and operate on them.
statements = globals.get('__statements', [])
if not statements:
print "No packages defined."
try: try:
for (lineno, stype, name, args, kw) in locals['__statements']: for (lineno, stype, name, args, kw) in statements:
if stype == 'class': if stype == 'class':
classDef = locals[name] classDef = globals[name]
p3dApplication = (class_p3d in classDef.__bases__) p3dApplication = (class_p3d in classDef.__bases__)
self.beginPackage(name, p3dApplication = p3dApplication) solo = (class_solo in classDef.__bases__)
statements = classDef.__dict__['__statements'] self.beginPackage(name, p3dApplication = p3dApplication,
solo = solo)
statements = classDef.__dict__.get('__statements', [])
if not statements:
print "No files added to %s" % (name)
for (lineno, stype, name, args, kw) in statements: for (lineno, stype, name, args, kw) in statements:
if stype == 'class': if stype == 'class':
raise PackagerError, 'Nested classes not allowed' raise PackagerError, 'Nested classes not allowed'
@ -1512,22 +1572,6 @@ class Packager:
if descriptiveName: if descriptiveName:
self.hostDescriptiveName = descriptiveName self.hostDescriptiveName = descriptiveName
def do_modelPath(self, dirName):
""" Specifies an additional directory that will be searched
for required models, especially textures. Models in this
directory are not automatically added to the package unless
references to them are discovered; use dir() if you want to
add an entire directory hierarchy of models. """
newName = None
try:
command, dirName = words
except ValueError:
raise ArgumentError
getModelPath().appendDirectory(Filename.fromOsSpecific(dirName))
def __parseArgs(self, words, argList): def __parseArgs(self, words, argList):
args = {} args = {}
@ -1551,7 +1595,8 @@ class Packager:
del words[-1] del words[-1]
def beginPackage(self, packageName, p3dApplication = False): def beginPackage(self, packageName, p3dApplication = False,
solo = False):
""" Begins a new package specification. packageName is the """ Begins a new package specification. packageName is the
basename of the package. Follow this with a number of calls basename of the package. Follow this with a number of calls
to file() etc., and close the package with endPackage(). """ to file() etc., and close the package with endPackage(). """
@ -1563,7 +1608,7 @@ class Packager:
self.currentPackage = package self.currentPackage = package
package.p3dApplication = p3dApplication package.p3dApplication = p3dApplication
package.dryRun = self.dryRun package.solo = solo
def endPackage(self): def endPackage(self):
""" Closes the current package specification. This actually """ Closes the current package specification. This actually
@ -1939,20 +1984,19 @@ class Packager:
freezer.modules[newName] = freezer.modules[moduleName] freezer.modules[newName] = freezer.modules[moduleName]
freezer.done(compileToExe = compileToExe) freezer.done(compileToExe = compileToExe)
if not package.dryRun: dirname = ''
dirname = '' basename = filename
basename = filename if '/' in basename:
if '/' in basename: dirname, basename = filename.rsplit('/', 1)
dirname, basename = filename.rsplit('/', 1) dirname += '/'
dirname += '/'
basename = freezer.generateCode(basename, compileToExe = compileToExe) basename = freezer.generateCode(basename, compileToExe = compileToExe)
package.addFile(Filename(basename), newName = dirname + basename, package.addFile(Filename(basename), newName = dirname + basename,
deleteTemp = True, explicit = True, extract = True) deleteTemp = True, explicit = True, extract = True)
package.addExtensionModules() package.addExtensionModules()
if not package.platform: if not package.platform:
package.platform = PandaSystem.getPlatform() package.platform = PandaSystem.getPlatform()
# Reset the freezer for more Python files. # Reset the freezer for more Python files.
freezer.reset() freezer.reset()
@ -1964,9 +2008,9 @@ class Packager:
self.addFiles(args, **kw) self.addFiles(args, **kw)
def addFiles(self, filenames, text = None, newNameOrDir = None, def addFiles(self, filenames, text = None, newName = None,
extract = None, executable = None, deleteTemp = False, newDir = None, extract = None, executable = None,
literal = False): deleteTemp = False, literal = False):
""" Adds the indicated arbitrary files to the current package. """ Adds the indicated arbitrary files to the current package.
@ -1980,13 +2024,15 @@ class Packager:
extension. For instance, .py files may be automatically extension. For instance, .py files may be automatically
compiled and stored as Python modules. compiled and stored as Python modules.
If newNameOrDir ends in a slash character, it specifies the If newDir is not None, it specifies the directory in which the
directory in which the file should be placed. In this case, file should be placed. In this case, all files matched by the
all files matched by the filename expression are placed in the filename expression are placed in the named directory.
named directory. If newNameOrDir ends in something other than
a slash character, it specifies a new filename. In this case, If newName is not None, it specifies a new filename. In this
the filename expression must match only one file. If case, newDir is ignored, and the filename expression must
newNameOrDir is unspecified or None, the file is placed in the match only one file.
If newName and newDir are both None, the file is placed in the
toplevel directory, regardless of its source directory. toplevel directory, regardless of its source directory.
If text is nonempty, it contains the text of the file. In If text is nonempty, it contains the text of the file. In
@ -2042,17 +2088,16 @@ class Packager:
explicit = False explicit = False
files += thisFiles files += thisFiles
newName = None
prefix = '' prefix = ''
if newDir:
prefix = Filename(newDir).cStr()
if prefix[-1] != '/':
prefix += '/'
if newNameOrDir: if newName:
if newNameOrDir[-1] == '/': if len(files) != 1:
prefix = newNameOrDir message = 'Cannot install multiple files on target filename %s' % (newName)
else: raise PackagerError, message
newName = newNameOrDir
if len(files) != 1:
message = 'Cannot install multiple files on target filename %s' % (newName)
raise PackagerError, message
if text: if text:
if len(files) != 1: if len(files) != 1:
@ -2192,6 +2237,10 @@ class class_package:
__metaclass__ = metaclass_def __metaclass__ = metaclass_def
pass pass
class class_solo:
__metaclass__ = metaclass_def
pass
class func_closure: class func_closure:
""" This class is used to create a closure on the function name, """ This class is used to create a closure on the function name,

View File

@ -92,9 +92,12 @@ class ContentsMaker:
print >> f, '<?xml version="1.0" encoding="utf-8" ?>' print >> f, '<?xml version="1.0" encoding="utf-8" ?>'
print >> f, '' print >> f, ''
print >> f, contentsLine print >> f, contentsLine
for type, packageName, packagePlatform, packageVersion, file in self.packages: for type, packageName, packagePlatform, packageVersion, file, solo in self.packages:
print >> f, ' <%s name="%s" platform="%s" version="%s" %s />' % ( extra = ''
type, packageName, packagePlatform or '', packageVersion, file.getParams()) if solo:
extra += 'solo="1" '
print >> f, ' <%s name="%s" platform="%s" version="%s" %s%s />' % (
type, packageName, packagePlatform or '', packageVersion or '', extra, file.getParams())
print >> f, '</contents>' print >> f, '</contents>'
f.close() f.close()
@ -142,20 +145,23 @@ class ContentsMaker:
localpath = dirpath[len(prefix):].replace(os.sep, '/') + '/' localpath = dirpath[len(prefix):].replace(os.sep, '/') + '/'
xml = dirpath[len(prefix):].replace(os.sep, '_') + '.xml' xml = dirpath[len(prefix):].replace(os.sep, '_') + '.xml'
type = 'package' solo = False
# A special case: the "plugin" and "coreapi" directories # A special case: if a directory contains just one file,
# don't have xml files, just dll's. # it's a "solo", not an xml package.
if xml.startswith('plugin_') or xml.startswith('coreapi_'): if len(filenames) == 1 and not filenames[0].endswith('.xml'):
if filenames: xml = filenames[0]
assert len(filenames) == 1 solo = True
xml = filenames[0]
type = 'plugin'
if xml not in filenames: if xml not in filenames:
continue continue
if localpath.count('/') == 1:
packageName, junk = localpath.split('/')
packageVersion = None
packagePlatform = None
if localpath.count('/') == 2: elif localpath.count('/') == 2:
packageName, packageVersion, junk = localpath.split('/') packageName, packageVersion, junk = localpath.split('/')
packagePlatform = None packagePlatform = None
@ -167,9 +173,9 @@ class ContentsMaker:
file = FileSpec(localpath + xml, file = FileSpec(localpath + xml,
os.path.join(self.installDir, localpath + xml)) os.path.join(self.installDir, localpath + xml))
print file.filename print file.filename
self.packages.append((type, packageName, packagePlatform, packageVersion, file)) self.packages.append(('package', packageName, packagePlatform, packageVersion, file, solo))
if type == 'package': if not solo:
# Look for an _import.xml file, too. # Look for an _import.xml file, too.
xml = xml[:-4] + '_import.xml' xml = xml[:-4] + '_import.xml'
try: try:
@ -179,7 +185,7 @@ class ContentsMaker:
file = None file = None
if file: if file:
print file.filename print file.filename
self.packages.append(('import', packageName, packagePlatform, packageVersion, file)) self.packages.append(('import', packageName, packagePlatform, packageVersion, file, False))
def makeContents(args): def makeContents(args):

View File

@ -1,3 +1,5 @@
from pandac.PandaModules import getModelPath, Filename
# This file defines a number of standard "packages" that correspond to # This file defines a number of standard "packages" that correspond to
# a Panda3D distribution. These packages are built by passing this # a Panda3D distribution. These packages are built by passing this
# file to the ppackage utility, either as a packaged application, or # file to the ppackage utility, either as a packaged application, or
@ -12,6 +14,19 @@
# and then a number of smaller, optional packages, which may or may # and then a number of smaller, optional packages, which may or may
# not be needed by any one particular application. # not be needed by any one particular application.
class coreapi(solo):
# The special "coreapi" package. As a "solo", this is just a
# single .dll (or dylib, or whatever).
file('p3d_plugin.dll')
class splash(solo):
# We also store the default splash image, as "solo". Well, it
# has to go somewhere.
splashFilename = Filename('maps/panda_splash.jpg')
if splashFilename.resolveFilename(getModelPath().getValue()):
file(splashFilename, newName = 'splash.jpg')
else:
print "Could not locate %s" % (splashFilename)
class panda3d(package): class panda3d(package):
# The core Panda3D package. Contains Python and most of the graphics # The core Panda3D package. Contains Python and most of the graphics

View File

@ -146,6 +146,7 @@ get_package(const string &package_name, const string &package_version) {
bool P3DHost:: bool P3DHost::
get_package_desc_file(FileSpec &desc_file, // out get_package_desc_file(FileSpec &desc_file, // out
string &package_platform, // out string &package_platform, // out
bool &package_solo, // out
const string &package_name, // in const string &package_name, // in
const string &package_version) { // in const string &package_version) { // in
if (_xcontents == NULL) { if (_xcontents == NULL) {
@ -161,6 +162,7 @@ get_package_desc_file(FileSpec &desc_file, // out
const char *name = xpackage->Attribute("name"); const char *name = xpackage->Attribute("name");
const char *platform = xpackage->Attribute("platform"); const char *platform = xpackage->Attribute("platform");
const char *version = xpackage->Attribute("version"); const char *version = xpackage->Attribute("version");
const char *solo = xpackage->Attribute("solo");
if (name != NULL && platform != NULL && version != NULL && if (name != NULL && platform != NULL && version != NULL &&
package_name == name && package_name == name &&
inst_mgr->get_platform() == platform && inst_mgr->get_platform() == platform &&
@ -168,6 +170,10 @@ get_package_desc_file(FileSpec &desc_file, // out
// Here's the matching package definition. // Here's the matching package definition.
desc_file.load_xml(xpackage); desc_file.load_xml(xpackage);
package_platform = platform; package_platform = platform;
package_solo = false;
if (solo != NULL) {
package_solo = (atoi(solo) != 0);
}
return true; return true;
} }
@ -180,6 +186,7 @@ get_package_desc_file(FileSpec &desc_file, // out
const char *name = xpackage->Attribute("name"); const char *name = xpackage->Attribute("name");
const char *platform = xpackage->Attribute("platform"); const char *platform = xpackage->Attribute("platform");
const char *version = xpackage->Attribute("version"); const char *version = xpackage->Attribute("version");
const char *solo = xpackage->Attribute("solo");
if (platform == NULL) { if (platform == NULL) {
platform = ""; platform = "";
} }
@ -190,6 +197,10 @@ get_package_desc_file(FileSpec &desc_file, // out
// Here's the matching package definition. // Here's the matching package definition.
desc_file.load_xml(xpackage); desc_file.load_xml(xpackage);
package_platform = platform; package_platform = platform;
package_solo = false;
if (solo != NULL) {
package_solo = (atoi(solo) != 0);
}
return true; return true;
} }

View File

@ -47,6 +47,7 @@ public:
const string &package_version); const string &package_version);
bool get_package_desc_file(FileSpec &desc_file, bool get_package_desc_file(FileSpec &desc_file,
string &package_platform, string &package_platform,
bool &package_solo,
const string &package_name, const string &package_name,
const string &package_version); const string &package_version);

View File

@ -61,6 +61,7 @@ P3DInstance(P3D_request_ready_func *func,
_user_data = user_data; _user_data = user_data;
_request_pending = false; _request_pending = false;
_temp_p3d_filename = NULL; _temp_p3d_filename = NULL;
_splash_package = NULL;
_temp_splash_image = NULL; _temp_splash_image = NULL;
_got_fparams = false; _got_fparams = false;
_got_wparams = false; _got_wparams = false;
@ -121,6 +122,10 @@ P3DInstance::
(*pi)->remove_instance(this); (*pi)->remove_instance(this);
} }
_packages.clear(); _packages.clear();
if (_splash_package != NULL) {
_splash_package->remove_instance(this);
_splash_package = NULL;
}
if (_splash_window != NULL) { if (_splash_window != NULL) {
delete _splash_window; delete _splash_window;
@ -1201,32 +1206,37 @@ make_splash_window() {
_splash_window->set_wparams(_wparams); _splash_window->set_wparams(_wparams);
_splash_window->set_install_label(_install_label); _splash_window->set_install_label(_install_label);
string splash_image_url = _fparams.lookup_token("splash_img"); P3DInstanceManager *inst_mgr = P3DInstanceManager::get_global_ptr();
if (!_fparams.has_token("splash_img")) { if (!_fparams.has_token("splash_img")) {
// No specific splash image is specified; get the default splash // No specific splash image is specified; get the default splash
// image. // image. We do this via the P3DPackage interface, so we can
splash_image_url = PANDA_PACKAGE_HOST_URL; // use the cached version on disk if it's good.
if (!splash_image_url.empty() && splash_image_url[splash_image_url.size() - 1] != '/') { P3DHost *host = inst_mgr->get_host(PANDA_PACKAGE_HOST_URL);
splash_image_url += "/"; _splash_package = host->get_package("splash", "");
_splash_package->add_instance(this);
} else {
// We have an explicit splash image specified, so just download it
// directly. This one won't be cached locally (though the browser
// might be free to cache it).
string splash_image_url = _fparams.lookup_token("splash_img");
if (splash_image_url.empty()) {
// No splash image. Never mind.
return;
} }
splash_image_url += "coreapi/splash.jpg";
// Make a temporary file to receive the splash image.
assert(_temp_splash_image == NULL);
_temp_splash_image = new P3DTemporaryFile(".jpg");
// Start downloading the requested splash image.
SplashDownload *download = new SplashDownload(this);
download->set_url(splash_image_url);
download->set_filename(_temp_splash_image->get_filename());
start_download(download);
} }
if (splash_image_url.empty()) {
// No splash image. Never mind.
return;
}
// Make a temporary file to receive the splash image.
assert(_temp_splash_image == NULL);
_temp_splash_image = new P3DTemporaryFile(".jpg");
// Start downloading the requested splash image.
SplashDownload *download = new SplashDownload(this);
download->set_url(splash_image_url);
download->set_filename(_temp_splash_image->get_filename());
start_download(download);
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -1238,6 +1248,16 @@ make_splash_window() {
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
void P3DInstance:: void P3DInstance::
report_package_info_ready(P3DPackage *package) { report_package_info_ready(P3DPackage *package) {
if (package == _splash_package) {
// A special case: we just downloaded the splash image, via the
// package interface.
if (_splash_window != NULL) {
string filename = package->get_desc_file_pathname();
_splash_window->set_image_filename(filename, false);
}
return;
}
if (get_packages_info_ready()) { if (get_packages_info_ready()) {
// All packages are ready to go. Let's start some download // All packages are ready to go. Let's start some download
// action. // action.
@ -1669,8 +1689,9 @@ void P3DInstance::SplashDownload::
download_finished(bool success) { download_finished(bool success) {
P3DFileDownload::download_finished(success); P3DFileDownload::download_finished(success);
if (success) { if (success) {
// We've successfully downloaded the splash image. Put it // We've successfully downloaded the splash image (directly, not
// onscreen if our splash window still exists. // via the package interface). Put it onscreen if our splash
// window still exists.
if (_inst->_splash_window != NULL) { if (_inst->_splash_window != NULL) {
_inst->_splash_window->set_image_filename(get_filename(), true); _inst->_splash_window->set_image_filename(get_filename(), true);
} }

View File

@ -147,6 +147,7 @@ private:
P3DMainObject *_panda_script_object; P3DMainObject *_panda_script_object;
P3DTemporaryFile *_temp_p3d_filename; P3DTemporaryFile *_temp_p3d_filename;
P3DPackage *_splash_package;
P3DTemporaryFile *_temp_splash_image; P3DTemporaryFile *_temp_splash_image;
bool _got_fparams; bool _got_fparams;

View File

@ -256,11 +256,6 @@ paint_window() {
Boolean portChanged = false; Boolean portChanged = false;
if (_toplevel_window != NULL) { if (_toplevel_window != NULL) {
/*
GetPort(&portSave);
SetPortWindowPort(_toplevel_window);
BeginUpdate(_toplevel_window);
*/
GetPort(&out_port); GetPort(&out_port);
} else { } else {

View File

@ -139,3 +139,16 @@ inline const string &P3DPackage::
get_package_display_name() const { get_package_display_name() const {
return _package_display_name; return _package_display_name;
} }
////////////////////////////////////////////////////////////////////
// Function: P3DPackage::get_desc_file_pathname
// Access: Public
// Description: Returns the full path to the package's desc file. If
// this is a "solo" type package, the desc file itself
// represents the entire contents of the package.
////////////////////////////////////////////////////////////////////
inline const string &P3DPackage::
get_desc_file_pathname() const {
return _desc_file_pathname;
}

View File

@ -43,9 +43,16 @@ P3DPackage(P3DHost *host, const string &package_name,
_package_version(package_version) _package_version(package_version)
{ {
_package_fullname = _package_name; _package_fullname = _package_name;
_package_dir = _host->get_host_dir() + string("/packages/") + _package_name; _package_dir = _host->get_host_dir() + string("/") + _package_name;
_package_fullname += string("_") + _package_version;
_package_dir += string("/") + _package_version; if (!_package_version.empty()) {
_package_fullname += string("_") + _package_version;
_package_dir += string("/") + _package_version;
}
// This is set true if the package is a "solo", i.e. a single
// file, instead of an xml file and a multifile to unpack.
_package_solo = false;
_temp_contents_file = NULL; _temp_contents_file = NULL;
@ -59,9 +66,6 @@ P3DPackage(P3DHost *host, const string &package_name,
// Ensure the package directory exists; create it if it does not. // Ensure the package directory exists; create it if it does not.
mkdir_complete(_package_dir, nout); mkdir_complete(_package_dir, nout);
_desc_file_basename = _package_fullname + ".xml";
_desc_file_pathname = _package_dir + "/" + _desc_file_basename;
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
@ -258,7 +262,8 @@ download_desc_file() {
// exists, and is consistent with the server contents file, we don't // exists, and is consistent with the server contents file, we don't
// need to re-download it. // need to re-download it.
FileSpec desc_file; FileSpec desc_file;
if (!_host->get_package_desc_file(desc_file, _package_platform, if (!_host->get_package_desc_file(desc_file, _package_platform,
_package_solo,
_package_name, _package_version)) { _package_name, _package_version)) {
nout << "Couldn't find package " << _package_fullname nout << "Couldn't find package " << _package_fullname
<< " in contents file.\n"; << " in contents file.\n";
@ -266,21 +271,33 @@ download_desc_file() {
} }
// The desc file might have a different path on the host server than // The desc file might have a different path on the host server than
// it has locally, because we strip out the platform locally. // it has locally, because we strip out the platform directory
// Adjust desc_file to point to the local file. // locally. Adjust desc_file to point to the local file.
string url_filename = desc_file.get_filename(); string url_filename = desc_file.get_filename();
_desc_file_basename = url_filename;
size_t slash = _desc_file_basename.rfind('/');
if (slash != string::npos) {
_desc_file_basename = _desc_file_basename.substr(slash + 1);
}
desc_file.set_filename(_desc_file_basename); desc_file.set_filename(_desc_file_basename);
assert (desc_file.get_pathname(_package_dir) == _desc_file_pathname); _desc_file_pathname = desc_file.get_pathname(_package_dir);
if (!desc_file.full_verify(_package_dir)) { if (!desc_file.full_verify(_package_dir)) {
nout << _desc_file_pathname << " is stale.\n"; nout << _desc_file_pathname << " is stale.\n";
} else { } else {
// The desc file is current. Attempt to read it. // The desc file is current. Attempt to read it.
TiXmlDocument doc(_desc_file_pathname.c_str()); if (_package_solo) {
if (doc.LoadFile()) { // No need to load it: the desc file *is* the package.
got_desc_file(&doc, false); report_done(true);
return; return;
} else {
TiXmlDocument doc(_desc_file_pathname.c_str());
if (doc.LoadFile()) {
got_desc_file(&doc, false);
return;
}
} }
} }
@ -303,14 +320,21 @@ desc_file_download_finished(bool success) {
return; return;
} }
TiXmlDocument doc(_desc_file_pathname.c_str()); if (_package_solo) {
if (!doc.LoadFile()) { // No need to load it: the desc file *is* the package.
nout << "Couldn't read " << _desc_file_pathname << "\n"; report_done(true);
report_done(false);
return; return;
}
got_desc_file(&doc, true); } else {
TiXmlDocument doc(_desc_file_pathname.c_str());
if (!doc.LoadFile()) {
nout << "Couldn't read " << _desc_file_pathname << "\n";
report_done(false);
return;
}
got_desc_file(&doc, true);
}
} }
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////

View File

@ -57,6 +57,8 @@ public:
inline const string &get_package_version() const; inline const string &get_package_version() const;
inline const string &get_package_display_name() const; inline const string &get_package_display_name() const;
inline const string &get_desc_file_pathname() const;
void add_instance(P3DInstance *inst); void add_instance(P3DInstance *inst);
void remove_instance(P3DInstance *inst); void remove_instance(P3DInstance *inst);
@ -112,6 +114,7 @@ private:
string _package_name; string _package_name;
string _package_version; string _package_version;
string _package_platform; string _package_platform;
bool _package_solo;
string _package_display_name; string _package_display_name;
string _package_fullname; string _package_fullname;
string _package_dir; string _package_dir;

View File

@ -735,23 +735,23 @@ read_contents_file(const string &contents_filename) {
TiXmlElement *xcontents = doc.FirstChildElement("contents"); TiXmlElement *xcontents = doc.FirstChildElement("contents");
if (xcontents != NULL) { if (xcontents != NULL) {
TiXmlElement *xplugin = xcontents->FirstChildElement("plugin"); TiXmlElement *xpackage = xcontents->FirstChildElement("package");
while (xplugin != NULL) { while (xpackage != NULL) {
const char *name = xplugin->Attribute("name"); const char *name = xpackage->Attribute("name");
if (name != NULL && strcmp(name, "coreapi") == 0) { if (name != NULL && strcmp(name, "coreapi") == 0) {
const char *platform = xplugin->Attribute("platform"); const char *platform = xpackage->Attribute("platform");
if (platform != NULL && strcmp(platform, DTOOL_PLATFORM) == 0) { if (platform != NULL && strcmp(platform, DTOOL_PLATFORM) == 0) {
get_core_api(xplugin); get_core_api(xpackage);
return true; return true;
} }
} }
xplugin = xplugin->NextSiblingElement("plugin"); xpackage = xpackage->NextSiblingElement("package");
} }
} }
// Couldn't find the coreapi plugin description. // Couldn't find the coreapi package description.
nout << "No coreapi plugin defined in contents file for " nout << "No coreapi package defined in contents file for "
<< DTOOL_PLATFORM << "\n"; << DTOOL_PLATFORM << "\n";
return false; return false;
} }
@ -851,8 +851,8 @@ feed_file(PPDownloadRequest *req, const string &filename) {
// if necessary. // if necessary.
//////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////
void PPInstance:: void PPInstance::
get_core_api(TiXmlElement *xplugin) { get_core_api(TiXmlElement *xpackage) {
_core_api_dll.load_xml(xplugin); _core_api_dll.load_xml(xpackage);
if (_core_api_dll.quick_verify(_root_dir)) { if (_core_api_dll.quick_verify(_root_dir)) {
// The DLL file is good. Just load it. // The DLL file is good. Just load it.

View File

@ -72,7 +72,7 @@ private:
void feed_file(PPDownloadRequest *req, const string &filename); void feed_file(PPDownloadRequest *req, const string &filename);
bool read_contents_file(const string &contents_filename); bool read_contents_file(const string &contents_filename);
void get_core_api(TiXmlElement *xplugin); void get_core_api(TiXmlElement *xpackage);
void downloaded_plugin(const string &filename); void downloaded_plugin(const string &filename);
void do_load_plugin(); void do_load_plugin();

View File

@ -394,18 +394,18 @@ read_contents_file(Filename contents_filename, const string &download_url,
TiXmlElement *xcontents = doc.FirstChildElement("contents"); TiXmlElement *xcontents = doc.FirstChildElement("contents");
if (xcontents != NULL) { if (xcontents != NULL) {
TiXmlElement *xplugin = xcontents->FirstChildElement("plugin"); TiXmlElement *xpackage = xcontents->FirstChildElement("package");
while (xplugin != NULL) { while (xpackage != NULL) {
const char *name = xplugin->Attribute("name"); const char *name = xpackage->Attribute("name");
if (name != NULL && strcmp(name, "coreapi") == 0) { if (name != NULL && strcmp(name, "coreapi") == 0) {
const char *xplatform = xplugin->Attribute("platform"); const char *xplatform = xpackage->Attribute("platform");
if (xplatform != NULL && strcmp(xplatform, this_platform.c_str()) == 0) { if (xplatform != NULL && strcmp(xplatform, this_platform.c_str()) == 0) {
return get_core_api(contents_filename, download_url, return get_core_api(contents_filename, download_url,
this_platform, verify_contents, xplugin); this_platform, verify_contents, xpackage);
} }
} }
xplugin = xplugin->NextSiblingElement("plugin"); xpackage = xpackage->NextSiblingElement("package");
} }
} }
@ -426,8 +426,8 @@ read_contents_file(Filename contents_filename, const string &download_url,
bool Panda3D:: bool Panda3D::
get_core_api(const Filename &contents_filename, const string &download_url, get_core_api(const Filename &contents_filename, const string &download_url,
const string &this_platform, bool verify_contents, const string &this_platform, bool verify_contents,
TiXmlElement *xplugin) { TiXmlElement *xpackage) {
_core_api_dll.load_xml(xplugin); _core_api_dll.load_xml(xpackage);
if (!_core_api_dll.quick_verify(_root_dir)) { if (!_core_api_dll.quick_verify(_root_dir)) {
// The DLL file needs to be downloaded. Go get it. // The DLL file needs to be downloaded. Go get it.