Make skeleton UI more fluent

master
Jeremy Hu 2018-03-12 21:40:42 +08:00
parent 5b597b0f0c
commit 0ee18d41a8
5 changed files with 105 additions and 35 deletions

View File

@ -13,7 +13,8 @@ SkeletonEditGraphicsView::SkeletonEditGraphicsView(QWidget *parent) :
m_inAddNodeMode(true), m_inAddNodeMode(true),
m_nextStartNodeItem(NULL), m_nextStartNodeItem(NULL),
m_lastHoverNodeItem(NULL), m_lastHoverNodeItem(NULL),
m_lastMousePos(0, 0) m_lastMousePos(0, 0),
m_isMovingNodeItem(false)
{ {
setScene(new QGraphicsScene()); setScene(new QGraphicsScene());
@ -111,6 +112,7 @@ void SkeletonEditGraphicsView::mouseReleaseEvent(QMouseEvent *event)
setNextStartNodeItem(masterNode); setNextStartNodeItem(masterNode);
emit nodesChanged(); emit nodesChanged();
} }
m_isMovingNodeItem = false;
} else if (event->button() == Qt::RightButton) { } else if (event->button() == Qt::RightButton) {
if (m_inAddNodeMode) { if (m_inAddNodeMode) {
toggleAddNodeMode(); 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) void SkeletonEditGraphicsView::mouseMoveEvent(QMouseEvent *event)
{ {
QWidget::mouseMoveEvent(event); QWidget::mouseMoveEvent(event);
@ -139,6 +154,7 @@ void SkeletonEditGraphicsView::mouseMoveEvent(QMouseEvent *event)
m_pendingEdgeItem->setLine(QLineF(m_nextStartNodeItem->origin(), QPointF(moveTo.x() + m_pendingNodeItem->rect().width() / 2, m_pendingEdgeItem->setLine(QLineF(m_nextStartNodeItem->origin(), QPointF(moveTo.x() + m_pendingNodeItem->rect().width() / 2,
moveTo.y() + m_pendingNodeItem->rect().height() / 2))); moveTo.y() + m_pendingNodeItem->rect().height() / 2)));
} }
if (!m_isMovingNodeItem) {
if (!m_inAddNodeMode) { if (!m_inAddNodeMode) {
SkeletonEditNodeItem *hoverNodeItem = findNodeItemByPos(pos); SkeletonEditNodeItem *hoverNodeItem = findNodeItemByPos(pos);
if (hoverNodeItem) { if (hoverNodeItem) {
@ -155,18 +171,25 @@ void SkeletonEditGraphicsView::mouseMoveEvent(QMouseEvent *event)
m_lastHoverNodeItem = NULL; m_lastHoverNodeItem = NULL;
} }
} }
}
QPointF curMousePos = pos; QPointF curMousePos = pos;
if (m_lastHoverNodeItem) { 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 rect = m_lastHoverNodeItem->rect();
QRectF slaveRect;
if (m_lastHoverNodeItem->isMaster()) { if (m_lastHoverNodeItem->isMaster()) {
rect.translate(curMousePos.x() - m_lastMousePos.x(), curMousePos.y() - m_lastMousePos.y()); 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()); slaveRect.translate(0, curMousePos.y() - m_lastMousePos.y());
m_lastHoverNodeItem->slave()->setRect(slaveRect);
} else { } else {
rect.translate(curMousePos.x() - m_lastMousePos.x(), 0); rect.translate(curMousePos.x() - m_lastMousePos.x(), 0);
} }
if (canNodeItemMoveTo(m_lastHoverNodeItem, QPointF(rect.x(), rect.y()))) {
if (m_lastHoverNodeItem->isMaster()) {
m_lastHoverNodeItem->slave()->setRect(slaveRect);
}
m_lastHoverNodeItem->setRect(rect); m_lastHoverNodeItem->setRect(rect);
QList<QGraphicsItem *>::iterator it; QList<QGraphicsItem *>::iterator it;
QList<QGraphicsItem *> list = scene()->items(); QList<QGraphicsItem *> list = scene()->items();
@ -180,16 +203,15 @@ void SkeletonEditGraphicsView::mouseMoveEvent(QMouseEvent *event)
emit nodesChanged(); emit nodesChanged();
} }
} }
}
m_lastMousePos = curMousePos; m_lastMousePos = curMousePos;
} }
void SkeletonEditGraphicsView::wheelEvent(QWheelEvent *event) void SkeletonEditGraphicsView::AddItemRadius(QGraphicsEllipseItem *item, float delta)
{ {
QWidget::wheelEvent(event); QSizeF oldSize = item->rect().size();
qreal delta = event->delta(); QPointF originPt = QPointF(item->rect().left() + oldSize.width() / 2,
QSizeF oldSize = m_pendingNodeItem->rect().size(); item->rect().top() + oldSize.height() / 2);
QPointF originPt = QPointF(m_pendingNodeItem->rect().left() + oldSize.width() / 2,
m_pendingNodeItem->rect().top() + oldSize.height() / 2);
QSizeF newSize = QSizeF(oldSize.width() + delta, oldSize.height() + delta); QSizeF newSize = QSizeF(oldSize.width() + delta, oldSize.height() + delta);
if (newSize.width() < m_minimalNodeSize || newSize.height() < m_minimalNodeSize) { if (newSize.width() < m_minimalNodeSize || newSize.height() < m_minimalNodeSize) {
newSize.setWidth(m_minimalNodeSize); newSize.setWidth(m_minimalNodeSize);
@ -201,12 +223,46 @@ void SkeletonEditGraphicsView::wheelEvent(QWheelEvent *event)
return; return;
if (newLeftTop.y() < 0 || newLeftTop.y() + newSize.height() >= m_backgroundItem->boundingRect().height()) if (newLeftTop.y() < 0 || newLeftTop.y() + newSize.height() >= m_backgroundItem->boundingRect().height())
return; return;
m_pendingNodeItem->setRect(newLeftTop.x(), item->setRect(newLeftTop.x(),
newLeftTop.y(), newLeftTop.y(),
newSize.width(), newSize.width(),
newSize.height()); 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) void SkeletonEditGraphicsView::setNextStartNodeItem(SkeletonEditNodeItem *item)
{ {
if (m_nextStartNodeItem != item) { if (m_nextStartNodeItem != item) {

View File

@ -30,12 +30,15 @@ private:
SkeletonEditNodeItem *m_nextStartNodeItem; SkeletonEditNodeItem *m_nextStartNodeItem;
SkeletonEditNodeItem *m_lastHoverNodeItem; SkeletonEditNodeItem *m_lastHoverNodeItem;
QPointF m_lastMousePos; QPointF m_lastMousePos;
bool m_isMovingNodeItem;
void toggleAddNodeMode(); void toggleAddNodeMode();
void applyAddNodeMode(); void applyAddNodeMode();
SkeletonEditNodeItem *findNodeItemByPos(QPointF pos); SkeletonEditNodeItem *findNodeItemByPos(QPointF pos);
void setNextStartNodeItem(SkeletonEditNodeItem *item); void setNextStartNodeItem(SkeletonEditNodeItem *item);
float findXForSlave(float x); float findXForSlave(float x);
bool canNodeItemMoveTo(SkeletonEditNodeItem *item, QPointF moveTo);
void AddItemRadius(QGraphicsEllipseItem *item, float delta);
bool canAddItemRadius(QGraphicsEllipseItem *item, float delta);
}; };
#endif #endif

View File

@ -38,6 +38,11 @@ void SkeletonEditNodeItem::setSlave(SkeletonEditNodeItem *nodeItem)
m_slave = nodeItem; m_slave = nodeItem;
} }
SkeletonEditNodeItem *SkeletonEditNodeItem::pair()
{
return m_master ? m_master : m_slave;
}
SkeletonEditNodeItem *SkeletonEditNodeItem::slave() SkeletonEditNodeItem *SkeletonEditNodeItem::slave()
{ {
return m_slave; return m_slave;

View File

@ -18,6 +18,7 @@ public:
void setSlave(SkeletonEditNodeItem *nodeItem); void setSlave(SkeletonEditNodeItem *nodeItem);
SkeletonEditNodeItem *master(); SkeletonEditNodeItem *master();
SkeletonEditNodeItem *slave(); SkeletonEditNodeItem *slave();
SkeletonEditNodeItem *pair();
private: private:
bool m_highlighted; bool m_highlighted;
bool m_isNextStartNode; bool m_isNextStartNode;

View File

@ -83,6 +83,7 @@ void SkeletonToMesh::process()
float top = -1; float top = -1;
float bottom = -1; float bottom = -1;
float zLeft = -1; float zLeft = -1;
float zRight = -1;
for (size_t i = 0; i < m_nodes.size(); i++) { for (size_t i = 0; i < m_nodes.size(); i++) {
SkeletonNode *node = &m_nodes[i]; SkeletonNode *node = &m_nodes[i];
if (left < 0 || node->originX < left) { if (left < 0 || node->originX < left) {
@ -100,19 +101,23 @@ void SkeletonToMesh::process()
if (zLeft < 0 || node->originZ < zLeft) { if (zLeft < 0 || node->originZ < zLeft) {
zLeft = node->originZ; zLeft = node->originZ;
} }
if (node->originZ > zRight) {
zRight = node->originZ;
}
} }
float height = bottom - top; float height = bottom - top;
if (height <= 0) { if (height <= 0) {
emit finished(); emit finished();
return; return;
} }
float zWidth = right - left;
void *context = meshlite_create_context(); void *context = meshlite_create_context();
int bmesh = meshlite_bmesh_create(context); int bmesh = meshlite_bmesh_create(context);
for (size_t i = 0; i < m_nodes.size(); i++) { for (size_t i = 0; i < m_nodes.size(); i++) {
SkeletonNode *node = &m_nodes[i]; SkeletonNode *node = &m_nodes[i];
float x = (node->originX - left - height / 2) / height; float x = (node->originX - left - height / 2) / height;
float y = (node->originY - top - 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; float r = node->radius / height;
node->bmeshNodeId = meshlite_bmesh_add_node(context, bmesh, x, y, z, r); node->bmeshNodeId = meshlite_bmesh_add_node(context, bmesh, x, y, z, r);
} }