mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-01-25 06:35:30 +00:00
added data structures for referenceable records
This commit is contained in:
parent
b21dae8d75
commit
e9f1aac7bd
@ -22,7 +22,8 @@ opencs_units (model/world
|
||||
|
||||
|
||||
opencs_units_noqt (model/world
|
||||
universalid data record idcollection commands columnbase scriptcontext cell
|
||||
universalid data record idcollection commands columnbase scriptcontext cell refidcollection
|
||||
refidadapter refiddata
|
||||
)
|
||||
|
||||
opencs_hdrs_noqt (model/world
|
||||
|
6
apps/opencs/model/world/refidadapter.cpp
Normal file
6
apps/opencs/model/world/refidadapter.cpp
Normal file
@ -0,0 +1,6 @@
|
||||
|
||||
#include "refidadapter.hpp"
|
||||
|
||||
CSMWorld::RefIdAdapter::RefIdAdapter() {}
|
||||
|
||||
CSMWorld::RefIdAdapter::~RefIdAdapter() {}
|
36
apps/opencs/model/world/refidadapter.hpp
Normal file
36
apps/opencs/model/world/refidadapter.hpp
Normal file
@ -0,0 +1,36 @@
|
||||
#ifndef CSM_WOLRD_REDIDADAPTER_H
|
||||
#define CSM_WOLRD_REFIDADAPTER_H
|
||||
|
||||
#include <string>
|
||||
|
||||
class QVariant;
|
||||
|
||||
namespace CSMWorld
|
||||
{
|
||||
class RefIdColumn;
|
||||
class RefIdData;
|
||||
class RecordBase;
|
||||
|
||||
class RefIdAdapter
|
||||
{
|
||||
// not implemented
|
||||
RefIdAdapter (const RefIdAdapter&);
|
||||
RefIdAdapter& operator= (const RefIdAdapter&);
|
||||
|
||||
public:
|
||||
|
||||
RefIdAdapter();
|
||||
|
||||
virtual ~RefIdAdapter();
|
||||
|
||||
virtual QVariant getData (const RefIdColumn *column, const RefIdData& data) const = 0;
|
||||
|
||||
virtual void setData (const RefIdColumn *column, RefIdData& data, const QVariant& value)
|
||||
const = 0;
|
||||
///< If the data type does not match an exception is thrown.
|
||||
|
||||
virtual std::string getId (const RecordBase& record) const = 0;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
202
apps/opencs/model/world/refidcollection.cpp
Normal file
202
apps/opencs/model/world/refidcollection.cpp
Normal file
@ -0,0 +1,202 @@
|
||||
|
||||
#include "refidcollection.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include "refidadapter.hpp"
|
||||
|
||||
CSMWorld::RefIdColumn::RefIdColumn (const std::string& title, Display displayType, int flag,
|
||||
bool editable, bool userEditable)
|
||||
: ColumnBase (title, displayType, flag), mEditable (editable), mUserEditable (userEditable)
|
||||
{}
|
||||
|
||||
bool CSMWorld::RefIdColumn::isEditable() const
|
||||
{
|
||||
return mEditable;
|
||||
}
|
||||
|
||||
bool CSMWorld::RefIdColumn::isUserEditable() const
|
||||
{
|
||||
return mUserEditable;
|
||||
}
|
||||
|
||||
|
||||
const CSMWorld::RefIdAdapter& CSMWorld::RefIdCollection::findAdaptor (UniversalId::Type type) const
|
||||
{
|
||||
std::map<UniversalId::Type, RefIdAdapter *>::const_iterator iter = mAdapters.find (type);
|
||||
|
||||
if (iter==mAdapters.end())
|
||||
throw std::logic_error ("unsupported type in RefIdCollection");
|
||||
|
||||
return *iter->second;
|
||||
}
|
||||
|
||||
CSMWorld::RefIdCollection::RefIdCollection()
|
||||
{
|
||||
mColumns.push_back (RefIdColumn ("ID", ColumnBase::Display_String,
|
||||
ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue, false, false));
|
||||
mColumns.push_back (RefIdColumn ("*", ColumnBase::Display_Integer,
|
||||
ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue, false, false));
|
||||
mColumns.push_back (RefIdColumn ("Name", ColumnBase::Display_String));
|
||||
}
|
||||
|
||||
CSMWorld::RefIdCollection::~RefIdCollection()
|
||||
{
|
||||
for (std::map<UniversalId::Type, RefIdAdapter *>::iterator iter (mAdapters.begin());
|
||||
iter!=mAdapters.end(); ++iter)
|
||||
delete iter->second;
|
||||
}
|
||||
|
||||
int CSMWorld::RefIdCollection::getSize() const
|
||||
{
|
||||
return mData.getSize();
|
||||
}
|
||||
|
||||
std::string CSMWorld::RefIdCollection::getId (int index) const
|
||||
{
|
||||
return getData (index, 0).toString().toUtf8().constData();
|
||||
}
|
||||
|
||||
int CSMWorld::RefIdCollection::getIndex (const std::string& id) const
|
||||
{
|
||||
int index = searchId (id);
|
||||
|
||||
if (index==-1)
|
||||
throw std::runtime_error ("invalid ID: " + id);
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
int CSMWorld::RefIdCollection::getColumns() const
|
||||
{
|
||||
return mColumns.size();
|
||||
}
|
||||
|
||||
const CSMWorld::ColumnBase& CSMWorld::RefIdCollection::getColumn (int column) const
|
||||
{
|
||||
return mColumns.at (column);
|
||||
}
|
||||
|
||||
QVariant CSMWorld::RefIdCollection::getData (int index, int column) const
|
||||
{
|
||||
RefIdData::LocalIndex localIndex = mData.globalToLocalIndex (index);
|
||||
|
||||
const RefIdAdapter& adaptor = findAdaptor (localIndex.second);
|
||||
|
||||
return adaptor.getData (&mColumns.at (column), mData);
|
||||
}
|
||||
|
||||
void CSMWorld::RefIdCollection::setData (int index, int column, const QVariant& data)
|
||||
{
|
||||
RefIdData::LocalIndex localIndex = mData.globalToLocalIndex (index);
|
||||
|
||||
const RefIdAdapter& adaptor = findAdaptor (localIndex.second);
|
||||
|
||||
adaptor.setData (&mColumns.at (column), mData, data);
|
||||
}
|
||||
|
||||
void CSMWorld::RefIdCollection::removeRows (int index, int count)
|
||||
{
|
||||
mData.erase (index, count);
|
||||
}
|
||||
|
||||
void CSMWorld::RefIdCollection::appendBlankRecord (const std::string& id, UniversalId::Type type)
|
||||
{
|
||||
mData.appendRecord (type, id);
|
||||
}
|
||||
|
||||
int CSMWorld::RefIdCollection::searchId (const std::string& id) const
|
||||
{
|
||||
return mData.localToGlobalIndex (mData.searchId (id));
|
||||
}
|
||||
|
||||
void CSMWorld::RefIdCollection::replace (int index, const RecordBase& record)
|
||||
{
|
||||
mData.getRecord (mData.globalToLocalIndex (index)).assign (record);
|
||||
}
|
||||
|
||||
void CSMWorld::RefIdCollection::appendRecord (const RecordBase& record,
|
||||
UniversalId::Type type)
|
||||
{
|
||||
std::string id = findAdaptor (type).getId (record);
|
||||
|
||||
int index = mData.getAppendIndex (type);
|
||||
|
||||
mData.appendRecord (type, id);
|
||||
|
||||
mData.getRecord (mData.globalToLocalIndex (index)).assign (record);
|
||||
}
|
||||
|
||||
const CSMWorld::RecordBase& CSMWorld::RefIdCollection::getRecord (const std::string& id) const
|
||||
{
|
||||
return mData.getRecord (mData.searchId (id));
|
||||
}
|
||||
|
||||
const CSMWorld::RecordBase& CSMWorld::RefIdCollection::getRecord (int index) const
|
||||
{
|
||||
return mData.getRecord (mData.globalToLocalIndex (index));
|
||||
}
|
||||
|
||||
void CSMWorld::RefIdCollection::load (ESM::ESMReader& reader, bool base, UniversalId::Type type)
|
||||
{
|
||||
std::string id = reader.getHNOString ("NAME");
|
||||
|
||||
int index = searchId (id);
|
||||
|
||||
if (reader.isNextSub ("DELE"))
|
||||
{
|
||||
reader.skipRecord();
|
||||
|
||||
if (index==-1)
|
||||
{
|
||||
// deleting a record that does not exist
|
||||
|
||||
// ignore it for now
|
||||
|
||||
/// \todo report the problem to the user
|
||||
}
|
||||
else if (base)
|
||||
{
|
||||
mData.erase (index, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
mData.getRecord (mData.globalToLocalIndex (index)).mState = RecordBase::State_Deleted;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (index==-1)
|
||||
{
|
||||
// new record
|
||||
int index = mData.getAppendIndex (type);
|
||||
mData.appendRecord (type, id);
|
||||
|
||||
RefIdData::LocalIndex localIndex = mData.globalToLocalIndex (index);
|
||||
|
||||
mData.load (localIndex, reader, base);
|
||||
|
||||
mData.getRecord (localIndex).mState =
|
||||
base ? RecordBase::State_BaseOnly : RecordBase::State_ModifiedOnly;
|
||||
}
|
||||
else
|
||||
{
|
||||
// old record
|
||||
RefIdData::LocalIndex localIndex = mData.globalToLocalIndex (index);
|
||||
|
||||
if (!base)
|
||||
if (mData.getRecord (localIndex).mState==RecordBase::State_Erased)
|
||||
throw std::logic_error ("attempt to access a deleted record");
|
||||
|
||||
mData.load (localIndex, reader, base);
|
||||
|
||||
if (!base)
|
||||
mData.getRecord (localIndex).mState = RecordBase::State_Modified;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int CSMWorld::RefIdCollection::getAppendIndex (UniversalId::Type type) const
|
||||
{
|
||||
return mData.getAppendIndex (type);
|
||||
}
|
95
apps/opencs/model/world/refidcollection.hpp
Normal file
95
apps/opencs/model/world/refidcollection.hpp
Normal file
@ -0,0 +1,95 @@
|
||||
#ifndef CSM_WOLRD_REFIDCOLLECTION_H
|
||||
#define CSM_WOLRD_REFIDCOLLECTION_H
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include "columnbase.hpp"
|
||||
#include "idcollection.hpp"
|
||||
#include "refiddata.hpp"
|
||||
|
||||
namespace CSMWorld
|
||||
{
|
||||
class RefIdAdapter;
|
||||
|
||||
class RefIdColumn : public ColumnBase
|
||||
{
|
||||
bool mEditable;
|
||||
bool mUserEditable;
|
||||
|
||||
public:
|
||||
|
||||
RefIdColumn (const std::string& title, Display displayType,
|
||||
int flag = Flag_Table | Flag_Dialogue, bool editable = true,
|
||||
bool userEditable = true);
|
||||
|
||||
virtual bool isEditable() const;
|
||||
|
||||
virtual bool isUserEditable() const;
|
||||
};
|
||||
|
||||
class RefIdCollection : public IdCollectionBase
|
||||
{
|
||||
private:
|
||||
|
||||
RefIdData mData;
|
||||
std::vector<RefIdColumn> mColumns;
|
||||
std::map<UniversalId::Type, RefIdAdapter *> mAdapters;
|
||||
|
||||
private:
|
||||
|
||||
const RefIdAdapter& findAdaptor (UniversalId::Type) const;
|
||||
///< Throws an exception if no adaptor for \a Type can be found.
|
||||
|
||||
public:
|
||||
|
||||
RefIdCollection();
|
||||
|
||||
virtual ~RefIdCollection();
|
||||
|
||||
virtual int getSize() const;
|
||||
|
||||
virtual std::string getId (int index) const;
|
||||
|
||||
virtual int getIndex (const std::string& id) const;
|
||||
|
||||
virtual int getColumns() const;
|
||||
|
||||
virtual const ColumnBase& getColumn (int column) const;
|
||||
|
||||
virtual QVariant getData (int index, int column) const;
|
||||
|
||||
virtual void setData (int index, int column, const QVariant& data);
|
||||
|
||||
virtual void removeRows (int index, int count);
|
||||
|
||||
virtual void appendBlankRecord (const std::string& id, UniversalId::Type type);
|
||||
///< \param type Will be ignored, unless the collection supports multiple record types
|
||||
|
||||
virtual int searchId (const std::string& id) const;
|
||||
////< Search record with \a id.
|
||||
/// \return index of record (if found) or -1 (not found)
|
||||
|
||||
virtual void replace (int index, const RecordBase& record);
|
||||
///< If the record type does not match, an exception is thrown.
|
||||
///
|
||||
/// \attention \a record must not change the ID.
|
||||
|
||||
virtual void appendRecord (const RecordBase& record, UniversalId::Type type);
|
||||
///< If the record type does not match, an exception is thrown.
|
||||
///
|
||||
///< \param type Will be ignored, unless the collection supports multiple record types
|
||||
|
||||
virtual const RecordBase& getRecord (const std::string& id) const;
|
||||
|
||||
virtual const RecordBase& getRecord (int index) const;
|
||||
|
||||
virtual void load (ESM::ESMReader& reader, bool base, UniversalId::Type type);
|
||||
|
||||
virtual int getAppendIndex (UniversalId::Type type) const;
|
||||
///< \param type Will be ignored, unless the collection supports multiple record types
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
198
apps/opencs/model/world/refiddata.cpp
Normal file
198
apps/opencs/model/world/refiddata.cpp
Normal file
@ -0,0 +1,198 @@
|
||||
|
||||
#include "refiddata.hpp"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include <components/misc/stringops.hpp>
|
||||
|
||||
CSMWorld::RefIdDataContainerBase::~RefIdDataContainerBase() {}
|
||||
|
||||
CSMWorld::RefIdData::RefIdData()
|
||||
{
|
||||
mRecordContainers.insert (std::make_pair (UniversalId::Type_Activator, &mActivators));
|
||||
mRecordContainers.insert (std::make_pair (UniversalId::Type_Potion, &mPotions));
|
||||
mRecordContainers.insert (std::make_pair (UniversalId::Type_Apparatus, &mApparati));
|
||||
mRecordContainers.insert (std::make_pair (UniversalId::Type_Armor, &mArmors));
|
||||
mRecordContainers.insert (std::make_pair (UniversalId::Type_Book, &mBooks));
|
||||
mRecordContainers.insert (std::make_pair (UniversalId::Type_Clothing, &mClothing));
|
||||
mRecordContainers.insert (std::make_pair (UniversalId::Type_Container, &mContainers));
|
||||
mRecordContainers.insert (std::make_pair (UniversalId::Type_Creature, &mCreatures));
|
||||
mRecordContainers.insert (std::make_pair (UniversalId::Type_Door, &mDoors));
|
||||
mRecordContainers.insert (std::make_pair (UniversalId::Type_Ingredient, &mIngredients));
|
||||
mRecordContainers.insert (std::make_pair (UniversalId::Type_CreatureLevelledList,
|
||||
&mCreatureLevelledLists));
|
||||
mRecordContainers.insert (std::make_pair (UniversalId::Type_ItemLevelledList, &mItemLevelledLists));
|
||||
mRecordContainers.insert (std::make_pair (UniversalId::Type_Light, &mLights));
|
||||
mRecordContainers.insert (std::make_pair (UniversalId::Type_Lockpick, &mLockpicks));
|
||||
mRecordContainers.insert (std::make_pair (UniversalId::Type_Miscellaneous, &mMiscellaneous));
|
||||
mRecordContainers.insert (std::make_pair (UniversalId::Type_Npc, &mNpcs));
|
||||
mRecordContainers.insert (std::make_pair (UniversalId::Type_Probe, &mProbes));
|
||||
mRecordContainers.insert (std::make_pair (UniversalId::Type_Repair, &mRepairs));
|
||||
mRecordContainers.insert (std::make_pair (UniversalId::Type_Static, &mStatics));
|
||||
mRecordContainers.insert (std::make_pair (UniversalId::Type_Weapon, &mWeapons));
|
||||
}
|
||||
|
||||
CSMWorld::RefIdData::LocalIndex CSMWorld::RefIdData::globalToLocalIndex (int index) const
|
||||
{
|
||||
for (std::map<UniversalId::Type, RefIdDataContainerBase *>::const_iterator iter (
|
||||
mRecordContainers.begin()); iter!=mRecordContainers.end(); ++iter)
|
||||
{
|
||||
if (index<iter->second->getSize())
|
||||
return LocalIndex (index, iter->first);
|
||||
|
||||
index -= iter->second->getSize();
|
||||
}
|
||||
|
||||
throw std::runtime_error ("RefIdData index out of range");
|
||||
}
|
||||
|
||||
int CSMWorld::RefIdData::localToGlobalIndex (const LocalIndex& index)
|
||||
const
|
||||
{
|
||||
std::map<UniversalId::Type, RefIdDataContainerBase *>::const_iterator end =
|
||||
mRecordContainers.find (index.second);
|
||||
|
||||
if (end==mRecordContainers.end())
|
||||
throw std::logic_error ("invalid local index type");
|
||||
|
||||
int globalIndex = index.first;
|
||||
|
||||
for (std::map<UniversalId::Type, RefIdDataContainerBase *>::const_iterator iter (
|
||||
mRecordContainers.begin()); iter!=end; ++iter)
|
||||
globalIndex += iter->second->getSize();
|
||||
|
||||
return globalIndex;
|
||||
}
|
||||
|
||||
CSMWorld::RefIdData::LocalIndex CSMWorld::RefIdData::searchId (
|
||||
const std::string& id) const
|
||||
{
|
||||
std::string id2 = Misc::StringUtils::lowerCase (id);
|
||||
|
||||
std::map<std::string, std::pair<int, UniversalId::Type> >::const_iterator iter = mIndex.find (id2);
|
||||
|
||||
if (iter!=mIndex.end())
|
||||
return std::make_pair (-1, CSMWorld::UniversalId::Type_None);
|
||||
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
void CSMWorld::RefIdData::erase (int index, int count)
|
||||
{
|
||||
LocalIndex localIndex = globalToLocalIndex (index);
|
||||
|
||||
std::map<UniversalId::Type, RefIdDataContainerBase *>::const_iterator iter =
|
||||
mRecordContainers.find (localIndex.second);
|
||||
|
||||
while (count>0 && iter!=mRecordContainers.end())
|
||||
{
|
||||
int size = iter->second->getSize();
|
||||
|
||||
if (localIndex.first+count>size)
|
||||
{
|
||||
erase (localIndex, size-localIndex.first);
|
||||
count -= size-localIndex.first;
|
||||
|
||||
++iter;
|
||||
|
||||
if (iter==mRecordContainers.end())
|
||||
throw std::runtime_error ("invalid count value for erase operation");
|
||||
|
||||
localIndex.first = 0;
|
||||
localIndex.second = iter->first;
|
||||
}
|
||||
else
|
||||
{
|
||||
erase (localIndex, count);
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const CSMWorld::RecordBase& CSMWorld::RefIdData::getRecord (const LocalIndex& index) const
|
||||
{
|
||||
std::map<UniversalId::Type, RefIdDataContainerBase *>::const_iterator iter =
|
||||
mRecordContainers.find (index.second);
|
||||
|
||||
if (iter==mRecordContainers.end())
|
||||
throw std::logic_error ("invalid local index type");
|
||||
|
||||
return iter->second->getRecord (index.first);
|
||||
}
|
||||
|
||||
CSMWorld::RecordBase& CSMWorld::RefIdData::getRecord (const LocalIndex& index)
|
||||
{
|
||||
std::map<UniversalId::Type, RefIdDataContainerBase *>::iterator iter =
|
||||
mRecordContainers.find (index.second);
|
||||
|
||||
if (iter==mRecordContainers.end())
|
||||
throw std::logic_error ("invalid local index type");
|
||||
|
||||
return iter->second->getRecord (index.first);
|
||||
}
|
||||
|
||||
void CSMWorld::RefIdData::appendRecord (UniversalId::Type type, const std::string& id)
|
||||
{
|
||||
std::map<UniversalId::Type, RefIdDataContainerBase *>::iterator iter =
|
||||
mRecordContainers.find (type);
|
||||
|
||||
if (iter==mRecordContainers.end())
|
||||
throw std::logic_error ("invalid local index type");
|
||||
|
||||
iter->second->appendRecord (id);
|
||||
|
||||
mIndex.insert (std::make_pair (Misc::StringUtils::lowerCase (id),
|
||||
LocalIndex (iter->second->getSize()-1, type)));
|
||||
}
|
||||
|
||||
int CSMWorld::RefIdData::getAppendIndex (UniversalId::Type type) const
|
||||
{
|
||||
int index = 0;
|
||||
|
||||
for (std::map<UniversalId::Type, RefIdDataContainerBase *>::const_iterator iter (
|
||||
mRecordContainers.begin()); iter!=mRecordContainers.end(); ++iter)
|
||||
{
|
||||
index += iter->second->getSize();
|
||||
|
||||
if (type==iter->first)
|
||||
break;
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
void CSMWorld::RefIdData::load (const LocalIndex& index, ESM::ESMReader& reader, bool base)
|
||||
{
|
||||
std::map<UniversalId::Type, RefIdDataContainerBase *>::iterator iter =
|
||||
mRecordContainers.find (index.second);
|
||||
|
||||
if (iter==mRecordContainers.end())
|
||||
throw std::logic_error ("invalid local index type");
|
||||
|
||||
iter->second->load (index.first, reader, base);
|
||||
}
|
||||
|
||||
void CSMWorld::RefIdData::erase (const LocalIndex& index, int count)
|
||||
{
|
||||
std::map<UniversalId::Type, RefIdDataContainerBase *>::iterator iter =
|
||||
mRecordContainers.find (index.second);
|
||||
|
||||
if (iter==mRecordContainers.end())
|
||||
throw std::logic_error ("invalid local index type");
|
||||
|
||||
for (int i=index.first; i<index.first+count; ++i)
|
||||
{
|
||||
std::map<std::string, LocalIndex>::iterator result =
|
||||
mIndex.find (Misc::StringUtils::lowerCase (iter->second->getId (i)));
|
||||
|
||||
if (result!=mIndex.end())
|
||||
mIndex.erase (result);
|
||||
}
|
||||
|
||||
iter->second->erase (index.first, count);
|
||||
}
|
||||
|
||||
int CSMWorld::RefIdData::getSize() const
|
||||
{
|
||||
return mIndex.size();
|
||||
}
|
188
apps/opencs/model/world/refiddata.hpp
Normal file
188
apps/opencs/model/world/refiddata.hpp
Normal file
@ -0,0 +1,188 @@
|
||||
#ifndef CSM_WOLRD_REFIDDATA_H
|
||||
#define CSM_WOLRD_REFIDDATA_H
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include <components/esm/loadacti.hpp>
|
||||
#include <components/esm/loadalch.hpp>
|
||||
#include <components/esm/loadappa.hpp>
|
||||
#include <components/esm/loadarmo.hpp>
|
||||
#include <components/esm/loadbook.hpp>
|
||||
#include <components/esm/loadclot.hpp>
|
||||
#include <components/esm/loadcont.hpp>
|
||||
#include <components/esm/loadcrea.hpp>
|
||||
#include <components/esm/loaddoor.hpp>
|
||||
#include <components/esm/loadingr.hpp>
|
||||
#include <components/esm/loadlevlist.hpp>
|
||||
#include <components/esm/loadligh.hpp>
|
||||
#include <components/esm/loadlock.hpp>
|
||||
#include <components/esm/loadprob.hpp>
|
||||
#include <components/esm/loadrepa.hpp>
|
||||
#include <components/esm/loadstat.hpp>
|
||||
#include <components/esm/loadweap.hpp>
|
||||
#include <components/esm/loadnpc.hpp>
|
||||
#include <components/esm/loadmisc.hpp>
|
||||
|
||||
#include "record.hpp"
|
||||
#include "universalid.hpp"
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
class ESMReader;
|
||||
}
|
||||
|
||||
namespace CSMWorld
|
||||
{
|
||||
struct RefIdDataContainerBase
|
||||
{
|
||||
virtual ~RefIdDataContainerBase();
|
||||
|
||||
virtual int getSize() const = 0;
|
||||
|
||||
virtual const RecordBase& getRecord (int index) const = 0;
|
||||
|
||||
virtual RecordBase& getRecord (int index)= 0;
|
||||
|
||||
virtual void appendRecord (const std::string& id) = 0;
|
||||
|
||||
virtual void load (int index, ESM::ESMReader& reader, bool base) = 0;
|
||||
|
||||
virtual void erase (int index, int count) = 0;
|
||||
|
||||
virtual std::string getId (int index) const = 0;
|
||||
};
|
||||
|
||||
template<typename RecordT>
|
||||
struct RefIdDataContainer : public RefIdDataContainerBase
|
||||
{
|
||||
std::vector<Record<RecordT> > mContainer;
|
||||
|
||||
virtual int getSize() const;
|
||||
|
||||
virtual const RecordBase& getRecord (int index) const;
|
||||
|
||||
virtual RecordBase& getRecord (int index);
|
||||
|
||||
virtual void appendRecord (const std::string& id);
|
||||
|
||||
virtual void load (int index, ESM::ESMReader& reader, bool base);
|
||||
|
||||
virtual void erase (int index, int count);
|
||||
|
||||
virtual std::string getId (int index) const;
|
||||
};
|
||||
|
||||
template<typename RecordT>
|
||||
int RefIdDataContainer<RecordT>::getSize() const
|
||||
{
|
||||
return static_cast<int> (mContainer.size());
|
||||
}
|
||||
|
||||
template<typename RecordT>
|
||||
const RecordBase& RefIdDataContainer<RecordT>::getRecord (int index) const
|
||||
{
|
||||
return mContainer.at (index);
|
||||
}
|
||||
|
||||
template<typename RecordT>
|
||||
RecordBase& RefIdDataContainer<RecordT>::getRecord (int index)
|
||||
{
|
||||
return mContainer.at (index);
|
||||
}
|
||||
|
||||
template<typename RecordT>
|
||||
void RefIdDataContainer<RecordT>::appendRecord (const std::string& id)
|
||||
{
|
||||
Record<RecordT> record;
|
||||
record.mModified.mId = id;
|
||||
record.mModified.blank();
|
||||
record.mState = RecordBase::State_ModifiedOnly;
|
||||
|
||||
mContainer.push_back (record);
|
||||
}
|
||||
|
||||
template<typename RecordT>
|
||||
void RefIdDataContainer<RecordT>::load (int index, ESM::ESMReader& reader, bool base)
|
||||
{
|
||||
(base ? mContainer.at (index).mBase : mContainer.at (index).mModified).load (reader);
|
||||
}
|
||||
|
||||
template<typename RecordT>
|
||||
void RefIdDataContainer<RecordT>::erase (int index, int count)
|
||||
{
|
||||
if (index<0 || index+count>=getSize())
|
||||
throw std::runtime_error ("invalid RefIdDataContainer index");
|
||||
|
||||
mContainer.erase (mContainer.begin()+index, mContainer.begin()+index+count);
|
||||
}
|
||||
|
||||
template<typename RecordT>
|
||||
std::string RefIdDataContainer<RecordT>::getId (int index) const
|
||||
{
|
||||
return mContainer.at (index).get().mId;
|
||||
}
|
||||
|
||||
class RefIdData
|
||||
{
|
||||
public:
|
||||
|
||||
typedef std::pair<int, UniversalId::Type> LocalIndex;
|
||||
|
||||
private:
|
||||
|
||||
RefIdDataContainer<ESM::Activator> mActivators;
|
||||
RefIdDataContainer<ESM::Potion> mPotions;
|
||||
RefIdDataContainer<ESM::Apparatus> mApparati;
|
||||
RefIdDataContainer<ESM::Armor> mArmors;
|
||||
RefIdDataContainer<ESM::Book> mBooks;
|
||||
RefIdDataContainer<ESM::Clothing> mClothing;
|
||||
RefIdDataContainer<ESM::Container> mContainers;
|
||||
RefIdDataContainer<ESM::Creature> mCreatures;
|
||||
RefIdDataContainer<ESM::Door> mDoors;
|
||||
RefIdDataContainer<ESM::Ingredient> mIngredients;
|
||||
RefIdDataContainer<ESM::CreatureLevList> mCreatureLevelledLists;
|
||||
RefIdDataContainer<ESM::ItemLevList> mItemLevelledLists;
|
||||
RefIdDataContainer<ESM::Light> mLights;
|
||||
RefIdDataContainer<ESM::Lockpick> mLockpicks;
|
||||
RefIdDataContainer<ESM::Miscellaneous> mMiscellaneous;
|
||||
RefIdDataContainer<ESM::NPC> mNpcs;
|
||||
RefIdDataContainer<ESM::Probe> mProbes;
|
||||
RefIdDataContainer<ESM::Repair> mRepairs;
|
||||
RefIdDataContainer<ESM::Static> mStatics;
|
||||
RefIdDataContainer<ESM::Weapon> mWeapons;
|
||||
|
||||
std::map<std::string, LocalIndex> mIndex;
|
||||
|
||||
std::map<UniversalId::Type, RefIdDataContainerBase *> mRecordContainers;
|
||||
|
||||
void erase (const LocalIndex& index, int count);
|
||||
///< Must not spill over into another type.
|
||||
|
||||
public:
|
||||
|
||||
RefIdData();
|
||||
|
||||
LocalIndex globalToLocalIndex (int index) const;
|
||||
|
||||
int localToGlobalIndex (const LocalIndex& index) const;
|
||||
|
||||
LocalIndex searchId (const std::string& id) const;
|
||||
|
||||
void erase (int index, int count);
|
||||
|
||||
const RecordBase& getRecord (const LocalIndex& index) const;
|
||||
|
||||
RecordBase& getRecord (const LocalIndex& index);
|
||||
|
||||
void appendRecord (UniversalId::Type type, const std::string& id);
|
||||
|
||||
int getAppendIndex (UniversalId::Type type) const;
|
||||
|
||||
void load (const LocalIndex& index, ESM::ESMReader& reader, bool base);
|
||||
|
||||
int getSize() const;
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
Loading…
x
Reference in New Issue
Block a user