X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=src%2Fonmonitoritems%2Fonmonitorcornersitem.cpp;h=f37512b85b581c37c658f2e7ce89c902b70cebb9;hb=81be3bf632b306ffd8795f0c81d4372e358e88d2;hp=419f6b6028ee4971a9b7690e24ff71ba9bd36d74;hpb=9f60e7e5262a47694d8fcb238f9d11a3ba90d3a6;p=kdenlive diff --git a/src/onmonitoritems/onmonitorcornersitem.cpp b/src/onmonitoritems/onmonitorcornersitem.cpp index 419f6b60..f37512b8 100644 --- a/src/onmonitoritems/onmonitorcornersitem.cpp +++ b/src/onmonitoritems/onmonitorcornersitem.cpp @@ -20,141 +20,237 @@ #include "onmonitorcornersitem.h" #include "kdenlivesettings.h" +#include + #include #include #include #include -OnMonitorCornersItem::OnMonitorCornersItem(MonitorScene* scene, QGraphicsItem* parent) : - AbstractOnMonitorItem(scene), - QGraphicsPolygonItem(parent) +OnMonitorCornersItem::OnMonitorCornersItem(QGraphicsItem* parent) : + QGraphicsPolygonItem(parent), + m_selectedCorner(-1), + m_modified(false) { setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable); QPen framepen(Qt::SolidLine); framepen.setColor(Qt::yellow); setPen(framepen); - setBrush(Qt::transparent); + setBrush(Qt::NoBrush); + setAcceptHoverEvents(true); } -cornersActions OnMonitorCornersItem::getMode(QPoint pos) +OnMonitorCornersItem::cornersActions OnMonitorCornersItem::getMode(QPointF pos, int *corner) { - /*pos = mapFromScene(pos).toPoint(); - // Item mapped coordinates - QPolygon pol(rect().normalized().toRect()); - - QPainterPath top(pol.point(0)); - top.lineTo(pol.point(1)); - QPainterPath bottom(pol.point(2)); - bottom.lineTo(pol.point(3)); - QPainterPath left(pol.point(0)); - left.lineTo(pol.point(3)); - QPainterPath right(pol.point(1)); - right.lineTo(pol.point(2)); + *corner = -1; + if (polygon().count() != 4) + return NoAction; QPainterPath mouseArea; - mouseArea.addRect(pos.x() - 4, pos.y() - 4, 8, 8); - - // Check for collisions between the mouse and the borders - if (mouseArea.contains(pol.point(0))) - return ResizeTopLeft; - else if (mouseArea.contains(pol.point(2))) - return ResizeBottomRight; - else if (mouseArea.contains(pol.point(1))) - return ResizeTopRight; - else if (mouseArea.contains(pol.point(3))) - return ResizeBottomLeft; - else if (top.intersects(mouseArea)) - return ResizeTop; - else if (bottom.intersects(mouseArea)) - return ResizeBottom; - else if (right.intersects(mouseArea)) - return ResizeRight; - else if (left.intersects(mouseArea)) - return ResizeLeft; - else if (rect().normalized().contains(pos)) - return Move; - else - return NoAction;*/ + mouseArea.addRect(pos.x() - 6, pos.y() - 6, 12, 12); + for (int i = 0; i < 4; ++i) { + if (mouseArea.contains(polygon().at(i))) { + *corner = i; + return Corner; + } + } + if (KdenliveSettings::onmonitoreffects_cornersshowcontrols()) { + if (mouseArea.contains(getCentroid())) + return Move; + + int j; + for (int i = 0; i < 4; ++i) { + j = (i + 1) % 4; + if (mouseArea.contains(QLineF(polygon().at(i), polygon().at(j)).pointAt(.5))) { + *corner = i; + return MoveSide; + } + } + } + return NoAction; } -void OnMonitorCornersItem::slotMousePressed(QGraphicsSceneMouseEvent* event) +void OnMonitorCornersItem::mousePressEvent(QGraphicsSceneMouseEvent* event) { - event->accept(); + m_mode = getMode(event->pos(), &m_selectedCorner); + m_lastPoint = event->scenePos(); - if (!isEnabled()) - return; - - m_clickPoint = event->scenePos(); - m_mode = getMode(m_clickPoint.toPoint()); + if (m_mode == NoAction) + event->ignore(); } -void OnMonitorCornersItem::slotMouseMoved(QGraphicsSceneMouseEvent* event) +void OnMonitorCornersItem::mouseMoveEvent(QGraphicsSceneMouseEvent* event) { - event->accept(); - - if (!isEnabled()) { - emit requestCursor(QCursor(Qt::ArrowCursor)); - return; - } - /*if (event->buttons() != Qt::NoButton && (event->screenPos() - m_screenClickPoint).manhattanLength() < QApplication::startDragDistance()) { * event->accept(); * return; }*/ - QPointF mousePos = event->scenePos(); - if (event->buttons() & Qt::LeftButton) { - m_clickPoint = mousePos; + QPointF mousePos = mapFromScene(event->scenePos()); + QPolygonF p = polygon(); switch (m_mode) { - case Corner1: - - break; - case Corner2: - + case Corner: + p.replace(m_selectedCorner, mousePos); + m_modified = true; break; - case Corner3: - + case Move: + p.translate(mousePos - m_lastPoint); + m_modified = true; break; - case Corner4: - + case MoveSide: + p[m_selectedCorner] += mousePos - m_lastPoint; + p[(m_selectedCorner + 1) % 4] += mousePos - m_lastPoint; + m_modified = true; break; default: break; } - } else { - switch (getMode(event->scenePos().toPoint())) { - case NoAction: - emit requestCursor(QCursor(Qt::ArrowCursor)); - break; - default: - emit requestCursor(QCursor(Qt::OpenHandCursor)); - break; + m_lastPoint = mousePos; + setPolygon(p); + } + + if (m_modified) { + event->accept(); + if (KdenliveSettings::monitorscene_directupdate()) { + emit changed(); + m_modified = false; } + } else { + event->ignore(); } - if (m_modified && KdenliveSettings::monitorscene_directupdate()) { - emit actionFinished(); +} + +void OnMonitorCornersItem::mouseReleaseEvent(QGraphicsSceneMouseEvent* event) +{ + if (m_modified) { m_modified = false; + emit changed(); } + event->accept(); } -/*void OnMonitorRectItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) +void OnMonitorCornersItem::hoverMoveEvent(QGraphicsSceneHoverEvent* event) { - Q_UNUSED(widget); - - painter->setPen(pen()); - painter->drawRect(option->rect); - - if (isEnabled()) { - double handleSize = 6 / painter->matrix().m11(); - double halfHandleSize = handleSize / 2; - painter->fillRect(-halfHandleSize, -halfHandleSize, handleSize, handleSize, QColor(Qt::yellow)); - painter->fillRect(option->rect.width() - halfHandleSize, -halfHandleSize, handleSize, handleSize, QColor(Qt::yellow)); - painter->fillRect(option->rect.width() - halfHandleSize, option->rect.height() - halfHandleSize, handleSize, handleSize, QColor(Qt::yellow)); - painter->fillRect(-halfHandleSize, option->rect.height() - halfHandleSize, handleSize, handleSize, QColor(Qt::yellow)); + int corner; + switch (getMode(event->pos(), &corner)) { + case NoAction: + unsetCursor(); + break; + case Move: + setCursor(QCursor(Qt::SizeAllCursor)); + break; + default: + setCursor(QCursor(Qt::OpenHandCursor)); + break; } -}*/ +} + +void OnMonitorCornersItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) +{ + painter->setPen(QPen(Qt::yellow, 1, Qt::SolidLine)); + + if (KdenliveSettings::onmonitoreffects_cornersshowlines()) + QGraphicsPolygonItem::paint(painter, option, widget); + + if (polygon().count() != 4) + return; + + double baseSize = 1 / painter->matrix().m11(); + painter->setRenderHint(QPainter::Antialiasing); + painter->setBrush(QBrush(isEnabled() ? Qt::yellow : Qt::red)); + double handleSize = 4 * baseSize; + for (int i = 0; i < 4; ++i) + painter->drawEllipse(polygon().at(i), handleSize, handleSize); + + if (KdenliveSettings::onmonitoreffects_cornersshowcontrols() && isEnabled()) { + painter->setPen(QPen(Qt::red, 2, Qt::SolidLine)); + double toolSize = 6 * baseSize; + // move tool + QPointF c = getCentroid(); + painter->drawLine(QLineF(c - QPointF(toolSize, toolSize), c + QPointF(toolSize, toolSize))); + painter->drawLine(QLineF(c - QPointF(-toolSize, toolSize), c + QPointF(-toolSize, toolSize))); + + // move side tools (2 corners at once) + int j; + for (int i = 0; i < 4; ++i) { + j = (i + 1) % 4; + QPointF m = QLineF(polygon().at(i), polygon().at(j)).pointAt(.5); + painter->drawRect(QRectF(-toolSize / 2., -toolSize / 2., toolSize, toolSize).translated(m)); + } + } +} + +QPointF OnMonitorCornersItem::getCentroid() +{ + QList p = sortedClockwise(); + + /* + * See: http://local.wasp.uwa.edu.au/~pbourke/geometry/polyarea/ + */ + + double A = 0; + int i, j; + for (i = 0; i < 4; ++i) { + j = (i + 1) % 4; + A += p[j].x() * p[i].y() - p[i].x() * p[j].y(); + } + A /= 2.; + A = qAbs(A); + + double x = 0, y = 0, f; + for (i = 0; i < 4; ++i) { + j = (i + 1) % 4; + f = (p[i].x() * p[j].y() - p[j].x() * p[i].y()); + x += f * (p[i].x() + p[j].x()); + y += f * (p[i].y() + p[j].y()); + } + x /= 6*A; + y /= 6*A; + return QPointF(x, y); +} + +QList OnMonitorCornersItem::sortedClockwise() +{ + QList points = polygon().toList(); + QPointF& a = points[0]; + QPointF& b = points[1]; + QPointF& c = points[2]; + QPointF& d = points[3]; + + /* + * http://stackoverflow.com/questions/242404/sort-four-points-in-clockwise-order + */ + + double abc = a.x() * b.y() - a.y() * b.x() + b.x() * c.y() - b.y() * c.x() + c.x() * a.y() - c.y() * a.x(); + if (abc > 0) { + double acd = a.x() * c.y() - a.y() * c.x() + c.x() * d.y() - c.y() * d.x() + d.x() * a.y() - d.y() * a.x(); + if (acd > 0) { + ; + } else { + double abd = a.x() * b.y() - a.y() * b.x() + b.x() * d.y() - b.y() * d.x() + d.x() * a.y() - d.y() * a.x(); + if (abd > 0) { + std::swap(d, c); + } else{ + std::swap(a, d); + } + } + } else { + double acd = a.x() * c.y() - a.y() * c.x() + c.x() * d.y() - c.y() * d.x() + d.x() * a.y() - d.y() * a.x(); + if (acd > 0) { + double abd = a.x() * b.y() - a.y() * b.x() + b.x() * d.y() - b.y() * d.x() + d.x() * a.y() - d.y() * a.x(); + if (abd > 0) { + std::swap(b, c); + } else { + std::swap(a, b); + } + } else { + std::swap(a, c); + } + } + return points; +} #include "onmonitorcornersitem.moc"