mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-09-09 04:15:40 -04:00
Rework land texture handling
This commit is contained in:
parent
965bc20bab
commit
fbc6629d40
@ -25,7 +25,7 @@ opencs_units (model/world
|
|||||||
opencs_units (model/world
|
opencs_units (model/world
|
||||||
universalid record commands columnbase columnimp scriptcontext cell refidcollection
|
universalid record commands columnbase columnimp scriptcontext cell refidcollection
|
||||||
refiddata refidadapterimp ref collectionbase refcollection columns infocollection tablemimedata cellcoordinates cellselection resources resourcesmanager scope
|
refiddata refidadapterimp ref collectionbase refcollection columns infocollection tablemimedata cellcoordinates cellselection resources resourcesmanager scope
|
||||||
pathgrid landtexture land nestedtablewrapper nestedcollection nestedcoladapterimp nestedinfocollection
|
pathgrid land nestedtablewrapper nestedcollection nestedcoladapterimp nestedinfocollection
|
||||||
idcompletionmanager metadata defaultgmsts infoselectwrapper commandmacro
|
idcompletionmanager metadata defaultgmsts infoselectwrapper commandmacro
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -70,7 +70,7 @@ opencs_units (view/world
|
|||||||
cellcreator pathgridcreator referenceablecreator startscriptcreator referencecreator scenesubview
|
cellcreator pathgridcreator referenceablecreator startscriptcreator referencecreator scenesubview
|
||||||
infocreator scriptedit dialoguesubview previewsubview regionmap dragrecordtable nestedtable
|
infocreator scriptedit dialoguesubview previewsubview regionmap dragrecordtable nestedtable
|
||||||
dialoguespinbox recordbuttonbar tableeditidaction scripterrortable extendedcommandconfigurator
|
dialoguespinbox recordbuttonbar tableeditidaction scripterrortable extendedcommandconfigurator
|
||||||
bodypartcreator landtexturecreator landcreator tableheadermouseeventhandler
|
bodypartcreator landcreator tableheadermouseeventhandler
|
||||||
)
|
)
|
||||||
|
|
||||||
opencs_units (view/world
|
opencs_units (view/world
|
||||||
|
@ -17,7 +17,6 @@
|
|||||||
#include <apps/opencs/model/world/idcollection.hpp>
|
#include <apps/opencs/model/world/idcollection.hpp>
|
||||||
#include <apps/opencs/model/world/info.hpp>
|
#include <apps/opencs/model/world/info.hpp>
|
||||||
#include <apps/opencs/model/world/land.hpp>
|
#include <apps/opencs/model/world/land.hpp>
|
||||||
#include <apps/opencs/model/world/landtexture.hpp>
|
|
||||||
#include <apps/opencs/model/world/metadata.hpp>
|
#include <apps/opencs/model/world/metadata.hpp>
|
||||||
#include <apps/opencs/model/world/pathgrid.hpp>
|
#include <apps/opencs/model/world/pathgrid.hpp>
|
||||||
#include <apps/opencs/model/world/record.hpp>
|
#include <apps/opencs/model/world/record.hpp>
|
||||||
@ -498,11 +497,11 @@ int CSMDoc::WriteLandTextureCollectionStage::setup()
|
|||||||
void CSMDoc::WriteLandTextureCollectionStage::perform(int stage, Messages& messages)
|
void CSMDoc::WriteLandTextureCollectionStage::perform(int stage, Messages& messages)
|
||||||
{
|
{
|
||||||
ESM::ESMWriter& writer = mState.getWriter();
|
ESM::ESMWriter& writer = mState.getWriter();
|
||||||
const CSMWorld::Record<CSMWorld::LandTexture>& landTexture = mDocument.getData().getLandTextures().getRecord(stage);
|
const CSMWorld::Record<ESM::LandTexture>& landTexture = mDocument.getData().getLandTextures().getRecord(stage);
|
||||||
|
|
||||||
if (landTexture.isModified() || landTexture.mState == CSMWorld::RecordBase::State_Deleted)
|
if (landTexture.isModified() || landTexture.mState == CSMWorld::RecordBase::State_Deleted)
|
||||||
{
|
{
|
||||||
CSMWorld::LandTexture record = landTexture.get();
|
ESM::LandTexture record = landTexture.get();
|
||||||
writer.startRecord(record.sRecordId);
|
writer.startRecord(record.sRecordId);
|
||||||
record.save(writer, landTexture.mState == CSMWorld::RecordBase::State_Deleted);
|
record.save(writer, landTexture.mState == CSMWorld::RecordBase::State_Deleted);
|
||||||
writer.endRecord(record.sRecordId);
|
writer.endRecord(record.sRecordId);
|
||||||
|
@ -6,7 +6,6 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <apps/opencs/model/world/land.hpp>
|
#include <apps/opencs/model/world/land.hpp>
|
||||||
#include <apps/opencs/model/world/landtexture.hpp>
|
|
||||||
#include <apps/opencs/model/world/metadata.hpp>
|
#include <apps/opencs/model/world/metadata.hpp>
|
||||||
#include <apps/opencs/model/world/ref.hpp>
|
#include <apps/opencs/model/world/ref.hpp>
|
||||||
#include <apps/opencs/model/world/refcollection.hpp>
|
#include <apps/opencs/model/world/refcollection.hpp>
|
||||||
@ -137,13 +136,12 @@ int CSMTools::PopulateLandTexturesMergeStage::setup()
|
|||||||
|
|
||||||
void CSMTools::PopulateLandTexturesMergeStage::perform(int stage, CSMDoc::Messages& messages)
|
void CSMTools::PopulateLandTexturesMergeStage::perform(int stage, CSMDoc::Messages& messages)
|
||||||
{
|
{
|
||||||
const CSMWorld::Record<CSMWorld::LandTexture>& record = mState.mSource.getData().getLandTextures().getRecord(stage);
|
const CSMWorld::Record<ESM::LandTexture>& record = mState.mSource.getData().getLandTextures().getRecord(stage);
|
||||||
|
|
||||||
if (!record.isDeleted())
|
if (!record.isDeleted())
|
||||||
{
|
{
|
||||||
mState.mTarget->getData().getLandTextures().appendRecord(
|
mState.mTarget->getData().getLandTextures().appendRecord(std::make_unique<CSMWorld::Record<ESM::LandTexture>>(
|
||||||
std::make_unique<CSMWorld::Record<CSMWorld::LandTexture>>(CSMWorld::Record<CSMWorld::LandTexture>(
|
CSMWorld::Record<ESM::LandTexture>(CSMWorld::RecordBase::State_ModifiedOnly, nullptr, &record.get())));
|
||||||
CSMWorld::RecordBase::State_ModifiedOnly, nullptr, &record.get())));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,7 +24,6 @@
|
|||||||
#include "columnimp.hpp"
|
#include "columnimp.hpp"
|
||||||
#include "info.hpp"
|
#include "info.hpp"
|
||||||
#include "land.hpp"
|
#include "land.hpp"
|
||||||
#include "landtexture.hpp"
|
|
||||||
#include "record.hpp"
|
#include "record.hpp"
|
||||||
#include "ref.hpp"
|
#include "ref.hpp"
|
||||||
|
|
||||||
@ -74,16 +73,6 @@ namespace CSMWorld
|
|||||||
return ESM::RefId::stringRefId(Land::createUniqueRecordId(record.mX, record.mY));
|
return ESM::RefId::stringRefId(Land::createUniqueRecordId(record.mX, record.mY));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void setRecordId(const ESM::RefId& id, LandTexture& record)
|
|
||||||
{
|
|
||||||
int plugin = 0;
|
|
||||||
int index = 0;
|
|
||||||
|
|
||||||
LandTexture::parseUniqueRecordId(id.getRefIdString(), plugin, index);
|
|
||||||
record.mPluginIndex = plugin;
|
|
||||||
record.mIndex = index;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline ESM::RefId getRecordId(const ESM::MagicEffect& record)
|
inline ESM::RefId getRecordId(const ESM::MagicEffect& record)
|
||||||
{
|
{
|
||||||
return ESM::RefId::stringRefId(CSMWorld::getStringId(record.mId));
|
return ESM::RefId::stringRefId(CSMWorld::getStringId(record.mId));
|
||||||
@ -95,11 +84,6 @@ namespace CSMWorld
|
|||||||
record.mId = ESM::RefId::index(ESM::REC_MGEF, static_cast<std::uint32_t>(index));
|
record.mId = ESM::RefId::index(ESM::REC_MGEF, static_cast<std::uint32_t>(index));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline ESM::RefId getRecordId(const LandTexture& record)
|
|
||||||
{
|
|
||||||
return ESM::RefId::stringRefId(LandTexture::createUniqueRecordId(record.mPluginIndex, record.mIndex));
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void setRecordId(const ESM::RefId& id, ESM::Skill& record)
|
inline void setRecordId(const ESM::RefId& id, ESM::Skill& record)
|
||||||
{
|
{
|
||||||
if (const auto* skillId = id.getIf<ESM::SkillId>())
|
if (const auto* skillId = id.getIf<ESM::SkillId>())
|
||||||
@ -339,7 +323,7 @@ namespace CSMWorld
|
|||||||
const ESM::RefId& origin, const ESM::RefId& destination, const UniversalId::Type type)
|
const ESM::RefId& origin, const ESM::RefId& destination, const UniversalId::Type type)
|
||||||
{
|
{
|
||||||
const int index = cloneRecordImp(origin, destination, type);
|
const int index = cloneRecordImp(origin, destination, type);
|
||||||
mRecords.at(index)->get().setPlugin(0);
|
mRecords.at(index)->get().setPlugin(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ESXRecordT>
|
template <typename ESXRecordT>
|
||||||
@ -354,7 +338,7 @@ namespace CSMWorld
|
|||||||
const int index = touchRecordImp(id);
|
const int index = touchRecordImp(id);
|
||||||
if (index >= 0)
|
if (index >= 0)
|
||||||
{
|
{
|
||||||
mRecords.at(index)->get().setPlugin(0);
|
mRecords.at(index)->get().setPlugin(-1);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,10 +3,10 @@
|
|||||||
#include <apps/opencs/model/world/columnbase.hpp>
|
#include <apps/opencs/model/world/columnbase.hpp>
|
||||||
#include <apps/opencs/model/world/columns.hpp>
|
#include <apps/opencs/model/world/columns.hpp>
|
||||||
#include <apps/opencs/model/world/land.hpp>
|
#include <apps/opencs/model/world/land.hpp>
|
||||||
#include <apps/opencs/model/world/landtexture.hpp>
|
|
||||||
#include <apps/opencs/model/world/record.hpp>
|
#include <apps/opencs/model/world/record.hpp>
|
||||||
|
|
||||||
#include <components/esm3/loadland.hpp>
|
#include <components/esm3/loadland.hpp>
|
||||||
|
#include <components/esm3/loadltex.hpp>
|
||||||
#include <components/esm3/loadmgef.hpp>
|
#include <components/esm3/loadmgef.hpp>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@ -45,36 +45,13 @@ namespace CSMWorld
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/* LandTextureNicknameColumn */
|
|
||||||
LandTextureNicknameColumn::LandTextureNicknameColumn()
|
|
||||||
: Column<LandTexture>(Columns::ColumnId_TextureNickname, ColumnBase::Display_String)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariant LandTextureNicknameColumn::get(const Record<LandTexture>& record) const
|
|
||||||
{
|
|
||||||
return QString::fromStdString(record.get().mId.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
void LandTextureNicknameColumn::set(Record<LandTexture>& record, const QVariant& data)
|
|
||||||
{
|
|
||||||
LandTexture copy = record.get();
|
|
||||||
copy.mId = ESM::RefId::stringRefId(data.toString().toUtf8().constData());
|
|
||||||
record.setModified(copy);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool LandTextureNicknameColumn::isEditable() const
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* LandTextureIndexColumn */
|
/* LandTextureIndexColumn */
|
||||||
LandTextureIndexColumn::LandTextureIndexColumn()
|
LandTextureIndexColumn::LandTextureIndexColumn()
|
||||||
: Column<LandTexture>(Columns::ColumnId_TextureIndex, ColumnBase::Display_Integer)
|
: Column<ESM::LandTexture>(Columns::ColumnId_TextureIndex, ColumnBase::Display_Integer)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant LandTextureIndexColumn::get(const Record<LandTexture>& record) const
|
QVariant LandTextureIndexColumn::get(const Record<ESM::LandTexture>& record) const
|
||||||
{
|
{
|
||||||
return record.get().mIndex;
|
return record.get().mIndex;
|
||||||
}
|
}
|
||||||
@ -100,22 +77,6 @@ namespace CSMWorld
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* LandTexturePluginIndexColumn */
|
|
||||||
LandTexturePluginIndexColumn::LandTexturePluginIndexColumn()
|
|
||||||
: Column<LandTexture>(Columns::ColumnId_PluginIndex, ColumnBase::Display_Integer, 0)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariant LandTexturePluginIndexColumn::get(const Record<LandTexture>& record) const
|
|
||||||
{
|
|
||||||
return record.get().mPluginIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool LandTexturePluginIndexColumn::isEditable() const
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* LandNormalsColumn */
|
/* LandNormalsColumn */
|
||||||
LandNormalsColumn::LandNormalsColumn()
|
LandNormalsColumn::LandNormalsColumn()
|
||||||
: Column<Land>(Columns::ColumnId_LandNormalsIndex, ColumnBase::Display_String, 0)
|
: Column<Land>(Columns::ColumnId_LandNormalsIndex, ColumnBase::Display_String, 0)
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include <components/esm3/loadbody.hpp>
|
#include <components/esm3/loadbody.hpp>
|
||||||
#include <components/esm3/loaddial.hpp>
|
#include <components/esm3/loaddial.hpp>
|
||||||
#include <components/esm3/loadinfo.hpp>
|
#include <components/esm3/loadinfo.hpp>
|
||||||
|
#include <components/esm3/loadltex.hpp>
|
||||||
#include <components/esm3/loadrace.hpp>
|
#include <components/esm3/loadrace.hpp>
|
||||||
#include <components/esm3/loadskil.hpp>
|
#include <components/esm3/loadskil.hpp>
|
||||||
#include <components/esm3/selectiongroup.hpp>
|
#include <components/esm3/selectiongroup.hpp>
|
||||||
@ -29,7 +30,6 @@
|
|||||||
#include "columns.hpp"
|
#include "columns.hpp"
|
||||||
#include "info.hpp"
|
#include "info.hpp"
|
||||||
#include "land.hpp"
|
#include "land.hpp"
|
||||||
#include "landtexture.hpp"
|
|
||||||
#include "record.hpp"
|
#include "record.hpp"
|
||||||
|
|
||||||
namespace CSMWorld
|
namespace CSMWorld
|
||||||
@ -83,13 +83,6 @@ namespace CSMWorld
|
|||||||
return QString::fromUtf8(Land::createUniqueRecordId(land.mX, land.mY).c_str());
|
return QString::fromUtf8(Land::createUniqueRecordId(land.mX, land.mY).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
|
||||||
inline QVariant StringIdColumn<LandTexture>::get(const Record<LandTexture>& record) const
|
|
||||||
{
|
|
||||||
const LandTexture& ltex = record.get();
|
|
||||||
return QString::fromUtf8(LandTexture::createUniqueRecordId(ltex.mPluginIndex, ltex.mIndex).c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename ESXRecordT>
|
template <typename ESXRecordT>
|
||||||
struct RecordStateColumn : public Column<ESXRecordT>
|
struct RecordStateColumn : public Column<ESXRecordT>
|
||||||
{
|
{
|
||||||
@ -2365,20 +2358,11 @@ namespace CSMWorld
|
|||||||
bool isEditable() const override { return true; }
|
bool isEditable() const override { return true; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct LandTextureNicknameColumn : public Column<LandTexture>
|
struct LandTextureIndexColumn : public Column<ESM::LandTexture>
|
||||||
{
|
|
||||||
LandTextureNicknameColumn();
|
|
||||||
|
|
||||||
QVariant get(const Record<LandTexture>& record) const override;
|
|
||||||
void set(Record<LandTexture>& record, const QVariant& data) override;
|
|
||||||
bool isEditable() const override;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct LandTextureIndexColumn : public Column<LandTexture>
|
|
||||||
{
|
{
|
||||||
LandTextureIndexColumn();
|
LandTextureIndexColumn();
|
||||||
|
|
||||||
QVariant get(const Record<LandTexture>& record) const override;
|
QVariant get(const Record<ESM::LandTexture>& record) const override;
|
||||||
bool isEditable() const override;
|
bool isEditable() const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2390,14 +2374,6 @@ namespace CSMWorld
|
|||||||
bool isEditable() const override;
|
bool isEditable() const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct LandTexturePluginIndexColumn : public Column<LandTexture>
|
|
||||||
{
|
|
||||||
LandTexturePluginIndexColumn();
|
|
||||||
|
|
||||||
QVariant get(const Record<LandTexture>& record) const override;
|
|
||||||
bool isEditable() const override;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct LandNormalsColumn : public Column<Land>
|
struct LandNormalsColumn : public Column<Land>
|
||||||
{
|
{
|
||||||
using DataType = QVector<signed char>;
|
using DataType = QVector<signed char>;
|
||||||
|
@ -7,7 +7,6 @@
|
|||||||
|
|
||||||
#include <apps/opencs/model/world/columns.hpp>
|
#include <apps/opencs/model/world/columns.hpp>
|
||||||
#include <apps/opencs/model/world/land.hpp>
|
#include <apps/opencs/model/world/land.hpp>
|
||||||
#include <apps/opencs/model/world/landtexture.hpp>
|
|
||||||
#include <apps/opencs/model/world/record.hpp>
|
#include <apps/opencs/model/world/record.hpp>
|
||||||
#include <apps/opencs/model/world/universalid.hpp>
|
#include <apps/opencs/model/world/universalid.hpp>
|
||||||
|
|
||||||
@ -61,11 +60,11 @@ CSMWorld::ImportLandTexturesCommand::ImportLandTexturesCommand(
|
|||||||
|
|
||||||
void CSMWorld::ImportLandTexturesCommand::redo()
|
void CSMWorld::ImportLandTexturesCommand::redo()
|
||||||
{
|
{
|
||||||
int pluginColumn = mLands.findColumnIndex(Columns::ColumnId_PluginIndex);
|
const int pluginColumn = mLands.findColumnIndex(Columns::ColumnId_PluginIndex);
|
||||||
int oldPlugin = mLands.data(mLands.getModelIndex(getOriginId(), pluginColumn)).toInt();
|
const int oldPlugin = mLands.data(mLands.getModelIndex(getOriginId(), pluginColumn)).toInt();
|
||||||
|
|
||||||
// Original data
|
// Original data
|
||||||
int textureColumn = mLands.findColumnIndex(Columns::ColumnId_LandTexturesIndex);
|
const int textureColumn = mLands.findColumnIndex(Columns::ColumnId_LandTexturesIndex);
|
||||||
mOld = mLands.data(mLands.getModelIndex(getOriginId(), textureColumn)).value<DataType>();
|
mOld = mLands.data(mLands.getModelIndex(getOriginId(), textureColumn)).value<DataType>();
|
||||||
|
|
||||||
// Need to make a copy so the old values can be looked up
|
// Need to make a copy so the old values can be looked up
|
||||||
@ -74,44 +73,37 @@ void CSMWorld::ImportLandTexturesCommand::redo()
|
|||||||
// Perform touch/copy/etc...
|
// Perform touch/copy/etc...
|
||||||
onRedo();
|
onRedo();
|
||||||
|
|
||||||
// Find all indices used
|
std::unordered_map<uint16_t, uint16_t> indexMapping;
|
||||||
std::unordered_set<int> texIndices;
|
for (uint16_t index : mOld)
|
||||||
for (int i = 0; i < mOld.size(); ++i)
|
|
||||||
{
|
{
|
||||||
// All indices are offset by 1 for a default texture
|
// All indices are offset by 1 for a default texture
|
||||||
if (mOld[i] > 0)
|
if (index == 0)
|
||||||
texIndices.insert(mOld[i] - 1);
|
continue;
|
||||||
}
|
if (indexMapping.contains(index))
|
||||||
|
continue;
|
||||||
std::vector<std::string> oldTextures;
|
const CSMWorld::Record<ESM::LandTexture>* record
|
||||||
oldTextures.reserve(texIndices.size());
|
= static_cast<LandTextureIdTable&>(mLtexs).searchRecord(index - 1, oldPlugin);
|
||||||
for (int index : texIndices)
|
if (!record || record->isDeleted())
|
||||||
{
|
|
||||||
oldTextures.push_back(LandTexture::createUniqueRecordId(oldPlugin, index));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Import the textures, replace old values
|
|
||||||
LandTextureIdTable::ImportResults results = dynamic_cast<LandTextureIdTable&>(mLtexs).importTextures(oldTextures);
|
|
||||||
mCreatedTextures = std::move(results.createdRecords);
|
|
||||||
for (const auto& it : results.recordMapping)
|
|
||||||
{
|
|
||||||
int plugin = 0, newIndex = 0, oldIndex = 0;
|
|
||||||
LandTexture::parseUniqueRecordId(it.first, plugin, oldIndex);
|
|
||||||
LandTexture::parseUniqueRecordId(it.second, plugin, newIndex);
|
|
||||||
|
|
||||||
if (newIndex != oldIndex)
|
|
||||||
{
|
{
|
||||||
for (int i = 0; i < Land::LAND_NUM_TEXTURES; ++i)
|
indexMapping.emplace(index, 0);
|
||||||
{
|
continue;
|
||||||
// All indices are offset by 1 for a default texture
|
|
||||||
if (mOld[i] == oldIndex + 1)
|
|
||||||
copy[i] = newIndex + 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if (!record->isModified())
|
||||||
|
{
|
||||||
|
mTouchedTextures.emplace_back(record->clone());
|
||||||
|
mLtexs.touchRecord(record->get().mId.getRefIdString());
|
||||||
|
}
|
||||||
|
indexMapping.emplace(index, record->get().mIndex + 1);
|
||||||
|
}
|
||||||
|
for (int i = 0; i < Land::LAND_NUM_TEXTURES; ++i)
|
||||||
|
{
|
||||||
|
uint16_t oldIndex = mOld[i];
|
||||||
|
uint16_t newIndex = indexMapping[oldIndex];
|
||||||
|
copy[i] = newIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply modification
|
// Apply modification
|
||||||
int stateColumn = mLands.findColumnIndex(Columns::ColumnId_Modification);
|
const int stateColumn = mLands.findColumnIndex(Columns::ColumnId_Modification);
|
||||||
mOldState = mLands.data(mLands.getModelIndex(getDestinationId(), stateColumn)).toInt();
|
mOldState = mLands.data(mLands.getModelIndex(getDestinationId(), stateColumn)).toInt();
|
||||||
|
|
||||||
QVariant variant;
|
QVariant variant;
|
||||||
@ -133,12 +125,12 @@ void CSMWorld::ImportLandTexturesCommand::undo()
|
|||||||
// Undo copy/touch/etc...
|
// Undo copy/touch/etc...
|
||||||
onUndo();
|
onUndo();
|
||||||
|
|
||||||
for (const std::string& id : mCreatedTextures)
|
for (auto& ltex : mTouchedTextures)
|
||||||
{
|
{
|
||||||
int row = mLtexs.getModelIndex(id, 0).row();
|
ESM::RefId id = static_cast<Record<ESM::LandTexture>*>(ltex.get())->get().mId;
|
||||||
mLtexs.removeRows(row, 1);
|
mLtexs.setRecord(id.getRefIdString(), std::move(ltex));
|
||||||
}
|
}
|
||||||
mCreatedTextures.clear();
|
mTouchedTextures.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
CSMWorld::CopyLandTexturesCommand::CopyLandTexturesCommand(
|
CSMWorld::CopyLandTexturesCommand::CopyLandTexturesCommand(
|
||||||
|
@ -69,7 +69,7 @@ namespace CSMWorld
|
|||||||
IdTable& mLtexs;
|
IdTable& mLtexs;
|
||||||
DataType mOld;
|
DataType mOld;
|
||||||
int mOldState;
|
int mOldState;
|
||||||
std::vector<std::string> mCreatedTextures;
|
std::vector<std::unique_ptr<RecordBase>> mTouchedTextures;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief This command is used to fix LandTexture records and texture
|
/// \brief This command is used to fix LandTexture records and texture
|
||||||
|
@ -16,7 +16,6 @@
|
|||||||
#include <apps/opencs/model/world/info.hpp>
|
#include <apps/opencs/model/world/info.hpp>
|
||||||
#include <apps/opencs/model/world/infocollection.hpp>
|
#include <apps/opencs/model/world/infocollection.hpp>
|
||||||
#include <apps/opencs/model/world/land.hpp>
|
#include <apps/opencs/model/world/land.hpp>
|
||||||
#include <apps/opencs/model/world/landtexture.hpp>
|
|
||||||
#include <apps/opencs/model/world/metadata.hpp>
|
#include <apps/opencs/model/world/metadata.hpp>
|
||||||
#include <apps/opencs/model/world/nestedidcollection.hpp>
|
#include <apps/opencs/model/world/nestedidcollection.hpp>
|
||||||
#include <apps/opencs/model/world/nestedinfocollection.hpp>
|
#include <apps/opencs/model/world/nestedinfocollection.hpp>
|
||||||
@ -36,6 +35,7 @@
|
|||||||
#include <components/esm3/loadcell.hpp>
|
#include <components/esm3/loadcell.hpp>
|
||||||
#include <components/esm3/loaddoor.hpp>
|
#include <components/esm3/loaddoor.hpp>
|
||||||
#include <components/esm3/loadglob.hpp>
|
#include <components/esm3/loadglob.hpp>
|
||||||
|
#include <components/esm3/loadltex.hpp>
|
||||||
#include <components/esm3/loadstat.hpp>
|
#include <components/esm3/loadstat.hpp>
|
||||||
#include <components/files/collections.hpp>
|
#include <components/files/collections.hpp>
|
||||||
#include <components/misc/strings/lower.hpp>
|
#include <components/misc/strings/lower.hpp>
|
||||||
@ -530,13 +530,11 @@ CSMWorld::Data::Data(ToUTF8::FromType encoding, const Files::PathContainer& data
|
|||||||
mLand.addColumn(new LandColoursColumn);
|
mLand.addColumn(new LandColoursColumn);
|
||||||
mLand.addColumn(new LandTexturesColumn);
|
mLand.addColumn(new LandTexturesColumn);
|
||||||
|
|
||||||
mLandTextures.addColumn(new StringIdColumn<LandTexture>(true));
|
mLandTextures.addColumn(new StringIdColumn<ESM::LandTexture>);
|
||||||
mLandTextures.addColumn(new RecordStateColumn<LandTexture>);
|
mLandTextures.addColumn(new RecordStateColumn<ESM::LandTexture>);
|
||||||
mLandTextures.addColumn(new FixedRecordTypeColumn<LandTexture>(UniversalId::Type_LandTexture));
|
mLandTextures.addColumn(new FixedRecordTypeColumn<ESM::LandTexture>(UniversalId::Type_LandTexture));
|
||||||
mLandTextures.addColumn(new LandTextureNicknameColumn);
|
|
||||||
mLandTextures.addColumn(new LandTexturePluginIndexColumn);
|
|
||||||
mLandTextures.addColumn(new LandTextureIndexColumn);
|
mLandTextures.addColumn(new LandTextureIndexColumn);
|
||||||
mLandTextures.addColumn(new TextureColumn<LandTexture>);
|
mLandTextures.addColumn(new TextureColumn<ESM::LandTexture>);
|
||||||
|
|
||||||
mPathgrids.addColumn(new StringIdColumn<Pathgrid>);
|
mPathgrids.addColumn(new StringIdColumn<Pathgrid>);
|
||||||
mPathgrids.addColumn(new RecordStateColumn<Pathgrid>);
|
mPathgrids.addColumn(new RecordStateColumn<Pathgrid>);
|
||||||
@ -939,12 +937,12 @@ CSMWorld::IdCollection<CSMWorld::Land>& CSMWorld::Data::getLand()
|
|||||||
return mLand;
|
return mLand;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CSMWorld::IdCollection<CSMWorld::LandTexture>& CSMWorld::Data::getLandTextures() const
|
const CSMWorld::IdCollection<ESM::LandTexture>& CSMWorld::Data::getLandTextures() const
|
||||||
{
|
{
|
||||||
return mLandTextures;
|
return mLandTextures;
|
||||||
}
|
}
|
||||||
|
|
||||||
CSMWorld::IdCollection<CSMWorld::LandTexture>& CSMWorld::Data::getLandTextures()
|
CSMWorld::IdCollection<ESM::LandTexture>& CSMWorld::Data::getLandTextures()
|
||||||
{
|
{
|
||||||
return mLandTextures;
|
return mLandTextures;
|
||||||
}
|
}
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include <components/esm3/loadfact.hpp>
|
#include <components/esm3/loadfact.hpp>
|
||||||
#include <components/esm3/loadglob.hpp>
|
#include <components/esm3/loadglob.hpp>
|
||||||
#include <components/esm3/loadgmst.hpp>
|
#include <components/esm3/loadgmst.hpp>
|
||||||
|
#include <components/esm3/loadltex.hpp>
|
||||||
#include <components/esm3/loadmgef.hpp>
|
#include <components/esm3/loadmgef.hpp>
|
||||||
#include <components/esm3/loadrace.hpp>
|
#include <components/esm3/loadrace.hpp>
|
||||||
#include <components/esm3/loadregn.hpp>
|
#include <components/esm3/loadregn.hpp>
|
||||||
@ -43,7 +44,6 @@
|
|||||||
#include "idcollection.hpp"
|
#include "idcollection.hpp"
|
||||||
#include "infocollection.hpp"
|
#include "infocollection.hpp"
|
||||||
#include "land.hpp"
|
#include "land.hpp"
|
||||||
#include "landtexture.hpp"
|
|
||||||
#include "metadata.hpp"
|
#include "metadata.hpp"
|
||||||
#include "nestedidcollection.hpp"
|
#include "nestedidcollection.hpp"
|
||||||
#include "nestedinfocollection.hpp"
|
#include "nestedinfocollection.hpp"
|
||||||
@ -114,7 +114,7 @@ namespace CSMWorld
|
|||||||
InfoCollection mJournalInfos;
|
InfoCollection mJournalInfos;
|
||||||
NestedIdCollection<Cell> mCells;
|
NestedIdCollection<Cell> mCells;
|
||||||
SubCellCollection<Pathgrid> mPathgrids;
|
SubCellCollection<Pathgrid> mPathgrids;
|
||||||
IdCollection<LandTexture> mLandTextures;
|
IdCollection<ESM::LandTexture> mLandTextures;
|
||||||
IdCollection<Land> mLand;
|
IdCollection<Land> mLand;
|
||||||
RefIdCollection mReferenceables;
|
RefIdCollection mReferenceables;
|
||||||
RefCollection mRefs;
|
RefCollection mRefs;
|
||||||
@ -259,9 +259,9 @@ namespace CSMWorld
|
|||||||
|
|
||||||
IdCollection<CSMWorld::Land>& getLand();
|
IdCollection<CSMWorld::Land>& getLand();
|
||||||
|
|
||||||
const IdCollection<CSMWorld::LandTexture>& getLandTextures() const;
|
const IdCollection<ESM::LandTexture>& getLandTextures() const;
|
||||||
|
|
||||||
IdCollection<CSMWorld::LandTexture>& getLandTextures();
|
IdCollection<ESM::LandTexture>& getLandTextures();
|
||||||
|
|
||||||
const IdCollection<ESM::SoundGenerator>& getSoundGens() const;
|
const IdCollection<ESM::SoundGenerator>& getSoundGens() const;
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include <apps/opencs/model/world/pathgrid.hpp>
|
#include <apps/opencs/model/world/pathgrid.hpp>
|
||||||
#include <apps/opencs/model/world/record.hpp>
|
#include <apps/opencs/model/world/record.hpp>
|
||||||
|
|
||||||
|
#include <components/esm3/esmreader.hpp>
|
||||||
#include <components/esm3/loadpgrd.hpp>
|
#include <components/esm3/loadpgrd.hpp>
|
||||||
|
|
||||||
namespace ESM
|
namespace ESM
|
||||||
@ -18,12 +19,12 @@ namespace ESM
|
|||||||
namespace CSMWorld
|
namespace CSMWorld
|
||||||
{
|
{
|
||||||
template <>
|
template <>
|
||||||
int IdCollection<Pathgrid>::load(ESM::ESMReader& reader, bool base)
|
int BaseIdCollection<Pathgrid>::load(ESM::ESMReader& reader, bool base)
|
||||||
{
|
{
|
||||||
Pathgrid record;
|
Pathgrid record;
|
||||||
bool isDeleted = false;
|
bool isDeleted = false;
|
||||||
|
|
||||||
loadRecord(record, reader, isDeleted);
|
loadRecord(record, reader, isDeleted, base);
|
||||||
|
|
||||||
const ESM::RefId id = getRecordId(record);
|
const ESM::RefId id = getRecordId(record);
|
||||||
int index = this->searchId(id);
|
int index = this->searchId(id);
|
||||||
@ -55,4 +56,115 @@ namespace CSMWorld
|
|||||||
|
|
||||||
return load(record, base, index);
|
return load(record, base, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Record<ESM::LandTexture>* IdCollection<ESM::LandTexture>::searchRecord(std::uint16_t index, int plugin) const
|
||||||
|
{
|
||||||
|
auto found = mIndices.find({ plugin, index });
|
||||||
|
if (found != mIndices.end())
|
||||||
|
{
|
||||||
|
int index = searchId(found->second);
|
||||||
|
if (index != -1)
|
||||||
|
return &getRecord(index);
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string* IdCollection<ESM::LandTexture>::getLandTexture(std::uint16_t index, int plugin) const
|
||||||
|
{
|
||||||
|
const Record<ESM::LandTexture>* record = searchRecord(index, plugin);
|
||||||
|
if (record && !record->isDeleted())
|
||||||
|
return &record->get().mTexture;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IdCollection<ESM::LandTexture>::loadRecord(
|
||||||
|
ESM::LandTexture& record, ESM::ESMReader& reader, bool& isDeleted, bool base)
|
||||||
|
{
|
||||||
|
record.load(reader, isDeleted);
|
||||||
|
int plugin = base ? reader.getIndex() : -1;
|
||||||
|
mIndices.emplace(std::make_pair(plugin, record.mIndex), record.mId);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::uint16_t IdCollection<ESM::LandTexture>::assignNewIndex(ESM::RefId id)
|
||||||
|
{
|
||||||
|
std::uint16_t index = 0;
|
||||||
|
if (!mIndices.empty())
|
||||||
|
{
|
||||||
|
auto end = mIndices.lower_bound({ -1, std::numeric_limits<std::uint16_t>::max() });
|
||||||
|
if (end != mIndices.begin())
|
||||||
|
end = std::prev(end);
|
||||||
|
if (end->first.first == -1)
|
||||||
|
{
|
||||||
|
constexpr std::uint16_t maxIndex = std::numeric_limits<std::uint16_t>::max() - 1;
|
||||||
|
if (end->first.second < maxIndex)
|
||||||
|
index = end->first.second + 1;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::uint16_t prevIndex = 0;
|
||||||
|
for (auto it = mIndices.lower_bound({ -1, 0 }); it != end; ++it)
|
||||||
|
{
|
||||||
|
if (prevIndex != it->first.second)
|
||||||
|
{
|
||||||
|
index = prevIndex;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
++prevIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mIndices.emplace(std::make_pair(-1, index), id);
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IdCollection<ESM::LandTexture>::touchRecord(const ESM::RefId& id)
|
||||||
|
{
|
||||||
|
int row = BaseIdCollection<ESM::LandTexture>::touchRecordImp(id);
|
||||||
|
if (row != -1)
|
||||||
|
{
|
||||||
|
const_cast<ESM::LandTexture&>(getRecord(row).get()).mIndex = assignNewIndex(id);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IdCollection<ESM::LandTexture>::cloneRecord(
|
||||||
|
const ESM::RefId& origin, const ESM::RefId& destination, const UniversalId::Type type)
|
||||||
|
{
|
||||||
|
int row = cloneRecordImp(origin, destination, type);
|
||||||
|
const_cast<ESM::LandTexture&>(getRecord(row).get()).mIndex = assignNewIndex(destination);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IdCollection<ESM::LandTexture>::appendBlankRecord(const ESM::RefId& id, UniversalId::Type type)
|
||||||
|
{
|
||||||
|
ESM::LandTexture record;
|
||||||
|
record.blank();
|
||||||
|
record.mId = id;
|
||||||
|
record.mIndex = assignNewIndex(id);
|
||||||
|
|
||||||
|
auto record2 = std::make_unique<Record<ESM::LandTexture>>();
|
||||||
|
record2->mState = Record<ESM::LandTexture>::State_ModifiedOnly;
|
||||||
|
record2->mModified = std::move(record);
|
||||||
|
|
||||||
|
insertRecord(std::move(record2), getAppendIndex(id, type), type);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IdCollection<ESM::LandTexture>::removeRows(int index, int count)
|
||||||
|
{
|
||||||
|
for (int row = index; row < index + count; ++row)
|
||||||
|
{
|
||||||
|
const auto& record = getRecord(row);
|
||||||
|
if (record.isModified())
|
||||||
|
mIndices.erase({ -1, record.get().mIndex });
|
||||||
|
}
|
||||||
|
BaseIdCollection<ESM::LandTexture>::removeRows(index, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IdCollection<ESM::LandTexture>::replace(int index, std::unique_ptr<RecordBase> record)
|
||||||
|
{
|
||||||
|
const auto& current = getRecord(index);
|
||||||
|
if (current.isModified() && !record->isModified())
|
||||||
|
mIndices.erase({ -1, current.get().mIndex });
|
||||||
|
BaseIdCollection<ESM::LandTexture>::replace(index, std::move(record));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
namespace ESM
|
namespace ESM
|
||||||
{
|
{
|
||||||
class ESMReader;
|
class ESMReader;
|
||||||
|
struct LandTexture;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace CSMWorld
|
namespace CSMWorld
|
||||||
@ -25,9 +26,9 @@ namespace CSMWorld
|
|||||||
|
|
||||||
/// \brief Single type collection of top level records
|
/// \brief Single type collection of top level records
|
||||||
template <typename ESXRecordT>
|
template <typename ESXRecordT>
|
||||||
class IdCollection : public Collection<ESXRecordT>
|
class BaseIdCollection : public Collection<ESXRecordT>
|
||||||
{
|
{
|
||||||
virtual void loadRecord(ESXRecordT& record, ESM::ESMReader& reader, bool& isDeleted);
|
virtual void loadRecord(ESXRecordT& record, ESM::ESMReader& reader, bool& isDeleted, bool base);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// \return Index of loaded record (-1 if no record was loaded)
|
/// \return Index of loaded record (-1 if no record was loaded)
|
||||||
@ -46,14 +47,46 @@ namespace CSMWorld
|
|||||||
/// \return Has the ID been deleted?
|
/// \return Has the ID been deleted?
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template <class ESXRecordT>
|
||||||
|
class IdCollection : public BaseIdCollection<ESXRecordT>
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
class IdCollection<ESM::LandTexture> : public BaseIdCollection<ESM::LandTexture>
|
||||||
|
{
|
||||||
|
std::map<std::pair<int, std::uint16_t>, ESM::RefId> mIndices;
|
||||||
|
|
||||||
|
void loadRecord(ESM::LandTexture& record, ESM::ESMReader& reader, bool& isDeleted, bool base) override;
|
||||||
|
|
||||||
|
std::uint16_t assignNewIndex(ESM::RefId id);
|
||||||
|
|
||||||
|
public:
|
||||||
|
const Record<ESM::LandTexture>* searchRecord(std::uint16_t index, int plugin) const;
|
||||||
|
|
||||||
|
const std::string* getLandTexture(std::uint16_t index, int plugin) const;
|
||||||
|
|
||||||
|
bool touchRecord(const ESM::RefId& id) override;
|
||||||
|
|
||||||
|
void cloneRecord(
|
||||||
|
const ESM::RefId& origin, const ESM::RefId& destination, const UniversalId::Type type) override;
|
||||||
|
|
||||||
|
void appendBlankRecord(const ESM::RefId& id, UniversalId::Type type) override;
|
||||||
|
|
||||||
|
void removeRows(int index, int count) override;
|
||||||
|
|
||||||
|
void replace(int index, std::unique_ptr<RecordBase> record) override;
|
||||||
|
};
|
||||||
|
|
||||||
template <typename ESXRecordT>
|
template <typename ESXRecordT>
|
||||||
void IdCollection<ESXRecordT>::loadRecord(ESXRecordT& record, ESM::ESMReader& reader, bool& isDeleted)
|
void BaseIdCollection<ESXRecordT>::loadRecord(
|
||||||
|
ESXRecordT& record, ESM::ESMReader& reader, bool& isDeleted, bool base)
|
||||||
{
|
{
|
||||||
record.load(reader, isDeleted);
|
record.load(reader, isDeleted);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
inline void IdCollection<Land>::loadRecord(Land& record, ESM::ESMReader& reader, bool& isDeleted)
|
inline void BaseIdCollection<Land>::loadRecord(Land& record, ESM::ESMReader& reader, bool& isDeleted, bool base)
|
||||||
{
|
{
|
||||||
record.load(reader, isDeleted);
|
record.load(reader, isDeleted);
|
||||||
|
|
||||||
@ -64,22 +97,17 @@ namespace CSMWorld
|
|||||||
|
|
||||||
// Prevent data from being reloaded.
|
// Prevent data from being reloaded.
|
||||||
record.mContext.filename.clear();
|
record.mContext.filename.clear();
|
||||||
|
if (!base)
|
||||||
|
record.setPlugin(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ESXRecordT>
|
template <typename ESXRecordT>
|
||||||
int IdCollection<ESXRecordT>::load(ESM::ESMReader& reader, bool base)
|
int BaseIdCollection<ESXRecordT>::load(ESM::ESMReader& reader, bool base)
|
||||||
{
|
{
|
||||||
ESXRecordT record;
|
ESXRecordT record;
|
||||||
bool isDeleted = false;
|
bool isDeleted = false;
|
||||||
|
|
||||||
loadRecord(record, reader, isDeleted);
|
loadRecord(record, reader, isDeleted, base);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
ESM::RefId id = getRecordId(record);
|
ESM::RefId id = getRecordId(record);
|
||||||
int index = this->searchId(id);
|
int index = this->searchId(id);
|
||||||
@ -110,7 +138,7 @@ namespace CSMWorld
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename ESXRecordT>
|
template <typename ESXRecordT>
|
||||||
int IdCollection<ESXRecordT>::load(const ESXRecordT& record, bool base, int index)
|
int BaseIdCollection<ESXRecordT>::load(const ESXRecordT& record, bool base, int index)
|
||||||
{
|
{
|
||||||
if (index == -2) // index unknown
|
if (index == -2) // index unknown
|
||||||
index = this->searchId(getRecordId(record));
|
index = this->searchId(getRecordId(record));
|
||||||
@ -142,7 +170,7 @@ namespace CSMWorld
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename ESXRecordT>
|
template <typename ESXRecordT>
|
||||||
bool IdCollection<ESXRecordT>::tryDelete(const ESM::RefId& id)
|
bool BaseIdCollection<ESXRecordT>::tryDelete(const ESM::RefId& id)
|
||||||
{
|
{
|
||||||
int index = this->searchId(id);
|
int index = this->searchId(id);
|
||||||
|
|
||||||
@ -169,7 +197,7 @@ namespace CSMWorld
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
int IdCollection<Pathgrid>::load(ESM::ESMReader& reader, bool base);
|
int BaseIdCollection<Pathgrid>::load(ESM::ESMReader& reader, bool base);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
#include <apps/opencs/model/world/columns.hpp>
|
#include <apps/opencs/model/world/columns.hpp>
|
||||||
|
#include <apps/opencs/model/world/idcollection.hpp>
|
||||||
#include <apps/opencs/model/world/idtablebase.hpp>
|
#include <apps/opencs/model/world/idtablebase.hpp>
|
||||||
#include <apps/opencs/model/world/record.hpp>
|
#include <apps/opencs/model/world/record.hpp>
|
||||||
#include <apps/opencs/model/world/universalid.hpp>
|
#include <apps/opencs/model/world/universalid.hpp>
|
||||||
@ -21,7 +22,6 @@
|
|||||||
|
|
||||||
#include "collectionbase.hpp"
|
#include "collectionbase.hpp"
|
||||||
#include "columnbase.hpp"
|
#include "columnbase.hpp"
|
||||||
#include "landtexture.hpp"
|
|
||||||
|
|
||||||
CSMWorld::IdTable::IdTable(CollectionBase* idCollection, unsigned int features)
|
CSMWorld::IdTable::IdTable(CollectionBase* idCollection, unsigned int features)
|
||||||
: IdTableBase(features)
|
: IdTableBase(features)
|
||||||
@ -361,73 +361,8 @@ CSMWorld::LandTextureIdTable::LandTextureIdTable(CollectionBase* idCollection, u
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
CSMWorld::LandTextureIdTable::ImportResults CSMWorld::LandTextureIdTable::importTextures(
|
const CSMWorld::Record<ESM::LandTexture>* CSMWorld::LandTextureIdTable::searchRecord(
|
||||||
const std::vector<std::string>& ids)
|
std::uint16_t index, int plugin) const
|
||||||
{
|
{
|
||||||
ImportResults results;
|
return static_cast<CSMWorld::IdCollection<ESM::LandTexture>*>(idCollection())->searchRecord(index, plugin);
|
||||||
|
|
||||||
// Map existing textures to ids
|
|
||||||
std::map<std::string, std::string> reverseLookupMap;
|
|
||||||
for (int i = 0; i < idCollection()->getSize(); ++i)
|
|
||||||
{
|
|
||||||
auto& record = static_cast<const Record<LandTexture>&>(idCollection()->getRecord(i));
|
|
||||||
if (record.isModified())
|
|
||||||
reverseLookupMap.emplace(
|
|
||||||
Misc::StringUtils::lowerCase(record.get().mTexture), idCollection()->getId(i).getRefIdString());
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const std::string& id : ids)
|
|
||||||
{
|
|
||||||
int plugin, index;
|
|
||||||
LandTexture::parseUniqueRecordId(id, plugin, index);
|
|
||||||
|
|
||||||
const ESM::RefId refId = ESM::RefId::stringRefId(id);
|
|
||||||
const int oldRow = idCollection()->searchId(refId);
|
|
||||||
|
|
||||||
// If it does not exist, it can be skipped.
|
|
||||||
if (oldRow < 0)
|
|
||||||
{
|
|
||||||
results.recordMapping.emplace_back(id, id);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// Look for a pre-existing record
|
|
||||||
auto& record = static_cast<const Record<LandTexture>&>(idCollection()->getRecord(oldRow));
|
|
||||||
// If it is in the current plugin, it can be skipped.
|
|
||||||
if (record.mState == Record<LandTexture>::State_ModifiedOnly)
|
|
||||||
{
|
|
||||||
results.recordMapping.emplace_back(id, id);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
std::string texture = Misc::StringUtils::lowerCase(record.get().mTexture);
|
|
||||||
auto searchIt = reverseLookupMap.find(texture);
|
|
||||||
if (searchIt != reverseLookupMap.end())
|
|
||||||
{
|
|
||||||
results.recordMapping.emplace_back(id, searchIt->second);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Iterate until an unused index or found, or the index has completely wrapped around.
|
|
||||||
int startIndex = index;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
std::string newId = LandTexture::createUniqueRecordId(-1, index);
|
|
||||||
const ESM::RefId newRefId = ESM::RefId::stringRefId(newId);
|
|
||||||
int newRow = idCollection()->searchId(newRefId);
|
|
||||||
|
|
||||||
if (newRow < 0)
|
|
||||||
{
|
|
||||||
// Id not taken, clone it
|
|
||||||
cloneRecord(refId, newRefId, UniversalId::Type_LandTexture);
|
|
||||||
results.createdRecords.push_back(newId);
|
|
||||||
results.recordMapping.emplace_back(id, newId);
|
|
||||||
reverseLookupMap.emplace(texture, newId);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
const size_t MaxIndex = std::numeric_limits<uint16_t>::max() - 1;
|
|
||||||
index = (index + 1) % MaxIndex;
|
|
||||||
} while (index != startIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
return results;
|
|
||||||
}
|
}
|
||||||
|
@ -16,10 +16,17 @@
|
|||||||
|
|
||||||
class QObject;
|
class QObject;
|
||||||
|
|
||||||
|
namespace ESM
|
||||||
|
{
|
||||||
|
struct LandTexture;
|
||||||
|
}
|
||||||
|
|
||||||
namespace CSMWorld
|
namespace CSMWorld
|
||||||
{
|
{
|
||||||
class CollectionBase;
|
class CollectionBase;
|
||||||
struct RecordBase;
|
struct RecordBase;
|
||||||
|
template <typename ESXRecordT>
|
||||||
|
struct Record;
|
||||||
|
|
||||||
class IdTable : public IdTableBase
|
class IdTable : public IdTableBase
|
||||||
{
|
{
|
||||||
@ -103,26 +110,12 @@ namespace CSMWorld
|
|||||||
virtual CollectionBase* idCollection() const;
|
virtual CollectionBase* idCollection() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// An IdTable customized to handle the more unique needs of LandTextureId's which behave
|
|
||||||
/// differently from other records. The major difference is that base records cannot be
|
|
||||||
/// modified.
|
|
||||||
class LandTextureIdTable : public IdTable
|
class LandTextureIdTable : public IdTable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
struct ImportResults
|
|
||||||
{
|
|
||||||
using StringPair = std::pair<std::string, std::string>;
|
|
||||||
|
|
||||||
/// The newly added records
|
|
||||||
std::vector<std::string> createdRecords;
|
|
||||||
/// The 1st string is the original id, the 2nd is the mapped id
|
|
||||||
std::vector<StringPair> recordMapping;
|
|
||||||
};
|
|
||||||
|
|
||||||
LandTextureIdTable(CollectionBase* idCollection, unsigned int features = 0);
|
LandTextureIdTable(CollectionBase* idCollection, unsigned int features = 0);
|
||||||
|
|
||||||
/// Finds and maps/recreates the specified ids.
|
const CSMWorld::Record<ESM::LandTexture>* searchRecord(std::uint16_t index, int plugin) const;
|
||||||
ImportResults importTextures(const std::vector<std::string>& ids);
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,35 +0,0 @@
|
|||||||
#include "landtexture.hpp"
|
|
||||||
|
|
||||||
#include <sstream>
|
|
||||||
#include <stdexcept>
|
|
||||||
|
|
||||||
#include <components/esm3/esmreader.hpp>
|
|
||||||
#include <components/misc/strings/conversion.hpp>
|
|
||||||
|
|
||||||
namespace CSMWorld
|
|
||||||
{
|
|
||||||
void LandTexture::load(ESM::ESMReader& esm, bool& isDeleted)
|
|
||||||
{
|
|
||||||
ESM::LandTexture::load(esm, isDeleted);
|
|
||||||
|
|
||||||
mPluginIndex = esm.getIndex();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string LandTexture::createUniqueRecordId(int plugin, int index)
|
|
||||||
{
|
|
||||||
std::stringstream ss;
|
|
||||||
ss << 'L' << plugin << '#' << index;
|
|
||||||
return ss.str();
|
|
||||||
}
|
|
||||||
|
|
||||||
void LandTexture::parseUniqueRecordId(const std::string& id, int& plugin, int& index)
|
|
||||||
{
|
|
||||||
size_t middle = id.find('#');
|
|
||||||
|
|
||||||
if (middle == std::string::npos || id[0] != 'L')
|
|
||||||
throw std::runtime_error("Invalid LandTexture ID");
|
|
||||||
|
|
||||||
plugin = Misc::StringUtils::toNumeric<int>(id.substr(1, middle - 1), 0);
|
|
||||||
index = Misc::StringUtils::toNumeric<int>(id.substr(middle + 1), 0);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,29 +0,0 @@
|
|||||||
#ifndef CSM_WORLD_LANDTEXTURE_H
|
|
||||||
#define CSM_WORLD_LANDTEXTURE_H
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include <components/esm3/loadltex.hpp>
|
|
||||||
|
|
||||||
namespace ESM
|
|
||||||
{
|
|
||||||
class ESMReader;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace CSMWorld
|
|
||||||
{
|
|
||||||
/// \brief Wrapper for LandTexture record, providing info which plugin the LandTexture was loaded from.
|
|
||||||
struct LandTexture : public ESM::LandTexture
|
|
||||||
{
|
|
||||||
int mPluginIndex;
|
|
||||||
|
|
||||||
void load(ESM::ESMReader& esm, bool& isDeleted);
|
|
||||||
|
|
||||||
/// Returns a string identifier that will be unique to any LandTexture.
|
|
||||||
static std::string createUniqueRecordId(int plugin, int index);
|
|
||||||
/// Deconstructs a unique string identifier into plugin and index.
|
|
||||||
static void parseUniqueRecordId(const std::string& id, int& plugin, int& index);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
@ -18,14 +18,15 @@ namespace CSMWorld
|
|||||||
{
|
{
|
||||||
const IdCollection<Cell>& mCells;
|
const IdCollection<Cell>& mCells;
|
||||||
|
|
||||||
void loadRecord(ESXRecordT& record, ESM::ESMReader& reader, bool& isDeleted) override;
|
void loadRecord(ESXRecordT& record, ESM::ESMReader& reader, bool& isDeleted, bool base) override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SubCellCollection(const IdCollection<Cell>& cells);
|
SubCellCollection(const IdCollection<Cell>& cells);
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename ESXRecordT>
|
template <typename ESXRecordT>
|
||||||
void SubCellCollection<ESXRecordT>::loadRecord(ESXRecordT& record, ESM::ESMReader& reader, bool& isDeleted)
|
void SubCellCollection<ESXRecordT>::loadRecord(
|
||||||
|
ESXRecordT& record, ESM::ESMReader& reader, bool& isDeleted, bool base)
|
||||||
{
|
{
|
||||||
record.load(reader, isDeleted, mCells);
|
record.load(reader, isDeleted, mCells);
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,6 @@
|
|||||||
#include <apps/opencs/model/world/data.hpp>
|
#include <apps/opencs/model/world/data.hpp>
|
||||||
#include <apps/opencs/model/world/idcollection.hpp>
|
#include <apps/opencs/model/world/idcollection.hpp>
|
||||||
#include <apps/opencs/model/world/land.hpp>
|
#include <apps/opencs/model/world/land.hpp>
|
||||||
#include <apps/opencs/model/world/landtexture.hpp>
|
|
||||||
#include <apps/opencs/model/world/record.hpp>
|
#include <apps/opencs/model/world/record.hpp>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@ -44,12 +43,7 @@ namespace CSVRender
|
|||||||
|
|
||||||
const std::string* TerrainStorage::getLandTexture(std::uint16_t index, int plugin)
|
const std::string* TerrainStorage::getLandTexture(std::uint16_t index, int plugin)
|
||||||
{
|
{
|
||||||
const int row = mData.getLandTextures().searchId(
|
return mData.getLandTextures().getLandTexture(index, plugin);
|
||||||
ESM::RefId::stringRefId(CSMWorld::LandTexture::createUniqueRecordId(plugin, index)));
|
|
||||||
if (row == -1)
|
|
||||||
return nullptr;
|
|
||||||
|
|
||||||
return &mData.getLandTextures().getRecord(row).get().mTexture;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TerrainStorage::setAlteredHeight(int inCellX, int inCellY, float height)
|
void TerrainStorage::setAlteredHeight(int inCellX, int inCellY, float height)
|
||||||
|
@ -38,7 +38,6 @@
|
|||||||
#include "../../model/world/data.hpp"
|
#include "../../model/world/data.hpp"
|
||||||
#include "../../model/world/idtable.hpp"
|
#include "../../model/world/idtable.hpp"
|
||||||
#include "../../model/world/idtree.hpp"
|
#include "../../model/world/idtree.hpp"
|
||||||
#include "../../model/world/landtexture.hpp"
|
|
||||||
#include "../../model/world/tablemimedata.hpp"
|
#include "../../model/world/tablemimedata.hpp"
|
||||||
#include "../../model/world/universalid.hpp"
|
#include "../../model/world/universalid.hpp"
|
||||||
|
|
||||||
@ -52,7 +51,6 @@ CSVRender::TerrainTextureMode::TerrainTextureMode(
|
|||||||
WorldspaceWidget* worldspaceWidget, osg::Group* parentNode, QWidget* parent)
|
WorldspaceWidget* worldspaceWidget, osg::Group* parentNode, QWidget* parent)
|
||||||
: EditMode(worldspaceWidget, Misc::ScalableIcon::load(":scenetoolbar/editing-terrain-texture"),
|
: EditMode(worldspaceWidget, Misc::ScalableIcon::load(":scenetoolbar/editing-terrain-texture"),
|
||||||
Mask_Terrain | Mask_Reference, "Terrain texture editing", parent)
|
Mask_Terrain | Mask_Reference, "Terrain texture editing", parent)
|
||||||
, mBrushTexture("L0#0")
|
|
||||||
, mBrushSize(1)
|
, mBrushSize(1)
|
||||||
, mBrushShape(CSVWidget::BrushShape_Point)
|
, mBrushShape(CSVWidget::BrushShape_Point)
|
||||||
, mTextureBrushScenetool(nullptr)
|
, mTextureBrushScenetool(nullptr)
|
||||||
@ -137,8 +135,8 @@ void CSVRender::TerrainTextureMode::primaryEditPressed(const WorldspaceHitResult
|
|||||||
mCellId = getWorldspaceWidget().getCellId(hit.worldPos);
|
mCellId = getWorldspaceWidget().getCellId(hit.worldPos);
|
||||||
|
|
||||||
QUndoStack& undoStack = document.getUndoStack();
|
QUndoStack& undoStack = document.getUndoStack();
|
||||||
CSMWorld::IdCollection<CSMWorld::LandTexture>& landtexturesCollection = document.getData().getLandTextures();
|
CSMWorld::IdCollection<ESM::LandTexture>& landtexturesCollection = document.getData().getLandTextures();
|
||||||
int index = landtexturesCollection.searchId(ESM::RefId::stringRefId(mBrushTexture));
|
int index = landtexturesCollection.searchId(mBrushTexture);
|
||||||
|
|
||||||
if (index != -1 && !landtexturesCollection.getRecord(index).isDeleted() && hit.hit && hit.tag == nullptr)
|
if (index != -1 && !landtexturesCollection.getRecord(index).isDeleted() && hit.hit && hit.tag == nullptr)
|
||||||
{
|
{
|
||||||
@ -186,8 +184,8 @@ bool CSVRender::TerrainTextureMode::primaryEditStartDrag(const QPoint& pos)
|
|||||||
|
|
||||||
mDragMode = InteractionType_PrimaryEdit;
|
mDragMode = InteractionType_PrimaryEdit;
|
||||||
|
|
||||||
CSMWorld::IdCollection<CSMWorld::LandTexture>& landtexturesCollection = document.getData().getLandTextures();
|
CSMWorld::IdCollection<ESM::LandTexture>& landtexturesCollection = document.getData().getLandTextures();
|
||||||
const int index = landtexturesCollection.searchId(ESM::RefId::stringRefId(mBrushTexture));
|
const int index = landtexturesCollection.searchId(mBrushTexture);
|
||||||
|
|
||||||
if (index != -1 && !landtexturesCollection.getRecord(index).isDeleted() && hit.hit && hit.tag == nullptr)
|
if (index != -1 && !landtexturesCollection.getRecord(index).isDeleted() && hit.hit && hit.tag == nullptr)
|
||||||
{
|
{
|
||||||
@ -242,8 +240,8 @@ void CSVRender::TerrainTextureMode::drag(const QPoint& pos, int diffX, int diffY
|
|||||||
std::string cellId = getWorldspaceWidget().getCellId(hit.worldPos);
|
std::string cellId = getWorldspaceWidget().getCellId(hit.worldPos);
|
||||||
CSMDoc::Document& document = getWorldspaceWidget().getDocument();
|
CSMDoc::Document& document = getWorldspaceWidget().getDocument();
|
||||||
|
|
||||||
CSMWorld::IdCollection<CSMWorld::LandTexture>& landtexturesCollection = document.getData().getLandTextures();
|
CSMWorld::IdCollection<ESM::LandTexture>& landtexturesCollection = document.getData().getLandTextures();
|
||||||
const int index = landtexturesCollection.searchId(ESM::RefId::stringRefId(mBrushTexture));
|
const int index = landtexturesCollection.searchId(mBrushTexture);
|
||||||
|
|
||||||
if (index != -1 && !landtexturesCollection.getRecord(index).isDeleted() && hit.hit && hit.tag == nullptr)
|
if (index != -1 && !landtexturesCollection.getRecord(index).isDeleted() && hit.hit && hit.tag == nullptr)
|
||||||
{
|
{
|
||||||
@ -273,8 +271,8 @@ void CSVRender::TerrainTextureMode::dragCompleted(const QPoint& pos)
|
|||||||
CSMDoc::Document& document = getWorldspaceWidget().getDocument();
|
CSMDoc::Document& document = getWorldspaceWidget().getDocument();
|
||||||
QUndoStack& undoStack = document.getUndoStack();
|
QUndoStack& undoStack = document.getUndoStack();
|
||||||
|
|
||||||
CSMWorld::IdCollection<CSMWorld::LandTexture>& landtexturesCollection = document.getData().getLandTextures();
|
CSMWorld::IdCollection<ESM::LandTexture>& landtexturesCollection = document.getData().getLandTextures();
|
||||||
const int index = landtexturesCollection.searchId(ESM::RefId::stringRefId(mBrushTexture));
|
const int index = landtexturesCollection.searchId(mBrushTexture);
|
||||||
|
|
||||||
if (index != -1 && !landtexturesCollection.getRecord(index).isDeleted())
|
if (index != -1 && !landtexturesCollection.getRecord(index).isDeleted())
|
||||||
{
|
{
|
||||||
@ -303,18 +301,7 @@ void CSVRender::TerrainTextureMode::handleDropEvent(QDropEvent* event)
|
|||||||
|
|
||||||
for (const CSMWorld::UniversalId& uid : ids)
|
for (const CSMWorld::UniversalId& uid : ids)
|
||||||
{
|
{
|
||||||
mBrushTexture = uid.getId();
|
mBrushTexture = ESM::RefId::stringRefId(uid.getId());
|
||||||
emit passBrushTexture(mBrushTexture);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (mime->holdsType(CSMWorld::UniversalId::Type_Texture))
|
|
||||||
{
|
|
||||||
const std::vector<CSMWorld::UniversalId> ids = mime->getData();
|
|
||||||
|
|
||||||
for (const CSMWorld::UniversalId& uid : ids)
|
|
||||||
{
|
|
||||||
std::string textureFileName = uid.toString();
|
|
||||||
createTexture(textureFileName);
|
|
||||||
emit passBrushTexture(mBrushTexture);
|
emit passBrushTexture(mBrushTexture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -359,11 +346,8 @@ void CSVRender::TerrainTextureMode::editTerrainTextureGrid(const WorldspaceHitRe
|
|||||||
|
|
||||||
int textureColumn = landTable.findColumnIndex(CSMWorld::Columns::ColumnId_LandTexturesIndex);
|
int textureColumn = landTable.findColumnIndex(CSMWorld::Columns::ColumnId_LandTexturesIndex);
|
||||||
|
|
||||||
std::size_t hashlocation = mBrushTexture.find('#');
|
|
||||||
std::string mBrushTextureInt = mBrushTexture.substr(hashlocation + 1);
|
|
||||||
|
|
||||||
// All indices are offset by +1
|
// All indices are offset by +1
|
||||||
int brushInt = Misc::StringUtils::toNumeric<int>(mBrushTexture.substr(hashlocation + 1), 0) + 1;
|
uint32_t brushInt = document.getData().getLandTextures().getRecord(mBrushTexture).get().mIndex + 1;
|
||||||
|
|
||||||
int r = static_cast<float>(mBrushSize) / 2;
|
int r = static_cast<float>(mBrushSize) / 2;
|
||||||
|
|
||||||
@ -662,50 +646,6 @@ void CSVRender::TerrainTextureMode::pushEditToCommand(CSMWorld::LandTexturesColu
|
|||||||
undoStack.push(new CSMWorld::TouchLandCommand(landTable, ltexTable, cellId));
|
undoStack.push(new CSMWorld::TouchLandCommand(landTable, ltexTable, cellId));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVRender::TerrainTextureMode::createTexture(const std::string& textureFileName)
|
|
||||||
{
|
|
||||||
CSMDoc::Document& document = getWorldspaceWidget().getDocument();
|
|
||||||
|
|
||||||
CSMWorld::IdTable& ltexTable
|
|
||||||
= dynamic_cast<CSMWorld::IdTable&>(*document.getData().getTableModel(CSMWorld::UniversalId::Type_LandTextures));
|
|
||||||
|
|
||||||
QUndoStack& undoStack = document.getUndoStack();
|
|
||||||
|
|
||||||
std::string newId;
|
|
||||||
|
|
||||||
int counter = 0;
|
|
||||||
bool freeIndexFound = false;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
const size_t maxCounter = std::numeric_limits<uint16_t>::max() - 1;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
newId = CSMWorld::LandTexture::createUniqueRecordId(-1, counter);
|
|
||||||
if (!ltexTable.getRecord(newId).isDeleted())
|
|
||||||
counter = (counter + 1) % maxCounter;
|
|
||||||
}
|
|
||||||
catch (const std::exception&)
|
|
||||||
{
|
|
||||||
newId = CSMWorld::LandTexture::createUniqueRecordId(-1, counter);
|
|
||||||
freeIndexFound = true;
|
|
||||||
}
|
|
||||||
} while (freeIndexFound == false);
|
|
||||||
|
|
||||||
std::size_t idlocation = textureFileName.find("Texture: ");
|
|
||||||
QString fileName = QString::fromStdString(textureFileName.substr(idlocation + 9));
|
|
||||||
|
|
||||||
QVariant textureFileNameVariant;
|
|
||||||
textureFileNameVariant.setValue(fileName);
|
|
||||||
|
|
||||||
undoStack.beginMacro("Add land texture record");
|
|
||||||
|
|
||||||
undoStack.push(new CSMWorld::CreateCommand(ltexTable, newId));
|
|
||||||
QModelIndex index(ltexTable.getModelIndex(newId, ltexTable.findColumnIndex(CSMWorld::Columns::ColumnId_Texture)));
|
|
||||||
undoStack.push(new CSMWorld::ModifyCommand(ltexTable, index, textureFileNameVariant));
|
|
||||||
undoStack.endMacro();
|
|
||||||
mBrushTexture = std::move(newId);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CSVRender::TerrainTextureMode::allowLandTextureEditing(const std::string& cellId)
|
bool CSVRender::TerrainTextureMode::allowLandTextureEditing(const std::string& cellId)
|
||||||
{
|
{
|
||||||
CSMDoc::Document& document = getWorldspaceWidget().getDocument();
|
CSMDoc::Document& document = getWorldspaceWidget().getDocument();
|
||||||
@ -832,7 +772,7 @@ void CSVRender::TerrainTextureMode::setBrushShape(CSVWidget::BrushShape brushSha
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVRender::TerrainTextureMode::setBrushTexture(std::string brushTexture)
|
void CSVRender::TerrainTextureMode::setBrushTexture(ESM::RefId brushTexture)
|
||||||
{
|
{
|
||||||
mBrushTexture = std::move(brushTexture);
|
mBrushTexture = brushTexture;
|
||||||
}
|
}
|
||||||
|
@ -117,14 +117,11 @@ namespace CSVRender
|
|||||||
void pushEditToCommand(CSMWorld::LandTexturesColumn::DataType& newLandGrid, CSMDoc::Document& document,
|
void pushEditToCommand(CSMWorld::LandTexturesColumn::DataType& newLandGrid, CSMDoc::Document& document,
|
||||||
CSMWorld::IdTable& landTable, std::string cellId);
|
CSMWorld::IdTable& landTable, std::string cellId);
|
||||||
|
|
||||||
/// \brief Create new land texture record from texture asset
|
|
||||||
void createTexture(const std::string& textureFileName);
|
|
||||||
|
|
||||||
/// \brief Create new cell and land if needed
|
/// \brief Create new cell and land if needed
|
||||||
bool allowLandTextureEditing(const std::string& textureFileName);
|
bool allowLandTextureEditing(const std::string& textureFileName);
|
||||||
|
|
||||||
std::string mCellId;
|
std::string mCellId;
|
||||||
std::string mBrushTexture;
|
ESM::RefId mBrushTexture;
|
||||||
int mBrushSize;
|
int mBrushSize;
|
||||||
CSVWidget::BrushShape mBrushShape;
|
CSVWidget::BrushShape mBrushShape;
|
||||||
std::unique_ptr<BrushDraw> mBrushDraw;
|
std::unique_ptr<BrushDraw> mBrushDraw;
|
||||||
@ -139,13 +136,13 @@ namespace CSVRender
|
|||||||
const int landTextureSize{ ESM::Land::LAND_TEXTURE_SIZE };
|
const int landTextureSize{ ESM::Land::LAND_TEXTURE_SIZE };
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void passBrushTexture(std::string brushTexture);
|
void passBrushTexture(ESM::RefId brushTexture);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void handleDropEvent(QDropEvent* event);
|
void handleDropEvent(QDropEvent* event);
|
||||||
void setBrushSize(int brushSize);
|
void setBrushSize(int brushSize);
|
||||||
void setBrushShape(CSVWidget::BrushShape brushShape);
|
void setBrushShape(CSVWidget::BrushShape brushShape);
|
||||||
void setBrushTexture(std::string brushShape);
|
void setBrushTexture(ESM::RefId brushShape);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#include <apps/opencs/model/prefs/category.hpp>
|
#include <apps/opencs/model/prefs/category.hpp>
|
||||||
#include <apps/opencs/model/prefs/setting.hpp>
|
#include <apps/opencs/model/prefs/setting.hpp>
|
||||||
#include <apps/opencs/model/world/columns.hpp>
|
#include <apps/opencs/model/world/columns.hpp>
|
||||||
|
#include <apps/opencs/model/world/commandmacro.hpp>
|
||||||
#include <apps/opencs/model/world/record.hpp>
|
#include <apps/opencs/model/world/record.hpp>
|
||||||
#include <apps/opencs/view/widget/brushshapes.hpp>
|
#include <apps/opencs/view/widget/brushshapes.hpp>
|
||||||
#include <apps/opencs/view/widget/pushbutton.hpp>
|
#include <apps/opencs/view/widget/pushbutton.hpp>
|
||||||
@ -39,7 +40,6 @@
|
|||||||
#include "../../model/world/data.hpp"
|
#include "../../model/world/data.hpp"
|
||||||
#include "../../model/world/idcollection.hpp"
|
#include "../../model/world/idcollection.hpp"
|
||||||
#include "../../model/world/idtable.hpp"
|
#include "../../model/world/idtable.hpp"
|
||||||
#include "../../model/world/landtexture.hpp"
|
|
||||||
#include "../../model/world/universalid.hpp"
|
#include "../../model/world/universalid.hpp"
|
||||||
|
|
||||||
namespace CSVWidget
|
namespace CSVWidget
|
||||||
@ -74,12 +74,12 @@ CSVWidget::TextureBrushWindow::TextureBrushWindow(CSMDoc::Document& document, QW
|
|||||||
: QFrame(parent, Qt::Popup)
|
: QFrame(parent, Qt::Popup)
|
||||||
, mDocument(document)
|
, mDocument(document)
|
||||||
{
|
{
|
||||||
mBrushTextureLabel = "Selected texture: " + mBrushTexture + " ";
|
mBrushTextureLabel = "Selected texture: " + mBrushTexture.getRefIdString() + " ";
|
||||||
|
|
||||||
CSMWorld::IdCollection<CSMWorld::LandTexture>& landtexturesCollection = mDocument.getData().getLandTextures();
|
CSMWorld::IdCollection<ESM::LandTexture>& landtexturesCollection = mDocument.getData().getLandTextures();
|
||||||
|
|
||||||
int landTextureFilename = landtexturesCollection.findColumnIndex(CSMWorld::Columns::ColumnId_Texture);
|
int landTextureFilename = landtexturesCollection.findColumnIndex(CSMWorld::Columns::ColumnId_Texture);
|
||||||
const int index = landtexturesCollection.searchId(ESM::RefId::stringRefId(mBrushTexture));
|
const int index = landtexturesCollection.searchId(mBrushTexture);
|
||||||
|
|
||||||
if (index != -1 && !landtexturesCollection.getRecord(index).isDeleted())
|
if (index != -1 && !landtexturesCollection.getRecord(index).isDeleted())
|
||||||
{
|
{
|
||||||
@ -154,68 +154,38 @@ void CSVWidget::TextureBrushWindow::configureButtonInitialSettings(QPushButton*
|
|||||||
button->setCheckable(true);
|
button->setCheckable(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVWidget::TextureBrushWindow::setBrushTexture(std::string brushTexture)
|
void CSVWidget::TextureBrushWindow::setBrushTexture(ESM::RefId brushTexture)
|
||||||
{
|
{
|
||||||
CSMWorld::IdTable& ltexTable = dynamic_cast<CSMWorld::IdTable&>(
|
CSMWorld::IdTable& ltexTable = dynamic_cast<CSMWorld::IdTable&>(
|
||||||
*mDocument.getData().getTableModel(CSMWorld::UniversalId::Type_LandTextures));
|
*mDocument.getData().getTableModel(CSMWorld::UniversalId::Type_LandTextures));
|
||||||
QUndoStack& undoStack = mDocument.getUndoStack();
|
QUndoStack& undoStack = mDocument.getUndoStack();
|
||||||
|
|
||||||
CSMWorld::IdCollection<CSMWorld::LandTexture>& landtexturesCollection = mDocument.getData().getLandTextures();
|
CSMWorld::IdCollection<ESM::LandTexture>& landtexturesCollection = mDocument.getData().getLandTextures();
|
||||||
int landTextureFilename = landtexturesCollection.findColumnIndex(CSMWorld::Columns::ColumnId_Texture);
|
int landTextureFilename = landtexturesCollection.findColumnIndex(CSMWorld::Columns::ColumnId_Texture);
|
||||||
|
|
||||||
int index = 0;
|
int row = landtexturesCollection.getIndex(brushTexture);
|
||||||
int pluginInDragged = 0;
|
const auto& record = landtexturesCollection.getRecord(row);
|
||||||
CSMWorld::LandTexture::parseUniqueRecordId(brushTexture, pluginInDragged, index);
|
|
||||||
const ESM::RefId brushTextureRefId = ESM::RefId::stringRefId(brushTexture);
|
|
||||||
std::string newBrushTextureId = CSMWorld::LandTexture::createUniqueRecordId(-1, index);
|
|
||||||
ESM::RefId newBrushTextureRefId = ESM::RefId::stringRefId(newBrushTextureId);
|
|
||||||
int rowInBase = landtexturesCollection.searchId(brushTextureRefId);
|
|
||||||
int rowInNew = landtexturesCollection.searchId(newBrushTextureRefId);
|
|
||||||
|
|
||||||
// Check if texture exists in current plugin, and clone if id found in base, otherwise reindex the texture
|
if (!record.isDeleted())
|
||||||
// TO-DO: Handle case when texture is not found in neither base or plugin properly (finding new index is not enough)
|
|
||||||
// TO-DO: Handle conflicting plugins properly
|
|
||||||
if (rowInNew == -1)
|
|
||||||
{
|
{
|
||||||
if (rowInBase == -1)
|
// Ensure the texture is defined by the current plugin
|
||||||
|
if (!record.isModified())
|
||||||
{
|
{
|
||||||
int counter = 0;
|
CSMWorld::CommandMacro macro(undoStack);
|
||||||
bool freeIndexFound = false;
|
macro.push(new CSMWorld::TouchCommand(ltexTable, brushTexture.getRefIdString()));
|
||||||
const int maxCounter = std::numeric_limits<uint16_t>::max() - 1;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
newBrushTextureId = CSMWorld::LandTexture::createUniqueRecordId(-1, counter);
|
|
||||||
newBrushTextureRefId = ESM::RefId::stringRefId(newBrushTextureId);
|
|
||||||
if (landtexturesCollection.searchId(brushTextureRefId) != -1
|
|
||||||
&& landtexturesCollection.getRecord(brushTextureRefId).isDeleted() == 0
|
|
||||||
&& landtexturesCollection.searchId(newBrushTextureRefId) != -1
|
|
||||||
&& landtexturesCollection.getRecord(newBrushTextureRefId).isDeleted() == 0)
|
|
||||||
counter = (counter + 1) % maxCounter;
|
|
||||||
else
|
|
||||||
freeIndexFound = true;
|
|
||||||
} while (freeIndexFound == false || counter < maxCounter);
|
|
||||||
}
|
}
|
||||||
|
mBrushTextureLabel = "Selected texture: " + brushTexture.getRefIdString() + " ";
|
||||||
undoStack.beginMacro("Add land texture record");
|
|
||||||
undoStack.push(new CSMWorld::CloneCommand(
|
|
||||||
ltexTable, brushTexture, newBrushTextureId, CSMWorld::UniversalId::Type_LandTexture));
|
|
||||||
undoStack.endMacro();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (index != -1 && !landtexturesCollection.getRecord(rowInNew).isDeleted())
|
|
||||||
{
|
|
||||||
mBrushTextureLabel = "Selected texture: " + newBrushTextureId + " ";
|
|
||||||
mSelectedBrush->setText(QString::fromStdString(mBrushTextureLabel)
|
mSelectedBrush->setText(QString::fromStdString(mBrushTextureLabel)
|
||||||
+ landtexturesCollection.getData(rowInNew, landTextureFilename).value<QString>());
|
+ landtexturesCollection.getData(row, landTextureFilename).value<QString>());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
newBrushTextureId.clear();
|
brushTexture = {};
|
||||||
mBrushTextureLabel = "No selected texture or invalid texture";
|
mBrushTextureLabel = "No selected texture or invalid texture";
|
||||||
mSelectedBrush->setText(QString::fromStdString(mBrushTextureLabel));
|
mSelectedBrush->setText(QString::fromStdString(mBrushTextureLabel));
|
||||||
}
|
}
|
||||||
|
|
||||||
mBrushTexture = std::move(newBrushTextureId);
|
mBrushTexture = brushTexture;
|
||||||
|
|
||||||
emit passTextureId(mBrushTexture);
|
emit passTextureId(mBrushTexture);
|
||||||
emit passBrushShape(mBrushShape); // updates the icon tooltip
|
emit passBrushShape(mBrushShape); // updates the icon tooltip
|
||||||
@ -250,7 +220,6 @@ CSVWidget::SceneToolTextureBrush::SceneToolTextureBrush(
|
|||||||
, mTextureBrushWindow(new TextureBrushWindow(document, this))
|
, mTextureBrushWindow(new TextureBrushWindow(document, this))
|
||||||
{
|
{
|
||||||
mBrushHistory.resize(1);
|
mBrushHistory.resize(1);
|
||||||
mBrushHistory[0] = "L0#0";
|
|
||||||
|
|
||||||
setAcceptDrops(true);
|
setAcceptDrops(true);
|
||||||
connect(mTextureBrushWindow, &TextureBrushWindow::passBrushShape, this, &SceneToolTextureBrush::setButtonIcon);
|
connect(mTextureBrushWindow, &TextureBrushWindow::passBrushShape, this, &SceneToolTextureBrush::setButtonIcon);
|
||||||
@ -309,14 +278,15 @@ void CSVWidget::SceneToolTextureBrush::setButtonIcon(CSVWidget::BrushShape brush
|
|||||||
|
|
||||||
tooltip += "<p>(right click to access of previously used brush settings)";
|
tooltip += "<p>(right click to access of previously used brush settings)";
|
||||||
|
|
||||||
CSMWorld::IdCollection<CSMWorld::LandTexture>& landtexturesCollection = mDocument.getData().getLandTextures();
|
CSMWorld::IdCollection<ESM::LandTexture>& landtexturesCollection = mDocument.getData().getLandTextures();
|
||||||
|
|
||||||
int landTextureFilename = landtexturesCollection.findColumnIndex(CSMWorld::Columns::ColumnId_Texture);
|
int landTextureFilename = landtexturesCollection.findColumnIndex(CSMWorld::Columns::ColumnId_Texture);
|
||||||
const int index = landtexturesCollection.searchId(ESM::RefId::stringRefId(mTextureBrushWindow->mBrushTexture));
|
const int index = landtexturesCollection.searchId(mTextureBrushWindow->mBrushTexture);
|
||||||
|
|
||||||
if (index != -1 && !landtexturesCollection.getRecord(index).isDeleted())
|
if (index != -1 && !landtexturesCollection.getRecord(index).isDeleted())
|
||||||
{
|
{
|
||||||
tooltip += "<p>Selected texture: " + QString::fromStdString(mTextureBrushWindow->mBrushTexture) + " ";
|
tooltip += "<p>Selected texture: " + QString::fromStdString(mTextureBrushWindow->mBrushTexture.getRefIdString())
|
||||||
|
+ " ";
|
||||||
|
|
||||||
tooltip += landtexturesCollection.getData(index, landTextureFilename).value<QString>();
|
tooltip += landtexturesCollection.getData(index, landTextureFilename).value<QString>();
|
||||||
}
|
}
|
||||||
@ -342,25 +312,25 @@ void CSVWidget::SceneToolTextureBrush::updatePanel()
|
|||||||
|
|
||||||
for (int i = mBrushHistory.size() - 1; i >= 0; --i)
|
for (int i = mBrushHistory.size() - 1; i >= 0; --i)
|
||||||
{
|
{
|
||||||
CSMWorld::IdCollection<CSMWorld::LandTexture>& landtexturesCollection = mDocument.getData().getLandTextures();
|
CSMWorld::IdCollection<ESM::LandTexture>& landtexturesCollection = mDocument.getData().getLandTextures();
|
||||||
int landTextureFilename = landtexturesCollection.findColumnIndex(CSMWorld::Columns::ColumnId_Texture);
|
int landTextureFilename = landtexturesCollection.findColumnIndex(CSMWorld::Columns::ColumnId_Texture);
|
||||||
const int index = landtexturesCollection.searchId(ESM::RefId::stringRefId(mBrushHistory[i]));
|
const int index = landtexturesCollection.searchId(mBrushHistory[i]);
|
||||||
|
|
||||||
if (index != -1 && !landtexturesCollection.getRecord(index).isDeleted())
|
if (index != -1 && !landtexturesCollection.getRecord(index).isDeleted())
|
||||||
{
|
{
|
||||||
mTable->setItem(i, 1,
|
mTable->setItem(i, 1,
|
||||||
new QTableWidgetItem(landtexturesCollection.getData(index, landTextureFilename).value<QString>()));
|
new QTableWidgetItem(landtexturesCollection.getData(index, landTextureFilename).value<QString>()));
|
||||||
mTable->setItem(i, 0, new QTableWidgetItem(QString::fromStdString(mBrushHistory[i])));
|
mTable->setItem(i, 0, new QTableWidgetItem(QString::fromStdString(mBrushHistory[i].getRefIdString())));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mTable->setItem(i, 1, new QTableWidgetItem("Invalid/deleted texture"));
|
mTable->setItem(i, 1, new QTableWidgetItem("Invalid/deleted texture"));
|
||||||
mTable->setItem(i, 0, new QTableWidgetItem(QString::fromStdString(mBrushHistory[i])));
|
mTable->setItem(i, 0, new QTableWidgetItem(QString::fromStdString(mBrushHistory[i].getRefIdString())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVWidget::SceneToolTextureBrush::updateBrushHistory(const std::string& brushTexture)
|
void CSVWidget::SceneToolTextureBrush::updateBrushHistory(ESM::RefId brushTexture)
|
||||||
{
|
{
|
||||||
mBrushHistory.insert(mBrushHistory.begin(), brushTexture);
|
mBrushHistory.insert(mBrushHistory.begin(), brushTexture);
|
||||||
if (mBrushHistory.size() > 5)
|
if (mBrushHistory.size() > 5)
|
||||||
@ -371,7 +341,7 @@ void CSVWidget::SceneToolTextureBrush::clicked(const QModelIndex& index)
|
|||||||
{
|
{
|
||||||
if (index.column() == 0 || index.column() == 1)
|
if (index.column() == 0 || index.column() == 1)
|
||||||
{
|
{
|
||||||
std::string brushTexture = mBrushHistory[index.row()];
|
ESM::RefId brushTexture = mBrushHistory[index.row()];
|
||||||
std::swap(mBrushHistory[index.row()], mBrushHistory[0]);
|
std::swap(mBrushHistory[index.row()], mBrushHistory[0]);
|
||||||
mTextureBrushWindow->setBrushTexture(brushTexture);
|
mTextureBrushWindow->setBrushTexture(brushTexture);
|
||||||
emit passTextureId(brushTexture);
|
emit passTextureId(brushTexture);
|
||||||
|
@ -9,6 +9,8 @@
|
|||||||
#include "scenetool.hpp"
|
#include "scenetool.hpp"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <components/esm/refid.hpp>
|
||||||
|
|
||||||
class QTableWidget;
|
class QTableWidget;
|
||||||
class QDragEnterEvent;
|
class QDragEnterEvent;
|
||||||
class QDropEvent;
|
class QDropEvent;
|
||||||
@ -70,7 +72,7 @@ namespace CSVWidget
|
|||||||
private:
|
private:
|
||||||
CSVWidget::BrushShape mBrushShape = CSVWidget::BrushShape_Point;
|
CSVWidget::BrushShape mBrushShape = CSVWidget::BrushShape_Point;
|
||||||
int mBrushSize = 1;
|
int mBrushSize = 1;
|
||||||
std::string mBrushTexture = "L0#0";
|
ESM::RefId mBrushTexture;
|
||||||
CSMDoc::Document& mDocument;
|
CSMDoc::Document& mDocument;
|
||||||
QLabel* mSelectedBrush;
|
QLabel* mSelectedBrush;
|
||||||
QGroupBox* mHorizontalGroupBox;
|
QGroupBox* mHorizontalGroupBox;
|
||||||
@ -85,14 +87,14 @@ namespace CSVWidget
|
|||||||
friend class CSVRender::TerrainTextureMode;
|
friend class CSVRender::TerrainTextureMode;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void setBrushTexture(std::string brushTexture);
|
void setBrushTexture(ESM::RefId brushTexture);
|
||||||
void setBrushShape();
|
void setBrushShape();
|
||||||
void setBrushSize(int brushSize);
|
void setBrushSize(int brushSize);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void passBrushSize(int brushSize);
|
void passBrushSize(int brushSize);
|
||||||
void passBrushShape(CSVWidget::BrushShape brushShape);
|
void passBrushShape(CSVWidget::BrushShape brushShape);
|
||||||
void passTextureId(std::string brushTexture);
|
void passTextureId(ESM::RefId brushTexture);
|
||||||
};
|
};
|
||||||
|
|
||||||
class SceneToolTextureBrush : public SceneTool
|
class SceneToolTextureBrush : public SceneTool
|
||||||
@ -103,7 +105,7 @@ namespace CSVWidget
|
|||||||
CSMDoc::Document& mDocument;
|
CSMDoc::Document& mDocument;
|
||||||
QFrame* mPanel;
|
QFrame* mPanel;
|
||||||
QTableWidget* mTable;
|
QTableWidget* mTable;
|
||||||
std::vector<std::string> mBrushHistory;
|
std::vector<ESM::RefId> mBrushHistory;
|
||||||
TextureBrushWindow* mTextureBrushWindow;
|
TextureBrushWindow* mTextureBrushWindow;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -122,14 +124,14 @@ namespace CSVWidget
|
|||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void setButtonIcon(CSVWidget::BrushShape brushShape);
|
void setButtonIcon(CSVWidget::BrushShape brushShape);
|
||||||
void updateBrushHistory(const std::string& mBrushTexture);
|
void updateBrushHistory(ESM::RefId mBrushTexture);
|
||||||
void clicked(const QModelIndex& index);
|
void clicked(const QModelIndex& index);
|
||||||
void activate() override;
|
void activate() override;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void passEvent(QDropEvent* event);
|
void passEvent(QDropEvent* event);
|
||||||
void passEvent(QDragEnterEvent* event);
|
void passEvent(QDragEnterEvent* event);
|
||||||
void passTextureId(std::string brushTexture);
|
void passTextureId(ESM::RefId brushTexture);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,107 +0,0 @@
|
|||||||
#include "landtexturecreator.hpp"
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
#include <limits>
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
#include <QLabel>
|
|
||||||
#include <QLineEdit>
|
|
||||||
#include <QSpinBox>
|
|
||||||
|
|
||||||
#include <apps/opencs/model/world/columns.hpp>
|
|
||||||
#include <apps/opencs/model/world/data.hpp>
|
|
||||||
#include <apps/opencs/model/world/idcollection.hpp>
|
|
||||||
#include <apps/opencs/view/world/genericcreator.hpp>
|
|
||||||
|
|
||||||
#include "../../model/world/commands.hpp"
|
|
||||||
#include "../../model/world/idtable.hpp"
|
|
||||||
#include "../../model/world/landtexture.hpp"
|
|
||||||
|
|
||||||
namespace CSVWorld
|
|
||||||
{
|
|
||||||
LandTextureCreator::LandTextureCreator(CSMWorld::Data& data, QUndoStack& undoStack, const CSMWorld::UniversalId& id)
|
|
||||||
: GenericCreator(data, undoStack, id)
|
|
||||||
{
|
|
||||||
// One index is reserved for a default texture
|
|
||||||
const size_t MaxIndex = std::numeric_limits<uint16_t>::max() - 1;
|
|
||||||
|
|
||||||
setManualEditing(false);
|
|
||||||
|
|
||||||
QLabel* nameLabel = new QLabel("Name");
|
|
||||||
insertBeforeButtons(nameLabel, false);
|
|
||||||
|
|
||||||
mNameEdit = new QLineEdit(this);
|
|
||||||
insertBeforeButtons(mNameEdit, true);
|
|
||||||
|
|
||||||
QLabel* indexLabel = new QLabel("Index");
|
|
||||||
insertBeforeButtons(indexLabel, false);
|
|
||||||
|
|
||||||
mIndexBox = new QSpinBox(this);
|
|
||||||
mIndexBox->setMinimum(0);
|
|
||||||
mIndexBox->setMaximum(MaxIndex);
|
|
||||||
insertBeforeButtons(mIndexBox, true);
|
|
||||||
|
|
||||||
connect(mNameEdit, &QLineEdit::textChanged, this, &LandTextureCreator::nameChanged);
|
|
||||||
connect(mIndexBox, qOverload<int>(&QSpinBox::valueChanged), this, &LandTextureCreator::indexChanged);
|
|
||||||
}
|
|
||||||
|
|
||||||
void LandTextureCreator::cloneMode(const std::string& originId, const CSMWorld::UniversalId::Type type)
|
|
||||||
{
|
|
||||||
GenericCreator::cloneMode(originId, type);
|
|
||||||
|
|
||||||
CSMWorld::IdTable& table = dynamic_cast<CSMWorld::IdTable&>(*getData().getTableModel(getCollectionId()));
|
|
||||||
|
|
||||||
int column = table.findColumnIndex(CSMWorld::Columns::ColumnId_TextureNickname);
|
|
||||||
mNameEdit->setText((table.data(table.getModelIndex(originId, column)).toString()));
|
|
||||||
|
|
||||||
column = table.findColumnIndex(CSMWorld::Columns::ColumnId_TextureIndex);
|
|
||||||
mIndexBox->setValue((table.data(table.getModelIndex(originId, column)).toInt()));
|
|
||||||
}
|
|
||||||
|
|
||||||
void LandTextureCreator::focus()
|
|
||||||
{
|
|
||||||
mIndexBox->setFocus();
|
|
||||||
}
|
|
||||||
|
|
||||||
void LandTextureCreator::reset()
|
|
||||||
{
|
|
||||||
GenericCreator::reset();
|
|
||||||
mNameEdit->setText("");
|
|
||||||
mIndexBox->setValue(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string LandTextureCreator::getErrors() const
|
|
||||||
{
|
|
||||||
if (getData().getLandTextures().searchId(ESM::RefId::stringRefId(getId())) >= 0)
|
|
||||||
{
|
|
||||||
return "Index is already in use";
|
|
||||||
}
|
|
||||||
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
void LandTextureCreator::configureCreateCommand(CSMWorld::CreateCommand& command) const
|
|
||||||
{
|
|
||||||
GenericCreator::configureCreateCommand(command);
|
|
||||||
|
|
||||||
CSMWorld::IdTable& table = dynamic_cast<CSMWorld::IdTable&>(*getData().getTableModel(getCollectionId()));
|
|
||||||
int column = table.findColumnIndex(CSMWorld::Columns::ColumnId_TextureNickname);
|
|
||||||
command.addValue(column, mName.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string LandTextureCreator::getId() const
|
|
||||||
{
|
|
||||||
return CSMWorld::LandTexture::createUniqueRecordId(-1, mIndexBox->value());
|
|
||||||
}
|
|
||||||
|
|
||||||
void LandTextureCreator::nameChanged(const QString& value)
|
|
||||||
{
|
|
||||||
mName = value.toUtf8().constData();
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
|
|
||||||
void LandTextureCreator::indexChanged(int value)
|
|
||||||
{
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,54 +0,0 @@
|
|||||||
#ifndef CSV_WORLD_LANDTEXTURECREATOR_H
|
|
||||||
#define CSV_WORLD_LANDTEXTURECREATOR_H
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include "genericcreator.hpp"
|
|
||||||
|
|
||||||
#include <apps/opencs/model/world/universalid.hpp>
|
|
||||||
|
|
||||||
namespace CSMWorld
|
|
||||||
{
|
|
||||||
class CreateCommand;
|
|
||||||
class Data;
|
|
||||||
}
|
|
||||||
|
|
||||||
class QLineEdit;
|
|
||||||
class QSpinBox;
|
|
||||||
|
|
||||||
namespace CSVWorld
|
|
||||||
{
|
|
||||||
class LandTextureCreator : public GenericCreator
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
LandTextureCreator(CSMWorld::Data& data, QUndoStack& undoStack, const CSMWorld::UniversalId& id);
|
|
||||||
|
|
||||||
void cloneMode(const std::string& originId, const CSMWorld::UniversalId::Type type) override;
|
|
||||||
|
|
||||||
void focus() override;
|
|
||||||
|
|
||||||
void reset() override;
|
|
||||||
|
|
||||||
std::string getErrors() const override;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void configureCreateCommand(CSMWorld::CreateCommand& command) const override;
|
|
||||||
|
|
||||||
std::string getId() const override;
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
|
|
||||||
void nameChanged(const QString& val);
|
|
||||||
void indexChanged(int val);
|
|
||||||
|
|
||||||
private:
|
|
||||||
QLineEdit* mNameEdit;
|
|
||||||
QSpinBox* mIndexBox;
|
|
||||||
|
|
||||||
std::string mName;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
@ -10,7 +10,6 @@
|
|||||||
#include "globalcreator.hpp"
|
#include "globalcreator.hpp"
|
||||||
#include "infocreator.hpp"
|
#include "infocreator.hpp"
|
||||||
#include "landcreator.hpp"
|
#include "landcreator.hpp"
|
||||||
#include "landtexturecreator.hpp"
|
|
||||||
#include "pathgridcreator.hpp"
|
#include "pathgridcreator.hpp"
|
||||||
#include "previewsubview.hpp"
|
#include "previewsubview.hpp"
|
||||||
#include "referenceablecreator.hpp"
|
#include "referenceablecreator.hpp"
|
||||||
@ -92,7 +91,7 @@ void CSVWorld::addSubViewFactories(CSVDoc::SubViewFactoryManager& manager)
|
|||||||
new CSVDoc::SubViewFactoryWithCreator<TableSubView, CreatorFactory<LandCreator>>);
|
new CSVDoc::SubViewFactoryWithCreator<TableSubView, CreatorFactory<LandCreator>>);
|
||||||
|
|
||||||
manager.add(CSMWorld::UniversalId::Type_LandTextures,
|
manager.add(CSMWorld::UniversalId::Type_LandTextures,
|
||||||
new CSVDoc::SubViewFactoryWithCreator<TableSubView, CreatorFactory<LandTextureCreator>>);
|
new CSVDoc::SubViewFactoryWithCreator<TableSubView, CreatorFactory<GenericCreator>>);
|
||||||
|
|
||||||
manager.add(CSMWorld::UniversalId::Type_Globals,
|
manager.add(CSMWorld::UniversalId::Type_Globals,
|
||||||
new CSVDoc::SubViewFactoryWithCreator<TableSubView, CreatorFactory<GlobalCreator>>);
|
new CSVDoc::SubViewFactoryWithCreator<TableSubView, CreatorFactory<GlobalCreator>>);
|
||||||
@ -195,7 +194,7 @@ void CSVWorld::addSubViewFactories(CSVDoc::SubViewFactoryManager& manager)
|
|||||||
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<LandCreator>>(false));
|
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<LandCreator>>(false));
|
||||||
|
|
||||||
manager.add(CSMWorld::UniversalId::Type_LandTexture,
|
manager.add(CSMWorld::UniversalId::Type_LandTexture,
|
||||||
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<LandTextureCreator>>(false));
|
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<GenericCreator>>(false));
|
||||||
|
|
||||||
manager.add(CSMWorld::UniversalId::Type_DebugProfile,
|
manager.add(CSMWorld::UniversalId::Type_DebugProfile,
|
||||||
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView,
|
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user