NOISSUE Support mod grouping and dependencies

This commit is contained in:
Jamie Mansfield 2021-05-28 23:10:02 +01:00
parent 74311a54cf
commit 4ba0c9c298
No known key found for this signature in database
GPG Key ID: 36F61598F39F67B0
4 changed files with 103 additions and 7 deletions

View File

@ -147,7 +147,20 @@ static void loadVersionMod(ATLauncher::VersionMod & p, QJsonObject & obj) {
p.optional = Json::ensureBoolean(obj, QString("optional"), false); p.optional = Json::ensureBoolean(obj, QString("optional"), false);
p.recommended = Json::ensureBoolean(obj, QString("recommended"), false); p.recommended = Json::ensureBoolean(obj, QString("recommended"), false);
p.selected = Json::ensureBoolean(obj, QString("selected"), false); p.selected = Json::ensureBoolean(obj, QString("selected"), false);
p.hidden = Json::ensureBoolean(obj, QString("hidden"), false);
p.library = Json::ensureBoolean(obj, QString("library"), false);
p.group = Json::ensureString(obj, QString("group"), "");
if(obj.contains("depends")) {
auto dependsArr = Json::requireArray(obj, "depends");
for (const auto depends : dependsArr) {
p.depends.append(Json::requireString(depends));
}
}
p.client = Json::ensureBoolean(obj, QString("client"), false); p.client = Json::ensureBoolean(obj, QString("client"), false);
// computed
p.effectively_hidden = p.hidden || p.library;
} }
void ATLauncher::loadVersion(PackVersion & v, QJsonObject & obj) void ATLauncher::loadVersion(PackVersion & v, QJsonObject & obj)

View File

@ -90,7 +90,15 @@ struct VersionMod
bool optional; bool optional;
bool recommended; bool recommended;
bool selected; bool selected;
bool hidden;
bool library;
QString group;
QVector<QString> depends;
bool client; bool client;
// computed
bool effectively_hidden;
}; };
struct PackVersion struct PackVersion

View File

@ -4,8 +4,16 @@
AtlOptionalModListModel::AtlOptionalModListModel(QWidget *parent, QVector<ATLauncher::VersionMod> mods) AtlOptionalModListModel::AtlOptionalModListModel(QWidget *parent, QVector<ATLauncher::VersionMod> mods)
: QAbstractListModel(parent), m_mods(mods) { : QAbstractListModel(parent), m_mods(mods) {
for (const auto& mod : mods) { // fill mod index
m_selection[mod.name] = mod.selected; for (int i = 0; i < m_mods.size(); i++) {
auto mod = m_mods.at(i);
m_index[mod.name] = i;
}
// set initial state
for (int i = 0; i < m_mods.size(); i++) {
auto mod = m_mods.at(i);
m_selection[mod.name] = false;
setMod(mod, i, mod.selected, false);
} }
} }
@ -61,11 +69,7 @@ bool AtlOptionalModListModel::setData(const QModelIndex &index, const QVariant &
auto row = index.row(); auto row = index.row();
auto mod = m_mods.at(row); auto mod = m_mods.at(row);
// toggle the state toggleMod(mod, row);
m_selection[mod.name] = !m_selection[mod.name];
emit dataChanged(AtlOptionalModListModel::index(index.row(), EnabledColumn),
AtlOptionalModListModel::index(index.row(), EnabledColumn));
return true; return true;
} }
@ -113,6 +117,71 @@ void AtlOptionalModListModel::clearAll() {
AtlOptionalModListModel::index(m_mods.size() - 1, EnabledColumn)); AtlOptionalModListModel::index(m_mods.size() - 1, EnabledColumn));
} }
void AtlOptionalModListModel::toggleMod(ATLauncher::VersionMod mod, int index) {
setMod(mod, index, !m_selection[mod.name]);
}
void AtlOptionalModListModel::setMod(ATLauncher::VersionMod mod, int index, bool enable, bool shouldEmit) {
if (m_selection[mod.name] == enable) return;
m_selection[mod.name] = enable;
// disable other mods in the group, if applicable
if (enable && !mod.group.isEmpty()) {
for (int i = 0; i < m_mods.size(); i++) {
if (index == i) continue;
auto other = m_mods.at(i);
if (mod.group == other.group) {
setMod(other, i, false, shouldEmit);
}
}
}
for (const auto& dependencyName : mod.depends) {
auto dependencyIndex = m_index[dependencyName];
auto dependencyMod = m_mods.at(dependencyIndex);
// enable/disable dependencies
if (enable) {
setMod(dependencyMod, dependencyIndex, true, shouldEmit);
}
// if the dependency is 'effectively hidden', then track which mods
// depend on it - so we can efficiently disable it when no more dependents
// depend on it.
auto dependants = m_dependants[dependencyName];
if (enable) {
dependants.append(mod.name);
}
else {
dependants.removeAll(mod.name);
// if there are no longer any dependents, let's disable the mod
if (dependencyMod.effectively_hidden && dependants.isEmpty()) {
setMod(dependencyMod, dependencyIndex, false, shouldEmit);
}
}
}
// disable mods that depend on this one, if disabling
if (!enable) {
auto dependants = m_dependants[mod.name];
for (const auto& dependencyName : dependants) {
auto dependencyIndex = m_index[dependencyName];
auto dependencyMod = m_mods.at(dependencyIndex);
setMod(dependencyMod, dependencyIndex, false, shouldEmit);
}
}
if (shouldEmit) {
emit dataChanged(AtlOptionalModListModel::index(index, EnabledColumn),
AtlOptionalModListModel::index(index, EnabledColumn));
}
}
AtlOptionalModDialog::AtlOptionalModDialog(QWidget *parent, QVector<ATLauncher::VersionMod> mods) AtlOptionalModDialog::AtlOptionalModDialog(QWidget *parent, QVector<ATLauncher::VersionMod> mods)
: QDialog(parent), ui(new Ui::AtlOptionalModDialog) { : QDialog(parent), ui(new Ui::AtlOptionalModDialog) {

View File

@ -37,9 +37,15 @@ public slots:
void selectRecommended(); void selectRecommended();
void clearAll(); void clearAll();
private:
void toggleMod(ATLauncher::VersionMod mod, int index);
void setMod(ATLauncher::VersionMod mod, int index, bool enable, bool shouldEmit = true);
private: private:
QVector<ATLauncher::VersionMod> m_mods; QVector<ATLauncher::VersionMod> m_mods;
QMap<QString, bool> m_selection; QMap<QString, bool> m_selection;
QMap<QString, int> m_index;
QMap<QString, QVector<QString>> m_dependants;
}; };
class AtlOptionalModDialog : public QDialog { class AtlOptionalModDialog : public QDialog {