2018-04-07 11:51:33 +00:00
|
|
|
#include <QVBoxLayout>
|
|
|
|
#include <QHBoxLayout>
|
2018-08-27 08:50:40 +00:00
|
|
|
#include <QAction>
|
2018-04-17 13:13:32 +00:00
|
|
|
#include <QMenu>
|
|
|
|
#include <QWidgetAction>
|
2018-04-26 02:23:22 +00:00
|
|
|
#include <QColorDialog>
|
2018-05-10 09:16:22 +00:00
|
|
|
#include <QSizePolicy>
|
2018-10-09 02:19:12 +00:00
|
|
|
#include <QFileDialog>
|
2019-02-24 13:42:23 +00:00
|
|
|
#include <QSizePolicy>
|
2019-11-07 12:08:47 +00:00
|
|
|
#include <QCheckBox>
|
2020-03-24 11:54:55 +00:00
|
|
|
#include <QLabel>
|
2020-03-25 11:40:44 +00:00
|
|
|
#include <QRadioButton>
|
2018-10-25 00:19:38 +00:00
|
|
|
#include "partwidget.h"
|
2018-04-07 08:44:39 +00:00
|
|
|
#include "theme.h"
|
2018-04-17 13:13:32 +00:00
|
|
|
#include "floatnumberwidget.h"
|
2018-10-09 02:19:12 +00:00
|
|
|
#include "materiallistwidget.h"
|
|
|
|
#include "infolabel.h"
|
2019-05-05 12:49:26 +00:00
|
|
|
#include "cutface.h"
|
2019-02-24 13:42:23 +00:00
|
|
|
#include "cutdocument.h"
|
|
|
|
#include "skeletongraphicswidget.h"
|
|
|
|
#include "shortcuts.h"
|
|
|
|
#include "graphicscontainerwidget.h"
|
2019-05-19 03:21:38 +00:00
|
|
|
#include "flowlayout.h"
|
|
|
|
#include "cutfacelistwidget.h"
|
2019-08-03 10:21:27 +00:00
|
|
|
#include "imageforever.h"
|
|
|
|
#include "imagepreviewwidget.h"
|
2018-04-07 08:44:39 +00:00
|
|
|
|
2018-10-25 00:19:38 +00:00
|
|
|
PartWidget::PartWidget(const Document *document, QUuid partId) :
|
2018-04-07 08:44:39 +00:00
|
|
|
m_document(document),
|
2018-11-14 03:11:31 +00:00
|
|
|
m_partId(partId),
|
2018-11-14 13:21:45 +00:00
|
|
|
m_unnormal(false)
|
2018-04-07 08:44:39 +00:00
|
|
|
{
|
2018-05-10 09:16:22 +00:00
|
|
|
QSizePolicy retainSizePolicy = sizePolicy();
|
|
|
|
retainSizePolicy.setRetainSizeWhenHidden(true);
|
|
|
|
|
2018-04-08 01:30:55 +00:00
|
|
|
m_visibleButton = new QPushButton();
|
2019-01-07 13:03:42 +00:00
|
|
|
m_visibleButton->setToolTip(tr("Show/hide nodes"));
|
2018-05-10 09:16:22 +00:00
|
|
|
m_visibleButton->setSizePolicy(retainSizePolicy);
|
2018-04-08 01:30:55 +00:00
|
|
|
initButton(m_visibleButton);
|
2018-04-07 08:44:39 +00:00
|
|
|
|
2018-04-08 01:30:55 +00:00
|
|
|
m_lockButton = new QPushButton();
|
2019-01-07 13:03:42 +00:00
|
|
|
m_lockButton->setToolTip(tr("Lock/unlock nodes"));
|
2018-05-10 09:16:22 +00:00
|
|
|
m_lockButton->setSizePolicy(retainSizePolicy);
|
2018-04-08 01:30:55 +00:00
|
|
|
initButton(m_lockButton);
|
2018-04-07 12:30:26 +00:00
|
|
|
|
2018-04-08 01:30:55 +00:00
|
|
|
m_subdivButton = new QPushButton();
|
2019-02-24 13:42:23 +00:00
|
|
|
m_subdivButton->setToolTip(tr("Subdivide"));
|
2018-05-10 09:16:22 +00:00
|
|
|
m_subdivButton->setSizePolicy(retainSizePolicy);
|
2018-04-08 01:30:55 +00:00
|
|
|
initButton(m_subdivButton);
|
2018-04-07 12:30:26 +00:00
|
|
|
|
2018-04-11 09:19:27 +00:00
|
|
|
m_disableButton = new QPushButton();
|
2019-01-07 13:03:42 +00:00
|
|
|
m_disableButton->setToolTip(tr("Join/Remove from final result"));
|
2018-05-10 09:16:22 +00:00
|
|
|
m_disableButton->setSizePolicy(retainSizePolicy);
|
2018-04-11 09:19:27 +00:00
|
|
|
initButton(m_disableButton);
|
|
|
|
|
2018-04-15 12:11:51 +00:00
|
|
|
m_xMirrorButton = new QPushButton();
|
2019-01-07 13:03:42 +00:00
|
|
|
m_xMirrorButton->setToolTip(tr("Toggle mirror"));
|
2018-05-10 09:16:22 +00:00
|
|
|
m_xMirrorButton->setSizePolicy(retainSizePolicy);
|
2018-04-15 12:11:51 +00:00
|
|
|
initButton(m_xMirrorButton);
|
|
|
|
|
2018-04-17 16:14:31 +00:00
|
|
|
m_deformButton = new QPushButton();
|
2019-01-07 13:03:42 +00:00
|
|
|
m_deformButton->setToolTip(tr("Deform"));
|
2018-05-10 09:16:22 +00:00
|
|
|
m_deformButton->setSizePolicy(retainSizePolicy);
|
2018-04-17 16:14:31 +00:00
|
|
|
initButton(m_deformButton);
|
2018-04-15 12:11:51 +00:00
|
|
|
|
2018-04-26 02:23:22 +00:00
|
|
|
m_roundButton = new QPushButton;
|
2019-01-07 13:03:42 +00:00
|
|
|
m_roundButton->setToolTip(tr("Toggle round end"));
|
2018-05-10 09:16:22 +00:00
|
|
|
m_roundButton->setSizePolicy(retainSizePolicy);
|
2018-04-26 02:23:22 +00:00
|
|
|
initButton(m_roundButton);
|
|
|
|
|
2019-03-09 22:10:39 +00:00
|
|
|
m_chamferButton = new QPushButton;
|
|
|
|
m_chamferButton->setToolTip(tr("Chamfer"));
|
|
|
|
m_chamferButton->setSizePolicy(retainSizePolicy);
|
|
|
|
initButton(m_chamferButton);
|
|
|
|
|
2018-04-26 02:23:22 +00:00
|
|
|
m_colorButton = new QPushButton;
|
2019-01-07 13:03:42 +00:00
|
|
|
m_colorButton->setToolTip(tr("Color and material picker"));
|
2018-05-10 09:16:22 +00:00
|
|
|
m_colorButton->setSizePolicy(retainSizePolicy);
|
2018-04-26 02:23:22 +00:00
|
|
|
initButton(m_colorButton);
|
|
|
|
|
2019-02-24 13:42:23 +00:00
|
|
|
m_cutRotationButton = new QPushButton;
|
2019-05-19 03:21:38 +00:00
|
|
|
m_cutRotationButton->setToolTip(tr("Cut face"));
|
2019-02-24 13:42:23 +00:00
|
|
|
m_cutRotationButton->setSizePolicy(retainSizePolicy);
|
|
|
|
initButton(m_cutRotationButton);
|
|
|
|
|
2018-09-18 06:22:29 +00:00
|
|
|
m_previewWidget = new ModelWidget;
|
2018-10-25 07:03:51 +00:00
|
|
|
m_previewWidget->setAttribute(Qt::WA_TransparentForMouseEvents);
|
2018-09-18 06:22:29 +00:00
|
|
|
m_previewWidget->enableMove(false);
|
|
|
|
m_previewWidget->enableZoom(false);
|
2018-09-21 07:10:18 +00:00
|
|
|
m_previewWidget->setFixedSize(Theme::partPreviewImageSize, Theme::partPreviewImageSize);
|
2018-04-07 08:44:39 +00:00
|
|
|
|
2018-04-23 00:10:01 +00:00
|
|
|
QWidget *hrLightWidget = new QWidget;
|
|
|
|
hrLightWidget->setFixedHeight(1);
|
|
|
|
hrLightWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
2018-05-10 09:16:22 +00:00
|
|
|
//hrLightWidget->setStyleSheet(QString("background-color: #565656;"));
|
2018-04-23 00:10:01 +00:00
|
|
|
hrLightWidget->setContentsMargins(0, 0, 0, 0);
|
|
|
|
|
2018-04-08 01:30:55 +00:00
|
|
|
QWidget *hrWidget = new QWidget;
|
|
|
|
hrWidget->setFixedHeight(1);
|
|
|
|
hrWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
2018-05-10 09:16:22 +00:00
|
|
|
//hrWidget->setStyleSheet(QString("background-color: #1a1a1a;"));
|
2018-04-08 01:30:55 +00:00
|
|
|
hrWidget->setContentsMargins(0, 0, 0, 0);
|
|
|
|
|
2018-08-27 08:50:40 +00:00
|
|
|
QGridLayout *toolsLayout = new QGridLayout;
|
2018-04-23 00:10:01 +00:00
|
|
|
toolsLayout->setSpacing(0);
|
2018-08-27 08:50:40 +00:00
|
|
|
toolsLayout->setContentsMargins(0, 0, 5, 0);
|
|
|
|
int row = 0;
|
|
|
|
int col = 0;
|
2019-02-24 13:42:23 +00:00
|
|
|
toolsLayout->addWidget(m_visibleButton, row, col++, Qt::AlignBottom);
|
2018-08-27 08:50:40 +00:00
|
|
|
toolsLayout->addWidget(m_lockButton, row, col++, Qt::AlignBottom);
|
|
|
|
toolsLayout->addWidget(m_disableButton, row, col++, Qt::AlignBottom);
|
2019-02-21 22:48:15 +00:00
|
|
|
toolsLayout->addWidget(m_xMirrorButton, row, col++, Qt::AlignBottom);
|
2018-08-27 08:50:40 +00:00
|
|
|
toolsLayout->addWidget(m_colorButton, row, col++, Qt::AlignBottom);
|
|
|
|
row++;
|
|
|
|
col = 0;
|
|
|
|
toolsLayout->addWidget(m_subdivButton, row, col++, Qt::AlignTop);
|
|
|
|
toolsLayout->addWidget(m_roundButton, row, col++, Qt::AlignTop);
|
2019-03-09 22:10:39 +00:00
|
|
|
//toolsLayout->addWidget(m_cutTemplateButton, row, col++, Qt::AlignTop);
|
|
|
|
toolsLayout->addWidget(m_chamferButton, row, col++, Qt::AlignTop);
|
2019-02-24 13:42:23 +00:00
|
|
|
toolsLayout->addWidget(m_cutRotationButton, row, col++, Qt::AlignTop);
|
2019-02-21 22:48:15 +00:00
|
|
|
toolsLayout->addWidget(m_deformButton, row, col++, Qt::AlignTop);
|
2018-08-27 08:50:40 +00:00
|
|
|
|
2019-02-24 13:42:23 +00:00
|
|
|
//m_visibleButton->setContentsMargins(0, 0, 0, 0);
|
2018-08-31 04:54:32 +00:00
|
|
|
|
2018-08-27 08:50:40 +00:00
|
|
|
QHBoxLayout *previewAndToolsLayout = new QHBoxLayout;
|
|
|
|
previewAndToolsLayout->setSpacing(0);
|
|
|
|
previewAndToolsLayout->setContentsMargins(0, 0, 0, 0);
|
2019-02-24 13:42:23 +00:00
|
|
|
//previewAndToolsLayout->addWidget(m_visibleButton);
|
2018-09-18 06:22:29 +00:00
|
|
|
previewAndToolsLayout->addWidget(m_previewWidget);
|
2018-08-27 08:50:40 +00:00
|
|
|
previewAndToolsLayout->addLayout(toolsLayout);
|
|
|
|
previewAndToolsLayout->setStretch(0, 0);
|
|
|
|
previewAndToolsLayout->setStretch(1, 0);
|
2018-08-31 04:54:32 +00:00
|
|
|
previewAndToolsLayout->setStretch(2, 1);
|
2018-04-23 00:10:01 +00:00
|
|
|
|
|
|
|
QWidget *backgroundWidget = new QWidget;
|
2018-08-27 08:50:40 +00:00
|
|
|
backgroundWidget->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
|
2018-09-21 07:10:18 +00:00
|
|
|
backgroundWidget->setFixedSize(preferredSize().width(), Theme::partPreviewImageSize);
|
2018-04-23 00:10:01 +00:00
|
|
|
backgroundWidget->setObjectName("background");
|
|
|
|
m_backgroundWidget = backgroundWidget;
|
2018-08-27 08:50:40 +00:00
|
|
|
backgroundWidget->setLayout(previewAndToolsLayout);
|
2018-04-23 00:10:01 +00:00
|
|
|
|
|
|
|
QHBoxLayout *backgroundLayout = new QHBoxLayout;
|
|
|
|
backgroundLayout->setSpacing(0);
|
2018-08-27 08:50:40 +00:00
|
|
|
backgroundLayout->setContentsMargins(0, 0, 0, 0);
|
2018-04-23 00:10:01 +00:00
|
|
|
backgroundLayout->addWidget(backgroundWidget);
|
2018-08-27 08:50:40 +00:00
|
|
|
backgroundLayout->addSpacing(10);
|
2018-04-23 00:10:01 +00:00
|
|
|
|
2018-04-07 11:51:33 +00:00
|
|
|
QVBoxLayout *mainLayout = new QVBoxLayout;
|
|
|
|
mainLayout->setSpacing(0);
|
|
|
|
mainLayout->setContentsMargins(0, 0, 0, 0);
|
2018-04-23 00:10:01 +00:00
|
|
|
mainLayout->addWidget(hrLightWidget);
|
|
|
|
mainLayout->addSpacing(3);
|
|
|
|
mainLayout->addLayout(backgroundLayout);
|
|
|
|
mainLayout->addSpacing(3);
|
2018-04-08 01:30:55 +00:00
|
|
|
mainLayout->addWidget(hrWidget);
|
2018-04-07 08:44:39 +00:00
|
|
|
|
|
|
|
setLayout(mainLayout);
|
2018-04-08 01:30:55 +00:00
|
|
|
|
2018-10-25 00:19:38 +00:00
|
|
|
connect(this, &PartWidget::setPartLockState, m_document, &Document::setPartLockState);
|
|
|
|
connect(this, &PartWidget::setPartVisibleState, m_document, &Document::setPartVisibleState);
|
|
|
|
connect(this, &PartWidget::setPartSubdivState, m_document, &Document::setPartSubdivState);
|
|
|
|
connect(this, &PartWidget::setPartDisableState, m_document, &Document::setPartDisableState);
|
|
|
|
connect(this, &PartWidget::setPartXmirrorState, m_document, &Document::setPartXmirrorState);
|
|
|
|
connect(this, &PartWidget::setPartDeformThickness, m_document, &Document::setPartDeformThickness);
|
|
|
|
connect(this, &PartWidget::setPartDeformWidth, m_document, &Document::setPartDeformWidth);
|
2019-08-03 10:21:27 +00:00
|
|
|
connect(this, &PartWidget::setPartDeformMapImageId, m_document, &Document::setPartDeformMapImageId);
|
|
|
|
connect(this, &PartWidget::setPartDeformMapScale, m_document, &Document::setPartDeformMapScale);
|
2018-10-25 00:19:38 +00:00
|
|
|
connect(this, &PartWidget::setPartRoundState, m_document, &Document::setPartRoundState);
|
2019-03-09 22:10:39 +00:00
|
|
|
connect(this, &PartWidget::setPartChamferState, m_document, &Document::setPartChamferState);
|
2019-02-21 22:48:15 +00:00
|
|
|
connect(this, &PartWidget::setPartCutRotation, m_document, &Document::setPartCutRotation);
|
2019-05-05 12:49:26 +00:00
|
|
|
connect(this, &PartWidget::setPartCutFace, m_document, &Document::setPartCutFace);
|
2019-05-19 03:21:38 +00:00
|
|
|
connect(this, &PartWidget::setPartCutFaceLinkedId, m_document, &Document::setPartCutFaceLinkedId);
|
2018-10-25 00:19:38 +00:00
|
|
|
connect(this, &PartWidget::setPartColorState, m_document, &Document::setPartColorState);
|
|
|
|
connect(this, &PartWidget::setPartMaterialId, m_document, &Document::setPartMaterialId);
|
2019-05-25 23:24:24 +00:00
|
|
|
connect(this, &PartWidget::setPartColorSolubility, m_document, &Document::setPartColorSolubility);
|
2019-08-18 12:02:39 +00:00
|
|
|
connect(this, &PartWidget::setPartHollowThickness, m_document, &Document::setPartHollowThickness);
|
2019-11-07 12:08:47 +00:00
|
|
|
connect(this, &PartWidget::setPartCountershaded, m_document, &Document::setPartCountershaded);
|
2018-10-25 00:19:38 +00:00
|
|
|
connect(this, &PartWidget::checkPart, m_document, &Document::checkPart);
|
|
|
|
connect(this, &PartWidget::enableBackgroundBlur, m_document, &Document::enableBackgroundBlur);
|
|
|
|
connect(this, &PartWidget::disableBackgroundBlur, m_document, &Document::disableBackgroundBlur);
|
|
|
|
|
|
|
|
connect(this, &PartWidget::groupOperationAdded, m_document, &Document::saveSnapshot);
|
2018-04-18 02:37:50 +00:00
|
|
|
|
2018-04-08 01:30:55 +00:00
|
|
|
connect(m_lockButton, &QPushButton::clicked, [=]() {
|
2018-11-03 08:09:42 +00:00
|
|
|
const SkeletonPart *part = m_document->findPart(m_partId);
|
2018-04-15 12:11:51 +00:00
|
|
|
if (!part) {
|
|
|
|
qDebug() << "Part not found:" << m_partId;
|
|
|
|
return;
|
2018-04-08 01:30:55 +00:00
|
|
|
}
|
2018-04-15 12:11:51 +00:00
|
|
|
emit setPartLockState(m_partId, !part->locked);
|
2018-08-31 12:19:56 +00:00
|
|
|
emit groupOperationAdded();
|
2018-04-08 01:30:55 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
connect(m_visibleButton, &QPushButton::clicked, [=]() {
|
2018-11-03 08:09:42 +00:00
|
|
|
const SkeletonPart *part = m_document->findPart(m_partId);
|
2018-04-15 12:11:51 +00:00
|
|
|
if (!part) {
|
|
|
|
qDebug() << "Part not found:" << m_partId;
|
|
|
|
return;
|
2018-04-08 01:30:55 +00:00
|
|
|
}
|
2018-04-15 12:11:51 +00:00
|
|
|
emit setPartVisibleState(m_partId, !part->visible);
|
2018-08-31 12:19:56 +00:00
|
|
|
emit groupOperationAdded();
|
2018-04-08 01:30:55 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
connect(m_subdivButton, &QPushButton::clicked, [=]() {
|
2018-11-03 08:09:42 +00:00
|
|
|
const SkeletonPart *part = m_document->findPart(m_partId);
|
2018-04-15 12:11:51 +00:00
|
|
|
if (!part) {
|
|
|
|
qDebug() << "Part not found:" << m_partId;
|
|
|
|
return;
|
2018-04-08 01:30:55 +00:00
|
|
|
}
|
2020-04-08 23:25:37 +00:00
|
|
|
if (!part->hasSubdivFunction())
|
|
|
|
return;
|
2018-04-15 12:11:51 +00:00
|
|
|
emit setPartSubdivState(m_partId, !part->subdived);
|
2018-04-18 02:37:50 +00:00
|
|
|
emit groupOperationAdded();
|
2018-04-08 01:30:55 +00:00
|
|
|
});
|
2018-04-11 09:19:27 +00:00
|
|
|
|
|
|
|
connect(m_disableButton, &QPushButton::clicked, [=]() {
|
2018-11-03 08:09:42 +00:00
|
|
|
const SkeletonPart *part = m_document->findPart(m_partId);
|
2018-04-15 12:11:51 +00:00
|
|
|
if (!part) {
|
|
|
|
qDebug() << "Part not found:" << m_partId;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
emit setPartDisableState(m_partId, !part->disabled);
|
2018-04-18 02:37:50 +00:00
|
|
|
emit groupOperationAdded();
|
2018-04-15 12:11:51 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
connect(m_xMirrorButton, &QPushButton::clicked, [=]() {
|
2018-11-03 08:09:42 +00:00
|
|
|
const SkeletonPart *part = m_document->findPart(m_partId);
|
2018-04-15 12:11:51 +00:00
|
|
|
if (!part) {
|
|
|
|
qDebug() << "Part not found:" << m_partId;
|
|
|
|
return;
|
2018-04-11 09:19:27 +00:00
|
|
|
}
|
2020-04-08 23:25:37 +00:00
|
|
|
if (!part->hasMirrorFunction())
|
|
|
|
return;
|
2018-04-15 12:11:51 +00:00
|
|
|
emit setPartXmirrorState(m_partId, !part->xMirrored);
|
2018-04-18 02:37:50 +00:00
|
|
|
emit groupOperationAdded();
|
2018-04-15 12:11:51 +00:00
|
|
|
});
|
|
|
|
|
2018-04-17 16:14:31 +00:00
|
|
|
connect(m_deformButton, &QPushButton::clicked, [=]() {
|
2018-11-03 08:09:42 +00:00
|
|
|
const SkeletonPart *part = m_document->findPart(m_partId);
|
2018-04-15 12:11:51 +00:00
|
|
|
if (!part) {
|
|
|
|
qDebug() << "Part not found:" << m_partId;
|
|
|
|
return;
|
|
|
|
}
|
2020-04-08 23:25:37 +00:00
|
|
|
if (!part->hasDeformFunction())
|
|
|
|
return;
|
2018-04-17 16:14:31 +00:00
|
|
|
showDeformSettingPopup(mapFromGlobal(QCursor::pos()));
|
2018-04-26 02:23:22 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
connect(m_roundButton, &QPushButton::clicked, [=]() {
|
2018-11-03 08:09:42 +00:00
|
|
|
const SkeletonPart *part = m_document->findPart(m_partId);
|
2018-04-26 02:23:22 +00:00
|
|
|
if (!part) {
|
|
|
|
qDebug() << "Part not found:" << m_partId;
|
|
|
|
return;
|
|
|
|
}
|
2020-04-08 23:25:37 +00:00
|
|
|
if (!part->hasRoundEndFunction())
|
|
|
|
return;
|
2018-04-26 02:23:22 +00:00
|
|
|
emit setPartRoundState(m_partId, !part->rounded);
|
2018-04-18 02:37:50 +00:00
|
|
|
emit groupOperationAdded();
|
2018-04-11 09:19:27 +00:00
|
|
|
});
|
2018-04-26 02:23:22 +00:00
|
|
|
|
2019-03-09 22:10:39 +00:00
|
|
|
connect(m_chamferButton, &QPushButton::clicked, [=]() {
|
2018-11-03 08:09:42 +00:00
|
|
|
const SkeletonPart *part = m_document->findPart(m_partId);
|
2018-04-26 02:23:22 +00:00
|
|
|
if (!part) {
|
|
|
|
qDebug() << "Part not found:" << m_partId;
|
|
|
|
return;
|
|
|
|
}
|
2020-04-08 23:25:37 +00:00
|
|
|
if (!part->hasChamferFunction())
|
|
|
|
return;
|
2019-03-09 22:10:39 +00:00
|
|
|
emit setPartChamferState(m_partId, !part->chamfered);
|
|
|
|
emit groupOperationAdded();
|
2018-04-26 02:23:22 +00:00
|
|
|
});
|
|
|
|
|
2019-03-09 22:10:39 +00:00
|
|
|
connect(m_colorButton, &QPushButton::clicked, [=]() {
|
2018-11-03 08:09:42 +00:00
|
|
|
const SkeletonPart *part = m_document->findPart(m_partId);
|
2018-08-31 04:54:32 +00:00
|
|
|
if (!part) {
|
|
|
|
qDebug() << "Part not found:" << m_partId;
|
|
|
|
return;
|
|
|
|
}
|
2020-04-08 23:25:37 +00:00
|
|
|
if (!part->hasColorFunction())
|
|
|
|
return;
|
2019-03-09 22:10:39 +00:00
|
|
|
showColorSettingPopup(mapFromGlobal(QCursor::pos()));
|
2018-08-31 04:54:32 +00:00
|
|
|
});
|
|
|
|
|
2019-03-09 22:10:39 +00:00
|
|
|
connect(m_cutRotationButton, &QPushButton::clicked, [=]() {
|
2019-02-24 13:42:23 +00:00
|
|
|
const SkeletonPart *part = m_document->findPart(m_partId);
|
|
|
|
if (!part) {
|
|
|
|
qDebug() << "Part not found:" << m_partId;
|
|
|
|
return;
|
|
|
|
}
|
2020-04-08 23:25:37 +00:00
|
|
|
if (!part->hasRotationFunction())
|
|
|
|
return;
|
2019-03-09 22:10:39 +00:00
|
|
|
showCutRotationSettingPopup(mapFromGlobal(QCursor::pos()));
|
2019-02-24 13:42:23 +00:00
|
|
|
});
|
|
|
|
|
2018-08-27 08:50:40 +00:00
|
|
|
setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
|
|
|
|
setFixedSize(preferredSize());
|
2018-05-10 09:16:22 +00:00
|
|
|
|
|
|
|
updateAllButtons();
|
2018-08-27 08:50:40 +00:00
|
|
|
}
|
|
|
|
|
2018-10-25 00:19:38 +00:00
|
|
|
ModelWidget *PartWidget::previewWidget()
|
2018-09-18 06:22:29 +00:00
|
|
|
{
|
|
|
|
return m_previewWidget;
|
|
|
|
}
|
|
|
|
|
2018-10-25 00:19:38 +00:00
|
|
|
QSize PartWidget::preferredSize()
|
2018-08-27 08:50:40 +00:00
|
|
|
{
|
2018-09-21 07:10:18 +00:00
|
|
|
return QSize(Theme::miniIconSize + Theme::partPreviewImageSize + Theme::miniIconSize * 4 + 5 + 2, Theme::partPreviewImageSize + 6);
|
2018-05-10 09:16:22 +00:00
|
|
|
}
|
|
|
|
|
2018-10-25 00:19:38 +00:00
|
|
|
void PartWidget::updateAllButtons()
|
2018-05-10 09:16:22 +00:00
|
|
|
{
|
|
|
|
updateVisibleButton();
|
|
|
|
updateLockButton();
|
|
|
|
updateSubdivButton();
|
|
|
|
updateDisableButton();
|
|
|
|
updateXmirrorButton();
|
|
|
|
updateDeformButton();
|
|
|
|
updateRoundButton();
|
2019-03-09 22:10:39 +00:00
|
|
|
updateChamferButton();
|
2018-05-10 09:16:22 +00:00
|
|
|
updateColorButton();
|
2019-02-21 22:48:15 +00:00
|
|
|
updateCutRotationButton();
|
2018-04-26 02:23:22 +00:00
|
|
|
}
|
|
|
|
|
2018-10-25 00:19:38 +00:00
|
|
|
void PartWidget::updateCheckedState(bool checked)
|
2018-04-23 00:10:01 +00:00
|
|
|
{
|
|
|
|
if (checked)
|
2018-11-14 13:21:45 +00:00
|
|
|
m_backgroundWidget->setStyleSheet("QWidget#background {border: 1px solid " + (m_unnormal ? Theme::blue.name() : Theme::red.name()) + ";}");
|
2018-04-23 00:10:01 +00:00
|
|
|
else
|
|
|
|
m_backgroundWidget->setStyleSheet("QWidget#background {border: 1px solid transparent;}");
|
|
|
|
}
|
|
|
|
|
2018-11-14 13:21:45 +00:00
|
|
|
void PartWidget::updateUnnormalState(bool unnormal)
|
2018-11-14 03:11:31 +00:00
|
|
|
{
|
2018-11-14 13:21:45 +00:00
|
|
|
if (m_unnormal == unnormal)
|
2018-11-14 03:11:31 +00:00
|
|
|
return;
|
|
|
|
|
2018-11-14 13:21:45 +00:00
|
|
|
m_unnormal = unnormal;
|
2018-11-14 03:11:31 +00:00
|
|
|
updateAllButtons();
|
|
|
|
}
|
|
|
|
|
2020-01-13 11:20:37 +00:00
|
|
|
//void PartWidget::mouseDoubleClickEvent(QMouseEvent *event)
|
|
|
|
//{
|
|
|
|
// QWidget::mouseDoubleClickEvent(event);
|
|
|
|
// emit checkPart(m_partId);
|
|
|
|
//}
|
2018-04-18 01:49:23 +00:00
|
|
|
|
2018-10-25 00:19:38 +00:00
|
|
|
void PartWidget::initToolButtonWithoutFont(QPushButton *button)
|
2018-04-17 16:14:31 +00:00
|
|
|
{
|
2018-09-06 15:04:59 +00:00
|
|
|
Theme::initAwesomeToolButtonWithoutFont(button);
|
2018-04-17 16:14:31 +00:00
|
|
|
}
|
|
|
|
|
2018-10-25 00:19:38 +00:00
|
|
|
void PartWidget::initToolButton(QPushButton *button)
|
2018-04-26 02:23:22 +00:00
|
|
|
{
|
2018-09-06 15:04:59 +00:00
|
|
|
Theme::initAwesomeToolButton(button);
|
2018-04-26 02:23:22 +00:00
|
|
|
}
|
|
|
|
|
2018-10-25 00:19:38 +00:00
|
|
|
void PartWidget::showColorSettingPopup(const QPoint &pos)
|
2018-04-26 02:23:22 +00:00
|
|
|
{
|
|
|
|
QMenu popupMenu;
|
|
|
|
|
2018-11-03 08:09:42 +00:00
|
|
|
const SkeletonPart *part = m_document->findPart(m_partId);
|
2018-04-26 02:23:22 +00:00
|
|
|
if (!part) {
|
|
|
|
qDebug() << "Find part failed:" << m_partId;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
QWidget *popup = new QWidget;
|
|
|
|
|
|
|
|
QPushButton *colorEraser = new QPushButton(QChar(fa::eraser));
|
|
|
|
initToolButton(colorEraser);
|
|
|
|
|
|
|
|
QPushButton *pickButton = new QPushButton();
|
|
|
|
initToolButtonWithoutFont(pickButton);
|
|
|
|
QPalette palette = pickButton->palette();
|
2019-06-01 13:12:53 +00:00
|
|
|
QColor choosenColor = part->color;
|
2018-04-26 02:23:22 +00:00
|
|
|
palette.setColor(QPalette::Window, choosenColor);
|
|
|
|
palette.setColor(QPalette::Button, choosenColor);
|
|
|
|
pickButton->setPalette(palette);
|
|
|
|
|
2019-11-07 12:08:47 +00:00
|
|
|
QCheckBox *countershadeStateBox = new QCheckBox();
|
|
|
|
Theme::initCheckbox(countershadeStateBox);
|
|
|
|
countershadeStateBox->setText(tr("Countershaded"));
|
|
|
|
countershadeStateBox->setChecked(part->countershaded);
|
|
|
|
|
|
|
|
connect(countershadeStateBox, &QCheckBox::stateChanged, this, [=]() {
|
|
|
|
emit setPartCountershaded(m_partId, countershadeStateBox->isChecked());
|
|
|
|
emit groupOperationAdded();
|
|
|
|
});
|
|
|
|
|
2018-10-04 12:51:01 +00:00
|
|
|
QHBoxLayout *colorLayout = new QHBoxLayout;
|
|
|
|
colorLayout->addWidget(colorEraser);
|
|
|
|
colorLayout->addWidget(pickButton);
|
|
|
|
colorLayout->addStretch();
|
2019-11-07 12:08:47 +00:00
|
|
|
colorLayout->addWidget(countershadeStateBox);
|
2018-04-26 02:23:22 +00:00
|
|
|
|
|
|
|
connect(colorEraser, &QPushButton::clicked, [=]() {
|
2019-02-20 22:57:15 +00:00
|
|
|
emit setPartColorState(m_partId, false, Qt::white);
|
2018-08-31 12:19:56 +00:00
|
|
|
emit groupOperationAdded();
|
2018-04-26 02:23:22 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
connect(pickButton, &QPushButton::clicked, [=]() {
|
|
|
|
emit disableBackgroundBlur();
|
|
|
|
QColor color = QColorDialog::getColor(part->color, this);
|
|
|
|
emit enableBackgroundBlur();
|
2019-06-01 13:12:53 +00:00
|
|
|
if (color.isValid()) {
|
2019-11-02 02:43:23 +00:00
|
|
|
const SkeletonPart *part = m_document->findPart(m_partId);
|
|
|
|
if (nullptr == part) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
color.setAlphaF(part->color.alphaF());
|
2018-04-26 02:23:22 +00:00
|
|
|
emit setPartColorState(m_partId, true, color);
|
2018-08-31 12:19:56 +00:00
|
|
|
emit groupOperationAdded();
|
2018-04-26 02:23:22 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2019-11-02 02:43:23 +00:00
|
|
|
FloatNumberWidget *colorTransparencyWidget = new FloatNumberWidget;
|
|
|
|
colorTransparencyWidget->setItemName(tr("Transparency"));
|
|
|
|
colorTransparencyWidget->setRange(0.0, 1.0);
|
|
|
|
colorTransparencyWidget->setValue(1.0 - part->color.alphaF());
|
|
|
|
|
|
|
|
connect(colorTransparencyWidget, &FloatNumberWidget::valueChanged, [=](float value) {
|
|
|
|
const SkeletonPart *part = m_document->findPart(m_partId);
|
|
|
|
if (nullptr == part) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
QColor color = part->color;
|
|
|
|
color.setAlphaF(1.0 - value);
|
|
|
|
emit setPartColorState(m_partId, true, color);
|
|
|
|
emit groupOperationAdded();
|
|
|
|
});
|
|
|
|
|
|
|
|
QPushButton *colorTransparencyEraser = new QPushButton(QChar(fa::eraser));
|
|
|
|
initToolButton(colorTransparencyEraser);
|
|
|
|
|
|
|
|
connect(colorTransparencyEraser, &QPushButton::clicked, [=]() {
|
|
|
|
colorTransparencyWidget->setValue(0.0);
|
|
|
|
emit groupOperationAdded();
|
|
|
|
});
|
|
|
|
|
|
|
|
QHBoxLayout *colorTransparencyLayout = new QHBoxLayout;
|
|
|
|
colorTransparencyLayout->addWidget(colorTransparencyEraser);
|
|
|
|
colorTransparencyLayout->addWidget(colorTransparencyWidget);
|
|
|
|
|
2019-05-25 23:24:24 +00:00
|
|
|
FloatNumberWidget *colorSolubilityWidget = new FloatNumberWidget;
|
|
|
|
colorSolubilityWidget->setItemName(tr("Solubility"));
|
|
|
|
colorSolubilityWidget->setRange(0.0, 1.0);
|
|
|
|
colorSolubilityWidget->setValue(part->colorSolubility);
|
|
|
|
|
|
|
|
connect(colorSolubilityWidget, &FloatNumberWidget::valueChanged, [=](float value) {
|
|
|
|
emit setPartColorSolubility(m_partId, value);
|
|
|
|
emit groupOperationAdded();
|
|
|
|
});
|
|
|
|
|
|
|
|
QPushButton *colorSolubilityEraser = new QPushButton(QChar(fa::eraser));
|
|
|
|
initToolButton(colorSolubilityEraser);
|
|
|
|
|
|
|
|
connect(colorSolubilityEraser, &QPushButton::clicked, [=]() {
|
|
|
|
colorSolubilityWidget->setValue(0.0);
|
|
|
|
emit groupOperationAdded();
|
|
|
|
});
|
|
|
|
|
|
|
|
QHBoxLayout *colorSolubilityLayout = new QHBoxLayout;
|
|
|
|
colorSolubilityLayout->addWidget(colorSolubilityEraser);
|
|
|
|
colorSolubilityLayout->addWidget(colorSolubilityWidget);
|
|
|
|
|
2018-10-04 12:51:01 +00:00
|
|
|
QVBoxLayout *mainLayout = new QVBoxLayout;
|
|
|
|
mainLayout->addLayout(colorLayout);
|
2019-11-02 02:43:23 +00:00
|
|
|
mainLayout->addLayout(colorTransparencyLayout);
|
2019-05-25 23:24:24 +00:00
|
|
|
mainLayout->addLayout(colorSolubilityLayout);
|
2018-10-09 02:19:12 +00:00
|
|
|
|
|
|
|
if (m_document->materialIdList.empty()) {
|
|
|
|
InfoLabel *infoLabel = new InfoLabel;
|
|
|
|
infoLabel->setText(tr("Missing Materials"));
|
|
|
|
mainLayout->addWidget(infoLabel);
|
|
|
|
} else {
|
|
|
|
MaterialListWidget *materialListWidget = new MaterialListWidget(m_document);
|
|
|
|
materialListWidget->enableMultipleSelection(false);
|
|
|
|
materialListWidget->selectMaterial(part->materialId);
|
|
|
|
connect(materialListWidget, &MaterialListWidget::currentSelectedMaterialChanged, this, [=](QUuid materialId) {
|
|
|
|
emit setPartMaterialId(m_partId, materialId);
|
|
|
|
emit groupOperationAdded();
|
|
|
|
});
|
|
|
|
mainLayout->addWidget(materialListWidget);
|
|
|
|
}
|
2018-10-04 12:51:01 +00:00
|
|
|
|
|
|
|
popup->setLayout(mainLayout);
|
2018-04-26 02:23:22 +00:00
|
|
|
|
|
|
|
QWidgetAction *action = new QWidgetAction(this);
|
|
|
|
action->setDefaultWidget(popup);
|
|
|
|
|
|
|
|
popupMenu.addAction(action);
|
|
|
|
|
|
|
|
popupMenu.exec(mapToGlobal(pos));
|
|
|
|
}
|
|
|
|
|
2019-02-21 22:48:15 +00:00
|
|
|
void PartWidget::showCutRotationSettingPopup(const QPoint &pos)
|
|
|
|
{
|
|
|
|
QMenu popupMenu;
|
|
|
|
|
|
|
|
const SkeletonPart *part = m_document->findPart(m_partId);
|
|
|
|
if (!part) {
|
|
|
|
qDebug() << "Find part failed:" << m_partId;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
QWidget *popup = new QWidget;
|
|
|
|
|
|
|
|
FloatNumberWidget *rotationWidget = new FloatNumberWidget;
|
|
|
|
rotationWidget->setItemName(tr("Rotation"));
|
|
|
|
rotationWidget->setRange(-1, 1);
|
|
|
|
rotationWidget->setValue(part->cutRotation);
|
|
|
|
|
|
|
|
connect(rotationWidget, &FloatNumberWidget::valueChanged, [=](float value) {
|
|
|
|
emit setPartCutRotation(m_partId, value);
|
|
|
|
emit groupOperationAdded();
|
|
|
|
});
|
|
|
|
|
|
|
|
QPushButton *rotationEraser = new QPushButton(QChar(fa::eraser));
|
|
|
|
initToolButton(rotationEraser);
|
|
|
|
|
|
|
|
connect(rotationEraser, &QPushButton::clicked, [=]() {
|
|
|
|
rotationWidget->setValue(0.0);
|
|
|
|
emit groupOperationAdded();
|
|
|
|
});
|
|
|
|
|
2019-10-19 03:08:59 +00:00
|
|
|
QPushButton *rotationMinus5Button = new QPushButton(QChar(fa::rotateleft));
|
|
|
|
initToolButton(rotationMinus5Button);
|
|
|
|
|
|
|
|
connect(rotationMinus5Button, &QPushButton::clicked, [=]() {
|
|
|
|
rotationWidget->setValue(-0.5);
|
|
|
|
emit groupOperationAdded();
|
|
|
|
});
|
|
|
|
|
|
|
|
QPushButton *rotation5Button = new QPushButton(QChar(fa::rotateright));
|
|
|
|
initToolButton(rotation5Button);
|
|
|
|
|
|
|
|
connect(rotation5Button, &QPushButton::clicked, [=]() {
|
|
|
|
rotationWidget->setValue(0.5);
|
|
|
|
emit groupOperationAdded();
|
|
|
|
});
|
|
|
|
|
2019-02-21 22:48:15 +00:00
|
|
|
QHBoxLayout *rotationLayout = new QHBoxLayout;
|
|
|
|
rotationLayout->addWidget(rotationEraser);
|
|
|
|
rotationLayout->addWidget(rotationWidget);
|
2019-10-19 03:08:59 +00:00
|
|
|
rotationLayout->addWidget(rotationMinus5Button);
|
|
|
|
rotationLayout->addWidget(rotation5Button);
|
2019-02-21 22:48:15 +00:00
|
|
|
|
2020-04-08 23:25:37 +00:00
|
|
|
QHBoxLayout *hollowThicknessLayout = nullptr;
|
|
|
|
QHBoxLayout *standardFacesLayout = nullptr;
|
|
|
|
CutFaceListWidget *cutFaceListWidget = nullptr;
|
|
|
|
|
|
|
|
if (part->hasHollowFunction()) {
|
|
|
|
FloatNumberWidget *hollowThicknessWidget = new FloatNumberWidget;
|
|
|
|
hollowThicknessWidget->setItemName(tr("Hollow"));
|
|
|
|
hollowThicknessWidget->setRange(0.0, 1.0);
|
|
|
|
hollowThicknessWidget->setValue(part->hollowThickness);
|
|
|
|
|
|
|
|
connect(hollowThicknessWidget, &FloatNumberWidget::valueChanged, [=](float value) {
|
|
|
|
emit setPartHollowThickness(m_partId, value);
|
|
|
|
emit groupOperationAdded();
|
|
|
|
});
|
|
|
|
|
|
|
|
QPushButton *hollowThicknessEraser = new QPushButton(QChar(fa::eraser));
|
|
|
|
initToolButton(hollowThicknessEraser);
|
|
|
|
|
|
|
|
connect(hollowThicknessEraser, &QPushButton::clicked, [=]() {
|
|
|
|
hollowThicknessWidget->setValue(0.0);
|
|
|
|
emit groupOperationAdded();
|
|
|
|
});
|
|
|
|
|
|
|
|
hollowThicknessLayout = new QHBoxLayout;
|
|
|
|
hollowThicknessLayout->addWidget(hollowThicknessEraser);
|
|
|
|
hollowThicknessLayout->addWidget(hollowThicknessWidget);
|
|
|
|
}
|
2019-05-19 03:21:38 +00:00
|
|
|
|
2020-04-09 12:59:41 +00:00
|
|
|
QPushButton *buttons[(int)CutFace::Count] = {0};
|
|
|
|
|
2020-04-08 23:25:37 +00:00
|
|
|
if (part->hasCutFaceFunction()) {
|
|
|
|
standardFacesLayout = new QHBoxLayout;
|
|
|
|
|
|
|
|
cutFaceListWidget = new CutFaceListWidget(m_document);
|
|
|
|
size_t cutFaceTypeCount = (size_t)CutFace::UserDefined;
|
|
|
|
|
|
|
|
auto updateCutFaceButtonState = [&](size_t index) {
|
|
|
|
if (index != (int)CutFace::UserDefined)
|
|
|
|
cutFaceListWidget->selectCutFace(QUuid());
|
|
|
|
for (size_t i = 0; i < (size_t)cutFaceTypeCount; ++i) {
|
|
|
|
auto button = buttons[i];
|
|
|
|
if (i == index) {
|
|
|
|
button->setFlat(true);
|
|
|
|
button->setEnabled(false);
|
|
|
|
} else {
|
|
|
|
button->setFlat(false);
|
|
|
|
button->setEnabled(true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
cutFaceListWidget->enableMultipleSelection(false);
|
|
|
|
cutFaceListWidget->selectCutFace(part->cutFaceLinkedId);
|
|
|
|
connect(cutFaceListWidget, &CutFaceListWidget::currentSelectedCutFaceChanged, this, [=](QUuid partId) {
|
|
|
|
if (partId.isNull()) {
|
|
|
|
CutFace cutFace = CutFace::Quad;
|
|
|
|
updateCutFaceButtonState((int)cutFace);
|
|
|
|
emit setPartCutFace(m_partId, cutFace);
|
|
|
|
emit groupOperationAdded();
|
2019-05-05 12:49:26 +00:00
|
|
|
} else {
|
2020-04-08 23:25:37 +00:00
|
|
|
updateCutFaceButtonState((int)CutFace::UserDefined);
|
|
|
|
emit setPartCutFaceLinkedId(m_partId, partId);
|
|
|
|
emit groupOperationAdded();
|
2019-05-05 12:49:26 +00:00
|
|
|
}
|
|
|
|
});
|
2020-04-08 23:25:37 +00:00
|
|
|
if (cutFaceListWidget->isEmpty())
|
|
|
|
cutFaceListWidget->hide();
|
|
|
|
|
|
|
|
for (size_t i = 0; i < (size_t)cutFaceTypeCount; ++i) {
|
|
|
|
CutFace cutFace = (CutFace)i;
|
|
|
|
QString iconFilename = ":/resources/" + CutFaceToString(cutFace).toLower() + ".png";
|
|
|
|
QPixmap pixmap(iconFilename);
|
|
|
|
QIcon buttonIcon(pixmap);
|
|
|
|
QPushButton *button = new QPushButton;
|
|
|
|
button->setIconSize(QSize(Theme::toolIconSize / 2, Theme::toolIconSize / 2));
|
|
|
|
button->setIcon(buttonIcon);
|
|
|
|
connect(button, &QPushButton::clicked, [=]() {
|
|
|
|
updateCutFaceButtonState(i);
|
|
|
|
emit setPartCutFace(m_partId, cutFace);
|
|
|
|
emit groupOperationAdded();
|
|
|
|
});
|
|
|
|
standardFacesLayout->addWidget(button);
|
|
|
|
buttons[i] = button;
|
|
|
|
}
|
|
|
|
standardFacesLayout->addStretch();
|
|
|
|
updateCutFaceButtonState((size_t)part->cutFace);
|
2019-05-05 12:49:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
QVBoxLayout *popupLayout = new QVBoxLayout;
|
|
|
|
popupLayout->addLayout(rotationLayout);
|
2020-04-08 23:25:37 +00:00
|
|
|
if (nullptr != hollowThicknessLayout)
|
|
|
|
popupLayout->addLayout(hollowThicknessLayout);
|
|
|
|
if (nullptr != standardFacesLayout || nullptr != cutFaceListWidget)
|
|
|
|
popupLayout->addWidget(Theme::createHorizontalLineWidget());
|
|
|
|
if (nullptr != standardFacesLayout)
|
|
|
|
popupLayout->addLayout(standardFacesLayout);
|
|
|
|
if (nullptr != cutFaceListWidget)
|
|
|
|
popupLayout->addWidget(cutFaceListWidget);
|
2019-05-05 12:49:26 +00:00
|
|
|
|
|
|
|
popup->setLayout(popupLayout);
|
2019-02-21 22:48:15 +00:00
|
|
|
|
|
|
|
QWidgetAction action(this);
|
|
|
|
action.setDefaultWidget(popup);
|
|
|
|
|
|
|
|
popupMenu.addAction(&action);
|
|
|
|
|
|
|
|
popupMenu.exec(mapToGlobal(pos));
|
|
|
|
}
|
|
|
|
|
2018-10-25 00:19:38 +00:00
|
|
|
void PartWidget::showDeformSettingPopup(const QPoint &pos)
|
2018-04-17 13:13:32 +00:00
|
|
|
{
|
|
|
|
QMenu popupMenu;
|
|
|
|
|
2018-11-03 08:09:42 +00:00
|
|
|
const SkeletonPart *part = m_document->findPart(m_partId);
|
2018-04-17 13:13:32 +00:00
|
|
|
if (!part) {
|
|
|
|
qDebug() << "Find part failed:" << m_partId;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-04-17 16:14:31 +00:00
|
|
|
QWidget *popup = new QWidget;
|
|
|
|
|
|
|
|
FloatNumberWidget *thicknessWidget = new FloatNumberWidget;
|
2018-09-06 15:04:59 +00:00
|
|
|
thicknessWidget->setItemName(tr("Thickness"));
|
2018-04-17 16:14:31 +00:00
|
|
|
thicknessWidget->setRange(0, 2);
|
|
|
|
thicknessWidget->setValue(part->deformThickness);
|
|
|
|
|
|
|
|
connect(thicknessWidget, &FloatNumberWidget::valueChanged, [=](float value) {
|
|
|
|
emit setPartDeformThickness(m_partId, value);
|
2018-09-06 15:04:59 +00:00
|
|
|
emit groupOperationAdded();
|
2018-04-17 16:14:31 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
FloatNumberWidget *widthWidget = new FloatNumberWidget;
|
2018-09-06 15:04:59 +00:00
|
|
|
widthWidget->setItemName(tr("Width"));
|
2018-04-17 16:14:31 +00:00
|
|
|
widthWidget->setRange(0, 2);
|
|
|
|
widthWidget->setValue(part->deformWidth);
|
2018-04-17 13:13:32 +00:00
|
|
|
|
2018-04-17 16:14:31 +00:00
|
|
|
connect(widthWidget, &FloatNumberWidget::valueChanged, [=](float value) {
|
|
|
|
emit setPartDeformWidth(m_partId, value);
|
2018-08-31 12:19:56 +00:00
|
|
|
emit groupOperationAdded();
|
2018-04-17 13:13:32 +00:00
|
|
|
});
|
|
|
|
|
2018-04-17 16:14:31 +00:00
|
|
|
QPushButton *thicknessEraser = new QPushButton(QChar(fa::eraser));
|
|
|
|
initToolButton(thicknessEraser);
|
|
|
|
|
|
|
|
connect(thicknessEraser, &QPushButton::clicked, [=]() {
|
|
|
|
thicknessWidget->setValue(1.0);
|
2018-09-06 15:04:59 +00:00
|
|
|
emit groupOperationAdded();
|
2018-04-17 16:14:31 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
QPushButton *widthEraser = new QPushButton(QChar(fa::eraser));
|
|
|
|
initToolButton(widthEraser);
|
|
|
|
|
|
|
|
connect(widthEraser, &QPushButton::clicked, [=]() {
|
|
|
|
widthWidget->setValue(1.0);
|
2018-09-06 15:04:59 +00:00
|
|
|
emit groupOperationAdded();
|
2018-04-17 16:14:31 +00:00
|
|
|
});
|
|
|
|
|
2019-08-03 10:21:27 +00:00
|
|
|
QVBoxLayout *mainLayout = new QVBoxLayout;
|
|
|
|
|
2018-04-17 16:14:31 +00:00
|
|
|
QHBoxLayout *thicknessLayout = new QHBoxLayout;
|
|
|
|
QHBoxLayout *widthLayout = new QHBoxLayout;
|
|
|
|
thicknessLayout->addWidget(thicknessEraser);
|
|
|
|
thicknessLayout->addWidget(thicknessWidget);
|
|
|
|
widthLayout->addWidget(widthEraser);
|
|
|
|
widthLayout->addWidget(widthWidget);
|
|
|
|
|
2019-08-03 10:21:27 +00:00
|
|
|
auto pickImage = [this]() {
|
|
|
|
QString fileName = QFileDialog::getOpenFileName(this, QString(), QString(),
|
|
|
|
tr("Image Files (*.png *.jpg *.bmp)")).trimmed();
|
|
|
|
if (fileName.isEmpty())
|
|
|
|
return (QImage *)nullptr;
|
|
|
|
QImage *image = new QImage();
|
|
|
|
if (!image->load(fileName))
|
|
|
|
return (QImage *)nullptr;
|
|
|
|
return image;
|
|
|
|
};
|
|
|
|
|
|
|
|
ImagePreviewWidget *deformImageButton = new ImagePreviewWidget;
|
|
|
|
deformImageButton->setFixedHeight(Theme::partPreviewImageSize * 2);
|
|
|
|
deformImageButton->updateBackgroundColor(QColor(127, 127, 127));
|
|
|
|
|
|
|
|
QPushButton *deformImageEraser = new QPushButton(QChar(fa::eraser));
|
|
|
|
initToolButton(deformImageEraser);
|
|
|
|
|
|
|
|
auto updateImageButtonBackground = [=](const QImage *image) {
|
|
|
|
if (nullptr == image) {
|
|
|
|
deformImageButton->updateImage(QImage());
|
|
|
|
} else {
|
|
|
|
deformImageButton->updateImage(*image);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
if (!part->deformMapImageId.isNull())
|
|
|
|
updateImageButtonBackground(ImageForever::get(part->deformMapImageId));
|
|
|
|
else
|
|
|
|
updateImageButtonBackground(nullptr);
|
|
|
|
|
|
|
|
connect(deformImageEraser, &QPushButton::clicked, [=]() {
|
|
|
|
updateImageButtonBackground(nullptr);
|
|
|
|
emit setPartDeformMapImageId(m_partId, QUuid());
|
|
|
|
});
|
|
|
|
|
|
|
|
connect(deformImageButton, &ImagePreviewWidget::clicked, [=]() {
|
|
|
|
QImage *image = pickImage();
|
|
|
|
if (nullptr == image)
|
|
|
|
return;
|
|
|
|
QUuid imageId = ImageForever::add(image);
|
|
|
|
updateImageButtonBackground(image);
|
|
|
|
delete image;
|
|
|
|
emit setPartDeformMapImageId(m_partId, imageId);
|
|
|
|
});
|
|
|
|
|
2020-04-08 23:25:37 +00:00
|
|
|
QHBoxLayout *deformMapScaleLayout = nullptr;
|
|
|
|
QHBoxLayout *deformImageLayout = nullptr;
|
|
|
|
|
|
|
|
if (part->hasDeformImageFunction()) {
|
|
|
|
deformImageLayout = new QHBoxLayout;
|
|
|
|
deformImageLayout->addWidget(deformImageEraser);
|
|
|
|
deformImageLayout->addWidget(deformImageButton);
|
|
|
|
deformImageLayout->setStretch(1, 1);
|
|
|
|
|
|
|
|
FloatNumberWidget *deformMapScaleWidget = new FloatNumberWidget;
|
|
|
|
deformMapScaleWidget->setItemName(tr("Map Scale"));
|
|
|
|
deformMapScaleWidget->setRange(0, 1.0);
|
|
|
|
deformMapScaleWidget->setValue(part->deformMapScale);
|
|
|
|
|
|
|
|
connect(deformMapScaleWidget, &FloatNumberWidget::valueChanged, [=](float value) {
|
|
|
|
emit setPartDeformMapScale(m_partId, value);
|
|
|
|
emit groupOperationAdded();
|
|
|
|
});
|
2019-08-03 10:21:27 +00:00
|
|
|
|
2020-04-08 23:25:37 +00:00
|
|
|
QPushButton *deformMapScaleEraser = new QPushButton(QChar(fa::eraser));
|
|
|
|
initToolButton(deformMapScaleEraser);
|
|
|
|
|
|
|
|
connect(deformMapScaleEraser, &QPushButton::clicked, [=]() {
|
|
|
|
deformMapScaleWidget->setValue(0.5);
|
|
|
|
emit groupOperationAdded();
|
|
|
|
});
|
|
|
|
|
|
|
|
deformMapScaleLayout = new QHBoxLayout;
|
|
|
|
deformMapScaleLayout->addWidget(deformMapScaleEraser);
|
|
|
|
deformMapScaleLayout->addWidget(deformMapScaleWidget);
|
|
|
|
}
|
2019-08-03 10:21:27 +00:00
|
|
|
|
|
|
|
mainLayout->addLayout(thicknessLayout);
|
|
|
|
mainLayout->addLayout(widthLayout);
|
2020-04-08 23:25:37 +00:00
|
|
|
if (nullptr != deformMapScaleLayout || nullptr != deformImageLayout)
|
|
|
|
mainLayout->addWidget(Theme::createHorizontalLineWidget());
|
|
|
|
if (nullptr != deformMapScaleLayout)
|
|
|
|
mainLayout->addLayout(deformMapScaleLayout);
|
|
|
|
if (nullptr != deformImageLayout)
|
|
|
|
mainLayout->addLayout(deformImageLayout);
|
2019-08-03 10:21:27 +00:00
|
|
|
|
|
|
|
popup->setLayout(mainLayout);
|
2018-04-17 16:14:31 +00:00
|
|
|
|
2018-09-06 15:04:59 +00:00
|
|
|
QWidgetAction action(this);
|
|
|
|
action.setDefaultWidget(popup);
|
2018-04-17 13:13:32 +00:00
|
|
|
|
2018-09-06 15:04:59 +00:00
|
|
|
popupMenu.addAction(&action);
|
2018-04-17 13:13:32 +00:00
|
|
|
|
|
|
|
popupMenu.exec(mapToGlobal(pos));
|
|
|
|
}
|
|
|
|
|
2018-10-25 00:19:38 +00:00
|
|
|
void PartWidget::initButton(QPushButton *button)
|
2018-04-07 08:44:39 +00:00
|
|
|
{
|
2018-09-06 15:04:59 +00:00
|
|
|
Theme::initAwesomeMiniButton(button);
|
2018-04-07 08:44:39 +00:00
|
|
|
}
|
|
|
|
|
2020-04-08 23:25:37 +00:00
|
|
|
void PartWidget::updateButton(QPushButton *button, QChar icon, bool highlighted, bool enabled)
|
2018-04-08 01:30:55 +00:00
|
|
|
{
|
2020-04-08 23:25:37 +00:00
|
|
|
Theme::updateAwesomeMiniButton(button, icon, highlighted, enabled, m_unnormal);
|
2018-04-08 01:30:55 +00:00
|
|
|
}
|
|
|
|
|
2018-10-25 00:19:38 +00:00
|
|
|
void PartWidget::updatePreview()
|
2018-04-07 08:44:39 +00:00
|
|
|
{
|
2018-11-03 08:09:42 +00:00
|
|
|
const SkeletonPart *part = m_document->findPart(m_partId);
|
2018-04-07 08:44:39 +00:00
|
|
|
if (!part) {
|
|
|
|
qDebug() << "Part not found:" << m_partId;
|
|
|
|
return;
|
|
|
|
}
|
2018-09-18 06:22:29 +00:00
|
|
|
//m_previewLabel->setPixmap(QPixmap::fromImage(part->preview));
|
2020-04-07 23:15:20 +00:00
|
|
|
Model *previewMesh = part->takePreviewMesh();
|
2018-09-18 06:22:29 +00:00
|
|
|
m_previewWidget->updateMesh(previewMesh);
|
2020-03-25 11:40:44 +00:00
|
|
|
if (PartTarget::CutFace == part->target) {
|
|
|
|
if (0 != m_previewWidget->xRot()) {
|
|
|
|
m_previewWidget->setXRotation(0);
|
|
|
|
m_previewWidget->setYRotation(0);
|
|
|
|
m_previewWidget->setZRotation(0);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (0 == m_previewWidget->xRot()) {
|
|
|
|
m_previewWidget->setXRotation(ModelWidget::m_defaultXRotation);
|
|
|
|
m_previewWidget->setYRotation(ModelWidget::m_defaultYRotation);
|
|
|
|
m_previewWidget->setZRotation(ModelWidget::m_defaultZRotation);
|
|
|
|
}
|
|
|
|
}
|
2018-04-07 08:44:39 +00:00
|
|
|
}
|
|
|
|
|
2018-10-25 00:19:38 +00:00
|
|
|
void PartWidget::updateLockButton()
|
2018-04-08 01:30:55 +00:00
|
|
|
{
|
2018-11-03 08:09:42 +00:00
|
|
|
const SkeletonPart *part = m_document->findPart(m_partId);
|
2018-04-08 01:30:55 +00:00
|
|
|
if (!part) {
|
|
|
|
qDebug() << "Part not found:" << m_partId;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (part->locked)
|
|
|
|
updateButton(m_lockButton, QChar(fa::lock), true);
|
|
|
|
else
|
|
|
|
updateButton(m_lockButton, QChar(fa::unlock), false);
|
|
|
|
}
|
|
|
|
|
2018-10-25 00:19:38 +00:00
|
|
|
void PartWidget::updateVisibleButton()
|
2018-04-08 01:30:55 +00:00
|
|
|
{
|
2018-11-03 08:09:42 +00:00
|
|
|
const SkeletonPart *part = m_document->findPart(m_partId);
|
2018-04-08 01:30:55 +00:00
|
|
|
if (!part) {
|
|
|
|
qDebug() << "Part not found:" << m_partId;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (part->visible)
|
|
|
|
updateButton(m_visibleButton, QChar(fa::eye), false);
|
|
|
|
else
|
|
|
|
updateButton(m_visibleButton, QChar(fa::eyeslash), true);
|
|
|
|
}
|
|
|
|
|
2018-10-25 00:19:38 +00:00
|
|
|
void PartWidget::updateSubdivButton()
|
2018-04-08 01:30:55 +00:00
|
|
|
{
|
2018-11-03 08:09:42 +00:00
|
|
|
const SkeletonPart *part = m_document->findPart(m_partId);
|
2018-04-08 01:30:55 +00:00
|
|
|
if (!part) {
|
|
|
|
qDebug() << "Part not found:" << m_partId;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (part->subdived)
|
2020-04-08 23:25:37 +00:00
|
|
|
updateButton(m_subdivButton, QChar(fa::circleo), true, part->hasSubdivFunction());
|
2018-04-08 01:30:55 +00:00
|
|
|
else
|
2020-04-08 23:25:37 +00:00
|
|
|
updateButton(m_subdivButton, QChar(fa::squareo), false, part->hasSubdivFunction());
|
2018-04-08 01:30:55 +00:00
|
|
|
}
|
|
|
|
|
2018-10-25 00:19:38 +00:00
|
|
|
void PartWidget::updateDisableButton()
|
2018-04-11 09:19:27 +00:00
|
|
|
{
|
2018-11-03 08:09:42 +00:00
|
|
|
const SkeletonPart *part = m_document->findPart(m_partId);
|
2018-04-11 09:19:27 +00:00
|
|
|
if (!part) {
|
|
|
|
qDebug() << "Part not found:" << m_partId;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (part->disabled)
|
|
|
|
updateButton(m_disableButton, QChar(fa::unlink), true);
|
|
|
|
else
|
|
|
|
updateButton(m_disableButton, QChar(fa::link), false);
|
|
|
|
}
|
|
|
|
|
2018-10-25 00:19:38 +00:00
|
|
|
void PartWidget::updateXmirrorButton()
|
2018-04-15 12:11:51 +00:00
|
|
|
{
|
2018-11-03 08:09:42 +00:00
|
|
|
const SkeletonPart *part = m_document->findPart(m_partId);
|
2018-04-15 12:11:51 +00:00
|
|
|
if (!part) {
|
|
|
|
qDebug() << "Part not found:" << m_partId;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (part->xMirrored)
|
2020-04-08 23:25:37 +00:00
|
|
|
updateButton(m_xMirrorButton, QChar(fa::balancescale), true, part->hasMirrorFunction());
|
2018-04-15 12:11:51 +00:00
|
|
|
else
|
2020-04-08 23:25:37 +00:00
|
|
|
updateButton(m_xMirrorButton, QChar(fa::balancescale), false, part->hasMirrorFunction());
|
2018-04-15 12:11:51 +00:00
|
|
|
}
|
|
|
|
|
2018-10-25 00:19:38 +00:00
|
|
|
void PartWidget::updateDeformButton()
|
2018-04-15 12:11:51 +00:00
|
|
|
{
|
2018-11-03 08:09:42 +00:00
|
|
|
const SkeletonPart *part = m_document->findPart(m_partId);
|
2018-04-15 12:11:51 +00:00
|
|
|
if (!part) {
|
|
|
|
qDebug() << "Part not found:" << m_partId;
|
|
|
|
return;
|
|
|
|
}
|
2019-08-03 10:21:27 +00:00
|
|
|
if (part->deformAdjusted() || part->deformMapAdjusted())
|
2020-04-08 23:25:37 +00:00
|
|
|
updateButton(m_deformButton, QChar(fa::handlizardo), true, part->hasDeformFunction());
|
2018-04-15 12:11:51 +00:00
|
|
|
else
|
2020-04-08 23:25:37 +00:00
|
|
|
updateButton(m_deformButton, QChar(fa::handlizardo), false, part->hasDeformFunction());
|
2018-04-15 12:11:51 +00:00
|
|
|
}
|
|
|
|
|
2018-10-25 00:19:38 +00:00
|
|
|
void PartWidget::updateRoundButton()
|
2018-04-26 02:23:22 +00:00
|
|
|
{
|
2018-11-03 08:09:42 +00:00
|
|
|
const SkeletonPart *part = m_document->findPart(m_partId);
|
2018-04-26 02:23:22 +00:00
|
|
|
if (!part) {
|
|
|
|
qDebug() << "Part not found:" << m_partId;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (part->rounded)
|
2020-04-08 23:25:37 +00:00
|
|
|
updateButton(m_roundButton, QChar(fa::magnet), true, part->hasRoundEndFunction());
|
2018-04-26 02:23:22 +00:00
|
|
|
else
|
2020-04-08 23:25:37 +00:00
|
|
|
updateButton(m_roundButton, QChar(fa::magnet), false, part->hasRoundEndFunction());
|
2018-04-26 02:23:22 +00:00
|
|
|
}
|
|
|
|
|
2019-03-09 22:10:39 +00:00
|
|
|
void PartWidget::updateChamferButton()
|
2018-04-26 02:23:22 +00:00
|
|
|
{
|
2018-11-03 08:09:42 +00:00
|
|
|
const SkeletonPart *part = m_document->findPart(m_partId);
|
2018-04-26 02:23:22 +00:00
|
|
|
if (!part) {
|
|
|
|
qDebug() << "Part not found:" << m_partId;
|
|
|
|
return;
|
|
|
|
}
|
2019-03-09 22:10:39 +00:00
|
|
|
if (part->chamfered)
|
2020-04-08 23:25:37 +00:00
|
|
|
updateButton(m_chamferButton, QChar(fa::scissors), true, part->hasChamferFunction());
|
2018-04-26 02:23:22 +00:00
|
|
|
else
|
2020-04-08 23:25:37 +00:00
|
|
|
updateButton(m_chamferButton, QChar(fa::scissors), false, part->hasChamferFunction());
|
2018-04-26 02:23:22 +00:00
|
|
|
}
|
|
|
|
|
2019-03-09 22:10:39 +00:00
|
|
|
void PartWidget::updateColorButton()
|
2018-08-31 04:54:32 +00:00
|
|
|
{
|
2018-11-03 08:09:42 +00:00
|
|
|
const SkeletonPart *part = m_document->findPart(m_partId);
|
2018-08-31 04:54:32 +00:00
|
|
|
if (!part) {
|
|
|
|
qDebug() << "Part not found:" << m_partId;
|
|
|
|
return;
|
|
|
|
}
|
2019-11-07 12:08:47 +00:00
|
|
|
if (part->hasColor || part->materialAdjusted() || part->colorSolubilityAdjusted() || part->countershaded)
|
2020-04-08 23:25:37 +00:00
|
|
|
updateButton(m_colorButton, QChar(fa::eyedropper), true, part->hasColorFunction());
|
2019-02-24 13:42:23 +00:00
|
|
|
else
|
2020-04-08 23:25:37 +00:00
|
|
|
updateButton(m_colorButton, QChar(fa::eyedropper), false, part->hasColorFunction());
|
2019-02-24 13:42:23 +00:00
|
|
|
}
|
|
|
|
|
2019-03-09 22:10:39 +00:00
|
|
|
void PartWidget::updateCutRotationButton()
|
2019-02-24 13:42:23 +00:00
|
|
|
{
|
|
|
|
const SkeletonPart *part = m_document->findPart(m_partId);
|
|
|
|
if (!part) {
|
|
|
|
qDebug() << "Part not found:" << m_partId;
|
|
|
|
return;
|
|
|
|
}
|
2019-05-05 12:49:26 +00:00
|
|
|
if (part->cutAdjusted())
|
2020-04-08 23:25:37 +00:00
|
|
|
updateButton(m_cutRotationButton, QChar(fa::spinner), true, part->hasRotationFunction());
|
2018-08-31 04:54:32 +00:00
|
|
|
else
|
2020-04-08 23:25:37 +00:00
|
|
|
updateButton(m_cutRotationButton, QChar(fa::spinner), false, part->hasRotationFunction());
|
2018-08-31 04:54:32 +00:00
|
|
|
}
|
|
|
|
|
2018-10-25 00:19:38 +00:00
|
|
|
void PartWidget::reload()
|
2018-04-08 01:30:55 +00:00
|
|
|
{
|
|
|
|
updatePreview();
|
2018-08-31 04:54:32 +00:00
|
|
|
updateAllButtons();
|
2018-04-08 01:30:55 +00:00
|
|
|
}
|