From 7cc95a11a47721cd9c3f70d6acf9b0d595f576ba Mon Sep 17 00:00:00 2001 From: Kyle Cooley Date: Sun, 3 Sep 2017 20:00:19 -0400 Subject: [PATCH] Add more land table columns --- apps/opencs/model/world/columnimp.cpp | 234 ++++++++++++++++++++++++-- apps/opencs/model/world/columnimp.hpp | 45 +++++ apps/opencs/model/world/columns.hpp | 5 + apps/opencs/model/world/data.cpp | 5 + components/esm/loadland.hpp | 4 +- 5 files changed, 274 insertions(+), 19 deletions(-) diff --git a/apps/opencs/model/world/columnimp.cpp b/apps/opencs/model/world/columnimp.cpp index dc3d39edb2..65d2fecd2c 100644 --- a/apps/opencs/model/world/columnimp.cpp +++ b/apps/opencs/model/world/columnimp.cpp @@ -1,28 +1,226 @@ #include "columnimp.hpp" -CSMWorld::BodyPartRaceColumn::BodyPartRaceColumn(const MeshTypeColumn *meshType) - : mMeshType(meshType) -{} - -QVariant CSMWorld::BodyPartRaceColumn::get(const Record &record) const +namespace CSMWorld { - if (mMeshType != NULL && mMeshType->get(record) == ESM::BodyPart::MT_Skin) + /* LandMapLodColumn */ + LandMapLodColumn::LandMapLodColumn() + : Column(Columns::ColumnId_LandMapLodIndex, ColumnBase::Display_String, 0) { - return QString::fromUtf8(record.get().mRace.c_str()); } - return QVariant(QVariant::UserType); -} -void CSMWorld::BodyPartRaceColumn::set(Record &record, const QVariant &data) -{ - ESM::BodyPart record2 = record.get(); + QVariant LandMapLodColumn::get(const Record& record) const + { + // Note: original data is signed + const char* rawData = reinterpret_cast(&record.get().mWnam[0]); + return QByteArray(rawData, Land::LAND_GLOBAL_MAP_LOD_SIZE); + } + + void LandMapLodColumn::set(Record& record, const QVariant& data) + { + Land copy = record.get(); + QByteArray array = data.toByteArray(); + const signed char* rawData = reinterpret_cast(array.data()); - record2.mRace = data.toString().toUtf8().constData(); + assert (array.count() == Land::LAND_GLOBAL_MAP_LOD_SIZE); - record.setModified(record2); -} + for (int i = 0; i < array.count(); ++i) + { + copy.mWnam[i] = rawData[i]; + } -bool CSMWorld::BodyPartRaceColumn::isEditable() const -{ - return true; + record.setModified(copy); + } + + bool LandMapLodColumn::isEditable() const + { + return true; + } + + /* LandNormalsColumn */ + LandNormalsColumn::LandNormalsColumn() + : Column(Columns::ColumnId_LandNormalsIndex, ColumnBase::Display_String, 0) + { + } + + QVariant LandNormalsColumn::get(const Record& record) const + { + const Land::LandData* landData = record.get().getLandData(); + assert(landData); + + // Note: original data is signed + const char* rawData = reinterpret_cast(&landData->mNormals[0]); + return QByteArray(rawData, Land::LAND_NUM_VERTS * 3); + } + + void LandNormalsColumn::set(Record& record, const QVariant& data) + { + Land copy = record.get(); + Land::LandData* landData = copy.getLandData(); + assert (landData); + + QByteArray array = data.toByteArray(); + const signed char* rawData = reinterpret_cast(array.data()); + + assert (array.count() == Land::LAND_NUM_VERTS * 3); + + for (int i = 0; i < array.count(); ++i) + { + landData->mNormals[i] = rawData[i]; + } + + record.setModified(copy); + } + + bool LandNormalsColumn::isEditable() const + { + return true; + } + + /* LandHeightsColumn */ + LandHeightsColumn::LandHeightsColumn() + : Column(Columns::ColumnId_LandHeightsIndex, ColumnBase::Display_String, 0) + { + } + + QVariant LandHeightsColumn::get(const Record& record) const + { + const Land::LandData* landData = record.get().getLandData(); + assert(landData); + + // Note: original data is float + const char* rawData = reinterpret_cast(&landData->mHeights[0]); + return QByteArray(rawData, Land::LAND_NUM_VERTS * sizeof(float)); + } + + void LandHeightsColumn::set(Record& record, const QVariant& data) + { + Land copy = record.get(); + Land::LandData* landData = copy.getLandData(); + assert (landData); + + QByteArray array = data.toByteArray(); + const float* rawData = reinterpret_cast(array.data()); + + assert (array.count() == Land::LAND_NUM_VERTS * sizeof(float)); + + for (int i = 0; i < array.count(); ++i) + { + landData->mHeights[i] = rawData[i]; + } + + record.setModified(copy); + } + + bool LandHeightsColumn::isEditable() const + { + return true; + } + + /* LandColoursColumn */ + LandColoursColumn::LandColoursColumn() + : Column(Columns::ColumnId_LandColoursIndex, ColumnBase::Display_String, 0) + { + } + + QVariant LandColoursColumn::get(const Record& record) const + { + const Land::LandData* landData = record.get().getLandData(); + assert(landData); + + // Note: original data is unsigned char + const char* rawData = reinterpret_cast(&landData->mColours[0]); + return QByteArray(rawData, Land::LAND_NUM_VERTS * 3); + } + + void LandColoursColumn::set(Record& record, const QVariant& data) + { + Land copy = record.get(); + Land::LandData* landData = copy.getLandData(); + assert (landData); + + QByteArray array = data.toByteArray(); + const unsigned char* rawData = reinterpret_cast(array.data()); + + assert (array.count() == Land::LAND_NUM_VERTS * 3); + + for (int i = 0; i < array.count(); ++i) + { + landData->mColours[i] = rawData[i]; + } + + record.setModified(copy); + } + + bool LandColoursColumn::isEditable() const + { + return true; + } + + /* LandTexturesColumn */ + LandTexturesColumn::LandTexturesColumn() + : Column(Columns::ColumnId_LandTexturesIndex, ColumnBase::Display_String, 0) + { + } + + QVariant LandTexturesColumn::get(const Record& record) const + { + const Land::LandData* landData = record.get().getLandData(); + assert(landData); + + // Note: original data is uint16_t + const char* rawData = reinterpret_cast(&landData->mTextures[0]); + return QByteArray(rawData, Land::LAND_NUM_TEXTURES * sizeof(uint16_t)); + } + + void LandTexturesColumn::set(Record& record, const QVariant& data) + { + Land copy = record.get(); + Land::LandData* landData = copy.getLandData(); + assert (landData); + + QByteArray array = data.toByteArray(); + const uint16_t* rawData = reinterpret_cast(array.data()); + + assert (array.count() == Land::LAND_NUM_TEXTURES * sizeof(uint16_t)); + + for (int i = 0; i < array.count(); ++i) + { + landData->mTextures[i] = rawData[i]; + } + + record.setModified(copy); + } + + bool LandTexturesColumn::isEditable() const + { + return true; + } + + /* BodyPartRaceColumn */ + BodyPartRaceColumn::BodyPartRaceColumn(const MeshTypeColumn *meshType) + : mMeshType(meshType) + {} + + QVariant BodyPartRaceColumn::get(const Record &record) const + { + if (mMeshType != NULL && mMeshType->get(record) == ESM::BodyPart::MT_Skin) + { + return QString::fromUtf8(record.get().mRace.c_str()); + } + return QVariant(QVariant::UserType); + } + + void BodyPartRaceColumn::set(Record &record, const QVariant &data) + { + ESM::BodyPart record2 = record.get(); + + record2.mRace = data.toString().toUtf8().constData(); + + record.setModified(record2); + } + + bool BodyPartRaceColumn::isEditable() const + { + return true; + } } diff --git a/apps/opencs/model/world/columnimp.hpp b/apps/opencs/model/world/columnimp.hpp index 92e899a454..f58a35bc4a 100644 --- a/apps/opencs/model/world/columnimp.hpp +++ b/apps/opencs/model/world/columnimp.hpp @@ -2501,6 +2501,51 @@ namespace CSMWorld return record.get().mPluginIndex; } + struct LandMapLodColumn : public Column + { + LandMapLodColumn(); + + QVariant get(const Record& record) const override; + void set(Record& record, const QVariant& data) override; + bool isEditable() const override; + }; + + struct LandNormalsColumn : public Column + { + LandNormalsColumn(); + + QVariant get(const Record& record) const override; + void set(Record& record, const QVariant& data) override; + bool isEditable() const override; + }; + + struct LandHeightsColumn : public Column + { + LandHeightsColumn(); + + QVariant get(const Record& record) const override; + void set(Record& record, const QVariant& data) override; + bool isEditable() const override; + }; + + struct LandColoursColumn : public Column + { + LandColoursColumn(); + + QVariant get(const Record& record) const override; + void set(Record& record, const QVariant& data) override; + bool isEditable() const override; + }; + + struct LandTexturesColumn : public Column + { + LandTexturesColumn(); + + QVariant get(const Record& record) const override; + void set(Record& record, const QVariant& data) override; + bool isEditable() const override; + }; + struct BodyPartRaceColumn : public RaceColumn { const MeshTypeColumn *mMeshType; diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index c6e2a2a415..432597105a 100644 --- a/apps/opencs/model/world/columns.hpp +++ b/apps/opencs/model/world/columns.hpp @@ -332,6 +332,11 @@ namespace CSMWorld ColumnId_TextureHandle = 298, ColumnId_PluginIndex = 299, ColumnId_TextureIndex = 300, + ColumnId_LandMapLodIndex = 301, + ColumnId_LandNormalsIndex = 302, + ColumnId_LandHeightsIndex = 303, + ColumnId_LandColoursIndex = 304, + ColumnId_LandTexturesIndex = 305, // Allocated to a separate value range, so we don't get a collision should we ever need // to extend the number of use values. diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 27a914aeb6..3284d9b056 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -416,6 +416,11 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, bool fsStrict, const Files::Pat mLand.addColumn (new RecordStateColumn); mLand.addColumn (new FixedRecordTypeColumn(UniversalId::Type_Land)); mLand.addColumn (new PluginIndexColumn); + mLand.addColumn (new LandMapLodColumn); + mLand.addColumn (new LandNormalsColumn); + mLand.addColumn (new LandHeightsColumn); + mLand.addColumn (new LandColoursColumn); + mLand.addColumn (new LandTexturesColumn); mLandTextures.addColumn (new StringIdColumn(true)); mLandTextures.addColumn (new RecordStateColumn); diff --git a/components/esm/loadland.hpp b/components/esm/loadland.hpp index 9f33c37da8..a7b97a4654 100644 --- a/components/esm/loadland.hpp +++ b/components/esm/loadland.hpp @@ -64,6 +64,8 @@ struct Land //total number of textures per land static const int LAND_NUM_TEXTURES = LAND_TEXTURE_SIZE * LAND_TEXTURE_SIZE; + static const int LAND_GLOBAL_MAP_LOD_SIZE = 81; + #pragma pack(push,1) struct VHGT { @@ -109,7 +111,7 @@ struct Land }; // low-LOD heightmap (used for rendering the global map) - signed char mWnam[81]; + signed char mWnam[LAND_GLOBAL_MAP_LOD_SIZE]; void load(ESMReader &esm, bool &isDeleted); void save(ESMWriter &esm, bool isDeleted = false) const;