1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-01-21 08:53:52 +00:00

Merge branch 'refactor_refid_strong_type' into 'master'

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

See merge request OpenMW/openmw!2438
This commit is contained in:
psi29a 2022-12-28 09:44:30 +00:00
commit bad573a710
531 changed files with 4228 additions and 3587 deletions

View file

@ -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;
@ -1342,7 +1342,7 @@ namespace EsmTool
template <> template <>
std::string Record<ESM::Cell>::getId() const std::string Record<ESM::Cell>::getId() const
{ {
return mData.mName; return mData.mName.getRefIdString();
} }
template <> template <>

View file

@ -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; }

View file

@ -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;
@ -202,7 +202,7 @@ namespace ESSImport
} }
// note if the player is in a nameless exterior cell, we will assign the cellId later based on player position // note if the player is in a nameless exterior cell, we will assign the cellId later based on player position
if (cell.mName == mContext->mPlayerCellName) if (cell.mName == ESM::RefId::stringRefId(mContext->mPlayerCellName))
{ {
mContext->mPlayer.mCellId = cell.getCellId(); mContext->mPlayer.mCellId = cell.getCellId();
} }
@ -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;

View file

@ -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
@ -115,7 +116,7 @@ namespace ESSImport
// 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 == "gamehour")
mContext->mHour = global.mValue.getFloat(); mContext->mHour = global.mValue.getFloat();
if (Misc::StringUtils::ciEqual(global.mId, "day")) if (global.mId == "day")
mContext->mDay = global.mValue.getInteger(); mContext->mDay = global.mValue.getInteger();
if (Misc::StringUtils::ciEqual(global.mId, "month")) if (global.mId == "month")
mContext->mMonth = global.mValue.getInteger(); mContext->mMonth = global.mValue.getInteger();
if (Misc::StringUtils::ciEqual(global.mId, "year")) if (global.mId == "year")
mContext->mYear = global.mValue.getInteger(); mContext->mYear = global.mValue.getInteger();
mRecords[global.mId] = global; mRecords[global.mId] = global;
} }
@ -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,7 +213,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"));
NPCC npcc; NPCC npcc;
npcc.load(esm); npcc.load(esm);
if (id == "PlayerSaveGame") if (id == "PlayerSaveGame")
@ -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));
@ -351,7 +351,7 @@ namespace ESSImport
std::vector<unsigned int> mFogOfWar; std::vector<unsigned int> mFogOfWar;
}; };
std::map<std::string, Cell> mIntCells; std::map<ESM::RefId, Cell> mIntCells;
std::map<std::pair<int, int>, Cell> mExtCells; std::map<std::pair<int, int>, Cell> mExtCells;
std::vector<ESM::CustomMarker> mMarkers; std::vector<ESM::CustomMarker> mMarkers;
@ -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);
} }

View file

@ -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);

View file

@ -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;
@ -70,7 +70,7 @@ namespace ESSImport
// TODO: Figure out a better way to detect interiors. (0, 0) is a valid exterior cell. // TODO: Figure out a better way to detect interiors. (0, 0) is a valid exterior cell.
if (mark.mCellX == 0 && mark.mCellY == 0) if (mark.mCellX == 0 && mark.mCellY == 0)
{ {
cell.mWorldspace = pcdt.mMNAM; cell.mWorldspace = ESM::RefId::stringRefId(pcdt.mMNAM);
cell.mPaged = false; cell.mPaged = false;
} }

View file

@ -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);
} }

View file

@ -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);

View file

@ -373,7 +373,7 @@ 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 == "NEWCLASSID_CHARGEN")
profile.mPlayerClassName = context.mCustomPlayerClassName; profile.mPlayerClassName = context.mCustomPlayerClassName;
else else
@ -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_);

View file

@ -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;

View file

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

View file

@ -229,7 +229,8 @@ 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);

View file

