Add tile scale setting for texture generator

master
Jeremy Hu 2019-11-03 09:45:20 +09:30
parent 9a587fc895
commit 0abaa707f5
12 changed files with 106 additions and 40 deletions

View File

@ -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.

View File

@ -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());

View File

@ -336,6 +336,7 @@ class MaterialLayer
{
public:
std::vector<MaterialMap> maps;
float tileScale = 1.0;
};
class Material

View File

@ -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) {

View File

@ -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

View File

@ -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));

View File

@ -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;

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}
}

View File

@ -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;
};

View File

@ -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;
}