Something went wrong. Try again.
OpenMW is an open implementation of the Morrowind engine
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341#include "columnimp.hpp"
#include <apps/opencs/model/world/columnbase.hpp>#include <apps/opencs/model/world/columns.hpp>#include <apps/opencs/model/world/disabletag.hpp>#include <apps/opencs/model/world/land.hpp>#include <apps/opencs/model/world/record.hpp>
#include <components/esm3/loadland.hpp>#include <components/esm3/loadltex.hpp>#include <components/esm3/loadmgef.hpp>
#include <algorithm>#include <stdexcept>
namespace CSMWorld{ namespace { struct GetStringId { std::string operator()(ESM::EmptyRefId /*value*/) const { return std::string(); }
std::string operator()(ESM::StringRefId value) const { return value.getValue(); }
std::string operator()(ESM::FormId value) const { return value.toString("FormId:"); }
std::string operator()(ESM::IndexRefId value) const { return value.toDebugString(); }
template <class T> std::string operator()(const T& value) const { return value.toDebugString(); } }; }
/* LandTextureIndexColumn */ LandTextureIndexColumn::LandTextureIndexColumn() : Column<ESM::LandTexture>(Columns::ColumnId_TextureIndex, ColumnBase::Display_Integer) { }
QVariant LandTextureIndexColumn::get(const Record<ESM::LandTexture>& record) const { return record.get().mIndex; }
bool LandTextureIndexColumn::isEditable() const { return false; }
/* LandPluginIndexColumn */ LandPluginIndexColumn::LandPluginIndexColumn() : Column<Land>(Columns::ColumnId_PluginIndex, ColumnBase::Display_Integer, 0) { }
QVariant LandPluginIndexColumn::get(const Record<Land>& record) const { return record.get().getPlugin(); }
bool LandPluginIndexColumn::isEditable() const { return false; }
/* LandNormalsColumn */ LandNormalsColumn::LandNormalsColumn() : Column<Land>(Columns::ColumnId_LandNormalsIndex, ColumnBase::Display_String, 0) { }
QVariant LandNormalsColumn::get(const Record<Land>& record) const { const int size = Land::LAND_NUM_VERTS * 3; const Land& land = record.get();
DataType values(size, 0);
if (land.isDataLoaded(Land::DATA_VNML)) { for (int i = 0; i < size; ++i) values[i] = land.getLandData()->mNormals[i]; }
QVariant variant; variant.setValue(values); return variant; }
void LandNormalsColumn::set(Record<Land>& record, const QVariant& data) { DataType values = data.value<DataType>();
if (values.size() != Land::LAND_NUM_VERTS * 3) throw std::runtime_error("invalid land normals data");
Land copy = record.get(); copy.add(Land::DATA_VNML);
for (int i = 0; i < values.size(); ++i) { copy.getLandData()->mNormals[i] = values[i]; }
record.setModified(copy); }
bool LandNormalsColumn::isEditable() const { return true; }
/* LandHeightsColumn */ LandHeightsColumn::LandHeightsColumn() : Column<Land>(Columns::ColumnId_LandHeightsIndex, ColumnBase::Display_String, 0) { }
QVariant LandHeightsColumn::get(const Record<Land>& record) const { const int size = Land::LAND_NUM_VERTS; const Land& land = record.get();
DataType values(size, 0);
if (land.isDataLoaded(Land::DATA_VHGT)) { for (int i = 0; i < size; ++i) values[i] = land.getLandData()->mHeights[i]; }
QVariant variant; variant.setValue(values); return variant; }
void LandHeightsColumn::set(Record<Land>& record, const QVariant& data) { DataType values = data.value<DataType>();
if (values.size() != Land::LAND_NUM_VERTS) throw std::runtime_error("invalid land heights data");
Land copy = record.get(); copy.add(Land::DATA_VHGT);
for (int i = 0; i < values.size(); ++i) { copy.getLandData()->mHeights[i] = values[i]; }
copy.mFlags |= Land::Flag_HeightsNormals;
record.setModified(copy); }
bool LandHeightsColumn::isEditable() const { return true; }
/* LandColoursColumn */ LandColoursColumn::LandColoursColumn() : Column<Land>(Columns::ColumnId_LandColoursIndex, ColumnBase::Display_String, 0) { }
QVariant LandColoursColumn::get(const Record<Land>& record) const { const int size = Land::LAND_NUM_VERTS * 3; const Land& land = record.get();
// Missing VCLR should behave like default vertex colour (white), // not black. This avoids newly created/undefined edge land turning dark // when a single vertex edit writes the whole array back. DataType values(size, 255);
if (land.isDataLoaded(Land::DATA_VCLR)) { for (int i = 0; i < size; ++i) values[i] = land.getLandData()->mColours[i]; }
QVariant variant; variant.setValue(values); return variant; }
void LandColoursColumn::set(Record<Land>& record, const QVariant& data) { DataType values = data.value<DataType>();
if (values.size() != Land::LAND_NUM_VERTS * 3) throw std::runtime_error("invalid land colours data");
Land copy = record.get(); copy.add(Land::DATA_VCLR);
for (int i = 0; i < values.size(); ++i) { copy.getLandData()->mColours[i] = values[i]; }
copy.mFlags |= Land::Flag_Colors;
record.setModified(copy); }
bool LandColoursColumn::isEditable() const { return true; }
/* LandTexturesColumn */ LandTexturesColumn::LandTexturesColumn() : Column<Land>(Columns::ColumnId_LandTexturesIndex, ColumnBase::Display_String, 0) { }
QVariant LandTexturesColumn::get(const Record<Land>& record) const { const int size = Land::LAND_NUM_TEXTURES; const Land& land = record.get();
DataType values(size, 0);
if (land.isDataLoaded(Land::DATA_VTEX)) { for (int i = 0; i < size; ++i) values[i] = land.getLandData()->mTextures[i]; }
QVariant variant; variant.setValue(values); return variant; }
void LandTexturesColumn::set(Record<Land>& record, const QVariant& data) { DataType values = data.value<DataType>();
if (values.size() != Land::LAND_NUM_TEXTURES) throw std::runtime_error("invalid land textures data");
Land copy = record.get(); copy.add(Land::DATA_VTEX);
for (int i = 0; i < values.size(); ++i) { copy.getLandData()->mTextures[i] = values[i]; }
copy.mFlags |= Land::Flag_Textures;
record.setModified(copy); }
bool LandTexturesColumn::isEditable() const { return true; }
/* BodyPartRaceColumn */ BodyPartRaceColumn::BodyPartRaceColumn(const MeshTypeColumn<ESM::BodyPart>* meshType) : mMeshType(meshType) { }
QVariant BodyPartRaceColumn::get(const Record<ESM::BodyPart>& record) const { if (mMeshType != nullptr && mMeshType->get(record) == ESM::BodyPart::MT_Skin) { return QString::fromUtf8(record.get().mRace.getRefIdString().c_str()); }
return DisableTag::getVariant(); }
void BodyPartRaceColumn::set(Record<ESM::BodyPart>& record, const QVariant& data) { ESM::BodyPart record2 = record.get();
record2.mRace = ESM::RefId::stringRefId(data.toString().toUtf8().constData());
record.setModified(record2); }
bool BodyPartRaceColumn::isEditable() const { return true; }
SelectionGroupColumn::SelectionGroupColumn() : Column<ESM::SelectionGroup>(Columns::ColumnId_SelectionGroupObjects, ColumnBase::Display_None) { }
QVariant SelectionGroupColumn::get(const Record<ESM::SelectionGroup>& record) const { QVariant data; QStringList selectionInfo; const std::vector<std::string>& instances = record.get().selectedInstances;
for (const std::string& instance : instances) selectionInfo << QString::fromStdString(instance); data.setValue(selectionInfo);
return data; }
void SelectionGroupColumn::set(Record<ESM::SelectionGroup>& record, const QVariant& data) { ESM::SelectionGroup record2 = record.get(); for (const auto& item : data.toStringList()) record2.selectedInstances.push_back(item.toStdString()); record.setModified(record2); }
bool SelectionGroupColumn::isEditable() const { return false; }
std::optional<std::uint32_t> getSkillIndex(std::string_view value) { int index = ESM::Skill::refIdToIndex(ESM::RefId::stringRefId(value)); if (index < 0) return std::nullopt; return static_cast<std::uint32_t>(index); }
std::string getStringId(ESM::RefId value) { return visit(GetStringId{}, value); }}