1
0
Fork 1
mirror of https://github.com/TES3MP/openmw-tes3mp.git synced 2025-01-30 22:15:32 +00:00

Terrain shape editing related fixes

This commit is contained in:
Nelsson Huotari 2019-10-07 02:57:09 +03:00
parent 5b9debc554
commit 8acfa2600f
9 changed files with 126 additions and 86 deletions

View file

@ -40,6 +40,8 @@ New Features:
New Editor Features: New Editor Features:
- "Faction Ranks" table for "Faction" records (#4209) - "Faction Ranks" table for "Faction" records (#4209)
- Changes to height editing can be cancelled without changes to data (press esc to cancel) (#4840)
- Land heightmap/shape editing and vertex selection (#5170)
Bug Fixes: Bug Fixes:
- Scripted Items cannot be stacked anymore to avoid multiple script execution (#2969) - Scripted Items cannot be stacked anymore to avoid multiple script execution (#2969)

View file

@ -89,11 +89,13 @@ namespace CSMWorld
DataType values(Size, 0); DataType values(Size, 0);
if (land.isDataLoaded(Land::DATA_WNAM)) if (land.mDataTypes & Land::DATA_WNAM)
{ {
for (int i = 0; i < Size; ++i) for (int i = 0; i < Size; ++i)
{
values[i] = land.mWnam[i]; values[i] = land.mWnam[i];
} }
}
QVariant variant; QVariant variant;
variant.setValue(values); variant.setValue(values);

View file

@ -18,6 +18,7 @@
#include <components/esm/loadland.hpp> #include <components/esm/loadland.hpp>
#include <components/debug/debuglog.hpp> #include <components/debug/debuglog.hpp>
#include "../widget/brushshapes.hpp"
#include "../widget/modebutton.hpp" #include "../widget/modebutton.hpp"
#include "../widget/scenetoolbar.hpp" #include "../widget/scenetoolbar.hpp"
#include "../widget/scenetoolshapebrush.hpp" #include "../widget/scenetoolshapebrush.hpp"
@ -44,14 +45,14 @@
CSVRender::TerrainShapeMode::TerrainShapeMode (WorldspaceWidget *worldspaceWidget, osg::Group* parentNode, QWidget *parent) CSVRender::TerrainShapeMode::TerrainShapeMode (WorldspaceWidget *worldspaceWidget, osg::Group* parentNode, QWidget *parent)
: EditMode (worldspaceWidget, QIcon {":scenetoolbar/editing-terrain-shape"}, Mask_Terrain | Mask_Reference, "Terrain land editing", parent), : EditMode (worldspaceWidget, QIcon {":scenetoolbar/editing-terrain-shape"}, Mask_Terrain | Mask_Reference, "Terrain land editing", parent),
mBrushSize(0), mBrushSize(1),
mBrushShape(BrushShape_Point), mBrushShape(CSVWidget::BrushShape_Point),
mShapeBrushScenetool(0), mShapeBrushScenetool(0),
mDragMode(InteractionType_None), mDragMode(InteractionType_None),
mParentNode(parentNode), mParentNode(parentNode),
mIsEditing(false), mIsEditing(false),
mTotalDiffY(0), mTotalDiffY(0),
mShapeEditTool(0), mShapeEditTool(ShapeEditTool_Drag),
mShapeEditToolStrength(8), mShapeEditToolStrength(8),
mTargetHeight(0) mTargetHeight(0)
{ {
@ -69,7 +70,7 @@ void CSVRender::TerrainShapeMode::activate(CSVWidget::SceneToolbar* toolbar)
mShapeBrushScenetool = new CSVWidget::SceneToolShapeBrush (toolbar, "scenetoolshapebrush", getWorldspaceWidget().getDocument()); mShapeBrushScenetool = new CSVWidget::SceneToolShapeBrush (toolbar, "scenetoolshapebrush", getWorldspaceWidget().getDocument());
connect(mShapeBrushScenetool, SIGNAL (clicked()), mShapeBrushScenetool, SLOT (activate())); connect(mShapeBrushScenetool, SIGNAL (clicked()), mShapeBrushScenetool, SLOT (activate()));
connect(mShapeBrushScenetool->mShapeBrushWindow, SIGNAL(passBrushSize(int)), this, SLOT(setBrushSize(int))); connect(mShapeBrushScenetool->mShapeBrushWindow, SIGNAL(passBrushSize(int)), this, SLOT(setBrushSize(int)));
connect(mShapeBrushScenetool->mShapeBrushWindow, SIGNAL(passBrushShape(int)), this, SLOT(setBrushShape(int))); connect(mShapeBrushScenetool->mShapeBrushWindow, SIGNAL(passBrushShape(CSVWidget::BrushShape)), this, SLOT(setBrushShape(CSVWidget::BrushShape)));
connect(mShapeBrushScenetool->mShapeBrushWindow->mSizeSliders->mBrushSizeSlider, SIGNAL(valueChanged(int)), this, SLOT(setBrushSize(int))); connect(mShapeBrushScenetool->mShapeBrushWindow->mSizeSliders->mBrushSizeSlider, SIGNAL(valueChanged(int)), this, SLOT(setBrushSize(int)));
connect(mShapeBrushScenetool->mShapeBrushWindow->mToolSelector, SIGNAL(currentIndexChanged(int)), this, SLOT(setShapeEditTool(int))); connect(mShapeBrushScenetool->mShapeBrushWindow->mToolSelector, SIGNAL(currentIndexChanged(int)), this, SLOT(setShapeEditTool(int)));
connect(mShapeBrushScenetool->mShapeBrushWindow->mToolStrengthSlider, SIGNAL(valueChanged(int)), this, SLOT(setShapeEditToolStrength(int))); connect(mShapeBrushScenetool->mShapeBrushWindow->mToolStrengthSlider, SIGNAL(valueChanged(int)), this, SLOT(setShapeEditToolStrength(int)));
@ -94,12 +95,12 @@ void CSVRender::TerrainShapeMode::primaryEditPressed(const WorldspaceHitResult&
if (hit.hit && hit.tag == 0) if (hit.hit && hit.tag == 0)
{ {
if (mShapeEditTool == 4) if (mShapeEditTool == ShapeEditTool_Flatten)
setFlattenToolTargetHeight(hit); setFlattenToolTargetHeight(hit);
if (mDragMode == InteractionType_PrimaryEdit && mShapeEditTool > 0) if (mDragMode == InteractionType_PrimaryEdit && mShapeEditTool != ShapeEditTool_Drag)
{ {
std::string cellId = getWorldspaceWidget().getCellId (hit.worldPos); std::string cellId = getWorldspaceWidget().getCellId (hit.worldPos);
if (mShapeEditTool > 0) editTerrainShapeGrid(CSMWorld::CellCoordinates::toVertexCoords(hit.worldPos), true); editTerrainShapeGrid(CSMWorld::CellCoordinates::toVertexCoords(hit.worldPos), true);
applyTerrainEditChanges(); applyTerrainEditChanges();
} }
@ -149,7 +150,7 @@ bool CSVRender::TerrainShapeMode::primaryEditStartDrag (const QPoint& pos)
{ {
mEditingPos = hit.worldPos; mEditingPos = hit.worldPos;
mIsEditing = true; mIsEditing = true;
if (mShapeEditTool == 4) if (mShapeEditTool == ShapeEditTool_Flatten)
setFlattenToolTargetHeight(hit); setFlattenToolTargetHeight(hit);
} }
@ -194,8 +195,8 @@ void CSVRender::TerrainShapeMode::drag (const QPoint& pos, int diffX, int diffY,
WorldspaceHitResult hit = getWorldspaceWidget().mousePick (pos, getWorldspaceWidget().getInteractionMask()); WorldspaceHitResult hit = getWorldspaceWidget().mousePick (pos, getWorldspaceWidget().getInteractionMask());
std::string cellId = getWorldspaceWidget().getCellId (hit.worldPos); std::string cellId = getWorldspaceWidget().getCellId (hit.worldPos);
mTotalDiffY += diffY; mTotalDiffY += diffY;
if (mIsEditing == true && mShapeEditTool == 0) editTerrainShapeGrid(CSMWorld::CellCoordinates::toVertexCoords(mEditingPos), true); if (mIsEditing == true && mShapeEditTool == ShapeEditTool_Drag) editTerrainShapeGrid(CSMWorld::CellCoordinates::toVertexCoords(mEditingPos), true);
if (mIsEditing == true && mShapeEditTool > 0) editTerrainShapeGrid(CSMWorld::CellCoordinates::toVertexCoords(hit.worldPos), true); if (mIsEditing == true && mShapeEditTool != ShapeEditTool_Drag) editTerrainShapeGrid(CSMWorld::CellCoordinates::toVertexCoords(hit.worldPos), true);
} }
if (mDragMode == InteractionType_PrimarySelect) if (mDragMode == InteractionType_PrimarySelect)
@ -256,6 +257,7 @@ void CSVRender::TerrainShapeMode::applyTerrainEditChanges()
*document.getData().getTableModel (CSMWorld::UniversalId::Type_LandTextures)); *document.getData().getTableModel (CSMWorld::UniversalId::Type_LandTextures));
int landshapeColumn = landTable.findColumnIndex(CSMWorld::Columns::ColumnId_LandHeightsIndex); int landshapeColumn = landTable.findColumnIndex(CSMWorld::Columns::ColumnId_LandHeightsIndex);
int landMapLodColumn = landTable.findColumnIndex(CSMWorld::Columns::ColumnId_LandMapLodIndex);
int landnormalsColumn = landTable.findColumnIndex(CSMWorld::Columns::ColumnId_LandNormalsIndex); int landnormalsColumn = landTable.findColumnIndex(CSMWorld::Columns::ColumnId_LandNormalsIndex);
QUndoStack& undoStack = document.getUndoStack(); QUndoStack& undoStack = document.getUndoStack();
@ -296,7 +298,9 @@ void CSVRender::TerrainShapeMode::applyTerrainEditChanges()
std::string cellId = CSMWorld::CellCoordinates::generateId(cellCoordinates.getX(), cellCoordinates.getY()); std::string cellId = CSMWorld::CellCoordinates::generateId(cellCoordinates.getX(), cellCoordinates.getY());
undoStack.push (new CSMWorld::TouchLandCommand(landTable, ltexTable, cellId)); undoStack.push (new CSMWorld::TouchLandCommand(landTable, ltexTable, cellId));
const CSMWorld::LandHeightsColumn::DataType landShapePointer = landTable.data(landTable.getModelIndex(cellId, landshapeColumn)).value<CSMWorld::LandHeightsColumn::DataType>(); const CSMWorld::LandHeightsColumn::DataType landShapePointer = landTable.data(landTable.getModelIndex(cellId, landshapeColumn)).value<CSMWorld::LandHeightsColumn::DataType>();
const CSMWorld::LandMapLodColumn::DataType landMapLodPointer = landTable.data(landTable.getModelIndex(cellId, landMapLodColumn)).value<CSMWorld::LandMapLodColumn::DataType>();
CSMWorld::LandHeightsColumn::DataType landShapeNew(landShapePointer); CSMWorld::LandHeightsColumn::DataType landShapeNew(landShapePointer);
CSMWorld::LandMapLodColumn::DataType mapLodShapeNew(landMapLodPointer);
for(int i = 0; i < ESM::Land::LAND_SIZE; ++i) for(int i = 0; i < ESM::Land::LAND_SIZE; ++i)
{ {
for(int j = 0; j < ESM::Land::LAND_SIZE; ++j) for(int j = 0; j < ESM::Land::LAND_SIZE; ++j)
@ -311,7 +315,15 @@ void CSVRender::TerrainShapeMode::applyTerrainEditChanges()
} }
} }
} }
if (allowLandShapeEditing(cellId) == true) pushEditToCommand(landShapeNew, document, landTable, cellId); for(int i = 0; i < ESM::Land::LAND_GLOBAL_MAP_LOD_SIZE; ++i)
{
mapLodShapeNew[i] = landMapLodPointer[i]; //TO-DO: generate a new mWnam based on new heights
}
if (allowLandShapeEditing(cellId) == true)
{
pushEditToCommand(landShapeNew, document, landTable, cellId);
pushLodToCommand(mapLodShapeNew, document, landTable, cellId);
}
} }
for(CSMWorld::CellCoordinates cellCoordinates: mAlteredCells) for(CSMWorld::CellCoordinates cellCoordinates: mAlteredCells)
@ -358,9 +370,7 @@ void CSVRender::TerrainShapeMode::applyTerrainEditChanges()
v2.z() = 0; v2.z() = 0;
} }
normal.y() = v1.z()*v2.x() - v1.x()*v2.z(); normal = v1 ^ v2;
normal.x() = v1.y()*v2.z() - v1.z()*v2.y();
normal.z() = v1.x()*v2.y() - v1.y()*v2.x();
hyp = normal.length() / 127.0f; hyp = normal.length() / 127.0f;
@ -388,22 +398,22 @@ void CSVRender::TerrainShapeMode::editTerrainShapeGrid(const std::pair<int, int>
if (CSVRender::PagedWorldspaceWidget *paged = if (CSVRender::PagedWorldspaceWidget *paged =
dynamic_cast<CSVRender::PagedWorldspaceWidget *> (&getWorldspaceWidget())) dynamic_cast<CSVRender::PagedWorldspaceWidget *> (&getWorldspaceWidget()))
{ {
if (mShapeEditTool == 0) paged->resetAllAlteredHeights(); if (mShapeEditTool == ShapeEditTool_Drag) paged->resetAllAlteredHeights();
} }
if(allowLandShapeEditing(cellId)==true) if(allowLandShapeEditing(cellId)==true)
{ {
if (mBrushShape == BrushShape_Point) if (mBrushShape == CSVWidget::BrushShape_Point)
{ {
int x = CSMWorld::CellCoordinates::vertexGlobalToInCellCoords(vertexCoords.first); int x = CSMWorld::CellCoordinates::vertexGlobalToInCellCoords(vertexCoords.first);
int y = CSMWorld::CellCoordinates::vertexGlobalToInCellCoords(vertexCoords.second); int y = CSMWorld::CellCoordinates::vertexGlobalToInCellCoords(vertexCoords.second);
if (mShapeEditTool == 0) alterHeight(cellCoords, x, y, mTotalDiffY); if (mShapeEditTool == ShapeEditTool_Drag) alterHeight(cellCoords, x, y, mTotalDiffY);
if (mShapeEditTool == 1 || mShapeEditTool == 2) alterHeight(cellCoords, x, y, mShapeEditToolStrength); if (mShapeEditTool == ShapeEditTool_PaintToRaise || mShapeEditTool == ShapeEditTool_PaintToLower) alterHeight(cellCoords, x, y, mShapeEditToolStrength);
if (mShapeEditTool == 3) smoothHeight(cellCoords, x, y, mShapeEditToolStrength); if (mShapeEditTool == ShapeEditTool_Smooth) smoothHeight(cellCoords, x, y, mShapeEditToolStrength);
if (mShapeEditTool == 4) flattenHeight(cellCoords, x, y, mShapeEditToolStrength, mTargetHeight); if (mShapeEditTool == ShapeEditTool_Flatten) flattenHeight(cellCoords, x, y, mShapeEditToolStrength, mTargetHeight);
} }
if (mBrushShape == BrushShape_Square) if (mBrushShape == CSVWidget::BrushShape_Square)
{ {
for(int i = vertexCoords.first - r; i <= vertexCoords.first + r; ++i) for(int i = vertexCoords.first - r; i <= vertexCoords.first + r; ++i)
{ {
@ -413,15 +423,15 @@ void CSVRender::TerrainShapeMode::editTerrainShapeGrid(const std::pair<int, int>
cellCoords = CSMWorld::CellCoordinates::fromId(cellId).first; cellCoords = CSMWorld::CellCoordinates::fromId(cellId).first;
int x = CSMWorld::CellCoordinates::vertexGlobalToInCellCoords(i); int x = CSMWorld::CellCoordinates::vertexGlobalToInCellCoords(i);
int y = CSMWorld::CellCoordinates::vertexGlobalToInCellCoords(j); int y = CSMWorld::CellCoordinates::vertexGlobalToInCellCoords(j);
if (mShapeEditTool == 0) alterHeight(cellCoords, x, y, mTotalDiffY); if (mShapeEditTool == ShapeEditTool_Drag) alterHeight(cellCoords, x, y, mTotalDiffY);
if (mShapeEditTool == 1 || mShapeEditTool == 2) alterHeight(cellCoords, x, y, mShapeEditToolStrength); if (mShapeEditTool == ShapeEditTool_PaintToRaise || mShapeEditTool == ShapeEditTool_PaintToLower) alterHeight(cellCoords, x, y, mShapeEditToolStrength);
if (mShapeEditTool == 3) smoothHeight(cellCoords, x, y, mShapeEditToolStrength); if (mShapeEditTool == ShapeEditTool_Smooth) smoothHeight(cellCoords, x, y, mShapeEditToolStrength);
if (mShapeEditTool == 4) flattenHeight(cellCoords, x, y, mShapeEditToolStrength, mTargetHeight); if (mShapeEditTool == ShapeEditTool_Flatten) flattenHeight(cellCoords, x, y, mShapeEditToolStrength, mTargetHeight);
} }
} }
} }
if (mBrushShape == BrushShape_Circle) if (mBrushShape == CSVWidget::BrushShape_Circle)
{ {
for(int i = vertexCoords.first - r; i <= vertexCoords.first + r; ++i) for(int i = vertexCoords.first - r; i <= vertexCoords.first + r; ++i)
{ {
@ -436,18 +446,19 @@ void CSVRender::TerrainShapeMode::editTerrainShapeGrid(const std::pair<int, int>
int y = CSMWorld::CellCoordinates::vertexGlobalToInCellCoords(j); int y = CSMWorld::CellCoordinates::vertexGlobalToInCellCoords(j);
float distancePerRadius = 1.0f * distance / r; float distancePerRadius = 1.0f * distance / r;
float smoothedByDistance = 0.0f; float smoothedByDistance = 0.0f;
if (mShapeEditTool == 0) smoothedByDistance = mTotalDiffY - mTotalDiffY * (3 * distancePerRadius * distancePerRadius - 2 * distancePerRadius * distancePerRadius * distancePerRadius); if (mShapeEditTool == ShapeEditTool_Drag) smoothedByDistance = mTotalDiffY - mTotalDiffY * (3 * distancePerRadius * distancePerRadius - 2 * distancePerRadius * distancePerRadius * distancePerRadius);
if (mShapeEditTool == 1 || mShapeEditTool == 2) smoothedByDistance = (r + mShapeEditToolStrength) - (r + mShapeEditToolStrength) * (3 * distancePerRadius * distancePerRadius - 2 * distancePerRadius * distancePerRadius * distancePerRadius); if (mShapeEditTool == ShapeEditTool_PaintToRaise || mShapeEditTool == ShapeEditTool_PaintToLower) smoothedByDistance = (r + mShapeEditToolStrength) - (r + mShapeEditToolStrength) * (3 * distancePerRadius * distancePerRadius - 2 * distancePerRadius * distancePerRadius * distancePerRadius);
if (distance <= r) if (distance <= r)
{ {
if (mShapeEditTool >= 0 && mShapeEditTool < 3) alterHeight(cellCoords, x, y, smoothedByDistance); if (mShapeEditTool == ShapeEditTool_Drag || mShapeEditTool == ShapeEditTool_PaintToRaise || mShapeEditTool == ShapeEditTool_PaintToLower)
if (mShapeEditTool == 3) smoothHeight(cellCoords, x, y, mShapeEditToolStrength); alterHeight(cellCoords, x, y, smoothedByDistance);
if (mShapeEditTool == 4) flattenHeight(cellCoords, x, y, mShapeEditToolStrength, mTargetHeight); if (mShapeEditTool == ShapeEditTool_Smooth) smoothHeight(cellCoords, x, y, mShapeEditToolStrength);
if (mShapeEditTool == ShapeEditTool_Flatten) flattenHeight(cellCoords, x, y, mShapeEditToolStrength, mTargetHeight);
} }
} }
} }
} }
if (mBrushShape == BrushShape_Custom) if (mBrushShape == CSVWidget::BrushShape_Custom)
{ {
if(!mCustomBrushShape.empty()) if(!mCustomBrushShape.empty())
{ {
@ -457,10 +468,10 @@ void CSVRender::TerrainShapeMode::editTerrainShapeGrid(const std::pair<int, int>
cellCoords = CSMWorld::CellCoordinates::fromId(cellId).first; cellCoords = CSMWorld::CellCoordinates::fromId(cellId).first;
int x = CSMWorld::CellCoordinates::vertexGlobalToInCellCoords(vertexCoords.first + value.first); int x = CSMWorld::CellCoordinates::vertexGlobalToInCellCoords(vertexCoords.first + value.first);
int y = CSMWorld::CellCoordinates::vertexGlobalToInCellCoords(vertexCoords.second + value.second); int y = CSMWorld::CellCoordinates::vertexGlobalToInCellCoords(vertexCoords.second + value.second);
if (mShapeEditTool == 0) alterHeight(cellCoords, x, y, mTotalDiffY); if (mShapeEditTool == ShapeEditTool_Drag) alterHeight(cellCoords, x, y, mTotalDiffY);
if (mShapeEditTool == 1 || mShapeEditTool == 2) alterHeight(cellCoords, x, y, mShapeEditToolStrength); if (mShapeEditTool == ShapeEditTool_PaintToRaise || mShapeEditTool == ShapeEditTool_PaintToLower) alterHeight(cellCoords, x, y, mShapeEditToolStrength);
if (mShapeEditTool == 3) smoothHeight(cellCoords, x, y, mShapeEditToolStrength); if (mShapeEditTool == ShapeEditTool_Smooth) smoothHeight(cellCoords, x, y, mShapeEditToolStrength);
if (mShapeEditTool == 4) flattenHeight(cellCoords, x, y, mShapeEditToolStrength, mTargetHeight); if (mShapeEditTool == ShapeEditTool_Flatten) flattenHeight(cellCoords, x, y, mShapeEditToolStrength, mTargetHeight);
} }
} }
} }
@ -506,7 +517,7 @@ void CSVRender::TerrainShapeMode::alterHeight(const CSMWorld::CellCoordinates& c
if (useTool) if (useTool)
{ {
mAlteredCells.emplace_back(cellCoords); mAlteredCells.emplace_back(cellCoords);
if (mShapeEditTool == 0) if (mShapeEditTool == ShapeEditTool_Drag)
{ {
// Get distance from modified land, alter land change based on zoom // Get distance from modified land, alter land change based on zoom
osg::Vec3d eye, center, up; osg::Vec3d eye, center, up;
@ -514,9 +525,9 @@ void CSVRender::TerrainShapeMode::alterHeight(const CSMWorld::CellCoordinates& c
osg::Vec3d distance = eye - mEditingPos; osg::Vec3d distance = eye - mEditingPos;
alteredHeight = alteredHeight * (distance.length() / 500); alteredHeight = alteredHeight * (distance.length() / 500);
} }
if (mShapeEditTool == 1) alteredHeight = *paged->getCellAlteredHeight(cellCoords, inCellX, inCellY) + alteredHeight; if (mShapeEditTool == ShapeEditTool_PaintToRaise) alteredHeight = *paged->getCellAlteredHeight(cellCoords, inCellX, inCellY) + alteredHeight;
if (mShapeEditTool == 2) alteredHeight = *paged->getCellAlteredHeight(cellCoords, inCellX, inCellY) - alteredHeight; if (mShapeEditTool == ShapeEditTool_PaintToLower) alteredHeight = *paged->getCellAlteredHeight(cellCoords, inCellX, inCellY) - alteredHeight;
if (mShapeEditTool == 3) alteredHeight = *paged->getCellAlteredHeight(cellCoords, inCellX, inCellY) + alteredHeight; if (mShapeEditTool == ShapeEditTool_Smooth) 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)
@ -1037,12 +1048,12 @@ void CSVRender::TerrainShapeMode::selectTerrainShapes(const std::pair<int, int>&
int r = mBrushSize / 2; int r = mBrushSize / 2;
std::vector<std::pair<int, int>> selections; std::vector<std::pair<int, int>> selections;
if (mBrushShape == BrushShape_Point) if (mBrushShape == CSVWidget::BrushShape_Point)
{ {
selections.emplace_back(vertexCoords); selections.emplace_back(vertexCoords);
} }
if (mBrushShape == BrushShape_Square) if (mBrushShape == CSVWidget::BrushShape_Square)
{ {
for(int i = vertexCoords.first - r; i <= vertexCoords.first + r; ++i) for(int i = vertexCoords.first - r; i <= vertexCoords.first + r; ++i)
{ {
@ -1053,7 +1064,7 @@ void CSVRender::TerrainShapeMode::selectTerrainShapes(const std::pair<int, int>&
} }
} }
if (mBrushShape == BrushShape_Circle) if (mBrushShape == CSVWidget::BrushShape_Circle)
{ {
for(int i = vertexCoords.first - r; i <= vertexCoords.first + r; ++i) for(int i = vertexCoords.first - r; i <= vertexCoords.first + r; ++i)
{ {
@ -1067,7 +1078,7 @@ void CSVRender::TerrainShapeMode::selectTerrainShapes(const std::pair<int, int>&
} }
} }
if (mBrushShape == BrushShape_Custom) if (mBrushShape == CSVWidget::BrushShape_Custom)
{ {
if(!mCustomBrushShape.empty()) if(!mCustomBrushShape.empty())
{ {
@ -1084,7 +1095,7 @@ void CSVRender::TerrainShapeMode::selectTerrainShapes(const std::pair<int, int>&
} }
void CSVRender::TerrainShapeMode::pushEditToCommand(const CSMWorld::LandHeightsColumn::DataType& newLandGrid, CSMDoc::Document& document, void CSVRender::TerrainShapeMode::pushEditToCommand(const CSMWorld::LandHeightsColumn::DataType& newLandGrid, CSMDoc::Document& document,
CSMWorld::IdTable& landTable, std::string cellId) CSMWorld::IdTable& landTable, const std::string& cellId)
{ {
QVariant changedLand; QVariant changedLand;
changedLand.setValue(newLandGrid); changedLand.setValue(newLandGrid);
@ -1096,7 +1107,7 @@ void CSVRender::TerrainShapeMode::pushEditToCommand(const CSMWorld::LandHeightsC
} }
void CSVRender::TerrainShapeMode::pushNormalsEditToCommand(const CSMWorld::LandNormalsColumn::DataType& newLandGrid, CSMDoc::Document& document, void CSVRender::TerrainShapeMode::pushNormalsEditToCommand(const CSMWorld::LandNormalsColumn::DataType& newLandGrid, CSMDoc::Document& document,
CSMWorld::IdTable& landTable, std::string cellId) CSMWorld::IdTable& landTable, const std::string& cellId)
{ {
QVariant changedLand; QVariant changedLand;
changedLand.setValue(newLandGrid); changedLand.setValue(newLandGrid);
@ -1107,7 +1118,19 @@ void CSVRender::TerrainShapeMode::pushNormalsEditToCommand(const CSMWorld::LandN
undoStack.push (new CSMWorld::ModifyCommand(landTable, index, changedLand)); undoStack.push (new CSMWorld::ModifyCommand(landTable, index, changedLand));
} }
bool CSVRender::TerrainShapeMode::allowLandShapeEditing(std::string cellId) void CSVRender::TerrainShapeMode::pushLodToCommand(const CSMWorld::LandMapLodColumn::DataType& newLandMapLod, CSMDoc::Document& document,
CSMWorld::IdTable& landTable, const std::string& cellId)
{
QVariant changedLod;
changedLod.setValue(newLandMapLod);
QModelIndex index(landTable.getModelIndex (cellId, landTable.findColumnIndex (CSMWorld::Columns::ColumnId_LandMapLodIndex)));
QUndoStack& undoStack = document.getUndoStack();
undoStack.push (new CSMWorld::ModifyCommand(landTable, index, changedLod));
}
bool CSVRender::TerrainShapeMode::allowLandShapeEditing(const std::string& cellId)
{ {
CSMDoc::Document& document = getWorldspaceWidget().getDocument(); CSMDoc::Document& document = getWorldspaceWidget().getDocument();
CSMWorld::IdTable& landTable = dynamic_cast<CSMWorld::IdTable&> ( CSMWorld::IdTable& landTable = dynamic_cast<CSMWorld::IdTable&> (
@ -1191,12 +1214,12 @@ void CSVRender::TerrainShapeMode::setBrushSize(int brushSize)
mBrushSize = brushSize; mBrushSize = brushSize;
} }
void CSVRender::TerrainShapeMode::setBrushShape(int brushShape) void CSVRender::TerrainShapeMode::setBrushShape(CSVWidget::BrushShape brushShape)
{ {
mBrushShape = brushShape; mBrushShape = brushShape;
//Set custom brush shape //Set custom brush shape
if (mBrushShape == BrushShape_Custom && !mTerrainShapeSelection->getTerrainSelection().empty()) if (mBrushShape == CSVWidget::BrushShape_Custom && !mTerrainShapeSelection->getTerrainSelection().empty())
{ {
auto terrainSelection = mTerrainShapeSelection->getTerrainSelection(); auto terrainSelection = mTerrainShapeSelection->getTerrainSelection();
int selectionCenterX = 0; int selectionCenterX = 0;

View file

@ -12,11 +12,11 @@
#ifndef Q_MOC_RUN #ifndef Q_MOC_RUN
#include "../../model/world/data.hpp" #include "../../model/world/data.hpp"
#include "../../model/world/land.hpp" #include "../../model/world/land.hpp"
#include "../../model/doc/document.hpp" #include "../../model/doc/document.hpp"
#include "../../model/world/commands.hpp" #include "../../model/world/commands.hpp"
#include "../../model/world/idtable.hpp" #include "../../model/world/idtable.hpp"
#include "../../model/world/landtexture.hpp" #include "../../model/world/landtexture.hpp"
#include "../widget/brushshapes.hpp"
#endif #endif
#include "terrainselection.hpp" #include "terrainselection.hpp"
@ -46,12 +46,13 @@ namespace CSVRender
InteractionType_None InteractionType_None
}; };
enum BrushShape enum ShapeEditTool
{ {
BrushShape_Point = 0, ShapeEditTool_Drag = 0,
BrushShape_Square = 1, ShapeEditTool_PaintToRaise = 1,
BrushShape_Circle = 2, ShapeEditTool_PaintToLower = 2,
BrushShape_Custom = 3 ShapeEditTool_Smooth = 3,
ShapeEditTool_Flatten = 4
}; };
/// Editmode for terrain shape grid /// Editmode for terrain shape grid
@ -124,20 +125,24 @@ namespace CSVRender
/// Push terrain shape edits to command macro /// Push terrain shape edits to command macro
void pushEditToCommand (const CSMWorld::LandHeightsColumn::DataType& newLandGrid, CSMDoc::Document& document, void pushEditToCommand (const CSMWorld::LandHeightsColumn::DataType& newLandGrid, CSMDoc::Document& document,
CSMWorld::IdTable& landTable, std::string cellId); CSMWorld::IdTable& landTable, const std::string& cellId);
/// Push land normals edits to command macro /// Push land normals edits to command macro
void pushNormalsEditToCommand(const CSMWorld::LandNormalsColumn::DataType& newLandGrid, CSMDoc::Document& document, void pushNormalsEditToCommand(const CSMWorld::LandNormalsColumn::DataType& newLandGrid, CSMDoc::Document& document,
CSMWorld::IdTable& landTable, std::string cellId); CSMWorld::IdTable& landTable, const std::string& cellId);
/// Generate new land map LOD
void pushLodToCommand(const CSMWorld::LandMapLodColumn::DataType& newLandMapLod, CSMDoc::Document& document,
CSMWorld::IdTable& landTable, const std::string& cellId);
/// Create new cell and land if needed /// Create new cell and land if needed
bool allowLandShapeEditing(std::string textureFileName); bool allowLandShapeEditing(const std::string& textureFileName);
private: private:
std::string mCellId; std::string mCellId;
std::string mBrushTexture; std::string mBrushTexture;
int mBrushSize; int mBrushSize;
int mBrushShape; CSVWidget::BrushShape mBrushShape;
std::vector<std::pair<int, int>> mCustomBrushShape; std::vector<std::pair<int, int>> mCustomBrushShape;
CSVWidget::SceneToolShapeBrush *mShapeBrushScenetool; CSVWidget::SceneToolShapeBrush *mShapeBrushScenetool;
int mDragMode; int mDragMode;
@ -158,7 +163,7 @@ namespace CSVRender
public slots: public slots:
void setBrushSize(int brushSize); void setBrushSize(int brushSize);
void setBrushShape(int brushShape); void setBrushShape(CSVWidget::BrushShape brushShape);
void setShapeEditTool(int shapeEditTool); void setShapeEditTool(int shapeEditTool);
void setShapeEditToolStrength(int shapeEditToolStrength); void setShapeEditToolStrength(int shapeEditToolStrength);
}; };

View file

@ -128,13 +128,13 @@ namespace CSVRender
return abs(getThisHeight(col, row, heightData) - getDownHeight(col, row, heightData)); return abs(getThisHeight(col, row, heightData) - getDownHeight(col, row, heightData));
} }
bool TerrainStorage::LeftOrUpIsOverTheLimit(int col, int row, int heightWarningLimit, const ESM::Land::LandData *heightData) const bool TerrainStorage::leftOrUpIsOverTheLimit(int col, int row, int heightWarningLimit, const ESM::Land::LandData *heightData) const
{ {
return getHeightDifferenceToLeft(col, row, heightData) >= heightWarningLimit || return getHeightDifferenceToLeft(col, row, heightData) >= heightWarningLimit ||
getHeightDifferenceToUp(col, row, heightData) >= heightWarningLimit; getHeightDifferenceToUp(col, row, heightData) >= heightWarningLimit;
} }
bool TerrainStorage::RightOrDownIsOverTheLimit(int col, int row, int heightWarningLimit, const ESM::Land::LandData *heightData) const bool TerrainStorage::rightOrDownIsOverTheLimit(int col, int row, int heightWarningLimit, const ESM::Land::LandData *heightData) const
{ {
return getHeightDifferenceToRight(col, row, heightData) >= heightWarningLimit || return getHeightDifferenceToRight(col, row, heightData) >= heightWarningLimit ||
getHeightDifferenceToDown(col, row, heightData) >= heightWarningLimit; getHeightDifferenceToDown(col, row, heightData) >= heightWarningLimit;
@ -144,8 +144,8 @@ namespace CSVRender
{ {
// Highlight broken height changes // Highlight broken height changes
int heightWarningLimit = 1024; int heightWarningLimit = 1024;
if (((col > 0 && row > 0) && LeftOrUpIsOverTheLimit(col, row, heightWarningLimit, heightData)) || if (((col > 0 && row > 0) && leftOrUpIsOverTheLimit(col, row, heightWarningLimit, heightData)) ||
((col < ESM::Land::LAND_SIZE - 1 && row < ESM::Land::LAND_SIZE - 1) && RightOrDownIsOverTheLimit(col, row, heightWarningLimit, heightData))) ((col < ESM::Land::LAND_SIZE - 1 && row < ESM::Land::LAND_SIZE - 1) && rightOrDownIsOverTheLimit(col, row, heightWarningLimit, heightData)))
{ {
color.r() = 255; color.r() = 255;
color.g() = 0; color.g() = 0;

View file

@ -39,8 +39,8 @@ namespace CSVRender
int getHeightDifferenceToRight(int col, int row, const ESM::Land::LandData *heightData) const; int getHeightDifferenceToRight(int col, int row, const ESM::Land::LandData *heightData) const;
int getHeightDifferenceToUp(int col, int row, const ESM::Land::LandData *heightData) const; int getHeightDifferenceToUp(int col, int row, const ESM::Land::LandData *heightData) const;
int getHeightDifferenceToDown(int col, int row, const ESM::Land::LandData *heightData) const; int getHeightDifferenceToDown(int col, int row, const ESM::Land::LandData *heightData) const;
bool LeftOrUpIsOverTheLimit(int col, int row, int heightWarningLimit, const ESM::Land::LandData *heightData) const; bool leftOrUpIsOverTheLimit(int col, int row, int heightWarningLimit, const ESM::Land::LandData *heightData) const;
bool RightOrDownIsOverTheLimit(int col, int row, int heightWarningLimit, const ESM::Land::LandData *heightData) const; bool rightOrDownIsOverTheLimit(int col, int row, int heightWarningLimit, const ESM::Land::LandData *heightData) const;
void adjustColor(int col, int row, const ESM::Land::LandData *heightData, osg::Vec4ub& color) const override; void adjustColor(int col, int row, const ESM::Land::LandData *heightData, osg::Vec4ub& color) const override;
float getAlteredHeight(int col, int row) const override; float getAlteredHeight(int col, int row) const override;

View file

@ -0,0 +1,14 @@
#ifndef CSV_WIDGET_BRUSHSHAPES_H
#define CSV_WIDGET_BRUSHSHAPES_H
namespace CSVWidget
{
enum BrushShape
{
BrushShape_Point,
BrushShape_Square,
BrushShape_Circle,
BrushShape_Custom
};
}
#endif

View file

@ -21,6 +21,7 @@
#include <QApplication> #include <QApplication>
#include <QSizePolicy> #include <QSizePolicy>
#include "brushshapes.hpp"
#include "scenetool.hpp" #include "scenetool.hpp"
#include "../../model/doc/document.hpp" #include "../../model/doc/document.hpp"
@ -58,7 +59,7 @@ CSVWidget::ShapeBrushSizeControls::ShapeBrushSizeControls(const QString &title,
CSVWidget::ShapeBrushWindow::ShapeBrushWindow(CSMDoc::Document& document, QWidget *parent) CSVWidget::ShapeBrushWindow::ShapeBrushWindow(CSMDoc::Document& document, QWidget *parent)
: QFrame(parent, Qt::Popup), : QFrame(parent, Qt::Popup),
mBrushShape(BrushShape_Point), mBrushShape(CSVWidget::BrushShape_Point),
mBrushSize(1), mBrushSize(1),
mDocument(document) mDocument(document)
{ {
@ -169,7 +170,7 @@ CSVWidget::SceneToolShapeBrush::SceneToolShapeBrush (SceneToolbar *parent, const
mShapeBrushWindow(new ShapeBrushWindow(document, this)) mShapeBrushWindow(new ShapeBrushWindow(document, this))
{ {
setAcceptDrops(true); setAcceptDrops(true);
connect(mShapeBrushWindow, SIGNAL(passBrushShape(int)), this, SLOT(setButtonIcon(int))); connect(mShapeBrushWindow, SIGNAL(passBrushShape(CSVWidget::BrushShape)), this, SLOT(setButtonIcon(CSVWidget::BrushShape)));
setButtonIcon(mShapeBrushWindow->mBrushShape); setButtonIcon(mShapeBrushWindow->mBrushShape);
mPanel = new QFrame (this, Qt::Popup); mPanel = new QFrame (this, Qt::Popup);
@ -199,31 +200,31 @@ CSVWidget::SceneToolShapeBrush::SceneToolShapeBrush (SceneToolbar *parent, const
} }
void CSVWidget::SceneToolShapeBrush::setButtonIcon (int brushShape) void CSVWidget::SceneToolShapeBrush::setButtonIcon (CSVWidget::BrushShape brushShape)
{ {
QString tooltip = "Change brush settings <p>Currently selected: "; QString tooltip = "Change brush settings <p>Currently selected: ";
switch (brushShape) switch (brushShape)
{ {
case 0: case BrushShape_Point:
setIcon (QIcon (QPixmap (":scenetoolbar/brush-point"))); setIcon (QIcon (QPixmap (":scenetoolbar/brush-point")));
tooltip += mShapeBrushWindow->toolTipPoint; tooltip += mShapeBrushWindow->toolTipPoint;
break; break;
case 1: case BrushShape_Square:
setIcon (QIcon (QPixmap (":scenetoolbar/brush-square"))); setIcon (QIcon (QPixmap (":scenetoolbar/brush-square")));
tooltip += mShapeBrushWindow->toolTipSquare; tooltip += mShapeBrushWindow->toolTipSquare;
break; break;
case 2: case BrushShape_Circle:
setIcon (QIcon (QPixmap (":scenetoolbar/brush-circle"))); setIcon (QIcon (QPixmap (":scenetoolbar/brush-circle")));
tooltip += mShapeBrushWindow->toolTipCircle; tooltip += mShapeBrushWindow->toolTipCircle;
break; break;
case 3: case BrushShape_Custom:
setIcon (QIcon (QPixmap (":scenetoolbar/brush-custom"))); setIcon (QIcon (QPixmap (":scenetoolbar/brush-custom")));
tooltip += mShapeBrushWindow->toolTipCustom; tooltip += mShapeBrushWindow->toolTipCustom;

View file

@ -16,6 +16,7 @@
#include <QPushButton> #include <QPushButton>
#ifndef Q_MOC_RUN #ifndef Q_MOC_RUN
#include "brushshapes.hpp"
#include "scenetool.hpp" #include "scenetool.hpp"
#include "../../model/doc/document.hpp" #include "../../model/doc/document.hpp"
@ -54,24 +55,16 @@ namespace CSVWidget
public: public:
enum BrushShape
{
BrushShape_Point = 0,
BrushShape_Square = 1,
BrushShape_Circle = 2,
BrushShape_Custom = 3
};
ShapeBrushWindow(CSMDoc::Document& document, QWidget *parent = 0); ShapeBrushWindow(CSMDoc::Document& document, QWidget *parent = 0);
void configureButtonInitialSettings(QPushButton *button); void configureButtonInitialSettings(QPushButton *button);
const QString toolTipPoint = "Paint single point"; const QString toolTipPoint = "Paint single point";
const QString toolTipSquare = "Paint with square brush"; const QString toolTipSquare = "Paint with square brush";
const QString toolTipCircle = "Paint with circle brush"; const QString toolTipCircle = "Paint with circle brush";
const QString toolTipCustom = "Paint custom selection (not implemented yet)"; const QString toolTipCustom = "Paint with custom brush, defined by terrain selection";
private: private:
int mBrushShape; CSVWidget::BrushShape mBrushShape;
int mBrushSize; int mBrushSize;
CSMDoc::Document& mDocument; CSMDoc::Document& mDocument;
QGroupBox *mHorizontalGroupBox; QGroupBox *mHorizontalGroupBox;
@ -92,7 +85,7 @@ namespace CSVWidget
signals: signals:
void passBrushSize (int brushSize); void passBrushSize (int brushSize);
void passBrushShape(int brushShape); void passBrushShape(CSVWidget::BrushShape brushShape);
}; };
class SceneToolShapeBrush : public SceneTool class SceneToolShapeBrush : public SceneTool
@ -122,7 +115,7 @@ namespace CSVWidget
friend class CSVRender::TerrainShapeMode; friend class CSVRender::TerrainShapeMode;
public slots: public slots:
void setButtonIcon(int brushShape); void setButtonIcon(CSVWidget::BrushShape brushShape);
void clicked (const QModelIndex& index); void clicked (const QModelIndex& index);
virtual void activate(); virtual void activate();