From d186bcb46f96a00524ea0be2c8b8cf54504651fc Mon Sep 17 00:00:00 2001 From: Nelsson Huotari Date: Sun, 3 Nov 2019 13:27:27 +0200 Subject: [PATCH 1/3] Update selection during transient edit, clear to a single function. --- apps/opencs/view/render/terrainselection.hpp | 4 +- apps/opencs/view/render/terrainshapemode.cpp | 46 ++++++++------------ apps/opencs/view/render/terrainshapemode.hpp | 3 ++ 3 files changed, 22 insertions(+), 31 deletions(-) diff --git a/apps/opencs/view/render/terrainselection.hpp b/apps/opencs/view/render/terrainselection.hpp index ba80aeb07..ced6538a7 100644 --- a/apps/opencs/view/render/terrainselection.hpp +++ b/apps/opencs/view/render/terrainselection.hpp @@ -44,10 +44,10 @@ namespace CSVRender std::vector> getTerrainSelection() const; - protected: - void update(); + protected: + void drawShapeSelection(const osg::ref_ptr vertices); void drawTextureSelection(const osg::ref_ptr vertices); diff --git a/apps/opencs/view/render/terrainshapemode.cpp b/apps/opencs/view/render/terrainshapemode.cpp index f4f5322e5..4d456a9af 100644 --- a/apps/opencs/view/render/terrainshapemode.cpp +++ b/apps/opencs/view/render/terrainshapemode.cpp @@ -112,12 +112,7 @@ void CSVRender::TerrainShapeMode::primaryEditPressed(const WorldspaceHitResult& selectTerrainShapes(CSMWorld::CellCoordinates::toVertexCoords(hit.worldPos), 1, true); } } - if (CSVRender::PagedWorldspaceWidget *paged = - dynamic_cast (&getWorldspaceWidget())) - { - paged->resetAllAlteredHeights(); - mTotalDiffY = 0; - } + clearTransientEdits(); } void CSVRender::TerrainShapeMode::primarySelectPressed(const WorldspaceHitResult& hit) @@ -214,28 +209,15 @@ void CSVRender::TerrainShapeMode::dragCompleted(const QPoint& pos) { if (mDragMode == InteractionType_PrimaryEdit) { - if (mIsEditing) - { - mTotalDiffY = 0; - mIsEditing = false; - } - applyTerrainEditChanges(); - - if (CSVRender::PagedWorldspaceWidget *paged = dynamic_cast (&getWorldspaceWidget())) - paged->resetAllAlteredHeights(); + clearTransientEdits(); } } void CSVRender::TerrainShapeMode::dragAborted() { - if (CSVRender::PagedWorldspaceWidget *paged = - dynamic_cast (&getWorldspaceWidget())) - { - paged->resetAllAlteredHeights(); - mTotalDiffY = 0; - } + clearTransientEdits(); } void CSVRender::TerrainShapeMode::dragWheel (int diff, double speedFactor) @@ -266,17 +248,22 @@ void CSVRender::TerrainShapeMode::sortAndLimitAlteredCells() if (passes > 2) { Log(Debug::Warning) << "Warning: User edit exceeds accepted slope steepness. Automatic limiting has failed, edit has been discarded."; - if (CSVRender::PagedWorldspaceWidget *paged = - dynamic_cast (&getWorldspaceWidget())) - { - paged->resetAllAlteredHeights(); - mAlteredCells.clear(); - return; - } + clearTransientEdits(); + return; } } } +void CSVRender::TerrainShapeMode::clearTransientEdits() +{ + mTotalDiffY = 0; + mIsEditing = false; + mAlteredCells.clear(); + if (CSVRender::PagedWorldspaceWidget *paged = dynamic_cast (&getWorldspaceWidget())) + paged->resetAllAlteredHeights(); + mTerrainShapeSelection->update(); +} + void CSVRender::TerrainShapeMode::applyTerrainEditChanges() { CSMDoc::Document& document = getWorldspaceWidget().getDocument(); @@ -385,7 +372,7 @@ void CSVRender::TerrainShapeMode::applyTerrainEditChanges() pushNormalsEditToCommand(landNormalsNew, document, landTable, cellId); } undoStack.endMacro(); - mAlteredCells.clear(); + clearTransientEdits(); } float CSVRender::TerrainShapeMode::calculateBumpShape(float distance, int radius, float height) @@ -498,6 +485,7 @@ void CSVRender::TerrainShapeMode::editTerrainShapeGrid(const std::pair } } } + mTerrainShapeSelection->update(); } void CSVRender::TerrainShapeMode::setFlattenToolTargetHeight(const WorldspaceHitResult& hit) diff --git a/apps/opencs/view/render/terrainshapemode.hpp b/apps/opencs/view/render/terrainshapemode.hpp index 8e2a616c9..00218a63e 100644 --- a/apps/opencs/view/render/terrainshapemode.hpp +++ b/apps/opencs/view/render/terrainshapemode.hpp @@ -95,6 +95,9 @@ namespace CSVRender /// Remove duplicates and sort mAlteredCells, then limitAlteredHeights forward and reverse void sortAndLimitAlteredCells(); + /// Reset everything in the current edit + void clearTransientEdits(); + /// Move pending alteredHeights changes to omwgame/omwaddon -data void applyTerrainEditChanges(); From 9677203215fa4ebf5d8c9abd3bef76bda7c15323 Mon Sep 17 00:00:00 2001 From: Nelsson Huotari Date: Sun, 3 Nov 2019 22:07:04 +0200 Subject: [PATCH 2/3] Don't allow vertex selection outside visible cells --- apps/opencs/view/render/terrainshapemode.cpp | 21 ++++++++++++++++---- apps/opencs/view/render/terrainshapemode.hpp | 3 +++ 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/apps/opencs/view/render/terrainshapemode.cpp b/apps/opencs/view/render/terrainshapemode.cpp index 4d456a9af..af97e4d8f 100644 --- a/apps/opencs/view/render/terrainshapemode.cpp +++ b/apps/opencs/view/render/terrainshapemode.cpp @@ -1027,6 +1027,17 @@ bool CSVRender::TerrainShapeMode::limitAlteredHeights(const CSMWorld::CellCoordi return steepnessIsWithinLimits; } +bool CSVRender::TerrainShapeMode::isInCellSelection(int globalSelectionX, int globalSelectionY) +{ + if (CSVRender::PagedWorldspaceWidget *paged = dynamic_cast (&getWorldspaceWidget())) + { + std::pair vertexCoords = std::make_pair(globalSelectionX, globalSelectionY); + std::string cellId = CSMWorld::CellCoordinates::vertexGlobalToCellId(vertexCoords); + return paged->getCellSelection().has(CSMWorld::CellCoordinates::fromId(cellId).first) && isLandLoaded(cellId); + } + return false; +} + void CSVRender::TerrainShapeMode::selectTerrainShapes(const std::pair& vertexCoords, unsigned char selectMode, bool dragOperation) { int r = mBrushSize / 2; @@ -1034,7 +1045,7 @@ void CSVRender::TerrainShapeMode::selectTerrainShapes(const std::pair& if (mBrushShape == CSVWidget::BrushShape_Point) { - selections.emplace_back(vertexCoords); + if (isInCellSelection(vertexCoords.first, vertexCoords.second)) selections.emplace_back(vertexCoords.first, vertexCoords.second); } if (mBrushShape == CSVWidget::BrushShape_Square) @@ -1043,7 +1054,7 @@ void CSVRender::TerrainShapeMode::selectTerrainShapes(const std::pair& { for(int j = vertexCoords.second - r; j <= vertexCoords.second + r; ++j) { - selections.emplace_back(std::make_pair(i, j)); + if (isInCellSelection(i, j)) selections.emplace_back(i, j); } } } @@ -1057,7 +1068,7 @@ void CSVRender::TerrainShapeMode::selectTerrainShapes(const std::pair& int distanceX = abs(i - vertexCoords.first); int distanceY = abs(j - vertexCoords.second); int distance = std::round(sqrt(pow(distanceX, 2)+pow(distanceY, 2))); - if (distance <= r) selections.emplace_back(std::make_pair(i, j)); + if (isInCellSelection(i, j) && distance <= r) selections.emplace_back(i, j); } } } @@ -1068,7 +1079,9 @@ void CSVRender::TerrainShapeMode::selectTerrainShapes(const std::pair& { for(auto const& value: mCustomBrushShape) { - selections.emplace_back(std::make_pair(vertexCoords.first + value.first, vertexCoords.second + value.second)); + std::pair localVertexCoords (vertexCoords.first + value.first, vertexCoords.second + value.second); + std::string cellId (CSMWorld::CellCoordinates::vertexGlobalToCellId(localVertexCoords)); + if (isInCellSelection(localVertexCoords.first, localVertexCoords.second)) selections.emplace_back(localVertexCoords); } } } diff --git a/apps/opencs/view/render/terrainshapemode.hpp b/apps/opencs/view/render/terrainshapemode.hpp index 00218a63e..605827c9e 100644 --- a/apps/opencs/view/render/terrainshapemode.hpp +++ b/apps/opencs/view/render/terrainshapemode.hpp @@ -131,6 +131,9 @@ namespace CSVRender /// 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 if global selection coordinate belongs to cell in view + bool isInCellSelection(int globalSelectionX, int globalSelectionY); + /// Handle brush mechanics for terrain shape selection void selectTerrainShapes (const std::pair& vertexCoords, unsigned char selectMode, bool dragOperation); From 8f6dc78217de4c1f88c321ddc1b6ec10f84dc54d Mon Sep 17 00:00:00 2001 From: Nelsson Huotari Date: Sun, 3 Nov 2019 23:57:35 +0200 Subject: [PATCH 3/3] Get vertex height from data, if not available in visible cells. --- apps/opencs/view/render/terrainselection.cpp | 42 +++++++++++++++++++- apps/opencs/view/render/terrainselection.hpp | 8 ++++ 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/apps/opencs/view/render/terrainselection.cpp b/apps/opencs/view/render/terrainselection.cpp index 092688da2..e16a69048 100644 --- a/apps/opencs/view/render/terrainselection.cpp +++ b/apps/opencs/view/render/terrainselection.cpp @@ -242,10 +242,37 @@ void CSVRender::TerrainSelection::drawTextureSelection(const osg::ref_ptrgetDocument(); + const CSMWorld::IdCollection& cellCollection = document.getData().getCells(); + return cellCollection.searchId (cellId) == -1; +} + +bool CSVRender::TerrainSelection::noLand(const std::string& cellId) +{ + CSMDoc::Document& document = mWorldspaceWidget->getDocument(); + const CSMWorld::IdCollection& landCollection = document.getData().getLand(); + return landCollection.searchId (cellId) == -1; +} + +bool CSVRender::TerrainSelection::noLandLoaded(const std::string& cellId) +{ + CSMDoc::Document& document = mWorldspaceWidget->getDocument(); + const CSMWorld::IdCollection& landCollection = document.getData().getLand(); + return !landCollection.getRecord(cellId).get().isDataLoaded(ESM::Land::DATA_VNML); +} + +bool CSVRender::TerrainSelection::isLandLoaded(const std::string& cellId) +{ + if (!noCell(cellId) && !noLand(cellId) && !noLandLoaded(cellId)) return true; + return false; +} + int CSVRender::TerrainSelection::calculateLandHeight(int x, int y) // global vertex coordinates { - int cellX = std::floor((1.0f*x / (ESM::Land::LAND_SIZE - 1))); - int cellY = std::floor((1.0f*y / (ESM::Land::LAND_SIZE - 1))); + int cellX = std::floor(static_cast(x) / (ESM::Land::LAND_SIZE - 1)); + int cellY = std::floor(static_cast(y) / (ESM::Land::LAND_SIZE - 1)); int localX = x - cellX * (ESM::Land::LAND_SIZE - 1); int localY = y - cellY * (ESM::Land::LAND_SIZE - 1); @@ -253,7 +280,18 @@ int CSVRender::TerrainSelection::calculateLandHeight(int x, int y) // global ver float landHeight = 0.f; if (CSVRender::Cell* cell = dynamic_cast(mWorldspaceWidget->getCell(coords))) + { landHeight = cell->getSumOfAlteredAndTrueHeight(cellX, cellY, localX, localY); + } + else if (isLandLoaded(CSMWorld::CellCoordinates::generateId(cellX, cellY))) + { + CSMDoc::Document& document = mWorldspaceWidget->getDocument(); + CSMWorld::IdTable& landTable = dynamic_cast ( *document.getData().getTableModel (CSMWorld::UniversalId::Type_Land)); + std::string cellId = CSMWorld::CellCoordinates::generateId(cellX, cellY); + int landshapeColumn = landTable.findColumnIndex(CSMWorld::Columns::ColumnId_LandHeightsIndex); + const CSMWorld::LandHeightsColumn::DataType mPointer = landTable.data(landTable.getModelIndex(cellId, landshapeColumn)).value(); + return mPointer[localY*ESM::Land::LAND_SIZE + localX]; + } return landHeight; } diff --git a/apps/opencs/view/render/terrainselection.hpp b/apps/opencs/view/render/terrainselection.hpp index ced6538a7..84ee6f25a 100644 --- a/apps/opencs/view/render/terrainselection.hpp +++ b/apps/opencs/view/render/terrainselection.hpp @@ -55,6 +55,14 @@ namespace CSVRender private: + bool noCell(const std::string& cellId); + + bool noLand(const std::string& cellId); + + bool noLandLoaded(const std::string& cellId); + + bool isLandLoaded(const std::string& cellId); + osg::Group* mParentNode; WorldspaceWidget *mWorldspaceWidget; osg::ref_ptr mBaseNode;