diff --git a/CONTRIBUTORS b/CONTRIBUTORS index 8d96b4ed..bf9cec4f 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -27,4 +27,5 @@ fornclake bvanevery Toshio Araki Evan Gruda -KeepFenDou \ No newline at end of file +KeepFenDou +Kubilay Yalçın \ No newline at end of file diff --git a/src/document.cpp b/src/document.cpp index 18689789..c9b8003d 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -61,6 +61,9 @@ Document::Document() : { connect(&Preferences::instance(), &Preferences::partColorChanged, this, &Document::applyPreferencePartColorChange); connect(&Preferences::instance(), &Preferences::flatShadingChanged, this, &Document::applyPreferenceFlatShadingChange); + connect(&Preferences::instance(), &Preferences::threeNodesBranchEnableStateChanged, this, [&]() { + threeNodesBranchEnabled = Preferences::instance().threeNodesBranchEnabled(); + }); } void Document::applyPreferencePartColorChange() diff --git a/src/preferences.cpp b/src/preferences.cpp index a7b7962f..6653580c 100644 --- a/src/preferences.cpp +++ b/src/preferences.cpp @@ -15,6 +15,7 @@ void Preferences::loadDefault() m_componentCombineMode = CombineMode::Normal; m_partColor = Qt::white; m_flatShading = false; + m_threeNodesBranchEnabled = false; } Preferences::Preferences() @@ -32,9 +33,16 @@ Preferences::Preferences() } { QString value = m_settings.value("flatShading").toString(); - if (!value.isEmpty()) + if (value.isEmpty()) + m_flatShading = true; + else m_flatShading = isTrueValueString(value); } + { + QString value = m_settings.value("threeNodesBranchEnabled").toString(); + if (!value.isEmpty()) + m_threeNodesBranchEnabled = isTrueValueString(value); + } } CombineMode Preferences::componentCombineMode() const @@ -52,6 +60,11 @@ bool Preferences::flatShading() const return m_flatShading; } +bool Preferences::threeNodesBranchEnabled() const +{ + return m_threeNodesBranchEnabled; +} + void Preferences::setComponentCombineMode(CombineMode mode) { if (m_componentCombineMode == mode) @@ -79,6 +92,15 @@ void Preferences::setFlatShading(bool flatShading) emit flatShadingChanged(); } +void Preferences::setThreeNodesBranchEnableState(bool enabled) +{ + if (m_threeNodesBranchEnabled == enabled) + return; + m_threeNodesBranchEnabled = enabled; + m_settings.setValue("threeNodesBranchEnabled", enabled ? "true" : "false"); + emit threeNodesBranchEnableStateChanged(); +} + void Preferences::reset() { m_settings.clear(); @@ -86,4 +108,5 @@ void Preferences::reset() emit componentCombineModeChanged(); emit partColorChanged(); emit flatShadingChanged(); + emit threeNodesBranchEnableStateChanged(); } diff --git a/src/preferences.h b/src/preferences.h index 697c6226..8d48d088 100644 --- a/src/preferences.h +++ b/src/preferences.h @@ -13,20 +13,24 @@ public: CombineMode componentCombineMode() const; const QColor &partColor() const; bool flatShading() const; + bool threeNodesBranchEnabled() const; signals: void componentCombineModeChanged(); void partColorChanged(); void flatShadingChanged(); + void threeNodesBranchEnableStateChanged(); public slots: void setComponentCombineMode(CombineMode mode); void setPartColor(const QColor &color); void setFlatShading(bool flatShading); + void setThreeNodesBranchEnableState(bool enabled); void reset(); private: CombineMode m_componentCombineMode = CombineMode::Normal; QColor m_partColor; bool m_flatShading; QSettings m_settings; + bool m_threeNodesBranchEnabled; private: void loadDefault(); }; diff --git a/src/preferenceswidget.cpp b/src/preferenceswidget.cpp index 209d4665..04ffb273 100644 --- a/src/preferenceswidget.cpp +++ b/src/preferenceswidget.cpp @@ -60,15 +60,22 @@ PreferencesWidget::PreferencesWidget(const Document *document, QWidget *parent) Preferences::instance().setFlatShading(flatShadingBox->isChecked()); }); + QCheckBox *threeNodesBranchEnabledBox = new QCheckBox(); + connect(threeNodesBranchEnabledBox, &QCheckBox::stateChanged, this, [=]() { + Preferences::instance().setThreeNodesBranchEnableState(threeNodesBranchEnabledBox->isChecked()); + }); + QFormLayout *formLayout = new QFormLayout; formLayout->addRow(tr("Part color:"), colorLayout); formLayout->addRow(tr("Combine mode:"), combineModeSelectBox); formLayout->addRow(tr("Flat shading:"), flatShadingBox); + formLayout->addRow(tr("Three nodes branch:"), threeNodesBranchEnabledBox); auto loadFromPreferences = [=]() { updatePickButtonColor(); combineModeSelectBox->setCurrentIndex((int)Preferences::instance().componentCombineMode()); flatShadingBox->setChecked(Preferences::instance().flatShading()); + threeNodesBranchEnabledBox->setChecked(Preferences::instance().threeNodesBranchEnabled()); }; loadFromPreferences(); diff --git a/src/skeletondocument.cpp b/src/skeletondocument.cpp index e806aaf1..6b3931ac 100644 --- a/src/skeletondocument.cpp +++ b/src/skeletondocument.cpp @@ -71,3 +71,12 @@ void SkeletonDocument::findAllNeighbors(QUuid nodeId, std::set &neighbors } } +bool SkeletonDocument::isNodeConnectable(QUuid nodeId) const +{ + if (threeNodesBranchEnabled) + return true; + const SkeletonNode *node = findNode(nodeId); + if (nullptr == node) + return false; + return node->edgeIds.size() < 2; +} diff --git a/src/skeletondocument.h b/src/skeletondocument.h index e69d1c18..4d9dd56b 100644 --- a/src/skeletondocument.h +++ b/src/skeletondocument.h @@ -259,6 +259,7 @@ public: bool ylocked = false; bool zlocked = false; bool radiusLocked = false; + bool threeNodesBranchEnabled = Preferences::instance().threeNodesBranchEnabled(); QImage turnaround; QByteArray turnaroundPngByteArray; std::map partMap; @@ -270,6 +271,7 @@ public: const SkeletonPart *findPart(QUuid partId) const; const SkeletonEdge *findEdgeByNodes(QUuid firstNodeId, QUuid secondNodeId) const; void findAllNeighbors(QUuid nodeId, std::set &neighbors) const; + bool isNodeConnectable(QUuid nodeId) const; virtual bool undoable() const = 0; virtual bool redoable() const = 0; diff --git a/src/skeletongraphicswidget.cpp b/src/skeletongraphicswidget.cpp index 033bbf55..644ec4af 100644 --- a/src/skeletongraphicswidget.cpp +++ b/src/skeletongraphicswidget.cpp @@ -346,6 +346,10 @@ bool SkeletonGraphicsWidget::hasTwoDisconnectedNodesSelection() return false; if (m_document->findEdgeByNodes(nodeIds[0], nodeIds[1])) return false; + if (!m_document->isNodeConnectable(nodeIds[0])) + return false; + if (!m_document->isNodeConnectable(nodeIds[1])) + return false; return true; } @@ -378,6 +382,10 @@ void SkeletonGraphicsWidget::connectSelected() return; if (m_document->findEdgeByNodes(nodeIds[0], nodeIds[1])) return; + if (!m_document->isNodeConnectable(nodeIds[0])) + return; + if (!m_document->isNodeConnectable(nodeIds[1])) + return; emit addEdge(nodeIds[0], nodeIds[1]); emit groupOperationAdded(); } @@ -581,8 +589,11 @@ void SkeletonGraphicsWidget::editModeChanged() if (!m_rangeSelectionSet.empty()) { std::set nodeItems; readMergedSkeletonNodeSetFromRangeSelection(&nodeItems); - if (nodeItems.size() == 1) + if (nodeItems.size() == 1) { choosenNodeItem = *nodeItems.begin(); + if (!m_document->isNodeConnectable(choosenNodeItem->id())) + choosenNodeItem = nullptr; + } } m_addFromNodeItem = choosenNodeItem; } @@ -1267,9 +1278,11 @@ bool SkeletonGraphicsWidget::mousePress(QMouseEvent *event) m_hoveredNodeItem->profile() == m_addFromNodeItem->profile() && !m_document->findEdgeByNodes(m_addFromNodeItem->id(), m_hoveredNodeItem->id()) && m_document->isNodeEditable(m_hoveredNodeItem->id())) { - emit addEdge(m_addFromNodeItem->id(), m_hoveredNodeItem->id()); - emit groupOperationAdded(); - return true; + if (m_document->isNodeConnectable(m_hoveredNodeItem->id())) { + emit addEdge(m_addFromNodeItem->id(), m_hoveredNodeItem->id()); + emit groupOperationAdded(); + return true; + } } } QPointF mainProfile = m_cursorNodeItem->origin();