mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-02 04:45:34 +00:00
b6a2fd8fc1
There was additional logic to create topic infos index by topic id to make getTopicInfos and removeDialogueInfos functions faster. In practice it makes loading slower. Move infos index by topic to CSMWorld::Data and use only on loading.
1473 lines
60 KiB
C++
1473 lines
60 KiB
C++
#include "data.hpp"
|
|
|
|
#include <algorithm>
|
|
#include <stdexcept>
|
|
#include <type_traits>
|
|
#include <utility>
|
|
|
|
#include <QAbstractItemModel>
|
|
|
|
#include <apps/opencs/model/world/actoradapter.hpp>
|
|
#include <apps/opencs/model/world/cell.hpp>
|
|
#include <apps/opencs/model/world/collectionbase.hpp>
|
|
#include <apps/opencs/model/world/columnbase.hpp>
|
|
#include <apps/opencs/model/world/idcollection.hpp>
|
|
#include <apps/opencs/model/world/idtablebase.hpp>
|
|
#include <apps/opencs/model/world/info.hpp>
|
|
#include <apps/opencs/model/world/infocollection.hpp>
|
|
#include <apps/opencs/model/world/land.hpp>
|
|
#include <apps/opencs/model/world/landtexture.hpp>
|
|
#include <apps/opencs/model/world/metadata.hpp>
|
|
#include <apps/opencs/model/world/nestedidcollection.hpp>
|
|
#include <apps/opencs/model/world/nestedinfocollection.hpp>
|
|
#include <apps/opencs/model/world/pathgrid.hpp>
|
|
#include <apps/opencs/model/world/ref.hpp>
|
|
#include <apps/opencs/model/world/refcollection.hpp>
|
|
#include <apps/opencs/model/world/refidcollection.hpp>
|
|
#include <apps/opencs/model/world/subcellcollection.hpp>
|
|
#include <apps/opencs/model/world/universalid.hpp>
|
|
|
|
#include <components/esm/defs.hpp>
|
|
#include <components/esm/esmcommon.hpp>
|
|
#include <components/esm3/cellref.hpp>
|
|
#include <components/esm3/esmreader.hpp>
|
|
#include <components/esm3/loadcell.hpp>
|
|
#include <components/esm3/loaddoor.hpp>
|
|
#include <components/esm3/loadglob.hpp>
|
|
#include <components/esm3/loadstat.hpp>
|
|
#include <components/files/collections.hpp>
|
|
#include <components/misc/strings/lower.hpp>
|
|
#include <components/resource/resourcesystem.hpp>
|
|
#include <components/resource/scenemanager.hpp>
|
|
#include <components/sceneutil/shadow.hpp>
|
|
#include <components/shader/shadermanager.hpp>
|
|
#include <components/vfs/manager.hpp>
|
|
#include <components/vfs/registerarchives.hpp>
|
|
|
|
#include "../doc/messages.hpp"
|
|
|
|
#include "columnimp.hpp"
|
|
#include "columns.hpp"
|
|
#include "idtable.hpp"
|
|
#include "idtree.hpp"
|
|
#include "nestedcoladapterimp.hpp"
|
|
#include "regionmap.hpp"
|
|
#include "resourcesmanager.hpp"
|
|
#include "resourcetable.hpp"
|
|
|
|
namespace
|
|
{
|
|
void removeDialogueInfos(const ESM::RefId& dialogueId, const CSMWorld::InfosByTopic& infosByTopic,
|
|
CSMWorld::InfoCollection& infoCollection)
|
|
{
|
|
const auto topicInfos = infosByTopic.find(dialogueId);
|
|
|
|
if (topicInfos == infosByTopic.end())
|
|
return;
|
|
|
|
std::vector<int> erasedRecords;
|
|
|
|
for (const ESM::RefId& id : topicInfos->second)
|
|
{
|
|
const CSMWorld::Record<CSMWorld::Info>& record = infoCollection.getRecord(id);
|
|
|
|
if (record.mState == CSMWorld::RecordBase::State_ModifiedOnly)
|
|
{
|
|
erasedRecords.push_back(infoCollection.searchId(record.get().mId));
|
|
continue;
|
|
}
|
|
|
|
auto deletedRecord = std::make_unique<CSMWorld::Record<CSMWorld::Info>>(record);
|
|
deletedRecord->mState = CSMWorld::RecordBase::State_Deleted;
|
|
infoCollection.setRecord(infoCollection.searchId(record.get().mId), std::move(deletedRecord));
|
|
}
|
|
|
|
while (!erasedRecords.empty())
|
|
{
|
|
infoCollection.removeRows(erasedRecords.back(), 1);
|
|
erasedRecords.pop_back();
|
|
}
|
|
}
|
|
}
|
|
|
|
void CSMWorld::Data::addModel(QAbstractItemModel* model, UniversalId::Type type, bool update)
|
|
{
|
|
mModels.push_back(model);
|
|
mModelIndex.insert(std::make_pair(type, model));
|
|
|
|
UniversalId::Type type2 = UniversalId::getParentType(type);
|
|
|
|
if (type2 != UniversalId::Type_None)
|
|
mModelIndex.insert(std::make_pair(type2, model));
|
|
|
|
if (update)
|
|
{
|
|
connect(model, &QAbstractItemModel::dataChanged, this, &Data::dataChanged);
|
|
connect(model, &QAbstractItemModel::rowsInserted, this, &Data::rowsChanged);
|
|
connect(model, &QAbstractItemModel::rowsRemoved, this, &Data::rowsChanged);
|
|
}
|
|
}
|
|
|
|
void CSMWorld::Data::appendIds(std::vector<ESM::RefId>& ids, const CollectionBase& collection, bool listDeleted)
|
|
{
|
|
std::vector<ESM::RefId> ids2 = collection.getIds(listDeleted);
|
|
|
|
ids.insert(ids.end(), ids2.begin(), ids2.end());
|
|
}
|
|
|
|
int CSMWorld::Data::count(RecordBase::State state, const CollectionBase& collection)
|
|
{
|
|
int number = 0;
|
|
|
|
for (int i = 0; i < collection.getSize(); ++i)
|
|
if (collection.getRecord(i).mState == state)
|
|
++number;
|
|
|
|
return number;
|
|
}
|
|
|
|
CSMWorld::Data::Data(ToUTF8::FromType encoding, bool fsStrict, const Files::PathContainer& dataPaths,
|
|
const std::vector<std::string>& archives, const std::filesystem::path& resDir)
|
|
: mEncoder(encoding)
|
|
, mPathgrids(mCells)
|
|
, mRefs(mCells)
|
|
, mReader(nullptr)
|
|
, mDialogue(nullptr)
|
|
, mReaderIndex(1)
|
|
, mFsStrict(fsStrict)
|
|
, mDataPaths(dataPaths)
|
|
, mArchives(archives)
|
|
{
|
|
mVFS = std::make_unique<VFS::Manager>(mFsStrict);
|
|
VFS::registerArchives(mVFS.get(), Files::Collections(mDataPaths, !mFsStrict), mArchives, true);
|
|
|
|
mResourcesManager.setVFS(mVFS.get());
|
|
mResourceSystem = std::make_unique<Resource::ResourceSystem>(mVFS.get());
|
|
|
|
Shader::ShaderManager::DefineMap defines
|
|
= mResourceSystem->getSceneManager()->getShaderManager().getGlobalDefines();
|
|
Shader::ShaderManager::DefineMap shadowDefines = SceneUtil::ShadowManager::getShadowsDisabledDefines();
|
|
defines["forcePPL"] = "0"; // Don't force per-pixel lighting
|
|
defines["clamp"] = "1"; // Clamp lighting
|
|
defines["preLightEnv"] = "0"; // Apply environment maps after lighting like Morrowind
|
|
defines["radialFog"] = "0";
|
|
defines["lightingModel"] = "0";
|
|
defines["reverseZ"] = "0";
|
|
defines["refraction_enabled"] = "0";
|
|
for (const auto& define : shadowDefines)
|
|
defines[define.first] = define.second;
|
|
mResourceSystem->getSceneManager()->getShaderManager().setGlobalDefines(defines);
|
|
|
|
mResourceSystem->getSceneManager()->setShaderPath(resDir / "shaders");
|
|
|
|
int index = 0;
|
|
|
|
mGlobals.addColumn(new StringIdColumn<ESM::Global>);
|
|
mGlobals.addColumn(new RecordStateColumn<ESM::Global>);
|
|
mGlobals.addColumn(new FixedRecordTypeColumn<ESM::Global>(UniversalId::Type_Global));
|
|
mGlobals.addColumn(new VarTypeColumn<ESM::Global>(ColumnBase::Display_GlobalVarType));
|
|
mGlobals.addColumn(new VarValueColumn<ESM::Global>);
|
|
|
|
mGmsts.addColumn(new StringIdColumn<ESM::GameSetting>);
|
|
mGmsts.addColumn(new RecordStateColumn<ESM::GameSetting>);
|
|
mGmsts.addColumn(new FixedRecordTypeColumn<ESM::GameSetting>(UniversalId::Type_Gmst));
|
|
mGmsts.addColumn(new VarTypeColumn<ESM::GameSetting>(ColumnBase::Display_GmstVarType));
|
|
mGmsts.addColumn(new VarValueColumn<ESM::GameSetting>);
|
|
|
|
mSkills.addColumn(new StringIdColumn<ESM::Skill>);
|
|
mSkills.addColumn(new RecordStateColumn<ESM::Skill>);
|
|
mSkills.addColumn(new FixedRecordTypeColumn<ESM::Skill>(UniversalId::Type_Skill));
|
|
mSkills.addColumn(new AttributeColumn<ESM::Skill>);
|
|
mSkills.addColumn(new SpecialisationColumn<ESM::Skill>);
|
|
for (int i = 0; i < 4; ++i)
|
|
mSkills.addColumn(new UseValueColumn<ESM::Skill>(i));
|
|
mSkills.addColumn(new DescriptionColumn<ESM::Skill>);
|
|
|
|
mClasses.addColumn(new StringIdColumn<ESM::Class>);
|
|
mClasses.addColumn(new RecordStateColumn<ESM::Class>);
|
|
mClasses.addColumn(new FixedRecordTypeColumn<ESM::Class>(UniversalId::Type_Class));
|
|
mClasses.addColumn(new NameColumn<ESM::Class>);
|
|
mClasses.addColumn(new AttributesColumn<ESM::Class>(0));
|
|
mClasses.addColumn(new AttributesColumn<ESM::Class>(1));
|
|
mClasses.addColumn(new SpecialisationColumn<ESM::Class>);
|
|
for (int i = 0; i < 5; ++i)
|
|
mClasses.addColumn(new SkillsColumn<ESM::Class>(i, true, true));
|
|
for (int i = 0; i < 5; ++i)
|
|
mClasses.addColumn(new SkillsColumn<ESM::Class>(i, true, false));
|
|
mClasses.addColumn(new PlayableColumn<ESM::Class>);
|
|
mClasses.addColumn(new DescriptionColumn<ESM::Class>);
|
|
|
|
mFactions.addColumn(new StringIdColumn<ESM::Faction>);
|
|
mFactions.addColumn(new RecordStateColumn<ESM::Faction>);
|
|
mFactions.addColumn(new FixedRecordTypeColumn<ESM::Faction>(UniversalId::Type_Faction));
|
|
mFactions.addColumn(new NameColumn<ESM::Faction>(ColumnBase::Display_String32));
|
|
mFactions.addColumn(new AttributesColumn<ESM::Faction>(0));
|
|
mFactions.addColumn(new AttributesColumn<ESM::Faction>(1));
|
|
mFactions.addColumn(new HiddenColumn<ESM::Faction>);
|
|
for (int i = 0; i < 7; ++i)
|
|
mFactions.addColumn(new SkillsColumn<ESM::Faction>(i));
|
|
// Faction Reactions
|
|
mFactions.addColumn(new NestedParentColumn<ESM::Faction>(Columns::ColumnId_FactionReactions));
|
|
index = mFactions.getColumns() - 1;
|
|
mFactions.addAdapter(std::make_pair(&mFactions.getColumn(index), new FactionReactionsAdapter()));
|
|
mFactions.getNestableColumn(index)->addColumn(
|
|
new NestedChildColumn(Columns::ColumnId_Faction, ColumnBase::Display_Faction));
|
|
mFactions.getNestableColumn(index)->addColumn(
|
|
new NestedChildColumn(Columns::ColumnId_FactionReaction, ColumnBase::Display_Integer));
|
|
|
|
// Faction Ranks
|
|
mFactions.addColumn(new NestedParentColumn<ESM::Faction>(Columns::ColumnId_FactionRanks));
|
|
index = mFactions.getColumns() - 1;
|
|
mFactions.addAdapter(std::make_pair(&mFactions.getColumn(index), new FactionRanksAdapter()));
|
|
mFactions.getNestableColumn(index)->addColumn(
|
|
new NestedChildColumn(Columns::ColumnId_RankName, ColumnBase::Display_Rank));
|
|
mFactions.getNestableColumn(index)->addColumn(
|
|
new NestedChildColumn(Columns::ColumnId_FactionAttrib1, ColumnBase::Display_Integer));
|
|
mFactions.getNestableColumn(index)->addColumn(
|
|
new NestedChildColumn(Columns::ColumnId_FactionAttrib2, ColumnBase::Display_Integer));
|
|
mFactions.getNestableColumn(index)->addColumn(
|
|
new NestedChildColumn(Columns::ColumnId_FactionPrimSkill, ColumnBase::Display_Integer));
|
|
mFactions.getNestableColumn(index)->addColumn(
|
|
new NestedChildColumn(Columns::ColumnId_FactionFavSkill, ColumnBase::Display_Integer));
|
|
mFactions.getNestableColumn(index)->addColumn(
|
|
new NestedChildColumn(Columns::ColumnId_FactionRep, ColumnBase::Display_Integer));
|
|
|
|
mRaces.addColumn(new StringIdColumn<ESM::Race>);
|
|
mRaces.addColumn(new RecordStateColumn<ESM::Race>);
|
|
mRaces.addColumn(new FixedRecordTypeColumn<ESM::Race>(UniversalId::Type_Race));
|
|
mRaces.addColumn(new NameColumn<ESM::Race>);
|
|
mRaces.addColumn(new DescriptionColumn<ESM::Race>);
|
|
mRaces.addColumn(new FlagColumn<ESM::Race>(Columns::ColumnId_Playable, 0x1));
|
|
mRaces.addColumn(new FlagColumn<ESM::Race>(Columns::ColumnId_BeastRace, 0x2));
|
|
mRaces.addColumn(new WeightHeightColumn<ESM::Race>(true, true));
|
|
mRaces.addColumn(new WeightHeightColumn<ESM::Race>(true, false));
|
|
mRaces.addColumn(new WeightHeightColumn<ESM::Race>(false, true));
|
|
mRaces.addColumn(new WeightHeightColumn<ESM::Race>(false, false));
|
|
// Race spells
|
|
mRaces.addColumn(new NestedParentColumn<ESM::Race>(Columns::ColumnId_PowerList));
|
|
index = mRaces.getColumns() - 1;
|
|
mRaces.addAdapter(std::make_pair(&mRaces.getColumn(index), new SpellListAdapter<ESM::Race>()));
|
|
mRaces.getNestableColumn(index)->addColumn(
|
|
new NestedChildColumn(Columns::ColumnId_SpellId, ColumnBase::Display_Spell));
|
|
// Race attributes
|
|
mRaces.addColumn(new NestedParentColumn<ESM::Race>(
|
|
Columns::ColumnId_RaceAttributes, ColumnBase::Flag_Dialogue, true)); // fixed rows table
|
|
index = mRaces.getColumns() - 1;
|
|
mRaces.addAdapter(std::make_pair(&mRaces.getColumn(index), new RaceAttributeAdapter()));
|
|
mRaces.getNestableColumn(index)->addColumn(new NestedChildColumn(
|
|
Columns::ColumnId_Attribute, ColumnBase::Display_Attribute, ColumnBase::Flag_Dialogue, false));
|
|
mRaces.getNestableColumn(index)->addColumn(
|
|
new NestedChildColumn(Columns::ColumnId_Male, ColumnBase::Display_Integer));
|
|
mRaces.getNestableColumn(index)->addColumn(
|
|
new NestedChildColumn(Columns::ColumnId_Female, ColumnBase::Display_Integer));
|
|
// Race skill bonus
|
|
mRaces.addColumn(new NestedParentColumn<ESM::Race>(
|
|
Columns::ColumnId_RaceSkillBonus, ColumnBase::Flag_Dialogue, true)); // fixed rows table
|
|
index = mRaces.getColumns() - 1;
|
|
mRaces.addAdapter(std::make_pair(&mRaces.getColumn(index), new RaceSkillsBonusAdapter()));
|
|
mRaces.getNestableColumn(index)->addColumn(
|
|
new NestedChildColumn(Columns::ColumnId_Skill, ColumnBase::Display_SkillId));
|
|
mRaces.getNestableColumn(index)->addColumn(
|
|
new NestedChildColumn(Columns::ColumnId_RaceBonus, ColumnBase::Display_Integer));
|
|
|
|
mSounds.addColumn(new StringIdColumn<ESM::Sound>);
|
|
mSounds.addColumn(new RecordStateColumn<ESM::Sound>);
|
|
mSounds.addColumn(new FixedRecordTypeColumn<ESM::Sound>(UniversalId::Type_Sound));
|
|
mSounds.addColumn(new SoundParamColumn<ESM::Sound>(SoundParamColumn<ESM::Sound>::Type_Volume));
|
|
mSounds.addColumn(new SoundParamColumn<ESM::Sound>(SoundParamColumn<ESM::Sound>::Type_MinRange));
|
|
mSounds.addColumn(new SoundParamColumn<ESM::Sound>(SoundParamColumn<ESM::Sound>::Type_MaxRange));
|
|
mSounds.addColumn(new SoundFileColumn<ESM::Sound>);
|
|
|
|
mScripts.addColumn(new StringIdColumn<ESM::Script>);
|
|
mScripts.addColumn(new RecordStateColumn<ESM::Script>);
|
|
mScripts.addColumn(new FixedRecordTypeColumn<ESM::Script>(UniversalId::Type_Script));
|
|
mScripts.addColumn(new ScriptColumn<ESM::Script>(ScriptColumn<ESM::Script>::Type_File));
|
|
|
|
mRegions.addColumn(new StringIdColumn<ESM::Region>);
|
|
mRegions.addColumn(new RecordStateColumn<ESM::Region>);
|
|
mRegions.addColumn(new FixedRecordTypeColumn<ESM::Region>(UniversalId::Type_Region));
|
|
mRegions.addColumn(new NameColumn<ESM::Region>);
|
|
mRegions.addColumn(new MapColourColumn<ESM::Region>);
|
|
mRegions.addColumn(new SleepListColumn<ESM::Region>);
|
|
// Region Weather
|
|
mRegions.addColumn(new NestedParentColumn<ESM::Region>(Columns::ColumnId_RegionWeather));
|
|
index = mRegions.getColumns() - 1;
|
|
mRegions.addAdapter(std::make_pair(&mRegions.getColumn(index), new RegionWeatherAdapter()));
|
|
mRegions.getNestableColumn(index)->addColumn(
|
|
new NestedChildColumn(Columns::ColumnId_WeatherName, ColumnBase::Display_String, false));
|
|
mRegions.getNestableColumn(index)->addColumn(
|
|
new NestedChildColumn(Columns::ColumnId_WeatherChance, ColumnBase::Display_UnsignedInteger8));
|
|
// Region Sounds
|
|
mRegions.addColumn(new NestedParentColumn<ESM::Region>(Columns::ColumnId_RegionSounds));
|
|
index = mRegions.getColumns() - 1;
|
|
mRegions.addAdapter(std::make_pair(&mRegions.getColumn(index), new RegionSoundListAdapter()));
|
|
mRegions.getNestableColumn(index)->addColumn(
|
|
new NestedChildColumn(Columns::ColumnId_SoundName, ColumnBase::Display_Sound));
|
|
mRegions.getNestableColumn(index)->addColumn(
|
|
new NestedChildColumn(Columns::ColumnId_SoundChance, ColumnBase::Display_UnsignedInteger8));
|
|
|
|
mBirthsigns.addColumn(new StringIdColumn<ESM::BirthSign>);
|
|
mBirthsigns.addColumn(new RecordStateColumn<ESM::BirthSign>);
|
|
mBirthsigns.addColumn(new FixedRecordTypeColumn<ESM::BirthSign>(UniversalId::Type_Birthsign));
|
|
mBirthsigns.addColumn(new NameColumn<ESM::BirthSign>);
|
|
mBirthsigns.addColumn(new TextureColumn<ESM::BirthSign>);
|
|
mBirthsigns.addColumn(new DescriptionColumn<ESM::BirthSign>);
|
|
// Birthsign spells
|
|
mBirthsigns.addColumn(new NestedParentColumn<ESM::BirthSign>(Columns::ColumnId_PowerList));
|
|
index = mBirthsigns.getColumns() - 1;
|
|
mBirthsigns.addAdapter(std::make_pair(&mBirthsigns.getColumn(index), new SpellListAdapter<ESM::BirthSign>()));
|
|
mBirthsigns.getNestableColumn(index)->addColumn(
|
|
new NestedChildColumn(Columns::ColumnId_SpellId, ColumnBase::Display_Spell));
|
|
|
|
mSpells.addColumn(new StringIdColumn<ESM::Spell>);
|
|
mSpells.addColumn(new RecordStateColumn<ESM::Spell>);
|
|
mSpells.addColumn(new FixedRecordTypeColumn<ESM::Spell>(UniversalId::Type_Spell));
|
|
mSpells.addColumn(new NameColumn<ESM::Spell>);
|
|
mSpells.addColumn(new SpellTypeColumn<ESM::Spell>);
|
|
mSpells.addColumn(new CostColumn<ESM::Spell>);
|
|
mSpells.addColumn(new FlagColumn<ESM::Spell>(Columns::ColumnId_AutoCalc, 0x1));
|
|
mSpells.addColumn(new FlagColumn<ESM::Spell>(Columns::ColumnId_StarterSpell, 0x2));
|
|
mSpells.addColumn(new FlagColumn<ESM::Spell>(Columns::ColumnId_AlwaysSucceeds, 0x4));
|
|
// Spell effects
|
|
mSpells.addColumn(new NestedParentColumn<ESM::Spell>(Columns::ColumnId_EffectList));
|
|
index = mSpells.getColumns() - 1;
|
|
mSpells.addAdapter(std::make_pair(&mSpells.getColumn(index), new EffectsListAdapter<ESM::Spell>()));
|
|
mSpells.getNestableColumn(index)->addColumn(
|
|
new NestedChildColumn(Columns::ColumnId_EffectId, ColumnBase::Display_EffectId));
|
|
mSpells.getNestableColumn(index)->addColumn(
|
|
new NestedChildColumn(Columns::ColumnId_Skill, ColumnBase::Display_EffectSkill));
|
|
mSpells.getNestableColumn(index)->addColumn(
|
|
new NestedChildColumn(Columns::ColumnId_Attribute, ColumnBase::Display_EffectAttribute));
|
|
mSpells.getNestableColumn(index)->addColumn(
|
|
new NestedChildColumn(Columns::ColumnId_EffectRange, ColumnBase::Display_EffectRange));
|
|
mSpells.getNestableColumn(index)->addColumn(
|
|
new NestedChildColumn(Columns::ColumnId_EffectArea, ColumnBase::Display_String));
|
|
mSpells.getNestableColumn(index)->addColumn(
|
|
new NestedChildColumn(Columns::ColumnId_Duration, ColumnBase::Display_Integer)); // reuse from light
|
|
mSpells.getNestableColumn(index)->addColumn(
|
|
new NestedChildColumn(Columns::ColumnId_MinMagnitude, ColumnBase::Display_Integer));
|
|
mSpells.getNestableColumn(index)->addColumn(
|
|
new NestedChildColumn(Columns::ColumnId_MaxMagnitude, ColumnBase::Display_Integer));
|
|
|
|
mTopics.addColumn(new StringIdColumn<ESM::Dialogue>);
|
|
mTopics.addColumn(new RecordStateColumn<ESM::Dialogue>);
|
|
mTopics.addColumn(new FixedRecordTypeColumn<ESM::Dialogue>(UniversalId::Type_Topic));
|
|
mTopics.addColumn(new DialogueTypeColumn<ESM::Dialogue>);
|
|
|
|
mJournals.addColumn(new StringIdColumn<ESM::Dialogue>);
|
|
mJournals.addColumn(new RecordStateColumn<ESM::Dialogue>);
|
|
mJournals.addColumn(new FixedRecordTypeColumn<ESM::Dialogue>(UniversalId::Type_Journal));
|
|
mJournals.addColumn(new DialogueTypeColumn<ESM::Dialogue>(true));
|
|
|
|
mTopicInfos.addColumn(new StringIdColumn<Info>(true));
|
|
mTopicInfos.addColumn(new RecordStateColumn<Info>);
|
|
mTopicInfos.addColumn(new FixedRecordTypeColumn<Info>(UniversalId::Type_TopicInfo));
|
|
mTopicInfos.addColumn(new TopicColumn<Info>(false));
|
|
mTopicInfos.addColumn(new ResponseColumn<Info>);
|
|
mTopicInfos.addColumn(new ActorColumn<Info>);
|
|
mTopicInfos.addColumn(new RaceColumn<Info>);
|
|
mTopicInfos.addColumn(new ClassColumn<Info>);
|
|
mTopicInfos.addColumn(new FactionColumn<Info>);
|
|
mTopicInfos.addColumn(new CellColumn<Info>);
|
|
mTopicInfos.addColumn(new DispositionColumn<Info>);
|
|
mTopicInfos.addColumn(new RankColumn<Info>);
|
|
mTopicInfos.addColumn(new GenderColumn<Info>);
|
|
mTopicInfos.addColumn(new PcFactionColumn<Info>);
|
|
mTopicInfos.addColumn(new PcRankColumn<Info>);
|
|
mTopicInfos.addColumn(new SoundFileColumn<Info>);
|
|
// Result script
|
|
mTopicInfos.addColumn(new NestedParentColumn<Info>(
|
|
Columns::ColumnId_InfoList, ColumnBase::Flag_Dialogue | ColumnBase::Flag_Dialogue_List));
|
|
index = mTopicInfos.getColumns() - 1;
|
|
mTopicInfos.addAdapter(std::make_pair(&mTopicInfos.getColumn(index), new InfoListAdapter()));
|
|
mTopicInfos.getNestableColumn(index)->addColumn(
|
|
new NestedChildColumn(Columns::ColumnId_ScriptText, ColumnBase::Display_ScriptLines));
|
|
// Special conditions
|
|
mTopicInfos.addColumn(new NestedParentColumn<Info>(Columns::ColumnId_InfoCondition));
|
|
index = mTopicInfos.getColumns() - 1;
|
|
mTopicInfos.addAdapter(std::make_pair(&mTopicInfos.getColumn(index), new InfoConditionAdapter()));
|
|
mTopicInfos.getNestableColumn(index)->addColumn(
|
|
new NestedChildColumn(Columns::ColumnId_InfoCondFunc, ColumnBase::Display_InfoCondFunc));
|
|
// FIXME: don't have dynamic value enum delegate, use Display_String for now
|
|
mTopicInfos.getNestableColumn(index)->addColumn(
|
|
new NestedChildColumn(Columns::ColumnId_InfoCondVar, ColumnBase::Display_InfoCondVar));
|
|
mTopicInfos.getNestableColumn(index)->addColumn(
|
|
new NestedChildColumn(Columns::ColumnId_InfoCondComp, ColumnBase::Display_InfoCondComp));
|
|
mTopicInfos.getNestableColumn(index)->addColumn(
|
|
new NestedChildColumn(Columns::ColumnId_Value, ColumnBase::Display_Var));
|
|
|
|
mJournalInfos.addColumn(new StringIdColumn<Info>(true));
|
|
mJournalInfos.addColumn(new RecordStateColumn<Info>);
|
|
mJournalInfos.addColumn(new FixedRecordTypeColumn<Info>(UniversalId::Type_JournalInfo));
|
|
mJournalInfos.addColumn(new TopicColumn<Info>(true));
|
|
mJournalInfos.addColumn(new QuestStatusTypeColumn<Info>);
|
|
mJournalInfos.addColumn(new QuestIndexColumn<Info>);
|
|
mJournalInfos.addColumn(new QuestDescriptionColumn<Info>);
|
|
|
|
mCells.addColumn(new StringIdColumn<Cell>);
|
|
mCells.addColumn(new RecordStateColumn<Cell>);
|
|
mCells.addColumn(new FixedRecordTypeColumn<Cell>(UniversalId::Type_Cell));
|
|
mCells.addColumn(new NameColumn<Cell>(ColumnBase::Display_String64));
|
|
mCells.addColumn(new FlagColumn<Cell>(Columns::ColumnId_SleepForbidden, ESM::Cell::NoSleep));
|
|
mCells.addColumn(new FlagColumn<Cell>(Columns::ColumnId_InteriorWater, ESM::Cell::HasWater,
|
|
ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue | ColumnBase::Flag_Dialogue_Refresh));
|
|
mCells.addColumn(new FlagColumn<Cell>(Columns::ColumnId_InteriorSky, ESM::Cell::QuasiEx,
|
|
ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue | ColumnBase::Flag_Dialogue_Refresh));
|
|
mCells.addColumn(new RegionColumn<Cell>);
|
|
mCells.addColumn(new RefNumCounterColumn<Cell>);
|
|
// Misc Cell data
|
|
mCells.addColumn(new NestedParentColumn<Cell>(
|
|
Columns::ColumnId_Cell, ColumnBase::Flag_Dialogue | ColumnBase::Flag_Dialogue_List));
|
|
index = mCells.getColumns() - 1;
|
|
mCells.addAdapter(std::make_pair(&mCells.getColumn(index), new CellListAdapter()));
|
|
mCells.getNestableColumn(index)->addColumn(
|
|
new NestedChildColumn(Columns::ColumnId_Interior, ColumnBase::Display_Boolean,
|
|
ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue | ColumnBase::Flag_Dialogue_Refresh));
|
|
mCells.getNestableColumn(index)->addColumn(
|
|
new NestedChildColumn(Columns::ColumnId_Ambient, ColumnBase::Display_Colour));
|
|
mCells.getNestableColumn(index)->addColumn(
|
|
new NestedChildColumn(Columns::ColumnId_Sunlight, ColumnBase::Display_Colour));
|
|
mCells.getNestableColumn(index)->addColumn(
|
|
new NestedChildColumn(Columns::ColumnId_Fog, ColumnBase::Display_Colour));
|
|
mCells.getNestableColumn(index)->addColumn(
|
|
new NestedChildColumn(Columns::ColumnId_FogDensity, ColumnBase::Display_Float));
|
|
mCells.getNestableColumn(index)->addColumn(
|
|
new NestedChildColumn(Columns::ColumnId_WaterLevel, ColumnBase::Display_Float));
|
|
mCells.getNestableColumn(index)->addColumn(
|
|
new NestedChildColumn(Columns::ColumnId_MapColor, ColumnBase::Display_Colour));
|
|
|
|
mEnchantments.addColumn(new StringIdColumn<ESM::Enchantment>);
|
|
mEnchantments.addColumn(new RecordStateColumn<ESM::Enchantment>);
|
|
mEnchantments.addColumn(new FixedRecordTypeColumn<ESM::Enchantment>(UniversalId::Type_Enchantment));
|
|
mEnchantments.addColumn(new EnchantmentTypeColumn<ESM::Enchantment>);
|
|
mEnchantments.addColumn(new CostColumn<ESM::Enchantment>);
|
|
mEnchantments.addColumn(new ChargesColumn2<ESM::Enchantment>);
|
|
mEnchantments.addColumn(new FlagColumn<ESM::Enchantment>(Columns::ColumnId_AutoCalc, ESM::Enchantment::Autocalc));
|
|
// Enchantment effects
|
|
mEnchantments.addColumn(new NestedParentColumn<ESM::Enchantment>(Columns::ColumnId_EffectList));
|
|
index = mEnchantments.getColumns() - 1;
|
|
mEnchantments.addAdapter(
|
|
std::make_pair(&mEnchantments.getColumn(index), new EffectsListAdapter<ESM::Enchantment>()));
|
|
mEnchantments.getNestableColumn(index)->addColumn(
|
|
new NestedChildColumn(Columns::ColumnId_EffectId, ColumnBase::Display_EffectId));
|
|
mEnchantments.getNestableColumn(index)->addColumn(
|
|
new NestedChildColumn(Columns::ColumnId_Skill, ColumnBase::Display_EffectSkill));
|
|
mEnchantments.getNestableColumn(index)->addColumn(
|
|
new NestedChildColumn(Columns::ColumnId_Attribute, ColumnBase::Display_EffectAttribute));
|
|
mEnchantments.getNestableColumn(index)->addColumn(
|
|
new NestedChildColumn(Columns::ColumnId_EffectRange, ColumnBase::Display_EffectRange));
|
|
mEnchantments.getNestableColumn(index)->addColumn(
|
|
new NestedChildColumn(Columns::ColumnId_EffectArea, ColumnBase::Display_String));
|
|
mEnchantments.getNestableColumn(index)->addColumn(
|
|
new NestedChildColumn(Columns::ColumnId_Duration, ColumnBase::Display_Integer)); // reuse from light
|
|
mEnchantments.getNestableColumn(index)->addColumn(
|
|
new NestedChildColumn(Columns::ColumnId_MinMagnitude, ColumnBase::Display_Integer));
|
|
mEnchantments.getNestableColumn(index)->addColumn(
|
|
new NestedChildColumn(Columns::ColumnId_MaxMagnitude, ColumnBase::Display_Integer));
|
|
|
|
mBodyParts.addColumn(new StringIdColumn<ESM::BodyPart>);
|
|
mBodyParts.addColumn(new RecordStateColumn<ESM::BodyPart>);
|
|
mBodyParts.addColumn(new FixedRecordTypeColumn<ESM::BodyPart>(UniversalId::Type_BodyPart));
|
|
mBodyParts.addColumn(new BodyPartTypeColumn<ESM::BodyPart>);
|
|
mBodyParts.addColumn(new VampireColumn<ESM::BodyPart>);
|
|
mBodyParts.addColumn(new GenderNpcColumn<ESM::BodyPart>);
|
|
mBodyParts.addColumn(new FlagColumn<ESM::BodyPart>(Columns::ColumnId_Playable, ESM::BodyPart::BPF_NotPlayable,
|
|
ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue, true));
|
|
|
|
int meshTypeFlags = ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue | ColumnBase::Flag_Dialogue_Refresh;
|
|
MeshTypeColumn<ESM::BodyPart>* meshTypeColumn = new MeshTypeColumn<ESM::BodyPart>(meshTypeFlags);
|
|
mBodyParts.addColumn(meshTypeColumn);
|
|
mBodyParts.addColumn(new ModelColumn<ESM::BodyPart>);
|
|
mBodyParts.addColumn(new BodyPartRaceColumn(meshTypeColumn));
|
|
|
|
mSoundGens.addColumn(new StringIdColumn<ESM::SoundGenerator>);
|
|
mSoundGens.addColumn(new RecordStateColumn<ESM::SoundGenerator>);
|
|
mSoundGens.addColumn(new FixedRecordTypeColumn<ESM::SoundGenerator>(UniversalId::Type_SoundGen));
|
|
mSoundGens.addColumn(new CreatureColumn<ESM::SoundGenerator>);
|
|
mSoundGens.addColumn(new SoundColumn<ESM::SoundGenerator>);
|
|
mSoundGens.addColumn(new SoundGeneratorTypeColumn<ESM::SoundGenerator>);
|
|
|
|
mMagicEffects.addColumn(new StringIdColumn<ESM::MagicEffect>);
|
|
mMagicEffects.addColumn(new RecordStateColumn<ESM::MagicEffect>);
|
|
mMagicEffects.addColumn(new FixedRecordTypeColumn<ESM::MagicEffect>(UniversalId::Type_MagicEffect));
|
|
mMagicEffects.addColumn(new SchoolColumn<ESM::MagicEffect>);
|
|
mMagicEffects.addColumn(new BaseCostColumn<ESM::MagicEffect>);
|
|
mMagicEffects.addColumn(new EffectTextureColumn<ESM::MagicEffect>(Columns::ColumnId_Icon));
|
|
mMagicEffects.addColumn(new EffectTextureColumn<ESM::MagicEffect>(Columns::ColumnId_Particle));
|
|
mMagicEffects.addColumn(new EffectObjectColumn<ESM::MagicEffect>(Columns::ColumnId_CastingObject));
|
|
mMagicEffects.addColumn(new EffectObjectColumn<ESM::MagicEffect>(Columns::ColumnId_HitObject));
|
|
mMagicEffects.addColumn(new EffectObjectColumn<ESM::MagicEffect>(Columns::ColumnId_AreaObject));
|
|
mMagicEffects.addColumn(new EffectObjectColumn<ESM::MagicEffect>(Columns::ColumnId_BoltObject));
|
|
mMagicEffects.addColumn(new EffectSoundColumn<ESM::MagicEffect>(Columns::ColumnId_CastingSound));
|
|
mMagicEffects.addColumn(new EffectSoundColumn<ESM::MagicEffect>(Columns::ColumnId_HitSound));
|
|
mMagicEffects.addColumn(new EffectSoundColumn<ESM::MagicEffect>(Columns::ColumnId_AreaSound));
|
|
mMagicEffects.addColumn(new EffectSoundColumn<ESM::MagicEffect>(Columns::ColumnId_BoltSound));
|
|
mMagicEffects.addColumn(
|
|
new FlagColumn<ESM::MagicEffect>(Columns::ColumnId_AllowSpellmaking, ESM::MagicEffect::AllowSpellmaking));
|
|
mMagicEffects.addColumn(
|
|
new FlagColumn<ESM::MagicEffect>(Columns::ColumnId_AllowEnchanting, ESM::MagicEffect::AllowEnchanting));
|
|
mMagicEffects.addColumn(
|
|
new FlagColumn<ESM::MagicEffect>(Columns::ColumnId_NegativeLight, ESM::MagicEffect::NegativeLight));
|
|
mMagicEffects.addColumn(new DescriptionColumn<ESM::MagicEffect>);
|
|
|
|
mLand.addColumn(new StringIdColumn<Land>);
|
|
mLand.addColumn(new RecordStateColumn<Land>);
|
|
mLand.addColumn(new FixedRecordTypeColumn<Land>(UniversalId::Type_Land));
|
|
mLand.addColumn(new LandPluginIndexColumn);
|
|
mLand.addColumn(new LandNormalsColumn);
|
|
mLand.addColumn(new LandHeightsColumn);
|
|
mLand.addColumn(new LandColoursColumn);
|
|
mLand.addColumn(new LandTexturesColumn);
|
|
|
|
mLandTextures.addColumn(new StringIdColumn<LandTexture>(true));
|
|
mLandTextures.addColumn(new RecordStateColumn<LandTexture>);
|
|
mLandTextures.addColumn(new FixedRecordTypeColumn<LandTexture>(UniversalId::Type_LandTexture));
|
|
mLandTextures.addColumn(new LandTextureNicknameColumn);
|
|
mLandTextures.addColumn(new LandTexturePluginIndexColumn);
|
|
mLandTextures.addColumn(new LandTextureIndexColumn);
|
|
mLandTextures.addColumn(new TextureColumn<LandTexture>);
|
|
|
|
mPathgrids.addColumn(new StringIdColumn<Pathgrid>);
|
|
mPathgrids.addColumn(new RecordStateColumn<Pathgrid>);
|
|
mPathgrids.addColumn(new FixedRecordTypeColumn<Pathgrid>(UniversalId::Type_Pathgrid));
|
|
|
|
// new object deleted in dtor of Collection<T,A>
|
|
mPathgrids.addColumn(new NestedParentColumn<Pathgrid>(Columns::ColumnId_PathgridPoints));
|
|
index = mPathgrids.getColumns() - 1;
|
|
// new object deleted in dtor of NestedCollection<T,A>
|
|
mPathgrids.addAdapter(std::make_pair(&mPathgrids.getColumn(index), new PathgridPointListAdapter()));
|
|
// new objects deleted in dtor of NestableColumn
|
|
// WARNING: The order of the columns below are assumed in PathgridPointListAdapter
|
|
mPathgrids.getNestableColumn(index)->addColumn(new NestedChildColumn(
|
|
Columns::ColumnId_PathgridIndex, ColumnBase::Display_Integer, ColumnBase::Flag_Dialogue, false));
|
|
mPathgrids.getNestableColumn(index)->addColumn(
|
|
new NestedChildColumn(Columns::ColumnId_PathgridPosX, ColumnBase::Display_Integer));
|
|
mPathgrids.getNestableColumn(index)->addColumn(
|
|
new NestedChildColumn(Columns::ColumnId_PathgridPosY, ColumnBase::Display_Integer));
|
|
mPathgrids.getNestableColumn(index)->addColumn(
|
|
new NestedChildColumn(Columns::ColumnId_PathgridPosZ, ColumnBase::Display_Integer));
|
|
|
|
mPathgrids.addColumn(new NestedParentColumn<Pathgrid>(Columns::ColumnId_PathgridEdges));
|
|
index = mPathgrids.getColumns() - 1;
|
|
mPathgrids.addAdapter(std::make_pair(&mPathgrids.getColumn(index), new PathgridEdgeListAdapter()));
|
|
mPathgrids.getNestableColumn(index)->addColumn(new NestedChildColumn(
|
|
Columns::ColumnId_PathgridEdgeIndex, ColumnBase::Display_Integer, ColumnBase::Flag_Dialogue, false));
|
|
mPathgrids.getNestableColumn(index)->addColumn(
|
|
new NestedChildColumn(Columns::ColumnId_PathgridEdge0, ColumnBase::Display_Integer));
|
|
mPathgrids.getNestableColumn(index)->addColumn(
|
|
new NestedChildColumn(Columns::ColumnId_PathgridEdge1, ColumnBase::Display_Integer));
|
|
|
|
mStartScripts.addColumn(new StringIdColumn<ESM::StartScript>);
|
|
mStartScripts.addColumn(new RecordStateColumn<ESM::StartScript>);
|
|
mStartScripts.addColumn(new FixedRecordTypeColumn<ESM::StartScript>(UniversalId::Type_StartScript));
|
|
|
|
mRefs.addColumn(new StringIdColumn<CellRef>(true));
|
|
mRefs.addColumn(new RecordStateColumn<CellRef>);
|
|
mRefs.addColumn(new FixedRecordTypeColumn<CellRef>(UniversalId::Type_Reference));
|
|
mRefs.addColumn(new CellColumn<CellRef>(true));
|
|
mRefs.addColumn(new OriginalCellColumn<CellRef>);
|
|
mRefs.addColumn(new IdColumn<CellRef>);
|
|
mRefs.addColumn(new PosColumn<CellRef>(&CellRef::mPos, 0, false));
|
|
mRefs.addColumn(new PosColumn<CellRef>(&CellRef::mPos, 1, false));
|
|
mRefs.addColumn(new PosColumn<CellRef>(&CellRef::mPos, 2, false));
|
|
mRefs.addColumn(new RotColumn<CellRef>(&CellRef::mPos, 0, false));
|
|
mRefs.addColumn(new RotColumn<CellRef>(&CellRef::mPos, 1, false));
|
|
mRefs.addColumn(new RotColumn<CellRef>(&CellRef::mPos, 2, false));
|
|
mRefs.addColumn(new ScaleColumn<CellRef>);
|
|
mRefs.addColumn(new OwnerColumn<CellRef>);
|
|
mRefs.addColumn(new SoulColumn<CellRef>);
|
|
mRefs.addColumn(new FactionColumn<CellRef>);
|
|
mRefs.addColumn(new FactionIndexColumn<CellRef>);
|
|
mRefs.addColumn(new ChargesColumn<CellRef>);
|
|
mRefs.addColumn(new EnchantmentChargesColumn<CellRef>);
|
|
mRefs.addColumn(new GoldValueColumn<CellRef>);
|
|
mRefs.addColumn(new TeleportColumn<CellRef>);
|
|
mRefs.addColumn(new TeleportCellColumn<CellRef>);
|
|
mRefs.addColumn(new PosColumn<CellRef>(&CellRef::mDoorDest, 0, true));
|
|
mRefs.addColumn(new PosColumn<CellRef>(&CellRef::mDoorDest, 1, true));
|
|
mRefs.addColumn(new PosColumn<CellRef>(&CellRef::mDoorDest, 2, true));
|
|
mRefs.addColumn(new RotColumn<CellRef>(&CellRef::mDoorDest, 0, true));
|
|
mRefs.addColumn(new RotColumn<CellRef>(&CellRef::mDoorDest, 1, true));
|
|
mRefs.addColumn(new RotColumn<CellRef>(&CellRef::mDoorDest, 2, true));
|
|
mRefs.addColumn(new LockLevelColumn<CellRef>);
|
|
mRefs.addColumn(new KeyColumn<CellRef>);
|
|
mRefs.addColumn(new TrapColumn<CellRef>);
|
|
mRefs.addColumn(new OwnerGlobalColumn<CellRef>);
|
|
mRefs.addColumn(new RefNumColumn<CellRef>);
|
|
|
|
mFilters.addColumn(new StringIdColumn<ESM::Filter>);
|
|
mFilters.addColumn(new RecordStateColumn<ESM::Filter>);
|
|
mFilters.addColumn(new FixedRecordTypeColumn<ESM::Filter>(UniversalId::Type_Filter));
|
|
mFilters.addColumn(new FilterColumn<ESM::Filter>);
|
|
mFilters.addColumn(new DescriptionColumn<ESM::Filter>);
|
|
|
|
mDebugProfiles.addColumn(new StringIdColumn<ESM::DebugProfile>);
|
|
mDebugProfiles.addColumn(new RecordStateColumn<ESM::DebugProfile>);
|
|
mDebugProfiles.addColumn(new FixedRecordTypeColumn<ESM::DebugProfile>(UniversalId::Type_DebugProfile));
|
|
mDebugProfiles.addColumn(
|
|
new FlagColumn2<ESM::DebugProfile>(Columns::ColumnId_DefaultProfile, ESM::DebugProfile::Flag_Default));
|
|
mDebugProfiles.addColumn(
|
|
new FlagColumn2<ESM::DebugProfile>(Columns::ColumnId_BypassNewGame, ESM::DebugProfile::Flag_BypassNewGame));
|
|
mDebugProfiles.addColumn(
|
|
new FlagColumn2<ESM::DebugProfile>(Columns::ColumnId_GlobalProfile, ESM::DebugProfile::Flag_Global));
|
|
mDebugProfiles.addColumn(new DescriptionColumn<ESM::DebugProfile>);
|
|
mDebugProfiles.addColumn(new ScriptColumn<ESM::DebugProfile>(ScriptColumn<ESM::DebugProfile>::Type_Lines));
|
|
|
|
mMetaData.appendBlankRecord(ESM::RefId::stringRefId("sys::meta"));
|
|
|
|
mMetaData.addColumn(new StringIdColumn<MetaData>(true));
|
|
mMetaData.addColumn(new RecordStateColumn<MetaData>);
|
|
mMetaData.addColumn(new FixedRecordTypeColumn<MetaData>(UniversalId::Type_MetaData));
|
|
mMetaData.addColumn(new FormatColumn<MetaData>);
|
|
mMetaData.addColumn(new AuthorColumn<MetaData>);
|
|
mMetaData.addColumn(new FileDescriptionColumn<MetaData>);
|
|
|
|
addModel(new IdTable(&mGlobals), UniversalId::Type_Global);
|
|
addModel(new IdTable(&mGmsts), UniversalId::Type_Gmst);
|
|
addModel(new IdTable(&mSkills), UniversalId::Type_Skill);
|
|
addModel(new IdTable(&mClasses), UniversalId::Type_Class);
|
|
addModel(new IdTree(&mFactions, &mFactions), UniversalId::Type_Faction);
|
|
addModel(new IdTree(&mRaces, &mRaces), UniversalId::Type_Race);
|
|
addModel(new IdTable(&mSounds), UniversalId::Type_Sound);
|
|
addModel(new IdTable(&mScripts), UniversalId::Type_Script);
|
|
addModel(new IdTree(&mRegions, &mRegions), UniversalId::Type_Region);
|
|
addModel(new IdTree(&mBirthsigns, &mBirthsigns), UniversalId::Type_Birthsign);
|
|
addModel(new IdTree(&mSpells, &mSpells), UniversalId::Type_Spell);
|
|
addModel(new IdTable(&mTopics), UniversalId::Type_Topic);
|
|
addModel(new IdTable(&mJournals), UniversalId::Type_Journal);
|
|
addModel(new IdTree(&mTopicInfos, &mTopicInfos, IdTable::Feature_ReorderWithinTopic), UniversalId::Type_TopicInfo);
|
|
addModel(new IdTable(&mJournalInfos, IdTable::Feature_ReorderWithinTopic), UniversalId::Type_JournalInfo);
|
|
addModel(new IdTree(&mCells, &mCells, IdTable::Feature_ViewId), UniversalId::Type_Cell);
|
|
addModel(new IdTree(&mEnchantments, &mEnchantments), UniversalId::Type_Enchantment);
|
|
addModel(new IdTable(&mBodyParts), UniversalId::Type_BodyPart);
|
|
addModel(new IdTable(&mSoundGens), UniversalId::Type_SoundGen);
|
|
addModel(new IdTable(&mMagicEffects), UniversalId::Type_MagicEffect);
|
|
addModel(new IdTable(&mLand, IdTable::Feature_AllowTouch), UniversalId::Type_Land);
|
|
addModel(new LandTextureIdTable(&mLandTextures), UniversalId::Type_LandTexture);
|
|
addModel(new IdTree(&mPathgrids, &mPathgrids), UniversalId::Type_Pathgrid);
|
|
addModel(new IdTable(&mStartScripts), UniversalId::Type_StartScript);
|
|
addModel(new IdTree(&mReferenceables, &mReferenceables, IdTable::Feature_Preview), UniversalId::Type_Referenceable);
|
|
addModel(new IdTable(&mRefs, IdTable::Feature_ViewCell | IdTable::Feature_Preview), UniversalId::Type_Reference);
|
|
addModel(new IdTable(&mFilters), UniversalId::Type_Filter);
|
|
addModel(new IdTable(&mDebugProfiles), UniversalId::Type_DebugProfile);
|
|
addModel(new ResourceTable(&mResourcesManager.get(UniversalId::Type_Meshes)), UniversalId::Type_Mesh);
|
|
addModel(new ResourceTable(&mResourcesManager.get(UniversalId::Type_Icons)), UniversalId::Type_Icon);
|
|
addModel(new ResourceTable(&mResourcesManager.get(UniversalId::Type_Musics)), UniversalId::Type_Music);
|
|
addModel(new ResourceTable(&mResourcesManager.get(UniversalId::Type_SoundsRes)), UniversalId::Type_SoundRes);
|
|
addModel(new ResourceTable(&mResourcesManager.get(UniversalId::Type_Textures)), UniversalId::Type_Texture);
|
|
addModel(new ResourceTable(&mResourcesManager.get(UniversalId::Type_Videos)), UniversalId::Type_Video);
|
|
addModel(new IdTable(&mMetaData), UniversalId::Type_MetaData);
|
|
|
|
mActorAdapter = std::make_unique<ActorAdapter>(*this);
|
|
|
|
mRefLoadCache.clear(); // clear here rather than startLoading() and continueLoading() for multiple content files
|
|
}
|
|
|
|
CSMWorld::Data::~Data()
|
|
{
|
|
for (std::vector<QAbstractItemModel*>::iterator iter(mModels.begin()); iter != mModels.end(); ++iter)
|
|
delete *iter;
|
|
|
|
delete mReader;
|
|
}
|
|
|
|
std::shared_ptr<Resource::ResourceSystem> CSMWorld::Data::getResourceSystem()
|
|
{
|
|
return mResourceSystem;
|
|
}
|
|
|
|
std::shared_ptr<const Resource::ResourceSystem> CSMWorld::Data::getResourceSystem() const
|
|
{
|
|
return mResourceSystem;
|
|
}
|
|
|
|
const CSMWorld::IdCollection<ESM::Global>& CSMWorld::Data::getGlobals() const
|
|
{
|
|
return mGlobals;
|
|
}
|
|
|
|
CSMWorld::IdCollection<ESM::Global>& CSMWorld::Data::getGlobals()
|
|
{
|
|
return mGlobals;
|
|
}
|
|
|
|
const CSMWorld::IdCollection<ESM::GameSetting>& CSMWorld::Data::getGmsts() const
|
|
{
|
|
return mGmsts;
|
|
}
|
|
|
|
CSMWorld::IdCollection<ESM::GameSetting>& CSMWorld::Data::getGmsts()
|
|
{
|
|
return mGmsts;
|
|
}
|
|
|
|
const CSMWorld::IdCollection<ESM::Skill>& CSMWorld::Data::getSkills() const
|
|
{
|
|
return mSkills;
|
|
}
|
|
|
|
CSMWorld::IdCollection<ESM::Skill>& CSMWorld::Data::getSkills()
|
|
{
|
|
return mSkills;
|
|
}
|
|
|
|
const CSMWorld::IdCollection<ESM::Class>& CSMWorld::Data::getClasses() const
|
|
{
|
|
return mClasses;
|
|
}
|
|
|
|
CSMWorld::IdCollection<ESM::Class>& CSMWorld::Data::getClasses()
|
|
{
|
|
return mClasses;
|
|
}
|
|
|
|
const CSMWorld::IdCollection<ESM::Faction>& CSMWorld::Data::getFactions() const
|
|
{
|
|
return mFactions;
|
|
}
|
|
|
|
CSMWorld::IdCollection<ESM::Faction>& CSMWorld::Data::getFactions()
|
|
{
|
|
return mFactions;
|
|
}
|
|
|
|
const CSMWorld::IdCollection<ESM::Race>& CSMWorld::Data::getRaces() const
|
|
{
|
|
return mRaces;
|
|
}
|
|
|
|
CSMWorld::IdCollection<ESM::Race>& CSMWorld::Data::getRaces()
|
|
{
|
|
return mRaces;
|
|
}
|
|
|
|
const CSMWorld::IdCollection<ESM::Sound>& CSMWorld::Data::getSounds() const
|
|
{
|
|
return mSounds;
|
|
}
|
|
|
|
CSMWorld::IdCollection<ESM::Sound>& CSMWorld::Data::getSounds()
|
|
{
|
|
return mSounds;
|
|
}
|
|
|
|
const CSMWorld::IdCollection<ESM::Script>& CSMWorld::Data::getScripts() const
|
|
{
|
|
return mScripts;
|
|
}
|
|
|
|
CSMWorld::IdCollection<ESM::Script>& CSMWorld::Data::getScripts()
|
|
{
|
|
return mScripts;
|
|
}
|
|
|
|
const CSMWorld::IdCollection<ESM::Region>& CSMWorld::Data::getRegions() const
|
|
{
|
|
return mRegions;
|
|
}
|
|
|
|
CSMWorld::IdCollection<ESM::Region>& CSMWorld::Data::getRegions()
|
|
{
|
|
return mRegions;
|
|
}
|
|
|
|
const CSMWorld::IdCollection<ESM::BirthSign>& CSMWorld::Data::getBirthsigns() const
|
|
{
|
|
return mBirthsigns;
|
|
}
|
|
|
|
CSMWorld::IdCollection<ESM::BirthSign>& CSMWorld::Data::getBirthsigns()
|
|
{
|
|
return mBirthsigns;
|
|
}
|
|
|
|
const CSMWorld::IdCollection<ESM::Spell>& CSMWorld::Data::getSpells() const
|
|
{
|
|
return mSpells;
|
|
}
|
|
|
|
CSMWorld::IdCollection<ESM::Spell>& CSMWorld::Data::getSpells()
|
|
{
|
|
return mSpells;
|
|
}
|
|
|
|
const CSMWorld::IdCollection<ESM::Dialogue>& CSMWorld::Data::getTopics() const
|
|
{
|
|
return mTopics;
|
|
}
|
|
|
|
CSMWorld::IdCollection<ESM::Dialogue>& CSMWorld::Data::getTopics()
|
|
{
|
|
return mTopics;
|
|
}
|
|
|
|
const CSMWorld::IdCollection<ESM::Dialogue>& CSMWorld::Data::getJournals() const
|
|
{
|
|
return mJournals;
|
|
}
|
|
|
|
CSMWorld::IdCollection<ESM::Dialogue>& CSMWorld::Data::getJournals()
|
|
{
|
|
return mJournals;
|
|
}
|
|
|
|
const CSMWorld::InfoCollection& CSMWorld::Data::getTopicInfos() const
|
|
{
|
|
return mTopicInfos;
|
|
}
|
|
|
|
CSMWorld::InfoCollection& CSMWorld::Data::getTopicInfos()
|
|
{
|
|
return mTopicInfos;
|
|
}
|
|
|
|
const CSMWorld::InfoCollection& CSMWorld::Data::getJournalInfos() const
|
|
{
|
|
return mJournalInfos;
|
|
}
|
|
|
|
CSMWorld::InfoCollection& CSMWorld::Data::getJournalInfos()
|
|
{
|
|
return mJournalInfos;
|
|
}
|
|
|
|
const CSMWorld::IdCollection<CSMWorld::Cell>& CSMWorld::Data::getCells() const
|
|
{
|
|
return mCells;
|
|
}
|
|
|
|
CSMWorld::IdCollection<CSMWorld::Cell>& CSMWorld::Data::getCells()
|
|
{
|
|
return mCells;
|
|
}
|
|
|
|
const CSMWorld::RefIdCollection& CSMWorld::Data::getReferenceables() const
|
|
{
|
|
return mReferenceables;
|
|
}
|
|
|
|
CSMWorld::RefIdCollection& CSMWorld::Data::getReferenceables()
|
|
{
|
|
return mReferenceables;
|
|
}
|
|
|
|
const CSMWorld::RefCollection& CSMWorld::Data::getReferences() const
|
|
{
|
|
return mRefs;
|
|
}
|
|
|
|
CSMWorld::RefCollection& CSMWorld::Data::getReferences()
|
|
{
|
|
return mRefs;
|
|
}
|
|
|
|
const CSMWorld::IdCollection<ESM::Filter>& CSMWorld::Data::getFilters() const
|
|
{
|
|
return mFilters;
|
|
}
|
|
|
|
CSMWorld::IdCollection<ESM::Filter>& CSMWorld::Data::getFilters()
|
|
{
|
|
return mFilters;
|
|
}
|
|
|
|
const CSMWorld::IdCollection<ESM::Enchantment>& CSMWorld::Data::getEnchantments() const
|
|
{
|
|
return mEnchantments;
|
|
}
|
|
|
|
CSMWorld::IdCollection<ESM::Enchantment>& CSMWorld::Data::getEnchantments()
|
|
{
|
|
return mEnchantments;
|
|
}
|
|
|
|
const CSMWorld::IdCollection<ESM::BodyPart>& CSMWorld::Data::getBodyParts() const
|
|
{
|
|
return mBodyParts;
|
|
}
|
|
|
|
CSMWorld::IdCollection<ESM::BodyPart>& CSMWorld::Data::getBodyParts()
|
|
{
|
|
return mBodyParts;
|
|
}
|
|
|
|
const CSMWorld::IdCollection<ESM::DebugProfile>& CSMWorld::Data::getDebugProfiles() const
|
|
{
|
|
return mDebugProfiles;
|
|
}
|
|
|
|
CSMWorld::IdCollection<ESM::DebugProfile>& CSMWorld::Data::getDebugProfiles()
|
|
{
|
|
return mDebugProfiles;
|
|
}
|
|
|
|
const CSMWorld::IdCollection<CSMWorld::Land>& CSMWorld::Data::getLand() const
|
|
{
|
|
return mLand;
|
|
}
|
|
|
|
CSMWorld::IdCollection<CSMWorld::Land>& CSMWorld::Data::getLand()
|
|
{
|
|
return mLand;
|
|
}
|
|
|
|
const CSMWorld::IdCollection<CSMWorld::LandTexture>& CSMWorld::Data::getLandTextures() const
|
|
{
|
|
return mLandTextures;
|
|
}
|
|
|
|
CSMWorld::IdCollection<CSMWorld::LandTexture>& CSMWorld::Data::getLandTextures()
|
|
{
|
|
return mLandTextures;
|
|
}
|
|
|
|
const CSMWorld::IdCollection<ESM::SoundGenerator>& CSMWorld::Data::getSoundGens() const
|
|
{
|
|
return mSoundGens;
|
|
}
|
|
|
|
CSMWorld::IdCollection<ESM::SoundGenerator>& CSMWorld::Data::getSoundGens()
|
|
{
|
|
return mSoundGens;
|
|
}
|
|
|
|
const CSMWorld::IdCollection<ESM::MagicEffect>& CSMWorld::Data::getMagicEffects() const
|
|
{
|
|
return mMagicEffects;
|
|
}
|
|
|
|
CSMWorld::IdCollection<ESM::MagicEffect>& CSMWorld::Data::getMagicEffects()
|
|
{
|
|
return mMagicEffects;
|
|
}
|
|
|
|
const CSMWorld::SubCellCollection<CSMWorld::Pathgrid>& CSMWorld::Data::getPathgrids() const
|
|
{
|
|
return mPathgrids;
|
|
}
|
|
|
|
CSMWorld::SubCellCollection<CSMWorld::Pathgrid>& CSMWorld::Data::getPathgrids()
|
|
{
|
|
return mPathgrids;
|
|
}
|
|
|
|
const CSMWorld::IdCollection<ESM::StartScript>& CSMWorld::Data::getStartScripts() const
|
|
{
|
|
return mStartScripts;
|
|
}
|
|
|
|
CSMWorld::IdCollection<ESM::StartScript>& CSMWorld::Data::getStartScripts()
|
|
{
|
|
return mStartScripts;
|
|
}
|
|
|
|
const CSMWorld::Resources& CSMWorld::Data::getResources(const UniversalId& id) const
|
|
{
|
|
return mResourcesManager.get(id.getType());
|
|
}
|
|
|
|
const CSMWorld::MetaData& CSMWorld::Data::getMetaData() const
|
|
{
|
|
return mMetaData.getRecord(0).get();
|
|
}
|
|
|
|
void CSMWorld::Data::setMetaData(const MetaData& metaData)
|
|
{
|
|
mMetaData.setRecord(
|
|
0, std::make_unique<Record<MetaData>>(Record<MetaData>(RecordBase::State_ModifiedOnly, nullptr, &metaData)));
|
|
}
|
|
|
|
QAbstractItemModel* CSMWorld::Data::getTableModel(const CSMWorld::UniversalId& id)
|
|
{
|
|
std::map<UniversalId::Type, QAbstractItemModel*>::iterator iter = mModelIndex.find(id.getType());
|
|
|
|
if (iter == mModelIndex.end())
|
|
{
|
|
// try creating missing (secondary) tables on the fly
|
|
//
|
|
// Note: We create these tables here so we don't have to deal with them during load/initial
|
|
// construction of the ESX data where no update signals are available.
|
|
if (id.getType() == UniversalId::Type_RegionMap)
|
|
{
|
|
RegionMap* table = nullptr;
|
|
addModel(table = new RegionMap(*this), UniversalId::Type_RegionMap, false);
|
|
return table;
|
|
}
|
|
throw std::logic_error("No table model available for " + id.toString());
|
|
}
|
|
|
|
return iter->second;
|
|
}
|
|
|
|
const CSMWorld::ActorAdapter* CSMWorld::Data::getActorAdapter() const
|
|
{
|
|
return mActorAdapter.get();
|
|
}
|
|
|
|
CSMWorld::ActorAdapter* CSMWorld::Data::getActorAdapter()
|
|
{
|
|
return mActorAdapter.get();
|
|
}
|
|
|
|
void CSMWorld::Data::merge()
|
|
{
|
|
mGlobals.merge();
|
|
}
|
|
|
|
int CSMWorld::Data::getTotalRecords(const std::vector<std::filesystem::path>& files)
|
|
{
|
|
int records = 0;
|
|
|
|
std::unique_ptr<ESM::ESMReader> reader = std::make_unique<ESM::ESMReader>();
|
|
|
|
for (unsigned int i = 0; i < files.size(); ++i)
|
|
{
|
|
if (!std::filesystem::exists(files[i]))
|
|
continue;
|
|
|
|
reader->open(files[i]);
|
|
records += reader->getRecordCount();
|
|
reader->close();
|
|
}
|
|
|
|
return records;
|
|
}
|
|
|
|
int CSMWorld::Data::startLoading(const std::filesystem::path& path, bool base, bool project)
|
|
{
|
|
// Don't delete the Reader yet. Some record types store a reference to the Reader to handle on-demand loading
|
|
std::shared_ptr<ESM::ESMReader> ptr(mReader);
|
|
mReaders.push_back(ptr);
|
|
mReader = nullptr;
|
|
|
|
mDialogue = nullptr;
|
|
|
|
mReader = new ESM::ESMReader;
|
|
mReader->setEncoder(&mEncoder);
|
|
mReader->setIndex((project || !base) ? 0 : mReaderIndex++);
|
|
mReader->open(path);
|
|
|
|
mBase = base;
|
|
mProject = project;
|
|
|
|
if (!mProject && !mBase)
|
|
{
|
|
MetaData metaData;
|
|
metaData.mId = ESM::RefId::stringRefId("sys::meta");
|
|
metaData.load(*mReader);
|
|
|
|
mMetaData.setRecord(0,
|
|
std::make_unique<Record<MetaData>>(Record<MetaData>(RecordBase::State_ModifiedOnly, nullptr, &metaData)));
|
|
}
|
|
|
|
return mReader->getRecordCount();
|
|
}
|
|
|
|
void CSMWorld::Data::loadFallbackEntries()
|
|
{
|
|
// Load default marker definitions, if game files do not have them for some reason
|
|
std::pair<std::string, std::string> staticMarkers[] = { std::make_pair("DivineMarker", "marker_divine.nif"),
|
|
std::make_pair("DoorMarker", "marker_arrow.nif"), std::make_pair("NorthMarker", "marker_north.nif"),
|
|
std::make_pair("TempleMarker", "marker_temple.nif"), std::make_pair("TravelMarker", "marker_travel.nif") };
|
|
|
|
std::pair<std::string, std::string> doorMarkers[] = { std::make_pair("PrisonMarker", "marker_prison.nif") };
|
|
|
|
for (const auto& marker : staticMarkers)
|
|
{
|
|
if (mReferenceables.searchId(marker.first) == -1)
|
|
{
|
|
ESM::Static newMarker;
|
|
newMarker.mId = ESM::RefId::stringRefId(marker.first);
|
|
newMarker.mModel = marker.second;
|
|
newMarker.mRecordFlags = 0;
|
|
auto record = std::make_unique<CSMWorld::Record<ESM::Static>>();
|
|
record->mBase = newMarker;
|
|
record->mState = CSMWorld::RecordBase::State_BaseOnly;
|
|
mReferenceables.appendRecord(std::move(record), CSMWorld::UniversalId::Type_Static);
|
|
}
|
|
}
|
|
|
|
for (const auto& marker : doorMarkers)
|
|
{
|
|
if (mReferenceables.searchId(marker.first) == -1)
|
|
{
|
|
ESM::Door newMarker;
|
|
newMarker.mId = ESM::RefId::stringRefId(marker.first);
|
|
newMarker.mModel = marker.second;
|
|
newMarker.mRecordFlags = 0;
|
|
auto record = std::make_unique<CSMWorld::Record<ESM::Door>>();
|
|
record->mBase = newMarker;
|
|
record->mState = CSMWorld::RecordBase::State_BaseOnly;
|
|
mReferenceables.appendRecord(std::move(record), CSMWorld::UniversalId::Type_Door);
|
|
}
|
|
}
|
|
}
|
|
|
|
bool CSMWorld::Data::continueLoading(CSMDoc::Messages& messages)
|
|
{
|
|
if (!mReader)
|
|
throw std::logic_error("can't continue loading, because no load has been started");
|
|
|
|
if (!mReader->hasMoreRecs())
|
|
{
|
|
if (mBase)
|
|
{
|
|
// Don't delete the Reader yet. Some record types store a reference to the Reader to handle on-demand
|
|
// loading. We don't store non-base reader, because everything going into modified will be fully loaded
|
|
// during the initial loading process.
|
|
std::shared_ptr<ESM::ESMReader> ptr(mReader);
|
|
mReaders.push_back(ptr);
|
|
}
|
|
else
|
|
delete mReader;
|
|
|
|
mReader = nullptr;
|
|
|
|
mDialogue = nullptr;
|
|
|
|
loadFallbackEntries();
|
|
|
|
return true;
|
|
}
|
|
|
|
ESM::NAME n = mReader->getRecName();
|
|
mReader->getRecHeader();
|
|
|
|
bool unhandledRecord = false;
|
|
|
|
switch (n.toInt())
|
|
{
|
|
case ESM::REC_GLOB:
|
|
mGlobals.load(*mReader, mBase);
|
|
break;
|
|
case ESM::REC_GMST:
|
|
mGmsts.load(*mReader, mBase);
|
|
break;
|
|
case ESM::REC_SKIL:
|
|
mSkills.load(*mReader, mBase);
|
|
break;
|
|
case ESM::REC_CLAS:
|
|
mClasses.load(*mReader, mBase);
|
|
break;
|
|
case ESM::REC_FACT:
|
|
mFactions.load(*mReader, mBase);
|
|
break;
|
|
case ESM::REC_RACE:
|
|
mRaces.load(*mReader, mBase);
|
|
break;
|
|
case ESM::REC_SOUN:
|
|
mSounds.load(*mReader, mBase);
|
|
break;
|
|
case ESM::REC_SCPT:
|
|
mScripts.load(*mReader, mBase);
|
|
break;
|
|
case ESM::REC_REGN:
|
|
mRegions.load(*mReader, mBase);
|
|
break;
|
|
case ESM::REC_BSGN:
|
|
mBirthsigns.load(*mReader, mBase);
|
|
break;
|
|
case ESM::REC_SPEL:
|
|
mSpells.load(*mReader, mBase);
|
|
break;
|
|
case ESM::REC_ENCH:
|
|
mEnchantments.load(*mReader, mBase);
|
|
break;
|
|
case ESM::REC_BODY:
|
|
mBodyParts.load(*mReader, mBase);
|
|
break;
|
|
case ESM::REC_SNDG:
|
|
mSoundGens.load(*mReader, mBase);
|
|
break;
|
|
case ESM::REC_MGEF:
|
|
mMagicEffects.load(*mReader, mBase);
|
|
break;
|
|
case ESM::REC_PGRD:
|
|
mPathgrids.load(*mReader, mBase);
|
|
break;
|
|
case ESM::REC_SSCR:
|
|
mStartScripts.load(*mReader, mBase);
|
|
break;
|
|
|
|
case ESM::REC_LTEX:
|
|
mLandTextures.load(*mReader, mBase);
|
|
break;
|
|
|
|
case ESM::REC_LAND:
|
|
mLand.load(*mReader, mBase);
|
|
break;
|
|
|
|
case ESM::REC_CELL:
|
|
{
|
|
int index = mCells.load(*mReader, mBase);
|
|
if (index < 0 || index >= mCells.getSize())
|
|
{
|
|
// log an error and continue loading the refs to the last loaded cell
|
|
CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_None);
|
|
messages.add(id, "Logic error: cell index out of bounds", "", CSMDoc::Message::Severity_Error);
|
|
index = mCells.getSize() - 1;
|
|
}
|
|
const std::string cellId = mCells.getId(index).getRefIdString();
|
|
|
|
mRefs.load(*mReader, index, mBase, mRefLoadCache[cellId], messages);
|
|
break;
|
|
}
|
|
|
|
case ESM::REC_ACTI:
|
|
mReferenceables.load(*mReader, mBase, UniversalId::Type_Activator);
|
|
break;
|
|
case ESM::REC_ALCH:
|
|
mReferenceables.load(*mReader, mBase, UniversalId::Type_Potion);
|
|
break;
|
|
case ESM::REC_APPA:
|
|
mReferenceables.load(*mReader, mBase, UniversalId::Type_Apparatus);
|
|
break;
|
|
case ESM::REC_ARMO:
|
|
mReferenceables.load(*mReader, mBase, UniversalId::Type_Armor);
|
|
break;
|
|
case ESM::REC_BOOK:
|
|
mReferenceables.load(*mReader, mBase, UniversalId::Type_Book);
|
|
break;
|
|
case ESM::REC_CLOT:
|
|
mReferenceables.load(*mReader, mBase, UniversalId::Type_Clothing);
|
|
break;
|
|
case ESM::REC_CONT:
|
|
mReferenceables.load(*mReader, mBase, UniversalId::Type_Container);
|
|
break;
|
|
case ESM::REC_CREA:
|
|
mReferenceables.load(*mReader, mBase, UniversalId::Type_Creature);
|
|
break;
|
|
case ESM::REC_DOOR:
|
|
mReferenceables.load(*mReader, mBase, UniversalId::Type_Door);
|
|
break;
|
|
case ESM::REC_INGR:
|
|
mReferenceables.load(*mReader, mBase, UniversalId::Type_Ingredient);
|
|
break;
|
|
case ESM::REC_LEVC:
|
|
mReferenceables.load(*mReader, mBase, UniversalId::Type_CreatureLevelledList);
|
|
break;
|
|
case ESM::REC_LEVI:
|
|
mReferenceables.load(*mReader, mBase, UniversalId::Type_ItemLevelledList);
|
|
break;
|
|
case ESM::REC_LIGH:
|
|
mReferenceables.load(*mReader, mBase, UniversalId::Type_Light);
|
|
break;
|
|
case ESM::REC_LOCK:
|
|
mReferenceables.load(*mReader, mBase, UniversalId::Type_Lockpick);
|
|
break;
|
|
case ESM::REC_MISC:
|
|
mReferenceables.load(*mReader, mBase, UniversalId::Type_Miscellaneous);
|
|
break;
|
|
case ESM::REC_NPC_:
|
|
mReferenceables.load(*mReader, mBase, UniversalId::Type_Npc);
|
|
break;
|
|
case ESM::REC_PROB:
|
|
mReferenceables.load(*mReader, mBase, UniversalId::Type_Probe);
|
|
break;
|
|
case ESM::REC_REPA:
|
|
mReferenceables.load(*mReader, mBase, UniversalId::Type_Repair);
|
|
break;
|
|
case ESM::REC_STAT:
|
|
mReferenceables.load(*mReader, mBase, UniversalId::Type_Static);
|
|
break;
|
|
case ESM::REC_WEAP:
|
|
mReferenceables.load(*mReader, mBase, UniversalId::Type_Weapon);
|
|
break;
|
|
|
|
case ESM::REC_DIAL:
|
|
{
|
|
ESM::Dialogue record;
|
|
bool isDeleted = false;
|
|
|
|
record.load(*mReader, isDeleted);
|
|
const std::string& recordIdString = record.mId.getRefIdString();
|
|
|
|
if (isDeleted)
|
|
{
|
|
// record vector can be shuffled around which would make pointer to record invalid
|
|
mDialogue = nullptr;
|
|
|
|
if (mJournals.tryDelete(recordIdString))
|
|
{
|
|
removeDialogueInfos(record.mId, mJournalInfosByTopic, mJournalInfos);
|
|
}
|
|
else if (mTopics.tryDelete(recordIdString))
|
|
{
|
|
removeDialogueInfos(record.mId, mTopicInfosByTopic, mTopicInfos);
|
|
}
|
|
else
|
|
{
|
|
messages.add(UniversalId::Type_None,
|
|
"Trying to delete dialogue record " + recordIdString + " which does not exist", "",
|
|
CSMDoc::Message::Severity_Warning);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (record.mType == ESM::Dialogue::Journal)
|
|
{
|
|
mJournals.load(record, mBase);
|
|
mDialogue = &mJournals.getRecord(record.mId).get();
|
|
}
|
|
else
|
|
{
|
|
mTopics.load(record, mBase);
|
|
mDialogue = &mTopics.getRecord(record.mId).get();
|
|
}
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case ESM::REC_INFO:
|
|
{
|
|
if (!mDialogue)
|
|
{
|
|
messages.add(UniversalId::Type_None, "Found info record not following a dialogue record", "",
|
|
CSMDoc::Message::Severity_Error);
|
|
|
|
mReader->skipRecord();
|
|
break;
|
|
}
|
|
|
|
if (mDialogue->mType == ESM::Dialogue::Journal)
|
|
mJournalInfos.load(*mReader, mBase, *mDialogue, mJournalInfosByTopic);
|
|
else
|
|
mTopicInfos.load(*mReader, mBase, *mDialogue, mTopicInfosByTopic);
|
|
|
|
break;
|
|
}
|
|
|
|
case ESM::REC_FILT:
|
|
|
|
if (!mProject)
|
|
{
|
|
unhandledRecord = true;
|
|
break;
|
|
}
|
|
|
|
mFilters.load(*mReader, mBase);
|
|
break;
|
|
|
|
case ESM::REC_DBGP:
|
|
|
|
if (!mProject)
|
|
{
|
|
unhandledRecord = true;
|
|
break;
|
|
}
|
|
|
|
mDebugProfiles.load(*mReader, mBase);
|
|
break;
|
|
|
|
default:
|
|
|
|
unhandledRecord = true;
|
|
}
|
|
|
|
if (unhandledRecord)
|
|
{
|
|
messages.add(
|
|
UniversalId::Type_None, "Unsupported record type: " + n.toString(), "", CSMDoc::Message::Severity_Error);
|
|
|
|
mReader->skipRecord();
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
bool CSMWorld::Data::hasId(const std::string& id) const
|
|
{
|
|
return getGlobals().searchId(id) != -1 || getGmsts().searchId(id) != -1 || getSkills().searchId(id) != -1
|
|
|| getClasses().searchId(id) != -1 || getFactions().searchId(id) != -1 || getRaces().searchId(id) != -1
|
|
|| getSounds().searchId(id) != -1 || getScripts().searchId(id) != -1 || getRegions().searchId(id) != -1
|
|
|| getBirthsigns().searchId(id) != -1 || getSpells().searchId(id) != -1 || getTopics().searchId(id) != -1
|
|
|| getJournals().searchId(id) != -1 || getCells().searchId(id) != -1 || getEnchantments().searchId(id) != -1
|
|
|| getBodyParts().searchId(id) != -1 || getSoundGens().searchId(id) != -1
|
|
|| getMagicEffects().searchId(id) != -1 || getReferenceables().searchId(id) != -1;
|
|
}
|
|
|
|
int CSMWorld::Data::count(RecordBase::State state) const
|
|
{
|
|
return count(state, mGlobals) + count(state, mGmsts) + count(state, mSkills) + count(state, mClasses)
|
|
+ count(state, mFactions) + count(state, mRaces) + count(state, mSounds) + count(state, mScripts)
|
|
+ count(state, mRegions) + count(state, mBirthsigns) + count(state, mSpells) + count(state, mCells)
|
|
+ count(state, mEnchantments) + count(state, mBodyParts) + count(state, mLand) + count(state, mLandTextures)
|
|
+ count(state, mSoundGens) + count(state, mMagicEffects) + count(state, mReferenceables)
|
|
+ count(state, mPathgrids);
|
|
}
|
|
|
|
std::vector<ESM::RefId> CSMWorld::Data::getIds(bool listDeleted) const
|
|
{
|
|
std::vector<ESM::RefId> ids;
|
|
|
|
appendIds(ids, mGlobals, listDeleted);
|
|
appendIds(ids, mGmsts, listDeleted);
|
|
appendIds(ids, mClasses, listDeleted);
|
|
appendIds(ids, mFactions, listDeleted);
|
|
appendIds(ids, mRaces, listDeleted);
|
|
appendIds(ids, mSounds, listDeleted);
|
|
appendIds(ids, mScripts, listDeleted);
|
|
appendIds(ids, mRegions, listDeleted);
|
|
appendIds(ids, mBirthsigns, listDeleted);
|
|
appendIds(ids, mSpells, listDeleted);
|
|
appendIds(ids, mTopics, listDeleted);
|
|
appendIds(ids, mJournals, listDeleted);
|
|
appendIds(ids, mCells, listDeleted);
|
|
appendIds(ids, mEnchantments, listDeleted);
|
|
appendIds(ids, mBodyParts, listDeleted);
|
|
appendIds(ids, mSoundGens, listDeleted);
|
|
appendIds(ids, mMagicEffects, listDeleted);
|
|
appendIds(ids, mReferenceables, listDeleted);
|
|
|
|
std::sort(ids.begin(), ids.end());
|
|
|
|
return ids;
|
|
}
|
|
|
|
void CSMWorld::Data::assetsChanged()
|
|
{
|
|
mVFS.get()->reset();
|
|
VFS::registerArchives(mVFS.get(), Files::Collections(mDataPaths, !mFsStrict), mArchives, true);
|
|
|
|
const UniversalId assetTableIds[] = { UniversalId::Type_Meshes, UniversalId::Type_Icons, UniversalId::Type_Musics,
|
|
UniversalId::Type_SoundsRes, UniversalId::Type_Textures, UniversalId::Type_Videos };
|
|
|
|
size_t numAssetTables = sizeof(assetTableIds) / sizeof(UniversalId);
|
|
|
|
for (size_t i = 0; i < numAssetTables; ++i)
|
|
{
|
|
ResourceTable* table = static_cast<ResourceTable*>(getTableModel(assetTableIds[i]));
|
|
table->beginReset();
|
|
}
|
|
|
|
// Trigger recreation
|
|
mResourcesManager.recreateResources();
|
|
|
|
for (size_t i = 0; i < numAssetTables; ++i)
|
|
{
|
|
ResourceTable* table = static_cast<ResourceTable*>(getTableModel(assetTableIds[i]));
|
|
table->endReset();
|
|
}
|
|
|
|
// Get rid of potentially old cached assets
|
|
mResourceSystem->clearCache();
|
|
|
|
emit assetTablesChanged();
|
|
}
|
|
|
|
void CSMWorld::Data::dataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight)
|
|
{
|
|
if (topLeft.column() <= 0)
|
|
emit idListChanged();
|
|
}
|
|
|
|
void CSMWorld::Data::rowsChanged(const QModelIndex& parent, int start, int end)
|
|
{
|
|
emit idListChanged();
|
|
}
|
|
|
|
const VFS::Manager* CSMWorld::Data::getVFS() const
|
|
{
|
|
return mVFS.get();
|
|
}
|