Merge branch 'refactor_refid_strong_type' into 'master'

Every instance where a string or string_view is used to designate a RefId, we use a specialized type

See merge request OpenMW/openmw!2438
iwyu_full
psi29a 2 years ago
commit bad573a710

@ -560,7 +560,7 @@ namespace EsmTool
std::cout << " Name: " << mData.mName << std::endl;
std::cout << " Texture: " << mData.mTexture << std::endl;
std::cout << " Description: " << mData.mDescription << std::endl;
for (const std::string& power : mData.mPowers.mList)
for (const auto& power : mData.mPowers.mList)
std::cout << " Power: " << power << std::endl;
std::cout << " Deleted: " << mIsDeleted << std::endl;
}
@ -704,7 +704,7 @@ namespace EsmTool
std::cout << " Inventory: Count: " << Misc::StringUtils::format("%4d", item.mCount)
<< " Item: " << item.mItem << std::endl;
for (const std::string& spell : mData.mSpells.mList)
for (const auto& spell : mData.mSpells.mList)
std::cout << " Spell: " << spell << std::endl;
printTransport(mData.getTransport());
@ -1102,7 +1102,7 @@ namespace EsmTool
std::cout << " Inventory: Count: " << Misc::StringUtils::format("%4d", item.mCount)
<< " Item: " << item.mItem << std::endl;
for (const std::string& spell : mData.mSpells.mList)
for (const auto& spell : mData.mSpells.mList)
std::cout << " Spell: " << spell << std::endl;
printTransport(mData.getTransport());
@ -1187,7 +1187,7 @@ namespace EsmTool
std::cout << " Skill: " << skillLabel(mData.mData.mBonus[i].mSkill) << " ("
<< mData.mData.mBonus[i].mSkill << ") = " << mData.mData.mBonus[i].mBonus << std::endl;
for (const std::string& power : mData.mPowers.mList)
for (const auto& power : mData.mPowers.mList)
std::cout << " Power: " << power << std::endl;
std::cout << " Deleted: " << mIsDeleted << std::endl;
@ -1342,7 +1342,7 @@ namespace EsmTool
template <>
std::string Record<ESM::Cell>::getId() const
{
return mData.mName;
return mData.mName.getRefIdString();
}
template <>

@ -70,7 +70,7 @@ namespace EsmTool
{
}
std::string getId() const override { return mData.mId; }
std::string getId() const override { return mData.mId.getRefIdString(); }
T& get() { return mData; }

