diff --git a/apps/opencs/model/doc/savingstages.cpp b/apps/opencs/model/doc/savingstages.cpp index f9c028e29..b7eb369d7 100644 --- a/apps/opencs/model/doc/savingstages.cpp +++ b/apps/opencs/model/doc/savingstages.cpp @@ -269,7 +269,7 @@ void CSMDoc::WriteCellCollectionStage::perform (int stage, Messages& messages) bool interior = cellRecord.mId.substr (0, 1)!="#"; // count new references and adjust RefNumCount accordingsly - int newRefNum = cellRecord.mRefNumCounter; + unsigned int newRefNum = cellRecord.mRefNumCounter; if (references!=mState.getSubRecords().end()) { @@ -279,11 +279,17 @@ void CSMDoc::WriteCellCollectionStage::perform (int stage, Messages& messages) const CSMWorld::Record& ref = mDocument.getData().getReferences().getRecord (*iter); - if (ref.get().mNew || + CSMWorld::CellRef refRecord = ref.get(); + + if (refRecord.mNew || (!interior && ref.mState==CSMWorld::RecordBase::State_ModifiedOnly && /// \todo consider worldspace - CSMWorld::CellCoordinates (ref.get().getCellIndex()).getId("")!=ref.get().mCell)) + CSMWorld::CellCoordinates (refRecord.getCellIndex()).getId("") != refRecord.mCell)) ++cellRecord.mRefNumCounter; + + if (refRecord.mRefNum.mIndex >= newRefNum) + newRefNum = refRecord.mRefNum.mIndex + 1; + } } @@ -328,7 +334,7 @@ void CSMDoc::WriteCellCollectionStage::perform (int stage, Messages& messages) stream << "#" << index.first << " " << index.second; } - if (refRecord.mNew || + if (refRecord.mNew || refRecord.mRefNum.mIndex == 0 || (!interior && ref.mState==CSMWorld::RecordBase::State_ModifiedOnly && refRecord.mCell!=stream.str())) { diff --git a/apps/opencs/model/world/collection.hpp b/apps/opencs/model/world/collection.hpp index 80117d0c6..3d6802b86 100644 --- a/apps/opencs/model/world/collection.hpp +++ b/apps/opencs/model/world/collection.hpp @@ -17,6 +17,7 @@ #include "collectionbase.hpp" #include "land.hpp" #include "landtexture.hpp" +#include "ref.hpp" namespace CSMWorld { @@ -259,6 +260,11 @@ namespace CSMWorld copy.mState = RecordBase::State_ModifiedOnly; IdAccessorT().setId(copy.get(), destination); + if (type == UniversalId::Type_Reference) { + CSMWorld::CellRef* ptr = (CSMWorld::CellRef*) ©.mModified; + ptr->mRefNum.mIndex = 0; + } + int index = getAppendIndex(destination, type); insertRecord(copy, getAppendIndex(destination, type)); diff --git a/apps/opencs/model/world/commanddispatcher.cpp b/apps/opencs/model/world/commanddispatcher.cpp index 5d6a35cc5..2493813a6 100644 --- a/apps/opencs/model/world/commanddispatcher.cpp +++ b/apps/opencs/model/world/commanddispatcher.cpp @@ -4,6 +4,7 @@ #include #include +#include #include "../doc/document.hpp" @@ -140,29 +141,44 @@ void CSMWorld::CommandDispatcher::executeModify (QAbstractItemModel *model, cons std::unique_ptr modifyCell; + std::unique_ptr modifyDataRefNum; + int columnId = model->data (index, ColumnBase::Role_ColumnId).toInt(); if (columnId==Columns::ColumnId_PositionXPos || columnId==Columns::ColumnId_PositionYPos) { - IdTableProxyModel *proxy = dynamic_cast (model); + const float oldPosition = model->data (index).toFloat(); - int row = proxy ? proxy->mapToSource (index).row() : index.row(); - - // This is not guaranteed to be the same as \a model, since a proxy could be used. - IdTable& model2 = dynamic_cast (*mDocument.getData().getTableModel (mId)); - - int cellColumn = model2.searchColumnIndex (Columns::ColumnId_Cell); - - if (cellColumn!=-1) + // Modulate by cell size, update cell id if reference has been moved to a new cell + if (std::abs(std::fmod(oldPosition, Constants::CellSizeInUnits)) + - std::abs(std::fmod(new_.toFloat(), Constants::CellSizeInUnits)) >= 0.5f) { - QModelIndex cellIndex = model2.index (row, cellColumn); + IdTableProxyModel *proxy = dynamic_cast (model); - std::string cellId = model2.data (cellIndex).toString().toUtf8().data(); + int row = proxy ? proxy->mapToSource (index).row() : index.row(); - if (cellId.find ('#')!=std::string::npos) + // This is not guaranteed to be the same as \a model, since a proxy could be used. + IdTable& model2 = dynamic_cast (*mDocument.getData().getTableModel (mId)); + + int cellColumn = model2.searchColumnIndex (Columns::ColumnId_Cell); + + if (cellColumn!=-1) { - // Need to recalculate the cell - modifyCell.reset (new UpdateCellCommand (model2, row)); + QModelIndex cellIndex = model2.index (row, cellColumn); + + std::string cellId = model2.data (cellIndex).toString().toUtf8().data(); + + if (cellId.find ('#')!=std::string::npos) + { + // Need to recalculate the cell and (if necessary) clear the instance's refNum + modifyCell.reset (new UpdateCellCommand (model2, row)); + + // Not sure which model this should be applied to + int refNumColumn = model2.searchColumnIndex (Columns::ColumnId_RefNum); + + if (refNumColumn!=-1) + modifyDataRefNum.reset (new ModifyCommand(*model, model->index(row, refNumColumn), 0)); + } } } } @@ -175,6 +191,8 @@ void CSMWorld::CommandDispatcher::executeModify (QAbstractItemModel *model, cons CommandMacro macro (mDocument.getUndoStack()); macro.push (modifyData.release()); macro.push (modifyCell.release()); + if (modifyDataRefNum.get()) + macro.push (modifyDataRefNum.release()); } else mDocument.getUndoStack().push (modifyData.release()); diff --git a/apps/opencs/view/render/object.cpp b/apps/opencs/view/render/object.cpp index 026625795..0a3a950e0 100644 --- a/apps/opencs/view/render/object.cpp +++ b/apps/opencs/view/render/object.cpp @@ -670,6 +670,33 @@ void CSVRender::Object::apply (CSMWorld::CommandMacro& commands) if (mOverrideFlags & Override_Position) { + //Do cell check first so positions can be compared + const CSMWorld::CellRef& ref = collection.getRecord(recordIndex).get(); + + if (CSMWorld::CellCoordinates::isExteriorCell(ref.mCell)) + { + // Find cell index at new position + std::pair cellIndex = CSMWorld::CellCoordinates::coordinatesToCellIndex( + mPositionOverride.pos[0], mPositionOverride.pos[1]); + std::pair originalIndex = ref.getCellIndex(); + + int cellColumn = collection.findColumnIndex (static_cast ( + CSMWorld::Columns::ColumnId_Cell)); + int refNumColumn = collection.findColumnIndex (static_cast ( + CSMWorld::Columns::ColumnId_RefNum)); + + if (cellIndex != originalIndex) + { + /// \todo figure out worldspace (not important until multiple worldspaces are supported) + std::string cellId = CSMWorld::CellCoordinates (cellIndex).getId (""); + + commands.push (new CSMWorld::ModifyCommand (*model, + model->index (recordIndex, cellColumn), QString::fromUtf8 (cellId.c_str()))); + commands.push (new CSMWorld::ModifyCommand( *model, + model->index (recordIndex, refNumColumn), 0)); + } + } + for (int i=0; i<3; ++i) { int column = collection.findColumnIndex (static_cast ( @@ -678,20 +705,6 @@ void CSVRender::Object::apply (CSMWorld::CommandMacro& commands) commands.push (new CSMWorld::ModifyCommand (*model, model->index (recordIndex, column), mPositionOverride.pos[i])); } - - int column = collection.findColumnIndex (static_cast ( - CSMWorld::Columns::ColumnId_Cell)); - - if (CSMWorld::CellCoordinates::isExteriorCell(collection.getRecord (recordIndex).get().mCell)) - { - std::pair cellIndex = collection.getRecord (recordIndex).get().getCellIndex(); - - /// \todo figure out worldspace (not important until multiple worldspaces are supported) - std::string cellId = CSMWorld::CellCoordinates (cellIndex).getId (""); - - commands.push (new CSMWorld::ModifyCommand (*model, - model->index (recordIndex, column), QString::fromUtf8 (cellId.c_str()))); - } } if (mOverrideFlags & Override_Rotation)