From 731e5b57f5b13923ec3b512f7ab9cc9a7b0fa93f Mon Sep 17 00:00:00 2001 From: Nelsson Huotari Date: Sat, 15 Feb 2020 16:09:49 +0200 Subject: [PATCH] Tool outline for terraintexturemode and square shape. Various fixes. --- apps/opencs/view/render/brushdraw.cpp | 100 ++++++++++++++++-- apps/opencs/view/render/brushdraw.hpp | 14 ++- apps/opencs/view/render/terrainshapemode.cpp | 5 +- .../opencs/view/render/terraintexturemode.cpp | 44 +++++--- .../opencs/view/render/terraintexturemode.hpp | 18 ++-- .../view/widget/scenetooltexturebrush.cpp | 23 ++-- .../view/widget/scenetooltexturebrush.hpp | 11 +- 7 files changed, 162 insertions(+), 53 deletions(-) diff --git a/apps/opencs/view/render/brushdraw.cpp b/apps/opencs/view/render/brushdraw.cpp index a2874bd31e..b963b09f55 100644 --- a/apps/opencs/view/render/brushdraw.cpp +++ b/apps/opencs/view/render/brushdraw.cpp @@ -1,5 +1,7 @@ #include "brushdraw.hpp" +#include + #include #include #include @@ -9,29 +11,33 @@ #include +#include "../widget/brushshapes.hpp" + #include "mask.hpp" -CSVRender::BrushDraw::BrushDraw(osg::Group* parentNode) : +CSVRender::BrushDraw::BrushDraw(osg::ref_ptr parentNode, bool textureMode) : mParentNode(parentNode) { mBrushDrawNode = new osg::Group(); mGeometry = new osg::Geometry(); mBrushDrawNode->addChild(mGeometry); mParentNode->addChild(mBrushDrawNode); + if (textureMode) mLandSizeFactor = ESM::Land::REAL_SIZE / ESM::Land::LAND_TEXTURE_SIZE / 2; + else mLandSizeFactor = ESM::Land::REAL_SIZE / ESM::Land::LAND_SIZE / 2; } CSVRender::BrushDraw::~BrushDraw() { - if (mBrushDrawNode->containsNode(mGeometry)) mBrushDrawNode->removeChild(mGeometry); - if (mParentNode->containsNode(mBrushDrawNode)) mParentNode->removeChild(mBrushDrawNode); + mBrushDrawNode->removeChild(mGeometry); + mParentNode->removeChild(mBrushDrawNode); } float CSVRender::BrushDraw::getIntersectionHeight (const osg::Vec3d& point) { osg::Vec3d start = point; osg::Vec3d end = point; - start.z() += 8000.0f; // these numbers need fixing - end.z() -= 8000.0f; + start.z() = std::numeric_limits::max(); + end.z() = std::numeric_limits::min(); osg::Vec3d direction = end - start; // Get intersection @@ -60,13 +66,67 @@ float CSVRender::BrushDraw::getIntersectionHeight (const osg::Vec3d& point) return 0.0f; } +void CSVRender::BrushDraw::buildPointGeometry(const float& radius, const osg::Vec3d& point) +{ + // Not implemented +} -void CSVRender::BrushDraw::buildGeometry(const float& radius, const osg::Vec3d& point, int amountOfPoints) +void CSVRender::BrushDraw::buildSquareGeometry(const float& radius, const osg::Vec3d& point) { osg::ref_ptr geom = new osg::Geometry(); osg::ref_ptr vertices (new osg::Vec3Array()); osg::ref_ptr colors (new osg::Vec4Array()); + std::vector corners; + const float brushOutLineHeight (200.0f); + + corners.push_back(osg::Vec3d(point.x() - radius, point.y() - radius, point.z())); + corners.push_back(osg::Vec3d(point.x() + radius, point.y() - radius, point.z())); + corners.push_back(osg::Vec3d(point.x() + radius, point.y() + radius, point.z())); + corners.push_back(osg::Vec3d(point.x() - radius, point.y() + radius, point.z())); + corners.push_back(osg::Vec3d(point.x() - radius, point.y() - radius, point.z())); + + for (const auto& point : corners) + { + vertices->push_back(osg::Vec3d( + point.x(), + point.y(), + getIntersectionHeight(osg::Vec3d( + point.x(), + point.y(), + point.z()) ))); + colors->push_back(osg::Vec4f( + 50.0f, + 50.0f, + 50.0f, + 100.0f)); + vertices->push_back(osg::Vec3d( + point.x(), + point.y(), + getIntersectionHeight(osg::Vec3d( + point.x(), + point.y(), + point.z())) + brushOutLineHeight)); + colors->push_back(osg::Vec4f( + 50.0f, + 50.0f, + 50.0f, + 100.0f)); + } + + geom->setVertexArray(vertices); + geom->setColorArray(colors, osg::Array::BIND_PER_VERTEX); + geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::TRIANGLE_STRIP, 0, (10 + 2) - 2)); + mGeometry = geom; +} + +void CSVRender::BrushDraw::buildCircleGeometry(const float& radius, const osg::Vec3d& point) +{ + osg::ref_ptr geom = new osg::Geometry(); + osg::ref_ptr vertices (new osg::Vec3Array()); + osg::ref_ptr colors (new osg::Vec4Array()); + const int amountOfPoints = (osg::PI * 2.0f) * radius / 20; const float step ((osg::PI * 2.0f) / static_cast(amountOfPoints)); + const float brushOutLineHeight (200.0f); for (int i = 0; i < amountOfPoints + 2; i++) { @@ -90,7 +150,7 @@ void CSVRender::BrushDraw::buildGeometry(const float& radius, const osg::Vec3d& getIntersectionHeight(osg::Vec3d( point.x() + radius * cosf(angle), point.y() + radius * sinf(angle), - point.z()) ) + 200.0f)); + point.z()) ) + brushOutLineHeight)); colors->push_back(osg::Vec4f( 50.0f, 50.0f, @@ -104,14 +164,34 @@ void CSVRender::BrushDraw::buildGeometry(const float& radius, const osg::Vec3d& mGeometry = geom; } -void CSVRender::BrushDraw::update(osg::Vec3d point, int brushSize) +void CSVRender::BrushDraw::buildCustomGeometry(const float& radius, const osg::Vec3d& point) +{ + // Not implemented +} + +void CSVRender::BrushDraw::update(osg::Vec3d point, int brushSize, CSVWidget::BrushShape toolShape) { if (mBrushDrawNode->containsNode(mGeometry)) mBrushDrawNode->removeChild(mGeometry); mBrushDrawNode->setNodeMask (Mask_EditModeCursor); float radius = static_cast(brushSize * mLandSizeFactor); - int amountOfPoints = (osg::PI * 2.0f) * radius / 20; - buildGeometry(radius, point, amountOfPoints); + switch (toolShape) + { + case (CSVWidget::BrushShape_Point) : + buildSquareGeometry(1, point); + //buildPointGeometry(radius, point); + break; + case (CSVWidget::BrushShape_Square) : + buildSquareGeometry(radius, point); + break; + case (CSVWidget::BrushShape_Circle) : + buildCircleGeometry(radius, point); + break; + case (CSVWidget::BrushShape_Custom) : + buildSquareGeometry(1, point); + //buildCustomGeometry + break; + } osg::BlendFunc* blendFunc = new osg::BlendFunc(osg::BlendFunc::SRC_ALPHA, osg::BlendFunc::ONE_MINUS_SRC_ALPHA); mGeometry->getOrCreateStateSet()->setAttributeAndModes(blendFunc); diff --git a/apps/opencs/view/render/brushdraw.hpp b/apps/opencs/view/render/brushdraw.hpp index 5e0a095cef..6ecfccde7d 100644 --- a/apps/opencs/view/render/brushdraw.hpp +++ b/apps/opencs/view/render/brushdraw.hpp @@ -5,26 +5,30 @@ #include #include +#include "../widget/brushshapes.hpp" namespace CSVRender { class BrushDraw { public: - BrushDraw(osg::Group* parentNode); + BrushDraw(osg::ref_ptr parentNode, bool textureMode = false); ~BrushDraw(); - void update(osg::Vec3d point, int brushSize); + void update(osg::Vec3d point, int brushSize, CSVWidget::BrushShape toolShape); void hide(); private: - void buildGeometry(const float& radius, const osg::Vec3d& point, int amountOfPoints); + void buildPointGeometry(const float& radius, const osg::Vec3d& point); + void buildSquareGeometry(const float& radius, const osg::Vec3d& point); + void buildCircleGeometry(const float& radius, const osg::Vec3d& point); + void buildCustomGeometry(const float& radius, const osg::Vec3d& point); float getIntersectionHeight (const osg::Vec3d& point); - osg::Group* mParentNode; + osg::ref_ptr mParentNode; osg::ref_ptr mBrushDrawNode; osg::ref_ptr mGeometry; - float mLandSizeFactor = ESM::Land::REAL_SIZE / ESM::Land::LAND_SIZE / 2; + float mLandSizeFactor; }; } diff --git a/apps/opencs/view/render/terrainshapemode.cpp b/apps/opencs/view/render/terrainshapemode.cpp index 53fe92f8e2..31292645d7 100644 --- a/apps/opencs/view/render/terrainshapemode.cpp +++ b/apps/opencs/view/render/terrainshapemode.cpp @@ -93,6 +93,9 @@ void CSVRender::TerrainShapeMode::deactivate(CSVWidget::SceneToolbar* toolbar) mTerrainShapeSelection.reset(); } + if (mBrushDraw) + mBrushDraw.reset(); + EditMode::deactivate(toolbar); } @@ -1395,7 +1398,7 @@ void CSVRender::TerrainShapeMode::dragMoveEvent (QDragMoveEvent *event) void CSVRender::TerrainShapeMode::mouseMoveEvent (QMouseEvent *event) { WorldspaceHitResult hit = getWorldspaceWidget().mousePick(event->pos(), getInteractionMask()); - if (hit.hit && mBrushDraw && !(mShapeEditTool == ShapeEditTool_Drag && mIsEditing)) mBrushDraw->update(hit.worldPos, mBrushSize); + if (hit.hit && mBrushDraw && !(mShapeEditTool == ShapeEditTool_Drag && mIsEditing)) mBrushDraw->update(hit.worldPos, mBrushSize, mBrushShape); if (!hit.hit && !(mShapeEditTool == ShapeEditTool_Drag && mIsEditing)) mBrushDraw->hide(); } diff --git a/apps/opencs/view/render/terraintexturemode.cpp b/apps/opencs/view/render/terraintexturemode.cpp index e25d65a892..c1bbb28257 100644 --- a/apps/opencs/view/render/terraintexturemode.cpp +++ b/apps/opencs/view/render/terraintexturemode.cpp @@ -32,7 +32,9 @@ #include "../../model/world/resourcetable.hpp" #include "../../model/world/tablemimedata.hpp" #include "../../model/world/universalid.hpp" +#include "../widget/brushshapes.hpp" +#include "brushdraw.hpp" #include "editmode.hpp" #include "pagedworldspacewidget.hpp" #include "object.hpp" // Something small needed regarding pointers from here () @@ -50,6 +52,12 @@ CSVRender::TerrainTextureMode::TerrainTextureMode (WorldspaceWidget *worldspaceW { } +CSVRender::TerrainTextureMode::~TerrainTextureMode () +{ + if (mBrushDraw) + mBrushDraw.reset(); +} + void CSVRender::TerrainTextureMode::activate(CSVWidget::SceneToolbar* toolbar) { if(!mTextureBrushScenetool) @@ -57,7 +65,7 @@ void CSVRender::TerrainTextureMode::activate(CSVWidget::SceneToolbar* toolbar) mTextureBrushScenetool = new CSVWidget::SceneToolTextureBrush (toolbar, "scenetooltexturebrush", getWorldspaceWidget().getDocument()); connect(mTextureBrushScenetool, SIGNAL (clicked()), mTextureBrushScenetool, SLOT (activate())); connect(mTextureBrushScenetool->mTextureBrushWindow, SIGNAL(passBrushSize(int)), this, SLOT(setBrushSize(int))); - connect(mTextureBrushScenetool->mTextureBrushWindow, SIGNAL(passBrushShape(int)), this, SLOT(setBrushShape(int))); + connect(mTextureBrushScenetool->mTextureBrushWindow, SIGNAL(passBrushShape(CSVWidget::BrushShape)), this, SLOT(setBrushShape(CSVWidget::BrushShape))); connect(mTextureBrushScenetool->mTextureBrushWindow->mSizeSliders->mBrushSizeSlider, SIGNAL(valueChanged(int)), this, SLOT(setBrushSize(int))); connect(mTextureBrushScenetool, SIGNAL(passTextureId(std::string)), this, SLOT(setBrushTexture(std::string))); connect(mTextureBrushScenetool->mTextureBrushWindow, SIGNAL(passTextureId(std::string)), this, SLOT(setBrushTexture(std::string))); @@ -72,6 +80,9 @@ void CSVRender::TerrainTextureMode::activate(CSVWidget::SceneToolbar* toolbar) mTerrainTextureSelection.reset(new TerrainSelection(mParentNode, &getWorldspaceWidget(), TerrainSelectionType::Texture)); } + if (!mBrushDraw) + mBrushDraw.reset(new BrushDraw(mParentNode, true)); + EditMode::activate(toolbar); toolbar->addTool (mTextureBrushScenetool); } @@ -90,6 +101,9 @@ void CSVRender::TerrainTextureMode::deactivate(CSVWidget::SceneToolbar* toolbar) mTerrainTextureSelection.reset(); } + if (mBrushDraw) + mBrushDraw.reset(); + EditMode::deactivate(toolbar); } @@ -332,7 +346,7 @@ void CSVRender::TerrainTextureMode::editTerrainTextureGrid(const WorldspaceHitRe int r = mBrushSize / 2 + 1; int distance = 0; - if (mBrushShape == 0) + if (mBrushShape == CSVWidget::BrushShape_Point) { CSMWorld::LandTexturesColumn::DataType newTerrainPointer = landTable.data(landTable.getModelIndex(mCellId, textureColumn)).value(); CSMWorld::LandTexturesColumn::DataType newTerrain(newTerrainPointer); @@ -344,7 +358,7 @@ void CSVRender::TerrainTextureMode::editTerrainTextureGrid(const WorldspaceHitRe } } - if (mBrushShape == 1) + if (mBrushShape == CSVWidget::BrushShape_Square) { int upperLeftCellX = cellX - std::floor(r / landTextureSize); int upperLeftCellY = cellY - std::floor(r / landTextureSize); @@ -394,7 +408,7 @@ void CSVRender::TerrainTextureMode::editTerrainTextureGrid(const WorldspaceHitRe } } - if (mBrushShape == 2) + if (mBrushShape == CSVWidget::BrushShape_Circle) { int upperLeftCellX = cellX - std::floor(r / landTextureSize); int upperLeftCellY = cellY - std::floor(r / landTextureSize); @@ -454,7 +468,7 @@ void CSVRender::TerrainTextureMode::editTerrainTextureGrid(const WorldspaceHitRe } } - if (mBrushShape == 3) + if (mBrushShape == CSVWidget::BrushShape_Custom) { CSMWorld::LandTexturesColumn::DataType newTerrainPointer = landTable.data(landTable.getModelIndex(mCellId, textureColumn)).value(); CSMWorld::LandTexturesColumn::DataType newTerrain(newTerrainPointer); @@ -506,12 +520,12 @@ void CSVRender::TerrainTextureMode::selectTerrainTextures(const std::pair> selections; - if (mBrushShape == 0) + if (mBrushShape == CSVWidget::BrushShape_Point) { if (isInCellSelection(texCoords.first, texCoords.second)) selections.emplace_back(texCoords); } - if (mBrushShape == 1) + if (mBrushShape == CSVWidget::BrushShape_Square) { for (int i = -r; i <= r; i++) { @@ -527,7 +541,7 @@ void CSVRender::TerrainTextureMode::selectTerrainTextures(const std::pairpos(), getInteractionMask()); + if (hit.hit && mBrushDraw) mBrushDraw->update(hit.worldPos, mBrushSize, mBrushShape); + if (!hit.hit) mBrushDraw->hide(); +} + void CSVRender::TerrainTextureMode::setBrushSize(int brushSize) { mBrushSize = brushSize; } -void CSVRender::TerrainTextureMode::setBrushShape(int brushShape) +void CSVRender::TerrainTextureMode::setBrushShape(CSVWidget::BrushShape brushShape) { mBrushShape = brushShape; //Set custom brush shape - if (mBrushShape == 3 && !mTerrainTextureSelection->getTerrainSelection().empty()) + if (mBrushShape == CSVWidget::BrushShape_Custom && !mTerrainTextureSelection->getTerrainSelection().empty()) { auto terrainSelection = mTerrainTextureSelection->getTerrainSelection(); int selectionCenterX = 0; diff --git a/apps/opencs/view/render/terraintexturemode.hpp b/apps/opencs/view/render/terraintexturemode.hpp index 3b94097ee9..cc77bb331b 100644 --- a/apps/opencs/view/render/terraintexturemode.hpp +++ b/apps/opencs/view/render/terraintexturemode.hpp @@ -17,6 +17,8 @@ #include "../../model/world/commands.hpp" #include "../../model/world/idtable.hpp" #include "../../model/world/landtexture.hpp" +#include "../widget/brushshapes.hpp" +#include "brushdraw.hpp" #endif #include "terrainselection.hpp" @@ -50,6 +52,7 @@ namespace CSVRender /// \brief Editmode for terrain texture grid TerrainTextureMode(WorldspaceWidget*, osg::Group* parentNode, QWidget* parent = nullptr); + ~TerrainTextureMode(); void primaryOpenPressed (const WorldspaceHitResult& hit) final; @@ -104,14 +107,15 @@ namespace CSVRender bool allowLandTextureEditing(std::string textureFileName); std::string mCellId; - std::string mBrushTexture; - int mBrushSize; - int mBrushShape; + std::string mBrushTexture = "L0#0"; + int mBrushSize = 1; + CSVWidget::BrushShape mBrushShape = CSVWidget::BrushShape_Point; + std::unique_ptr mBrushDraw; std::vector> mCustomBrushShape; - CSVWidget::SceneToolTextureBrush *mTextureBrushScenetool; - int mDragMode; + CSVWidget::SceneToolTextureBrush *mTextureBrushScenetool = nullptr; + int mDragMode = InteractionType_None; osg::Group* mParentNode; - bool mIsEditing; + bool mIsEditing = false; std::unique_ptr mTerrainTextureSelection; const int cellSize {ESM::Land::REAL_SIZE}; @@ -123,7 +127,7 @@ namespace CSVRender public slots: void handleDropEvent(QDropEvent *event); void setBrushSize(int brushSize); - void setBrushShape(int brushShape); + void setBrushShape(CSVWidget::BrushShape brushShape); void setBrushTexture(std::string brushShape); }; } diff --git a/apps/opencs/view/widget/scenetooltexturebrush.cpp b/apps/opencs/view/widget/scenetooltexturebrush.cpp index 4081872795..0a1ed66835 100644 --- a/apps/opencs/view/widget/scenetooltexturebrush.cpp +++ b/apps/opencs/view/widget/scenetooltexturebrush.cpp @@ -57,9 +57,6 @@ CSVWidget::BrushSizeControls::BrushSizeControls(const QString &title, QWidget *p CSVWidget::TextureBrushWindow::TextureBrushWindow(CSMDoc::Document& document, QWidget *parent) : QFrame(parent, Qt::Popup), - mBrushShape(0), - mBrushSize(1), - mBrushTexture("L0#0"), mDocument(document) { mBrushTextureLabel = "Selected texture: " + mBrushTexture + " "; @@ -207,10 +204,10 @@ void CSVWidget::TextureBrushWindow::setBrushSize(int brushSize) void CSVWidget::TextureBrushWindow::setBrushShape() { - if(mButtonPoint->isChecked()) mBrushShape = 0; - if(mButtonSquare->isChecked()) mBrushShape = 1; - if(mButtonCircle->isChecked()) mBrushShape = 2; - if(mButtonCustom->isChecked()) mBrushShape = 3; + if(mButtonPoint->isChecked()) mBrushShape = CSVWidget::BrushShape_Point; + if(mButtonSquare->isChecked()) mBrushShape = CSVWidget::BrushShape_Square; + if(mButtonCircle->isChecked()) mBrushShape = CSVWidget::BrushShape_Circle; + if(mButtonCustom->isChecked()) mBrushShape = CSVWidget::BrushShape_Custom; emit passBrushShape(mBrushShape); } @@ -228,7 +225,7 @@ CSVWidget::SceneToolTextureBrush::SceneToolTextureBrush (SceneToolbar *parent, c mBrushHistory[0] = "L0#0"; setAcceptDrops(true); - connect(mTextureBrushWindow, SIGNAL(passBrushShape(int)), this, SLOT(setButtonIcon(int))); + connect(mTextureBrushWindow, SIGNAL(passBrushShape(CSVWidget::BrushShape)), this, SLOT(setButtonIcon(CSVWidget::BrushShape))); setButtonIcon(mTextureBrushWindow->mBrushShape); mPanel = new QFrame (this, Qt::Popup); @@ -258,31 +255,31 @@ CSVWidget::SceneToolTextureBrush::SceneToolTextureBrush (SceneToolbar *parent, c } -void CSVWidget::SceneToolTextureBrush::setButtonIcon (int brushShape) +void CSVWidget::SceneToolTextureBrush::setButtonIcon (CSVWidget::BrushShape brushShape) { QString tooltip = "Change brush settings

Currently selected: "; switch (brushShape) { - case 0: + case BrushShape_Point: setIcon (QIcon (QPixmap (":scenetoolbar/brush-point"))); tooltip += mTextureBrushWindow->toolTipPoint; break; - case 1: + case BrushShape_Square: setIcon (QIcon (QPixmap (":scenetoolbar/brush-square"))); tooltip += mTextureBrushWindow->toolTipSquare; break; - case 2: + case BrushShape_Circle: setIcon (QIcon (QPixmap (":scenetoolbar/brush-circle"))); tooltip += mTextureBrushWindow->toolTipCircle; break; - case 3: + case BrushShape_Custom: setIcon (QIcon (QPixmap (":scenetoolbar/brush-custom"))); tooltip += mTextureBrushWindow->toolTipCustom; diff --git a/apps/opencs/view/widget/scenetooltexturebrush.hpp b/apps/opencs/view/widget/scenetooltexturebrush.hpp index 80e9a93828..5f5ccc6b1c 100644 --- a/apps/opencs/view/widget/scenetooltexturebrush.hpp +++ b/apps/opencs/view/widget/scenetooltexturebrush.hpp @@ -15,6 +15,7 @@ #include #ifndef Q_MOC_RUN +#include "brushshapes.hpp" #include "scenetool.hpp" #include "../../model/doc/document.hpp" @@ -65,9 +66,9 @@ namespace CSVWidget const QString toolTipCustom = "Paint custom selection (not implemented yet)"; private: - int mBrushShape; - int mBrushSize; - std::string mBrushTexture; + CSVWidget::BrushShape mBrushShape = CSVWidget::BrushShape_Point; + int mBrushSize = 1; + std::string mBrushTexture = "L0#0"; CSMDoc::Document& mDocument; QLabel *mSelectedBrush; QGroupBox *mHorizontalGroupBox; @@ -88,7 +89,7 @@ namespace CSVWidget signals: void passBrushSize (int brushSize); - void passBrushShape(int brushShape); + void passBrushShape(CSVWidget::BrushShape brushShape); void passTextureId(std::string brushTexture); }; @@ -120,7 +121,7 @@ namespace CSVWidget friend class CSVRender::TerrainTextureMode; public slots: - void setButtonIcon(int brushShape); + void setButtonIcon(CSVWidget::BrushShape brushShape); void updateBrushHistory (const std::string& mBrushTexture); void clicked (const QModelIndex& index); virtual void activate();