diff --git a/src/libs/vgeometry/vsplinepoint.cpp b/src/libs/vgeometry/vsplinepoint.cpp index cce5b6e91..1c90ae014 100644 --- a/src/libs/vgeometry/vsplinepoint.cpp +++ b/src/libs/vgeometry/vsplinepoint.cpp @@ -28,6 +28,8 @@ #include "vsplinepoint.h" #include "vsplinepoint_p.h" +#include "../qmuparser/qmutokenparser.h" + #include #include @@ -322,3 +324,10 @@ void VSplinePoint::SetLength2(const qreal &value, const QString &length2F) d->length2 = value; d->length2F = length2F; } + +//--------------------------------------------------------------------------------------------------------------------- +bool VSplinePoint::IsMovable() const +{ + return qmu::QmuTokenParser::IsSingle(d->angle1F) && qmu::QmuTokenParser::IsSingle(d->angle2F) && + qmu::QmuTokenParser::IsSingle(d->length1F) && qmu::QmuTokenParser::IsSingle(d->length2F); +} diff --git a/src/libs/vgeometry/vsplinepoint.h b/src/libs/vgeometry/vsplinepoint.h index 75620f6ec..0aef7ff7a 100644 --- a/src/libs/vgeometry/vsplinepoint.h +++ b/src/libs/vgeometry/vsplinepoint.h @@ -98,6 +98,8 @@ public: qreal Length2() const; QString Length2Formula() const; void SetLength2(const qreal &value, const QString &length2F); + + bool IsMovable() const; protected: QSharedDataPointer d; }; diff --git a/src/libs/vtools/tools/drawTools/toolcurve/vtoolspline.cpp b/src/libs/vtools/tools/drawTools/toolcurve/vtoolspline.cpp index 0bada6c17..20f8871bf 100644 --- a/src/libs/vtools/tools/drawTools/toolcurve/vtoolspline.cpp +++ b/src/libs/vtools/tools/drawTools/toolcurve/vtoolspline.cpp @@ -336,12 +336,7 @@ void VToolSpline::mousePressEvent(QGraphicsSceneMouseEvent *event) { if (event->button() == Qt::LeftButton && event->type() != QEvent::GraphicsSceneMouseDoubleClick) { - const auto spline = VAbstractTool::data.GeometricObject(id); - - if (qmu::QmuTokenParser::IsSingle(spline->GetStartAngleFormula()) && - qmu::QmuTokenParser::IsSingle(spline->GetEndAngleFormula()) && - qmu::QmuTokenParser::IsSingle(spline->GetC1LengthFormula()) && - qmu::QmuTokenParser::IsSingle(spline->GetC2LengthFormula())) + if (IsMovable()) { SetOverrideCursor(cursorArrowCloseHand, 1, 1); oldPosition = event->scenePos(); @@ -359,12 +354,7 @@ void VToolSpline::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { if (event->button() == Qt::LeftButton && event->type() != QEvent::GraphicsSceneMouseDoubleClick) { - const auto spline = VAbstractTool::data.GeometricObject(id); - - if (qmu::QmuTokenParser::IsSingle(spline->GetStartAngleFormula()) && - qmu::QmuTokenParser::IsSingle(spline->GetEndAngleFormula()) && - qmu::QmuTokenParser::IsSingle(spline->GetC1LengthFormula()) && - qmu::QmuTokenParser::IsSingle(spline->GetC2LengthFormula())) + if (IsMovable()) { //Disable cursor-arrow-closehand RestoreOverrideCursor(cursorArrowCloseHand); @@ -377,12 +367,7 @@ void VToolSpline::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) //--------------------------------------------------------------------------------------------------------------------- void VToolSpline::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { - const auto spline = VAbstractTool::data.GeometricObject(id); - - if (qmu::QmuTokenParser::IsSingle(spline->GetStartAngleFormula()) && - qmu::QmuTokenParser::IsSingle(spline->GetEndAngleFormula()) && - qmu::QmuTokenParser::IsSingle(spline->GetC1LengthFormula()) && - qmu::QmuTokenParser::IsSingle(spline->GetC2LengthFormula())) + if (IsMovable()) { // Don't need check if left mouse button was pressed. According to the Qt documentation "If you do receive this // event, you can be certain that this item also received a mouse press event, and that this item is the current @@ -392,6 +377,7 @@ void VToolSpline::mouseMoveEvent(QGraphicsSceneMouseEvent *event) // "weight" describes how the influence of the drag should be distributed // among the handles; 0 = front handle only, 1 = back handle only. + const auto spline = VAbstractTool::data.GeometricObject(id); const qreal t = spline->ParamT(oldPosition); if (qFloor(t) == -1) @@ -460,12 +446,7 @@ void VToolSpline::hoverEnterEvent(QGraphicsSceneHoverEvent *event) { if (flags() & QGraphicsItem::ItemIsMovable) { - const auto spline = VAbstractTool::data.GeometricObject(id); - - if (qmu::QmuTokenParser::IsSingle(spline->GetStartAngleFormula()) && - qmu::QmuTokenParser::IsSingle(spline->GetEndAngleFormula()) && - qmu::QmuTokenParser::IsSingle(spline->GetC1LengthFormula()) && - qmu::QmuTokenParser::IsSingle(spline->GetC2LengthFormula())) + if (IsMovable()) { SetOverrideCursor(cursorArrowOpenHand, 1, 1); } @@ -479,12 +460,7 @@ void VToolSpline::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) { if (flags() & QGraphicsItem::ItemIsMovable) { - const auto spline = VAbstractTool::data.GeometricObject(id); - - if (qmu::QmuTokenParser::IsSingle(spline->GetStartAngleFormula()) && - qmu::QmuTokenParser::IsSingle(spline->GetEndAngleFormula()) && - qmu::QmuTokenParser::IsSingle(spline->GetC1LengthFormula()) && - qmu::QmuTokenParser::IsSingle(spline->GetC2LengthFormula())) + if (IsMovable()) { //Disable cursor-arrow-openhand RestoreOverrideCursor(cursorArrowOpenHand); @@ -515,6 +491,17 @@ void VToolSpline::SetVisualization() } } +//--------------------------------------------------------------------------------------------------------------------- +bool VToolSpline::IsMovable() const +{ + const auto spline = VAbstractTool::data.GeometricObject(id); + + return qmu::QmuTokenParser::IsSingle(spline->GetStartAngleFormula()) && + qmu::QmuTokenParser::IsSingle(spline->GetEndAngleFormula()) && + qmu::QmuTokenParser::IsSingle(spline->GetC1LengthFormula()) && + qmu::QmuTokenParser::IsSingle(spline->GetC2LengthFormula()); +} + //--------------------------------------------------------------------------------------------------------------------- /** * @brief RefreshGeometry refresh item on scene. diff --git a/src/libs/vtools/tools/drawTools/toolcurve/vtoolspline.h b/src/libs/vtools/tools/drawTools/toolcurve/vtoolspline.h index 72e77c981..d3a411123 100644 --- a/src/libs/vtools/tools/drawTools/toolcurve/vtoolspline.h +++ b/src/libs/vtools/tools/drawTools/toolcurve/vtoolspline.h @@ -80,6 +80,7 @@ private: Q_DISABLE_COPY(VToolSpline) QPointF oldPosition; + bool IsMovable() const; void RefreshGeometry (); void SetSplineAttributes(QDomElement &domElement, const VSpline &spl); }; diff --git a/src/libs/vtools/tools/drawTools/toolcurve/vtoolsplinepath.cpp b/src/libs/vtools/tools/drawTools/toolcurve/vtoolsplinepath.cpp index 08d42d543..78a51a3f7 100644 --- a/src/libs/vtools/tools/drawTools/toolcurve/vtoolsplinepath.cpp +++ b/src/libs/vtools/tools/drawTools/toolcurve/vtoolsplinepath.cpp @@ -53,7 +53,9 @@ const QString VToolSplinePath::OldToolType = QStringLiteral("path"); */ VToolSplinePath::VToolSplinePath(VAbstractPattern *doc, VContainer *data, quint32 id, const QString &color, const Source &typeCreation, QGraphicsItem *parent) - :VAbstractSpline(doc, data, id, parent), oldPosition() + : VAbstractSpline(doc, data, id, parent), + oldPosition(), + splIndex(-1) { sceneType = SceneObject::SplinePath; lineColor = color; @@ -256,7 +258,7 @@ void VToolSplinePath::UpdateControlPoints(const VSpline &spl, VSplinePath &splPa { VSplinePoint p = splPath.GetSplinePoint(indexSpline, SplinePointPosition::FirstPoint); p.SetAngle2(spl.GetStartAngle(), spl.GetStartAngleFormula()); - p.SetLength2(spl.GetC2Length(), spl.GetC2LengthFormula()); + p.SetLength2(spl.GetC1Length(), spl.GetC1LengthFormula()); splPath.UpdatePoint(indexSpline, SplinePointPosition::FirstPoint, p); p = splPath.GetSplinePoint(indexSpline, SplinePointPosition::LastPoint); @@ -442,9 +444,14 @@ void VToolSplinePath::mousePressEvent(QGraphicsSceneMouseEvent *event) { if (event->button() == Qt::LeftButton && event->type() != QEvent::GraphicsSceneMouseDoubleClick) { - SetOverrideCursor(cursorArrowCloseHand, 1, 1); oldPosition = event->scenePos(); - event->accept(); + const auto splPath = VAbstractTool::data.GeometricObject(id); + splIndex = splPath->Segment(oldPosition); + if (IsMovable(splIndex)) + { + SetOverrideCursor(cursorArrowCloseHand, 1, 1); + event->accept(); + } } } VAbstractSpline::mousePressEvent(event); @@ -457,6 +464,7 @@ void VToolSplinePath::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { if (event->button() == Qt::LeftButton && event->type() != QEvent::GraphicsSceneMouseDoubleClick) { + oldPosition = event->scenePos(); //Disable cursor-arrow-closehand RestoreOverrideCursor(cursorArrowCloseHand); } @@ -467,84 +475,82 @@ void VToolSplinePath::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) //--------------------------------------------------------------------------------------------------------------------- void VToolSplinePath::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { - // Don't need check if left mouse button was pressed. According to the Qt documentation "If you do receive this + // Don't need to check if left mouse button was pressed. According to the Qt documentation "If you do receive this // event, you can be certain that this item also received a mouse press event, and that this item is the current // mouse grabber.". - VSplinePath oldSplPath = *VAbstractTool::data.GeometricObject(id); - VSplinePath newSplPath = oldSplPath; - int indexSpline = oldSplPath.Segment(oldPosition); - if (indexSpline == -1) + if (IsMovable(splIndex)) { - return; - } + VSplinePath oldSplPath = *VAbstractTool::data.GeometricObject(id); + VSplinePath newSplPath = oldSplPath; - VSpline spline = newSplPath.GetSpline(indexSpline); - const qreal t = spline.ParamT(oldPosition); + VSpline spline = newSplPath.GetSpline(splIndex); + const qreal t = spline.ParamT(oldPosition); - if (qFloor(t) == -1) - { - return; - } + if (qFloor(t) == -1) + { + return; + } - // Magic Bezier Drag Equations follow! - // "weight" describes how the influence of the drag should be distributed - // among the handles; 0 = front handle only, 1 = back handle only. + // Magic Bezier Drag Equations follow! + // "weight" describes how the influence of the drag should be distributed + // among the handles; 0 = front handle only, 1 = back handle only. - double weight; - if (t <= 1.0 / 6.0) - { - weight = 0; - } - else if (t <= 0.5) - { - weight = (pow((6 * t - 1) / 2.0, 3)) / 2; - } - else if (t <= 5.0 / 6.0) - { - weight = (1 - pow((6 * (1-t) - 1) / 2.0, 3)) / 2 + 0.5; - } - else - { - weight = 1; - } + double weight; + if (t <= 1.0 / 6.0) + { + weight = 0; + } + else if (t <= 0.5) + { + weight = (pow((6 * t - 1) / 2.0, 3)) / 2; + } + else if (t <= 5.0 / 6.0) + { + weight = (1 - pow((6 * (1-t) - 1) / 2.0, 3)) / 2 + 0.5; + } + else + { + weight = 1; + } - const QPointF delta = event->scenePos() - oldPosition; - const QPointF offset0 = ((1-weight)/(3*t*(1-t)*(1-t))) * delta; - const QPointF offset1 = (weight/(3*t*t*(1-t))) * delta; + const QPointF delta = event->scenePos() - oldPosition; + const QPointF offset0 = ((1-weight)/(3*t*(1-t)*(1-t))) * delta; + const QPointF offset1 = (weight/(3*t*t*(1-t))) * delta; - const QPointF p2 = spline.GetP2() + offset0; - const QPointF p3 = spline.GetP3() + offset1; + const QPointF p2 = spline.GetP2() + offset0; + const QPointF p3 = spline.GetP3() + offset1; - oldPosition = event->scenePos(); // Now mouse here + oldPosition = event->scenePos(); // Now mouse here - const VSpline spl = VSpline(spline.GetP1(), p2, p3, spline.GetP4()); + const VSpline spl = VSpline(spline.GetP1(), p2, p3, spline.GetP4()); - UpdateControlPoints(spl, newSplPath, indexSpline); + UpdateControlPoints(spl, newSplPath, splIndex); - MoveSplinePath *moveSplPath = new MoveSplinePath(doc, oldSplPath, newSplPath, id, this->scene()); - connect(moveSplPath, &VUndoCommand::NeedLiteParsing, doc, &VAbstractPattern::LiteParseTree); - qApp->getUndoStack()->push(moveSplPath); + MoveSplinePath *moveSplPath = new MoveSplinePath(doc, oldSplPath, newSplPath, id, this->scene()); + connect(moveSplPath, &VUndoCommand::NeedLiteParsing, doc, &VAbstractPattern::LiteParseTree); + qApp->getUndoStack()->push(moveSplPath); - // Each time we move something we call recalculation scene rect. In some cases this can cause moving - // objects positions. And this cause infinite redrawing. That's why we wait the finish of saving the last move. - static bool changeFinished = true; - if (changeFinished) - { - changeFinished = false; + // Each time we move something we call recalculation scene rect. In some cases this can cause moving + // objects positions. And this cause infinite redrawing. That's why we wait the finish of saving the last move. + static bool changeFinished = true; + if (changeFinished) + { + changeFinished = false; - const QList viewList = scene()->views(); - if (not viewList.isEmpty()) - { - if (QGraphicsView *view = viewList.at(0)) + const QList viewList = scene()->views(); + if (not viewList.isEmpty()) { - VMainGraphicsScene *currentScene = qobject_cast(scene()); - SCASSERT(currentScene); - const QPointF cursorPosition = currentScene->getScenePos(); - view->ensureVisible(QRectF(cursorPosition.x()-5, cursorPosition.y()-5, 10, 10)); + if (QGraphicsView *view = viewList.at(0)) + { + VMainGraphicsScene *currentScene = qobject_cast(scene()); + SCASSERT(currentScene); + const QPointF cursorPosition = currentScene->getScenePos(); + view->ensureVisible(QRectF(cursorPosition.x()-5, cursorPosition.y()-5, 10, 10)); + } } - } - changeFinished = true; + changeFinished = true; + } } } @@ -553,7 +559,13 @@ void VToolSplinePath::hoverEnterEvent(QGraphicsSceneHoverEvent *event) { if (flags() & QGraphicsItem::ItemIsMovable) { - SetOverrideCursor(cursorArrowOpenHand, 1, 1); + oldPosition = event->scenePos(); + const auto splPath = VAbstractTool::data.GeometricObject(id); + splIndex = splPath->Segment(oldPosition); + if (IsMovable(splIndex)) + { + SetOverrideCursor(cursorArrowOpenHand, 1, 1); + } } VAbstractSpline::hoverEnterEvent(event); @@ -564,6 +576,7 @@ void VToolSplinePath::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) { if (flags() & QGraphicsItem::ItemIsMovable) { + oldPosition = event->scenePos(); //Disable cursor-arrow-openhand RestoreOverrideCursor(cursorArrowOpenHand); } @@ -586,6 +599,23 @@ void VToolSplinePath::SetVisualization() } } +//--------------------------------------------------------------------------------------------------------------------- +bool VToolSplinePath::IsMovable(int index) const +{ + const auto splPath = VAbstractTool::data.GeometricObject(id); + + //index == -1 - can delete, but decided to left + if (index == -1 || index < 1 || index > splPath->Count()) + { + return false; + } + + const VSplinePoint p1 = splPath->GetSplinePoint(index, SplinePointPosition::FirstPoint); + const VSplinePoint p2 = splPath->GetSplinePoint(index, SplinePointPosition::LastPoint); + + return p1.IsMovable() && p2.IsMovable(); +} + //--------------------------------------------------------------------------------------------------------------------- /** * @brief RefreshGeometry refresh item on scene. diff --git a/src/libs/vtools/tools/drawTools/toolcurve/vtoolsplinepath.h b/src/libs/vtools/tools/drawTools/toolcurve/vtoolsplinepath.h index 840d652c0..dc12005dc 100644 --- a/src/libs/vtools/tools/drawTools/toolcurve/vtoolsplinepath.h +++ b/src/libs/vtools/tools/drawTools/toolcurve/vtoolsplinepath.h @@ -101,7 +101,9 @@ protected: virtual void SetVisualization() Q_DECL_OVERRIDE; private: QPointF oldPosition; + int splIndex; + bool IsMovable(int index) const; void RefreshGeometry(); static void AddPathPoint(VAbstractPattern *doc, QDomElement &domElement, const VSplinePoint &splPoint); void UpdateControlPoints(const VSpline &spl, VSplinePath &splPath, const qint32 &indexSpline) const;