diff --git a/src/app/puzzle/puzzlemainwindow.cpp b/src/app/puzzle/puzzlemainwindow.cpp index 83375cba9..b76bcb9b0 100644 --- a/src/app/puzzle/puzzlemainwindow.cpp +++ b/src/app/puzzle/puzzlemainwindow.cpp @@ -200,6 +200,7 @@ VPuzzlePiece* PuzzleMainWindow::CreatePiece(const VLayoutPiece &rawPiece) // connect(piece, &VPuzzlePiece::SelectionChanged, this, &PuzzleMainWindow::on_PieceSelectionChanged); connect(piece, &VPuzzlePiece::PositionChanged, this, &PuzzleMainWindow::on_PiecePositionChanged); + connect(piece, &VPuzzlePiece::RotationChanged, this, &PuzzleMainWindow::on_PieceRotationChanged); return piece; @@ -892,3 +893,15 @@ void PuzzleMainWindow::on_PiecePositionChanged() SetDoubleSpinBoxValue(ui->doubleSpinBoxCurrentPieceBoxPositionY, UnitConvertor(pos.y(), Unit::Px, m_layout->GetUnit())); } } + +//--------------------------------------------------------------------------------------------------------------------- +void PuzzleMainWindow::on_PieceRotationChanged() +{ + if(m_selectedPieces.count() == 1) + { + VPuzzlePiece *piece = m_selectedPieces.first(); + qreal angle = piece->GetRotation(); + + SetDoubleSpinBoxValue(ui->doubleSpinBoxCurrentPieceAngle, angle); + } +} diff --git a/src/app/puzzle/puzzlemainwindow.h b/src/app/puzzle/puzzlemainwindow.h index 8d5015a4e..4ffa3f29c 100644 --- a/src/app/puzzle/puzzlemainwindow.h +++ b/src/app/puzzle/puzzlemainwindow.h @@ -373,6 +373,11 @@ private slots: */ void on_PiecePositionChanged(); + /** + * @brief on_PieceRotationChanged When the current piece rotation has changed + */ + void on_PieceRotationChanged(); + }; #endif // PUZZLEMAINWINDOW_H diff --git a/src/app/puzzle/share/resources/puzzleicon.qrc b/src/app/puzzle/share/resources/puzzleicon.qrc index fb33ba546..809e972be 100644 --- a/src/app/puzzle/share/resources/puzzleicon.qrc +++ b/src/app/puzzle/share/resources/puzzleicon.qrc @@ -9,5 +9,6 @@ puzzleicon/64x64/iconPortrait.png puzzleicon/64x64/iconGrainlineVertical.png puzzleicon/64x64/iconGrainlineHorizontal.png + puzzleicon/64x64/cursorRotate.png diff --git a/src/app/puzzle/share/resources/puzzleicon/64x64/cursorRotate.png b/src/app/puzzle/share/resources/puzzleicon/64x64/cursorRotate.png new file mode 100644 index 000000000..a9ade2aee Binary files /dev/null and b/src/app/puzzle/share/resources/puzzleicon/64x64/cursorRotate.png differ diff --git a/src/app/puzzle/share/resources/puzzleicon/64x64/cursorRotate@2x.png b/src/app/puzzle/share/resources/puzzleicon/64x64/cursorRotate@2x.png new file mode 100644 index 000000000..0bde89ddb Binary files /dev/null and b/src/app/puzzle/share/resources/puzzleicon/64x64/cursorRotate@2x.png differ diff --git a/src/app/puzzle/share/resources/puzzleicon/svg/cursor_rotate.svg b/src/app/puzzle/share/resources/puzzleicon/svg/cursor_rotate.svg new file mode 100644 index 000000000..f5b2423cb --- /dev/null +++ b/src/app/puzzle/share/resources/puzzleicon/svg/cursor_rotate.svg @@ -0,0 +1,67 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/src/app/puzzle/vpuzzlegraphicspiece.cpp b/src/app/puzzle/vpuzzlegraphicspiece.cpp index fb18783f6..3d53423fe 100644 --- a/src/app/puzzle/vpuzzlegraphicspiece.cpp +++ b/src/app/puzzle/vpuzzlegraphicspiece.cpp @@ -36,6 +36,8 @@ #include #include #include +#include +#include #include "vpuzzlepiece.h" #include "vpuzzlelayer.h" @@ -50,7 +52,8 @@ VPuzzleGraphicsPiece::VPuzzleGraphicsPiece(VPuzzlePiece *piece, QGraphicsItem *p m_piece(piece), m_cuttingLine(QPainterPath()), m_seamLine(QPainterPath()), - m_grainline(QPainterPath()) + m_grainline(QPainterPath()), + m_rotationStartPoint(QPointF()) { Init(); } @@ -66,6 +69,7 @@ void VPuzzleGraphicsPiece::Init() { // set some infos setFlags(ItemIsSelectable | ItemIsMovable | ItemSendsGeometryChanges); + setAcceptHoverEvents(true); setCursor(QCursor(Qt::OpenHandCursor)); // initialises the seam line @@ -188,8 +192,50 @@ void VPuzzleGraphicsPiece::mousePressEvent(QGraphicsSceneMouseEvent *event) setSelected(true); } } + + if((event->button() == Qt::LeftButton) && (event->modifiers() & Qt::AltModifier)) + { + m_rotationStartPoint = event->scenePos(); + + QPixmap cursor_pixmap = QPixmap(":/cursor_rotate"); + cursor_pixmap = cursor_pixmap.scaledToWidth(32); + QCursor cursor_rotate = QCursor(cursor_pixmap, 16, 16); + + setCursor(cursor_rotate); + } } +//--------------------------------------------------------------------------------------------------------------------- +void VPuzzleGraphicsPiece::mouseMoveEvent(QGraphicsSceneMouseEvent * event) +{ + if((event->buttons() == Qt::LeftButton) && (event->modifiers() & Qt::AltModifier)) + { + + QPointF rotationNewPoint = event->scenePos(); + QPointF rotationCenter = sceneBoundingRect().center(); + + // get the angle from the center to the initial click point + qreal init_x = m_rotationStartPoint.x() - rotationCenter.x(); + qreal init_y = m_rotationStartPoint.y() - rotationCenter.y(); + qreal initial_angle = qAtan2(init_y, init_x); + + qreal x = rotationNewPoint.x() - rotationCenter.x(); + qreal y = rotationNewPoint.y() - rotationCenter.y(); + qreal mv_angle = qAtan2(y,x); + + qreal angle = (initial_angle-mv_angle)*180/M_PI; + + setTransformOriginPoint(boundingRect().center()); + setRotation(-(angle+m_piece->GetRotation())); + event->accept(); + } + else + { + QGraphicsItem::mouseMoveEvent(event); + } +} + + //--------------------------------------------------------------------------------------------------------------------- void VPuzzleGraphicsPiece::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { @@ -204,6 +250,36 @@ void VPuzzleGraphicsPiece::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) setCursor(Qt::OpenHandCursor); setSelected(selectionState); + + if(m_piece->GetPosition() != pos()) + { + m_piece->SetPosition(pos()); + } + } + + if((event->button() == Qt::LeftButton) && (event->modifiers() & Qt::AltModifier)) + { + m_piece->SetRotation(-rotation()); + } +} + +//--------------------------------------------------------------------------------------------------------------------- +void VPuzzleGraphicsPiece::hoverMoveEvent(QGraphicsSceneHoverEvent *event) +{ + + if(event->modifiers() & Qt::AltModifier) + { + // TODO FIXME: find a more efficient way + + QPixmap cursor_pixmap = QPixmap(":/cursor_rotate"); + cursor_pixmap = cursor_pixmap.scaledToWidth(32); + QCursor cursor_rotate = QCursor(cursor_pixmap, 16, 16); + + setCursor(cursor_rotate); + } + else + { + setCursor(QCursor(Qt::OpenHandCursor)); } } @@ -246,7 +322,7 @@ void VPuzzleGraphicsPiece::on_ActionPieceMovedToLayer() { QAction *act = qobject_cast(sender()); QVariant v = act->data(); - VPuzzleLayer *layer = (VPuzzleLayer *) v.value(); + VPuzzleLayer *layer = v.value(); if(layer != nullptr) { layer->GetLayout()->MovePieceToLayer(m_piece, layer); @@ -277,12 +353,14 @@ void VPuzzleGraphicsPiece::on_PieceRotationChanged() QVariant VPuzzleGraphicsPiece::itemChange(GraphicsItemChange change, const QVariant &value) { if (scene()) { - if(change == ItemPositionHasChanged) - { - blockSignals(true); - m_piece->SetPosition(pos()); - blockSignals(false); - } + + // we do this in the mouseRelease button to avoid updated this property all the time. +// if(change == ItemPositionHasChanged) +// { +// blockSignals(true); +// m_piece->SetPosition(pos()); +// blockSignals(false); +// } if(change == ItemSelectedHasChanged) { diff --git a/src/app/puzzle/vpuzzlegraphicspiece.h b/src/app/puzzle/vpuzzlegraphicspiece.h index 496f55e76..fee04892f 100644 --- a/src/app/puzzle/vpuzzlegraphicspiece.h +++ b/src/app/puzzle/vpuzzlegraphicspiece.h @@ -69,8 +69,11 @@ protected: void paint(QPainter *painter, const QStyleOptionGraphicsItem *item, QWidget *widget) override; void mousePressEvent(QGraphicsSceneMouseEvent * event) override; + void mouseMoveEvent(QGraphicsSceneMouseEvent * event) override; void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override; + void hoverMoveEvent(QGraphicsSceneHoverEvent *event) override; + QVariant itemChange(GraphicsItemChange change, const QVariant &value) override; void contextMenuEvent(QGraphicsSceneContextMenuEvent *event) override; @@ -89,6 +92,9 @@ private: QPainterPath m_cuttingLine; QPainterPath m_seamLine; QPainterPath m_grainline; + + QPointF m_rotationStartPoint; + }; #endif // VPUZZLEGRAPHICSPIECE_H diff --git a/src/app/puzzle/vpuzzlepiece.cpp b/src/app/puzzle/vpuzzlepiece.cpp index 92a42191f..45e652516 100644 --- a/src/app/puzzle/vpuzzlepiece.cpp +++ b/src/app/puzzle/vpuzzlepiece.cpp @@ -144,27 +144,28 @@ QPointF VPuzzlePiece::GetPosition() //--------------------------------------------------------------------------------------------------------------------- void VPuzzlePiece::SetRotation(qreal angle) { - m_pieceAngle = angle; + // qreal currentAngle = GetRotation(); + // qreal newAngle = angle - currentAngle; - // make sure the angle is [0 <= angle < 360] - while(m_pieceAngle >= 360) + // m_transform.rotate(newAngle); + + if(m_pieceAngle != angle) { - m_pieceAngle -= 360; + m_pieceAngle = angle; + + // make sure the angle is [0 <= angle < 360] + while(m_pieceAngle >= 360) + { + m_pieceAngle -= 360; + } + + while(m_pieceAngle < 0) + { + m_pieceAngle += 360; + } + + emit RotationChanged(); } - - while(m_pieceAngle < 0) - { - m_pieceAngle += 360; - } - - -// qreal currentAngle = GetRotation(); -// qreal newAngle = angle - currentAngle; - -// m_transform.rotate(newAngle); - - - emit RotationChanged(); } //---------------------------------------------------------------------------------------------------------------------