forked from mirror/openmw-tes3mp
Nested table support for Pathgrids.
This commit is contained in:
parent
bdf0d8db22
commit
05210d7f21
10 changed files with 503 additions and 6 deletions
|
@ -120,6 +120,8 @@ namespace CSMWorld
|
||||||
|
|
||||||
virtual const Record<ESXRecordT>& getRecord (int index) const;
|
virtual const Record<ESXRecordT>& getRecord (int index) const;
|
||||||
|
|
||||||
|
virtual Record<ESXRecordT>& getRecord (int index);
|
||||||
|
|
||||||
virtual int getAppendIndex (const std::string& id,
|
virtual int getAppendIndex (const std::string& id,
|
||||||
UniversalId::Type type = UniversalId::Type_None) const;
|
UniversalId::Type type = UniversalId::Type_None) const;
|
||||||
///< \param type Will be ignored, unless the collection supports multiple record types
|
///< \param type Will be ignored, unless the collection supports multiple record types
|
||||||
|
@ -433,6 +435,12 @@ namespace CSMWorld
|
||||||
return mRecords.at (index);
|
return mRecords.at (index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename ESXRecordT, typename IdAccessorT>
|
||||||
|
Record<ESXRecordT>& Collection<ESXRecordT, IdAccessorT>::getRecord (int index)
|
||||||
|
{
|
||||||
|
return mRecords.at (index);
|
||||||
|
}
|
||||||
|
|
||||||
template<typename ESXRecordT, typename IdAccessorT>
|
template<typename ESXRecordT, typename IdAccessorT>
|
||||||
void Collection<ESXRecordT, IdAccessorT>::insertRecord (const RecordBase& record, int index,
|
void Collection<ESXRecordT, IdAccessorT>::insertRecord (const RecordBase& record, int index,
|
||||||
UniversalId::Type type)
|
UniversalId::Type type)
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
#include "columnbase.hpp"
|
#include "columnbase.hpp"
|
||||||
|
|
||||||
#include "columns.hpp"
|
#include "columns.hpp"
|
||||||
|
|
|
@ -97,6 +97,8 @@ namespace CSMWorld
|
||||||
Display_NestedItemList,
|
Display_NestedItemList,
|
||||||
Display_NestedSpellList,
|
Display_NestedSpellList,
|
||||||
Display_NestedDestinationsList,
|
Display_NestedDestinationsList,
|
||||||
|
Display_PathgridPointList,
|
||||||
|
Display_PathgridEdgeList,
|
||||||
|
|
||||||
Display_EnchantmentType,
|
Display_EnchantmentType,
|
||||||
Display_BodyPartType,
|
Display_BodyPartType,
|
||||||
|
|
|
@ -1277,7 +1277,6 @@ namespace CSMWorld
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
template<typename ESXRecordT>
|
template<typename ESXRecordT>
|
||||||
struct PosColumn : public Column<ESXRecordT>
|
struct PosColumn : public Column<ESXRecordT>
|
||||||
{
|
{
|
||||||
|
@ -2265,6 +2264,104 @@ namespace CSMWorld
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename ESXRecordT>
|
||||||
|
struct PathgridPointListColumn : public Column<ESXRecordT>
|
||||||
|
{
|
||||||
|
PathgridPointListColumn ()
|
||||||
|
: Column<ESXRecordT> (Columns::ColumnId_PathgridPoints,
|
||||||
|
ColumnBase::Display_PathgridPointList, ColumnBase::Flag_Dialogue)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual QVariant get (const Record<ESXRecordT>& record) const
|
||||||
|
{
|
||||||
|
return true; // required by IdTree::hasChildren()
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool isEditable() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename ESXRecordT>
|
||||||
|
struct PathgridPointColumn : public Column<ESXRecordT>
|
||||||
|
{
|
||||||
|
int mIndex; // 0=PosX, 1=PosY, 2=PosZ
|
||||||
|
|
||||||
|
PathgridPointColumn(int index)
|
||||||
|
: Column<ESXRecordT> (Columns::ColumnId_PathgridPosX+index, ColumnBase::Display_Integer), mIndex(index)
|
||||||
|
{}
|
||||||
|
|
||||||
|
virtual QVariant get (const Record<ESXRecordT>& record) const
|
||||||
|
{
|
||||||
|
return QVariant(); // FIXME
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool isEditable() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename ESXRecordT>
|
||||||
|
struct PathgridEdgeListColumn : public Column<ESXRecordT>
|
||||||
|
{
|
||||||
|
PathgridEdgeListColumn ()
|
||||||
|
: Column<ESXRecordT> (Columns::ColumnId_PathgridEdges,
|
||||||
|
ColumnBase::Display_PathgridEdgeList, ColumnBase::Flag_Dialogue)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual QVariant get (const Record<ESXRecordT>& record) const
|
||||||
|
{
|
||||||
|
return true; // required by IdTree::hasChildren()
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool isEditable() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename ESXRecordT>
|
||||||
|
struct PathgridEdgeColumn : public Column<ESXRecordT>
|
||||||
|
{
|
||||||
|
int mIndex;
|
||||||
|
|
||||||
|
PathgridEdgeColumn (int index)
|
||||||
|
: Column<ESXRecordT> (Columns::ColumnId_PathgridEdge0+index, ColumnBase::Display_Integer), mIndex(index)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual QVariant get (const Record<ESXRecordT>& record) const
|
||||||
|
{
|
||||||
|
return QVariant(); // FIXME
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool isEditable() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -223,6 +223,14 @@ namespace CSMWorld
|
||||||
{ ColumnId_AreaSound, "Area Sound" },
|
{ ColumnId_AreaSound, "Area Sound" },
|
||||||
{ ColumnId_BoltSound, "Bolt Sound" },
|
{ ColumnId_BoltSound, "Bolt Sound" },
|
||||||
|
|
||||||
|
{ ColumnId_PathgridPoints, "Points"},
|
||||||
|
{ ColumnId_PathgridPosX, "X"},
|
||||||
|
{ ColumnId_PathgridPosY, "Y"},
|
||||||
|
{ ColumnId_PathgridPosZ, "Z"},
|
||||||
|
{ ColumnId_PathgridEdges, "Edges"},
|
||||||
|
{ ColumnId_PathgridEdge0, "Edge 0"},
|
||||||
|
{ ColumnId_PathgridEdge1, "Edge 1"},
|
||||||
|
|
||||||
{ ColumnId_UseValue1, "Use value 1" },
|
{ ColumnId_UseValue1, "Use value 1" },
|
||||||
{ ColumnId_UseValue2, "Use value 2" },
|
{ ColumnId_UseValue2, "Use value 2" },
|
||||||
{ ColumnId_UseValue3, "Use value 3" },
|
{ ColumnId_UseValue3, "Use value 3" },
|
||||||
|
|
|
@ -211,6 +211,15 @@ namespace CSMWorld
|
||||||
ColumnId_HitSound = 196,
|
ColumnId_HitSound = 196,
|
||||||
ColumnId_AreaSound = 197,
|
ColumnId_AreaSound = 197,
|
||||||
ColumnId_BoltSound = 198,
|
ColumnId_BoltSound = 198,
|
||||||
|
|
||||||
|
ColumnId_PathgridPoints = 199,
|
||||||
|
ColumnId_PathgridPosX = 200,
|
||||||
|
ColumnId_PathgridPosY = 201,
|
||||||
|
ColumnId_PathgridPosZ = 202,
|
||||||
|
ColumnId_PathgridEdges = 203,
|
||||||
|
ColumnId_PathgridEdge0 = 204,
|
||||||
|
ColumnId_PathgridEdge1 = 205,
|
||||||
|
|
||||||
// Allocated to a separate value range, so we don't get a collision should we ever need
|
// Allocated to a separate value range, so we don't get a collision should we ever need
|
||||||
// to extend the number of use values.
|
// to extend the number of use values.
|
||||||
ColumnId_UseValue1 = 0x10000,
|
ColumnId_UseValue1 = 0x10000,
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include "columns.hpp"
|
#include "columns.hpp"
|
||||||
#include "resourcesmanager.hpp"
|
#include "resourcesmanager.hpp"
|
||||||
#include "resourcetable.hpp"
|
#include "resourcetable.hpp"
|
||||||
|
#include "idadapterimp.hpp"
|
||||||
|
|
||||||
void CSMWorld::Data::addModel (QAbstractItemModel *model, UniversalId::Type type, bool update)
|
void CSMWorld::Data::addModel (QAbstractItemModel *model, UniversalId::Type type, bool update)
|
||||||
{
|
{
|
||||||
|
@ -255,6 +256,22 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc
|
||||||
mPathgrids.addColumn (new RecordStateColumn<Pathgrid>);
|
mPathgrids.addColumn (new RecordStateColumn<Pathgrid>);
|
||||||
mPathgrids.addColumn (new FixedRecordTypeColumn<Pathgrid> (UniversalId::Type_Pathgrid));
|
mPathgrids.addColumn (new FixedRecordTypeColumn<Pathgrid> (UniversalId::Type_Pathgrid));
|
||||||
|
|
||||||
|
// new object deleted in dtor of Collection<T,A>
|
||||||
|
PathgridPointListColumn<Pathgrid> *pointList = new PathgridPointListColumn<Pathgrid> ();
|
||||||
|
mPathgrids.addColumn (pointList);
|
||||||
|
// new object deleted in dtor of SubCellCollection<T,A>
|
||||||
|
mPathgrids.addAdapter (std::make_pair(pointList, new PathgridPointListAdapter<Pathgrid> ()));
|
||||||
|
// new objects deleted in dtor of NestableColumn
|
||||||
|
mPathgrids.getNestableColumn(mPathgrids.getColumns()-1)->addColumn(new PathgridPointColumn<Pathgrid> (0));
|
||||||
|
mPathgrids.getNestableColumn(mPathgrids.getColumns()-1)->addColumn(new PathgridPointColumn<Pathgrid> (1));
|
||||||
|
mPathgrids.getNestableColumn(mPathgrids.getColumns()-1)->addColumn(new PathgridPointColumn<Pathgrid> (2));
|
||||||
|
|
||||||
|
PathgridEdgeListColumn<Pathgrid> *edgeList = new PathgridEdgeListColumn<Pathgrid> ();
|
||||||
|
mPathgrids.addColumn (edgeList);
|
||||||
|
mPathgrids.addAdapter (std::make_pair(edgeList, new PathgridEdgeListAdapter<Pathgrid> ()));
|
||||||
|
mPathgrids.getNestableColumn(mPathgrids.getColumns()-1)->addColumn(new PathgridEdgeColumn<Pathgrid> (0));
|
||||||
|
mPathgrids.getNestableColumn(mPathgrids.getColumns()-1)->addColumn(new PathgridEdgeColumn<Pathgrid> (1));
|
||||||
|
|
||||||
mStartScripts.addColumn (new StringIdColumn<ESM::StartScript>);
|
mStartScripts.addColumn (new StringIdColumn<ESM::StartScript>);
|
||||||
mStartScripts.addColumn (new RecordStateColumn<ESM::StartScript>);
|
mStartScripts.addColumn (new RecordStateColumn<ESM::StartScript>);
|
||||||
mStartScripts.addColumn (new FixedRecordTypeColumn<ESM::StartScript> (UniversalId::Type_StartScript));
|
mStartScripts.addColumn (new FixedRecordTypeColumn<ESM::StartScript> (UniversalId::Type_StartScript));
|
||||||
|
@ -331,7 +348,7 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, const ResourcesManager& resourc
|
||||||
addModel (new IdTable (&mBodyParts), UniversalId::Type_BodyPart);
|
addModel (new IdTable (&mBodyParts), UniversalId::Type_BodyPart);
|
||||||
addModel (new IdTable (&mSoundGens), UniversalId::Type_SoundGen);
|
addModel (new IdTable (&mSoundGens), UniversalId::Type_SoundGen);
|
||||||
addModel (new IdTable (&mMagicEffects), UniversalId::Type_MagicEffect);
|
addModel (new IdTable (&mMagicEffects), UniversalId::Type_MagicEffect);
|
||||||
addModel (new IdTable (&mPathgrids), UniversalId::Type_Pathgrid);
|
addModel (new IdTree (&mPathgrids, &mPathgrids), UniversalId::Type_Pathgrid);
|
||||||
addModel (new IdTable (&mStartScripts), UniversalId::Type_StartScript);
|
addModel (new IdTable (&mStartScripts), UniversalId::Type_StartScript);
|
||||||
addModel (new IdTree (&mReferenceables, &mReferenceables, IdTable::Feature_Preview),
|
addModel (new IdTree (&mReferenceables, &mReferenceables, IdTable::Feature_Preview),
|
||||||
UniversalId::Type_Referenceable);
|
UniversalId::Type_Referenceable);
|
||||||
|
|
39
apps/opencs/model/world/idadapter.hpp
Normal file
39
apps/opencs/model/world/idadapter.hpp
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
#ifndef CSM_WOLRD_IDADAPTER_H
|
||||||
|
#define CSM_WOLRD_IDADAPTER_H
|
||||||
|
|
||||||
|
#include "record.hpp"
|
||||||
|
|
||||||
|
class QVariant;
|
||||||
|
|
||||||
|
namespace CSMWorld
|
||||||
|
{
|
||||||
|
class NestedTableWrapperBase;
|
||||||
|
|
||||||
|
template<typename ESXRecordT>
|
||||||
|
class NestedIdAdapter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
NestedIdAdapter() {}
|
||||||
|
|
||||||
|
virtual ~NestedIdAdapter() {}
|
||||||
|
|
||||||
|
virtual void addNestedRow(Record<ESXRecordT>& record, int position) const = 0;
|
||||||
|
|
||||||
|
virtual void removeNestedRow(Record<ESXRecordT>& record, int rowToRemove) const = 0;
|
||||||
|
|
||||||
|
virtual void setNestedTable(Record<ESXRecordT>& record, const NestedTableWrapperBase& nestedTable) = 0;
|
||||||
|
|
||||||
|
virtual NestedTableWrapperBase* nestedTable(const Record<ESXRecordT>& record) const = 0;
|
||||||
|
|
||||||
|
virtual QVariant getNestedData(const Record<ESXRecordT>& record, int subRowIndex, int subColIndex) const = 0;
|
||||||
|
|
||||||
|
virtual void setNestedData(Record<ESXRecordT>& record, const QVariant& value, int subRowIndex, int subColIndex) const = 0;
|
||||||
|
|
||||||
|
virtual int getNestedColumnsCount(const Record<ESXRecordT>& record) const = 0;
|
||||||
|
|
||||||
|
virtual int getNestedRowsCount(const Record<ESXRecordT>& record) const = 0;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CSM_WOLRD_IDADAPTER_H
|
202
apps/opencs/model/world/idadapterimp.hpp
Normal file
202
apps/opencs/model/world/idadapterimp.hpp
Normal file
|
@ -0,0 +1,202 @@
|
||||||
|
#ifndef CSM_WOLRD_IDADAPTERIMP_H
|
||||||
|
#define CSM_WOLRD_IDADAPTERIMP_H
|
||||||
|
|
||||||
|
#include <QVariant>
|
||||||
|
|
||||||
|
#include <components/esm/loadpgrd.hpp>
|
||||||
|
|
||||||
|
#include "idadapter.hpp"
|
||||||
|
|
||||||
|
namespace CSMWorld
|
||||||
|
{
|
||||||
|
class NestedTableWrapperBase;
|
||||||
|
|
||||||
|
template<typename ESXRecordT>
|
||||||
|
class PathgridPointListAdapter : public NestedIdAdapter<ESXRecordT>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PathgridPointListAdapter () {}
|
||||||
|
|
||||||
|
virtual void addNestedRow(Record<ESXRecordT>& record, int position) const
|
||||||
|
{
|
||||||
|
ESXRecordT pathgrid = record.get();
|
||||||
|
|
||||||
|
ESXRecordT::PointList& points = pathgrid.mPoints;
|
||||||
|
|
||||||
|
// blank row
|
||||||
|
ESM::Pathgrid::Point point;
|
||||||
|
point.mX = 0;
|
||||||
|
point.mY = 0;
|
||||||
|
point.mZ = 0;
|
||||||
|
point.mAutogenerated = 0;
|
||||||
|
point.mConnectionNum = 0;
|
||||||
|
point.mUnknown = 0;
|
||||||
|
|
||||||
|
// FIXME: inserting a point should trigger re-indexing of the edges
|
||||||
|
points.insert(points.begin()+position, point);
|
||||||
|
pathgrid.mData.mS2 += 1; // increment the number of points
|
||||||
|
|
||||||
|
record.setModified (pathgrid);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void removeNestedRow(Record<ESXRecordT>& record, int rowToRemove) const
|
||||||
|
{
|
||||||
|
ESXRecordT pathgrid = record.get();
|
||||||
|
|
||||||
|
ESXRecordT::PointList& points = pathgrid.mPoints;
|
||||||
|
|
||||||
|
if (rowToRemove < 0 || rowToRemove >= static_cast<int> (points.size()))
|
||||||
|
throw std::runtime_error ("index out of range");
|
||||||
|
|
||||||
|
// FIXME: deleting a point should trigger re-indexing of the edges
|
||||||
|
points.erase(points.begin()+rowToRemove);
|
||||||
|
pathgrid.mData.mS2 -= 1; // decrement the number of points
|
||||||
|
|
||||||
|
record.setModified (pathgrid);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void setNestedTable(Record<ESXRecordT>& record, const NestedTableWrapperBase& nestedTable)
|
||||||
|
{
|
||||||
|
record.get().mPoints =
|
||||||
|
static_cast<const NestedTableWrapper<ESXRecordT::PointList> &>(nestedTable).mNestedTable;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual NestedTableWrapperBase* nestedTable(const Record<ESXRecordT>& record) const
|
||||||
|
{
|
||||||
|
// deleted by dtor of NestedTableStoring
|
||||||
|
return new NestedTableWrapper<ESXRecordT::PointList>(record.get().mPoints);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual QVariant getNestedData(const Record<ESXRecordT>& record, int subRowIndex, int subColIndex) const
|
||||||
|
{
|
||||||
|
ESM::Pathgrid::Point point = record.get().mPoints[subRowIndex];
|
||||||
|
switch (subColIndex)
|
||||||
|
{
|
||||||
|
case 0: return point.mX;
|
||||||
|
case 1: return point.mY;
|
||||||
|
case 2: return point.mZ;
|
||||||
|
default: throw std::logic_error("Pathgrid point subcolumn index out of range");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void setNestedData(Record<ESXRecordT>& record, const QVariant& value,
|
||||||
|
int subRowIndex, int subColIndex) const
|
||||||
|
{
|
||||||
|
ESXRecordT pathgrid = record.get();
|
||||||
|
ESM::Pathgrid::Point point = pathgrid.mPoints[subRowIndex];
|
||||||
|
switch (subColIndex)
|
||||||
|
{
|
||||||
|
case 0: point.mX = value.toInt(); break;
|
||||||
|
case 1: point.mY = value.toInt(); break;
|
||||||
|
case 2: point.mZ = value.toInt(); break;
|
||||||
|
default: throw std::logic_error("Pathgrid point subcolumn index out of range");
|
||||||
|
}
|
||||||
|
|
||||||
|
pathgrid.mPoints[subRowIndex] = point;
|
||||||
|
|
||||||
|
record.setModified (pathgrid);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int getNestedColumnsCount(const Record<ESXRecordT>& record) const
|
||||||
|
{
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int getNestedRowsCount(const Record<ESXRecordT>& record) const
|
||||||
|
{
|
||||||
|
return static_cast<int>(record.get().mPoints.size());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename ESXRecordT>
|
||||||
|
class PathgridEdgeListAdapter : public NestedIdAdapter<ESXRecordT>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PathgridEdgeListAdapter () {}
|
||||||
|
|
||||||
|
// FIXME: seems to be auto-sorted in the dialog table display after insertion
|
||||||
|
virtual void addNestedRow(Record<ESXRecordT>& record, int position) const
|
||||||
|
{
|
||||||
|
ESXRecordT pathgrid = record.get();
|
||||||
|
|
||||||
|
ESXRecordT::EdgeList& edges = pathgrid.mEdges;
|
||||||
|
|
||||||
|
// blank row
|
||||||
|
ESM::Pathgrid::Edge edge;
|
||||||
|
edge.mV0 = 0;
|
||||||
|
edge.mV1 = 0;
|
||||||
|
|
||||||
|
// FIXME: inserting a blank edge does not really make sense, perhaps this should be a
|
||||||
|
// logic_error exception
|
||||||
|
edges.insert(edges.begin()+position, edge);
|
||||||
|
|
||||||
|
record.setModified (pathgrid);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void removeNestedRow(Record<ESXRecordT>& record, int rowToRemove) const
|
||||||
|
{
|
||||||
|
ESXRecordT pathgrid = record.get();
|
||||||
|
|
||||||
|
ESXRecordT::EdgeList& edges = pathgrid.mEdges;
|
||||||
|
|
||||||
|
if (rowToRemove < 0 || rowToRemove >= static_cast<int> (edges.size()))
|
||||||
|
throw std::runtime_error ("index out of range");
|
||||||
|
|
||||||
|
edges.erase(edges.begin()+rowToRemove);
|
||||||
|
|
||||||
|
record.setModified (pathgrid);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void setNestedTable(Record<ESXRecordT>& record, const NestedTableWrapperBase& nestedTable)
|
||||||
|
{
|
||||||
|
record.get().mEdges =
|
||||||
|
static_cast<const NestedTableWrapper<ESXRecordT::EdgeList> &>(nestedTable).mNestedTable;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual NestedTableWrapperBase* nestedTable(const Record<ESXRecordT>& record) const
|
||||||
|
{
|
||||||
|
// deleted by dtor of NestedTableStoring
|
||||||
|
return new NestedTableWrapper<ESXRecordT::EdgeList>(record.get().mEdges);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual QVariant getNestedData(const Record<ESXRecordT>& record, int subRowIndex, int subColIndex) const
|
||||||
|
{
|
||||||
|
ESM::Pathgrid::Edge edge = record.get().mEdges[subRowIndex];
|
||||||
|
switch (subColIndex)
|
||||||
|
{
|
||||||
|
case 0: return edge.mV0;
|
||||||
|
case 1: return edge.mV1;
|
||||||
|
default: throw std::logic_error("Pathgrid edge subcolumn index out of range");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void setNestedData(Record<ESXRecordT>& record, const QVariant& value,
|
||||||
|
int subRowIndex, int subColIndex) const
|
||||||
|
{
|
||||||
|
ESXRecordT pathgrid = record.get();
|
||||||
|
ESM::Pathgrid::Edge edge = pathgrid.mEdges[subRowIndex];
|
||||||
|
switch (subColIndex)
|
||||||
|
{
|
||||||
|
case 0: edge.mV0 = value.toInt(); break;
|
||||||
|
case 1: edge.mV1 = value.toInt(); break;
|
||||||
|
default: throw std::logic_error("Pathgrid edge subcolumn index out of range");
|
||||||
|
}
|
||||||
|
|
||||||
|
pathgrid.mEdges[subRowIndex] = edge;
|
||||||
|
|
||||||
|
record.setModified (pathgrid);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int getNestedColumnsCount(const Record<ESXRecordT>& record) const
|
||||||
|
{
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual int getNestedRowsCount(const Record<ESXRecordT>& record) const
|
||||||
|
{
|
||||||
|
return static_cast<int>(record.get().mEdges.size());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CSM_WOLRD_IDADAPTERIMP_H
|
|
@ -1,6 +1,17 @@
|
||||||
#ifndef CSM_WOLRD_SUBCOLLECTION_H
|
#ifndef CSM_WOLRD_SUBCOLLECTION_H
|
||||||
#define CSM_WOLRD_SUBCOLLECTION_H
|
#define CSM_WOLRD_SUBCOLLECTION_H
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
#include <components/esm/loadpgrd.hpp>
|
||||||
|
|
||||||
|
#include "columnimp.hpp"
|
||||||
|
#include "idcollection.hpp"
|
||||||
|
#include "nestedcollection.hpp"
|
||||||
|
#include "nestedtablewrapper.hpp"
|
||||||
|
#include "idadapterimp.hpp"
|
||||||
|
|
||||||
namespace ESM
|
namespace ESM
|
||||||
{
|
{
|
||||||
class ESMReader;
|
class ESMReader;
|
||||||
|
@ -14,17 +25,40 @@ namespace CSMWorld
|
||||||
|
|
||||||
/// \brief Single type collection of top level records that are associated with cells
|
/// \brief Single type collection of top level records that are associated with cells
|
||||||
template<typename ESXRecordT, typename IdAccessorT = IdAccessor<ESXRecordT> >
|
template<typename ESXRecordT, typename IdAccessorT = IdAccessor<ESXRecordT> >
|
||||||
class SubCellCollection : public IdCollection<ESXRecordT, IdAccessorT>
|
class SubCellCollection : public IdCollection<ESXRecordT, IdAccessorT>, public NestedCollection
|
||||||
{
|
{
|
||||||
const IdCollection<Cell>& mCells;
|
const IdCollection<Cell>& mCells;
|
||||||
|
std::map<const ColumnBase*, NestedIdAdapter<ESXRecordT>* > mAdapters;
|
||||||
|
|
||||||
virtual void loadRecord (ESXRecordT& record, ESM::ESMReader& reader);
|
virtual void loadRecord (ESXRecordT& record, ESM::ESMReader& reader);
|
||||||
|
|
||||||
|
NestedIdAdapter<ESXRecordT>* getAdapter(const ColumnBase &column) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
SubCellCollection (const IdCollection<Cell>& cells);
|
SubCellCollection (const IdCollection<Cell>& cells);
|
||||||
|
~SubCellCollection();
|
||||||
|
|
||||||
|
virtual void addNestedRow(int row, int column, int position);
|
||||||
|
|
||||||
|
virtual void removeNestedRows(int row, int column, int subRow);
|
||||||
|
|
||||||
|
virtual QVariant getNestedData(int row, int column, int subRow, int subColumn) const;
|
||||||
|
|
||||||
|
virtual void setNestedData(int row, int column, const QVariant& data, int subRow, int subColumn);
|
||||||
|
|
||||||
|
virtual NestedTableWrapperBase* nestedTable(int row, int column) const;
|
||||||
|
|
||||||
|
virtual void setNestedTable(int row, int column, const NestedTableWrapperBase& nestedTable);
|
||||||
|
|
||||||
|
virtual int getNestedRowsCount(int row, int column) const;
|
||||||
|
|
||||||
|
virtual int getNestedColumnsCount(int row, int column) const;
|
||||||
|
|
||||||
|
// this method is inherited from NestedCollection, not from Collection<ESXRecordT>
|
||||||
|
virtual NestableColumn *getNestableColumn(int column);
|
||||||
|
|
||||||
|
void addAdapter(std::pair<const ColumnBase*, NestedIdAdapter<ESXRecordT>* > adapter);
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename ESXRecordT, typename IdAccessorT>
|
template<typename ESXRecordT, typename IdAccessorT>
|
||||||
|
@ -35,11 +69,93 @@ namespace CSMWorld
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename ESXRecordT, typename IdAccessorT>
|
template<typename ESXRecordT, typename IdAccessorT>
|
||||||
SubCellCollection<ESXRecordT, IdAccessorT>::SubCellCollection (
|
SubCellCollection<ESXRecordT, IdAccessorT>::SubCellCollection (const IdCollection<Cell>& cells)
|
||||||
const IdCollection<Cell>& cells)
|
|
||||||
: mCells (cells)
|
: mCells (cells)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
template<typename ESXRecordT, typename IdAccessorT>
|
||||||
|
SubCellCollection<ESXRecordT, IdAccessorT>::~SubCellCollection()
|
||||||
|
{
|
||||||
|
for (std::map<const ColumnBase *, NestedIdAdapter<ESXRecordT>* >::iterator iter (mAdapters.begin());
|
||||||
|
iter!=mAdapters.end(); ++iter)
|
||||||
|
delete (*iter).second;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ESXRecordT, typename IdAccessorT>
|
||||||
|
void SubCellCollection<ESXRecordT, IdAccessorT>::addAdapter(std::pair<const ColumnBase*, NestedIdAdapter<ESXRecordT>* > adapter)
|
||||||
|
{
|
||||||
|
mAdapters.insert(adapter);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ESXRecordT, typename IdAccessorT>
|
||||||
|
NestedIdAdapter<ESXRecordT>* SubCellCollection<ESXRecordT, IdAccessorT>::getAdapter(const ColumnBase &column) const
|
||||||
|
{
|
||||||
|
std::map<const ColumnBase *, NestedIdAdapter<ESXRecordT>* >::const_iterator iter =
|
||||||
|
mAdapters.find (&column);
|
||||||
|
|
||||||
|
if (iter==mAdapters.end())
|
||||||
|
throw std::logic_error("No such column in the nestedidadapter");
|
||||||
|
|
||||||
|
return iter->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ESXRecordT, typename IdAccessorT>
|
||||||
|
void SubCellCollection<ESXRecordT, IdAccessorT>::addNestedRow(int row, int column, int position)
|
||||||
|
{
|
||||||
|
getAdapter(getColumn(column))->addNestedRow(getRecord(row), position);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ESXRecordT, typename IdAccessorT>
|
||||||
|
void SubCellCollection<ESXRecordT, IdAccessorT>::removeNestedRows(int row, int column, int subRow)
|
||||||
|
{
|
||||||
|
getAdapter(getColumn(column))->removeNestedRow(getRecord(row), subRow);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ESXRecordT, typename IdAccessorT>
|
||||||
|
QVariant SubCellCollection<ESXRecordT, IdAccessorT>::getNestedData (int row,
|
||||||
|
int column, int subRow, int subColumn) const
|
||||||
|
{
|
||||||
|
return getAdapter(getColumn(column))->getNestedData(getRecord(row), subRow, subColumn);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ESXRecordT, typename IdAccessorT>
|
||||||
|
void SubCellCollection<ESXRecordT, IdAccessorT>::setNestedData(int row,
|
||||||
|
int column, const QVariant& data, int subRow, int subColumn)
|
||||||
|
{
|
||||||
|
getAdapter(getColumn(column))->setNestedData(getRecord(row), data, subRow, subColumn);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ESXRecordT, typename IdAccessorT>
|
||||||
|
CSMWorld::NestedTableWrapperBase* SubCellCollection<ESXRecordT, IdAccessorT>::nestedTable(int row,
|
||||||
|
int column) const
|
||||||
|
{
|
||||||
|
return getAdapter(getColumn(column))->nestedTable(getRecord(row));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ESXRecordT, typename IdAccessorT>
|
||||||
|
void SubCellCollection<ESXRecordT, IdAccessorT>::setNestedTable(int row,
|
||||||
|
int column, const CSMWorld::NestedTableWrapperBase& nestedTable)
|
||||||
|
{
|
||||||
|
getAdapter(getColumn(column))->setNestedTable(getRecord(row), nestedTable);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ESXRecordT, typename IdAccessorT>
|
||||||
|
int SubCellCollection<ESXRecordT, IdAccessorT>::getNestedRowsCount(int row, int column) const
|
||||||
|
{
|
||||||
|
return getAdapter(getColumn(column))->getNestedRowsCount(getRecord(row));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ESXRecordT, typename IdAccessorT>
|
||||||
|
int SubCellCollection<ESXRecordT, IdAccessorT>::getNestedColumnsCount(int row, int column) const
|
||||||
|
{
|
||||||
|
return getAdapter(getColumn(column))->getNestedColumnsCount(getRecord(row));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename ESXRecordT, typename IdAccessorT>
|
||||||
|
CSMWorld::NestableColumn *SubCellCollection<ESXRecordT, IdAccessorT>::getNestableColumn(int column)
|
||||||
|
{
|
||||||
|
return Collection::getNestableColumn(column);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue