diff --git a/dust3d.pro b/dust3d.pro index e8a86142..c43c644a 100644 --- a/dust3d.pro +++ b/dust3d.pro @@ -24,6 +24,9 @@ HEADERS += src/skeletoneditedgeitem.h SOURCES += src/skeletontomesh.cpp HEADERS += src/skeletontomesh.h +SOURCES += src/theme.cpp +HEADERS += src/theme.h + SOURCES += src/mesh.cpp HEADERS += src/mesh.h diff --git a/src/skeletoneditedgeitem.cpp b/src/skeletoneditedgeitem.cpp index 6a6423d1..5a572a2f 100644 --- a/src/skeletoneditedgeitem.cpp +++ b/src/skeletoneditedgeitem.cpp @@ -1,5 +1,6 @@ #include #include "skeletoneditedgeitem.h" +#include "theme.h" SkeletonEditEdgeItem::SkeletonEditEdgeItem(QGraphicsItem *parent) : QGraphicsLineItem(parent), @@ -7,8 +8,8 @@ SkeletonEditEdgeItem::SkeletonEditEdgeItem(QGraphicsItem *parent) : m_secondNode(NULL) { setData(0, "edge"); - QPen pen(Qt::darkGray); - pen.setWidth(15); + QPen pen(Theme::skeletonMasterNodeBorderColor); + pen.setWidth(Theme::skeletonMasterNodeBorderSize); setPen(pen); } @@ -19,6 +20,11 @@ void SkeletonEditEdgeItem::setNodes(SkeletonEditNodeItem *first, SkeletonEditNod updatePosition(); } +bool SkeletonEditEdgeItem::connects(SkeletonEditNodeItem *nodeItem) +{ + return m_firstNode == nodeItem || m_secondNode == nodeItem; +} + void SkeletonEditEdgeItem::updatePosition() { if (m_firstNode && m_secondNode) { diff --git a/src/skeletoneditedgeitem.h b/src/skeletoneditedgeitem.h index d797022f..2faa702e 100644 --- a/src/skeletoneditedgeitem.h +++ b/src/skeletoneditedgeitem.h @@ -11,6 +11,7 @@ public: void updatePosition(); SkeletonEditNodeItem *firstNode(); SkeletonEditNodeItem *secondNode(); + bool connects(SkeletonEditNodeItem *nodeItem); private: SkeletonEditNodeItem *m_firstNode; SkeletonEditNodeItem *m_secondNode; diff --git a/src/skeletoneditgraphicsview.cpp b/src/skeletoneditgraphicsview.cpp index 864cdab5..a25d8ea6 100644 --- a/src/skeletoneditgraphicsview.cpp +++ b/src/skeletoneditgraphicsview.cpp @@ -12,7 +12,8 @@ SkeletonEditGraphicsView::SkeletonEditGraphicsView(QWidget *parent) : m_pendingEdgeItem(NULL), m_inAddNodeMode(true), m_nextStartNodeItem(NULL), - m_lastHoverNodeItem(NULL) + m_lastHoverNodeItem(NULL), + m_lastMousePos(0, 0) { setScene(new QGraphicsScene()); @@ -76,25 +77,38 @@ void SkeletonEditGraphicsView::mousePressEvent(QMouseEvent *event) if (event->button() == Qt::LeftButton) { if (!m_inAddNodeMode) { if (m_lastHoverNodeItem) { - setNextStartNodeItem(m_lastHoverNodeItem); + setNextStartNodeItem(m_lastHoverNodeItem->master()); m_lastHoverNodeItem = NULL; } } } + m_lastMousePos = mapToScene(event->pos()); +} + +float SkeletonEditGraphicsView::findXForSlave(float x) +{ + return x - m_backgroundItem->boundingRect().width() / 4; } void SkeletonEditGraphicsView::mouseReleaseEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) { if (m_inAddNodeMode) { - SkeletonEditNodeItem *newNode = new SkeletonEditNodeItem(m_pendingNodeItem->rect()); - scene()->addItem(newNode); + SkeletonEditNodeItem *masterNode = new SkeletonEditNodeItem(m_pendingNodeItem->rect()); + scene()->addItem(masterNode); + QRectF slaveRect = m_pendingNodeItem->rect(); + float x = m_pendingNodeItem->x() + m_pendingNodeItem->rect().width() / 2; + slaveRect.translate(findXForSlave(x) - x, 0); + SkeletonEditNodeItem *slaveNode = new SkeletonEditNodeItem(slaveRect); + scene()->addItem(slaveNode); + masterNode->setSlave(slaveNode); + slaveNode->setMaster(masterNode); if (m_nextStartNodeItem) { SkeletonEditEdgeItem *newEdge = new SkeletonEditEdgeItem(); - newEdge->setNodes(newNode, m_nextStartNodeItem); + newEdge->setNodes(masterNode, m_nextStartNodeItem); scene()->addItem(newEdge); } - setNextStartNodeItem(newNode); + setNextStartNodeItem(masterNode); emit nodesChanged(); } } else if (event->button() == Qt::RightButton) { @@ -141,6 +155,32 @@ void SkeletonEditGraphicsView::mouseMoveEvent(QMouseEvent *event) m_lastHoverNodeItem = NULL; } } + QPointF curMousePos = pos; + if (m_lastHoverNodeItem) { + if (event->buttons() & Qt::LeftButton) { + QRectF rect = m_lastHoverNodeItem->rect(); + if (m_lastHoverNodeItem->isMaster()) { + rect.translate(curMousePos.x() - m_lastMousePos.x(), curMousePos.y() - m_lastMousePos.y()); + QRectF 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(); + } + } + emit nodesChanged(); + } + } + m_lastMousePos = curMousePos; } void SkeletonEditGraphicsView::wheelEvent(QWheelEvent *event) diff --git a/src/skeletoneditgraphicsview.h b/src/skeletoneditgraphicsview.h index 6b9e3f0a..1ecf3c7b 100644 --- a/src/skeletoneditgraphicsview.h +++ b/src/skeletoneditgraphicsview.h @@ -29,10 +29,12 @@ private: bool m_inAddNodeMode; SkeletonEditNodeItem *m_nextStartNodeItem; SkeletonEditNodeItem *m_lastHoverNodeItem; + QPointF m_lastMousePos; void toggleAddNodeMode(); void applyAddNodeMode(); SkeletonEditNodeItem *findNodeItemByPos(QPointF pos); void setNextStartNodeItem(SkeletonEditNodeItem *item); + float findXForSlave(float x); }; diff --git a/src/skeletoneditnodeitem.cpp b/src/skeletoneditnodeitem.cpp index 5ab15323..9ede8b73 100644 --- a/src/skeletoneditnodeitem.cpp +++ b/src/skeletoneditnodeitem.cpp @@ -1,19 +1,52 @@ #include #include "skeletoneditnodeitem.h" +#include "theme.h" SkeletonEditNodeItem::SkeletonEditNodeItem(const QRectF &rect, QGraphicsItem *parent) : QGraphicsEllipseItem(rect, parent), m_highlighted(false), - m_isNextStartNode(false) + m_isNextStartNode(false), + m_master(NULL), + m_slave(NULL) { setData(0, "node"); updateBorder(); } +bool SkeletonEditNodeItem::isSlave() +{ + return NULL != m_master; +} + +bool SkeletonEditNodeItem::isMaster() +{ + return NULL == m_master; +} + +SkeletonEditNodeItem *SkeletonEditNodeItem::master() +{ + return m_master ? m_master : this; +} + +void SkeletonEditNodeItem::setMaster(SkeletonEditNodeItem *nodeItem) +{ + m_master = nodeItem; +} + +void SkeletonEditNodeItem::setSlave(SkeletonEditNodeItem *nodeItem) +{ + m_slave = nodeItem; +} + +SkeletonEditNodeItem *SkeletonEditNodeItem::slave() +{ + return m_slave; +} + QPointF SkeletonEditNodeItem::origin() { - return QPointF(rect().left() + rect().width() / 2, - rect().top() + rect().height() / 2); + return QPointF(rect().x() + rect().width() / 2, + rect().y() + rect().height() / 2); } float SkeletonEditNodeItem::radius() @@ -25,10 +58,14 @@ void SkeletonEditNodeItem::setHighlighted(bool highlighted) { m_highlighted = highlighted; if (m_highlighted) { - setBrush(QBrush(Qt::gray)); + setBrush(QBrush(isMaster() ? Theme::skeletonMasterNodeFillColor : Theme::skeletonSlaveNodeFillColor)); } else { setBrush(QBrush(Qt::transparent)); } + if (m_slave) + { + m_slave->setHighlighted(highlighted); + } } void SkeletonEditNodeItem::setIsNextStartNode(bool isNextStartNode) @@ -39,7 +76,9 @@ void SkeletonEditNodeItem::setIsNextStartNode(bool isNextStartNode) void SkeletonEditNodeItem::updateBorder() { - QPen pen(m_isNextStartNode ? Qt::black : Qt::darkGray); - pen.setWidth(15); + QPen pen(m_isNextStartNode ? + (isMaster() ? Theme::skeletonMasterNodeBorderHighlightColor : Theme::skeletonSlaveNodeBorderHighlightColor) : + (isMaster() ? Theme::skeletonMasterNodeBorderColor : Theme::skeletonSlaveNodeBorderColor)); + pen.setWidth(isMaster() ? Theme::skeletonMasterNodeBorderSize : Theme::skeletonSlaveNodeBorderSize); setPen(pen); } diff --git a/src/skeletoneditnodeitem.h b/src/skeletoneditnodeitem.h index 24ca91f5..bc048036 100644 --- a/src/skeletoneditnodeitem.h +++ b/src/skeletoneditnodeitem.h @@ -2,6 +2,8 @@ #define SKELETON_EDIT_NODE_ITEM_H #include +class SkeletonEditEdgeItem; + class SkeletonEditNodeItem : public QGraphicsEllipseItem { public: @@ -10,9 +12,17 @@ public: float radius(); void setHighlighted(bool highlited); void setIsNextStartNode(bool isNextStartNode); + bool isSlave(); + bool isMaster(); + void setMaster(SkeletonEditNodeItem *nodeItem); + void setSlave(SkeletonEditNodeItem *nodeItem); + SkeletonEditNodeItem *master(); + SkeletonEditNodeItem *slave(); private: bool m_highlighted; bool m_isNextStartNode; + SkeletonEditNodeItem *m_master; + SkeletonEditNodeItem *m_slave; void updateBorder(); }; diff --git a/src/skeletontomesh.cpp b/src/skeletontomesh.cpp index b1df87f7..d1b2a47f 100644 --- a/src/skeletontomesh.cpp +++ b/src/skeletontomesh.cpp @@ -33,7 +33,7 @@ SkeletonToMesh::SkeletonToMesh(SkeletonEditGraphicsView *graphicsView) : node.originX = origin.x(); node.originY = origin.y(); - node.originZ = 0; + node.originZ = nodeItem->slave()->origin().x(); node.bmeshNodeId = -1; node.radius = nodeItem->radius(); @@ -79,8 +79,10 @@ void SkeletonToMesh::process() return; } float left = -1; + float right = -1; float top = -1; float bottom = -1; + float zLeft = -1; for (size_t i = 0; i < m_nodes.size(); i++) { SkeletonNode *node = &m_nodes[i]; if (left < 0 || node->originX < left) { @@ -89,9 +91,15 @@ void SkeletonToMesh::process() if (top < 0 || node->originY < top) { top = node->originY; } + if (node->originX > right) { + right = node->originX; + } if (node->originY > bottom) { bottom = node->originY; } + if (zLeft < 0 || node->originZ < zLeft) { + zLeft = node->originZ; + } } float height = bottom - top; if (height <= 0) { @@ -102,9 +110,9 @@ void SkeletonToMesh::process() 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; - float y = (node->originY - top) / height; - float z = node->originZ / height; + 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 r = node->radius / height; node->bmeshNodeId = meshlite_bmesh_add_node(context, bmesh, x, y, z, r); } diff --git a/src/theme.cpp b/src/theme.cpp new file mode 100644 index 00000000..61aba809 --- /dev/null +++ b/src/theme.cpp @@ -0,0 +1,10 @@ +#include "theme.h" + +QColor Theme::skeletonMasterNodeBorderColor = QColor(0x33, 0x33, 0x33, 128); +QColor Theme::skeletonMasterNodeBorderHighlightColor = QColor(0x00, 0x00, 0x00, 200); +QColor Theme::skeletonMasterNodeFillColor = QColor(0xcc, 0xcc, 0xcc, 128); +int Theme::skeletonMasterNodeBorderSize = 15; +QColor Theme::skeletonSlaveNodeBorderColor = QColor(0x33, 0x33, 0x33, 128); +QColor Theme::skeletonSlaveNodeBorderHighlightColor = QColor(0x00, 0x00, 0x00, 200); +QColor Theme::skeletonSlaveNodeFillColor = QColor(0xcc, 0xcc, 0xcc, 128); +int Theme::skeletonSlaveNodeBorderSize = 15; diff --git a/src/theme.h b/src/theme.h new file mode 100644 index 00000000..babf768a --- /dev/null +++ b/src/theme.h @@ -0,0 +1,18 @@ +#ifndef THEME_H +#define THEME_H +#include + +class Theme +{ +public: + static QColor skeletonMasterNodeBorderColor; + static QColor skeletonMasterNodeBorderHighlightColor; + static QColor skeletonMasterNodeFillColor; + static int skeletonMasterNodeBorderSize; + static QColor skeletonSlaveNodeBorderColor; + static QColor skeletonSlaveNodeBorderHighlightColor; + static QColor skeletonSlaveNodeFillColor; + static int skeletonSlaveNodeBorderSize; +}; + +#endif