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_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<QGraphicsItem *>::iterator it;
QList<QGraphicsItem *> list = scene()->items();
for (it = list.begin(); it != list.end(); ++it) {
if ((*it)->data(0).toString() == "edge") {
SkeletonEditEdgeItem *edgeItem = static_cast<SkeletonEditEdgeItem *>(*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<QGraphicsItem *>::iterator it;
QList<QGraphicsItem *> list = scene()->items();
for (it = list.begin(); it != list.end(); ++it) {
if ((*it)->data(0).toString() == "edge") {
SkeletonEditEdgeItem *edgeItem = static_cast<SkeletonEditEdgeItem *>(*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) {

View File

@ -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

View File

@ -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;

View File

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

View File

@ -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);
}