CS: Make painting terrain height over a cell border equalize the height

at both edge
This commit is contained in:
Marius DAVID 2025-08-27 18:08:54 +02:00
parent 77b08943a7
commit 0f500df183
7 changed files with 148 additions and 96 deletions

View File

@ -371,6 +371,11 @@ float CSVRender::Cell::getSumOfAlteredAndTrueHeight(int cellX, int cellY, int in
return mTerrainStorage->getSumOfAlteredAndTrueHeight(cellX, cellY, inCellX, inCellY); 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) float* CSVRender::Cell::getAlteredHeight(int inCellX, int inCellY)
{ {
return mTerrainStorage->getAlteredHeight(inCellX, inCellY); return mTerrainStorage->getAlteredHeight(inCellX, inCellY);

View File

@ -125,6 +125,8 @@ namespace CSVRender
float getSumOfAlteredAndTrueHeight(int cellX, int cellY, int inCellX, int inCellY); 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); float* getAlteredHeight(int inCellX, int inCellY);
void resetAlteredHeights(); void resetAlteredHeights();

View File

@ -824,6 +824,30 @@ CSVRender::Cell* CSVRender::PagedWorldspaceWidget::getCell(const CSMWorld::CellC
return nullptr; 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( void CSVRender::PagedWorldspaceWidget::setCellAlteredHeight(
const CSMWorld::CellCoordinates& coords, int inCellX, int inCellY, float height) const CSMWorld::CellCoordinates& coords, int inCellX, int inCellY, float height)
{ {

View File

@ -153,6 +153,11 @@ namespace CSVRender
Cell* getCell(const CSMWorld::CellCoordinates& coords) const override; 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); void setCellAlteredHeight(const CSMWorld::CellCoordinates& coords, int inCellX, int inCellY, float height);
float* getCellAlteredHeight(const CSMWorld::CellCoordinates& coords, int inCellX, int inCellY); float* getCellAlteredHeight(const CSMWorld::CellCoordinates& coords, int inCellX, int inCellY);

View File

@ -609,117 +609,127 @@ void CSVRender::TerrainShapeMode::alterHeight(const CSMWorld::CellCoordinates& c
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) || !useAndAlterAdjacentCell)
paged->setCellAlteredHeight(cellCoords, inCellX, inCellY, alteredHeight); paged->setCellAlteredHeight(cellCoords, inCellX, inCellY, alteredHeight);
else
if (useAndAlterAdjacentCell)
{ {
// Change values of cornering cells std::optional<float> originalHeight = paged->getCellOriginalHeight(cellCoords, inCellX, inCellY);
if ((inCellX == 0 && inCellY == 0) && (useTool || isLandLoaded(cellUpLeftId))) if (originalHeight)
{ {
if (allowLandShapeEditing(cellUpLeftId, useTool) && allowLandShapeEditing(cellLeftId, useTool) float absoluteHeight = *originalHeight + alteredHeight;
&& allowLandShapeEditing(cellUpId, useTool)) // Change values of cornering cells
if ((inCellX == 0 && inCellY == 0) && (useTool || isLandLoaded(cellUpLeftId)))
{ {
CSMWorld::CellCoordinates cornerCellCoords = cellCoords.move(-1, -1); if (allowLandShapeEditing(cellUpLeftId, useTool) && allowLandShapeEditing(cellLeftId, useTool)
if (useTool && allowLandShapeEditing(cellUpId, useTool))
&& std::find(mAlteredCells.begin(), mAlteredCells.end(), cornerCellCoords) == mAlteredCells.end()) {
mAlteredCells.emplace_back(cornerCellCoords); CSMWorld::CellCoordinates cornerCellCoords = cellCoords.move(-1, -1);
paged->setCellAlteredHeight( if (useTool
cornerCellCoords, ESM::Land::LAND_SIZE - 1, ESM::Land::LAND_SIZE - 1, alteredHeight); && 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 else if ((inCellX == 0 && inCellY == ESM::Land::LAND_SIZE - 1) && (useTool || isLandLoaded(cellDownLeftId)))
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 (allowLandShapeEditing(cellDownLeftId, useTool) && allowLandShapeEditing(cellLeftId, useTool)
if (useTool && allowLandShapeEditing(cellDownId, useTool))
&& std::find(mAlteredCells.begin(), mAlteredCells.end(), cornerCellCoords) == mAlteredCells.end()) {
mAlteredCells.emplace_back(cornerCellCoords); CSMWorld::CellCoordinates cornerCellCoords = cellCoords.move(-1, 1);
paged->setCellAlteredHeight(cornerCellCoords, ESM::Land::LAND_SIZE - 1, 0, alteredHeight); 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 else if ((inCellX == ESM::Land::LAND_SIZE - 1 && inCellY == 0) && (useTool || isLandLoaded(cellUpRightId)))
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 (allowLandShapeEditing(cellUpRightId, useTool) && allowLandShapeEditing(cellRightId, useTool)
if (useTool && allowLandShapeEditing(cellUpId, useTool))
&& std::find(mAlteredCells.begin(), mAlteredCells.end(), cornerCellCoords) == mAlteredCells.end()) {
mAlteredCells.emplace_back(cornerCellCoords); CSMWorld::CellCoordinates cornerCellCoords = cellCoords.move(1, -1);
paged->setCellAlteredHeight(cornerCellCoords, 0, ESM::Land::LAND_SIZE - 1, alteredHeight); 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 else if ((inCellX == ESM::Land::LAND_SIZE - 1 && inCellY == ESM::Land::LAND_SIZE - 1)
return; && (useTool || isLandLoaded(cellDownRightId)))
}
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 (allowLandShapeEditing(cellDownRightId, useTool) && allowLandShapeEditing(cellRightId, useTool)
if (useTool && allowLandShapeEditing(cellDownId, useTool))
&& std::find(mAlteredCells.begin(), mAlteredCells.end(), cornerCellCoords) == mAlteredCells.end()) {
mAlteredCells.emplace_back(cornerCellCoords); CSMWorld::CellCoordinates cornerCellCoords = cellCoords.move(1, 1);
paged->setCellAlteredHeight(cornerCellCoords, 0, 0, alteredHeight); if (useTool
&& std::find(mAlteredCells.begin(), mAlteredCells.end(), cornerCellCoords)
== mAlteredCells.end())
mAlteredCells.emplace_back(cornerCellCoords);
paged->setCellAlteredAbsoluteHeight(cornerCellCoords, 0, 0, absoluteHeight);
}
else
return;
} }
else
return;
}
// Change values of edging cells // Change values of edging cells
if ((inCellX == 0) && (useTool || isLandLoaded(cellLeftId))) if ((inCellX == 0) && (useTool || isLandLoaded(cellLeftId)))
{
if (allowLandShapeEditing(cellLeftId, useTool))
{ {
CSMWorld::CellCoordinates edgeCellCoords = cellCoords.move(-1, 0); if (allowLandShapeEditing(cellLeftId, useTool))
if (useTool {
&& std::find(mAlteredCells.begin(), mAlteredCells.end(), edgeCellCoords) == mAlteredCells.end()) CSMWorld::CellCoordinates edgeCellCoords = cellCoords.move(-1, 0);
mAlteredCells.emplace_back(edgeCellCoords); if (useTool
paged->setCellAlteredHeight(cellCoords, inCellX, inCellY, alteredHeight); && std::find(mAlteredCells.begin(), mAlteredCells.end(), edgeCellCoords) == mAlteredCells.end())
paged->setCellAlteredHeight(edgeCellCoords, ESM::Land::LAND_SIZE - 1, inCellY, alteredHeight); 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 ((inCellY == 0) && (useTool || isLandLoaded(cellUpId)))
{
if (allowLandShapeEditing(cellUpId, useTool))
{ {
CSMWorld::CellCoordinates edgeCellCoords = cellCoords.move(0, -1); if (allowLandShapeEditing(cellUpId, useTool))
if (useTool {
&& std::find(mAlteredCells.begin(), mAlteredCells.end(), edgeCellCoords) == mAlteredCells.end()) CSMWorld::CellCoordinates edgeCellCoords = cellCoords.move(0, -1);
mAlteredCells.emplace_back(edgeCellCoords); if (useTool
paged->setCellAlteredHeight(cellCoords, inCellX, inCellY, alteredHeight); && std::find(mAlteredCells.begin(), mAlteredCells.end(), edgeCellCoords) == mAlteredCells.end())
paged->setCellAlteredHeight(edgeCellCoords, inCellX, ESM::Land::LAND_SIZE - 1, alteredHeight); mAlteredCells.emplace_back(edgeCellCoords);
paged->setCellAlteredHeight(cellCoords, inCellX, inCellY, alteredHeight);
paged->setCellAlteredAbsoluteHeight(
edgeCellCoords, inCellX, ESM::Land::LAND_SIZE - 1, absoluteHeight);
}
} }
}
if ((inCellX == ESM::Land::LAND_SIZE - 1) && (useTool || isLandLoaded(cellRightId))) if ((inCellX == ESM::Land::LAND_SIZE - 1) && (useTool || isLandLoaded(cellRightId)))
{
if (allowLandShapeEditing(cellRightId, useTool))
{ {
CSMWorld::CellCoordinates edgeCellCoords = cellCoords.move(1, 0); if (allowLandShapeEditing(cellRightId, useTool))
if (useTool {
&& std::find(mAlteredCells.begin(), mAlteredCells.end(), edgeCellCoords) == mAlteredCells.end()) CSMWorld::CellCoordinates edgeCellCoords = cellCoords.move(1, 0);
mAlteredCells.emplace_back(edgeCellCoords); if (useTool
paged->setCellAlteredHeight(cellCoords, inCellX, inCellY, alteredHeight); && std::find(mAlteredCells.begin(), mAlteredCells.end(), edgeCellCoords) == mAlteredCells.end())
paged->setCellAlteredHeight(edgeCellCoords, 0, inCellY, alteredHeight); 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 ((inCellY == ESM::Land::LAND_SIZE - 1) && (useTool || isLandLoaded(cellDownId)))
{
if (allowLandShapeEditing(cellDownId, useTool))
{ {
CSMWorld::CellCoordinates edgeCellCoords = cellCoords.move(0, 1); if (allowLandShapeEditing(cellDownId, useTool))
if (useTool {
&& std::find(mAlteredCells.begin(), mAlteredCells.end(), edgeCellCoords) == mAlteredCells.end()) CSMWorld::CellCoordinates edgeCellCoords = cellCoords.move(0, 1);
mAlteredCells.emplace_back(edgeCellCoords); if (useTool
paged->setCellAlteredHeight(cellCoords, inCellX, inCellY, alteredHeight); && std::find(mAlteredCells.begin(), mAlteredCells.end(), edgeCellCoords) == mAlteredCells.end())
paged->setCellAlteredHeight(edgeCellCoords, inCellX, 0, alteredHeight); mAlteredCells.emplace_back(edgeCellCoords);
paged->setCellAlteredHeight(cellCoords, inCellX, inCellY, alteredHeight);
paged->setCellAlteredAbsoluteHeight(edgeCellCoords, inCellX, 0, absoluteHeight);
}
} }
} }
} }

View File

@ -59,16 +59,21 @@ namespace CSVRender
float TerrainStorage::getSumOfAlteredAndTrueHeight(int cellX, int cellY, int inCellX, int inCellY) 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 const int index
= mData.getLand().searchId(ESM::RefId::stringRefId(CSMWorld::Land::createUniqueRecordId(cellX, cellY))); = mData.getLand().searchId(ESM::RefId::stringRefId(CSMWorld::Land::createUniqueRecordId(cellX, cellY)));
if (index == -1) // no land! if (index == -1) // no land!
return height; return {};
const ESM::Land::LandData* landData = mData.getLand().getRecord(index).get().getLandData(ESM::Land::DATA_VHGT); 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 landData->mHeights[inCellY * ESM::Land::LAND_SIZE + inCellX];
return mAlteredHeight[inCellY * ESM::Land::LAND_SIZE + inCellX] + height;
} }
float* TerrainStorage::getAlteredHeight(int inCellX, int inCellY) float* TerrainStorage::getAlteredHeight(int inCellX, int inCellY)

View File

@ -31,6 +31,7 @@ namespace CSVRender
bool useAlteration() const override { return true; } bool useAlteration() const override { return true; }
float getSumOfAlteredAndTrueHeight(int cellX, int cellY, int inCellX, int inCellY); 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); float* getAlteredHeight(int inCellX, int inCellY);
private: private: