mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-09-21 19:04:42 -04:00
Merge branch 'fix_some_terrain_bug' into 'master'
CS: Make painting terrain height over a cell border equalize the height at both edge See merge request OpenMW/openmw!4898
This commit is contained in:
commit
a240f01d5f
@ -371,6 +371,11 @@ float CSVRender::Cell::getSumOfAlteredAndTrueHeight(int cellX, int cellY, int in
|
||||
return mTerrainStorage->getSumOfAlteredAndTrueHeight(cellX, cellY, inCellX, inCellY);
|
||||
}
|
||||
|
||||
std::optional<float> CSVRender::Cell::getOriginalHeight(int cellX, int cellY, int inCellX, int inCellY)
|
||||
{
|
||||
return mTerrainStorage->getOriginalHeight(cellX, cellY, inCellX, inCellY);
|
||||
}
|
||||
|
||||
float* CSVRender::Cell::getAlteredHeight(int inCellX, int inCellY)
|
||||
{
|
||||
return mTerrainStorage->getAlteredHeight(inCellX, inCellY);
|
||||
|
@ -125,6 +125,8 @@ namespace CSVRender
|
||||
|
||||
float getSumOfAlteredAndTrueHeight(int cellX, int cellY, int inCellX, int inCellY);
|
||||
|
||||
std::optional<float> getOriginalHeight(int cellX, int cellY, int inCellX, int inCellY);
|
||||
|
||||
float* getAlteredHeight(int inCellX, int inCellY);
|
||||
|
||||
void resetAlteredHeights();
|
||||
|
@ -824,6 +824,30 @@ CSVRender::Cell* CSVRender::PagedWorldspaceWidget::getCell(const CSMWorld::CellC
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void CSVRender::PagedWorldspaceWidget::setCellAlteredAbsoluteHeight(
|
||||
const CSMWorld::CellCoordinates& coords, int inCellX, int inCellY, float absoluteHeight)
|
||||
{
|
||||
std::map<CSMWorld::CellCoordinates, Cell*>::iterator searchResult = mCells.find(coords);
|
||||
if (searchResult != mCells.end())
|
||||
{
|
||||
std::optional<float> baseHeight
|
||||
= searchResult->second->getOriginalHeight(coords.getX(), coords.getY(), inCellX, inCellY);
|
||||
if (baseHeight)
|
||||
searchResult->second->setAlteredHeight(inCellX, inCellY, absoluteHeight - *baseHeight);
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<float> CSVRender::PagedWorldspaceWidget::getCellOriginalHeight(
|
||||
const CSMWorld::CellCoordinates& coords, int inCellX, int inCellY)
|
||||
{
|
||||
std::map<CSMWorld::CellCoordinates, Cell*>::iterator searchResult = mCells.find(coords);
|
||||
if (searchResult != mCells.end())
|
||||
{
|
||||
return searchResult->second->getOriginalHeight(coords.getX(), coords.getY(), inCellX, inCellY);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
void CSVRender::PagedWorldspaceWidget::setCellAlteredHeight(
|
||||
const CSMWorld::CellCoordinates& coords, int inCellX, int inCellY, float height)
|
||||
{
|
||||
|
@ -153,6 +153,11 @@ namespace CSVRender
|
||||
|
||||
Cell* getCell(const CSMWorld::CellCoordinates& coords) const override;
|
||||
|
||||
void setCellAlteredAbsoluteHeight(
|
||||
const CSMWorld::CellCoordinates& coords, int inCellX, int inCellY, float absoluteHeight);
|
||||
|
||||
std::optional<float> getCellOriginalHeight(const CSMWorld::CellCoordinates& coords, int inCellX, int inCellY);
|
||||
|
||||
void setCellAlteredHeight(const CSMWorld::CellCoordinates& coords, int inCellX, int inCellY, float height);
|
||||
|
||||
float* getCellAlteredHeight(const CSMWorld::CellCoordinates& coords, int inCellX, int inCellY);
|
||||
|
@ -258,35 +258,12 @@ void CSVRender::TerrainShapeMode::dragWheel(int diff, double speedFactor) {}
|
||||
|
||||
void CSVRender::TerrainShapeMode::sortAndLimitAlteredCells()
|
||||
{
|
||||
bool passing = false;
|
||||
int passes = 0;
|
||||
|
||||
std::sort(mAlteredCells.begin(), mAlteredCells.end());
|
||||
mAlteredCells.erase(std::unique(mAlteredCells.begin(), mAlteredCells.end()), mAlteredCells.end());
|
||||
|
||||
while (!passing) // Multiple passes are needed when steepness problems arise for both x and y axis simultaneously
|
||||
for (CSMWorld::CellCoordinates cellCoordinates : mAlteredCells)
|
||||
{
|
||||
passing = true;
|
||||
for (CSMWorld::CellCoordinates cellCoordinates : mAlteredCells)
|
||||
{
|
||||
limitAlteredHeights(cellCoordinates);
|
||||
}
|
||||
std::reverse(mAlteredCells.begin(),
|
||||
mAlteredCells
|
||||
.end()); // Instead of alphabetical order, this should be fixed to sort cells by cell coordinates
|
||||
for (CSMWorld::CellCoordinates cellCoordinates : mAlteredCells)
|
||||
{
|
||||
if (!limitAlteredHeights(cellCoordinates, true))
|
||||
passing = false;
|
||||
}
|
||||
++passes;
|
||||
if (passes > 2)
|
||||
{
|
||||
Log(Debug::Warning) << "Warning: User edit exceeds accepted slope steepness. Automatic limiting has "
|
||||
"failed, edit has been discarded.";
|
||||
clearTransientEdits();
|
||||
return;
|
||||
}
|
||||
limitAlteredHeights(cellCoordinates);
|
||||
}
|
||||
}
|
||||
|
||||
@ -590,8 +567,8 @@ void CSVRender::TerrainShapeMode::setFlattenToolTargetHeight(const WorldspaceHit
|
||||
mTargetHeight = landShapePointer[inCellY * ESM::Land::LAND_SIZE + inCellX];
|
||||
}
|
||||
|
||||
void CSVRender::TerrainShapeMode::alterHeight(
|
||||
const CSMWorld::CellCoordinates& cellCoords, int inCellX, int inCellY, float alteredHeight, bool useTool)
|
||||
void CSVRender::TerrainShapeMode::alterHeight(const CSMWorld::CellCoordinates& cellCoords, int inCellX, int inCellY,
|
||||
float alteredHeight, bool useTool, bool useAndAlterAdjacentCell)
|
||||
{
|
||||
std::string cellId = CSMWorld::CellCoordinates::generateId(cellCoords.getX(), cellCoords.getY());
|
||||
|
||||
@ -629,113 +606,131 @@ void CSVRender::TerrainShapeMode::alterHeight(
|
||||
alteredHeight = *paged->getCellAlteredHeight(cellCoords, inCellX, inCellY) + alteredHeight;
|
||||
}
|
||||
|
||||
if (inCellX != 0 && inCellY != 0 && inCellX != ESM::Land::LAND_SIZE - 1 && inCellY != ESM::Land::LAND_SIZE - 1)
|
||||
if ((inCellX != 0 && inCellY != 0 && inCellX != ESM::Land::LAND_SIZE - 1 && inCellY != ESM::Land::LAND_SIZE - 1)
|
||||
|| !useAndAlterAdjacentCell)
|
||||
paged->setCellAlteredHeight(cellCoords, inCellX, inCellY, alteredHeight);
|
||||
else
|
||||
{
|
||||
std::optional<float> originalHeight = paged->getCellOriginalHeight(cellCoords, inCellX, inCellY);
|
||||
if (originalHeight)
|
||||
{
|
||||
float absoluteHeight = *originalHeight + alteredHeight;
|
||||
// Change values of cornering cells
|
||||
if ((inCellX == 0 && inCellY == 0) && (useTool || isLandLoaded(cellUpLeftId)))
|
||||
{
|
||||
if (allowLandShapeEditing(cellUpLeftId, useTool) && allowLandShapeEditing(cellLeftId, useTool)
|
||||
&& allowLandShapeEditing(cellUpId, useTool))
|
||||
{
|
||||
CSMWorld::CellCoordinates cornerCellCoords = cellCoords.move(-1, -1);
|
||||
if (useTool
|
||||
&& std::find(mAlteredCells.begin(), mAlteredCells.end(), cornerCellCoords)
|
||||
== mAlteredCells.end())
|
||||
mAlteredCells.emplace_back(cornerCellCoords);
|
||||
paged->setCellAlteredAbsoluteHeight(
|
||||
cornerCellCoords, ESM::Land::LAND_SIZE - 1, ESM::Land::LAND_SIZE - 1, absoluteHeight);
|
||||
}
|
||||
else
|
||||
return;
|
||||
}
|
||||
else if ((inCellX == 0 && inCellY == ESM::Land::LAND_SIZE - 1) && (useTool || isLandLoaded(cellDownLeftId)))
|
||||
{
|
||||
if (allowLandShapeEditing(cellDownLeftId, useTool) && allowLandShapeEditing(cellLeftId, useTool)
|
||||
&& allowLandShapeEditing(cellDownId, useTool))
|
||||
{
|
||||
CSMWorld::CellCoordinates cornerCellCoords = cellCoords.move(-1, 1);
|
||||
if (useTool
|
||||
&& std::find(mAlteredCells.begin(), mAlteredCells.end(), cornerCellCoords)
|
||||
== mAlteredCells.end())
|
||||
mAlteredCells.emplace_back(cornerCellCoords);
|
||||
paged->setCellAlteredAbsoluteHeight(cornerCellCoords, ESM::Land::LAND_SIZE - 1, 0, absoluteHeight);
|
||||
}
|
||||
else
|
||||
return;
|
||||
}
|
||||
else if ((inCellX == ESM::Land::LAND_SIZE - 1 && inCellY == 0) && (useTool || isLandLoaded(cellUpRightId)))
|
||||
{
|
||||
if (allowLandShapeEditing(cellUpRightId, useTool) && allowLandShapeEditing(cellRightId, useTool)
|
||||
&& allowLandShapeEditing(cellUpId, useTool))
|
||||
{
|
||||
CSMWorld::CellCoordinates cornerCellCoords = cellCoords.move(1, -1);
|
||||
if (useTool
|
||||
&& std::find(mAlteredCells.begin(), mAlteredCells.end(), cornerCellCoords)
|
||||
== mAlteredCells.end())
|
||||
mAlteredCells.emplace_back(cornerCellCoords);
|
||||
paged->setCellAlteredAbsoluteHeight(cornerCellCoords, 0, ESM::Land::LAND_SIZE - 1, absoluteHeight);
|
||||
}
|
||||
else
|
||||
return;
|
||||
}
|
||||
else if ((inCellX == ESM::Land::LAND_SIZE - 1 && inCellY == ESM::Land::LAND_SIZE - 1)
|
||||
&& (useTool || isLandLoaded(cellDownRightId)))
|
||||
{
|
||||
if (allowLandShapeEditing(cellDownRightId, useTool) && allowLandShapeEditing(cellRightId, useTool)
|
||||
&& allowLandShapeEditing(cellDownId, useTool))
|
||||
{
|
||||
CSMWorld::CellCoordinates cornerCellCoords = cellCoords.move(1, 1);
|
||||
if (useTool
|
||||
&& std::find(mAlteredCells.begin(), mAlteredCells.end(), cornerCellCoords)
|
||||
== mAlteredCells.end())
|
||||
mAlteredCells.emplace_back(cornerCellCoords);
|
||||
paged->setCellAlteredAbsoluteHeight(cornerCellCoords, 0, 0, absoluteHeight);
|
||||
}
|
||||
else
|
||||
return;
|
||||
}
|
||||
|
||||
// Change values of cornering cells
|
||||
if ((inCellX == 0 && inCellY == 0) && (useTool || isLandLoaded(cellUpLeftId)))
|
||||
{
|
||||
if (allowLandShapeEditing(cellUpLeftId, useTool) && allowLandShapeEditing(cellLeftId, useTool)
|
||||
&& allowLandShapeEditing(cellUpId, useTool))
|
||||
{
|
||||
CSMWorld::CellCoordinates cornerCellCoords = cellCoords.move(-1, -1);
|
||||
if (useTool
|
||||
&& std::find(mAlteredCells.begin(), mAlteredCells.end(), cornerCellCoords) == mAlteredCells.end())
|
||||
mAlteredCells.emplace_back(cornerCellCoords);
|
||||
paged->setCellAlteredHeight(
|
||||
cornerCellCoords, ESM::Land::LAND_SIZE - 1, ESM::Land::LAND_SIZE - 1, alteredHeight);
|
||||
}
|
||||
else
|
||||
return;
|
||||
}
|
||||
else if ((inCellX == 0 && inCellY == ESM::Land::LAND_SIZE - 1) && (useTool || isLandLoaded(cellDownLeftId)))
|
||||
{
|
||||
if (allowLandShapeEditing(cellDownLeftId, useTool) && allowLandShapeEditing(cellLeftId, useTool)
|
||||
&& allowLandShapeEditing(cellDownId, useTool))
|
||||
{
|
||||
CSMWorld::CellCoordinates cornerCellCoords = cellCoords.move(-1, 1);
|
||||
if (useTool
|
||||
&& std::find(mAlteredCells.begin(), mAlteredCells.end(), cornerCellCoords) == mAlteredCells.end())
|
||||
mAlteredCells.emplace_back(cornerCellCoords);
|
||||
paged->setCellAlteredHeight(cornerCellCoords, ESM::Land::LAND_SIZE - 1, 0, alteredHeight);
|
||||
}
|
||||
else
|
||||
return;
|
||||
}
|
||||
else if ((inCellX == ESM::Land::LAND_SIZE - 1 && inCellY == 0) && (useTool || isLandLoaded(cellUpRightId)))
|
||||
{
|
||||
if (allowLandShapeEditing(cellUpRightId, useTool) && allowLandShapeEditing(cellRightId, useTool)
|
||||
&& allowLandShapeEditing(cellUpId, useTool))
|
||||
{
|
||||
CSMWorld::CellCoordinates cornerCellCoords = cellCoords.move(1, -1);
|
||||
if (useTool
|
||||
&& std::find(mAlteredCells.begin(), mAlteredCells.end(), cornerCellCoords) == mAlteredCells.end())
|
||||
mAlteredCells.emplace_back(cornerCellCoords);
|
||||
paged->setCellAlteredHeight(cornerCellCoords, 0, ESM::Land::LAND_SIZE - 1, alteredHeight);
|
||||
}
|
||||
else
|
||||
return;
|
||||
}
|
||||
else if ((inCellX == ESM::Land::LAND_SIZE - 1 && inCellY == ESM::Land::LAND_SIZE - 1)
|
||||
&& (useTool || isLandLoaded(cellDownRightId)))
|
||||
{
|
||||
if (allowLandShapeEditing(cellDownRightId, useTool) && allowLandShapeEditing(cellRightId, useTool)
|
||||
&& allowLandShapeEditing(cellDownId, useTool))
|
||||
{
|
||||
CSMWorld::CellCoordinates cornerCellCoords = cellCoords.move(1, 1);
|
||||
if (useTool
|
||||
&& std::find(mAlteredCells.begin(), mAlteredCells.end(), cornerCellCoords) == mAlteredCells.end())
|
||||
mAlteredCells.emplace_back(cornerCellCoords);
|
||||
paged->setCellAlteredHeight(cornerCellCoords, 0, 0, alteredHeight);
|
||||
}
|
||||
else
|
||||
return;
|
||||
}
|
||||
// Change values of edging cells
|
||||
if ((inCellX == 0) && (useTool || isLandLoaded(cellLeftId)))
|
||||
{
|
||||
if (allowLandShapeEditing(cellLeftId, useTool))
|
||||
{
|
||||
CSMWorld::CellCoordinates edgeCellCoords = cellCoords.move(-1, 0);
|
||||
if (useTool
|
||||
&& std::find(mAlteredCells.begin(), mAlteredCells.end(), edgeCellCoords) == mAlteredCells.end())
|
||||
mAlteredCells.emplace_back(edgeCellCoords);
|
||||
paged->setCellAlteredHeight(cellCoords, inCellX, inCellY, alteredHeight);
|
||||
paged->setCellAlteredAbsoluteHeight(
|
||||
edgeCellCoords, ESM::Land::LAND_SIZE - 1, inCellY, absoluteHeight);
|
||||
}
|
||||
}
|
||||
if ((inCellY == 0) && (useTool || isLandLoaded(cellUpId)))
|
||||
{
|
||||
if (allowLandShapeEditing(cellUpId, useTool))
|
||||
{
|
||||
CSMWorld::CellCoordinates edgeCellCoords = cellCoords.move(0, -1);
|
||||
if (useTool
|
||||
&& std::find(mAlteredCells.begin(), mAlteredCells.end(), edgeCellCoords) == mAlteredCells.end())
|
||||
mAlteredCells.emplace_back(edgeCellCoords);
|
||||
paged->setCellAlteredHeight(cellCoords, inCellX, inCellY, alteredHeight);
|
||||
paged->setCellAlteredAbsoluteHeight(
|
||||
edgeCellCoords, inCellX, ESM::Land::LAND_SIZE - 1, absoluteHeight);
|
||||
}
|
||||
}
|
||||
|
||||
// Change values of edging cells
|
||||
if ((inCellX == 0) && (useTool || isLandLoaded(cellLeftId)))
|
||||
{
|
||||
if (allowLandShapeEditing(cellLeftId, useTool))
|
||||
{
|
||||
CSMWorld::CellCoordinates edgeCellCoords = cellCoords.move(-1, 0);
|
||||
if (useTool && std::find(mAlteredCells.begin(), mAlteredCells.end(), edgeCellCoords) == mAlteredCells.end())
|
||||
mAlteredCells.emplace_back(edgeCellCoords);
|
||||
paged->setCellAlteredHeight(cellCoords, inCellX, inCellY, alteredHeight);
|
||||
paged->setCellAlteredHeight(edgeCellCoords, ESM::Land::LAND_SIZE - 1, inCellY, alteredHeight);
|
||||
}
|
||||
}
|
||||
if ((inCellY == 0) && (useTool || isLandLoaded(cellUpId)))
|
||||
{
|
||||
if (allowLandShapeEditing(cellUpId, useTool))
|
||||
{
|
||||
CSMWorld::CellCoordinates edgeCellCoords = cellCoords.move(0, -1);
|
||||
if (useTool && std::find(mAlteredCells.begin(), mAlteredCells.end(), edgeCellCoords) == mAlteredCells.end())
|
||||
mAlteredCells.emplace_back(edgeCellCoords);
|
||||
paged->setCellAlteredHeight(cellCoords, inCellX, inCellY, alteredHeight);
|
||||
paged->setCellAlteredHeight(edgeCellCoords, inCellX, ESM::Land::LAND_SIZE - 1, alteredHeight);
|
||||
}
|
||||
}
|
||||
|
||||
if ((inCellX == ESM::Land::LAND_SIZE - 1) && (useTool || isLandLoaded(cellRightId)))
|
||||
{
|
||||
if (allowLandShapeEditing(cellRightId, useTool))
|
||||
{
|
||||
CSMWorld::CellCoordinates edgeCellCoords = cellCoords.move(1, 0);
|
||||
if (useTool && std::find(mAlteredCells.begin(), mAlteredCells.end(), edgeCellCoords) == mAlteredCells.end())
|
||||
mAlteredCells.emplace_back(edgeCellCoords);
|
||||
paged->setCellAlteredHeight(cellCoords, inCellX, inCellY, alteredHeight);
|
||||
paged->setCellAlteredHeight(edgeCellCoords, 0, inCellY, alteredHeight);
|
||||
}
|
||||
}
|
||||
if ((inCellY == ESM::Land::LAND_SIZE - 1) && (useTool || isLandLoaded(cellDownId)))
|
||||
{
|
||||
if (allowLandShapeEditing(cellDownId, useTool))
|
||||
{
|
||||
CSMWorld::CellCoordinates edgeCellCoords = cellCoords.move(0, 1);
|
||||
if (useTool && std::find(mAlteredCells.begin(), mAlteredCells.end(), edgeCellCoords) == mAlteredCells.end())
|
||||
mAlteredCells.emplace_back(edgeCellCoords);
|
||||
paged->setCellAlteredHeight(cellCoords, inCellX, inCellY, alteredHeight);
|
||||
paged->setCellAlteredHeight(edgeCellCoords, inCellX, 0, alteredHeight);
|
||||
if ((inCellX == ESM::Land::LAND_SIZE - 1) && (useTool || isLandLoaded(cellRightId)))
|
||||
{
|
||||
if (allowLandShapeEditing(cellRightId, useTool))
|
||||
{
|
||||
CSMWorld::CellCoordinates edgeCellCoords = cellCoords.move(1, 0);
|
||||
if (useTool
|
||||
&& std::find(mAlteredCells.begin(), mAlteredCells.end(), edgeCellCoords) == mAlteredCells.end())
|
||||
mAlteredCells.emplace_back(edgeCellCoords);
|
||||
paged->setCellAlteredHeight(cellCoords, inCellX, inCellY, alteredHeight);
|
||||
paged->setCellAlteredAbsoluteHeight(edgeCellCoords, 0, inCellY, absoluteHeight);
|
||||
}
|
||||
}
|
||||
if ((inCellY == ESM::Land::LAND_SIZE - 1) && (useTool || isLandLoaded(cellDownId)))
|
||||
{
|
||||
if (allowLandShapeEditing(cellDownId, useTool))
|
||||
{
|
||||
CSMWorld::CellCoordinates edgeCellCoords = cellCoords.move(0, 1);
|
||||
if (useTool
|
||||
&& std::find(mAlteredCells.begin(), mAlteredCells.end(), edgeCellCoords) == mAlteredCells.end())
|
||||
mAlteredCells.emplace_back(edgeCellCoords);
|
||||
paged->setCellAlteredHeight(cellCoords, inCellX, inCellY, alteredHeight);
|
||||
paged->setCellAlteredAbsoluteHeight(edgeCellCoords, inCellX, 0, absoluteHeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -966,70 +961,6 @@ void CSVRender::TerrainShapeMode::updateKeyHeightValues(const CSMWorld::CellCoor
|
||||
*rightHeight = *thisHeight;
|
||||
*downHeight = *thisHeight;
|
||||
|
||||
// If at edge, get values from neighboring cell
|
||||
if (inCellX == 0)
|
||||
{
|
||||
if (isLandLoaded(cellLeftId))
|
||||
{
|
||||
const CSMWorld::LandHeightsColumn::DataType landLeftShapePointer
|
||||
= landTable.data(landTable.getModelIndex(cellLeftId, landshapeColumn))
|
||||
.value<CSMWorld::LandHeightsColumn::DataType>();
|
||||
*leftHeight = landLeftShapePointer[inCellY * ESM::Land::LAND_SIZE + (ESM::Land::LAND_SIZE - 2)];
|
||||
if (paged->getCellAlteredHeight(cellCoords.move(-1, 0), ESM::Land::LAND_SIZE - 2, inCellY))
|
||||
{
|
||||
*leftAlteredHeight
|
||||
= *paged->getCellAlteredHeight(cellCoords.move(-1, 0), ESM::Land::LAND_SIZE - 2, inCellY);
|
||||
*leftHeight += *leftAlteredHeight;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (inCellY == 0)
|
||||
{
|
||||
if (isLandLoaded(cellUpId))
|
||||
{
|
||||
const CSMWorld::LandHeightsColumn::DataType landUpShapePointer
|
||||
= landTable.data(landTable.getModelIndex(cellUpId, landshapeColumn))
|
||||
.value<CSMWorld::LandHeightsColumn::DataType>();
|
||||
*upHeight = landUpShapePointer[(ESM::Land::LAND_SIZE - 2) * ESM::Land::LAND_SIZE + inCellX];
|
||||
if (paged->getCellAlteredHeight(cellCoords.move(0, -1), inCellX, ESM::Land::LAND_SIZE - 2))
|
||||
{
|
||||
*upAlteredHeight
|
||||
= *paged->getCellAlteredHeight(cellCoords.move(0, -1), inCellX, ESM::Land::LAND_SIZE - 2);
|
||||
*upHeight += *upAlteredHeight;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (inCellX == ESM::Land::LAND_SIZE - 1)
|
||||
{
|
||||
if (isLandLoaded(cellRightId))
|
||||
{
|
||||
const CSMWorld::LandHeightsColumn::DataType landRightShapePointer
|
||||
= landTable.data(landTable.getModelIndex(cellRightId, landshapeColumn))
|
||||
.value<CSMWorld::LandHeightsColumn::DataType>();
|
||||
*rightHeight = landRightShapePointer[inCellY * ESM::Land::LAND_SIZE + 1];
|
||||
if (paged->getCellAlteredHeight(cellCoords.move(1, 0), 1, inCellY))
|
||||
{
|
||||
*rightAlteredHeight = *paged->getCellAlteredHeight(cellCoords.move(1, 0), 1, inCellY);
|
||||
*rightHeight += *rightAlteredHeight;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (inCellY == ESM::Land::LAND_SIZE - 1)
|
||||
{
|
||||
if (isLandLoaded(cellDownId))
|
||||
{
|
||||
const CSMWorld::LandHeightsColumn::DataType landDownShapePointer
|
||||
= landTable.data(landTable.getModelIndex(cellDownId, landshapeColumn))
|
||||
.value<CSMWorld::LandHeightsColumn::DataType>();
|
||||
*downHeight = landDownShapePointer[ESM::Land::LAND_SIZE + inCellX];
|
||||
if (paged->getCellAlteredHeight(cellCoords.move(0, 1), inCellX, 1))
|
||||
{
|
||||
*downAlteredHeight = *paged->getCellAlteredHeight(cellCoords.move(0, 1), inCellX, 1);
|
||||
*downHeight += *downAlteredHeight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If not at edge, get values from the same cell
|
||||
if (inCellX != 0)
|
||||
{
|
||||
@ -1063,38 +994,7 @@ void CSVRender::TerrainShapeMode::updateKeyHeightValues(const CSMWorld::CellCoor
|
||||
}
|
||||
}
|
||||
|
||||
void CSVRender::TerrainShapeMode::compareAndLimit(const CSMWorld::CellCoordinates& cellCoords, int inCellX, int inCellY,
|
||||
float* limitedAlteredHeightXAxis, float* limitedAlteredHeightYAxis, bool* steepnessIsWithinLimits)
|
||||
{
|
||||
if (limitedAlteredHeightXAxis)
|
||||
{
|
||||
if (limitedAlteredHeightYAxis)
|
||||
{
|
||||
if (std::abs(*limitedAlteredHeightXAxis) >= std::abs(*limitedAlteredHeightYAxis))
|
||||
{
|
||||
alterHeight(cellCoords, inCellX, inCellY, *limitedAlteredHeightXAxis, false);
|
||||
*steepnessIsWithinLimits = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
alterHeight(cellCoords, inCellX, inCellY, *limitedAlteredHeightYAxis, false);
|
||||
*steepnessIsWithinLimits = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
alterHeight(cellCoords, inCellX, inCellY, *limitedAlteredHeightXAxis, false);
|
||||
*steepnessIsWithinLimits = false;
|
||||
}
|
||||
}
|
||||
else if (limitedAlteredHeightYAxis)
|
||||
{
|
||||
alterHeight(cellCoords, inCellX, inCellY, *limitedAlteredHeightYAxis, false);
|
||||
*steepnessIsWithinLimits = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool CSVRender::TerrainShapeMode::limitAlteredHeights(const CSMWorld::CellCoordinates& cellCoords, bool reverseMode)
|
||||
void CSVRender::TerrainShapeMode::limitAlteredHeights(const CSMWorld::CellCoordinates& cellCoords)
|
||||
{
|
||||
CSMDoc::Document& document = getWorldspaceWidget().getDocument();
|
||||
CSMWorld::IdTable& landTable
|
||||
@ -1104,7 +1004,6 @@ bool CSVRender::TerrainShapeMode::limitAlteredHeights(const CSMWorld::CellCoordi
|
||||
std::string cellId = CSMWorld::CellCoordinates::generateId(cellCoords.getX(), cellCoords.getY());
|
||||
|
||||
int limitHeightChange = 1016.0f; // Limited by save format
|
||||
bool steepnessIsWithinLimits = true;
|
||||
|
||||
if (isLandLoaded(cellId))
|
||||
{
|
||||
@ -1123,27 +1022,18 @@ bool CSVRender::TerrainShapeMode::limitAlteredHeights(const CSMWorld::CellCoordi
|
||||
float downHeight = 0.0f;
|
||||
float downAlteredHeight = 0.0f;
|
||||
|
||||
if (!reverseMode)
|
||||
for (int inCellY = 0; inCellY < ESM::Land::LAND_SIZE; ++inCellY)
|
||||
{
|
||||
for (int inCellY = 0; inCellY < ESM::Land::LAND_SIZE; ++inCellY)
|
||||
for (int inCellX = 0; inCellX < ESM::Land::LAND_SIZE; ++inCellX)
|
||||
{
|
||||
for (int inCellX = 0; inCellX < ESM::Land::LAND_SIZE; ++inCellX)
|
||||
updateKeyHeightValues(cellCoords, inCellX, inCellY, &thisHeight, &thisAlteredHeight, &leftHeight,
|
||||
&leftAlteredHeight, &upHeight, &upAlteredHeight, &rightHeight, &rightAlteredHeight, &downHeight,
|
||||
&downAlteredHeight);
|
||||
|
||||
if (inCellX == 0)
|
||||
{
|
||||
std::unique_ptr<float> limitedAlteredHeightXAxis(nullptr);
|
||||
std::unique_ptr<float> limitedAlteredHeightYAxis(nullptr);
|
||||
updateKeyHeightValues(cellCoords, inCellX, inCellY, &thisHeight, &thisAlteredHeight, &leftHeight,
|
||||
&leftAlteredHeight, &upHeight, &upAlteredHeight, &rightHeight, &rightAlteredHeight, &downHeight,
|
||||
&downAlteredHeight);
|
||||
|
||||
// Check for height limits on x-axis
|
||||
if (leftHeight - thisHeight > limitHeightChange)
|
||||
limitedAlteredHeightXAxis = std::make_unique<float>(
|
||||
leftHeight - limitHeightChange - (thisHeight - thisAlteredHeight));
|
||||
else if (leftHeight - thisHeight < -limitHeightChange)
|
||||
limitedAlteredHeightXAxis = std::make_unique<float>(
|
||||
leftHeight + limitHeightChange - (thisHeight - thisAlteredHeight));
|
||||
|
||||
// Check for height limits on y-axis
|
||||
std::unique_ptr<float> limitedAlteredHeightYAxis(nullptr);
|
||||
if (upHeight - thisHeight > limitHeightChange)
|
||||
limitedAlteredHeightYAxis
|
||||
= std::make_unique<float>(upHeight - limitHeightChange - (thisHeight - thisAlteredHeight));
|
||||
@ -1151,49 +1041,26 @@ bool CSVRender::TerrainShapeMode::limitAlteredHeights(const CSMWorld::CellCoordi
|
||||
limitedAlteredHeightYAxis
|
||||
= std::make_unique<float>(upHeight + limitHeightChange - (thisHeight - thisAlteredHeight));
|
||||
|
||||
// Limit altered height value based on x or y, whichever is the smallest
|
||||
compareAndLimit(cellCoords, inCellX, inCellY, limitedAlteredHeightXAxis.get(),
|
||||
limitedAlteredHeightYAxis.get(), &steepnessIsWithinLimits);
|
||||
if (limitedAlteredHeightYAxis)
|
||||
alterHeight(cellCoords, inCellX, inCellY, *limitedAlteredHeightYAxis, false, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (reverseMode)
|
||||
{
|
||||
for (int inCellY = ESM::Land::LAND_SIZE - 1; inCellY >= 0; --inCellY)
|
||||
{
|
||||
for (int inCellX = ESM::Land::LAND_SIZE - 1; inCellX >= 0; --inCellX)
|
||||
else
|
||||
{
|
||||
std::unique_ptr<float> limitedAlteredHeightXAxis(nullptr);
|
||||
std::unique_ptr<float> limitedAlteredHeightYAxis(nullptr);
|
||||
updateKeyHeightValues(cellCoords, inCellX, inCellY, &thisHeight, &thisAlteredHeight, &leftHeight,
|
||||
&leftAlteredHeight, &upHeight, &upAlteredHeight, &rightHeight, &rightAlteredHeight, &downHeight,
|
||||
&downAlteredHeight);
|
||||
|
||||
// Check for height limits on x-axis
|
||||
if (rightHeight - thisHeight > limitHeightChange)
|
||||
std::unique_ptr<float> limitedAlteredHeightXAxis(nullptr);
|
||||
if (leftHeight - thisHeight > limitHeightChange)
|
||||
limitedAlteredHeightXAxis = std::make_unique<float>(
|
||||
rightHeight - limitHeightChange - (thisHeight - thisAlteredHeight));
|
||||
else if (rightHeight - thisHeight < -limitHeightChange)
|
||||
leftHeight - limitHeightChange - (thisHeight - thisAlteredHeight));
|
||||
else if (leftHeight - thisHeight < -limitHeightChange)
|
||||
limitedAlteredHeightXAxis = std::make_unique<float>(
|
||||
rightHeight + limitHeightChange - (thisHeight - thisAlteredHeight));
|
||||
leftHeight + limitHeightChange - (thisHeight - thisAlteredHeight));
|
||||
|
||||
// Check for height limits on y-axis
|
||||
if (downHeight - thisHeight > limitHeightChange)
|
||||
limitedAlteredHeightYAxis = std::make_unique<float>(
|
||||
downHeight - limitHeightChange - (thisHeight - thisAlteredHeight));
|
||||
else if (downHeight - thisHeight < -limitHeightChange)
|
||||
limitedAlteredHeightYAxis = std::make_unique<float>(
|
||||
downHeight + limitHeightChange - (thisHeight - thisAlteredHeight));
|
||||
|
||||
// Limit altered height value based on x or y, whichever is the smallest
|
||||
compareAndLimit(cellCoords, inCellX, inCellY, limitedAlteredHeightXAxis.get(),
|
||||
limitedAlteredHeightYAxis.get(), &steepnessIsWithinLimits);
|
||||
if (limitedAlteredHeightXAxis)
|
||||
alterHeight(cellCoords, inCellX, inCellY, *limitedAlteredHeightXAxis, false, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return steepnessIsWithinLimits;
|
||||
}
|
||||
|
||||
bool CSVRender::TerrainShapeMode::isInCellSelection(int globalSelectionX, int globalSelectionY)
|
||||
|
@ -137,7 +137,7 @@ namespace CSVRender
|
||||
|
||||
/// Do a single height alteration for transient shape edit map
|
||||
void alterHeight(const CSMWorld::CellCoordinates& cellCoords, int inCellX, int inCellY, float alteredHeight,
|
||||
bool useTool = true);
|
||||
bool useTool = true, bool useAndAlterAdjacentCell = true);
|
||||
|
||||
/// Do a single smoothing height alteration for transient shape edit map
|
||||
void smoothHeight(const CSMWorld::CellCoordinates& cellCoords, int inCellX, int inCellY, int toolStrength);
|
||||
@ -149,19 +149,15 @@ namespace CSVRender
|
||||
/// Do a single equalize alteration for transient shape edit map
|
||||
void equalizeHeight(const CSMWorld::CellCoordinates& cellCoords, int inCellX, int inCellY, int targetHeight);
|
||||
|
||||
/// Get altered height values around one vertex
|
||||
/// Get altered height values around one vertex. Default to value of this height for height out of this cell,
|
||||
/// with 0 for altered height.
|
||||
void updateKeyHeightValues(const CSMWorld::CellCoordinates& cellCoords, int inCellX, int inCellY,
|
||||
float* thisHeight, float* thisAlteredHeight, float* leftHeight, float* leftAlteredHeight, float* upHeight,
|
||||
float* upAlteredHeight, float* rightHeight, float* rightAlteredHeight, float* downHeight,
|
||||
float* downAlteredHeight);
|
||||
|
||||
/// Limit steepness based on either X or Y and return false if steepness is limited
|
||||
void compareAndLimit(const CSMWorld::CellCoordinates& cellCoords, int inCellX, int inCellY,
|
||||
float* limitedAlteredHeightXAxis, float* limitedAlteredHeightYAxis, bool* steepnessIsWithinLimits);
|
||||
|
||||
/// Check that the edit doesn't break save format limits, fix if necessary, return true if slope steepness is
|
||||
/// within limits
|
||||
bool limitAlteredHeights(const CSMWorld::CellCoordinates& cellCoords, bool reverseMode = false);
|
||||
/// Check that the edit doesn't break save format limits, fix if necessary
|
||||
void limitAlteredHeights(const CSMWorld::CellCoordinates& cellCoords);
|
||||
|
||||
/// Check if global selection coordinate belongs to cell in view
|
||||
bool isInCellSelection(int globalSelectionX, int globalSelectionY);
|
||||
|
@ -59,16 +59,21 @@ namespace CSVRender
|
||||
|
||||
float TerrainStorage::getSumOfAlteredAndTrueHeight(int cellX, int cellY, int inCellX, int inCellY)
|
||||
{
|
||||
float height = 0.f;
|
||||
std::optional<float> true_height = getOriginalHeight(cellX, cellY, inCellX, inCellY);
|
||||
if (true_height)
|
||||
return *true_height + *getAlteredHeight(inCellX, inCellY);
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
std::optional<float> TerrainStorage::getOriginalHeight(int cellX, int cellY, int inCellX, int inCellY)
|
||||
{
|
||||
const int index
|
||||
= mData.getLand().searchId(ESM::RefId::stringRefId(CSMWorld::Land::createUniqueRecordId(cellX, cellY)));
|
||||
if (index == -1) // no land!
|
||||
return height;
|
||||
return {};
|
||||
|
||||
const ESM::Land::LandData* landData = mData.getLand().getRecord(index).get().getLandData(ESM::Land::DATA_VHGT);
|
||||
height = landData->mHeights[inCellY * ESM::Land::LAND_SIZE + inCellX];
|
||||
return mAlteredHeight[inCellY * ESM::Land::LAND_SIZE + inCellX] + height;
|
||||
return landData->mHeights[inCellY * ESM::Land::LAND_SIZE + inCellX];
|
||||
}
|
||||
|
||||
float* TerrainStorage::getAlteredHeight(int inCellX, int inCellY)
|
||||
@ -102,14 +107,14 @@ namespace CSVRender
|
||||
|
||||
int TerrainStorage::getUpHeight(int col, int row, std::span<const float> heightData) const
|
||||
{
|
||||
return heightData[(col - 1) * ESM::Land::LAND_SIZE + row]
|
||||
+ mAlteredHeight[static_cast<unsigned int>((col - 1) * ESM::Land::LAND_SIZE + row)];
|
||||
return heightData[(col + 1) * ESM::Land::LAND_SIZE + row]
|
||||
+ mAlteredHeight[static_cast<unsigned int>((col + 1) * ESM::Land::LAND_SIZE + row)];
|
||||
}
|
||||
|
||||
int TerrainStorage::getDownHeight(int col, int row, std::span<const float> heightData) const
|
||||
{
|
||||
return heightData[(col + 1) * ESM::Land::LAND_SIZE + row]
|
||||
+ mAlteredHeight[static_cast<unsigned int>((col + 1) * ESM::Land::LAND_SIZE + row)];
|
||||
return heightData[(col - 1) * ESM::Land::LAND_SIZE + row]
|
||||
+ mAlteredHeight[static_cast<unsigned int>((col - 1) * ESM::Land::LAND_SIZE + row)];
|
||||
}
|
||||
|
||||
int TerrainStorage::getHeightDifferenceToLeft(int col, int row, std::span<const float> heightData) const
|
||||
@ -132,29 +137,19 @@ namespace CSVRender
|
||||
return abs(getThisHeight(col, row, heightData) - getDownHeight(col, row, heightData));
|
||||
}
|
||||
|
||||
bool TerrainStorage::leftOrUpIsOverTheLimit(
|
||||
int col, int row, int heightWarningLimit, std::span<const float> heightData) const
|
||||
{
|
||||
return getHeightDifferenceToLeft(col, row, heightData) >= heightWarningLimit
|
||||
|| getHeightDifferenceToUp(col, row, heightData) >= heightWarningLimit;
|
||||
}
|
||||
|
||||
bool TerrainStorage::rightOrDownIsOverTheLimit(
|
||||
int col, int row, int heightWarningLimit, std::span<const float> heightData) const
|
||||
{
|
||||
return getHeightDifferenceToRight(col, row, heightData) >= heightWarningLimit
|
||||
|| getHeightDifferenceToDown(col, row, heightData) >= heightWarningLimit;
|
||||
}
|
||||
|
||||
void TerrainStorage::adjustColor(int col, int row, const ESM::LandData* heightData, osg::Vec4ub& color) const
|
||||
{
|
||||
if (!heightData)
|
||||
return;
|
||||
// Highlight broken height changes
|
||||
int heightWarningLimit = 1024;
|
||||
if (((col > 0 && row > 0) && leftOrUpIsOverTheLimit(col, row, heightWarningLimit, heightData->getHeights()))
|
||||
|| ((col < ESM::Land::LAND_SIZE - 1 && row < ESM::Land::LAND_SIZE - 1)
|
||||
&& rightOrDownIsOverTheLimit(col, row, heightWarningLimit, heightData->getHeights())))
|
||||
if ((row > 0 && (getHeightDifferenceToRight(col, row, heightData->getHeights()) >= heightWarningLimit))
|
||||
|| (row > 0 && row < ESM::Land::LAND_SIZE
|
||||
&& (getHeightDifferenceToLeft(col, row, heightData->getHeights()) >= heightWarningLimit))
|
||||
|| (row == 0 && col > 0
|
||||
&& (getHeightDifferenceToDown(col, row, heightData->getHeights()) >= heightWarningLimit))
|
||||
|| (row == 0 && col < ESM::Land::LAND_SIZE
|
||||
&& (getHeightDifferenceToUp(col, row, heightData->getHeights()) >= heightWarningLimit)))
|
||||
{
|
||||
color.r() = 255;
|
||||
color.g() = 0;
|
||||
|
@ -31,6 +31,7 @@ namespace CSVRender
|
||||
|
||||
bool useAlteration() const override { return true; }
|
||||
float getSumOfAlteredAndTrueHeight(int cellX, int cellY, int inCellX, int inCellY);
|
||||
std::optional<float> getOriginalHeight(int cellX, int cellY, int inCellX, int inCellY);
|
||||
float* getAlteredHeight(int inCellX, int inCellY);
|
||||
|
||||
private:
|
||||
@ -51,9 +52,6 @@ namespace CSVRender
|
||||
int getHeightDifferenceToRight(int col, int row, std::span<const float> heightData) const;
|
||||
int getHeightDifferenceToUp(int col, int row, std::span<const float> heightData) const;
|
||||
int getHeightDifferenceToDown(int col, int row, std::span<const float> heightData) const;
|
||||
bool leftOrUpIsOverTheLimit(int col, int row, int heightWarningLimit, std::span<const float> heightData) const;
|
||||
bool rightOrDownIsOverTheLimit(
|
||||
int col, int row, int heightWarningLimit, std::span<const float> heightData) const;
|
||||
|
||||
void adjustColor(int col, int row, const ESM::LandData* heightData, osg::Vec4ub& color) const override;
|
||||
float getAlteredHeight(int col, int row) const override;
|
||||
|
Loading…
x
Reference in New Issue
Block a user