Add multiple selection
parent
8ee0dee3db
commit
7b3540f0c1
|
@ -206,7 +206,7 @@ void MeshGenerator::process()
|
|||
int mergedMeshId = 0;
|
||||
if (meshIds.size() > 1) {
|
||||
mergedMeshId = unionMeshs(meshliteContext, meshIds);
|
||||
} else {
|
||||
} else if (meshIds.size() > 0) {
|
||||
mergedMeshId = meshIds[0];
|
||||
}
|
||||
if (mergedMeshId > 0) {
|
||||
|
|
|
@ -39,6 +39,8 @@ public:
|
|||
float y;
|
||||
float z;
|
||||
float radius;
|
||||
bool xMirrored;
|
||||
bool zMirrored;
|
||||
SkeletonNodeRootMarkMode rootMarkMode;
|
||||
std::vector<QUuid> edgeIds;
|
||||
};
|
||||
|
|
|
@ -44,13 +44,13 @@ SkeletonDocumentWindow::SkeletonDocumentWindow() :
|
|||
QPushButton *changeTurnaroundButton = new QPushButton(QChar(fa::image));
|
||||
initButton(changeTurnaroundButton);
|
||||
|
||||
QPushButton *markTrivialBranchButton = new QPushButton(QChar(fa::leaf));
|
||||
initButton(markTrivialBranchButton);
|
||||
|
||||
QPushButton *markCenterButton = new QPushButton(QChar(fa::bullseye));
|
||||
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);
|
||||
|
||||
toolButtonLayout->addWidget(undoButton);
|
||||
|
@ -62,10 +62,10 @@ SkeletonDocumentWindow::SkeletonDocumentWindow() :
|
|||
toolButtonLayout->addWidget(zoomOutButton);
|
||||
//toolButtonLayout->addSpacing(10);
|
||||
//toolButtonLayout->addWidget(changeTurnaroundButton);
|
||||
toolButtonLayout->addSpacing(30);
|
||||
toolButtonLayout->addWidget(markCenterButton);
|
||||
toolButtonLayout->addWidget(markTrivialBranchButton);
|
||||
toolButtonLayout->addWidget(markMirrorButton);
|
||||
//toolButtonLayout->addSpacing(30);
|
||||
//toolButtonLayout->addWidget(markCenterButton);
|
||||
//toolButtonLayout->addWidget(markTrivialBranchButton);
|
||||
//toolButtonLayout->addWidget(markMirrorButton);
|
||||
|
||||
QLabel *dust3dJezzasoftLabel = new QLabel;
|
||||
QImage dust3dJezzasoftImage;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <cmath>
|
||||
#include <QtGlobal>
|
||||
#include <algorithm>
|
||||
#include <QVector2D>
|
||||
#include "skeletongraphicswidget.h"
|
||||
#include "theme.h"
|
||||
#include "util.h"
|
||||
|
@ -15,14 +16,16 @@ SkeletonGraphicsWidget::SkeletonGraphicsWidget(const SkeletonDocument *document)
|
|||
m_dragStarted(false),
|
||||
m_cursorNodeItem(nullptr),
|
||||
m_cursorEdgeItem(nullptr),
|
||||
m_checkedNodeItem(nullptr),
|
||||
m_addFromNodeItem(nullptr),
|
||||
m_moveStarted(false),
|
||||
m_hoveredNodeItem(nullptr),
|
||||
m_hoveredEdgeItem(nullptr),
|
||||
m_checkedEdgeItem(nullptr),
|
||||
m_lastAddedX(0),
|
||||
m_lastAddedY(0),
|
||||
m_lastAddedZ(0)
|
||||
m_lastAddedZ(0),
|
||||
m_selectionItem(nullptr),
|
||||
m_rangeSelectionStarted(false),
|
||||
m_mouseEventFromSelf(false)
|
||||
{
|
||||
setRenderHint(QPainter::Antialiasing, false);
|
||||
setBackgroundBrush(QBrush(QWidget::palette().color(QWidget::backgroundRole()), Qt::SolidPattern));
|
||||
|
@ -45,6 +48,10 @@ SkeletonGraphicsWidget::SkeletonGraphicsWidget(const SkeletonDocument *document)
|
|||
m_cursorEdgeItem->hide();
|
||||
scene()->addItem(m_cursorEdgeItem);
|
||||
|
||||
m_selectionItem = new SkeletonGraphicsSelectionItem();
|
||||
m_selectionItem->hide();
|
||||
scene()->addItem(m_selectionItem);
|
||||
|
||||
scene()->setSceneRect(rect());
|
||||
|
||||
setMouseTracking(true);
|
||||
|
@ -126,7 +133,7 @@ void SkeletonGraphicsWidget::updateCursor()
|
|||
setCursor(QCursor(Theme::awesome()->icon(fa::plus).pixmap(Theme::toolIconFontSize, Theme::toolIconFontSize)));
|
||||
break;
|
||||
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;
|
||||
case SkeletonDocumentEditMode::Drag:
|
||||
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()
|
||||
{
|
||||
if (m_checkedNodeItem) {
|
||||
if (!m_checkedNodeItem->checked()) {
|
||||
if (m_hoveredNodeItem == m_checkedNodeItem) {
|
||||
m_checkedNodeItem->setHovered(false);
|
||||
m_hoveredNodeItem = nullptr;
|
||||
}
|
||||
m_checkedNodeItem = nullptr;
|
||||
}
|
||||
}
|
||||
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)
|
||||
|
@ -180,7 +188,20 @@ void SkeletonGraphicsWidget::mouseReleaseEvent(QMouseEvent *event)
|
|||
void SkeletonGraphicsWidget::mousePressEvent(QMouseEvent *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)
|
||||
|
@ -207,6 +228,17 @@ bool SkeletonGraphicsWidget::mouseMove(QMouseEvent *event)
|
|||
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 ||
|
||||
SkeletonDocumentEditMode::Add == m_document->editMode) {
|
||||
SkeletonGraphicsNodeItem *newHoverNodeItem = nullptr;
|
||||
|
@ -250,8 +282,8 @@ bool SkeletonGraphicsWidget::mouseMove(QMouseEvent *event)
|
|||
if (!m_cursorNodeItem->isVisible()) {
|
||||
m_cursorNodeItem->show();
|
||||
}
|
||||
if (m_checkedNodeItem) {
|
||||
m_cursorEdgeItem->setEndpoints(m_checkedNodeItem, m_cursorNodeItem);
|
||||
if (m_addFromNodeItem) {
|
||||
m_cursorEdgeItem->setEndpoints(m_addFromNodeItem, m_cursorNodeItem);
|
||||
if (!m_cursorEdgeItem->isVisible()) {
|
||||
m_cursorEdgeItem->show();
|
||||
}
|
||||
|
@ -260,14 +292,19 @@ bool SkeletonGraphicsWidget::mouseMove(QMouseEvent *event)
|
|||
}
|
||||
|
||||
if (SkeletonDocumentEditMode::Select == m_document->editMode) {
|
||||
if (m_moveStarted && m_checkedNodeItem) {
|
||||
if (m_moveStarted && !m_rangeSelectionSet.empty()) {
|
||||
QPointF mouseScenePos = mouseEventScenePos(event);
|
||||
float byX = sceneRadiusToUnified(mouseScenePos.x() - m_lastScenePos.x());
|
||||
float byY = sceneRadiusToUnified(mouseScenePos.y() - m_lastScenePos.y());
|
||||
if (SkeletonProfile::Main == m_checkedNodeItem->profile()) {
|
||||
emit moveNodeBy(m_checkedNodeItem->id(), byX, byY, 0);
|
||||
} else {
|
||||
emit moveNodeBy(m_checkedNodeItem->id(), 0, byY, byX);
|
||||
std::set<SkeletonGraphicsNodeItem *> nodeItems;
|
||||
readMergedSkeletonNodeSetFromRangeSelection(&nodeItems);
|
||||
for (const auto &it: nodeItems) {
|
||||
SkeletonGraphicsNodeItem *nodeItem = it;
|
||||
if (SkeletonProfile::Main == nodeItem->profile()) {
|
||||
emit moveNodeBy(nodeItem->id(), byX, byY, 0);
|
||||
} else {
|
||||
emit moveNodeBy(nodeItem->id(), 0, byY, byX);
|
||||
}
|
||||
}
|
||||
m_lastScenePos = mouseScenePos;
|
||||
return true;
|
||||
|
@ -295,11 +332,37 @@ bool SkeletonGraphicsWidget::wheel(QWheelEvent *event)
|
|||
return true;
|
||||
}
|
||||
} else if (SkeletonDocumentEditMode::Select == m_document->editMode) {
|
||||
if (m_hoveredNodeItem) {
|
||||
emit scaleNodeByAddRadius(m_hoveredNodeItem->id(), sceneRadiusToUnified(delta));
|
||||
if (!m_rangeSelectionSet.empty()) {
|
||||
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;
|
||||
} else if (m_checkedNodeItem) {
|
||||
emit scaleNodeByAddRadius(m_checkedNodeItem->id(), sceneRadiusToUnified(delta));
|
||||
} else if (m_hoveredNodeItem) {
|
||||
float unifiedDelta = sceneRadiusToUnified(delta);
|
||||
emit scaleNodeByAddRadius(m_hoveredNodeItem->id(), unifiedDelta);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -309,7 +372,7 @@ bool SkeletonGraphicsWidget::wheel(QWheelEvent *event)
|
|||
bool SkeletonGraphicsWidget::mouseRelease(QMouseEvent *event)
|
||||
{
|
||||
if (event->button() == Qt::LeftButton) {
|
||||
bool processed = m_dragStarted || m_moveStarted;
|
||||
bool processed = m_dragStarted || m_moveStarted || m_rangeSelectionStarted;
|
||||
if (m_dragStarted) {
|
||||
m_dragStarted = false;
|
||||
updateCursor();
|
||||
|
@ -317,6 +380,10 @@ bool SkeletonGraphicsWidget::mouseRelease(QMouseEvent *event)
|
|||
if (m_moveStarted) {
|
||||
m_moveStarted = false;
|
||||
}
|
||||
if (m_rangeSelectionStarted) {
|
||||
m_selectionItem->hide();
|
||||
m_rangeSelectionStarted = false;
|
||||
}
|
||||
return processed;
|
||||
}
|
||||
return false;
|
||||
|
@ -332,13 +399,13 @@ bool SkeletonGraphicsWidget::mousePress(QMouseEvent *event)
|
|||
if (event->button() == Qt::LeftButton) {
|
||||
if (SkeletonDocumentEditMode::ZoomIn == m_document->editMode) {
|
||||
ViewportAnchor lastAnchor = transformationAnchor();
|
||||
setTransformationAnchor(QGraphicsView::AnchorUnderMouse) ;
|
||||
setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
|
||||
scale(1.5, 1.5);
|
||||
setTransformationAnchor(lastAnchor);
|
||||
return true;
|
||||
} else if (SkeletonDocumentEditMode::ZoomOut == m_document->editMode) {
|
||||
ViewportAnchor lastAnchor = transformationAnchor();
|
||||
setTransformationAnchor(QGraphicsView::AnchorUnderMouse) ;
|
||||
setTransformationAnchor(QGraphicsView::AnchorUnderMouse);
|
||||
scale(0.5, 0.5);
|
||||
setTransformationAnchor(lastAnchor);
|
||||
if ((!verticalScrollBar() || !verticalScrollBar()->isVisible()) &&
|
||||
|
@ -354,20 +421,20 @@ bool SkeletonGraphicsWidget::mousePress(QMouseEvent *event)
|
|||
}
|
||||
} else if (SkeletonDocumentEditMode::Add == m_document->editMode) {
|
||||
if (m_cursorNodeItem->isVisible()) {
|
||||
if (m_checkedNodeItem) {
|
||||
if (m_hoveredNodeItem && m_checkedNodeItem &&
|
||||
m_hoveredNodeItem != m_checkedNodeItem &&
|
||||
m_hoveredNodeItem->profile() == m_checkedNodeItem->profile()) {
|
||||
if (m_document->findEdgeByNodes(m_checkedNodeItem->id(), m_hoveredNodeItem->id()))
|
||||
if (m_addFromNodeItem) {
|
||||
if (m_hoveredNodeItem && m_addFromNodeItem &&
|
||||
m_hoveredNodeItem != m_addFromNodeItem &&
|
||||
m_hoveredNodeItem->profile() == m_addFromNodeItem->profile()) {
|
||||
if (m_document->findEdgeByNodes(m_addFromNodeItem->id(), m_hoveredNodeItem->id()))
|
||||
return true;
|
||||
emit addEdge(m_checkedNodeItem->id(), m_hoveredNodeItem->id());
|
||||
emit addEdge(m_addFromNodeItem->id(), m_hoveredNodeItem->id());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
QPointF mainProfile = m_cursorNodeItem->origin();
|
||||
QPointF sideProfile = mainProfile;
|
||||
if (m_checkedNodeItem) {
|
||||
auto itemIt = nodeItemMap.find(m_checkedNodeItem->id());
|
||||
if (m_addFromNodeItem) {
|
||||
auto itemIt = nodeItemMap.find(m_addFromNodeItem->id());
|
||||
sideProfile.setX(itemIt->second.second->origin().x());
|
||||
} else {
|
||||
if (mainProfile.x() >= scene()->width() / 2) {
|
||||
|
@ -384,52 +451,35 @@ bool SkeletonGraphicsWidget::mousePress(QMouseEvent *event)
|
|||
m_lastAddedY = unifiedMainPos.y();
|
||||
m_lastAddedZ = unifiedSidePos.x();
|
||||
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;
|
||||
}
|
||||
} else if (SkeletonDocumentEditMode::Select == m_document->editMode) {
|
||||
bool processed = false;
|
||||
if (m_hoveredNodeItem) {
|
||||
if (m_checkedNodeItem != m_hoveredNodeItem) {
|
||||
if (m_checkedNodeItem) {
|
||||
emit uncheckNode(m_checkedNodeItem->id());
|
||||
m_checkedNodeItem->setChecked(false);
|
||||
if (m_mouseEventFromSelf) {
|
||||
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();
|
||||
}
|
||||
m_checkedNodeItem = m_hoveredNodeItem;
|
||||
m_checkedNodeItem->setChecked(true);
|
||||
emit checkNode(m_checkedNodeItem->id());
|
||||
}
|
||||
m_moveStarted = true;
|
||||
m_lastScenePos = mouseEventScenePos(event);
|
||||
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);
|
||||
if (m_hoveredNodeItem) {
|
||||
m_hoveredNodeItem->setChecked(true);
|
||||
m_rangeSelectionSet.insert(m_hoveredNodeItem);
|
||||
} else if (m_hoveredEdgeItem) {
|
||||
m_hoveredEdgeItem->setChecked(true);
|
||||
m_rangeSelectionSet.insert(m_hoveredEdgeItem);
|
||||
}
|
||||
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 (!m_rangeSelectionSet.empty()) {
|
||||
if (!QGuiApplication::queryKeyboardModifiers().testFlag(Qt::ControlModifier)) {
|
||||
m_moveStarted = true;
|
||||
m_lastScenePos = mouseEventScenePos(event);
|
||||
processed = true;
|
||||
}
|
||||
}
|
||||
if (processed) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (processed) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -469,13 +519,18 @@ bool SkeletonGraphicsWidget::keyPress(QKeyEvent *event)
|
|||
{
|
||||
if (event->key() == Qt::Key_Delete || event->key() ==Qt::Key_Backspace) {
|
||||
bool processed = false;
|
||||
if (m_checkedNodeItem) {
|
||||
emit removeNode(m_checkedNodeItem->id());
|
||||
processed = true;
|
||||
}
|
||||
if (m_checkedEdgeItem) {
|
||||
emit removeEdge(m_checkedEdgeItem->id());
|
||||
processed = true;
|
||||
if (!m_rangeSelectionSet.empty()) {
|
||||
std::set<QUuid> nodeIdSet;
|
||||
std::set<QUuid> edgeIdSet;
|
||||
readSkeletonNodeAndEdgeIdSetFromRangeSelection(&nodeIdSet, &edgeIdSet);
|
||||
for (const auto &id: edgeIdSet) {
|
||||
emit removeEdge(id);
|
||||
processed = true;
|
||||
}
|
||||
for (const auto &id: nodeIdSet) {
|
||||
emit removeNode(id);
|
||||
processed = true;
|
||||
}
|
||||
}
|
||||
if (processed) {
|
||||
return true;
|
||||
|
@ -510,15 +565,15 @@ void SkeletonGraphicsWidget::nodeAdded(QUuid nodeId)
|
|||
scene()->addItem(sideProfileItem);
|
||||
nodeItemMap[nodeId] = std::make_pair(mainProfileItem, sideProfileItem);
|
||||
|
||||
if (nullptr == m_checkedNodeItem) {
|
||||
m_checkedNodeItem = mainProfileItem;
|
||||
if (nullptr == m_addFromNodeItem) {
|
||||
m_addFromNodeItem = mainProfileItem;
|
||||
} else {
|
||||
if (SkeletonProfile::Main == m_checkedNodeItem->profile()) {
|
||||
m_checkedNodeItem = mainProfileItem;
|
||||
if (SkeletonProfile::Main == m_addFromNodeItem->profile()) {
|
||||
m_addFromNodeItem = mainProfileItem;
|
||||
} 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);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
m_lastAddedX = 0;
|
||||
|
@ -566,14 +632,8 @@ void SkeletonGraphicsWidget::nodeRemoved(QUuid nodeId)
|
|||
qDebug() << "Node removed but node id not exist:" << nodeId;
|
||||
return;
|
||||
}
|
||||
if (m_hoveredNodeItem == nodeItemIt->second.first)
|
||||
m_hoveredNodeItem = nullptr;
|
||||
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;
|
||||
removeItem(nodeItemIt->second.first);
|
||||
removeItem(nodeItemIt->second.second);
|
||||
delete nodeItemIt->second.first;
|
||||
delete nodeItemIt->second.second;
|
||||
nodeItemMap.erase(nodeItemIt);
|
||||
|
@ -586,14 +646,8 @@ void SkeletonGraphicsWidget::edgeRemoved(QUuid edgeId)
|
|||
qDebug() << "Edge removed but edge id not exist:" << edgeId;
|
||||
return;
|
||||
}
|
||||
if (m_hoveredEdgeItem == edgeItemIt->second.first)
|
||||
m_hoveredEdgeItem = nullptr;
|
||||
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;
|
||||
removeItem(edgeItemIt->second.first);
|
||||
removeItem(edgeItemIt->second.second);
|
||||
delete edgeItemIt->second.first;
|
||||
delete edgeItemIt->second.second;
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,10 +9,28 @@
|
|||
#include <QGraphicsPixmapItem>
|
||||
#include <QThread>
|
||||
#include <cmath>
|
||||
#include <set>
|
||||
#include "skeletondocument.h"
|
||||
#include "turnaroundloader.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
|
||||
{
|
||||
public:
|
||||
|
@ -24,7 +42,6 @@ public:
|
|||
setData(0, "node");
|
||||
setRadius(32);
|
||||
}
|
||||
|
||||
void updateAppearance()
|
||||
{
|
||||
QColor color = Theme::white;
|
||||
|
@ -52,7 +69,6 @@ public:
|
|||
QBrush brush(brushColor);
|
||||
setBrush(brush);
|
||||
}
|
||||
|
||||
void setOrigin(QPointF point)
|
||||
{
|
||||
QPointF moveBy = point - origin();
|
||||
|
@ -61,18 +77,15 @@ public:
|
|||
setRect(newRect);
|
||||
updateAppearance();
|
||||
}
|
||||
|
||||
QPointF origin()
|
||||
{
|
||||
return QPointF(rect().x() + rect().width() / 2,
|
||||
rect().y() + rect().height() / 2);
|
||||
}
|
||||
|
||||
float radius()
|
||||
{
|
||||
return rect().width() / 2;
|
||||
}
|
||||
|
||||
void setRadius(float radius)
|
||||
{
|
||||
if (radius < 4)
|
||||
|
@ -82,38 +95,36 @@ public:
|
|||
radius * 2, radius * 2);
|
||||
updateAppearance();
|
||||
}
|
||||
|
||||
SkeletonProfile profile()
|
||||
{
|
||||
return m_profile;
|
||||
}
|
||||
|
||||
QUuid id()
|
||||
{
|
||||
return m_uuid;
|
||||
}
|
||||
|
||||
void setId(QUuid id)
|
||||
{
|
||||
m_uuid = id;
|
||||
}
|
||||
|
||||
void setHovered(bool hovered)
|
||||
{
|
||||
m_hovered = hovered;
|
||||
updateAppearance();
|
||||
}
|
||||
|
||||
void setChecked(bool checked)
|
||||
{
|
||||
m_checked = checked;
|
||||
updateAppearance();
|
||||
}
|
||||
|
||||
bool checked()
|
||||
{
|
||||
return m_checked;
|
||||
}
|
||||
bool hovered()
|
||||
{
|
||||
return m_hovered;
|
||||
}
|
||||
private:
|
||||
QUuid m_uuid;
|
||||
SkeletonProfile m_profile;
|
||||
|
@ -128,23 +139,32 @@ public:
|
|||
m_firstItem(nullptr),
|
||||
m_secondItem(nullptr),
|
||||
m_hovered(false),
|
||||
m_checked(false)
|
||||
m_checked(false),
|
||||
m_profile(SkeletonProfile::Unknown)
|
||||
{
|
||||
setData(0, "edge");
|
||||
}
|
||||
|
||||
void setEndpoints(SkeletonGraphicsNodeItem *first, SkeletonGraphicsNodeItem *second)
|
||||
{
|
||||
m_firstItem = first;
|
||||
m_secondItem = second;
|
||||
updateAppearance();
|
||||
}
|
||||
|
||||
SkeletonGraphicsNodeItem *firstItem()
|
||||
{
|
||||
return m_firstItem;
|
||||
}
|
||||
SkeletonGraphicsNodeItem *secondItem()
|
||||
{
|
||||
return m_secondItem;
|
||||
}
|
||||
void updateAppearance()
|
||||
{
|
||||
if (nullptr == m_firstItem || nullptr == m_secondItem)
|
||||
return;
|
||||
|
||||
m_profile = m_firstItem->profile();
|
||||
|
||||
QLineF line(m_firstItem->origin(), m_secondItem->origin());
|
||||
|
||||
QPolygonF polygon;
|
||||
|
@ -176,29 +196,36 @@ public:
|
|||
pen.setWidth(0);
|
||||
setPen(pen);
|
||||
}
|
||||
|
||||
QUuid id()
|
||||
{
|
||||
return m_uuid;
|
||||
}
|
||||
|
||||
void setId(QUuid id)
|
||||
{
|
||||
m_uuid = id;
|
||||
}
|
||||
|
||||
SkeletonProfile profile()
|
||||
{
|
||||
return m_profile;
|
||||
}
|
||||
void setHovered(bool hovered)
|
||||
{
|
||||
m_hovered = hovered;
|
||||
updateAppearance();
|
||||
}
|
||||
|
||||
void setChecked(bool checked)
|
||||
{
|
||||
m_checked = checked;
|
||||
updateAppearance();
|
||||
}
|
||||
|
||||
bool checked()
|
||||
{
|
||||
return m_checked;
|
||||
}
|
||||
bool hovered()
|
||||
{
|
||||
return m_hovered;
|
||||
}
|
||||
private:
|
||||
QUuid m_uuid;
|
||||
SkeletonGraphicsNodeItem *m_firstItem;
|
||||
|
@ -206,6 +233,7 @@ private:
|
|||
QPolygonF m_selectionPolygon;
|
||||
bool m_hovered;
|
||||
bool m_checked;
|
||||
SkeletonProfile m_profile;
|
||||
};
|
||||
|
||||
class SkeletonGraphicsFunctions
|
||||
|
@ -224,10 +252,6 @@ class SkeletonGraphicsWidget : public QGraphicsView, public SkeletonGraphicsFunc
|
|||
Q_OBJECT
|
||||
signals:
|
||||
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 moveNodeBy(QUuid nodeId, float x, float y, float z);
|
||||
void removeNode(QUuid nodeId);
|
||||
|
@ -245,6 +269,10 @@ public:
|
|||
bool mousePress(QMouseEvent *event);
|
||||
bool mouseDoubleClick(QMouseEvent *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:
|
||||
void mouseMoveEvent(QMouseEvent *event);
|
||||
void wheelEvent(QWheelEvent *event);
|
||||
|
@ -275,6 +303,9 @@ private:
|
|||
float sceneRadiusFromUnified(float radius);
|
||||
void updateTurnaround();
|
||||
void updateItems();
|
||||
void checkRangeSelection();
|
||||
void clearRangeSelection();
|
||||
void removeItem(QGraphicsItem *item);
|
||||
private:
|
||||
QGraphicsPixmapItem *m_backgroundItem;
|
||||
const SkeletonDocument *m_document;
|
||||
|
@ -286,13 +317,17 @@ private:
|
|||
QPointF m_lastScenePos;
|
||||
SkeletonGraphicsNodeItem *m_cursorNodeItem;
|
||||
SkeletonGraphicsEdgeItem *m_cursorEdgeItem;
|
||||
SkeletonGraphicsNodeItem *m_checkedNodeItem;
|
||||
SkeletonGraphicsNodeItem *m_addFromNodeItem;
|
||||
SkeletonGraphicsNodeItem *m_hoveredNodeItem;
|
||||
SkeletonGraphicsEdgeItem *m_hoveredEdgeItem;
|
||||
SkeletonGraphicsEdgeItem *m_checkedEdgeItem;
|
||||
float m_lastAddedX;
|
||||
float m_lastAddedY;
|
||||
float m_lastAddedZ;
|
||||
SkeletonGraphicsSelectionItem *m_selectionItem;
|
||||
QPointF m_rangeSelectionStartPos;
|
||||
bool m_rangeSelectionStarted;
|
||||
std::set<QGraphicsItem *> m_rangeSelectionSet;
|
||||
bool m_mouseEventFromSelf;
|
||||
};
|
||||
|
||||
class SkeletonGraphicsContainerWidget : public QWidget
|
||||
|
|
Loading…
Reference in New Issue