@ -29,6 +29,7 @@
#include <osg/ref_ptr> #include <osg/ref_ptr>
#include <algorithm> #include <algorithm>
#include <components/esm/refid.hpp>
#include <memory> #include <memory>
#include <stdexcept> #include <stdexcept>
#include <string> #include <string>
@ -36,7 +37,6 @@
#include <tuple> #include <tuple>
#include <utility> #include <utility>
#include <vector> #include <vector>
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;
@ -264,16 +263,16 @@ namespace NavMeshTool
const osg::Vec2i cellPosition(cell.mData.mX, cell.mData.mY); const osg::Vec2i cellPosition(cell.mData.mX, cell.mData.mY);
const std::size_t cellObjectsBegin = data.mObjects.size(); const std::size_t cellObjectsBegin = data.mObjects.size();
const auto cellNameLowerCase = Misc::StringUtils::lowerCase(cell.mCellId.mWorldspace.getRefIdString());
WorldspaceNavMeshInput& navMeshInput = [&]() -> WorldspaceNavMeshInput& { WorldspaceNavMeshInput& navMeshInput = [&]() -> WorldspaceNavMeshInput& {
auto it = navMeshInputs.find(cell.mCellId.mWorldspace); auto it = navMeshInputs.find(cellNameLowerCase);
if (it == navMeshInputs.end()) if (it == navMeshInputs.end())
{ {
it = navMeshInputs it = navMeshInputs
.emplace(cell.mCellId.mWorldspace, .emplace(cellNameLowerCase,
std::make_unique<WorldspaceNavMeshInput>(cell.mCellId.mWorldspace, settings.mRecast)) std::make_unique<WorldspaceNavMeshInput>(cellNameLowerCase, settings.mRecast))
.first; .first;
it->second->mTileCachedRecastMeshManager.setWorldspace(cell.mCellId.mWorldspace, nullptr); it->second->mTileCachedRecastMeshManager.setWorldspace(cellNameLowerCase, nullptr);
} }
return *it->second; return *it->second;
}(); }();

View file

@ -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,8 @@ 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();

View file

@ -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_view infoIdString = info.mId.getRefIdString();
info.mId = ESM::RefId::stringRefId(infoIdString.substr(infoIdString.find_last_of('#') + 1));
info.mPrev.clear(); info.mPrev = ESM::RefId::sEmpty;
if (iter != range.first) if (iter != range.first)
{ {
CSMWorld::InfoCollection::RecordConstIterator prev = iter; CSMWorld::InfoCollection::RecordConstIterator prev = iter;
--prev; --prev;
std::string_view 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_view 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,13 @@ 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; const ESM::RefId& cellId
= record.get().mOriginalCell.empty() ? record.get().mCell : record.get().mOriginalCell;
std::deque<int>& indices = mState.getSubRecords()[Misc::StringUtils::lowerCase(cellId)]; std::deque<int>& indices = mState.getSubRecords()[cellId.getRefIdString()];
// collect moved references at the end of the container // collect moved references at the end of the container
bool interior = cellId.substr(0, 1) != "#"; bool interior = cellId.getRefIdString()[0] != '#';
std::ostringstream stream; std::ostringstream stream;
if (!interior) if (!interior)
{ {
@ -267,7 +270,8 @@ void CSMDoc::CollectionReferencesStage::perform(int stage, Messages& messages)
// An empty mOriginalCell is meant to indicate that it is the same as // 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 +316,13 @@ 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 != streamId))
&& refRecord.mCell != stream.str()))
{ {
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 +357,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()[0] != '#';
// 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 +391,8 @@ 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 +409,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 +447,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[0] == '#')
{ {
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;
} }

View file

@ -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();

View file

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

View file

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

View file

@ -61,6 +61,7 @@ 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);
} }
} }

View file

@ -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);
const 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);

View file

@ -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)
{ {

View file

@ -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();
} }
@ -124,12 +124,15 @@ 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.getRefIdString() + "' does not exist", "",
id, "Casting sound '" + effect.mCastSound + "' does not exist", "", CSMDoc::Message::Severity_Error); 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);
} }

View file

@ -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,

View file

@ -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());
} }

View file

@ -4,9 +4,9 @@
#include <string> #include <string>
#include <vector> #include <vector>
#include "../world/universalid.hpp"
#include "../doc/stage.hpp" #include "../doc/stage.hpp"
#include "../world/universalid.hpp"
#include <components/esm/refid.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

View file

