Add multiple selection

master
Jeremy Hu 2018-04-08 23:08:23 +08:00
parent 8ee0dee3db
commit 7b3540f0c1
5 changed files with 333 additions and 138 deletions

View File

@ -206,7 +206,7 @@ void MeshGenerator::process()
int mergedMeshId = 0; int mergedMeshId = 0;
if (meshIds.size() > 1) { if (meshIds.size() > 1) {
mergedMeshId = unionMeshs(meshliteContext, meshIds); mergedMeshId = unionMeshs(meshliteContext, meshIds);
} else { } else if (meshIds.size() > 0) {
mergedMeshId = meshIds[0]; mergedMeshId = meshIds[0];
} }
if (mergedMeshId > 0) { if (mergedMeshId > 0) {

View File

@ -39,6 +39,8 @@ public:
float y; float y;
float z; float z;
float radius; float radius;
bool xMirrored;
bool zMirrored;
SkeletonNodeRootMarkMode rootMarkMode; SkeletonNodeRootMarkMode rootMarkMode;
std::vector<QUuid> edgeIds; std::vector<QUuid> edgeIds;
}; };

View File

@ -44,13 +44,13 @@ SkeletonDocumentWindow::SkeletonDocumentWindow() :
QPushButton *changeTurnaroundButton = new QPushButton(QChar(fa::image)); QPushButton *changeTurnaroundButton = new QPushButton(QChar(fa::image));
initButton(changeTurnaroundButton); initButton(changeTurnaroundButton);
QPushButton *markTrivialBranchButton = new QPushButton(QChar(fa::leaf));
initButton(markTrivialBranchButton);
QPushButton *markCenterButton = new QPushButton(QChar(fa::bullseye)); QPushButton *markCenterButton = new QPushButton(QChar(fa::bullseye));
initButton(markCenterButton); initButton(markCenterButton);
QPushButton *markMirrorButton = new QPushButton(QChar(fa::adjust)); QPushButton *markTrivialBranchButton = new QPushButton(QChar(fa::link));
initButton(markTrivialBranchButton);
QPushButton *markMirrorButton = new QPushButton(QChar(fa::clone));
initButton(markMirrorButton); initButton(markMirrorButton);
toolButtonLayout->addWidget(undoButton); toolButtonLayout->addWidget(undoButton);
@ -62,10 +62,10 @@ SkeletonDocumentWindow::SkeletonDocumentWindow() :
toolButtonLayout->addWidget(zoomOutButton); toolButtonLayout->addWidget(zoomOutButton);
//toolButtonLayout->addSpacing(10); //toolButtonLayout->addSpacing(10);
//toolButtonLayout->addWidget(changeTurnaroundButton); //toolButtonLayout->addWidget(changeTurnaroundButton);
toolButtonLayout->addSpacing(30); //toolButtonLayout->addSpacing(30);
toolButtonLayout->addWidget(markCenterButton); //toolButtonLayout->addWidget(markCenterButton);
toolButtonLayout->addWidget(markTrivialBranchButton); //toolButtonLayout->addWidget(markTrivialBranchButton);
toolButtonLayout->addWidget(markMirrorButton); //toolButtonLayout->addWidget(markMirrorButton);
QLabel *dust3dJezzasoftLabel = new QLabel; QLabel *dust3dJezzasoftLabel = new QLabel;
QImage dust3dJezzasoftImage; QImage dust3dJezzasoftImage;

View File

