Follow grainline.
This commit is contained in:
parent
acfbc5478e
commit
877fe380e3
|
@ -55,6 +55,21 @@ struct VPTransformationOrigon
|
|||
{
|
||||
QPointF origin{};
|
||||
bool custom{false};
|
||||
|
||||
bool operator==(const VPTransformationOrigon &origin) const;
|
||||
bool operator!=(const VPTransformationOrigon &origin) const;
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
inline bool VPTransformationOrigon::operator==(const VPTransformationOrigon &origin) const
|
||||
{
|
||||
return this->origin == origin.origin && custom == origin.custom;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
inline bool VPTransformationOrigon::operator!=(const VPTransformationOrigon &origin) const
|
||||
{
|
||||
return !VPTransformationOrigon::operator==(origin);
|
||||
}
|
||||
|
||||
#endif // LAYOUTDEF_H
|
||||
|
|
|
@ -108,6 +108,23 @@ auto VPLayout::GetPieces() const -> QList<VPPiecePtr>
|
|||
return m_pieces.values();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto VPLayout::GetPlacedPieces() const -> QList<VPPiecePtr>
|
||||
{
|
||||
QList<VPPiecePtr> pieces;
|
||||
pieces.reserve(m_pieces.size());
|
||||
|
||||
for (const auto& piece : m_pieces)
|
||||
{
|
||||
if (not piece->isNull() && piece->Sheet() != VPSheetPtr() && piece->Sheet() != m_trashSheet)
|
||||
{
|
||||
pieces.append(piece);
|
||||
}
|
||||
}
|
||||
|
||||
return pieces;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
auto VPLayout::GetUnplacedPieces() const -> QList<VPPiecePtr>
|
||||
{
|
||||
|
|
|
@ -49,6 +49,7 @@ public:
|
|||
static void AddPiece(const VPLayoutPtr &layout, const VPPiecePtr &piece);
|
||||
|
||||
auto GetPieces() const -> QList<VPPiecePtr>;
|
||||
auto GetPlacedPieces() const -> QList<VPPiecePtr>;
|
||||
auto GetUnplacedPieces() const -> QList<VPPiecePtr>;
|
||||
auto GetTrashedPieces() const -> QList<VPPiecePtr>;
|
||||
|
||||
|
|
|
@ -76,7 +76,7 @@ auto VPPiece::GetPosition() -> QPointF
|
|||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void VPPiece::RotateToGrainline()
|
||||
void VPPiece::RotateToGrainline(const VPTransformationOrigon &origin)
|
||||
{
|
||||
VPSheetPtr sheet = Sheet();
|
||||
if (not IsGrainlineEnabled() || sheet.isNull())
|
||||
|
@ -105,7 +105,8 @@ void VPPiece::RotateToGrainline()
|
|||
atFront.setAngle(90);
|
||||
}
|
||||
|
||||
return grainline.angleTo(atFront);
|
||||
qreal angleTo = grainline.angleTo(atFront);
|
||||
return angleTo;
|
||||
};
|
||||
|
||||
auto DegreesAtRear = [grainline, canonical, grainlineType]()
|
||||
|
@ -113,7 +114,8 @@ void VPPiece::RotateToGrainline()
|
|||
QLineF atRear = canonical;
|
||||
atRear.setAngle(grainlineType == GrainlineType::Vertical ? 270 : 180);
|
||||
|
||||
return grainline.angleTo(atRear);
|
||||
qreal angleTo = grainline.angleTo(atRear);
|
||||
return angleTo;
|
||||
};
|
||||
|
||||
GrainlineArrowDirection type = GrainlineArrowType();
|
||||
|
@ -129,10 +131,25 @@ void VPPiece::RotateToGrainline()
|
|||
}
|
||||
else
|
||||
{
|
||||
degrees = qMin(DegreesAtFront(), DegreesAtRear());
|
||||
const qreal atFront = DegreesAtFront();
|
||||
if (atFront <= 90 || atFront >= 270)
|
||||
{
|
||||
degrees = atFront;
|
||||
}
|
||||
else
|
||||
{
|
||||
degrees = DegreesAtRear();
|
||||
}
|
||||
}
|
||||
|
||||
Rotate(MappedDetailBoundingRect().center(), degrees);
|
||||
if (origin.custom)
|
||||
{
|
||||
Rotate(MappedDetailBoundingRect().center(), degrees);
|
||||
}
|
||||
else
|
||||
{
|
||||
Rotate(origin.origin, degrees);
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -64,7 +64,7 @@ public:
|
|||
/**
|
||||
* @brief RotateToGrainline rotates the piece to follow the grainline
|
||||
*/
|
||||
void RotateToGrainline();
|
||||
void RotateToGrainline(const VPTransformationOrigon &origin);
|
||||
|
||||
/**
|
||||
* @brief SetSelected Sets wether the piece is selected
|
||||
|
|
|
@ -71,17 +71,20 @@ enum class HandleCorner : int
|
|||
BottomLeft = 4
|
||||
};
|
||||
|
||||
auto TransformationOrigin(const VPLayoutPtr &layout, const QRectF &boundingRect) -> QPointF
|
||||
auto TransformationOrigin(const VPLayoutPtr &layout, const QRectF &boundingRect) -> VPTransformationOrigon
|
||||
{
|
||||
SCASSERT(layout != nullptr)
|
||||
VPSheetPtr sheet = layout->GetFocusedSheet();
|
||||
if (not sheet.isNull())
|
||||
{
|
||||
VPTransformationOrigon origin = sheet->TransformationOrigin();
|
||||
return origin.origin;
|
||||
return sheet->TransformationOrigin();
|
||||
}
|
||||
|
||||
return boundingRect.center();
|
||||
VPTransformationOrigon origin;
|
||||
origin.origin = boundingRect.center();
|
||||
origin.custom = false;
|
||||
|
||||
return origin;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
|
@ -233,8 +236,8 @@ auto VPGraphicsTransformationOrigin::RotationCenter(QPainter *painter) const ->
|
|||
|
||||
const qreal scale = SceneScale(scene());
|
||||
qreal radius = centerRadius1/scale;
|
||||
QPointF transformationOrigin = TransformationOrigin(m_layout, QRectF());
|
||||
QRectF rect(transformationOrigin.x()-radius, transformationOrigin.y()-radius, radius*2., radius*2.);
|
||||
VPTransformationOrigon transformationOrigin = TransformationOrigin(m_layout, QRectF());
|
||||
QRectF rect(transformationOrigin.origin.x()-radius, transformationOrigin.origin.y()-radius, radius*2., radius*2.);
|
||||
|
||||
QPainterPath center1;
|
||||
center1.addEllipse(rect);
|
||||
|
@ -249,7 +252,7 @@ auto VPGraphicsTransformationOrigin::RotationCenter(QPainter *painter) const ->
|
|||
path.addPath(center1);
|
||||
|
||||
radius = centerRadius2/scale;
|
||||
rect = QRectF(transformationOrigin.x()-radius, transformationOrigin.y()-radius, radius*2., radius*2.);
|
||||
rect = QRectF(transformationOrigin.origin.x()-radius, transformationOrigin.origin.y()-radius, radius*2., radius*2.);
|
||||
|
||||
QPainterPath center2;
|
||||
center2.addEllipse(rect);
|
||||
|
@ -271,8 +274,8 @@ auto VPGraphicsTransformationOrigin::Center1() const -> QPainterPath
|
|||
{
|
||||
const qreal scale = SceneScale(scene());
|
||||
qreal radius = centerRadius1/scale;
|
||||
QPointF transformationOrigin = TransformationOrigin(m_layout, QRectF());
|
||||
QRectF rect(transformationOrigin.x()-radius, transformationOrigin.y()-radius, radius*2., radius*2.);
|
||||
VPTransformationOrigon transformationOrigin = TransformationOrigin(m_layout, QRectF());
|
||||
QRectF rect(transformationOrigin.origin.x()-radius, transformationOrigin.origin.y()-radius, radius*2., radius*2.);
|
||||
|
||||
QPainterPath center1;
|
||||
center1.addEllipse(rect);
|
||||
|
@ -285,8 +288,9 @@ auto VPGraphicsTransformationOrigin::Center2() const -> QPainterPath
|
|||
{
|
||||
const qreal scale = SceneScale(scene());
|
||||
qreal radius = centerRadius2/scale;
|
||||
QPointF transformationOrigin = TransformationOrigin(m_layout, QRectF());
|
||||
QRectF rect = QRectF(transformationOrigin.x()-radius, transformationOrigin.y()-radius, radius*2., radius*2.);
|
||||
VPTransformationOrigon transformationOrigin = TransformationOrigin(m_layout, QRectF());
|
||||
QRectF rect = QRectF(transformationOrigin.origin.x()-radius, transformationOrigin.origin.y()-radius, radius*2.,
|
||||
radius*2.);
|
||||
|
||||
QPainterPath center2;
|
||||
center2.addEllipse(rect);
|
||||
|
@ -389,6 +393,7 @@ void VPGraphicsPieceControls::mousePressEvent(QGraphicsSceneMouseEvent *event)
|
|||
if(event->button() == Qt::LeftButton)
|
||||
{
|
||||
m_rotationStartPoint = event->scenePos();
|
||||
m_rotationSum = 0;
|
||||
m_controlsVisible = false;
|
||||
m_handleCorner = HandleCorner(event->scenePos());
|
||||
m_ignorePieceTransformation = true;
|
||||
|
@ -470,13 +475,18 @@ void VPGraphicsPieceControls::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
|||
QPointF rotationNewPoint = event->scenePos();
|
||||
|
||||
// get the angle from the center to the initial click point
|
||||
QPointF rotationOrigin = TransformationOrigin(m_layout, m_pieceRect);
|
||||
QLineF initPosition(rotationOrigin, m_rotationStartPoint);
|
||||
QLineF initRotationPosition(rotationOrigin, rotationNewPoint);
|
||||
VPTransformationOrigon rotationOrigin = TransformationOrigin(m_layout, m_pieceRect);
|
||||
QLineF initPosition(rotationOrigin.origin, m_rotationStartPoint);
|
||||
QLineF initRotationPosition(rotationOrigin.origin, rotationNewPoint);
|
||||
|
||||
qreal angle = initPosition.angleTo(initRotationPosition);
|
||||
qreal rotateOn = initPosition.angleTo(initRotationPosition);
|
||||
|
||||
if (not qFuzzyIsNull(angle))
|
||||
if (rotateOn > 180)
|
||||
{
|
||||
rotateOn = rotateOn - 360.;
|
||||
}
|
||||
|
||||
if (not qFuzzyIsNull(rotateOn))
|
||||
{
|
||||
auto PreparePieces = [this]()
|
||||
{
|
||||
|
@ -499,14 +509,32 @@ void VPGraphicsPieceControls::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
|||
VPLayoutPtr layout = m_layout.toStrongRef();
|
||||
if (not layout.isNull())
|
||||
{
|
||||
if (layout->LayoutSettings().GetFollowGrainline() && not rotationOrigin.custom)
|
||||
{
|
||||
if (m_rotationSum > 90 || m_rotationSum < -90)
|
||||
{
|
||||
m_rotationSum = rotateOn;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_rotationSum += rotateOn;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_rotationSum = rotateOn;
|
||||
}
|
||||
|
||||
if (pieces.size() == 1)
|
||||
{
|
||||
auto *command = new VPUndoPieceRotate(pieces.first(), rotationOrigin, angle, allowChangeMerge);
|
||||
auto *command = new VPUndoPieceRotate(pieces.first(), rotationOrigin, rotateOn, m_rotationSum,
|
||||
allowChangeMerge);
|
||||
layout->UndoStack()->push(command);
|
||||
}
|
||||
else if (pieces.size() > 1)
|
||||
{
|
||||
auto *command = new VPUndoPiecesRotate(pieces, rotationOrigin, angle, allowChangeMerge);
|
||||
auto *command = new VPUndoPiecesRotate(pieces, rotationOrigin, rotateOn, m_rotationSum,
|
||||
allowChangeMerge);
|
||||
layout->UndoStack()->push(command);
|
||||
}
|
||||
}
|
||||
|
@ -514,8 +542,8 @@ void VPGraphicsPieceControls::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
|
|||
|
||||
if (m_originSaved && m_savedOrigin.custom)
|
||||
{
|
||||
QLineF line(rotationOrigin, m_savedOrigin.origin);
|
||||
line.setAngle(line.angle()+angle);
|
||||
QLineF line(rotationOrigin.origin, m_savedOrigin.origin);
|
||||
line.setAngle(line.angle()+rotateOn);
|
||||
m_savedOrigin.origin = line.p2();
|
||||
}
|
||||
|
||||
|
|
|
@ -108,6 +108,7 @@ private:
|
|||
Q_DISABLE_COPY(VPGraphicsPieceControls)
|
||||
QRectF m_pieceRect{};
|
||||
QPointF m_rotationStartPoint{};
|
||||
qreal m_rotationSum{0};
|
||||
bool m_controlsVisible{true};
|
||||
VPLayoutWeakPtr m_layout{};
|
||||
int m_handleCorner{0};
|
||||
|
|
|
@ -371,6 +371,7 @@ void VPMainGraphicsView::keyReleaseEvent(QKeyEvent *event)
|
|||
m_rotationControls->SetIgnorePieceTransformation(false);
|
||||
m_rotationControls->on_UpdateControls();
|
||||
m_rotationControls->on_HideHandles(false);
|
||||
m_rotationSum = 0;
|
||||
}
|
||||
}
|
||||
VMainGraphicsView::keyReleaseEvent(event);
|
||||
|
@ -558,16 +559,32 @@ void VPMainGraphicsView::RotatePiecesByAngle(qreal angle)
|
|||
return pieces;
|
||||
};
|
||||
|
||||
if (layout->LayoutSettings().GetFollowGrainline() && not origin.custom)
|
||||
{
|
||||
if (m_rotationSum > 90 || m_rotationSum < -90)
|
||||
{
|
||||
m_rotationSum = angle;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_rotationSum += angle;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_rotationSum = angle;
|
||||
}
|
||||
|
||||
QList<VPPiecePtr> pieces = PreparePieces();
|
||||
|
||||
if (pieces.size() == 1)
|
||||
{
|
||||
auto *command = new VPUndoPieceRotate(pieces.first(), origin.origin, angle, m_allowChangeMerge);
|
||||
auto *command = new VPUndoPieceRotate(pieces.first(), origin, angle, m_rotationSum, m_allowChangeMerge);
|
||||
layout->UndoStack()->push(command);
|
||||
}
|
||||
else if (pieces.size() > 1)
|
||||
{
|
||||
auto *command = new VPUndoPiecesRotate(pieces, origin.origin, angle, m_allowChangeMerge);
|
||||
auto *command = new VPUndoPiecesRotate(pieces, origin, angle, m_rotationSum, m_allowChangeMerge);
|
||||
layout->UndoStack()->push(command);
|
||||
}
|
||||
|
||||
|
|
|
@ -124,6 +124,8 @@ private:
|
|||
bool m_showGridTmp{false};
|
||||
bool m_allowChangeMerge{false};
|
||||
|
||||
qreal m_rotationSum{0};
|
||||
|
||||
void ConnectPiece(VPGraphicsPiece *piece);
|
||||
|
||||
void RotatePiecesByAngle(qreal angle);
|
||||
|
|
|
@ -41,6 +41,12 @@ VPUndoMovePieceOnSheet::VPUndoMovePieceOnSheet(const VPSheetPtr &sheet, const VP
|
|||
|
||||
m_oldSheet = piece->Sheet();
|
||||
|
||||
VPLayoutPtr layout = piece->Layout();
|
||||
if (not layout.isNull())
|
||||
{
|
||||
m_followGrainline = layout->LayoutSettings().GetFollowGrainline();
|
||||
}
|
||||
|
||||
setText(tr("move piece on sheet"));
|
||||
}
|
||||
|
||||
|
@ -105,6 +111,14 @@ void VPUndoMovePieceOnSheet::redo()
|
|||
{
|
||||
piece->SetSheet(sourceSheet);
|
||||
|
||||
if (m_followGrainline)
|
||||
{
|
||||
VPTransformationOrigon origin;
|
||||
origin.custom = true;
|
||||
|
||||
piece->RotateToGrainline(origin);
|
||||
}
|
||||
|
||||
if (not layout.isNull())
|
||||
{
|
||||
emit layout->PieceSheetChanged(piece);
|
||||
|
|
|
@ -48,6 +48,7 @@ private:
|
|||
VPSheetWeakPtr m_oldSheet{};
|
||||
VPSheetWeakPtr m_sheet;
|
||||
VPPieceWeakPtr m_piece;
|
||||
bool m_followGrainline{false};
|
||||
};
|
||||
|
||||
#endif // VPUNDOMOVEPIECEONSHEET_H
|
||||
|
|
|
@ -29,18 +29,35 @@
|
|||
#include "../layout/vppiece.h"
|
||||
#include "../layout/vplayout.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
auto RoundAngle(qreal angle) -> qreal
|
||||
{
|
||||
QLineF l(10, 10, 100, 10);
|
||||
l.setAngle(angle);
|
||||
return l.angle();
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
VPUndoPieceRotate::VPUndoPieceRotate(const VPPiecePtr &piece, const QPointF &origin, qreal angle, bool allowMerge,
|
||||
QUndoCommand *parent)
|
||||
VPUndoPieceRotate::VPUndoPieceRotate(const VPPiecePtr &piece, const VPTransformationOrigon &origin, qreal angle,
|
||||
qreal angleSum, bool allowMerge, QUndoCommand *parent)
|
||||
: VPUndoCommand(allowMerge, parent),
|
||||
m_piece(piece),
|
||||
m_origin(origin),
|
||||
m_angle(angle)
|
||||
m_angle(angle),
|
||||
m_angleSum(angleSum)
|
||||
{
|
||||
SCASSERT(not piece.isNull())
|
||||
|
||||
m_oldTransform = piece->GetMatrix();
|
||||
|
||||
VPLayoutPtr layout = piece->Layout();
|
||||
if (not layout.isNull())
|
||||
{
|
||||
m_followGrainline = layout->LayoutSettings().GetFollowGrainline();
|
||||
}
|
||||
|
||||
setText(tr("rotate piece"));
|
||||
}
|
||||
|
||||
|
@ -88,8 +105,33 @@ void VPUndoPieceRotate::redo()
|
|||
layout->SetFocusedSheet(piece->Sheet());
|
||||
}
|
||||
|
||||
piece->Rotate(m_origin, m_angle);
|
||||
if (m_firstCall)
|
||||
{
|
||||
if (m_followGrainline && piece->IsGrainlineEnabled())
|
||||
{
|
||||
piece->Rotate(m_origin.origin, m_angleSum);
|
||||
}
|
||||
else
|
||||
{
|
||||
piece->Rotate(m_origin.origin, m_angle);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
piece->Rotate(m_origin.origin, m_angle);
|
||||
}
|
||||
|
||||
if (m_followGrainline)
|
||||
{
|
||||
piece->RotateToGrainline(m_origin);
|
||||
}
|
||||
|
||||
emit layout->PieceTransformationChanged(piece);
|
||||
|
||||
if (m_firstCall)
|
||||
{
|
||||
m_firstCall = false;
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
@ -105,12 +147,14 @@ auto VPUndoPieceRotate::mergeWith(const QUndoCommand *command) -> bool
|
|||
|
||||
VPPiecePtr piece = Piece();
|
||||
if (not moveCommand->AllowMerge() || (moveCommand->Piece().isNull() || piece.isNull()) ||
|
||||
moveCommand->Piece() != piece || moveCommand->Origin() != m_origin)
|
||||
moveCommand->Piece() != piece || moveCommand->Origin() != m_origin ||
|
||||
moveCommand->FollowGrainline() != m_followGrainline)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_angle += moveCommand->Angle();
|
||||
m_angle = RoundAngle(m_angle);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -122,11 +166,12 @@ auto VPUndoPieceRotate::id() const -> int
|
|||
|
||||
// rotate pieces
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
VPUndoPiecesRotate::VPUndoPiecesRotate(const QList<VPPiecePtr> &pieces, const QPointF &origin, qreal angle,
|
||||
bool allowMerge, QUndoCommand *parent)
|
||||
VPUndoPiecesRotate::VPUndoPiecesRotate(const QList<VPPiecePtr> &pieces, const VPTransformationOrigon &origin,
|
||||
qreal angle, qreal angleSum, bool allowMerge, QUndoCommand *parent)
|
||||
: VPUndoCommand(allowMerge, parent),
|
||||
m_origin(origin),
|
||||
m_angle(angle)
|
||||
m_angle(angle),
|
||||
m_angleSum(angleSum)
|
||||
{
|
||||
setText(QObject::tr("rotate pieces"));
|
||||
|
||||
|
@ -138,6 +183,12 @@ VPUndoPiecesRotate::VPUndoPiecesRotate(const QList<VPPiecePtr> &pieces, const QP
|
|||
m_oldTransforms.insert(piece->GetUniqueID(), piece->GetMatrix());
|
||||
}
|
||||
}
|
||||
|
||||
VPLayoutPtr layout = Layout();
|
||||
if (not layout.isNull())
|
||||
{
|
||||
m_followGrainline = layout->LayoutSettings().GetFollowGrainline();
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
@ -199,10 +250,35 @@ void VPUndoPiecesRotate::redo()
|
|||
VPPiecePtr p = piece.toStrongRef();
|
||||
if (not p.isNull())
|
||||
{
|
||||
p->Rotate(m_origin, m_angle);
|
||||
if (m_firstCall)
|
||||
{
|
||||
if (m_followGrainline && p->IsGrainlineEnabled())
|
||||
{
|
||||
p->Rotate(m_origin.origin, m_angleSum);
|
||||
}
|
||||
else
|
||||
{
|
||||
p->Rotate(m_origin.origin, m_angle);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
p->Rotate(m_origin.origin, m_angle);
|
||||
}
|
||||
|
||||
if (m_followGrainline)
|
||||
{
|
||||
p->RotateToGrainline(m_origin);
|
||||
}
|
||||
|
||||
emit layout->PieceTransformationChanged(p);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_firstCall)
|
||||
{
|
||||
m_firstCall = false;
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
@ -216,12 +292,14 @@ auto VPUndoPiecesRotate::mergeWith(const QUndoCommand *command) -> bool
|
|||
const auto *moveCommand = dynamic_cast<const VPUndoPiecesRotate *>(command);
|
||||
SCASSERT(moveCommand != nullptr)
|
||||
|
||||
if (not moveCommand->AllowMerge() || moveCommand->PieceIds() != PieceIds() || moveCommand->Origin() != m_origin)
|
||||
if (not moveCommand->AllowMerge() || moveCommand->PieceIds() != PieceIds() || moveCommand->Origin() != m_origin ||
|
||||
moveCommand->FollowGrainline() != m_followGrainline)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_angle += moveCommand->Angle();
|
||||
m_angle = RoundAngle(m_angle);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -38,8 +38,8 @@ class VPUndoPieceRotate : public VPUndoCommand
|
|||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
VPUndoPieceRotate(const VPPiecePtr &piece, const QPointF &origin, qreal angle, bool allowMerge = false,
|
||||
QUndoCommand *parent = nullptr);
|
||||
VPUndoPieceRotate(const VPPiecePtr &piece, const VPTransformationOrigon &origin, qreal angle, qreal angleSum,
|
||||
bool allowMerge = false, QUndoCommand *parent = nullptr);
|
||||
|
||||
virtual ~VPUndoPieceRotate()=default;
|
||||
|
||||
|
@ -50,16 +50,21 @@ public:
|
|||
virtual auto id() const -> int override ;
|
||||
|
||||
auto Piece() const -> VPPiecePtr;
|
||||
auto Origin() const -> QPointF;
|
||||
auto Origin() const -> VPTransformationOrigon;
|
||||
auto Angle() const -> qreal;
|
||||
|
||||
bool FollowGrainline() const;
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(VPUndoPieceRotate)
|
||||
|
||||
bool m_firstCall{true};
|
||||
VPPieceWeakPtr m_piece;
|
||||
QTransform m_oldTransform{};
|
||||
QPointF m_origin;
|
||||
VPTransformationOrigon m_origin;
|
||||
qreal m_angle;
|
||||
qreal m_angleSum;
|
||||
bool m_followGrainline{false};
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
@ -69,7 +74,7 @@ inline auto VPUndoPieceRotate::Piece() const -> VPPiecePtr
|
|||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
inline auto VPUndoPieceRotate::Origin() const -> QPointF
|
||||
inline auto VPUndoPieceRotate::Origin() const -> VPTransformationOrigon
|
||||
{
|
||||
return m_origin;
|
||||
}
|
||||
|
@ -80,13 +85,19 @@ inline auto VPUndoPieceRotate::Angle() const -> qreal
|
|||
return m_angle;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
inline auto VPUndoPieceRotate::FollowGrainline() const -> bool
|
||||
{
|
||||
return m_followGrainline;
|
||||
}
|
||||
|
||||
// Rotate pieces
|
||||
class VPUndoPiecesRotate : public VPUndoCommand
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit VPUndoPiecesRotate(const QList<VPPiecePtr> &pieces, const QPointF &origin, qreal angle,
|
||||
bool allowMerge = false, QUndoCommand *parent = nullptr);
|
||||
explicit VPUndoPiecesRotate(const QList<VPPiecePtr> &pieces, const VPTransformationOrigon &origin, qreal angle,
|
||||
qreal angleSum, bool allowMerge = false, QUndoCommand *parent = nullptr);
|
||||
virtual ~VPUndoPiecesRotate()=default;
|
||||
|
||||
virtual void undo() override;
|
||||
|
@ -96,23 +107,27 @@ public:
|
|||
virtual auto id() const -> int override ;
|
||||
|
||||
auto PieceIds() const -> QSet<QString>;
|
||||
auto Origin() const -> QPointF;
|
||||
auto Origin() const -> VPTransformationOrigon;
|
||||
auto Angle() const -> qreal;
|
||||
auto FollowGrainline() const -> bool;
|
||||
|
||||
private:
|
||||
Q_DISABLE_COPY(VPUndoPiecesRotate)
|
||||
|
||||
bool m_firstCall{true};
|
||||
QVector<VPPieceWeakPtr> m_pieces{};
|
||||
QMap<QString, QTransform> m_oldTransforms{};
|
||||
QPointF m_origin;
|
||||
VPTransformationOrigon m_origin;
|
||||
qreal m_angle;
|
||||
qreal m_angleSum;
|
||||
bool m_followGrainline{false};
|
||||
|
||||
auto Layout() const -> VPLayoutPtr;
|
||||
auto Sheet() const -> VPSheetPtr;
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
inline auto VPUndoPiecesRotate::Origin() const -> QPointF
|
||||
inline auto VPUndoPiecesRotate::Origin() const -> VPTransformationOrigon
|
||||
{
|
||||
return m_origin;
|
||||
}
|
||||
|
@ -123,4 +138,10 @@ inline auto VPUndoPiecesRotate::Angle() const -> qreal
|
|||
return m_angle;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
inline auto VPUndoPiecesRotate::FollowGrainline() const -> bool
|
||||
{
|
||||
return m_followGrainline;
|
||||
}
|
||||
|
||||
#endif // VPUNDOPIECEROTATE_H
|
||||
|
|
|
@ -862,8 +862,13 @@ void VPMainWindow::InitPropertyTabLayout()
|
|||
if (not m_layout.isNull())
|
||||
{
|
||||
m_layout->LayoutSettings().SetFollowGrainline(checked);
|
||||
|
||||
if (checked)
|
||||
{
|
||||
RotatePiecesToGrainline();
|
||||
}
|
||||
|
||||
LayoutWasSaved(false);
|
||||
// TODO update the QGraphicView
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -1742,6 +1747,11 @@ void VPMainWindow::SheetPaperSizeChanged()
|
|||
ui->toolButtonSheetLandscapeOrientation->blockSignals(true);
|
||||
ui->toolButtonSheetLandscapeOrientation->setChecked(not portrait);
|
||||
ui->toolButtonSheetLandscapeOrientation->blockSignals(false);
|
||||
|
||||
if (not m_layout.isNull() && m_layout->LayoutSettings().GetFollowGrainline())
|
||||
{
|
||||
RotatePiecesToGrainline();
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
|
@ -1862,6 +1872,29 @@ void VPMainWindow::CorrectMaxMargins()
|
|||
CorrectTileMaxMargins();
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void VPMainWindow::RotatePiecesToGrainline()
|
||||
{
|
||||
QList<VPSheetPtr> sheets = m_layout->GetSheets();
|
||||
for(const auto& sheet : sheets)
|
||||
{
|
||||
if (not sheet.isNull())
|
||||
{
|
||||
QList<VPPiecePtr> pieces = sheet->GetPieces();
|
||||
for(const auto& piece : pieces)
|
||||
{
|
||||
if (not piece.isNull() && piece->IsGrainlineEnabled())
|
||||
{
|
||||
VPTransformationOrigon origin;
|
||||
origin.custom = true;
|
||||
piece->RotateToGrainline(origin);
|
||||
emit m_layout->PieceTransformationChanged(piece);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------------------------------------------------
|
||||
void VPMainWindow::on_actionNew_triggered()
|
||||
{
|
||||
|
@ -2513,7 +2546,12 @@ void VPMainWindow::on_ApplyPieceTransformation()
|
|||
if (not piece.isNull())
|
||||
{
|
||||
const QRectF rect = piece->MappedDetailBoundingRect();
|
||||
auto *command = new VPUndoPieceRotate(piece, rect.center(), angle);
|
||||
|
||||
VPTransformationOrigon origin;
|
||||
origin.origin = rect.center();
|
||||
origin.custom = true;
|
||||
|
||||
auto *command = new VPUndoPieceRotate(piece, origin, angle, angle);
|
||||
m_layout->UndoStack()->push(command);
|
||||
}
|
||||
}
|
||||
|
@ -2528,7 +2566,7 @@ void VPMainWindow::on_ApplyPieceTransformation()
|
|||
}
|
||||
|
||||
VPTransformationOrigon origin = sheet->TransformationOrigin();
|
||||
auto *command = new VPUndoPiecesRotate(selectedPieces, origin.origin, angle);
|
||||
auto *command = new VPUndoPiecesRotate(selectedPieces, origin, angle, angle);
|
||||
m_layout->UndoStack()->push(command);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -454,6 +454,8 @@ private:
|
|||
void CorrectTileMaxMargins();
|
||||
void CorrectSheetMaxMargins();
|
||||
void CorrectMaxMargins();
|
||||
|
||||
void RotatePiecesToGrainline();
|
||||
};
|
||||
|
||||
#endif // VPMAINWINDOW_H
|
||||
|
|
|
@ -189,7 +189,7 @@
|
|||
<enum>QTabWidget::Rounded</enum>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="iconSize">
|
||||
<size>
|
||||
|
|
|
@ -298,7 +298,7 @@ void VPLayoutFileReader::ReadControl(const VPLayoutPtr &layout)
|
|||
layout->LayoutSettings().SetWarningPiecesOutOfBound(ReadAttributeBool(attribs, ML::AttrWarningOutOfBound, trueStr));
|
||||
layout->LayoutSettings().SetStickyEdges(ReadAttributeBool(attribs, ML::AttrStickyEdges, trueStr));
|
||||
layout->LayoutSettings().SetPiecesGap(ReadAttributeDouble(attribs, ML::AttrPiecesGap, QChar('0')));
|
||||
// layout->LayoutSettings().SetFollowGrainline(ReadAttributeBool(attribs, ML::AttrFollowGrainLine, trueStr));
|
||||
layout->LayoutSettings().SetFollowGrainline(ReadAttributeBool(attribs, ML::AttrFollowGrainline, falseStr));
|
||||
|
||||
readElementText();
|
||||
}
|
||||
|
|
|
@ -176,7 +176,7 @@ void VPLayoutFileWriter::WriteProperties(const VPLayoutPtr &layout)
|
|||
SetAttribute(ML::AttrWarningOutOfBound, layout->LayoutSettings().GetWarningPiecesOutOfBound());
|
||||
SetAttribute(ML::AttrStickyEdges, layout->LayoutSettings().GetStickyEdges());
|
||||
SetAttribute(ML::AttrPiecesGap, layout->LayoutSettings().GetPiecesGap());
|
||||
// SetAttribute(ML::AttrFollowGrainLine, layout->LayoutSettings().GetFollowGrainline());
|
||||
SetAttribute(ML::AttrFollowGrainline, layout->LayoutSettings().GetFollowGrainline());
|
||||
writeEndElement(); // control
|
||||
|
||||
WriteTiles(layout);
|
||||
|
|
|
@ -73,7 +73,7 @@ const QString AttrRight = QStringLiteral("right");
|
|||
const QString AttrBottom = QStringLiteral("bottom");
|
||||
const QString AttrWidth = QStringLiteral("width");
|
||||
const QString AttrLength = QStringLiteral("length");
|
||||
const QString AttrFollowGrainLine = QStringLiteral("followGrainLine");
|
||||
const QString AttrFollowGrainline = QStringLiteral("followGrainline");
|
||||
const QString AttrID = QStringLiteral("id");
|
||||
const QString AttrMirrored = QStringLiteral("mirrored");
|
||||
const QString AttrTransform = QStringLiteral("transform");
|
||||
|
|
|
@ -78,7 +78,7 @@ extern const QString AttrRight;
|
|||
extern const QString AttrBottom;
|
||||
extern const QString AttrWidth;
|
||||
extern const QString AttrLength;
|
||||
extern const QString AttrFollowGrainLine;
|
||||
extern const QString AttrFollowGrainline;
|
||||
extern const QString AttrID;
|
||||
extern const QString AttrMirrored;
|
||||
extern const QString AttrTransform;
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
<xs:attribute type="xs:boolean" name="warningSuperposition"/>
|
||||
<xs:attribute type="xs:boolean" name="warningOutOfBound"/>
|
||||
<xs:attribute type="xs:boolean" name="stickyEdges"/>
|
||||
<xs:attribute type="xs:boolean" name="followGrainline"/>
|
||||
<xs:attribute type="xs:float" name="piecesGap"/>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
|
|
|
@ -117,7 +117,7 @@ public:
|
|||
/** @brief grainlineInfo line */
|
||||
QVector<QPointF> grainlinePoints{};
|
||||
|
||||
GrainlineArrowDirection grainlineArrowType{GrainlineArrowDirection::atFront};
|
||||
GrainlineArrowDirection grainlineArrowType{GrainlineArrowDirection::atFront};
|
||||
qreal grainlineAngle{0};
|
||||
bool grainlineEnabled{false};
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user