Skip to content

Commit

Permalink
Refactor|FS|Resources: PackageLoader handles optional package contents
Browse files Browse the repository at this point in the history
Rather than doing it in libdoomsday, optional package contents
(recommends, extras) are now handled at the lowest level in
PackageLoader. This allows using the same mechanism for Doomsday 2
packages.
  • Loading branch information
skyjake committed Jul 5, 2016
1 parent fb331a0 commit eb029a9
Show file tree
Hide file tree
Showing 9 changed files with 82 additions and 55 deletions.
@@ -1,6 +1,6 @@
# The Doomsday Engine Project -- Doomsday Client
#
# Copyright (c) 2013 Jaakko Keränen <jaakko.keranen@iki.fi>
# Copyright (c) 2013-2016 Jaakko Keränen <jaakko.keranen@iki.fi>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -97,7 +97,6 @@ def setDefaults(d)
record d.resource
d.resource.iwadFolder = ''
d.resource.packageFolder = ''
d.resource.selectedPackages = {}

# Renderer settings.
record d.render
Expand Down
Expand Up @@ -71,12 +71,12 @@ DENG_GUI_PIMPL(PackageContentOptionsWidget)

DictionaryValue &conf()
{
return Config::get()["resource.selectedPackages"].value<DictionaryValue>();
return Config::get()["fs.selectedPackages"].value<DictionaryValue>();
}

DictionaryValue const &conf() const
{
return Config::get()["resource.selectedPackages"].value<DictionaryValue>();
return Config::get()["fs.selectedPackages"].value<DictionaryValue>();
}

bool isSelected() const
Expand Down
48 changes: 2 additions & 46 deletions doomsday/apps/libdoomsday/src/resource/bundles.cpp
Expand Up @@ -355,57 +355,13 @@ QList<DataBundle const *> Bundles::loaded() const
auto &loader = PackageLoader::get();
QList<DataBundle const *> loadedBundles;

// Collection contents enabled/disabled for use.
DictionaryValue const &selPkgs = Config::get()["resource.selectedPackages"].value<DictionaryValue>();

// Check all the loaded packages to see which ones are data bundles.
for (auto *f : loader.loadedPackagesAsFilesInPackageOrder())
{
if (DataBundle const *bundle = f->maybeAs<DataBundle>())
{
if (bundle->format() == DataBundle::Collection)
{
// Instead of adding the collection, check which contained packages are
// selected for loading.

auto isSelected = [bundle, &selPkgs] (TextValue const &id, bool byDefault) -> bool
{
TextValue const key(bundle->packageId());
if (selPkgs.contains(key)) {
auto const &sels = selPkgs.element(key).as<DictionaryValue>();
if (sels.contains(id)) {
return sels.element(id).isTrue();
}
}
return byDefault;
};

auto addToLoaded = [&loadedBundles] (String const &id)
{
if (DataBundle const *b = DataBundle::bundleForPackage(id)) {
loadedBundles << b;
}
};

Record const &meta = bundle->packageMetadata();
for (auto const *id : meta.geta("requires").elements())
{
addToLoaded(id->asText());
}
for (auto const *id : meta.geta("recommends").elements())
{
if (isSelected(id->asText(), true)) addToLoaded(id->asText());
}
for (auto const *id : meta.geta("extras").elements())
{
if (isSelected(id->asText(), false)) addToLoaded(id->asText());
}
}
else
{
// Non-collection data files are loaded as-is.
loadedBundles << bundle;
}
// Non-collection data files are loaded as-is.
loadedBundles << bundle;
}
}

Expand Down
2 changes: 2 additions & 0 deletions doomsday/sdk/libcore/include/de/core/app.h
Expand Up @@ -318,6 +318,8 @@ class DENG2_PUBLIC App : DENG2_OBSERVES(Clock, TimeChange)
*/
static ScriptSystem &scriptSystem();

static bool configExists();

/**
* Returns the configuration.
*/
Expand Down
2 changes: 2 additions & 0 deletions doomsday/sdk/libcore/include/de/filesys/package.h
Expand Up @@ -169,6 +169,8 @@ class DENG2_PUBLIC Package : public IObject

static Record &initializeMetadata(File &packageFile, String const &id = String());

static Record const &metadata(File const &packageFile);

