diff --git a/src/app/geometry/vsplinepath.cpp b/src/app/geometry/vsplinepath.cpp index 068c910cb..635653333 100644 --- a/src/app/geometry/vsplinepath.cpp +++ b/src/app/geometry/vsplinepath.cpp @@ -236,6 +236,30 @@ void VSplinePath::setMaxCountPoints(const qint32 &value) d->maxCountPoints = value; } +//--------------------------------------------------------------------------------------------------------------------- +int VSplinePath::Segment(const QPointF &p) const +{ + int index = -1; + for (qint32 i = 1; i <= Count(); ++i) + { + VSpline spl = VSpline(d->path.at(i-1).P(), d->path.at(i).P(), d->path.at(i-1).Angle2(), d->path.at(i).Angle1(), + d->path.at(i-1).KAsm2(), d->path.at(i).KAsm1(), d->kCurve); + + const qreal t = spl.ParamT(p); + + if (qFloor(t) == -1) + { + continue; + } + else + { + index = i; + break; + } + } + return index; +} + //--------------------------------------------------------------------------------------------------------------------- qint32 VSplinePath::CountPoint() const { diff --git a/src/app/geometry/vsplinepath.h b/src/app/geometry/vsplinepath.h index b3de10941..eec37a532 100644 --- a/src/app/geometry/vsplinepath.h +++ b/src/app/geometry/vsplinepath.h @@ -185,6 +185,8 @@ public: * @param value max count. */ void setMaxCountPoints(const qint32 &value); + + int Segment(const QPointF &p) const; private: QSharedDataPointer d; }; diff --git a/src/app/tools/drawTools/vtoolsplinepath.cpp b/src/app/tools/drawTools/vtoolsplinepath.cpp index 9c7b4157f..d40c258bf 100644 --- a/src/app/tools/drawTools/vtoolsplinepath.cpp +++ b/src/app/tools/drawTools/vtoolsplinepath.cpp @@ -44,7 +44,7 @@ const QString VToolSplinePath::ToolType = QStringLiteral("path"); */ VToolSplinePath::VToolSplinePath(VPattern *doc, VContainer *data, quint32 id, const QString &color, const Source &typeCreation, QGraphicsItem *parent) - :VAbstractSpline(doc, data, id, parent) + :VAbstractSpline(doc, data, id, parent), oldPosition() { sceneType = SceneObject::SplinePath; @@ -52,6 +52,7 @@ VToolSplinePath::VToolSplinePath(VPattern *doc, VContainer *data, quint32 id, co this->setPen(QPen(Qt::black, qApp->toPixel(qApp->widthHairLine())/factor)); this->setFlag(QGraphicsItem::ItemIsSelectable, true); this->setFlag(QGraphicsItem::ItemIsFocusable, true); + this->setFlag(QGraphicsItem::ItemIsMovable, true); this->setAcceptHoverEvents(true); const QSharedPointer splPath = data->GeometricObject(id); @@ -167,6 +168,7 @@ VToolSplinePath* VToolSplinePath::Create(const quint32 _id, VSplinePath *path, c connect(spl, &VToolSplinePath::ChoosedTool, scene, &VMainGraphicsScene::ChoosedItem); connect(scene, &VMainGraphicsScene::NewFactor, spl, &VToolSplinePath::SetFactor); connect(scene, &VMainGraphicsScene::DisableItem, spl, &VToolSplinePath::Disable); + connect(scene, &VMainGraphicsScene::EnableToolMove, spl, &VToolSplinePath::EnableToolMove); doc->AddTool(id, spl); return spl; } @@ -414,6 +416,121 @@ void VToolSplinePath::SaveOptions(QDomElement &tag, QSharedPointer &ob } } +//--------------------------------------------------------------------------------------------------------------------- +void VToolSplinePath::mousePressEvent(QGraphicsSceneMouseEvent *event) +{ + if (flags() & QGraphicsItem::ItemIsMovable) + { + if (event->button() == Qt::LeftButton && event->type() != QEvent::GraphicsSceneMouseDoubleClick) + { + VApplication::setOverrideCursor(cursorArrowCloseHand, 1, 1); + oldPosition = event->scenePos(); + event->accept(); + } + } + VAbstractSpline::mousePressEvent(event); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VToolSplinePath::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) +{ + if (flags() & QGraphicsItem::ItemIsMovable) + { + if (event->button() == Qt::LeftButton && event->type() != QEvent::GraphicsSceneMouseDoubleClick) + { + //Disable cursor-arrow-closehand + VApplication::restoreOverrideCursor(cursorArrowCloseHand); + } + } + VAbstractSpline::mouseReleaseEvent(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 + // 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) + { + return; + } + + VSpline spline = newSplPath.GetSpline(indexSpline); + const qreal t = spline.ParamT(oldPosition); + + 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. + + 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 p2 = spline.GetP2() + offset0; + const QPointF p3 = spline.GetP3() + offset1; + + oldPosition = event->scenePos(); // Now mouse here + + const VSpline spl = VSpline(spline.GetP1(), p2, p3, spline.GetP4(), spline.GetKcurve()); + + UpdateControlPoints(spl, newSplPath, indexSpline); + + MoveSplinePath *moveSplPath = new MoveSplinePath(doc, oldSplPath, newSplPath, id, this->scene()); + connect(moveSplPath, &VUndoCommand::NeedLiteParsing, doc, &VPattern::LiteParseTree); + qApp->getUndoStack()->push(moveSplPath); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VToolSplinePath::hoverEnterEvent(QGraphicsSceneHoverEvent *event) +{ + if (flags() & QGraphicsItem::ItemIsMovable) + { + VApplication::setOverrideCursor(cursorArrowOpenHand, 1, 1); + } + + VAbstractSpline::hoverEnterEvent(event); +} + +//--------------------------------------------------------------------------------------------------------------------- +void VToolSplinePath::hoverLeaveEvent(QGraphicsSceneHoverEvent *event) +{ + if (flags() & QGraphicsItem::ItemIsMovable) + { + //Disable cursor-arrow-openhand + VApplication::restoreOverrideCursor(cursorArrowOpenHand); + } + + VAbstractSpline::hoverLeaveEvent(event); +} + //--------------------------------------------------------------------------------------------------------------------- /** * @brief RefreshGeometry refresh item on scene. diff --git a/src/app/tools/drawTools/vtoolsplinepath.h b/src/app/tools/drawTools/vtoolsplinepath.h index 9b3dfd3c9..52fb849db 100644 --- a/src/app/tools/drawTools/vtoolsplinepath.h +++ b/src/app/tools/drawTools/vtoolsplinepath.h @@ -79,7 +79,14 @@ protected: virtual void RemoveReferens(); virtual void SaveDialog(QDomElement &domElement); virtual void SaveOptions(QDomElement &tag, QSharedPointer &obj); + virtual void mousePressEvent(QGraphicsSceneMouseEvent * event); + virtual void mouseReleaseEvent ( QGraphicsSceneMouseEvent * event ); + virtual void mouseMoveEvent(QGraphicsSceneMouseEvent * event); + virtual void hoverEnterEvent ( QGraphicsSceneHoverEvent * event ); + virtual void hoverLeaveEvent ( QGraphicsSceneHoverEvent * event ); private: + QPointF oldPosition; + void RefreshGeometry(); static void AddPathPoint(VPattern *doc, QDomElement &domElement, const VSplinePoint &splPoint); void UpdateControlPoints(const VSpline &spl, VSplinePath &splPath, const qint32 &indexSpline) const;