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