static QStringList tags(File const &packageFile);

static bool matchTags(File const &packageFile, String const &tagRegExp);
Expand Down
@@ -1,6 +1,6 @@
# The Doomsday Engine Project -- libcore
#
# Copyright (c) 2012-2014 Jaakko Keränen <jaakko.keranen@iki.fi>
# Copyright (c) 2012-2016 Jaakko Keränen <jaakko.keranen@iki.fi>
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
Expand Down Expand Up @@ -65,6 +65,10 @@ def setDefaults(d = None)
initFilter(record d.log.filter.input, Log.MESSAGE, False)
initFilter(record d.log.filter.network, Log.MESSAGE, False)

# File system settings.
record d.fs
d.fs.selectedPackages = {}

try
# Get the application's default configuration, if we can.
import appconfig
Expand Down
5 changes: 5 additions & 0 deletions doomsday/sdk/libcore/src/core/app.cpp
Expand Up @@ -771,6 +771,11 @@ ScriptSystem &App::scriptSystem()
return DENG2_APP->d->scriptSys;
}

bool App::configExists()
{
return DENG2_APP->d->config != nullptr;
}

Folder &App::rootFolder()
{
return fileSystem().root();
Expand Down
5 changes: 5 additions & 0 deletions doomsday/sdk/libcore/src/filesys/package.cpp
Expand Up @@ -332,6 +332,11 @@ Record &Package::initializeMetadata(File &packageFile, String const &id)
return metadata;
}

Record const &Package::metadata(File const &packageFile)
{
return packageFile.objectNamespace().subrecord(VAR_PACKAGE);
}

QStringList Package::tags(File const &packageFile)
{
return tags(packageFile.objectNamespace().gets(PACKAGE_TAGS));
Expand Down
62 changes: 58 additions & 4 deletions doomsday/sdk/libcore/src/filesys/packageloader.cpp
Expand Up @@ -17,15 +17,18 @@
*/

#include "de/PackageLoader"
#include "de/FS"

#include "de/App"
#include "de/CommandLine"
#include "de/Version"
#include "de/Config"
#include "de/DictionaryValue"
#include "de/FS"
#include "de/Info"
#include "de/Log"
#include "de/Parser"
#include "de/LinkFile"
#include "de/Log"
#include "de/PackageFeed"
#include "de/Parser"
#include "de/Version"

#include <QMap>
#include <QRegExp>
Expand Down Expand Up @@ -208,6 +211,13 @@ DENG2_PIMPL(PackageLoader)
// exception is any are missing.
loadRequirements(source);

// Optional content can be loaded once Config is available so the user's
// preferences are known.
if (App::configExists())
{
loadOptionalContent(source);
}

Package *pkg = new Package(source);
loaded.insert(packageId, pkg);
pkg->setOrder(loadCounter++);
Expand Down Expand Up @@ -288,6 +298,50 @@ DENG2_PIMPL(PackageLoader)
}
}

void loadOptionalContent(File const &packageFile)
{
// Packages enabled/disabled for use.
DictionaryValue const &selPkgs = Config::get()["fs.selectedPackages"]
.value<DictionaryValue>();

Record const &meta = Package::metadata(packageFile);

// Helper function to determine if a particular pacakge is marked for loading.
auto isPackageSelected = [meta, &selPkgs] (TextValue const &id, bool byDefault) -> bool {
TextValue const key(meta.gets("ID"));
if (selPkgs.contains(key)) {
auto const &sels = selPkgs.element(key).as<DictionaryValue>();
if (sels.contains(id)) {
return sels.element(id).isTrue();
}
}
return byDefault;
};

if (meta.has("recommends"))
{
for (auto const *id : meta.geta("recommends").elements())
{
String const pkgId = id->asText();
if (isPackageSelected(pkgId, true) && !self.isLoaded(pkgId))
{
self.load(pkgId);
}
}
}
if (meta.has("extras"))
{
for (auto const *id : meta.geta("extras").elements())
{
String const pkgId = id->asText();
if (isPackageSelected(pkgId, false) && !self.isLoaded(pkgId))
{
self.load(pkgId);
}
}
}
}

QList<Package *> loadedInOrder() const
{
QList<Package *> pkgs = loaded.values();
Expand Down

0 comments on commit eb029a9

Please sign in to comment.