optimization angle / rotation

This commit is contained in:
Ronan Le Tiec 2020-05-09 14:45:36 +02:00
parent dc44bef761
commit a9d6fae27d
9 changed files with 197 additions and 26 deletions

View File

@ -200,6 +200,7 @@ VPuzzlePiece* PuzzleMainWindow::CreatePiece(const VLayoutPiece &rawPiece)
// //
connect(piece, &VPuzzlePiece::SelectionChanged, this, &PuzzleMainWindow::on_PieceSelectionChanged); connect(piece, &VPuzzlePiece::SelectionChanged, this, &PuzzleMainWindow::on_PieceSelectionChanged);
connect(piece, &VPuzzlePiece::PositionChanged, this, &PuzzleMainWindow::on_PiecePositionChanged); connect(piece, &VPuzzlePiece::PositionChanged, this, &PuzzleMainWindow::on_PiecePositionChanged);
connect(piece, &VPuzzlePiece::RotationChanged, this, &PuzzleMainWindow::on_PieceRotationChanged);
return piece; return piece;
@ -892,3 +893,15 @@ void PuzzleMainWindow::on_PiecePositionChanged()
SetDoubleSpinBoxValue(ui->doubleSpinBoxCurrentPieceBoxPositionY, UnitConvertor(pos.y(), Unit::Px, m_layout->GetUnit())); 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);
}
}

View File

@ -373,6 +373,11 @@ private slots:
*/ */
void on_PiecePositionChanged(); void on_PiecePositionChanged();
/**
* @brief on_PieceRotationChanged When the current piece rotation has changed
*/
void on_PieceRotationChanged();
}; };
#endif // PUZZLEMAINWINDOW_H #endif // PUZZLEMAINWINDOW_H

View File

@ -9,5 +9,6 @@
<file>puzzleicon/64x64/iconPortrait.png</file> <file>puzzleicon/64x64/iconPortrait.png</file>
<file>puzzleicon/64x64/iconGrainlineVertical.png</file> <file>puzzleicon/64x64/iconGrainlineVertical.png</file>
<file>puzzleicon/64x64/iconGrainlineHorizontal.png</file> <file>puzzleicon/64x64/iconGrainlineHorizontal.png</file>
<file alias="cursor_rotate">puzzleicon/64x64/cursorRotate.png</file>
</qresource> </qresource>
</RCC> </RCC>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

