diff --git a/direct/src/p3d/Packager.py b/direct/src/p3d/Packager.py index af02509fe1..dd84b6640d 100644 --- a/direct/src/p3d/Packager.py +++ b/direct/src/p3d/Packager.py @@ -138,6 +138,7 @@ class Packager: self.version = None self.host = None self.p3dApplication = False + self.solo = False self.compressionLevel = 0 self.importedMapsDir = 'imported_maps' self.mainModule = None @@ -166,10 +167,6 @@ class Packager: # far. 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): """ Writes out the contents of the current package. """ @@ -198,18 +195,46 @@ class Packager: # Every p3dapp requires panda3d. self.packager.do_require('panda3d') - if self.dryRun: - self.multifile = None + # Check to see if any of the files are platform-specific. + 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: - self.multifile = Multifile() + self.installMultifile() - if self.p3dApplication: - self.multifile.setHeaderPrefix('#! /usr/bin/env panda3d\n') + def installMultifile(self): + """ 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 - # know enough to determine the output filename. - multifileFilename = Filename.temporary('', self.packageName) - self.multifile.openReadWrite(multifileFilename) + if self.p3dApplication: + self.multifile.setHeaderPrefix('#! /usr/bin/env panda3d\n') + + # 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.components = [] @@ -306,13 +331,12 @@ class Packager: # Skip this file. continue - if not self.dryRun: - if ext == 'egg' or ext == 'bam': - # Skip model files this pass. - pass - else: - # Any other file. - self.addComponent(file) + if ext == 'egg' or ext == 'bam': + # Skip model files this pass. + pass + else: + # Any other file. + self.addComponent(file) # Finally, now add the model files. It's important to add # these after we have added all of the texture files, so @@ -331,27 +355,17 @@ class Packager: # Skip this file. continue - if not self.dryRun: - if ext == 'egg': - self.addEggFile(file) - elif ext == 'bam': - self.addBamFile(file) - else: - # Handled above. - pass + if ext == 'egg': + self.addEggFile(file) + elif ext == 'bam': + self.addBamFile(file) + else: + # Handled above. + pass # Now that we've processed all of the component files, # (and set our platform if necessary), we can generate the # 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 packageDir = self.packageName @@ -379,23 +393,63 @@ class Packager: self.packageFullpath.makeDir() self.packageFullpath.unlink() - if not self.dryRun: - if self.p3dApplication: - self.makeP3dInfo() - self.multifile.repack() - self.multifile.close() + if self.p3dApplication: + self.makeP3dInfo() + self.multifile.repack() + self.multifile.close() - multifileFilename.renameTo(self.packageFullpath) + multifileFilename.renameTo(self.packageFullpath) - if self.p3dApplication: - # Make the application file executable. - os.chmod(self.packageFullpath.toOsSpecific(), 0755) - else: - self.compressMultifile() - self.writeDescFile() - self.writeImportDescFile() - + if self.p3dApplication: + # Make the application file executable. + os.chmod(self.packageFullpath.toOsSpecific(), 0755) + else: + self.compressMultifile() + self.writeDescFile() + 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 # the temporary files. for file in self.files: @@ -1214,8 +1268,6 @@ class Packager: # A table of all known packages by name. self.packages = {} - self.dryRun = False - def addWindowsSearchPath(self, searchPath, varname): """ Expands $varname, interpreting as a Windows-style search 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 # 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['__name__'] = packageDef.getBasenameWoExtension() globals['platform'] = PandaSystem.getPlatform() - # The local dictionary is initially empty, but it will be - # 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 + # We'll stuff all of the predefined functions, and the # predefined classes, in the global dictionary, so the pdef # file can reference them. @@ -1416,23 +1463,36 @@ class Packager: globals['p3d'] = class_p3d globals['package'] = class_package + globals['solo'] = class_solo # Now exec the pdef file. Assuming there are no syntax # errors, and that the pdef file doesn't contain any really # crazy Python code, all this will do is fill in the # '__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 = [] # Now iterate through the statements and operate on them. + statements = globals.get('__statements', []) + if not statements: + print "No packages defined." + try: - for (lineno, stype, name, args, kw) in locals['__statements']: + for (lineno, stype, name, args, kw) in statements: if stype == 'class': - classDef = locals[name] + classDef = globals[name] p3dApplication = (class_p3d in classDef.__bases__) - self.beginPackage(name, p3dApplication = p3dApplication) - statements = classDef.__dict__['__statements'] + solo = (class_solo in classDef.__bases__) + 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: if stype == 'class': raise PackagerError, 'Nested classes not allowed' @@ -1512,22 +1572,6 @@ class Packager: if 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): args = {} @@ -1551,7 +1595,8 @@ class Packager: 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 basename of the package. Follow this with a number of calls to file() etc., and close the package with endPackage(). """ @@ -1563,7 +1608,7 @@ class Packager: self.currentPackage = package package.p3dApplication = p3dApplication - package.dryRun = self.dryRun + package.solo = solo def endPackage(self): """ Closes the current package specification. This actually @@ -1939,20 +1984,19 @@ class Packager: freezer.modules[newName] = freezer.modules[moduleName] freezer.done(compileToExe = compileToExe) - if not package.dryRun: - dirname = '' - basename = filename - if '/' in basename: - dirname, basename = filename.rsplit('/', 1) - dirname += '/' + dirname = '' + basename = filename + if '/' in basename: + dirname, basename = filename.rsplit('/', 1) + dirname += '/' - basename = freezer.generateCode(basename, compileToExe = compileToExe) + basename = freezer.generateCode(basename, compileToExe = compileToExe) - package.addFile(Filename(basename), newName = dirname + basename, - deleteTemp = True, explicit = True, extract = True) - package.addExtensionModules() - if not package.platform: - package.platform = PandaSystem.getPlatform() + package.addFile(Filename(basename), newName = dirname + basename, + deleteTemp = True, explicit = True, extract = True) + package.addExtensionModules() + if not package.platform: + package.platform = PandaSystem.getPlatform() # Reset the freezer for more Python files. freezer.reset() @@ -1964,9 +2008,9 @@ class Packager: self.addFiles(args, **kw) - def addFiles(self, filenames, text = None, newNameOrDir = None, - extract = None, executable = None, deleteTemp = False, - literal = False): + def addFiles(self, filenames, text = None, newName = None, + newDir = None, extract = None, executable = None, + deleteTemp = False, literal = False): """ Adds the indicated arbitrary files to the current package. @@ -1980,13 +2024,15 @@ class Packager: extension. For instance, .py files may be automatically compiled and stored as Python modules. - If newNameOrDir ends in a slash character, it specifies the - directory in which the file should be placed. In this case, - all files matched by the filename expression are placed in the - named directory. If newNameOrDir ends in something other than - a slash character, it specifies a new filename. In this case, - the filename expression must match only one file. If - newNameOrDir is unspecified or None, the file is placed in the + If newDir is not None, it specifies the directory in which the + file should be placed. In this case, all files matched by the + filename expression are placed in the named directory. + + If newName is not None, it specifies a new filename. In this + case, newDir is ignored, and the filename expression must + match only one file. + + If newName and newDir are both None, the file is placed in the toplevel directory, regardless of its source directory. If text is nonempty, it contains the text of the file. In @@ -2042,17 +2088,16 @@ class Packager: explicit = False files += thisFiles - newName = None prefix = '' + if newDir: + prefix = Filename(newDir).cStr() + if prefix[-1] != '/': + prefix += '/' - if newNameOrDir: - if newNameOrDir[-1] == '/': - prefix = newNameOrDir - else: - newName = newNameOrDir - if len(files) != 1: - message = 'Cannot install multiple files on target filename %s' % (newName) - raise PackagerError, message + if newName: + if len(files) != 1: + message = 'Cannot install multiple files on target filename %s' % (newName) + raise PackagerError, message if text: if len(files) != 1: @@ -2192,6 +2237,10 @@ class class_package: __metaclass__ = metaclass_def pass +class class_solo: + __metaclass__ = metaclass_def + pass + class func_closure: """ This class is used to create a closure on the function name, diff --git a/direct/src/p3d/make_contents.py b/direct/src/p3d/make_contents.py index a6122543fc..6386a108a5 100755 --- a/direct/src/p3d/make_contents.py +++ b/direct/src/p3d/make_contents.py @@ -92,9 +92,12 @@ class ContentsMaker: print >> f, '' print >> f, '' print >> f, contentsLine - for type, packageName, packagePlatform, packageVersion, file in self.packages: - print >> f, ' <%s name="%s" platform="%s" version="%s" %s />' % ( - type, packageName, packagePlatform or '', packageVersion, file.getParams()) + for type, packageName, packagePlatform, packageVersion, file, solo in self.packages: + extra = '' + 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, '' f.close() @@ -142,20 +145,23 @@ class ContentsMaker: localpath = dirpath[len(prefix):].replace(os.sep, '/') + '/' xml = dirpath[len(prefix):].replace(os.sep, '_') + '.xml' - type = 'package' + solo = False - # A special case: the "plugin" and "coreapi" directories - # don't have xml files, just dll's. - if xml.startswith('plugin_') or xml.startswith('coreapi_'): - if filenames: - assert len(filenames) == 1 - xml = filenames[0] - type = 'plugin' + # A special case: if a directory contains just one file, + # it's a "solo", not an xml package. + if len(filenames) == 1 and not filenames[0].endswith('.xml'): + xml = filenames[0] + solo = True if xml not in filenames: 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('/') packagePlatform = None @@ -167,9 +173,9 @@ class ContentsMaker: file = FileSpec(localpath + xml, os.path.join(self.installDir, localpath + xml)) 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. xml = xml[:-4] + '_import.xml' try: @@ -179,7 +185,7 @@ class ContentsMaker: file = None if file: print file.filename - self.packages.append(('import', packageName, packagePlatform, packageVersion, file)) + self.packages.append(('import', packageName, packagePlatform, packageVersion, file, False)) def makeContents(args): diff --git a/direct/src/p3d/panda3d.pdef b/direct/src/p3d/panda3d.pdef index 38e7e58dfc..d986ea78d5 100755 --- a/direct/src/p3d/panda3d.pdef +++ b/direct/src/p3d/panda3d.pdef @@ -1,3 +1,5 @@ +from pandac.PandaModules import getModelPath, Filename + # This file defines a number of standard "packages" that correspond to # a Panda3D distribution. These packages are built by passing this # 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 # 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): # The core Panda3D package. Contains Python and most of the graphics diff --git a/direct/src/plugin/p3dHost.cxx b/direct/src/plugin/p3dHost.cxx index a0c2270694..4c3eddcf03 100644 --- a/direct/src/plugin/p3dHost.cxx +++ b/direct/src/plugin/p3dHost.cxx @@ -146,6 +146,7 @@ get_package(const string &package_name, const string &package_version) { bool P3DHost:: get_package_desc_file(FileSpec &desc_file, // out string &package_platform, // out + bool &package_solo, // out const string &package_name, // in const string &package_version) { // in if (_xcontents == NULL) { @@ -161,6 +162,7 @@ get_package_desc_file(FileSpec &desc_file, // out const char *name = xpackage->Attribute("name"); const char *platform = xpackage->Attribute("platform"); const char *version = xpackage->Attribute("version"); + const char *solo = xpackage->Attribute("solo"); if (name != NULL && platform != NULL && version != NULL && package_name == name && inst_mgr->get_platform() == platform && @@ -168,6 +170,10 @@ get_package_desc_file(FileSpec &desc_file, // out // Here's the matching package definition. desc_file.load_xml(xpackage); package_platform = platform; + package_solo = false; + if (solo != NULL) { + package_solo = (atoi(solo) != 0); + } return true; } @@ -180,6 +186,7 @@ get_package_desc_file(FileSpec &desc_file, // out const char *name = xpackage->Attribute("name"); const char *platform = xpackage->Attribute("platform"); const char *version = xpackage->Attribute("version"); + const char *solo = xpackage->Attribute("solo"); if (platform == NULL) { platform = ""; } @@ -190,6 +197,10 @@ get_package_desc_file(FileSpec &desc_file, // out // Here's the matching package definition. desc_file.load_xml(xpackage); package_platform = platform; + package_solo = false; + if (solo != NULL) { + package_solo = (atoi(solo) != 0); + } return true; } diff --git a/direct/src/plugin/p3dHost.h b/direct/src/plugin/p3dHost.h index 27e17c7d70..d8376d57b4 100644 --- a/direct/src/plugin/p3dHost.h +++ b/direct/src/plugin/p3dHost.h @@ -47,6 +47,7 @@ public: const string &package_version); bool get_package_desc_file(FileSpec &desc_file, string &package_platform, + bool &package_solo, const string &package_name, const string &package_version); diff --git a/direct/src/plugin/p3dInstance.cxx b/direct/src/plugin/p3dInstance.cxx index 2ff57d9728..34be343d3a 100644 --- a/direct/src/plugin/p3dInstance.cxx +++ b/direct/src/plugin/p3dInstance.cxx @@ -61,6 +61,7 @@ P3DInstance(P3D_request_ready_func *func, _user_data = user_data; _request_pending = false; _temp_p3d_filename = NULL; + _splash_package = NULL; _temp_splash_image = NULL; _got_fparams = false; _got_wparams = false; @@ -121,6 +122,10 @@ P3DInstance:: (*pi)->remove_instance(this); } _packages.clear(); + if (_splash_package != NULL) { + _splash_package->remove_instance(this); + _splash_package = NULL; + } if (_splash_window != NULL) { delete _splash_window; @@ -1201,32 +1206,37 @@ make_splash_window() { _splash_window->set_wparams(_wparams); _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")) { // No specific splash image is specified; get the default splash - // image. - splash_image_url = PANDA_PACKAGE_HOST_URL; - if (!splash_image_url.empty() && splash_image_url[splash_image_url.size() - 1] != '/') { - splash_image_url += "/"; + // image. We do this via the P3DPackage interface, so we can + // use the cached version on disk if it's good. + P3DHost *host = inst_mgr->get_host(PANDA_PACKAGE_HOST_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:: 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()) { // All packages are ready to go. Let's start some download // action. @@ -1669,8 +1689,9 @@ void P3DInstance::SplashDownload:: download_finished(bool success) { P3DFileDownload::download_finished(success); if (success) { - // We've successfully downloaded the splash image. Put it - // onscreen if our splash window still exists. + // We've successfully downloaded the splash image (directly, not + // via the package interface). Put it onscreen if our splash + // window still exists. if (_inst->_splash_window != NULL) { _inst->_splash_window->set_image_filename(get_filename(), true); } diff --git a/direct/src/plugin/p3dInstance.h b/direct/src/plugin/p3dInstance.h index ad00a8d5f6..f7f01db299 100644 --- a/direct/src/plugin/p3dInstance.h +++ b/direct/src/plugin/p3dInstance.h @@ -147,6 +147,7 @@ private: P3DMainObject *_panda_script_object; P3DTemporaryFile *_temp_p3d_filename; + P3DPackage *_splash_package; P3DTemporaryFile *_temp_splash_image; bool _got_fparams; diff --git a/direct/src/plugin/p3dOsxSplashWindow.cxx b/direct/src/plugin/p3dOsxSplashWindow.cxx index 89ebd97576..1dc7b48e25 100644 --- a/direct/src/plugin/p3dOsxSplashWindow.cxx +++ b/direct/src/plugin/p3dOsxSplashWindow.cxx @@ -256,11 +256,6 @@ paint_window() { Boolean portChanged = false; if (_toplevel_window != NULL) { - /* - GetPort(&portSave); - SetPortWindowPort(_toplevel_window); - BeginUpdate(_toplevel_window); - */ GetPort(&out_port); } else { diff --git a/direct/src/plugin/p3dPackage.I b/direct/src/plugin/p3dPackage.I index c7220a5f5c..eec9d969e2 100755 --- a/direct/src/plugin/p3dPackage.I +++ b/direct/src/plugin/p3dPackage.I @@ -139,3 +139,16 @@ inline const string &P3DPackage:: get_package_display_name() const { 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; +} + diff --git a/direct/src/plugin/p3dPackage.cxx b/direct/src/plugin/p3dPackage.cxx index befa6721de..bc58323bdf 100755 --- a/direct/src/plugin/p3dPackage.cxx +++ b/direct/src/plugin/p3dPackage.cxx @@ -43,9 +43,16 @@ P3DPackage(P3DHost *host, const string &package_name, _package_version(package_version) { _package_fullname = _package_name; - _package_dir = _host->get_host_dir() + string("/packages/") + _package_name; - _package_fullname += string("_") + _package_version; - _package_dir += string("/") + _package_version; + _package_dir = _host->get_host_dir() + string("/") + _package_name; + + 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; @@ -59,9 +66,6 @@ P3DPackage(P3DHost *host, const string &package_name, // Ensure the package directory exists; create it if it does not. 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 // need to re-download it. 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)) { nout << "Couldn't find package " << _package_fullname << " in contents file.\n"; @@ -266,21 +271,33 @@ download_desc_file() { } // The desc file might have a different path on the host server than - // it has locally, because we strip out the platform locally. - // Adjust desc_file to point to the local file. + // it has locally, because we strip out the platform directory + // locally. Adjust desc_file to point to the local file. 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); - 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)) { nout << _desc_file_pathname << " is stale.\n"; } else { // The desc file is current. Attempt to read it. - TiXmlDocument doc(_desc_file_pathname.c_str()); - if (doc.LoadFile()) { - got_desc_file(&doc, false); + if (_package_solo) { + // No need to load it: the desc file *is* the package. + report_done(true); 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; } - TiXmlDocument doc(_desc_file_pathname.c_str()); - if (!doc.LoadFile()) { - nout << "Couldn't read " << _desc_file_pathname << "\n"; - report_done(false); + if (_package_solo) { + // No need to load it: the desc file *is* the package. + report_done(true); 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); + } } //////////////////////////////////////////////////////////////////// diff --git a/direct/src/plugin/p3dPackage.h b/direct/src/plugin/p3dPackage.h index 813813a4e4..1ee914950e 100755 --- a/direct/src/plugin/p3dPackage.h +++ b/direct/src/plugin/p3dPackage.h @@ -57,6 +57,8 @@ public: inline const string &get_package_version() const; inline const string &get_package_display_name() const; + inline const string &get_desc_file_pathname() const; + void add_instance(P3DInstance *inst); void remove_instance(P3DInstance *inst); @@ -112,6 +114,7 @@ private: string _package_name; string _package_version; string _package_platform; + bool _package_solo; string _package_display_name; string _package_fullname; string _package_dir; diff --git a/direct/src/plugin_npapi/ppInstance.cxx b/direct/src/plugin_npapi/ppInstance.cxx index 7d4b180575..8597f13f4f 100644 --- a/direct/src/plugin_npapi/ppInstance.cxx +++ b/direct/src/plugin_npapi/ppInstance.cxx @@ -735,23 +735,23 @@ read_contents_file(const string &contents_filename) { TiXmlElement *xcontents = doc.FirstChildElement("contents"); if (xcontents != NULL) { - TiXmlElement *xplugin = xcontents->FirstChildElement("plugin"); - while (xplugin != NULL) { - const char *name = xplugin->Attribute("name"); + TiXmlElement *xpackage = xcontents->FirstChildElement("package"); + while (xpackage != NULL) { + const char *name = xpackage->Attribute("name"); 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) { - get_core_api(xplugin); + get_core_api(xpackage); return true; } } - xplugin = xplugin->NextSiblingElement("plugin"); + xpackage = xpackage->NextSiblingElement("package"); } } - // Couldn't find the coreapi plugin description. - nout << "No coreapi plugin defined in contents file for " + // Couldn't find the coreapi package description. + nout << "No coreapi package defined in contents file for " << DTOOL_PLATFORM << "\n"; return false; } @@ -851,8 +851,8 @@ feed_file(PPDownloadRequest *req, const string &filename) { // if necessary. //////////////////////////////////////////////////////////////////// void PPInstance:: -get_core_api(TiXmlElement *xplugin) { - _core_api_dll.load_xml(xplugin); +get_core_api(TiXmlElement *xpackage) { + _core_api_dll.load_xml(xpackage); if (_core_api_dll.quick_verify(_root_dir)) { // The DLL file is good. Just load it. diff --git a/direct/src/plugin_npapi/ppInstance.h b/direct/src/plugin_npapi/ppInstance.h index 21b44c9ab2..afe4752361 100644 --- a/direct/src/plugin_npapi/ppInstance.h +++ b/direct/src/plugin_npapi/ppInstance.h @@ -72,7 +72,7 @@ private: void feed_file(PPDownloadRequest *req, const string &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 do_load_plugin(); diff --git a/direct/src/plugin_standalone/panda3d.cxx b/direct/src/plugin_standalone/panda3d.cxx index a938316988..f65187bb48 100644 --- a/direct/src/plugin_standalone/panda3d.cxx +++ b/direct/src/plugin_standalone/panda3d.cxx @@ -394,18 +394,18 @@ read_contents_file(Filename contents_filename, const string &download_url, TiXmlElement *xcontents = doc.FirstChildElement("contents"); if (xcontents != NULL) { - TiXmlElement *xplugin = xcontents->FirstChildElement("plugin"); - while (xplugin != NULL) { - const char *name = xplugin->Attribute("name"); + TiXmlElement *xpackage = xcontents->FirstChildElement("package"); + while (xpackage != NULL) { + const char *name = xpackage->Attribute("name"); 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) { 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:: get_core_api(const Filename &contents_filename, const string &download_url, const string &this_platform, bool verify_contents, - TiXmlElement *xplugin) { - _core_api_dll.load_xml(xplugin); + TiXmlElement *xpackage) { + _core_api_dll.load_xml(xpackage); if (!_core_api_dll.quick_verify(_root_dir)) { // The DLL file needs to be downloaded. Go get it.