Add tile scale setting for texture generator
parent
9a587fc895
commit
0abaa707f5
|
@ -791,6 +791,10 @@ Tips:
|
|||
<source>Transparency</source>
|
||||
<translation>透明度</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Tile Scale</source>
|
||||
<translation>平铺缩放</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>PoseEditWidget</name>
|
||||
|
|
Binary file not shown.
|
@ -1192,6 +1192,8 @@ void Document::toSnapshot(Snapshot *snapshot, const std::set<QUuid> &limitNodeId
|
|||
maps.push_back(textureMap);
|
||||
}
|
||||
std::map<QString, QString> layerAttributes;
|
||||
if (!qFuzzyCompare((float)layer.tileScale, (float)1.0))
|
||||
layerAttributes["tileScale"] = QString::number(layer.tileScale);
|
||||
layers.push_back({layerAttributes, maps});
|
||||
}
|
||||
snapshot->materials.push_back(std::make_pair(material, layers));
|
||||
|
@ -1300,6 +1302,9 @@ void Document::addFromSnapshot(const Snapshot &snapshot, bool fromPaste)
|
|||
oldNewIdMap[QUuid(valueOfKeyInMapOrEmpty(materialAttributes, "id"))] = newMaterialId;
|
||||
for (const auto &layerIt: materialIt.second) {
|
||||
MaterialLayer layer;
|
||||
auto findTileScale = layerIt.first.find("tileScale");
|
||||
if (findTileScale != layerIt.first.end())
|
||||
layer.tileScale = findTileScale->second.toFloat();
|
||||
for (const auto &mapItem: layerIt.second) {
|
||||
auto textureTypeString = valueOfKeyInMapOrEmpty(mapItem, "for");
|
||||
auto textureType = TextureTypeFromString(textureTypeString.toUtf8().constData());
|
||||
|
|
|
@ -336,6 +336,7 @@ class MaterialLayer
|
|||
{
|
||||
public:
|
||||
std::vector<MaterialMap> maps;
|
||||
float tileScale = 1.0;
|
||||
};
|
||||
|
||||
class Material
|
||||
|
|
|
@ -2,7 +2,10 @@
|
|||
#include "imageforever.h"
|
||||
#include "util.h"
|
||||
|
||||
void initializeMaterialTexturesFromSnapshot(const Snapshot &snapshot, const QUuid &materialId, MaterialTextures &materialTextures)
|
||||
void initializeMaterialTexturesFromSnapshot(const Snapshot &snapshot,
|
||||
const QUuid &materialId,
|
||||
MaterialTextures &materialTextures,
|
||||
float &tileScale)
|
||||
{
|
||||
QString materialIdString = materialId.toString();
|
||||
for (const auto &materialItem: snapshot.materials) {
|
||||
|
@ -10,6 +13,9 @@ void initializeMaterialTexturesFromSnapshot(const Snapshot &snapshot, const QUui
|
|||
continue;
|
||||
for (const auto &layer: materialItem.second) {
|
||||
//FIXME: Only support one layer currently
|
||||
auto findTileScale = layer.first.find("tileScale");
|
||||
if (findTileScale != layer.first.end())
|
||||
tileScale = findTileScale->second.toFloat();
|
||||
for (const auto &mapItem: layer.second) {
|
||||
auto textureType = TextureTypeFromString(valueOfKeyInMapOrEmpty(mapItem, "for").toUtf8().constData());
|
||||
if (textureType != TextureType::None) {
|
||||
|
|
|
@ -10,6 +10,9 @@ struct MaterialTextures
|
|||
const QImage *textureImages[(int)TextureType::Count - 1] = {nullptr};
|
||||
};
|
||||
|
||||
void initializeMaterialTexturesFromSnapshot(const Snapshot &snapshot, const QUuid &materialId, MaterialTextures &materialTextures);
|
||||
void initializeMaterialTexturesFromSnapshot(const Snapshot &snapshot,
|
||||
const QUuid &materialId,
|
||||
MaterialTextures &materialTextures,
|
||||
float &tileScale);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -122,6 +122,30 @@ MaterialEditWidget::MaterialEditWidget(const Document *document, QWidget *parent
|
|||
connect(saveButton, &QPushButton::clicked, this, &MaterialEditWidget::save);
|
||||
saveButton->setDefault(true);
|
||||
|
||||
FloatNumberWidget *tileScaleWidget = new FloatNumberWidget;
|
||||
tileScaleWidget->setItemName(tr("Tile Scale"));
|
||||
tileScaleWidget->setRange(0.01, 1.0);
|
||||
tileScaleWidget->setValue(m_layers[0].tileScale);
|
||||
|
||||
m_tileScaleSlider = tileScaleWidget;
|
||||
|
||||
connect(tileScaleWidget, &FloatNumberWidget::valueChanged, [=](float value) {
|
||||
m_layers[0].tileScale = value;
|
||||
emit layersAdjusted();
|
||||
});
|
||||
|
||||
QPushButton *tileScaleEraser = new QPushButton(QChar(fa::eraser));
|
||||
Theme::initAwesomeToolButton(tileScaleEraser);
|
||||
|
||||
connect(tileScaleEraser, &QPushButton::clicked, [=]() {
|
||||
tileScaleWidget->setValue(1.0);
|
||||
});
|
||||
|
||||
QHBoxLayout *tileScaleLayout = new QHBoxLayout;
|
||||
tileScaleLayout->addWidget(tileScaleEraser);
|
||||
tileScaleLayout->addWidget(tileScaleWidget);
|
||||
tileScaleLayout->addStretch();
|
||||
|
||||
QHBoxLayout *baseInfoLayout = new QHBoxLayout;
|
||||
baseInfoLayout->addWidget(new QLabel(tr("Name")));
|
||||
baseInfoLayout->addWidget(m_nameEdit);
|
||||
|
@ -132,6 +156,7 @@ MaterialEditWidget::MaterialEditWidget(const Document *document, QWidget *parent
|
|||
mainLayout->addLayout(paramtersLayout);
|
||||
mainLayout->addStretch();
|
||||
mainLayout->addWidget(Theme::createHorizontalLineWidget());
|
||||
mainLayout->addLayout(tileScaleLayout);
|
||||
mainLayout->addLayout(baseInfoLayout);
|
||||
|
||||
setLayout(mainLayout);
|
||||
|
@ -273,6 +298,7 @@ void MaterialEditWidget::setEditMaterialLayers(std::vector<MaterialLayer> layers
|
|||
}
|
||||
if (!layers.empty()) {
|
||||
for (const auto &layer: layers) {
|
||||
m_layers[0].tileScale = layer.tileScale;
|
||||
for (const auto &mapItem: layer.maps) {
|
||||
int index = (int)mapItem.forWhat - 1;
|
||||
if (index >= 0 && index < (int)TextureType::Count - 1) {
|
||||
|
@ -280,6 +306,7 @@ void MaterialEditWidget::setEditMaterialLayers(std::vector<MaterialLayer> layers
|
|||
}
|
||||
}
|
||||
}
|
||||
m_tileScaleSlider->setValue(m_layers[0].tileScale);
|
||||
}
|
||||
for (int i = 1; i < (int)TextureType::Count; i++) {
|
||||
updateMapButtonBackground(m_textureMapButtons[i - 1], ImageForever::get(m_layers[0].maps[i - 1].imageId));
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "modelwidget.h"
|
||||
#include "materialpreviewsgenerator.h"
|
||||
#include "imagepreviewwidget.h"
|
||||
#include "floatnumberwidget.h"
|
||||
|
||||
enum class PopupWidgetType
|
||||
{
|
||||
|
@ -47,6 +48,7 @@ private:
|
|||
const Document *m_document = nullptr;
|
||||
MaterialPreviewsGenerator *m_materialPreviewsGenerator = nullptr;
|
||||
ModelWidget *m_previewWidget = nullptr;
|
||||
FloatNumberWidget *m_tileScaleSlider = nullptr;
|
||||
bool m_isPreviewDirty = false;
|
||||
bool m_closed = false;
|
||||
QUuid m_materialId;
|
||||
|
|
|
@ -82,15 +82,15 @@ void MaterialPreviewsGenerator::generate()
|
|||
continue;
|
||||
for (const auto &partId: partIds) {
|
||||
if (TextureType::BaseColor == mapItem.forWhat)
|
||||
textureGenerator->addPartColorMap(partId, image);
|
||||
textureGenerator->addPartColorMap(partId, image, layer.tileScale);
|
||||
else if (TextureType::Normal == mapItem.forWhat)
|
||||
textureGenerator->addPartNormalMap(partId, image);
|
||||
textureGenerator->addPartNormalMap(partId, image, layer.tileScale);
|
||||
else if (TextureType::Metalness == mapItem.forWhat)
|
||||
textureGenerator->addPartMetalnessMap(partId, image);
|
||||
textureGenerator->addPartMetalnessMap(partId, image, layer.tileScale);
|
||||
else if (TextureType::Roughness == mapItem.forWhat)
|
||||
textureGenerator->addPartRoughnessMap(partId, image);
|
||||
textureGenerator->addPartRoughnessMap(partId, image, layer.tileScale);
|
||||
else if (TextureType::AmbientOcclusion == mapItem.forWhat)
|
||||
textureGenerator->addPartAmbientOcclusionMap(partId, image);
|
||||
textureGenerator->addPartAmbientOcclusionMap(partId, image, layer.tileScale);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -123,39 +123,39 @@ MeshLoader *TextureGenerator::takeResultMesh()
|
|||
return resultMesh;
|
||||
}
|
||||
|
||||
void TextureGenerator::addPartColorMap(QUuid partId, const QImage *image)
|
||||
void TextureGenerator::addPartColorMap(QUuid partId, const QImage *image, float tileScale)
|
||||
{
|
||||
if (nullptr == image)
|
||||
return;
|
||||
m_partColorTextureMap[partId] = *image;
|
||||
m_partColorTextureMap[partId] = std::make_pair(*image, tileScale);
|
||||
}
|
||||
|
||||
void TextureGenerator::addPartNormalMap(QUuid partId, const QImage *image)
|
||||
void TextureGenerator::addPartNormalMap(QUuid partId, const QImage *image, float tileScale)
|
||||
{
|
||||
if (nullptr == image)
|
||||
return;
|
||||
m_partNormalTextureMap[partId] = *image;
|
||||
m_partNormalTextureMap[partId] = std::make_pair(*image, tileScale);
|
||||
}
|
||||
|
||||
void TextureGenerator::addPartMetalnessMap(QUuid partId, const QImage *image)
|
||||
void TextureGenerator::addPartMetalnessMap(QUuid partId, const QImage *image, float tileScale)
|
||||
{
|
||||
if (nullptr == image)
|
||||
return;
|
||||
m_partMetalnessTextureMap[partId] = *image;
|
||||
m_partMetalnessTextureMap[partId] = std::make_pair(*image, tileScale);
|
||||
}
|
||||
|
||||
void TextureGenerator::addPartRoughnessMap(QUuid partId, const QImage *image)
|
||||
void TextureGenerator::addPartRoughnessMap(QUuid partId, const QImage *image, float tileScale)
|
||||
{
|
||||
if (nullptr == image)
|
||||
return;
|
||||
m_partRoughnessTextureMap[partId] = *image;
|
||||
m_partRoughnessTextureMap[partId] = std::make_pair(*image, tileScale);
|
||||
}
|
||||
|
||||
void TextureGenerator::addPartAmbientOcclusionMap(QUuid partId, const QImage *image)
|
||||
void TextureGenerator::addPartAmbientOcclusionMap(QUuid partId, const QImage *image, float tileScale)
|
||||
{
|
||||
if (nullptr == image)
|
||||
return;
|
||||
m_partAmbientOcclusionTextureMap[partId] = *image;
|
||||
m_partAmbientOcclusionTextureMap[partId] = std::make_pair(*image, tileScale);
|
||||
}
|
||||
|
||||
QPainterPath TextureGenerator::expandedPainterPath(const QPainterPath &painterPath, int expandSize)
|
||||
|
@ -188,19 +188,20 @@ void TextureGenerator::prepare()
|
|||
auto findUpdatedMaterialIdResult = updatedMaterialIdMap.find(bmeshNode.mirrorFromPartId.isNull() ? bmeshNode.partId : bmeshNode.mirrorFromPartId);
|
||||
if (findUpdatedMaterialIdResult != updatedMaterialIdMap.end())
|
||||
materialId = findUpdatedMaterialIdResult->second;
|
||||
initializeMaterialTexturesFromSnapshot(*m_snapshot, materialId, materialTextures);
|
||||
float tileScale = 1.0;
|
||||
initializeMaterialTexturesFromSnapshot(*m_snapshot, materialId, materialTextures, tileScale);
|
||||
const QImage *image = materialTextures.textureImages[i];
|
||||
if (nullptr != image) {
|
||||
if (TextureType::BaseColor == forWhat)
|
||||
addPartColorMap(bmeshNode.partId, image);
|
||||
addPartColorMap(bmeshNode.partId, image, tileScale);
|
||||
else if (TextureType::Normal == forWhat)
|
||||
addPartNormalMap(bmeshNode.partId, image);
|
||||
addPartNormalMap(bmeshNode.partId, image, tileScale);
|
||||
else if (TextureType::Metalness == forWhat)
|
||||
addPartMetalnessMap(bmeshNode.partId, image);
|
||||
addPartMetalnessMap(bmeshNode.partId, image, tileScale);
|
||||
else if (TextureType::Roughness == forWhat)
|
||||
addPartRoughnessMap(bmeshNode.partId, image);
|
||||
addPartRoughnessMap(bmeshNode.partId, image, tileScale);
|
||||
else if (TextureType::AmbientOcclusion == forWhat)
|
||||
addPartAmbientOcclusionMap(bmeshNode.partId, image);
|
||||
addPartAmbientOcclusionMap(bmeshNode.partId, image, tileScale);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -395,13 +396,18 @@ void TextureGenerator::generate()
|
|||
drawGradient(oppositeSource.first, std::get<0>(opposite->second), std::get<1>(opposite->second), std::get<2>(opposite->second), source.first);
|
||||
}
|
||||
|
||||
auto drawTexture = [&](const std::map<QUuid, QImage> &map, QPainter &painter) {
|
||||
auto drawTexture = [&](const std::map<QUuid, std::pair<QImage, float>> &map, QPainter &painter) {
|
||||
for (const auto &it: partUvRects) {
|
||||
const auto &partId = it.first;
|
||||
const auto &rects = it.second;
|
||||
auto findTextureResult = map.find(partId);
|
||||
if (findTextureResult != map.end()) {
|
||||
const auto &image = findTextureResult->second;
|
||||
float tileScale = findTextureResult->second.second;
|
||||
const auto &image = findTextureResult->second.first;
|
||||
auto newSize = image.size() * tileScale;
|
||||
QImage scaledImage = image.scaled(newSize);
|
||||
auto pixmap = QPixmap::fromImage(scaledImage);
|
||||
QPixmap rotatedPixmap;
|
||||
for (const auto &rect: rects) {
|
||||
QRectF translatedRect = {
|
||||
rect.left() * TextureGenerator::m_textureSize,
|
||||
|
@ -409,7 +415,19 @@ void TextureGenerator::generate()
|
|||
rect.width() * TextureGenerator::m_textureSize,
|
||||
rect.height() * TextureGenerator::m_textureSize
|
||||
};
|
||||
painter.drawImage(translatedRect, image, QRectF(0, 0, image.width(), image.height()));
|
||||
if (translatedRect.width() < translatedRect.height()) {
|
||||
if (rotatedPixmap.isNull()) {
|
||||
QPoint center = scaledImage.rect().center();
|
||||
QMatrix matrix;
|
||||
matrix.translate(center.x(), center.y());
|
||||
matrix.rotate(90);
|
||||
auto rotatedImage = scaledImage.transformed(matrix);
|
||||
rotatedPixmap = QPixmap::fromImage(rotatedImage);
|
||||
}
|
||||
painter.drawTiledPixmap(translatedRect, rotatedPixmap);
|
||||
} else {
|
||||
painter.drawTiledPixmap(translatedRect, pixmap);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,11 +25,11 @@ public:
|
|||
QImage *takeResultTextureAmbientOcclusionImage();
|
||||
Outcome *takeOutcome();
|
||||
MeshLoader *takeResultMesh();
|
||||
void addPartColorMap(QUuid partId, const QImage *image);
|
||||
void addPartNormalMap(QUuid partId, const QImage *image);
|
||||
void addPartMetalnessMap(QUuid partId, const QImage *image);
|
||||
void addPartRoughnessMap(QUuid partId, const QImage *image);
|
||||
void addPartAmbientOcclusionMap(QUuid partId, const QImage *image);
|
||||
void addPartColorMap(QUuid partId, const QImage *image, float tileScale);
|
||||
void addPartNormalMap(QUuid partId, const QImage *image, float tileScale);
|
||||
void addPartMetalnessMap(QUuid partId, const QImage *image, float tileScale);
|
||||
void addPartRoughnessMap(QUuid partId, const QImage *image, float tileScale);
|
||||
void addPartAmbientOcclusionMap(QUuid partId, const QImage *image, float tileScale);
|
||||
void generate();
|
||||
signals:
|
||||
void finished();
|
||||
|
@ -53,11 +53,11 @@ private:
|
|||
QImage *m_resultTextureMetalnessImage;
|
||||
QImage *m_resultTextureAmbientOcclusionImage;
|
||||
MeshLoader *m_resultMesh;
|
||||
std::map<QUuid, QImage> m_partColorTextureMap;
|
||||
std::map<QUuid, QImage> m_partNormalTextureMap;
|
||||
std::map<QUuid, QImage> m_partMetalnessTextureMap;
|
||||
std::map<QUuid, QImage> m_partRoughnessTextureMap;
|
||||
std::map<QUuid, QImage> m_partAmbientOcclusionTextureMap;
|
||||
std::map<QUuid, std::pair<QImage, float>> m_partColorTextureMap;
|
||||
std::map<QUuid, std::pair<QImage, float>> m_partNormalTextureMap;
|
||||
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;
|
||||
Snapshot *m_snapshot;
|
||||
};
|
||||
|
||||
|
|
|
@ -57,10 +57,10 @@ void Theme::initAwsomeBaseSizes()
|
|||
Theme::miniIconSize = (int)(Theme::miniIconFontSize * 1.67);
|
||||
Theme::partPreviewImageSize = (Theme::miniIconSize * 3);
|
||||
Theme::sidebarPreferredWidth = Theme::partPreviewImageSize * 3.7;
|
||||
Theme::materialPreviewImageSize = Theme::sidebarPreferredWidth * 0.4;
|
||||
Theme::cutFacePreviewImageSize = Theme::materialPreviewImageSize;
|
||||
Theme::posePreviewImageSize = Theme::materialPreviewImageSize;
|
||||
Theme::motionPreviewImageSize = Theme::materialPreviewImageSize;
|
||||
Theme::posePreviewImageSize = Theme::sidebarPreferredWidth * 0.4;
|
||||
Theme::materialPreviewImageSize = Theme::posePreviewImageSize;
|
||||
Theme::cutFacePreviewImageSize = Theme::posePreviewImageSize;
|
||||
Theme::motionPreviewImageSize = Theme::posePreviewImageSize;
|
||||
Theme::normalButtonSize = Theme::toolIconSize * 2;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue