From b84e41bd278c7b55755d93ae615f4b6b75f07141 Mon Sep 17 00:00:00 2001 From: unelsson Date: Sun, 22 Aug 2021 15:33:40 +0300 Subject: [PATCH] Avoid storing ref, dynamic cast worldspacewidget for safety --- apps/opencs/view/render/commands.cpp | 29 ++++++++++++++++--- apps/opencs/view/render/commands.hpp | 8 +++-- apps/opencs/view/render/terrainshapemode.cpp | 13 ++++++--- apps/opencs/view/render/terrainshapemode.hpp | 4 ++- .../opencs/view/render/terraintexturemode.cpp | 5 ++++ .../opencs/view/render/terraintexturemode.hpp | 4 ++- apps/opencs/view/render/worldspacewidget.hpp | 2 ++ 7 files changed, 53 insertions(+), 12 deletions(-) diff --git a/apps/opencs/view/render/commands.cpp b/apps/opencs/view/render/commands.cpp index 7b3760296..7afbd024a 100644 --- a/apps/opencs/view/render/commands.cpp +++ b/apps/opencs/view/render/commands.cpp @@ -1,19 +1,40 @@ #include "commands.hpp" +#include #include +#include "editmode.hpp" #include "terrainselection.hpp" +#include "terrainshapemode.hpp" +#include "terraintexturemode.hpp" +#include "worldspacewidget.hpp" -CSVRender::DrawTerrainSelectionCommand::DrawTerrainSelectionCommand(TerrainSelection& terrainSelection, QUndoCommand* parent) - : mTerrainSelection(terrainSelection) +CSVRender::DrawTerrainSelectionCommand::DrawTerrainSelectionCommand(WorldspaceWidget* worldspaceWidget, QUndoCommand* parent) + : mWorldspaceWidget(worldspaceWidget) { } void CSVRender::DrawTerrainSelectionCommand::redo() { - mTerrainSelection.update(); + if (CSVRender::WorldspaceWidget* worldspaceWidget = dynamic_cast (mWorldspaceWidget)) + { + if (CSVRender::TerrainShapeMode* terrainMode = dynamic_cast (worldspaceWidget->getEditMode()) ) + { + terrainMode->getTerrainSelection()->update(); + return; + } + } + Log(Debug::Warning) << "Error in redoing terrain selection"; } void CSVRender::DrawTerrainSelectionCommand::undo() { - mTerrainSelection.update(); + if (CSVRender::WorldspaceWidget* worldspaceWidget = dynamic_cast (mWorldspaceWidget)) + { + if (CSVRender::TerrainShapeMode* terrainMode = dynamic_cast (worldspaceWidget->getEditMode()) ) + { + terrainMode->getTerrainSelection()->update(); + return; + } + } + Log(Debug::Warning) << "Error in undoing terrain selection"; } diff --git a/apps/opencs/view/render/commands.hpp b/apps/opencs/view/render/commands.hpp index cdc389e33..6845785ec 100644 --- a/apps/opencs/view/render/commands.hpp +++ b/apps/opencs/view/render/commands.hpp @@ -3,6 +3,8 @@ #include +#include "worldspacewidget.hpp" + namespace CSVRender { class TerrainSelection; @@ -21,11 +23,13 @@ namespace CSVRender */ class DrawTerrainSelectionCommand : public QUndoCommand { + friend class WorldspaceWidget; + private: - TerrainSelection& mTerrainSelection; + WorldspaceWidget *mWorldspaceWidget; public: - DrawTerrainSelectionCommand(TerrainSelection& terrainSelection, QUndoCommand* parent = nullptr); + DrawTerrainSelectionCommand(WorldspaceWidget* worldspaceWidget, QUndoCommand* parent = nullptr); void redo() override; void undo() override; diff --git a/apps/opencs/view/render/terrainshapemode.cpp b/apps/opencs/view/render/terrainshapemode.cpp index 866ff69cd..050494495 100644 --- a/apps/opencs/view/render/terrainshapemode.cpp +++ b/apps/opencs/view/render/terrainshapemode.cpp @@ -287,7 +287,7 @@ void CSVRender::TerrainShapeMode::applyTerrainEditChanges() undoStack.beginMacro ("Edit shape and normal records"); // One command at the beginning of the macro for redrawing the terrain-selection grid when undoing the changes. - undoStack.push(new DrawTerrainSelectionCommand(*mTerrainShapeSelection)); + undoStack.push(new DrawTerrainSelectionCommand(&getWorldspaceWidget())); for(CSMWorld::CellCoordinates cellCoordinates: mAlteredCells) { @@ -358,7 +358,7 @@ void CSVRender::TerrainShapeMode::applyTerrainEditChanges() pushNormalsEditToCommand(landNormalsNew, document, landTable, cellId); } // One command at the end of the macro for redrawing the terrain-selection grid when redoing the changes. - undoStack.push(new DrawTerrainSelectionCommand(*mTerrainShapeSelection)); + undoStack.push(new DrawTerrainSelectionCommand(&getWorldspaceWidget())); undoStack.endMacro(); clearTransientEdits(); @@ -1049,7 +1049,7 @@ void CSVRender::TerrainShapeMode::handleSelection(int globalSelectionX, int glob */ if (xIsAtCellBorder && yIsAtCellBorder) { - /* + /* Handle the NW, NE, and SE corner vertices. NW corner: (+1, -1) offset to reach current cell. NE corner: (-1, -1) offset to reach current cell. @@ -1132,7 +1132,7 @@ void CSVRender::TerrainShapeMode::selectTerrainShapes(const std::pair& selectAction = CSMPrefs::get()["3D Scene Editing"]["primary-select-action"].toString(); else selectAction = CSMPrefs::get()["3D Scene Editing"]["secondary-select-action"].toString(); - + if (selectAction == "Select only") mTerrainShapeSelection->onlySelect(selections); else if (selectAction == "Add to selection") @@ -1444,6 +1444,11 @@ void CSVRender::TerrainShapeMode::mouseMoveEvent (QMouseEvent *event) mBrushDraw->hide(); } +std::shared_ptr CSVRender::TerrainShapeMode::getTerrainSelection() +{ + return mTerrainShapeSelection; +} + void CSVRender::TerrainShapeMode::setBrushSize(int brushSize) { mBrushSize = brushSize; diff --git a/apps/opencs/view/render/terrainshapemode.hpp b/apps/opencs/view/render/terrainshapemode.hpp index a88e60c9c..abc4b8aba 100644 --- a/apps/opencs/view/render/terrainshapemode.hpp +++ b/apps/opencs/view/render/terrainshapemode.hpp @@ -92,6 +92,8 @@ namespace CSVRender void dragMoveEvent (QDragMoveEvent *event) override; void mouseMoveEvent (QMouseEvent *event) override; + std::shared_ptr getTerrainSelection(); + private: /// Remove duplicates and sort mAlteredCells, then limitAlteredHeights forward and reverse @@ -176,7 +178,7 @@ namespace CSVRender int mDragMode = InteractionType_None; osg::Group* mParentNode; bool mIsEditing = false; - std::unique_ptr mTerrainShapeSelection; + std::shared_ptr mTerrainShapeSelection; int mTotalDiffY = 0; std::vector mAlteredCells; osg::Vec3d mEditingPos; diff --git a/apps/opencs/view/render/terraintexturemode.cpp b/apps/opencs/view/render/terraintexturemode.cpp index 4e267e942..dfcc29ae0 100644 --- a/apps/opencs/view/render/terraintexturemode.cpp +++ b/apps/opencs/view/render/terraintexturemode.cpp @@ -712,6 +712,11 @@ void CSVRender::TerrainTextureMode::mouseMoveEvent (QMouseEvent *event) mBrushDraw->hide(); } +std::shared_ptr CSVRender::TerrainTextureMode::getTerrainSelection() +{ + return mTerrainTextureSelection; +} + void CSVRender::TerrainTextureMode::setBrushSize(int brushSize) { diff --git a/apps/opencs/view/render/terraintexturemode.hpp b/apps/opencs/view/render/terraintexturemode.hpp index 31932df21..e0c6e4b40 100644 --- a/apps/opencs/view/render/terraintexturemode.hpp +++ b/apps/opencs/view/render/terraintexturemode.hpp @@ -85,6 +85,8 @@ namespace CSVRender void mouseMoveEvent (QMouseEvent *event) override; + std::shared_ptr getTerrainSelection(); + private: /// \brief Handle brush mechanics, maths regarding worldspace hit etc. void editTerrainTextureGrid (const WorldspaceHitResult& hit); @@ -115,7 +117,7 @@ namespace CSVRender int mDragMode; osg::Group* mParentNode; bool mIsEditing; - std::unique_ptr mTerrainTextureSelection; + std::shared_ptr mTerrainTextureSelection; const int cellSize {ESM::Land::REAL_SIZE}; const int landTextureSize {ESM::Land::LAND_TEXTURE_SIZE}; diff --git a/apps/opencs/view/render/worldspacewidget.hpp b/apps/opencs/view/render/worldspacewidget.hpp index 5e224b380..d73a6c06e 100644 --- a/apps/opencs/view/render/worldspacewidget.hpp +++ b/apps/opencs/view/render/worldspacewidget.hpp @@ -49,6 +49,8 @@ namespace CSVRender { Q_OBJECT + friend class DrawTerrainSelectionCommand; + CSVWidget::SceneToolToggle2 *mSceneElements; CSVWidget::SceneToolRun *mRun; CSMDoc::Document& mDocument;