@ -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[Misc::StringUtils::lowerCase(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); const 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();

View file

@ -519,10 +519,11 @@ 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.getRefIdString() + "' does not exist", "",
id, "Parent creature '" + creature.mOriginal + "' does not exist", "", CSMDoc::Message::Severity_Error); 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 +682,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 == "Player") // Happy now, scrawl?
mPlayerPresent = true; mPlayerPresent = true;
// Skip "Base" records (setting!) // Skip "Base" records (setting!)
@ -739,22 +740,26 @@ 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) == -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) == -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) == -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) == -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
} }
@ -763,7 +768,8 @@ void CSMTools::ReferenceableCheckStage::npcCheck(
else else
{ {
if (mBodyParts.searchId(npc.mHair) == -1) if (mBodyParts.searchId(npc.mHair) == -1)
messages.add(id, "Hair body part '" + npc.mHair + "' does not exist", "", CSMDoc::Message::Severity_Error); messages.add(id, "Hair body part '" + npc.mHair.getRefIdString() + "' does not exist", "",
CSMDoc::Message::Severity_Error);
/// \todo Check gender, race and other body part stuff validity for the specific NPC /// \todo Check gender, race and other body part stuff validity for the specific NPC
} }
@ -903,8 +909,9 @@ void CSMTools::ReferenceableCheckStage::inventoryListCheck(
{ {
for (size_t i = 0; i < itemList.size(); ++i) for (size_t i = 0; i < itemList.size(); ++i)
{ {
std::string itemName = itemList[i].mItem; const ESM::RefId& item = itemList[i].mItem;
CSMWorld::RefIdData::LocalIndex localIndex = mReferencables.searchId(itemName); const 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);
@ -1035,11 +1042,11 @@ void CSMTools::ReferenceableCheckStage::listCheck(
for (unsigned i = 0; i < someList.mList.size(); ++i) for (unsigned i = 0; i < someList.mList.size(); ++i)
{ {
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.getRefIdString() + "' does not exist", "",
someID, "Object '" + someList.mList[i].mId + "' does not exist", "", CSMDoc::Message::Severity_Error); 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);
} }
} }
@ -1051,7 +1058,7 @@ void CSMTools::ReferenceableCheckStage::scriptCheck(
if (!someTool.mScript.empty()) if (!someTool.mScript.empty())
{ {
if (mScripts.searchId(someTool.mScript) == -1) if (mScripts.searchId(someTool.mScript) == -1)
messages.add( messages.add(someID, "Script '" + someTool.mScript.getRefIdString() + "' does not exist", "",
someID, "Script '" + someTool.mScript + "' does not exist", "", CSMDoc::Message::Severity_Error); CSMDoc::Message::Severity_Error);
} }
} }

View file

@ -50,8 +50,8 @@ 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.getRefIdString() + "'", "",
id, "Instance of a non-existent object '" + cellRef.mRefID + "'", "", CSMDoc::Message::Severity_Error); 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,14 @@ 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.getRefIdString() + "' does not exist", "",
id, "Trapped soul object '" + cellRef.mSoul + "' does not exist", "", CSMDoc::Message::Severity_Error); CSMDoc::Message::Severity_Error);
if (cellRef.mFaction.empty()) if (cellRef.mFaction.empty())
{ {
@ -80,14 +81,15 @@ 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);
} }
if (!cellRef.mDestCell.empty() && mCells.searchId(cellRef.mDestCell) == -1) if (!cellRef.mDestCell.empty() && mCells.searchId(cellRef.mDestCell) == -1)
messages.add( messages.add(id, "Destination cell '" + cellRef.mDestCell.getRefIdString() + "' does not exist", "",
id, "Destination cell '" + cellRef.mDestCell + "' does not exist", "", CSMDoc::Message::Severity_Error); CSMDoc::Message::Severity_Error);
if (cellRef.mScale < 0) if (cellRef.mScale < 0)
messages.add(id, "Negative scale", "", CSMDoc::Message::Severity_Error); messages.add(id, "Negative scale", "", CSMDoc::Message::Severity_Error);

View file

@ -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);
} }

View file

@ -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());

View file

@ -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;

View file

@ -49,12 +49,13 @@ void CSMTools::SoundGenCheckStage::perform(int stage, CSMDoc::Messages& messages
CSMWorld::RefIdData::LocalIndex creatureIndex = mObjects.getDataSet().searchId(soundGen.mCreature); CSMWorld::RefIdData::LocalIndex creatureIndex = mObjects.getDataSet().searchId(soundGen.mCreature);
if (creatureIndex.first == -1) if (creatureIndex.first == -1)
{ {
messages.add( messages.add(id, "Creature '" + soundGen.mCreature.getRefIdString() + "' doesn't exist", "",
id, "Creature '" + soundGen.mCreature + "' doesn't exist", "", CSMDoc::Message::Severity_Error); 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 +65,7 @@ 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);
} }
} }

View file

@ -35,12 +35,13 @@ 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; const 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()

View file

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

View file