@ -71,7 +71,7 @@ namespace
std::string refId;
splitIndexedRefId(indexedRefId, refIndex, refId);
auto it = context.mActorIdMap.find(std::make_pair(refIndex, refId));
auto it = context.mActorIdMap.find(std::make_pair(refIndex, ESM::RefId::stringRefId(refId)));
if (it == context.mActorIdMap.end())
return -1;
return it->second;
@ -202,7 +202,7 @@ namespace ESSImport
}
// note if the player is in a nameless exterior cell, we will assign the cellId later based on player position
if (cell.mName == mContext->mPlayerCellName)
if (cell.mName == ESM::RefId::stringRefId(mContext->mPlayerCellName))
{
mContext->mPlayer.mCellId = cell.getCellId();
}
@ -338,13 +338,12 @@ namespace ESSImport
{
// non-indexed RefNum, i.e. no CREC/NPCC/CNTC record associated with it
// this could be any type of object really (even creatures/npcs too)
out.mRefID = cellref.mIndexedRefId;
std::string idLower = Misc::StringUtils::lowerCase(out.mRefID);
out.mRefID = ESM::RefId::stringRefId(cellref.mIndexedRefId);
ESM::ObjectState objstate;
objstate.blank();
objstate.mRef = out;
objstate.mRef.mRefID = idLower;
objstate.mRef.mRefID = out.mRefID;
objstate.mHasCustomState = false;
convertCellRef(cellref, objstate);
esm.writeHNT("OBJE", 0);
@ -354,9 +353,9 @@ namespace ESSImport
else
{
int refIndex = 0;
splitIndexedRefId(cellref.mIndexedRefId, refIndex, out.mRefID);
std::string idLower = Misc::StringUtils::lowerCase(out.mRefID);
std::string outStringId;
splitIndexedRefId(cellref.mIndexedRefId, refIndex, outStringId);
out.mRefID = ESM::RefId::stringRefId(outStringId);
auto npccIt = mContext->mNpcChanges.find(std::make_pair(refIndex, out.mRefID));
if (npccIt != mContext->mNpcChanges.end())
@ -364,7 +363,7 @@ namespace ESSImport
ESM::NpcState objstate;
objstate.blank();
objstate.mRef = out;
objstate.mRef.mRefID = idLower;
objstate.mRef.mRefID = out.mRefID;
// TODO: need more micromanagement here so we don't overwrite values
// from the ESM with default values
if (cellref.mActorData.mHasACDT)
@ -392,7 +391,7 @@ namespace ESSImport
ESM::ContainerState objstate;
objstate.blank();
objstate.mRef = out;
objstate.mRef.mRefID = idLower;
objstate.mRef.mRefID = out.mRefID;
convertCNTC(cntcIt->second, objstate);
convertCellRef(cellref, objstate);
esm.writeHNT("OBJE", ESM::REC_CONT);
@ -406,7 +405,7 @@ namespace ESSImport
ESM::CreatureState objstate;
objstate.blank();
objstate.mRef = out;
objstate.mRef.mRefID = idLower;
objstate.mRef.mRefID = out.mRefID;
// TODO: need more micromanagement here so we don't overwrite values
// from the ESM with default values
if (cellref.mActorData.mHasACDT)
@ -466,7 +465,7 @@ namespace ESSImport
ESM::ProjectileState out;
convertBaseState(out, pnam);
out.mBowId = pnam.mBowId.toString();
out.mBowId = ESM::RefId::stringRefId(pnam.mBowId.toString());
out.mVelocity = pnam.mVelocity;
out.mAttackStrength = pnam.mAttackStrength;
@ -489,7 +488,7 @@ namespace ESSImport
continue;
}
out.mSpellId = it->mSPDT.mId.toString();
out.mSpellId = ESM::RefId::stringRefId(it->mSPDT.mId.toString());
out.mSpeed = pnam.mSpeed * 0.001f; // not sure where this factor comes from
out.mSlot = 0;
@ -502,7 +501,7 @@ namespace ESSImport
void ConvertPROJ::convertBaseState(ESM::BaseProjectileState& base, const PROJ::PNAM& pnam)
{
base.mId = pnam.mArrowId.toString();
base.mId = ESM::RefId::stringRefId(pnam.mArrowId.toString());
base.mPosition = pnam.mPosition;
osg::Quat orient;

@ -45,6 +45,7 @@
#include "convertnpcc.hpp"
#include "convertplayer.hpp"
#include "convertscpt.hpp"
#include <components/esm/refid.hpp>
namespace ESSImport
{
@ -89,7 +90,7 @@ namespace ESSImport
void write(ESM::ESMWriter& esm) override
{
for (typename std::map<std::string, T>::const_iterator it = mRecords.begin(); it != mRecords.end(); ++it)
for (auto it = mRecords.begin(); it != mRecords.end(); ++it)
{
esm.startRecord(T::sRecordId);
it->second.save(esm);
@ -98,7 +99,7 @@ namespace ESSImport
}
protected:
std::map<std::string, T> mRecords;
std::map<ESM::RefId, T> mRecords;
};
class ConvertNPC : public Converter
@ -115,7 +116,7 @@ namespace ESSImport
// Handles changes to the NPC struct, but since there is no index here
// it will apply to ALL instances of the class. seems to be the reason for the
// "feature" in MW where changing AI settings of one guard will change it for all guards of that refID.
mContext->mNpcs[Misc::StringUtils::lowerCase(npc.mId)] = npc;
mContext->mNpcs[npc.mId] = npc;
}
else
{
@ -146,7 +147,7 @@ namespace ESSImport
bool isDeleted = false;
creature.load(esm, isDeleted);
mContext->mCreatures[Misc::StringUtils::lowerCase(creature.mId)] = creature;
mContext->mCreatures[creature.mId] = creature;
}
};
@ -163,13 +164,13 @@ namespace ESSImport
bool isDeleted = false;
global.load(esm, isDeleted);
if (Misc::StringUtils::ciEqual(global.mId, "gamehour"))
if (global.mId == "gamehour")
mContext->mHour = global.mValue.getFloat();
if (Misc::StringUtils::ciEqual(global.mId, "day"))
if (global.mId == "day")
mContext->mDay = global.mValue.getInteger();
if (Misc::StringUtils::ciEqual(global.mId, "month"))
if (global.mId == "month")
mContext->mMonth = global.mValue.getInteger();
if (Misc::StringUtils::ciEqual(global.mId, "year"))
if (global.mId == "year")
mContext->mYear = global.mValue.getInteger();
mRecords[global.mId] = global;
}
@ -201,7 +202,7 @@ namespace ESSImport
book.load(esm, isDeleted);
if (book.mData.mSkillId == -1)
mContext->mPlayer.mObject.mNpcStats.mUsedIds.push_back(Misc::StringUtils::lowerCase(book.mId));
mContext->mPlayer.mObject.mNpcStats.mUsedIds.push_back(book.mId);
mRecords[book.mId] = book;
}
@ -212,7 +213,7 @@ namespace ESSImport
public:
void read(ESM::ESMReader& esm) override
{
std::string id = esm.getHNString("NAME");
auto id = ESM::RefId::stringRefId(esm.getHNString("NAME"));
NPCC npcc;
npcc.load(esm);
if (id == "PlayerSaveGame")
@ -251,8 +252,7 @@ namespace ESSImport
for (unsigned int i = 0; i < invState.mItems.size(); ++i)
{
// FIXME: in case of conflict (multiple items with this refID) use the already equipped one?
if (Misc::StringUtils::ciEqual(
invState.mItems[i].mRef.mRefID, refr.mActorData.mSelectedEnchantItem))
if (invState.mItems[i].mRef.mRefID == ESM::RefId::stringRefId(refr.mActorData.mSelectedEnchantItem))
invState.mSelectedEnchantItem = i;
}
}
@ -308,7 +308,7 @@ namespace ESSImport
{
void read(ESM::ESMReader& esm) override
{
std::string id = esm.getHNString("NAME");
auto id = ESM::RefId::stringRefId(esm.getHNString("NAME"));
CNTC cntc;
cntc.load(esm);
mContext->mContainerChanges.insert(std::make_pair(std::make_pair(cntc.mIndex, id), cntc));
@ -320,7 +320,7 @@ namespace ESSImport
public:
void read(ESM::ESMReader& esm) override
{
std::string id = esm.getHNString("NAME");
auto id = ESM::RefId::stringRefId(esm.getHNString("NAME"));
CREC crec;
crec.load(esm);
mContext->mCreatureChanges.insert(std::make_pair(std::make_pair(crec.mIndex, id), crec));
@ -351,7 +351,7 @@ namespace ESSImport
std::vector<unsigned int> mFogOfWar;
};
std::map<std::string, Cell> mIntCells;
std::map<ESM::RefId, Cell> mIntCells;
std::map<std::pair<int, int>, Cell> mExtCells;
std::vector<ESM::CustomMarker> mMarkers;
@ -395,11 +395,11 @@ namespace ESSImport
bool isDeleted = false;
faction.load(esm, isDeleted);
std::string id = Misc::StringUtils::lowerCase(faction.mId);
const auto& id = faction.mId;
for (auto it = faction.mReactions.begin(); it != faction.mReactions.end(); ++it)
{
std::string faction2 = Misc::StringUtils::lowerCase(it->first);
const auto& faction2 = it->first;
mContext->mDialogueState.mChangedFactionReaction[id].insert(std::make_pair(faction2, it->second));
}
}
@ -433,10 +433,10 @@ namespace ESSImport
ESM::StolenItems items;
for (auto it = mStolenItems.begin(); it != mStolenItems.end(); ++it)
{
std::map<std::pair<std::string, bool>, int> owners;
std::map<std::pair<ESM::RefId, bool>, int> owners;
for (const auto& ownerIt : it->second)
{
owners.insert(std::make_pair(std::make_pair(ownerIt.first, ownerIt.second)
owners.insert(std::make_pair(std::make_pair(ESM::RefId::stringRefId(ownerIt.first), ownerIt.second)
// Since OpenMW doesn't suffer from the owner contamination bug,
// it needs a count argument. But for legacy savegames, we don't know
// this count, so must assume all items of that ID are stolen,
@ -445,7 +445,7 @@ namespace ESSImport
std::numeric_limits<int>::max()));
}
items.mStolenItems.insert(std::make_pair(it->first, owners));
items.mStolenItems.insert(std::make_pair(ESM::RefId::stringRefId(it->first), owners));
}
esm.startRecord(ESM::REC_STLN);
@ -494,7 +494,7 @@ namespace ESSImport
ESM::QuestState state;
state.mFinished = 0;
state.mState = it->second.mIndex;
state.mTopic = Misc::StringUtils::lowerCase(it->first);
state.mTopic = ESM::RefId::stringRefId(it->first);
state.save(esm);
esm.endRecord(ESM::REC_QUES);
}

@ -15,7 +15,7 @@ namespace ESSImport
ESM::ObjectState objstate;
objstate.blank();
objstate.mRef = item;
objstate.mRef.mRefID = Misc::StringUtils::lowerCase(item.mId);
objstate.mRef.mRefID = ESM::RefId::stringRefId(item.mId);
objstate.mCount = std::abs(item.mCount); // restocking items have negative count in the savefile
// openmw handles them differently, so no need to set any flags
state.mItems.push_back(objstate);

@ -8,13 +8,13 @@
namespace ESSImport
{
void convertPCDT(const PCDT& pcdt, ESM::Player& out, std::vector<std::string>& outDialogueTopics,
void convertPCDT(const PCDT& pcdt, ESM::Player& out, std::vector<ESM::RefId>& outDialogueTopics,
bool& firstPersonCam, bool& teleportingEnabled, bool& levitationEnabled, ESM::ControlsState& controls)
{
out.mObject.mPosition.rot[0]
= -atan2(pcdt.mPNAM.mVerticalRotation.mData[2][1], pcdt.mPNAM.mVerticalRotation.mData[2][2]);
out.mBirthsign = pcdt.mBirthsign;
out.mBirthsign = ESM::RefId::stringRefId(pcdt.mBirthsign);
out.mObject.mNpcStats.mBounty = pcdt.mBounty;
for (const auto& essFaction : pcdt.mFactions)
{
@ -22,7 +22,7 @@ namespace ESSImport
faction.mExpelled = (essFaction.mFlags & 0x2) != 0;
faction.mRank = essFaction.mRank;
faction.mReputation = essFaction.mReputation;
out.mObject.mNpcStats.mFactions[Misc::StringUtils::lowerCase(essFaction.mFactionName.toString())] = faction;
out.mObject.mNpcStats.mFactions[ESM::RefId::stringRefId(essFaction.mFactionName.toString())] = faction;
}
for (int i = 0; i < 3; ++i)
out.mObject.mNpcStats.mSpecIncreases[i] = pcdt.mPNAM.mSpecIncreases[i];
@ -43,7 +43,7 @@ namespace ESSImport
for (const auto& knownDialogueTopic : pcdt.mKnownDialogueTopics)
{
outDialogueTopics.push_back(Misc::StringUtils::lowerCase(knownDialogueTopic));
outDialogueTopics.push_back(ESM::RefId::stringRefId(knownDialogueTopic));
}
controls.mViewSwitchDisabled = pcdt.mPNAM.mPlayerFlags & PCDT::PlayerFlags_ViewSwitchDisabled;
@ -70,7 +70,7 @@ namespace ESSImport
// TODO: Figure out a better way to detect interiors. (0, 0) is a valid exterior cell.
if (mark.mCellX == 0 && mark.mCellY == 0)
{
cell.mWorldspace = pcdt.mMNAM;
cell.mWorldspace = ESM::RefId::stringRefId(pcdt.mMNAM);
cell.mPaged = false;
}

@ -9,7 +9,7 @@
namespace ESSImport
{
void convertPCDT(const PCDT& pcdt, ESM::Player& out, std::vector<std::string>& outDialogueTopics,
void convertPCDT(const PCDT& pcdt, ESM::Player& out, std::vector<ESM::RefId>& outDialogueTopics,
bool& firstPersonCam, bool& teleportingEnabled, bool& levitationEnabled, ESM::ControlsState& controls);
}

@ -9,7 +9,7 @@ namespace ESSImport
void convertSCPT(const SCPT& scpt, ESM::GlobalScript& out)
{
out.mId = Misc::StringUtils::lowerCase(scpt.mSCHD.mName.toString());
out.mId = ESM::RefId::stringRefId(scpt.mSCHD.mName.toString());
out.mRunning = scpt.mRunning;
out.mTargetRef.unset(); // TODO: convert target reference of global script
convertSCRI(scpt.mSCRI, out.mLocals);

@ -373,7 +373,7 @@ namespace ESSImport
profile.mInGameTime.mMonth = context.mMonth;
profile.mInGameTime.mYear = context.mYear;
profile.mTimePlayed = 0;
profile.mPlayerCell = header.mGameData.mCurrentCell.toString();
profile.mPlayerCell = ESM::RefId::stringRefId(header.mGameData.mCurrentCell.toString());
if (context.mPlayerBase.mClass == "NEWCLASSID_CHARGEN")
profile.mPlayerClassName = context.mCustomPlayerClassName;
else
@ -397,7 +397,7 @@ namespace ESSImport
}
writer.startRecord(ESM::REC_NPC_);
context.mPlayerBase.mId = "player";
context.mPlayerBase.mId = ESM::RefId::stringRefId("Player");
context.mPlayerBase.save(writer);
writer.endRecord(ESM::REC_NPC_);

@ -40,15 +40,15 @@ namespace ESSImport
float mHour;
// key <refIndex, refId>
std::map<std::pair<int, std::string>, CREC> mCreatureChanges;
std::map<std::pair<int, std::string>, NPCC> mNpcChanges;
std::map<std::pair<int, std::string>, CNTC> mContainerChanges;
std::map<std::pair<int, ESM::RefId>, CREC> mCreatureChanges;
std::map<std::pair<int, ESM::RefId>, NPCC> mNpcChanges;
std::map<std::pair<int, ESM::RefId>, CNTC> mContainerChanges;
std::map<std::pair<int, std::string>, int> mActorIdMap;
std::map<std::pair<int, ESM::RefId>, int> mActorIdMap;
int mNextActorId;
std::map<std::string, ESM::Creature> mCreatures;
std::map<std::string, ESM::NPC> mNpcs;
std::map<ESM::RefId, ESM::Creature> mCreatures;
std::map<ESM::RefId, ESM::NPC> mNpcs;
std::vector<SPLM::ActiveSpell> mActiveSpells;
@ -70,7 +70,7 @@ namespace ESSImport
mPlayer.mPaidCrimeId = -1;
mPlayer.mObject.blank();
mPlayer.mObject.mEnabled = true;
mPlayer.mObject.mRef.mRefID = "player"; // REFR.mRefID would be PlayerSaveGame
mPlayer.mObject.mRef.mRefID = ESM::RefId::stringRefId("player"); // REFR.mRefID would be PlayerSaveGame
mPlayer.mObject.mCreatureStats.mActorId = generateActorId();
mGlobalMapState.mBounds.mMinX = 0;

@ -48,5 +48,5 @@ QString CellNameLoader::getCellName(ESM::ESMReader& esmReader)
bool isDeleted = false;
cell.loadNameAndData(esmReader, isDeleted);
return QString::fromStdString(cell.mName);
return QString::fromStdString(cell.mName.getRefIdString());
}

@ -229,7 +229,8 @@ namespace NavMeshTool
DetourNavigator::RecastGlobalAllocator::init();
DetourNavigator::Settings navigatorSettings = DetourNavigator::makeSettingsFromSettingsManager();
navigatorSettings.mRecast.mSwimHeightScale
= EsmLoader::getGameSetting(esmData.mGameSettings, "fSwimHeightScale").getFloat();
= EsmLoader::getGameSetting(esmData.mGameSettings, ESM::RefId::stringRefId("fSwimHeightScale"))
.getFloat();
WorldspaceData cellsData = gatherWorldspaceData(
navigatorSettings, readers, vfs, bulletShapeManager, esmData, processInteriorCells, writeBinaryLog);

@ -29,6 +29,7 @@
#include <osg/ref_ptr>
#include <algorithm>
#include <components/esm/refid.hpp>
#include <memory>
#include <stdexcept>
#include <string>
@ -36,7 +37,6 @@
#include <tuple>
#include <utility>
#include <vector>
namespace NavMeshTool
{
namespace
@ -52,12 +52,12 @@ namespace NavMeshTool
{
ESM::RecNameInts mType;
ESM::RefNum mRefNum;
std::string mRefId;
ESM::RefId mRefId;
float mScale;
ESM::Position mPos;
CellRef(
ESM::RecNameInts type, ESM::RefNum refNum, std::string&& refId, float scale, const ESM::Position& pos)
ESM::RecNameInts type, ESM::RefNum refNum, ESM::RefId&& refId, float scale, const ESM::Position& pos)
: mType(type)
, mRefNum(refNum)
, mRefId(std::move(refId))
@ -67,7 +67,7 @@ namespace NavMeshTool
}
};
ESM::RecNameInts getType(const EsmLoader::EsmData& esmData, std::string_view refId)
ESM::RecNameInts getType(const EsmLoader::EsmData& esmData, const ESM::RefId& refId)
{
const auto it = std::lower_bound(
esmData.mRefIdTypes.begin(), esmData.mRefIdTypes.end(), refId, EsmLoader::LessById{});
@ -89,7 +89,6 @@ namespace NavMeshTool
bool deleted = false;
while (ESM::Cell::getNextRef(*reader, cellRef, deleted))
{
Misc::StringUtils::lowerCaseInPlace(cellRef.mRefID);
const ESM::RecNameInts type = getType(esmData, cellRef.mRefID);
if (type == ESM::RecNameInts{})
continue;
@ -264,16 +263,16 @@ namespace NavMeshTool
const osg::Vec2i cellPosition(cell.mData.mX, cell.mData.mY);
const std::size_t cellObjectsBegin = data.mObjects.size();
const auto cellNameLowerCase = Misc::StringUtils::lowerCase(cell.mCellId.mWorldspace.getRefIdString());
WorldspaceNavMeshInput& navMeshInput = [&]() -> WorldspaceNavMeshInput& {
auto it = navMeshInputs.find(cell.mCellId.mWorldspace);
auto it = navMeshInputs.find(cellNameLowerCase);
if (it == navMeshInputs.end())
{
it = navMeshInputs
.emplace(cell.mCellId.mWorldspace,
std::make_unique<WorldspaceNavMeshInput>(cell.mCellId.mWorldspace, settings.mRecast))
.emplace(cellNameLowerCase,
std::make_unique<WorldspaceNavMeshInput>(cellNameLowerCase, settings.mRecast))
.first;
it->second->mTileCachedRecastMeshManager.setWorldspace(cell.mCellId.mWorldspace, nullptr);
it->second->mTileCachedRecastMeshManager.setWorldspace(cellNameLowerCase, nullptr);
}
return *it->second;
}();

@ -46,7 +46,7 @@ void CSMDoc::Document::addGmsts()
for (size_t i = 0; i < CSMWorld::DefaultGmsts::FloatCount; ++i)
{
ESM::GameSetting gmst;
gmst.mId = CSMWorld::DefaultGmsts::Floats[i];
gmst.mId = ESM::RefId::stringRefId(CSMWorld::DefaultGmsts::Floats[i]);
gmst.mValue.setType(ESM::VT_Float);
gmst.mRecordFlags = 0;
gmst.mValue.setFloat(CSMWorld::DefaultGmsts::FloatsDefaultValues[i]);
@ -56,7 +56,7 @@ void CSMDoc::Document::addGmsts()
for (size_t i = 0; i < CSMWorld::DefaultGmsts::IntCount; ++i)
{
ESM::GameSetting gmst;
gmst.mId = CSMWorld::DefaultGmsts::Ints[i];
gmst.mId = ESM::RefId::stringRefId(CSMWorld::DefaultGmsts::Ints[i]);
gmst.mValue.setType(ESM::VT_Int);
gmst.mRecordFlags = 0;
gmst.mValue.setInteger(CSMWorld::DefaultGmsts::IntsDefaultValues[i]);
@ -66,7 +66,7 @@ void CSMDoc::Document::addGmsts()
for (size_t i = 0; i < CSMWorld::DefaultGmsts::StringCount; ++i)
{
ESM::GameSetting gmst;
gmst.mId = CSMWorld::DefaultGmsts::Strings[i];
gmst.mId = ESM::RefId::stringRefId(CSMWorld::DefaultGmsts::Strings[i]);
gmst.mValue.setType(ESM::VT_String);
gmst.mRecordFlags = 0;
gmst.mValue.setString("");
@ -79,7 +79,7 @@ void CSMDoc::Document::addOptionalGmsts()
for (size_t i = 0; i < CSMWorld::DefaultGmsts::OptionalFloatCount; ++i)
{
ESM::GameSetting gmst;
gmst.mId = CSMWorld::DefaultGmsts::OptionalFloats[i];
gmst.mId = ESM::RefId::stringRefId(CSMWorld::DefaultGmsts::OptionalFloats[i]);
gmst.blank();
gmst.mValue.setType(ESM::VT_Float);
addOptionalGmst(gmst);
@ -88,7 +88,7 @@ void CSMDoc::Document::addOptionalGmsts()
for (size_t i = 0; i < CSMWorld::DefaultGmsts::OptionalIntCount; ++i)
{
ESM::GameSetting gmst;
gmst.mId = CSMWorld::DefaultGmsts::OptionalInts[i];
gmst.mId = ESM::RefId::stringRefId(CSMWorld::DefaultGmsts::OptionalInts[i]);
gmst.blank();
gmst.mValue.setType(ESM::VT_Int);
addOptionalGmst(gmst);
@ -97,7 +97,7 @@ void CSMDoc::Document::addOptionalGmsts()
for (size_t i = 0; i < CSMWorld::DefaultGmsts::OptionalStringCount; ++i)
{
ESM::GameSetting gmst;
gmst.mId = CSMWorld::DefaultGmsts::OptionalStrings[i];
gmst.mId = ESM::RefId::stringRefId(CSMWorld::DefaultGmsts::OptionalStrings[i]);
gmst.blank();
gmst.mValue.setType(ESM::VT_String);
gmst.mValue.setString("<no text>");
@ -117,7 +117,7 @@ void CSMDoc::Document::addOptionalGlobals()
for (int i = 0; sGlobals[i]; ++i)
{
ESM::Global global;
global.mId = sGlobals[i];
global.mId = ESM::RefId::stringRefId(sGlobals[i]);
global.blank();
global.mValue.setType(ESM::VT_Long);
@ -134,7 +134,7 @@ void CSMDoc::Document::addOptionalMagicEffects()
{
ESM::MagicEffect effect;
effect.mIndex = i;
effect.mId = ESM::MagicEffect::indexToId(i);
effect.mId = ESM::RefId::stringRefId(ESM::MagicEffect::indexToId(i));
effect.blank();
addOptionalMagicEffect(effect);
@ -191,7 +191,7 @@ void CSMDoc::Document::createBase()
for (int i = 0; sGlobals[i]; ++i)
{
ESM::Global record;
record.mId = sGlobals[i];
record.mId = ESM::RefId::stringRefId(sGlobals[i]);
record.mRecordFlags = 0;
record.mValue.setType(i == 2 ? ESM::VT_Float : ESM::VT_Long);
@ -207,7 +207,7 @@ void CSMDoc::Document::createBase()
{
ESM::Skill record;
record.mIndex = i;
record.mId = ESM::Skill::indexToId(record.mIndex);
record.mId = ESM::RefId::stringRefId(ESM::Skill::indexToId(record.mIndex));
record.blank();
getData().getSkills().add(record);
@ -228,7 +228,7 @@ void CSMDoc::Document::createBase()
for (int i = 0; sVoice[i]; ++i)
{
ESM::Dialogue record;
record.mId = sVoice[i];
record.mId = ESM::RefId::stringRefId(sVoice[i]);
record.mType = ESM::Dialogue::Voice;
record.blank();
@ -252,7 +252,7 @@ void CSMDoc::Document::createBase()
for (int i = 0; sGreetings[i]; ++i)
{
ESM::Dialogue record;
record.mId = sGreetings[i];
record.mId = ESM::RefId::stringRefId(sGreetings[i]);
record.mType = ESM::Dialogue::Greeting;
record.blank();
@ -276,7 +276,7 @@ void CSMDoc::Document::createBase()
for (int i = 0; sPersuasion[i]; ++i)
{
ESM::Dialogue record;
record.mId = sPersuasion[i];
record.mId = ESM::RefId::stringRefId(sPersuasion[i]);
record.mType = ESM::Dialogue::Persuasion;
record.blank();
@ -288,7 +288,7 @@ void CSMDoc::Document::createBase()
ESM::MagicEffect record;
record.mIndex = i;
record.mId = ESM::MagicEffect::indexToId(i);
record.mId = ESM::RefId::stringRefId(ESM::MagicEffect::indexToId(i));
record.blank();
@ -504,7 +504,8 @@ void CSMDoc::Document::startRunning(const std::string& profile, const std::strin
contentFiles.emplace_back(mContentFile.filename());
}
mRunner.configure(getData().getDebugProfiles().getRecord(profile).get(), contentFiles, startupInstruction);
mRunner.configure(getData().getDebugProfiles().getRecord(ESM::RefId::stringRefId(profile)).get(), contentFiles,
startupInstruction);
int state = getState();

@ -145,7 +145,7 @@ void CSMDoc::WriteDialogueCollectionStage::perform(int stage, Messages& messages
// Test, if we need to save anything associated info records.
bool infoModified = false;
CSMWorld::InfoCollection::Range range = mInfos.getTopicRange(topic.get().mId);
CSMWorld::InfoCollection::Range range = mInfos.getTopicRange(topic.get().mId.getRefIdString());
for (CSMWorld::InfoCollection::RecordConstIterator iter(range.first); iter != range.second; ++iter)
{
@ -178,24 +178,26 @@ void CSMDoc::WriteDialogueCollectionStage::perform(int stage, Messages& messages
if ((*iter)->isModified() || (*iter)->mState == CSMWorld::RecordBase::State_Deleted)
{
ESM::DialInfo info = (*iter)->get();
info.mId = info.mId.substr(info.mId.find_last_of('#') + 1);
std::string_view infoIdString = info.mId.getRefIdString();
info.mId = ESM::RefId::stringRefId(infoIdString.substr(infoIdString.find_last_of('#') + 1));
info.mPrev.clear();
info.mPrev = ESM::RefId::sEmpty;
if (iter != range.first)
{
CSMWorld::InfoCollection::RecordConstIterator prev = iter;
--prev;
info.mPrev = (*prev)->get().mId.substr((*prev)->get().mId.find_last_of('#') + 1);
std::string_view prevIdString = (*prev)->get().mId.getRefIdString();
info.mPrev = ESM::RefId::stringRefId(prevIdString.substr(prevIdString.find_last_of('#') + 1));
}
CSMWorld::InfoCollection::RecordConstIterator next = iter;
++next;
info.mNext.clear();
info.mNext = ESM::RefId::sEmpty;
if (next != range.second)
{
info.mNext = (*next)->get().mId.substr((*next)->get().mId.find_last_of('#') + 1);
std::string_view nextIdString = (*next)->get().mId.getRefIdString();
info.mNext = ESM::RefId::stringRefId(nextIdString.substr(nextIdString.find_last_of('#') + 1));
}
writer.startRecord(info.sRecordId);
@ -251,12 +253,13 @@ void CSMDoc::CollectionReferencesStage::perform(int stage, Messages& messages)
if (record.isModified() || record.mState == CSMWorld::RecordBase::State_Deleted)
{
std::string cellId = record.get().mOriginalCell.empty() ? record.get().mCell : record.get().mOriginalCell;
const ESM::RefId& cellId
= record.get().mOriginalCell.empty() ? record.get().mCell : record.get().mOriginalCell;
std::deque<int>& indices = mState.getSubRecords()[Misc::StringUtils::lowerCase(cellId)];
std::deque<int>& indices = mState.getSubRecords()[cellId.getRefIdString()];
// collect moved references at the end of the container
bool interior = cellId.substr(0, 1) != "#";
bool interior = cellId.getRefIdString()[0] != '#';
std::ostringstream stream;
if (!interior)
{
@ -267,7 +270,8 @@ void CSMDoc::CollectionReferencesStage::perform(int stage, Messages& messages)
// An empty mOriginalCell is meant to indicate that it is the same as
// the current cell. It is possible that a moved ref is moved again.
if ((record.get().mOriginalCell.empty() ? record.get().mCell : record.get().mOriginalCell) != stream.str()
if ((record.get().mOriginalCell.empty() ? record.get().mCell : record.get().mOriginalCell)
!= ESM::RefId::stringRefId(stream.str())
&& !interior && record.mState != CSMWorld::RecordBase::State_ModifiedOnly && !record.get().mNew)
indices.push_back(i);
else
@ -312,13 +316,13 @@ void CSMDoc::WriteCellCollectionStage::writeReferences(
stream << "#" << index.first << " " << index.second;
}
ESM::RefId streamId = ESM::RefId::stringRefId(stream.str());
if (refRecord.mNew || refRecord.mRefNum.mIndex == 0
|| (!interior && ref.mState == CSMWorld::RecordBase::State_ModifiedOnly
&& refRecord.mCell != stream.str()))
|| (!interior && ref.mState == CSMWorld::RecordBase::State_ModifiedOnly && refRecord.mCell != streamId))
{
refRecord.mRefNum.mIndex = newRefNum++;
}
else if ((refRecord.mOriginalCell.empty() ? refRecord.mCell : refRecord.mOriginalCell) != stream.str()
else if ((refRecord.mOriginalCell.empty() ? refRecord.mCell : refRecord.mOriginalCell) != streamId
&& !interior)
{
// An empty mOriginalCell is meant to indicate that it is the same as
@ -353,13 +357,13 @@ void CSMDoc::WriteCellCollectionStage::perform(int stage, Messages& messages)
std::deque<int> persistentRefs;
std::map<std::string, std::deque<int>>::const_iterator references
= mState.getSubRecords().find(Misc::StringUtils::lowerCase(cell.get().mId));
= mState.getSubRecords().find(cell.get().mId.getRefIdString());
if (cell.isModified() || cell.mState == CSMWorld::RecordBase::State_Deleted
|| references != mState.getSubRecords().end())
{
CSMWorld::Cell cellRecord = cell.get();
bool interior = cellRecord.mId.substr(0, 1) != "#";
bool interior = cellRecord.mId.getRefIdString()[0] != '#';
// count new references and adjust RefNumCount accordingsly
unsigned int newRefNum = cellRecord.mRefNumCounter;
@ -387,7 +391,8 @@ void CSMDoc::WriteCellCollectionStage::perform(int stage, Messages& messages)
if (refRecord.mNew
|| (!interior && ref.mState == CSMWorld::RecordBase::State_ModifiedOnly &&
/// \todo consider worldspace
CSMWorld::CellCoordinates(refRecord.getCellIndex()).getId("") != refRecord.mCell))
ESM::RefId::stringRefId(CSMWorld::CellCoordinates(refRecord.getCellIndex()).getId(""))
!= refRecord.mCell))
++cellRecord.mRefNumCounter;
if (refRecord.mRefNum.mIndex >= newRefNum)
@ -404,7 +409,7 @@ void CSMDoc::WriteCellCollectionStage::perform(int stage, Messages& messages)
{
cellRecord.mData.mFlags &= ~ESM::Cell::Interior;
std::istringstream stream(cellRecord.mId.c_str());
std::istringstream stream(cellRecord.mId.getRefIdString().c_str());
char ignore;
stream >> ignore >> cellRecord.mData.mX >> cellRecord.mData.mY;
}
@ -442,10 +447,10 @@ void CSMDoc::WritePathgridCollectionStage::perform(int stage, Messages& messages
if (pathgrid.isModified() || pathgrid.mState == CSMWorld::RecordBase::State_Deleted)
{
CSMWorld::Pathgrid record = pathgrid.get();
if (record.mId.substr(0, 1) == "#")
std::string recordIdString = record.mId.getRefIdString();
if (recordIdString[0] == '#')
{
std::istringstream stream(record.mId.c_str());
std::istringstream stream(recordIdString.c_str());
char ignore;
stream >> ignore >> record.mData.mX >> record.mData.mY;
}

@ -97,7 +97,7 @@ namespace CSMDoc
template <class CollectionT>
void WriteCollectionStage<CollectionT>::perform(int stage, Messages& messages)
{
if (CSMWorld::getScopeFromId(mCollection.getRecord(stage).get().mId) != mScope)
if (CSMWorld::getScopeFromId(mCollection.getRecord(stage).get().mId.getRefIdString()) != mScope)
return;
ESM::ESMWriter& writer = mState.getWriter();

@ -68,7 +68,7 @@ bool CSMDoc::SavingState::isProjectFile() const
return mProjectFile;
}
std::map<std::string, std::deque<int>>& CSMDoc::SavingState::getSubRecords()
std::map<std::string, std::deque<int>, Misc::StringUtils::CiComp>& CSMDoc::SavingState::getSubRecords()
{
return mSubRecords;
}

@ -9,8 +9,8 @@
#include <components/esm3/esmwriter.hpp>
#include <components/misc/algorithm.hpp>
#include <components/to_utf8/to_utf8.hpp>
namespace CSMDoc
{
class Operation;
@ -26,7 +26,7 @@ namespace CSMDoc
ESM::ESMWriter mWriter;
std::filesystem::path mProjectPath;
bool mProjectFile;
std::map<std::string, std::deque<int>> mSubRecords; // record ID, list of subrecords
std::map<std::string, std::deque<int>, Misc::StringUtils::CiComp> mSubRecords; // record ID, list of subrecords
public:
SavingState(Operation& operation, std::filesystem::path projectPath, ToUTF8::FromType encoding);
@ -47,7 +47,7 @@ namespace CSMDoc
bool isProjectFile() const;
///< Currently saving project file? (instead of content file)
std::map<std::string, std::deque<int>>& getSubRecords();
std::map<std::string, std::deque<int>, Misc::StringUtils::CiComp>& getSubRecords();
};
}

@ -61,6 +61,7 @@ void CSMTools::BodyPartCheckStage::perform(int stage, CSMDoc::Messages& messages
if (bodyPart.mRace.empty())
messages.add(id, "Race is missing", "", CSMDoc::Message::Severity_Error);
else if (mRaces.searchId(bodyPart.mRace) == -1)
messages.add(id, "Race '" + bodyPart.mRace + "' does not exist", "", CSMDoc::Message::Severity_Error);
messages.add(id, "Race '" + bodyPart.mRace.getRefIdString() + "' does not exist", "",
CSMDoc::Message::Severity_Error);
}
}

@ -40,18 +40,18 @@ void CSMTools::GmstCheckStage::perform(int stage, CSMDoc::Messages& messages)
const ESM::GameSetting& gmst = record.get();
CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Gmst, gmst.mId);
const std::string& gmstIdString = gmst.mId.getRefIdString();
// Test for empty string
if (gmst.mValue.getType() == ESM::VT_String && gmst.mValue.getString().empty())
messages.add(id, gmst.mId + " is an empty string", "", CSMDoc::Message::Severity_Warning);
messages.add(id, gmstIdString + " is an empty string", "", CSMDoc::Message::Severity_Warning);
// Checking type and limits
// optimization - compare it to lists based on naming convention (f-float,i-int,s-string)
if (gmst.mId[0] == 'f')
if (gmstIdString[0] == 'f')
{
for (size_t i = 0; i < CSMWorld::DefaultGmsts::FloatCount; ++i)
{
if (gmst.mId == CSMWorld::DefaultGmsts::Floats[i])
if (gmst.mId == ESM::RefId::stringRefId(CSMWorld::DefaultGmsts::Floats[i]))
{
if (gmst.mValue.getType() != ESM::VT_Float)
{
@ -64,21 +64,21 @@ void CSMTools::GmstCheckStage::perform(int stage, CSMDoc::Messages& messages)
if (gmst.mValue.getFloat() < CSMWorld::DefaultGmsts::FloatLimits[i * 2])
messages.add(
id, gmst.mId + " is less than the suggested range", "", CSMDoc::Message::Severity_Warning);
id, gmstIdString + " is less than the suggested range", "", CSMDoc::Message::Severity_Warning);
if (gmst.mValue.getFloat() > CSMWorld::DefaultGmsts::FloatLimits[i * 2 + 1])
messages.add(
id, gmst.mId + " is more than the suggested range", "", CSMDoc::Message::Severity_Warning);
id, gmstIdString + " is more than the suggested range", "", CSMDoc::Message::Severity_Warning);
break; // for loop
}
}
}
else if (gmst.mId[0] == 'i')
else if (gmstIdString[0] == 'i')
{
for (size_t i = 0; i < CSMWorld::DefaultGmsts::IntCount; ++i)
{
if (gmst.mId == CSMWorld::DefaultGmsts::Ints[i])
if (gmst.mId == ESM::RefId::stringRefId(CSMWorld::DefaultGmsts::Ints[i]))
{
if (gmst.mValue.getType() != ESM::VT_Int)
{
@ -91,28 +91,28 @@ void CSMTools::GmstCheckStage::perform(int stage, CSMDoc::Messages& messages)
if (gmst.mValue.getInteger() < CSMWorld::DefaultGmsts::IntLimits[i * 2])
messages.add(
id, gmst.mId + " is less than the suggested range", "", CSMDoc::Message::Severity_Warning);
id, gmstIdString + " is less than the suggested range", "", CSMDoc::Message::Severity_Warning);
if (gmst.mValue.getInteger() > CSMWorld::DefaultGmsts::IntLimits[i * 2 + 1])
messages.add(
id, gmst.mId + " is more than the suggested range", "", CSMDoc::Message::Severity_Warning);
id, gmstIdString + " is more than the suggested range", "", CSMDoc::Message::Severity_Warning);
break; // for loop
}
}
}
else if (gmst.mId[0] == 's')
else if (gmstIdString[0] == 's')
{
for (size_t i = 0; i < CSMWorld::DefaultGmsts::StringCount; ++i)
{
if (gmst.mId == CSMWorld::DefaultGmsts::Strings[i])
if (gmst.mId == ESM::RefId::stringRefId(CSMWorld::DefaultGmsts::Strings[i]))
{
ESM::VarType type = gmst.mValue.getType();
if (type != ESM::VT_String && type != ESM::VT_None)
{
std::ostringstream stream;
stream << "Expected string or none type for " << gmst.mId << " but found "
stream << "Expected string or none type for " << gmstIdString << " but found "
<< varTypeToString(gmst.mValue.getType()) << " type";
messages.add(id, stream.str(), "", CSMDoc::Message::Severity_Error);

@ -50,7 +50,7 @@ void CSMTools::JournalCheckStage::perform(int stage, CSMDoc::Messages& messages)
int totalInfoCount = 0;
std::set<int> questIndices;
CSMWorld::InfoCollection::Range range = mJournalInfos.getTopicRange(journal.mId);
CSMWorld::InfoCollection::Range range = mJournalInfos.getTopicRange(journal.mId.getRefIdString());
for (CSMWorld::InfoCollection::RecordConstIterator it = range.first; it != range.second; ++it)
{

@ -20,13 +20,13 @@ namespace ESM
}
std::string CSMTools::MagicEffectCheckStage::checkObject(
const std::string& id, const CSMWorld::UniversalId& type, const std::string& column) const
const ESM::RefId& id, const CSMWorld::UniversalId& type, const std::string& column) const
{
CSMWorld::RefIdData::LocalIndex index = mObjects.getDataSet().searchId(id);
if (index.first == -1)
return (column + " '" + id + "' does not exist");
return (column + " '" + id.getRefIdString() + "' does not exist");
else if (index.second != type.getType())
return (column + " '" + id + "' does not have " + type.getTypeName() + " type");
return (column + " '" + id.getRefIdString() + "' does not have " + type.getTypeName() + " type");
return std::string();
}
@ -124,12 +124,15 @@ void CSMTools::MagicEffectCheckStage::perform(int stage, CSMDoc::Messages& messa
}
if (!effect.mCastSound.empty() && mSounds.searchId(effect.mCastSound) == -1)
messages.add(
id, "Casting sound '" + effect.mCastSound + "' does not exist", "", CSMDoc::Message::Severity_Error);
messages.add(id, "Casting sound '" + effect.mCastSound.getRefIdString() + "' does not exist", "",
CSMDoc::Message::Severity_Error);
if (!effect.mHitSound.empty() && mSounds.searchId(effect.mHitSound) == -1)
messages.add(id, "Hit sound '" + effect.mHitSound + "' does not exist", "", CSMDoc::Message::Severity_Error);
messages.add(id, "Hit sound '" + effect.mHitSound.getRefIdString() + "' does not exist", "",
CSMDoc::Message::Severity_Error);
if (!effect.mAreaSound.empty() && mSounds.searchId(effect.mAreaSound) == -1)
messages.add(id, "Area sound '" + effect.mAreaSound + "' does not exist", "", CSMDoc::Message::Severity_Error);
messages.add(id, "Area sound '" + effect.mAreaSound.getRefIdString() + "' does not exist", "",
CSMDoc::Message::Severity_Error);
if (!effect.mBoltSound.empty() && mSounds.searchId(effect.mBoltSound) == -1)
messages.add(id, "Bolt sound '" + effect.mBoltSound + "' does not exist", "", CSMDoc::Message::Severity_Error);
messages.add(id, "Bolt sound '" + effect.mBoltSound.getRefIdString() + "' does not exist", "",
CSMDoc::Message::Severity_Error);
}

@ -42,7 +42,7 @@ namespace CSMTools
private:
std::string checkObject(
const std::string& id, const CSMWorld::UniversalId& type, const std::string& column) const;
const ESM::RefId& id, const CSMWorld::UniversalId& type, const std::string& column) const;
public:
MagicEffectCheckStage(const CSMWorld::IdCollection<ESM::MagicEffect>& effects,

@ -10,7 +10,7 @@
#include <apps/opencs/model/world/universalid.hpp>
CSMTools::MandatoryIdStage::MandatoryIdStage(const CSMWorld::CollectionBase& idCollection,
const CSMWorld::UniversalId& collectionId, const std::vector<std::string>& ids)
const CSMWorld::UniversalId& collectionId, const std::vector<ESM::RefId>& ids)
: mIdCollection(idCollection)
, mCollectionId(collectionId)
, mIds(ids)
@ -25,5 +25,5 @@ int CSMTools::MandatoryIdStage::setup()
void CSMTools::MandatoryIdStage::perform(int stage, CSMDoc::Messages& messages)
{
if (mIdCollection.searchId(mIds.at(stage)) == -1 || mIdCollection.getRecord(mIds.at(stage)).isDeleted())
messages.add(mCollectionId, "Missing mandatory record: " + mIds.at(stage));
messages.add(mCollectionId, "Missing mandatory record: " + mIds.at(stage).getRefIdString());
}

@ -4,9 +4,9 @@
#include <string>
#include <vector>
#include "../world/universalid.hpp"
#include "../doc/stage.hpp"
#include "../world/universalid.hpp"
#include <components/esm/refid.hpp>
namespace CSMDoc
{
@ -25,11 +25,11 @@ namespace CSMTools
{
const CSMWorld::CollectionBase& mIdCollection;
CSMWorld::UniversalId mCollectionId;
std::vector<std::string> mIds;
std::vector<ESM::RefId> mIds;
public:
MandatoryIdStage(const CSMWorld::CollectionBase& idCollection, const CSMWorld::UniversalId& collectionId,
const std::vector<std::string>& ids);
const std::vector<ESM::RefId>& ids);
int setup() override;
///< \return number of steps

@ -68,7 +68,7 @@ void CSMTools::FinishMergedDocumentStage::perform(int stage, CSMDoc::Messages& m
reader.open(path);
CSMWorld::MetaData source;
source.mId = "sys::meta";
source.mId = ESM::RefId::stringRefId("sys::meta");
source.load(reader);
CSMWorld::MetaData target = mState.mTarget->getData().getMetaData();
@ -117,7 +117,7 @@ void CSMTools::MergeReferencesStage::perform(int stage, CSMDoc::Messages& messag
ref.mOriginalCell = ref.mCell;
ref.mRefNum.mIndex = mIndex[Misc::StringUtils::lowerCase(ref.mCell)]++;
ref.mRefNum.mIndex = mIndex[Misc::StringUtils::lowerCase(ref.mCell.getRefIdString())]++;
ref.mRefNum.mContentFile = 0;
ref.mNew = false;
@ -190,7 +190,7 @@ void CSMTools::FixLandsAndLandTexturesMergeStage::perform(int stage, CSMDoc::Mes
CSMWorld::IdTable& ltexTable = dynamic_cast<CSMWorld::IdTable&>(
*mState.mTarget->getData().getTableModel(CSMWorld::UniversalId::Type_LandTextures));
std::string id = mState.mTarget->getData().getLand().getId(stage);
const std::string& id = mState.mTarget->getData().getLand().getId(stage).getRefIdString();
CSMWorld::TouchLandCommand cmd(landTable, ltexTable, id);
cmd.redo();

@ -519,10 +519,11 @@ void CSMTools::ReferenceableCheckStage::creatureCheck(
{
CSMWorld::RefIdData::LocalIndex index = mReferencables.searchId(creature.mOriginal);
if (index.first == -1)
messages.add(
id, "Parent creature '" + creature.mOriginal + "' does not exist", "", CSMDoc::Message::Severity_Error);
messages.add(id, "Parent creature '" + creature.mOriginal.getRefIdString() + "' does not exist", "",
CSMDoc::Message::Severity_Error);
else if (index.second != CSMWorld::UniversalId::Type_Creature)
messages.add(id, "'" + creature.mOriginal + "' is not a creature", "", CSMDoc::Message::Severity_Error);
messages.add(id, "'" + creature.mOriginal.getRefIdString() + "' is not a creature", "",
CSMDoc::Message::Severity_Error);
}
// Check inventory
@ -681,7 +682,7 @@ void CSMTools::ReferenceableCheckStage::npcCheck(
CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Npc, npc.mId);
// Detect if player is present
if (Misc::StringUtils::ciEqual(npc.mId, "player")) // Happy now, scrawl?
if (npc.mId == "Player") // Happy now, scrawl?
mPlayerPresent = true;
// Skip "Base" records (setting!)
@ -739,22 +740,26 @@ void CSMTools::ReferenceableCheckStage::npcCheck(
if (npc.mClass.empty())
messages.add(id, "Class is missing", "", CSMDoc::Message::Severity_Error);
else if (mClasses.searchId(npc.mClass) == -1)
messages.add(id, "Class '" + npc.mClass + "' does not exist", "", CSMDoc::Message::Severity_Error);
messages.add(
id, "Class '" + npc.mClass.getRefIdString() + "' does not exist", "", CSMDoc::Message::Severity_Error);
if (npc.mRace.empty())
messages.add(id, "Race is missing", "", CSMDoc::Message::Severity_Error);
else if (mRaces.searchId(npc.mRace) == -1)
messages.add(id, "Race '" + npc.mRace + "' does not exist", "", CSMDoc::Message::Severity_Error);
messages.add(
id, "Race '" + npc.mRace.getRefIdString() + "' does not exist", "", CSMDoc::Message::Severity_Error);
if (!npc.mFaction.empty() && mFactions.searchId(npc.mFaction) == -1)
messages.add(id, "Faction '" + npc.mFaction + "' does not exist", "", CSMDoc::Message::Severity_Error);
messages.add(
id, "Faction '" + npc.mFaction.getRefIdString() + "' does not exist", "", CSMDoc::Message::Severity_Error);
if (npc.mHead.empty())
messages.add(id, "Head is missing", "", CSMDoc::Message::Severity_Error);
else
{
if (mBodyParts.searchId(npc.mHead) == -1)
messages.add(id, "Head body part '" + npc.mHead + "' does not exist", "", CSMDoc::Message::Severity_Error);
messages.add(id, "Head body part '" + npc.mHead.getRefIdString() + "' does not exist", "",
CSMDoc::Message::Severity_Error);
/// \todo Check gender, race and other body parts stuff validity for the specific NPC
}
@ -763,7 +768,8 @@ void CSMTools::ReferenceableCheckStage::npcCheck(
else
{
if (mBodyParts.searchId(npc.mHair) == -1)
messages.add(id, "Hair body part '" + npc.mHair + "' does not exist", "", CSMDoc::Message::Severity_Error);
messages.add(id, "Hair body part '" + npc.mHair.getRefIdString() + "' does not exist", "",
CSMDoc::Message::Severity_Error);
/// \todo Check gender, race and other body part stuff validity for the specific NPC
}
@ -903,8 +909,9 @@ void CSMTools::ReferenceableCheckStage::inventoryListCheck(
{
for (size_t i = 0; i < itemList.size(); ++i)
{
std::string itemName = itemList[i].mItem;
CSMWorld::RefIdData::LocalIndex localIndex = mReferencables.searchId(itemName);
const ESM::RefId& item = itemList[i].mItem;
const auto& itemName = item.getRefIdString();
CSMWorld::RefIdData::LocalIndex localIndex = mReferencables.searchId(item);
if (localIndex.first == -1)
messages.add(id, "Item '" + itemName + "' does not exist", "", CSMDoc::Message::Severity_Error);
@ -1035,11 +1042,11 @@ void CSMTools::ReferenceableCheckStage::listCheck(
for (unsigned i = 0; i < someList.mList.size(); ++i)
{
if (mReferencables.searchId(someList.mList[i].mId).first == -1)
messages.add(
someID, "Object '" + someList.mList[i].mId + "' does not exist", "", CSMDoc::Message::Severity_Error);
messages.add(someID, "Object '" + someList.mList[i].mId.getRefIdString() + "' does not exist", "",
CSMDoc::Message::Severity_Error);
if (someList.mList[i].mLevel < 1)
messages.add(someID, "Level of item '" + someList.mList[i].mId + "' is non-positive", "",
messages.add(someID, "Level of item '" + someList.mList[i].mId.getRefIdString() + "' is non-positive", "",
CSMDoc::Message::Severity_Error);
}
}
@ -1051,7 +1058,7 @@ void CSMTools::ReferenceableCheckStage::scriptCheck(
if (!someTool.mScript.empty())
{
if (mScripts.searchId(someTool.mScript) == -1)
messages.add(
someID, "Script '" + someTool.mScript + "' does not exist", "", CSMDoc::Message::Severity_Error);
messages.add(someID, "Script '" + someTool.mScript.getRefIdString() + "' does not exist", "",
CSMDoc::Message::Severity_Error);
}
}

@ -50,8 +50,8 @@ void CSMTools::ReferenceCheckStage::perform(int stage, CSMDoc::Messages& message
{
// Check for non existing referenced object
if (mObjects.searchId(cellRef.mRefID) == -1)
messages.add(
id, "Instance of a non-existent object '" + cellRef.mRefID + "'", "", CSMDoc::Message::Severity_Error);
messages.add(id, "Instance of a non-existent object '" + cellRef.mRefID.getRefIdString() + "'", "",
CSMDoc::Message::Severity_Error);
else
{
// Check if reference charge is valid for it's proper referenced type
@ -64,13 +64,14 @@ void CSMTools::ReferenceCheckStage::perform(int stage, CSMDoc::Messages& message
// If object have owner, check if that owner reference is valid
if (!cellRef.mOwner.empty() && mObjects.searchId(cellRef.mOwner) == -1)
messages.add(id, "Owner object '" + cellRef.mOwner + "' does not exist", "", CSMDoc::Message::Severity_Error);
messages.add(id, "Owner object '" + cellRef.mOwner.getRefIdString() + "' does not exist", "",
CSMDoc::Message::Severity_Error);
// If object have creature soul trapped, check if that creature reference is valid
if (!cellRef.mSoul.empty())
if (mObjects.searchId(cellRef.mSoul) == -1)
messages.add(
id, "Trapped soul object '" + cellRef.mSoul + "' does not exist", "", CSMDoc::Message::Severity_Error);
messages.add(id, "Trapped soul object '" + cellRef.mSoul.getRefIdString() + "' does not exist", "",
CSMDoc::Message::Severity_Error);
if (cellRef.mFaction.empty())
{
@ -80,14 +81,15 @@ void CSMTools::ReferenceCheckStage::perform(int stage, CSMDoc::Messages& message
else
{
if (mFactions.searchId(cellRef.mFaction) == -1)
messages.add(id, "Faction '" + cellRef.mFaction + "' does not exist", "", CSMDoc::Message::Severity_Error);
messages.add(id, "Faction '" + cellRef.mFaction.getRefIdString() + "' does not exist", "",
CSMDoc::Message::Severity_Error);
else if (cellRef.mFactionRank < -1)
messages.add(id, "Invalid faction rank", "", CSMDoc::Message::Severity_Error);
}
if (!cellRef.mDestCell.empty() && mCells.searchId(cellRef.mDestCell) == -1)
messages.add(
id, "Destination cell '" + cellRef.mDestCell + "' does not exist", "", CSMDoc::Message::Severity_Error);
messages.add(id, "Destination cell '" + cellRef.mDestCell.getRefIdString() + "' does not exist", "",
CSMDoc::Message::Severity_Error);
if (cellRef.mScale < 0)
messages.add(id, "Negative scale", "", CSMDoc::Message::Severity_Error);

@ -56,7 +56,7 @@ void CSMTools::RegionCheckStage::perform(int stage, CSMDoc::Messages& messages)
for (const ESM::Region::SoundRef& sound : region.mSoundList)
{
if (sound.mChance > 100)
messages.add(id, "Chance of '" + sound.mSound + "' sound to play is over 100 percent", "",
messages.add(id, "Chance of '" + sound.mSound.getRefIdString() + "' sound to play is over 100 percent", "",
CSMDoc::Message::Severity_Warning);
}

@ -92,7 +92,7 @@ int CSMTools::ScriptCheckStage::setup()
mContext.clear();
mMessages = nullptr;
mId.clear();
mId = ESM::RefId::sEmpty;
Compiler::ErrorHandler::reset();
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
@ -130,7 +130,7 @@ void CSMTools::ScriptCheckStage::perform(int stage, CSMDoc::Messages& messages)
try
{
mFile = record.get().mId;
mFile = record.get().mId.getRefIdString();
std::istringstream input(record.get().mScriptText);
Compiler::Scanner scanner(*this, input, mContext.getExtensions());

@ -37,7 +37,7 @@ namespace CSMTools
const CSMDoc::Document& mDocument;
Compiler::Extensions mExtensions;
CSMWorld::ScriptContext mContext;
std::string mId;
ESM::RefId mId;
std::string mFile;
CSMDoc::Messages* mMessages;
WarningMode mWarningMode;

@ -49,12 +49,13 @@ void CSMTools::SoundGenCheckStage::perform(int stage, CSMDoc::Messages& messages
CSMWorld::RefIdData::LocalIndex creatureIndex = mObjects.getDataSet().searchId(soundGen.mCreature);
if (creatureIndex.first == -1)
{
messages.add(
id, "Creature '" + soundGen.mCreature + "' doesn't exist", "", CSMDoc::Message::Severity_Error);
messages.add(id, "Creature '" + soundGen.mCreature.getRefIdString() + "' doesn't exist", "",
CSMDoc::Message::Severity_Error);
}
else if (creatureIndex.second != CSMWorld::UniversalId::Type_Creature)
{
messages.add(id, "'" + soundGen.mCreature + "' is not a creature", "", CSMDoc::Message::Severity_Error);
messages.add(id, "'" + soundGen.mCreature.getRefIdString() + "' is not a creature", "",
CSMDoc::Message::Severity_Error);
}
}
@ -64,6 +65,7 @@ void CSMTools::SoundGenCheckStage::perform(int stage, CSMDoc::Messages& messages
}
else if (mSounds.searchId(soundGen.mSound) == -1)
{
messages.add(id, "Sound '" + soundGen.mSound + "' doesn't exist", "", CSMDoc::Message::Severity_Error);
messages.add(
id, "Sound '" + soundGen.mSound.getRefIdString() + "' doesn't exist", "", CSMDoc::Message::Severity_Error);
}
}

@ -35,12 +35,13 @@ void CSMTools::StartScriptCheckStage::perform(int stage, CSMDoc::Messages& messa
if ((mIgnoreBaseRecords && record.mState == CSMWorld::RecordBase::State_BaseOnly) || record.isDeleted())
return;
std::string scriptId = record.get().mId;
const auto& scriptId = record.get().mId;
CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_StartScript, scriptId);
if (mScripts.searchId(Misc::StringUtils::lowerCase(scriptId)) == -1)
messages.add(id, "Start script " + scriptId + " does not exist", "", CSMDoc::Message::Severity_Error);
if (mScripts.searchId(scriptId) == -1)
messages.add(
id, "Start script " + scriptId.getRefIdString() + " does not exist", "", CSMDoc::Message::Severity_Error);
}
int CSMTools::StartScriptCheckStage::setup()

@ -77,10 +77,15 @@ CSMDoc::OperationHolder* CSMTools::Tools::getVerifier()
connect(&mVerifier, &CSMDoc::OperationHolder::done, this, &Tools::done);
connect(&mVerifier, &CSMDoc::OperationHolder::reportMessage, this, &Tools::verifierMessage);
std::vector<std::string> mandatoryIds{ "Day", "DaysPassed", "GameHour", "Month", "PCRace" };
std::vector<ESM::RefId> mandatoryRefIds;
{
auto mandatoryIds = { "Day", "DaysPassed", "GameHour", "Month", "PCRace" };
for (auto& id : mandatoryIds)
mandatoryRefIds.push_back(ESM::RefId::stringRefId(id));
}
mVerifierOperation->appendStage(new MandatoryIdStage(
mData.getGlobals(), CSMWorld::UniversalId(CSMWorld::UniversalId::Type_Globals), mandatoryIds));
mData.getGlobals(), CSMWorld::UniversalId(CSMWorld::UniversalId::Type_Globals), mandatoryRefIds));
mVerifierOperation->appendStage(new SkillCheckStage(mData.getSkills()));

@ -75,7 +75,7 @@ int CSMTools::TopicInfoCheckStage::setup()
if (regionRecord.isDeleted())
continue;
mCellNames.insert(regionRecord.get().mName);
mCellNames.insert(ESM::RefId::stringRefId(regionRecord.get().mName));
}
// Default cell name
int index = mGameSettings.searchId("sDefaultCellname");
@ -85,7 +85,7 @@ int CSMTools::TopicInfoCheckStage::setup()
if (!gmstRecord.isDeleted() && gmstRecord.get().mValue.getType() == ESM::VT_String)
{
mCellNames.insert(gmstRecord.get().mValue.getString());
mCellNames.insert(ESM::RefId::stringRefId(gmstRecord.get().mValue.getString()));
}
}
@ -181,18 +181,20 @@ void CSMTools::TopicInfoCheckStage::perform(int stage, CSMDoc::Messages& message
// Verification functions
bool CSMTools::TopicInfoCheckStage::verifyActor(
const std::string& actor, const CSMWorld::UniversalId& id, CSMDoc::Messages& messages)
const ESM::RefId& actor, const CSMWorld::UniversalId& id, CSMDoc::Messages& messages)
{
const std::string& actorString = actor.getRefIdString();
CSMWorld::RefIdData::LocalIndex index = mReferencables.searchId(actor);
if (index.first == -1)
{
messages.add(id, "Actor '" + actor + "' does not exist", "", CSMDoc::Message::Severity_Error);
messages.add(id, "Actor '" + actorString + "' does not exist", "", CSMDoc::Message::Severity_Error);
return false;
}
else if (mReferencables.getRecord(index).isDeleted())
{
messages.add(id, "Deleted actor '" + actor + "' is being referenced", "", CSMDoc::Message::Severity_Error);
messages.add(
id, "Deleted actor '" + actorString + "' is being referenced", "", CSMDoc::Message::Severity_Error);
return false;
}
else if (index.second != CSMWorld::UniversalId::Type_Npc && index.second != CSMWorld::UniversalId::Type_Creature)
@ -209,11 +211,11 @@ bool CSMTools::TopicInfoCheckStage::verifyActor(
}
bool CSMTools::TopicInfoCheckStage::verifyCell(
const std::string& cell, const CSMWorld::UniversalId& id, CSMDoc::Messages& messages)
const ESM::RefId& cell, const CSMWorld::UniversalId& id, CSMDoc::Messages& messages)
{
if (mCellNames.find(cell) == mCellNames.end())
{
messages.add(id, "Cell '" + cell + "' does not exist", "", CSMDoc::Message::Severity_Error);
messages.add(id, "Cell '" + cell.getRefIdString() + "' does not exist", "", CSMDoc::Message::Severity_Error);
return false;
}
@ -221,7 +223,7 @@ bool CSMTools::TopicInfoCheckStage::verifyCell(
}
bool CSMTools::TopicInfoCheckStage::verifyFactionRank(
const std::string& factionName, int rank, const CSMWorld::UniversalId& id, CSMDoc::Messages& messages)
const ESM::RefId& factionName, int rank, const CSMWorld::UniversalId& id, CSMDoc::Messages& messages)
{
if (rank < -1)
{
@ -256,18 +258,19 @@ bool CSMTools::TopicInfoCheckStage::verifyFactionRank(
}
bool CSMTools::TopicInfoCheckStage::verifyItem(
const std::string& item, const CSMWorld::UniversalId& id, CSMDoc::Messages& messages)
const ESM::RefId& item, const CSMWorld::UniversalId& id, CSMDoc::Messages& messages)
{
const std::string& idString = item.getRefIdString();
CSMWorld::RefIdData::LocalIndex index = mReferencables.searchId(item);
if (index.first == -1)
{
messages.add(id, ("Item '" + item + "' does not exist"), "", CSMDoc::Message::Severity_Error);
messages.add(id, ("Item '" + idString + "' does not exist"), "", CSMDoc::Message::Severity_Error);
return false;
}
else if (mReferencables.getRecord(index).isDeleted())
{
messages.add(id, ("Deleted item '" + item + "' is being referenced"), "", CSMDoc::Message::Severity_Error);
messages.add(id, ("Deleted item '" + idString + "' is being referenced"), "", CSMDoc::Message::Severity_Error);
return false;
}
else
@ -363,47 +366,47 @@ bool CSMTools::TopicInfoCheckStage::verifySelectStruct(
// Id checks
if (infoCondition.getFunctionName() == CSMWorld::ConstInfoSelectWrapper::Function_Global
&& !verifyId(infoCondition.getVariableName(), mGlobals, id, messages))
&& !verifyId(ESM::RefId::stringRefId(infoCondition.getVariableName()), mGlobals, id, messages))
{
return false;
}
else if (infoCondition.getFunctionName() == CSMWorld::ConstInfoSelectWrapper::Function_Journal
&& !verifyId(infoCondition.getVariableName(), mJournals, id, messages))
&& !verifyId(ESM::RefId::stringRefId(infoCondition.getVariableName()), mJournals, id, messages))
{
return false;
}
else if (infoCondition.getFunctionName() == CSMWorld::ConstInfoSelectWrapper::Function_Item
&& !verifyItem(infoCondition.getVariableName(), id, messages))
&& !verifyItem(ESM::RefId::stringRefId(infoCondition.getVariableName()), id, messages))
{
return false;
}
else if (infoCondition.getFunctionName() == CSMWorld::ConstInfoSelectWrapper::Function_Dead
&& !verifyActor(infoCondition.getVariableName(), id, messages))
&& !verifyActor(ESM::RefId::stringRefId(infoCondition.getVariableName()), id, messages))
{
return false;
}
else if (infoCondition.getFunctionName() == CSMWorld::ConstInfoSelectWrapper::Function_NotId
&& !verifyActor(infoCondition.getVariableName(), id, messages))
&& !verifyActor(ESM::RefId::stringRefId(infoCondition.getVariableName()), id, messages))
{
return false;
}
else if (infoCondition.getFunctionName() == CSMWorld::ConstInfoSelectWrapper::Function_NotFaction
&& !verifyId(infoCondition.getVariableName(), mFactions, id, messages))
&& !verifyId(ESM::RefId::stringRefId(infoCondition.getVariableName()), mFactions, id, messages))
{
return false;
}
else if (infoCondition.getFunctionName() == CSMWorld::ConstInfoSelectWrapper::Function_NotClass
&& !verifyId(infoCondition.getVariableName(), mClasses, id, messages))
&& !verifyId(ESM::RefId::stringRefId(infoCondition.getVariableName()), mClasses, id, messages))
{
return false;
}
else if (infoCondition.getFunctionName() == CSMWorld::ConstInfoSelectWrapper::Function_NotRace
&& !verifyId(infoCondition.getVariableName(), mRaces, id, messages))
&& !verifyId(ESM::RefId::stringRefId(infoCondition.getVariableName()), mRaces, id, messages))
{
return false;
}
else if (infoCondition.getFunctionName() == CSMWorld::ConstInfoSelectWrapper::Function_NotCell
&& !verifyCell(infoCondition.getVariableName(), id, messages))
&& !verifyCell(ESM::RefId::stringRefId(infoCondition.getVariableName()), id, messages))
{
return false;
}
@ -424,20 +427,22 @@ bool CSMTools::TopicInfoCheckStage::verifySound(
}
template <typename T>
bool CSMTools::TopicInfoCheckStage::verifyId(const std::string& name, const CSMWorld::IdCollection<T>& collection,
bool CSMTools::TopicInfoCheckStage::verifyId(const ESM::RefId& name, const CSMWorld::IdCollection<T>& collection,
const CSMWorld::UniversalId& id, CSMDoc::Messages& messages)
{
int index = collection.searchId(name);
if (index == -1)
{
messages.add(id, std::string(T::getRecordType()) + " '" + name + "' does not exist", "",
messages.add(id, std::string(T::getRecordType()) + " '" + name.getRefIdString() + "' does not exist", "",
CSMDoc::Message::Severity_Error);
return false;
}
else if (collection.getRecord(index).isDeleted())
{
messages.add(id, "Deleted " + std::string(T::getRecordType()) + " record '" + name + "' is being referenced",
messages.add(id,
"Deleted " + std::string(T::getRecordType()) + " record '" + name.getRefIdString()
+ "' is being referenced",
"", CSMDoc::Message::Severity_Error);
return false;
}

@ -72,22 +72,22 @@ namespace CSMTools
const CSMWorld::RefIdData& mReferencables;
const CSMWorld::Resources& mSoundFiles;
std::set<std::string> mCellNames;
std::set<ESM::RefId> mCellNames;
bool mIgnoreBaseRecords;
// These return false when not successful and write an error
bool verifyActor(const std::string& name, const CSMWorld::UniversalId& id, CSMDoc::Messages& messages);
bool verifyCell(const std::string& name, const CSMWorld::UniversalId& id, CSMDoc::Messages& messages);
bool verifyActor(const ESM::RefId& name, const CSMWorld::UniversalId& id, CSMDoc::Messages& messages);
bool verifyCell(const ESM::RefId& name, const CSMWorld::UniversalId& id, CSMDoc::Messages& messages);
bool verifyFactionRank(
const std::string& name, int rank, const CSMWorld::UniversalId& id, CSMDoc::Messages& messages);
bool verifyItem(const std::string& name, const CSMWorld::UniversalId& id, CSMDoc::Messages& messages);
const ESM::RefId& name, int rank, const CSMWorld::UniversalId& id, CSMDoc::Messages& messages);
bool verifyItem(const ESM::RefId& name, const CSMWorld::UniversalId& id, CSMDoc::Messages& messages);
bool verifySelectStruct(
const ESM::DialInfo::SelectStruct& select, const CSMWorld::UniversalId& id, CSMDoc::Messages& messages);
bool verifySound(const std::string& name, const CSMWorld::UniversalId& id, CSMDoc::Messages& messages);
template <typename T>
bool verifyId(const std::string& name, const CSMWorld::IdCollection<T>& collection,
bool verifyId(const ESM::RefId& name, const CSMWorld::IdCollection<T>& collection,
const CSMWorld::UniversalId& id, CSMDoc::Messages& messages);
};
}

@ -26,7 +26,7 @@
namespace CSMWorld
{
const std::string& ActorAdapter::RaceData::getId() const
const ESM::RefId& ActorAdapter::RaceData::getId() const
{
return mId;
}
@ -56,47 +56,47 @@ namespace CSMWorld
}
}
const std::string& ActorAdapter::RaceData::getFemalePart(ESM::PartReferenceType index) const
const ESM::RefId& ActorAdapter::RaceData::getFemalePart(ESM::PartReferenceType index) const
{
return mFemaleParts[ESM::getMeshPart(index)];
}
const std::string& ActorAdapter::RaceData::getMalePart(ESM::PartReferenceType index) const
const ESM::RefId& ActorAdapter::RaceData::getMalePart(ESM::PartReferenceType index) const
{
return mMaleParts[ESM::getMeshPart(index)];
}
bool ActorAdapter::RaceData::hasDependency(const std::string& id) const
bool ActorAdapter::RaceData::hasDependency(const ESM::RefId& id) const
{
return mDependencies.find(id) != mDependencies.end();
}
void ActorAdapter::RaceData::setFemalePart(ESM::BodyPart::MeshPart index, const std::string& partId)
void ActorAdapter::RaceData::setFemalePart(ESM::BodyPart::MeshPart index, const ESM::RefId& partId)
{
mFemaleParts[index] = partId;
addOtherDependency(partId);
}
void ActorAdapter::RaceData::setMalePart(ESM::BodyPart::MeshPart index, const std::string& partId)
void ActorAdapter::RaceData::setMalePart(ESM::BodyPart::MeshPart index, const ESM::RefId& partId)
{
mMaleParts[index] = partId;
addOtherDependency(partId);
}
void ActorAdapter::RaceData::addOtherDependency(const std::string& id)
void ActorAdapter::RaceData::addOtherDependency(const ESM::RefId& id)
{
if (!id.empty())
mDependencies.emplace(id);
}
void ActorAdapter::RaceData::reset_data(const std::string& id, bool isBeast)
void ActorAdapter::RaceData::reset_data(const ESM::RefId& id, bool isBeast)
{
mId = id;
mIsBeast = isBeast;
for (auto& str : mFemaleParts)
str.clear();
str = ESM::RefId::sEmpty;
for (auto& str : mMaleParts)
str.clear();
str = ESM::RefId::sEmpty;
mDependencies.clear();
// Mark self as a dependency
@ -109,7 +109,7 @@ namespace CSMWorld
mFemale = false;
}
const std::string& ActorAdapter::ActorData::getId() const
const ESM::RefId& ActorAdapter::ActorData::getId() const
{
return mId;
}
@ -146,12 +146,12 @@ namespace CSMWorld
if (mFemale)
{
// Note: we should use male parts for females as fallback
const std::string& femalePart = mRaceData->getFemalePart(index);
const std::string& femalePart = mRaceData->getFemalePart(index).getRefIdString();
if (!femalePart.empty())
return femalePart;
}
return mRaceData->getMalePart(index);
return mRaceData->getMalePart(index).getRefIdString();
}
return {};
@ -160,12 +160,12 @@ namespace CSMWorld
return it->second.first;
}
bool ActorAdapter::ActorData::hasDependency(const std::string& id) const
bool ActorAdapter::ActorData::hasDependency(const ESM::RefId& id) const
{
return mDependencies.find(id) != mDependencies.end();
}
void ActorAdapter::ActorData::setPart(ESM::PartReferenceType index, const std::string& partId, int priority)
void ActorAdapter::ActorData::setPart(ESM::PartReferenceType index, const ESM::RefId& partId, int priority)
{
auto it = mParts.find(index);
if (it != mParts.end())
@ -174,18 +174,18 @@ namespace CSMWorld
return;
}
mParts[index] = std::make_pair(partId, priority);
mParts[index] = std::make_pair(partId.getRefIdString(), priority);
addOtherDependency(partId);
}
void ActorAdapter::ActorData::addOtherDependency(const std::string& id)
void ActorAdapter::ActorData::addOtherDependency(const ESM::RefId& id)
{
if (!id.empty())
mDependencies.emplace(id);
}
void ActorAdapter::ActorData::reset_data(
const std::string& id, const std::string& skeleton, bool isCreature, bool isFemale, RaceDataPtr raceData)
const ESM::RefId& id, const std::string& skeleton, bool isCreature, bool isFemale, RaceDataPtr raceData)
{
mId = id;
mCreature = isCreature;
@ -225,7 +225,7 @@ namespace CSMWorld
partModel, &QAbstractItemModel::rowsAboutToBeRemoved, this, &ActorAdapter::handleBodyPartsAboutToBeRemoved);
}
ActorAdapter::ActorDataPtr ActorAdapter::getActorData(const std::string& id)
ActorAdapter::ActorDataPtr ActorAdapter::getActorData(const ESM::RefId& id)
{
// Return cached actor data if it exists
ActorDataPtr data = mCachedActors.get(id);
@ -248,7 +248,7 @@ namespace CSMWorld
{
for (int row = start; row <= end; ++row)
{
std::string refId = mReferenceables.getId(row);
auto refId = mReferenceables.getId(row);
markDirtyDependency(refId);
}
}
@ -269,7 +269,7 @@ namespace CSMWorld
// Handle each record
for (int row = start; row <= end; ++row)
{
std::string refId = mReferenceables.getId(row);
auto refId = mReferenceables.getId(row);
markDirtyDependency(refId);
}
@ -284,7 +284,7 @@ namespace CSMWorld
{
for (int row = start; row <= end; ++row)
{
std::string refId = mReferenceables.getId(row);
auto refId = mReferenceables.getId(row);
markDirtyDependency(refId);
}
}
@ -303,7 +303,7 @@ namespace CSMWorld
{
for (int row = start; row <= end; ++row)
{
std::string raceId = mReferenceables.getId(row);
auto raceId = mReferenceables.getId(row);
markDirtyDependency(raceId);
}
}
@ -323,7 +323,7 @@ namespace CSMWorld
for (int row = start; row <= end; ++row)
{
std::string raceId = mRaces.getId(row);
auto raceId = mRaces.getId(row);
markDirtyDependency(raceId);
}
@ -338,7 +338,7 @@ namespace CSMWorld
{
for (int row = start; row <= end; ++row)
{
std::string raceId = mRaces.getId(row);
auto raceId = mRaces.getId(row);
markDirtyDependency(raceId);
}
}
@ -364,7 +364,7 @@ namespace CSMWorld
markDirtyDependency(record.get().mRace);
}
std::string partId = mBodyParts.getId(row);
auto partId = mBodyParts.getId(row);
markDirtyDependency(partId);
}
}
@ -392,7 +392,7 @@ namespace CSMWorld
}
// Update entries with a tracked dependency
std::string partId = mBodyParts.getId(row);
auto partId = mBodyParts.getId(row);
markDirtyDependency(partId);
}
@ -407,7 +407,7 @@ namespace CSMWorld
{
for (int row = start; row <= end; ++row)
{
std::string partId = mBodyParts.getId(row);
auto partId = mBodyParts.getId(row);
markDirtyDependency(partId);
}
}
@ -431,7 +431,7 @@ namespace CSMWorld
return name.size() >= 4 && name.find(".1st", name.size() - 4) != std::string::npos;
}
ActorAdapter::RaceDataPtr ActorAdapter::getRaceData(const std::string& id)
ActorAdapter::RaceDataPtr ActorAdapter::getRaceData(const ESM::RefId& id)
{
// Return cached race data if it exists
RaceDataPtr data = mCachedRaces.get(id);
@ -445,7 +445,7 @@ namespace CSMWorld
return data;
}
void ActorAdapter::setupActor(const std::string& id, ActorDataPtr data)
void ActorAdapter::setupActor(const ESM::RefId& id, ActorDataPtr data)
{
int index = mReferenceables.searchId(id);
if (index == -1)
@ -487,7 +487,7 @@ namespace CSMWorld
}
}
void ActorAdapter::setupRace(const std::string& id, RaceDataPtr data)
void ActorAdapter::setupRace(const ESM::RefId& id, RaceDataPtr data)
{
int index = mRaces.searchId(id);
if (index == -1)
@ -511,7 +511,7 @@ namespace CSMWorld
// Setup body parts
for (int i = 0; i < mBodyParts.getSize(); ++i)
{
std::string partId = mBodyParts.getId(i);
auto partId = mBodyParts.getId(i);
auto& partRecord = mBodyParts.getRecord(i);
if (partRecord.isDeleted())
@ -521,7 +521,8 @@ namespace CSMWorld
}
auto& part = partRecord.get();
if (part.mRace == id && part.mData.mType == ESM::BodyPart::MT_Skin && !is1stPersonPart(part.mId))
if (part.mRace == id && part.mData.mType == ESM::BodyPart::MT_Skin
&& !is1stPersonPart(part.mId.getRefIdString()))
{
auto type = (ESM::BodyPart::MeshPart)part.mData.mPart;
bool female = part.mData.mFlags & ESM::BodyPart::BPF_Female;
@ -533,7 +534,7 @@ namespace CSMWorld
}
}
void ActorAdapter::setupNpc(const std::string& id, ActorDataPtr data)
void ActorAdapter::setupNpc(const ESM::RefId& id, ActorDataPtr data)
{
// Common setup, record is known to exist and is not deleted
int index = mReferenceables.searchId(id);
@ -551,12 +552,12 @@ namespace CSMWorld
{
if (item.mCount <= 0)
continue;
std::string itemId = item.mItem;
auto itemId = item.mItem;
addNpcItem(itemId, data);
}
}
void ActorAdapter::addNpcItem(const std::string& itemId, ActorDataPtr data)
void ActorAdapter::addNpcItem(const ESM::RefId& itemId, ActorDataPtr data)
{
int index = mReferenceables.searchId(itemId);
if (index == -1)
@ -578,7 +579,7 @@ namespace CSMWorld
auto addParts = [&](const std::vector<ESM::PartReference>& list, int priority) {
for (auto& part : list)
{
std::string partId;
ESM::RefId partId;
auto partType = (ESM::PartReferenceType)part.mPart;
if (data->isFemale())
@ -590,7 +591,7 @@ namespace CSMWorld
// An another vanilla quirk: hide hairs if an item replaces Head part
if (partType == ESM::PRT_Head)
data->setPart(ESM::PRT_Hair, "", priority);
data->setPart(ESM::PRT_Hair, ESM::RefId::sEmpty, priority);
}
};
@ -637,7 +638,7 @@ namespace CSMWorld
}
}
void ActorAdapter::setupCreature(const std::string& id, ActorDataPtr data)
void ActorAdapter::setupCreature(const ESM::RefId& id, ActorDataPtr data)
{
// Record is known to exist and is not deleted
int index = mReferenceables.searchId(id);
@ -646,7 +647,7 @@ namespace CSMWorld
data->reset_data(id, creature.mModel, true);
}
void ActorAdapter::markDirtyDependency(const std::string& dep)
void ActorAdapter::markDirtyDependency(const ESM::RefId& dep)
{
for (auto raceIt : mCachedRaces)
{

@ -37,9 +37,9 @@ namespace CSMWorld
/// A list indexed by ESM::PartReferenceType
using ActorPartList = std::map<ESM::PartReferenceType, std::pair<std::string, int>>;
/// A list indexed by ESM::BodyPart::MeshPart
using RacePartList = std::array<std::string, ESM::BodyPart::MP_Count>;
using RacePartList = std::array<ESM::RefId, ESM::BodyPart::MP_Count>;
/// Tracks unique strings
using StringSet = std::unordered_set<std::string>;
using RefIdSet = std::unordered_set<ESM::RefId>;
/// Contains base race data shared between actors
class RaceData
@ -48,34 +48,34 @@ namespace CSMWorld
RaceData();
/// Retrieves the id of the race represented
const std::string& getId() const;
const ESM::RefId& getId() const;
/// Checks if it's a beast race
bool isBeast() const;
/// Checks if a part could exist for the given type
bool handlesPart(ESM::PartReferenceType type) const;
/// Retrieves the associated body part
const std::string& getFemalePart(ESM::PartReferenceType index) const;
const ESM::RefId& getFemalePart(ESM::PartReferenceType index) const;
/// Retrieves the associated body part
const std::string& getMalePart(ESM::PartReferenceType index) const;
const ESM::RefId& getMalePart(ESM::PartReferenceType index) const;
/// Checks if the race has a data dependency
bool hasDependency(const std::string& id) const;
bool hasDependency(const ESM::RefId& id) const;
/// Sets the associated part if it's empty and marks a dependency
void setFemalePart(ESM::BodyPart::MeshPart partIndex, const std::string& partId);
void setFemalePart(ESM::BodyPart::MeshPart partIndex, const ESM::RefId& partId);
/// Sets the associated part if it's empty and marks a dependency
void setMalePart(ESM::BodyPart::MeshPart partIndex, const std::string& partId);
void setMalePart(ESM::BodyPart::MeshPart partIndex, const ESM::RefId& partId);
/// Marks an additional dependency
void addOtherDependency(const std::string& id);
void addOtherDependency(const ESM::RefId& id);
/// Clears parts and dependencies
void reset_data(const std::string& raceId, bool isBeast = false);
void reset_data(const ESM::RefId& raceId, bool isBeast = false);
private:
bool handles(ESM::PartReferenceType type) const;
std::string mId;
ESM::RefId mId;
bool mIsBeast;
RacePartList mFemaleParts;
RacePartList mMaleParts;
StringSet mDependencies;
RefIdSet mDependencies;
};
using RaceDataPtr = std::shared_ptr<RaceData>;
@ -87,7 +87,7 @@ namespace CSMWorld
ActorData();
/// Retrieves the id of the actor represented
const std::string& getId() const;
const ESM::RefId& getId() const;
/// Checks if the actor is a creature
bool isCreature() const;
/// Checks if the actor is female
@ -97,35 +97,35 @@ namespace CSMWorld
/// Retrieves the associated actor part
std::string_view getPart(ESM::PartReferenceType index) const;
/// Checks if the actor has a data dependency
bool hasDependency(const std::string& id) const;
bool hasDependency(const ESM::RefId& id) const;
/// Sets the actor part used and marks a dependency
void setPart(ESM::PartReferenceType partIndex, const std::string& partId, int priority);
void setPart(ESM::PartReferenceType partIndex, const ESM::RefId& partId, int priority);
/// Marks an additional dependency for the actor
void addOtherDependency(const std::string& id);
void addOtherDependency(const ESM::RefId& id);
/// Clears race, parts, and dependencies
void reset_data(const std::string& actorId, const std::string& skeleton = "", bool isCreature = false,
void reset_data(const ESM::RefId& actorId, const std::string& skeleton = "", bool isCreature = false,
bool female = true, RaceDataPtr raceData = nullptr);
private:
std::string mId;
ESM::RefId mId;
bool mCreature;
bool mFemale;
std::string mSkeletonOverride;
RaceDataPtr mRaceData;
ActorPartList mParts;
StringSet mDependencies;
RefIdSet mDependencies;
};
using ActorDataPtr = std::shared_ptr<ActorData>;
ActorAdapter(Data& data);
/// Obtains the shared data for a given actor
ActorDataPtr getActorData(const std::string& refId);
ActorDataPtr getActorData(const ESM::RefId& refId);
signals:
void actorChanged(const std::string& refId);
void actorChanged(const ESM::RefId& refId);
public slots:
@ -151,28 +151,28 @@ namespace CSMWorld
QModelIndex getHighestIndex(QModelIndex) const;
bool is1stPersonPart(const std::string& id) const;
RaceDataPtr getRaceData(const std::string& raceId);
RaceDataPtr getRaceData(const ESM::RefId& raceId);
void setupActor(const std::string& id, ActorDataPtr data);
void setupRace(const std::string& id, RaceDataPtr data);
void setupActor(const ESM::RefId& id, ActorDataPtr data);
void setupRace(const ESM::RefId& id, RaceDataPtr data);
void setupNpc(const std::string& id, ActorDataPtr data);
void addNpcItem(const std::string& itemId, ActorDataPtr data);
void setupNpc(const ESM::RefId& id, ActorDataPtr data);
void addNpcItem(const ESM::RefId& itemId, ActorDataPtr data);
void setupCreature(const std::string& id, ActorDataPtr data);
void setupCreature(const ESM::RefId& id, ActorDataPtr data);
void markDirtyDependency(const std::string& dependency);
void markDirtyDependency(const ESM::RefId& dependency);
void updateDirty();
RefIdCollection& mReferenceables;
IdCollection<ESM::Race>& mRaces;
IdCollection<ESM::BodyPart>& mBodyParts;
Misc::WeakCache<std::string, ActorData> mCachedActors; // Key: referenceable id
Misc::WeakCache<std::string, RaceData> mCachedRaces; // Key: race id
Misc::WeakCache<ESM::RefId, ActorData> mCachedActors; // Key: referenceable id
Misc::WeakCache<ESM::RefId, RaceData> mCachedRaces; // Key: race id
StringSet mDirtyActors; // Actors that need updating
StringSet mDirtyRaces; // Races that need updating
RefIdSet mDirtyActors; // Actors that need updating
RefIdSet mDirtyRaces; // Races that need updating
};
}

@ -11,6 +11,6 @@ void CSMWorld::Cell::load(ESM::ESMReader& esm, bool& isDeleted)
{
std::ostringstream stream;
stream << "#" << mData.mX << " " << mData.mY;
mId = stream.str();
mId = ESM::RefId::stringRefId(stream.str());
}
}

@ -18,7 +18,7 @@ namespace CSMWorld
/// Exterior cell coordinates are encoded in the cell ID.
struct Cell : public ESM::Cell
{
std::string mId;
ESM::RefId mId;
void load(ESM::ESMReader& esm, bool& isDeleted);
};

@ -28,53 +28,53 @@ namespace CSMWorld
template <typename ESXRecordT>
struct IdAccessor
{
void setId(ESXRecordT& record, const std::string& id) const;
const std::string getId(const ESXRecordT& record) const;
void setId(ESXRecordT& record, const ESM::RefId& id) const;
const ESM::RefId getId(const ESXRecordT& record) const;
};
template <typename ESXRecordT>
void IdAccessor<ESXRecordT>::setId(ESXRecordT& record, const std::string& id) const
void IdAccessor<ESXRecordT>::setId(ESXRecordT& record, const ESM::RefId& id) const
{
record.mId = id;
}
template <typename ESXRecordT>
const std::string IdAccessor<ESXRecordT>::getId(const ESXRecordT& record) const
const ESM::RefId IdAccessor<ESXRecordT>::getId(const ESXRecordT& record) const
{
return record.mId;
}
template <>
inline void IdAccessor<Land>::setId(Land& record, const std::string& id) const
inline void IdAccessor<Land>::setId(Land& record, const ESM::RefId& id) const
{
int x = 0, y = 0;
Land::parseUniqueRecordId(id, x, y);
Land::parseUniqueRecordId(id.getRefIdString(), x, y);
record.mX = x;
record.mY = y;
}
template <>
inline void IdAccessor<LandTexture>::setId(LandTexture& record, const std::string& id) const
inline void IdAccessor<LandTexture>::setId(LandTexture& record, const ESM::RefId& id) const
{
int plugin = 0;
int index = 0;
LandTexture::parseUniqueRecordId(id, plugin, index);
LandTexture::parseUniqueRecordId(id.getRefIdString(), plugin, index);
record.mPluginIndex = plugin;
record.mIndex = index;
}
template <>
inline const std::string IdAccessor<Land>::getId(const Land& record) const
inline const ESM::RefId IdAccessor<Land>::getId(const Land& record) const
{
return Land::createUniqueRecordId(record.mX, record.mY);
return ESM::RefId::stringRefId(Land::createUniqueRecordId(record.mX, record.mY));
}
template <>
inline const std::string IdAccessor<LandTexture>::getId(const LandTexture& record) const
inline const ESM::RefId IdAccessor<LandTexture>::getId(const LandTexture& record) const
{
return LandTexture::createUniqueRecordId(record.mPluginIndex, record.mIndex);
return ESM::RefId::stringRefId(LandTexture::createUniqueRecordId(record.mPluginIndex, record.mIndex));
}
/// \brief Single-type record collection
@ -118,9 +118,9 @@ namespace CSMWorld
int getSize() const override;
std::string getId(int index) const override;
ESM::RefId getId(int index) const override;
int getIndex(const std::string& id) const override;
int getIndex(const ESM::RefId& id) const override;
int getColumns() const override;
@ -138,13 +138,13 @@ namespace CSMWorld
void removeRows(int index, int count) override;
void appendBlankRecord(const std::string& id, UniversalId::Type type = UniversalId::Type_None) override;
void appendBlankRecord(const ESM::RefId& id, UniversalId::Type type = UniversalId::Type_None) override;
///< \param type Will be ignored, unless the collection supports multiple record types
void cloneRecord(
const std::string& origin, const std::string& destination, const UniversalId::Type type) override;
const ESM::RefId& origin, const ESM::RefId& destination, const UniversalId::Type type) override;
bool touchRecord(const std::string& id) override;
bool touchRecord(const ESM::RefId& id) override;
///< Change the state of a record from base to modified, if it is not already.
/// \return True if the record was changed.
@ -152,6 +152,10 @@ namespace CSMWorld
////< Search record with \a id.
/// \return index of record (if found) or -1 (not found)
int searchId(const ESM::RefId& id) const override;
////< Search record with \a id.
/// \return index of record (if found) or -1 (not found)
void replace(int index, std::unique_ptr<RecordBase> record) override;
///< If the record type does not match, an exception is thrown.
///
@ -161,14 +165,14 @@ namespace CSMWorld
///< If the record type does not match, an exception is thrown.
///< \param type Will be ignored, unless the collection supports multiple record types
const Record<ESXRecordT>& getRecord(const std::string& id) const override;
const Record<ESXRecordT>& getRecord(const ESM::RefId& id) const override;
const Record<ESXRecordT>& getRecord(int index) const override;
int getAppendIndex(const std::string& id, UniversalId::Type type = UniversalId::Type_None) const override;
int getAppendIndex(const ESM::RefId& id, UniversalId::Type type = UniversalId::Type_None) const override;
///< \param type Will be ignored, unless the collection supports multiple record types
std::vector<std::string> getIds(bool listDeleted = true) const override;
std::vector<ESM::RefId> getIds(bool listDeleted = true) const override;
///< Return a sorted collection of all IDs
///
/// \param listDeleted include deleted record in the list
@ -241,18 +245,18 @@ namespace CSMWorld
const std::string& origin, const std::string& destination, UniversalId::Type type)
{
auto copy = std::make_unique<Record<ESXRecordT>>();
copy->mModified = getRecord(origin).get();
copy->mModified = getRecord(ESM::RefId::stringRefId(origin)).get();
copy->mState = RecordBase::State_ModifiedOnly;
IdAccessorT().setId(copy->get(), destination);
IdAccessorT().setId(copy->get(), ESM::RefId::stringRefId(destination));
if (type == UniversalId::Type_Reference)
{
CSMWorld::CellRef* ptr = (CSMWorld::CellRef*)&copy->mModified;
ptr->mRefNum.mIndex = 0;
}
int index = getAppendIndex(destination, type);
insertRecord(std::move(copy), getAppendIndex(destination, type));
ESM::RefId destinationRefId = ESM::RefId::stringRefId(destination);
int index = getAppendIndex(destinationRefId, type);
insertRecord(std::move(copy), getAppendIndex(destinationRefId, type));
return index;
}
@ -260,7 +264,7 @@ namespace CSMWorld
template <typename ESXRecordT, typename IdAccessorT>
int Collection<ESXRecordT, IdAccessorT>::touchRecordImp(const std::string& id)
{
int index = getIndex(id);
int index = getIndex(ESM::RefId::stringRefId(id));
Record<ESXRecordT>& record = *mRecords.at(index);
if (record.isDeleted())
{
@ -278,29 +282,29 @@ namespace CSMWorld
template <typename ESXRecordT, typename IdAccessorT>
void Collection<ESXRecordT, IdAccessorT>::cloneRecord(
const std::string& origin, const std::string& destination, const UniversalId::Type type)
const ESM::RefId& origin, const ESM::RefId& destination, const UniversalId::Type type)
{
cloneRecordImp(origin, destination, type);
cloneRecordImp(origin.getRefIdString(), destination.getRefIdString(), type);
}
template <>
inline void Collection<Land, IdAccessor<Land>>::cloneRecord(
const std::string& origin, const std::string& destination, const UniversalId::Type type)
const ESM::RefId& origin, const ESM::RefId& destination, const UniversalId::Type type)
{
int index = cloneRecordImp(origin, destination, type);
int index = cloneRecordImp(origin.getRefIdString(), destination.getRefIdString(), type);
mRecords.at(index)->get().setPlugin(0);
}
template <typename ESXRecordT, typename IdAccessorT>
bool Collection<ESXRecordT, IdAccessorT>::touchRecord(const std::string& id)
bool Collection<ESXRecordT, IdAccessorT>::touchRecord(const ESM::RefId& id)
{
return touchRecordImp(id) != -1;
return touchRecordImp(id.getRefIdString()) != -1;
}
template <>
inline bool Collection<Land, IdAccessor<Land>>::touchRecord(const std::string& id)
inline bool Collection<Land, IdAccessor<Land>>::touchRecord(const ESM::RefId& id)
{
int index = touchRecordImp(id);
int index = touchRecordImp(id.getRefIdString());
if (index >= 0)
{
mRecords.at(index)->get().setPlugin(0);
@ -325,9 +329,9 @@ namespace CSMWorld
template <typename ESXRecordT, typename IdAccessorT>
void Collection<ESXRecordT, IdAccessorT>::add(const ESXRecordT& record)
{
std::string id = Misc::StringUtils::lowerCase(IdAccessorT().getId(record));
auto id = IdAccessorT().getId(record);
std::map<std::string, int>::iterator iter = mIndex.find(id);
auto iter = mIndex.find(Misc::StringUtils::lowerCase(id.getRefIdString()));
if (iter == mIndex.end())
{
@ -350,18 +354,18 @@ namespace CSMWorld
}
template <typename ESXRecordT, typename IdAccessorT>
std::string Collection<ESXRecordT, IdAccessorT>::getId(int index) const
ESM::RefId Collection<ESXRecordT, IdAccessorT>::getId(int index) const
{
return IdAccessorT().getId(mRecords.at(index)->get());
}
template <typename ESXRecordT, typename IdAccessorT>
int Collection<ESXRecordT, IdAccessorT>::getIndex(const std::string& id) const
int Collection<ESXRecordT, IdAccessorT>::getIndex(const ESM::RefId& id) const
{
int index = searchId(id);
if (index == -1)
throw std::runtime_error("invalid ID: " + id);
throw std::runtime_error("invalid ID: " + id.getRefIdString());
return index;
}
@ -456,7 +460,7 @@ namespace CSMWorld
}
template <typename ESXRecordT, typename IdAccessorT>
void Collection<ESXRecordT, IdAccessorT>::appendBlankRecord(const std::string& id, UniversalId::Type type)
void Collection<ESXRecordT, IdAccessorT>::appendBlankRecord(const ESM::RefId& id, UniversalId::Type type)
{
ESXRecordT record;
IdAccessorT().setId(record, id);
@ -482,6 +486,19 @@ namespace CSMWorld
return iter->second;
}
template <typename ESXRecordT, typename IdAccessorT>
int Collection<ESXRecordT, IdAccessorT>::searchId(const ESM::RefId& id) const
{
std::map<std::string, int>::const_iterator iter
= mIndex.find(Misc::StringUtils::lowerCase(id.getRefIdString()));
if (iter == mIndex.end())
return -1;
return iter->second;
}
template <typename ESXRecordT, typename IdAccessorT>
void Collection<ESXRecordT, IdAccessorT>::replace(int index, std::unique_ptr<RecordBase> record)
{
@ -497,17 +514,17 @@ namespace CSMWorld
}
template <typename ESXRecordT, typename IdAccessorT>
int Collection<ESXRecordT, IdAccessorT>::getAppendIndex(const std::string& id, UniversalId::Type type) const
int Collection<ESXRecordT, IdAccessorT>::getAppendIndex(const ESM::RefId& id, UniversalId::Type type) const
{
return static_cast<int>(mRecords.size());
}
template <typename ESXRecordT, typename IdAccessorT>
std::vector<std::string> Collection<ESXRecordT, IdAccessorT>::getIds(bool listDeleted) const
std::vector<ESM::RefId> Collection<ESXRecordT, IdAccessorT>::getIds(bool listDeleted) const
{
std::vector<std::string> ids;
std::vector<ESM::RefId> ids;
for (typename std::map<std::string, int>::const_iterator iter = mIndex.begin(); iter != mIndex.end(); ++iter)
for (auto iter = mIndex.begin(); iter != mIndex.end(); ++iter)
{
if (listDeleted || !mRecords[iter->second]->isDeleted())
ids.push_back(IdAccessorT().getId(mRecords[iter->second]->get()));
@ -517,7 +534,7 @@ namespace CSMWorld
}
template <typename ESXRecordT, typename IdAccessorT>
const Record<ESXRecordT>& Collection<ESXRecordT, IdAccessorT>::getRecord(const std::string& id) const
const Record<ESXRecordT>& Collection<ESXRecordT, IdAccessorT>::getRecord(const ESM::RefId& id) const
{
int index = getIndex(id);
return *mRecords.at(index);
@ -538,7 +555,7 @@ namespace CSMWorld
throw std::runtime_error("index out of range");
std::unique_ptr<Record<ESXRecordT>> record2(static_cast<Record<ESXRecordT>*>(record.release()));
std::string lowerId = Misc::StringUtils::lowerCase(IdAccessorT().getId(record2->get()));
std::string id = Misc::StringUtils::lowerCase(IdAccessorT().getId(record2->get()).getRefIdString());
if (index == size)
mRecords.push_back(std::move(record2));
@ -554,14 +571,13 @@ namespace CSMWorld
}
}
mIndex.insert(std::make_pair(lowerId, index));
mIndex.insert(std::make_pair(id, index));
}
template <typename ESXRecordT, typename IdAccessorT>
void Collection<ESXRecordT, IdAccessorT>::setRecord(int index, std::unique_ptr<Record<ESXRecordT>> record)
{
if (Misc::StringUtils::lowerCase(IdAccessorT().getId(mRecords.at(index)->get()))
!= Misc::StringUtils::lowerCase(IdAccessorT().getId(record->get())))
if (IdAccessorT().getId(mRecords.at(index)->get()) != IdAccessorT().getId(record->get()))
throw std::runtime_error("attempt to change the ID of a record");
mRecords.at(index) = std::move(record);

@ -13,7 +13,7 @@ CSMWorld::CollectionBase::~CollectionBase() {}
int CSMWorld::CollectionBase::getInsertIndex(const std::string& id, UniversalId::Type type, RecordBase* record) const
{
return getAppendIndex(id, type);
return getAppendIndex(ESM::RefId::stringRefId(id), type);
}
int CSMWorld::CollectionBase::searchColumnIndex(Columns::ColumnId id) const

@ -11,6 +11,11 @@
class QVariant;
namespace ESM
{
struct RefId;
}
namespace CSMWorld
{
struct ColumnBase;
@ -35,9 +40,9 @@ namespace CSMWorld
virtual int getSize() const = 0;
virtual std::string getId(int index) const = 0;
virtual ESM::RefId getId(int index) const = 0;
virtual int getIndex(const std::string& id) const = 0;
virtual int getIndex(const ESM::RefId& id) const = 0;
virtual int getColumns() const = 0;
@ -57,13 +62,17 @@ namespace CSMWorld
virtual void removeRows(int index, int count) = 0;
virtual void appendBlankRecord(const std::string& id, UniversalId::Type type = UniversalId::Type_None) = 0;
virtual void appendBlankRecord(const ESM::RefId& id, UniversalId::Type type = UniversalId::Type_None) = 0;
///< \param type Will be ignored, unless the collection supports multiple record types
virtual int searchId(std::string_view id) const = 0;
////< Search record with \a id.
/// \return index of record (if found) or -1 (not found)
virtual int searchId(const ESM::RefId& id) const = 0;
////< Search record with \a id.
/// \return index of record (if found) or -1 (not found)
virtual void replace(int index, std::unique_ptr<RecordBase> record) = 0;
///< If the record type does not match, an exception is thrown.
///
@ -74,20 +83,19 @@ namespace CSMWorld
= 0;
///< If the record type does not match, an exception is thrown.
virtual void cloneRecord(
const std::string& origin, const std::string& destination, const UniversalId::Type type)
virtual void cloneRecord(const ESM::RefId& origin, const ESM::RefId& destination, const UniversalId::Type type)
= 0;
virtual bool touchRecord(const std::string& id) = 0;
virtual bool touchRecord(const ESM::RefId& id) = 0;
virtual const RecordBase& getRecord(const std::string& id) const = 0;
virtual const RecordBase& getRecord(const ESM::RefId& id) const = 0;
virtual const RecordBase& getRecord(int index) const = 0;
virtual int getAppendIndex(const std::string& id, UniversalId::Type type = UniversalId::Type_None) const = 0;
virtual int getAppendIndex(const ESM::RefId& id, UniversalId::Type type = UniversalId::Type_None) const = 0;
///< \param type Will be ignored, unless the collection supports multiple record types
virtual std::vector<std::string> getIds(bool listDeleted = true) const = 0;
virtual std::vector<ESM::RefId> getIds(bool listDeleted = true) const = 0;
///< Return a sorted collection of all IDs
///
/// \param listDeleted include deleted record in the list

@ -20,13 +20,13 @@ namespace CSMWorld
QVariant LandTextureNicknameColumn::get(const Record<LandTexture>& record) const
{
return QString::fromUtf8(record.get().mId.c_str());
return QString::fromUtf8(record.get().mId.getRefIdString().c_str());
}
void LandTextureNicknameColumn::set(Record<LandTexture>& record, const QVariant& data)
{
LandTexture copy = record.get();
copy.mId = data.toString().toUtf8().constData();
copy.mId = ESM::RefId::stringRefId(data.toString().toUtf8().constData());
record.setModified(copy);
}
@ -281,7 +281,7 @@ namespace CSMWorld
{
if (mMeshType != nullptr && mMeshType->get(record) == ESM::BodyPart::MT_Skin)
{
return QString::fromUtf8(record.get().mRace.c_str());
return QString::fromUtf8(record.get().mRace.getRefIdString().c_str());
}
return QVariant(QVariant::UserType);
}
@ -290,7 +290,7 @@ namespace CSMWorld
{
ESM::BodyPart record2 = record.get();
record2.mRace = data.toString().toUtf8().constData();
record2.mRace = ESM::RefId::stringRefId(data.toString().toUtf8().constData());
record.setModified(record2);
}

@ -9,6 +9,7 @@
#include <osg/Math>
#include <apps/opencs/model/world/cell.hpp>
#include <components/esm/defs.hpp>
#include <components/esm3/loadbody.hpp>
#include <components/esm3/loadinfo.hpp>
@ -61,7 +62,7 @@ namespace CSMWorld
QVariant get(const Record<ESXRecordT>& record) const override
{
return QString::fromUtf8(record.get().mId.c_str());
return QString::fromUtf8(record.get().mId.getRefIdString().c_str());
}
bool isEditable() const override { return false; }
@ -333,6 +334,31 @@ namespace CSMWorld
bool isEditable() const override { return true; }
};
template <>
struct NameColumn<CSMWorld::Cell> : public Column<CSMWorld::Cell>
{
NameColumn(ColumnBase::Display display = ColumnBase::Display_String)
: Column<CSMWorld::Cell>(Columns::ColumnId_Name, display)
{
}
QVariant get(const Record<CSMWorld::Cell>& record) const override
{
return QString::fromUtf8(record.get().mName.getRefIdString().c_str());
}
void set(Record<CSMWorld::Cell>& record, const QVariant& data) override
{
CSMWorld::Cell record2 = record.get();
record2.mName = ESM::RefId::stringRefId(data.toString().toUtf8().constData());
record.setModified(record2);
}
bool isEditable() const override { return true; }
};
template <typename ESXRecordT>
struct AttributesColumn : public Column<ESXRecordT>
{
@ -690,14 +716,14 @@ namespace CSMWorld
QVariant get(const Record<ESXRecordT>& record) const override
{
return QString::fromUtf8(record.get().mSleepList.c_str());
return QString::fromUtf8(record.get().mSleepList.getRefIdString().c_str());
}
void set(Record<ESXRecordT>& record, const QVariant& data) override
{
ESXRecordT record2 = record.get();
record2.mSleepList = data.toString().toUtf8().constData();
record2.mSleepList = ESM::RefId::stringRefId(data.toString().toUtf8().constData());
record.setModified(record2);
}
@ -816,14 +842,14 @@ namespace CSMWorld
QVariant get(const Record<ESXRecordT>& record) const override
{
return QString::fromUtf8(record.get().mRegion.c_str());
return QString::fromUtf8(record.get().mRegion.getRefIdString().c_str());
}
void set(Record<ESXRecordT>& record, const QVariant& data) override
{
ESXRecordT record2 = record.get();
record2.mRegion = data.toString().toUtf8().constData();
record2.mRegion = ESM::RefId::stringRefId(data.toString().toUtf8().constData());
record.setModified(record2);
}
@ -845,14 +871,14 @@ namespace CSMWorld
QVariant get(const Record<ESXRecordT>& record) const override
{
return QString::fromUtf8(record.get().mCell.c_str());
return QString::fromUtf8(record.get().mCell.getRefIdString().c_str());
}
void set(Record<ESXRecordT>& record, const QVariant& data) override
{
ESXRecordT record2 = record.get();
record2.mCell = data.toString().toUtf8().constData();
record2.mCell = ESM::RefId::stringRefId(data.toString().toUtf8().constData());
record.setModified(record2);
}
@ -872,14 +898,14 @@ namespace CSMWorld
QVariant get(const Record<ESXRecordT>& record) const override
{
return QString::fromUtf8(record.get().mOriginalCell.c_str());
return QString::fromUtf8(record.get().mOriginalCell.getRefIdString().c_str());
}
void set(Record<ESXRecordT>& record, const QVariant& data) override
{
ESXRecordT record2 = record.get();
record2.mOriginalCell = data.toString().toUtf8().constData();
record2.mOriginalCell = ESM::RefId::stringRefId(data.toString().toUtf8().constData());
record.setModified(record2);
}
@ -899,14 +925,14 @@ namespace CSMWorld
QVariant get(const Record<ESXRecordT>& record) const override
{
return QString::fromUtf8(record.get().mRefID.c_str());
return QString::fromUtf8(record.get().mRefID.getRefIdString().c_str());
}
void set(Record<ESXRecordT>& record, const QVariant& data) override
{
ESXRecordT record2 = record.get();
record2.mRefID = data.toString().toUtf8().constData();
record2.mRefID = ESM::RefId::stringRefId(data.toString().toUtf8().constData());
record.setModified(record2);
}
@ -944,14 +970,14 @@ namespace CSMWorld
QVariant get(const Record<ESXRecordT>& record) const override
{
return QString::fromUtf8(record.get().mOwner.c_str());
return QString::fromUtf8(record.get().mOwner.getRefIdString().c_str());
}
void set(Record<ESXRecordT>& record, const QVariant& data) override
{
ESXRecordT record2 = record.get();
record2.mOwner = data.toString().toUtf8().constData();
record2.mOwner = ESM::RefId::stringRefId(data.toString().toUtf8().constData());
record.setModified(record2);
}
@ -969,14 +995,14 @@ namespace CSMWorld
QVariant get(const Record<ESXRecordT>& record) const override
{
return QString::fromUtf8(record.get().mSoul.c_str());
return QString::fromUtf8(record.get().mSoul.getRefIdString().c_str());
}
void set(Record<ESXRecordT>& record, const QVariant& data) override
{
ESXRecordT record2 = record.get();
record2.mSoul = data.toString().toUtf8().constData();
record2.mSoul = ESM::RefId::stringRefId(data.toString().toUtf8().constData());
record.setModified(record2);
}
@ -994,14 +1020,14 @@ namespace CSMWorld
QVariant get(const Record<ESXRecordT>& record) const override
{
return QString::fromUtf8(record.get().mFaction.c_str());
return QString::fromUtf8(record.get().mFaction.getRefIdString().c_str());
}
void set(Record<ESXRecordT>& record, const QVariant& data) override
{
ESXRecordT record2 = record.get();
record2.mFaction = data.toString().toUtf8().constData();
record2.mFaction = ESM::RefId::stringRefId(data.toString().toUtf8().constData());
record.setModified(record2);
}
@ -1121,14 +1147,14 @@ namespace CSMWorld
QVariant get(const Record<ESXRecordT>& record) const override
{
return QString::fromUtf8(record.get().mDestCell.c_str());
return QString::fromUtf8(record.get().mDestCell.getRefIdString().c_str());
}
void set(Record<ESXRecordT>& record, const QVariant& data) override
{
ESXRecordT record2 = record.get();
record2.mDestCell = data.toString().toUtf8().constData();
record2.mDestCell = ESM::RefId::stringRefId(data.toString().toUtf8().constData());
record.setModified(record2);
}
@ -1168,14 +1194,14 @@ namespace CSMWorld
QVariant get(const Record<ESXRecordT>& record) const override
{
return QString::fromUtf8(record.get().mKey.c_str());
return QString::fromUtf8(record.get().mKey.getRefIdString().c_str());
}
void set(Record<ESXRecordT>& record, const QVariant& data) override
{
ESXRecordT record2 = record.get();
record2.mKey = data.toString().toUtf8().constData();
record2.mKey = ESM::RefId::stringRefId(data.toString().toUtf8().constData());
record.setModified(record2);
}
@ -1193,14 +1219,14 @@ namespace CSMWorld
QVariant get(const Record<ESXRecordT>& record) const override
{
return QString::fromUtf8(record.get().mTrap.c_str());
return QString::fromUtf8(record.get().mTrap.getRefIdString().c_str());
}
void set(Record<ESXRecordT>& record, const QVariant& data) override
{
ESXRecordT record2 = record.get();
record2.mTrap = data.toString().toUtf8().constData();
record2.mTrap = ESM::RefId::stringRefId(data.toString().toUtf8().constData());
record.setModified(record2);
}
@ -1407,14 +1433,14 @@ namespace CSMWorld
QVariant get(const Record<ESXRecordT>& record) const override
{
return QString::fromUtf8(record.get().mTopicId.c_str());
return QString::fromUtf8(record.get().mTopicId.getRefIdString().c_str());
}
void set(Record<ESXRecordT>& record, const QVariant& data) override
{
ESXRecordT record2 = record.get();
record2.mTopicId = data.toString().toUtf8().constData();
record2.mTopicId = ESM::RefId::stringRefId(data.toString().toUtf8().constData());
record.setModified(record2);
}
@ -1434,14 +1460,14 @@ namespace CSMWorld
QVariant get(const Record<ESXRecordT>& record) const override
{
return QString::fromUtf8(record.get().mActor.c_str());
return QString::fromUtf8(record.get().mActor.getRefIdString().c_str());
}
void set(Record<ESXRecordT>& record, const QVariant& data) override
{
ESXRecordT record2 = record.get();
record2.mActor = data.toString().toUtf8().constData();
record2.mActor = ESM::RefId::stringRefId(data.toString().toUtf8().constData());
record.setModified(record2);
}
@ -1459,14 +1485,14 @@ namespace CSMWorld
QVariant get(const Record<ESXRecordT>& record) const override
{
return QString::fromUtf8(record.get().mRace.c_str());
return QString::fromUtf8(record.get().mRace.getRefIdString().c_str());
}
void set(Record<ESXRecordT>& record, const QVariant& data) override
{
ESXRecordT record2 = record.get();
record2.mRace = data.toString().toUtf8().constData();
record2.mRace = ESM::RefId::stringRefId(data.toString().toUtf8().constData());
record.setModified(record2);
}
@ -1484,14 +1510,14 @@ namespace CSMWorld
QVariant get(const Record<ESXRecordT>& record) const override
{
return QString::fromUtf8(record.get().mClass.c_str());
return QString::fromUtf8(record.get().mClass.getRefIdString().c_str());
}
void set(Record<ESXRecordT>& record, const QVariant& data) override
{
ESXRecordT record2 = record.get();
record2.mClass = data.toString().toUtf8().constData();
record2.mClass = ESM::RefId::stringRefId(data.toString().toUtf8().constData());
record.setModified(record2);
}
@ -1509,14 +1535,14 @@ namespace CSMWorld
QVariant get(const Record<ESXRecordT>& record) const override
{
return QString::fromUtf8(record.get().mPcFaction.c_str());
return QString::fromUtf8(record.get().mPcFaction.getRefIdString().c_str());
}
void set(Record<ESXRecordT>& record, const QVariant& data) override
{
ESXRecordT record2 = record.get();
record2.mPcFaction = data.toString().toUtf8().constData();
record2.mPcFaction = ESM::RefId::stringRefId(data.toString().toUtf8().constData());
record.setModified(record2);
}
@ -1926,14 +1952,14 @@ namespace CSMWorld
QVariant get(const Record<ESXRecordT>& record) const override
{
return QString::fromUtf8(record.get().mSound.c_str());
return QString::fromUtf8(record.get().mSound.getRefIdString().c_str());
}
void set(Record<ESXRecordT>& record, const QVariant& data) override
{
ESXRecordT record2 = record.get();
record2.mSound = data.toString().toUtf8().constData();
record2.mSound = ESM::RefId::stringRefId(data.toString().toUtf8().constData());
record.setModified(record2);
}
@ -1951,14 +1977,14 @@ namespace CSMWorld
QVariant get(const Record<ESXRecordT>& record) const override
{
return QString::fromUtf8(record.get().mCreature.c_str());
return QString::fromUtf8(record.get().mCreature.getRefIdString().c_str());
}
void set(Record<ESXRecordT>& record, const QVariant& data) override
{
ESXRecordT record2 = record.get();
record2.mCreature = data.toString().toUtf8().constData();
record2.mCreature = ESM::RefId::stringRefId(data.toString().toUtf8().constData());
record.setModified(record2);
}
@ -2072,7 +2098,7 @@ namespace CSMWorld
QVariant get(const Record<ESXRecordT>& record) const override
{
const std::string* string = nullptr;
const ESM::RefId* string = nullptr;
switch (this->mColumnId)
{
@ -2093,35 +2119,35 @@ namespace CSMWorld
if (!string)
throw std::logic_error("Unsupported column ID");
return QString::fromUtf8(string->c_str());
return QString::fromUtf8(string->getRefIdString().c_str());
}
void set(Record<ESXRecordT>& record, const QVariant& data) override
{
std::string* string = nullptr;
ESM::RefId* id = nullptr;
ESXRecordT record2 = record.get();
switch (this->mColumnId)
{
case Columns::ColumnId_CastingObject:
string = &record2.mCasting;
id = &record2.mCasting;
break;
case Columns::ColumnId_HitObject:
string = &record2.mHit;
id = &record2.mHit;
break;
case Columns::ColumnId_AreaObject:
string = &record2.mArea;
id = &record2.mArea;
break;
case Columns::ColumnId_BoltObject:
string = &record2.mBolt;
id = &record2.mBolt;
break;
}
if (!string)
if (!id)
throw std::logic_error("Unsupported column ID");
*string = data.toString().toUtf8().constData();
*id = ESM::RefId::stringRefId(data.toString().toUtf8().constData());
record.setModified(record2);
}
@ -2141,56 +2167,56 @@ namespace CSMWorld
QVariant get(const Record<ESXRecordT>& record) const override
{
const std::string* string = nullptr;
const ESM::RefId* id = nullptr;
switch (this->mColumnId)
{
case Columns::ColumnId_CastingSound:
string = &record.get().mCastSound;
id = &record.get().mCastSound;
break;
case Columns::ColumnId_HitSound:
string = &record.get().mHitSound;
id = &record.get().mHitSound;
break;
case Columns::ColumnId_AreaSound:
string = &record.get().mAreaSound;
id = &record.get().mAreaSound;
break;
case Columns::ColumnId_BoltSound:
string = &record.get().mBoltSound;
id = &record.get().mBoltSound;
break;
}
if (!string)
if (!id)
throw std::logic_error("Unsupported column ID");
return QString::fromUtf8(string->c_str());
return QString::fromUtf8(id->getRefIdString().c_str());
}
void set(Record<ESXRecordT>& record, const QVariant& data) override
{
std::string* string = nullptr;
ESM::RefId* id = nullptr;
ESXRecordT record2 = record.get();
switch (this->mColumnId)
{
case Columns::ColumnId_CastingSound:
string = &record2.mCastSound;
id = &record2.mCastSound;
break;
case Columns::ColumnId_HitSound:
string = &record2.mHitSound;
id = &record2.mHitSound;
break;
case Columns::ColumnId_AreaSound:
string = &record2.mAreaSound;
id = &record2.mAreaSound;
break;
case Columns::ColumnId_BoltSound:
string = &record2.mBoltSound;
id = &record2.mBoltSound;
break;
}
if (!string)
if (!id)
throw std::logic_error("Unsupported column ID");
*string = data.toString().toUtf8().constData();
*id = ESM::RefId::stringRefId(data.toString().toUtf8().constData());
record.setModified(record2);
}

@ -290,11 +290,11 @@ void CSMWorld::CommandDispatcher::executeExtendedDelete()
if (record.mState == RecordBase::State_Deleted)
continue;
if (!std::binary_search(
mSelection.begin(), mSelection.end(), Misc::StringUtils::lowerCase(record.get().mCell)))
if (!std::binary_search(mSelection.begin(), mSelection.end(),
Misc::StringUtils::lowerCase(record.get().mCell.getRefIdString())))
continue;
macro.push(new CSMWorld::DeleteCommand(model, record.get().mId));
macro.push(new CSMWorld::DeleteCommand(model, record.get().mId.getRefIdString()));
}
}
}
@ -321,11 +321,11 @@ void CSMWorld::CommandDispatcher::executeExtendedRevert()
{
const Record<CellRef>& record = collection.getRecord(i);
if (!std::binary_search(
mSelection.begin(), mSelection.end(), Misc::StringUtils::lowerCase(record.get().mCell)))
if (!std::binary_search(mSelection.begin(), mSelection.end(),
Misc::StringUtils::lowerCase(record.get().mCell.getRefIdString())))
continue;
macro.push(new CSMWorld::RevertCommand(model, record.get().mId));
macro.push(new CSMWorld::RevertCommand(model, record.get().mId.getRefIdString()));
}
}
}

@ -411,7 +411,7 @@ CSMWorld::CloneCommand::CloneCommand(CSMWorld::IdTable& model, const std::string
void CSMWorld::CloneCommand::redo()
{
mModel.cloneRecord(mIdOrigin, mId, mType);
mModel.cloneRecord(ESM::RefId::stringRefId(mIdOrigin), ESM::RefId::stringRefId(mId), mType);
applyModifications();
for (auto& value : mOverrideValues)
{
@ -442,7 +442,7 @@ void CSMWorld::CreatePathgridCommand::redo()
std::unique_ptr<Record<Pathgrid>> record
= std::make_unique<Record<Pathgrid>>(static_cast<const Record<Pathgrid>&>(mModel.getRecord(mId)));
record->get().blank();
record->get().mCell = mId;
record->get().mCell = ESM::RefId::stringRefId(mId);
std::pair<CellCoordinates, bool> coords = CellCoordinates::fromId(mId);
if (coords.second)

@ -73,9 +73,9 @@ void CSMWorld::Data::addModel(QAbstractItemModel* model, UniversalId::Type type,
}
}
void CSMWorld::Data::appendIds(std::vector<std::string>& ids, const CollectionBase& collection, bool listDeleted)
void CSMWorld::Data::appendIds(std::vector<ESM::RefId>& ids, const CollectionBase& collection, bool listDeleted)
{
std::vector<std::string> ids2 = collection.getIds(listDeleted);
std::vector<ESM::RefId> ids2 = collection.getIds(listDeleted);
ids.insert(ids.end(), ids2.begin(), ids2.end());
}
@ -578,7 +578,7 @@ CSMWorld::Data::Data(ToUTF8::FromType encoding, bool fsStrict, const Files::Path
mDebugProfiles.addColumn(new DescriptionColumn<ESM::DebugProfile>);
mDebugProfiles.addColumn(new ScriptColumn<ESM::DebugProfile>(ScriptColumn<ESM::DebugProfile>::Type_Lines));
mMetaData.appendBlankRecord("sys::meta");
mMetaData.appendBlankRecord(ESM::RefId::stringRefId("sys::meta"));
mMetaData.addColumn(new StringIdColumn<MetaData>(true));
mMetaData.addColumn(new RecordStateColumn<MetaData>);
@ -1018,7 +1018,7 @@ int CSMWorld::Data::startLoading(const std::filesystem::path& path, bool base, b
if (!mProject && !mBase)
{
MetaData metaData;
metaData.mId = "sys::meta";
metaData.mId = ESM::RefId::stringRefId("sys::meta");
metaData.load(*mReader);
mMetaData.setRecord(0,
@ -1042,7 +1042,7 @@ void CSMWorld::Data::loadFallbackEntries()
if (mReferenceables.searchId(marker.first) == -1)
{
ESM::Static newMarker;
newMarker.mId = marker.first;
newMarker.mId = ESM::RefId::stringRefId(marker.first);
newMarker.mModel = marker.second;
newMarker.mRecordFlags = 0;
auto record = std::make_unique<CSMWorld::Record<ESM::Static>>();
@ -1057,7 +1057,7 @@ void CSMWorld::Data::loadFallbackEntries()
if (mReferenceables.searchId(marker.first) == -1)
{
ESM::Door newMarker;
newMarker.mId = marker.first;
newMarker.mId = ESM::RefId::stringRefId(marker.first);
newMarker.mModel = marker.second;
newMarker.mRecordFlags = 0;
auto record = std::make_unique<CSMWorld::Record<ESM::Door>>();
@ -1172,7 +1172,8 @@ bool CSMWorld::Data::continueLoading(CSMDoc::Messages& messages)
messages.add(id, "Logic error: cell index out of bounds", "", CSMDoc::Message::Severity_Error);
index = mCells.getSize() - 1;
}
std::string cellId = Misc::StringUtils::lowerCase(mCells.getId(index));
const std::string& cellId = mCells.getId(index).getRefIdString();
mRefs.load(*mReader, index, mBase, mRefLoadCache[cellId], messages);
break;
}
@ -1241,6 +1242,7 @@ bool CSMWorld::Data::continueLoading(CSMDoc::Messages& messages)
case ESM::REC_DIAL:
{
ESM::Dialogue record;
const std::string& recordIdString = record.mId.getRefIdString();
bool isDeleted = false;
record.load(*mReader, isDeleted);
@ -1250,18 +1252,18 @@ bool CSMWorld::Data::continueLoading(CSMDoc::Messages& messages)
// record vector can be shuffled around which would make pointer to record invalid
mDialogue = nullptr;
if (mJournals.tryDelete(record.mId))
if (mJournals.tryDelete(recordIdString))
{
mJournalInfos.removeDialogueInfos(record.mId);
mJournalInfos.removeDialogueInfos(recordIdString);
}
else if (mTopics.tryDelete(record.mId))
else if (mTopics.tryDelete(recordIdString))
{
mTopicInfos.removeDialogueInfos(record.mId);
mTopicInfos.removeDialogueInfos(recordIdString);
}
else
{
messages.add(UniversalId::Type_None,
"Trying to delete dialogue record " + record.mId + " which does not exist", "",
"Trying to delete dialogue record " + recordIdString + " which does not exist", "",
CSMDoc::Message::Severity_Warning);
}
}
@ -1360,9 +1362,9 @@ int CSMWorld::Data::count(RecordBase::State state) const
+ count(state, mPathgrids);
}
std::vector<std::string> CSMWorld::Data::getIds(bool listDeleted) const
std::vector<ESM::RefId> CSMWorld::Data::getIds(bool listDeleted) const
{
std::vector<std::string> ids;
std::vector<ESM::RefId> ids;
appendIds(ids, mGlobals, listDeleted);
appendIds(ids, mGmsts, listDeleted);

@ -33,6 +33,7 @@
#include <components/esm3/loadspel.hpp>
#include <components/esm3/loadsscr.hpp>
#include <components/files/multidircollection.hpp>
#include <components/misc/algorithm.hpp>
#include <components/to_utf8/to_utf8.hpp>
#include "cell.hpp"
@ -122,7 +123,7 @@ namespace CSMWorld
const ESM::Dialogue* mDialogue; // last loaded dialogue
bool mBase;
bool mProject;
std::map<std::string, std::map<unsigned int, unsigned int>> mRefLoadCache;
std::map<std::string, std::map<unsigned int, unsigned int>, Misc::StringUtils::CiComp> mRefLoadCache;
int mReaderIndex;
bool mFsStrict;
@ -140,7 +141,7 @@ namespace CSMWorld
void addModel(QAbstractItemModel* model, UniversalId::Type type, bool update = true);
static void appendIds(std::vector<std::string>& ids, const CollectionBase& collection, bool listDeleted);
static void appendIds(std::vector<ESM::RefId>& ids, const CollectionBase& collection, bool listDeleted);
///< Append all IDs from collection to \a ids.
static int count(RecordBase::State state, const CollectionBase& collection);
@ -305,7 +306,7 @@ namespace CSMWorld
bool hasId(const std::string& id) const;
std::vector<std::string> getIds(bool listDeleted = true) const;
std::vector<ESM::RefId> getIds(bool listDeleted = true) const;
///< Return a sorted collection of all IDs that are not internal to the editor.
///
/// \param listDeleted include deleted record in the list

@ -25,7 +25,7 @@ namespace CSMWorld
loadRecord(record, reader, isDeleted);
std::string id = IdAccessor<Pathgrid>().getId(record);
auto id = IdAccessor<Pathgrid>().getId(record);
int index = this->searchId(id);
if (record.mPoints.empty() || record.mEdges.empty())

@ -74,7 +74,7 @@ namespace CSMWorld
loadRecord(record, reader, isDeleted);
std::string id = IdAccessorT().getId(record);
ESM::RefId id = IdAccessorT().getId(record);
int index = this->searchId(id);
if (isDeleted)

@ -181,11 +181,12 @@ QModelIndex CSMWorld::IdTable::parent(const QModelIndex& index) const
void CSMWorld::IdTable::addRecord(const std::string& id, UniversalId::Type type)
{
int index = mIdCollection->getAppendIndex(id, type);
ESM::RefId refId = ESM::RefId::stringRefId(id);
int index = mIdCollection->getAppendIndex(refId, type);
beginInsertRows(QModelIndex(), index, index);
mIdCollection->appendBlankRecord(id, type);
mIdCollection->appendBlankRecord(refId, type);
endInsertRows();
}
@ -193,11 +194,12 @@ void CSMWorld::IdTable::addRecord(const std::string& id, UniversalId::Type type)
void CSMWorld::IdTable::addRecordWithData(
const std::string& id, const std::map<int, QVariant>& data, UniversalId::Type type)
{
int index = mIdCollection->getAppendIndex(id, type);
ESM::RefId refId = ESM::RefId::stringRefId(id);
int index = mIdCollection->getAppendIndex(refId, type);
beginInsertRows(QModelIndex(), index, index);
mIdCollection->appendBlankRecord(id, type);
mIdCollection->appendBlankRecord(refId, type);
for (std::map<int, QVariant>::const_iterator iter(data.begin()); iter != data.end(); ++iter)
{
@ -208,7 +210,7 @@ void CSMWorld::IdTable::addRecordWithData(
}
void CSMWorld::IdTable::cloneRecord(
const std::string& origin, const std::string& destination, CSMWorld::UniversalId::Type type)
const ESM::RefId& origin, const ESM::RefId& destination, CSMWorld::UniversalId::Type type)
{
int index = mIdCollection->getAppendIndex(destination, type);
@ -219,9 +221,10 @@ void CSMWorld::IdTable::cloneRecord(
bool CSMWorld::IdTable::touchRecord(const std::string& id)
{
bool changed = mIdCollection->touchRecord(id);
ESM::RefId refId = ESM::RefId::stringRefId(id);
bool changed = mIdCollection->touchRecord(refId);
int row = mIdCollection->getIndex(id);
int row = mIdCollection->getIndex(refId);
int column = mIdCollection->searchColumnIndex(Columns::ColumnId_RecordType);
if (changed && column != -1)
{
@ -234,7 +237,7 @@ bool CSMWorld::IdTable::touchRecord(const std::string& id)
std::string CSMWorld::IdTable::getId(int row) const
{
return mIdCollection->getId(row);
return mIdCollection->getId(row).getRefIdString();
}
/// This method can return only indexes to the top level table cells
@ -278,7 +281,7 @@ void CSMWorld::IdTable::setRecord(
const CSMWorld::RecordBase& CSMWorld::IdTable::getRecord(const std::string& id) const
{
return mIdCollection->getRecord(id);
return mIdCollection->getRecord(ESM::RefId::stringRefId(id));
}
int CSMWorld::IdTable::searchColumnIndex(Columns::ColumnId id) const
@ -330,7 +333,7 @@ std::pair<CSMWorld::UniversalId, std::string> CSMWorld::IdTable::view(int row) c
return std::make_pair(UniversalId::Type_None, "");
if (id[0] == '#')
id = ESM::CellId::sDefaultWorldspace;
id = ESM::CellId::sDefaultWorldspace.getRefIdString();
return std::make_pair(UniversalId(UniversalId::Type_Scene, id), hint);
}
@ -367,7 +370,8 @@ CSMWorld::LandTextureIdTable::ImportResults CSMWorld::LandTextureIdTable::import
{
auto& record = static_cast<const Record<LandTexture>&>(idCollection()->getRecord(i));
if (record.isModified())
reverseLookupMap.emplace(Misc::StringUtils::lowerCase(record.get().mTexture), idCollection()->getId(i));
reverseLookupMap.emplace(
Misc::StringUtils::lowerCase(record.get().mTexture), idCollection()->getId(i).getRefIdString());
}
for (const std::string& id : ids)
@ -404,7 +408,7 @@ CSMWorld::LandTextureIdTable::ImportResults CSMWorld::LandTextureIdTable::import
if (newRow < 0)
{
// Id not taken, clone it
cloneRecord(id, newId, UniversalId::Type_LandTexture);
cloneRecord(ESM::RefId::stringRefId(id), ESM::RefId::stringRefId(newId), UniversalId::Type_LandTexture);
results.createdRecords.push_back(newId);
results.recordMapping.emplace_back(id, newId);
reverseLookupMap.emplace(texture, newId);

@ -64,7 +64,7 @@ namespace CSMWorld
///< \param type Will be ignored, unless the collection supports multiple record types
void cloneRecord(
const std::string& origin, const std::string& destination, UniversalId::Type type = UniversalId::Type_None);
const ESM::RefId& origin, const ESM::RefId& destination, UniversalId::Type type = UniversalId::Type_None);
bool touchRecord(const std::string& id);
///< Will change the record state to modified, if it is not already.

@ -194,7 +194,7 @@ QModelIndex CSMWorld::IdTree::index(int row, int column, const QModelIndex& pare
QModelIndex CSMWorld::IdTree::getNestedModelIndex(const std::string& id, int column) const
{
return CSMWorld::IdTable::index(idCollection()->getIndex(id), column);
return CSMWorld::IdTable::index(idCollection()->getIndex(ESM::RefId::stringRefId(id)), column);
}
QModelIndex CSMWorld::IdTree::parent(const QModelIndex& index) const

@ -7,7 +7,7 @@ namespace CSMWorld
{
struct Info : public ESM::DialInfo
{
std::string mTopicId;
ESM::RefId mTopicId;
};
}

@ -76,7 +76,7 @@ namespace CSMWorld
void CSMWorld::InfoCollection::load(const Info& record, bool base)
{
int index = searchId(record.mId);
int index = searchId(record.mId.getRefIdString());
if (index == -1)
{
@ -135,7 +135,7 @@ int CSMWorld::InfoCollection::getInsertIndex(const std::string& id, UniversalId:
std::pair<RecordConstIterator, RecordConstIterator> range = getTopicRange(id.substr(0, separator));
if (range.first == range.second)
return Collection<Info, IdAccessor<Info>>::getAppendIndex(id, type);
return Collection<Info, IdAccessor<Info>>::getAppendIndex(ESM::RefId::stringRefId(id), type);
return std::distance(getRecords().begin(), range.second);
}
@ -143,12 +143,12 @@ int CSMWorld::InfoCollection::getInsertIndex(const std::string& id, UniversalId:
int index = -1;
const Info& info = static_cast<Record<Info>*>(record)->get();
std::string topic = info.mTopicId;
const std::string& topic = info.mTopicId.getRefIdString();
// if the record has a prev, find its index value
if (!info.mPrev.empty())
{
index = getInfoIndex(info.mPrev, topic);
index = getInfoIndex(info.mPrev.getRefIdString(), topic);
if (index != -1)
++index; // if prev exists, set current index to one above prev
@ -158,7 +158,7 @@ int CSMWorld::InfoCollection::getInsertIndex(const std::string& id, UniversalId:
if (index == -1 && !info.mNext.empty())
{
// if next exists, use its index as the current index
index = getInfoIndex(info.mNext, topic);
index = getInfoIndex(info.mNext.getRefIdString(), topic);
}
// if next doesn't exist or not found (i.e. neither exist yet) then start a new one
@ -181,7 +181,7 @@ bool CSMWorld::InfoCollection::reorderRows(int baseIndex, const std::vector<int>
return false;
// Check that topics match
if (!Misc::StringUtils::ciEqual(getRecord(baseIndex).get().mTopicId, getRecord(lastIndex).get().mTopicId))
if (!(getRecord(baseIndex).get().mTopicId == getRecord(lastIndex).get().mTopicId))
return false;
// reorder
@ -204,7 +204,7 @@ void CSMWorld::InfoCollection::load(ESM::ESMReader& reader, bool base, const ESM
bool isDeleted = false;
info.load(reader, isDeleted);
std::string id = Misc::StringUtils::lowerCase(dialogue.mId) + "#" + info.mId;
std::string id = dialogue.mId.getRefIdString() + "#" + info.mId.getRefIdString();
if (isDeleted)
{
@ -230,7 +230,7 @@ void CSMWorld::InfoCollection::load(ESM::ESMReader& reader, bool base, const ESM
else
{
info.mTopicId = dialogue.mId;
info.mId = id;
info.mId = ESM::RefId::stringRefId(id);
load(info, base);
}
}
@ -274,7 +274,7 @@ void CSMWorld::InfoCollection::removeDialogueInfos(const std::string& dialogueId
{
const Record<Info>& record = **range.first;
if (Misc::StringUtils::ciEqual(dialogueId, record.get().mTopicId))
if ((ESM::RefId::stringRefId(dialogueId) == record.get().mTopicId))
{
if (record.mState == RecordBase::State_ModifiedOnly)
{
@ -333,7 +333,7 @@ void CSMWorld::InfoCollection::removeRows(int index, int count)
}
}
void CSMWorld::InfoCollection::appendBlankRecord(const std::string& id, UniversalId::Type type)
void CSMWorld::InfoCollection::appendBlankRecord(const ESM::RefId& id, UniversalId::Type type)
{
auto record2 = std::make_unique<Record<Info>>();
@ -342,7 +342,8 @@ void CSMWorld::InfoCollection::appendBlankRecord(const std::string& id, Universa
record2->get().mId = id;
insertRecord(std::move(record2), getInsertIndex(id, type, nullptr), type); // call InfoCollection::insertRecord()
insertRecord(std::move(record2), getInsertIndex(id.getRefIdString(), type, nullptr),
type); // call InfoCollection::insertRecord()
}
int CSMWorld::InfoCollection::searchId(std::string_view id) const
@ -357,7 +358,8 @@ int CSMWorld::InfoCollection::searchId(std::string_view id) const
void CSMWorld::InfoCollection::appendRecord(std::unique_ptr<RecordBase> record, UniversalId::Type type)
{
int index = getInsertIndex(static_cast<Record<Info>*>(record.get())->get().mId, type, record.get());
int index
= getInsertIndex(static_cast<Record<Info>*>(record.get())->get().mId.getRefIdString(), type, record.get());
insertRecord(std::move(record), index, type);
}
@ -366,7 +368,7 @@ void CSMWorld::InfoCollection::insertRecord(std::unique_ptr<RecordBase> record,
{
int size = static_cast<int>(getRecords().size());
std::string id = static_cast<Record<Info>*>(record.get())->get().mId;
std::string id = static_cast<Record<Info>*>(record.get())->get().mId.getRefIdString();
std::string::size_type separator = id.find_last_of('#');
if (separator == std::string::npos)

@ -65,9 +65,9 @@ namespace CSMWorld
/// Works like getAppendIndex unless an overloaded method uses the record pointer
/// to get additional info about the record that results in an alternative index.
int getAppendIndex(const std::string& id, UniversalId::Type type) const override
int getAppendIndex(const ESM::RefId& id, UniversalId::Type type) const override
{
return getInsertIndex(id, type);
return getInsertIndex(id.getRefIdString(), type);
}
bool reorderRows(int baseIndex, const std::vector<int>& newOrder) override;
@ -86,7 +86,7 @@ namespace CSMWorld
void removeRows(int index, int count) override;
void appendBlankRecord(const std::string& id, UniversalId::Type type = UniversalId::Type_None) override;
void appendBlankRecord(const ESM::RefId& id, UniversalId::Type type = UniversalId::Type_None) override;
int searchId(std::string_view id) const override;

@ -1,6 +1,7 @@
#ifndef CSM_WOLRD_METADATA_H
#define CSM_WOLRD_METADATA_H
#include <components/esm/refid.hpp>
#include <string>
namespace ESM
@ -13,7 +14,7 @@ namespace CSMWorld
{
struct MetaData
{
std::string mId;
ESM::RefId mId;
int mFormat;
std::string mAuthor;

@ -252,10 +252,10 @@ namespace CSMWorld
{
ESM::Faction faction = record.get();
std::map<std::string, int>& reactions = faction.mReactions;
std::map<ESM::RefId, int>& reactions = faction.mReactions;
// blank row
reactions.insert(std::make_pair("", 0));
reactions.insert(std::make_pair(ESM::RefId::sEmpty, 0));
record.setModified(faction);
}
@ -264,14 +264,14 @@ namespace CSMWorld
{
ESM::Faction faction = record.get();
std::map<std::string, int>& reactions = faction.mReactions;
std::map<ESM::RefId, int>& reactions = faction.mReactions;
if (rowToRemove < 0 || rowToRemove >= static_cast<int>(reactions.size()))
throw std::runtime_error("index out of range");
// FIXME: how to ensure that the map entries correspond to table indicies?
// WARNING: Assumed that the table view has the same order as std::map
std::map<std::string, int>::iterator iter = reactions.begin();
auto iter = reactions.begin();
for (int i = 0; i < rowToRemove; ++i)
++iter;
reactions.erase(iter);
@ -285,7 +285,7 @@ namespace CSMWorld
ESM::Faction faction = record.get();
faction.mReactions
= static_cast<const NestedTableWrapper<std::map<std::string, int>>&>(nestedTable).mNestedTable;
= static_cast<const NestedTableWrapper<std::map<ESM::RefId, int>>&>(nestedTable).mNestedTable;
record.setModified(faction);
}
@ -293,7 +293,7 @@ namespace CSMWorld
NestedTableWrapperBase* FactionReactionsAdapter::table(const Record<ESM::Faction>& record) const
{
// deleted by dtor of NestedTableStoring
return new NestedTableWrapper<std::map<std::string, int>>(record.get().mReactions);
return new NestedTableWrapper<std::map<ESM::RefId, int>>(record.get().mReactions);
}
QVariant FactionReactionsAdapter::getData(
@ -301,20 +301,20 @@ namespace CSMWorld
{
ESM::Faction faction = record.get();
std::map<std::string, int>& reactions = faction.mReactions;
std::map<ESM::RefId, int>& reactions = faction.mReactions;
if (subRowIndex < 0 || subRowIndex >= static_cast<int>(reactions.size()))
throw std::runtime_error("index out of range");
// FIXME: how to ensure that the map entries correspond to table indicies?
// WARNING: Assumed that the table view has the same order as std::map
std::map<std::string, int>::const_iterator iter = reactions.begin();
auto iter = reactions.begin();
for (int i = 0; i < subRowIndex; ++i)
++iter;
switch (subColIndex)
{
case 0:
return QString((*iter).first.c_str());
return QString((*iter).first.getRefIdString().c_str());
case 1:
return (*iter).second;
default:
@ -327,18 +327,18 @@ namespace CSMWorld
{
ESM::Faction faction = record.get();
std::map<std::string, int>& reactions = faction.mReactions;
std::map<ESM::RefId, int>& reactions = faction.mReactions;
if (subRowIndex < 0 || subRowIndex >= static_cast<int>(reactions.size()))
throw std::runtime_error("index out of range");
// FIXME: how to ensure that the map entries correspond to table indicies?
// WARNING: Assumed that the table view has the same order as std::map
std::map<std::string, int>::iterator iter = reactions.begin();
auto iter = reactions.begin();
for (int i = 0; i < subRowIndex; ++i)
++iter;
std::string factionId = (*iter).first;
ESM::RefId factionId = (*iter).first;
int reaction = (*iter).second;
switch (subColIndex)
@ -346,7 +346,8 @@ namespace CSMWorld
case 0:
{
reactions.erase(iter);
reactions.insert(std::make_pair(value.toString().toUtf8().constData(), reaction));
reactions.insert(
std::make_pair(ESM::RefId::stringRefId(value.toString().toUtf8().constData()), reaction));
break;
}
case 1:
@ -381,7 +382,7 @@ namespace CSMWorld
// blank row
ESM::Region::SoundRef soundRef;
soundRef.mSound.assign("");
soundRef.mSound = ESM::RefId::sEmpty;
soundRef.mChance = 0;
soundList.insert(soundList.begin() + position, soundRef);
@ -432,7 +433,7 @@ namespace CSMWorld
switch (subColIndex)
{
case 0:
return QString(soundRef.mSound.c_str());
return QString(soundRef.mSound.getRefIdString().c_str());
case 1:
return soundRef.mChance;
default:
@ -454,7 +455,7 @@ namespace CSMWorld
switch (subColIndex)
{
case 0:
soundRef.mSound.assign(value.toString().toUtf8().constData());
soundRef.mSound = ESM::RefId::stringRefId(value.toString().toUtf8().constData());
break;
case 1:
soundRef.mChance = static_cast<unsigned char>(value.toInt());

@ -154,10 +154,10 @@ namespace CSMWorld
{
ESXRecordT raceOrBthSgn = record.get();
std::vector<std::string>& spells = raceOrBthSgn.mPowers.mList;
std::vector<ESM::RefId>& spells = raceOrBthSgn.mPowers.mList;
// blank row
std::string spell;
ESM::RefId spell;
spells.insert(spells.begin() + position, spell);
@ -168,7 +168,7 @@ namespace CSMWorld
{
ESXRecordT raceOrBthSgn = record.get();
std::vector<std::string>& spells = raceOrBthSgn.mPowers.mList;
std::vector<ESM::RefId>& spells = raceOrBthSgn.mPowers.mList;
if (rowToRemove < 0 || rowToRemove >= static_cast<int>(spells.size()))
throw std::runtime_error("index out of range");
@ -183,7 +183,7 @@ namespace CSMWorld
ESXRecordT raceOrBthSgn = record.get();
raceOrBthSgn.mPowers.mList
= static_cast<const NestedTableWrapper<std::vector<std::string>>&>(nestedTable).mNestedTable;
= static_cast<const NestedTableWrapper<std::vector<ESM::RefId>>&>(nestedTable).mNestedTable;
record.setModified(raceOrBthSgn);
}
@ -191,23 +191,23 @@ namespace CSMWorld
NestedTableWrapperBase* table(const Record<ESXRecordT>& record) const override
{
// deleted by dtor of NestedTableStoring
return new NestedTableWrapper<std::vector<std::string>>(record.get().mPowers.mList);
return new NestedTableWrapper<std::vector<ESM::RefId>>(record.get().mPowers.mList);
}
QVariant getData(const Record<ESXRecordT>& record, int subRowIndex, int subColIndex) const override
{
ESXRecordT raceOrBthSgn = record.get();
std::vector<std::string>& spells = raceOrBthSgn.mPowers.mList;
std::vector<ESM::RefId>& spells = raceOrBthSgn.mPowers.mList;
if (subRowIndex < 0 || subRowIndex >= static_cast<int>(spells.size()))
throw std::runtime_error("index out of range");
std::string spell = spells[subRowIndex];
ESM::RefId spell = spells[subRowIndex];
switch (subColIndex)
{
case 0:
return QString(spell.c_str());
return QString(spell.getRefIdString().c_str());
default:
throw std::runtime_error("Spells subcolumn index out of range");
}
@ -217,16 +217,16 @@ namespace CSMWorld
{
ESXRecordT raceOrBthSgn = record.get();
std::vector<std::string>& spells = raceOrBthSgn.mPowers.mList;
std::vector<ESM::RefId>& spells = raceOrBthSgn.mPowers.mList;
if (subRowIndex < 0 || subRowIndex >= static_cast<int>(spells.size()))
throw std::runtime_error("index out of range");
std::string spell = spells[subRowIndex];
ESM::RefId spell = spells[subRowIndex];
switch (subColIndex)
{
case 0:
spell = value.toString().toUtf8().constData();
spell = ESM::RefId::stringRefId(value.toString().toUtf8().constData());
break;
default:
throw std::runtime_error("Spells subcolumn index out of range");

@ -9,11 +9,11 @@ void CSMWorld::Pathgrid::load(ESM::ESMReader& esm, bool& isDeleted, const IdColl
load(esm, isDeleted);
// correct ID
if (!mId.empty() && mId[0] != '#' && cells.searchId(mId) == -1)
if (!mId.empty() && mId.getRefIdString()[0] != '#' && cells.searchId(mId) == -1)
{
std::ostringstream stream;
stream << "#" << mData.mX << " " << mData.mY;
mId = stream.str();
mId = ESM::RefId::stringRefId(stream.str());
}
}
@ -26,6 +26,6 @@ void CSMWorld::Pathgrid::load(ESM::ESMReader& esm, bool& isDeleted)
{
std::ostringstream stream;
stream << "#" << mData.mX << " " << mData.mY;
mId = stream.str();
mId = ESM::RefId::stringRefId(stream.str());
}
}

@ -3,6 +3,7 @@
#include <string>
#include <components/esm/refid.hpp>
#include <components/esm3/loadpgrd.hpp>
namespace ESM
@ -25,7 +26,7 @@ namespace CSMWorld
/// Exterior cell coordinates are encoded in the pathgrid ID.
struct Pathgrid : public ESM::Pathgrid
{
std::string mId;
ESM::RefId mId;
void load(ESM::ESMReader& esm, bool& isDeleted, const IdCollection<Cell, IdAccessor<Cell>>& cells);
void load(ESM::ESMReader& esm, bool& isDeleted);

@ -11,9 +11,9 @@ namespace CSMWorld
/// \brief Wrapper for CellRef sub record
struct CellRef : public ESM::CellRef
{
std::string mId;
std::string mCell;
std::string mOriginalCell;
ESM::RefId mId;
ESM::RefId mCell;
ESM::RefId mOriginalCell;
bool mNew; // new reference, not counted yet, ref num not assigned yet
unsigned int mIdNum;

@ -64,14 +64,14 @@ void CSMWorld::RefCollection::load(ESM::ESMReader& reader, int cellIndex, bool b
{
// Keep mOriginalCell empty when in modified (as an indicator that the
// original cell will always be equal the current cell).
ref.mOriginalCell = base ? cell2.mId : "";
ref.mOriginalCell = base ? cell2.mId : ESM::RefId::sEmpty;
if (cell.get().isExterior())
{
// Autocalculate the cell index from coordinates first
std::pair<int, int> index = ref.getCellIndex();
ref.mCell = "#" + std::to_string(index.first) + " " + std::to_string(index.second);
ref.mCell = ESM::RefId::stringRefId("#" + std::to_string(index.first) + " " + std::to_string(index.second));
// Handle non-base moved references
if (!base && isMoved)
@ -86,12 +86,13 @@ void CSMWorld::RefCollection::load(ESM::ESMReader& reader, int cellIndex, bool b
// Log a warning if the record target cell is different
if (index.first != mref.mTarget[0] || index.second != mref.mTarget[1])
{
std::string indexCell = ref.mCell;
ref.mCell = "#" + std::to_string(mref.mTarget[0]) + " " + std::to_string(mref.mTarget[1]);
ESM::RefId indexCell = ref.mCell;
ref.mCell = ESM::RefId::stringRefId(
"#" + std::to_string(mref.mTarget[0]) + " " + std::to_string(mref.mTarget[1]));
CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Cell, mCells.getId(cellIndex));
messages.add(id, "The position of the moved reference " + ref.mRefID + " (cell " + indexCell + ")"
" does not match the target cell (" + ref.mCell + ")",
messages.add(id, "The position of the moved reference " + ref.mRefID.getRefIdString() + " (cell " + indexCell.getRefIdString() + ")"
" does not match the target cell (" + ref.mCell.getRefIdString() + ")",
std::string(), CSMDoc::Message::Severity_Warning);
}
}
@ -118,7 +119,8 @@ void CSMWorld::RefCollection::load(ESM::ESMReader& reader, int cellIndex, bool b
messages.add(id,
"Attempt to move a non-existent reference - RefNum index " + std::to_string(ref.mRefNum.mIndex)
+ ", refID " + ref.mRefID + ", content file index " + std::to_string(ref.mRefNum.mContentFile),
+ ", refID " + ref.mRefID.getRefIdString() + ", content file index "
+ std::to_string(ref.mRefNum.mContentFile),
/*hint*/ "", CSMDoc::Message::Severity_Warning);
continue;
}
@ -127,7 +129,7 @@ void CSMWorld::RefCollection::load(ESM::ESMReader& reader, int cellIndex, bool b
// ensure we have the same record id for setRecord()
ref.mId = getRecord(index).get().mId;
ref.mIdNum = extractIdNum(ref.mId);
ref.mIdNum = extractIdNum(ref.mId.getRefIdString());
auto record = std::make_unique<Record<CellRef>>();
// TODO: check whether a base record be moved
@ -148,7 +150,8 @@ void CSMWorld::RefCollection::load(ESM::ESMReader& reader, int cellIndex, bool b
messages.add(id,
"Attempt to delete a non-existent reference - RefNum index " + std::to_string(ref.mRefNum.mIndex)
+ ", refID " + ref.mRefID + ", content file index " + std::to_string(ref.mRefNum.mContentFile),
+ ", refID " + ref.mRefID.getRefIdString() + ", content file index "
+ std::to_string(ref.mRefNum.mContentFile),
/*hint*/ "", CSMDoc::Message::Severity_Warning);
continue;
}
@ -174,7 +177,7 @@ void CSMWorld::RefCollection::load(ESM::ESMReader& reader, int cellIndex, bool b
{
// new reference
ref.mIdNum = mNextId; // FIXME: fragile
ref.mId = getNewId();
ref.mId = ESM::RefId::stringRefId(getNewId());
cache.emplace(refNum, ref.mIdNum);
@ -207,7 +210,7 @@ void CSMWorld::RefCollection::load(ESM::ESMReader& reader, int cellIndex, bool b
}
#endif
ref.mId = getRecord(index).get().mId;
ref.mIdNum = extractIdNum(ref.mId);
ref.mIdNum = extractIdNum(ref.mId.getRefIdString());
auto record = std::make_unique<Record<CellRef>>(getRecord(index));
record->mState = base ? RecordBase::State_BaseOnly : RecordBase::State_Modified;
@ -282,14 +285,27 @@ void CSMWorld::RefCollection::appendBlankRecord(const std::string& id, Universal
record->mState = Record<CellRef>::State_ModifiedOnly;
record->mModified.blank();
record->get().mId = id;
record->get().mId = ESM::RefId::stringRefId(id);
record->get().mIdNum = extractIdNum(id);
Collection<CellRef, IdAccessor<CellRef>>::appendRecord(std::move(record));
}
void CSMWorld::RefCollection::appendBlankRecord(const ESM::RefId& id, UniversalId::Type type)
{
auto record = std::make_unique<Record<CellRef>>();
record->mState = Record<CellRef>::State_ModifiedOnly;
record->mModified.blank();
record->get().mId = id;
record->get().mIdNum = extractIdNum(id.getRefIdString());
Collection<CellRef, IdAccessor<CellRef>>::appendRecord(std::move(record));
}
void CSMWorld::RefCollection::cloneRecord(
const std::string& origin, const std::string& destination, const UniversalId::Type type)
const ESM::RefId& origin, const ESM::RefId& destination, const UniversalId::Type type)
{
auto copy = std::make_unique<Record<CellRef>>();
@ -297,7 +313,7 @@ void CSMWorld::RefCollection::cloneRecord(
copy->mState = RecordBase::State_ModifiedOnly;
copy->get().mId = destination;
copy->get().mIdNum = extractIdNum(destination);
copy->get().mIdNum = extractIdNum(destination.getRefIdString());
insertRecord(std::move(copy), getAppendIndex(destination, type)); // call RefCollection::insertRecord()
}
@ -307,9 +323,14 @@ int CSMWorld::RefCollection::searchId(std::string_view id) const
return searchId(extractIdNum(id));
}
int CSMWorld::RefCollection::searchId(const ESM::RefId& id) const
{
return searchId(extractIdNum(id.getRefIdString()));
}
void CSMWorld::RefCollection::appendRecord(std::unique_ptr<RecordBase> record, UniversalId::Type type)
{
int index = getAppendIndex(/*id*/ "", type); // for CellRef records id is ignored
int index = getAppendIndex(/*id*/ ESM::RefId::sEmpty, type); // for CellRef records id is ignored
mRefIndex.insert(std::make_pair(static_cast<Record<CellRef>*>(record.get())->get().mIdNum, index));
@ -318,7 +339,7 @@ void CSMWorld::RefCollection::appendRecord(std::unique_ptr<RecordBase> record, U
void CSMWorld::RefCollection::insertRecord(std::unique_ptr<RecordBase> record, int index, UniversalId::Type type)
{
int size = getAppendIndex(/*id*/ "", type); // for CellRef records id is ignored
int size = getAppendIndex(/*id*/ ESM::RefId::sEmpty, type); // for CellRef records id is ignored
unsigned int idNum = static_cast<Record<CellRef>*>(record.get())->get().mIdNum;
Collection<CellRef, IdAccessor<CellRef>>::insertRecord(std::move(record), index, type); // add records only

@ -65,11 +65,12 @@ namespace CSMWorld
virtual void removeRows(int index, int count);
virtual void appendBlankRecord(const std::string& id, UniversalId::Type type = UniversalId::Type_None);
virtual void appendBlankRecord(const ESM::RefId& id, UniversalId::Type type = UniversalId::Type_None);
virtual void cloneRecord(
const std::string& origin, const std::string& destination, const UniversalId::Type type);
virtual void cloneRecord(const ESM::RefId& origin, const ESM::RefId& destination, const UniversalId::Type type);
virtual int searchId(std::string_view id) const;
virtual int searchId(const ESM::RefId& id) const;
virtual void appendRecord(std::unique_ptr<RecordBase> record, UniversalId::Type type = UniversalId::Type_None);

@ -1,7 +1,9 @@
#ifndef CSM_WOLRD_REFIDADAPTER_H
#define CSM_WOLRD_REFIDADAPTER_H
#include <components/esm/refid.hpp>
#include <string>
#include <vector>
/*! \brief
* Adapters acts as indirection layer, abstracting details of the record types (in the wrappers) from the higher levels
@ -38,7 +40,7 @@ namespace CSMWorld
virtual void setData(const RefIdColumn* column, RefIdData& data, int index, const QVariant& value) const = 0;
///< If the data type does not match an exception is thrown.
virtual std::string getId(const RecordBase& record) const = 0;
virtual ESM::RefId getId(const RecordBase& record) const = 0;
virtual void setId(RecordBase& record, const std::string& id) = 0; // used by RefIdCollection::cloneRecord()
};

@ -503,7 +503,7 @@ QVariant CSMWorld::CreatureRefIdAdapter::getData(const RefIdColumn* column, cons
return record.get().mScale;
if (column == mColumns.mOriginal)
return QString::fromUtf8(record.get().mOriginal.c_str());
return QString::fromUtf8(record.get().mOriginal.getRefIdString().c_str());
if (column == mColumns.mAttributes)
return QVariant::fromValue(ColumnBase::TableEdit_FixedRows);
@ -538,7 +538,7 @@ void CSMWorld::CreatureRefIdAdapter::setData(
else if (column == mColumns.mScale)
creature.mScale = value.toFloat();
else if (column == mColumns.mOriginal)
creature.mOriginal = value.toString().toUtf8().constData();
creature.mOriginal = ESM::RefId::stringRefId(value.toString().toUtf8().constData());
else if (column == mColumns.mBloodType)
creature.mBloodType = value.toInt();
else
@ -577,10 +577,10 @@ QVariant CSMWorld::DoorRefIdAdapter::getData(const RefIdColumn* column, const Re
= static_cast<const Record<ESM::Door>&>(data.getRecord(RefIdData::LocalIndex(index, UniversalId::Type_Door)));
if (column == mOpenSound)
return QString::fromUtf8(record.get().mOpenSound.c_str());
return QString::fromUtf8(record.get().mOpenSound.getRefIdString().c_str());
if (column == mCloseSound)
return QString::fromUtf8(record.get().mCloseSound.c_str());
return QString::fromUtf8(record.get().mCloseSound.getRefIdString().c_str());
return NameRefIdAdapter<ESM::Door>::getData(column, data, index);
}
@ -594,9 +594,9 @@ void CSMWorld::DoorRefIdAdapter::setData(
ESM::Door door = record.get();
if (column == mOpenSound)
door.mOpenSound = value.toString().toUtf8().constData();
door.mOpenSound = ESM::RefId::stringRefId(value.toString().toUtf8().constData());
else if (column == mCloseSound)
door.mCloseSound = value.toString().toUtf8().constData();
door.mCloseSound = ESM::RefId::stringRefId(value.toString().toUtf8().constData());
else
{
NameRefIdAdapter<ESM::Door>::setData(column, data, index, value);
@ -638,7 +638,7 @@ QVariant CSMWorld::LightRefIdAdapter::getData(const RefIdColumn* column, const R
return record.get().mData.mColor;
if (column == mColumns.mSound)
return QString::fromUtf8(record.get().mSound.c_str());
return QString::fromUtf8(record.get().mSound.getRefIdString().c_str());
if (column == mColumns.mEmitterType)
{
@ -682,7 +682,7 @@ void CSMWorld::LightRefIdAdapter::setData(
else if (column == mColumns.mColor)
light.mData.mColor = value.toInt();
else if (column == mColumns.mSound)
light.mSound = value.toString().toUtf8().constData();
light.mSound = ESM::RefId::stringRefId(value.toString().toUtf8().constData());
else if (column == mColumns.mEmitterType)
{
int mask = ~(ESM::Light::Flicker | ESM::Light::FlickerSlow | ESM::Light::Pulse | ESM::Light::PulseSlow);
@ -784,19 +784,19 @@ QVariant CSMWorld::NpcRefIdAdapter::getData(const RefIdColumn* column, const Ref
= static_cast<const Record<ESM::NPC>&>(data.getRecord(RefIdData::LocalIndex(index, UniversalId::Type_Npc)));
if (column == mColumns.mRace)
return QString::fromUtf8(record.get().mRace.c_str());
return QString::fromUtf8(record.get().mRace.getRefIdString().c_str());
if (column == mColumns.mClass)
return QString::fromUtf8(record.get().mClass.c_str());
return QString::fromUtf8(record.get().mClass.getRefIdString().c_str());
if (column == mColumns.mFaction)
return QString::fromUtf8(record.get().mFaction.c_str());
return QString::fromUtf8(record.get().mFaction.getRefIdString().c_str());
if (column == mColumns.mHair)
return QString::fromUtf8(record.get().mHair.c_str());
return QString::fromUtf8(record.get().mHair.getRefIdString().c_str());
if (column == mColumns.mHead)
return QString::fromUtf8(record.get().mHead.c_str());
return QString::fromUtf8(record.get().mHead.getRefIdString().c_str());
if (column == mColumns.mAttributes || column == mColumns.mSkills)
{
@ -838,15 +838,15 @@ void CSMWorld::NpcRefIdAdapter::setData(
ESM::NPC npc = record.get();
if (column == mColumns.mRace)
npc.mRace = value.toString().toUtf8().constData();
npc.mRace = ESM::RefId::stringRefId(value.toString().toUtf8().constData());
else if (column == mColumns.mClass)
npc.mClass = value.toString().toUtf8().constData();
npc.mClass = ESM::RefId::stringRefId(value.toString().toUtf8().constData());
else if (column == mColumns.mFaction)
npc.mFaction = value.toString().toUtf8().constData();
npc.mFaction = ESM::RefId::stringRefId(value.toString().toUtf8().constData());
else if (column == mColumns.mHair)
npc.mHair = value.toString().toUtf8().constData();
npc.mHair = ESM::RefId::stringRefId(value.toString().toUtf8().constData());
else if (column == mColumns.mHead)
npc.mHead = value.toString().toUtf8().constData();
npc.mHead = ESM::RefId::stringRefId(value.toString().toUtf8().constData());
else if (column == mColumns.mBloodType)
npc.mBloodType = value.toInt();
else if (column == mColumns.mGender)

@ -68,7 +68,7 @@ namespace CSMWorld
public:
BaseRefIdAdapter(UniversalId::Type type, const BaseColumns& base);
std::string getId(const RecordBase& record) const override;
ESM::RefId getId(const RecordBase& record) const override;
void setId(RecordBase& record, const std::string& id) override;
@ -90,11 +90,11 @@ namespace CSMWorld
template <typename RecordT>
void BaseRefIdAdapter<RecordT>::setId(RecordBase& record, const std::string& id)
{
(dynamic_cast<Record<RecordT>&>(record).get().mId) = id;
(dynamic_cast<Record<RecordT>&>(record).get().mId) = ESM::RefId::stringRefId(id);
}
template <typename RecordT>
std::string BaseRefIdAdapter<RecordT>::getId(const RecordBase& record) const
ESM::RefId BaseRefIdAdapter<RecordT>::getId(const RecordBase& record) const
{
return dynamic_cast<const Record<RecordT>&>(record).get().mId;
}
@ -106,7 +106,7 @@ namespace CSMWorld
= static_cast<const Record<RecordT>&>(data.getRecord(RefIdData::LocalIndex(index, mType)));
if (column == mBase.mId)
return QString::fromUtf8(record.get().mId.c_str());
return QString::fromUtf8(record.get().mId.getRefIdString().c_str());
if (column == mBase.mModified)
{
@ -282,7 +282,7 @@ namespace CSMWorld
return QString::fromUtf8(record.get().mName.c_str());
if (column == mName.mScript)
return QString::fromUtf8(record.get().mScript.c_str());
return QString::fromUtf8(record.get().mScript.getRefIdString().c_str());
return ModelRefIdAdapter<RecordT>::getData(column, data, index);
}
@ -298,7 +298,7 @@ namespace CSMWorld
if (column == mName.mName)
record2.mName = value.toString().toUtf8().constData();
else if (column == mName.mScript)
record2.mScript = value.toString().toUtf8().constData();
record2.mScript = ESM::RefId::stringRefId(value.toString().toUtf8().constData());
else
{
ModelRefIdAdapter<RecordT>::setData(column, data, index, value);
@ -503,7 +503,7 @@ namespace CSMWorld
data.getRecord(RefIdData::LocalIndex(index, BaseRefIdAdapter<RecordT>::getType())));
if (column == mEnchantable.mEnchantment)
return QString::fromUtf8(record.get().mEnchant.c_str());
return QString::fromUtf8(record.get().mEnchant.getRefIdString().c_str());
if (column == mEnchantable.mEnchantmentPoints)
return static_cast<int>(record.get().mData.mEnchant);
@ -520,7 +520,7 @@ namespace CSMWorld
RecordT record2 = record.get();
if (column == mEnchantable.mEnchantment)
record2.mEnchant = value.toString().toUtf8().constData();
record2.mEnchant = ESM::RefId::stringRefId(value.toString().toUtf8().constData());
else if (column == mEnchantable.mEnchantmentPoints)
record2.mData.mEnchant = value.toInt();
else
@ -1265,7 +1265,7 @@ namespace CSMWorld
switch (subColIndex)
{
case 0:
return QString::fromUtf8(content.mItem.c_str());
return QString::fromUtf8(content.mItem.getRefIdString().c_str());
case 1:
return content.mCount;
default:
@ -1287,7 +1287,7 @@ namespace CSMWorld
switch (subColIndex)
{
case 0:
list.at(subRowIndex).mItem.assign(std::string(value.toString().toUtf8().constData()));
list.at(subRowIndex).mItem = ESM::RefId::stringRefId(value.toString().toUtf8().constData());
break;
case 1:
@ -1335,9 +1335,9 @@ namespace CSMWorld
= static_cast<Record<ESXRecordT>&>(data.getRecord(RefIdData::LocalIndex(index, mType)));
ESXRecordT caster = record.get();
std::vector<std::string>& list = caster.mSpells.mList;
std::vector<ESM::RefId>& list = caster.mSpells.mList;
std::string newString;
ESM::RefId newString;
if (position >= (int)list.size())
list.push_back(newString);
@ -1353,7 +1353,7 @@ namespace CSMWorld
= static_cast<Record<ESXRecordT>&>(data.getRecord(RefIdData::LocalIndex(index, mType)));
ESXRecordT caster = record.get();
std::vector<std::string>& list = caster.mSpells.mList;
std::vector<ESM::RefId>& list = caster.mSpells.mList;
if (rowToRemove < 0 || rowToRemove >= static_cast<int>(list.size()))
throw std::runtime_error("index out of range");
@ -1371,7 +1371,7 @@ namespace CSMWorld
ESXRecordT caster = record.get();
caster.mSpells.mList
= static_cast<const NestedTableWrapper<std::vector<typename std::string>>&>(nestedTable).mNestedTable;
= static_cast<const NestedTableWrapper<std::vector<typename ESM::RefId>>&>(nestedTable).mNestedTable;
record.setModified(caster);
}
@ -1382,7 +1382,7 @@ namespace CSMWorld
= static_cast<const Record<ESXRecordT>&>(data.getRecord(RefIdData::LocalIndex(index, mType)));
// deleted by dtor of NestedTableStoring
return new NestedTableWrapper<std::vector<typename std::string>>(record.get().mSpells.mList);
return new NestedTableWrapper<std::vector<typename ESM::RefId>>(record.get().mSpells.mList);
}
QVariant getNestedData(const RefIdColumn* column, const RefIdData& data, int index, int subRowIndex,
@ -1391,15 +1391,15 @@ namespace CSMWorld
const Record<ESXRecordT>& record
= static_cast<const Record<ESXRecordT>&>(data.getRecord(RefIdData::LocalIndex(index, mType)));
const std::vector<std::string>& list = record.get().mSpells.mList;
const std::vector<ESM::RefId>& list = record.get().mSpells.mList;
if (subRowIndex < 0 || subRowIndex >= static_cast<int>(list.size()))
throw std::runtime_error("index out of range");
const std::string& content = list.at(subRowIndex);
const ESM::RefId& content = list.at(subRowIndex);
if (subColIndex == 0)
return QString::fromUtf8(content.c_str());
return QString::fromUtf8(content.getRefIdString().c_str());
else
throw std::runtime_error("Trying to access non-existing column in the nested table!");
}
@ -1410,13 +1410,13 @@ namespace CSMWorld
Record<ESXRecordT>& record
= static_cast<Record<ESXRecordT>&>(data.getRecord(RefIdData::LocalIndex(row, mType)));
ESXRecordT caster = record.get();
std::vector<std::string>& list = caster.mSpells.mList;
std::vector<ESM::RefId>& list = caster.mSpells.mList;
if (subRowIndex < 0 || subRowIndex >= static_cast<int>(list.size()))
throw std::runtime_error("index out of range");
if (subColIndex == 0)
list.at(subRowIndex) = std::string(value.toString().toUtf8());
list.at(subRowIndex) = ESM::RefId::stringRefId(value.toString().toUtf8().constData());
else
throw std::runtime_error("Trying to access non-existing column in the nested table!");
@ -1468,7 +1468,7 @@ namespace CSMWorld
ESM::Transport::Dest newRow;
newRow.mPos = newPos;
newRow.mCellName.clear();
newRow.mCellName = ESM::RefId::sEmpty;
if (position >= (int)list.size())
list.push_back(newRow);
@ -1533,7 +1533,7 @@ namespace CSMWorld
switch (subColIndex)
{
case 0:
return QString::fromUtf8(content.mCellName.c_str());
return QString::fromUtf8(content.mCellName.getRefIdString().c_str());
case 1:
return content.mPos.pos[0];
case 2:
@ -1565,7 +1565,7 @@ namespace CSMWorld
switch (subColIndex)
{
case 0:
list.at(subRowIndex).mCellName = std::string(value.toString().toUtf8().constData());
list.at(subRowIndex).mCellName = ESM::RefId::stringRefId(value.toString().toUtf8().constData());
break;
case 1:
list.at(subRowIndex).mPos.pos[0] = value.toFloat();
@ -1986,8 +1986,8 @@ namespace CSMWorld
ESM::PartReference newPart;
newPart.mPart = 0; // 0 == head
newPart.mMale.clear();
newPart.mFemale.clear();
newPart.mMale = ESM::RefId::sEmpty;
newPart.mFemale = ESM::RefId::sEmpty;
if (position >= (int)list.size())
list.push_back(newPart);
@ -2059,9 +2059,9 @@ namespace CSMWorld
throw std::runtime_error("Part Reference Type unexpected value");
}
case 1:
return QString(content.mMale.c_str());
return QString(content.mMale.getRefIdString().c_str());
case 2:
return QString(content.mFemale.c_str());
return QString(content.mFemale.getRefIdString().c_str());
default:
throw std::runtime_error("Trying to access non-existing column in the nested table!");
}
@ -2084,10 +2084,10 @@ namespace CSMWorld
list.at(subRowIndex).mPart = static_cast<unsigned char>(value.toInt());
break;
case 1:
list.at(subRowIndex).mMale = value.toString().toStdString();
list.at(subRowIndex).mMale = ESM::RefId::stringRefId(value.toString().toStdString());
break;
case 2:
list.at(subRowIndex).mFemale = value.toString().toStdString();
list.at(subRowIndex).mFemale = ESM::RefId::stringRefId(value.toString().toStdString());
break;
default:
throw std::runtime_error("Trying to access non-existing column in the nested table!");
@ -2343,7 +2343,7 @@ namespace CSMWorld
std::vector<ESM::LevelledListBase::LevelItem>& list = leveled.mList;
ESM::LevelledListBase::LevelItem newItem;
newItem.mId.clear();
newItem.mId = ESM::RefId::sEmpty;
newItem.mLevel = 0;
if (position >= (int)list.size())
@ -2410,7 +2410,7 @@ namespace CSMWorld
switch (subColIndex)
{
case 0:
return QString(content.mId.c_str());
return QString(content.mId.getRefIdString().c_str());
case 1:
return content.mLevel;
default:
@ -2432,7 +2432,7 @@ namespace CSMWorld
switch (subColIndex)
{
case 0:
list.at(subRowIndex).mId = value.toString().toStdString();
list.at(subRowIndex).mId = ESM::RefId::stringRefId(value.toString().toStdString());
break;
case 1:
list.at(subRowIndex).mLevel = static_cast<short>(value.toInt());

@ -648,17 +648,17 @@ int CSMWorld::RefIdCollection::getSize() const
return mData.getSize();
}
std::string CSMWorld::RefIdCollection::getId(int index) const
ESM::RefId CSMWorld::RefIdCollection::getId(int index) const
{
return getData(index, 0).toString().toUtf8().constData();
return ESM::RefId::stringRefId(getData(index, 0).toString().toUtf8().constData());
}
int CSMWorld::RefIdCollection::getIndex(const std::string& id) const
int CSMWorld::RefIdCollection::getIndex(const ESM::RefId& id) const
{
int index = searchId(id);
if (index == -1)
throw std::runtime_error("invalid ID: " + id);
throw std::runtime_error("invalid ID: " + id.getRefIdString());
return index;
}
@ -720,14 +720,14 @@ void CSMWorld::RefIdCollection::removeNestedRows(int row, int column, int subRow
nestedAdapter.removeNestedRow(&mColumns.at(column), mData, localIndex.first, subRow);
}
void CSMWorld::RefIdCollection::appendBlankRecord(const std::string& id, UniversalId::Type type)
void CSMWorld::RefIdCollection::appendBlankRecord(const ESM::RefId& id, UniversalId::Type type)
{
mData.appendRecord(type, id, false);
}
int CSMWorld::RefIdCollection::searchId(std::string_view id) const
{
RefIdData::LocalIndex localIndex = mData.searchId(id);
RefIdData::LocalIndex localIndex = mData.searchId(ESM::RefId::stringRefId(id));
if (localIndex.first == -1)
return -1;
@ -735,20 +735,25 @@ int CSMWorld::RefIdCollection::searchId(std::string_view id) const
return mData.localToGlobalIndex(localIndex);
}
int CSMWorld::RefIdCollection::searchId(const ESM::RefId& id) const
{
return searchId(id.getRefIdString());
}
void CSMWorld::RefIdCollection::replace(int index, std::unique_ptr<RecordBase> record)
{
mData.getRecord(mData.globalToLocalIndex(index)).assign(*record.release());
}
void CSMWorld::RefIdCollection::cloneRecord(
const std::string& origin, const std::string& destination, const CSMWorld::UniversalId::Type type)
const ESM::RefId& origin, const ESM::RefId& destination, const CSMWorld::UniversalId::Type type)
{
std::unique_ptr<RecordBase> newRecord = mData.getRecord(mData.searchId(origin)).modifiedCopy();
mAdapters.find(type)->second->setId(*newRecord, destination);
mAdapters.find(type)->second->setId(*newRecord, destination.getRefIdString());
mData.insertRecord(std::move(newRecord), type, destination);
}
bool CSMWorld::RefIdCollection::touchRecord(const std::string& id)
bool CSMWorld::RefIdCollection::touchRecord(const ESM::RefId& id)
{
throw std::runtime_error("RefIdCollection::touchRecord is unimplemented");
return false;
@ -756,7 +761,7 @@ bool CSMWorld::RefIdCollection::touchRecord(const std::string& id)
void CSMWorld::RefIdCollection::appendRecord(std::unique_ptr<RecordBase> record, UniversalId::Type type)
{
std::string id = findAdapter(type).getId(*record.get());
auto id = findAdapter(type).getId(*record.get());
int index = mData.getAppendIndex(type);
@ -765,7 +770,7 @@ void CSMWorld::RefIdCollection::appendRecord(std::unique_ptr<RecordBase> record,
mData.getRecord(mData.globalToLocalIndex(index)).assign(*record.release());
}
const CSMWorld::RecordBase& CSMWorld::RefIdCollection::getRecord(const std::string& id) const
const CSMWorld::RecordBase& CSMWorld::RefIdCollection::getRecord(const ESM::RefId& id) const
{
return mData.getRecord(mData.searchId(id));
}
@ -780,12 +785,12 @@ void CSMWorld::RefIdCollection::load(ESM::ESMReader& reader, bool base, Universa
mData.load(reader, base, type);
}
int CSMWorld::RefIdCollection::getAppendIndex(const std::string& id, UniversalId::Type type) const
int CSMWorld::RefIdCollection::getAppendIndex(const ESM::RefId& id, UniversalId::Type type) const
{
return mData.getAppendIndex(type);
}
std::vector<std::string> CSMWorld::RefIdCollection::getIds(bool listDeleted) const
std::vector<ESM::RefId> CSMWorld::RefIdCollection::getIds(bool listDeleted) const
{
return mData.getIds(listDeleted);
}

@ -67,9 +67,9 @@ namespace CSMWorld
int getSize() const override;
std::string getId(int index) const override;
ESM::RefId getId(int index) const override;
int getIndex(const std::string& id) const override;
int getIndex(const ESM::RefId& id) const override;
int getColumns() const override;
@ -82,17 +82,21 @@ namespace CSMWorld
void removeRows(int index, int count) override;
void cloneRecord(
const std::string& origin, const std::string& destination, const UniversalId::Type type) override;
const ESM::RefId& origin, const ESM::RefId& destination, const UniversalId::Type type) override;
bool touchRecord(const std::string& id) override;
bool touchRecord(const ESM::RefId& id) override;
void appendBlankRecord(const std::string& id, UniversalId::Type type) override;
void appendBlankRecord(const ESM::RefId& id, UniversalId::Type type) override;
///< \param type Will be ignored, unless the collection supports multiple record types
int searchId(std::string_view id) const override;
////< Search record with \a id.
/// \return index of record (if found) or -1 (not found)
int searchId(const ESM::RefId& id) const override;
////< Search record with \a id.
/// \return index of record (if found) or -1 (not found)
void replace(int index, std::unique_ptr<RecordBase> record) override;
///< If the record type does not match, an exception is thrown.
///
@ -103,16 +107,16 @@ namespace CSMWorld
///
///< \param type Will be ignored, unless the collection supports multiple record types
const RecordBase& getRecord(const std::string& id) const override;
const RecordBase& getRecord(const ESM::RefId& id) const override;
const RecordBase& getRecord(int index) const override;
void load(ESM::ESMReader& reader, bool base, UniversalId::Type type);
int getAppendIndex(const std::string& id, UniversalId::Type type) const override;
int getAppendIndex(const ESM::RefId& id, UniversalId::Type type) const override;
///< \param type Will be ignored, unless the collection supports multiple record types
std::vector<std::string> getIds(bool listDeleted) const override;
std::vector<ESM::RefId> getIds(bool listDeleted) const override;
///< Return a sorted collection of all IDs
///
/// \param listDeleted include deleted record in the list

@ -16,7 +16,7 @@ namespace ESM
CSMWorld::RefIdDataContainerBase::~RefIdDataContainerBase() {}
std::string CSMWorld::RefIdData::getRecordId(const CSMWorld::RefIdData::LocalIndex& index) const
ESM::RefId CSMWorld::RefIdData::getRecordId(const CSMWorld::RefIdData::LocalIndex& index) const
{
std::map<UniversalId::Type, RefIdDataContainerBase*>::const_iterator found = mRecordContainers.find(index.second);
@ -80,11 +80,9 @@ int CSMWorld::RefIdData::localToGlobalIndex(const LocalIndex& index) const
return globalIndex;
}
CSMWorld::RefIdData::LocalIndex CSMWorld::RefIdData::searchId(std::string_view id) const
CSMWorld::RefIdData::LocalIndex CSMWorld::RefIdData::searchId(const ESM::RefId& id) const
{
std::string id2 = Misc::StringUtils::lowerCase(id);
std::map<std::string, std::pair<int, UniversalId::Type>>::const_iterator iter = mIndex.find(id2);
auto iter = mIndex.find(id);
if (iter == mIndex.end())
return std::make_pair(-1, CSMWorld::UniversalId::Type_None);
@ -92,7 +90,7 @@ CSMWorld::RefIdData::LocalIndex CSMWorld::RefIdData::searchId(std::string_view i
return iter->second;
}
unsigned int CSMWorld::RefIdData::getRecordFlags(const std::string& id) const
unsigned int CSMWorld::RefIdData::getRecordFlags(const ESM::RefId& id) const
{
LocalIndex localIndex = searchId(id);
@ -197,7 +195,7 @@ CSMWorld::RecordBase& CSMWorld::RefIdData::getRecord(const LocalIndex& index)
return iter->second->getRecord(index.first);
}
void CSMWorld::RefIdData::appendRecord(UniversalId::Type type, const std::string& id, bool base)
void CSMWorld::RefIdData::appendRecord(UniversalId::Type type, const ESM::RefId& id, bool base)
{
std::map<UniversalId::Type, RefIdDataContainerBase*>::iterator iter = mRecordContainers.find(type);
@ -206,7 +204,7 @@ void CSMWorld::RefIdData::appendRecord(UniversalId::Type type, const std::string
iter->second->appendRecord(id, base);
mIndex.insert(std::make_pair(Misc::StringUtils::lowerCase(id), LocalIndex(iter->second->getSize() - 1, type)));
mIndex.insert(std::make_pair(id, LocalIndex(iter->second->getSize() - 1, type)));
}
int CSMWorld::RefIdData::getAppendIndex(UniversalId::Type type) const
@ -242,7 +240,7 @@ void CSMWorld::RefIdData::load(ESM::ESMReader& reader, bool base, CSMWorld::Univ
}
else
{
mIndex[Misc::StringUtils::lowerCase(getRecordId(localIndex))] = localIndex;
mIndex[getRecordId(localIndex)] = localIndex;
}
}
}
@ -255,8 +253,7 @@ void CSMWorld::RefIdData::erase(const LocalIndex& index, int count)
for (int i = index.first; i < index.first + count; ++i)
{
std::map<std::string, LocalIndex>::iterator result
= mIndex.find(Misc::StringUtils::lowerCase(iter->second->getId(i)));
auto result = mIndex.find(iter->second->getId(i));
if (result != mIndex.end())
mIndex.erase(result);
@ -267,8 +264,7 @@ void CSMWorld::RefIdData::erase(const LocalIndex& index, int count)
int recordCount = iter->second->getSize();
while (recordIndex < recordCount)
{
std::map<std::string, LocalIndex>::iterator recordIndexFound
= mIndex.find(Misc::StringUtils::lowerCase(iter->second->getId(recordIndex)));
auto recordIndexFound = mIndex.find(iter->second->getId(recordIndex));
if (recordIndexFound != mIndex.end())
{
recordIndexFound->second.first -= count;
@ -284,11 +280,11 @@ int CSMWorld::RefIdData::getSize() const
return mIndex.size();
}
std::vector<std::string> CSMWorld::RefIdData::getIds(bool listDeleted) const
std::vector<ESM::RefId> CSMWorld::RefIdData::getIds(bool listDeleted) const
{
std::vector<std::string> ids;
std::vector<ESM::RefId> ids;
for (std::map<std::string, LocalIndex>::const_iterator iter(mIndex.begin()); iter != mIndex.end(); ++iter)
for (auto iter(mIndex.begin()); iter != mIndex.end(); ++iter)
{
if (listDeleted || !getRecord(iter->second).isDeleted())
{
@ -419,7 +415,7 @@ const CSMWorld::RefIdDataContainer<ESM::Static>& CSMWorld::RefIdData::getStatics
}
void CSMWorld::RefIdData::insertRecord(
std::unique_ptr<CSMWorld::RecordBase> record, CSMWorld::UniversalId::Type type, const std::string& id)
std::unique_ptr<CSMWorld::RecordBase> record, CSMWorld::UniversalId::Type type, const ESM::RefId& id)
{
std::map<UniversalId::Type, RefIdDataContainerBase*>::iterator iter = mRecordContainers.find(type);
@ -428,7 +424,7 @@ void CSMWorld::RefIdData::insertRecord(
iter->second->insertRecord(std::move(record));
mIndex.insert(std::make_pair(Misc::StringUtils::lowerCase(id), LocalIndex(iter->second->getSize() - 1, type)));
mIndex.insert(std::make_pair(id, LocalIndex(iter->second->getSize() - 1, type)));
}
void CSMWorld::RefIdData::copyTo(int index, RefIdData& target) const

@ -56,7 +56,7 @@ namespace CSMWorld
virtual unsigned int getRecordFlags(int index) const = 0;
virtual void appendRecord(const std::string& id, bool base) = 0;
virtual void appendRecord(const ESM::RefId& id, bool base) = 0;
virtual void insertRecord(std::unique_ptr<RecordBase> record) = 0;
@ -65,7 +65,7 @@ namespace CSMWorld
virtual void erase(int index, int count) = 0;
virtual std::string getId(int index) const = 0;
virtual ESM::RefId getId(int index) const = 0;
virtual void save(int index, ESM::ESMWriter& writer) const = 0;
};
@ -83,7 +83,7 @@ namespace CSMWorld
unsigned int getRecordFlags(int index) const override;
void appendRecord(const std::string& id, bool base) override;
void appendRecord(const ESM::RefId& id, bool base) override;
void insertRecord(std::unique_ptr<RecordBase> record) override;
@ -92,7 +92,7 @@ namespace CSMWorld
void erase(int index, int count) override;
std::string getId(int index) const override;
ESM::RefId getId(int index) const override;
void save(int index, ESM::ESMWriter& writer) const override;
};
@ -132,7 +132,7 @@ namespace CSMWorld
}
template <typename RecordT>
void RefIdDataContainer<RecordT>::appendRecord(const std::string& id, bool base)
void RefIdDataContainer<RecordT>::appendRecord(const ESM::RefId& id, bool base)
{
auto record = std::make_unique<Record<RecordT>>();
@ -157,7 +157,7 @@ namespace CSMWorld
int numRecords = static_cast<int>(mContainer.size());
for (; index < numRecords; ++index)
{
if (Misc::StringUtils::ciEqual(mContainer[index]->get().mId, record.mId))
if ((mContainer[index]->get().mId == record.mId))
{
break;
}
@ -216,7 +216,7 @@ namespace CSMWorld
}
template <typename RecordT>
std::string RefIdDataContainer<RecordT>::getId(int index) const
ESM::RefId RefIdDataContainer<RecordT>::getId(int index) const
{
return mContainer.at(index)->get().mId;
}
@ -262,14 +262,14 @@ namespace CSMWorld
RefIdDataContainer<ESM::Static> mStatics;
RefIdDataContainer<ESM::Weapon> mWeapons;
std::map<std::string, LocalIndex> mIndex;
std::map<ESM::RefId, LocalIndex> mIndex;
std::map<UniversalId::Type, RefIdDataContainerBase*> mRecordContainers;
void erase(const LocalIndex& index, int count);
///< Must not spill over into another type.
std::string getRecordId(const LocalIndex& index) const;
ESM::RefId getRecordId(const LocalIndex& index) const;
public:
RefIdData();
@ -278,19 +278,19 @@ namespace CSMWorld
int localToGlobalIndex(const LocalIndex& index) const;
LocalIndex searchId(std::string_view id) const;
LocalIndex searchId(const ESM::RefId& id) const;
void erase(int index, int count);
void insertRecord(std::unique_ptr<RecordBase> record, CSMWorld::UniversalId::Type type, const std::string& id);
void insertRecord(std::unique_ptr<RecordBase> record, CSMWorld::UniversalId::Type type, const ESM::RefId& id);
const RecordBase& getRecord(const LocalIndex& index) const;
RecordBase& getRecord(const LocalIndex& index);
unsigned int getRecordFlags(const std::string& id) const;
unsigned int getRecordFlags(const ESM::RefId& id) const;
void appendRecord(UniversalId::Type type, const std::string& id, bool base);
void appendRecord(UniversalId::Type type, const ESM::RefId& id, bool base);
int getAppendIndex(UniversalId::Type type) const;
@ -298,7 +298,7 @@ namespace CSMWorld
int getSize() const;
std::vector<std::string> getIds(bool listDeleted = true) const;
std::vector<ESM::RefId> getIds(bool listDeleted = true) const;
///< Return a sorted collection of all IDs
///
/// \param listDeleted include deleted record in the list

@ -53,7 +53,7 @@ QModelIndex CSMWorld::RegionMap::getIndex(const CellCoordinates& index) const
CSMWorld::CellCoordinates CSMWorld::RegionMap::getIndex(const Cell& cell) const
{
std::istringstream stream(cell.mId);
std::istringstream stream(cell.mId.getRefIdString());
char ignore;
int x = 0;
@ -74,7 +74,7 @@ void CSMWorld::RegionMap::buildRegions()
const Record<ESM::Region>& region = regions.getRecord(i);
if (!region.isDeleted())
mColours.insert(std::make_pair(Misc::StringUtils::lowerCase(region.get().mId), region.get().mMapColor));
mColours.insert(std::make_pair(region.get().mId, region.get().mMapColor));
}
}
@ -163,34 +163,29 @@ void CSMWorld::RegionMap::removeCell(const CellCoordinates& index)
}
}
void CSMWorld::RegionMap::addRegion(const std::string& region, unsigned int colour)
void CSMWorld::RegionMap::addRegion(const ESM::RefId& region, unsigned int colour)
{
mColours[Misc::StringUtils::lowerCase(region)] = colour;
mColours[region] = colour;
}
void CSMWorld::RegionMap::removeRegion(const std::string& region)
void CSMWorld::RegionMap::removeRegion(const ESM::RefId& region)
{
std::map<std::string, unsigned int>::iterator iter(mColours.find(Misc::StringUtils::lowerCase(region)));
auto iter(mColours.find(region));
if (iter != mColours.end())
mColours.erase(iter);
}
void CSMWorld::RegionMap::updateRegions(const std::vector<std::string>& regions)
void CSMWorld::RegionMap::updateRegions(const std::vector<ESM::RefId>& regions)
{
std::vector<std::string> regions2(regions);
std::vector<ESM::RefId> regions2(regions);
for (auto& region2 : regions2)
{
Misc::StringUtils::lowerCaseInPlace(region2);
}
std::sort(regions2.begin(), regions2.end());
for (std::map<CellCoordinates, CellDescription>::const_iterator iter(mMap.begin()); iter != mMap.end(); ++iter)
{
if (!iter->second.mRegion.empty()
&& std::find(regions2.begin(), regions2.end(), Misc::StringUtils::lowerCase(iter->second.mRegion))
!= regions2.end())
&& std::find(regions2.begin(), regions2.end(), iter->second.mRegion) != regions2.end())
{
QModelIndex index = getIndex(iter->first);
@ -337,8 +332,7 @@ QVariant CSMWorld::RegionMap::data(const QModelIndex& index, int role) const
if (cell->second.mDeleted)
return QBrush(Qt::red, Qt::DiagCrossPattern);
std::map<std::string, unsigned int>::const_iterator iter
= mColours.find(Misc::StringUtils::lowerCase(cell->second.mRegion));
auto iter = mColours.find(cell->second.mRegion);
if (iter != mColours.end())
return QBrush(QColor(iter->second & 0xff, (iter->second >> 8) & 0xff, (iter->second >> 16) & 0xff));
@ -374,8 +368,7 @@ QVariant CSMWorld::RegionMap::data(const QModelIndex& index, int role) const
{
stream << "<br>";
std::map<std::string, unsigned int>::const_iterator iter
= mColours.find(Misc::StringUtils::lowerCase(cell->second.mRegion));
auto iter = mColours.find(cell->second.mRegion);
if (iter != mColours.end())
stream << cell->second.mRegion;
@ -396,7 +389,7 @@ QVariant CSMWorld::RegionMap::data(const QModelIndex& index, int role) const
std::map<CellCoordinates, CellDescription>::const_iterator cell = mMap.find(cellIndex);
if (cell != mMap.end() && !cell->second.mRegion.empty())
return QString::fromUtf8(Misc::StringUtils::lowerCase(cell->second.mRegion).c_str());
return QString::fromUtf8(cell->second.mRegion.getRefIdString().c_str());
}
if (role == Role_CellId)
@ -419,7 +412,7 @@ Qt::ItemFlags CSMWorld::RegionMap::flags(const QModelIndex& index) const
void CSMWorld::RegionMap::regionsAboutToBeRemoved(const QModelIndex& parent, int start, int end)
{
std::vector<std::string> update;
std::vector<ESM::RefId> update;
const IdCollection<ESM::Region>& regions = mData.getRegions();
@ -437,7 +430,7 @@ void CSMWorld::RegionMap::regionsAboutToBeRemoved(const QModelIndex& parent, int
void CSMWorld::RegionMap::regionsInserted(const QModelIndex& parent, int start, int end)
{
std::vector<std::string> update;
std::vector<ESM::RefId> update;
const IdCollection<ESM::Region>& regions = mData.getRegions();
@ -461,7 +454,7 @@ void CSMWorld::RegionMap::regionsChanged(const QModelIndex& topLeft, const QMode
// Note: At this point an additional check could be inserted to see if there is any change to the
// columns we are interested in. If not we can exit the function here and avoid all updating.
std::vector<std::string> update;
std::vector<ESM::RefId> update;
const IdCollection<ESM::Region>& regions = mData.getRegions();

@ -11,6 +11,7 @@
#include <QVariant>
#include "cellcoordinates.hpp"
#include <components/esm/refid.hpp>
class QObject;
@ -40,8 +41,8 @@ namespace CSMWorld
struct CellDescription
{
bool mDeleted;
std::string mRegion;
std::string mName;
ESM::RefId mRegion;
ESM::RefId mName;
CellDescription();
@ -52,7 +53,7 @@ namespace CSMWorld
std::map<CellCoordinates, CellDescription> mMap;
CellCoordinates mMin; ///< inclusive
CellCoordinates mMax; ///< exclusive
std::map<std::string, unsigned int> mColours; ///< region ID, colour (RGBA)
std::map<ESM::RefId, unsigned int> mColours; ///< region ID, colour (RGBA)
CellCoordinates getIndex(const QModelIndex& index) const;
///< Translates a Qt model index into a cell index (which can contain negative components)
@ -74,18 +75,18 @@ namespace CSMWorld
void removeCell(const CellCoordinates& index);
///< May be called on a cell that is not in the map (in which case the call is ignored)
void addRegion(const std::string& region, unsigned int colour);
void addRegion(const ESM::RefId& region, unsigned int colour);
///< May be called on a region that is already listed (in which case an update is
/// performed)
///
/// \note This function does not update the region map.
void removeRegion(const std::string& region);
void removeRegion(const ESM::RefId& region);
///< May be called on a region that is not listed (in which case the call is ignored)
///
/// \note This function does not update the region map.
void updateRegions(const std::vector<std::string>& regions);
void updateRegions(const std::vector<ESM::RefId>& regions);
///< Update cells affected by the listed regions
void updateSize();

@ -53,9 +53,9 @@ char CSMWorld::ScriptContext::getGlobalType(const std::string& name) const
return ' ';
}
std::pair<char, bool> CSMWorld::ScriptContext::getMemberType(const std::string& name, const std::string& id) const
std::pair<char, bool> CSMWorld::ScriptContext::getMemberType(const std::string& name, const ESM::RefId& id) const
{
std::string id2 = Misc::StringUtils::lowerCase(id);
ESM::RefId id2 = id;
int index = mData.getScripts().searchId(id2);
bool reference = false;
@ -70,7 +70,7 @@ std::pair<char, bool> CSMWorld::ScriptContext::getMemberType(const std::string&
// Referenceable found.
int columnIndex = mData.getReferenceables().findColumnIndex(Columns::ColumnId_Script);
id2 = Misc::StringUtils::lowerCase(
id2 = ESM::RefId::stringRefId(
mData.getReferenceables().getData(index, columnIndex).toString().toUtf8().constData());
if (!id2.empty())
@ -85,7 +85,7 @@ std::pair<char, bool> CSMWorld::ScriptContext::getMemberType(const std::string&
if (index == -1)
return std::make_pair(' ', false);
std::map<std::string, Compiler::Locals>::iterator iter = mLocals.find(id2);
std::map<std::string, Compiler::Locals>::iterator iter = mLocals.find(id2.getRefIdString());
if (iter == mLocals.end())
{
@ -97,28 +97,24 @@ std::pair<char, bool> CSMWorld::ScriptContext::getMemberType(const std::string&
Compiler::Scanner scanner(errorHandler, stream, getExtensions());
scanner.scan(parser);
iter = mLocals.insert(std::make_pair(id2, locals)).first;
iter = mLocals.insert(std::make_pair(id2.getRefIdString(), locals)).first;
}
return std::make_pair(iter->second.getType(Misc::StringUtils::lowerCase(name)), reference);
}
bool CSMWorld::ScriptContext::isId(const std::string& name) const
bool CSMWorld::ScriptContext::isId(const ESM::RefId& name) const
{
if (!mIdsUpdated)
{
mIds = mData.getIds();
for (auto& id : mIds)
{
Misc::StringUtils::lowerCaseInPlace(id);
}
std::sort(mIds.begin(), mIds.end());
mIdsUpdated = true;
}
return std::binary_search(mIds.begin(), mIds.end(), Misc::StringUtils::lowerCase(name));
return std::binary_search(mIds.begin(), mIds.end(), name);
}
void CSMWorld::ScriptContext::invalidateIds()
@ -135,7 +131,7 @@ void CSMWorld::ScriptContext::clear()
bool CSMWorld::ScriptContext::clearLocals(const std::string& script)
{
std::map<std::string, Compiler::Locals>::iterator iter = mLocals.find(Misc::StringUtils::lowerCase(script));
std::map<std::string, Compiler::Locals>::iterator iter = mLocals.find(script);
if (iter != mLocals.end())
{

@ -8,6 +8,7 @@
#include <components/compiler/context.hpp>
#include <components/compiler/locals.hpp>
#include <components/misc/algorithm.hpp>
namespace CSMWorld
{
@ -16,9 +17,9 @@ namespace CSMWorld
class ScriptContext : public Compiler::Context
{
const Data& mData;
mutable std::vector<std::string> mIds;
mutable std::vector<ESM::RefId> mIds;
mutable bool mIdsUpdated;
mutable std::map<std::string, Compiler::Locals> mLocals;
mutable std::map<std::string, Compiler::Locals, Misc::StringUtils::CiComp> mLocals;
public:
ScriptContext(const Data& data);
@ -29,13 +30,13 @@ namespace CSMWorld
char getGlobalType(const std::string& name) const override;
///< 'l: long, 's': short, 'f': float, ' ': does not exist.
std::pair<char, bool> getMemberType(const std::string& name, const std::string& id) const override;
std::pair<char, bool> getMemberType(const std::string& name, const ESM::RefId& id) const override;
///< Return type of member variable \a name in script \a id or in script of reference of
/// \a id
/// \return first: 'l: long, 's': short, 'f': float, ' ': does not exist.
/// second: true: script of reference
bool isId(const std::string& name) const override;
bool isId(const ESM::RefId& name) const override;
///< Does \a name match an ID, that can be referenced?
void invalidateIds();

@ -275,6 +275,11 @@ CSMWorld::UniversalId::UniversalId(Type type, const std::string& id)
throw std::logic_error("invalid ID argument UniversalId type");
}
CSMWorld::UniversalId::UniversalId(Type type, const ESM::RefId& id)
{
UniversalId(type, id.getRefIdString());
}
CSMWorld::UniversalId::UniversalId(Type type, int index)
: mArgumentType(ArgumentType_Index)
, mType(type)

@ -5,6 +5,7 @@
#include <vector>
#include <QMetaType>
#include <components/esm/refid.hpp>
namespace CSMWorld
{
@ -158,6 +159,8 @@ namespace CSMWorld
UniversalId(Type type, const std::string& id);
///< Using a type for a non-ID-argument UniversalId will throw an exception.
UniversalId(Type type, const ESM::RefId& id);
UniversalId(Type type, int index);
///< Using a type for a non-index-argument UniversalId will throw an exception.

@ -26,7 +26,7 @@ namespace CSVRender
{
const std::string Actor::MeshPrefix = "meshes\\";
Actor::Actor(const std::string& id, CSMWorld::Data& data)
Actor::Actor(const ESM::RefId& id, CSMWorld::Data& data)
: mId(id)
, mData(data)
, mBaseNode(new osg::Group())
@ -73,7 +73,7 @@ namespace CSVRender
mSkeleton->setActive(SceneUtil::Skeleton::Active);
}
void Actor::handleActorChanged(const std::string& refId)
void Actor::handleActorChanged(const ESM::RefId& refId)
{
if (mId == refId)
{

@ -35,7 +35,7 @@ namespace CSVRender
/// \param id The referenceable id
/// \param type The record type
/// \param data The data store
Actor(const std::string& id, CSMWorld::Data& data);
Actor(const ESM::RefId& id, CSMWorld::Data& data);
/// Retrieves the base node that meshes are attached to
osg::Group* getBaseNode();
@ -44,7 +44,7 @@ namespace CSVRender
void update();
private slots:
void handleActorChanged(const std::string& refId);
void handleActorChanged(const ESM::RefId& refId);
private:
void loadSkeleton(const std::string& model);
@ -55,7 +55,7 @@ namespace CSVRender
static const std::string MeshPrefix;
std::string mId;
ESM::RefId mId;
CSMWorld::Data& mData;
CSMWorld::ActorAdapter::ActorDataPtr mActorData;

@ -95,13 +95,13 @@ bool CSVRender::Cell::addObjects(int start, int end)
for (int i = start; i <= end; ++i)
{
std::string cell = Misc::StringUtils::lowerCase(collection.getRecord(i).get().mCell);
const auto& cellId = collection.getRecord(i).get().mCell;
CSMWorld::RecordBase::State state = collection.getRecord(i).mState;
if (cell == mId && state != CSMWorld::RecordBase::State_Deleted)
if (cellId == mId && state != CSMWorld::RecordBase::State_Deleted)
{
std::string id = Misc::StringUtils::lowerCase(collection.getRecord(i).get().mId);
const std::string& id = collection.getRecord(i).get().mId.getRefIdString();
auto object = std::make_unique<Object>(mData, mCellNode, id, false);
@ -176,7 +176,7 @@ void CSVRender::Cell::unloadLand()
CSVRender::Cell::Cell(CSMWorld::Data& data, osg::Group* rootNode, const std::string& id, bool deleted)
: mData(data)
, mId(Misc::StringUtils::lowerCase(id))
, mId(ESM::RefId::stringRefId(id))
, mDeleted(deleted)
, mSubMode(0)
, mSubModeElementMask(0)
@ -208,8 +208,8 @@ CSVRender::Cell::Cell(CSMWorld::Data& data, osg::Group* rootNode, const std::str
updateLand();
mPathgrid = std::make_unique<Pathgrid>(mData, mCellNode, mId, mCoordinates);
mCellWater = std::make_unique<CellWater>(mData, mCellNode, mId, mCoordinates);
mPathgrid = std::make_unique<Pathgrid>(mData, mCellNode, mId.getRefIdString(), mCoordinates);
mCellWater = std::make_unique<CellWater>(mData, mCellNode, mId.getRefIdString(), mCoordinates);
}
}
@ -268,8 +268,8 @@ bool CSVRender::Cell::referenceDataChanged(const QModelIndex& topLeft, const QMo
for (int i = topLeft.row(); i <= bottomRight.row(); ++i)
{
std::string cell = Misc::StringUtils::lowerCase(
references.data(references.index(i, cellColumn)).toString().toUtf8().constData());
auto cell
= ESM::RefId::stringRefId(references.data(references.index(i, cellColumn)).toString().toUtf8().constData());
if (cell == mId)
{

@ -11,6 +11,8 @@
#include "../../model/world/cellcoordinates.hpp"
#include "instancedragmodes.hpp"
#include <components/esm/refid.hpp>
#include <components/misc/algorithm.hpp>
class QModelIndex;
@ -44,9 +46,9 @@ namespace CSVRender
class Cell
{
CSMWorld::Data& mData;
std::string mId;
ESM::RefId mId;
osg::ref_ptr<osg::Group> mCellNode;
std::map<std::string, Object*> mObjects;
std::map<std::string, Object*, Misc::StringUtils::CiComp> mObjects;
std::unique_ptr<Terrain::TerrainGrid> mTerrain;
CSMWorld::CellCoordinates mCoordinates;
std::unique_ptr<CellArrow> mCellArrows[4];

@ -131,7 +131,7 @@ namespace CSVRender
{
const CSMWorld::Record<CSMWorld::Cell>& cellRecord = cells.getRecord(row);
if (Misc::StringUtils::lowerCase(cellRecord.get().mId) == mId)
if (cellRecord.get().mId == ESM::RefId::stringRefId(mId))
updateCellData(cellRecord);
}
}

@ -155,7 +155,7 @@ void CSVRender::Object::update()
}
else
{
throw std::runtime_error(mReferenceableId + " has no model");
throw std::runtime_error(mReferenceableId.getRefIdString() + " has no model");
}
}
catch (std::exception& e)
@ -460,14 +460,14 @@ CSVRender::Object::Object(
parentNode->addChild(mRootNode);
mRootNode->setNodeMask(Mask_Reference);
ESM::RefId refId = ESM::RefId::stringRefId(id);
if (referenceable)
{
mReferenceableId = id;
mReferenceableId = refId;
}
else
{
mReferenceId = id;
mReferenceId = refId;
mReferenceableId = getReference().mRefID;
}
@ -607,7 +607,8 @@ bool CSVRender::Object::referenceDataChanged(const QModelIndex& topLeft, const Q
if (columnIndex >= topLeft.column() && columnIndex <= bottomRight.row())
{
mReferenceableId = references.getData(index, columnIndex).toString().toUtf8().constData();
mReferenceableId
= ESM::RefId::stringRefId(references.getData(index, columnIndex).toString().toUtf8().constData());
update();
updateMarker();
@ -627,12 +628,12 @@ void CSVRender::Object::reloadAssets()
std::string CSVRender::Object::getReferenceId() const
{
return mReferenceId;
return mReferenceId.getRefIdString();
}
std::string CSVRender::Object::getReferenceableId() const
{
return mReferenceableId;
return mReferenceableId.getRefIdString();
}
osg::ref_ptr<CSVRender::TagBase> CSVRender::Object::getTag() const
@ -734,7 +735,7 @@ void CSVRender::Object::apply(CSMWorld::CommandMacro& commands)
// Do cell check first so positions can be compared
const CSMWorld::CellRef& ref = collection.getRecord(recordIndex).get();
if (CSMWorld::CellCoordinates::isExteriorCell(ref.mCell))
if (CSMWorld::CellCoordinates::isExteriorCell(ref.mCell.getRefIdString()))
{
// Find cell index at new position
std::pair<int, int> cellIndex

@ -8,6 +8,7 @@
#include <osg/ref_ptr>
#include <components/esm/defs.hpp>
#include <components/esm/refid.hpp>
#include "tagbase.hpp"
@ -81,8 +82,8 @@ namespace CSVRender
static const float MarkerHeadLength;
CSMWorld::Data& mData;
std::string mReferenceId;
std::string mReferenceableId;
ESM::RefId mReferenceId;
ESM::RefId mReferenceableId;
osg::ref_ptr<osg::PositionAttitudeTransform> mRootNode;
osg::ref_ptr<osg::PositionAttitudeTransform> mBaseNode;
osg::ref_ptr<osgFX::Scribe> mOutline;

@ -380,9 +380,9 @@ void CSVRender::PagedWorldspaceWidget::landDataChanged(const QModelIndex& topLef
{
for (int r = topLeft.row(); r <= bottomRight.row(); ++r)
{
std::string id = mDocument.getData().getLand().getId(r);
const auto& id = mDocument.getData().getLand().getId(r);
auto cellIt = mCells.find(CSMWorld::CellCoordinates::fromId(id).first);
auto cellIt = mCells.find(CSMWorld::CellCoordinates::fromId(id.getRefIdString()).first);
if (cellIt != mCells.end())
{
cellIt->second->landDataChanged(topLeft, bottomRight);
@ -395,9 +395,9 @@ void CSVRender::PagedWorldspaceWidget::landAboutToBeRemoved(const QModelIndex& p
{
for (int r = start; r <= end; ++r)
{
std::string id = mDocument.getData().getLand().getId(r);
const auto& id = mDocument.getData().getLand().getId(r);
auto cellIt = mCells.find(CSMWorld::CellCoordinates::fromId(id).first);
auto cellIt = mCells.find(CSMWorld::CellCoordinates::fromId(id.getRefIdString()).first);
if (cellIt != mCells.end())
{
cellIt->second->landAboutToBeRemoved(parent, start, end);
@ -410,9 +410,9 @@ void CSVRender::PagedWorldspaceWidget::landAdded(const QModelIndex& parent, int
{
for (int r = start; r <= end; ++r)
{
std::string id = mDocument.getData().getLand().getId(r);
const auto& id = mDocument.getData().getLand().getId(r);
auto cellIt = mCells.find(CSMWorld::CellCoordinates::fromId(id).first);
auto cellIt = mCells.find(CSMWorld::CellCoordinates::fromId(id.getRefIdString()).first);
if (cellIt != mCells.end())
{
cellIt->second->landAdded(parent, start, end);

@ -85,7 +85,7 @@ namespace CSVRender
const CSMWorld::CellCoordinates& coordinates)
: mData(data)
, mPathgridCollection(mData.getPathgrids())
, mId(pathgridId)
, mId(ESM::RefId::stringRefId(pathgridId))
, mCoords(coordinates)
, mInterior(false)
, mDragOrigin(0)
@ -131,7 +131,7 @@ namespace CSVRender
const std::string& Pathgrid::getId() const
{
return mId;
return mId.getRefIdString();
}
bool Pathgrid::isSelected() const
@ -259,7 +259,7 @@ namespace CSVRender
{
CSMWorld::IdTree* model
= &dynamic_cast<CSMWorld::IdTree&>(*mData.getTableModel(CSMWorld::UniversalId::Type_Pathgrids));
const std::string& idString = mId.getRefIdString();
const CSMWorld::Pathgrid* source = getPathgridSource();
if (source)
{
@ -285,7 +285,7 @@ namespace CSVRender
int row = static_cast<int>(source->mPoints.size());
// Add node to end of list
commands.push(new CSMWorld::AddNestedCommand(*model, mId, row, parentColumn));
commands.push(new CSMWorld::AddNestedCommand(*model, idString, row, parentColumn));
commands.push(new CSMWorld::ModifyCommand(*model, model->index(row, posXColumn, parent), posX));
commands.push(new CSMWorld::ModifyCommand(*model, model->index(row, posYColumn, parent), posY));
commands.push(new CSMWorld::ModifyCommand(*model, model->index(row, posZColumn, parent), posZ));
@ -296,25 +296,25 @@ namespace CSVRender
if (index == -1)
{
// Does not exist
commands.push(new CSMWorld::CreatePathgridCommand(*model, mId));
commands.push(new CSMWorld::CreatePathgridCommand(*model, idString));
}
else
{
source = &mPathgridCollection.getRecord(index).get();
// Deleted, so revert and remove all data
commands.push(new CSMWorld::RevertCommand(*model, mId));
commands.push(new CSMWorld::RevertCommand(*model, idString));
int parentColumn = mPathgridCollection.findColumnIndex(CSMWorld::Columns::ColumnId_PathgridPoints);
for (int row = source->mPoints.size() - 1; row >= 0; --row)
{
commands.push(new CSMWorld::DeleteNestedCommand(*model, mId, row, parentColumn));
commands.push(new CSMWorld::DeleteNestedCommand(*model, idString, row, parentColumn));
}
parentColumn = mPathgridCollection.findColumnIndex(CSMWorld::Columns::ColumnId_PathgridEdges);
for (int row = source->mEdges.size() - 1; row >= 0; --row)
{
commands.push(new CSMWorld::DeleteNestedCommand(*model, mId, row, parentColumn));
commands.push(new CSMWorld::DeleteNestedCommand(*model, idString, row, parentColumn));
}
}
}
@ -401,7 +401,8 @@ namespace CSVRender
for (std::vector<unsigned short>::iterator row = mSelected.begin(); row != mSelected.end(); ++row)
{
commands.push(new CSMWorld::DeleteNestedCommand(*model, mId, static_cast<int>(*row), parentColumn));
commands.push(new CSMWorld::DeleteNestedCommand(
*model, mId.getRefIdString(), static_cast<int>(*row), parentColumn));
}
// Fix/remove edges
@ -459,7 +460,7 @@ namespace CSVRender
std::set<int, std::greater<int>>::iterator row;
for (row = edgeRowsToRemove.begin(); row != edgeRowsToRemove.end(); ++row)
{
commands.push(new CSMWorld::DeleteNestedCommand(*model, mId, *row, parentColumn));
commands.push(new CSMWorld::DeleteNestedCommand(*model, mId.getRefIdString(), *row, parentColumn));
}
}
@ -498,7 +499,7 @@ namespace CSVRender
std::set<int, std::greater<int>>::iterator row;
for (row = rowsToRemove.begin(); row != rowsToRemove.end(); ++row)
{
commands.push(new CSMWorld::DeleteNestedCommand(*model, mId, *row, parentColumn));
commands.push(new CSMWorld::DeleteNestedCommand(*model, mId.getRefIdString(), *row, parentColumn));
}
}
}
@ -682,7 +683,7 @@ namespace CSVRender
if (edgeExists(source, node1, node2) == -1)
{
commands.push(new CSMWorld::AddNestedCommand(*model, mId, row, parentColumn));
commands.push(new CSMWorld::AddNestedCommand(*model, mId.getRefIdString(), row, parentColumn));
commands.push(new CSMWorld::ModifyCommand(*model, model->index(row, edge0Column, parent), node1));
commands.push(new CSMWorld::ModifyCommand(*model, model->index(row, edge1Column, parent), node2));
++row;
@ -690,7 +691,7 @@ namespace CSVRender
if (edgeExists(source, node2, node1) == -1)
{
commands.push(new CSMWorld::AddNestedCommand(*model, mId, row, parentColumn));
commands.push(new CSMWorld::AddNestedCommand(*model, mId.getRefIdString(), row, parentColumn));
commands.push(new CSMWorld::ModifyCommand(*model, model->index(row, edge0Column, parent), node2));
commands.push(new CSMWorld::ModifyCommand(*model, model->index(row, edge1Column, parent), node1));
}

@ -11,8 +11,8 @@
#include "../../model/world/cellcoordinates.hpp"
#include "../../model/world/subcellcollection.hpp"
#include "tagbase.hpp"
#include <components/esm/refid.hpp>
namespace osg
{
@ -92,7 +92,7 @@ namespace CSVRender
private:
CSMWorld::Data& mData;
CSMWorld::SubCellCollection<CSMWorld::Pathgrid>& mPathgridCollection;
std::string mId;
ESM::RefId mId;
CSMWorld::CellCoordinates mCoords;
bool mInterior;

@ -310,7 +310,7 @@ bool CSVRender::TerrainSelection::noLandLoaded(const std::string& cellId)
{
CSMDoc::Document& document = mWorldspaceWidget->getDocument();
const CSMWorld::IdCollection<CSMWorld::Land>& landCollection = document.getData().getLand();
return !landCollection.getRecord(cellId).get().isDataLoaded(ESM::Land::DATA_VNML);
return !landCollection.getRecord(ESM::RefId::stringRefId(cellId)).get().isDataLoaded(ESM::Land::DATA_VNML);
}
bool CSVRender::TerrainSelection::isLandLoaded(const std::string& cellId)
@ -338,8 +338,11 @@ int CSVRender::TerrainSelection::calculateLandHeight(int x, int y) // global ver
{
CSMDoc::Document& document = mWorldspaceWidget->getDocument();
std::string cellId = CSMWorld::CellCoordinates::generateId(cellX, cellY);
const ESM::Land::LandData* landData
= document.getData().getLand().getRecord(cellId).get().getLandData(ESM::Land::DATA_VHGT);
const ESM::Land::LandData* landData = document.getData()
.getLand()
.getRecord(ESM::RefId::stringRefId(cellId))
.get()
.getLandData(ESM::Land::DATA_VHGT);
return landData->mHeights[localY * ESM::Land::LAND_SIZE + localX];
}

@ -1340,7 +1340,7 @@ bool CSVRender::TerrainShapeMode::noLandLoaded(const std::string& cellId)
{
CSMDoc::Document& document = getWorldspaceWidget().getDocument();
const CSMWorld::IdCollection<CSMWorld::Land>& landCollection = document.getData().getLand();
return !landCollection.getRecord(cellId).get().isDataLoaded(ESM::Land::DATA_VNML);
return !landCollection.getRecord(ESM::RefId::stringRefId(cellId)).get().isDataLoaded(ESM::Land::DATA_VNML);
}
bool CSVRender::TerrainShapeMode::isLandLoaded(const std::string& cellId)

@ -286,7 +286,7 @@ void CSVRender::UnpagedWorldspaceWidget::pathgridDataChanged(const QModelIndex&
for (int row = rowStart; row <= rowEnd; ++row)
{
const CSMWorld::Pathgrid& pathgrid = pathgrids.getRecord(row).get();
if (mCellId == pathgrid.mId)
if (ESM::RefId::stringRefId(mCellId) == pathgrid.mId)
{
mCell->pathgridModified();
flagAsModified();
@ -305,7 +305,7 @@ void CSVRender::UnpagedWorldspaceWidget::pathgridAboutToBeRemoved(const QModelIn
for (int row = start; row <= end; ++row)
{
const CSMWorld::Pathgrid& pathgrid = pathgrids.getRecord(row).get();
if (mCellId == pathgrid.mId)
if (ESM::RefId::stringRefId(mCellId) == pathgrid.mId)
{
mCell->pathgridRemoved();
flagAsModified();
@ -324,7 +324,7 @@ void CSVRender::UnpagedWorldspaceWidget::pathgridAdded(const QModelIndex& parent
for (int row = start; row <= end; ++row)
{
const CSMWorld::Pathgrid& pathgrid = pathgrids.getRecord(row).get();
if (mCellId == pathgrid.mId)
if (ESM::RefId::stringRefId(mCellId) == pathgrid.mId)
{
mCell->pathgridModified();
flagAsModified();

@ -300,7 +300,7 @@ CSVRender::WorldspaceWidget::DropType CSVRender::WorldspaceWidget::getDropType(
if (iter->getType() == CSMWorld::UniversalId::Type_Cell
|| iter->getType() == CSMWorld::UniversalId::Type_Cell_Missing)
{
type = iter->getId().substr(0, 1) == "#" ? Type_CellsExterior : Type_CellsInterior;
type = iter->getId()[0] == '#' ? Type_CellsExterior : Type_CellsInterior;
}
else if (iter->getType() == CSMWorld::UniversalId::Type_DebugProfile)
type = Type_DebugProfile;

@ -182,9 +182,9 @@ void CSVWidget::TextureBrushWindow::setBrushTexture(std::string brushTexture)
{
newBrushTextureId = CSMWorld::LandTexture::createUniqueRecordId(0, counter);
if (landtexturesCollection.searchId(brushTexture) != -1
&& landtexturesCollection.getRecord(brushTexture).isDeleted() == 0
&& landtexturesCollection.getRecord(ESM::RefId::stringRefId(brushTexture)).isDeleted() == 0
&& landtexturesCollection.searchId(newBrushTextureId) != -1
&& landtexturesCollection.getRecord(newBrushTextureId).isDeleted() == 0)
&& landtexturesCollection.getRecord(ESM::RefId::stringRefId(newBrushTextureId)).isDeleted() == 0)
counter = (counter + 1) % maxCounter;
else
freeIndexFound = true;

@ -24,7 +24,11 @@ CSVWorld::PreviewSubView::PreviewSubView(const CSMWorld::UniversalId& id, CSMDoc
if (document.getData().getReferenceables().searchId(id.getId()) == -1)
{
std::string referenceableId = document.getData().getReferences().getRecord(id.getId()).get().mRefID;
std::string referenceableId = document.getData()
.getReferences()
.getRecord(ESM::RefId::stringRefId(id.getId()))
.get()
.mRefID.getRefIdString();
referenceableIdChanged(referenceableId);

@ -49,7 +49,7 @@ CSVWorld::SceneSubView::SceneSubView(const CSMWorld::UniversalId& id, CSMDoc::Do
CSVRender::WorldspaceWidget* worldspaceWidget = nullptr;
widgetType whatWidget;
if (id.getId() == ESM::CellId::sDefaultWorldspace)
if (ESM::RefId::stringRefId(id.getId()) == ESM::CellId::sDefaultWorldspace)
{
whatWidget = widget_Paged;

@ -3,13 +3,13 @@
#include <sstream>
#include <utility>
#include <apps/opencs/model/prefs/category.hpp>
#include <apps/opencs/model/prefs/setting.hpp>
#include <apps/opencs/model/world/scriptcontext.hpp>
#include <components/compiler/extensions0.hpp>
#include <components/compiler/scanner.hpp>
#include <components/compiler/tokenloc.hpp>
#include "../../model/prefs/category.hpp"
#include "../../model/prefs/setting.hpp"
#include <components/esm/refid.hpp>
class QTextDocument;
@ -33,7 +33,7 @@ bool CSVWorld::ScriptHighlighter::parseFloat(float value, const Compiler::TokenL
bool CSVWorld::ScriptHighlighter::parseName(
const std::string& name, const Compiler::TokenLoc& loc, Compiler::Scanner& scanner)
{
highlight(loc, mContext.isId(name) ? Type_Id : Type_Name);
highlight(loc, mContext.isId(ESM::RefId::stringRefId(name)) ? Type_Id : Type_Name);
return true;
}

@ -163,7 +163,7 @@ void OMW::Engine::executeLocalScripts()
MWWorld::LocalScripts& localScripts = mWorld->getLocalScripts();
localScripts.startIteration();
std::pair<std::string, MWWorld::Ptr> script;
std::pair<ESM::RefId, MWWorld::Ptr> script;
while (localScripts.getNext(script))
{
MWScript::InterpreterContext interpreterContext(&script.second.getRefData().getLocals(), script.second);
@ -444,7 +444,7 @@ void OMW::Engine::setResourceDir(const std::filesystem::path& parResDir)
// Set start cell name
void OMW::Engine::setCell(const std::string& cellName)
{
mCellName = cellName;
mCellName = ESM::RefId::stringRefId(cellName);
}
void OMW::Engine::addContentFile(const std::string& file)
@ -790,7 +790,7 @@ void OMW::Engine::prepareEngine()
mScriptContext->setExtensions(&mExtensions);
mScriptManager = std::make_unique<MWScript::ScriptManager>(mWorld->getStore(), *mScriptContext, mWarningsMode,
mScriptBlacklistUse ? mScriptBlacklist : std::vector<std::string>());
mScriptBlacklistUse ? mScriptBlacklist : std::vector<ESM::RefId>());
mEnvironment.setScriptManager(*mScriptManager);
// Create game mechanics system
@ -1003,7 +1003,7 @@ void OMW::Engine::setWarningsMode(int mode)
mWarningsMode = mode;
}
void OMW::Engine::setScriptBlacklist(const std::vector<std::string>& list)
void OMW::Engine::setScriptBlacklist(const std::vector<ESM::RefId>& list)
{
mScriptBlacklist = list;
}

@ -4,6 +4,7 @@
#include <filesystem>
#include <components/compiler/extensions.hpp>
#include <components/esm/refid.hpp>
#include <components/files/collections.hpp>
#include <components/settings/settings.hpp>
#include <components/translation/translation.hpp>
@ -151,7 +152,7 @@ namespace OMW
osg::ref_ptr<SceneUtil::AsyncScreenCaptureOperation> mScreenCaptureOperation;
osg::ref_ptr<SceneUtil::SelectDepthFormatOperation> mSelectDepthFormatOperation;
osg::ref_ptr<SceneUtil::Color::SelectColorFormatOperation> mSelectColorFormatOperation;
std::string mCellName;
ESM::RefId mCellName;
std::vector<std::string> mContentFiles;
std::vector<std::string> mGroundcoverFiles;
@ -178,7 +179,7 @@ namespace OMW
Files::Collections mFileCollections;
bool mFSStrict;
Translation::Storage mTranslationDataStorage;
std::vector<std::string> mScriptBlacklist;
std::vector<ESM::RefId> mScriptBlacklist;
bool mScriptBlacklistUse;
bool mNewGame;
@ -259,7 +260,7 @@ namespace OMW
void setWarningsMode(int mode);
void setScriptBlacklist(const std::vector<std::string>& list);
void setScriptBlacklist(const std::vector<ESM::RefId>& list);
void setScriptBlacklistUse(bool use);

@ -161,7 +161,13 @@ bool parseOptions(int argc, char** argv, OMW::Engine& engine, Files::Configurati
engine.setScriptConsoleMode(variables["script-console"].as<bool>());
engine.setStartupScript(variables["script-run"].as<std::string>());
engine.setWarningsMode(variables["script-warn"].as<int>());
engine.setScriptBlacklist(variables["script-blacklist"].as<StringsVector>());
std::vector<ESM::RefId> scriptBlacklist;
auto& scriptBlacklistString = variables["script-blacklist"].as<StringsVector>();
for (const auto& blacklistString : scriptBlacklistString)
{
scriptBlacklist.push_back(ESM::RefId::stringRefId(blacklistString));
}
engine.setScriptBlacklist(scriptBlacklist);
engine.setScriptBlacklistUse(variables["script-blacklist-use"].as<bool>());
engine.setSaveGameFile(variables["load-savegame"].as<Files::MaybeQuotedPath>().u8string());

@ -17,6 +17,7 @@ namespace ESM
{
class ESMReader;
class ESMWriter;
struct RefId;
}
namespace MWWorld
@ -53,9 +54,9 @@ namespace MWBase
virtual bool startDialogue(const MWWorld::Ptr& actor, ResponseCallback* callback) = 0;
virtual bool inJournal(const std::string& topicId, const std::string& infoId) const = 0;
virtual bool inJournal(const ESM::RefId& topicId, const ESM::RefId& infoId) const = 0;
virtual void addTopic(std::string_view topic) = 0;
virtual void addTopic(const ESM::RefId& topic) = 0;
virtual void addChoice(std::string_view text, int choice) = 0;
virtual const std::vector<std::pair<std::string, int>>& getChoices() const = 0;
@ -64,7 +65,7 @@ namespace MWBase
virtual void goodbye() = 0;
virtual void say(const MWWorld::Ptr& actor, const std::string& topic) = 0;
virtual void say(const MWWorld::Ptr& actor, const ESM::RefId& topic) = 0;
virtual void keywordSelected(const std::string& keyword, ResponseCallback* callback) = 0;
virtual void goodbyeSelected() = 0;
@ -89,7 +90,7 @@ namespace MWBase
};
virtual std::list<std::string> getAvailableTopics() = 0;
virtual int getTopicFlag(const std::string&) const = 0;
virtual int getTopicFlag(const ESM::RefId&) const = 0;
virtual bool checkServiceRefused(ResponseCallback* callback, ServiceType service = ServiceType::Any) = 0;
@ -105,12 +106,12 @@ namespace MWBase
virtual void readRecord(ESM::ESMReader& reader, uint32_t type) = 0;
/// Changes faction1's opinion of faction2 by \a diff.
virtual void modFactionReaction(std::string_view faction1, std::string_view faction2, int diff) = 0;
virtual void modFactionReaction(const ESM::RefId& faction1, const ESM::RefId& faction2, int diff) = 0;
virtual void setFactionReaction(std::string_view faction1, std::string_view faction2, int absolute) = 0;
virtual void setFactionReaction(const ESM::RefId& faction1, const ESM::RefId& faction2, int absolute) = 0;
/// @return faction1's opinion of faction2
virtual int getFactionReaction(std::string_view faction1, std::string_view faction2) const = 0;
virtual int getFactionReaction(const ESM::RefId& faction1, const ESM::RefId& faction2) const = 0;
/// Removes the last added topic response for the given actor from the journal
virtual void clearInfoActor(const MWWorld::Ptr& actor) const = 0;

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save