@ -4,6 +4,7 @@
#include <cmath> #include <cmath>
#include <QtGlobal> #include <QtGlobal>
#include <algorithm> #include <algorithm>
#include <QVector2D>
#include "skeletongraphicswidget.h" #include "skeletongraphicswidget.h"
#include "theme.h" #include "theme.h"
#include "util.h" #include "util.h"
@ -15,14 +16,16 @@ SkeletonGraphicsWidget::SkeletonGraphicsWidget(const SkeletonDocument *document)
m_dragStarted(false), m_dragStarted(false),
m_cursorNodeItem(nullptr), m_cursorNodeItem(nullptr),
m_cursorEdgeItem(nullptr), m_cursorEdgeItem(nullptr),
m_checkedNodeItem(nullptr), m_addFromNodeItem(nullptr),
m_moveStarted(false), m_moveStarted(false),
m_hoveredNodeItem(nullptr), m_hoveredNodeItem(nullptr),
m_hoveredEdgeItem(nullptr), m_hoveredEdgeItem(nullptr),
m_checkedEdgeItem(nullptr),
m_lastAddedX(0), m_lastAddedX(0),
m_lastAddedY(0), m_lastAddedY(0),
m_lastAddedZ(0) m_lastAddedZ(0),
m_selectionItem(nullptr),
m_rangeSelectionStarted(false),
m_mouseEventFromSelf(false)
{ {
setRenderHint(QPainter::Antialiasing, false); setRenderHint(QPainter::Antialiasing, false);
setBackgroundBrush(QBrush(QWidget::palette().color(QWidget::backgroundRole()), Qt::SolidPattern)); setBackgroundBrush(QBrush(QWidget::palette().color(QWidget::backgroundRole()), Qt::SolidPattern));
@ -45,6 +48,10 @@ SkeletonGraphicsWidget::SkeletonGraphicsWidget(const SkeletonDocument *document)
m_cursorEdgeItem->hide(); m_cursorEdgeItem->hide();
scene()->addItem(m_cursorEdgeItem); scene()->addItem(m_cursorEdgeItem);
m_selectionItem = new SkeletonGraphicsSelectionItem();
m_selectionItem->hide();
scene()->addItem(m_selectionItem);
scene()->setSceneRect(rect()); scene()->setSceneRect(rect());
setMouseTracking(true); setMouseTracking(true);
@ -126,7 +133,7 @@ void SkeletonGraphicsWidget::updateCursor()
setCursor(QCursor(Theme::awesome()->icon(fa::plus).pixmap(Theme::toolIconFontSize, Theme::toolIconFontSize))); setCursor(QCursor(Theme::awesome()->icon(fa::plus).pixmap(Theme::toolIconFontSize, Theme::toolIconFontSize)));
break; break;
case SkeletonDocumentEditMode::Select: case SkeletonDocumentEditMode::Select:
setCursor(QCursor(Theme::awesome()->icon(fa::mousepointer).pixmap(Theme::toolIconFontSize, Theme::toolIconFontSize))); setCursor(QCursor(Theme::awesome()->icon(fa::mousepointer).pixmap(Theme::toolIconFontSize, Theme::toolIconFontSize), Theme::toolIconFontSize / 5, 0));
break; break;
case SkeletonDocumentEditMode::Drag: case SkeletonDocumentEditMode::Drag:
setCursor(QCursor(Theme::awesome()->icon(m_dragStarted ? fa::handrocko : fa::handpapero).pixmap(Theme::toolIconFontSize, Theme::toolIconFontSize))); setCursor(QCursor(Theme::awesome()->icon(m_dragStarted ? fa::handrocko : fa::handpapero).pixmap(Theme::toolIconFontSize, Theme::toolIconFontSize)));
@ -144,16 +151,17 @@ void SkeletonGraphicsWidget::updateCursor()
void SkeletonGraphicsWidget::editModeChanged() void SkeletonGraphicsWidget::editModeChanged()
{ {
if (m_checkedNodeItem) {
if (!m_checkedNodeItem->checked()) {
if (m_hoveredNodeItem == m_checkedNodeItem) {
m_checkedNodeItem->setHovered(false);
m_hoveredNodeItem = nullptr;
}
m_checkedNodeItem = nullptr;
}
}
updateCursor(); updateCursor();
if (SkeletonDocumentEditMode::Add == m_document->editMode) {
SkeletonGraphicsNodeItem *choosenNodeItem = nullptr;
if (!m_rangeSelectionSet.empty()) {
std::set<SkeletonGraphicsNodeItem *> nodeItems;
readMergedSkeletonNodeSetFromRangeSelection(&nodeItems);
if (nodeItems.size() == 1)
choosenNodeItem = *nodeItems.begin();
}
m_addFromNodeItem = choosenNodeItem;
}
} }
void SkeletonGraphicsWidget::mouseMoveEvent(QMouseEvent *event) void SkeletonGraphicsWidget::mouseMoveEvent(QMouseEvent *event)
@ -180,7 +188,20 @@ void SkeletonGraphicsWidget::mouseReleaseEvent(QMouseEvent *event)
void SkeletonGraphicsWidget::mousePressEvent(QMouseEvent *event) void SkeletonGraphicsWidget::mousePressEvent(QMouseEvent *event)
{ {
QGraphicsView::mousePressEvent(event); QGraphicsView::mousePressEvent(event);
mousePress(event); m_mouseEventFromSelf = true;
if (mousePress(event)) {
m_mouseEventFromSelf = false;
return;
}
m_mouseEventFromSelf = false;
if (event->button() == Qt::LeftButton) {
if (SkeletonDocumentEditMode::Select == m_document->editMode) {
if (!m_rangeSelectionStarted) {
m_rangeSelectionStartPos = mouseEventScenePos(event);
m_rangeSelectionStarted = true;
}
}
}
} }
void SkeletonGraphicsWidget::mouseDoubleClickEvent(QMouseEvent *event) void SkeletonGraphicsWidget::mouseDoubleClickEvent(QMouseEvent *event)
@ -207,6 +228,17 @@ bool SkeletonGraphicsWidget::mouseMove(QMouseEvent *event)
return true; return true;
} }
if (SkeletonDocumentEditMode::Select == m_document->editMode) {
if (m_rangeSelectionStarted) {
QPointF mouseScenePos = mouseEventScenePos(event);
m_selectionItem->updateRange(m_rangeSelectionStartPos, mouseScenePos);
if (!m_selectionItem->isVisible())
m_selectionItem->setVisible(true);
checkRangeSelection();
return true;
}
}
if (SkeletonDocumentEditMode::Select == m_document->editMode || if (SkeletonDocumentEditMode::Select == m_document->editMode ||
SkeletonDocumentEditMode::Add == m_document->editMode) { SkeletonDocumentEditMode::Add == m_document->editMode) {
SkeletonGraphicsNodeItem *newHoverNodeItem = nullptr; SkeletonGraphicsNodeItem *newHoverNodeItem = nullptr;
@ -250,8 +282,8 @@ bool SkeletonGraphicsWidget::mouseMove(QMouseEvent *event)
if (!m_cursorNodeItem->isVisible()) { if (!m_cursorNodeItem->isVisible()) {
m_cursorNodeItem->show(); m_cursorNodeItem->show();
} }
if (m_checkedNodeItem) { if (m_addFromNodeItem) {
m_cursorEdgeItem->setEndpoints(m_checkedNodeItem, m_cursorNodeItem); m_cursorEdgeItem->setEndpoints(m_addFromNodeItem, m_cursorNodeItem);
if (!m_cursorEdgeItem->isVisible()) { if (!m_cursorEdgeItem->isVisible()) {
m_cursorEdgeItem->show(); m_cursorEdgeItem->show();
} }
@ -260,14 +292,19 @@ bool SkeletonGraphicsWidget::mouseMove(QMouseEvent *event)
} }
if (SkeletonDocumentEditMode::Select == m_document->editMode) { if (SkeletonDocumentEditMode::Select == m_document->editMode) {
if (m_moveStarted && m_checkedNodeItem) { if (m_moveStarted && !m_rangeSelectionSet.empty()) {
QPointF mouseScenePos = mouseEventScenePos(event); QPointF mouseScenePos = mouseEventScenePos(event);
float byX = sceneRadiusToUnified(mouseScenePos.x() - m_lastScenePos.x()); float byX = sceneRadiusToUnified(mouseScenePos.x() - m_lastScenePos.x());
float byY = sceneRadiusToUnified(mouseScenePos.y() - m_lastScenePos.y()); float byY = sceneRadiusToUnified(mouseScenePos.y() - m_lastScenePos.y());
if (SkeletonProfile::Main == m_checkedNodeItem->profile()) { std::set<SkeletonGraphicsNodeItem *> nodeItems;
emit moveNodeBy(m_checkedNodeItem->id(), byX, byY, 0); readMergedSkeletonNodeSetFromRangeSelection(&nodeItems);
for (const auto &it: nodeItems) {
SkeletonGraphicsNodeItem *nodeItem = it;
if (SkeletonProfile::Main == nodeItem->profile()) {
emit moveNodeBy(nodeItem->id(), byX, byY, 0);
} else { } else {
emit moveNodeBy(m_checkedNodeItem->id(), 0, byY, byX); emit moveNodeBy(nodeItem->id(), 0, byY, byX);
}
} }
m_lastScenePos = mouseScenePos; m_lastScenePos = mouseScenePos;
return true; return true;
@ -295,11 +332,37 @@ bool SkeletonGraphicsWidget::wheel(QWheelEvent *event)
return true; return true;
} }
} else if (SkeletonDocumentEditMode::Select == m_document->editMode) { } else if (SkeletonDocumentEditMode::Select == m_document->editMode) {
if (m_hoveredNodeItem) { if (!m_rangeSelectionSet.empty()) {
emit scaleNodeByAddRadius(m_hoveredNodeItem->id(), sceneRadiusToUnified(delta)); std::set<SkeletonGraphicsNodeItem *> nodeItems;
readMergedSkeletonNodeSetFromRangeSelection(&nodeItems);
float unifiedDelta = sceneRadiusToUnified(delta);
if (QGuiApplication::queryKeyboardModifiers().testFlag(Qt::ControlModifier)) {
QVector2D center;
for (const auto &nodeItem: nodeItems) {
center += QVector2D(nodeItem->origin());
}
center /= nodeItems.size();
for (const auto &nodeItem: nodeItems) {
QVector2D origin = QVector2D(nodeItem->origin());
QVector2D ray = (center - origin) * 0.01 * delta;
float byX = -sceneRadiusToUnified(ray.x());
float byY = -sceneRadiusToUnified(ray.y());
if (SkeletonProfile::Main == nodeItem->profile()) {
emit moveNodeBy(nodeItem->id(), byX, byY, 0);
} else {
emit moveNodeBy(nodeItem->id(), 0, byY, byX);
}
}
} else {
for (const auto &it: nodeItems) {
SkeletonGraphicsNodeItem *nodeItem = it;
emit scaleNodeByAddRadius(nodeItem->id(), unifiedDelta);
}
}
return true; return true;
} else if (m_checkedNodeItem) { } else if (m_hoveredNodeItem) {
emit scaleNodeByAddRadius(m_checkedNodeItem->id(), sceneRadiusToUnified(delta)); float unifiedDelta = sceneRadiusToUnified(delta);
emit scaleNodeByAddRadius(m_hoveredNodeItem->id(), unifiedDelta);
return true; return true;
} }
} }
@ -309,7 +372,7 @@ bool SkeletonGraphicsWidget::wheel(QWheelEvent *event)
bool SkeletonGraphicsWidget::mouseRelease(QMouseEvent *event) bool SkeletonGraphicsWidget::mouseRelease(QMouseEvent *event)
{ {
if (event->button() == Qt::LeftButton) { if (event->button() == Qt::LeftButton) {
bool processed = m_dragStarted || m_moveStarted; bool processed = m_dragStarted || m_moveStarted || m_rangeSelectionStarted;
if (m_dragStarted) { if (m_dragStarted) {
m_dragStarted = false; m_dragStarted = false;
updateCursor(); updateCursor();
@ -317,6 +380,10 @@ bool SkeletonGraphicsWidget::mouseRelease(QMouseEvent *event)
if (m_moveStarted) { if (m_moveStarted) {
m_moveStarted = false; m_moveStarted = false;
} }
if (m_rangeSelectionStarted) {
m_selectionItem->hide();
m_rangeSelectionStarted = false;
}
return processed; return processed;
} }
return false; return false;
@ -332,13 +399,13 @@ bool SkeletonGraphicsWidget::mousePress(QMouseEvent *event)
if (event->button() == Qt::LeftButton) { if (event->button() == Qt::LeftButton) {
if (SkeletonDocumentEditMode::ZoomIn == m_document->editMode) { if (SkeletonDocumentEditMode::ZoomIn == m_document->editMode) {
ViewportAnchor lastAnchor = transformationAnchor(); ViewportAnchor lastAnchor = transformationAnchor();
setTransformationAnchor(QGraphicsView::AnchorUnderMouse) ; setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
scale(1.5, 1.5); scale(1.5, 1.5);
setTransformationAnchor(lastAnchor); setTransformationAnchor(lastAnchor);
return true; return true;
} else if (SkeletonDocumentEditMode::ZoomOut == m_document->editMode) { } else if (SkeletonDocumentEditMode::ZoomOut == m_document->editMode) {
ViewportAnchor lastAnchor = transformationAnchor(); ViewportAnchor lastAnchor = transformationAnchor();
setTransformationAnchor(QGraphicsView::AnchorUnderMouse) ; setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
scale(0.5, 0.5); scale(0.5, 0.5);
setTransformationAnchor(lastAnchor); setTransformationAnchor(lastAnchor);
if ((!verticalScrollBar() || !verticalScrollBar()->isVisible()) && if ((!verticalScrollBar() || !verticalScrollBar()->isVisible()) &&
@ -354,20 +421,20 @@ bool SkeletonGraphicsWidget::mousePress(QMouseEvent *event)
} }
} else if (SkeletonDocumentEditMode::Add == m_document->editMode) { } else if (SkeletonDocumentEditMode::Add == m_document->editMode) {
if (m_cursorNodeItem->isVisible()) { if (m_cursorNodeItem->isVisible()) {
if (m_checkedNodeItem) { if (m_addFromNodeItem) {
if (m_hoveredNodeItem && m_checkedNodeItem && if (m_hoveredNodeItem && m_addFromNodeItem &&
m_hoveredNodeItem != m_checkedNodeItem && m_hoveredNodeItem != m_addFromNodeItem &&
m_hoveredNodeItem->profile() == m_checkedNodeItem->profile()) { m_hoveredNodeItem->profile() == m_addFromNodeItem->profile()) {
if (m_document->findEdgeByNodes(m_checkedNodeItem->id(), m_hoveredNodeItem->id())) if (m_document->findEdgeByNodes(m_addFromNodeItem->id(), m_hoveredNodeItem->id()))
return true; return true;
emit addEdge(m_checkedNodeItem->id(), m_hoveredNodeItem->id()); emit addEdge(m_addFromNodeItem->id(), m_hoveredNodeItem->id());
return true; return true;
} }
} }
QPointF mainProfile = m_cursorNodeItem->origin(); QPointF mainProfile = m_cursorNodeItem->origin();
QPointF sideProfile = mainProfile; QPointF sideProfile = mainProfile;
if (m_checkedNodeItem) { if (m_addFromNodeItem) {
auto itemIt = nodeItemMap.find(m_checkedNodeItem->id()); auto itemIt = nodeItemMap.find(m_addFromNodeItem->id());
sideProfile.setX(itemIt->second.second->origin().x()); sideProfile.setX(itemIt->second.second->origin().x());
} else { } else {
if (mainProfile.x() >= scene()->width() / 2) { if (mainProfile.x() >= scene()->width() / 2) {
@ -384,48 +451,30 @@ bool SkeletonGraphicsWidget::mousePress(QMouseEvent *event)
m_lastAddedY = unifiedMainPos.y(); m_lastAddedY = unifiedMainPos.y();
m_lastAddedZ = unifiedSidePos.x(); m_lastAddedZ = unifiedSidePos.x();
qDebug() << "Emit add node " << m_lastAddedX << m_lastAddedY << m_lastAddedZ; qDebug() << "Emit add node " << m_lastAddedX << m_lastAddedY << m_lastAddedZ;
emit addNode(unifiedMainPos.x(), unifiedMainPos.y(), unifiedSidePos.x(), sceneRadiusToUnified(m_cursorNodeItem->radius()), nullptr == m_checkedNodeItem ? QUuid() : m_checkedNodeItem->id()); emit addNode(unifiedMainPos.x(), unifiedMainPos.y(), unifiedSidePos.x(), sceneRadiusToUnified(m_cursorNodeItem->radius()), nullptr == m_addFromNodeItem ? QUuid() : m_addFromNodeItem->id());
return true; return true;
} }
} else if (SkeletonDocumentEditMode::Select == m_document->editMode) { } else if (SkeletonDocumentEditMode::Select == m_document->editMode) {
if (m_mouseEventFromSelf) {
bool processed = false; bool processed = false;
if ((nullptr == m_hoveredNodeItem || m_rangeSelectionSet.find(m_hoveredNodeItem) == m_rangeSelectionSet.end()) &&
(nullptr == m_hoveredEdgeItem || m_rangeSelectionSet.find(m_hoveredEdgeItem) == m_rangeSelectionSet.end())) {
if (!QGuiApplication::queryKeyboardModifiers().testFlag(Qt::ControlModifier)) {
clearRangeSelection();
}
if (m_hoveredNodeItem) { if (m_hoveredNodeItem) {
if (m_checkedNodeItem != m_hoveredNodeItem) { m_hoveredNodeItem->setChecked(true);
if (m_checkedNodeItem) { m_rangeSelectionSet.insert(m_hoveredNodeItem);
emit uncheckNode(m_checkedNodeItem->id()); } else if (m_hoveredEdgeItem) {
m_checkedNodeItem->setChecked(false); m_hoveredEdgeItem->setChecked(true);
m_rangeSelectionSet.insert(m_hoveredEdgeItem);
} }
m_checkedNodeItem = m_hoveredNodeItem;
m_checkedNodeItem->setChecked(true);
emit checkNode(m_checkedNodeItem->id());
} }
if (!m_rangeSelectionSet.empty()) {
if (!QGuiApplication::queryKeyboardModifiers().testFlag(Qt::ControlModifier)) {
m_moveStarted = true; m_moveStarted = true;
m_lastScenePos = mouseEventScenePos(event); m_lastScenePos = mouseEventScenePos(event);
processed = true; processed = true;
} else {
if (m_checkedNodeItem) {
m_checkedNodeItem->setChecked(false);
emit uncheckNode(m_checkedNodeItem->id());
m_checkedNodeItem = nullptr;
processed = true;
}
}
if (m_hoveredEdgeItem) {
if (m_checkedEdgeItem != m_hoveredEdgeItem) {
if (m_checkedEdgeItem) {
emit uncheckEdge(m_checkedEdgeItem->id());
m_checkedEdgeItem->setChecked(false);
}
m_checkedEdgeItem = m_hoveredEdgeItem;
m_checkedEdgeItem->setChecked(true);
emit checkEdge(m_checkedEdgeItem->id());
}
} else {
if (m_checkedEdgeItem) {
m_checkedEdgeItem->setChecked(false);
emit uncheckEdge(m_checkedEdgeItem->id());
m_checkedEdgeItem = nullptr;
processed = true;
} }
} }
if (processed) { if (processed) {
@ -433,6 +482,7 @@ bool SkeletonGraphicsWidget::mousePress(QMouseEvent *event)
} }
} }
} }
}
return false; return false;
} }
@ -469,14 +519,19 @@ bool SkeletonGraphicsWidget::keyPress(QKeyEvent *event)
{ {
if (event->key() == Qt::Key_Delete || event->key() ==Qt::Key_Backspace) { if (event->key() == Qt::Key_Delete || event->key() ==Qt::Key_Backspace) {
bool processed = false; bool processed = false;
if (m_checkedNodeItem) { if (!m_rangeSelectionSet.empty()) {
emit removeNode(m_checkedNodeItem->id()); std::set<QUuid> nodeIdSet;
std::set<QUuid> edgeIdSet;
readSkeletonNodeAndEdgeIdSetFromRangeSelection(&nodeIdSet, &edgeIdSet);
for (const auto &id: edgeIdSet) {
emit removeEdge(id);
processed = true; processed = true;
} }
if (m_checkedEdgeItem) { for (const auto &id: nodeIdSet) {
emit removeEdge(m_checkedEdgeItem->id()); emit removeNode(id);
processed = true; processed = true;
} }
}
if (processed) { if (processed) {
return true; return true;
} }
@ -510,15 +565,15 @@ void SkeletonGraphicsWidget::nodeAdded(QUuid nodeId)
scene()->addItem(sideProfileItem); scene()->addItem(sideProfileItem);
nodeItemMap[nodeId] = std::make_pair(mainProfileItem, sideProfileItem); nodeItemMap[nodeId] = std::make_pair(mainProfileItem, sideProfileItem);
if (nullptr == m_checkedNodeItem) { if (nullptr == m_addFromNodeItem) {
m_checkedNodeItem = mainProfileItem; m_addFromNodeItem = mainProfileItem;
} else { } else {
if (SkeletonProfile::Main == m_checkedNodeItem->profile()) { if (SkeletonProfile::Main == m_addFromNodeItem->profile()) {
m_checkedNodeItem = mainProfileItem; m_addFromNodeItem = mainProfileItem;
} else { } else {
m_checkedNodeItem = sideProfileItem; m_addFromNodeItem = sideProfileItem;
} }
m_cursorEdgeItem->setEndpoints(m_checkedNodeItem, m_cursorNodeItem); m_cursorEdgeItem->setEndpoints(m_addFromNodeItem, m_cursorNodeItem);
} }
} }
@ -556,6 +611,17 @@ void SkeletonGraphicsWidget::edgeAdded(QUuid edgeId)
edgeItemMap[edgeId] = std::make_pair(mainProfileEdgeItem, sideProfileEdgeItem); edgeItemMap[edgeId] = std::make_pair(mainProfileEdgeItem, sideProfileEdgeItem);
} }
void SkeletonGraphicsWidget::removeItem(QGraphicsItem *item)
{
if (m_hoveredNodeItem == item)
m_hoveredNodeItem = nullptr;
if (m_addFromNodeItem == item)
m_addFromNodeItem = nullptr;
if (m_hoveredEdgeItem == item)
m_hoveredEdgeItem = nullptr;
m_rangeSelectionSet.erase(item);
}
void SkeletonGraphicsWidget::nodeRemoved(QUuid nodeId) void SkeletonGraphicsWidget::nodeRemoved(QUuid nodeId)
{ {
m_lastAddedX = 0; m_lastAddedX = 0;
@ -566,14 +632,8 @@ void SkeletonGraphicsWidget::nodeRemoved(QUuid nodeId)
qDebug() << "Node removed but node id not exist:" << nodeId; qDebug() << "Node removed but node id not exist:" << nodeId;
return; return;
} }
if (m_hoveredNodeItem == nodeItemIt->second.first) removeItem(nodeItemIt->second.first);
m_hoveredNodeItem = nullptr; removeItem(nodeItemIt->second.second);
if (m_hoveredNodeItem == nodeItemIt->second.second)
m_hoveredNodeItem = nullptr;
if (m_checkedNodeItem == nodeItemIt->second.first)
m_checkedNodeItem = nullptr;
if (m_checkedNodeItem == nodeItemIt->second.second)
m_checkedNodeItem = nullptr;
delete nodeItemIt->second.first; delete nodeItemIt->second.first;
delete nodeItemIt->second.second; delete nodeItemIt->second.second;
nodeItemMap.erase(nodeItemIt); nodeItemMap.erase(nodeItemIt);
@ -586,14 +646,8 @@ void SkeletonGraphicsWidget::edgeRemoved(QUuid edgeId)
qDebug() << "Edge removed but edge id not exist:" << edgeId; qDebug() << "Edge removed but edge id not exist:" << edgeId;
return; return;
} }
if (m_hoveredEdgeItem == edgeItemIt->second.first) removeItem(edgeItemIt->second.first);
m_hoveredEdgeItem = nullptr; removeItem(edgeItemIt->second.second);
if (m_hoveredEdgeItem == edgeItemIt->second.second)
m_hoveredEdgeItem = nullptr;
if (m_checkedEdgeItem == edgeItemIt->second.first)
m_checkedEdgeItem = nullptr;
if (m_checkedEdgeItem == edgeItemIt->second.second)
m_checkedEdgeItem = nullptr;
delete edgeItemIt->second.first; delete edgeItemIt->second.first;
delete edgeItemIt->second.second; delete edgeItemIt->second.second;
edgeItemMap.erase(edgeItemIt); edgeItemMap.erase(edgeItemIt);
@ -671,3 +725,107 @@ void SkeletonGraphicsWidget::partVisibleStateChanged(QUuid partId)
} }
} }
bool SkeletonGraphicsWidget::checkSkeletonItem(QGraphicsItem *item, bool checked)
{
if (item->data(0) == "node") {
SkeletonGraphicsNodeItem *nodeItem = (SkeletonGraphicsNodeItem *)item;
if (checked != nodeItem->checked())
nodeItem->setChecked(checked);
return true;
} else if (item->data(0) == "edge") {
SkeletonGraphicsEdgeItem *edgeItem = (SkeletonGraphicsEdgeItem *)item;
if (checked != edgeItem->checked())
edgeItem->setChecked(checked);
return true;
}
return false;
}
SkeletonProfile SkeletonGraphicsWidget::readSkeletonItemProfile(QGraphicsItem *item)
{
if (item->data(0) == "node") {
SkeletonGraphicsNodeItem *nodeItem = (SkeletonGraphicsNodeItem *)item;
return nodeItem->profile();
} else if (item->data(0) == "edge") {
SkeletonGraphicsEdgeItem *edgeItem = (SkeletonGraphicsEdgeItem *)item;
return edgeItem->profile();
}
return SkeletonProfile::Unknown;
}
void SkeletonGraphicsWidget::checkRangeSelection()
{
std::set<QGraphicsItem *> newSet;
std::set<QGraphicsItem *> deleteSet;
SkeletonProfile choosenProfile = SkeletonProfile::Unknown;
if (!m_rangeSelectionSet.empty()) {
auto it = m_rangeSelectionSet.begin();
choosenProfile = readSkeletonItemProfile(*it);
}
if (m_selectionItem->isVisible()) {
QList<QGraphicsItem *> items = scene()->items(m_selectionItem->sceneBoundingRect());
for (auto it = items.begin(); it != items.end(); it++) {
QGraphicsItem *item = *it;
if (SkeletonProfile::Unknown == choosenProfile) {
if (checkSkeletonItem(item, true)) {
choosenProfile = readSkeletonItemProfile(item);
newSet.insert(item);
}
} else if (choosenProfile == readSkeletonItemProfile(item)) {
if (checkSkeletonItem(item, true))
newSet.insert(item);
}
}
}
if (!QGuiApplication::queryKeyboardModifiers().testFlag(Qt::ControlModifier)) {
for (const auto &item: m_rangeSelectionSet) {
if (newSet.find(item) == newSet.end()) {
checkSkeletonItem(item, false);
deleteSet.insert(item);
}
}
}
for (const auto &item: newSet) {
m_rangeSelectionSet.insert(item);
}
for (const auto &item: deleteSet) {
m_rangeSelectionSet.erase(item);
}
}
void SkeletonGraphicsWidget::clearRangeSelection()
{
for (const auto &item: m_rangeSelectionSet) {
checkSkeletonItem(item, false);
}
m_rangeSelectionSet.clear();
}
void SkeletonGraphicsWidget::readMergedSkeletonNodeSetFromRangeSelection(std::set<SkeletonGraphicsNodeItem *> *nodeItemSet)
{
for (const auto &it: m_rangeSelectionSet) {
QGraphicsItem *item = it;
if (item->data(0) == "node") {
nodeItemSet->insert((SkeletonGraphicsNodeItem *)item);
} else if (item->data(0) == "edge") {
SkeletonGraphicsEdgeItem *edgeItem = (SkeletonGraphicsEdgeItem *)item;
if (edgeItem->firstItem() && edgeItem->secondItem()) {
nodeItemSet->insert(edgeItem->firstItem());
nodeItemSet->insert(edgeItem->secondItem());
}
}
}
}
void SkeletonGraphicsWidget::readSkeletonNodeAndEdgeIdSetFromRangeSelection(std::set<QUuid> *nodeIdSet, std::set<QUuid> *edgeIdSet)
{
for (const auto &it: m_rangeSelectionSet) {
QGraphicsItem *item = it;
if (item->data(0) == "node") {
nodeIdSet->insert(((SkeletonGraphicsNodeItem *)item)->id());
} else if (item->data(0) == "edge") {
edgeIdSet->insert(((SkeletonGraphicsEdgeItem *)item)->id());
}
}
}

View File

@ -9,10 +9,28 @@
#include <QGraphicsPixmapItem> #include <QGraphicsPixmapItem>
#include <QThread> #include <QThread>
#include <cmath> #include <cmath>
#include <set>
#include "skeletondocument.h" #include "skeletondocument.h"
#include "turnaroundloader.h" #include "turnaroundloader.h"
#include "theme.h" #include "theme.h"
class SkeletonGraphicsSelectionItem : public QGraphicsRectItem
{
public:
SkeletonGraphicsSelectionItem()
{
QColor penColor = Theme::white;
QPen pen(penColor);
pen.setWidth(0);
pen.setStyle(Qt::DashLine);
setPen(pen);
}
void updateRange(QPointF beginPos, QPointF endPos)
{
setRect(QRectF(beginPos, endPos).normalized());
}
};
class SkeletonGraphicsNodeItem : public QGraphicsEllipseItem class SkeletonGraphicsNodeItem : public QGraphicsEllipseItem
{ {
public: public:
@ -24,7 +42,6 @@ public:
setData(0, "node"); setData(0, "node");
setRadius(32); setRadius(32);
} }
void updateAppearance() void updateAppearance()
{ {
QColor color = Theme::white; QColor color = Theme::white;
@ -52,7 +69,6 @@ public:
QBrush brush(brushColor); QBrush brush(brushColor);
setBrush(brush); setBrush(brush);
} }
void setOrigin(QPointF point) void setOrigin(QPointF point)
{ {
QPointF moveBy = point - origin(); QPointF moveBy = point - origin();
@ -61,18 +77,15 @@ public:
setRect(newRect); setRect(newRect);
updateAppearance(); updateAppearance();
} }
QPointF origin() QPointF origin()
{ {
return QPointF(rect().x() + rect().width() / 2, return QPointF(rect().x() + rect().width() / 2,
rect().y() + rect().height() / 2); rect().y() + rect().height() / 2);
} }
float radius() float radius()
{ {
return rect().width() / 2; return rect().width() / 2;
} }
void setRadius(float radius) void setRadius(float radius)
{ {
if (radius < 4) if (radius < 4)
@ -82,38 +95,36 @@ public:
radius * 2, radius * 2); radius * 2, radius * 2);
updateAppearance(); updateAppearance();
} }
SkeletonProfile profile() SkeletonProfile profile()
{ {
return m_profile; return m_profile;
} }
QUuid id() QUuid id()
{ {
return m_uuid; return m_uuid;
} }
void setId(QUuid id) void setId(QUuid id)
{ {
m_uuid = id; m_uuid = id;
} }
void setHovered(bool hovered) void setHovered(bool hovered)
{ {
m_hovered = hovered; m_hovered = hovered;
updateAppearance(); updateAppearance();
} }
void setChecked(bool checked) void setChecked(bool checked)
{ {
m_checked = checked; m_checked = checked;
updateAppearance(); updateAppearance();
} }
bool checked() bool checked()
{ {
return m_checked; return m_checked;
} }
bool hovered()
{
return m_hovered;
}
private: private:
QUuid m_uuid; QUuid m_uuid;
SkeletonProfile m_profile; SkeletonProfile m_profile;
@ -128,23 +139,32 @@ public:
m_firstItem(nullptr), m_firstItem(nullptr),
m_secondItem(nullptr), m_secondItem(nullptr),
m_hovered(false), m_hovered(false),
m_checked(false) m_checked(false),
m_profile(SkeletonProfile::Unknown)
{ {
setData(0, "edge"); setData(0, "edge");
} }
void setEndpoints(SkeletonGraphicsNodeItem *first, SkeletonGraphicsNodeItem *second) void setEndpoints(SkeletonGraphicsNodeItem *first, SkeletonGraphicsNodeItem *second)
{ {
m_firstItem = first; m_firstItem = first;
m_secondItem = second; m_secondItem = second;
updateAppearance(); updateAppearance();
} }
SkeletonGraphicsNodeItem *firstItem()
{
return m_firstItem;
}
SkeletonGraphicsNodeItem *secondItem()
{
return m_secondItem;
}
void updateAppearance() void updateAppearance()
{ {
if (nullptr == m_firstItem || nullptr == m_secondItem) if (nullptr == m_firstItem || nullptr == m_secondItem)
return; return;
m_profile = m_firstItem->profile();
QLineF line(m_firstItem->origin(), m_secondItem->origin()); QLineF line(m_firstItem->origin(), m_secondItem->origin());
QPolygonF polygon; QPolygonF polygon;
@ -176,29 +196,36 @@ public:
pen.setWidth(0); pen.setWidth(0);
setPen(pen); setPen(pen);
} }
QUuid id() QUuid id()
{ {
return m_uuid; return m_uuid;
} }
void setId(QUuid id) void setId(QUuid id)
{ {
m_uuid = id; m_uuid = id;
} }
SkeletonProfile profile()
{
return m_profile;
}
void setHovered(bool hovered) void setHovered(bool hovered)
{ {
m_hovered = hovered; m_hovered = hovered;
updateAppearance(); updateAppearance();
} }
void setChecked(bool checked) void setChecked(bool checked)
{ {
m_checked = checked; m_checked = checked;
updateAppearance(); updateAppearance();
} }
bool checked()
{
return m_checked;
}
bool hovered()
{
return m_hovered;
}
private: private:
QUuid m_uuid; QUuid m_uuid;
SkeletonGraphicsNodeItem *m_firstItem; SkeletonGraphicsNodeItem *m_firstItem;
@ -206,6 +233,7 @@ private:
QPolygonF m_selectionPolygon; QPolygonF m_selectionPolygon;
bool m_hovered; bool m_hovered;
bool m_checked; bool m_checked;
SkeletonProfile m_profile;
}; };
class SkeletonGraphicsFunctions class SkeletonGraphicsFunctions
@ -224,10 +252,6 @@ class SkeletonGraphicsWidget : public QGraphicsView, public SkeletonGraphicsFunc
Q_OBJECT Q_OBJECT
signals: signals:
void addNode(float x, float y, float z, float radius, QUuid fromNodeId); void addNode(float x, float y, float z, float radius, QUuid fromNodeId);
void uncheckNode(QUuid nodeId);
void checkNode(QUuid nodeId);
void uncheckEdge(QUuid edgeId);
void checkEdge(QUuid edgeId);
void scaleNodeByAddRadius(QUuid nodeId, float amount); void scaleNodeByAddRadius(QUuid nodeId, float amount);
void moveNodeBy(QUuid nodeId, float x, float y, float z); void moveNodeBy(QUuid nodeId, float x, float y, float z);
void removeNode(QUuid nodeId); void removeNode(QUuid nodeId);
@ -245,6 +269,10 @@ public:
bool mousePress(QMouseEvent *event); bool mousePress(QMouseEvent *event);
bool mouseDoubleClick(QMouseEvent *event); bool mouseDoubleClick(QMouseEvent *event);
bool keyPress(QKeyEvent *event); bool keyPress(QKeyEvent *event);
static bool checkSkeletonItem(QGraphicsItem *item, bool checked);
static SkeletonProfile readSkeletonItemProfile(QGraphicsItem *item);
void readMergedSkeletonNodeSetFromRangeSelection(std::set<SkeletonGraphicsNodeItem *> *nodeItemSet);
void readSkeletonNodeAndEdgeIdSetFromRangeSelection(std::set<QUuid> *nodeIdSet, std::set<QUuid> *edgeIdSet);
protected: protected:
void mouseMoveEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event);
void wheelEvent(QWheelEvent *event); void wheelEvent(QWheelEvent *event);
@ -275,6 +303,9 @@ private:
float sceneRadiusFromUnified(float radius); float sceneRadiusFromUnified(float radius);
void updateTurnaround(); void updateTurnaround();
void updateItems(); void updateItems();
void checkRangeSelection();
void clearRangeSelection();
void removeItem(QGraphicsItem *item);
private: private:
QGraphicsPixmapItem *m_backgroundItem; QGraphicsPixmapItem *m_backgroundItem;
const SkeletonDocument *m_document; const SkeletonDocument *m_document;
@ -286,13 +317,17 @@ private:
QPointF m_lastScenePos; QPointF m_lastScenePos;
SkeletonGraphicsNodeItem *m_cursorNodeItem; SkeletonGraphicsNodeItem *m_cursorNodeItem;
SkeletonGraphicsEdgeItem *m_cursorEdgeItem; SkeletonGraphicsEdgeItem *m_cursorEdgeItem;
SkeletonGraphicsNodeItem *m_checkedNodeItem; SkeletonGraphicsNodeItem *m_addFromNodeItem;
SkeletonGraphicsNodeItem *m_hoveredNodeItem; SkeletonGraphicsNodeItem *m_hoveredNodeItem;
SkeletonGraphicsEdgeItem *m_hoveredEdgeItem; SkeletonGraphicsEdgeItem *m_hoveredEdgeItem;
SkeletonGraphicsEdgeItem *m_checkedEdgeItem;
float m_lastAddedX; float m_lastAddedX;
float m_lastAddedY; float m_lastAddedY;
float m_lastAddedZ; float m_lastAddedZ;
SkeletonGraphicsSelectionItem *m_selectionItem;
QPointF m_rangeSelectionStartPos;
bool m_rangeSelectionStarted;
std::set<QGraphicsItem *> m_rangeSelectionSet;
bool m_mouseEventFromSelf;
}; };
class SkeletonGraphicsContainerWidget : public QWidget class SkeletonGraphicsContainerWidget : public QWidget