Changes to land data access in tables, also update Land once per frame in scene view.

new-script-api
Kyle Cooley 7 years ago
parent d030b595f8
commit 25d4a0370f

@ -10,19 +10,31 @@ namespace CSMWorld
QVariant LandMapLodColumn::get(const Record<Land>& record) const QVariant LandMapLodColumn::get(const Record<Land>& record) const
{ {
// Note: original data is signed const int Size = Land::LAND_GLOBAL_MAP_LOD_SIZE;
const char* rawData = reinterpret_cast<const char*>(&record.get().mWnam[0]); const Land& land = record.get();
return QByteArray(rawData, Land::LAND_GLOBAL_MAP_LOD_SIZE);
if (land.isDataLoaded(Land::DATA_WNAM))
{
// Note: original data is signed
const char* rawData = reinterpret_cast<const char*>(&land.mWnam[0]);
return QByteArray(rawData, Size);
}
else
{
// Return a blank array
return QByteArray(Size, 0);
}
} }
void LandMapLodColumn::set(Record<Land>& record, const QVariant& data) void LandMapLodColumn::set(Record<Land>& record, const QVariant& data)
{ {
Land copy = record.get();
QByteArray array = data.toByteArray(); QByteArray array = data.toByteArray();
const signed char* rawData = reinterpret_cast<const signed char*>(array.data()); const signed char* rawData = reinterpret_cast<const signed char*>(array.data());
assert (array.count() == Land::LAND_GLOBAL_MAP_LOD_SIZE); assert (array.count() == Land::LAND_GLOBAL_MAP_LOD_SIZE);
Land copy = record.get();
copy.setDataLoaded(Land::DATA_WNAM);
for (int i = 0; i < array.count(); ++i) for (int i = 0; i < array.count(); ++i)
{ {
copy.mWnam[i] = rawData[i]; copy.mWnam[i] = rawData[i];
@ -44,28 +56,34 @@ namespace CSMWorld
QVariant LandNormalsColumn::get(const Record<Land>& record) const QVariant LandNormalsColumn::get(const Record<Land>& record) const
{ {
const Land::LandData* landData = record.get().getLandData(); const int Size = Land::LAND_NUM_VERTS * 3;
assert(landData); const Land& land = record.get();
// Note: original data is signed if (land.isDataLoaded(Land::DATA_VNML))
const char* rawData = reinterpret_cast<const char*>(&landData->mNormals[0]); {
return QByteArray(rawData, Land::LAND_NUM_VERTS * 3); // Note: original data is signed
const char* rawData = reinterpret_cast<const char*>(&land.getLandData()->mNormals[0]);
return QByteArray(rawData, Size);
}
else
{
// Return a blank array
return QByteArray(Size, 0);
}
} }
void LandNormalsColumn::set(Record<Land>& record, const QVariant& data) void LandNormalsColumn::set(Record<Land>& record, const QVariant& data)
{ {
Land copy = record.get();
Land::LandData* landData = copy.getLandData();
assert (landData);
QByteArray array = data.toByteArray(); QByteArray array = data.toByteArray();
const signed char* rawData = reinterpret_cast<const signed char*>(array.data()); const signed char* rawData = reinterpret_cast<const signed char*>(array.data());
assert (array.count() == Land::LAND_NUM_VERTS * 3); assert (array.count() == Land::LAND_NUM_VERTS * 3);
Land copy = record.get();
copy.setDataLoaded(Land::DATA_VNML);
for (int i = 0; i < array.count(); ++i) for (int i = 0; i < array.count(); ++i)
{ {
landData->mNormals[i] = rawData[i]; copy.getLandData()->mNormals[i] = rawData[i];
} }
record.setModified(copy); record.setModified(copy);
@ -84,29 +102,34 @@ namespace CSMWorld
QVariant LandHeightsColumn::get(const Record<Land>& record) const QVariant LandHeightsColumn::get(const Record<Land>& record) const
{ {
const Land::LandData* landData = record.get().getLandData(); const int Size = Land::LAND_NUM_VERTS * sizeof(float);
assert(landData); const Land& land = record.get();
// Note: original data is float if (land.isDataLoaded(Land::DATA_VHGT))
const char* rawData = reinterpret_cast<const char*>(&landData->mHeights[0]); {
return QByteArray(rawData, Land::LAND_NUM_VERTS * sizeof(float)); // Note: original data is float
const char* rawData = reinterpret_cast<const char*>(&land.getLandData()->mHeights[0]);
return QByteArray(rawData, Size);
}
else
{
return QByteArray(Size, 0);
}
} }
void LandHeightsColumn::set(Record<Land>& record, const QVariant& data) void LandHeightsColumn::set(Record<Land>& record, const QVariant& data)
{ {
Land copy = record.get();
Land::LandData* landData = copy.getLandData();
assert (landData);
QByteArray array = data.toByteArray(); QByteArray array = data.toByteArray();
const float* rawData = reinterpret_cast<const float*>(array.data()); const float* rawData = reinterpret_cast<const float*>(array.data());
assert (array.count() == Land::LAND_NUM_VERTS * sizeof(float)); assert (array.count() == Land::LAND_NUM_VERTS * sizeof(float));
Land copy = record.get();
copy.setDataLoaded(Land::DATA_VHGT);
int count = array.count() / sizeof(float); int count = array.count() / sizeof(float);
for (int i = 0; i < count; ++i) for (int i = 0; i < count; ++i)
{ {
landData->mHeights[i] = rawData[i]; copy.getLandData()->mHeights[i] = rawData[i];
} }
record.setModified(copy); record.setModified(copy);
@ -125,28 +148,33 @@ namespace CSMWorld
QVariant LandColoursColumn::get(const Record<Land>& record) const QVariant LandColoursColumn::get(const Record<Land>& record) const
{ {
const Land::LandData* landData = record.get().getLandData(); const int Size = Land::LAND_NUM_VERTS * 3;
assert(landData); const Land& land = record.get();
// Note: original data is unsigned char if (land.isDataLoaded(Land::DATA_VCLR))
const char* rawData = reinterpret_cast<const char*>(&landData->mColours[0]); {
return QByteArray(rawData, Land::LAND_NUM_VERTS * 3); // Note: original data is unsigned char
const char* rawData = reinterpret_cast<const char*>(&land.getLandData()->mColours[0]);
return QByteArray(rawData, Size);
}
else
{
return QByteArray(Size, 0);
}
} }
void LandColoursColumn::set(Record<Land>& record, const QVariant& data) void LandColoursColumn::set(Record<Land>& record, const QVariant& data)
{ {
Land copy = record.get();
Land::LandData* landData = copy.getLandData();
assert (landData);
QByteArray array = data.toByteArray(); QByteArray array = data.toByteArray();
const unsigned char* rawData = reinterpret_cast<const unsigned char*>(array.data()); const unsigned char* rawData = reinterpret_cast<const unsigned char*>(array.data());
assert (array.count() == Land::LAND_NUM_VERTS * 3); assert (array.count() == Land::LAND_NUM_VERTS * 3);
Land copy = record.get();
copy.setDataLoaded(Land::DATA_VCLR);
for (int i = 0; i < array.count(); ++i) for (int i = 0; i < array.count(); ++i)
{ {
landData->mColours[i] = rawData[i]; copy.getLandData()->mColours[i] = rawData[i];
} }
record.setModified(copy); record.setModified(copy);
@ -165,29 +193,34 @@ namespace CSMWorld
QVariant LandTexturesColumn::get(const Record<Land>& record) const QVariant LandTexturesColumn::get(const Record<Land>& record) const
{ {
const Land::LandData* landData = record.get().getLandData(); const int Size = Land::LAND_NUM_TEXTURES * sizeof(uint16_t);
assert(landData); const Land& land = record.get();
// Note: original data is uint16_t if (land.isDataLoaded(Land::DATA_VTEX))
const char* rawData = reinterpret_cast<const char*>(&landData->mTextures[0]); {
return QByteArray(rawData, Land::LAND_NUM_TEXTURES * sizeof(uint16_t)); // Note: original data is uint16_t
const char* rawData = reinterpret_cast<const char*>(&land.getLandData()->mTextures[0]);
return QByteArray(rawData, Size);
}
else
{
return QByteArray(Size, 0);
}
} }
void LandTexturesColumn::set(Record<Land>& record, const QVariant& data) void LandTexturesColumn::set(Record<Land>& record, const QVariant& data)
{ {
Land copy = record.get();
Land::LandData* landData = copy.getLandData();
assert (landData);
QByteArray array = data.toByteArray(); QByteArray array = data.toByteArray();
const uint16_t* rawData = reinterpret_cast<const uint16_t*>(array.data()); const uint16_t* rawData = reinterpret_cast<const uint16_t*>(array.data());
assert (array.count() == Land::LAND_NUM_TEXTURES * sizeof(uint16_t)); assert (array.count() == Land::LAND_NUM_TEXTURES * sizeof(uint16_t));
Land copy = record.get();
copy.setDataLoaded(Land::DATA_VTEX);
int count = array.count() / sizeof(uint16_t); int count = array.count() / sizeof(uint16_t);
for (int i = 0; i < count; ++i) for (int i = 0; i < count; ++i)
{ {
landData->mTextures[i] = rawData[i]; copy.getLandData()->mTextures[i] = rawData[i];
} }
record.setModified(copy); record.setModified(copy);

@ -356,6 +356,7 @@ CSMWorld::LandTextureIdTable::ImportResults CSMWorld::LandTextureIdTable::import
// Try a direct mapping to the current plugin first. Otherwise iterate until one is found. // Try a direct mapping to the current plugin first. Otherwise iterate until one is found.
// Iteration is deterministic to avoid duplicates. // Iteration is deterministic to avoid duplicates.
int startIndex = index;
do { do {
std::string newId = LandTexture::createUniqueRecordId(0, index); std::string newId = LandTexture::createUniqueRecordId(0, index);
int newRow = idCollection()->searchId(newId); int newRow = idCollection()->searchId(newId);
@ -384,7 +385,7 @@ CSMWorld::LandTextureIdTable::ImportResults CSMWorld::LandTextureIdTable::import
size_t Prime = (1 << 13) - 1; // A mersenne prime size_t Prime = (1 << 13) - 1; // A mersenne prime
index = (index + Prime) % MaxIndex; index = (index + Prime) % MaxIndex;
} while (true); } while (index != startIndex);
} }
return results; return results;

@ -26,6 +26,33 @@
#include "terrainstorage.hpp" #include "terrainstorage.hpp"
#include "object.hpp" #include "object.hpp"
namespace CSVRender
{
class CellNodeContainer : public osg::Referenced
{
public:
CellNodeContainer(Cell* cell) : mCell(cell) {}
Cell* getCell(){ return mCell; }
private:
Cell* mCell;
};
class CellNodeCallback : public osg::NodeCallback
{
public:
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
{
CellNodeContainer* container = static_cast<CellNodeContainer*>(node->getUserData());
container->getCell()->updateLand();
}
};
}
bool CSVRender::Cell::removeObject (const std::string& id) bool CSVRender::Cell::removeObject (const std::string& id)
{ {
std::map<std::string, Object *>::iterator iter = std::map<std::string, Object *>::iterator iter =
@ -77,6 +104,11 @@ bool CSVRender::Cell::addObjects (int start, int end)
void CSVRender::Cell::updateLand() void CSVRender::Cell::updateLand()
{ {
if (!mUpdateLand || mLandDeleted)
return;
mUpdateLand = false;
// Cell is deleted // Cell is deleted
if (mDeleted) if (mDeleted)
{ {
@ -116,6 +148,7 @@ void CSVRender::Cell::updateLand()
} }
// No land data // No land data
mLandDeleted = true;
unloadLand(); unloadLand();
} }
@ -131,7 +164,7 @@ void CSVRender::Cell::unloadLand()
CSVRender::Cell::Cell (CSMWorld::Data& data, osg::Group* rootNode, const std::string& id, CSVRender::Cell::Cell (CSMWorld::Data& data, osg::Group* rootNode, const std::string& id,
bool deleted) bool deleted)
: mData (data), mId (Misc::StringUtils::lowerCase (id)), mDeleted (deleted), mSubMode (0), : mData (data), mId (Misc::StringUtils::lowerCase (id)), mDeleted (deleted), mSubMode (0),
mSubModeElementMask (0) mSubModeElementMask (0), mUpdateLand(true), mLandDeleted(false)
{ {
std::pair<CSMWorld::CellCoordinates, bool> result = CSMWorld::CellCoordinates::fromId (id); std::pair<CSMWorld::CellCoordinates, bool> result = CSMWorld::CellCoordinates::fromId (id);
@ -139,6 +172,8 @@ CSVRender::Cell::Cell (CSMWorld::Data& data, osg::Group* rootNode, const std::st
mCoordinates = result.first; mCoordinates = result.first;
mCellNode = new osg::Group; mCellNode = new osg::Group;
mCellNode->setUserData(new CellNodeContainer(this));
mCellNode->setUpdateCallback(new CellNodeCallback);
rootNode->addChild(mCellNode); rootNode->addChild(mCellNode);
setCellMarker(); setCellMarker();
@ -325,32 +360,34 @@ void CSVRender::Cell::pathgridRemoved()
void CSVRender::Cell::landDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight) void CSVRender::Cell::landDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight)
{ {
updateLand(); mUpdateLand = true;
} }
void CSVRender::Cell::landAboutToBeRemoved (const QModelIndex& parent, int start, int end) void CSVRender::Cell::landAboutToBeRemoved (const QModelIndex& parent, int start, int end)
{ {
updateLand(); mLandDeleted = true;
unloadLand();
} }
void CSVRender::Cell::landAdded (const QModelIndex& parent, int start, int end) void CSVRender::Cell::landAdded (const QModelIndex& parent, int start, int end)
{ {
updateLand(); mUpdateLand = true;
mLandDeleted = false;
} }
void CSVRender::Cell::landTextureChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight) void CSVRender::Cell::landTextureChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight)
{ {
updateLand(); mUpdateLand = true;
} }
void CSVRender::Cell::landTextureAboutToBeRemoved (const QModelIndex& parent, int start, int end) void CSVRender::Cell::landTextureAboutToBeRemoved (const QModelIndex& parent, int start, int end)
{ {
updateLand(); mUpdateLand = true;
} }
void CSVRender::Cell::landTextureAdded (const QModelIndex& parent, int start, int end) void CSVRender::Cell::landTextureAdded (const QModelIndex& parent, int start, int end)
{ {
updateLand(); mUpdateLand = true;
} }
void CSVRender::Cell::reloadAssets() void CSVRender::Cell::reloadAssets()

@ -57,6 +57,7 @@ namespace CSVRender
bool mDeleted; bool mDeleted;
int mSubMode; int mSubMode;
unsigned int mSubModeElementMask; unsigned int mSubModeElementMask;
bool mUpdateLand, mLandDeleted;
/// Ignored if cell does not have an object with the given ID. /// Ignored if cell does not have an object with the given ID.
/// ///
@ -160,6 +161,8 @@ namespace CSVRender
/// Erase all overrides and restore the visual representation of the cell to its /// Erase all overrides and restore the visual representation of the cell to its
/// true state. /// true state.
void reset (unsigned int elementMask); void reset (unsigned int elementMask);
friend class CellNodeCallback;
}; };
} }

@ -322,6 +322,15 @@ namespace ESM
return mLandData && (mLandData->mDataLoaded & flags) == (flags & mDataTypes); return mLandData && (mLandData->mDataLoaded & flags) == (flags & mDataTypes);
} }
void Land::setDataLoaded(int flags)
{
if (!mLandData)
mLandData = new LandData;
mDataTypes |= flags;
mLandData->mDataLoaded |= flags;
}
Land::Land (const Land& land) Land::Land (const Land& land)
: mFlags (land.mFlags), mX (land.mX), mY (land.mY), mPlugin (land.mPlugin), : mFlags (land.mFlags), mX (land.mX), mY (land.mY), mPlugin (land.mPlugin),
mContext (land.mContext), mDataTypes (land.mDataTypes), mContext (land.mContext), mDataTypes (land.mDataTypes),

@ -135,6 +135,9 @@ struct Land
/// @note We only check data types that *can* be loaded (present in mDataTypes) /// @note We only check data types that *can* be loaded (present in mDataTypes)
bool isDataLoaded(int flags) const; bool isDataLoaded(int flags) const;
/// Sets the flags and creates a LandData if needed
void setDataLoaded(int flags);
Land (const Land& land); Land (const Land& land);
Land& operator= (Land land); Land& operator= (Land land);

Loading…
Cancel
Save