@ -75,7 +75,7 @@ int CSMTools::TopicInfoCheckStage::setup()
if (regionRecord.isDeleted()) if (regionRecord.isDeleted())
continue; continue;
mCellNames.insert(regionRecord.get().mName); mCellNames.insert(ESM::RefId::stringRefId(regionRecord.get().mName));
} }
// Default cell name // Default cell name
int index = mGameSettings.searchId("sDefaultCellname"); int index = mGameSettings.searchId("sDefaultCellname");
@ -85,7 +85,7 @@ int CSMTools::TopicInfoCheckStage::setup()
if (!gmstRecord.isDeleted() && gmstRecord.get().mValue.getType() == ESM::VT_String) if (!gmstRecord.isDeleted() && gmstRecord.get().mValue.getType() == ESM::VT_String)
{ {
mCellNames.insert(gmstRecord.get().mValue.getString()); mCellNames.insert(ESM::RefId::stringRefId(gmstRecord.get().mValue.getString()));
} }
} }
@ -181,18 +181,20 @@ void CSMTools::TopicInfoCheckStage::perform(int stage, CSMDoc::Messages& message
// Verification functions // 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)
{ {
const 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 +211,11 @@ 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()) if (mCellNames.find(cell) == mCellNames.end())
{ {
messages.add(id, "Cell '" + cell + "' does not exist", "", CSMDoc::Message::Severity_Error); messages.add(id, "Cell '" + cell.getRefIdString() + "' does not exist", "", CSMDoc::Message::Severity_Error);
return false; 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)
{ {
const 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,22 @@ 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;
} }

View file

@ -72,22 +72,22 @@ namespace CSMTools
const CSMWorld::RefIdData& mReferencables; const CSMWorld::RefIdData& mReferencables;
const CSMWorld::Resources& mSoundFiles; const CSMWorld::Resources& mSoundFiles;
std::set<std::string> mCellNames; std::set<ESM::RefId> mCellNames;
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);
}; };
} }

View file

@ -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,8 @@ 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 +534,7 @@ namespace CSMWorld
} }
} }
void ActorAdapter::setupNpc(const std::string& id, ActorDataPtr data) void ActorAdapter::setupNpc(const ESM::RefId& id, ActorDataPtr data)
{ {
// Common setup, record is known to exist and is not deleted // Common setup, record is known to exist and is not deleted
int index = mReferenceables.searchId(id); int index = mReferenceables.searchId(id);
@ -551,12 +552,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 +579,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 +591,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 +638,7 @@ namespace CSMWorld
} }
} }
void ActorAdapter::setupCreature(const std::string& id, ActorDataPtr data) void ActorAdapter::setupCreature(const ESM::RefId& id, ActorDataPtr data)
{ {
// Record is known to exist and is not deleted // Record is known to exist and is not deleted
int index = mReferenceables.searchId(id); int index = mReferenceables.searchId(id);
@ -646,7 +647,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)
{ {

View file

@ -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
}; };
} }

View file

@ -11,6 +11,6 @@ void CSMWorld::Cell::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());
} }
} }

View file

@ -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);
}; };

View file

@ -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(Misc::StringUtils::lowerCase(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,19 @@ 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(Misc::StringUtils::lowerCase(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 +514,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 +534,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 +555,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 = Misc::StringUtils::lowerCase(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 +571,13 @@ 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()) != IdAccessorT().getId(record->get()))
!= Misc::StringUtils::lowerCase(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);

View file

@ -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

View file

@ -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.
/// ///
@ -74,20 +83,19 @@ namespace CSMWorld
= 0; = 0;
///< 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 ESM::RefId& origin, const ESM::RefId& destination, const UniversalId::Type type)
const std::string& origin, const std::string& 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

View file

@ -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);
} }

View file

