From 122744454c9befc06b582a8f0feb03bfbb85aa71 Mon Sep 17 00:00:00 2001 From: LostDragonist Date: Wed, 31 Oct 2018 20:00:20 -0500 Subject: Improve changing mod and plugin priorities --- src/modlist.cpp | 44 +++++++++++++++++++++++-------- src/organizercore.cpp | 6 +++-- src/pluginlist.cpp | 32 ++++++++++++++++++----- src/profile.cpp | 71 ++++++++++++++++++++++++--------------------------- src/profile.h | 6 +++-- 5 files changed, 100 insertions(+), 59 deletions(-) diff --git a/src/modlist.cpp b/src/modlist.cpp index 6caafeb2..7b57eeda 100644 --- a/src/modlist.cpp +++ b/src/modlist.cpp @@ -654,26 +654,48 @@ void ModList::changeModPriority(std::vector sourceIndices, int newPriority) emit layoutAboutToBeChanged(); Profile *profile = m_Profile; - // sort rows to insert by their old priority (ascending) and insert them move them in that order + + // sort the moving mods by ascending priorities std::sort(sourceIndices.begin(), sourceIndices.end(), - [profile](const int &LHS, const int &RHS) { - return profile->getModPriority(LHS) < profile->getModPriority(RHS); - }); + [profile](const int &LHS, const int &RHS) { + return profile->getModPriority(LHS) > profile->getModPriority(RHS); + }); - // odd stuff: if any of the dragged sources has priority lower than the destination then the - // target idx is that of the row BELOW the dropped location, otherwise it's the one above. why? + // move mods that are decreasing in priority for (std::vector::const_iterator iter = sourceIndices.begin(); iter != sourceIndices.end(); ++iter) { - if (profile->getModPriority(*iter) < newPriority) { + int oldPriority = profile->getModPriority(*iter); + if (oldPriority > newPriority) { + profile->setModPriority(*iter, newPriority); + m_ModMoved(ModInfo::getByIndex(*iter)->name(), oldPriority, newPriority); + } + } + + // sort the moving mods by descending priorities + std::sort(sourceIndices.begin(), sourceIndices.end(), + [profile](const int &LHS, const int &RHS) { + return profile->getModPriority(LHS) < profile->getModPriority(RHS); + }); + + // if at least one mod is increasing in priority, the target index is + // that of the row BELOW the dropped location, otherwise it's the one above + for (std::vector::const_iterator iter = sourceIndices.begin(); + iter != sourceIndices.end(); ++iter) { + int oldPriority = profile->getModPriority(*iter); + if (oldPriority < newPriority) { --newPriority; break; } } + + // move mods that are increasing in priority for (std::vector::const_iterator iter = sourceIndices.begin(); - iter != sourceIndices.end(); ++iter) { - int oldPriority = m_Profile->getModPriority(*iter); - m_Profile->setModPriority(*iter, newPriority); - m_ModMoved(ModInfo::getByIndex(*iter)->name(), oldPriority, newPriority); + iter != sourceIndices.end(); ++iter) { + int oldPriority = profile->getModPriority(*iter); + if (oldPriority < newPriority) { + profile->setModPriority(*iter, newPriority); + m_ModMoved(ModInfo::getByIndex(*iter)->name(), oldPriority, newPriority); + } } emit layoutChanged(); diff --git a/src/organizercore.cpp b/src/organizercore.cpp index 5c85e323..1fafd4c1 100644 --- a/src/organizercore.cpp +++ b/src/organizercore.cpp @@ -1183,7 +1183,9 @@ ModList *OrganizerCore::modList() QStringList OrganizerCore::modsSortedByProfilePriority() const { QStringList res; - for (unsigned int i = 0; i < currentProfile()->numRegularMods(); ++i) { + for (int i = currentProfile()->getPriorityMinimum(); + i < currentProfile()->getPriorityMinimum() + currentProfile()->numRegularMods(); + ++i) { int modIndex = currentProfile()->modIndexByPriority(i); res.push_back(ModInfo::getByIndex(modIndex)->name()); } @@ -2304,4 +2306,4 @@ std::vector OrganizerCore::fileMapping( result.insert(result.end(), subRes.begin(), subRes.end()); } return result; -} \ No newline at end of file +} diff --git a/src/pluginlist.cpp b/src/pluginlist.cpp index 4097ba98..8f714afd 100644 --- a/src/pluginlist.cpp +++ b/src/pluginlist.cpp @@ -1183,17 +1183,35 @@ void PluginList::setPluginPriority(int row, int &newPriority) void PluginList::changePluginPriority(std::vector rows, int newPriority) { ChangeBracket layoutChange(this); - // sort rows to insert by their old priority (ascending) and insert them move them in that order const std::vector &esp = m_ESPs; + + int minPriority = INT_MAX; + int maxPriority = INT_MIN; + + // don't try to move plugins before force-enabled plugins + for (std::vector::const_iterator iter = m_ESPs.begin(); + iter != m_ESPs.end(); ++iter) { + if (iter->m_ForceEnabled) { + newPriority = std::max(newPriority, iter->m_Priority+1); + } + maxPriority = std::max(maxPriority, iter->m_Priority+1); + minPriority = std::min(minPriority, iter->m_Priority); + } + + // limit the new priority to existing priorities + newPriority = std::min(newPriority, maxPriority); + newPriority = std::max(newPriority, minPriority); + + // sort the moving plugins by ascending priorities std::sort(rows.begin(), rows.end(), - [&esp](const int &LHS, const int &RHS) { - return esp[LHS].m_Priority < esp[RHS].m_Priority; - }); + [&esp](const int &LHS, const int &RHS) { + return esp[LHS].m_Priority < esp[RHS].m_Priority; + }); - // odd stuff: if any of the dragged sources has priority lower than the destination then the - // target idx is that of the row BELOW the dropped location, otherwise it's the one above. why? + // if at least on plugin is increasing in priority, the target index is + // that of the row BELOW the dropped location, otherwise it's the one above for (std::vector::const_iterator iter = rows.begin(); - iter != rows.end(); ++iter) { + iter != rows.end(); ++iter) { if (m_ESPs[*iter].m_Priority < newPriority) { --newPriority; break; diff --git a/src/profile.cpp b/src/profile.cpp index 7f10bd02..00818d0b 100644 --- a/src/profile.cpp +++ b/src/profile.cpp @@ -184,9 +184,10 @@ void Profile::doWriteModlist() return; } - for (int i = static_cast(m_ModStatus.size()) - 1; i >= 0; --i) { + for (std::map::const_reverse_iterator iter = m_ModIndexByPriority.crbegin(); iter != m_ModIndexByPriority.crend(); iter++ ) { + //qDebug(QString("write mod %1 to priority %2").arg(iter->first).arg(iter->second).toLocal8Bit()); // the priority order was inverted on load so it has to be inverted again - unsigned int index = m_ModIndexByPriority[i]; + unsigned int index = iter->second; if (index != UINT_MAX) { ModInfo::Ptr modInfo = ModInfo::getByIndex(index); std::vector flags = modInfo->getFlags(); @@ -223,9 +224,9 @@ void Profile::createTweakedIniFile() return; } - for (unsigned int i = 0; i < m_ModStatus.size(); ++i) { + for (int i = getPriorityMinimum(); i < getPriorityMinimum() + (int)numRegularMods(); ++i) { unsigned int idx = modIndexByPriority(i); - if ((idx != UINT_MAX) && m_ModStatus[idx].m_Enabled) { + if (m_ModStatus[idx].m_Enabled) { ModInfo::Ptr modInfo = ModInfo::getByIndex(idx); mergeTweaks(modInfo, tweakedIni); } @@ -454,18 +455,14 @@ void Profile::updateIndices() { m_NumRegularMods = 0; m_ModIndexByPriority.clear(); - m_ModIndexByPriority.resize(m_ModStatus.size(), UINT_MAX); for (unsigned int i = 0; i < m_ModStatus.size(); ++i) { int priority = m_ModStatus[i].m_Priority; - if (priority < 0) { + if (priority == INT_MIN) { // don't assign this to mapping at all, it's probably the overwrite mod continue; - } else if (priority >= static_cast(m_ModIndexByPriority.size())) { - qCritical("invalid priority %d for mod", priority); - continue; } else { ++m_NumRegularMods; - m_ModIndexByPriority.at(priority) = i; + m_ModIndexByPriority[priority] = i; } } } @@ -474,11 +471,10 @@ void Profile::updateIndices() std::vector > Profile::getActiveMods() { std::vector > result; - for (std::vector::const_iterator iter = m_ModIndexByPriority.begin(); - iter != m_ModIndexByPriority.end(); ++iter) { - if ((*iter != UINT_MAX) && m_ModStatus[*iter].m_Enabled) { - ModInfo::Ptr modInfo = ModInfo::getByIndex(*iter); - result.push_back(std::make_tuple(modInfo->internalName(), modInfo->absolutePath(), m_ModStatus[*iter].m_Priority)); + for (std::map::const_iterator iter = m_ModIndexByPriority.begin(); iter != m_ModIndexByPriority.end(); iter++ ) { + if ((iter->second != UINT_MAX) && m_ModStatus[iter->second].m_Enabled) { + ModInfo::Ptr modInfo = ModInfo::getByIndex(iter->second); + result.push_back(std::make_tuple(modInfo->internalName(), modInfo->absolutePath(), m_ModStatus[iter->second].m_Priority)); } } @@ -496,13 +492,13 @@ std::vector > Profile::getActiveMods() } -unsigned int Profile::modIndexByPriority(unsigned int priority) const +unsigned int Profile::modIndexByPriority(int priority) const { - if (priority >= m_ModStatus.size()) { + try { + return m_ModIndexByPriority.at(priority); + } catch (std::out_of_range) { throw MyException(tr("invalid priority %1").arg(priority)); } - - return m_ModIndexByPriority[priority]; } @@ -552,30 +548,26 @@ void Profile::setModPriority(unsigned int index, int &newPriority) return; } - int newPriorityTemp = - (std::max)(0, (std::min)(static_cast(m_ModStatus.size()) - 1, - newPriority)); + int oldPriority = m_ModStatus.at(index).m_Priority; + int lastPriority = INT_MIN; - // don't try to place below overwrite - while ((m_ModIndexByPriority.at(newPriorityTemp) >= m_ModStatus.size()) || - m_ModStatus.at(m_ModIndexByPriority.at(newPriorityTemp)).m_Overwrite) { - --newPriorityTemp; + if (newPriority == oldPriority) { + // nothing to do + return; } - int oldPriority = m_ModStatus.at(index).m_Priority; - if (newPriorityTemp > oldPriority) { - // priority is higher than the old, so the gap we left is in lower priorities - for (int i = oldPriority + 1; i <= newPriorityTemp; ++i) { - --m_ModStatus.at(m_ModIndexByPriority.at(i)).m_Priority; + for (std::map::iterator iter = m_ModIndexByPriority.begin(); iter != m_ModIndexByPriority.end(); iter++) { + if (newPriority < oldPriority && iter->first >= newPriority && iter->first < oldPriority) { + m_ModStatus.at(iter->second).m_Priority += 1; } - } else { - for (int i = newPriorityTemp; i < oldPriority; ++i) { - ++m_ModStatus.at(m_ModIndexByPriority.at(i)).m_Priority; + else if (newPriority > oldPriority && iter->first <= newPriority && iter->first > oldPriority) { + m_ModStatus.at(iter->second).m_Priority -= 1; } - ++newPriority; + lastPriority = std::max(lastPriority, iter->first); } - m_ModStatus.at(index).m_Priority = newPriorityTemp; + newPriority = std::min(newPriority, lastPriority); + m_ModStatus.at(index).m_Priority = std::min(newPriority, lastPriority); updateIndices(); m_ModListWriter.write(); @@ -839,4 +831,9 @@ void Profile::storeSetting(const QString §ion, const QString &name, void Profile::removeSetting(const QString §ion, const QString &name) { m_Settings->remove(section + "/" + name); -} \ No newline at end of file +} + +int Profile::getPriorityMinimum() const +{ + return m_ModIndexByPriority.begin()->first; +} diff --git a/src/profile.h b/src/profile.h index 1fcad046..9ddd5b89 100644 --- a/src/profile.h +++ b/src/profile.h @@ -247,7 +247,7 @@ public: * @return the index of the mod * @throw std::exception an exception is thrown if there is no mod with the specified priority **/ - unsigned int modIndexByPriority(unsigned int priority) const; + unsigned int modIndexByPriority(int priority) const; /** * @brief enable or disable a mod @@ -294,6 +294,8 @@ public: const QVariant &value); void removeSetting(const QString §ion, const QString &name); + int getPriorityMinimum() const; + signals: /** @@ -347,7 +349,7 @@ private: mutable QByteArray m_LastModlistHash; std::vector m_ModStatus; - std::vector m_ModIndexByPriority; + std::map m_ModIndexByPriority; unsigned int m_NumRegularMods; MOBase::DelayedFileWriter m_ModListWriter; -- cgit v1.3.1