openMW_test_suite compiles and runs

Slowly moving through the open-cs errors

Good progress in openCS

Very good progress on openCS

Getting closer with openCS

OpenCS compiles and runs! Didn't have time to test it all though

ix openMW

everything compiles on windows??

Fix gcc

Fix Clang
iwyu_full
fteppe 2 years ago committed by florent.teppe
parent 2f2e401559
commit 20da0892ef

@ -560,7 +560,7 @@ namespace EsmTool
std::cout << " Name: " << mData.mName << std::endl; std::cout << " Name: " << mData.mName << std::endl;
std::cout << " Texture: " << mData.mTexture << std::endl; std::cout << " Texture: " << mData.mTexture << std::endl;
std::cout << " Description: " << mData.mDescription << 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 << " Power: " << power << std::endl;
std::cout << " Deleted: " << mIsDeleted << std::endl; std::cout << " Deleted: " << mIsDeleted << std::endl;
} }
@ -704,7 +704,7 @@ namespace EsmTool
std::cout << " Inventory: Count: " << Misc::StringUtils::format("%4d", item.mCount) std::cout << " Inventory: Count: " << Misc::StringUtils::format("%4d", item.mCount)
<< " Item: " << item.mItem << std::endl; << " 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; std::cout << " Spell: " << spell << std::endl;
printTransport(mData.getTransport()); printTransport(mData.getTransport());
@ -1102,7 +1102,7 @@ namespace EsmTool
std::cout << " Inventory: Count: " << Misc::StringUtils::format("%4d", item.mCount) std::cout << " Inventory: Count: " << Misc::StringUtils::format("%4d", item.mCount)
<< " Item: " << item.mItem << std::endl; << " 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; std::cout << " Spell: " << spell << std::endl;
printTransport(mData.getTransport()); printTransport(mData.getTransport());
@ -1187,7 +1187,7 @@ namespace EsmTool
std::cout << " Skill: " << skillLabel(mData.mData.mBonus[i].mSkill) << " (" std::cout << " Skill: " << skillLabel(mData.mData.mBonus[i].mSkill) << " ("
<< mData.mData.mBonus[i].mSkill << ") = " << mData.mData.mBonus[i].mBonus << std::endl; << 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 << " Power: " << power << std::endl;
std::cout << " Deleted: " << mIsDeleted << std::endl; std::cout << " Deleted: " << mIsDeleted << std::endl;

@ -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; } T& get() { return mData; }

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

@ -45,6 +45,7 @@
#include "convertnpcc.hpp" #include "convertnpcc.hpp"
#include "convertplayer.hpp" #include "convertplayer.hpp"
#include "convertscpt.hpp" #include "convertscpt.hpp"
#include <components/esm/refid.hpp>
namespace ESSImport namespace ESSImport
{ {
@ -89,7 +90,7 @@ namespace ESSImport
void write(ESM::ESMWriter& esm) override 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); esm.startRecord(T::sRecordId);
it->second.save(esm); it->second.save(esm);
@ -98,7 +99,7 @@ namespace ESSImport
} }
protected: protected:
std::map<std::string, T> mRecords; std::map<ESM::RefId, T> mRecords;
}; };
class ConvertNPC : public Converter class ConvertNPC : public Converter
@ -110,12 +111,12 @@ namespace ESSImport
bool isDeleted = false; bool isDeleted = false;
npc.load(esm, isDeleted); npc.load(esm, isDeleted);
if (npc.mId != "player") if (npc.mId != ESM::RefId::stringRefId("player"))
{ {
// Handles changes to the NPC struct, but since there is no index here // 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 // 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. // "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 else
{ {
@ -146,7 +147,7 @@ namespace ESSImport
bool isDeleted = false; bool isDeleted = false;
creature.load(esm, isDeleted); 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; bool isDeleted = false;
global.load(esm, isDeleted); global.load(esm, isDeleted);
if (Misc::StringUtils::ciEqual(global.mId, "gamehour")) if (global.mId == ESM::RefId::stringRefId("gamehour"))
mContext->mHour = global.mValue.getFloat(); mContext->mHour = global.mValue.getFloat();
if (Misc::StringUtils::ciEqual(global.mId, "day")) if (global.mId == ESM::RefId::stringRefId("day"))
mContext->mDay = global.mValue.getInteger(); mContext->mDay = global.mValue.getInteger();
if (Misc::StringUtils::ciEqual(global.mId, "month")) if (global.mId == ESM::RefId::stringRefId("month"))
mContext->mMonth = global.mValue.getInteger(); mContext->mMonth = global.mValue.getInteger();
if (Misc::StringUtils::ciEqual(global.mId, "year")) if (global.mId == ESM::RefId::stringRefId("year"))
mContext->mYear = global.mValue.getInteger(); mContext->mYear = global.mValue.getInteger();
mRecords[global.mId] = global; mRecords[global.mId] = global;
} }
@ -184,7 +185,7 @@ namespace ESSImport
bool isDeleted = false; bool isDeleted = false;
class_.load(esm, isDeleted); class_.load(esm, isDeleted);
if (class_.mId == "NEWCLASSID_CHARGEN") if (class_.mId == ESM::RefId::stringRefId("NEWCLASSID_CHARGEN"))
mContext->mCustomPlayerClassName = class_.mName; mContext->mCustomPlayerClassName = class_.mName;
mRecords[class_.mId] = class_; mRecords[class_.mId] = class_;
@ -201,7 +202,7 @@ namespace ESSImport
book.load(esm, isDeleted); book.load(esm, isDeleted);
if (book.mData.mSkillId == -1) 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; mRecords[book.mId] = book;
} }
@ -212,10 +213,10 @@ namespace ESSImport
public: public:
void read(ESM::ESMReader& esm) override void read(ESM::ESMReader& esm) override
{ {
std::string id = esm.getHNString("NAME"); auto id = ESM::RefId::stringRefId(esm.getHNString("NAME"));
NPCC npcc; NPCC npcc;
npcc.load(esm); npcc.load(esm);
if (id == "PlayerSaveGame") if (id == ESM::RefId::stringRefId("PlayerSaveGame"))
{ {
convertNPCC(npcc, mContext->mPlayer.mObject); convertNPCC(npcc, mContext->mPlayer.mObject);
} }
@ -251,8 +252,7 @@ namespace ESSImport
for (unsigned int i = 0; i < invState.mItems.size(); ++i) 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? // FIXME: in case of conflict (multiple items with this refID) use the already equipped one?
if (Misc::StringUtils::ciEqual( if (invState.mItems[i].mRef.mRefID == ESM::RefId::stringRefId(refr.mActorData.mSelectedEnchantItem))
invState.mItems[i].mRef.mRefID, refr.mActorData.mSelectedEnchantItem))
invState.mSelectedEnchantItem = i; invState.mSelectedEnchantItem = i;
} }
} }
@ -308,7 +308,7 @@ namespace ESSImport
{ {
void read(ESM::ESMReader& esm) override void read(ESM::ESMReader& esm) override
{ {
std::string id = esm.getHNString("NAME"); auto id = ESM::RefId::stringRefId(esm.getHNString("NAME"));
CNTC cntc; CNTC cntc;
cntc.load(esm); cntc.load(esm);
mContext->mContainerChanges.insert(std::make_pair(std::make_pair(cntc.mIndex, id), cntc)); mContext->mContainerChanges.insert(std::make_pair(std::make_pair(cntc.mIndex, id), cntc));
@ -320,7 +320,7 @@ namespace ESSImport
public: public:
void read(ESM::ESMReader& esm) override void read(ESM::ESMReader& esm) override
{ {
std::string id = esm.getHNString("NAME"); auto id = ESM::RefId::stringRefId(esm.getHNString("NAME"));
CREC crec; CREC crec;
crec.load(esm); crec.load(esm);
mContext->mCreatureChanges.insert(std::make_pair(std::make_pair(crec.mIndex, id), crec)); mContext->mCreatureChanges.insert(std::make_pair(std::make_pair(crec.mIndex, id), crec));
@ -395,11 +395,11 @@ namespace ESSImport
bool isDeleted = false; bool isDeleted = false;
faction.load(esm, isDeleted); 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) 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)); mContext->mDialogueState.mChangedFactionReaction[id].insert(std::make_pair(faction2, it->second));
} }
} }
@ -433,10 +433,10 @@ namespace ESSImport
ESM::StolenItems items; ESM::StolenItems items;
for (auto it = mStolenItems.begin(); it != mStolenItems.end(); ++it) 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) 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, // Since OpenMW doesn't suffer from the owner contamination bug,
// it needs a count argument. But for legacy savegames, we don't know // 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, // this count, so must assume all items of that ID are stolen,
@ -445,7 +445,7 @@ namespace ESSImport
std::numeric_limits<int>::max())); 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); esm.startRecord(ESM::REC_STLN);
@ -494,7 +494,7 @@ namespace ESSImport
ESM::QuestState state; ESM::QuestState state;
state.mFinished = 0; state.mFinished = 0;
state.mState = it->second.mIndex; state.mState = it->second.mIndex;
state.mTopic = Misc::StringUtils::lowerCase(it->first); state.mTopic = ESM::RefId::stringRefId(it->first);
state.save(esm); state.save(esm);
esm.endRecord(ESM::REC_QUES); esm.endRecord(ESM::REC_QUES);
} }

@ -15,7 +15,7 @@ namespace ESSImport
ESM::ObjectState objstate; ESM::ObjectState objstate;
objstate.blank(); objstate.blank();
objstate.mRef = item; 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 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 // openmw handles them differently, so no need to set any flags
state.mItems.push_back(objstate); state.mItems.push_back(objstate);

@ -8,13 +8,13 @@
namespace ESSImport 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) bool& firstPersonCam, bool& teleportingEnabled, bool& levitationEnabled, ESM::ControlsState& controls)
{ {
out.mObject.mPosition.rot[0] out.mObject.mPosition.rot[0]
= -atan2(pcdt.mPNAM.mVerticalRotation.mData[2][1], pcdt.mPNAM.mVerticalRotation.mData[2][2]); = -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; out.mObject.mNpcStats.mBounty = pcdt.mBounty;
for (const auto& essFaction : pcdt.mFactions) for (const auto& essFaction : pcdt.mFactions)
{ {
@ -22,7 +22,7 @@ namespace ESSImport
faction.mExpelled = (essFaction.mFlags & 0x2) != 0; faction.mExpelled = (essFaction.mFlags & 0x2) != 0;
faction.mRank = essFaction.mRank; faction.mRank = essFaction.mRank;
faction.mReputation = essFaction.mReputation; 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) for (int i = 0; i < 3; ++i)
out.mObject.mNpcStats.mSpecIncreases[i] = pcdt.mPNAM.mSpecIncreases[i]; out.mObject.mNpcStats.mSpecIncreases[i] = pcdt.mPNAM.mSpecIncreases[i];
@ -43,7 +43,7 @@ namespace ESSImport
for (const auto& knownDialogueTopic : pcdt.mKnownDialogueTopics) 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; controls.mViewSwitchDisabled = pcdt.mPNAM.mPlayerFlags & PCDT::PlayerFlags_ViewSwitchDisabled;

@ -9,7 +9,7 @@
namespace ESSImport 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); bool& firstPersonCam, bool& teleportingEnabled, bool& levitationEnabled, ESM::ControlsState& controls);
} }

@ -9,7 +9,7 @@ namespace ESSImport
void convertSCPT(const SCPT& scpt, ESM::GlobalScript& out) 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.mRunning = scpt.mRunning;
out.mTargetRef.unset(); // TODO: convert target reference of global script out.mTargetRef.unset(); // TODO: convert target reference of global script
convertSCRI(scpt.mSCRI, out.mLocals); convertSCRI(scpt.mSCRI, out.mLocals);

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

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

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

