mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-03 23:45:33 +00:00
Merge pull request #2585 from unelsson/terrainselectionfixes
Terrain selection fixes
This commit is contained in:
commit
2ee17f39fd
4 changed files with 90 additions and 37 deletions
|
@ -242,10 +242,37 @@ void CSVRender::TerrainSelection::drawTextureSelection(const osg::ref_ptr<osg::V
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CSVRender::TerrainSelection::noCell(const std::string& cellId)
|
||||||
|
{
|
||||||
|
CSMDoc::Document& document = mWorldspaceWidget->getDocument();
|
||||||
|
const CSMWorld::IdCollection<CSMWorld::Cell>& 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<CSMWorld::Land>& 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<CSMWorld::Land>& 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 CSVRender::TerrainSelection::calculateLandHeight(int x, int y) // global vertex coordinates
|
||||||
{
|
{
|
||||||
int cellX = std::floor((1.0f*x / (ESM::Land::LAND_SIZE - 1)));
|
int cellX = std::floor(static_cast<float>(x) / (ESM::Land::LAND_SIZE - 1));
|
||||||
int cellY = std::floor((1.0f*y / (ESM::Land::LAND_SIZE - 1)));
|
int cellY = std::floor(static_cast<float>(y) / (ESM::Land::LAND_SIZE - 1));
|
||||||
int localX = x - cellX * (ESM::Land::LAND_SIZE - 1);
|
int localX = x - cellX * (ESM::Land::LAND_SIZE - 1);
|
||||||
int localY = y - cellY * (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;
|
float landHeight = 0.f;
|
||||||
if (CSVRender::Cell* cell = dynamic_cast<CSVRender::Cell*>(mWorldspaceWidget->getCell(coords)))
|
if (CSVRender::Cell* cell = dynamic_cast<CSVRender::Cell*>(mWorldspaceWidget->getCell(coords)))
|
||||||
|
{
|
||||||
landHeight = cell->getSumOfAlteredAndTrueHeight(cellX, cellY, localX, localY);
|
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<CSMWorld::IdTable&> ( *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<CSMWorld::LandHeightsColumn::DataType>();
|
||||||
|
return mPointer[localY*ESM::Land::LAND_SIZE + localX];
|
||||||
|
}
|
||||||
|
|
||||||
return landHeight;
|
return landHeight;
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,10 +44,10 @@ namespace CSVRender
|
||||||
|
|
||||||
std::vector<std::pair<int, int>> getTerrainSelection() const;
|
std::vector<std::pair<int, int>> getTerrainSelection() const;
|
||||||
|
|
||||||
protected:
|
|
||||||
|
|
||||||
void update();
|
void update();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
void drawShapeSelection(const osg::ref_ptr<osg::Vec3Array> vertices);
|
void drawShapeSelection(const osg::ref_ptr<osg::Vec3Array> vertices);
|
||||||
void drawTextureSelection(const osg::ref_ptr<osg::Vec3Array> vertices);
|
void drawTextureSelection(const osg::ref_ptr<osg::Vec3Array> vertices);
|
||||||
|
|
||||||
|
@ -55,6 +55,14 @@ namespace CSVRender
|
||||||
|
|
||||||
private:
|
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;
|
osg::Group* mParentNode;
|
||||||
WorldspaceWidget *mWorldspaceWidget;
|
WorldspaceWidget *mWorldspaceWidget;
|
||||||
osg::ref_ptr<osg::PositionAttitudeTransform> mBaseNode;
|
osg::ref_ptr<osg::PositionAttitudeTransform> mBaseNode;
|
||||||
|
|
|
@ -112,12 +112,7 @@ void CSVRender::TerrainShapeMode::primaryEditPressed(const WorldspaceHitResult&
|
||||||
selectTerrainShapes(CSMWorld::CellCoordinates::toVertexCoords(hit.worldPos), 1, true);
|
selectTerrainShapes(CSMWorld::CellCoordinates::toVertexCoords(hit.worldPos), 1, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (CSVRender::PagedWorldspaceWidget *paged =
|
clearTransientEdits();
|
||||||
dynamic_cast<CSVRender::PagedWorldspaceWidget *> (&getWorldspaceWidget()))
|
|
||||||
{
|
|
||||||
paged->resetAllAlteredHeights();
|
|
||||||
mTotalDiffY = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVRender::TerrainShapeMode::primarySelectPressed(const WorldspaceHitResult& hit)
|
void CSVRender::TerrainShapeMode::primarySelectPressed(const WorldspaceHitResult& hit)
|
||||||
|
@ -214,28 +209,15 @@ void CSVRender::TerrainShapeMode::dragCompleted(const QPoint& pos)
|
||||||
{
|
{
|
||||||
if (mDragMode == InteractionType_PrimaryEdit)
|
if (mDragMode == InteractionType_PrimaryEdit)
|
||||||
{
|
{
|
||||||
if (mIsEditing)
|
|
||||||
{
|
|
||||||
mTotalDiffY = 0;
|
|
||||||
mIsEditing = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
applyTerrainEditChanges();
|
applyTerrainEditChanges();
|
||||||
|
clearTransientEdits();
|
||||||
if (CSVRender::PagedWorldspaceWidget *paged = dynamic_cast<CSVRender::PagedWorldspaceWidget *> (&getWorldspaceWidget()))
|
|
||||||
paged->resetAllAlteredHeights();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void CSVRender::TerrainShapeMode::dragAborted()
|
void CSVRender::TerrainShapeMode::dragAborted()
|
||||||
{
|
{
|
||||||
if (CSVRender::PagedWorldspaceWidget *paged =
|
clearTransientEdits();
|
||||||
dynamic_cast<CSVRender::PagedWorldspaceWidget *> (&getWorldspaceWidget()))
|
|
||||||
{
|
|
||||||
paged->resetAllAlteredHeights();
|
|
||||||
mTotalDiffY = 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVRender::TerrainShapeMode::dragWheel (int diff, double speedFactor)
|
void CSVRender::TerrainShapeMode::dragWheel (int diff, double speedFactor)
|
||||||
|
@ -266,15 +248,20 @@ void CSVRender::TerrainShapeMode::sortAndLimitAlteredCells()
|
||||||
if (passes > 2)
|
if (passes > 2)
|
||||||
{
|
{
|
||||||
Log(Debug::Warning) << "Warning: User edit exceeds accepted slope steepness. Automatic limiting has failed, edit has been discarded.";
|
Log(Debug::Warning) << "Warning: User edit exceeds accepted slope steepness. Automatic limiting has failed, edit has been discarded.";
|
||||||
if (CSVRender::PagedWorldspaceWidget *paged =
|
clearTransientEdits();
|
||||||
dynamic_cast<CSVRender::PagedWorldspaceWidget *> (&getWorldspaceWidget()))
|
|
||||||
{
|
|
||||||
paged->resetAllAlteredHeights();
|
|
||||||
mAlteredCells.clear();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSVRender::TerrainShapeMode::clearTransientEdits()
|
||||||
|
{
|
||||||
|
mTotalDiffY = 0;
|
||||||
|
mIsEditing = false;
|
||||||
|
mAlteredCells.clear();
|
||||||
|
if (CSVRender::PagedWorldspaceWidget *paged = dynamic_cast<CSVRender::PagedWorldspaceWidget *> (&getWorldspaceWidget()))
|
||||||
|
paged->resetAllAlteredHeights();
|
||||||
|
mTerrainShapeSelection->update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVRender::TerrainShapeMode::applyTerrainEditChanges()
|
void CSVRender::TerrainShapeMode::applyTerrainEditChanges()
|
||||||
|
@ -385,7 +372,7 @@ void CSVRender::TerrainShapeMode::applyTerrainEditChanges()
|
||||||
pushNormalsEditToCommand(landNormalsNew, document, landTable, cellId);
|
pushNormalsEditToCommand(landNormalsNew, document, landTable, cellId);
|
||||||
}
|
}
|
||||||
undoStack.endMacro();
|
undoStack.endMacro();
|
||||||
mAlteredCells.clear();
|
clearTransientEdits();
|
||||||
}
|
}
|
||||||
|
|
||||||
float CSVRender::TerrainShapeMode::calculateBumpShape(float distance, int radius, float height)
|
float CSVRender::TerrainShapeMode::calculateBumpShape(float distance, int radius, float height)
|
||||||
|
@ -498,6 +485,7 @@ void CSVRender::TerrainShapeMode::editTerrainShapeGrid(const std::pair<int, int>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
mTerrainShapeSelection->update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSVRender::TerrainShapeMode::setFlattenToolTargetHeight(const WorldspaceHitResult& hit)
|
void CSVRender::TerrainShapeMode::setFlattenToolTargetHeight(const WorldspaceHitResult& hit)
|
||||||
|
@ -1039,6 +1027,17 @@ bool CSVRender::TerrainShapeMode::limitAlteredHeights(const CSMWorld::CellCoordi
|
||||||
return steepnessIsWithinLimits;
|
return steepnessIsWithinLimits;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CSVRender::TerrainShapeMode::isInCellSelection(int globalSelectionX, int globalSelectionY)
|
||||||
|
{
|
||||||
|
if (CSVRender::PagedWorldspaceWidget *paged = dynamic_cast<CSVRender::PagedWorldspaceWidget *> (&getWorldspaceWidget()))
|
||||||
|
{
|
||||||
|
std::pair<int, int> 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<int, int>& vertexCoords, unsigned char selectMode, bool dragOperation)
|
void CSVRender::TerrainShapeMode::selectTerrainShapes(const std::pair<int, int>& vertexCoords, unsigned char selectMode, bool dragOperation)
|
||||||
{
|
{
|
||||||
int r = mBrushSize / 2;
|
int r = mBrushSize / 2;
|
||||||
|
@ -1046,7 +1045,7 @@ void CSVRender::TerrainShapeMode::selectTerrainShapes(const std::pair<int, int>&
|
||||||
|
|
||||||
if (mBrushShape == CSVWidget::BrushShape_Point)
|
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)
|
if (mBrushShape == CSVWidget::BrushShape_Square)
|
||||||
|
@ -1055,7 +1054,7 @@ void CSVRender::TerrainShapeMode::selectTerrainShapes(const std::pair<int, int>&
|
||||||
{
|
{
|
||||||
for(int j = vertexCoords.second - r; j <= vertexCoords.second + r; ++j)
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1069,7 +1068,7 @@ void CSVRender::TerrainShapeMode::selectTerrainShapes(const std::pair<int, int>&
|
||||||
int distanceX = abs(i - vertexCoords.first);
|
int distanceX = abs(i - vertexCoords.first);
|
||||||
int distanceY = abs(j - vertexCoords.second);
|
int distanceY = abs(j - vertexCoords.second);
|
||||||
int distance = std::round(sqrt(pow(distanceX, 2)+pow(distanceY, 2)));
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1080,7 +1079,9 @@ void CSVRender::TerrainShapeMode::selectTerrainShapes(const std::pair<int, int>&
|
||||||
{
|
{
|
||||||
for(auto const& value: mCustomBrushShape)
|
for(auto const& value: mCustomBrushShape)
|
||||||
{
|
{
|
||||||
selections.emplace_back(std::make_pair(vertexCoords.first + value.first, vertexCoords.second + value.second));
|
std::pair<int, int> 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -95,6 +95,9 @@ namespace CSVRender
|
||||||
/// Remove duplicates and sort mAlteredCells, then limitAlteredHeights forward and reverse
|
/// Remove duplicates and sort mAlteredCells, then limitAlteredHeights forward and reverse
|
||||||
void sortAndLimitAlteredCells();
|
void sortAndLimitAlteredCells();
|
||||||
|
|
||||||
|
/// Reset everything in the current edit
|
||||||
|
void clearTransientEdits();
|
||||||
|
|
||||||
/// Move pending alteredHeights changes to omwgame/omwaddon -data
|
/// Move pending alteredHeights changes to omwgame/omwaddon -data
|
||||||
void applyTerrainEditChanges();
|
void applyTerrainEditChanges();
|
||||||
|
|
||||||
|
@ -128,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
|
/// 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);
|
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
|
/// Handle brush mechanics for terrain shape selection
|
||||||
void selectTerrainShapes (const std::pair<int, int>& vertexCoords, unsigned char selectMode, bool dragOperation);
|
void selectTerrainShapes (const std::pair<int, int>& vertexCoords, unsigned char selectMode, bool dragOperation);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue