Skip to content

Commit

Permalink
Merge branch 'OpenCS-moved-reference' into 'master'
Browse files Browse the repository at this point in the history
OpenCS - Fix moved reference - Issues #3514 and #4752

See merge request OpenMW/openmw!1051

(cherry picked from commit 2bee171c7990522da33c2667f7d079fa35f4ede0)

36c30f7 Fix for Issue #3514 where moving a reference to another cell is not handled properly.
4032768 Update the changelog.
  • Loading branch information
psi29a committed Aug 3, 2021
1 parent e10e9c0 commit 9b7e14e
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 24 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
0.48.0
------

Bug #3514: Editing a reference's position after loading an esp file makes the reference disappear
Bug #3737: Scripts from The Underground 2 .esp do not play (all patched versions)
Bug #3846: Strings starting with "-" fail to compile if not enclosed in quotes
Bug #3905: Great House Dagoth issues
Bug #4203: Resurrecting an actor should close the loot GUI
Bug #4752: UpdateCellCommand doesn't undo properly
Bug #5100: Persuasion doesn't always clamp the resulting disposition
Bug #5120: Scripted object spawning updates physics system
Bug #5379: Wandering NPCs falling through cantons
Expand Down
3 changes: 2 additions & 1 deletion apps/opencs/model/doc/savingstages.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,8 @@ void CSMDoc::WriteCellCollectionStage::writeReferences (const std::deque<int>& r
{
refRecord.mRefNum.mIndex = newRefNum++;
}
else if ((refRecord.mOriginalCell.empty() ? refRecord.mCell : refRecord.mOriginalCell)

if ((refRecord.mOriginalCell.empty() ? refRecord.mCell : refRecord.mOriginalCell)
!= stream.str() && !interior)
{
// An empty mOriginalCell is meant to indicate that it is the same as
Expand Down
69 changes: 48 additions & 21 deletions apps/opencs/model/world/commanddispatcher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,13 +139,28 @@ void CSMWorld::CommandDispatcher::executeModify (QAbstractItemModel *model, cons
if (mLocked)
return;

std::unique_ptr<CSMWorld::UpdateCellCommand> modifyCell;
std::unique_ptr<CSMWorld::CloneCommand> clonedData;
std::unique_ptr<CSMWorld::DeleteCommand> deleteData;

std::string newId;

std::unique_ptr<CSMWorld::ModifyCommand> modifyDataRefNum;
std::unique_ptr<CSMWorld::ModifyCommand> modifyData;
std::unique_ptr<CSMWorld::UpdateCellCommand> modifyCell;

int columnId = model->data (index, ColumnBase::Role_ColumnId).toInt();

if (columnId==Columns::ColumnId_PositionXPos || columnId==Columns::ColumnId_PositionYPos)
int stateColumn = dynamic_cast<CSMWorld::IdTable&>(*model).findColumnIndex(Columns::ColumnId_Modification);

CSMWorld::IdTable& table = dynamic_cast<CSMWorld::IdTable&>(*model); // for getId()
QModelIndex stateIndex = table.getModelIndex(table.getId(index.row()), stateColumn);
RecordBase::State state = static_cast<RecordBase::State> (model->data(stateIndex).toInt());

// This is not guaranteed to be the same as \a model, since a proxy could be used.
IdTable& model2 = dynamic_cast<IdTable&> (*mDocument.getData().getTableModel(mId));

// DeleteCommand triggers a signal to the whole row from IdTable::setData(), so ignore the second call
if (state != RecordBase::State_Deleted &&
(columnId==Columns::ColumnId_PositionXPos || columnId==Columns::ColumnId_PositionYPos))
{
const float oldPosition = model->data (index).toFloat();

Expand All @@ -157,44 +172,56 @@ void CSMWorld::CommandDispatcher::executeModify (QAbstractItemModel *model, cons

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<IdTable&> (*mDocument.getData().getTableModel (mId));

int cellColumn = model2.searchColumnIndex (Columns::ColumnId_Cell);

if (cellColumn!=-1)
if (cellColumn != -1)
{
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));
RefCollection& collection = mDocument.getData().getReferences();
newId = collection.getNewId();

// Not sure which model this should be applied to
int refNumColumn = model2.searchColumnIndex (Columns::ColumnId_RefNum);
clonedData.reset(new CloneCommand(table,
table.getId(row),
newId,
CSMWorld::UniversalId::Type_Reference));

if (refNumColumn!=-1)
modifyDataRefNum.reset (new ModifyCommand(*model, model->index(row, refNumColumn), 0));
deleteData.reset(new DeleteCommand(table,
table.getId(row),
CSMWorld::UniversalId::Type_Reference));
}
}
}
}

std::unique_ptr<CSMWorld::ModifyCommand> modifyData (
new CSMWorld::ModifyCommand (*model, index, new_));
if (!clonedData.get())
{
// DeleteCommand will trigger executeModify after setting the state to State_Deleted
// from CommandDelegate::setModelDataImp() - ignore
if (state != RecordBase::State_Deleted)
modifyData.reset(new CSMWorld::ModifyCommand(*model, index, new_));
}

if (modifyCell.get())
if (clonedData.get())
{
CommandMacro macro (mDocument.getUndoStack());
macro.push (modifyData.release());
macro.push (modifyCell.release());
if (modifyDataRefNum.get())
macro.push (modifyDataRefNum.release());
macro.push(clonedData.release());
macro.push(deleteData.release());

// cannot do these earlier because newIndex is not available until CloneCommand is executed
QModelIndex newIndex = model2.getModelIndex (newId, index.column());
modifyData.reset (new CSMWorld::ModifyCommand (*model, newIndex, new_));
macro.push(modifyData.release());

// once the data is updated update the cell location
modifyCell.reset(new UpdateCellCommand(model2, newIndex.row()));
macro.push(modifyCell.release());
}
else
else if (!clonedData.get() && modifyData.get())
mDocument.getUndoStack().push (modifyData.release());
}

Expand Down
2 changes: 1 addition & 1 deletion components/esm/loadcell.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ namespace ESM
mWater = 0;
mWaterInt = false;
mMapColor = 0;
mRefNumCounter = -1;
mRefNumCounter = 0;

mData.mFlags = 0;
mData.mX = 0;
Expand Down
2 changes: 1 addition & 1 deletion components/esm/loadcell.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ struct Cell
mWater(0),
mWaterInt(false),
mMapColor(0),
mRefNumCounter(-1)
mRefNumCounter(0)
{}

// Interior cells are indexed by this (it's the 'id'), for exterior
Expand Down

0 comments on commit 9b7e14e

Please sign in to comment.