Something went wrong. Try again.
OpenMW is an open implementation of the Morrowind engine
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142#include "infocollection.hpp"
#include <algorithm>#include <memory>#include <stdexcept>#include <string>#include <utility>
#include "components/debug/debuglog.hpp"#include "components/esm3/infoorder.hpp"#include "components/esm3/loaddial.hpp"#include "components/esm3/loadinfo.hpp"
#include "collection.hpp"#include "info.hpp"
namespace CSMWorld{ namespace { std::string_view getInfoTopicId(const ESM::RefId& infoId) { return parseInfoRefId(infoId).first; } }
ESM::RefId makeCompositeInfoRefId(const ESM::RefId& topicId, const ESM::RefId& infoId) { return ESM::RefId::stringRefId(topicId.getRefIdString() + '#' + infoId.getRefIdString()); }}
void CSMWorld::InfoCollection::load(const Info& value, bool base){ const int index = searchId(value.mId);
if (index == -1) { // new record auto record = std::make_unique<Record<Info>>(); record->mState = base ? RecordBase::State_BaseOnly : RecordBase::State_ModifiedOnly; (base ? record->mBase : record->mModified) = value;
insertRecord(std::move(record), getSize()); } else { // old record auto record = std::make_unique<Record<Info>>(getRecord(index));
if (base) record->mBase = value; else record->setModified(value);
setRecord(index, std::move(record)); }}
void CSMWorld::InfoCollection::load( ESM::ESMReader& reader, bool base, const ESM::Dialogue& dialogue, InfoOrderByTopic& infoOrders){ Info info; bool isDeleted = false;
info.load(reader, isDeleted);
const ESM::RefId id = makeCompositeInfoRefId(dialogue.mId, info.mId);
if (isDeleted) { const int index = searchId(id);
if (index == -1) { Log(Debug::Warning) << "Trying to delete absent info \"" << info.mId << "\" from topic \"" << dialogue.mId << "\""; return; }
if (base) { infoOrders.at(dialogue.mId).removeInfo(info.mId); removeRows(index, 1); return; }
auto record = std::make_unique<Record<Info>>(getRecord(index)); record->mState = RecordBase::State_Deleted; setRecord(index, std::move(record));
return; }
info.mTopicId = dialogue.mId; info.mOriginalId = info.mId; info.mId = id;
load(info, base);
infoOrders[dialogue.mId].insertInfo(OrderedInfo(info), isDeleted);}
void CSMWorld::InfoCollection::sort(const InfoOrderByTopic& infoOrders){ std::vector<int> order; order.reserve(getSize()); for (const auto& [topicId, infoOrder] : infoOrders) for (const OrderedInfo& info : infoOrder.getOrderedInfo()) order.push_back(getIndex(makeCompositeInfoRefId(topicId, info.mId))); reorderRowsImp(order);}
CSMWorld::InfosRecordPtrByTopic CSMWorld::InfoCollection::getInfosByTopic() const{ InfosRecordPtrByTopic result; for (const std::unique_ptr<Record<Info>>& record : getRecords()) result[record->get().mTopicId].push_back(record.get()); return result;}
int CSMWorld::InfoCollection::getAppendIndex(const ESM::RefId& id, UniversalId::Type /*type*/) const{ const auto lessByTopicId = [](std::string_view lhs, const std::unique_ptr<Record<Info>>& rhs) { return lhs < rhs->get().mTopicId; }; const auto it = std::upper_bound(getRecords().begin(), getRecords().end(), getInfoTopicId(id), lessByTopicId); return static_cast<int>(it - getRecords().begin());}
bool CSMWorld::InfoCollection::reorderRows(int baseIndex, const std::vector<int>& newOrder){ const int lastIndex = baseIndex + static_cast<int>(newOrder.size()) - 1;
if (lastIndex >= getSize()) return false;
if (getRecord(baseIndex).get().mTopicId != getRecord(lastIndex).get().mTopicId) return false;
return reorderRowsImp(baseIndex, newOrder);}