mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-09-23 03:47:34 -04:00
Editor: Fix crash if the smoothed terrain vertex belongs to an unloaded cell (#8686)
This commit is contained in:
parent
0c95d62e89
commit
35cc6e6daf
@ -743,17 +743,19 @@ void CSVRender::TerrainShapeMode::alterHeight(
|
|||||||
void CSVRender::TerrainShapeMode::smoothHeight(
|
void CSVRender::TerrainShapeMode::smoothHeight(
|
||||||
const CSMWorld::CellCoordinates& cellCoords, int inCellX, int inCellY, int toolStrength)
|
const CSMWorld::CellCoordinates& cellCoords, int inCellX, int inCellY, int toolStrength)
|
||||||
{
|
{
|
||||||
if (CSVRender::PagedWorldspaceWidget* paged
|
auto paged = dynamic_cast<CSVRender::PagedWorldspaceWidget*>(&getWorldspaceWidget());
|
||||||
= dynamic_cast<CSVRender::PagedWorldspaceWidget*>(&getWorldspaceWidget()))
|
if (paged == nullptr)
|
||||||
{
|
return;
|
||||||
|
|
||||||
|
std::string cellId = CSMWorld::CellCoordinates::generateId(cellCoords.getX(), cellCoords.getY());
|
||||||
|
if (!allowLandShapeEditing(cellId))
|
||||||
|
return;
|
||||||
|
|
||||||
CSMDoc::Document& document = getWorldspaceWidget().getDocument();
|
CSMDoc::Document& document = getWorldspaceWidget().getDocument();
|
||||||
CSMWorld::IdTable& landTable
|
CSMWorld::IdTable& landTable
|
||||||
= dynamic_cast<CSMWorld::IdTable&>(*document.getData().getTableModel(CSMWorld::UniversalId::Type_Land));
|
= dynamic_cast<CSMWorld::IdTable&>(*document.getData().getTableModel(CSMWorld::UniversalId::Type_Land));
|
||||||
int landshapeColumn = landTable.findColumnIndex(CSMWorld::Columns::ColumnId_LandHeightsIndex);
|
const int landshapeColumn = landTable.findColumnIndex(CSMWorld::Columns::ColumnId_LandHeightsIndex);
|
||||||
|
const auto landShapePointer = landTable.data(landTable.getModelIndex(cellId, landshapeColumn))
|
||||||
std::string cellId = CSMWorld::CellCoordinates::generateId(cellCoords.getX(), cellCoords.getY());
|
|
||||||
const CSMWorld::LandHeightsColumn::DataType landShapePointer
|
|
||||||
= landTable.data(landTable.getModelIndex(cellId, landshapeColumn))
|
|
||||||
.value<CSMWorld::LandHeightsColumn::DataType>();
|
.value<CSMWorld::LandHeightsColumn::DataType>();
|
||||||
|
|
||||||
// ### Variable naming key ###
|
// ### Variable naming key ###
|
||||||
@ -762,112 +764,99 @@ void CSVRender::TerrainShapeMode::smoothHeight(
|
|||||||
// left = x - 1, up = y - 1, right = x + 1, down = y + 1
|
// left = x - 1, up = y - 1, right = x + 1, down = y + 1
|
||||||
// Altered = transient edit (in current edited)
|
// Altered = transient edit (in current edited)
|
||||||
float thisHeight = landShapePointer[inCellY * ESM::Land::LAND_SIZE + inCellX];
|
float thisHeight = landShapePointer[inCellY * ESM::Land::LAND_SIZE + inCellX];
|
||||||
float* thisAlteredHeightPtr = paged->getCellAlteredHeight(cellCoords, inCellX, inCellY);
|
if (const float* thisAlteredHeightPtr = paged->getCellAlteredHeight(cellCoords, inCellX, inCellY))
|
||||||
float thisAlteredHeight = thisAlteredHeightPtr != nullptr ? *thisAlteredHeightPtr : 0.f;
|
thisHeight += *thisAlteredHeightPtr;
|
||||||
float leftHeight = thisHeight;
|
float leftHeight = thisHeight;
|
||||||
float leftAlteredHeight = thisAlteredHeight;
|
|
||||||
float rightHeight = thisHeight;
|
float rightHeight = thisHeight;
|
||||||
float rightAlteredHeight = thisAlteredHeight;
|
|
||||||
float downHeight = thisHeight;
|
float downHeight = thisHeight;
|
||||||
float downAlteredHeight = thisAlteredHeight;
|
|
||||||
float upHeight = thisHeight;
|
float upHeight = thisHeight;
|
||||||
float upAlteredHeight = thisAlteredHeight;
|
|
||||||
|
|
||||||
if (allowLandShapeEditing(cellId))
|
|
||||||
{
|
|
||||||
// Get key values for calculating average, handle cell edges, check for null pointers
|
// Get key values for calculating average, handle cell edges, check for null pointers
|
||||||
if (inCellX == 0)
|
if (inCellX == 0)
|
||||||
{
|
{
|
||||||
cellId = CSMWorld::CellCoordinates::generateId(cellCoords.getX() - 1, cellCoords.getY());
|
cellId = CSMWorld::CellCoordinates::generateId(cellCoords.getX() - 1, cellCoords.getY());
|
||||||
if (isLandLoaded(cellId))
|
if (isLandLoaded(cellId))
|
||||||
{
|
{
|
||||||
const CSMWorld::LandHeightsColumn::DataType landLeftShapePointer
|
const auto landLeftShapePointer = landTable.data(landTable.getModelIndex(cellId, landshapeColumn))
|
||||||
= landTable.data(landTable.getModelIndex(cellId, landshapeColumn))
|
|
||||||
.value<CSMWorld::LandHeightsColumn::DataType>();
|
.value<CSMWorld::LandHeightsColumn::DataType>();
|
||||||
leftHeight = landLeftShapePointer[inCellY * ESM::Land::LAND_SIZE + (ESM::Land::LAND_SIZE - 2)];
|
leftHeight = landLeftShapePointer[inCellY * ESM::Land::LAND_SIZE + (ESM::Land::LAND_SIZE - 2)];
|
||||||
float* alteredHeightPtr
|
if (const float* alteredHeightPtr
|
||||||
= paged->getCellAlteredHeight(cellCoords.move(-1, 0), ESM::Land::LAND_SIZE - 2, inCellY);
|
= paged->getCellAlteredHeight(cellCoords.move(-1, 0), ESM::Land::LAND_SIZE - 2, inCellY))
|
||||||
leftAlteredHeight = alteredHeightPtr != nullptr ? *alteredHeightPtr : 0.f;
|
leftHeight += *alteredHeightPtr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (inCellX > 0)
|
||||||
|
{
|
||||||
|
leftHeight = landShapePointer[inCellY * ESM::Land::LAND_SIZE + inCellX - 1];
|
||||||
|
if (const float* alteredHeightPtr = paged->getCellAlteredHeight(cellCoords, inCellX - 1, inCellY))
|
||||||
|
leftHeight += *alteredHeightPtr;
|
||||||
|
}
|
||||||
|
|
||||||
if (inCellY == 0)
|
if (inCellY == 0)
|
||||||
{
|
{
|
||||||
cellId = CSMWorld::CellCoordinates::generateId(cellCoords.getX(), cellCoords.getY() - 1);
|
cellId = CSMWorld::CellCoordinates::generateId(cellCoords.getX(), cellCoords.getY() - 1);
|
||||||
if (isLandLoaded(cellId))
|
if (isLandLoaded(cellId))
|
||||||
{
|
{
|
||||||
const CSMWorld::LandHeightsColumn::DataType landUpShapePointer
|
const auto landUpShapePointer = landTable.data(landTable.getModelIndex(cellId, landshapeColumn))
|
||||||
= landTable.data(landTable.getModelIndex(cellId, landshapeColumn))
|
|
||||||
.value<CSMWorld::LandHeightsColumn::DataType>();
|
.value<CSMWorld::LandHeightsColumn::DataType>();
|
||||||
upHeight = landUpShapePointer[(ESM::Land::LAND_SIZE - 2) * ESM::Land::LAND_SIZE + inCellX];
|
upHeight = landUpShapePointer[(ESM::Land::LAND_SIZE - 2) * ESM::Land::LAND_SIZE + inCellX];
|
||||||
float* alteredHeightPtr
|
if (const float* alteredHeightPtr
|
||||||
= paged->getCellAlteredHeight(cellCoords.move(0, -1), inCellX, ESM::Land::LAND_SIZE - 2);
|
= paged->getCellAlteredHeight(cellCoords.move(0, -1), inCellX, ESM::Land::LAND_SIZE - 2))
|
||||||
upAlteredHeight = alteredHeightPtr != nullptr ? *alteredHeightPtr : 0.f;
|
upHeight += *alteredHeightPtr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (inCellX > 0)
|
else if (inCellY > 0)
|
||||||
{
|
|
||||||
leftHeight = landShapePointer[inCellY * ESM::Land::LAND_SIZE + inCellX - 1];
|
|
||||||
float* alteredHeightPtr = paged->getCellAlteredHeight(cellCoords, inCellX - 1, inCellY);
|
|
||||||
leftAlteredHeight = alteredHeightPtr != nullptr ? *alteredHeightPtr : 0.f;
|
|
||||||
}
|
|
||||||
if (inCellY > 0)
|
|
||||||
{
|
{
|
||||||
upHeight = landShapePointer[(inCellY - 1) * ESM::Land::LAND_SIZE + inCellX];
|
upHeight = landShapePointer[(inCellY - 1) * ESM::Land::LAND_SIZE + inCellX];
|
||||||
float* alteredHeightPtr = paged->getCellAlteredHeight(cellCoords, inCellX, inCellY - 1);
|
if (const float* alteredHeightPtr = paged->getCellAlteredHeight(cellCoords, inCellX, inCellY - 1))
|
||||||
upAlteredHeight = alteredHeightPtr != nullptr ? *alteredHeightPtr : 0.f;
|
upHeight += *alteredHeightPtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inCellX == ESM::Land::LAND_SIZE - 1)
|
if (inCellX == ESM::Land::LAND_SIZE - 1)
|
||||||
{
|
{
|
||||||
cellId = CSMWorld::CellCoordinates::generateId(cellCoords.getX() + 1, cellCoords.getY());
|
cellId = CSMWorld::CellCoordinates::generateId(cellCoords.getX() + 1, cellCoords.getY());
|
||||||
if (isLandLoaded(cellId))
|
if (isLandLoaded(cellId))
|
||||||
{
|
{
|
||||||
const CSMWorld::LandHeightsColumn::DataType landRightShapePointer
|
const auto landRightShapePointer = landTable.data(landTable.getModelIndex(cellId, landshapeColumn))
|
||||||
= landTable.data(landTable.getModelIndex(cellId, landshapeColumn))
|
|
||||||
.value<CSMWorld::LandHeightsColumn::DataType>();
|
.value<CSMWorld::LandHeightsColumn::DataType>();
|
||||||
rightHeight = landRightShapePointer[inCellY * ESM::Land::LAND_SIZE + 1];
|
rightHeight = landRightShapePointer[inCellY * ESM::Land::LAND_SIZE + 1];
|
||||||
float* alteredHeightPtr = paged->getCellAlteredHeight(cellCoords.move(1, 0), 1, inCellY);
|
if (const float* alteredHeightPtr = paged->getCellAlteredHeight(cellCoords.move(1, 0), 1, inCellY))
|
||||||
rightAlteredHeight = alteredHeightPtr != nullptr ? *alteredHeightPtr : 0.f;
|
rightHeight += *alteredHeightPtr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (inCellX < ESM::Land::LAND_SIZE - 1)
|
||||||
|
{
|
||||||
|
rightHeight = landShapePointer[inCellY * ESM::Land::LAND_SIZE + inCellX + 1];
|
||||||
|
if (const float* alteredHeightPtr = paged->getCellAlteredHeight(cellCoords, inCellX + 1, inCellY))
|
||||||
|
rightHeight += *alteredHeightPtr;
|
||||||
|
}
|
||||||
|
|
||||||
if (inCellY == ESM::Land::LAND_SIZE - 1)
|
if (inCellY == ESM::Land::LAND_SIZE - 1)
|
||||||
{
|
{
|
||||||
cellId = CSMWorld::CellCoordinates::generateId(cellCoords.getX(), cellCoords.getY() + 1);
|
cellId = CSMWorld::CellCoordinates::generateId(cellCoords.getX(), cellCoords.getY() + 1);
|
||||||
if (isLandLoaded(cellId))
|
if (isLandLoaded(cellId))
|
||||||
{
|
{
|
||||||
const CSMWorld::LandHeightsColumn::DataType landDownShapePointer
|
const auto landDownShapePointer = landTable.data(landTable.getModelIndex(cellId, landshapeColumn))
|
||||||
= landTable.data(landTable.getModelIndex(cellId, landshapeColumn))
|
|
||||||
.value<CSMWorld::LandHeightsColumn::DataType>();
|
.value<CSMWorld::LandHeightsColumn::DataType>();
|
||||||
downHeight = landDownShapePointer[1 * ESM::Land::LAND_SIZE + inCellX];
|
downHeight = landDownShapePointer[1 * ESM::Land::LAND_SIZE + inCellX];
|
||||||
float* alteredHeightPtr = paged->getCellAlteredHeight(cellCoords.move(0, 1), inCellX, 1);
|
if (const float* alteredHeightPtr = paged->getCellAlteredHeight(cellCoords.move(0, 1), inCellX, 1))
|
||||||
downAlteredHeight = alteredHeightPtr != nullptr ? *alteredHeightPtr : 0.f;
|
downHeight += *alteredHeightPtr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (inCellX < ESM::Land::LAND_SIZE - 1)
|
else if (inCellY < ESM::Land::LAND_SIZE - 1)
|
||||||
{
|
|
||||||
rightHeight = landShapePointer[inCellY * ESM::Land::LAND_SIZE + inCellX + 1];
|
|
||||||
float* alteredHeightPtr = paged->getCellAlteredHeight(cellCoords, inCellX + 1, inCellY);
|
|
||||||
rightAlteredHeight = alteredHeightPtr != nullptr ? *alteredHeightPtr : 0.f;
|
|
||||||
}
|
|
||||||
if (inCellY < ESM::Land::LAND_SIZE - 1)
|
|
||||||
{
|
{
|
||||||
downHeight = landShapePointer[(inCellY + 1) * ESM::Land::LAND_SIZE + inCellX];
|
downHeight = landShapePointer[(inCellY + 1) * ESM::Land::LAND_SIZE + inCellX];
|
||||||
float* alteredHeightPtr = paged->getCellAlteredHeight(cellCoords, inCellX, inCellY + 1);
|
if (const float* alteredHeightPtr = paged->getCellAlteredHeight(cellCoords, inCellX, inCellY + 1))
|
||||||
downAlteredHeight = alteredHeightPtr != nullptr ? *alteredHeightPtr : 0.f;
|
downHeight += *alteredHeightPtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
float averageHeight = (upHeight + downHeight + rightHeight + leftHeight + upAlteredHeight
|
const float averageHeight = (upHeight + downHeight + rightHeight + leftHeight) / 4.f;
|
||||||
+ downAlteredHeight + rightAlteredHeight + leftAlteredHeight)
|
if (thisHeight == averageHeight)
|
||||||
/ 4;
|
return;
|
||||||
if ((thisHeight + thisAlteredHeight) != averageHeight)
|
|
||||||
mAlteredCells.emplace_back(cellCoords);
|
mAlteredCells.emplace_back(cellCoords);
|
||||||
if (toolStrength > abs(thisHeight + thisAlteredHeight - averageHeight))
|
const float delta = std::min(static_cast<float>(toolStrength), std::abs(thisHeight - averageHeight));
|
||||||
toolStrength = abs(thisHeight + thisAlteredHeight - averageHeight);
|
alterHeight(cellCoords, inCellX, inCellY, thisHeight < averageHeight ? delta : -delta);
|
||||||
if (thisHeight + thisAlteredHeight > averageHeight)
|
|
||||||
alterHeight(cellCoords, inCellX, inCellY, -toolStrength);
|
|
||||||
if (thisHeight + thisAlteredHeight < averageHeight)
|
|
||||||
alterHeight(cellCoords, inCellX, inCellY, +toolStrength);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVRender::TerrainShapeMode::flattenHeight(
|
void CSVRender::TerrainShapeMode::flattenHeight(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user