@ -0,0 +1,67 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="128"
height="128"
viewBox="0 0 33.866666 33.866668"
version="1.1"
id="svg8"
sodipodi:docname="icon_rotate.svg"
inkscape:export-filename="/home/ronan/Desktop/iconRotate.png"
inkscape:export-xdpi="48"
inkscape:export-ydpi="48"
inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)">
<defs
id="defs2" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1.4142136"
inkscape:cx="-73.50406"
inkscape:cy="-5.7476577"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:window-width="1487"
inkscape:window-height="906"
inkscape:window-x="648"
inkscape:window-y="365"
inkscape:window-maximized="0" />
<metadata
id="metadata5">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Ebene 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-263.13332)">
<path
style="fill:#000000;fill-opacity:0.99622641;stroke:#000000;stroke-width:0.56587124;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 7.0186194,287.41283 -6.32117702,-9.61886 4.59283552,0.0718 c 0.2260142,-13.99266 14.6277861,-19.32352 24.6168741,-9.04316 8.326613,8.56942 1.645094,23.6663 -11.704329,23.56294 l -0.02016,4.07882 -9.3161816,-5.90315 9.3649386,-5.23047 -0.0097,3.75053 c 12.855101,-0.23223 15.657569,-13.03558 9.321879,-19.01152 -6.380838,-6.01853 -18.7084318,-6.45152 -19.0255146,7.87916 l 4.6551916,0.099 z"
id="path873"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cccscccccsccc" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -36,6 +36,8 @@
#include <QStyleOptionGraphicsItem> #include <QStyleOptionGraphicsItem>
#include <QGraphicsSceneContextMenuEvent> #include <QGraphicsSceneContextMenuEvent>
#include <QMenu> #include <QMenu>
#include <QtMath>
#include <QGraphicsScene>
#include "vpuzzlepiece.h" #include "vpuzzlepiece.h"
#include "vpuzzlelayer.h" #include "vpuzzlelayer.h"
@ -50,7 +52,8 @@ VPuzzleGraphicsPiece::VPuzzleGraphicsPiece(VPuzzlePiece *piece, QGraphicsItem *p
m_piece(piece), m_piece(piece),
m_cuttingLine(QPainterPath()), m_cuttingLine(QPainterPath()),
m_seamLine(QPainterPath()), m_seamLine(QPainterPath()),
m_grainline(QPainterPath()) m_grainline(QPainterPath()),
m_rotationStartPoint(QPointF())
{ {
Init(); Init();
} }
@ -66,6 +69,7 @@ void VPuzzleGraphicsPiece::Init()
{ {
// set some infos // set some infos
setFlags(ItemIsSelectable | ItemIsMovable | ItemSendsGeometryChanges); setFlags(ItemIsSelectable | ItemIsMovable | ItemSendsGeometryChanges);
setAcceptHoverEvents(true);
setCursor(QCursor(Qt::OpenHandCursor)); setCursor(QCursor(Qt::OpenHandCursor));
// initialises the seam line // initialises the seam line
@ -188,8 +192,50 @@ void VPuzzleGraphicsPiece::mousePressEvent(QGraphicsSceneMouseEvent *event)
setSelected(true); 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) void VPuzzleGraphicsPiece::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{ {
@ -204,6 +250,36 @@ void VPuzzleGraphicsPiece::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
setCursor(Qt::OpenHandCursor); setCursor(Qt::OpenHandCursor);
setSelected(selectionState); 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<QAction *>(sender()); QAction *act = qobject_cast<QAction *>(sender());
QVariant v = act->data(); QVariant v = act->data();
VPuzzleLayer *layer = (VPuzzleLayer *) v.value<VPuzzleLayer *>(); VPuzzleLayer *layer = v.value<VPuzzleLayer *>();
if(layer != nullptr) if(layer != nullptr)
{ {
layer->GetLayout()->MovePieceToLayer(m_piece, layer); layer->GetLayout()->MovePieceToLayer(m_piece, layer);
@ -277,12 +353,14 @@ void VPuzzleGraphicsPiece::on_PieceRotationChanged()
QVariant VPuzzleGraphicsPiece::itemChange(GraphicsItemChange change, const QVariant &value) QVariant VPuzzleGraphicsPiece::itemChange(GraphicsItemChange change, const QVariant &value)
{ {
if (scene()) { if (scene()) {
if(change == ItemPositionHasChanged)
{ // we do this in the mouseRelease button to avoid updated this property all the time.
blockSignals(true); // if(change == ItemPositionHasChanged)
m_piece->SetPosition(pos()); // {
blockSignals(false); // blockSignals(true);
} // m_piece->SetPosition(pos());
// blockSignals(false);
// }
if(change == ItemSelectedHasChanged) if(change == ItemSelectedHasChanged)
{ {

View File

@ -69,8 +69,11 @@ protected:
void paint(QPainter *painter, const QStyleOptionGraphicsItem *item, QWidget *widget) override; void paint(QPainter *painter, const QStyleOptionGraphicsItem *item, QWidget *widget) override;
void mousePressEvent(QGraphicsSceneMouseEvent * event) override; void mousePressEvent(QGraphicsSceneMouseEvent * event) override;
void mouseMoveEvent(QGraphicsSceneMouseEvent * event) override;
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override; void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) override;
void hoverMoveEvent(QGraphicsSceneHoverEvent *event) override;
QVariant itemChange(GraphicsItemChange change, const QVariant &value) override; QVariant itemChange(GraphicsItemChange change, const QVariant &value) override;
void contextMenuEvent(QGraphicsSceneContextMenuEvent *event) override; void contextMenuEvent(QGraphicsSceneContextMenuEvent *event) override;
@ -89,6 +92,9 @@ private:
QPainterPath m_cuttingLine; QPainterPath m_cuttingLine;
QPainterPath m_seamLine; QPainterPath m_seamLine;
QPainterPath m_grainline; QPainterPath m_grainline;
QPointF m_rotationStartPoint;
}; };
#endif // VPUZZLEGRAPHICSPIECE_H #endif // VPUZZLEGRAPHICSPIECE_H

View File

@ -144,27 +144,28 @@ QPointF VPuzzlePiece::GetPosition()
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------
void VPuzzlePiece::SetRotation(qreal angle) void VPuzzlePiece::SetRotation(qreal angle)
{ {
m_pieceAngle = angle; // qreal currentAngle = GetRotation();
// qreal newAngle = angle - currentAngle;
// make sure the angle is [0 <= angle < 360] // m_transform.rotate(newAngle);
while(m_pieceAngle >= 360)
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();
} }
//--------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------