@ -36,7 +36,7 @@
#include <tuple> #include <tuple>
#include <utility> #include <utility>
#include <vector> #include <vector>
#include <components/esm/refid.hpp>
namespace NavMeshTool namespace NavMeshTool
{ {
namespace namespace
@ -52,12 +52,12 @@ namespace NavMeshTool
{ {
ESM::RecNameInts mType; ESM::RecNameInts mType;
ESM::RefNum mRefNum; ESM::RefNum mRefNum;
std::string mRefId; ESM::RefId mRefId;
float mScale; float mScale;
ESM::Position mPos; ESM::Position mPos;
CellRef( 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) : mType(type)
, mRefNum(refNum) , mRefNum(refNum)
, mRefId(std::move(refId)) , 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( const auto it = std::lower_bound(
esmData.mRefIdTypes.begin(), esmData.mRefIdTypes.end(), refId, EsmLoader::LessById{}); esmData.mRefIdTypes.begin(), esmData.mRefIdTypes.end(), refId, EsmLoader::LessById{});
@ -89,7 +89,6 @@ namespace NavMeshTool
bool deleted = false; bool deleted = false;
while (ESM::Cell::getNextRef(*reader, cellRef, deleted)) while (ESM::Cell::getNextRef(*reader, cellRef, deleted))
{ {
Misc::StringUtils::lowerCaseInPlace(cellRef.mRefID);
const ESM::RecNameInts type = getType(esmData, cellRef.mRefID); const ESM::RecNameInts type = getType(esmData, cellRef.mRefID);
if (type == ESM::RecNameInts{}) if (type == ESM::RecNameInts{})
continue; continue;

@ -46,7 +46,7 @@ void CSMDoc::Document::addGmsts()
for (size_t i = 0; i < CSMWorld::DefaultGmsts::FloatCount; ++i) for (size_t i = 0; i < CSMWorld::DefaultGmsts::FloatCount; ++i)
{ {
ESM::GameSetting gmst; 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.mValue.setType(ESM::VT_Float);
gmst.mRecordFlags = 0; gmst.mRecordFlags = 0;
gmst.mValue.setFloat(CSMWorld::DefaultGmsts::FloatsDefaultValues[i]); 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) for (size_t i = 0; i < CSMWorld::DefaultGmsts::IntCount; ++i)
{ {
ESM::GameSetting gmst; 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.mValue.setType(ESM::VT_Int);
gmst.mRecordFlags = 0; gmst.mRecordFlags = 0;
gmst.mValue.setInteger(CSMWorld::DefaultGmsts::IntsDefaultValues[i]); 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) for (size_t i = 0; i < CSMWorld::DefaultGmsts::StringCount; ++i)
{ {
ESM::GameSetting gmst; 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.mValue.setType(ESM::VT_String);
gmst.mRecordFlags = 0; gmst.mRecordFlags = 0;
gmst.mValue.setString(""); gmst.mValue.setString("");
@ -79,7 +79,7 @@ void CSMDoc::Document::addOptionalGmsts()
for (size_t i = 0; i < CSMWorld::DefaultGmsts::OptionalFloatCount; ++i) for (size_t i = 0; i < CSMWorld::DefaultGmsts::OptionalFloatCount; ++i)
{ {
ESM::GameSetting gmst; ESM::GameSetting gmst;
gmst.mId = CSMWorld::DefaultGmsts::OptionalFloats[i]; gmst.mId = ESM::RefId::stringRefId(CSMWorld::DefaultGmsts::OptionalFloats[i]);
gmst.blank(); gmst.blank();
gmst.mValue.setType(ESM::VT_Float); gmst.mValue.setType(ESM::VT_Float);
addOptionalGmst(gmst); addOptionalGmst(gmst);
@ -88,7 +88,7 @@ void CSMDoc::Document::addOptionalGmsts()
for (size_t i = 0; i < CSMWorld::DefaultGmsts::OptionalIntCount; ++i) for (size_t i = 0; i < CSMWorld::DefaultGmsts::OptionalIntCount; ++i)
{ {
ESM::GameSetting gmst; ESM::GameSetting gmst;
gmst.mId = CSMWorld::DefaultGmsts::OptionalInts[i]; gmst.mId = ESM::RefId::stringRefId(CSMWorld::DefaultGmsts::OptionalInts[i]);
gmst.blank(); gmst.blank();
gmst.mValue.setType(ESM::VT_Int); gmst.mValue.setType(ESM::VT_Int);
addOptionalGmst(gmst); addOptionalGmst(gmst);
@ -97,7 +97,7 @@ void CSMDoc::Document::addOptionalGmsts()
for (size_t i = 0; i < CSMWorld::DefaultGmsts::OptionalStringCount; ++i) for (size_t i = 0; i < CSMWorld::DefaultGmsts::OptionalStringCount; ++i)
{ {
ESM::GameSetting gmst; ESM::GameSetting gmst;
gmst.mId = CSMWorld::DefaultGmsts::OptionalStrings[i]; gmst.mId = ESM::RefId::stringRefId(CSMWorld::DefaultGmsts::OptionalStrings[i]);
gmst.blank(); gmst.blank();
gmst.mValue.setType(ESM::VT_String); gmst.mValue.setType(ESM::VT_String);
gmst.mValue.setString("<no text>"); gmst.mValue.setString("<no text>");
@ -117,7 +117,7 @@ void CSMDoc::Document::addOptionalGlobals()
for (int i = 0; sGlobals[i]; ++i) for (int i = 0; sGlobals[i]; ++i)
{ {
ESM::Global global; ESM::Global global;
global.mId = sGlobals[i]; global.mId = ESM::RefId::stringRefId(sGlobals[i]);
global.blank(); global.blank();
global.mValue.setType(ESM::VT_Long); global.mValue.setType(ESM::VT_Long);
@ -134,7 +134,7 @@ void CSMDoc::Document::addOptionalMagicEffects()
{ {
ESM::MagicEffect effect; ESM::MagicEffect effect;
effect.mIndex = i; effect.mIndex = i;
effect.mId = ESM::MagicEffect::indexToId(i); effect.mId = ESM::RefId::stringRefId(ESM::MagicEffect::indexToId(i));
effect.blank(); effect.blank();
addOptionalMagicEffect(effect); addOptionalMagicEffect(effect);
@ -191,7 +191,7 @@ void CSMDoc::Document::createBase()
for (int i = 0; sGlobals[i]; ++i) for (int i = 0; sGlobals[i]; ++i)
{ {
ESM::Global record; ESM::Global record;
record.mId = sGlobals[i]; record.mId = ESM::RefId::stringRefId(sGlobals[i]);
record.mRecordFlags = 0; record.mRecordFlags = 0;
record.mValue.setType(i == 2 ? ESM::VT_Float : ESM::VT_Long); record.mValue.setType(i == 2 ? ESM::VT_Float : ESM::VT_Long);
@ -207,7 +207,7 @@ void CSMDoc::Document::createBase()
{ {
ESM::Skill record; ESM::Skill record;
record.mIndex = i; record.mIndex = i;
record.mId = ESM::Skill::indexToId(record.mIndex); record.mId = ESM::RefId::stringRefId(ESM::Skill::indexToId(record.mIndex));
record.blank(); record.blank();
getData().getSkills().add(record); getData().getSkills().add(record);
@ -228,7 +228,7 @@ void CSMDoc::Document::createBase()
for (int i = 0; sVoice[i]; ++i) for (int i = 0; sVoice[i]; ++i)
{ {
ESM::Dialogue record; ESM::Dialogue record;
record.mId = sVoice[i]; record.mId = ESM::RefId::stringRefId(sVoice[i]);
record.mType = ESM::Dialogue::Voice; record.mType = ESM::Dialogue::Voice;
record.blank(); record.blank();
@ -252,7 +252,7 @@ void CSMDoc::Document::createBase()
for (int i = 0; sGreetings[i]; ++i) for (int i = 0; sGreetings[i]; ++i)
{ {
ESM::Dialogue record; ESM::Dialogue record;
record.mId = sGreetings[i]; record.mId = ESM::RefId::stringRefId(sGreetings[i]);
record.mType = ESM::Dialogue::Greeting; record.mType = ESM::Dialogue::Greeting;
record.blank(); record.blank();
@ -276,7 +276,7 @@ void CSMDoc::Document::createBase()
for (int i = 0; sPersuasion[i]; ++i) for (int i = 0; sPersuasion[i]; ++i)
{ {
ESM::Dialogue record; ESM::Dialogue record;
record.mId = sPersuasion[i]; record.mId = ESM::RefId::stringRefId(sPersuasion[i]);
record.mType = ESM::Dialogue::Persuasion; record.mType = ESM::Dialogue::Persuasion;
record.blank(); record.blank();
@ -288,7 +288,7 @@ void CSMDoc::Document::createBase()
ESM::MagicEffect record; ESM::MagicEffect record;
record.mIndex = i; record.mIndex = i;
record.mId = ESM::MagicEffect::indexToId(i); record.mId = ESM::RefId::stringRefId(ESM::MagicEffect::indexToId(i));
record.blank(); record.blank();
@ -504,7 +504,7 @@ void CSMDoc::Document::startRunning(const std::string& profile, const std::strin
contentFiles.emplace_back(mContentFile.filename()); 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(); 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. // Test, if we need to save anything associated info records.
bool infoModified = false; 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) 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) if ((*iter)->isModified() || (*iter)->mState == CSMWorld::RecordBase::State_Deleted)
{ {
ESM::DialInfo info = (*iter)->get(); ESM::DialInfo info = (*iter)->get();
info.mId = info.mId.substr(info.mId.find_last_of('#') + 1); std::string 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) if (iter != range.first)
{ {
CSMWorld::InfoCollection::RecordConstIterator prev = iter; CSMWorld::InfoCollection::RecordConstIterator prev = iter;
--prev; --prev;
std::string prevIdString = (*prev)->get().mId.getRefIdString();
info.mPrev = (*prev)->get().mId.substr((*prev)->get().mId.find_last_of('#') + 1); info.mPrev = ESM::RefId::stringRefId(prevIdString.substr(prevIdString.find_last_of('#') + 1));
} }
CSMWorld::InfoCollection::RecordConstIterator next = iter; CSMWorld::InfoCollection::RecordConstIterator next = iter;
++next; ++next;
info.mNext.clear(); info.mNext = ESM::RefId::sEmpty;
if (next != range.second) if (next != range.second)
{ {
info.mNext = (*next)->get().mId.substr((*next)->get().mId.find_last_of('#') + 1); std::string nextIdString = (*next)->get().mId.getRefIdString();
info.mNext = ESM::RefId::stringRefId(nextIdString.substr(nextIdString.find_last_of('#') + 1));
} }
writer.startRecord(info.sRecordId); writer.startRecord(info.sRecordId);
@ -251,12 +253,12 @@ void CSMDoc::CollectionReferencesStage::perform(int stage, Messages& messages)
if (record.isModified() || record.mState == CSMWorld::RecordBase::State_Deleted) if (record.isModified() || record.mState == CSMWorld::RecordBase::State_Deleted)
{ {
std::string cellId = record.get().mOriginalCell.empty() ? record.get().mCell : record.get().mOriginalCell; 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 // collect moved references at the end of the container
bool interior = cellId.substr(0, 1) != "#"; bool interior = cellId.getRefIdString().substr(0, 1) != "#";
std::ostringstream stream; std::ostringstream stream;
if (!interior) if (!interior)
{ {
@ -267,7 +269,7 @@ void CSMDoc::CollectionReferencesStage::perform(int stage, Messages& messages)
// An empty mOriginalCell is meant to indicate that it is the same as // 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. // 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) && !interior && record.mState != CSMWorld::RecordBase::State_ModifiedOnly && !record.get().mNew)
indices.push_back(i); indices.push_back(i);
else else
@ -312,13 +314,14 @@ void CSMDoc::WriteCellCollectionStage::writeReferences(
stream << "#" << index.first << " " << index.second; stream << "#" << index.first << " " << index.second;
} }
ESM::RefId streamId = ESM::RefId::stringRefId(stream.str());
if (refRecord.mNew || refRecord.mRefNum.mIndex == 0 if (refRecord.mNew || refRecord.mRefNum.mIndex == 0
|| (!interior && ref.mState == CSMWorld::RecordBase::State_ModifiedOnly || (!interior && ref.mState == CSMWorld::RecordBase::State_ModifiedOnly
&& refRecord.mCell != stream.str())) && refRecord.mCell != streamId))
{ {
refRecord.mRefNum.mIndex = newRefNum++; 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) && !interior)
{ {
// An empty mOriginalCell is meant to indicate that it is the same as // An empty mOriginalCell is meant to indicate that it is the same as
@ -353,13 +356,13 @@ void CSMDoc::WriteCellCollectionStage::perform(int stage, Messages& messages)
std::deque<int> persistentRefs; std::deque<int> persistentRefs;
std::map<std::string, std::deque<int>>::const_iterator references 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 if (cell.isModified() || cell.mState == CSMWorld::RecordBase::State_Deleted
|| references != mState.getSubRecords().end()) || references != mState.getSubRecords().end())
{ {
CSMWorld::Cell cellRecord = cell.get(); CSMWorld::Cell cellRecord = cell.get();
bool interior = cellRecord.mId.substr(0, 1) != "#"; bool interior = cellRecord.mId.getRefIdString().substr(0, 1) != "#";
// count new references and adjust RefNumCount accordingsly // count new references and adjust RefNumCount accordingsly
unsigned int newRefNum = cellRecord.mRefNumCounter; unsigned int newRefNum = cellRecord.mRefNumCounter;
@ -387,7 +390,7 @@ void CSMDoc::WriteCellCollectionStage::perform(int stage, Messages& messages)
if (refRecord.mNew if (refRecord.mNew
|| (!interior && ref.mState == CSMWorld::RecordBase::State_ModifiedOnly && || (!interior && ref.mState == CSMWorld::RecordBase::State_ModifiedOnly &&
/// \todo consider worldspace /// \todo consider worldspace
CSMWorld::CellCoordinates(refRecord.getCellIndex()).getId("") != refRecord.mCell)) ESM::RefId::stringRefId(CSMWorld::CellCoordinates( refRecord.getCellIndex()).getId("")) != refRecord.mCell))
++cellRecord.mRefNumCounter; ++cellRecord.mRefNumCounter;
if (refRecord.mRefNum.mIndex >= newRefNum) if (refRecord.mRefNum.mIndex >= newRefNum)
@ -404,7 +407,7 @@ void CSMDoc::WriteCellCollectionStage::perform(int stage, Messages& messages)
{ {
cellRecord.mData.mFlags &= ~ESM::Cell::Interior; cellRecord.mData.mFlags &= ~ESM::Cell::Interior;
std::istringstream stream(cellRecord.mId.c_str()); std::istringstream stream(cellRecord.mId.getRefIdString().c_str());
char ignore; char ignore;
stream >> ignore >> cellRecord.mData.mX >> cellRecord.mData.mY; stream >> ignore >> cellRecord.mData.mX >> cellRecord.mData.mY;
} }
@ -442,10 +445,10 @@ void CSMDoc::WritePathgridCollectionStage::perform(int stage, Messages& messages
if (pathgrid.isModified() || pathgrid.mState == CSMWorld::RecordBase::State_Deleted) if (pathgrid.isModified() || pathgrid.mState == CSMWorld::RecordBase::State_Deleted)
{ {
CSMWorld::Pathgrid record = pathgrid.get(); CSMWorld::Pathgrid record = pathgrid.get();
std::string recordIdString = record.mId.getRefIdString();
if (record.mId.substr(0, 1) == "#") if (recordIdString.substr(0, 1) == "#")
{ {
std::istringstream stream(record.mId.c_str()); std::istringstream stream(recordIdString.c_str());
char ignore; char ignore;
stream >> ignore >> record.mData.mX >> record.mData.mY; stream >> ignore >> record.mData.mX >> record.mData.mY;
} }

@ -97,7 +97,7 @@ namespace CSMDoc
template <class CollectionT> template <class CollectionT>
void WriteCollectionStage<CollectionT>::perform(int stage, Messages& messages) 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; return;
ESM::ESMWriter& writer = mState.getWriter(); ESM::ESMWriter& writer = mState.getWriter();

@ -61,6 +61,6 @@ void CSMTools::BodyPartCheckStage::perform(int stage, CSMDoc::Messages& messages
if (bodyPart.mRace.empty()) if (bodyPart.mRace.empty())
messages.add(id, "Race is missing", "", CSMDoc::Message::Severity_Error); messages.add(id, "Race is missing", "", CSMDoc::Message::Severity_Error);
else if (mRaces.searchId(bodyPart.mRace) == -1) 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(); const ESM::GameSetting& gmst = record.get();
CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Gmst, gmst.mId); CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Gmst, gmst.mId);
std::string gmstIdString = gmst.mId.getRefIdString();
// Test for empty string // Test for empty string
if (gmst.mValue.getType() == ESM::VT_String && gmst.mValue.getString().empty()) 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 // Checking type and limits
// optimization - compare it to lists based on naming convention (f-float,i-int,s-string) // 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) 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) 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]) if (gmst.mValue.getFloat() < CSMWorld::DefaultGmsts::FloatLimits[i * 2])
messages.add( 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]) if (gmst.mValue.getFloat() > CSMWorld::DefaultGmsts::FloatLimits[i * 2 + 1])
messages.add( 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 break; // for loop
} }
} }
} }
else if (gmst.mId[0] == 'i') else if (gmstIdString[0] == 'i')
{ {
for (size_t i = 0; i < CSMWorld::DefaultGmsts::IntCount; ++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) 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]) if (gmst.mValue.getInteger() < CSMWorld::DefaultGmsts::IntLimits[i * 2])
messages.add( 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]) if (gmst.mValue.getInteger() > CSMWorld::DefaultGmsts::IntLimits[i * 2 + 1])
messages.add( 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 break; // for loop
} }
} }
} }
else if (gmst.mId[0] == 's') else if (gmstIdString[0] == 's')
{ {
for (size_t i = 0; i < CSMWorld::DefaultGmsts::StringCount; ++i) 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(); ESM::VarType type = gmst.mValue.getType();
if (type != ESM::VT_String && type != ESM::VT_None) if (type != ESM::VT_String && type != ESM::VT_None)
{ {
std::ostringstream stream; 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"; << varTypeToString(gmst.mValue.getType()) << " type";
messages.add(id, stream.str(), "", CSMDoc::Message::Severity_Error); 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; int totalInfoCount = 0;
std::set<int> questIndices; 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) for (CSMWorld::InfoCollection::RecordConstIterator it = range.first; it != range.second; ++it)
{ {

@ -20,13 +20,13 @@ namespace ESM
} }
std::string CSMTools::MagicEffectCheckStage::checkObject( 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); CSMWorld::RefIdData::LocalIndex index = mObjects.getDataSet().searchId(id);
if (index.first == -1) if (index.first == -1)
return (column + " '" + id + "' does not exist"); return (column + " '" + id.getRefIdString() + "' does not exist");
else if (index.second != type.getType()) 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(); return std::string();
} }
@ -125,11 +125,11 @@ void CSMTools::MagicEffectCheckStage::perform(int stage, CSMDoc::Messages& messa
if (!effect.mCastSound.empty() && mSounds.searchId(effect.mCastSound) == -1) if (!effect.mCastSound.empty() && mSounds.searchId(effect.mCastSound) == -1)
messages.add( messages.add(
id, "Casting sound '" + effect.mCastSound + "' does not exist", "", CSMDoc::Message::Severity_Error); id, "Casting sound '" + effect.mCastSound.getRefIdString() + "' does not exist", "", CSMDoc::Message::Severity_Error);
if (!effect.mHitSound.empty() && mSounds.searchId(effect.mHitSound) == -1) 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) 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) 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: private:
std::string checkObject( 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: public:
MagicEffectCheckStage(const CSMWorld::IdCollection<ESM::MagicEffect>& effects, MagicEffectCheckStage(const CSMWorld::IdCollection<ESM::MagicEffect>& effects,

@ -10,7 +10,7 @@
#include <apps/opencs/model/world/universalid.hpp> #include <apps/opencs/model/world/universalid.hpp>
CSMTools::MandatoryIdStage::MandatoryIdStage(const CSMWorld::CollectionBase& idCollection, 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) : mIdCollection(idCollection)
, mCollectionId(collectionId) , mCollectionId(collectionId)
, mIds(ids) , mIds(ids)
@ -25,5 +25,5 @@ int CSMTools::MandatoryIdStage::setup()
void CSMTools::MandatoryIdStage::perform(int stage, CSMDoc::Messages& messages) void CSMTools::MandatoryIdStage::perform(int stage, CSMDoc::Messages& messages)
{ {
if (mIdCollection.searchId(mIds.at(stage)) == -1 || mIdCollection.getRecord(mIds.at(stage)).isDeleted()) 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());
} }

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

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

@ -520,9 +520,9 @@ void CSMTools::ReferenceableCheckStage::creatureCheck(
CSMWorld::RefIdData::LocalIndex index = mReferencables.searchId(creature.mOriginal); CSMWorld::RefIdData::LocalIndex index = mReferencables.searchId(creature.mOriginal);
if (index.first == -1) if (index.first == -1)
messages.add( messages.add(
id, "Parent creature '" + creature.mOriginal + "' does not exist", "", CSMDoc::Message::Severity_Error); id, "Parent creature '" + creature.mOriginal.getRefIdString() + "' does not exist", "", CSMDoc::Message::Severity_Error);
else if (index.second != CSMWorld::UniversalId::Type_Creature) 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 // Check inventory
@ -681,7 +681,7 @@ void CSMTools::ReferenceableCheckStage::npcCheck(
CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Npc, npc.mId); CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Npc, npc.mId);
// Detect if player is present // Detect if player is present
if (Misc::StringUtils::ciEqual(npc.mId, "player")) // Happy now, scrawl? if (npc.mId == ESM::RefId::stringRefId("player")) // Happy now, scrawl?
mPlayerPresent = true; mPlayerPresent = true;
// Skip "Base" records (setting!) // Skip "Base" records (setting!)
@ -738,23 +738,23 @@ void CSMTools::ReferenceableCheckStage::npcCheck(
if (npc.mClass.empty()) if (npc.mClass.empty())
messages.add(id, "Class is missing", "", CSMDoc::Message::Severity_Error); messages.add(id, "Class is missing", "", CSMDoc::Message::Severity_Error);
else if (mClasses.searchId(npc.mClass) == -1) else if (mClasses.searchId(npc.mClass.getRefIdString()) == -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()) if (npc.mRace.empty())
messages.add(id, "Race is missing", "", CSMDoc::Message::Severity_Error); messages.add(id, "Race is missing", "", CSMDoc::Message::Severity_Error);
else if (mRaces.searchId(npc.mRace) == -1) else if (mRaces.searchId(npc.mRace.getRefIdString()) == -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) if (!npc.mFaction.empty() && mFactions.searchId(npc.mFaction.getRefIdString()) == -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()) if (npc.mHead.empty())
messages.add(id, "Head is missing", "", CSMDoc::Message::Severity_Error); messages.add(id, "Head is missing", "", CSMDoc::Message::Severity_Error);
else else
{ {
if (mBodyParts.searchId(npc.mHead) == -1) if (mBodyParts.searchId(npc.mHead.getRefIdString()) == -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 /// \todo Check gender, race and other body parts stuff validity for the specific NPC
} }
@ -762,8 +762,8 @@ void CSMTools::ReferenceableCheckStage::npcCheck(
messages.add(id, "Hair is missing", "", CSMDoc::Message::Severity_Error); messages.add(id, "Hair is missing", "", CSMDoc::Message::Severity_Error);
else else
{ {
if (mBodyParts.searchId(npc.mHair) == -1) if (mBodyParts.searchId(npc.mHair.getRefIdString()) == -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 /// \todo Check gender, race and other body part stuff validity for the specific NPC
} }
@ -788,18 +788,18 @@ void CSMTools::ReferenceableCheckStage::weaponCheck(
// TODO, It seems that this stuff for spellcasting is obligatory and In fact We should check if records are present // TODO, It seems that this stuff for spellcasting is obligatory and In fact We should check if records are present
if ( // THOSE ARE HARDCODED! if ( // THOSE ARE HARDCODED!
!(weapon.mId == "VFX_Hands" || weapon.mId == "VFX_Absorb" || weapon.mId == "VFX_Reflect" !(weapon.mId == ESM::RefId::stringRefId("VFX_Hands") || weapon.mId == ESM::RefId::stringRefId("VFX_Absorb") || weapon.mId == ESM::RefId::stringRefId("VFX_Reflect")
|| weapon.mId == "VFX_DefaultBolt" || || weapon.mId == ESM::RefId::stringRefId("VFX_DefaultBolt") ||
// TODO I don't know how to get full list of effects :/ // TODO I don't know how to get full list of effects :/
// DANGER!, ACHTUNG! FIXME! The following is the list of the magical bolts, valid for Morrowind.esm. However // DANGER!, ACHTUNG! FIXME! The following is the list of the magical bolts, valid for Morrowind.esm. However
// those are not hardcoded. // those are not hardcoded.
weapon.mId == "magic_bolt" || weapon.mId == "shock_bolt" || weapon.mId == "shield_bolt" weapon.mId == ESM::RefId::stringRefId("magic_bolt") || weapon.mId == ESM::RefId::stringRefId("shock_bolt") || weapon.mId == ESM::RefId::stringRefId("shield_bolt")
|| weapon.mId == "VFX_DestructBolt" || weapon.mId == "VFX_PoisonBolt" || weapon.mId == "VFX_RestoreBolt" || weapon.mId == ESM::RefId::stringRefId("VFX_DestructBolt") || weapon.mId == ESM::RefId::stringRefId("VFX_PoisonBolt") || weapon.mId == ESM::RefId::stringRefId("VFX_RestoreBolt")
|| weapon.mId == "VFX_AlterationBolt" || weapon.mId == "VFX_ConjureBolt" || weapon.mId == "VFX_FrostBolt" || weapon.mId == ESM::RefId::stringRefId("VFX_AlterationBolt") || weapon.mId == ESM::RefId::stringRefId("VFX_ConjureBolt") || weapon.mId == ESM::RefId::stringRefId("VFX_FrostBolt")
|| weapon.mId == "VFX_MysticismBolt" || weapon.mId == "VFX_IllusionBolt" || weapon.mId == "VFX_Multiple2" || weapon.mId == ESM::RefId::stringRefId("VFX_MysticismBolt") || weapon.mId == ESM::RefId::stringRefId("VFX_IllusionBolt") || weapon.mId == ESM::RefId::stringRefId("VFX_Multiple2")
|| weapon.mId == "VFX_Multiple3" || weapon.mId == "VFX_Multiple4" || weapon.mId == "VFX_Multiple5" || weapon.mId == ESM::RefId::stringRefId("VFX_Multiple3") || weapon.mId == ESM::RefId::stringRefId("VFX_Multiple4") || weapon.mId == ESM::RefId::stringRefId("VFX_Multiple5")
|| weapon.mId == "VFX_Multiple6" || weapon.mId == "VFX_Multiple7" || weapon.mId == "VFX_Multiple8" || weapon.mId == ESM::RefId::stringRefId("VFX_Multiple6") || weapon.mId == ESM::RefId::stringRefId("VFX_Multiple7") || weapon.mId == ESM::RefId::stringRefId("VFX_Multiple8")
|| weapon.mId == "VFX_Multiple9")) || weapon.mId == ESM::RefId::stringRefId("VFX_Multiple9")))
{ {
inventoryItemCheck<ESM::Weapon>(weapon, messages, id.toString(), true); inventoryItemCheck<ESM::Weapon>(weapon, messages, id.toString(), true);
@ -903,8 +903,9 @@ void CSMTools::ReferenceableCheckStage::inventoryListCheck(
{ {
for (size_t i = 0; i < itemList.size(); ++i) for (size_t i = 0; i < itemList.size(); ++i)
{ {
std::string itemName = itemList[i].mItem; ESM::RefId item = itemList[i].mItem;
CSMWorld::RefIdData::LocalIndex localIndex = mReferencables.searchId(itemName); auto itemName = item.getRefIdString();
CSMWorld::RefIdData::LocalIndex localIndex = mReferencables.searchId(item);
if (localIndex.first == -1) if (localIndex.first == -1)
messages.add(id, "Item '" + itemName + "' does not exist", "", CSMDoc::Message::Severity_Error); messages.add(id, "Item '" + itemName + "' does not exist", "", CSMDoc::Message::Severity_Error);
@ -1036,10 +1037,10 @@ void CSMTools::ReferenceableCheckStage::listCheck(
{ {
if (mReferencables.searchId(someList.mList[i].mId).first == -1) if (mReferencables.searchId(someList.mList[i].mId).first == -1)
messages.add( messages.add(
someID, "Object '" + someList.mList[i].mId + "' does not exist", "", CSMDoc::Message::Severity_Error); someID, "Object '" + someList.mList[i].mId.getRefIdString() + "' does not exist", "", CSMDoc::Message::Severity_Error);
if (someList.mList[i].mLevel < 1) 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); CSMDoc::Message::Severity_Error);
} }
} }
@ -1052,6 +1053,6 @@ void CSMTools::ReferenceableCheckStage::scriptCheck(
{ {
if (mScripts.searchId(someTool.mScript) == -1) if (mScripts.searchId(someTool.mScript) == -1)
messages.add( messages.add(
someID, "Script '" + someTool.mScript + "' does not exist", "", CSMDoc::Message::Severity_Error); someID, "Script '" + someTool.mScript.getRefIdString() + "' does not exist", "", CSMDoc::Message::Severity_Error);
} }
} }

@ -51,7 +51,7 @@ void CSMTools::ReferenceCheckStage::perform(int stage, CSMDoc::Messages& message
// Check for non existing referenced object // Check for non existing referenced object
if (mObjects.searchId(cellRef.mRefID) == -1) if (mObjects.searchId(cellRef.mRefID) == -1)
messages.add( messages.add(
id, "Instance of a non-existent object '" + cellRef.mRefID + "'", "", CSMDoc::Message::Severity_Error); id, "Instance of a non-existent object '" + cellRef.mRefID.getRefIdString() + "'", "", CSMDoc::Message::Severity_Error);
else else
{ {
// Check if reference charge is valid for it's proper referenced type // Check if reference charge is valid for it's proper referenced type
@ -64,13 +64,13 @@ void CSMTools::ReferenceCheckStage::perform(int stage, CSMDoc::Messages& message
// If object have owner, check if that owner reference is valid // If object have owner, check if that owner reference is valid
if (!cellRef.mOwner.empty() && mObjects.searchId(cellRef.mOwner) == -1) 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 object have creature soul trapped, check if that creature reference is valid
if (!cellRef.mSoul.empty()) if (!cellRef.mSoul.empty())
if (mObjects.searchId(cellRef.mSoul) == -1) if (mObjects.searchId(cellRef.mSoul) == -1)
messages.add( messages.add(
id, "Trapped soul object '" + cellRef.mSoul + "' does not exist", "", CSMDoc::Message::Severity_Error); id, "Trapped soul object '" + cellRef.mSoul.getRefIdString() + "' does not exist", "", CSMDoc::Message::Severity_Error);
if (cellRef.mFaction.empty()) if (cellRef.mFaction.empty())
{ {
@ -80,7 +80,7 @@ void CSMTools::ReferenceCheckStage::perform(int stage, CSMDoc::Messages& message
else else
{ {
if (mFactions.searchId(cellRef.mFaction) == -1) 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) else if (cellRef.mFactionRank < -1)
messages.add(id, "Invalid faction rank", "", CSMDoc::Message::Severity_Error); messages.add(id, "Invalid faction rank", "", 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) for (const ESM::Region::SoundRef& sound : region.mSoundList)
{ {
if (sound.mChance > 100) 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); CSMDoc::Message::Severity_Warning);
} }

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

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

@ -50,11 +50,11 @@ void CSMTools::SoundGenCheckStage::perform(int stage, CSMDoc::Messages& messages
if (creatureIndex.first == -1) if (creatureIndex.first == -1)
{ {
messages.add( messages.add(
id, "Creature '" + soundGen.mCreature + "' doesn't exist", "", CSMDoc::Message::Severity_Error); id, "Creature '" + soundGen.mCreature.getRefIdString() + "' doesn't exist", "", CSMDoc::Message::Severity_Error);
} }
else if (creatureIndex.second != CSMWorld::UniversalId::Type_Creature) 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 +64,6 @@ void CSMTools::SoundGenCheckStage::perform(int stage, CSMDoc::Messages& messages
} }
else if (mSounds.searchId(soundGen.mSound) == -1) 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,12 @@ void CSMTools::StartScriptCheckStage::perform(int stage, CSMDoc::Messages& messa
if ((mIgnoreBaseRecords && record.mState == CSMWorld::RecordBase::State_BaseOnly) || record.isDeleted()) if ((mIgnoreBaseRecords && record.mState == CSMWorld::RecordBase::State_BaseOnly) || record.isDeleted())
return; return;
std::string scriptId = record.get().mId; auto scriptId = record.get().mId;
CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_StartScript, scriptId); CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_StartScript, scriptId);
if (mScripts.searchId(Misc::StringUtils::lowerCase(scriptId)) == -1) if (mScripts.searchId(scriptId) == -1)
messages.add(id, "Start script " + scriptId + " does not exist", "", CSMDoc::Message::Severity_Error); messages.add(id, "Start script " + scriptId.getRefIdString() + " does not exist", "", CSMDoc::Message::Severity_Error);
} }
int CSMTools::StartScriptCheckStage::setup() int CSMTools::StartScriptCheckStage::setup()

@ -79,8 +79,12 @@ CSMDoc::OperationHolder* CSMTools::Tools::getVerifier()
std::vector<std::string> mandatoryIds{ "Day", "DaysPassed", "GameHour", "Month", "PCRace" }; std::vector<std::string> mandatoryIds{ "Day", "DaysPassed", "GameHour", "Month", "PCRace" };
std::vector<ESM::RefId> mandatoryRefIds;
for (auto& id : mandatoryIds)
mandatoryRefIds.push_back(ESM::RefId::stringRefId(id));
mVerifierOperation->appendStage(new MandatoryIdStage( 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())); mVerifierOperation->appendStage(new SkillCheckStage(mData.getSkills()));

@ -181,18 +181,19 @@ void CSMTools::TopicInfoCheckStage::perform(int stage, CSMDoc::Messages& message
// Verification functions // Verification functions
bool CSMTools::TopicInfoCheckStage::verifyActor( 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)
{ {
std::string actorString = actor.getRefIdString();
CSMWorld::RefIdData::LocalIndex index = mReferencables.searchId(actor); CSMWorld::RefIdData::LocalIndex index = mReferencables.searchId(actor);
if (index.first == -1) 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; return false;
} }
else if (mReferencables.getRecord(index).isDeleted()) 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; return false;
} }
else if (index.second != CSMWorld::UniversalId::Type_Npc && index.second != CSMWorld::UniversalId::Type_Creature) else if (index.second != CSMWorld::UniversalId::Type_Npc && index.second != CSMWorld::UniversalId::Type_Creature)
@ -209,11 +210,12 @@ bool CSMTools::TopicInfoCheckStage::verifyActor(
} }
bool CSMTools::TopicInfoCheckStage::verifyCell( 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()) std::string cellName = cell.getRefIdString();
if (mCellNames.find(cellName) == mCellNames.end())
{ {
messages.add(id, "Cell '" + cell + "' does not exist", "", CSMDoc::Message::Severity_Error); messages.add(id, "Cell '" + cellName + "' does not exist", "", CSMDoc::Message::Severity_Error);
return false; return false;
} }
@ -221,7 +223,7 @@ bool CSMTools::TopicInfoCheckStage::verifyCell(
} }
bool CSMTools::TopicInfoCheckStage::verifyFactionRank( 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) if (rank < -1)
{ {
@ -256,18 +258,19 @@ bool CSMTools::TopicInfoCheckStage::verifyFactionRank(
} }
bool CSMTools::TopicInfoCheckStage::verifyItem( 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)
{ {
std::string idString = item.getRefIdString();
CSMWorld::RefIdData::LocalIndex index = mReferencables.searchId(item); CSMWorld::RefIdData::LocalIndex index = mReferencables.searchId(item);
if (index.first == -1) 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; return false;
} }
else if (mReferencables.getRecord(index).isDeleted()) 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; return false;
} }
else else
@ -363,47 +366,47 @@ bool CSMTools::TopicInfoCheckStage::verifySelectStruct(
// Id checks // Id checks
if (infoCondition.getFunctionName() == CSMWorld::ConstInfoSelectWrapper::Function_Global if (infoCondition.getFunctionName() == CSMWorld::ConstInfoSelectWrapper::Function_Global
&& !verifyId(infoCondition.getVariableName(), mGlobals, id, messages)) && !verifyId(ESM::RefId::stringRefId(infoCondition.getVariableName()), mGlobals, id, messages))
{ {
return false; return false;
} }
else if (infoCondition.getFunctionName() == CSMWorld::ConstInfoSelectWrapper::Function_Journal 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; return false;
} }
else if (infoCondition.getFunctionName() == CSMWorld::ConstInfoSelectWrapper::Function_Item else if (infoCondition.getFunctionName() == CSMWorld::ConstInfoSelectWrapper::Function_Item
&& !verifyItem(infoCondition.getVariableName(), id, messages)) && !verifyItem(ESM::RefId::stringRefId(infoCondition.getVariableName()), id, messages))
{ {
return false; return false;
} }
else if (infoCondition.getFunctionName() == CSMWorld::ConstInfoSelectWrapper::Function_Dead else if (infoCondition.getFunctionName() == CSMWorld::ConstInfoSelectWrapper::Function_Dead
&& !verifyActor(infoCondition.getVariableName(), id, messages)) && !verifyActor(ESM::RefId::stringRefId(infoCondition.getVariableName()), id, messages))
{ {
return false; return false;
} }
else if (infoCondition.getFunctionName() == CSMWorld::ConstInfoSelectWrapper::Function_NotId else if (infoCondition.getFunctionName() == CSMWorld::ConstInfoSelectWrapper::Function_NotId
&& !verifyActor(infoCondition.getVariableName(), id, messages)) && !verifyActor(ESM::RefId::stringRefId(infoCondition.getVariableName()), id, messages))
{ {
return false; return false;
} }
else if (infoCondition.getFunctionName() == CSMWorld::ConstInfoSelectWrapper::Function_NotFaction 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; return false;
} }
else if (infoCondition.getFunctionName() == CSMWorld::ConstInfoSelectWrapper::Function_NotClass 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; return false;
} }
else if (infoCondition.getFunctionName() == CSMWorld::ConstInfoSelectWrapper::Function_NotRace 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; return false;
} }
else if (infoCondition.getFunctionName() == CSMWorld::ConstInfoSelectWrapper::Function_NotCell else if (infoCondition.getFunctionName() == CSMWorld::ConstInfoSelectWrapper::Function_NotCell
&& !verifyCell(infoCondition.getVariableName(), id, messages)) && !verifyCell(ESM::RefId::stringRefId(infoCondition.getVariableName()), id, messages))
{ {
return false; return false;
} }
@ -424,20 +427,20 @@ bool CSMTools::TopicInfoCheckStage::verifySound(
} }
template <typename T> 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) const CSMWorld::UniversalId& id, CSMDoc::Messages& messages)
{ {
int index = collection.searchId(name); int index = collection.searchId(name);
if (index == -1) 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); CSMDoc::Message::Severity_Error);
return false; return false;
} }
else if (collection.getRecord(index).isDeleted()) 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); "", CSMDoc::Message::Severity_Error);
return false; return false;
} }

@ -77,17 +77,17 @@ namespace CSMTools
bool mIgnoreBaseRecords; bool mIgnoreBaseRecords;
// These return false when not successful and write an error // These return false when not successful and write an error
bool verifyActor(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 std::string& name, const CSMWorld::UniversalId& id, CSMDoc::Messages& messages); bool verifyCell(const ESM::RefId& name, const CSMWorld::UniversalId& id, CSMDoc::Messages& messages);
bool verifyFactionRank( bool verifyFactionRank(
const std::string& name, int rank, const CSMWorld::UniversalId& id, CSMDoc::Messages& messages); const ESM::RefId& name, int rank, const CSMWorld::UniversalId& id, CSMDoc::Messages& messages);
bool verifyItem(const std::string& name, const CSMWorld::UniversalId& id, CSMDoc::Messages& messages); bool verifyItem(const ESM::RefId& name, const CSMWorld::UniversalId& id, CSMDoc::Messages& messages);
bool verifySelectStruct( bool verifySelectStruct(
const ESM::DialInfo::SelectStruct& select, const CSMWorld::UniversalId& id, CSMDoc::Messages& messages); 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); bool verifySound(const std::string& name, const CSMWorld::UniversalId& id, CSMDoc::Messages& messages);
template <typename T> 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); const CSMWorld::UniversalId& id, CSMDoc::Messages& messages);
}; };
} }

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

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

@ -6,11 +6,11 @@ void CSMWorld::Cell::load(ESM::ESMReader& esm, bool& isDeleted)
{ {
ESM::Cell::load(esm, isDeleted, false); ESM::Cell::load(esm, isDeleted, false);
mId = mName; mId = ESM::RefId::stringRefId(mName);
if (isExterior()) if (isExterior())
{ {
std::ostringstream stream; std::ostringstream stream;
stream << "#" << mData.mX << " " << mData.mY; 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. /// Exterior cell coordinates are encoded in the cell ID.
struct Cell : public ESM::Cell struct Cell : public ESM::Cell
{ {
std::string mId; ESM::RefId mId;
void load(ESM::ESMReader& esm, bool& isDeleted); void load(ESM::ESMReader& esm, bool& isDeleted);
}; };

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

@ -11,6 +11,11 @@
class QVariant; class QVariant;
namespace ESM
{
struct RefId;
}
namespace CSMWorld namespace CSMWorld
{ {
struct ColumnBase; struct ColumnBase;
@ -35,9 +40,9 @@ namespace CSMWorld
virtual int getSize() const = 0; 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; virtual int getColumns() const = 0;
@ -57,13 +62,17 @@ namespace CSMWorld
virtual void removeRows(int index, int count) = 0; 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 ///< \param type Will be ignored, unless the collection supports multiple record types
virtual int searchId(std::string_view id) const = 0; virtual int searchId(std::string_view id) const = 0;
////< Search record with \a id. ////< Search record with \a id.
/// \return index of record (if found) or -1 (not found) /// \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; virtual void replace(int index, std::unique_ptr<RecordBase> record) = 0;
///< If the record type does not match, an exception is thrown. ///< If the record type does not match, an exception is thrown.
/// ///
@ -75,19 +84,19 @@ namespace CSMWorld
///< If the record type does not match, an exception is thrown. ///< If the record type does not match, an exception is thrown.
virtual void cloneRecord( virtual void 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)
= 0; = 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 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 ///< \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 ///< Return a sorted collection of all IDs
/// ///
/// \param listDeleted include deleted record in the list /// \param listDeleted include deleted record in the list

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

@ -61,7 +61,7 @@ namespace CSMWorld
QVariant get(const Record<ESXRecordT>& record) const override 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; } bool isEditable() const override { return false; }
@ -690,14 +690,14 @@ namespace CSMWorld
QVariant get(const Record<ESXRecordT>& record) const override 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 void set(Record<ESXRecordT>& record, const QVariant& data) override
{ {
ESXRecordT record2 = record.get(); ESXRecordT record2 = record.get();
record2.mSleepList = data.toString().toUtf8().constData(); record2.mSleepList = ESM::RefId::stringRefId(data.toString().toUtf8().constData());
record.setModified(record2); record.setModified(record2);
} }
@ -816,14 +816,14 @@ namespace CSMWorld
QVariant get(const Record<ESXRecordT>& record) const override 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 void set(Record<ESXRecordT>& record, const QVariant& data) override
{ {
ESXRecordT record2 = record.get(); ESXRecordT record2 = record.get();
record2.mRegion = data.toString().toUtf8().constData(); record2.mRegion = ESM::RefId::stringRefId(data.toString().toUtf8().constData());
record.setModified(record2); record.setModified(record2);
} }
@ -845,14 +845,14 @@ namespace CSMWorld
QVariant get(const Record<ESXRecordT>& record) const override 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 void set(Record<ESXRecordT>& record, const QVariant& data) override
{ {
ESXRecordT record2 = record.get(); ESXRecordT record2 = record.get();
record2.mCell = data.toString().toUtf8().constData(); record2.mCell = ESM::RefId::stringRefId(data.toString().toUtf8().constData());
record.setModified(record2); record.setModified(record2);
} }
@ -872,14 +872,14 @@ namespace CSMWorld
QVariant get(const Record<ESXRecordT>& record) const override 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 void set(Record<ESXRecordT>& record, const QVariant& data) override
{ {
ESXRecordT record2 = record.get(); ESXRecordT record2 = record.get();
record2.mOriginalCell = data.toString().toUtf8().constData(); record2.mOriginalCell = ESM::RefId::stringRefId(data.toString().toUtf8().constData());
record.setModified(record2); record.setModified(record2);
} }
@ -899,14 +899,14 @@ namespace CSMWorld
QVariant get(const Record<ESXRecordT>& record) const override 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 void set(Record<ESXRecordT>& record, const QVariant& data) override
{ {
ESXRecordT record2 = record.get(); ESXRecordT record2 = record.get();
record2.mRefID = data.toString().toUtf8().constData(); record2.mRefID = ESM::RefId::stringRefId(data.toString().toUtf8().constData());
record.setModified(record2); record.setModified(record2);
} }
@ -944,14 +944,14 @@ namespace CSMWorld
QVariant get(const Record<ESXRecordT>& record) const override 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 void set(Record<ESXRecordT>& record, const QVariant& data) override
{ {
ESXRecordT record2 = record.get(); ESXRecordT record2 = record.get();
record2.mOwner = data.toString().toUtf8().constData(); record2.mOwner = ESM::RefId::stringRefId(data.toString().toUtf8().constData());
record.setModified(record2); record.setModified(record2);
} }
@ -969,14 +969,14 @@ namespace CSMWorld
QVariant get(const Record<ESXRecordT>& record) const override 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 void set(Record<ESXRecordT>& record, const QVariant& data) override
{ {
ESXRecordT record2 = record.get(); ESXRecordT record2 = record.get();
record2.mSoul = data.toString().toUtf8().constData(); record2.mSoul = ESM::RefId::stringRefId(data.toString().toUtf8().constData());
record.setModified(record2); record.setModified(record2);
} }
@ -994,14 +994,14 @@ namespace CSMWorld
QVariant get(const Record<ESXRecordT>& record) const override 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 void set(Record<ESXRecordT>& record, const QVariant& data) override
{ {
ESXRecordT record2 = record.get(); ESXRecordT record2 = record.get();
record2.mFaction = data.toString().toUtf8().constData(); record2.mFaction = ESM::RefId::stringRefId(data.toString().toUtf8().constData());
record.setModified(record2); record.setModified(record2);
} }
@ -1168,14 +1168,14 @@ namespace CSMWorld
QVariant get(const Record<ESXRecordT>& record) const override 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 void set(Record<ESXRecordT>& record, const QVariant& data) override
{ {
ESXRecordT record2 = record.get(); ESXRecordT record2 = record.get();
record2.mKey = data.toString().toUtf8().constData(); record2.mKey = ESM::RefId::stringRefId(data.toString().toUtf8().constData());
record.setModified(record2); record.setModified(record2);
} }
@ -1193,14 +1193,14 @@ namespace CSMWorld
QVariant get(const Record<ESXRecordT>& record) const override 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 void set(Record<ESXRecordT>& record, const QVariant& data) override
{ {
ESXRecordT record2 = record.get(); ESXRecordT record2 = record.get();
record2.mTrap = data.toString().toUtf8().constData(); record2.mTrap = ESM::RefId::stringRefId(data.toString().toUtf8().constData());
record.setModified(record2); record.setModified(record2);
} }
@ -1407,14 +1407,14 @@ namespace CSMWorld
QVariant get(const Record<ESXRecordT>& record) const override 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 void set(Record<ESXRecordT>& record, const QVariant& data) override
{ {
ESXRecordT record2 = record.get(); ESXRecordT record2 = record.get();
record2.mTopicId = data.toString().toUtf8().constData(); record2.mTopicId = ESM::RefId::stringRefId(data.toString().toUtf8().constData());
record.setModified(record2); record.setModified(record2);
} }
@ -1434,14 +1434,14 @@ namespace CSMWorld
QVariant get(const Record<ESXRecordT>& record) const override 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 void set(Record<ESXRecordT>& record, const QVariant& data) override
{ {
ESXRecordT record2 = record.get(); ESXRecordT record2 = record.get();
record2.mActor = data.toString().toUtf8().constData(); record2.mActor = ESM::RefId::stringRefId(data.toString().toUtf8().constData());
record.setModified(record2); record.setModified(record2);
} }
@ -1459,14 +1459,14 @@ namespace CSMWorld
QVariant get(const Record<ESXRecordT>& record) const override 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 void set(Record<ESXRecordT>& record, const QVariant& data) override
{ {
ESXRecordT record2 = record.get(); ESXRecordT record2 = record.get();
record2.mRace = data.toString().toUtf8().constData(); record2.mRace = ESM::RefId::stringRefId( data.toString().toUtf8().constData());
record.setModified(record2); record.setModified(record2);
} }
@ -1484,14 +1484,14 @@ namespace CSMWorld
QVariant get(const Record<ESXRecordT>& record) const override 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 void set(Record<ESXRecordT>& record, const QVariant& data) override
{ {
ESXRecordT record2 = record.get(); ESXRecordT record2 = record.get();
record2.mClass = data.toString().toUtf8().constData(); record2.mClass = ESM::RefId::stringRefId(data.toString().toUtf8().constData());
record.setModified(record2); record.setModified(record2);
} }
@ -1509,14 +1509,14 @@ namespace CSMWorld
QVariant get(const Record<ESXRecordT>& record) const override 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 void set(Record<ESXRecordT>& record, const QVariant& data) override
{ {
ESXRecordT record2 = record.get(); ESXRecordT record2 = record.get();
record2.mPcFaction = data.toString().toUtf8().constData(); record2.mPcFaction = ESM::RefId::stringRefId(data.toString().toUtf8().constData());
record.setModified(record2); record.setModified(record2);
} }
@ -1926,14 +1926,14 @@ namespace CSMWorld
QVariant get(const Record<ESXRecordT>& record) const override 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 void set(Record<ESXRecordT>& record, const QVariant& data) override
{ {
ESXRecordT record2 = record.get(); ESXRecordT record2 = record.get();
record2.mSound = data.toString().toUtf8().constData(); record2.mSound = ESM::RefId::stringRefId(data.toString().toUtf8().constData());
record.setModified(record2); record.setModified(record2);
} }
@ -1951,14 +1951,14 @@ namespace CSMWorld
QVariant get(const Record<ESXRecordT>& record) const override 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 void set(Record<ESXRecordT>& record, const QVariant& data) override
{ {
ESXRecordT record2 = record.get(); ESXRecordT record2 = record.get();
record2.mCreature = data.toString().toUtf8().constData(); record2.mCreature = ESM::RefId::stringRefId(data.toString().toUtf8().constData());
record.setModified(record2); record.setModified(record2);
} }
@ -2072,7 +2072,7 @@ namespace CSMWorld
QVariant get(const Record<ESXRecordT>& record) const override QVariant get(const Record<ESXRecordT>& record) const override
{ {
const std::string* string = nullptr; const ESM::RefId* string = nullptr;
switch (this->mColumnId) switch (this->mColumnId)
{ {
@ -2093,12 +2093,12 @@ namespace CSMWorld
if (!string) if (!string)
throw std::logic_error("Unsupported column ID"); 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 void set(Record<ESXRecordT>& record, const QVariant& data) override
{ {
std::string* string = nullptr; ESM::RefId* string = nullptr;
ESXRecordT record2 = record.get(); ESXRecordT record2 = record.get();
@ -2121,7 +2121,7 @@ namespace CSMWorld
if (!string) if (!string)
throw std::logic_error("Unsupported column ID"); throw std::logic_error("Unsupported column ID");
*string = data.toString().toUtf8().constData(); *string = ESM::RefId::stringRefId(data.toString().toUtf8().constData());
record.setModified(record2); record.setModified(record2);
} }
@ -2141,7 +2141,7 @@ namespace CSMWorld
QVariant get(const Record<ESXRecordT>& record) const override QVariant get(const Record<ESXRecordT>& record) const override
{ {
const std::string* string = nullptr; const ESM::RefId* string = nullptr;
switch (this->mColumnId) switch (this->mColumnId)
{ {
@ -2162,12 +2162,12 @@ namespace CSMWorld
if (!string) if (!string)
throw std::logic_error("Unsupported column ID"); 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 void set(Record<ESXRecordT>& record, const QVariant& data) override
{ {
std::string* string = nullptr; ESM::RefId* string = nullptr;
ESXRecordT record2 = record.get(); ESXRecordT record2 = record.get();
@ -2190,7 +2190,7 @@ namespace CSMWorld
if (!string) if (!string)
throw std::logic_error("Unsupported column ID"); throw std::logic_error("Unsupported column ID");
*string = data.toString().toUtf8().constData(); *string = ESM::RefId::stringRefId(data.toString().toUtf8().constData());
record.setModified(record2); record.setModified(record2);
} }

@ -291,10 +291,10 @@ void CSMWorld::CommandDispatcher::executeExtendedDelete()
continue; continue;
if (!std::binary_search( if (!std::binary_search(
mSelection.begin(), mSelection.end(), Misc::StringUtils::lowerCase(record.get().mCell))) mSelection.begin(), mSelection.end(), record.get().mCell.getRefIdString()))
continue; continue;
macro.push(new CSMWorld::DeleteCommand(model, record.get().mId)); macro.push(new CSMWorld::DeleteCommand(model, record.get().mId.getRefIdString()));
} }
} }
} }
@ -322,10 +322,10 @@ void CSMWorld::CommandDispatcher::executeExtendedRevert()
const Record<CellRef>& record = collection.getRecord(i); const Record<CellRef>& record = collection.getRecord(i);
if (!std::binary_search( if (!std::binary_search(
mSelection.begin(), mSelection.end(), Misc::StringUtils::lowerCase(record.get().mCell))) mSelection.begin(), mSelection.end(), record.get().mCell.getRefIdString()))
continue; 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() void CSMWorld::CloneCommand::redo()
{ {
mModel.cloneRecord(mIdOrigin, mId, mType); mModel.cloneRecord(ESM::RefId::stringRefId(mIdOrigin), ESM::RefId::stringRefId(mId), mType);
applyModifications(); applyModifications();
for (auto& value : mOverrideValues) for (auto& value : mOverrideValues)
{ {
@ -442,7 +442,7 @@ void CSMWorld::CreatePathgridCommand::redo()
std::unique_ptr<Record<Pathgrid>> record std::unique_ptr<Record<Pathgrid>> record
= std::make_unique<Record<Pathgrid>>(static_cast<const Record<Pathgrid>&>(mModel.getRecord(mId))); = std::make_unique<Record<Pathgrid>>(static_cast<const Record<Pathgrid>&>(mModel.getRecord(mId)));
record->get().blank(); record->get().blank();
record->get().mCell = mId; record->get().mCell = ESM::RefId::stringRefId(mId);
std::pair<CellCoordinates, bool> coords = CellCoordinates::fromId(mId); std::pair<CellCoordinates, bool> coords = CellCoordinates::fromId(mId);
if (coords.second) 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()); 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 DescriptionColumn<ESM::DebugProfile>);
mDebugProfiles.addColumn(new ScriptColumn<ESM::DebugProfile>(ScriptColumn<ESM::DebugProfile>::Type_Lines)); 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 StringIdColumn<MetaData>(true));
mMetaData.addColumn(new RecordStateColumn<MetaData>); mMetaData.addColumn(new RecordStateColumn<MetaData>);
@ -1018,7 +1018,7 @@ int CSMWorld::Data::startLoading(const std::filesystem::path& path, bool base, b
if (!mProject && !mBase) if (!mProject && !mBase)
{ {
MetaData metaData; MetaData metaData;
metaData.mId = "sys::meta"; metaData.mId = ESM::RefId::stringRefId("sys::meta");
metaData.load(*mReader); metaData.load(*mReader);
mMetaData.setRecord(0, mMetaData.setRecord(0,
@ -1042,7 +1042,7 @@ void CSMWorld::Data::loadFallbackEntries()
if (mReferenceables.searchId(marker.first) == -1) if (mReferenceables.searchId(marker.first) == -1)
{ {
ESM::Static newMarker; ESM::Static newMarker;
newMarker.mId = marker.first; newMarker.mId = ESM::RefId::stringRefId(marker.first);
newMarker.mModel = marker.second; newMarker.mModel = marker.second;
newMarker.mRecordFlags = 0; newMarker.mRecordFlags = 0;
auto record = std::make_unique<CSMWorld::Record<ESM::Static>>(); auto record = std::make_unique<CSMWorld::Record<ESM::Static>>();
@ -1057,7 +1057,7 @@ void CSMWorld::Data::loadFallbackEntries()
if (mReferenceables.searchId(marker.first) == -1) if (mReferenceables.searchId(marker.first) == -1)
{ {
ESM::Door newMarker; ESM::Door newMarker;
newMarker.mId = marker.first; newMarker.mId = ESM::RefId::stringRefId(marker.first);
newMarker.mModel = marker.second; newMarker.mModel = marker.second;
newMarker.mRecordFlags = 0; newMarker.mRecordFlags = 0;
auto record = std::make_unique<CSMWorld::Record<ESM::Door>>(); auto record = std::make_unique<CSMWorld::Record<ESM::Door>>();
@ -1172,7 +1172,7 @@ bool CSMWorld::Data::continueLoading(CSMDoc::Messages& messages)
messages.add(id, "Logic error: cell index out of bounds", "", CSMDoc::Message::Severity_Error); messages.add(id, "Logic error: cell index out of bounds", "", CSMDoc::Message::Severity_Error);
index = mCells.getSize() - 1; index = mCells.getSize() - 1;
} }
std::string cellId = Misc::StringUtils::lowerCase(mCells.getId(index)); std::string cellId = mCells.getId(index).getRefIdString();;
mRefs.load(*mReader, index, mBase, mRefLoadCache[cellId], messages); mRefs.load(*mReader, index, mBase, mRefLoadCache[cellId], messages);
break; break;
} }
@ -1241,6 +1241,7 @@ bool CSMWorld::Data::continueLoading(CSMDoc::Messages& messages)
case ESM::REC_DIAL: case ESM::REC_DIAL:
{ {
ESM::Dialogue record; ESM::Dialogue record;
std::string recordIdString = record.mId.getRefIdString();
bool isDeleted = false; bool isDeleted = false;
record.load(*mReader, isDeleted); record.load(*mReader, isDeleted);
@ -1250,18 +1251,18 @@ bool CSMWorld::Data::continueLoading(CSMDoc::Messages& messages)
// record vector can be shuffled around which would make pointer to record invalid // record vector can be shuffled around which would make pointer to record invalid
mDialogue = nullptr; 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 else
{ {
messages.add(UniversalId::Type_None, 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); CSMDoc::Message::Severity_Warning);
} }
} }
@ -1360,9 +1361,9 @@ int CSMWorld::Data::count(RecordBase::State state) const
+ count(state, mPathgrids); + 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, mGlobals, listDeleted);
appendIds(ids, mGmsts, listDeleted); appendIds(ids, mGmsts, listDeleted);

@ -140,7 +140,7 @@ namespace CSMWorld
void addModel(QAbstractItemModel* model, UniversalId::Type type, bool update = true); 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. ///< Append all IDs from collection to \a ids.
static int count(RecordBase::State state, const CollectionBase& collection); static int count(RecordBase::State state, const CollectionBase& collection);
@ -305,7 +305,7 @@ namespace CSMWorld
bool hasId(const std::string& id) const; 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. ///< Return a sorted collection of all IDs that are not internal to the editor.
/// ///
/// \param listDeleted include deleted record in the list /// \param listDeleted include deleted record in the list

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

@ -74,7 +74,7 @@ namespace CSMWorld
loadRecord(record, reader, isDeleted); loadRecord(record, reader, isDeleted);
std::string id = IdAccessorT().getId(record); ESM::RefId id = IdAccessorT().getId(record);
int index = this->searchId(id); int index = this->searchId(id);
if (isDeleted) 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) 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); beginInsertRows(QModelIndex(), index, index);
mIdCollection->appendBlankRecord(id, type); mIdCollection->appendBlankRecord(refId, type);
endInsertRows(); endInsertRows();
} }
@ -193,11 +194,12 @@ void CSMWorld::IdTable::addRecord(const std::string& id, UniversalId::Type type)
void CSMWorld::IdTable::addRecordWithData( void CSMWorld::IdTable::addRecordWithData(
const std::string& id, const std::map<int, QVariant>& data, UniversalId::Type type) 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); 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) 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( 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); int index = mIdCollection->getAppendIndex(destination, type);
@ -219,9 +221,10 @@ void CSMWorld::IdTable::cloneRecord(
bool CSMWorld::IdTable::touchRecord(const std::string& id) 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); int column = mIdCollection->searchColumnIndex(Columns::ColumnId_RecordType);
if (changed && column != -1) if (changed && column != -1)
{ {
@ -234,7 +237,7 @@ bool CSMWorld::IdTable::touchRecord(const std::string& id)
std::string CSMWorld::IdTable::getId(int row) const 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 /// 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 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 int CSMWorld::IdTable::searchColumnIndex(Columns::ColumnId id) const
@ -367,7 +370,7 @@ CSMWorld::LandTextureIdTable::ImportResults CSMWorld::LandTextureIdTable::import
{ {
auto& record = static_cast<const Record<LandTexture>&>(idCollection()->getRecord(i)); auto& record = static_cast<const Record<LandTexture>&>(idCollection()->getRecord(i));
if (record.isModified()) 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) for (const std::string& id : ids)
@ -404,7 +407,7 @@ CSMWorld::LandTextureIdTable::ImportResults CSMWorld::LandTextureIdTable::import
if (newRow < 0) if (newRow < 0)
{ {
// Id not taken, clone it // 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.createdRecords.push_back(newId);
results.recordMapping.emplace_back(id, newId); results.recordMapping.emplace_back(id, newId);
reverseLookupMap.emplace(texture, newId); reverseLookupMap.emplace(texture, newId);

@ -64,7 +64,7 @@ namespace CSMWorld
///< \param type Will be ignored, unless the collection supports multiple record types ///< \param type Will be ignored, unless the collection supports multiple record types
void cloneRecord( 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); bool touchRecord(const std::string& id);
///< Will change the record state to modified, if it is not already. ///< 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 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 QModelIndex CSMWorld::IdTree::parent(const QModelIndex& index) const

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

@ -86,7 +86,7 @@ namespace CSMWorld
void removeRows(int index, int count) override; 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; int searchId(std::string_view id) const override;

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

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

@ -154,10 +154,10 @@ namespace CSMWorld
{ {
ESXRecordT raceOrBthSgn = record.get(); ESXRecordT raceOrBthSgn = record.get();
std::vector<std::string>& spells = raceOrBthSgn.mPowers.mList; std::vector<ESM::RefId>& spells = raceOrBthSgn.mPowers.mList;
// blank row // blank row
std::string spell; ESM::RefId spell;
spells.insert(spells.begin() + position, spell); spells.insert(spells.begin() + position, spell);
@ -168,7 +168,7 @@ namespace CSMWorld
{ {
ESXRecordT raceOrBthSgn = record.get(); 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())) if (rowToRemove < 0 || rowToRemove >= static_cast<int>(spells.size()))
throw std::runtime_error("index out of range"); throw std::runtime_error("index out of range");
@ -183,7 +183,7 @@ namespace CSMWorld
ESXRecordT raceOrBthSgn = record.get(); ESXRecordT raceOrBthSgn = record.get();
raceOrBthSgn.mPowers.mList 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); record.setModified(raceOrBthSgn);
} }
@ -191,23 +191,23 @@ namespace CSMWorld
NestedTableWrapperBase* table(const Record<ESXRecordT>& record) const override NestedTableWrapperBase* table(const Record<ESXRecordT>& record) const override
{ {
// deleted by dtor of NestedTableStoring // 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 QVariant getData(const Record<ESXRecordT>& record, int subRowIndex, int subColIndex) const override
{ {
ESXRecordT raceOrBthSgn = record.get(); 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())) if (subRowIndex < 0 || subRowIndex >= static_cast<int>(spells.size()))
throw std::runtime_error("index out of range"); throw std::runtime_error("index out of range");
std::string spell = spells[subRowIndex]; ESM::RefId spell = spells[subRowIndex];
switch (subColIndex) switch (subColIndex)
{ {
case 0: case 0:
return QString(spell.c_str()); return QString(spell.getRefIdString().c_str());
default: default:
throw std::runtime_error("Spells subcolumn index out of range"); throw std::runtime_error("Spells subcolumn index out of range");
} }
@ -217,16 +217,16 @@ namespace CSMWorld
{ {
ESXRecordT raceOrBthSgn = record.get(); 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())) if (subRowIndex < 0 || subRowIndex >= static_cast<int>(spells.size()))
throw std::runtime_error("index out of range"); throw std::runtime_error("index out of range");
std::string spell = spells[subRowIndex]; ESM::RefId spell = spells[subRowIndex];
switch (subColIndex) switch (subColIndex)
{ {
case 0: case 0:
spell = value.toString().toUtf8().constData(); spell = ESM::RefId::stringRefId(value.toString().toUtf8().constData());
break; break;
default: default:
throw std::runtime_error("Spells subcolumn index out of range"); 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); load(esm, isDeleted);
// correct ID // correct ID
if (!mId.empty() && mId[0] != '#' && cells.searchId(mId) == -1) if (!mId.empty() && mId.getRefIdString()[0] != '#' && cells.searchId(mId) == -1)
{ {
std::ostringstream stream; std::ostringstream stream;
stream << "#" << mData.mX << " " << mData.mY; 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; std::ostringstream stream;
stream << "#" << mData.mX << " " << mData.mY; stream << "#" << mData.mX << " " << mData.mY;
mId = stream.str(); mId = ESM::RefId::stringRefId(stream.str());
} }
} }

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

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

@ -65,11 +65,13 @@ namespace CSMWorld
virtual void removeRows(int index, int count); virtual void removeRows(int index, int count);
virtual void appendBlankRecord(const std::string& id, UniversalId::Type type = UniversalId::Type_None); 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( virtual void 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);
virtual int searchId(std::string_view id) const; 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); virtual void appendRecord(std::unique_ptr<RecordBase> record, UniversalId::Type type = UniversalId::Type_None);

@ -2,6 +2,7 @@
#define CSM_WOLRD_REFIDADAPTER_H #define CSM_WOLRD_REFIDADAPTER_H
#include <string> #include <string>
#include <components/esm/refid.hpp>
/*! \brief /*! \brief
* Adapters acts as indirection layer, abstracting details of the record types (in the wrappers) from the higher levels * Adapters acts as indirection layer, abstracting details of the record types (in the wrappers) from the higher levels
@ -38,7 +39,7 @@ namespace CSMWorld
virtual void setData(const RefIdColumn* column, RefIdData& data, int index, const QVariant& value) const = 0; 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. ///< 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() 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; return record.get().mScale;
if (column == mColumns.mOriginal) 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) if (column == mColumns.mAttributes)
return QVariant::fromValue(ColumnBase::TableEdit_FixedRows); return QVariant::fromValue(ColumnBase::TableEdit_FixedRows);
@ -538,7 +538,7 @@ void CSMWorld::CreatureRefIdAdapter::setData(
else if (column == mColumns.mScale) else if (column == mColumns.mScale)
creature.mScale = value.toFloat(); creature.mScale = value.toFloat();
else if (column == mColumns.mOriginal) 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) else if (column == mColumns.mBloodType)
creature.mBloodType = value.toInt(); creature.mBloodType = value.toInt();
else 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))); = static_cast<const Record<ESM::Door>&>(data.getRecord(RefIdData::LocalIndex(index, UniversalId::Type_Door)));
if (column == mOpenSound) if (column == mOpenSound)
return QString::fromUtf8(record.get().mOpenSound.c_str()); return QString::fromUtf8(record.get().mOpenSound.getRefIdString().c_str());
if (column == mCloseSound) 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); return NameRefIdAdapter<ESM::Door>::getData(column, data, index);
} }
@ -594,9 +594,9 @@ void CSMWorld::DoorRefIdAdapter::setData(
ESM::Door door = record.get(); ESM::Door door = record.get();
if (column == mOpenSound) if (column == mOpenSound)
door.mOpenSound = value.toString().toUtf8().constData(); door.mOpenSound = ESM::RefId::stringRefId(value.toString().toUtf8().constData());
else if (column == mCloseSound) else if (column == mCloseSound)
door.mCloseSound = value.toString().toUtf8().constData(); door.mCloseSound = ESM::RefId::stringRefId(value.toString().toUtf8().constData());
else else
{ {
NameRefIdAdapter<ESM::Door>::setData(column, data, index, value); 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; return record.get().mData.mColor;
if (column == mColumns.mSound) 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) if (column == mColumns.mEmitterType)
{ {
@ -682,7 +682,7 @@ void CSMWorld::LightRefIdAdapter::setData(
else if (column == mColumns.mColor) else if (column == mColumns.mColor)
light.mData.mColor = value.toInt(); light.mData.mColor = value.toInt();
else if (column == mColumns.mSound) 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) else if (column == mColumns.mEmitterType)
{ {
int mask = ~(ESM::Light::Flicker | ESM::Light::FlickerSlow | ESM::Light::Pulse | ESM::Light::PulseSlow); 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))); = static_cast<const Record<ESM::NPC>&>(data.getRecord(RefIdData::LocalIndex(index, UniversalId::Type_Npc)));
if (column == mColumns.mRace) 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) 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) 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) 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) 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) if (column == mColumns.mAttributes || column == mColumns.mSkills)
{ {
@ -838,15 +838,15 @@ void CSMWorld::NpcRefIdAdapter::setData(
ESM::NPC npc = record.get(); ESM::NPC npc = record.get();
if (column == mColumns.mRace) if (column == mColumns.mRace)
npc.mRace = value.toString().toUtf8().constData(); npc.mRace = ESM::RefId::stringRefId(value.toString().toUtf8().constData());
else if (column == mColumns.mClass) 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) 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) 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) 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) else if (column == mColumns.mBloodType)
npc.mBloodType = value.toInt(); npc.mBloodType = value.toInt();
else if (column == mColumns.mGender) else if (column == mColumns.mGender)

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

@ -648,17 +648,17 @@ int CSMWorld::RefIdCollection::getSize() const
return mData.getSize(); 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); int index = searchId(id);
if (index == -1) if (index == -1)
throw std::runtime_error("invalid ID: " + id); throw std::runtime_error("invalid ID: " + id.getRefIdString());
return index; 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); 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); mData.appendRecord(type, id, false);
} }
int CSMWorld::RefIdCollection::searchId(std::string_view id) const 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) if (localIndex.first == -1)
return -1; return -1;
@ -735,20 +735,25 @@ int CSMWorld::RefIdCollection::searchId(std::string_view id) const
return mData.localToGlobalIndex(localIndex); 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) void CSMWorld::RefIdCollection::replace(int index, std::unique_ptr<RecordBase> record)
{ {
mData.getRecord(mData.globalToLocalIndex(index)).assign(*record.release()); mData.getRecord(mData.globalToLocalIndex(index)).assign(*record.release());
} }
void CSMWorld::RefIdCollection::cloneRecord( 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(); 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); 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"); throw std::runtime_error("RefIdCollection::touchRecord is unimplemented");
return false; 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) 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); 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()); 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)); 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); 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); 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); return mData.getIds(listDeleted);
} }

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

@ -16,7 +16,7 @@ namespace ESM
CSMWorld::RefIdDataContainerBase::~RefIdDataContainerBase() {} 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); 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; 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); auto iter = mIndex.find(id);
std::map<std::string, std::pair<int, UniversalId::Type>>::const_iterator iter = mIndex.find(id2);
if (iter == mIndex.end()) if (iter == mIndex.end())
return std::make_pair(-1, CSMWorld::UniversalId::Type_None); 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; 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); LocalIndex localIndex = searchId(id);
@ -197,7 +195,7 @@ CSMWorld::RecordBase& CSMWorld::RefIdData::getRecord(const LocalIndex& index)
return iter->second->getRecord(index.first); 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); 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); 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 int CSMWorld::RefIdData::getAppendIndex(UniversalId::Type type) const
@ -242,7 +240,7 @@ void CSMWorld::RefIdData::load(ESM::ESMReader& reader, bool base, CSMWorld::Univ
} }
else else
{ {
mIndex[Misc::StringUtils::lowerCase(getRecordId(localIndex))] = localIndex; mIndex[getRecordId(localIndex)] = localIndex;
} }
} }
} }
@ -255,8 +253,8 @@ void CSMWorld::RefIdData::erase(const LocalIndex& index, int count)
for (int i = index.first; i < index.first + count; ++i) for (int i = index.first; i < index.first + count; ++i)
{ {
std::map<std::string, LocalIndex>::iterator result auto result
= mIndex.find(Misc::StringUtils::lowerCase(iter->second->getId(i))); = mIndex.find(iter->second->getId(i));
if (result != mIndex.end()) if (result != mIndex.end())
mIndex.erase(result); mIndex.erase(result);
@ -267,8 +265,8 @@ void CSMWorld::RefIdData::erase(const LocalIndex& index, int count)
int recordCount = iter->second->getSize(); int recordCount = iter->second->getSize();
while (recordIndex < recordCount) while (recordIndex < recordCount)
{ {
std::map<std::string, LocalIndex>::iterator recordIndexFound auto recordIndexFound
= mIndex.find(Misc::StringUtils::lowerCase(iter->second->getId(recordIndex))); = mIndex.find(iter->second->getId(recordIndex));
if (recordIndexFound != mIndex.end()) if (recordIndexFound != mIndex.end())
{ {
recordIndexFound->second.first -= count; recordIndexFound->second.first -= count;
@ -284,11 +282,11 @@ int CSMWorld::RefIdData::getSize() const
return mIndex.size(); 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()) if (listDeleted || !getRecord(iter->second).isDeleted())
{ {
@ -419,7 +417,7 @@ const CSMWorld::RefIdDataContainer<ESM::Static>& CSMWorld::RefIdData::getStatics
} }
void CSMWorld::RefIdData::insertRecord( 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); std::map<UniversalId::Type, RefIdDataContainerBase*>::iterator iter = mRecordContainers.find(type);
@ -428,7 +426,7 @@ void CSMWorld::RefIdData::insertRecord(
iter->second->insertRecord(std::move(record)); 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 void CSMWorld::RefIdData::copyTo(int index, RefIdData& target) const

@ -56,7 +56,7 @@ namespace CSMWorld
virtual unsigned int getRecordFlags(int index) const = 0; 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; virtual void insertRecord(std::unique_ptr<RecordBase> record) = 0;
@ -65,7 +65,7 @@ namespace CSMWorld
virtual void erase(int index, int count) = 0; 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; virtual void save(int index, ESM::ESMWriter& writer) const = 0;
}; };
@ -83,7 +83,7 @@ namespace CSMWorld
unsigned int getRecordFlags(int index) const override; 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; void insertRecord(std::unique_ptr<RecordBase> record) override;
@ -92,7 +92,7 @@ namespace CSMWorld
void erase(int index, int count) override; 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; void save(int index, ESM::ESMWriter& writer) const override;
}; };
@ -132,7 +132,7 @@ namespace CSMWorld
} }
template <typename RecordT> 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>>(); auto record = std::make_unique<Record<RecordT>>();
@ -157,7 +157,7 @@ namespace CSMWorld
int numRecords = static_cast<int>(mContainer.size()); int numRecords = static_cast<int>(mContainer.size());
for (; index < numRecords; ++index) for (; index < numRecords; ++index)
{ {
if (Misc::StringUtils::ciEqual(mContainer[index]->get().mId, record.mId)) if ((mContainer[index]->get().mId == record.mId))
{ {
break; break;
} }
@ -216,7 +216,7 @@ namespace CSMWorld
} }
template <typename RecordT> 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; return mContainer.at(index)->get().mId;
} }
@ -262,14 +262,14 @@ namespace CSMWorld
RefIdDataContainer<ESM::Static> mStatics; RefIdDataContainer<ESM::Static> mStatics;
RefIdDataContainer<ESM::Weapon> mWeapons; RefIdDataContainer<ESM::Weapon> mWeapons;
std::map<std::string, LocalIndex> mIndex; std::map<ESM::RefId, LocalIndex> mIndex;
std::map<UniversalId::Type, RefIdDataContainerBase*> mRecordContainers; std::map<UniversalId::Type, RefIdDataContainerBase*> mRecordContainers;
void erase(const LocalIndex& index, int count); void erase(const LocalIndex& index, int count);
///< Must not spill over into another type. ///< Must not spill over into another type.
std::string getRecordId(const LocalIndex& index) const; ESM::RefId getRecordId(const LocalIndex& index) const;
public: public:
RefIdData(); RefIdData();
@ -278,19 +278,19 @@ namespace CSMWorld
int localToGlobalIndex(const LocalIndex& index) const; 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 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; const RecordBase& getRecord(const LocalIndex& index) const;
RecordBase& getRecord(const LocalIndex& index); 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; int getAppendIndex(UniversalId::Type type) const;
@ -298,7 +298,7 @@ namespace CSMWorld
int getSize() const; 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 ///< Return a sorted collection of all IDs
/// ///
/// \param listDeleted include deleted record in the list /// \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 CSMWorld::CellCoordinates CSMWorld::RegionMap::getIndex(const Cell& cell) const
{ {
std::istringstream stream(cell.mId); std::istringstream stream(cell.mId.getRefIdString());
char ignore; char ignore;
int x = 0; int x = 0;
@ -74,7 +74,7 @@ void CSMWorld::RegionMap::buildRegions()
const Record<ESM::Region>& region = regions.getRecord(i); const Record<ESM::Region>& region = regions.getRecord(i);
if (!region.isDeleted()) 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,33 +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()) if (iter != mColours.end())
mColours.erase(iter); 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()); std::sort(regions2.begin(), regions2.end());
for (std::map<CellCoordinates, CellDescription>::const_iterator iter(mMap.begin()); iter != mMap.end(); ++iter) for (std::map<CellCoordinates, CellDescription>::const_iterator iter(mMap.begin()); iter != mMap.end(); ++iter)
{ {
if (!iter->second.mRegion.empty() if (!iter->second.mRegion.empty()
&& std::find(regions2.begin(), regions2.end(), Misc::StringUtils::lowerCase(iter->second.mRegion)) && std::find(regions2.begin(), regions2.end(),iter->second.mRegion)
!= regions2.end()) != regions2.end())
{ {
QModelIndex index = getIndex(iter->first); QModelIndex index = getIndex(iter->first);
@ -337,8 +333,8 @@ QVariant CSMWorld::RegionMap::data(const QModelIndex& index, int role) const
if (cell->second.mDeleted) if (cell->second.mDeleted)
return QBrush(Qt::red, Qt::DiagCrossPattern); return QBrush(Qt::red, Qt::DiagCrossPattern);
std::map<std::string, unsigned int>::const_iterator iter auto iter
= mColours.find(Misc::StringUtils::lowerCase(cell->second.mRegion)); = mColours.find(cell->second.mRegion);
if (iter != mColours.end()) if (iter != mColours.end())
return QBrush(QColor(iter->second & 0xff, (iter->second >> 8) & 0xff, (iter->second >> 16) & 0xff)); return QBrush(QColor(iter->second & 0xff, (iter->second >> 8) & 0xff, (iter->second >> 16) & 0xff));
@ -374,8 +370,8 @@ QVariant CSMWorld::RegionMap::data(const QModelIndex& index, int role) const
{ {
stream << "<br>"; stream << "<br>";
std::map<std::string, unsigned int>::const_iterator iter auto iter
= mColours.find(Misc::StringUtils::lowerCase(cell->second.mRegion)); = mColours.find(cell->second.mRegion);
if (iter != mColours.end()) if (iter != mColours.end())
stream << cell->second.mRegion; stream << cell->second.mRegion;
@ -396,7 +392,7 @@ QVariant CSMWorld::RegionMap::data(const QModelIndex& index, int role) const
std::map<CellCoordinates, CellDescription>::const_iterator cell = mMap.find(cellIndex); std::map<CellCoordinates, CellDescription>::const_iterator cell = mMap.find(cellIndex);
if (cell != mMap.end() && !cell->second.mRegion.empty()) 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) if (role == Role_CellId)
@ -419,7 +415,7 @@ Qt::ItemFlags CSMWorld::RegionMap::flags(const QModelIndex& index) const
void CSMWorld::RegionMap::regionsAboutToBeRemoved(const QModelIndex& parent, int start, int end) 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(); const IdCollection<ESM::Region>& regions = mData.getRegions();
@ -437,7 +433,7 @@ void CSMWorld::RegionMap::regionsAboutToBeRemoved(const QModelIndex& parent, int
void CSMWorld::RegionMap::regionsInserted(const QModelIndex& parent, int start, int end) 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(); const IdCollection<ESM::Region>& regions = mData.getRegions();
@ -461,7 +457,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 // 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. // 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(); const IdCollection<ESM::Region>& regions = mData.getRegions();

@ -40,7 +40,7 @@ namespace CSMWorld
struct CellDescription struct CellDescription
{ {
bool mDeleted; bool mDeleted;
std::string mRegion; ESM::RefId mRegion;
std::string mName; std::string mName;
CellDescription(); CellDescription();
@ -52,7 +52,7 @@ namespace CSMWorld
std::map<CellCoordinates, CellDescription> mMap; std::map<CellCoordinates, CellDescription> mMap;
CellCoordinates mMin; ///< inclusive CellCoordinates mMin; ///< inclusive
CellCoordinates mMax; ///< exclusive 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; CellCoordinates getIndex(const QModelIndex& index) const;
///< Translates a Qt model index into a cell index (which can contain negative components) ///< Translates a Qt model index into a cell index (which can contain negative components)
@ -74,18 +74,18 @@ namespace CSMWorld
void removeCell(const CellCoordinates& index); void removeCell(const CellCoordinates& index);
///< May be called on a cell that is not in the map (in which case the call is ignored) ///< 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 ///< May be called on a region that is already listed (in which case an update is
/// performed) /// performed)
/// ///
/// \note This function does not update the region map. /// \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) ///< 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. /// \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 ///< Update cells affected by the listed regions
void updateSize(); void updateSize();

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

@ -16,7 +16,7 @@ namespace CSMWorld
class ScriptContext : public Compiler::Context class ScriptContext : public Compiler::Context
{ {
const Data& mData; const Data& mData;
mutable std::vector<std::string> mIds; mutable std::vector<ESM::RefId> mIds;
mutable bool mIdsUpdated; mutable bool mIdsUpdated;
mutable std::map<std::string, Compiler::Locals> mLocals; mutable std::map<std::string, Compiler::Locals> mLocals;
@ -29,13 +29,13 @@ namespace CSMWorld
char getGlobalType(const std::string& name) const override; char getGlobalType(const std::string& name) const override;
///< 'l: long, 's': short, 'f': float, ' ': does not exist. ///< '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 ///< Return type of member variable \a name in script \a id or in script of reference of
/// \a id /// \a id
/// \return first: 'l: long, 's': short, 'f': float, ' ': does not exist. /// \return first: 'l: long, 's': short, 'f': float, ' ': does not exist.
/// second: true: script of reference /// 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? ///< Does \a name match an ID, that can be referenced?
void invalidateIds(); void invalidateIds();

@ -275,6 +275,11 @@ CSMWorld::UniversalId::UniversalId(Type type, const std::string& id)
throw std::logic_error("invalid ID argument UniversalId type"); 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) CSMWorld::UniversalId::UniversalId(Type type, int index)
: mArgumentType(ArgumentType_Index) : mArgumentType(ArgumentType_Index)
, mType(type) , mType(type)

@ -5,6 +5,7 @@
#include <vector> #include <vector>
#include <QMetaType> #include <QMetaType>
#include <components/esm/refid.hpp>
namespace CSMWorld namespace CSMWorld
{ {
@ -158,6 +159,9 @@ namespace CSMWorld
UniversalId(Type type, const std::string& id); UniversalId(Type type, const std::string& id);
///< Using a type for a non-ID-argument UniversalId will throw an exception. ///< 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); UniversalId(Type type, int index);
///< Using a type for a non-index-argument UniversalId will throw an exception. ///< 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\\"; 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) : mId(id)
, mData(data) , mData(data)
, mBaseNode(new osg::Group()) , mBaseNode(new osg::Group())
@ -73,7 +73,7 @@ namespace CSVRender
mSkeleton->setActive(SceneUtil::Skeleton::Active); mSkeleton->setActive(SceneUtil::Skeleton::Active);
} }
void Actor::handleActorChanged(const std::string& refId) void Actor::handleActorChanged(const ESM::RefId& refId)
{ {
if (mId == refId) if (mId == refId)
{ {

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

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

@ -44,7 +44,7 @@ namespace CSVRender
class Cell class Cell
{ {
CSMWorld::Data& mData; CSMWorld::Data& mData;
std::string mId; ESM::RefId mId;
osg::ref_ptr<osg::Group> mCellNode; osg::ref_ptr<osg::Group> mCellNode;
std::map<std::string, Object*> mObjects; std::map<std::string, Object*> mObjects;
std::unique_ptr<Terrain::TerrainGrid> mTerrain; std::unique_ptr<Terrain::TerrainGrid> mTerrain;

@ -131,7 +131,7 @@ namespace CSVRender
{ {
const CSMWorld::Record<CSMWorld::Cell>& cellRecord = cells.getRecord(row); 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); updateCellData(cellRecord);
} }
} }

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

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

@ -23,6 +23,7 @@
#include <components/esm3/loadpgrd.hpp> #include <components/esm3/loadpgrd.hpp>
#include <components/misc/constants.hpp> #include <components/misc/constants.hpp>
#include <components/esm/refid.hpp>
#include <osg/Camera> #include <osg/Camera>
#include <osg/Vec3f> #include <osg/Vec3f>
@ -380,9 +381,9 @@ void CSVRender::PagedWorldspaceWidget::landDataChanged(const QModelIndex& topLef
{ {
for (int r = topLeft.row(); r <= bottomRight.row(); ++r) for (int r = topLeft.row(); r <= bottomRight.row(); ++r)
{ {
std::string id = mDocument.getData().getLand().getId(r); 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()) if (cellIt != mCells.end())
{ {
cellIt->second->landDataChanged(topLeft, bottomRight); cellIt->second->landDataChanged(topLeft, bottomRight);
@ -395,9 +396,9 @@ void CSVRender::PagedWorldspaceWidget::landAboutToBeRemoved(const QModelIndex& p
{ {
for (int r = start; r <= end; ++r) for (int r = start; r <= end; ++r)
{ {
std::string id = mDocument.getData().getLand().getId(r); 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()) if (cellIt != mCells.end())
{ {
cellIt->second->landAboutToBeRemoved(parent, start, end); cellIt->second->landAboutToBeRemoved(parent, start, end);
@ -410,9 +411,9 @@ void CSVRender::PagedWorldspaceWidget::landAdded(const QModelIndex& parent, int
{ {
for (int r = start; r <= end; ++r) for (int r = start; r <= end; ++r)
{ {
std::string id = mDocument.getData().getLand().getId(r); 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()) if (cellIt != mCells.end())
{ {
cellIt->second->landAdded(parent, start, end); cellIt->second->landAdded(parent, start, end);

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

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

@ -310,7 +310,7 @@ bool CSVRender::TerrainSelection::noLandLoaded(const std::string& cellId)
{ {
CSMDoc::Document& document = mWorldspaceWidget->getDocument(); CSMDoc::Document& document = mWorldspaceWidget->getDocument();
const CSMWorld::IdCollection<CSMWorld::Land>& landCollection = document.getData().getLand(); 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) bool CSVRender::TerrainSelection::isLandLoaded(const std::string& cellId)
@ -339,7 +339,7 @@ int CSVRender::TerrainSelection::calculateLandHeight(int x, int y) // global ver
CSMDoc::Document& document = mWorldspaceWidget->getDocument(); CSMDoc::Document& document = mWorldspaceWidget->getDocument();
std::string cellId = CSMWorld::CellCoordinates::generateId(cellX, cellY); std::string cellId = CSMWorld::CellCoordinates::generateId(cellX, cellY);
const ESM::Land::LandData* landData const ESM::Land::LandData* landData
= document.getData().getLand().getRecord(cellId).get().getLandData(ESM::Land::DATA_VHGT); = document.getData().getLand().getRecord(ESM::RefId::stringRefId(cellId)).get().getLandData(ESM::Land::DATA_VHGT);
return landData->mHeights[localY * ESM::Land::LAND_SIZE + localX]; 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(); CSMDoc::Document& document = getWorldspaceWidget().getDocument();
const CSMWorld::IdCollection<CSMWorld::Land>& landCollection = document.getData().getLand(); 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) 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) for (int row = rowStart; row <= rowEnd; ++row)
{ {
const CSMWorld::Pathgrid& pathgrid = pathgrids.getRecord(row).get(); const CSMWorld::Pathgrid& pathgrid = pathgrids.getRecord(row).get();
if (mCellId == pathgrid.mId) if (ESM::RefId::stringRefId(mCellId) == pathgrid.mId)
{ {
mCell->pathgridModified(); mCell->pathgridModified();
flagAsModified(); flagAsModified();
@ -305,7 +305,7 @@ void CSVRender::UnpagedWorldspaceWidget::pathgridAboutToBeRemoved(const QModelIn
for (int row = start; row <= end; ++row) for (int row = start; row <= end; ++row)
{ {
const CSMWorld::Pathgrid& pathgrid = pathgrids.getRecord(row).get(); const CSMWorld::Pathgrid& pathgrid = pathgrids.getRecord(row).get();
if (mCellId == pathgrid.mId) if (ESM::RefId::stringRefId(mCellId) == pathgrid.mId)
{ {
mCell->pathgridRemoved(); mCell->pathgridRemoved();
flagAsModified(); flagAsModified();
@ -324,7 +324,7 @@ void CSVRender::UnpagedWorldspaceWidget::pathgridAdded(const QModelIndex& parent
for (int row = start; row <= end; ++row) for (int row = start; row <= end; ++row)
{ {
const CSMWorld::Pathgrid& pathgrid = pathgrids.getRecord(row).get(); const CSMWorld::Pathgrid& pathgrid = pathgrids.getRecord(row).get();
if (mCellId == pathgrid.mId) if (ESM::RefId::stringRefId(mCellId) == pathgrid.mId)
{ {
mCell->pathgridModified(); mCell->pathgridModified();
flagAsModified(); flagAsModified();

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

@ -24,7 +24,7 @@ CSVWorld::PreviewSubView::PreviewSubView(const CSMWorld::UniversalId& id, CSMDoc
if (document.getData().getReferenceables().searchId(id.getId()) == -1) 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); referenceableIdChanged(referenceableId);

@ -7,7 +7,7 @@
#include <components/compiler/extensions0.hpp> #include <components/compiler/extensions0.hpp>
#include <components/compiler/scanner.hpp> #include <components/compiler/scanner.hpp>
#include <components/compiler/tokenloc.hpp> #include <components/compiler/tokenloc.hpp>
#include <components/esm/refid.hpp>
#include "../../model/prefs/category.hpp" #include "../../model/prefs/category.hpp"
#include "../../model/prefs/setting.hpp" #include "../../model/prefs/setting.hpp"
@ -33,7 +33,7 @@ bool CSVWorld::ScriptHighlighter::parseFloat(float value, const Compiler::TokenL
bool CSVWorld::ScriptHighlighter::parseName( bool CSVWorld::ScriptHighlighter::parseName(
const std::string& name, const Compiler::TokenLoc& loc, Compiler::Scanner& scanner) 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; return true;
} }

@ -1319,11 +1319,11 @@ namespace MWClass
switch (boots->getClass().getEquipmentSkill(*boots)) switch (boots->getClass().getEquipmentSkill(*boots))
{ {
case ESM::Skill::LightArmor: case ESM::Skill::LightArmor:
sound = (name == "left") ? "FootLightLeft" : "FootLightRight"; sound = (name == "left") ? "FootLightLeft" : "FootLightRight"; break;
case ESM::Skill::MediumArmor: case ESM::Skill::MediumArmor:
sound = (name == "left") ? "FootMedLeft" : "FootMedRight"; sound = (name == "left") ? "FootMedLeft" : "FootMedRight"; break;
case ESM::Skill::HeavyArmor: case ESM::Skill::HeavyArmor:
sound = (name == "left") ? "FootHeavyLeft" : "FootHeavyRight"; sound = (name == "left") ? "FootHeavyLeft" : "FootHeavyRight"; break;
} }
} }
return ESM::RefId::sEmpty; return ESM::RefId::sEmpty;

@ -668,7 +668,7 @@ namespace MWDialogue
if (winMgr->getSubtitlesEnabled()) if (winMgr->getSubtitlesEnabled())
winMgr->messageBox(info->mResponse); winMgr->messageBox(info->mResponse);
if (!info->mSound.empty()) if (!info->mSound.empty())
sndMgr->say(actor, info->mSound.getRefIdString()); sndMgr->say(actor, info->mSound);
if (!info->mResultScript.empty()) if (!info->mResultScript.empty())
executeScript(info->mResultScript, actor); executeScript(info->mResultScript, actor);
} }

@ -36,7 +36,7 @@ namespace
{ {
EsmData data; EsmData data;
GetParam().mPushBack(data); GetParam().mPushBack(data);
EXPECT_EQ(EsmLoader::getModel(data, GetParam().mRefId, GetParam().mType), GetParam().mResult); EXPECT_EQ(EsmLoader::getModel(data, ESM::RefId::stringRefId(GetParam().mRefId), GetParam().mType), GetParam().mResult);
} }
void pushBack(ESM::Activator&& value, EsmData& esmData) void pushBack(ESM::Activator&& value, EsmData& esmData)
@ -68,7 +68,7 @@ namespace
void operator()(EsmData& esmData) const void operator()(EsmData& esmData) const
{ {
T value; T value;
value.mId = mId; value.mId = ESM::RefId::stringRefId(mId);
value.mModel = mModel; value.mModel = mModel;
pushBack(std::move(value), esmData); pushBack(std::move(value), esmData);
} }
@ -98,15 +98,15 @@ namespace
{ {
std::vector<ESM::GameSetting> settings; std::vector<ESM::GameSetting> settings;
ESM::GameSetting setting; ESM::GameSetting setting;
setting.mId = "setting"; setting.mId = ESM::RefId::stringRefId("setting");
setting.mValue = ESM::Variant(42); setting.mValue = ESM::Variant(42);
settings.push_back(setting); settings.push_back(setting);
EXPECT_EQ(EsmLoader::getGameSetting(settings, "setting"), ESM::Variant(42)); EXPECT_EQ(EsmLoader::getGameSetting(settings, ESM::RefId::stringRefId("setting")), ESM::Variant(42));
} }
TEST(EsmLoaderGetGameSettingTest, shouldThrowExceptionWhenNotFound) TEST(EsmLoaderGetGameSettingTest, shouldThrowExceptionWhenNotFound)
{ {
const std::vector<ESM::GameSetting> settings; const std::vector<ESM::GameSetting> settings;
EXPECT_THROW(EsmLoader::getGameSetting(settings, "setting"), std::runtime_error); EXPECT_THROW(EsmLoader::getGameSetting(settings, ESM::RefId::stringRefId("setting")), std::runtime_error);
} }
} }

@ -58,9 +58,11 @@ namespace
EXPECT_THAT(asVector(conf.getGlobalConf()), ElementsAre(Pair(0, ""))); EXPECT_THAT(asVector(conf.getGlobalConf()), ElementsAre(Pair(0, "")));
EXPECT_THAT(asVector(conf.getPlayerConf()), ElementsAre(Pair(1, ""))); EXPECT_THAT(asVector(conf.getPlayerConf()), ElementsAre(Pair(1, "")));
EXPECT_THAT(asVector(conf.getLocalConf(ESM::REC_CONT, "something", ESM::RefNum())), ElementsAre()); const ESM::RefId something = ESM::RefId::stringRefId("something");
EXPECT_THAT(asVector(conf.getLocalConf(ESM::REC_NPC_, "something", ESM::RefNum())), ElementsAre(Pair(1, "")));
EXPECT_THAT(asVector(conf.getLocalConf(ESM::REC_CREA, "something", ESM::RefNum())), EXPECT_THAT(asVector(conf.getLocalConf(ESM::REC_CONT, something, ESM::RefNum())), ElementsAre());
EXPECT_THAT(asVector(conf.getLocalConf(ESM::REC_NPC_, something, ESM::RefNum())), ElementsAre(Pair(1, "")));
EXPECT_THAT(asVector(conf.getLocalConf(ESM::REC_CREA, something, ESM::RefNum())),
ElementsAre(Pair(1, ""), Pair(3, ""))); ElementsAre(Pair(1, ""), Pair(3, "")));
// Check that initialization cleans old data // Check that initialization cleans old data
@ -90,7 +92,7 @@ namespace
script1.mInitializationData = "data1"; script1.mInitializationData = "data1";
script1.mFlags = ESM::LuaScriptCfg::sPlayer; script1.mFlags = ESM::LuaScriptCfg::sPlayer;
script1.mTypes.push_back(ESM::REC_CREA); script1.mTypes.push_back(ESM::REC_CREA);
script1.mRecords.push_back({ true, "record1", "dataRecord1" }); script1.mRecords.push_back({ true, ESM::RefId::stringRefId("record1"), "dataRecord1" });
script1.mRefs.push_back({ true, 2, 3, "" }); script1.mRefs.push_back({ true, 2, 3, "" });
script1.mRefs.push_back({ true, 2, 4, "" }); script1.mRefs.push_back({ true, 2, 4, "" });
@ -103,8 +105,8 @@ namespace
script1Extra.mScriptPath = "script1.LUA"; script1Extra.mScriptPath = "script1.LUA";
script1Extra.mFlags = ESM::LuaScriptCfg::sCustom | ESM::LuaScriptCfg::sMerge; script1Extra.mFlags = ESM::LuaScriptCfg::sCustom | ESM::LuaScriptCfg::sMerge;
script1Extra.mTypes.push_back(ESM::REC_NPC_); script1Extra.mTypes.push_back(ESM::REC_NPC_);
script1Extra.mRecords.push_back({ false, "rat", "" }); script1Extra.mRecords.push_back({ false, ESM::RefId::stringRefId("rat"), "" });
script1Extra.mRecords.push_back({ true, "record2", "" }); script1Extra.mRecords.push_back({ true, ESM::RefId::stringRefId("record2"), "" });
script1Extra.mRefs.push_back({ true, 3, 5, "dataRef35" }); script1Extra.mRefs.push_back({ true, 3, 5, "dataRef35" });
script1Extra.mRefs.push_back({ false, 2, 3, "" }); script1Extra.mRefs.push_back({ false, 2, 3, "" });
@ -116,17 +118,17 @@ namespace
EXPECT_EQ(LuaUtil::scriptCfgToString(conf[1]), "CUSTOM CONTAINER : Script2.lua"); EXPECT_EQ(LuaUtil::scriptCfgToString(conf[1]), "CUSTOM CONTAINER : Script2.lua");
EXPECT_THAT(asVector(conf.getPlayerConf()), ElementsAre(Pair(0, "data1"))); EXPECT_THAT(asVector(conf.getPlayerConf()), ElementsAre(Pair(0, "data1")));
EXPECT_THAT(asVector(conf.getLocalConf(ESM::REC_CONT, "something", ESM::RefNum())), ElementsAre(Pair(1, ""))); EXPECT_THAT(asVector(conf.getLocalConf(ESM::REC_CONT, ESM::RefId::stringRefId("something"), ESM::RefNum())), ElementsAre(Pair(1, "")));
EXPECT_THAT(asVector(conf.getLocalConf(ESM::REC_CREA, "guar", ESM::RefNum())), ElementsAre(Pair(0, "data1"))); EXPECT_THAT(asVector(conf.getLocalConf(ESM::REC_CREA, ESM::RefId::stringRefId("guar"), ESM::RefNum())), ElementsAre(Pair(0, "data1")));
EXPECT_THAT(asVector(conf.getLocalConf(ESM::REC_CREA, "rat", ESM::RefNum())), ElementsAre()); EXPECT_THAT(asVector(conf.getLocalConf(ESM::REC_CREA, ESM::RefId::stringRefId("rat"), ESM::RefNum())), ElementsAre());
EXPECT_THAT( EXPECT_THAT(
asVector(conf.getLocalConf(ESM::REC_DOOR, "record1", ESM::RefNum())), ElementsAre(Pair(0, "dataRecord1"))); asVector(conf.getLocalConf(ESM::REC_DOOR, ESM::RefId::stringRefId("record1"), ESM::RefNum())), ElementsAre(Pair(0, "dataRecord1")));
EXPECT_THAT( EXPECT_THAT(
asVector(conf.getLocalConf(ESM::REC_DOOR, "record2", ESM::RefNum())), ElementsAre(Pair(0, "data1"))); asVector(conf.getLocalConf(ESM::REC_DOOR, ESM::RefId::stringRefId("record2"), ESM::RefNum())), ElementsAre(Pair(0, "data1")));
EXPECT_THAT(asVector(conf.getLocalConf(ESM::REC_NPC_, "record3", { 1, 1 })), ElementsAre(Pair(0, "data1"))); EXPECT_THAT(asVector(conf.getLocalConf(ESM::REC_NPC_, ESM::RefId::stringRefId("record3"), { 1, 1 })), ElementsAre(Pair(0, "data1")));
EXPECT_THAT(asVector(conf.getLocalConf(ESM::REC_NPC_, "record3", { 2, 3 })), ElementsAre()); EXPECT_THAT(asVector(conf.getLocalConf(ESM::REC_NPC_, ESM::RefId::stringRefId("record3"), { 2, 3 })), ElementsAre());
EXPECT_THAT(asVector(conf.getLocalConf(ESM::REC_NPC_, "record3", { 3, 5 })), ElementsAre(Pair(0, "dataRef35"))); EXPECT_THAT(asVector(conf.getLocalConf(ESM::REC_NPC_, ESM::RefId::stringRefId("record3"), { 3, 5 })), ElementsAre(Pair(0, "dataRef35")));
EXPECT_THAT(asVector(conf.getLocalConf(ESM::REC_CONT, "record4", { 2, 4 })), EXPECT_THAT(asVector(conf.getLocalConf(ESM::REC_CONT, ESM::RefId::stringRefId("record4"), { 2, 4 })),
ElementsAre(Pair(0, "data1"), Pair(1, ""))); ElementsAre(Pair(0, "data1"), Pair(1, "")));
ESM::LuaScriptCfg& script3 = cfg.mScripts.emplace_back(); ESM::LuaScriptCfg& script3 = cfg.mScripts.emplace_back();
@ -169,8 +171,8 @@ namespace
script.mFlags = ESM::LuaScriptCfg::sMerge; script.mFlags = ESM::LuaScriptCfg::sMerge;
script.mTypes.push_back(ESM::REC_DOOR); script.mTypes.push_back(ESM::REC_DOOR);
script.mTypes.push_back(ESM::REC_MISC); script.mTypes.push_back(ESM::REC_MISC);
script.mRecords.push_back({ true, "rat", luaData }); script.mRecords.push_back({ true, ESM::RefId::stringRefId("rat"), luaData });
script.mRecords.push_back({ false, "chargendoorjournal", "" }); script.mRecords.push_back({ false, ESM::RefId::stringRefId("chargendoorjournal"), "" });
script.mRefs.push_back({ true, 128964, 1, "" }); script.mRefs.push_back({ true, 128964, 1, "" });
script.mRefs.push_back({ true, 128962, 1, luaData }); script.mRefs.push_back({ true, 128962, 1, luaData });
} }

@ -297,7 +297,7 @@ CUSTOM, PLAYER: useInterface.lua
TEST_F(LuaScriptsContainerTest, Interface) TEST_F(LuaScriptsContainerTest, Interface)
{ {
LuaUtil::ScriptsContainer scripts(&mLua, "Test"); LuaUtil::ScriptsContainer scripts(&mLua, "Test");
scripts.setAutoStartConf(mCfg.getLocalConf(ESM::REC_CREA, "", ESM::RefNum())); scripts.setAutoStartConf(mCfg.getLocalConf(ESM::REC_CREA, ESM::RefId::sEmpty, ESM::RefNum()));
int addIfaceId = *mCfg.findId("testInterface.lua"); int addIfaceId = *mCfg.findId("testInterface.lua");
int overrideIfaceId = *mCfg.findId("overrideInterface.lua"); int overrideIfaceId = *mCfg.findId("overrideInterface.lua");
int useIfaceId = *mCfg.findId("useInterface.lua"); int useIfaceId = *mCfg.findId("useInterface.lua");
@ -327,8 +327,8 @@ CUSTOM, PLAYER: useInterface.lua
LuaUtil::ScriptsContainer scripts1(&mLua, "Test"); LuaUtil::ScriptsContainer scripts1(&mLua, "Test");
LuaUtil::ScriptsContainer scripts2(&mLua, "Test"); LuaUtil::ScriptsContainer scripts2(&mLua, "Test");
LuaUtil::ScriptsContainer scripts3(&mLua, "Test"); LuaUtil::ScriptsContainer scripts3(&mLua, "Test");
scripts1.setAutoStartConf(mCfg.getLocalConf(ESM::REC_NPC_, "", ESM::RefNum())); scripts1.setAutoStartConf(mCfg.getLocalConf(ESM::REC_NPC_, ESM::RefId::sEmpty, ESM::RefNum()));
scripts2.setAutoStartConf(mCfg.getLocalConf(ESM::REC_NPC_, "", ESM::RefNum())); scripts2.setAutoStartConf(mCfg.getLocalConf(ESM::REC_NPC_, ESM::RefId::sEmpty, ESM::RefNum()));
scripts3.setAutoStartConf(mCfg.getPlayerConf()); scripts3.setAutoStartConf(mCfg.getPlayerConf());
scripts1.addAutoStartedScripts(); scripts1.addAutoStartedScripts();

@ -29,11 +29,11 @@ namespace
public: public:
bool canDeclareLocals() const override { return true; } bool canDeclareLocals() const override { return true; }
char getGlobalType(const std::string& name) const override { return ' '; } char getGlobalType(const std::string& name) const override { return ' '; }
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 { ' ', false }; return { ' ', false };
} }
bool isId(const std::string& name) const override { return Misc::StringUtils::ciEqual(name, "player"); } bool isId(const ESM::RefId& name) const override { return name == ESM::RefId::stringRefId("player"); }
}; };
class TestErrorHandler : public Compiler::ErrorHandler class TestErrorHandler : public Compiler::ErrorHandler
@ -147,7 +147,7 @@ namespace
std::map<std::string, GlobalVariables, std::less<>> mMembers; std::map<std::string, GlobalVariables, std::less<>> mMembers;
public: public:
std::string_view getTarget() const override { return {}; } const ESM::RefId& getTarget() const override { return ESM::RefId::sEmpty; };
int getLocalShort(int index) const override { return mLocals.getShort(index); } int getLocalShort(int index) const override { return mLocals.getShort(index); }
@ -207,44 +207,44 @@ namespace
std::string_view getCurrentCellName() const override { return {}; } std::string_view getCurrentCellName() const override { return {}; }
int getMemberShort(std::string_view id, std::string_view name, bool global) const override int getMemberShort(const ESM::RefId id, std::string_view name, bool global) const override
{ {
auto it = mMembers.find(id); auto it = mMembers.find(id.getRefIdString());
if (it != mMembers.end()) if (it != mMembers.end())
return it->second.getShort(name); return it->second.getShort(name);
return {}; return {};
} }
int getMemberLong(std::string_view id, std::string_view name, bool global) const override int getMemberLong(const ESM::RefId id, std::string_view name, bool global) const override
{ {
auto it = mMembers.find(id); auto it = mMembers.find(id.getRefIdString());
if (it != mMembers.end()) if (it != mMembers.end())
return it->second.getLong(name); return it->second.getLong(name);
return {}; return {};
} }
float getMemberFloat(std::string_view id, std::string_view name, bool global) const override float getMemberFloat(const ESM::RefId id, std::string_view name, bool global) const override
{ {
auto it = mMembers.find(id); auto it = mMembers.find(id.getRefIdString());
if (it != mMembers.end()) if (it != mMembers.end())
return it->second.getFloat(name); return it->second.getFloat(name);
return {}; return {};
} }
void setMemberShort(std::string_view id, std::string_view name, int value, bool global) override void setMemberShort(const ESM::RefId id, std::string_view name, int value, bool global) override
{ {
mMembers[std::string(id)].setShort(name, value); mMembers[id.getRefIdString()].setShort(name, value);
} };
void setMemberLong(std::string_view id, std::string_view name, int value, bool global) override void setMemberLong(const ESM::RefId id, std::string_view name, int value, bool global) override
{ {
mMembers[std::string(id)].setLong(name, value); mMembers[id.getRefIdString()].setLong(name, value);
} };
void setMemberFloat(std::string_view id, std::string_view name, float value, bool global) override void setMemberFloat(const ESM::RefId id, std::string_view name, float value, bool global) override
{ {
mMembers[std::string(id)].setFloat(name, value); mMembers[id.getRefIdString()].setFloat(name, value);
} };
}; };
struct CompiledScript struct CompiledScript

@ -20,7 +20,7 @@
namespace MWMechanics namespace MWMechanics
{ {
SpellList::SpellList(const std::string& id, int type) SpellList::SpellList(const ESM::RefId& id, int type)
: mId(id) : mId(id)
, mType(type) , mType(type)
{ {
@ -255,7 +255,7 @@ std::unique_ptr<std::istream> getEsmFile(T record, bool deleted)
/// Tests deletion of records. /// Tests deletion of records.
TEST_F(StoreTest, delete_test) TEST_F(StoreTest, delete_test)
{ {
const std::string recordId = "foobar"; const ESM::RefId recordId = ESM::RefId::stringRefId("foobar");
typedef ESM::Apparatus RecordType; typedef ESM::Apparatus RecordType;
@ -292,8 +292,8 @@ TEST_F(StoreTest, delete_test)
/// Tests overwriting of records. /// Tests overwriting of records.
TEST_F(StoreTest, overwrite_test) TEST_F(StoreTest, overwrite_test)
{ {
const std::string recordId = "foobar"; const ESM::RefId recordId = ESM::RefId::stringRefId("foobar");
const std::string recordIdUpper = "Foobar"; const ESM::RefId recordIdUpper = ESM::RefId::stringRefId("Foobar");
typedef ESM::Apparatus RecordType; typedef ESM::Apparatus RecordType;

@ -50,7 +50,7 @@ namespace ESM
mPcFaction = esm.getRefId(); mPcFaction = esm.getRefId();
break; break;
case fourCC("SNAM"): case fourCC("SNAM"):
mSound = esm.getRefId(); mSound = esm.getHString();
break; break;
case SREC_NAME: case SREC_NAME:
mResponse = esm.getHString(); mResponse = esm.getHString();
@ -108,7 +108,7 @@ namespace ESM
esm.writeHNOCString("FNAM", mFaction.getRefIdString()); esm.writeHNOCString("FNAM", mFaction.getRefIdString());
esm.writeHNOCString("ANAM", mCell.getRefIdString()); esm.writeHNOCString("ANAM", mCell.getRefIdString());
esm.writeHNOCString("DNAM", mPcFaction.getRefIdString()); esm.writeHNOCString("DNAM", mPcFaction.getRefIdString());
esm.writeHNOCString("SNAM", mSound.getRefIdString()); esm.writeHNOCString("SNAM", mSound);
esm.writeHNOString("NAME", mResponse); esm.writeHNOString("NAME", mResponse);
for (std::vector<SelectStruct>::const_iterator it = mSelects.begin(); it != mSelects.end(); ++it) for (std::vector<SelectStruct>::const_iterator it = mSelects.begin(); it != mSelects.end(); ++it)
@ -148,7 +148,7 @@ namespace ESM
mFaction = ESM::RefId::sEmpty; mFaction = ESM::RefId::sEmpty;
mPcFaction = ESM::RefId::sEmpty; mPcFaction = ESM::RefId::sEmpty;
mCell = ESM::RefId::sEmpty; mCell = ESM::RefId::sEmpty;
mSound = ESM::RefId::sEmpty; mSound.clear();
mResponse.clear(); mResponse.clear();
mResultScript.clear(); mResultScript.clear();
mFactionLess = false; mFactionLess = false;

@ -75,7 +75,7 @@ namespace ESM
RefId mActor, mRace, mClass, mFaction, mPcFaction, mCell; RefId mActor, mRace, mClass, mFaction, mPcFaction, mCell;
// Sound and text associated with this item // Sound and text associated with this item
RefId mSound; std::string mSound;
std::string mResponse; std::string mResponse;
// Result script (uncompiled) to run whenever this dialog item is // Result script (uncompiled) to run whenever this dialog item is
// selected // selected

Loading…
Cancel
Save