From 0ee18d41a8db67aaf44cf6d80f5cf690ee8c6f0d Mon Sep 17 00:00:00 2001 From: Jeremy Hu Date: Mon, 12 Mar 2018 21:40:42 +0800 Subject: [PATCH] Make skeleton UI more fluent --- src/skeletoneditgraphicsview.cpp | 122 ++++++++++++++++++++++--------- src/skeletoneditgraphicsview.h | 5 +- src/skeletoneditnodeitem.cpp | 5 ++ src/skeletoneditnodeitem.h | 1 + src/skeletontomesh.cpp | 7 +- 5 files changed, 105 insertions(+), 35 deletions(-) diff --git a/src/skeletoneditgraphicsview.cpp b/src/skeletoneditgraphicsview.cpp index a25d8ea6..3a4ed1e2 100644 --- a/src/skeletoneditgraphicsview.cpp +++ b/src/skeletoneditgraphicsview.cpp @@ -13,7 +13,8 @@ SkeletonEditGraphicsView::SkeletonEditGraphicsView(QWidget *parent) : m_inAddNodeMode(true), m_nextStartNodeItem(NULL), m_lastHoverNodeItem(NULL), - m_lastMousePos(0, 0) + m_lastMousePos(0, 0), + m_isMovingNodeItem(false) { setScene(new QGraphicsScene()); @@ -111,6 +112,7 @@ void SkeletonEditGraphicsView::mouseReleaseEvent(QMouseEvent *event) setNextStartNodeItem(masterNode); emit nodesChanged(); } + m_isMovingNodeItem = false; } else if (event->button() == Qt::RightButton) { if (m_inAddNodeMode) { toggleAddNodeMode(); @@ -118,6 +120,19 @@ void SkeletonEditGraphicsView::mouseReleaseEvent(QMouseEvent *event) } } +bool SkeletonEditGraphicsView::canNodeItemMoveTo(SkeletonEditNodeItem *item, QPointF moveTo) +{ + if (moveTo.x() < 0) + return false; + if (moveTo.y() < 0) + return false; + if (moveTo.x() + item->rect().width() >= m_backgroundItem->boundingRect().width()) + return false; + if (moveTo.y() + item->rect().height() >= m_backgroundItem->boundingRect().height()) + return false; + return true; +} + void SkeletonEditGraphicsView::mouseMoveEvent(QMouseEvent *event) { QWidget::mouseMoveEvent(event); @@ -139,57 +154,64 @@ void SkeletonEditGraphicsView::mouseMoveEvent(QMouseEvent *event) m_pendingEdgeItem->setLine(QLineF(m_nextStartNodeItem->origin(), QPointF(moveTo.x() + m_pendingNodeItem->rect().width() / 2, moveTo.y() + m_pendingNodeItem->rect().height() / 2))); } - if (!m_inAddNodeMode) { - SkeletonEditNodeItem *hoverNodeItem = findNodeItemByPos(pos); - if (hoverNodeItem) { - hoverNodeItem->setHighlighted(true); - } - if (hoverNodeItem != m_lastHoverNodeItem) { - if (m_lastHoverNodeItem) + if (!m_isMovingNodeItem) { + if (!m_inAddNodeMode) { + SkeletonEditNodeItem *hoverNodeItem = findNodeItemByPos(pos); + if (hoverNodeItem) { + hoverNodeItem->setHighlighted(true); + } + if (hoverNodeItem != m_lastHoverNodeItem) { + if (m_lastHoverNodeItem) + m_lastHoverNodeItem->setHighlighted(false); + m_lastHoverNodeItem = hoverNodeItem; + } + } else { + if (m_lastHoverNodeItem) { m_lastHoverNodeItem->setHighlighted(false); - m_lastHoverNodeItem = hoverNodeItem; - } - } else { - if (m_lastHoverNodeItem) { - m_lastHoverNodeItem->setHighlighted(false); - m_lastHoverNodeItem = NULL; + m_lastHoverNodeItem = NULL; + } } } QPointF curMousePos = pos; if (m_lastHoverNodeItem) { - if (event->buttons() & Qt::LeftButton) { + if ((event->buttons() & Qt::LeftButton) && + (curMousePos != m_lastMousePos || m_isMovingNodeItem)) { + m_isMovingNodeItem = true; QRectF rect = m_lastHoverNodeItem->rect(); + QRectF slaveRect; if (m_lastHoverNodeItem->isMaster()) { rect.translate(curMousePos.x() - m_lastMousePos.x(), curMousePos.y() - m_lastMousePos.y()); - QRectF slaveRect = m_lastHoverNodeItem->slave()->rect(); + slaveRect = m_lastHoverNodeItem->slave()->rect(); slaveRect.translate(0, curMousePos.y() - m_lastMousePos.y()); - m_lastHoverNodeItem->slave()->setRect(slaveRect); } else { rect.translate(curMousePos.x() - m_lastMousePos.x(), 0); } - m_lastHoverNodeItem->setRect(rect); - QList::iterator it; - QList list = scene()->items(); - for (it = list.begin(); it != list.end(); ++it) { - if ((*it)->data(0).toString() == "edge") { - SkeletonEditEdgeItem *edgeItem = static_cast(*it); - if (edgeItem->connects(m_lastHoverNodeItem)) - edgeItem->updatePosition(); + if (canNodeItemMoveTo(m_lastHoverNodeItem, QPointF(rect.x(), rect.y()))) { + if (m_lastHoverNodeItem->isMaster()) { + m_lastHoverNodeItem->slave()->setRect(slaveRect); } + m_lastHoverNodeItem->setRect(rect); + QList::iterator it; + QList list = scene()->items(); + for (it = list.begin(); it != list.end(); ++it) { + if ((*it)->data(0).toString() == "edge") { + SkeletonEditEdgeItem *edgeItem = static_cast(*it); + if (edgeItem->connects(m_lastHoverNodeItem)) + edgeItem->updatePosition(); + } + } + emit nodesChanged(); } - emit nodesChanged(); } } m_lastMousePos = curMousePos; } -void SkeletonEditGraphicsView::wheelEvent(QWheelEvent *event) +void SkeletonEditGraphicsView::AddItemRadius(QGraphicsEllipseItem *item, float delta) { - QWidget::wheelEvent(event); - qreal delta = event->delta(); - QSizeF oldSize = m_pendingNodeItem->rect().size(); - QPointF originPt = QPointF(m_pendingNodeItem->rect().left() + oldSize.width() / 2, - m_pendingNodeItem->rect().top() + oldSize.height() / 2); + QSizeF oldSize = item->rect().size(); + QPointF originPt = QPointF(item->rect().left() + oldSize.width() / 2, + item->rect().top() + oldSize.height() / 2); QSizeF newSize = QSizeF(oldSize.width() + delta, oldSize.height() + delta); if (newSize.width() < m_minimalNodeSize || newSize.height() < m_minimalNodeSize) { newSize.setWidth(m_minimalNodeSize); @@ -201,12 +223,46 @@ void SkeletonEditGraphicsView::wheelEvent(QWheelEvent *event) return; if (newLeftTop.y() < 0 || newLeftTop.y() + newSize.height() >= m_backgroundItem->boundingRect().height()) return; - m_pendingNodeItem->setRect(newLeftTop.x(), + item->setRect(newLeftTop.x(), newLeftTop.y(), newSize.width(), newSize.height()); } +bool SkeletonEditGraphicsView::canAddItemRadius(QGraphicsEllipseItem *item, float delta) +{ + QSizeF oldSize = item->rect().size(); + QPointF originPt = QPointF(item->rect().left() + oldSize.width() / 2, + item->rect().top() + oldSize.height() / 2); + QSizeF newSize = QSizeF(oldSize.width() + delta, oldSize.height() + delta); + if (newSize.width() < m_minimalNodeSize || newSize.height() < m_minimalNodeSize) { + newSize.setWidth(m_minimalNodeSize); + newSize.setHeight(m_minimalNodeSize); + } + QPointF newLeftTop = QPointF(originPt.x() - newSize.width() / 2, + originPt.y() - newSize.height() / 2); + if (newLeftTop.x() < 0 || newLeftTop.x() + newSize.width() >= m_backgroundItem->boundingRect().width()) + return false; + if (newLeftTop.y() < 0 || newLeftTop.y() + newSize.height() >= m_backgroundItem->boundingRect().height()) + return false; + return true; +} + +void SkeletonEditGraphicsView::wheelEvent(QWheelEvent *event) +{ + QWidget::wheelEvent(event); + qreal delta = event->delta(); + AddItemRadius(m_pendingNodeItem, delta); + if (!m_inAddNodeMode && m_lastHoverNodeItem) { + if (canAddItemRadius(m_lastHoverNodeItem, delta) && + canAddItemRadius(m_lastHoverNodeItem->pair(), delta)) { + AddItemRadius(m_lastHoverNodeItem, delta); + AddItemRadius(m_lastHoverNodeItem->pair(), delta); + } + emit nodesChanged(); + } +} + void SkeletonEditGraphicsView::setNextStartNodeItem(SkeletonEditNodeItem *item) { if (m_nextStartNodeItem != item) { diff --git a/src/skeletoneditgraphicsview.h b/src/skeletoneditgraphicsview.h index 1ecf3c7b..6b78e8f8 100644 --- a/src/skeletoneditgraphicsview.h +++ b/src/skeletoneditgraphicsview.h @@ -30,12 +30,15 @@ private: SkeletonEditNodeItem *m_nextStartNodeItem; SkeletonEditNodeItem *m_lastHoverNodeItem; QPointF m_lastMousePos; + bool m_isMovingNodeItem; void toggleAddNodeMode(); void applyAddNodeMode(); SkeletonEditNodeItem *findNodeItemByPos(QPointF pos); void setNextStartNodeItem(SkeletonEditNodeItem *item); float findXForSlave(float x); - + bool canNodeItemMoveTo(SkeletonEditNodeItem *item, QPointF moveTo); + void AddItemRadius(QGraphicsEllipseItem *item, float delta); + bool canAddItemRadius(QGraphicsEllipseItem *item, float delta); }; #endif diff --git a/src/skeletoneditnodeitem.cpp b/src/skeletoneditnodeitem.cpp index 9ede8b73..e29821b9 100644 --- a/src/skeletoneditnodeitem.cpp +++ b/src/skeletoneditnodeitem.cpp @@ -38,6 +38,11 @@ void SkeletonEditNodeItem::setSlave(SkeletonEditNodeItem *nodeItem) m_slave = nodeItem; } +SkeletonEditNodeItem *SkeletonEditNodeItem::pair() +{ + return m_master ? m_master : m_slave; +} + SkeletonEditNodeItem *SkeletonEditNodeItem::slave() { return m_slave; diff --git a/src/skeletoneditnodeitem.h b/src/skeletoneditnodeitem.h index bc048036..a74f9878 100644 --- a/src/skeletoneditnodeitem.h +++ b/src/skeletoneditnodeitem.h @@ -18,6 +18,7 @@ public: void setSlave(SkeletonEditNodeItem *nodeItem); SkeletonEditNodeItem *master(); SkeletonEditNodeItem *slave(); + SkeletonEditNodeItem *pair(); private: bool m_highlighted; bool m_isNextStartNode; diff --git a/src/skeletontomesh.cpp b/src/skeletontomesh.cpp index d1b2a47f..06a02f4a 100644 --- a/src/skeletontomesh.cpp +++ b/src/skeletontomesh.cpp @@ -83,6 +83,7 @@ void SkeletonToMesh::process() float top = -1; float bottom = -1; float zLeft = -1; + float zRight = -1; for (size_t i = 0; i < m_nodes.size(); i++) { SkeletonNode *node = &m_nodes[i]; if (left < 0 || node->originX < left) { @@ -100,19 +101,23 @@ void SkeletonToMesh::process() if (zLeft < 0 || node->originZ < zLeft) { zLeft = node->originZ; } + if (node->originZ > zRight) { + zRight = node->originZ; + } } float height = bottom - top; if (height <= 0) { emit finished(); return; } + float zWidth = right - left; void *context = meshlite_create_context(); int bmesh = meshlite_bmesh_create(context); for (size_t i = 0; i < m_nodes.size(); i++) { SkeletonNode *node = &m_nodes[i]; float x = (node->originX - left - height / 2) / height; float y = (node->originY - top - height / 2) / height; - float z = (node->originZ - zLeft - height / 2) / height; + float z = (node->originZ - zLeft - zWidth / 2) / height; float r = node->radius / height; node->bmeshNodeId = meshlite_bmesh_add_node(context, bmesh, x, y, z, r); }