Add base normal rotation
parent
a9dd15991f
commit
73b3dc3941
|
@ -4,6 +4,7 @@
|
|||
#include <QPushButton>
|
||||
#include <QColorDialog>
|
||||
#include "component_property_widget.h"
|
||||
#include "float_number_widget.h"
|
||||
#include "document.h"
|
||||
#include "theme.h"
|
||||
|
||||
|
@ -22,21 +23,140 @@ ComponentPropertyWidget::ComponentPropertyWidget(Document *document,
|
|||
colorPreviewArea->setFixedSize(Theme::toolIconSize * 1.8, Theme::toolIconSize);
|
||||
|
||||
QPushButton *colorPickerButton = new QPushButton(QChar(fa::eyedropper));
|
||||
colorPickerButton->setFixedSize(Theme::toolIconSize, Theme::toolIconSize);
|
||||
Theme::initIconButton(colorPickerButton);
|
||||
connect(colorPickerButton, &QPushButton::clicked, this, &ComponentPropertyWidget::showColorDialog);
|
||||
|
||||
QHBoxLayout *colorLayout = new QHBoxLayout;
|
||||
colorLayout->addWidget(colorPreviewArea);
|
||||
colorLayout->addWidget(colorPickerButton);
|
||||
colorLayout->addStretch();
|
||||
colorLayout->setSizeConstraint(QLayout::SetFixedSize);
|
||||
|
||||
QVBoxLayout *deformLayout = nullptr;
|
||||
if (nullptr != m_part) {
|
||||
|
||||
FloatNumberWidget *thicknessWidget = new FloatNumberWidget;
|
||||
thicknessWidget->setItemName(tr("Thickness"));
|
||||
thicknessWidget->setRange(0, 2);
|
||||
thicknessWidget->setValue(m_part->deformThickness);
|
||||
|
||||
connect(thicknessWidget, &FloatNumberWidget::valueChanged, [=](float value) {
|
||||
emit setPartDeformThickness(m_partId, value);
|
||||
emit groupOperationAdded();
|
||||
});
|
||||
|
||||
FloatNumberWidget *widthWidget = new FloatNumberWidget;
|
||||
widthWidget->setItemName(tr("Width"));
|
||||
widthWidget->setRange(0, 2);
|
||||
widthWidget->setValue(m_part->deformWidth);
|
||||
|
||||
connect(widthWidget, &FloatNumberWidget::valueChanged, [=](float value) {
|
||||
emit setPartDeformWidth(m_partId, value);
|
||||
emit groupOperationAdded();
|
||||
});
|
||||
|
||||
QPushButton *thicknessEraser = new QPushButton(QChar(fa::eraser));
|
||||
Theme::initIconButton(thicknessEraser);
|
||||
|
||||
connect(thicknessEraser, &QPushButton::clicked, [=]() {
|
||||
thicknessWidget->setValue(1.0);
|
||||
emit groupOperationAdded();
|
||||
});
|
||||
|
||||
QPushButton *widthEraser = new QPushButton(QChar(fa::eraser));
|
||||
Theme::initIconButton(widthEraser);
|
||||
|
||||
connect(widthEraser, &QPushButton::clicked, [=]() {
|
||||
widthWidget->setValue(1.0);
|
||||
emit groupOperationAdded();
|
||||
});
|
||||
|
||||
deformLayout = new QVBoxLayout;
|
||||
|
||||
QHBoxLayout *thicknessLayout = new QHBoxLayout;
|
||||
QHBoxLayout *widthLayout = new QHBoxLayout;
|
||||
thicknessLayout->addWidget(thicknessEraser);
|
||||
thicknessLayout->addWidget(thicknessWidget);
|
||||
widthLayout->addWidget(widthEraser);
|
||||
widthLayout->addWidget(widthWidget);
|
||||
|
||||
QCheckBox *deformUnifyStateBox = new QCheckBox();
|
||||
Theme::initCheckbox(deformUnifyStateBox);
|
||||
deformUnifyStateBox->setText(tr("Unified"));
|
||||
deformUnifyStateBox->setChecked(m_part->deformUnified);
|
||||
|
||||
connect(deformUnifyStateBox, &QCheckBox::stateChanged, this, [=]() {
|
||||
emit setPartDeformUnified(m_partId, deformUnifyStateBox->isChecked());
|
||||
emit groupOperationAdded();
|
||||
});
|
||||
|
||||
QHBoxLayout *deformUnifyLayout = new QHBoxLayout;
|
||||
deformUnifyLayout->addStretch();
|
||||
deformUnifyLayout->addWidget(deformUnifyStateBox);
|
||||
|
||||
deformLayout->addLayout(thicknessLayout);
|
||||
deformLayout->addLayout(widthLayout);
|
||||
deformLayout->addLayout(deformUnifyLayout);
|
||||
}
|
||||
|
||||
QHBoxLayout *rotationLayout = nullptr;
|
||||
if (nullptr != m_part) {
|
||||
FloatNumberWidget *rotationWidget = new FloatNumberWidget;
|
||||
rotationWidget->setItemName(tr("Rotation"));
|
||||
rotationWidget->setRange(-1, 1);
|
||||
rotationWidget->setValue(m_part->cutRotation);
|
||||
|
||||
connect(rotationWidget, &FloatNumberWidget::valueChanged, [=](float value) {
|
||||
emit setPartCutRotation(m_partId, value);
|
||||
emit groupOperationAdded();
|
||||
});
|
||||
|
||||
QPushButton *rotationEraser = new QPushButton(QChar(fa::eraser));
|
||||
Theme::initIconButton(rotationEraser);
|
||||
|
||||
connect(rotationEraser, &QPushButton::clicked, [=]() {
|
||||
rotationWidget->setValue(0.0);
|
||||
emit groupOperationAdded();
|
||||
});
|
||||
|
||||
QPushButton *rotationMinus5Button = new QPushButton(QChar(fa::rotateleft));
|
||||
Theme::initIconButton(rotationMinus5Button);
|
||||
|
||||
connect(rotationMinus5Button, &QPushButton::clicked, [=]() {
|
||||
rotationWidget->setValue(-0.5);
|
||||
emit groupOperationAdded();
|
||||
});
|
||||
|
||||
QPushButton *rotation5Button = new QPushButton(QChar(fa::rotateright));
|
||||
Theme::initIconButton(rotation5Button);
|
||||
|
||||
connect(rotation5Button, &QPushButton::clicked, [=]() {
|
||||
rotationWidget->setValue(0.5);
|
||||
emit groupOperationAdded();
|
||||
});
|
||||
|
||||
rotationLayout = new QHBoxLayout;
|
||||
rotationLayout->addWidget(rotationEraser);
|
||||
rotationLayout->addWidget(rotationWidget);
|
||||
rotationLayout->addWidget(rotationMinus5Button);
|
||||
rotationLayout->addWidget(rotation5Button);
|
||||
}
|
||||
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||
mainLayout->addLayout(colorLayout);
|
||||
if (nullptr != deformLayout)
|
||||
mainLayout->addLayout(deformLayout);
|
||||
if (nullptr != rotationLayout)
|
||||
mainLayout->addLayout(rotationLayout);
|
||||
mainLayout->setSizeConstraint(QLayout::SetFixedSize);
|
||||
|
||||
connect(this, &ComponentPropertyWidget::setPartColorState, m_document, &Document::setPartColorState);
|
||||
connect(this, &ComponentPropertyWidget::endColorPicking, m_document, &Document::enableBackgroundBlur);
|
||||
connect(this, &ComponentPropertyWidget::beginColorPicking, m_document, &Document::disableBackgroundBlur);
|
||||
connect(this, &ComponentPropertyWidget::setPartDeformThickness, m_document, &Document::setPartDeformThickness);
|
||||
connect(this, &ComponentPropertyWidget::setPartDeformWidth, m_document, &Document::setPartDeformWidth);
|
||||
connect(this, &ComponentPropertyWidget::setPartDeformUnified, m_document, &Document::setPartDeformUnified);
|
||||
connect(this, &ComponentPropertyWidget::setPartCutRotation, m_document, &Document::setPartCutRotation);
|
||||
connect(this, &ComponentPropertyWidget::groupOperationAdded, m_document, &Document::saveSnapshot);
|
||||
|
||||
setLayout(mainLayout);
|
||||
|
@ -55,6 +175,11 @@ void ComponentPropertyWidget::preparePartIds()
|
|||
m_partIds.emplace_back(it);
|
||||
}
|
||||
}
|
||||
if (1 == m_partIds.size()) {
|
||||
m_part = m_document->findPart(m_partIds.front());
|
||||
if (nullptr != m_part)
|
||||
m_partId = m_partIds.front();
|
||||
}
|
||||
}
|
||||
|
||||
QColor ComponentPropertyWidget::lastColor()
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <QWidget>
|
||||
|
||||
class Document;
|
||||
class SkeletonPart;
|
||||
|
||||
class ComponentPropertyWidget: public QWidget
|
||||
{
|
||||
|
@ -13,6 +14,10 @@ signals:
|
|||
void beginColorPicking();
|
||||
void endColorPicking();
|
||||
void setPartColorState(const dust3d::Uuid &partId, bool hasColor, const QColor &color);
|
||||
void setPartDeformThickness(const dust3d::Uuid &partId, float thickness);
|
||||
void setPartDeformWidth(const dust3d::Uuid &partId, float width);
|
||||
void setPartDeformUnified(const dust3d::Uuid &partId, bool unified);
|
||||
void setPartCutRotation(const dust3d::Uuid &partId, float cutRotation);
|
||||
void groupOperationAdded();
|
||||
public:
|
||||
ComponentPropertyWidget(Document *document,
|
||||
|
@ -24,6 +29,8 @@ private:
|
|||
Document *m_document = nullptr;
|
||||
std::vector<dust3d::Uuid> m_componentIds;
|
||||
std::vector<dust3d::Uuid> m_partIds;
|
||||
dust3d::Uuid m_partId;
|
||||
const SkeletonPart *m_part = nullptr;
|
||||
QColor m_color;
|
||||
QColor lastColor();
|
||||
void preparePartIds();
|
||||
|
|
|
@ -29,7 +29,7 @@ QImage *buildCutFaceTemplatePreviewImage(const std::vector<dust3d::Vector2> &cut
|
|||
|
||||
const float scale = 0.7f;
|
||||
QPolygon polygon;
|
||||
for (int i = 0; i <= cutTemplate.size(); ++i) {
|
||||
for (size_t i = 0; i <= cutTemplate.size(); ++i) {
|
||||
const auto &it = cutTemplate[i % cutTemplate.size()];
|
||||
polygon.append(QPoint((it.x() * scale + 1.0) * 0.5 * Theme::partPreviewImageSize,
|
||||
(it.y() * scale + 1.0) * 0.5 * Theme::partPreviewImageSize));
|
||||
|
|
|
@ -22,7 +22,7 @@ PartManageWidget::PartManageWidget(Document *document, QWidget *parent):
|
|||
|
||||
auto createButton = [](QChar icon, const QString &title) {
|
||||
QPushButton *button = new QPushButton(icon);
|
||||
button->setFixedSize(Theme::toolIconSize, Theme::toolIconSize);
|
||||
Theme::initIconButton(button);
|
||||
button->setToolTip(title);
|
||||
return button;
|
||||
};
|
||||
|
|
|
@ -158,3 +158,8 @@ void Theme::initCheckbox(QCheckBox *checkbox)
|
|||
palette.setColor(QPalette::Background, Theme::white);
|
||||
checkbox->setPalette(palette);
|
||||
}
|
||||
|
||||
void Theme::initIconButton(QPushButton *button)
|
||||
{
|
||||
button->setFixedSize(Theme::toolIconSize, Theme::toolIconSize);
|
||||
}
|
||||
|
|
|
@ -43,6 +43,7 @@ public:
|
|||
static void initAwsome();
|
||||
static void initToolButton(QPushButton *button);
|
||||
static void initCheckbox(QCheckBox *checkbox);
|
||||
static void initIconButton(QPushButton *button);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -659,6 +659,10 @@ std::unique_ptr<MeshCombiner::Mesh> MeshGenerator::combinePartMesh(const std::st
|
|||
return nullptr;
|
||||
|
||||
TubeMeshBuilder::BuildParameters buildParameters;
|
||||
buildParameters.deformThickness = deformThickness;
|
||||
buildParameters.deformWidth = deformWidth;
|
||||
buildParameters.deformUnified = deformUnified;
|
||||
buildParameters.baseNormalRotation = cutRotation * Math::Pi;
|
||||
buildParameters.cutFace = cutTemplate;
|
||||
auto tubeMeshBuilder = std::make_unique<TubeMeshBuilder>(buildParameters, std::move(meshNodes), isCircle);
|
||||
tubeMeshBuilder->build();
|
||||
|
|
|
@ -94,8 +94,8 @@ std::vector<Vector3> TubeMeshBuilder::buildCutFaceVertices(const Vector3 &origin
|
|||
const Vector3 &forwardDirection)
|
||||
{
|
||||
std::vector<Vector3> cutFaceVertices(m_buildParameters.cutFace.size());
|
||||
Vector3 u = m_generatedBaseNormal;
|
||||
Vector3 v = Vector3::crossProduct(forwardDirection, m_generatedBaseNormal).normalized();
|
||||
Vector3 u = m_generatedBaseNormal.rotated(-forwardDirection, m_buildParameters.baseNormalRotation);
|
||||
Vector3 v = Vector3::crossProduct(forwardDirection, u).normalized();
|
||||
auto uFactor = u * radius;
|
||||
auto vFactor = v * radius;
|
||||
for (size_t i = 0; i < m_buildParameters.cutFace.size(); ++i) {
|
||||
|
|
|
@ -37,7 +37,10 @@ public:
|
|||
struct BuildParameters
|
||||
{
|
||||
std::vector<Vector2> cutFace;
|
||||
double baseNormalRotation;
|
||||
double deformThickness = 1.0;
|
||||
double deformWidth = 1.0;
|
||||
bool deformUnified = false;
|
||||
double baseNormalRotation = 0.0;
|
||||
};
|
||||
|
||||
TubeMeshBuilder(const BuildParameters &buildParameters, std::vector<MeshNode> &&nodes, bool isCircle);
|
||||
|
|
Loading…
Reference in New Issue