1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-01-20 16:53:55 +00:00
openmw/apps/opencs/model/world/idcollection.hpp

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

176 lines
5.1 KiB
C++
Raw Normal View History

#ifndef CSM_WOLRD_IDCOLLECTION_H
#define CSM_WOLRD_IDCOLLECTION_H
2022-10-19 17:02:00 +00:00
#include <filesystem>
#include <memory>
#include <string>
#include <apps/opencs/model/world/record.hpp>
#include <components/esm/esmcommon.hpp>
#include <components/esm3/loadland.hpp>
2013-02-07 11:52:01 +00:00
#include "collection.hpp"
#include "land.hpp"
#include "pathgrid.hpp"
2013-02-07 11:52:01 +00:00
2022-10-19 17:02:00 +00:00
namespace ESM
{
class ESMReader;
}
namespace CSMWorld
{
2022-10-19 17:02:00 +00:00
struct Pathgrid;
/// \brief Single type collection of top level records
template <typename ESXRecordT>
class IdCollection : public Collection<ESXRecordT>
{
virtual void loadRecord(ESXRecordT& record, ESM::ESMReader& reader, bool& isDeleted);
2022-09-22 18:26:05 +00:00
public:
/// \return Index of loaded record (-1 if no record was loaded)
int load(ESM::ESMReader& reader, bool base);
2022-09-22 18:26:05 +00:00
/// \param index Index at which the record can be found.
/// Special values: -2 index unknown, -1 record does not exist yet and therefore
/// does not have an index
///
/// \return index
int load(const ESXRecordT& record, bool base, int index = -2);
2022-09-22 18:26:05 +00:00
bool tryDelete(const ESM::RefId& id);
2013-10-21 13:38:13 +00:00
///< Try deleting \a id. If the id does not exist or can't be deleted the call is ignored.
///
/// \return Has the ID been deleted?
};
template <typename ESXRecordT>
void IdCollection<ESXRecordT>::loadRecord(ESXRecordT& record, ESM::ESMReader& reader, bool& isDeleted)
2014-10-04 13:36:52 +00:00
{
record.load(reader, isDeleted);
2014-10-04 13:36:52 +00:00
}
template <>
inline void IdCollection<Land>::loadRecord(Land& record, ESM::ESMReader& reader, bool& isDeleted)
{
record.load(reader, isDeleted);
// Load all land data for now. A future optimisation may only load non-base data
// if a suitable mechanism for avoiding race conditions can be established.
int flags = ESM::Land::DATA_VHGT | ESM::Land::DATA_VNML | ESM::Land::DATA_VCLR | ESM::Land::DATA_VTEX;
record.loadData(flags);
// Prevent data from being reloaded.
record.mContext.filename.clear();
}
template <typename ESXRecordT>
int IdCollection<ESXRecordT>::load(ESM::ESMReader& reader, bool base)
2013-02-07 11:52:01 +00:00
{
ESXRecordT record;
bool isDeleted = false;
loadRecord(record, reader, isDeleted);
if constexpr (std::is_same_v<ESXRecordT, LandTexture>)
{
// This doesn't really matter since the value never gets saved, but it makes the index uniqueness check more
// sensible
if (!base)
record.mPluginIndex = -1;
}
2013-02-07 11:52:01 +00:00
ESM::RefId id = getRecordId(record);
2015-07-19 20:27:51 +00:00
int index = this->searchId(id);
2013-02-07 11:52:01 +00:00
if (isDeleted)
{
2013-02-07 12:26:00 +00:00
if (index == -1)
{
// deleting a record that does not exist
// ignore it for now
/// \todo report the problem to the user
return -1;
2013-02-07 12:26:00 +00:00
}
if (base)
2013-02-07 12:26:00 +00:00
{
2015-07-19 20:27:51 +00:00
this->removeRows(index, 1);
return -1;
2013-02-07 12:26:00 +00:00
}
2022-05-29 11:25:17 +00:00
auto baseRecord = std::make_unique<Record<ESXRecordT>>(this->getRecord(index));
baseRecord->mState = RecordBase::State_Deleted;
this->setRecord(index, std::move(baseRecord));
return index;
2013-02-07 11:52:01 +00:00
}
return load(record, base, index);
2013-10-20 15:13:31 +00:00
}
2013-04-14 15:04:55 +00:00
template <typename ESXRecordT>
int IdCollection<ESXRecordT>::load(const ESXRecordT& record, bool base, int index)
2013-10-20 15:13:31 +00:00
{
if (index == -2) // index unknown
index = this->searchId(getRecordId(record));
2013-02-07 11:52:01 +00:00
2013-10-20 15:13:31 +00:00
if (index == -1)
{
// new record
2022-05-29 11:25:17 +00:00
auto record2 = std::make_unique<Record<ESXRecordT>>();
record2->mState = base ? RecordBase::State_BaseOnly : RecordBase::State_ModifiedOnly;
(base ? record2->mBase : record2->mModified) = record;
2013-10-20 15:13:31 +00:00
index = this->getSize();
this->appendRecord(std::move(record2));
2013-10-20 15:13:31 +00:00
}
else
{
// old record
auto record2 = std::make_unique<Record<ESXRecordT>>(Collection<ESXRecordT>::getRecord(index));
2013-02-07 12:26:00 +00:00
2013-10-20 15:13:31 +00:00
if (base)
record2->mBase = record;
2013-10-20 15:13:31 +00:00
else
record2->setModified(record);
this->setRecord(index, std::move(record2));
2013-02-07 11:52:01 +00:00
}
return index;
2013-02-07 11:52:01 +00:00
}
2013-10-21 13:38:13 +00:00
template <typename ESXRecordT>
bool IdCollection<ESXRecordT>::tryDelete(const ESM::RefId& id)
2013-10-21 13:38:13 +00:00
{
int index = this->searchId(id);
if (index == -1)
return false;
const Record<ESXRecordT>& record = Collection<ESXRecordT>::getRecord(index);
2013-10-21 13:38:13 +00:00
if (record.isDeleted())
return false;
if (record.mState == RecordBase::State_ModifiedOnly)
{
Collection<ESXRecordT>::removeRows(index, 1);
2013-10-21 13:38:13 +00:00
}
else
{
auto record2 = std::make_unique<Record<ESXRecordT>>(Collection<ESXRecordT>::getRecord(index));
record2->mState = RecordBase::State_Deleted;
this->setRecord(index, std::move(record2));
2013-10-21 13:38:13 +00:00
}
return true;
}
template <>
int IdCollection<Pathgrid>::load(ESM::ESMReader& reader, bool base);
}
#endif