diff --git a/TextureSheetMaker/TextureSheet.cpp b/TextureSheetMaker/TextureSheet.cpp new file mode 100644 index 0000000..466e232 --- /dev/null +++ b/TextureSheetMaker/TextureSheet.cpp @@ -0,0 +1,140 @@ +#include "TextureSheet.h" + + +bool pixmapSortFunc(const std::pair>& pixmap1, const std::pair>& pixmap2) +{ + return pixmap1.second->width() * pixmap1.second->height() > pixmap2.second->width() * pixmap2.second->height(); +} + + +bool resultTexturePositionsSortFunc(const std::pair& result1, const std::pair& result2) +{ + return result1.first < result2.first; +} + +void TextureSheet::Calculate(int width, int height) +{ + spaceAreaArr.clear(); + resultTexturePositions.clear(); + + std::sort(pixmapArray.begin(), pixmapArray.end(), &pixmapSortFunc); + + resultPixmap = boost::shared_ptr(new QPixmap(width, height)); + + QColor transparentColor(0,0,0,0); + + resultPixmap->fill(transparentColor); + + + spaceAreaArr.push_back(SpaceArea(0,0,width,height)); + + QPainter p; + + + p.begin(&(*resultPixmap)); + + for (std::vector>>::iterator pixmapItr = pixmapArray.begin(); pixmapItr != pixmapArray.end(); pixmapItr++) + { + + boost::shared_ptr selectedPixmap = pixmapItr->second; + + + + int foundIndex = -1; + + for (size_t i = 0; i < spaceAreaArr.size(); i++) + { + if (spaceAreaArr[i].Width >= selectedPixmap->width() + && spaceAreaArr[i].Height >= selectedPixmap->height() + && (foundIndex == -1 || + spaceAreaArr[i].Width*spaceAreaArr[i].Height < spaceAreaArr[foundIndex].Width*spaceAreaArr[foundIndex].Height)) + { + foundIndex = i; + } + } + + if (foundIndex != -1) + { + //split space + + SpaceArea rightSpaceArea(spaceAreaArr[foundIndex].posX + selectedPixmap->width(), + spaceAreaArr[foundIndex].posY, + spaceAreaArr[foundIndex].Width - selectedPixmap->width(), + selectedPixmap->height()); + + SpaceArea topSpaceArea(spaceAreaArr[foundIndex].posX, + spaceAreaArr[foundIndex].posY + selectedPixmap->height(), + spaceAreaArr[foundIndex].Width, + spaceAreaArr[foundIndex].Height - selectedPixmap->height()); + + + p.drawPixmap(spaceAreaArr[foundIndex].posX, spaceAreaArr[foundIndex].posY, *selectedPixmap); + + TexCoordRect texCoordRect(spaceAreaArr[foundIndex].posX / static_cast(width), + spaceAreaArr[foundIndex].posY / static_cast(height), + (spaceAreaArr[foundIndex].posX + selectedPixmap->width()) / static_cast(width), + (spaceAreaArr[foundIndex].posY + selectedPixmap->height()) / static_cast(height)); + + texCoordRect.texCoordFromY = 1.f - texCoordRect.texCoordFromY; + texCoordRect.texCoordToY = 1.f - texCoordRect.texCoordToY; + + float temp = texCoordRect.texCoordFromY; + texCoordRect.texCoordFromY = texCoordRect.texCoordToY; + texCoordRect.texCoordToY = temp; + + resultTexturePositions.push_back(std::pair(pixmapItr->first, texCoordRect)); + + spaceAreaArr.erase(spaceAreaArr.begin() + foundIndex); + spaceAreaArr.push_back(rightSpaceArea); + spaceAreaArr.push_back(topSpaceArea); + + + + } + else + { + throw std::runtime_error("Not enough space"); + } + + } + +} + +QString TextureSheet::GetCalculatedXml() +{ + QString result; + + result = "\n\t\n"; + + std::sort(imageNamesArray.begin(), imageNamesArray.end()); + + std::sort(resultTexturePositions.begin(), resultTexturePositions.end(), &resultTexturePositionsSortFunc); + + for (size_t i = 0; i < imageNamesArray.size(); i++) + { + result += QString("\t\t%1\n") + .arg(imageNamesArray[i]) + .arg(QString::number(resultTexturePositions[i].second.texCoordFromX)) + .arg(QString::number(resultTexturePositions[i].second.texCoordFromY)) + .arg(QString::number(resultTexturePositions[i].second.texCoordToX)) + .arg(QString::number(resultTexturePositions[i].second.texCoordToY)); + } + + result += "\t\n"; + + return result; +} + +void TextureSheet::Clear() +{ + spaceAreaArr.clear(); + resultTexturePositions.clear(); + pixmapArray.clear(); + imageNamesArray.clear(); + + resultPixmap = boost::shared_ptr(new QPixmap(4,4)); + + QColor transparentColor(0,0,0,0); + + resultPixmap->fill(transparentColor); +} diff --git a/TextureSheetMaker/TextureSheet.h b/TextureSheetMaker/TextureSheet.h new file mode 100644 index 0000000..9b468f6 --- /dev/null +++ b/TextureSheetMaker/TextureSheet.h @@ -0,0 +1,88 @@ +#ifndef TEXTURESHEET_H +#define TEXTURESHEET_H + +#include +#include +#include +#include +#include +#include +#include +#include "boost/shared_ptr.hpp" +#include + +struct TexCoordRect +{ + float texCoordFromX; + float texCoordFromY; + float texCoordToX; + float texCoordToY; + + TexCoordRect() + : texCoordFromX(0) + , texCoordFromY(0) + , texCoordToX(0) + , texCoordToY(0) + { + + } + + TexCoordRect(float itexCoordFromX, float itexCoordFromY, float itexCoordToX, float itexCoordToY) + : texCoordFromX(itexCoordFromX) + , texCoordFromY(itexCoordFromY) + , texCoordToX(itexCoordToX) + , texCoordToY(itexCoordToY) + { + + } +}; + +struct SpaceArea +{ + int posX; + int posY; + int Width; + int Height; + + SpaceArea() + : posX(0) + , posY(0) + , Width(0) + , Height(0) + { + + } + + SpaceArea(int iposX, int iposY, int iWidth, int iHeight) + : posX(iposX) + , posY(iposY) + , Width(iWidth) + , Height(iHeight) + { + + } +}; + +class TextureSheet +{ +protected: + +public: + std::vector>> pixmapArray; + std::vector imageNamesArray; + + boost::shared_ptr resultPixmap; + std::vector> resultTexturePositions; + + std::vector spaceAreaArr; + + void Calculate(int width, int height); + QString GetCalculatedXml(); + + void Clear(); + +}; + + + +#endif // TEXTURESHEET_H diff --git a/TextureSheetMaker/TextureSheetMaker.pro b/TextureSheetMaker/TextureSheetMaker.pro new file mode 100644 index 0000000..ad8a567 --- /dev/null +++ b/TextureSheetMaker/TextureSheetMaker.pro @@ -0,0 +1,24 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2013-06-20T22:38:10 +# +#------------------------------------------------- + +QT += core gui + +TARGET = TextureSheetMaker +TEMPLATE = app + + +SOURCES += main.cpp\ + mainwindow.cpp \ + TextureSheet.cpp + +HEADERS += mainwindow.h \ + TextureSheet.h + + +INCLUDEPATH += $$(LibsPath)/boost_1_52_0 +DEPENDPATH += $$(LibsPath)/boost_1_52_0 + +FORMS += mainwindow.ui diff --git a/TextureSheetMaker/main.cpp b/TextureSheetMaker/main.cpp new file mode 100644 index 0000000..f818a49 --- /dev/null +++ b/TextureSheetMaker/main.cpp @@ -0,0 +1,16 @@ +#include +#include "mainwindow.h" +#include "ui_mainwindow.h" + + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + MainWindow w; + + w.show(); + + w.RegisterSignals(); + + return a.exec(); +} diff --git a/TextureSheetMaker/mainwindow.cpp b/TextureSheetMaker/mainwindow.cpp new file mode 100644 index 0000000..65def63 --- /dev/null +++ b/TextureSheetMaker/mainwindow.cpp @@ -0,0 +1,144 @@ +#include "mainwindow.h" +#include "ui_mainwindow.h" +#include + +MainWindow::MainWindow(QWidget *parent) : + QMainWindow(parent), + ui(new Ui::MainWindow) +{ + ui->setupUi(this); + +} + +MainWindow::~MainWindow() +{ + delete ui; +} + +Ui::MainWindow* MainWindow::GetUi() +{ + return ui; +} + +void MainWindow::RegisterSignals() +{ + QObject::connect(ui->AddTexturesButton, SIGNAL(pressed()), this, SLOT(OnAddTexturesPressed())); + QObject::connect(ui->GenerateButton, SIGNAL(pressed()), this, SLOT(OnGeneratePressed())); + QObject::connect(ui->ClearButton, SIGNAL(pressed()), this, SLOT(OnClearPressed())); + QObject::connect(ui->SaveTextureButton, SIGNAL(pressed()), this, SLOT(OnSaveTexturePressed())); + QObject::connect(ui->SaveParamsButton, SIGNAL(pressed()), this, SLOT(OnSaveSheetParamsPressed())); +} + + + +void MainWindow::OnAddTexturesPressed() +{ + QFileDialog dialog(this); + + dialog.setFileMode(QFileDialog::ExistingFiles); + + dialog.setNameFilter("PNG images (*.png)"); + + if (dialog.exec()) + { + + QStringList fileNames = dialog.selectedFiles(); + + for (int i = 0; i < fileNames.count(); i++) + { + boost::shared_ptr pixmap(new QPixmap(fileNames[i], "PNG")); + + QFileInfo q; + q.setFile(fileNames[i]); + + QString fn = q.fileName(); + + //std::string fileName = fn.toUtf8().constData(); + + ui->textureList->addItem(fn); + + textureSheet.pixmapArray.push_back(std::pair>(fn, pixmap)); + textureSheet.imageNamesArray.push_back(fn); + + } + } +} + +void MainWindow::OnGeneratePressed() +{ + int width = ui->widthSpinBox->value(); + int height = ui->heightSpinBox->value(); + + try + { + textureSheet.Calculate(width, height); + QString xml = textureSheet.GetCalculatedXml(); + ui->textureParamsEdit->clear(); + + ui->textureParamsEdit->appendPlainText(xml); + + } + catch (std::runtime_error& error) + { + QMessageBox msgBox; + msgBox.setText("Not enough space"); + msgBox.exec(); + } + + + ui->PixmapSheet->setPixmap(*(textureSheet.resultPixmap)); +} + +void MainWindow::OnClearPressed() +{ + textureSheet.Clear(); + ui->PixmapSheet->setPixmap(*(textureSheet.resultPixmap)); + + ui->textureList->clear(); +} + +void MainWindow::OnSaveTexturePressed() +{ + QFileDialog dialog(this); + + dialog.setAcceptMode(QFileDialog::AcceptSave); + + dialog.setFileMode(QFileDialog::AnyFile); + + dialog.setNameFilter("PNG images (*.png)"); + + dialog.setDefaultSuffix("png"); + + if (dialog.exec()) + { + QString fileName = *(dialog.selectedFiles().begin()); + + textureSheet.resultPixmap->save(fileName, "PNG"); + } +} + +void MainWindow::OnSaveSheetParamsPressed() +{ + QFileDialog dialog(this); + + dialog.setAcceptMode(QFileDialog::AcceptSave); + + dialog.setFileMode(QFileDialog::AnyFile); + + dialog.setNameFilter("XML files (*.xml)"); + + dialog.setDefaultSuffix("xml"); + + if (dialog.exec()) + { + QString fileName = *(dialog.selectedFiles().begin()); + + QFile file(fileName); + if (file.open(QIODevice::WriteOnly | QIODevice::Text)) + { + QTextStream outStream(&file); + outStream << ui->textureParamsEdit->toPlainText(); + } + + } +} diff --git a/TextureSheetMaker/mainwindow.h b/TextureSheetMaker/mainwindow.h new file mode 100644 index 0000000..b834566 --- /dev/null +++ b/TextureSheetMaker/mainwindow.h @@ -0,0 +1,40 @@ +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include +#include +#include "boost/shared_ptr.hpp" + +#include "TextureSheet.h" + +namespace Ui { +class MainWindow; +} + + +class MainWindow : public QMainWindow +{ + Q_OBJECT + + TextureSheet textureSheet; +public: + explicit MainWindow(QWidget *parent = 0); + ~MainWindow(); + + Ui::MainWindow* GetUi(); + + void RegisterSignals(); +public slots: + void OnAddTexturesPressed(); + void OnGeneratePressed(); + void OnClearPressed(); + void OnSaveTexturePressed(); + + void OnSaveSheetParamsPressed(); + + +private: + Ui::MainWindow *ui; +}; + +#endif // MAINWINDOW_H diff --git a/TextureSheetMaker/mainwindow.ui b/TextureSheetMaker/mainwindow.ui new file mode 100644 index 0000000..e614b84 --- /dev/null +++ b/TextureSheetMaker/mainwindow.ui @@ -0,0 +1,234 @@ + + + MainWindow + + + + 0 + 0 + 844 + 688 + + + + MainWindow + + + + + + 10 + 50 + 191 + 251 + + + + + + + 10 + 20 + 91 + 23 + + + + Add textures... + + + + + + 110 + 20 + 91 + 23 + + + + Clear + + + + + + 310 + 40 + 61 + 22 + + + + 4 + + + 4096 + + + 512 + + + + + + 311 + 70 + 61 + 22 + + + + 4 + + + 4096 + + + 512 + + + + + + 260 + 50 + 46 + 13 + + + + Width: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + 260 + 70 + 46 + 13 + + + + Height: + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + 10 + 340 + 191 + 131 + + + + Qt::ScrollBarAlwaysOn + + + Qt::ScrollBarAlwaysOn + + + QPlainTextEdit::NoWrap + + + + + + 10 + 310 + 121 + 23 + + + + Generate + + + + + + 10 + 480 + 121 + 23 + + + + Save texture... + + + + + + 10 + 510 + 121 + 23 + + + + Save params... + + + + + + 220 + 110 + 512 + 512 + + + + QFrame::Box + + + QFrame::Raised + + + + + 0 + 0 + 512 + 512 + + + + + + + + + + + + 0 + 0 + 844 + 21 + + + + + + TopToolBarArea + + + false + + + + + + + +