1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-01-20 16:23:52 +00:00
openmw/apps/opencs/view/render/terrainshapemode.hpp
psi29a 716eebe616 Merge branch 'terrainselectioncrashfix' into 'openmw-47'
Fix terrain selection crash

See merge request OpenMW/openmw!1165

(cherry picked from commit ec4e3b04a7)

b84e41bd Avoid storing ref, dynamic cast worldspacewidget for safety
d62ddc00 Use QPointer to detect object existence, less verbose debug messages
cb42b528 Remove friend, make getEditMode public to allow editmode testing.
4b148180 Restucture code
08f7c73e Fix text
2021-08-22 19:22:54 +00:00

200 lines
8.4 KiB
C++

#ifndef CSV_RENDER_TERRAINSHAPEMODE_H
#define CSV_RENDER_TERRAINSHAPEMODE_H
#include "editmode.hpp"
#include <string>
#include <memory>
#include <QWidget>
#include <QEvent>
#ifndef Q_MOC_RUN
#include "../../model/world/data.hpp"
#include "../../model/world/land.hpp"
#include "../../model/doc/document.hpp"
#include "../../model/world/commands.hpp"
#include "../../model/world/idtable.hpp"
#include "../../model/world/landtexture.hpp"
#include "../widget/brushshapes.hpp"
#endif
#include "brushdraw.hpp"
#include "terrainselection.hpp"
namespace CSVWidget
{
class SceneToolShapeBrush;
}
namespace CSVRender
{
class PagedWorldspaceWidget;
/// \brief EditMode for handling the terrain shape editing
class TerrainShapeMode : public EditMode
{
Q_OBJECT
public:
enum InteractionType
{
InteractionType_PrimaryEdit,
InteractionType_PrimarySelect,
InteractionType_SecondaryEdit,
InteractionType_SecondarySelect,
InteractionType_None
};
enum ShapeEditTool
{
ShapeEditTool_Drag = 0,
ShapeEditTool_PaintToRaise = 1,
ShapeEditTool_PaintToLower = 2,
ShapeEditTool_Smooth = 3,
ShapeEditTool_Flatten = 4
};
/// Editmode for terrain shape grid
TerrainShapeMode(WorldspaceWidget*, osg::Group* parentNode, QWidget* parent = nullptr);
void primaryOpenPressed (const WorldspaceHitResult& hit) override;
/// Create single command for one-click shape editing
void primaryEditPressed (const WorldspaceHitResult& hit) override;
/// Open brush settings window
void primarySelectPressed(const WorldspaceHitResult&) override;
void secondarySelectPressed(const WorldspaceHitResult&) override;
void activate(CSVWidget::SceneToolbar*) override;
void deactivate(CSVWidget::SceneToolbar*) override;
/// Start shape editing command macro
bool primaryEditStartDrag (const QPoint& pos) override;
bool secondaryEditStartDrag (const QPoint& pos) override;
bool primarySelectStartDrag (const QPoint& pos) override;
bool secondarySelectStartDrag (const QPoint& pos) override;
/// Handle shape edit behavior during dragging
void drag (const QPoint& pos, int diffX, int diffY, double speedFactor) override;
/// End shape editing command macro
void dragCompleted(const QPoint& pos) override;
/// Cancel shape editing, and reset all pending changes
void dragAborted() override;
void dragWheel (int diff, double speedFactor) override;
void dragMoveEvent (QDragMoveEvent *event) override;
void mouseMoveEvent (QMouseEvent *event) override;
std::shared_ptr<TerrainSelection> getTerrainSelection();
private:
/// 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();
/// Handle brush mechanics for shape editing
void editTerrainShapeGrid (const std::pair<int, int>& vertexCoords, bool dragOperation);
/// Calculate height, when aiming for bump-shaped terrain change
float calculateBumpShape(float distance, int radius, float height);
/// set the target height for flatten tool
void setFlattenToolTargetHeight(const WorldspaceHitResult& hit);
/// Do a single height alteration for transient shape edit map
void alterHeight(const CSMWorld::CellCoordinates& cellCoords, int inCellX, int inCellY, float alteredHeight, bool useTool = true);
/// Do a single smoothing height alteration for transient shape edit map
void smoothHeight(const CSMWorld::CellCoordinates& cellCoords, int inCellX, int inCellY, int toolStrength);
/// Do a single flattening height alteration for transient shape edit map
void flattenHeight(const CSMWorld::CellCoordinates& cellCoords, int inCellX, int inCellY, int toolStrength, int targetHeight);
/// Get altered height values around one vertex
void updateKeyHeightValues(const CSMWorld::CellCoordinates& cellCoords, int inCellX, int inCellY, float* thisHeight,
float* thisAlteredHeight, float* leftHeight, float* leftAlteredHeight, float* upHeight, float* upAlteredHeight,
float* rightHeight, float* rightAlteredHeight, float* downHeight, float* downAlteredHeight);
///Limit steepness based on either X or Y and return false if steepness is limited
void compareAndLimit(const CSMWorld::CellCoordinates& cellCoords, int inCellX, int inCellY, float* limitedAlteredHeightXAxis,
float* limitedAlteredHeightYAxis, bool* steepnessIsWithinLimits);
/// 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);
/// Select vertex at global selection coordinate
void handleSelection(int globalSelectionX, int globalSelectionY, std::vector<std::pair<int, int>>* selections);
/// Handle brush mechanics for terrain shape selection
void selectTerrainShapes (const std::pair<int, int>& vertexCoords, unsigned char selectMode, bool dragOperation);
/// Push terrain shape edits to command macro
void pushEditToCommand (const CSMWorld::LandHeightsColumn::DataType& newLandGrid, CSMDoc::Document& document,
CSMWorld::IdTable& landTable, const std::string& cellId);
/// Push land normals edits to command macro
void pushNormalsEditToCommand(const CSMWorld::LandNormalsColumn::DataType& newLandGrid, CSMDoc::Document& document,
CSMWorld::IdTable& landTable, const std::string& cellId);
bool noCell(const std::string& cellId);
bool noLand(const std::string& cellId);
bool noLandLoaded(const std::string& cellId);
bool isLandLoaded(const std::string& cellId);
/// Create new blank height record and new normals, if there are valid adjancent cell, take sample points and set the average height based on that
void createNewLandData(const CSMWorld::CellCoordinates& cellCoords);
/// Create new cell and land if needed, only user tools may ask for opening new cells (useTool == false is for automated land changes)
bool allowLandShapeEditing(const std::string& textureFileName, bool useTool = true);
/// Bind the edging vertice to the values of the adjancent cells
void fixEdges(CSMWorld::CellCoordinates cellCoords);
std::string mBrushTexture;
int mBrushSize = 1;
CSVWidget::BrushShape mBrushShape = CSVWidget::BrushShape_Point;
std::unique_ptr<BrushDraw> mBrushDraw;
std::vector<std::pair<int, int>> mCustomBrushShape;
CSVWidget::SceneToolShapeBrush *mShapeBrushScenetool = nullptr;
int mDragMode = InteractionType_None;
osg::Group* mParentNode;
bool mIsEditing = false;
std::shared_ptr<TerrainSelection> mTerrainShapeSelection;
int mTotalDiffY = 0;
std::vector<CSMWorld::CellCoordinates> mAlteredCells;
osg::Vec3d mEditingPos;
int mShapeEditTool = ShapeEditTool_Drag;
int mShapeEditToolStrength = 8;
int mTargetHeight = 0;
PagedWorldspaceWidget& getPagedWorldspaceWidget();
public slots:
void setBrushSize(int brushSize);
void setBrushShape(CSVWidget::BrushShape brushShape);
void setShapeEditTool(int shapeEditTool);
void setShapeEditToolStrength(int shapeEditToolStrength);
};
}
#endif