Replace nonconst getId with setId, add template specialization and specialized derived classes for LandTexture

new-script-api
Kyle Cooley 7 years ago
parent 5d14a2afcc
commit 9e41f1340a

@ -70,7 +70,7 @@ opencs_units (view/world
cellcreator pathgridcreator referenceablecreator startscriptcreator referencecreator scenesubview
infocreator scriptedit dialoguesubview previewsubview regionmap dragrecordtable nestedtable
dialoguespinbox recordbuttonbar tableeditidaction scripterrortable extendedcommandconfigurator
bodypartcreator
bodypartcreator landtexturecreator
)
opencs_units_noqt (view/world

@ -6,6 +6,7 @@
#include <algorithm>
#include <cctype>
#include <stdexcept>
#include <string>
#include <functional>
#include <QVariant>
@ -13,8 +14,8 @@
#include <components/misc/stringops.hpp>
#include "columnbase.hpp"
#include "collectionbase.hpp"
#include "landtexture.hpp"
namespace CSMWorld
{
@ -22,15 +23,14 @@ namespace CSMWorld
template<typename ESXRecordT>
struct IdAccessor
{
std::string& getId (ESXRecordT& record);
void setId(ESXRecordT& record, const std::string& id) const;
const std::string getId (const ESXRecordT& record) const;
};
template<typename ESXRecordT>
std::string& IdAccessor<ESXRecordT>::getId (ESXRecordT& record)
void IdAccessor<ESXRecordT>::setId(ESXRecordT& record, const std::string& id) const
{
return record.mId;
record.mId = id;
}
template<typename ESXRecordT>
@ -39,6 +39,23 @@ namespace CSMWorld
return record.mId;
}
template<>
inline void IdAccessor<LandTexture>::setId (LandTexture& record, const std::string& id) const
{
int plugin = 0;
int index = 0;
LandTexture::parseUniqueRecordId(id, plugin, index);
record.mPluginIndex = plugin;
record.mIndex = index;
}
template<>
inline const std::string IdAccessor<LandTexture>::getId (const LandTexture& record) const
{
return LandTexture::createUniqueRecordId(record.mPluginIndex, record.mIndex);
}
/// \brief Single-type record collection
template<typename ESXRecordT, typename IdAccessorT = IdAccessor<ESXRecordT> >
class Collection : public CollectionBase
@ -213,7 +230,7 @@ namespace CSMWorld
Record<ESXRecordT> copy;
copy.mModified = getRecord(origin).get();
copy.mState = RecordBase::State_ModifiedOnly;
copy.get().mId = destination;
IdAccessorT().setId(copy.get(), destination);
insertRecord(copy, getAppendIndex(destination, type));
}
@ -366,7 +383,7 @@ namespace CSMWorld
UniversalId::Type type)
{
ESXRecordT record;
IdAccessorT().getId (record) = id;
IdAccessorT().setId(record, id);
record.blank();
Record<ESXRecordT> record2;

@ -63,6 +63,13 @@ namespace CSMWorld
}
};
template<>
inline QVariant StringIdColumn<LandTexture>::get(const Record<LandTexture>& record) const
{
const LandTexture& ltex = record.get();
return QString::fromUtf8(std::string('L' + std::to_string(ltex.mPluginIndex) + '#' + std::to_string(ltex.mIndex)).c_str());
}
template<typename ESXRecordT>
struct RecordStateColumn : public Column<ESXRecordT>
{
@ -2421,6 +2428,31 @@ namespace CSMWorld
}
};
template<typename ESXRecordT>
struct TextureHandleColumn : public Column<ESXRecordT>
{
TextureHandleColumn()
: Column<ESXRecordT> (Columns::ColumnId_TextureHandle, ColumnBase::Display_String)
{}
QVariant get(const Record<ESXRecordT>& record) const override
{
return QString::fromUtf8(record.get().mId.c_str());
}
void set(Record<ESXRecordT>& record, const QVariant& data) override
{
ESXRecordT copy = record.get();
copy.mId = data.toString().toUtf8().constData();
record.setModified(copy);
}
bool isEditable() const override
{
return true;
}
};
template<typename ESXRecordT>
struct TextureIndexColumn : public Column<ESXRecordT>
{
@ -2428,31 +2460,30 @@ namespace CSMWorld
: Column<ESXRecordT> (Columns::ColumnId_TextureIndex, ColumnBase::Display_Integer)
{}
QVariant get (const Record<ESXRecordT>& record) const
QVariant get(const Record<ESXRecordT>& record) const override
{
return record.get().mIndex;
}
virtual bool isEditable() const
bool isEditable() const override
{
return false;
}
};
// TODO remove
template<typename ESXRecordT>
struct PluginIndexColumn : public Column<ESXRecordT>
{
PluginIndexColumn()
: Column<ESXRecordT> (Columns::ColumnId_PluginIndex, ColumnBase::Display_Integer)
: Column<ESXRecordT> (Columns::ColumnId_PluginIndex, ColumnBase::Display_Integer,0)
{}
QVariant get (const Record<ESXRecordT>& record) const
QVariant get(const Record<ESXRecordT>& record) const override
{
return -1;
}
virtual bool isEditable() const
virtual bool isEditable() const override
{
return false;
}

@ -330,6 +330,7 @@ namespace CSMWorld
{ ColumnId_WeatherChance, "Percent Chance" },
{ ColumnId_Text, "Text" },
{ ColumnId_TextureHandle, "Texture Handle" },
{ ColumnId_PluginIndex, "Plugin Index" },
{ ColumnId_TextureIndex, "Texture Index" },

@ -329,8 +329,9 @@ namespace CSMWorld
ColumnId_Text = 297,
ColumnId_PluginIndex = 298,
ColumnId_TextureIndex = 299,
ColumnId_TextureHandle = 298,
ColumnId_PluginIndex = 299,
ColumnId_TextureIndex = 300,
// Allocated to a separate value range, so we don't get a collision should we ever need
// to extend the number of use values.

@ -417,9 +417,10 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, bool fsStrict, const Files::Pat
mLand.addColumn (new FixedRecordTypeColumn<Land>(UniversalId::Type_Land));
mLand.addColumn (new PluginIndexColumn<Land>);
mLandTextures.addColumn (new StringIdColumn<LandTexture>);
mLandTextures.addColumn (new StringIdColumn<LandTexture>(true));
mLandTextures.addColumn (new RecordStateColumn<LandTexture>);
mLandTextures.addColumn (new FixedRecordTypeColumn<LandTexture>(UniversalId::Type_LandTexture));
mLandTextures.addColumn (new TextureHandleColumn<LandTexture>);
mLandTextures.addColumn (new PluginIndexColumn<LandTexture>);
mLandTextures.addColumn (new TextureIndexColumn<LandTexture>);
mLandTextures.addColumn (new TextureColumn<LandTexture>);
@ -544,7 +545,7 @@ CSMWorld::Data::Data (ToUTF8::FromType encoding, bool fsStrict, const Files::Pat
addModel (new IdTable (&mSoundGens), UniversalId::Type_SoundGen);
addModel (new IdTable (&mMagicEffects), UniversalId::Type_MagicEffect);
addModel (new IdTable (&mLand), UniversalId::Type_Land);
addModel (new IdTable (&mLandTextures), UniversalId::Type_LandTexture);
addModel (new LandTextureIdTable (&mLandTextures), UniversalId::Type_LandTexture);
addModel (new IdTree (&mPathgrids, &mPathgrids), UniversalId::Type_Pathgrid);
addModel (new IdTable (&mStartScripts), UniversalId::Type_StartScript);
addModel (new IdTree (&mReferenceables, &mReferenceables, IdTable::Feature_Preview),

@ -281,3 +281,34 @@ CSMWorld::CollectionBase *CSMWorld::IdTable::idCollection() const
{
return mIdCollection;
}
CSMWorld::LandTextureIdTable::LandTextureIdTable(CollectionBase* idCollection, unsigned int features)
: IdTable(idCollection, features)
{
}
QVariant CSMWorld::LandTextureIdTable::data(const QModelIndex& index, int role) const
{
if (role==Qt::EditRole && !idCollection()->getRecord(index.row()).isModified())
return QVariant();
return IdTable::data(index, role);
}
bool CSMWorld::LandTextureIdTable::setData(const QModelIndex& index, const QVariant& value, int role)
{
if (!idCollection()->getRecord(index.row()).isModified())
return false;
else
return IdTable::setData(index, value, role);
}
Qt::ItemFlags CSMWorld::LandTextureIdTable::flags(const QModelIndex& index) const
{
Qt::ItemFlags flags = IdTable::flags(index);
if (!idCollection()->getRecord(index.row()).isModified())
flags &= ~Qt::ItemIsEditable;
return flags;
}

@ -93,6 +93,21 @@ namespace CSMWorld
virtual CollectionBase *idCollection() const;
};
/// An IdTable customized to handle the more unique needs of LandTextureId's which behave
/// differently from other records.
class LandTextureIdTable : public IdTable
{
public:
LandTextureIdTable(CollectionBase* idCollection, unsigned int features=0);
QVariant data(const QModelIndex& index, int role=Qt::DisplayRole) const override;
bool setData(const QModelIndex& index, const QVariant& value, int role) override;
Qt::ItemFlags flags (const QModelIndex & index) const override;
};
}
#endif

@ -1,5 +1,7 @@
#include "landtexture.hpp"
#include <string>
#include <components/esm/esmreader.hpp>
namespace CSMWorld
@ -11,4 +13,19 @@ namespace CSMWorld
mPluginIndex = esm.getIndex();
}
std::string LandTexture::createUniqueRecordId(int plugin, int index)
{
return 'L' + std::to_string(plugin) + '#' + std::to_string(index);
}
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 = std::stoi(id.substr(1,middle-1));
index = std::stoi(id.substr(middle+1));
}
}