@ -9,6 +9,7 @@
#include <osg/Math> #include <osg/Math>
#include <apps/opencs/model/world/cell.hpp>
#include <components/esm/defs.hpp> #include <components/esm/defs.hpp>
#include <components/esm3/loadbody.hpp> #include <components/esm3/loadbody.hpp>
#include <components/esm3/loadinfo.hpp> #include <components/esm3/loadinfo.hpp>
@ -61,7 +62,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; }
@ -333,6 +334,31 @@ namespace CSMWorld
bool isEditable() const override { return true; } bool isEditable() const override { return true; }
}; };
template <>
struct NameColumn<CSMWorld::Cell> : public Column<CSMWorld::Cell>
{
NameColumn(ColumnBase::Display display = ColumnBase::Display_String)
: Column<CSMWorld::Cell>(Columns::ColumnId_Name, display)
{
}
QVariant get(const Record<CSMWorld::Cell>& record) const override
{
return QString::fromUtf8(record.get().mName.getRefIdString().c_str());
}
void set(Record<CSMWorld::Cell>& record, const QVariant& data) override
{
CSMWorld::Cell record2 = record.get();
record2.mName = ESM::RefId::stringRefId(data.toString().toUtf8().constData());
record.setModified(record2);
}
bool isEditable() const override { return true; }
};
template <typename ESXRecordT> template <typename ESXRecordT>
struct AttributesColumn : public Column<ESXRecordT> struct AttributesColumn : public Column<ESXRecordT>
{ {
@ -690,14 +716,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 +842,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 +871,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 +898,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 +925,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 +970,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 +995,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 +1020,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);
} }
@ -1121,14 +1147,14 @@ namespace CSMWorld
QVariant get(const Record<ESXRecordT>& record) const override QVariant get(const Record<ESXRecordT>& record) const override
{ {
return QString::fromUtf8(record.get().mDestCell.c_str()); return QString::fromUtf8(record.get().mDestCell.getRefIdString().c_str());
} }
void set(Record<ESXRecordT>& record, const QVariant& data) override void set(Record<ESXRecordT>& record, const QVariant& data) override
{ {
ESXRecordT record2 = record.get(); ESXRecordT record2 = record.get();
record2.mDestCell = data.toString().toUtf8().constData(); record2.mDestCell = ESM::RefId::stringRefId(data.toString().toUtf8().constData());
record.setModified(record2); record.setModified(record2);
} }
@ -1168,14 +1194,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 +1219,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 +1433,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 +1460,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 +1485,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 +1510,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 +1535,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 +1952,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 +1977,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 +2098,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,35 +2119,35 @@ 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* id = nullptr;
ESXRecordT record2 = record.get(); ESXRecordT record2 = record.get();
switch (this->mColumnId) switch (this->mColumnId)
{ {
case Columns::ColumnId_CastingObject: case Columns::ColumnId_CastingObject:
string = &record2.mCasting; id = &record2.mCasting;
break; break;
case Columns::ColumnId_HitObject: case Columns::ColumnId_HitObject:
string = &record2.mHit; id = &record2.mHit;
break; break;
case Columns::ColumnId_AreaObject: case Columns::ColumnId_AreaObject:
string = &record2.mArea; id = &record2.mArea;
break; break;
case Columns::ColumnId_BoltObject: case Columns::ColumnId_BoltObject:
string = &record2.mBolt; id = &record2.mBolt;
break; break;
} }
if (!string) if (!id)
throw std::logic_error("Unsupported column ID"); throw std::logic_error("Unsupported column ID");
*string = data.toString().toUtf8().constData(); *id = ESM::RefId::stringRefId(data.toString().toUtf8().constData());
record.setModified(record2); record.setModified(record2);
} }
@ -2141,56 +2167,56 @@ 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* id = nullptr;
switch (this->mColumnId) switch (this->mColumnId)
{ {
case Columns::ColumnId_CastingSound: case Columns::ColumnId_CastingSound:
string = &record.get().mCastSound; id = &record.get().mCastSound;
break; break;
case Columns::ColumnId_HitSound: case Columns::ColumnId_HitSound:
string = &record.get().mHitSound; id = &record.get().mHitSound;
break; break;
case Columns::ColumnId_AreaSound: case Columns::ColumnId_AreaSound:
string = &record.get().mAreaSound; id = &record.get().mAreaSound;
break; break;
case Columns::ColumnId_BoltSound: case Columns::ColumnId_BoltSound:
string = &record.get().mBoltSound; id = &record.get().mBoltSound;
break; break;
} }
if (!string) if (!id)
throw std::logic_error("Unsupported column ID"); throw std::logic_error("Unsupported column ID");
return QString::fromUtf8(string->c_str()); return QString::fromUtf8(id->getRefIdString().c_str());
} }
void set(Record<ESXRecordT>& record, const QVariant& data) override void set(Record<ESXRecordT>& record, const QVariant& data) override
{ {
std::string* string = nullptr; ESM::RefId* id = nullptr;
ESXRecordT record2 = record.get(); ESXRecordT record2 = record.get();
switch (this->mColumnId) switch (this->mColumnId)
{ {
case Columns::ColumnId_CastingSound: case Columns::ColumnId_CastingSound:
string = &record2.mCastSound; id = &record2.mCastSound;
break; break;
case Columns::ColumnId_HitSound: case Columns::ColumnId_HitSound:
string = &record2.mHitSound; id = &record2.mHitSound;
break; break;
case Columns::ColumnId_AreaSound: case Columns::ColumnId_AreaSound:
string = &record2.mAreaSound; id = &record2.mAreaSound;
break; break;
case Columns::ColumnId_BoltSound: case Columns::ColumnId_BoltSound:
string = &record2.mBoltSound; id = &record2.mBoltSound;
break; break;
} }
if (!string) if (!id)
throw std::logic_error("Unsupported column ID"); throw std::logic_error("Unsupported column ID");
*string = data.toString().toUtf8().constData(); *id = ESM::RefId::stringRefId(data.toString().toUtf8().constData());
record.setModified(record2); record.setModified(record2);
} }

