diff --git a/dust3d.pro b/dust3d.pro index 9d82921f..1a2cf6cc 100644 --- a/dust3d.pro +++ b/dust3d.pro @@ -291,6 +291,9 @@ HEADERS += src/skeletondocument.h SOURCES += src/posedocument.cpp HEADERS += src/posedocument.h +SOURCES += src/combinemode.cpp +HEADERS += src/combinemode.h + SOURCES += src/main.cpp HEADERS += src/version.h diff --git a/src/combinemode.cpp b/src/combinemode.cpp new file mode 100644 index 00000000..4087cdd5 --- /dev/null +++ b/src/combinemode.cpp @@ -0,0 +1,6 @@ +#include +#include "combinemode.h" + +IMPL_CombineModeToString +IMPL_CombineModeFromString +IMPL_CombineModeToDispName diff --git a/src/combinemode.h b/src/combinemode.h new file mode 100644 index 00000000..95ff2a52 --- /dev/null +++ b/src/combinemode.h @@ -0,0 +1,49 @@ +#ifndef DUST3D_COMBINE_MODE_H +#define DUST3D_COMBINE_MODE_H +#include + +enum class CombineMode +{ + Normal = 0, + Inversion, + Count +}; +CombineMode CombineModeFromString(const char *modeString); +#define IMPL_CombineModeFromString \ +CombineMode CombineModeFromString(const char *modeString) \ +{ \ + QString mode = modeString; \ + if (mode == "Normal") \ + return CombineMode::Normal; \ + if (mode == "Inversion") \ + return CombineMode::Inversion; \ + return CombineMode::Normal; \ +} +const char *CombineModeToString(CombineMode mode); +#define IMPL_CombineModeToString \ +const char *CombineModeToString(CombineMode mode) \ +{ \ + switch (mode) { \ + case CombineMode::Normal: \ + return "Normal"; \ + case CombineMode::Inversion: \ + return "Inversion"; \ + default: \ + return "Normal"; \ + } \ +} +QString CombineModeToDispName(CombineMode mode); +#define IMPL_CombineModeToDispName \ +QString CombineModeToDispName(CombineMode mode) \ +{ \ + switch (mode) { \ + case CombineMode::Normal: \ + return QObject::tr("Normal"); \ + case CombineMode::Inversion: \ + return QObject::tr("Inversion"); \ + default: \ + return QObject::tr("Normal"); \ + } \ +} + +#endif diff --git a/src/document.cpp b/src/document.cpp index e1175b4c..dd6402f8 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -903,7 +903,7 @@ void Document::toSnapshot(Snapshot *snapshot, const std::set &limitNodeId if (!componentIt.second.name.isEmpty()) component["name"] = componentIt.second.name; component["expanded"] = componentIt.second.expanded ? "true" : "false"; - component["inverse"] = componentIt.second.inverse ? "true" : "false"; + component["combineMode"] = CombineModeToString(componentIt.second.combineMode); component["dirty"] = componentIt.second.dirty ? "true" : "false"; if (componentIt.second.smoothAllAdjusted()) component["smoothAll"] = QString::number(componentIt.second.smoothAll); @@ -1178,7 +1178,11 @@ void Document::addFromSnapshot(const Snapshot &snapshot, bool fromPaste) oldNewIdMap[QUuid(componentKv.first)] = component.id; component.name = valueOfKeyInMapOrEmpty(componentKv.second, "name"); component.expanded = isTrueValueString(valueOfKeyInMapOrEmpty(componentKv.second, "expanded")); - component.inverse = isTrueValueString(valueOfKeyInMapOrEmpty(componentKv.second, "inverse")); + component.combineMode = CombineModeFromString(valueOfKeyInMapOrEmpty(componentKv.second, "combineMode").toUtf8().constData()); + if (component.combineMode == CombineMode::Normal) { + if (isTrueValueString(valueOfKeyInMapOrEmpty(componentKv.second, "inverse"))) + component.combineMode = CombineMode::Inversion; + } const auto &smoothAllIt = componentKv.second.find("smoothAll"); if (smoothAllIt != componentKv.second.end()) component.setSmoothAll(smoothAllIt->second.toFloat()); @@ -1192,7 +1196,7 @@ void Document::addFromSnapshot(const Snapshot &snapshot, bool fromPaste) //qDebug() << "Add part:" << partId << " from component:" << component.id; partMap[partId].componentId = component.id; if (inversePartIds.find(partId) != inversePartIds.end()) - component.inverse = true; + component.combineMode = CombineMode::Inversion; } componentMap[component.id] = component; newAddedComponentIds.insert(component.id); @@ -1609,18 +1613,18 @@ void Document::setPartVisibleState(QUuid partId, bool visible) emit optionsChanged(); } -void Document::setComponentInverseState(QUuid componentId, bool inverse) +void Document::setComponentCombineMode(QUuid componentId, CombineMode combineMode) { auto component = componentMap.find(componentId); if (component == componentMap.end()) { qDebug() << "Component not found:" << componentId; return; } - if (component->second.inverse == inverse) + if (component->second.combineMode == combineMode) return; - component->second.inverse = inverse; + component->second.combineMode = combineMode; component->second.dirty = true; - emit componentInverseStateChanged(componentId); + emit componentCombineModeChanged(componentId); emit skeletonChanged(); } diff --git a/src/document.h b/src/document.h index 18bebe03..85611898 100644 --- a/src/document.h +++ b/src/document.h @@ -24,6 +24,7 @@ #include "interpolationtype.h" #include "jointnodetree.h" #include "skeletondocument.h" +#include "combinemode.h" class MaterialPreviewsGenerator; class MotionsGenerator; @@ -55,7 +56,7 @@ public: QUuid linkToPartId; QUuid parentId; bool expanded = true; - bool inverse = false; + CombineMode combineMode = CombineMode::Normal; bool dirty = true; float smoothAll = 0.0; float smoothSeam = 0.0; @@ -401,7 +402,7 @@ signals: void partColorStateChanged(QUuid partId); void partWrapStateChanged(QUuid partId); void partMaterialIdChanged(QUuid partId); - void componentInverseStateChanged(QUuid partId); + void componentCombineModeChanged(QUuid componentId); void cleanup(); void originChanged(); void xlockStateChanged(); @@ -549,7 +550,7 @@ public slots: void setPartColorState(QUuid partId, bool hasColor, QColor color); void setPartWrapState(QUuid partId, bool wrapped); void setPartMaterialId(QUuid partId, QUuid materialId); - void setComponentInverseState(QUuid componentId, bool inverse); + void setComponentCombineMode(QUuid componentId, CombineMode combineMode); void moveComponentUp(QUuid componentId); void moveComponentDown(QUuid componentId); void moveComponentToTop(QUuid componentId); diff --git a/src/documentwindow.cpp b/src/documentwindow.cpp index 934dfb94..21074683 100644 --- a/src/documentwindow.cpp +++ b/src/documentwindow.cpp @@ -783,7 +783,7 @@ DocumentWindow::DocumentWindow() : connect(partTreeWidget, &PartTreeWidget::unlockAllComponents, m_document, &Document::unlockAllComponents); connect(partTreeWidget, &PartTreeWidget::setPartLockState, m_document, &Document::setPartLockState); connect(partTreeWidget, &PartTreeWidget::setPartVisibleState, m_document, &Document::setPartVisibleState); - connect(partTreeWidget, &PartTreeWidget::setComponentInverseState, m_document, &Document::setComponentInverseState); + connect(partTreeWidget, &PartTreeWidget::setComponentCombineMode, m_document, &Document::setComponentCombineMode); connect(partTreeWidget, &PartTreeWidget::hideDescendantComponents, m_document, &Document::hideDescendantComponents); connect(partTreeWidget, &PartTreeWidget::showDescendantComponents, m_document, &Document::showDescendantComponents); connect(partTreeWidget, &PartTreeWidget::lockDescendantComponents, m_document, &Document::lockDescendantComponents); @@ -796,7 +796,7 @@ DocumentWindow::DocumentWindow() : connect(m_document, &Document::componentRemoved, partTreeWidget, &PartTreeWidget::componentRemoved); connect(m_document, &Document::componentAdded, partTreeWidget, &PartTreeWidget::componentAdded); connect(m_document, &Document::componentExpandStateChanged, partTreeWidget, &PartTreeWidget::componentExpandStateChanged); - connect(m_document, &Document::componentInverseStateChanged, partTreeWidget, &PartTreeWidget::componentInverseStateChanged); + connect(m_document, &Document::componentCombineModeChanged, partTreeWidget, &PartTreeWidget::componentCombineModeChanged); connect(m_document, &Document::partPreviewChanged, partTreeWidget, &PartTreeWidget::partPreviewChanged); connect(m_document, &Document::partLockStateChanged, partTreeWidget, &PartTreeWidget::partLockStateChanged); connect(m_document, &Document::partVisibleStateChanged, partTreeWidget, &PartTreeWidget::partVisibleStateChanged); diff --git a/src/meshgenerator.cpp b/src/meshgenerator.cpp index f7824b4d..d7727e65 100644 --- a/src/meshgenerator.cpp +++ b/src/meshgenerator.cpp @@ -516,7 +516,8 @@ void *MeshGenerator::combineComponentMesh(QString componentId, bool *inverse) component = &findComponent->second; } - if (isTrueValueString(valueOfKeyInMapOrEmpty(*component, "inverse"))) + CombineMode combineMode = CombineModeFromString(valueOfKeyInMapOrEmpty(*component, "combineMode").toUtf8().constData()); + if (combineMode == CombineMode::Inversion) *inverse = true; if (m_dirtyComponentIds.find(componentId) == m_dirtyComponentIds.end()) { diff --git a/src/parttreewidget.cpp b/src/parttreewidget.cpp index 0d450e3f..daa1afc9 100644 --- a/src/parttreewidget.cpp +++ b/src/parttreewidget.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include "parttreewidget.h" #include "partwidget.h" #include "skeletongraphicswidget.h" @@ -119,8 +120,8 @@ void PartTreeWidget::updateComponentSelectState(QUuid componentId, bool selected auto item = m_partItemMap.find(component->linkToPartId); if (item != m_componentItemMap.end()) { PartWidget *widget = (PartWidget *)itemWidget(item->second, 0); - // Inverse state updating call should be called before check state updating call - widget->updateInverseState(component->inverse); + // Unnormal state updating call should be called before check state updating call + widget->updateUnnormalState(component->combineMode != CombineMode::Normal); widget->updateCheckedState(selected); } return; @@ -128,7 +129,7 @@ void PartTreeWidget::updateComponentSelectState(QUuid componentId, bool selected auto item = m_componentItemMap.find(componentId); if (item != m_componentItemMap.end()) { item->second->setFont(0, selected ? m_selectedFont : m_normalFont); - if (component->inverse) + if (component->combineMode != CombineMode::Normal) item->second->setForeground(0, selected ? QBrush(Theme::blue) : QBrush(Theme::blue)); else item->second->setForeground(0, selected ? QBrush(Theme::red) : QBrush(Theme::white)); @@ -259,7 +260,7 @@ void PartTreeWidget::showContextMenu(const QPoint &pos) } else { QLabel *previewLabel = new QLabel; previewLabel->setFixedHeight(Theme::partPreviewImageSize); - previewLabel->setStyleSheet("QLabel {color: " + (component && component->inverse ? Theme::blue.name() : Theme::red.name()) + "}"); + previewLabel->setStyleSheet("QLabel {color: " + (component && (component->combineMode != CombineMode::Normal) ? Theme::blue.name() : Theme::red.name()) + "}"); if (nullptr != component) { previewLabel->setText(component->name); } else if (!componentIds.empty()) { @@ -268,7 +269,31 @@ void PartTreeWidget::showContextMenu(const QPoint &pos) layout->addWidget(previewLabel); } QWidget *widget = new QWidget; - widget->setLayout(layout); + if (nullptr != component) { + QComboBox *combineModeSelectBox = new QComboBox; + for (size_t i = 0; i < (size_t)CombineMode::Count; ++i) { + CombineMode mode = (CombineMode)i; + combineModeSelectBox->addItem(CombineModeToDispName(mode)); + } + combineModeSelectBox->setCurrentIndex((int)component->combineMode); + + connect(combineModeSelectBox, static_cast(&QComboBox::currentIndexChanged), this, [=](int index) { + emit setComponentCombineMode(component->id, (CombineMode)index); + }); + + QHBoxLayout *combineModeLayout = new QHBoxLayout; + combineModeLayout->setAlignment(Qt::AlignCenter); + combineModeLayout->setContentsMargins(0, 0, 0, 0); + combineModeLayout->setSpacing(0); + combineModeLayout->addWidget(combineModeSelectBox); + + QVBoxLayout *newLayout = new QVBoxLayout; + newLayout->addLayout(layout); + newLayout->addLayout(combineModeLayout); + widget->setLayout(newLayout); + } else { + widget->setLayout(layout); + } forDisplayPartImage.setDefaultWidget(widget); if (!componentIds.empty()) { contextMenu.addAction(&forDisplayPartImage); @@ -283,8 +308,6 @@ void PartTreeWidget::showContextMenu(const QPoint &pos) lockAction.setIcon(Theme::awesome()->icon(fa::lock)); QAction unlockAction(tr("Unlock"), this); unlockAction.setIcon(Theme::awesome()->icon(fa::unlock)); - QAction invertAction(tr("Invert"), this); - QAction cancelInverseAction(tr("Cancel Inverse"), this); QAction selectAction(tr("Select"), this); if (nullptr != component && nullptr != part) { @@ -353,6 +376,7 @@ void PartTreeWidget::showContextMenu(const QPoint &pos) contextMenu.addAction(&unlockAction); } + /* if (component && !component->inverse) { connect(&invertAction, &QAction::triggered, [=]() { emit setComponentInverseState(component->id, true); @@ -366,6 +390,7 @@ void PartTreeWidget::showContextMenu(const QPoint &pos) }); contextMenu.addAction(&cancelInverseAction); } + */ contextMenu.addSeparator(); @@ -655,7 +680,7 @@ void PartTreeWidget::componentExpandStateChanged(QUuid componentId) componentItem->second->setExpanded(component->expanded); } -void PartTreeWidget::componentInverseStateChanged(QUuid componentId) +void PartTreeWidget::componentCombineModeChanged(QUuid componentId) { updateComponentAppearance(componentId); } diff --git a/src/parttreewidget.h b/src/parttreewidget.h index a03486a3..7471b97a 100644 --- a/src/parttreewidget.h +++ b/src/parttreewidget.h @@ -33,7 +33,7 @@ signals: void unlockAllComponents(); void setPartLockState(QUuid partId, bool locked); void setPartVisibleState(QUuid partId, bool visible); - void setComponentInverseState(QUuid componentId, bool inverse); + void setComponentCombineMode(QUuid componentId, CombineMode combineMode); void hideDescendantComponents(QUuid componentId); void showDescendantComponents(QUuid componentId); void lockDescendantComponents(QUuid componentId); @@ -49,7 +49,7 @@ public slots: void componentRemoved(QUuid componentId); void componentAdded(QUuid componentId); void componentExpandStateChanged(QUuid componentId); - void componentInverseStateChanged(QUuid componentId); + void componentCombineModeChanged(QUuid componentId); void partRemoved(QUuid partId); void partPreviewChanged(QUuid partid); void partLockStateChanged(QUuid partId); diff --git a/src/partwidget.cpp b/src/partwidget.cpp index 85bf5ce3..b6a3e9f7 100644 --- a/src/partwidget.cpp +++ b/src/partwidget.cpp @@ -15,7 +15,7 @@ PartWidget::PartWidget(const Document *document, QUuid partId) : m_document(document), m_partId(partId), - m_inverted(false) + m_unnormal(false) { QSizePolicy retainSizePolicy = sizePolicy(); retainSizePolicy.setRetainSizeWhenHidden(true); @@ -263,17 +263,17 @@ void PartWidget::updateAllButtons() void PartWidget::updateCheckedState(bool checked) { if (checked) - m_backgroundWidget->setStyleSheet("QWidget#background {border: 1px solid " + (m_inverted ? Theme::blue.name() : Theme::red.name()) + ";}"); + m_backgroundWidget->setStyleSheet("QWidget#background {border: 1px solid " + (m_unnormal ? Theme::blue.name() : Theme::red.name()) + ";}"); else m_backgroundWidget->setStyleSheet("QWidget#background {border: 1px solid transparent;}"); } -void PartWidget::updateInverseState(bool inverse) +void PartWidget::updateUnnormalState(bool unnormal) { - if (m_inverted == inverse) + if (m_unnormal == unnormal) return; - m_inverted = inverse; + m_unnormal = unnormal; updateAllButtons(); } @@ -439,7 +439,7 @@ void PartWidget::initButton(QPushButton *button) void PartWidget::updateButton(QPushButton *button, QChar icon, bool highlighted) { - Theme::updateAwesomeMiniButton(button, icon, highlighted, m_inverted); + Theme::updateAwesomeMiniButton(button, icon, highlighted, m_unnormal); } void PartWidget::updatePreview() diff --git a/src/partwidget.h b/src/partwidget.h index 15a4ef72..f6b63609 100644 --- a/src/partwidget.h +++ b/src/partwidget.h @@ -45,7 +45,7 @@ public: void updateColorButton(); void updateWrapButton(); void updateCheckedState(bool checked); - void updateInverseState(bool inverse); + void updateUnnormalState(bool unnormal); static QSize preferredSize(); ModelWidget *previewWidget(); protected: @@ -56,7 +56,7 @@ public slots: private: // need initialize const Document *m_document; QUuid m_partId; - bool m_inverted; + bool m_unnormal; private: ModelWidget *m_previewWidget; QPushButton *m_visibleButton; diff --git a/src/theme.cpp b/src/theme.cpp index 8742d9ec..9cd6d7b2 100644 --- a/src/theme.cpp +++ b/src/theme.cpp @@ -103,14 +103,14 @@ void Theme::initAwesomeMiniButton(QPushButton *button) button->setFocusPolicy(Qt::NoFocus); } -void Theme::updateAwesomeMiniButton(QPushButton *button, QChar icon, bool highlighted, bool inverted) +void Theme::updateAwesomeMiniButton(QPushButton *button, QChar icon, bool highlighted, bool unnormal) { button->setText(icon); QColor color; bool needDesaturation = true; if (highlighted) { - if (inverted) { + if (unnormal) { color = Theme::blue; needDesaturation = false; } else { diff --git a/src/theme.h b/src/theme.h index 4c68fe62..e0867f6c 100644 --- a/src/theme.h +++ b/src/theme.h @@ -47,7 +47,7 @@ public: static void initAwesomeLabel(QLabel *label); static void initAwesomeSmallButton(QPushButton *button); static void initAwesomeMiniButton(QPushButton *button); - static void updateAwesomeMiniButton(QPushButton *button, QChar icon, bool highlighted, bool inverted=false); + static void updateAwesomeMiniButton(QPushButton *button, QChar icon, bool highlighted, bool unnormal=false); static void initAwesomeToolButton(QPushButton *button); static void initAwesomeToolButtonWithoutFont(QPushButton *button); };