@ -13,6 +13,11 @@ namespace CSMWorld
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);
};
}

@ -0,0 +1,106 @@
#include "landtexturecreator.hpp"
#include <cstdint>
#include <limits>
#include <QIntValidator>
#include <QLabel>
#include <QLineEdit>
#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);
QIntValidator* indexValidator = new QIntValidator(0, MaxIndex, this);
mIndexEdit = new QLineEdit(this);
mIndexEdit->setValidator(indexValidator);
insertBeforeButtons(mIndexEdit, true);
connect(mNameEdit, SIGNAL(textChanged(const QString&)), this, SLOT(nameChanged(const QString&)));
connect(mIndexEdit, SIGNAL(textChanged(const QString&)), this, SLOT(indexChanged(const QString&)));
}
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_TextureHandle);
mNameEdit->setText((table.data(table.getModelIndex(originId, column)).toString()));
column = table.findColumnIndex(CSMWorld::Columns::ColumnId_TextureIndex);
mIndexEdit->setText((table.data(table.getModelIndex(originId, column)).toString()));
}
void LandTextureCreator::focus()
{
mIndexEdit->setFocus();
}
void LandTextureCreator::reset()
{
GenericCreator::reset();
mNameEdit->setText("");
mIndexEdit->setText("");
}
std::string LandTextureCreator::getErrors() const
{
std::string id = getId();
// TODO empty index edit?
if (getData().getLandTextures().searchId(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_TextureHandle);
command.addValue(column, mName.c_str());
}
std::string LandTextureCreator::getId() const
{
return CSMWorld::LandTexture::createUniqueRecordId(0, mIndex);
}
void LandTextureCreator::nameChanged(const QString& value)
{
mName = value.toUtf8().constData();
update();
}
void LandTextureCreator::indexChanged(const QString& value)
{
mIndex = value.toInt();
update();
}
}