View file

@ -290,11 +290,11 @@ void CSMWorld::CommandDispatcher::executeExtendedDelete()
if (record.mState == RecordBase::State_Deleted) if (record.mState == RecordBase::State_Deleted)
continue; continue;
if (!std::binary_search( if (!std::binary_search(mSelection.begin(), mSelection.end(),
mSelection.begin(), mSelection.end(), Misc::StringUtils::lowerCase(record.get().mCell))) Misc::StringUtils::lowerCase(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()));
} }
} }
} }
@ -321,11 +321,11 @@ 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(),
mSelection.begin(), mSelection.end(), Misc::StringUtils::lowerCase(record.get().mCell))) Misc::StringUtils::lowerCase(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()));
} }
} }
} }

View file

@ -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)

View file

@ -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,8 @@ 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)); const 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 +1242,7 @@ bool CSMWorld::Data::continueLoading(CSMDoc::Messages& messages)
case ESM::REC_DIAL: case ESM::REC_DIAL:
{ {
ESM::Dialogue record; ESM::Dialogue record;
const std::string& recordIdString = record.mId.getRefIdString();
bool isDeleted = false; bool isDeleted = false;
record.load(*mReader, isDeleted); record.load(*mReader, isDeleted);
@ -1250,18 +1252,18 @@ bool CSMWorld::Data::continueLoading(CSMDoc::Messages& messages)
// record vector can be shuffled around which would make pointer to record invalid // 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 +1362,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);

View file

@ -33,6 +33,7 @@
#include <components/esm3/loadspel.hpp> #include <components/esm3/loadspel.hpp>
#include <components/esm3/loadsscr.hpp> #include <components/esm3/loadsscr.hpp>
#include <components/files/multidircollection.hpp> #include <components/files/multidircollection.hpp>
#include <components/misc/algorithm.hpp>
#include <components/to_utf8/to_utf8.hpp> #include <components/to_utf8/to_utf8.hpp>
#include "cell.hpp" #include "cell.hpp"
@ -122,7 +123,7 @@ namespace CSMWorld
const ESM::Dialogue* mDialogue; // last loaded dialogue const ESM::Dialogue* mDialogue; // last loaded dialogue
bool mBase; bool mBase;
bool mProject; bool mProject;
std::map<std::string, std::map<unsigned int, unsigned int>> mRefLoadCache; std::map<std::string, std::map<unsigned int, unsigned int>, Misc::StringUtils::CiComp> mRefLoadCache;
int mReaderIndex; int mReaderIndex;
bool mFsStrict; bool mFsStrict;
@ -140,7 +141,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 +306,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

View file

@ -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())

View file

@ -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)

View file

@ -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
@ -330,7 +333,7 @@ std::pair<CSMWorld::UniversalId, std::string> CSMWorld::IdTable::view(int row) c
return std::make_pair(UniversalId::Type_None, ""); return std::make_pair(UniversalId::Type_None, "");
if (id[0] == '#') if (id[0] == '#')
id = ESM::CellId::sDefaultWorldspace; id = ESM::CellId::sDefaultWorldspace.getRefIdString();
return std::make_pair(UniversalId(UniversalId::Type_Scene, id), hint); return std::make_pair(UniversalId(UniversalId::Type_Scene, id), hint);
} }
@ -367,7 +370,8 @@ CSMWorld::LandTextureIdTable::ImportResults CSMWorld::LandTextureIdTable::import
{ {
auto& record = static_cast<const Record<LandTexture>&>(idCollection()->getRecord(i)); 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 +408,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);

View file

@ -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.

View file

@ -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

View file

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

View file

@ -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; const std::string& topic = info.mTopicId.getRefIdString();
// 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);
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,7 +158,7 @@ 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);
} }
// 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
@ -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,8 @@ 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 +358,8 @@ 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 +368,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)

