NOISSUE Support mod grouping and dependencies
This commit is contained in:
parent
74311a54cf
commit
4ba0c9c298
@ -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)
|
||||||
|
@ -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
|
||||||
|
@ -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) {
|
||||||
|
@ -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 {
|
||||||
|
Loading…
Reference in New Issue
Block a user