@ -0,0 +1,49 @@
#ifndef CSV_WORLD_LANDTEXTURECREATOR_H
#define CSV_WORLD_LANDTEXTURECREATOR_H
#include <string>
#include "genericcreator.hpp"
class QLineEdit;
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(const QString& val);
private:
QLineEdit* mNameEdit;
QLineEdit* mIndexEdit;
std::string mName;
int mIndex;
};
}
#endif

@ -18,6 +18,7 @@
#include "pathgridcreator.hpp"
#include "previewsubview.hpp"
#include "bodypartcreator.hpp"
#include "landtexturecreator.hpp"
void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager)
{
@ -43,8 +44,6 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager)
CSMWorld::UniversalId::Type_Spells,
CSMWorld::UniversalId::Type_Enchantments,
CSMWorld::UniversalId::Type_SoundGens,
CSMWorld::UniversalId::Type_Lands,
CSMWorld::UniversalId::Type_LandTextures,
CSMWorld::UniversalId::Type_None // end marker
};
@ -83,6 +82,12 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager)
manager.add (CSMWorld::UniversalId::Type_Pathgrids,
new CSVDoc::SubViewFactoryWithCreator<TableSubView, PathgridCreatorFactory>);
manager.add (CSMWorld::UniversalId::Type_Lands,
new CSVDoc::SubViewFactoryWithCreator<TableSubView, CreatorFactory<GenericCreator> >);
manager.add (CSMWorld::UniversalId::Type_LandTextures,
new CSVDoc::SubViewFactoryWithCreator<TableSubView, CreatorFactory<LandTextureCreator> >);
manager.add (CSMWorld::UniversalId::Type_Globals,
new CSVDoc::SubViewFactoryWithCreator<TableSubView, CreatorFactory<GlobalCreator> >);
@ -183,6 +188,12 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager)
manager.add (CSMWorld::UniversalId::Type_Pathgrid,
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, PathgridCreatorFactory> (false));
manager.add (CSMWorld::UniversalId::Type_Land,
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<GenericCreator> >(false));
manager.add (CSMWorld::UniversalId::Type_LandTexture,
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<LandTextureCreator> >(false));
manager.add (CSMWorld::UniversalId::Type_DebugProfile,
new CSVDoc::SubViewFactoryWithCreator<DialogueSubView, CreatorFactory<GenericCreator, CSMWorld::Scope_Project | CSMWorld::Scope_Session> > (false));

@ -59,7 +59,7 @@ namespace ESM
void LandTexture::blank()
{
mId.clear();
mTexture.clear();
mIndex = -1;
}
}

@ -31,14 +31,15 @@ struct LandTexture
/// Return a string descriptor for this record type. Currently used for debugging / error logs only.
static std::string getRecordType() { return "LandTexture"; }
// mId is merely a user friendly name for the texture in the editor.
std::string mId, mTexture;
int mIndex;
void load(ESMReader &esm, bool &isDeleted);
void save(ESMWriter &esm, bool isDeleted = false) const;
/// Sets the record to the default state. Does not touch the index. Does touch mID.
void blank();
///< Set record to default state (does not touch the ID).
};
}
#endif

Loading…
Cancel
Save