View file

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

View file

@ -1,6 +1,7 @@
#ifndef CSM_WOLRD_METADATA_H #ifndef CSM_WOLRD_METADATA_H
#define CSM_WOLRD_METADATA_H #define CSM_WOLRD_METADATA_H
#include <components/esm/refid.hpp>
#include <string> #include <string>
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;

View file

@ -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,8 @@ 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 +382,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 +433,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 +455,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());

View file

@ -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");

View file

@ -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());
} }
} }

View file

@ -3,6 +3,7 @@
#include <string> #include <string>
#include <components/esm/refid.hpp>
#include <components/esm3/loadpgrd.hpp> #include <components/esm3/loadpgrd.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);

View file

@ -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;

View file

@ -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,13 @@ 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 +119,8 @@ 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 +129,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 +150,8 @@ 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 +177,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 +210,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 +285,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 +313,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 +323,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 +339,7 @@ void CSMWorld::RefCollection::appendRecord(std::unique_ptr<RecordBase> record, U
void CSMWorld::RefCollection::insertRecord(std::unique_ptr<RecordBase> record, int index, UniversalId::Type type) 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

View file

@ -65,11 +65,12 @@ 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 ESM::RefId& origin, const ESM::RefId& destination, const UniversalId::Type type);
const std::string& origin, const std::string& 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);

View file

