forked from teamnwah/openmw-tes3coop
Tweaks to land loading, land cloning, terrain signals, placeholder land update handling
This commit is contained in:
parent
99e90ef808
commit
ab607f3028
13 changed files with 369 additions and 96 deletions
|
@ -297,6 +297,7 @@ namespace CSMWorld
|
||||||
{
|
{
|
||||||
int index = cloneRecordImp(origin, destination, type);
|
int index = cloneRecordImp(origin, destination, type);
|
||||||
mRecords.at(index).get().mPlugin = 0;
|
mRecords.at(index).get().mPlugin = 0;
|
||||||
|
mRecords.at(index).get().mContext.filename.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename ESXRecordT, typename IdAccessorT>
|
template<typename ESXRecordT, typename IdAccessorT>
|
||||||
|
@ -312,6 +313,7 @@ namespace CSMWorld
|
||||||
if (index >= 0)
|
if (index >= 0)
|
||||||
{
|
{
|
||||||
mRecords.at(index).get().mPlugin = 0;
|
mRecords.at(index).get().mPlugin = 0;
|
||||||
|
mRecords.at(index).get().mContext.filename.clear();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,10 +41,116 @@ void CSMWorld::TouchCommand::undo()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CSMWorld::TouchLandCommand::TouchLandCommand(IdTable& landTable, IdTable& ltexTable, const std::string& id, QUndoCommand* parent)
|
CSMWorld::ImportLandTexturesCommand::ImportLandTexturesCommand(IdTable& landTable,
|
||||||
|
IdTable& ltexTable, QUndoCommand* parent)
|
||||||
: QUndoCommand(parent)
|
: QUndoCommand(parent)
|
||||||
, mLands(landTable)
|
, mLands(landTable)
|
||||||
, mLtexs(ltexTable)
|
, mLtexs(ltexTable)
|
||||||
|
, mOldState(0)
|
||||||
|
{
|
||||||
|
setText("Import land textures");
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMWorld::ImportLandTexturesCommand::redo()
|
||||||
|
{
|
||||||
|
int pluginColumn = mLands.findColumnIndex(Columns::ColumnId_PluginIndex);
|
||||||
|
int oldPlugin = mLands.data(mLands.getModelIndex(getOriginId(), pluginColumn)).toInt();
|
||||||
|
|
||||||
|
// Original data
|
||||||
|
int textureColumn = mLands.findColumnIndex(Columns::ColumnId_LandTexturesIndex);
|
||||||
|
mOld = mLands.data(mLands.getModelIndex(getOriginId(), textureColumn)).toByteArray();
|
||||||
|
const uint16_t* textureData = reinterpret_cast<uint16_t*>(mOld.data());
|
||||||
|
|
||||||
|
// Need to make a copy so the old values can be looked up
|
||||||
|
QByteArray newTextureByteArray(mOld.data(), mOld.size());
|
||||||
|
uint16_t* newTextureData = reinterpret_cast<uint16_t*>(newTextureByteArray.data());
|
||||||
|
|
||||||
|
// Perform touch/copy/etc...
|
||||||
|
onRedo();
|
||||||
|
|
||||||
|
// Find all indices used
|
||||||
|
std::unordered_set<int> texIndices;
|
||||||
|
for (int i = 0; i < Land::LAND_NUM_TEXTURES; ++i)
|
||||||
|
{
|
||||||
|
// All indices are offset by 1 for a default texture
|
||||||
|
if (textureData[i] > 0)
|
||||||
|
texIndices.insert(textureData[i] - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> oldTextures;
|
||||||
|
for (int index : texIndices)
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
// All indices are offset by 1 for a default texture
|
||||||
|
if (textureData[i] == oldIndex + 1)
|
||||||
|
newTextureData[i] = newIndex + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply modification
|
||||||
|
int stateColumn = mLands.findColumnIndex(Columns::ColumnId_Modification);
|
||||||
|
mOldState = mLands.data(mLands.getModelIndex(getDestinationId(), stateColumn)).toInt();
|
||||||
|
|
||||||
|
mLands.setData(mLands.getModelIndex(getDestinationId(), textureColumn), newTextureByteArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMWorld::ImportLandTexturesCommand::undo()
|
||||||
|
{
|
||||||
|
// Restore to previous
|
||||||
|
int textureColumn = mLands.findColumnIndex(Columns::ColumnId_LandTexturesIndex);
|
||||||
|
mLands.setData(mLands.getModelIndex(getDestinationId(), textureColumn), mOld);
|
||||||
|
|
||||||
|
int stateColumn = mLands.findColumnIndex(Columns::ColumnId_Modification);
|
||||||
|
mLands.setData(mLands.getModelIndex(getDestinationId(), stateColumn), mOldState);
|
||||||
|
|
||||||
|
// Undo copy/touch/etc...
|
||||||
|
onUndo();
|
||||||
|
|
||||||
|
for (const std::string& id : mCreatedTextures)
|
||||||
|
{
|
||||||
|
int row = mLtexs.getModelIndex(id, 0).row();
|
||||||
|
mLtexs.removeRows(row, 1);
|
||||||
|
}
|
||||||
|
mCreatedTextures.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
CSMWorld::CopyLandTexturesCommand::CopyLandTexturesCommand(IdTable& landTable, IdTable& ltexTable,
|
||||||
|
const std::string& origin, const std::string& dest, QUndoCommand* parent)
|
||||||
|
: ImportLandTexturesCommand(landTable, ltexTable, parent)
|
||||||
|
, mOriginId(origin)
|
||||||
|
, mDestId(dest)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& CSMWorld::CopyLandTexturesCommand::getOriginId() const
|
||||||
|
{
|
||||||
|
return mOriginId;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& CSMWorld::CopyLandTexturesCommand::getDestinationId() const
|
||||||
|
{
|
||||||
|
return mDestId;
|
||||||
|
}
|
||||||
|
|
||||||
|
CSMWorld::TouchLandCommand::TouchLandCommand(IdTable& landTable, IdTable& ltexTable,
|
||||||
|
const std::string& id, QUndoCommand* parent)
|
||||||
|
: ImportLandTexturesCommand(landTable, ltexTable, parent)
|
||||||
, mId(id)
|
, mId(id)
|
||||||
, mOld(nullptr)
|
, mOld(nullptr)
|
||||||
, mChanged(false)
|
, mChanged(false)
|
||||||
|
@ -53,75 +159,27 @@ CSMWorld::TouchLandCommand::TouchLandCommand(IdTable& landTable, IdTable& ltexTa
|
||||||
mOld.reset(mLands.getRecord(mId).clone());
|
mOld.reset(mLands.getRecord(mId).clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMWorld::TouchLandCommand::redo()
|
const std::string& CSMWorld::TouchLandCommand::getOriginId() const
|
||||||
{
|
{
|
||||||
int pluginColumn = mLands.findColumnIndex(Columns::ColumnId_PluginIndex);
|
return mId;
|
||||||
int oldPlugin = mLands.data(mLands.getModelIndex(mId, pluginColumn)).toInt();
|
|
||||||
|
|
||||||
mChanged = mLands.touchRecord(mId);
|
|
||||||
if (mChanged)
|
|
||||||
{
|
|
||||||
// Original data
|
|
||||||
int textureColumn = mLands.findColumnIndex(Columns::ColumnId_LandTexturesIndex);
|
|
||||||
QByteArray textureByteArray = mLands.data(mLands.getModelIndex(mId, textureColumn)).toByteArray();
|
|
||||||
const uint16_t* textureData = reinterpret_cast<uint16_t*>(textureByteArray.data());
|
|
||||||
|
|
||||||
// Need to make a copy so the old values can be looked up
|
|
||||||
QByteArray newTextureByteArray(textureByteArray.data(), textureByteArray.size());
|
|
||||||
uint16_t* newTextureData = reinterpret_cast<uint16_t*>(newTextureByteArray.data());
|
|
||||||
|
|
||||||
// Find all indices used
|
|
||||||
std::unordered_set<int> texIndices;
|
|
||||||
for (int i = 0; i < Land::LAND_NUM_TEXTURES; ++i)
|
|
||||||
{
|
|
||||||
// All indices are offset by 1 for a default texture
|
|
||||||
if (textureData[i] > 0)
|
|
||||||
texIndices.insert(textureData[i] - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<std::string> oldTextures;
|
|
||||||
for (int index : texIndices)
|
|
||||||
{
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
// All indices are offset by 1 for a default texture
|
|
||||||
if (textureData[i] == oldIndex)
|
|
||||||
newTextureData[i] = newIndex + 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mLands.setData(mLands.getModelIndex(mId, textureColumn), newTextureByteArray);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSMWorld::TouchLandCommand::undo()
|
const std::string& CSMWorld::TouchLandCommand::getDestinationId() const
|
||||||
|
{
|
||||||
|
return mId;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMWorld::TouchLandCommand::onRedo()
|
||||||
|
{
|
||||||
|
mChanged = mLands.touchRecord(mId);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSMWorld::TouchLandCommand::onUndo()
|
||||||
{
|
{
|
||||||
if (mChanged)
|
if (mChanged)
|
||||||
{
|
{
|
||||||
mLands.setRecord(mId, *mOld);
|
mLands.setRecord(mId, *mOld);
|
||||||
mChanged = false;
|
mChanged = false;
|
||||||
|
|
||||||
for (const std::string& id : mCreatedTextures)
|
|
||||||
{
|
|
||||||
int row = mLtexs.getModelIndex(id, 0).row();
|
|
||||||
mLtexs.removeRows(row, 1);
|
|
||||||
}
|
|
||||||
mCreatedTextures.clear();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,23 +43,67 @@ namespace CSMWorld
|
||||||
bool mChanged;
|
bool mChanged;
|
||||||
};
|
};
|
||||||
|
|
||||||
class TouchLandCommand : public QUndoCommand
|
class ImportLandTexturesCommand : public QUndoCommand
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
TouchLandCommand(IdTable& landTable, IdTable& ltexTable, const std::string& id,
|
ImportLandTexturesCommand(IdTable& landTable, IdTable& ltexTable,
|
||||||
QUndoCommand* parent = nullptr);
|
QUndoCommand* parent);
|
||||||
|
|
||||||
void redo() override;
|
void redo() override;
|
||||||
void undo() override;
|
void undo() override;
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
|
|
||||||
|
virtual const std::string& getOriginId() const = 0;
|
||||||
|
virtual const std::string& getDestinationId() const = 0;
|
||||||
|
|
||||||
|
virtual void onRedo() = 0;
|
||||||
|
virtual void onUndo() = 0;
|
||||||
|
|
||||||
IdTable& mLands;
|
IdTable& mLands;
|
||||||
IdTable& mLtexs;
|
IdTable& mLtexs;
|
||||||
|
QByteArray mOld;
|
||||||
|
int mOldState;
|
||||||
|
std::vector<std::string> mCreatedTextures;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CopyLandTexturesCommand : public ImportLandTexturesCommand
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
CopyLandTexturesCommand(IdTable& landTable, IdTable& ltexTable, const std::string& origin,
|
||||||
|
const std::string& dest, QUndoCommand* parent = nullptr);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
const std::string& getOriginId() const override;
|
||||||
|
const std::string& getDestinationId() const override;
|
||||||
|
|
||||||
|
void onRedo() override {}
|
||||||
|
void onUndo() override {}
|
||||||
|
|
||||||
|
std::string mOriginId;
|
||||||
|
std::string mDestId;
|
||||||
|
};
|
||||||
|
|
||||||
|
class TouchLandCommand : public ImportLandTexturesCommand
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
TouchLandCommand(IdTable& landTable, IdTable& ltexTable,
|
||||||
|
const std::string& id, QUndoCommand* parent = nullptr);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
const std::string& getOriginId() const override;
|
||||||
|
const std::string& getDestinationId() const override;
|
||||||
|
|
||||||
|
void onRedo() override;
|
||||||
|
void onUndo() override;
|
||||||
|
|
||||||
std::string mId;
|
std::string mId;
|
||||||
std::unique_ptr<RecordBase> mOld;
|
std::unique_ptr<RecordBase> mOld;
|
||||||
std::vector<std::string> mCreatedTextures;
|
|
||||||
|
|
||||||
bool mChanged;
|
bool mChanged;
|
||||||
};
|
};
|
||||||
|
|
|
@ -75,6 +75,31 @@ bool CSVRender::Cell::addObjects (int start, int end)
|
||||||
return modified;
|
return modified;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSVRender::Cell::createLand()
|
||||||
|
{
|
||||||
|
if (mDeleted)
|
||||||
|
{
|
||||||
|
mTerrain.reset();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const CSMWorld::IdCollection<CSMWorld::Land>& land = mData.getLand();
|
||||||
|
int landIndex = land.searchId(mId);
|
||||||
|
if (landIndex != -1)
|
||||||
|
{
|
||||||
|
const ESM::Land& esmLand = land.getRecord(mId).get();
|
||||||
|
|
||||||
|
if (esmLand.getLandData (ESM::Land::DATA_VHGT))
|
||||||
|
{
|
||||||
|
mTerrain.reset(new Terrain::TerrainGrid(mCellNode, mCellNode, mData.getResourceSystem().get(), new TerrainStorage(mData), Mask_Terrain));
|
||||||
|
mTerrain->loadCell(esmLand.mX, esmLand.mY);
|
||||||
|
|
||||||
|
mCellBorder.reset(new CellBorder(mCellNode, mCoordinates));
|
||||||
|
mCellBorder->buildShape(esmLand);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CSVRender::Cell::Cell (CSMWorld::Data& data, osg::Group* rootNode, const std::string& id,
|
CSVRender::Cell::Cell (CSMWorld::Data& data, osg::Group* rootNode, const std::string& id,
|
||||||
bool deleted)
|
bool deleted)
|
||||||
: mData (data), mId (Misc::StringUtils::lowerCase (id)), mDeleted (deleted), mSubMode (0),
|
: mData (data), mId (Misc::StringUtils::lowerCase (id)), mDeleted (deleted), mSubMode (0),
|
||||||
|
@ -99,22 +124,7 @@ CSVRender::Cell::Cell (CSMWorld::Data& data, osg::Group* rootNode, const std::st
|
||||||
|
|
||||||
addObjects (0, rows-1);
|
addObjects (0, rows-1);
|
||||||
|
|
||||||
const CSMWorld::IdCollection<CSMWorld::Land>& land = mData.getLand();
|
createLand();
|
||||||
int landIndex = land.searchId(mId);
|
|
||||||
if (landIndex != -1)
|
|
||||||
{
|
|
||||||
const ESM::Land& esmLand = land.getRecord(mId).get();
|
|
||||||
|
|
||||||
if (esmLand.getLandData (ESM::Land::DATA_VHGT))
|
|
||||||
{
|
|
||||||
mTerrain.reset(new Terrain::TerrainGrid(mCellNode, mCellNode, data.getResourceSystem().get(), new TerrainStorage(mData), Mask_Terrain));
|
|
||||||
mTerrain->loadCell(esmLand.mX,
|
|
||||||
esmLand.mY);
|
|
||||||
|
|
||||||
mCellBorder.reset(new CellBorder(mCellNode, mCoordinates));
|
|
||||||
mCellBorder->buildShape(esmLand);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mPathgrid.reset(new Pathgrid(mData, mCellNode, mId, mCoordinates));
|
mPathgrid.reset(new Pathgrid(mData, mCellNode, mId, mCoordinates));
|
||||||
mCellWater.reset(new CellWater(mData, mCellNode, mId, mCoordinates));
|
mCellWater.reset(new CellWater(mData, mCellNode, mId, mCoordinates));
|
||||||
|
@ -285,6 +295,36 @@ void CSVRender::Cell::pathgridRemoved()
|
||||||
mPathgrid->removeGeometry();
|
mPathgrid->removeGeometry();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSVRender::Cell::landDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight)
|
||||||
|
{
|
||||||
|
createLand();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVRender::Cell::landAboutToBeRemoved (const QModelIndex& parent, int start, int end)
|
||||||
|
{
|
||||||
|
createLand();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVRender::Cell::landAdded (const QModelIndex& parent, int start, int end)
|
||||||
|
{
|
||||||
|
createLand();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVRender::Cell::landTextureChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight)
|
||||||
|
{
|
||||||
|
createLand();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVRender::Cell::landTextureAboutToBeRemoved (const QModelIndex& parent, int start, int end)
|
||||||
|
{
|
||||||
|
createLand();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVRender::Cell::landTextureAdded (const QModelIndex& parent, int start, int end)
|
||||||
|
{
|
||||||
|
createLand();
|
||||||
|
}
|
||||||
|
|
||||||
void CSVRender::Cell::reloadAssets()
|
void CSVRender::Cell::reloadAssets()
|
||||||
{
|
{
|
||||||
for (std::map<std::string, Object *>::const_iterator iter (mObjects.begin());
|
for (std::map<std::string, Object *>::const_iterator iter (mObjects.begin());
|
||||||
|
|
|
@ -72,6 +72,8 @@ namespace CSVRender
|
||||||
/// \return Have any objects been added?
|
/// \return Have any objects been added?
|
||||||
bool addObjects (int start, int end);
|
bool addObjects (int start, int end);
|
||||||
|
|
||||||
|
void createLand();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
enum Selection
|
enum Selection
|
||||||
|
@ -118,6 +120,18 @@ namespace CSVRender
|
||||||
|
|
||||||
void pathgridRemoved();
|
void pathgridRemoved();
|
||||||
|
|
||||||
|
void landDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight);
|
||||||
|
|
||||||
|
void landAboutToBeRemoved (const QModelIndex& parent, int start, int end);
|
||||||
|
|
||||||
|
void landAdded (const QModelIndex& parent, int start, int end);
|
||||||
|
|
||||||
|
void landTextureChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight);
|
||||||
|
|
||||||
|
void landTextureAboutToBeRemoved (const QModelIndex& parent, int start, int end);
|
||||||
|
|
||||||
|
void landTextureAdded (const QModelIndex& parent, int start, int end);
|
||||||
|
|
||||||
void reloadAssets();
|
void reloadAssets();
|
||||||
|
|
||||||
void setSelection (int elementMask, Selection mode);
|
void setSelection (int elementMask, Selection mode);
|
||||||
|
|
|
@ -351,6 +351,69 @@ void CSVRender::PagedWorldspaceWidget::pathgridAdded(const QModelIndex& parent,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSVRender::PagedWorldspaceWidget::landDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight)
|
||||||
|
{
|
||||||
|
for (int r = topLeft.row(); r <= bottomRight.row(); ++r)
|
||||||
|
{
|
||||||
|
std::string id = mDocument.getData().getLand().getId(r);
|
||||||
|
|
||||||
|
auto cellIt = mCells.find(CSMWorld::CellCoordinates::fromId(id).first);
|
||||||
|
if (cellIt != mCells.end())
|
||||||
|
{
|
||||||
|
cellIt->second->landDataChanged(topLeft, bottomRight);
|
||||||
|
flagAsModified();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVRender::PagedWorldspaceWidget::landAboutToBeRemoved (const QModelIndex& parent, int start, int end)
|
||||||
|
{
|
||||||
|
for (int r = start; r <= end; ++r)
|
||||||
|
{
|
||||||
|
std::string id = mDocument.getData().getLand().getId(r);
|
||||||
|
|
||||||
|
auto cellIt = mCells.find(CSMWorld::CellCoordinates::fromId(id).first);
|
||||||
|
if (cellIt != mCells.end())
|
||||||
|
{
|
||||||
|
cellIt->second->landAboutToBeRemoved(parent, start, end);
|
||||||
|
flagAsModified();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVRender::PagedWorldspaceWidget::landAdded (const QModelIndex& parent, int start, int end)
|
||||||
|
{
|
||||||
|
for (int r = start; r <= end; ++r)
|
||||||
|
{
|
||||||
|
std::string id = mDocument.getData().getLand().getId(r);
|
||||||
|
|
||||||
|
auto cellIt = mCells.find(CSMWorld::CellCoordinates::fromId(id).first);
|
||||||
|
if (cellIt != mCells.end())
|
||||||
|
{
|
||||||
|
cellIt->second->landAdded(parent, start, end);
|
||||||
|
flagAsModified();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVRender::PagedWorldspaceWidget::landTextureDataChanged (const QModelIndex& topLeft, const QModelIndex& bottomRight)
|
||||||
|
{
|
||||||
|
for (auto cellIt : mCells)
|
||||||
|
cellIt.second->landTextureChanged(topLeft, bottomRight);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVRender::PagedWorldspaceWidget::landTextureAboutToBeRemoved (const QModelIndex& parent, int start, int end)
|
||||||
|
{
|
||||||
|
for (auto cellIt : mCells)
|
||||||
|
cellIt.second->landTextureAboutToBeRemoved(parent, start, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CSVRender::PagedWorldspaceWidget::landTextureAdded (const QModelIndex& parent, int start, int end)
|
||||||
|
{
|
||||||
|
for (auto cellIt : mCells)
|
||||||
|
cellIt.second->landTextureAdded(parent, start, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
std::string CSVRender::PagedWorldspaceWidget::getStartupInstruction()
|
std::string CSVRender::PagedWorldspaceWidget::getStartupInstruction()
|
||||||
{
|
{
|
||||||
|
@ -475,6 +538,24 @@ CSVRender::PagedWorldspaceWidget::PagedWorldspaceWidget (QWidget* parent, CSMDoc
|
||||||
connect (&document.getData(), SIGNAL (assetTablesChanged ()),
|
connect (&document.getData(), SIGNAL (assetTablesChanged ()),
|
||||||
this, SLOT (assetTablesChanged ()));
|
this, SLOT (assetTablesChanged ()));
|
||||||
|
|
||||||
|
QAbstractItemModel *lands = document.getData().getTableModel (CSMWorld::UniversalId::Type_Lands);
|
||||||
|
|
||||||
|
connect (lands, SIGNAL (dataChanged (const QModelIndex&, const QModelIndex&)),
|
||||||
|
this, SLOT (landDataChanged (const QModelIndex&, const QModelIndex&)));
|
||||||
|
connect (lands, SIGNAL (rowsAboutToBeRemoved (const QModelIndex&, int, int)),
|
||||||
|
this, SLOT (landAboutToBeRemoved (const QModelIndex&, int, int)));
|
||||||
|
connect (lands, SIGNAL (rowsInserted (const QModelIndex&, int, int)),
|
||||||
|
this, SLOT (landAdded (const QModelIndex&, int, int)));
|
||||||
|
|
||||||
|
QAbstractItemModel *ltexs = document.getData().getTableModel (CSMWorld::UniversalId::Type_LandTextures);
|
||||||
|
|
||||||
|
connect (ltexs, SIGNAL (dataChanged (const QModelIndex&, const QModelIndex&)),
|
||||||
|
this, SLOT (landTextureDataChanged (const QModelIndex&, const QModelIndex&)));
|
||||||
|
connect (ltexs, SIGNAL (rowsAboutToBeRemoved (const QModelIndex&, int, int)),
|
||||||
|
this, SLOT (landTextureAboutToBeRemoved (const QModelIndex&, int, int)));
|
||||||
|
connect (ltexs, SIGNAL (rowsInserted (const QModelIndex&, int, int)),
|
||||||
|
this, SLOT (landTextureAdded (const QModelIndex&, int, int)));
|
||||||
|
|
||||||
// Shortcuts
|
// Shortcuts
|
||||||
CSMPrefs::Shortcut* loadCameraCellShortcut = new CSMPrefs::Shortcut("scene-load-cam-cell", this);
|
CSMPrefs::Shortcut* loadCameraCellShortcut = new CSMPrefs::Shortcut("scene-load-cam-cell", this);
|
||||||
connect(loadCameraCellShortcut, SIGNAL(activated()), this, SLOT(loadCameraCell()));
|
connect(loadCameraCellShortcut, SIGNAL(activated()), this, SLOT(loadCameraCell()));
|
||||||
|
|
|
@ -155,6 +155,14 @@ namespace CSVRender
|
||||||
|
|
||||||
virtual void cellAdded (const QModelIndex& index, int start, int end);
|
virtual void cellAdded (const QModelIndex& index, int start, int end);
|
||||||
|
|
||||||
|
virtual void landDataChanged (const QModelIndex& topLeft, const QModelIndex& botomRight);
|
||||||
|
virtual void landAboutToBeRemoved (const QModelIndex& parent, int start, int end);
|
||||||
|
virtual void landAdded (const QModelIndex& parent, int start, int end);
|
||||||
|
|
||||||
|
virtual void landTextureDataChanged (const QModelIndex& topLeft, const QModelIndex& botomRight);
|
||||||
|
virtual void landTextureAboutToBeRemoved (const QModelIndex& parent, int start, int end);
|
||||||
|
virtual void landTextureAdded (const QModelIndex& parent, int start, int end);
|
||||||
|
|
||||||
void assetTablesChanged ();
|
void assetTablesChanged ();
|
||||||
|
|
||||||
void loadCameraCell();
|
void loadCameraCell();
|
||||||
|
|
|
@ -51,6 +51,11 @@ std::string CSVWorld::GenericCreator::getId() const
|
||||||
return mId->text().toUtf8().constData();
|
return mId->text().toUtf8().constData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string CSVWorld::GenericCreator::getClonedId() const
|
||||||
|
{
|
||||||
|
return mClonedId;
|
||||||
|
}
|
||||||
|
|
||||||
std::string CSVWorld::GenericCreator::getIdValidatorResult() const
|
std::string CSVWorld::GenericCreator::getIdValidatorResult() const
|
||||||
{
|
{
|
||||||
std::string errors;
|
std::string errors;
|
||||||
|
|
|
@ -64,6 +64,8 @@ namespace CSVWorld
|
||||||
|
|
||||||
virtual std::string getId() const;
|
virtual std::string getId() const;
|
||||||
|
|
||||||
|
std::string getClonedId() const;
|
||||||
|
|
||||||
virtual std::string getIdValidatorResult() const;
|
virtual std::string getIdValidatorResult() const;
|
||||||
|
|
||||||
/// Allow subclasses to add additional data to \a command.
|
/// Allow subclasses to add additional data to \a command.
|
||||||
|
|
|
@ -95,6 +95,25 @@ namespace CSVWorld
|
||||||
return CSMWorld::Land::createUniqueRecordId(mX->value(), mY->value());
|
return CSMWorld::Land::createUniqueRecordId(mX->value(), mY->value());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LandCreator::pushCommand(std::unique_ptr<CSMWorld::CreateCommand> command, const std::string& id)
|
||||||
|
{
|
||||||
|
if (mCloneMode)
|
||||||
|
{
|
||||||
|
CSMWorld::IdTable& lands = dynamic_cast<CSMWorld::IdTable&>(*getData().getTableModel(CSMWorld::UniversalId::Type_Lands));
|
||||||
|
CSMWorld::IdTable& ltexs = dynamic_cast<CSMWorld::IdTable&>(*getData().getTableModel(CSMWorld::UniversalId::Type_LandTextures));
|
||||||
|
|
||||||
|
getUndoStack().beginMacro(("Clone " + id).c_str());
|
||||||
|
getUndoStack().push(command.release());
|
||||||
|
|
||||||
|
CSMWorld::CopyLandTexturesCommand* ltexCopy = new CSMWorld::CopyLandTexturesCommand(lands, ltexs, getClonedId(), getId());
|
||||||
|
getUndoStack().push(ltexCopy);
|
||||||
|
|
||||||
|
getUndoStack().endMacro();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
getUndoStack().push (command.release());
|
||||||
|
}
|
||||||
|
|
||||||
void LandCreator::coordChanged(int value)
|
void LandCreator::coordChanged(int value)
|
||||||
{
|
{
|
||||||
update();
|
update();
|
||||||
|
|
|
@ -31,13 +31,16 @@ namespace CSVWorld
|
||||||
|
|
||||||
std::string getErrors() const override;
|
std::string getErrors() const override;
|
||||||
|
|
||||||
private slots:
|
|
||||||
|
|
||||||
void coordChanged(int value);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
std::string getId() const override;
|
std::string getId() const override;
|
||||||
|
|
||||||
|
void pushCommand(std::unique_ptr<CSMWorld::CreateCommand> command,
|
||||||
|
const std::string& id) override;
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
|
||||||
|
void coordChanged(int value);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,6 @@ namespace ESM
|
||||||
, mX(0)
|
, mX(0)
|
||||||
, mY(0)
|
, mY(0)
|
||||||
, mPlugin(0)
|
, mPlugin(0)
|
||||||
, mNoFile(false)
|
|
||||||
, mDataTypes(0)
|
, mDataTypes(0)
|
||||||
, mLandData(NULL)
|
, mLandData(NULL)
|
||||||
{
|
{
|
||||||
|
@ -214,7 +213,8 @@ namespace ESM
|
||||||
Land::DATA_VCLR | Land::DATA_VTEX;
|
Land::DATA_VCLR | Land::DATA_VTEX;
|
||||||
mDataTypes = mLandData->mDataLoaded;
|
mDataTypes = mLandData->mDataLoaded;
|
||||||
|
|
||||||
mNoFile = true;
|
// No file associated with the land now
|
||||||
|
mContext.filename.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Land::loadData(int flags, LandData* target) const
|
void Land::loadData(int flags, LandData* target) const
|
||||||
|
@ -236,7 +236,7 @@ namespace ESM
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy data to target if no file
|
// Copy data to target if no file
|
||||||
if (mNoFile)
|
if (mContext.filename.empty())
|
||||||
{
|
{
|
||||||
*target = *mLandData;
|
*target = *mLandData;
|
||||||
return;
|
return;
|
||||||
|
@ -320,7 +320,7 @@ namespace ESM
|
||||||
|
|
||||||
Land::Land (const Land& land)
|
Land::Land (const Land& land)
|
||||||
: mFlags (land.mFlags), mX (land.mX), mY (land.mY), mPlugin (land.mPlugin),
|
: mFlags (land.mFlags), mX (land.mX), mY (land.mY), mPlugin (land.mPlugin),
|
||||||
mContext (land.mContext), mNoFile(land.mNoFile), mDataTypes (land.mDataTypes),
|
mContext (land.mContext), mDataTypes (land.mDataTypes),
|
||||||
mLandData (land.mLandData ? new LandData (*land.mLandData) : 0)
|
mLandData (land.mLandData ? new LandData (*land.mLandData) : 0)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
@ -337,7 +337,6 @@ namespace ESM
|
||||||
std::swap (mY, land.mY);
|
std::swap (mY, land.mY);
|
||||||
std::swap (mPlugin, land.mPlugin);
|
std::swap (mPlugin, land.mPlugin);
|
||||||
std::swap (mContext, land.mContext);
|
std::swap (mContext, land.mContext);
|
||||||
std::swap (mNoFile, land.mNoFile);
|
|
||||||
std::swap (mDataTypes, land.mDataTypes);
|
std::swap (mDataTypes, land.mDataTypes);
|
||||||
std::swap (mLandData, land.mLandData);
|
std::swap (mLandData, land.mLandData);
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,12 +31,10 @@ struct Land
|
||||||
|
|
||||||
// File context. This allows the ESM reader to be 'reset' to this
|
// File context. This allows the ESM reader to be 'reset' to this
|
||||||
// location later when we are ready to load the full data set.
|
// location later when we are ready to load the full data set.
|
||||||
|
// In the editor, there may not be a file associated with the Land,
|
||||||
|
// in which case the filename will be empty.
|
||||||
ESM_Context mContext;
|
ESM_Context mContext;
|
||||||
|
|
||||||
// In the editor, a new Land is not associated with a file, thus mContext should not be accessed
|
|
||||||
// when land data is being requested. Instead simply copy over the data.
|
|
||||||
bool mNoFile;
|
|
||||||
|
|
||||||
int mDataTypes;
|
int mDataTypes;
|
||||||
|
|
||||||
enum
|
enum
|
||||||
|
|
Loading…
Reference in a new issue