diff --git a/src/meshgenerator.cpp b/src/meshgenerator.cpp index e495d34c..a01479fc 100644 --- a/src/meshgenerator.cpp +++ b/src/meshgenerator.cpp @@ -181,6 +181,24 @@ void MeshGenerator::process() meshlite_bmesh_add_edge(meshliteContext, bmeshId, bmeshFromNodeId, bmeshToNodeId); } + for (const auto &nodeIt: m_snapshot->nodes) { + QString partId = valueOfKeyInMapOrEmpty(nodeIt.second, "partId"); + const auto partBmeshIt = partBmeshMap.find(partId); + if (partBmeshIt == partBmeshMap.end()) + continue; + const auto nodeBmeshIt = bmeshNodeMap.find(nodeIt.first); + if (nodeBmeshIt != bmeshNodeMap.end()) + continue; + int bmeshId = partBmeshIt->second; + float radius = valueOfKeyInMapOrEmpty(nodeIt.second, "radius").toFloat() / longHeight; + float x = (valueOfKeyInMapOrEmpty(nodeIt.second, "x").toFloat() - mainProfileMiddleX) / longHeight; + float y = (valueOfKeyInMapOrEmpty(nodeIt.second, "y").toFloat() - mainProfileMiddleY) / longHeight; + float z = (valueOfKeyInMapOrEmpty(nodeIt.second, "z").toFloat() - sideProfileMiddleX) / longHeight; + int bmeshNodeId = meshlite_bmesh_add_node(meshliteContext, bmeshId, x, y, z, radius); + qDebug() << "bmeshId[" << bmeshId << "] add lonely node[" << bmeshNodeId << "]" << radius << x << y << z; + bmeshNodeMap[nodeIt.first] = bmeshNodeId; + } + std::map partMeshMap; std::vector meshIds; for (const auto &partIdIt: m_snapshot->partIdList) { diff --git a/src/skeletondocumentwindow.cpp b/src/skeletondocumentwindow.cpp index 7ab3d60e..4bafbd60 100644 --- a/src/skeletondocumentwindow.cpp +++ b/src/skeletondocumentwindow.cpp @@ -194,6 +194,7 @@ SkeletonDocumentWindow::SkeletonDocumentWindow() : connect(graphicsWidget, &SkeletonGraphicsWidget::undo, m_document, &SkeletonDocument::undo); connect(graphicsWidget, &SkeletonGraphicsWidget::redo, m_document, &SkeletonDocument::redo); connect(graphicsWidget, &SkeletonGraphicsWidget::paste, m_document, &SkeletonDocument::paste); + connect(graphicsWidget, &SkeletonGraphicsWidget::changeTurnaround, this, &SkeletonDocumentWindow::changeTurnaround); connect(m_document, &SkeletonDocument::nodeAdded, graphicsWidget, &SkeletonGraphicsWidget::nodeAdded); connect(m_document, &SkeletonDocument::nodeRemoved, graphicsWidget, &SkeletonGraphicsWidget::nodeRemoved); diff --git a/src/skeletongraphicswidget.cpp b/src/skeletongraphicswidget.cpp index 2e89272a..ac789e6e 100644 --- a/src/skeletongraphicswidget.cpp +++ b/src/skeletongraphicswidget.cpp @@ -92,12 +92,12 @@ void SkeletonGraphicsWidget::showContextMenu(const QPoint &pos) QAction cutAction("Cut", this); connect(&cutAction, &QAction::triggered, this, &SkeletonGraphicsWidget::cut); - cutAction.setEnabled(!nodeItemMap.empty()); + cutAction.setEnabled(!m_rangeSelectionSet.empty()); contextMenu.addAction(&cutAction); QAction copyAction("Copy", this); connect(©Action, &QAction::triggered, this, &SkeletonGraphicsWidget::copy); - copyAction.setEnabled(!nodeItemMap.empty()); + copyAction.setEnabled(!m_rangeSelectionSet.empty()); contextMenu.addAction(©Action); QAction pasteAction("Paste", this); @@ -120,6 +120,26 @@ void SkeletonGraphicsWidget::showContextMenu(const QPoint &pos) connect(&unselectAllAction, &QAction::triggered, this, &SkeletonGraphicsWidget::unselectAll); unselectAllAction.setEnabled(!m_rangeSelectionSet.empty()); contextMenu.addAction(&unselectAllAction); + + contextMenu.addSeparator(); + + QAction addMirrorAction("Mirror", this); + connect(&addMirrorAction, &QAction::triggered, this, &SkeletonGraphicsWidget::addMirror); + addMirrorAction.setEnabled(readSkeletonNodeAndAnyEdgeOfNodeFromRangeSelection(nullptr, nullptr)); + contextMenu.addAction(&addMirrorAction); + + QAction deleteMirrorAction("Delete Mirror", this); + connect(&deleteMirrorAction, &QAction::triggered, this, &SkeletonGraphicsWidget::deleteMirror); + deleteMirrorAction.setEnabled(readSkeletonNodeAndAnyEdgeOfNodeFromRangeSelection(nullptr, nullptr)); + contextMenu.addAction(&deleteMirrorAction); + + contextMenu.addSeparator(); + + QAction changeTurnaroundAction("Change Turnaround..", this); + connect(&changeTurnaroundAction, &QAction::triggered, [=]() { + emit changeTurnaround(); + }); + contextMenu.addAction(&changeTurnaroundAction); contextMenu.exec(mapToGlobal(pos)); } @@ -589,6 +609,10 @@ QPointF SkeletonGraphicsWidget::scenePosFromUnified(QPointF pos) bool SkeletonGraphicsWidget::mouseDoubleClick(QMouseEvent *event) { + if (m_hoveredNodeItem || m_hoveredEdgeItem) { + selectPartAll(); + return true; + } return false; } @@ -947,6 +971,35 @@ void SkeletonGraphicsWidget::readSkeletonNodeAndEdgeIdSetFromRangeSelection(std: } } +bool SkeletonGraphicsWidget::readSkeletonNodeAndAnyEdgeOfNodeFromRangeSelection(SkeletonGraphicsNodeItem **nodeItem, SkeletonGraphicsEdgeItem **edgeItem) +{ + SkeletonGraphicsNodeItem *choosenNodeItem = nullptr; + SkeletonGraphicsEdgeItem *choosenEdgeItem = nullptr; + for (const auto &it: m_rangeSelectionSet) { + QGraphicsItem *item = it; + if (item->data(0) == "node") { + choosenNodeItem = (SkeletonGraphicsNodeItem *)item; + } else if (item->data(0) == "edge") { + choosenEdgeItem = (SkeletonGraphicsEdgeItem *)item; + } + if (choosenNodeItem && choosenEdgeItem) + break; + } + if (!choosenNodeItem || !choosenEdgeItem) + return false; + if (choosenNodeItem->profile() != choosenEdgeItem->profile()) + return false; + if (choosenNodeItem != choosenEdgeItem->firstItem() && choosenNodeItem != choosenEdgeItem->secondItem()) + return false; + if (nodeItem) + *nodeItem = choosenNodeItem; + if (edgeItem) + *edgeItem = choosenEdgeItem; + if (m_rangeSelectionSet.size() != 2) + return false; + return true; +} + void SkeletonGraphicsWidget::selectPartAll() { unselectAll(); @@ -1041,4 +1094,3 @@ void SkeletonGraphicsWidget::copy() QClipboard *clipboard = QApplication::clipboard(); clipboard->setText(snapshotXml); } - diff --git a/src/skeletongraphicswidget.h b/src/skeletongraphicswidget.h index 783042d1..bddca0a3 100644 --- a/src/skeletongraphicswidget.h +++ b/src/skeletongraphicswidget.h @@ -263,6 +263,9 @@ signals: void undo(); void redo(); void paste(); + void changeTurnaround(); + void addMirror(); + void deleteMirror(); public: SkeletonGraphicsWidget(const SkeletonDocument *document); std::map> nodeItemMap; @@ -277,6 +280,7 @@ public: static SkeletonProfile readSkeletonItemProfile(QGraphicsItem *item); void readMergedSkeletonNodeSetFromRangeSelection(std::set *nodeItemSet); void readSkeletonNodeAndEdgeIdSetFromRangeSelection(std::set *nodeIdSet, std::set *edgeIdSet); + bool readSkeletonNodeAndAnyEdgeOfNodeFromRangeSelection(SkeletonGraphicsNodeItem **nodeItem, SkeletonGraphicsEdgeItem **edgeItem); protected: void mouseMoveEvent(QMouseEvent *event); void wheelEvent(QWheelEvent *event); diff --git a/src/skeletonpartlistwidget.cpp b/src/skeletonpartlistwidget.cpp index daeca252..adb2740e 100644 --- a/src/skeletonpartlistwidget.cpp +++ b/src/skeletonpartlistwidget.cpp @@ -25,7 +25,6 @@ SkeletonPartWidget::SkeletonPartWidget(const SkeletonDocument *document, QUuid p QHBoxLayout *miniToolLayout = new QHBoxLayout; miniToolLayout->setSpacing(0); miniToolLayout->setContentsMargins(0, 0, 0, 0); - miniToolLayout->addSpacing(5); miniToolLayout->addWidget(m_visibleButton); miniToolLayout->addWidget(m_lockButton); miniToolLayout->addWidget(m_subdivButton);