@ -1,7 +1,9 @@
#ifndef CSM_WOLRD_REFIDADAPTER_H #ifndef CSM_WOLRD_REFIDADAPTER_H
#define CSM_WOLRD_REFIDADAPTER_H #define CSM_WOLRD_REFIDADAPTER_H
#include <components/esm/refid.hpp>
#include <string> #include <string>
#include <vector>
/*! \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 +40,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()
}; };

View file

@ -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)

View file

@ -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());

View file

@ -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);
} }

View file

@ -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

View file

@ -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,7 @@ 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(iter->second->getId(i));
= mIndex.find(Misc::StringUtils::lowerCase(iter->second->getId(i)));
if (result != mIndex.end()) if (result != mIndex.end())
mIndex.erase(result); mIndex.erase(result);
@ -267,8 +264,7 @@ 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(iter->second->getId(recordIndex));
= mIndex.find(Misc::StringUtils::lowerCase(iter->second->getId(recordIndex)));
if (recordIndexFound != mIndex.end()) if (recordIndexFound != mIndex.end())
{ {
recordIndexFound->second.first -= count; recordIndexFound->second.first -= count;
@ -284,11 +280,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 +415,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 +424,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

View file

@ -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

View file

@ -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,34 +163,29 @@ void CSMWorld::RegionMap::removeCell(const CellCoordinates& index)
} }
} }
void CSMWorld::RegionMap::addRegion(const std::string& region, unsigned int colour) void CSMWorld::RegionMap::addRegion(const ESM::RefId& region, unsigned int colour)
{ {
mColours[Misc::StringUtils::lowerCase(region)] = colour; mColours[region] = colour;
} }
void CSMWorld::RegionMap::removeRegion(const std::string& region) void CSMWorld::RegionMap::removeRegion(const ESM::RefId& region)
{ {
std::map<std::string, unsigned int>::iterator iter(mColours.find(Misc::StringUtils::lowerCase(region))); auto iter(mColours.find(region));
if (iter != mColours.end()) 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 +332,7 @@ 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(cell->second.mRegion);
= mColours.find(Misc::StringUtils::lowerCase(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 +368,7 @@ 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(cell->second.mRegion);
= mColours.find(Misc::StringUtils::lowerCase(cell->second.mRegion));
if (iter != mColours.end()) if (iter != mColours.end())
stream << cell->second.mRegion; stream << cell->second.mRegion;
@ -396,7 +389,7 @@ QVariant CSMWorld::RegionMap::data(const QModelIndex& index, int role) const
std::map<CellCoordinates, CellDescription>::const_iterator cell = mMap.find(cellIndex); 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 +412,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 +430,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 +454,7 @@ void CSMWorld::RegionMap::regionsChanged(const QModelIndex& topLeft, const QMode
// Note: At this point an additional check could be inserted to see if there is any change to the // 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();

View file

@ -11,6 +11,7 @@
#include <QVariant> #include <QVariant>
#include "cellcoordinates.hpp" #include "cellcoordinates.hpp"
#include <components/esm/refid.hpp>
class QObject; class QObject;
@ -40,8 +41,8 @@ namespace CSMWorld
struct CellDescription struct CellDescription
{ {
bool mDeleted; bool mDeleted;
std::string mRegion; ESM::RefId mRegion;
std::string mName; ESM::RefId mName;
CellDescription(); CellDescription();
@ -52,7 +53,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 +75,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();

View file

@ -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()
@ -135,7 +131,7 @@ void CSMWorld::ScriptContext::clear()
bool CSMWorld::ScriptContext::clearLocals(const std::string& script) bool CSMWorld::ScriptContext::clearLocals(const std::string& script)
{ {
std::map<std::string, Compiler::Locals>::iterator iter = mLocals.find(Misc::StringUtils::lowerCase(script)); std::map<std::string, Compiler::Locals>::iterator iter = mLocals.find(script);
if (iter != mLocals.end()) if (iter != mLocals.end())
{ {

View file

@ -8,6 +8,7 @@
#include <components/compiler/context.hpp> #include <components/compiler/context.hpp>
#include <components/compiler/locals.hpp> #include <components/compiler/locals.hpp>
#include <components/misc/algorithm.hpp>
namespace CSMWorld namespace CSMWorld
{ {
@ -16,9 +17,9 @@ 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, Misc::StringUtils::CiComp> mLocals;
public: public:
ScriptContext(const Data& data); ScriptContext(const Data& data);
@ -29,13 +30,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();

View file

@ -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)

View file

@ -5,6 +5,7 @@
#include <vector> #include <vector>
#include <QMetaType> #include <QMetaType>
#include <components/esm/refid.hpp>
namespace CSMWorld namespace CSMWorld
{ {
@ -158,6 +159,8 @@ 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.

View file

@ -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)
{ {

View file

@ -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;

View file

@ -95,13 +95,13 @@ 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); const auto& cellId = collection.getRecord(i).get().mCell;
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); const 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 +176,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 +208,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,8 +268,8 @@ 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
references.data(references.index(i, cellColumn)).toString().toUtf8().constData()); = ESM::RefId::stringRefId(references.data(references.index(i, cellColumn)).toString().toUtf8().constData());
if (cell == mId) if (cell == mId)
{ {

View file

@ -11,6 +11,8 @@
#include "../../model/world/cellcoordinates.hpp" #include "../../model/world/cellcoordinates.hpp"
#include "instancedragmodes.hpp" #include "instancedragmodes.hpp"
#include <components/esm/refid.hpp>
#include <components/misc/algorithm.hpp>
class QModelIndex; class QModelIndex;
@ -44,9 +46,9 @@ 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*, Misc::StringUtils::CiComp> mObjects;
std::unique_ptr<Terrain::TerrainGrid> mTerrain; std::unique_ptr<Terrain::TerrainGrid> mTerrain;
CSMWorld::CellCoordinates mCoordinates; CSMWorld::CellCoordinates mCoordinates;
std::unique_ptr<CellArrow> mCellArrows[4]; std::unique_ptr<CellArrow> mCellArrows[4];

View file

@ -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);
} }
} }

View file

@ -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;
} }
@ -607,7 +607,8 @@ 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 +628,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 +735,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

View file

@ -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;

View file

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

View file

@ -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));
const 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,8 @@ 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 +460,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 +499,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 +683,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 +691,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));
} }

View file

@ -11,8 +11,8 @@
#include "../../model/world/cellcoordinates.hpp" #include "../../model/world/cellcoordinates.hpp"
#include "../../model/world/subcellcollection.hpp" #include "../../model/world/subcellcollection.hpp"
#include "tagbase.hpp" #include "tagbase.hpp"
#include <components/esm/refid.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;

View file

@ -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)
@ -338,8 +338,11 @@ 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()
= document.getData().getLand().getRecord(cellId).get().getLandData(ESM::Land::DATA_VHGT); .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];
} }

View file

@ -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)

View file

@ -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();

View file

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

View file

@ -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;

View file

@ -24,7 +24,11 @@ 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);

View file

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

View file

@ -3,13 +3,13 @@
#include <sstream> #include <sstream>
#include <utility> #include <utility>
#include <apps/opencs/model/prefs/category.hpp>
#include <apps/opencs/model/prefs/setting.hpp>
#include <apps/opencs/model/world/scriptcontext.hpp> #include <apps/opencs/model/world/scriptcontext.hpp>
#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/setting.hpp"
class QTextDocument; class QTextDocument;
@ -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;
} }

View file

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

View file

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

View file

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

View file

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

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