Add part countershading setting
Countershaded parts will be belly white colored.master
parent
d5d46b8337
commit
5c34ae61ce
|
@ -606,16 +606,16 @@ Tips:
|
|||
<translation>曲线</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Accelerating:</source>
|
||||
<translation>加速:</translation>
|
||||
<source>Accelerating</source>
|
||||
<translation>加速</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Bouncing:</source>
|
||||
<translation>回弹:</translation>
|
||||
<source>Decelerating</source>
|
||||
<translation>减速</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Decelerating:</source>
|
||||
<translation>减速:</translation>
|
||||
<source>Bouncing</source>
|
||||
<translation>回弹</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
|
@ -807,6 +807,10 @@ Tips:
|
|||
<source>Transparency</source>
|
||||
<translation>透明度</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Countershaded</source>
|
||||
<translation>肚白效果</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>PoseEditWidget</name>
|
||||
|
|
|
@ -1081,6 +1081,8 @@ void Document::toSnapshot(Snapshot *snapshot, const std::set<QUuid> &limitNodeId
|
|||
part["name"] = partIt.second.name;
|
||||
if (partIt.second.materialAdjusted())
|
||||
part["materialId"] = partIt.second.materialId.toString();
|
||||
if (partIt.second.countershaded)
|
||||
part["countershaded"] = "true";
|
||||
snapshot->parts[part["id"]] = part;
|
||||
}
|
||||
for (const auto &nodeIt: nodeMap) {
|
||||
|
@ -1386,6 +1388,7 @@ void Document::addFromSnapshot(const Snapshot &snapshot, bool fromPaste)
|
|||
const auto &materialIdIt = partKv.second.find("materialId");
|
||||
if (materialIdIt != partKv.second.end())
|
||||
part.materialId = oldNewIdMap[QUuid(materialIdIt->second)];
|
||||
part.countershaded = isTrueValueString(valueOfKeyInMapOrEmpty(partKv.second, "countershaded"));
|
||||
newAddedPartIds.insert(part.id);
|
||||
}
|
||||
for (const auto &it: cutFaceLinkedIdModifyMap) {
|
||||
|
@ -2744,6 +2747,21 @@ void Document::setPartHollowThickness(QUuid partId, float hollowThickness)
|
|||
emit skeletonChanged();
|
||||
}
|
||||
|
||||
void Document::setPartCountershaded(QUuid partId, bool countershaded)
|
||||
{
|
||||
auto part = partMap.find(partId);
|
||||
if (part == partMap.end()) {
|
||||
qDebug() << "Part not found:" << partId;
|
||||
return;
|
||||
}
|
||||
if (part->second.countershaded == countershaded)
|
||||
return;
|
||||
part->second.countershaded = countershaded;
|
||||
part->second.dirty = true;
|
||||
emit partCountershadeStateChanged(partId);
|
||||
emit textureChanged();
|
||||
}
|
||||
|
||||
void Document::setPartCutRotation(QUuid partId, float cutRotation)
|
||||
{
|
||||
auto part = partMap.find(partId);
|
||||
|
|
|
@ -434,6 +434,7 @@ signals:
|
|||
void partTargetChanged(QUuid partId);
|
||||
void partColorSolubilityChanged(QUuid partId);
|
||||
void partHollowThicknessChanged(QUuid partId);
|
||||
void partCountershadeStateChanged(QUuid partId);
|
||||
void componentCombineModeChanged(QUuid componentId);
|
||||
void cleanup();
|
||||
void cleanupScript();
|
||||
|
@ -622,6 +623,7 @@ public slots:
|
|||
void setPartTarget(QUuid partId, PartTarget target);
|
||||
void setPartColorSolubility(QUuid partId, float solubility);
|
||||
void setPartHollowThickness(QUuid partId, float hollowThickness);
|
||||
void setPartCountershaded(QUuid partId, bool countershaded);
|
||||
void setComponentCombineMode(QUuid componentId, CombineMode combineMode);
|
||||
void moveComponentUp(QUuid componentId);
|
||||
void moveComponentDown(QUuid componentId);
|
||||
|
|
|
@ -1018,6 +1018,7 @@ DocumentWindow::DocumentWindow() :
|
|||
connect(m_document, &Document::partHollowThicknessChanged, partTreeWidget, &PartTreeWidget::partHollowThicknessChanged);
|
||||
connect(m_document, &Document::partMaterialIdChanged, partTreeWidget, &PartTreeWidget::partMaterialIdChanged);
|
||||
connect(m_document, &Document::partColorSolubilityChanged, partTreeWidget, &PartTreeWidget::partColorSolubilityChanged);
|
||||
connect(m_document, &Document::partCountershadeStateChanged, partTreeWidget, &PartTreeWidget::partCountershadeStateChanged);
|
||||
connect(m_document, &Document::partRemoved, partTreeWidget, &PartTreeWidget::partRemoved);
|
||||
connect(m_document, &Document::cleanup, partTreeWidget, &PartTreeWidget::removeAllContent);
|
||||
connect(m_document, &Document::partChecked, partTreeWidget, &PartTreeWidget::partChecked);
|
||||
|
|
|
@ -40,7 +40,7 @@ int main(int argc, char ** argv)
|
|||
darkPalette.setColor(QPalette::BrightText, Theme::red);
|
||||
darkPalette.setColor(QPalette::Link, QColor(42, 130, 218));
|
||||
darkPalette.setColor(QPalette::Highlight, Theme::red);
|
||||
darkPalette.setColor(QPalette::HighlightedText, Theme::black);
|
||||
darkPalette.setColor(QPalette::HighlightedText, Theme::black);
|
||||
qApp->setPalette(darkPalette);
|
||||
//qApp->setStyleSheet("QToolTip { color: #ffffff; background-color: #fc6621; border: 1px solid white; }");
|
||||
|
||||
|
|
|
@ -587,6 +587,7 @@ nodemesh::Combiner::Mesh *MeshGenerator::combinePartMesh(const QString &partIdSt
|
|||
const auto &originNodeIdString = nodeIndexToIdStringMap[node.originNodeIndex];
|
||||
|
||||
OutcomePaintNode paintNode;
|
||||
paintNode.originNodeIndex = node.originNodeIndex;
|
||||
paintNode.originNodeId = QUuid(originNodeIdString);
|
||||
paintNode.radius = node.radius;
|
||||
paintNode.origin = node.position;
|
||||
|
@ -615,6 +616,8 @@ nodemesh::Combiner::Mesh *MeshGenerator::combinePartMesh(const QString &partIdSt
|
|||
paintNode.baseNormal = builder->nodeBaseNormal(i);
|
||||
paintNode.direction = builder->nodeTraverseDirection(i);
|
||||
paintNode.order = builder->nodeTraverseOrder(i);
|
||||
|
||||
partCache.outcomeNodes[paintNode.originNodeIndex].direction = paintNode.direction;
|
||||
}
|
||||
|
||||
bool hasMeshError = false;
|
||||
|
|
|
@ -193,9 +193,20 @@ void MotionTimelineWidget::showInterpolationSettingPopup(int clipIndex, const QP
|
|||
QWidget *cubicWidget = new QWidget;
|
||||
|
||||
QCheckBox *hasAcceleratingBox = new QCheckBox();
|
||||
hasAcceleratingBox->setText(tr("Accelerating"));
|
||||
Theme::initCheckbox(hasAcceleratingBox);
|
||||
|
||||
QCheckBox *hasDeceleratingBox = new QCheckBox();
|
||||
hasDeceleratingBox->setText(tr("Decelerating"));
|
||||
Theme::initCheckbox(hasDeceleratingBox);
|
||||
|
||||
QCheckBox *bouncingBeginBox = new QCheckBox();
|
||||
bouncingBeginBox->setText(tr("Bouncing"));
|
||||
Theme::initCheckbox(bouncingBeginBox);
|
||||
|
||||
QCheckBox *bouncingEndBox = new QCheckBox();
|
||||
bouncingEndBox->setText(tr("Bouncing"));
|
||||
Theme::initCheckbox(bouncingEndBox);
|
||||
|
||||
QStackedWidget *stackedWidget = new QStackedWidget;
|
||||
stackedWidget->addWidget(linearWidget);
|
||||
|
@ -271,29 +282,13 @@ void MotionTimelineWidget::showInterpolationSettingPopup(int clipIndex, const QP
|
|||
QVBoxLayout *cubicLayout = new QVBoxLayout;
|
||||
|
||||
QHBoxLayout *acceleratingLayout = new QHBoxLayout;
|
||||
{
|
||||
QFormLayout *formLayout = new QFormLayout;
|
||||
formLayout->addRow(tr("Accelerating:"), hasAcceleratingBox);
|
||||
acceleratingLayout->addLayout(formLayout);
|
||||
}
|
||||
{
|
||||
QFormLayout *formLayout = new QFormLayout;
|
||||
formLayout->addRow(tr("Bouncing:"), bouncingBeginBox);
|
||||
acceleratingLayout->addLayout(formLayout);
|
||||
}
|
||||
acceleratingLayout->addWidget(hasAcceleratingBox);
|
||||
acceleratingLayout->addWidget(bouncingBeginBox);
|
||||
cubicLayout->addLayout(acceleratingLayout);
|
||||
|
||||
QHBoxLayout *deceleratingLayout = new QHBoxLayout;
|
||||
{
|
||||
QFormLayout *formLayout = new QFormLayout;
|
||||
formLayout->addRow(tr("Decelerating:"), hasDeceleratingBox);
|
||||
deceleratingLayout->addLayout(formLayout);
|
||||
}
|
||||
{
|
||||
QFormLayout *formLayout = new QFormLayout;
|
||||
formLayout->addRow(tr("Bouncing:"), bouncingEndBox);
|
||||
deceleratingLayout->addLayout(formLayout);
|
||||
}
|
||||
deceleratingLayout->addWidget(hasDeceleratingBox);
|
||||
deceleratingLayout->addWidget(bouncingEndBox);
|
||||
cubicLayout->addLayout(deceleratingLayout);
|
||||
|
||||
cubicWidget->setLayout(cubicLayout);
|
||||
|
|
|
@ -23,10 +23,12 @@ struct OutcomeNode
|
|||
QUuid mirrorFromPartId;
|
||||
QUuid mirroredByPartId;
|
||||
BoneMark boneMark;
|
||||
QVector3D direction;
|
||||
};
|
||||
|
||||
struct OutcomePaintNode
|
||||
{
|
||||
int originNodeIndex;
|
||||
QUuid originNodeId;
|
||||
QVector3D origin;
|
||||
float radius = 0;
|
||||
|
|
|
@ -1046,6 +1046,17 @@ void PartTreeWidget::partColorSolubilityChanged(QUuid partId)
|
|||
widget->updateColorButton();
|
||||
}
|
||||
|
||||
void PartTreeWidget::partCountershadeStateChanged(QUuid partId)
|
||||
{
|
||||
auto item = m_partItemMap.find(partId);
|
||||
if (item == m_partItemMap.end()) {
|
||||
qDebug() << "Part item not found:" << partId;
|
||||
return;
|
||||
}
|
||||
PartWidget *widget = (PartWidget *)itemWidget(item->second, 0);
|
||||
widget->updateColorButton();
|
||||
}
|
||||
|
||||
void PartTreeWidget::partChecked(QUuid partId)
|
||||
{
|
||||
auto item = m_partItemMap.find(partId);
|
||||
|
|
|
@ -71,6 +71,7 @@ public slots:
|
|||
void partHollowThicknessChanged(QUuid partId);
|
||||
void partMaterialIdChanged(QUuid partId);
|
||||
void partColorSolubilityChanged(QUuid partId);
|
||||
void partCountershadeStateChanged(QUuid partId);
|
||||
void partChecked(QUuid partId);
|
||||
void partUnchecked(QUuid partId);
|
||||
void partComponentChecked(QUuid partId);
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <QSizePolicy>
|
||||
#include <QFileDialog>
|
||||
#include <QSizePolicy>
|
||||
#include <QCheckBox>
|
||||
#include <nodemesh/misc.h>
|
||||
#include "partwidget.h"
|
||||
#include "theme.h"
|
||||
|
@ -172,6 +173,7 @@ PartWidget::PartWidget(const Document *document, QUuid partId) :
|
|||
connect(this, &PartWidget::setPartMaterialId, m_document, &Document::setPartMaterialId);
|
||||
connect(this, &PartWidget::setPartColorSolubility, m_document, &Document::setPartColorSolubility);
|
||||
connect(this, &PartWidget::setPartHollowThickness, m_document, &Document::setPartHollowThickness);
|
||||
connect(this, &PartWidget::setPartCountershaded, m_document, &Document::setPartCountershaded);
|
||||
connect(this, &PartWidget::checkPart, m_document, &Document::checkPart);
|
||||
connect(this, &PartWidget::enableBackgroundBlur, m_document, &Document::enableBackgroundBlur);
|
||||
connect(this, &PartWidget::disableBackgroundBlur, m_document, &Document::disableBackgroundBlur);
|
||||
|
@ -361,10 +363,21 @@ void PartWidget::showColorSettingPopup(const QPoint &pos)
|
|||
palette.setColor(QPalette::Button, choosenColor);
|
||||
pickButton->setPalette(palette);
|
||||
|
||||
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();
|
||||
});
|
||||
|
||||
QHBoxLayout *colorLayout = new QHBoxLayout;
|
||||
colorLayout->addWidget(colorEraser);
|
||||
colorLayout->addWidget(pickButton);
|
||||
colorLayout->addStretch();
|
||||
colorLayout->addWidget(countershadeStateBox);
|
||||
|
||||
connect(colorEraser, &QPushButton::clicked, [=]() {
|
||||
emit setPartColorState(m_partId, false, Qt::white);
|
||||
|
@ -894,7 +907,7 @@ void PartWidget::updateColorButton()
|
|||
qDebug() << "Part not found:" << m_partId;
|
||||
return;
|
||||
}
|
||||
if (part->hasColor || part->materialAdjusted() || part->colorSolubilityAdjusted())
|
||||
if (part->hasColor || part->materialAdjusted() || part->colorSolubilityAdjusted() || part->countershaded)
|
||||
updateButton(m_colorButton, QChar(fa::eyedropper), true);
|
||||
else
|
||||
updateButton(m_colorButton, QChar(fa::eyedropper), false);
|
||||
|
|
|
@ -29,6 +29,7 @@ signals:
|
|||
void setPartMaterialId(QUuid partId, QUuid materialId);
|
||||
void setPartColorSolubility(QUuid partId, float colorSolubility);
|
||||
void setPartHollowThickness(QUuid partId, float hollowThickness);
|
||||
void setPartCountershaded(QUuid partId, bool countershaded);
|
||||
void movePartUp(QUuid partId);
|
||||
void movePartDown(QUuid partId);
|
||||
void movePartToTop(QUuid partId);
|
||||
|
|
|
@ -58,11 +58,13 @@ PreferencesWidget::PreferencesWidget(const Document *document, QWidget *parent)
|
|||
});
|
||||
|
||||
QCheckBox *flatShadingBox = new QCheckBox();
|
||||
Theme::initCheckbox(flatShadingBox);
|
||||
connect(flatShadingBox, &QCheckBox::stateChanged, this, [=]() {
|
||||
Preferences::instance().setFlatShading(flatShadingBox->isChecked());
|
||||
});
|
||||
|
||||
QCheckBox *threeNodesBranchEnabledBox = new QCheckBox();
|
||||
Theme::initCheckbox(threeNodesBranchEnabledBox);
|
||||
connect(threeNodesBranchEnabledBox, &QCheckBox::stateChanged, this, [=]() {
|
||||
Preferences::instance().setThreeNodesBranchEnableState(threeNodesBranchEnabledBox->isChecked());
|
||||
});
|
||||
|
|
|
@ -87,6 +87,7 @@ void ScriptVariablesWidget::reload()
|
|||
auto defaultValue = isTrueValueString(valueOfKeyInMapOrEmpty(variable.second, "defaultValue"));
|
||||
|
||||
QCheckBox *checkBox = new QCheckBox;
|
||||
Theme::initCheckbox(checkBox);
|
||||
checkBox->setText(name);
|
||||
checkBox->setChecked(value);
|
||||
|
||||
|
|
|
@ -178,6 +178,7 @@ public:
|
|||
float deformMapScale;
|
||||
QUuid deformMapImageId;
|
||||
float hollowThickness;
|
||||
bool countershaded;
|
||||
SkeletonPart(const QUuid &withId=QUuid()) :
|
||||
visible(true),
|
||||
locked(false),
|
||||
|
@ -198,7 +199,8 @@ public:
|
|||
target(PartTarget::Model),
|
||||
colorSolubility(0.0),
|
||||
deformMapScale(1.0),
|
||||
hollowThickness(0.0)
|
||||
hollowThickness(0.0),
|
||||
countershaded(false)
|
||||
{
|
||||
id = withId.isNull() ? QUuid::createUuid() : withId;
|
||||
}
|
||||
|
@ -311,6 +313,7 @@ public:
|
|||
materialId = other.materialId;
|
||||
target = other.target;
|
||||
colorSolubility = other.colorSolubility;
|
||||
countershaded = other.countershaded;
|
||||
}
|
||||
void updatePreviewMesh(MeshLoader *previewMesh)
|
||||
{
|
||||
|
|
|
@ -171,6 +171,8 @@ void TextureGenerator::prepare()
|
|||
materialId = QUuid(materialIdIt->second);
|
||||
QUuid partId = QUuid(partIt.first);
|
||||
updatedMaterialIdMap.insert({partId, materialId});
|
||||
if (isTrueValueString(valueOfKeyInMapOrEmpty(partIt.second, "countershaded")))
|
||||
m_countershadedPartIds.insert(partId);
|
||||
}
|
||||
for (const auto &bmeshNode: m_outcome->nodes) {
|
||||
for (size_t i = 0; i < (int)TextureType::Count - 1; ++i) {
|
||||
|
@ -221,6 +223,7 @@ void TextureGenerator::generate()
|
|||
const auto &triangleVertexUvs = *m_outcome->triangleVertexUvs();
|
||||
const auto &triangleSourceNodes = *m_outcome->triangleSourceNodes();
|
||||
const auto &partUvRects = *m_outcome->partUvRects();
|
||||
const auto &triangleNormals = m_outcome->triangleNormals;
|
||||
|
||||
std::map<QUuid, QColor> partColorMap;
|
||||
std::map<std::pair<QUuid, QUuid>, const OutcomeNode *> nodeMap;
|
||||
|
@ -382,7 +385,7 @@ void TextureGenerator::generate()
|
|||
drawTexture(partRoughnessTexturePixmaps, textureRoughnessPainter, false);
|
||||
drawTexture(partAmbientOcclusionTexturePixmaps, textureAmbientOcclusionPainter, false);
|
||||
|
||||
auto drawGradient = [&](const QUuid &partId, size_t triangleIndex, size_t firstVertexIndex, size_t secondVertexIndex,
|
||||
auto drawBySolubility = [&](const QUuid &partId, size_t triangleIndex, size_t firstVertexIndex, size_t secondVertexIndex,
|
||||
const QUuid &neighborPartId) {
|
||||
const std::vector<QVector2D> &uv = triangleVertexUvs[triangleIndex];
|
||||
const auto &allRects = partUvRects.find(partId);
|
||||
|
@ -495,8 +498,110 @@ void TextureGenerator::generate()
|
|||
const std::pair<QUuid, QUuid> &oppositeSource = triangleSourceNodes[std::get<0>(opposite->second)];
|
||||
if (source.first == oppositeSource.first)
|
||||
continue;
|
||||
drawGradient(source.first, std::get<0>(it.second), std::get<1>(it.second), std::get<2>(it.second), oppositeSource.first);
|
||||
drawGradient(oppositeSource.first, std::get<0>(opposite->second), std::get<1>(opposite->second), std::get<2>(opposite->second), source.first);
|
||||
drawBySolubility(source.first, std::get<0>(it.second), std::get<1>(it.second), std::get<2>(it.second), oppositeSource.first);
|
||||
drawBySolubility(oppositeSource.first, std::get<0>(opposite->second), std::get<1>(opposite->second), std::get<2>(opposite->second), source.first);
|
||||
}
|
||||
|
||||
// Draw belly white
|
||||
texturePainter.setCompositionMode(QPainter::CompositionMode_SoftLight);
|
||||
for (size_t triangleIndex = 0; triangleIndex < m_outcome->triangles.size(); ++triangleIndex) {
|
||||
const auto &normal = triangleNormals[triangleIndex];
|
||||
const std::pair<QUuid, QUuid> &source = triangleSourceNodes[triangleIndex];
|
||||
const auto &partId = source.first;
|
||||
if (m_countershadedPartIds.find(partId) == m_countershadedPartIds.end())
|
||||
continue;
|
||||
|
||||
const auto &allRects = partUvRects.find(partId);
|
||||
if (allRects == partUvRects.end()) {
|
||||
qDebug() << "Found part uv rects failed";
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto &findOutcomeNode = nodeMap.find(source);
|
||||
if (findOutcomeNode == nodeMap.end())
|
||||
continue;
|
||||
const OutcomeNode *outcomeNode = findOutcomeNode->second;
|
||||
if (qAbs(QVector3D::dotProduct(outcomeNode->direction, QVector3D(0, 1, 0))) >= 0.707) {
|
||||
if (QVector3D::dotProduct(normal, QVector3D(0, 0, 1)) <= 0.0)
|
||||
continue;
|
||||
} else {
|
||||
if (QVector3D::dotProduct(normal, QVector3D(0, -1, 0)) <= 0.0)
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto &triangleIndices = m_outcome->triangles[triangleIndex];
|
||||
if (triangleIndices.size() != 3) {
|
||||
qDebug() << "Found invalid triangle indices";
|
||||
continue;
|
||||
}
|
||||
|
||||
const std::vector<QVector2D> &uv = triangleVertexUvs[triangleIndex];
|
||||
QVector2D middlePoint = (uv[0] + uv[1] + uv[2]) / 3.0;
|
||||
float finalRadius = (uv[0].distanceToPoint(uv[1]) +
|
||||
uv[1].distanceToPoint(uv[2]) +
|
||||
uv[2].distanceToPoint(uv[0])) / 3.0;
|
||||
QRadialGradient gradient(QPointF(middlePoint.x() * TextureGenerator::m_textureSize,
|
||||
middlePoint.y() * TextureGenerator::m_textureSize),
|
||||
finalRadius * TextureGenerator::m_textureSize);
|
||||
gradient.setColorAt(0.0, Qt::white);
|
||||
gradient.setColorAt(1.0, Qt::transparent);
|
||||
for (const auto &it: allRects->second) {
|
||||
if (it.contains(middlePoint.x(), middlePoint.y())) {
|
||||
QRectF fillTarget((middlePoint.x() - finalRadius),
|
||||
(middlePoint.y() - finalRadius),
|
||||
(finalRadius + finalRadius),
|
||||
(finalRadius + finalRadius));
|
||||
auto clippedRect = it.intersected(fillTarget);
|
||||
QRectF translatedRect = {
|
||||
clippedRect.left() * TextureGenerator::m_textureSize,
|
||||
clippedRect.top() * TextureGenerator::m_textureSize,
|
||||
clippedRect.width() * TextureGenerator::m_textureSize,
|
||||
clippedRect.height() * TextureGenerator::m_textureSize
|
||||
};
|
||||
texturePainter.fillRect(translatedRect, gradient);
|
||||
}
|
||||
}
|
||||
|
||||
// Fill the neighbor halfedges
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
int j = (i + 1) % 3;
|
||||
auto oppositeHalfEdge = std::make_pair(triangleIndices[j], triangleIndices[i]);
|
||||
const auto &opposite = halfEdgeToTriangleMap.find(oppositeHalfEdge);
|
||||
if (opposite == halfEdgeToTriangleMap.end())
|
||||
continue;
|
||||
auto oppositeTriangleIndex = std::get<0>(opposite->second);
|
||||
const std::pair<QUuid, QUuid> &oppositeSource = triangleSourceNodes[oppositeTriangleIndex];
|
||||
if (partId == oppositeSource.first)
|
||||
continue;
|
||||
const auto &oppositeAllRects = partUvRects.find(oppositeSource.first);
|
||||
if (oppositeAllRects == partUvRects.end()) {
|
||||
qDebug() << "Found part uv rects failed";
|
||||
continue;
|
||||
}
|
||||
const std::vector<QVector2D> &oppositeUv = triangleVertexUvs[oppositeTriangleIndex];
|
||||
QVector2D oppositeMiddlePoint = (oppositeUv[std::get<1>(opposite->second)] + oppositeUv[std::get<2>(opposite->second)]) * 0.5;
|
||||
QRadialGradient oppositeGradient(QPointF(oppositeMiddlePoint.x() * TextureGenerator::m_textureSize,
|
||||
oppositeMiddlePoint.y() * TextureGenerator::m_textureSize),
|
||||
finalRadius * TextureGenerator::m_textureSize);
|
||||
oppositeGradient.setColorAt(0.0, Qt::white);
|
||||
oppositeGradient.setColorAt(1.0, Qt::transparent);
|
||||
for (const auto &it: oppositeAllRects->second) {
|
||||
if (it.contains(oppositeMiddlePoint.x(), oppositeMiddlePoint.y())) {
|
||||
QRectF fillTarget((oppositeMiddlePoint.x() - finalRadius),
|
||||
(oppositeMiddlePoint.y() - finalRadius),
|
||||
(finalRadius + finalRadius),
|
||||
(finalRadius + finalRadius));
|
||||
auto clippedRect = it.intersected(fillTarget);
|
||||
QRectF translatedRect = {
|
||||
clippedRect.left() * TextureGenerator::m_textureSize,
|
||||
clippedRect.top() * TextureGenerator::m_textureSize,
|
||||
clippedRect.width() * TextureGenerator::m_textureSize,
|
||||
clippedRect.height() * TextureGenerator::m_textureSize
|
||||
};
|
||||
texturePainter.fillRect(translatedRect, oppositeGradient);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hasNormalMap = !m_partNormalTextureMap.empty();
|
||||
|
|
|
@ -58,6 +58,7 @@ private:
|
|||
std::map<QUuid, std::pair<QImage, float>> m_partMetalnessTextureMap;
|
||||
std::map<QUuid, std::pair<QImage, float>> m_partRoughnessTextureMap;
|
||||
std::map<QUuid, std::pair<QImage, float>> m_partAmbientOcclusionTextureMap;
|
||||
std::set<QUuid> m_countershadedPartIds;
|
||||
Snapshot *m_snapshot;
|
||||
};
|
||||
|
||||
|
|
|
@ -177,6 +177,13 @@ void Theme::initToolButton(QPushButton *button)
|
|||
button->setFocusPolicy(Qt::NoFocus);
|
||||
}
|
||||
|
||||
void Theme::initCheckbox(QCheckBox *checkbox)
|
||||
{
|
||||
QPalette palette = checkbox->palette();
|
||||
palette.setColor(QPalette::Background, Theme::white);
|
||||
checkbox->setPalette(palette);
|
||||
}
|
||||
|
||||
QWidget *Theme::createHorizontalLineWidget()
|
||||
{
|
||||
QWidget *hrLightWidget = new QWidget;
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <map>
|
||||
#include <QPushButton>
|
||||
#include <QLabel>
|
||||
#include <QCheckBox>
|
||||
#include "QtAwesome.h"
|
||||
|
||||
class Theme
|
||||
|
@ -53,6 +54,7 @@ public:
|
|||
static void initAwesomeToolButtonWithoutFont(QPushButton *button);
|
||||
static void initAwsomeBaseSizes();
|
||||
static void initToolButton(QPushButton *button);
|
||||
static void initCheckbox(QCheckBox *checkbox);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue