Something went wrong. Try again.
OpenMW is an open implementation of the Morrowind engine
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518#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/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/debug/debuglog.hpp>#include <components/esm/defs.hpp>#include <components/esm/esmcommon.hpp>#include <components/esm3/cellref.hpp>#include <components/esm3/esmreader.hpp>#include <components/esm3/infoorder.hpp>#include <components/esm3/loadcell.hpp>#include <components/esm3/loaddoor.hpp>#include <components/esm3/loadglob.hpp>#include <components/esm3/loadltex.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 CSMWorld{ namespace { void removeDialogueInfos( const ESM::RefId& dialogueId, InfoOrderByTopic& infoOrders, InfoCollection& infoCollection) { const auto topicInfoOrder = infoOrders.find(dialogueId);
if (topicInfoOrder == infoOrders.end()) return;
std::vector<int> erasedRecords;
for (const OrderedInfo& info : topicInfoOrder->second.getOrderedInfo()) { const ESM::RefId id = makeCompositeInfoRefId(dialogueId, info.mId); const Record<Info>& record = infoCollection.getRecord(id);
if (record.mState == RecordBase::State_ModifiedOnly) { erasedRecords.push_back(infoCollection.searchId(id)); continue; }
auto deletedRecord = std::make_unique<Record<Info>>(record); deletedRecord->mState = RecordBase::State_Deleted; infoCollection.setRecord(infoCollection.searchId(id), 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, const Files::PathContainer& dataPaths, const std::vector<std::string>& archives, const std::filesystem::path& resDir) : mEncoder(encoding) , mPathgrids(mCells) , mReferenceables(mMagicEffects) , mRefs(mCells) , mDialogue(nullptr) , mReaderIndex(0) , mDataPaths(dataPaths) , mArchives(archives) , mVFS(std::make_unique<VFS::Manager>()){ VFS::registerArchives(mVFS.get(), Files::Collections(mDataPaths), mArchives, true, &mEncoder.getStatelessEncoder());
mResourcesManager.setVFS(mVFS.get());
constexpr double expiryDelay = 0; mResourceSystem = std::make_unique<Resource::ResourceSystem>(mVFS.get(), expiryDelay, &mEncoder.getStatelessEncoder());
auto defines = Shader::getDefaultDefines();
defines["classicFalloff"] = "1";
auto shadowDefines = SceneUtil::ShadowManager::getShadowsDisabledDefines();
osg::ref_ptr<SceneUtil::LightManager> lightManager = new SceneUtil::LightManager(SceneUtil::LightSettings{}, mResourceSystem.get()); auto lightDefines = lightManager->getLightDefines();
for (const auto& define : shadowDefines) defines[define.first] = define.second; for (const auto& define : lightDefines) 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, ColumnBase::Flag_Dialogue, 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)); mRegions.getNestableColumn(index)->addColumn(new NestedChildColumn( Columns::ColumnId_SoundProbability, ColumnBase::Display_String, ColumnBase::Flag_Dialogue, false));
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>(mMagicEffects))); 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>(mMagicEffects))); 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 ProjectileSpeedColumn<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<ESM::LandTexture>); mLandTextures.addColumn(new RecordStateColumn<ESM::LandTexture>); mLandTextures.addColumn(new FixedRecordTypeColumn<ESM::LandTexture>(UniversalId::Type_LandTexture)); mLandTextures.addColumn(new LandTextureIndexColumn); mLandTextures.addColumn(new TextureColumn<ESM::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 StackSizeColumn<CellRef>); mRefs.addColumn(new TeleportColumn<CellRef>( ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue | ColumnBase::Flag_Dialogue_Refresh)); 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 IsLockedColumn<CellRef>( ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue | ColumnBase::Flag_Dialogue_Refresh)); 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));
mSelectionGroups.addColumn(new StringIdColumn<ESM::SelectionGroup>); mSelectionGroups.addColumn(new RecordStateColumn<ESM::SelectionGroup>); mSelectionGroups.addColumn(new FixedRecordTypeColumn<ESM::SelectionGroup>(UniversalId::Type_SelectionGroup)); mSelectionGroups.addColumn(new SelectionGroupColumn);
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); addModel(new IdTable(&mSelectionGroups), UniversalId::Type_SelectionGroup);
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;}
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;}
CSMWorld::IdCollection<ESM::SelectionGroup>& CSMWorld::Data::getSelectionGroups(){ return mSelectionGroups;}
const CSMWorld::IdCollection<ESM::SelectionGroup>& CSMWorld::Data::getSelectionGroups() const{ return mSelectionGroups;}
const CSMWorld::IdCollection<CSMWorld::Land>& CSMWorld::Data::getLand() const{ return mLand;}
CSMWorld::IdCollection<CSMWorld::Land>& CSMWorld::Data::getLand(){ return mLand;}
const CSMWorld::IdCollection<ESM::LandTexture>& CSMWorld::Data::getLandTextures() const{ return mLandTextures;}
CSMWorld::IdCollection<ESM::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 (const auto& file : files) { if (!std::filesystem::exists(file)) continue;
reader->open(file); records += reader->getRecordCount(); reader->close(); }
return records;}
int CSMWorld::Data::startLoading(const std::filesystem::path& path, bool base, bool project){ Log(Debug::Info) << "Loading content file " << path;
mDialogue = nullptr;
ESM::ReadersCache::BusyItem reader = mReaders.get(mReaderIndex++); reader->setEncoder(&mEncoder); reader->open(path);
mBase = base; mProject = project;
if (!mProject && !mBase) { MetaData metaData; metaData.mId = ESM::RefId::stringRefId("sys::meta"); metaData.load(*reader);
mMetaData.setRecord(0, std::make_unique<Record<MetaData>>(Record<MetaData>(RecordBase::State_ModifiedOnly, nullptr, &metaData))); }
return reader->getRecordCount();}
void CSMWorld::Data::loadFallbackEntries(){ // Load default marker definitions, if game files do not have them for some reason static const std::pair<ESM::RefId, std::string_view> staticMarkers[] = { { ESM::RefId::stringRefId("DivineMarker"), "marker_divine.nif" }, { ESM::RefId::stringRefId("DoorMarker"), "marker_arrow.nif" }, { ESM::RefId::stringRefId("NorthMarker"), "marker_north.nif" }, { ESM::RefId::stringRefId("TempleMarker"), "marker_temple.nif" }, { ESM::RefId::stringRefId("TravelMarker"), "marker_travel.nif" }, };
static const std::pair<ESM::RefId, std::string_view> doorMarkers[] = { { ESM::RefId::stringRefId("PrisonMarker"), "marker_prison.nif" }, };
for (const auto& [refId, model] : staticMarkers) { if (mReferenceables.searchId(refId) == -1) { ESM::Static newMarker; newMarker.mId = refId; newMarker.mModel = model; newMarker.mRecordFlags = 0; auto record = std::make_unique<CSMWorld::Record<ESM::Static>>(); record->mBase = std::move(newMarker); record->mState = CSMWorld::RecordBase::State_BaseOnly; mReferenceables.appendRecord(std::move(record), CSMWorld::UniversalId::Type_Static); } }
for (const auto& [refId, model] : doorMarkers) { if (mReferenceables.searchId(refId) == -1) { ESM::Door newMarker; newMarker.mId = refId; newMarker.mModel = model; newMarker.mRecordFlags = 0; auto record = std::make_unique<CSMWorld::Record<ESM::Door>>(); record->mBase = std::move(newMarker); record->mState = CSMWorld::RecordBase::State_BaseOnly; mReferenceables.appendRecord(std::move(record), CSMWorld::UniversalId::Type_Door); } }}
bool CSMWorld::Data::continueLoading(CSMDoc::Messages& messages){ if (mReaderIndex == 0) throw std::logic_error("can't continue loading, because no load has been started"); ESM::ReadersCache::BusyItem reader = mReaders.get(mReaderIndex - 1); if (!reader->isOpen()) throw std::logic_error("can't continue loading, because no load has been started"); reader->setEncoder(&mEncoder); reader->setIndex(static_cast<int>(mReaderIndex - 1)); reader->resolveParentFileIndices(mReaders);
if (!reader->hasMoreRecs()) { mDialogue = nullptr;
loadFallbackEntries();
return true; }
ESM::NAME n = reader->getRecName(); reader->getRecHeader();
bool unhandledRecord = false;
switch (n.toInt()) { case ESM::REC_GLOB: mGlobals.load(*reader, mBase); break; case ESM::REC_GMST: mGmsts.load(*reader, mBase); break; case ESM::REC_SKIL: mSkills.load(*reader, mBase); break; case ESM::REC_CLAS: mClasses.load(*reader, mBase); break; case ESM::REC_FACT: mFactions.load(*reader, mBase); break; case ESM::REC_RACE: mRaces.load(*reader, mBase); break; case ESM::REC_SOUN: mSounds.load(*reader, mBase); break; case ESM::REC_SCPT: mScripts.load(*reader, mBase); break; case ESM::REC_REGN: mRegions.load(*reader, mBase); break; case ESM::REC_BSGN: mBirthsigns.load(*reader, mBase); break; case ESM::REC_SPEL: mSpells.load(*reader, mBase); break; case ESM::REC_ENCH: mEnchantments.load(*reader, mBase); break; case ESM::REC_BODY: mBodyParts.load(*reader, mBase); break; case ESM::REC_SNDG: mSoundGens.load(*reader, mBase); break; case ESM::REC_MGEF: mMagicEffects.load(*reader, mBase); break; case ESM::REC_PGRD: mPathgrids.load(*reader, mBase); break; case ESM::REC_SSCR: mStartScripts.load(*reader, mBase); break;
case ESM::REC_LTEX: mLandTextures.load(*reader, mBase); break;
case ESM::REC_LAND: mLand.load(*reader, mBase); break;
case ESM::REC_CELL: { int index = mCells.load(*reader, 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; }
mRefs.load(*reader, index, mBase, mRefLoadCache[mCells.getId(index)], messages); break; }
case ESM::REC_ACTI: mReferenceables.load(*reader, mBase, UniversalId::Type_Activator); break; case ESM::REC_ALCH: mReferenceables.load(*reader, mBase, UniversalId::Type_Potion); break; case ESM::REC_APPA: mReferenceables.load(*reader, mBase, UniversalId::Type_Apparatus); break; case ESM::REC_ARMO: mReferenceables.load(*reader, mBase, UniversalId::Type_Armor); break; case ESM::REC_BOOK: mReferenceables.load(*reader, mBase, UniversalId::Type_Book); break; case ESM::REC_CLOT: mReferenceables.load(*reader, mBase, UniversalId::Type_Clothing); break; case ESM::REC_CONT: mReferenceables.load(*reader, mBase, UniversalId::Type_Container); break; case ESM::REC_CREA: mReferenceables.load(*reader, mBase, UniversalId::Type_Creature); break; case ESM::REC_DOOR: mReferenceables.load(*reader, mBase, UniversalId::Type_Door); break; case ESM::REC_INGR: mReferenceables.load(*reader, mBase, UniversalId::Type_Ingredient); break; case ESM::REC_LEVC: mReferenceables.load(*reader, mBase, UniversalId::Type_CreatureLevelledList); break; case ESM::REC_LEVI: mReferenceables.load(*reader, mBase, UniversalId::Type_ItemLevelledList); break; case ESM::REC_LIGH: mReferenceables.load(*reader, mBase, UniversalId::Type_Light); break; case ESM::REC_LOCK: mReferenceables.load(*reader, mBase, UniversalId::Type_Lockpick); break; case ESM::REC_MISC: mReferenceables.load(*reader, mBase, UniversalId::Type_Miscellaneous); break; case ESM::REC_NPC_: mReferenceables.load(*reader, mBase, UniversalId::Type_Npc); break; case ESM::REC_PROB: mReferenceables.load(*reader, mBase, UniversalId::Type_Probe); break; case ESM::REC_REPA: mReferenceables.load(*reader, mBase, UniversalId::Type_Repair); break; case ESM::REC_STAT: mReferenceables.load(*reader, mBase, UniversalId::Type_Static); break; case ESM::REC_WEAP: mReferenceables.load(*reader, mBase, UniversalId::Type_Weapon); break;
case ESM::REC_DIAL: { ESM::Dialogue record; bool isDeleted = false;
record.load(*reader, isDeleted);
if (isDeleted) { // record vector can be shuffled around which would make pointer to record invalid mDialogue = nullptr;
if (mJournals.tryDelete(record.mId)) { removeDialogueInfos(record.mId, mJournalInfoOrder, mJournalInfos); } else if (mTopics.tryDelete(record.mId)) { removeDialogueInfos(record.mId, mTopicInfoOrder, mTopicInfos); } else { messages.add(UniversalId::Type_None, "Trying to delete dialogue record " + record.mId.getRefIdString() + " 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);
reader->skipRecord(); break; }
if (mDialogue->mType == ESM::Dialogue::Journal) mJournalInfos.load(*reader, mBase, *mDialogue, mJournalInfoOrder); else mTopicInfos.load(*reader, mBase, *mDialogue, mTopicInfoOrder);
break; }
case ESM::REC_FILT:
if (!mProject) { unhandledRecord = true; break; }
mFilters.load(*reader, mBase); break;
case ESM::REC_DBGP:
if (!mProject) { unhandledRecord = true; break; }
mDebugProfiles.load(*reader, mBase); break;
case ESM::REC_SELG:
if (!mProject) { unhandledRecord = true; break; }
mSelectionGroups.load(*reader, mBase); break;
default:
unhandledRecord = true; }
if (unhandledRecord) { messages.add( UniversalId::Type_None, "Unsupported record type: " + n.toString(), "", CSMDoc::Message::Severity_Error);
reader->skipRecord(); }
return false;}
void CSMWorld::Data::finishLoading(){ mTopicInfos.sort(mTopicInfoOrder); mJournalInfos.sort(mJournalInfoOrder); // Release file locks so we can actually write to the file we're editing mReaders.clear();}
bool CSMWorld::Data::hasId(const std::string& id) const{ const ESM::RefId refId = ESM::RefId::stringRefId(id); return getGlobals().searchId(refId) != -1 || getGmsts().searchId(refId) != -1 || getSkills().searchId(refId) != -1 || getClasses().searchId(refId) != -1 || getFactions().searchId(refId) != -1 || getRaces().searchId(refId) != -1 || getSounds().searchId(refId) != -1 || getScripts().searchId(refId) != -1 || getRegions().searchId(refId) != -1 || getBirthsigns().searchId(refId) != -1 || getSpells().searchId(refId) != -1 || getTopics().searchId(refId) != -1 || getJournals().searchId(refId) != -1 || getCells().searchId(refId) != -1 || getEnchantments().searchId(refId) != -1 || getBodyParts().searchId(refId) != -1 || getSoundGens().searchId(refId) != -1 || getMagicEffects().searchId(refId) != -1 || getReferenceables().searchId(refId) != -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) + count(state, mTopics) + count(state, mTopicInfos) + count(state, mJournals) + count(state, mJournalInfos);}
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), mArchives, true, &mEncoder.getStatelessEncoder());
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();}