diff --git a/languages/dust3d_zh_CN.ts b/languages/dust3d_zh_CN.ts index 170d0140..ffc1910d 100644 --- a/languages/dust3d_zh_CN.ts +++ b/languages/dust3d_zh_CN.ts @@ -1147,6 +1147,18 @@ Tips: Clear Cut Face 清除切面 + + Blank + 空白 + + + Auto Color + 自动着色 + + + Colorize + 着色 + UpdatesCheckWidget diff --git a/src/documentwindow.cpp b/src/documentwindow.cpp index 46c73851..719f3992 100644 --- a/src/documentwindow.cpp +++ b/src/documentwindow.cpp @@ -900,6 +900,7 @@ DocumentWindow::DocumentWindow() : connect(graphicsWidget, &SkeletonGraphicsWidget::setPartVisibleState, m_document, &Document::setPartVisibleState); connect(graphicsWidget, &SkeletonGraphicsWidget::setPartSubdivState, m_document, &Document::setPartSubdivState); connect(graphicsWidget, &SkeletonGraphicsWidget::setPartChamferState, m_document, &Document::setPartChamferState); + connect(graphicsWidget, &SkeletonGraphicsWidget::setPartColorState, m_document, &Document::setPartColorState); connect(graphicsWidget, &SkeletonGraphicsWidget::setPartDisableState, m_document, &Document::setPartDisableState); connect(graphicsWidget, &SkeletonGraphicsWidget::setPartXmirrorState, m_document, &Document::setPartXmirrorState); connect(graphicsWidget, &SkeletonGraphicsWidget::setPartRoundState, m_document, &Document::setPartRoundState); diff --git a/src/shortcuts.cpp b/src/shortcuts.cpp index a53cfa93..1f1111eb 100644 --- a/src/shortcuts.cpp +++ b/src/shortcuts.cpp @@ -11,9 +11,11 @@ void initShortCuts(QWidget *widget, SkeletonGraphicsWidget *graphicsWidget) { + defineKey(Qt::Key_Escape, &SkeletonGraphicsWidget::shortcutEscape); defineKey(Qt::Key_Delete, &SkeletonGraphicsWidget::shortcutDelete); defineKey(Qt::Key_Backspace, &SkeletonGraphicsWidget::shortcutDelete); defineKey(Qt::Key_A, &SkeletonGraphicsWidget::shortcutAddMode); + defineKey(Qt::CTRL + Qt::Key_A, &SkeletonGraphicsWidget::shortcutSelectAll); defineKey(Qt::CTRL + Qt::Key_Z, &SkeletonGraphicsWidget::shortcutUndo); defineKey(Qt::CTRL + Qt::SHIFT + Qt::Key_Z, &SkeletonGraphicsWidget::shortcutRedo); defineKey(Qt::CTRL + Qt::Key_Y, &SkeletonGraphicsWidget::shortcutRedo); diff --git a/src/skeletongraphicswidget.cpp b/src/skeletongraphicswidget.cpp index c92516b1..62b11863 100644 --- a/src/skeletongraphicswidget.cpp +++ b/src/skeletongraphicswidget.cpp @@ -49,7 +49,8 @@ SkeletonGraphicsWidget::SkeletonGraphicsWidget(const SkeletonDocument *document) m_nodePositionModifyOnly(false), m_mainProfileOnly(false), m_turnaroundOpacity(0.25), - m_rotated(false) + m_rotated(false), + m_backgroundImage(nullptr) { setRenderHint(QPainter::Antialiasing, false); setBackgroundBrush(QBrush(QWidget::palette().color(QWidget::backgroundRole()), Qt::SolidPattern)); @@ -95,6 +96,11 @@ SkeletonGraphicsWidget::SkeletonGraphicsWidget(const SkeletonDocument *document) connect(this, &SkeletonGraphicsWidget::customContextMenuRequested, this, &SkeletonGraphicsWidget::showContextMenu); } +SkeletonGraphicsWidget::~SkeletonGraphicsWidget() +{ + delete m_backgroundImage; +} + void SkeletonGraphicsWidget::setRotated(bool rotated) { if (m_rotated == rotated) @@ -126,6 +132,14 @@ void SkeletonGraphicsWidget::setBackgroundBlur(float turnaroundOpacity) m_backgroundItem->setOpacity(m_turnaroundOpacity); } +void SkeletonGraphicsWidget::shortcutEscape() +{ + if (SkeletonDocumentEditMode::Add == m_document->editMode) { + emit setEditMode(SkeletonDocumentEditMode::Select); + return; + } +} + void SkeletonGraphicsWidget::showContextMenu(const QPoint &pos) { if (SkeletonDocumentEditMode::Add == m_document->editMode) { @@ -302,6 +316,18 @@ void SkeletonGraphicsWidget::showContextMenu(const QPoint &pos) } } + QAction colorizeAsBlankAction(tr("Blank"), this); + QAction colorizeAsAutoColorAction(tr("Auto Color"), this); + if (!m_nodePositionModifyOnly && hasNodeSelection()) { + QMenu *subMenu = contextMenu.addMenu(tr("Colorize")); + + connect(&colorizeAsBlankAction, &QAction::triggered, this, &SkeletonGraphicsWidget::fadeSelected); + subMenu->addAction(&colorizeAsBlankAction); + + connect(&colorizeAsAutoColorAction, &QAction::triggered, this, &SkeletonGraphicsWidget::colorizeSelected); + subMenu->addAction(&colorizeAsAutoColorAction); + } + QAction selectAllAction(tr("Select All"), this); if (hasItems()) { connect(&selectAllAction, &QAction::triggered, this, &SkeletonGraphicsWidget::selectAll); @@ -396,6 +422,72 @@ bool SkeletonGraphicsWidget::hasCutFaceAdjustedNodesSelection() return false; } +void SkeletonGraphicsWidget::fadeSelected() +{ + std::set partIds; + for (const auto &it: m_rangeSelectionSet) { + if (it->data(0) == "node") { + SkeletonGraphicsNodeItem *nodeItem = (SkeletonGraphicsNodeItem *)it; + const SkeletonNode *node = m_document->findNode(nodeItem->id()); + if (nullptr == node) + continue; + if (partIds.find(node->partId) != partIds.end()) + continue; + partIds.insert(node->partId); + } + } + if (partIds.empty()) + return; + emit batchChangeBegin(); + for (const auto &it: partIds) { + emit setPartColorState(it, false, Qt::white); + } + emit batchChangeEnd(); + emit groupOperationAdded(); +} + +void SkeletonGraphicsWidget::colorizeSelected() +{ + if (nullptr == m_backgroundImage) + return; + std::map> sumOfColor; + for (const auto &it: m_rangeSelectionSet) { + if (it->data(0) == "node") { + SkeletonGraphicsNodeItem *nodeItem = (SkeletonGraphicsNodeItem *)it; + const SkeletonNode *node = m_document->findNode(nodeItem->id()); + if (nullptr == node) + continue; + const auto &position = nodeItem->origin(); + sumOfColor[node->partId][m_backgroundImage->pixelColor(position.x(), position.y()).name()]++; + } else if (it->data(0) == "edge") { + SkeletonGraphicsEdgeItem *edgeItem = (SkeletonGraphicsEdgeItem *)it; + const SkeletonEdge *edge = m_document->findEdge(edgeItem->id()); + if (nullptr == edge) + continue; + const auto position = (edgeItem->firstItem()->origin() + edgeItem->secondItem()->origin()) / 2; + sumOfColor[edge->partId][m_backgroundImage->pixelColor(position.x(), position.y()).name()]++; + } + } + if (sumOfColor.empty()) + return; + emit batchChangeBegin(); + for (const auto &it: sumOfColor) { + int r = 0; + int g = 0; + int b = 0; + for (const auto &freq: it.second) { + QColor color(freq.first); + r += color.red(); + g += color.green(); + b += color.blue(); + } + QColor color(r / it.second.size(), g / it.second.size(), b / it.second.size()); + emit setPartColorState(it.first, true, color); + } + emit batchChangeEnd(); + emit groupOperationAdded(); +} + void SkeletonGraphicsWidget::breakSelected() { std::set edgeIds; @@ -592,17 +684,17 @@ void SkeletonGraphicsWidget::updateTurnaround() void SkeletonGraphicsWidget::turnaroundImageReady() { - QImage *backgroundImage = m_turnaroundLoader->takeResultImage(); - if (backgroundImage && backgroundImage->width() > 0 && backgroundImage->height() > 0) { + delete m_backgroundImage; + m_backgroundImage = m_turnaroundLoader->takeResultImage(); + if (m_backgroundImage && m_backgroundImage->width() > 0 && m_backgroundImage->height() > 0) { //qDebug() << "Fit turnaround finished with image size:" << backgroundImage->size(); - setFixedSize(backgroundImage->size()); + setFixedSize(m_backgroundImage->size()); scene()->setSceneRect(rect()); - m_backgroundItem->setPixmap(QPixmap::fromImage(*backgroundImage)); + m_backgroundItem->setPixmap(QPixmap::fromImage(*m_backgroundImage)); updateItems(); } else { qDebug() << "Fit turnaround failed"; } - delete backgroundImage; delete m_turnaroundLoader; m_turnaroundLoader = nullptr; @@ -1830,6 +1922,11 @@ void SkeletonGraphicsWidget::shortcutChamferedOrNotSelectedPart() } } +void SkeletonGraphicsWidget::shortcutSelectAll() +{ + selectAll(); +} + void SkeletonGraphicsWidget::shortcutRoundEndOrNotSelectedPart() { if (SkeletonDocumentEditMode::Select == m_document->editMode && !m_lastCheckedPart.isNull()) { diff --git a/src/skeletongraphicswidget.h b/src/skeletongraphicswidget.h index 6ffb70cd..7d03f5fc 100644 --- a/src/skeletongraphicswidget.h +++ b/src/skeletongraphicswidget.h @@ -389,6 +389,8 @@ private: class SkeletonGraphicsWidget : public QGraphicsView { Q_OBJECT +public: + ~SkeletonGraphicsWidget(); signals: void addNode(float x, float y, float z, float radius, QUuid fromNodeId); void scaleNodeByAddRadius(QUuid nodeId, float amount); @@ -420,6 +422,7 @@ signals: void setPartRoundState(QUuid partId, bool rounded); void setPartWrapState(QUuid partId, bool wrapped); void setPartChamferState(QUuid partId, bool chamfered); + void setPartColorState(QUuid partId, bool hasColor, QColor color); void setXlockState(bool locked); void setYlockState(bool locked); void setZlockState(bool locked); @@ -506,6 +509,8 @@ public slots: void rotateAllMainProfileClockwise90DegreeAlongOrigin(); void rotateAllMainProfileCounterclockwise90DegreeAlongOrigin(); void removeAllContent(); + void fadeSelected(); + void colorizeSelected(); void breakSelected(); void connectSelected(); void rotateSelected(int degree); @@ -569,6 +574,8 @@ public slots: void shortcutRoundEndOrNotSelectedPart(); void shortcutCheckPartComponent(); void shortcutChamferedOrNotSelectedPart(); + void shortcutSelectAll(); + void shortcutEscape(); private slots: void turnaroundImageReady(); private: @@ -628,6 +635,7 @@ private: //need initalize bool m_mainProfileOnly; float m_turnaroundOpacity; bool m_rotated; + QImage *m_backgroundImage; private: QVector3D m_ikMoveTarget; QUuid m_ikMoveEndEffectorId;