From 9abda07c487a755b44845f839bf021566c4d45b3 Mon Sep 17 00:00:00 2001 From: Marcus Huderle Date: Sat, 29 Sep 2018 14:13:07 -0500 Subject: [PATCH 01/15] Add Tileset Editor window --- forms/mainwindow.ui | 27 +++++++++++++++---------- forms/tileseteditor.ui | 40 ++++++++++++++++++++++++++++++++++++++ include/editor.h | 1 + include/mainwindow.h | 4 ++++ include/ui/tileseteditor.h | 26 +++++++++++++++++++++++++ porymap.pro | 5 ++++- src/editor.cpp | 6 ++++++ src/mainwindow.cpp | 13 +++++++++++++ src/ui/tileseteditor.cpp | 26 +++++++++++++++++++++++++ 9 files changed, 137 insertions(+), 11 deletions(-) create mode 100644 forms/tileseteditor.ui create mode 100644 include/ui/tileseteditor.h create mode 100644 src/ui/tileseteditor.cpp diff --git a/forms/mainwindow.ui b/forms/mainwindow.ui index b42acbaf..4c4a0277 100644 --- a/forms/mainwindow.ui +++ b/forms/mainwindow.ui @@ -73,7 +73,7 @@ - + :/icons/map.ico:/icons/map.ico @@ -177,7 +177,7 @@ Paint - + :/icons/pencil.ico:/icons/pencil.ico @@ -203,7 +203,7 @@ Select - + :/icons/cursor.ico:/icons/cursor.ico @@ -220,7 +220,7 @@ Fill - + :/icons/fill_color.ico:/icons/fill_color.ico @@ -237,7 +237,7 @@ Dropper - + :/icons/pipette.ico:/icons/pipette.ico @@ -254,7 +254,7 @@ ... - + :/icons/move.ico:/icons/move.ico @@ -271,7 +271,7 @@ Shift - + :/icons/shift.ico:/icons/shift.ico @@ -1355,7 +1355,7 @@ New Object - + :/icons/add.ico:/icons/add.ico @@ -1384,7 +1384,7 @@ Delete - + :/icons/delete.ico:/icons/delete.ico @@ -2127,6 +2127,8 @@ + + @@ -2268,6 +2270,11 @@ P + + + Tileset Editor + + @@ -2288,7 +2295,7 @@ - + diff --git a/forms/tileseteditor.ui b/forms/tileseteditor.ui new file mode 100644 index 00000000..33074d3f --- /dev/null +++ b/forms/tileseteditor.ui @@ -0,0 +1,40 @@ + + + TilesetEditor + + + + 0 + 0 + 800 + 600 + + + + MainWindow + + + + + + + + + + + + + + + 0 + 0 + 800 + 21 + + + + + + + + \ No newline at end of file diff --git a/include/editor.h b/include/editor.h index a9433e95..31f11586 100644 --- a/include/editor.h +++ b/include/editor.h @@ -71,6 +71,7 @@ public: void updatePrimaryTileset(QString tilesetLabel); void updateSecondaryTileset(QString tilesetLabel); void toggleBorderVisibility(bool visible); + Tileset *getCurrentMapPrimaryTileset(); DraggablePixmapItem *addMapEvent(Event *event); void selectMapEvent(DraggablePixmapItem *object); diff --git a/include/mainwindow.h b/include/mainwindow.h index 7dd7c773..eff9b871 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -12,6 +12,7 @@ #include "project.h" #include "map.h" #include "editor.h" +#include "tileseteditor.h" namespace Ui { class MainWindow; @@ -123,8 +124,11 @@ private slots: void resetMapViewScale(); + void on_actionTileset_Editor_triggered(); + private: Ui::MainWindow *ui; + TilesetEditor *tilesetEditor; QStandardItemModel *mapListModel; QList *mapGroupsModel; QMap mapListIndexes; diff --git a/include/ui/tileseteditor.h b/include/ui/tileseteditor.h new file mode 100644 index 00000000..7725a16f --- /dev/null +++ b/include/ui/tileseteditor.h @@ -0,0 +1,26 @@ +#ifndef TILESETEDITOR_H +#define TILESETEDITOR_H + +#include +#include "project.h" + +namespace Ui { +class TilesetEditor; +} + +class TilesetEditor : public QMainWindow +{ + Q_OBJECT + +public: + explicit TilesetEditor(QWidget *parent = nullptr, Project *project = nullptr); + ~TilesetEditor(); + +private: + void displayPrimaryTilesetTiles(); + Ui::TilesetEditor *ui; + Project *project; + QString primaryTilesetLabel; +}; + +#endif // TILESETEDITOR_H diff --git a/porymap.pro b/porymap.pro index 665b5c19..3a027a4c 100644 --- a/porymap.pro +++ b/porymap.pro @@ -40,6 +40,7 @@ SOURCES += src/core/block.cpp \ src/ui/noscrollcombobox.cpp \ src/ui/noscrollspinbox.cpp \ src/ui/selectablepixmapitem.cpp \ + src/ui/tileseteditor.cpp \ src/editor.cpp \ src/main.cpp \ src/mainwindow.cpp \ @@ -74,13 +75,15 @@ HEADERS += include/core/block.h \ include/ui/noscrollcombobox.h \ include/ui/noscrollspinbox.h \ include/ui/selectablepixmapitem.h \ + include/ui/tileseteditor.h \ include/editor.h \ include/mainwindow.h \ include/project.h \ include/settings.h FORMS += forms/mainwindow.ui \ - forms/eventpropertiesframe.ui + forms/eventpropertiesframe.ui \ + forms/tileseteditor.ui RESOURCES += \ resources/images.qrc diff --git a/src/editor.cpp b/src/editor.cpp index 23fce69d..6da57f69 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -987,6 +987,12 @@ void Editor::toggleBorderVisibility(bool visible) this->setConnectionsVisibility(visible); } +Tileset* Editor::getCurrentMapPrimaryTileset() +{ + QString tilesetLabel = map->layout->tileset_primary_label; + return project->getTileset(tilesetLabel); +} + void DraggablePixmapItem::mousePressEvent(QGraphicsSceneMouseEvent *mouse) { active = true; last_x = static_cast(mouse->pos().x() + this->pos().x()) / 16; diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 70d875f3..581d84e2 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -1227,3 +1227,16 @@ void MainWindow::on_checkBox_ToggleBorder_stateChanged(int selected) bool visible = selected != 0; editor->toggleBorderVisibility(visible); } + +void MainWindow::on_actionTileset_Editor_triggered() +{ + if (!this->tilesetEditor) { + this->tilesetEditor = new TilesetEditor(nullptr, this->editor->project); + } + + if (!this->tilesetEditor->isVisible()) { + this->tilesetEditor->show(); + } else { + this->tilesetEditor->activateWindow(); + } +} diff --git a/src/ui/tileseteditor.cpp b/src/ui/tileseteditor.cpp new file mode 100644 index 00000000..8b6dc5c6 --- /dev/null +++ b/src/ui/tileseteditor.cpp @@ -0,0 +1,26 @@ +#include "tileseteditor.h" +#include "ui_tileseteditor.h" + +TilesetEditor::TilesetEditor(QWidget *parent, Project *project) : + QMainWindow(parent), + ui(new Ui::TilesetEditor) +{ + ui->setupUi(this); + this->project = project; + + displayPrimaryTilesetTiles(); +} + +TilesetEditor::~TilesetEditor() +{ + delete ui; +} + +void TilesetEditor::displayPrimaryTilesetTiles() +{ + Tileset *primaryTileset = this->project->getTileset(this->primaryTilesetLabel); +// scene_metatiles = new QGraphicsScene; +// metatiles_item = new MetatilesPixmapItem(map); +// metatiles_item->draw(); +// scene_metatiles->addItem(metatiles_item); +} From 990a4aafb7eb76735b3fbbc5350befb64d456227 Mon Sep 17 00:00:00 2001 From: Marcus Huderle Date: Sat, 29 Sep 2018 15:24:35 -0500 Subject: [PATCH 02/15] Add metatile selector in tileset editor window --- forms/tileseteditor.ui | 148 ++++++++++++++++++++- include/ui/tileseteditor.h | 13 +- include/ui/tileseteditormetatileselector.h | 43 ++++++ porymap.pro | 2 + src/mainwindow.cpp | 2 +- src/ui/tileseteditor.cpp | 44 +++++- src/ui/tileseteditormetatileselector.cpp | 111 ++++++++++++++++ 7 files changed, 350 insertions(+), 13 deletions(-) create mode 100644 include/ui/tileseteditormetatileselector.h create mode 100644 src/ui/tileseteditormetatileselector.cpp diff --git a/forms/tileseteditor.ui b/forms/tileseteditor.ui index 33074d3f..dbc84d15 100644 --- a/forms/tileseteditor.ui +++ b/forms/tileseteditor.ui @@ -16,10 +16,152 @@ - + + + true + + + + + 0 + 0 + 386 + 539 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + - + + + true + + + + + 0 + 0 + 386 + 539 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + @@ -37,4 +179,4 @@ - \ No newline at end of file + diff --git a/include/ui/tileseteditor.h b/include/ui/tileseteditor.h index 7725a16f..2ea6f3ed 100644 --- a/include/ui/tileseteditor.h +++ b/include/ui/tileseteditor.h @@ -3,6 +3,7 @@ #include #include "project.h" +#include "tileseteditormetatileselector.h" namespace Ui { class TilesetEditor; @@ -13,14 +14,22 @@ class TilesetEditor : public QMainWindow Q_OBJECT public: - explicit TilesetEditor(QWidget *parent = nullptr, Project *project = nullptr); + explicit TilesetEditor(Project*, QString, QString, QWidget *parent = nullptr); ~TilesetEditor(); +private slots: + void onHoveredMetatileChanged(uint16_t); + void onHoveredMetatileCleared(); + void onSelectedMetatileChanged(uint16_t); + private: - void displayPrimaryTilesetTiles(); + void initMetatilesSelector(); Ui::TilesetEditor *ui; + TilesetEditorMetatileSelector *metatileSelector; Project *project; QString primaryTilesetLabel; + QString secondaryTilesetLabel; + QGraphicsScene *metatilesScene; }; #endif // TILESETEDITOR_H diff --git a/include/ui/tileseteditormetatileselector.h b/include/ui/tileseteditormetatileselector.h new file mode 100644 index 00000000..eb8d45fe --- /dev/null +++ b/include/ui/tileseteditormetatileselector.h @@ -0,0 +1,43 @@ +#ifndef TILESETEDITORMETATILESELECTOR_H +#define TILESETEDITORMETATILESELECTOR_H + +#include "selectablepixmapitem.h" +#include "tileset.h" + +class TilesetEditorMetatileSelector: public SelectablePixmapItem { + Q_OBJECT +public: + TilesetEditorMetatileSelector(Tileset *primaryTileset, Tileset *secondaryTileset): SelectablePixmapItem(32, 32, 1, 1) { + this->primaryTileset = primaryTileset; + this->secondaryTileset = secondaryTileset; + this->numMetatilesWide = 8; + setAcceptHoverEvents(true); + } + void draw(); + void select(uint16_t metatileId); + void setTilesets(Tileset*, Tileset*); + uint16_t getSelectedMetatile(); + +protected: + void mousePressEvent(QGraphicsSceneMouseEvent*); + void mouseMoveEvent(QGraphicsSceneMouseEvent*); + void mouseReleaseEvent(QGraphicsSceneMouseEvent*); + void hoverMoveEvent(QGraphicsSceneHoverEvent*); + void hoverLeaveEvent(QGraphicsSceneHoverEvent*); + +private: + Tileset *primaryTileset; + Tileset *secondaryTileset; + uint16_t selectedMetatile; + int numMetatilesWide; + void updateSelectedMetatile(); + uint16_t getMetatileId(int x, int y); + QPoint getMetatileIdCoords(uint16_t); + +signals: + void hoveredMetatileChanged(uint16_t); + void hoveredMetatileCleared(); + void selectedMetatileChanged(uint16_t); +}; + +#endif // TILESETEDITORMETATILESELECTOR_H diff --git a/porymap.pro b/porymap.pro index 3a027a4c..62c92337 100644 --- a/porymap.pro +++ b/porymap.pro @@ -41,6 +41,7 @@ SOURCES += src/core/block.cpp \ src/ui/noscrollspinbox.cpp \ src/ui/selectablepixmapitem.cpp \ src/ui/tileseteditor.cpp \ + src/ui/tileseteditormetatileselector.cpp \ src/editor.cpp \ src/main.cpp \ src/mainwindow.cpp \ @@ -76,6 +77,7 @@ HEADERS += include/core/block.h \ include/ui/noscrollspinbox.h \ include/ui/selectablepixmapitem.h \ include/ui/tileseteditor.h \ + include/ui/tileseteditormetatileselector.h \ include/editor.h \ include/mainwindow.h \ include/project.h \ diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 581d84e2..9f77938d 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -1231,7 +1231,7 @@ void MainWindow::on_checkBox_ToggleBorder_stateChanged(int selected) void MainWindow::on_actionTileset_Editor_triggered() { if (!this->tilesetEditor) { - this->tilesetEditor = new TilesetEditor(nullptr, this->editor->project); + this->tilesetEditor = new TilesetEditor(this->editor->project, this->editor->map->layout->tileset_primary_label, this->editor->map->layout->tileset_secondary_label); } if (!this->tilesetEditor->isVisible()) { diff --git a/src/ui/tileseteditor.cpp b/src/ui/tileseteditor.cpp index 8b6dc5c6..6579d72d 100644 --- a/src/ui/tileseteditor.cpp +++ b/src/ui/tileseteditor.cpp @@ -1,14 +1,18 @@ #include "tileseteditor.h" #include "ui_tileseteditor.h" +#include -TilesetEditor::TilesetEditor(QWidget *parent, Project *project) : +TilesetEditor::TilesetEditor(Project *project, QString primaryTilesetLabel, QString secondaryTilesetLabel, QWidget *parent) : QMainWindow(parent), ui(new Ui::TilesetEditor) { ui->setupUi(this); this->project = project; - displayPrimaryTilesetTiles(); + this->primaryTilesetLabel = primaryTilesetLabel; + this->secondaryTilesetLabel = secondaryTilesetLabel; + + initMetatilesSelector(); } TilesetEditor::~TilesetEditor() @@ -16,11 +20,37 @@ TilesetEditor::~TilesetEditor() delete ui; } -void TilesetEditor::displayPrimaryTilesetTiles() +void TilesetEditor::initMetatilesSelector() { Tileset *primaryTileset = this->project->getTileset(this->primaryTilesetLabel); -// scene_metatiles = new QGraphicsScene; -// metatiles_item = new MetatilesPixmapItem(map); -// metatiles_item->draw(); -// scene_metatiles->addItem(metatiles_item); + Tileset *secondaryTileset = this->project->getTileset(this->secondaryTilesetLabel); + this->metatileSelector = new TilesetEditorMetatileSelector(primaryTileset, secondaryTileset); + connect(this->metatileSelector, SIGNAL(hoveredMetatileChanged(uint16_t)), + this, SLOT(onHoveredMetatileChanged(uint16_t))); + connect(this->metatileSelector, SIGNAL(hoveredMetatileCleared()), + this, SLOT(onHoveredMetatileCleared())); + connect(this->metatileSelector, SIGNAL(selectedMetatileChanged(uint16_t)), + this, SLOT(onSelectedMetatileChanged(uint16_t))); + + this->metatilesScene = new QGraphicsScene; + this->metatilesScene->addItem(this->metatileSelector); + this->metatileSelector->select(0); + this->metatileSelector->draw(); + + this->ui->graphicsView_Metatiles->setScene(this->metatilesScene); + this->ui->graphicsView_Metatiles->setFixedSize(this->metatileSelector->pixmap().width() + 2, this->metatileSelector->pixmap().height() + 2); +} + +void TilesetEditor::onHoveredMetatileChanged(uint16_t metatileId) { + QString message = QString("Metatile: 0x%1") + .arg(QString("%1").arg(metatileId, 3, 16, QChar('0')).toUpper()); + this->ui->statusbar->showMessage(message); +} + +void TilesetEditor::onHoveredMetatileCleared() { + this->ui->statusbar->clearMessage(); +} + +void TilesetEditor::onSelectedMetatileChanged(uint16_t) { + } diff --git a/src/ui/tileseteditormetatileselector.cpp b/src/ui/tileseteditormetatileselector.cpp new file mode 100644 index 00000000..a5e607f7 --- /dev/null +++ b/src/ui/tileseteditormetatileselector.cpp @@ -0,0 +1,111 @@ +#include "tileseteditormetatileselector.h" +#include "imageproviders.h" +#include "project.h" +#include + +void TilesetEditorMetatileSelector::draw() { + if (!this->primaryTileset || !this->primaryTileset->metatiles + || !this->secondaryTileset || !this->secondaryTileset->metatiles) { + this->setPixmap(QPixmap()); + } + + int primaryLength = this->primaryTileset->metatiles->length(); + int length_ = primaryLength + this->secondaryTileset->metatiles->length(); + int height_ = length_ / this->numMetatilesWide; + QImage image(this->numMetatilesWide * 32, height_ * 32, QImage::Format_RGBA8888); + QPainter painter(&image); + for (int i = 0; i < length_; i++) { + int tile = i; + if (i >= primaryLength) { + tile += Project::getNumMetatilesPrimary() - primaryLength; + } + QImage metatile_image = getMetatileImage(tile, this->primaryTileset, this->secondaryTileset).scaled(32, 32); + int map_y = i / this->numMetatilesWide; + int map_x = i % this->numMetatilesWide; + QPoint metatile_origin = QPoint(map_x * 32, map_y * 32); + painter.drawImage(metatile_origin, metatile_image); + } + + painter.end(); + this->setPixmap(QPixmap::fromImage(image)); + this->drawSelection(); +} + +void TilesetEditorMetatileSelector::select(uint16_t metatileId) { + QPoint coords = this->getMetatileIdCoords(metatileId); + SelectablePixmapItem::select(coords.x(), coords.y(), 0, 0); + this->selectedMetatile = metatileId; + emit selectedMetatileChanged(metatileId); +} + +void TilesetEditorMetatileSelector::setTilesets(Tileset *primaryTileset, Tileset *secondaryTileset) { + this->primaryTileset = primaryTileset; + this->secondaryTileset = secondaryTileset; + this->draw(); +} + +void TilesetEditorMetatileSelector::updateSelectedMetatile() { + QPoint origin = this->getSelectionStart(); + this->selectedMetatile = this->getMetatileId(origin.x(), origin.y()); +} + +uint16_t TilesetEditorMetatileSelector::getSelectedMetatile() { + return this->selectedMetatile; +} + +uint16_t TilesetEditorMetatileSelector::getMetatileId(int x, int y) { + int index = y * this->numMetatilesWide + x; + if (index < this->primaryTileset->metatiles->length()) { + return static_cast(index); + } else { + return static_cast(Project::getNumMetatilesPrimary() + index - this->primaryTileset->metatiles->length()); + } +} + +void TilesetEditorMetatileSelector::mousePressEvent(QGraphicsSceneMouseEvent *event) { + SelectablePixmapItem::mousePressEvent(event); + this->updateSelectedMetatile(); + emit selectedMetatileChanged(this->selectedMetatile); +} + +void TilesetEditorMetatileSelector::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { + SelectablePixmapItem::mouseMoveEvent(event); + this->updateSelectedMetatile(); + + QPoint pos = this->getCellPos(event->pos()); + uint16_t metatileId = this->getMetatileId(pos.x(), pos.y()); + emit hoveredMetatileChanged(metatileId); + emit selectedMetatileChanged(metatileId); +} + +void TilesetEditorMetatileSelector::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { + SelectablePixmapItem::mouseReleaseEvent(event); + this->updateSelectedMetatile(); + emit selectedMetatileChanged(this->selectedMetatile); +} + +void TilesetEditorMetatileSelector::hoverMoveEvent(QGraphicsSceneHoverEvent *event) { + QPoint pos = this->getCellPos(event->pos()); + uint16_t metatileId = this->getMetatileId(pos.x(), pos.y()); + emit this->hoveredMetatileChanged(metatileId); +} + +void TilesetEditorMetatileSelector::hoverLeaveEvent(QGraphicsSceneHoverEvent*) { + emit this->hoveredMetatileCleared(); +} + +QPoint TilesetEditorMetatileSelector::getMetatileIdCoords(uint16_t metatileId) { + if (metatileId >= Project::getNumMetatilesTotal() + || (metatileId < Project::getNumMetatilesPrimary() && metatileId >= this->primaryTileset->metatiles->length()) + || (metatileId < Project::getNumMetatilesTotal() && metatileId >= Project::getNumMetatilesPrimary() + this->secondaryTileset->metatiles->length())) + { + // Invalid metatile id. + return QPoint(0, 0); + } + + int index = metatileId < Project::getNumMetatilesPrimary() + ? metatileId + : metatileId - Project::getNumMetatilesPrimary() + this->primaryTileset->metatiles->length(); + return QPoint(index % this->numMetatilesWide, index / this->numMetatilesWide); +} + From 0bc3513b15f19f54ce7289a4190afab89981517e Mon Sep 17 00:00:00 2001 From: Marcus Huderle Date: Sun, 30 Sep 2018 12:33:58 -0500 Subject: [PATCH 03/15] Add tile selector to Tileset Editor window --- include/mainwindow.h | 2 +- include/ui/imageproviders.h | 5 +- include/ui/tileseteditor.h | 10 +- include/ui/tileseteditortileselector.h | 47 +++++++++ porymap.pro | 2 + src/ui/imageproviders.cpp | 12 ++- src/ui/tileseteditor.cpp | 40 +++++++- src/ui/tileseteditortileselector.cpp | 126 +++++++++++++++++++++++++ 8 files changed, 236 insertions(+), 8 deletions(-) create mode 100644 include/ui/tileseteditortileselector.h create mode 100644 src/ui/tileseteditortileselector.cpp diff --git a/include/mainwindow.h b/include/mainwindow.h index eff9b871..8178b625 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -128,7 +128,7 @@ private slots: private: Ui::MainWindow *ui; - TilesetEditor *tilesetEditor; + TilesetEditor *tilesetEditor = nullptr; QStandardItemModel *mapListModel; QList *mapGroupsModel; QMap mapListIndexes; diff --git a/include/ui/imageproviders.h b/include/ui/imageproviders.h index 4bff143a..c48f920f 100644 --- a/include/ui/imageproviders.h +++ b/include/ui/imageproviders.h @@ -8,7 +8,8 @@ QImage getCollisionMetatileImage(Block); QImage getCollisionMetatileImage(int, int); -QImage getMetatileImage(int, Tileset*, Tileset*); -QImage getTileImage(int, Tileset*, Tileset*); +QImage getMetatileImage(uint16_t, Tileset*, Tileset*); +QImage getTileImage(uint16_t, Tileset*, Tileset*); +QImage getColoredTileImage(uint16_t, Tileset*, Tileset*, QList); #endif // IMAGEPROVIDERS_H diff --git a/include/ui/tileseteditor.h b/include/ui/tileseteditor.h index 2ea6f3ed..43370ab0 100644 --- a/include/ui/tileseteditor.h +++ b/include/ui/tileseteditor.h @@ -4,6 +4,7 @@ #include #include "project.h" #include "tileseteditormetatileselector.h" +#include "tileseteditortileselector.h" namespace Ui { class TilesetEditor; @@ -21,15 +22,22 @@ private slots: void onHoveredMetatileChanged(uint16_t); void onHoveredMetatileCleared(); void onSelectedMetatileChanged(uint16_t); + void onHoveredTileChanged(uint16_t); + void onHoveredTileCleared(); + void onSelectedTileChanged(uint16_t); private: - void initMetatilesSelector(); + void initMetatileSelector(); + void initTileSelector(); Ui::TilesetEditor *ui; TilesetEditorMetatileSelector *metatileSelector; + TilesetEditorTileSelector *tileSelector; Project *project; + uint paletteNum; QString primaryTilesetLabel; QString secondaryTilesetLabel; QGraphicsScene *metatilesScene; + QGraphicsScene *tilesScene; }; #endif // TILESETEDITOR_H diff --git a/include/ui/tileseteditortileselector.h b/include/ui/tileseteditortileselector.h new file mode 100644 index 00000000..d13aa19e --- /dev/null +++ b/include/ui/tileseteditortileselector.h @@ -0,0 +1,47 @@ +#ifndef TILESETEDITORTILESELECTOR_H +#define TILESETEDITORTILESELECTOR_H + +#include "selectablepixmapitem.h" +#include "tileset.h" + +class TilesetEditorTileSelector: public SelectablePixmapItem { + Q_OBJECT +public: + TilesetEditorTileSelector(Tileset *primaryTileset, Tileset *secondaryTileset): SelectablePixmapItem(16, 16, 1, 1) { + this->primaryTileset = primaryTileset; + this->secondaryTileset = secondaryTileset; + this->numTilesWide = 16; + this->paletteNum = 0; + setAcceptHoverEvents(true); + } + void draw(); + void select(uint16_t metatileId); + void setTilesets(Tileset*, Tileset*); + void setPaletteNum(int); + uint16_t getSelectedTile(); + +protected: + void mousePressEvent(QGraphicsSceneMouseEvent*); + void mouseMoveEvent(QGraphicsSceneMouseEvent*); + void mouseReleaseEvent(QGraphicsSceneMouseEvent*); + void hoverMoveEvent(QGraphicsSceneHoverEvent*); + void hoverLeaveEvent(QGraphicsSceneHoverEvent*); + +private: + Tileset *primaryTileset; + Tileset *secondaryTileset; + uint16_t selectedTile; + int numTilesWide; + int paletteNum; + void updateSelectedTile(); + uint16_t getTileId(int x, int y); + QPoint getTileCoords(uint16_t); + QList getCurPaletteTable(); + +signals: + void hoveredTileChanged(uint16_t); + void hoveredTileCleared(); + void selectedTileChanged(uint16_t); +}; + +#endif // TILESETEDITORTILESELECTOR_H diff --git a/porymap.pro b/porymap.pro index 62c92337..311630d9 100644 --- a/porymap.pro +++ b/porymap.pro @@ -42,6 +42,7 @@ SOURCES += src/core/block.cpp \ src/ui/selectablepixmapitem.cpp \ src/ui/tileseteditor.cpp \ src/ui/tileseteditormetatileselector.cpp \ + src/ui/tileseteditortileselector.cpp \ src/editor.cpp \ src/main.cpp \ src/mainwindow.cpp \ @@ -78,6 +79,7 @@ HEADERS += include/core/block.h \ include/ui/selectablepixmapitem.h \ include/ui/tileseteditor.h \ include/ui/tileseteditormetatileselector.h \ + include/ui/tileseteditortileselector.h \ include/editor.h \ include/mainwindow.h \ include/project.h \ diff --git a/src/ui/imageproviders.cpp b/src/ui/imageproviders.cpp index d5873800..bda02cc0 100644 --- a/src/ui/imageproviders.cpp +++ b/src/ui/imageproviders.cpp @@ -13,7 +13,7 @@ QImage getCollisionMetatileImage(int collision, int elevation) { return collisionImage.toImage(); } -QImage getMetatileImage(int tile, Tileset *primaryTileset, Tileset *secondaryTileset) { +QImage getMetatileImage(uint16_t tile, Tileset *primaryTileset, Tileset *secondaryTileset) { QImage metatile_image(16, 16, QImage::Format_RGBA8888); Metatile* metatile = Tileset::getMetatile(tile, primaryTileset, secondaryTileset); @@ -71,7 +71,7 @@ QImage getMetatileImage(int tile, Tileset *primaryTileset, Tileset *secondaryTil return metatile_image; } -QImage getTileImage(int tile, Tileset *primaryTileset, Tileset *secondaryTileset) { +QImage getTileImage(uint16_t tile, Tileset *primaryTileset, Tileset *secondaryTileset) { Tileset *tileset = Tileset::getBlockTileset(tile, primaryTileset, secondaryTileset); int local_index = Metatile::getBlockIndex(tile); if (!tileset || !tileset->tiles) { @@ -79,3 +79,11 @@ QImage getTileImage(int tile, Tileset *primaryTileset, Tileset *secondaryTileset } return tileset->tiles->value(local_index, QImage()); } + +QImage getColoredTileImage(uint16_t tile, Tileset *primaryTileset, Tileset *secondaryTileset, QList palette) { + QImage tileImage = getTileImage(tile, primaryTileset, secondaryTileset); + for (int i = 0; i < 16; i++) { + tileImage.setColor(i, palette.at(i)); + } + return tileImage; +} diff --git a/src/ui/tileseteditor.cpp b/src/ui/tileseteditor.cpp index 6579d72d..63c90ff1 100644 --- a/src/ui/tileseteditor.cpp +++ b/src/ui/tileseteditor.cpp @@ -12,7 +12,8 @@ TilesetEditor::TilesetEditor(Project *project, QString primaryTilesetLabel, QStr this->primaryTilesetLabel = primaryTilesetLabel; this->secondaryTilesetLabel = secondaryTilesetLabel; - initMetatilesSelector(); + initMetatileSelector(); + initTileSelector(); } TilesetEditor::~TilesetEditor() @@ -20,7 +21,7 @@ TilesetEditor::~TilesetEditor() delete ui; } -void TilesetEditor::initMetatilesSelector() +void TilesetEditor::initMetatileSelector() { Tileset *primaryTileset = this->project->getTileset(this->primaryTilesetLabel); Tileset *secondaryTileset = this->project->getTileset(this->secondaryTilesetLabel); @@ -41,6 +42,27 @@ void TilesetEditor::initMetatilesSelector() this->ui->graphicsView_Metatiles->setFixedSize(this->metatileSelector->pixmap().width() + 2, this->metatileSelector->pixmap().height() + 2); } +void TilesetEditor::initTileSelector() +{ + Tileset *primaryTileset = this->project->getTileset(this->primaryTilesetLabel); + Tileset *secondaryTileset = this->project->getTileset(this->secondaryTilesetLabel); + this->tileSelector = new TilesetEditorTileSelector(primaryTileset, secondaryTileset); + connect(this->tileSelector, SIGNAL(hoveredTileChanged(uint16_t)), + this, SLOT(onHoveredTileChanged(uint16_t))); + connect(this->tileSelector, SIGNAL(hoveredTileCleared()), + this, SLOT(onHoveredTileCleared())); + connect(this->tileSelector, SIGNAL(selectedTileChanged(uint16_t)), + this, SLOT(onSelectedTileChanged(uint16_t))); + + this->tilesScene = new QGraphicsScene; + this->tilesScene->addItem(this->tileSelector); + this->tileSelector->select(0); + this->tileSelector->draw(); + + this->ui->graphicsView_Tiles->setScene(this->tilesScene); + this->ui->graphicsView_Tiles->setFixedSize(this->tileSelector->pixmap().width() + 2, this->tileSelector->pixmap().height() + 2); +} + void TilesetEditor::onHoveredMetatileChanged(uint16_t metatileId) { QString message = QString("Metatile: 0x%1") .arg(QString("%1").arg(metatileId, 3, 16, QChar('0')).toUpper()); @@ -54,3 +76,17 @@ void TilesetEditor::onHoveredMetatileCleared() { void TilesetEditor::onSelectedMetatileChanged(uint16_t) { } + +void TilesetEditor::onHoveredTileChanged(uint16_t tile) { + QString message = QString("Tile: 0x%1") + .arg(QString("%1").arg(tile, 3, 16, QChar('0')).toUpper()); + this->ui->statusbar->showMessage(message); +} + +void TilesetEditor::onHoveredTileCleared() { + this->ui->statusbar->clearMessage(); +} + +void TilesetEditor::onSelectedTileChanged(uint16_t) { + +} diff --git a/src/ui/tileseteditortileselector.cpp b/src/ui/tileseteditortileselector.cpp new file mode 100644 index 00000000..367af1b4 --- /dev/null +++ b/src/ui/tileseteditortileselector.cpp @@ -0,0 +1,126 @@ +#include "tileseteditortileselector.h" +#include "imageproviders.h" +#include "project.h" +#include + +void TilesetEditorTileSelector::draw() { + if (!this->primaryTileset || !this->primaryTileset->tiles + || !this->secondaryTileset || !this->secondaryTileset->tiles) { + this->setPixmap(QPixmap()); + } + + int totalTiles = Project::getNumTilesTotal(); + int primaryLength = this->primaryTileset->tiles->length(); + int secondaryLength = this->secondaryTileset->tiles->length(); + int height = totalTiles / this->numTilesWide; + QList palette = this->getCurPaletteTable(); + QImage image(this->numTilesWide * 16, height * 16, QImage::Format_RGBA8888); + + QPainter painter(&image); + for (uint16_t tile = 0; tile < totalTiles; tile++) { + QImage tileImage; + if (tile < primaryLength) { + tileImage = getColoredTileImage(tile, this->primaryTileset, this->secondaryTileset, palette).scaled(16, 16); + } else if (tile < Project::getNumTilesPrimary()) { + tileImage = QImage(16, 16, QImage::Format_RGBA8888); + tileImage.fill(palette.at(0)); + } else if (tile < Project::getNumTilesPrimary() + secondaryLength) { + tileImage = getColoredTileImage(tile, this->primaryTileset, this->secondaryTileset, palette).scaled(16, 16); + } else { + tileImage = QImage(16, 16, QImage::Format_RGBA8888); + QPainter painter(&tileImage); + painter.fillRect(0, 0, 16, 16, palette.at(0)); + } + + int y = tile / this->numTilesWide; + int x = tile % this->numTilesWide; + QPoint origin = QPoint(x * 16, y * 16); + painter.drawImage(origin, tileImage); + } + + painter.end(); + this->setPixmap(QPixmap::fromImage(image)); + this->drawSelection(); +} + +QList TilesetEditorTileSelector::getCurPaletteTable() { + QList paletteTable; + for (int i = 0; i < this->primaryTileset->palettes->at(this->paletteNum).length(); i++) { + paletteTable.append(this->primaryTileset->palettes->at(this->paletteNum).at(i)); + } + + return paletteTable; +} + +void TilesetEditorTileSelector::select(uint16_t tile) { + QPoint coords = this->getTileCoords(tile); + SelectablePixmapItem::select(coords.x(), coords.y(), 0, 0); + this->selectedTile = tile; + emit selectedTileChanged(tile); +} + +void TilesetEditorTileSelector::setTilesets(Tileset *primaryTileset, Tileset *secondaryTileset) { + this->primaryTileset = primaryTileset; + this->secondaryTileset = secondaryTileset; + this->draw(); +} + +void TilesetEditorTileSelector::setPaletteNum(int paletteNum) { + this->paletteNum = paletteNum; + this->draw(); +} + +void TilesetEditorTileSelector::updateSelectedTile() { + QPoint origin = this->getSelectionStart(); + this->selectedTile = this->getTileId(origin.x(), origin.y()); +} + +uint16_t TilesetEditorTileSelector::getSelectedTile() { + return this->selectedTile; +} + +uint16_t TilesetEditorTileSelector::getTileId(int x, int y) { + return static_cast(y * this->numTilesWide + x); +} + +void TilesetEditorTileSelector::mousePressEvent(QGraphicsSceneMouseEvent *event) { + SelectablePixmapItem::mousePressEvent(event); + this->updateSelectedTile(); + emit selectedTileChanged(this->selectedTile); +} + +void TilesetEditorTileSelector::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { + SelectablePixmapItem::mouseMoveEvent(event); + this->updateSelectedTile(); + + QPoint pos = this->getCellPos(event->pos()); + uint16_t tile = this->getTileId(pos.x(), pos.y()); + emit hoveredTileChanged(tile); + emit selectedTileChanged(tile); +} + +void TilesetEditorTileSelector::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { + SelectablePixmapItem::mouseReleaseEvent(event); + this->updateSelectedTile(); + emit selectedTileChanged(this->selectedTile); +} + +void TilesetEditorTileSelector::hoverMoveEvent(QGraphicsSceneHoverEvent *event) { + QPoint pos = this->getCellPos(event->pos()); + uint16_t tile = this->getTileId(pos.x(), pos.y()); + emit this->hoveredTileChanged(tile); +} + +void TilesetEditorTileSelector::hoverLeaveEvent(QGraphicsSceneHoverEvent*) { + emit this->hoveredTileCleared(); +} + +QPoint TilesetEditorTileSelector::getTileCoords(uint16_t tile) { + if (tile >= Project::getNumTilesTotal()) + { + // Invalid tile. + return QPoint(0, 0); + } + + return QPoint(tile % this->numTilesWide, tile / this->numTilesWide); +} From ffd769f7eda97424f00e84b256adc7b70d0fbe23 Mon Sep 17 00:00:00 2001 From: Marcus Huderle Date: Sun, 30 Sep 2018 14:54:38 -0500 Subject: [PATCH 04/15] Add palette and flip selectors to tileset editor --- forms/tileseteditor.ui | 262 ++++++++++++++++++------- include/core/tileset.h | 1 + include/ui/imageproviders.h | 2 +- include/ui/tileseteditor.h | 18 +- include/ui/tileseteditortileselector.h | 6 +- src/core/tileset.cpp | 11 ++ src/ui/imageproviders.cpp | 3 +- src/ui/tileseteditor.cpp | 51 ++++- src/ui/tileseteditortileselector.cpp | 19 +- 9 files changed, 278 insertions(+), 95 deletions(-) diff --git a/forms/tileseteditor.ui b/forms/tileseteditor.ui index dbc84d15..0eeffd04 100644 --- a/forms/tileseteditor.ui +++ b/forms/tileseteditor.ui @@ -25,7 +25,7 @@ 0 0 - 386 + 363 539 @@ -90,77 +90,199 @@ - - - true + + + QFrame::StyledPanel - - - - 0 - 0 - 386 - 539 - - - - - - - Qt::Horizontal + + QFrame::Raised + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + Y Flip + + + + + + + Palette + + + + + + + + + + X Flip + + + + + + + Qt::LeftToRight + + + + + + + + + + + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + 32 + 32 + + + + + 32 + 32 + + + + Qt::ScrollBarAlwaysOff + + + Qt::ScrollBarAlwaysOff + + + + + + + + + + + + + true + + + + + 0 + 0 + 363 + 415 + - - - 40 - 20 - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + diff --git a/include/core/tileset.h b/include/core/tileset.h index d18ab5e0..82113e4b 100644 --- a/include/core/tileset.h +++ b/include/core/tileset.h @@ -27,6 +27,7 @@ public: static Tileset* getBlockTileset(int, Tileset*, Tileset*); static Metatile* getMetatile(int, Tileset*, Tileset*); static QList> getBlockPalettes(Tileset*, Tileset*); + static QList getPalette(int, Tileset*, Tileset*); }; #endif // TILESET_H diff --git a/include/ui/imageproviders.h b/include/ui/imageproviders.h index c48f920f..96896e78 100644 --- a/include/ui/imageproviders.h +++ b/include/ui/imageproviders.h @@ -10,6 +10,6 @@ QImage getCollisionMetatileImage(Block); QImage getCollisionMetatileImage(int, int); QImage getMetatileImage(uint16_t, Tileset*, Tileset*); QImage getTileImage(uint16_t, Tileset*, Tileset*); -QImage getColoredTileImage(uint16_t, Tileset*, Tileset*, QList); +QImage getColoredTileImage(uint16_t, Tileset*, Tileset*, int); #endif // IMAGEPROVIDERS_H diff --git a/include/ui/tileseteditor.h b/include/ui/tileseteditor.h index 43370ab0..989fb717 100644 --- a/include/ui/tileseteditor.h +++ b/include/ui/tileseteditor.h @@ -26,18 +26,30 @@ private slots: void onHoveredTileCleared(); void onSelectedTileChanged(uint16_t); + void on_spinBox_paletteSelector_valueChanged(int arg1); + + void on_checkBox_xFlip_stateChanged(int arg1); + + void on_checkBox_yFlip_stateChanged(int arg1); + private: void initMetatileSelector(); void initTileSelector(); + void initSelectedTileItem(); + void drawSelectedTile(); Ui::TilesetEditor *ui; TilesetEditorMetatileSelector *metatileSelector; TilesetEditorTileSelector *tileSelector; Project *project; - uint paletteNum; + int paletteId; + bool tileXFlip; + bool tileYFlip; QString primaryTilesetLabel; QString secondaryTilesetLabel; - QGraphicsScene *metatilesScene; - QGraphicsScene *tilesScene; + QGraphicsScene *metatilesScene = nullptr; + QGraphicsScene *tilesScene = nullptr; + QGraphicsScene *selectedTileScene = nullptr; + QGraphicsPixmapItem *selectedTilePixmapItem = nullptr; }; #endif // TILESETEDITOR_H diff --git a/include/ui/tileseteditortileselector.h b/include/ui/tileseteditortileselector.h index d13aa19e..7369babb 100644 --- a/include/ui/tileseteditortileselector.h +++ b/include/ui/tileseteditortileselector.h @@ -11,13 +11,13 @@ public: this->primaryTileset = primaryTileset; this->secondaryTileset = secondaryTileset; this->numTilesWide = 16; - this->paletteNum = 0; + this->paletteId = 0; setAcceptHoverEvents(true); } void draw(); void select(uint16_t metatileId); void setTilesets(Tileset*, Tileset*); - void setPaletteNum(int); + void setPaletteId(int); uint16_t getSelectedTile(); protected: @@ -32,7 +32,7 @@ private: Tileset *secondaryTileset; uint16_t selectedTile; int numTilesWide; - int paletteNum; + int paletteId; void updateSelectedTile(); uint16_t getTileId(int x, int y); QPoint getTileCoords(uint16_t); diff --git a/src/core/tileset.cpp b/src/core/tileset.cpp index 772e4d7b..36187c02 100644 --- a/src/core/tileset.cpp +++ b/src/core/tileset.cpp @@ -39,3 +39,14 @@ QList> Tileset::getBlockPalettes(Tileset *primaryTileset, Tileset *s } return palettes; } + +QList Tileset::getPalette(int paletteId, Tileset *primaryTileset, Tileset *secondaryTileset) { + QList paletteTable; + Tileset *tileset = paletteId < Project::getNumPalettesPrimary() + ? primaryTileset + : secondaryTileset; + for (int i = 0; i < tileset->palettes->at(paletteId).length(); i++) { + paletteTable.append(tileset->palettes->at(paletteId).at(i)); + } + return paletteTable; +} diff --git a/src/ui/imageproviders.cpp b/src/ui/imageproviders.cpp index bda02cc0..2a1bc5ef 100644 --- a/src/ui/imageproviders.cpp +++ b/src/ui/imageproviders.cpp @@ -80,7 +80,8 @@ QImage getTileImage(uint16_t tile, Tileset *primaryTileset, Tileset *secondaryTi return tileset->tiles->value(local_index, QImage()); } -QImage getColoredTileImage(uint16_t tile, Tileset *primaryTileset, Tileset *secondaryTileset, QList palette) { +QImage getColoredTileImage(uint16_t tile, Tileset *primaryTileset, Tileset *secondaryTileset, int paletteId) { + QList palette = Tileset::getPalette(paletteId, primaryTileset, secondaryTileset); QImage tileImage = getTileImage(tile, primaryTileset, secondaryTileset); for (int i = 0; i < 16; i++) { tileImage.setColor(i, palette.at(i)); diff --git a/src/ui/tileseteditor.cpp b/src/ui/tileseteditor.cpp index 63c90ff1..f9774eed 100644 --- a/src/ui/tileseteditor.cpp +++ b/src/ui/tileseteditor.cpp @@ -1,5 +1,6 @@ #include "tileseteditor.h" #include "ui_tileseteditor.h" +#include "imageproviders.h" #include TilesetEditor::TilesetEditor(Project *project, QString primaryTilesetLabel, QString secondaryTilesetLabel, QWidget *parent) : @@ -9,11 +10,17 @@ TilesetEditor::TilesetEditor(Project *project, QString primaryTilesetLabel, QStr ui->setupUi(this); this->project = project; + this->tileXFlip = ui->checkBox_xFlip->isChecked(); + this->tileYFlip = ui->checkBox_yFlip->isChecked(); + this->paletteId = ui->spinBox_paletteSelector->value(); this->primaryTilesetLabel = primaryTilesetLabel; this->secondaryTilesetLabel = secondaryTilesetLabel; - initMetatileSelector(); - initTileSelector(); + ui->spinBox_paletteSelector->setMinimum(0); + ui->spinBox_paletteSelector->setMaximum(Project::getNumPalettesTotal() - 1); + this->initMetatileSelector(); + this->initTileSelector(); + this->initSelectedTileItem(); } TilesetEditor::~TilesetEditor() @@ -63,6 +70,25 @@ void TilesetEditor::initTileSelector() this->ui->graphicsView_Tiles->setFixedSize(this->tileSelector->pixmap().width() + 2, this->tileSelector->pixmap().height() + 2); } +void TilesetEditor::initSelectedTileItem() { + this->selectedTileScene = new QGraphicsScene; + this->drawSelectedTile(); + this->ui->graphicsView_selectedTile->setScene(this->selectedTileScene); +} + +void TilesetEditor::drawSelectedTile() { + if (!this->selectedTileScene) { + return; + } + + Tileset *primaryTileset = this->project->getTileset(this->primaryTilesetLabel); + Tileset *secondaryTileset = this->project->getTileset(this->secondaryTilesetLabel); + QImage tileImage = getColoredTileImage(this->tileSelector->getSelectedTile(), primaryTileset, secondaryTileset, this->paletteId) + .mirrored(this->tileXFlip, this->tileYFlip); + this->selectedTilePixmapItem = new QGraphicsPixmapItem(QPixmap::fromImage(tileImage).scaled(32, 32)); + this->selectedTileScene->addItem(this->selectedTilePixmapItem); +} + void TilesetEditor::onHoveredMetatileChanged(uint16_t metatileId) { QString message = QString("Metatile: 0x%1") .arg(QString("%1").arg(metatileId, 3, 16, QChar('0')).toUpper()); @@ -88,5 +114,24 @@ void TilesetEditor::onHoveredTileCleared() { } void TilesetEditor::onSelectedTileChanged(uint16_t) { - + this->drawSelectedTile(); +} + +void TilesetEditor::on_spinBox_paletteSelector_valueChanged(int paletteId) +{ + this->paletteId = paletteId; + this->tileSelector->setPaletteId(paletteId); + this->drawSelectedTile(); +} + +void TilesetEditor::on_checkBox_xFlip_stateChanged(int checked) +{ + this->tileXFlip = checked; + this->drawSelectedTile(); +} + +void TilesetEditor::on_checkBox_yFlip_stateChanged(int checked) +{ + this->tileYFlip = checked; + this->drawSelectedTile(); } diff --git a/src/ui/tileseteditortileselector.cpp b/src/ui/tileseteditortileselector.cpp index 367af1b4..09bc2d60 100644 --- a/src/ui/tileseteditortileselector.cpp +++ b/src/ui/tileseteditortileselector.cpp @@ -13,19 +13,19 @@ void TilesetEditorTileSelector::draw() { int primaryLength = this->primaryTileset->tiles->length(); int secondaryLength = this->secondaryTileset->tiles->length(); int height = totalTiles / this->numTilesWide; - QList palette = this->getCurPaletteTable(); + QList palette = Tileset::getPalette(this->paletteId, this->primaryTileset, this->secondaryTileset); QImage image(this->numTilesWide * 16, height * 16, QImage::Format_RGBA8888); QPainter painter(&image); for (uint16_t tile = 0; tile < totalTiles; tile++) { QImage tileImage; if (tile < primaryLength) { - tileImage = getColoredTileImage(tile, this->primaryTileset, this->secondaryTileset, palette).scaled(16, 16); + tileImage = getColoredTileImage(tile, this->primaryTileset, this->secondaryTileset, this->paletteId).scaled(16, 16); } else if (tile < Project::getNumTilesPrimary()) { tileImage = QImage(16, 16, QImage::Format_RGBA8888); tileImage.fill(palette.at(0)); } else if (tile < Project::getNumTilesPrimary() + secondaryLength) { - tileImage = getColoredTileImage(tile, this->primaryTileset, this->secondaryTileset, palette).scaled(16, 16); + tileImage = getColoredTileImage(tile, this->primaryTileset, this->secondaryTileset, this->paletteId).scaled(16, 16); } else { tileImage = QImage(16, 16, QImage::Format_RGBA8888); QPainter painter(&tileImage); @@ -43,15 +43,6 @@ void TilesetEditorTileSelector::draw() { this->drawSelection(); } -QList TilesetEditorTileSelector::getCurPaletteTable() { - QList paletteTable; - for (int i = 0; i < this->primaryTileset->palettes->at(this->paletteNum).length(); i++) { - paletteTable.append(this->primaryTileset->palettes->at(this->paletteNum).at(i)); - } - - return paletteTable; -} - void TilesetEditorTileSelector::select(uint16_t tile) { QPoint coords = this->getTileCoords(tile); SelectablePixmapItem::select(coords.x(), coords.y(), 0, 0); @@ -65,8 +56,8 @@ void TilesetEditorTileSelector::setTilesets(Tileset *primaryTileset, Tileset *se this->draw(); } -void TilesetEditorTileSelector::setPaletteNum(int paletteNum) { - this->paletteNum = paletteNum; +void TilesetEditorTileSelector::setPaletteId(int paletteId) { + this->paletteId = paletteId; this->draw(); } From 322238c7b82092d3eb2c31e3a8f5dc62d12b3f73 Mon Sep 17 00:00:00 2001 From: Marcus Huderle Date: Sun, 30 Sep 2018 16:15:04 -0500 Subject: [PATCH 05/15] Add metatile layer item --- forms/tileseteditor.ui | 64 +++++++++++++++++++++++++++++++-- include/ui/metatilelayersitem.h | 29 +++++++++++++++ include/ui/tileseteditor.h | 10 ++++-- porymap.pro | 2 ++ src/ui/metatilelayersitem.cpp | 48 +++++++++++++++++++++++++ src/ui/tileseteditor.cpp | 38 +++++++++++++++++--- 6 files changed, 182 insertions(+), 9 deletions(-) create mode 100644 include/ui/metatilelayersitem.h create mode 100644 src/ui/metatilelayersitem.cpp diff --git a/forms/tileseteditor.ui b/forms/tileseteditor.ui index 0eeffd04..3d7d733a 100644 --- a/forms/tileseteditor.ui +++ b/forms/tileseteditor.ui @@ -25,7 +25,7 @@ 0 0 - 363 + 308 539 @@ -207,7 +207,7 @@ 0 0 - 363 + 309 415 @@ -282,7 +282,65 @@ QFrame::Raised - + + + + + + 0 + 0 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + Bottom/Top + + + + + + + + 64 + 32 + + + + + 64 + 32 + + + + Qt::ScrollBarAlwaysOff + + + Qt::ScrollBarAlwaysOff + + + + + + + Metatile Behavior + + + + + + + + + + diff --git a/include/ui/metatilelayersitem.h b/include/ui/metatilelayersitem.h new file mode 100644 index 00000000..d2b7d243 --- /dev/null +++ b/include/ui/metatilelayersitem.h @@ -0,0 +1,29 @@ +#ifndef METATILELAYERSITEM_H +#define METATILELAYERSITEM_H + +#include "tileset.h" +#include +#include + +class MetatileLayersItem : public QObject, public QGraphicsPixmapItem { + Q_OBJECT +public: + MetatileLayersItem(Metatile *metatile, Tileset *primaryTileset, Tileset *secondaryTileset) { + this->metatile = metatile; + this->primaryTileset = primaryTileset; + this->secondaryTileset = secondaryTileset; + } + void draw(); + void setTilesets(Tileset*, Tileset*); + void setMetatile(Metatile*); +private: + Metatile* metatile; + Tileset *primaryTileset; + Tileset *secondaryTileset; +signals: + void tileChanged(int); +protected: + void mousePressEvent(QGraphicsSceneMouseEvent*); +}; + +#endif // METATILELAYERSITEM_H diff --git a/include/ui/tileseteditor.h b/include/ui/tileseteditor.h index 989fb717..084d3af1 100644 --- a/include/ui/tileseteditor.h +++ b/include/ui/tileseteditor.h @@ -5,6 +5,7 @@ #include "project.h" #include "tileseteditormetatileselector.h" #include "tileseteditortileselector.h" +#include "metatilelayersitem.h" namespace Ui { class TilesetEditor; @@ -25,6 +26,7 @@ private slots: void onHoveredTileChanged(uint16_t); void onHoveredTileCleared(); void onSelectedTileChanged(uint16_t); + void onMetatileLayerTileChanged(int); void on_spinBox_paletteSelector_valueChanged(int arg1); @@ -36,11 +38,14 @@ private: void initMetatileSelector(); void initTileSelector(); void initSelectedTileItem(); + void initMetatileLayersItem(); void drawSelectedTile(); Ui::TilesetEditor *ui; - TilesetEditorMetatileSelector *metatileSelector; - TilesetEditorTileSelector *tileSelector; + TilesetEditorMetatileSelector *metatileSelector = nullptr; + TilesetEditorTileSelector *tileSelector = nullptr; + MetatileLayersItem *metatileLayersItem = nullptr; Project *project; + Metatile *metatile; int paletteId; bool tileXFlip; bool tileYFlip; @@ -50,6 +55,7 @@ private: QGraphicsScene *tilesScene = nullptr; QGraphicsScene *selectedTileScene = nullptr; QGraphicsPixmapItem *selectedTilePixmapItem = nullptr; + QGraphicsScene *metatileLayersScene = nullptr; }; #endif // TILESETEDITOR_H diff --git a/porymap.pro b/porymap.pro index 311630d9..b0ef9c13 100644 --- a/porymap.pro +++ b/porymap.pro @@ -34,6 +34,7 @@ SOURCES += src/core/block.cpp \ src/ui/imageproviders.cpp \ src/ui/mappixmapitem.cpp \ src/ui/mapsceneeventfilter.cpp \ + src/ui/metatilelayersitem.cpp \ src/ui/metatileselector.cpp \ src/ui/movementpermissionsselector.cpp \ src/ui/neweventtoolbutton.cpp \ @@ -71,6 +72,7 @@ HEADERS += include/core/block.h \ include/ui/imageproviders.h \ include/ui/mappixmapitem.h \ include/ui/mapsceneeventfilter.h \ + include/ui/metatilelayersitem.h \ include/ui/metatileselector.h \ include/ui/movementpermissionsselector.h \ include/ui/neweventtoolbutton.h \ diff --git a/src/ui/metatilelayersitem.cpp b/src/ui/metatilelayersitem.cpp new file mode 100644 index 00000000..14e6d95c --- /dev/null +++ b/src/ui/metatilelayersitem.cpp @@ -0,0 +1,48 @@ +#include "metatilelayersitem.h" +#include "imageproviders.h" +#include +#include + +void MetatileLayersItem::draw() { + const QList tileCoords = QList{ + QPoint(0, 0), + QPoint(16, 0), + QPoint(0, 16), + QPoint(16, 16), + QPoint(32, 0), + QPoint(48, 0), + QPoint(32, 16), + QPoint(48, 16), + }; + + QPixmap pixmap(64, 32); + QPainter painter(&pixmap); + for (int i = 0; i < 8; i++) { + Tile tile = this->metatile->tiles->at(i); + QImage tileImage = getColoredTileImage(tile.tile, this->primaryTileset, this->secondaryTileset, tile.palette) + .mirrored(tile.xflip, tile.yflip) + .scaled(16, 16); + painter.drawImage(tileCoords.at(i), tileImage); + } + + this->setPixmap(pixmap); +} + +void MetatileLayersItem::setMetatile(Metatile *metatile) { + this->metatile = metatile; +} + +void MetatileLayersItem::setTilesets(Tileset *primaryTileset, Tileset *secondaryTileset) { + this->primaryTileset = primaryTileset; + this->secondaryTileset = secondaryTileset; + this->draw(); +} + +void MetatileLayersItem::mousePressEvent(QGraphicsSceneMouseEvent *event) { + QPointF pos = event->pos(); + int x = static_cast(pos.x()) / 16; + int y = static_cast(pos.y()) / 16; + int tileIndex = (x / 2 * 4) + (y * 2) + (x % 2); + qDebug() << tileIndex; + emit this->tileChanged(tileIndex); +} diff --git a/src/ui/tileseteditor.cpp b/src/ui/tileseteditor.cpp index f9774eed..8fcf9117 100644 --- a/src/ui/tileseteditor.cpp +++ b/src/ui/tileseteditor.cpp @@ -19,8 +19,10 @@ TilesetEditor::TilesetEditor(Project *project, QString primaryTilesetLabel, QStr ui->spinBox_paletteSelector->setMinimum(0); ui->spinBox_paletteSelector->setMaximum(Project::getNumPalettesTotal() - 1); this->initMetatileSelector(); + this->initMetatileLayersItem(); this->initTileSelector(); this->initSelectedTileItem(); + this->metatileSelector->select(0); } TilesetEditor::~TilesetEditor() @@ -42,7 +44,6 @@ void TilesetEditor::initMetatileSelector() this->metatilesScene = new QGraphicsScene; this->metatilesScene->addItem(this->metatileSelector); - this->metatileSelector->select(0); this->metatileSelector->draw(); this->ui->graphicsView_Metatiles->setScene(this->metatilesScene); @@ -81,6 +82,7 @@ void TilesetEditor::drawSelectedTile() { return; } + this->selectedTileScene->clear(); Tileset *primaryTileset = this->project->getTileset(this->primaryTilesetLabel); Tileset *secondaryTileset = this->project->getTileset(this->secondaryTilesetLabel); QImage tileImage = getColoredTileImage(this->tileSelector->getSelectedTile(), primaryTileset, secondaryTileset, this->paletteId) @@ -89,6 +91,19 @@ void TilesetEditor::drawSelectedTile() { this->selectedTileScene->addItem(this->selectedTilePixmapItem); } +void TilesetEditor::initMetatileLayersItem() { + Tileset *primaryTileset = this->project->getTileset(this->primaryTilesetLabel); + Tileset *secondaryTileset = this->project->getTileset(this->secondaryTilesetLabel); + Metatile *metatile = Tileset::getMetatile(this->metatileSelector->getSelectedMetatile(), primaryTileset, secondaryTileset); + this->metatileLayersItem = new MetatileLayersItem(metatile, primaryTileset, secondaryTileset); + connect(this->metatileLayersItem, SIGNAL(tileChanged(int)), + this, SLOT(onMetatileLayerTileChanged(int))); + + this->metatileLayersScene = new QGraphicsScene; + this->metatileLayersScene->addItem(this->metatileLayersItem); + this->ui->graphicsView_metatileLayers->setScene(this->metatileLayersScene); +} + void TilesetEditor::onHoveredMetatileChanged(uint16_t metatileId) { QString message = QString("Metatile: 0x%1") .arg(QString("%1").arg(metatileId, 3, 16, QChar('0')).toUpper()); @@ -99,8 +114,12 @@ void TilesetEditor::onHoveredMetatileCleared() { this->ui->statusbar->clearMessage(); } -void TilesetEditor::onSelectedMetatileChanged(uint16_t) { - +void TilesetEditor::onSelectedMetatileChanged(uint16_t metatileId) { + Tileset *primaryTileset = this->project->getTileset(this->primaryTilesetLabel); + Tileset *secondaryTileset = this->project->getTileset(this->secondaryTilesetLabel); + this->metatile = Tileset::getMetatile(metatileId, primaryTileset, secondaryTileset); + this->metatileLayersItem->setMetatile(metatile); + this->metatileLayersItem->draw(); } void TilesetEditor::onHoveredTileChanged(uint16_t tile) { @@ -113,10 +132,21 @@ void TilesetEditor::onHoveredTileCleared() { this->ui->statusbar->clearMessage(); } -void TilesetEditor::onSelectedTileChanged(uint16_t) { +void TilesetEditor::onSelectedTileChanged(uint16_t) { this->drawSelectedTile(); } +void TilesetEditor::onMetatileLayerTileChanged(int tileIndex) { + Tile tile = this->metatile->tiles->at(tileIndex); + tile.tile = this->tileSelector->getSelectedTile(); + tile.xflip = this->tileXFlip; + tile.yflip = this->tileYFlip; + tile.palette = this->paletteId; + (*this->metatile->tiles)[tileIndex] = tile; + this->metatileSelector->draw(); + this->metatileLayersItem->draw(); +} + void TilesetEditor::on_spinBox_paletteSelector_valueChanged(int paletteId) { this->paletteId = paletteId; From 428548b7e17e8ab967811052bc3dc4fe64719f92 Mon Sep 17 00:00:00 2001 From: Marcus Huderle Date: Tue, 2 Oct 2018 19:01:09 -0500 Subject: [PATCH 06/15] Add metatile attribute editing, and add tileset saving --- forms/tileseteditor.ui | 25 +++++++++++ include/core/metatile.h | 2 + include/core/tileset.h | 2 + include/project.h | 6 +++ include/ui/tileseteditor.h | 10 ++++- src/mainwindow.cpp | 1 + src/project.cpp | 83 ++++++++++++++++++++++++++++++----- src/ui/metatilelayersitem.cpp | 2 - src/ui/tileseteditor.cpp | 36 ++++++++++++++- 9 files changed, 150 insertions(+), 17 deletions(-) diff --git a/forms/tileseteditor.ui b/forms/tileseteditor.ui index 3d7d733a..57b66a1d 100644 --- a/forms/tileseteditor.ui +++ b/forms/tileseteditor.ui @@ -337,6 +337,16 @@ + + + + Layer Type + + + + + + @@ -354,8 +364,23 @@ 21 + + + File + + + + + + + Save Tileset + + + Ctrl+S + + diff --git a/include/core/metatile.h b/include/core/metatile.h index b5cb19d5..0a61f9fd 100644 --- a/include/core/metatile.h +++ b/include/core/metatile.h @@ -10,6 +10,8 @@ public: Metatile(); public: QList *tiles = nullptr; + uint8_t behavior; + uint8_t layerType; static int getBlockIndex(int); }; diff --git a/include/core/tileset.h b/include/core/tileset.h index 82113e4b..dea009eb 100644 --- a/include/core/tileset.h +++ b/include/core/tileset.h @@ -17,8 +17,10 @@ public: QString tiles_label; QString palettes_label; QString metatiles_label; + QString metatiles_path; QString callback_label; QString metatile_attrs_label; + QString metatile_attrs_path; QList *tiles = nullptr; QList *metatiles = nullptr; diff --git a/include/project.h b/include/project.h index 4efe58a6..856e3562 100644 --- a/include/project.h +++ b/include/project.h @@ -40,6 +40,8 @@ public: QStringList *secretBaseIds = nullptr; QStringList *bgEventFacingDirections = nullptr; QStringList mapsWithConnections; + QMap metatileBehaviorMap; + QMap metatileBehaviorMapInverse; QMap *map_cache; Map* loadMap(QString); @@ -83,6 +85,7 @@ public: void saveMapGroupsTable(); void saveMapConstantsHeader(); void saveHealLocationStruct(Map*); + void saveTilesets(Tileset*, Tileset*); QList* parseAsm(QString text); QStringList getSongNames(); @@ -100,6 +103,7 @@ public: void readCoordEventWeatherNames(); void readSecretBaseIds(); void readBgEventFacingDirections(); + void readMetatileBehaviors(); void loadEventPixmaps(QList objects); QMap getEventObjGfxConstants(); @@ -127,6 +131,8 @@ private: QString getMapLayoutFilepath(QString); void saveMapHeader(Map*); void saveMapConnections(Map*); + void saveTilesetMetatileAttributes(Tileset*); + void saveTilesetMetatiles(Tileset*); void updateMapsWithConnections(Map*); void saveMapsWithConnections(); void saveMapLayoutsTable(); diff --git a/include/ui/tileseteditor.h b/include/ui/tileseteditor.h index 084d3af1..9126985c 100644 --- a/include/ui/tileseteditor.h +++ b/include/ui/tileseteditor.h @@ -34,6 +34,12 @@ private slots: void on_checkBox_yFlip_stateChanged(int arg1); + void on_comboBox_metatileBehaviors_currentIndexChanged(const QString &arg1); + + void on_comboBox_layerType_currentIndexChanged(int index); + + void on_actionSave_Tileset_triggered(); + private: void initMetatileSelector(); void initTileSelector(); @@ -44,8 +50,8 @@ private: TilesetEditorMetatileSelector *metatileSelector = nullptr; TilesetEditorTileSelector *tileSelector = nullptr; MetatileLayersItem *metatileLayersItem = nullptr; - Project *project; - Metatile *metatile; + Project *project = nullptr; + Metatile *metatile = nullptr; int paletteId; bool tileXFlip; bool tileYFlip; diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 9f77938d..bba152a7 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -406,6 +406,7 @@ void MainWindow::loadDataStructures() { project->readSecretBaseIds(); project->readBgEventFacingDirections(); project->readMapsWithConnections(); + project->readMetatileBehaviors(); project->readTilesetProperties(); } diff --git a/src/project.cpp b/src/project.cpp index 63899604..5fcd5b71 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -576,6 +576,49 @@ void Project::saveHealLocationStruct(Map *map) { saveTextFile(root + "/include/constants/heal_locations.h", constants_text); } +void Project::saveTilesets(Tileset *primaryTileset, Tileset *secondaryTileset) { + saveTilesetMetatileAttributes(primaryTileset); + saveTilesetMetatileAttributes(secondaryTileset); + saveTilesetMetatiles(primaryTileset); + saveTilesetMetatiles(secondaryTileset); +} + +void Project::saveTilesetMetatileAttributes(Tileset *tileset) { + QFile attrs_file(tileset->metatile_attrs_path); + if (attrs_file.open(QIODevice::WriteOnly | QIODevice::Truncate)) { + QByteArray data; + for (Metatile *metatile : *tileset->metatiles) { + data.append(static_cast(metatile->behavior)); + data.append(static_cast((metatile->layerType << 4) & 0xF0)); + } + attrs_file.write(data); + } else { + qDebug() << QString("Could not save tileset metatile attributes file '%1'").arg(tileset->metatile_attrs_path); + } +} + +void Project::saveTilesetMetatiles(Tileset *tileset) { + QFile metatiles_file(tileset->metatiles_path); + if (metatiles_file.open(QIODevice::WriteOnly | QIODevice::Truncate)) { + QByteArray data; + for (Metatile *metatile : *tileset->metatiles) { + for (int i = 0; i < 8; i++) { + Tile tile = metatile->tiles->at(i); + uint16_t value = static_cast((tile.tile & 0x3ff) + | ((tile.xflip & 1) << 10) + | ((tile.yflip & 1) << 11) + | ((tile.palette & 0xf) << 12)); + data.append(static_cast(value & 0xff)); + data.append(static_cast((value >> 8) & 0xff)); + } + } + metatiles_file.write(data); + } else { + tileset->metatiles = new QList; + qDebug() << QString("Could not open tileset metatiles file '%1'").arg(tileset->metatiles_path); + } +} + void Project::loadMapTilesets(Map* map) { if (map->layout->has_unsaved_changes) { return; @@ -780,21 +823,19 @@ void Project::loadTilesetAssets(Tileset* tileset) { } } - QString metatiles_path; - QString metatile_attrs_path; QString metatiles_text = readTextFile(root + "/data/tilesets/metatiles.inc"); QList *metatiles_macros = parser->parseAsm(metatiles_text); QStringList *metatiles_values = getLabelValues(metatiles_macros, tileset->metatiles_label); if (!metatiles_values->isEmpty()) { - metatiles_path = root + "/" + metatiles_values->value(0).section('"', 1, 1); + tileset->metatiles_path = root + "/" + metatiles_values->value(0).section('"', 1, 1); } else { - metatiles_path = dir_path + "/metatiles.bin"; + tileset->metatiles_path = dir_path + "/metatiles.bin"; } QStringList *metatile_attrs_values = getLabelValues(metatiles_macros, tileset->metatile_attrs_label); if (!metatile_attrs_values->isEmpty()) { - metatile_attrs_path = root + "/" + metatile_attrs_values->value(0).section('"', 1, 1); + tileset->metatile_attrs_path = root + "/" + metatile_attrs_values->value(0).section('"', 1, 1); } else { - metatile_attrs_path = dir_path + "/metatile_attributes.bin"; + tileset->metatile_attrs_path = dir_path + "/metatile_attributes.bin"; } // tiles @@ -813,7 +854,7 @@ void Project::loadTilesetAssets(Tileset* tileset) { tileset->tiles = tiles; // metatiles - QFile metatiles_file(metatiles_path); + QFile metatiles_file(tileset->metatiles_path); if (metatiles_file.open(QIODevice::ReadOnly)) { QByteArray data = metatiles_file.readAll(); int num_metatiles = data.length() / 16; @@ -837,11 +878,10 @@ void Project::loadTilesetAssets(Tileset* tileset) { tileset->metatiles = metatiles; } else { tileset->metatiles = new QList; - qDebug() << QString("Could not open '%1'").arg(metatiles_path); + qDebug() << QString("Could not open tileset metatiles file '%1'").arg(tileset->metatiles_path); } - QFile attrs_file(metatile_attrs_path); - //qDebug() << metatile_attrs_path; + QFile attrs_file(tileset->metatile_attrs_path); if (attrs_file.open(QIODevice::ReadOnly)) { QByteArray data = attrs_file.readAll(); int num_metatiles = tileset->metatiles->count(); @@ -851,8 +891,13 @@ void Project::loadTilesetAssets(Tileset* tileset) { if (num_metatiles > num_metatileAttrs) num_metatiles = num_metatileAttrs; } + for (int i = 0; i < num_metatileAttrs; i++) { + int value = (static_cast(data.at(i * 2 + 1)) << 8) | static_cast(data.at(i * 2)); + tileset->metatiles->at(i)->behavior = value & 0xFF; + tileset->metatiles->at(i)->layerType = (value & 0xF000) >> 12; + } } else { - qDebug() << QString("Could not open '%1'").arg(metatile_attrs_path); + qDebug() << QString("Could not open tileset metatile attributes file '%1'").arg(tileset->metatile_attrs_path); } // palettes @@ -1249,6 +1294,22 @@ void Project::readBgEventFacingDirections() { readCDefinesSorted(filepath, prefixes, bgEventFacingDirections); } +void Project::readMetatileBehaviors() { + this->metatileBehaviorMap.clear(); + this->metatileBehaviorMapInverse.clear(); + QString filepath = root + "/include/constants/metatile_behaviors.h"; + QString text = readTextFile(filepath); + if (!text.isNull()) { + QStringList prefixes = (QStringList() << "MB_"); + this->metatileBehaviorMap = readCDefines(text, prefixes); + for (QString defineName : this->metatileBehaviorMap.keys()) { + this->metatileBehaviorMapInverse.insert(this->metatileBehaviorMap[defineName], defineName); + } + } else { + qDebug() << "Failed to read C defines file: " << filepath; + } +} + void Project::readCDefinesSorted(QString filepath, QStringList prefixes, QStringList* definesToSet) { QString text = readTextFile(filepath); if (!text.isNull()) { diff --git a/src/ui/metatilelayersitem.cpp b/src/ui/metatilelayersitem.cpp index 14e6d95c..50e6afaa 100644 --- a/src/ui/metatilelayersitem.cpp +++ b/src/ui/metatilelayersitem.cpp @@ -1,7 +1,6 @@ #include "metatilelayersitem.h" #include "imageproviders.h" #include -#include void MetatileLayersItem::draw() { const QList tileCoords = QList{ @@ -43,6 +42,5 @@ void MetatileLayersItem::mousePressEvent(QGraphicsSceneMouseEvent *event) { int x = static_cast(pos.x()) / 16; int y = static_cast(pos.y()) / 16; int tileIndex = (x / 2 * 4) + (y * 2) + (x % 2); - qDebug() << tileIndex; emit this->tileChanged(tileIndex); } diff --git a/src/ui/tileseteditor.cpp b/src/ui/tileseteditor.cpp index 8fcf9117..06a889eb 100644 --- a/src/ui/tileseteditor.cpp +++ b/src/ui/tileseteditor.cpp @@ -16,8 +16,16 @@ TilesetEditor::TilesetEditor(Project *project, QString primaryTilesetLabel, QStr this->primaryTilesetLabel = primaryTilesetLabel; this->secondaryTilesetLabel = secondaryTilesetLabel; - ui->spinBox_paletteSelector->setMinimum(0); - ui->spinBox_paletteSelector->setMaximum(Project::getNumPalettesTotal() - 1); + QList sortedBehaviors; + for (int num : project->metatileBehaviorMapInverse.keys()) { + this->ui->comboBox_metatileBehaviors->addItem(project->metatileBehaviorMapInverse[num], num); + } + this->ui->comboBox_layerType->addItem("Normal - Middle/Top", 0); + this->ui->comboBox_layerType->addItem("Covered - Bottom/Middle", 1); + this->ui->comboBox_layerType->addItem("Split - Bottom/Top", 2); + this->ui->spinBox_paletteSelector->setMinimum(0); + this->ui->spinBox_paletteSelector->setMaximum(Project::getNumPalettesTotal() - 1); + this->initMetatileSelector(); this->initMetatileLayersItem(); this->initTileSelector(); @@ -120,6 +128,8 @@ void TilesetEditor::onSelectedMetatileChanged(uint16_t metatileId) { this->metatile = Tileset::getMetatile(metatileId, primaryTileset, secondaryTileset); this->metatileLayersItem->setMetatile(metatile); this->metatileLayersItem->draw(); + this->ui->comboBox_metatileBehaviors->setCurrentIndex(this->ui->comboBox_metatileBehaviors->findData(this->metatile->behavior)); + this->ui->comboBox_layerType->setCurrentIndex(this->ui->comboBox_layerType->findData(this->metatile->layerType)); } void TilesetEditor::onHoveredTileChanged(uint16_t tile) { @@ -165,3 +175,25 @@ void TilesetEditor::on_checkBox_yFlip_stateChanged(int checked) this->tileYFlip = checked; this->drawSelectedTile(); } + +void TilesetEditor::on_comboBox_metatileBehaviors_currentIndexChanged(const QString &metatileBehavior) +{ + if (this->metatile) { + this->metatile->behavior = static_cast(project->metatileBehaviorMap[metatileBehavior]); + } +} + + +void TilesetEditor::on_comboBox_layerType_currentIndexChanged(int layerType) +{ + if (this->metatile) { + this->metatile->layerType = static_cast(layerType); + } +} + +void TilesetEditor::on_actionSave_Tileset_triggered() +{ + Tileset *primaryTileset = this->project->getTileset(this->primaryTilesetLabel); + Tileset *secondaryTileset = this->project->getTileset(this->secondaryTilesetLabel); + this->project->saveTilesets(primaryTileset, secondaryTileset); +} From 8d38783833ba950c361c1a115d348b4d1f413f07 Mon Sep 17 00:00:00 2001 From: Marcus Huderle Date: Tue, 2 Oct 2018 19:01:15 -0500 Subject: [PATCH 07/15] Add ability to save tileset changes --- include/core/metatile.h | 1 + include/core/tileset.h | 2 ++ include/editor.h | 4 +-- include/mainwindow.h | 1 + include/project.h | 4 +-- include/ui/tileseteditor.h | 7 +++-- include/ui/tileseteditormetatileselector.h | 4 +-- src/core/map.cpp | 2 +- src/core/metatile.cpp | 11 +++++++ src/core/tileset.cpp | 32 ++++++++++++++++++++ src/editor.cpp | 11 +++---- src/mainwindow.cpp | 6 ++++ src/project.cpp | 18 ++++++++---- src/ui/tileseteditor.cpp | 34 +++++++++------------- 14 files changed, 97 insertions(+), 40 deletions(-) diff --git a/include/core/metatile.h b/include/core/metatile.h index 0a61f9fd..4f280608 100644 --- a/include/core/metatile.h +++ b/include/core/metatile.h @@ -13,6 +13,7 @@ public: uint8_t behavior; uint8_t layerType; + Metatile *copy(); static int getBlockIndex(int); }; diff --git a/include/core/tileset.h b/include/core/tileset.h index dea009eb..c3d55b1d 100644 --- a/include/core/tileset.h +++ b/include/core/tileset.h @@ -26,6 +26,8 @@ public: QList *metatiles = nullptr; QList> *palettes = nullptr; + Tileset* copy(); + static Tileset* getBlockTileset(int, Tileset*, Tileset*); static Metatile* getMetatile(int, Tileset*, Tileset*); static QList> getBlockPalettes(Tileset*, Tileset*); diff --git a/include/editor.h b/include/editor.h index 31f11586..ac95c761 100644 --- a/include/editor.h +++ b/include/editor.h @@ -68,8 +68,8 @@ public: void updateDiveMap(QString mapName); void updateEmergeMap(QString mapName); void setSelectedConnectionFromMap(QString mapName); - void updatePrimaryTileset(QString tilesetLabel); - void updateSecondaryTileset(QString tilesetLabel); + void updatePrimaryTileset(QString tilesetLabel, bool forceLoad = false); + void updateSecondaryTileset(QString tilesetLabel, bool forceLoad = false); void toggleBorderVisibility(bool visible); Tileset *getCurrentMapPrimaryTileset(); diff --git a/include/mainwindow.h b/include/mainwindow.h index 8178b625..a120644c 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -43,6 +43,7 @@ private slots: void onLoadMapRequested(QString, QString); void onMapChanged(Map *map); void onMapNeedsRedrawing(); + void onTilesetsSaved(QString, QString); void on_action_Save_triggered(); void on_tabWidget_2_currentChanged(int index); diff --git a/include/project.h b/include/project.h index 856e3562..4aa8d35e 100644 --- a/include/project.h +++ b/include/project.h @@ -48,8 +48,8 @@ public: Map* getMap(QString); QMap *tileset_cache = nullptr; - Tileset* loadTileset(QString); - Tileset* getTileset(QString); + Tileset* loadTileset(QString, Tileset *tileset = nullptr); + Tileset* getTileset(QString, bool forceLoad = false); Blockdata* readBlockdata(QString); void loadBlockdata(Map*); diff --git a/include/ui/tileseteditor.h b/include/ui/tileseteditor.h index 9126985c..2bef6227 100644 --- a/include/ui/tileseteditor.h +++ b/include/ui/tileseteditor.h @@ -55,13 +55,16 @@ private: int paletteId; bool tileXFlip; bool tileYFlip; - QString primaryTilesetLabel; - QString secondaryTilesetLabel; + Tileset *primaryTileset; + Tileset *secondaryTileset; QGraphicsScene *metatilesScene = nullptr; QGraphicsScene *tilesScene = nullptr; QGraphicsScene *selectedTileScene = nullptr; QGraphicsPixmapItem *selectedTilePixmapItem = nullptr; QGraphicsScene *metatileLayersScene = nullptr; + +signals: + void tilesetsSaved(QString, QString); }; #endif // TILESETEDITOR_H diff --git a/include/ui/tileseteditormetatileselector.h b/include/ui/tileseteditormetatileselector.h index eb8d45fe..4b1a0d49 100644 --- a/include/ui/tileseteditormetatileselector.h +++ b/include/ui/tileseteditormetatileselector.h @@ -26,8 +26,8 @@ protected: void hoverLeaveEvent(QGraphicsSceneHoverEvent*); private: - Tileset *primaryTileset; - Tileset *secondaryTileset; + Tileset *primaryTileset = nullptr; + Tileset *secondaryTileset = nullptr; uint16_t selectedMetatile; int numMetatilesWide; void updateSelectedMetatile(); diff --git a/src/core/map.cpp b/src/core/map.cpp index 3954df06..185306e5 100644 --- a/src/core/map.cpp +++ b/src/core/map.cpp @@ -226,7 +226,7 @@ QPixmap Map::renderBorder() { } QPixmap Map::renderConnection(MapConnection connection) { - render(); + render(true); int x, y, w, h; if (connection.direction == "up") { x = 0; diff --git a/src/core/metatile.cpp b/src/core/metatile.cpp index 6dff9dc6..a44b4fa3 100644 --- a/src/core/metatile.cpp +++ b/src/core/metatile.cpp @@ -7,6 +7,17 @@ Metatile::Metatile() tiles = new QList; } +Metatile* Metatile::copy() { + Metatile *copy = new Metatile; + copy->behavior = this->behavior; + copy->layerType = this->layerType; + copy->tiles = new QList; + for (Tile tile : *this->tiles) { + copy->tiles->append(tile); + } + return copy; +} + int Metatile::getBlockIndex(int index) { if (index < Project::getNumMetatilesPrimary()) { return index; diff --git a/src/core/tileset.cpp b/src/core/tileset.cpp index 36187c02..5bb51e23 100644 --- a/src/core/tileset.cpp +++ b/src/core/tileset.cpp @@ -11,6 +11,38 @@ Tileset::Tileset() } +Tileset* Tileset::copy() { + Tileset *copy = new Tileset; + copy->name = this->name; + copy->is_compressed = this->is_compressed; + copy->is_secondary = this->is_secondary; + copy->padding = this->padding; + copy->tiles_label = this->tiles_label; + copy->palettes_label = this->palettes_label; + copy->metatiles_label = this->metatiles_label; + copy->metatiles_path = this->metatiles_path; + copy->callback_label = this->callback_label; + copy->metatile_attrs_label = this->metatile_attrs_label; + copy->metatile_attrs_path = this->metatile_attrs_path; + copy->tiles = new QList; + for (QImage tile : *this->tiles) { + copy->tiles->append(tile.copy()); + } + copy->metatiles = new QList; + for (Metatile *metatile : *this->metatiles) { + copy->metatiles->append(metatile->copy()); + } + copy->palettes = new QList>; + for (QList palette : *this->palettes) { + QList copyPalette; + for (QRgb color : palette) { + copyPalette.append(color); + } + copy->palettes->append(copyPalette); + } + return copy; +} + Tileset* Tileset::getBlockTileset(int metatile_index, Tileset *primaryTileset, Tileset *secondaryTileset) { if (metatile_index < Project::getNumMetatilesPrimary()) { return primaryTileset; diff --git a/src/editor.cpp b/src/editor.cpp index 6da57f69..878e4a70 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -961,22 +961,23 @@ void Editor::updateDiveEmergeMap(QString mapName, QString direction) { ui->label_NumConnections->setText(QString::number(map->connections.length())); } -void Editor::updatePrimaryTileset(QString tilesetLabel) +void Editor::updatePrimaryTileset(QString tilesetLabel, bool forceLoad) { - if (map->layout->tileset_primary_label != tilesetLabel) + if (map->layout->tileset_primary_label != tilesetLabel || forceLoad) { + qDebug() << "updatePrimaryTileset"; map->layout->tileset_primary_label = tilesetLabel; - map->layout->tileset_primary = project->getTileset(tilesetLabel); + map->layout->tileset_primary = project->getTileset(tilesetLabel, forceLoad); emit tilesetChanged(map->name); } } -void Editor::updateSecondaryTileset(QString tilesetLabel) +void Editor::updateSecondaryTileset(QString tilesetLabel, bool forceLoad) { if (map->layout->tileset_secondary_label != tilesetLabel) { map->layout->tileset_secondary_label = tilesetLabel; - map->layout->tileset_secondary = project->getTileset(tilesetLabel); + map->layout->tileset_secondary = project->getTileset(tilesetLabel, forceLoad); emit tilesetChanged(map->name); } } diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index bba152a7..280e770c 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -1104,6 +1104,11 @@ void MainWindow::onMapNeedsRedrawing() { redrawMapScene(); } +void MainWindow::onTilesetsSaved(QString primaryTilesetLabel, QString secondaryTilesetLabel) { + this->editor->updatePrimaryTileset(primaryTilesetLabel, true); + this->editor->updateSecondaryTileset(secondaryTilesetLabel, true); +} + void MainWindow::on_action_Export_Map_Image_triggered() { QString defaultFilepath = QString("%1/%2.png").arg(editor->project->root).arg(editor->map->name); @@ -1233,6 +1238,7 @@ void MainWindow::on_actionTileset_Editor_triggered() { if (!this->tilesetEditor) { this->tilesetEditor = new TilesetEditor(this->editor->project, this->editor->map->layout->tileset_primary_label, this->editor->map->layout->tileset_secondary_label); + connect(this->tilesetEditor, SIGNAL(tilesetsSaved(QString, QString)), this, SLOT(onTilesetsSaved(QString, QString))); } if (!this->tilesetEditor->isVisible()) { diff --git a/src/project.cpp b/src/project.cpp index 5fcd5b71..2bc67c03 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -628,12 +628,14 @@ void Project::loadMapTilesets(Map* map) { map->layout->tileset_secondary = getTileset(map->layout->tileset_secondary_label); } -Tileset* Project::loadTileset(QString label) { +Tileset* Project::loadTileset(QString label, Tileset *tileset) { ParseUtil *parser = new ParseUtil; QString headers_text = readTextFile(root + "/data/tilesets/headers.inc"); QStringList *values = getLabelValues(parser->parseAsm(headers_text), label); - Tileset *tileset = new Tileset; + if (tileset == nullptr) { + tileset = new Tileset; + } tileset->name = label; tileset->is_compressed = values->value(0); tileset->is_secondary = values->value(1); @@ -793,7 +795,8 @@ void Project::loadTilesetAssets(Tileset* tileset) { if (tileset->name.isNull()) { return; } - QString dir_path = root + "/data/tilesets/" + category + "/" + tileset->name.replace("gTileset_", "").toLower(); + QString tilesetName = tileset->name; + QString dir_path = root + "/data/tilesets/" + category + "/" + tilesetName.replace("gTileset_", "").toLower(); QString graphics_text = readTextFile(root + "/data/tilesets/graphics.inc"); QList *graphics = parser->parseAsm(graphics_text); @@ -958,11 +961,16 @@ Map* Project::getMap(QString map_name) { } } -Tileset* Project::getTileset(QString label) { +Tileset* Project::getTileset(QString label, bool forceLoad) { + Tileset *existingTileset = nullptr; if (tileset_cache->contains(label)) { + existingTileset = tileset_cache->value(label); + } + + if (existingTileset && !forceLoad) { return tileset_cache->value(label); } else { - Tileset *tileset = loadTileset(label); + Tileset *tileset = loadTileset(label, existingTileset); return tileset; } } diff --git a/src/ui/tileseteditor.cpp b/src/ui/tileseteditor.cpp index 06a889eb..774e4a10 100644 --- a/src/ui/tileseteditor.cpp +++ b/src/ui/tileseteditor.cpp @@ -13,8 +13,11 @@ TilesetEditor::TilesetEditor(Project *project, QString primaryTilesetLabel, QStr this->tileXFlip = ui->checkBox_xFlip->isChecked(); this->tileYFlip = ui->checkBox_yFlip->isChecked(); this->paletteId = ui->spinBox_paletteSelector->value(); - this->primaryTilesetLabel = primaryTilesetLabel; - this->secondaryTilesetLabel = secondaryTilesetLabel; + + Tileset *primaryTileset = project->getTileset(primaryTilesetLabel); + Tileset *secondaryTileset = project->getTileset(secondaryTilesetLabel); + this->primaryTileset = primaryTileset->copy(); + this->secondaryTileset = secondaryTileset->copy(); QList sortedBehaviors; for (int num : project->metatileBehaviorMapInverse.keys()) { @@ -40,9 +43,7 @@ TilesetEditor::~TilesetEditor() void TilesetEditor::initMetatileSelector() { - Tileset *primaryTileset = this->project->getTileset(this->primaryTilesetLabel); - Tileset *secondaryTileset = this->project->getTileset(this->secondaryTilesetLabel); - this->metatileSelector = new TilesetEditorMetatileSelector(primaryTileset, secondaryTileset); + this->metatileSelector = new TilesetEditorMetatileSelector(this->primaryTileset, this->secondaryTileset); connect(this->metatileSelector, SIGNAL(hoveredMetatileChanged(uint16_t)), this, SLOT(onHoveredMetatileChanged(uint16_t))); connect(this->metatileSelector, SIGNAL(hoveredMetatileCleared()), @@ -60,9 +61,7 @@ void TilesetEditor::initMetatileSelector() void TilesetEditor::initTileSelector() { - Tileset *primaryTileset = this->project->getTileset(this->primaryTilesetLabel); - Tileset *secondaryTileset = this->project->getTileset(this->secondaryTilesetLabel); - this->tileSelector = new TilesetEditorTileSelector(primaryTileset, secondaryTileset); + this->tileSelector = new TilesetEditorTileSelector(this->primaryTileset, this->secondaryTileset); connect(this->tileSelector, SIGNAL(hoveredTileChanged(uint16_t)), this, SLOT(onHoveredTileChanged(uint16_t))); connect(this->tileSelector, SIGNAL(hoveredTileCleared()), @@ -91,19 +90,15 @@ void TilesetEditor::drawSelectedTile() { } this->selectedTileScene->clear(); - Tileset *primaryTileset = this->project->getTileset(this->primaryTilesetLabel); - Tileset *secondaryTileset = this->project->getTileset(this->secondaryTilesetLabel); - QImage tileImage = getColoredTileImage(this->tileSelector->getSelectedTile(), primaryTileset, secondaryTileset, this->paletteId) + QImage tileImage = getColoredTileImage(this->tileSelector->getSelectedTile(), this->primaryTileset, this->secondaryTileset, this->paletteId) .mirrored(this->tileXFlip, this->tileYFlip); this->selectedTilePixmapItem = new QGraphicsPixmapItem(QPixmap::fromImage(tileImage).scaled(32, 32)); this->selectedTileScene->addItem(this->selectedTilePixmapItem); } void TilesetEditor::initMetatileLayersItem() { - Tileset *primaryTileset = this->project->getTileset(this->primaryTilesetLabel); - Tileset *secondaryTileset = this->project->getTileset(this->secondaryTilesetLabel); - Metatile *metatile = Tileset::getMetatile(this->metatileSelector->getSelectedMetatile(), primaryTileset, secondaryTileset); - this->metatileLayersItem = new MetatileLayersItem(metatile, primaryTileset, secondaryTileset); + Metatile *metatile = Tileset::getMetatile(this->metatileSelector->getSelectedMetatile(), this->primaryTileset, this->secondaryTileset); + this->metatileLayersItem = new MetatileLayersItem(metatile, this->primaryTileset, this->secondaryTileset); connect(this->metatileLayersItem, SIGNAL(tileChanged(int)), this, SLOT(onMetatileLayerTileChanged(int))); @@ -123,9 +118,7 @@ void TilesetEditor::onHoveredMetatileCleared() { } void TilesetEditor::onSelectedMetatileChanged(uint16_t metatileId) { - Tileset *primaryTileset = this->project->getTileset(this->primaryTilesetLabel); - Tileset *secondaryTileset = this->project->getTileset(this->secondaryTilesetLabel); - this->metatile = Tileset::getMetatile(metatileId, primaryTileset, secondaryTileset); + this->metatile = Tileset::getMetatile(metatileId, this->primaryTileset, this->secondaryTileset); this->metatileLayersItem->setMetatile(metatile); this->metatileLayersItem->draw(); this->ui->comboBox_metatileBehaviors->setCurrentIndex(this->ui->comboBox_metatileBehaviors->findData(this->metatile->behavior)); @@ -193,7 +186,6 @@ void TilesetEditor::on_comboBox_layerType_currentIndexChanged(int layerType) void TilesetEditor::on_actionSave_Tileset_triggered() { - Tileset *primaryTileset = this->project->getTileset(this->primaryTilesetLabel); - Tileset *secondaryTileset = this->project->getTileset(this->secondaryTilesetLabel); - this->project->saveTilesets(primaryTileset, secondaryTileset); + this->project->saveTilesets(this->primaryTileset, this->secondaryTileset); + emit this->tilesetsSaved(this->primaryTileset->name, this->secondaryTileset->name); } From 0c7ecebe0baa4e3055f777750abe9105b5b8919c Mon Sep 17 00:00:00 2001 From: Marcus Huderle Date: Tue, 2 Oct 2018 19:01:18 -0500 Subject: [PATCH 08/15] Keep tileset editor in sync with currently opened map --- include/mainwindow.h | 1 + include/ui/tileseteditor.h | 1 + include/ui/tileseteditormetatileselector.h | 1 + src/mainwindow.cpp | 7 +++++++ src/ui/tileseteditor.cpp | 15 +++++++++++++++ src/ui/tileseteditormetatileselector.cpp | 19 +++++++++++-------- 6 files changed, 36 insertions(+), 8 deletions(-) diff --git a/include/mainwindow.h b/include/mainwindow.h index a120644c..9ba488b8 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -157,6 +157,7 @@ private: void initEditor(); void loadUserSettings(); void openRecentProject(); + void updateTilesetEditor(); }; enum MapListUserRoles { diff --git a/include/ui/tileseteditor.h b/include/ui/tileseteditor.h index 2bef6227..c179bfd0 100644 --- a/include/ui/tileseteditor.h +++ b/include/ui/tileseteditor.h @@ -18,6 +18,7 @@ class TilesetEditor : public QMainWindow public: explicit TilesetEditor(Project*, QString, QString, QWidget *parent = nullptr); ~TilesetEditor(); + void setTilesets(QString, QString); private slots: void onHoveredMetatileChanged(uint16_t); diff --git a/include/ui/tileseteditormetatileselector.h b/include/ui/tileseteditormetatileselector.h index 4b1a0d49..3da82721 100644 --- a/include/ui/tileseteditormetatileselector.h +++ b/include/ui/tileseteditormetatileselector.h @@ -33,6 +33,7 @@ private: void updateSelectedMetatile(); uint16_t getMetatileId(int x, int y); QPoint getMetatileIdCoords(uint16_t); + uint16_t getValidMetatileId(uint16_t); signals: void hoveredMetatileChanged(uint16_t); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 280e770c..83e0dccb 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -196,6 +196,7 @@ void MainWindow::setMap(QString map_name, bool scrollTreeView) { setRecentMap(map_name); updateMapList(); + updateTilesetEditor(); } void MainWindow::redrawMapScene() @@ -529,6 +530,12 @@ void MainWindow::onTilesetChanged(QString mapName) setMap(mapName); } +void MainWindow::updateTilesetEditor() { + if (this->tilesetEditor) { + this->tilesetEditor->setTilesets(editor->ui->comboBox_PrimaryTileset->currentText(), editor->ui->comboBox_SecondaryTileset->currentText()); + } +} + void MainWindow::currentMetatilesSelectionChanged() { ui->graphicsView_currentMetatileSelection->setFixedSize(editor->scene_current_metatile_selection_item->pixmap().width() + 2, editor->scene_current_metatile_selection_item->pixmap().height() + 2); diff --git a/src/ui/tileseteditor.cpp b/src/ui/tileseteditor.cpp index 774e4a10..871c869b 100644 --- a/src/ui/tileseteditor.cpp +++ b/src/ui/tileseteditor.cpp @@ -41,6 +41,21 @@ TilesetEditor::~TilesetEditor() delete ui; } +void TilesetEditor::setTilesets(QString primaryTilesetLabel, QString secondaryTilesetLabel) { + delete this->primaryTileset; + delete this->secondaryTileset; + Tileset *primaryTileset = project->getTileset(primaryTilesetLabel); + Tileset *secondaryTileset = project->getTileset(secondaryTilesetLabel); + this->primaryTileset = primaryTileset->copy(); + this->secondaryTileset = secondaryTileset->copy(); + + this->metatileSelector->setTilesets(this->primaryTileset, this->secondaryTileset); + this->tileSelector->setTilesets(this->primaryTileset, this->secondaryTileset); + this->metatileLayersItem->setTilesets(this->primaryTileset, this->secondaryTileset); + this->metatileSelector->select(this->metatileSelector->getSelectedMetatile()); + this->drawSelectedTile(); +} + void TilesetEditor::initMetatileSelector() { this->metatileSelector = new TilesetEditorMetatileSelector(this->primaryTileset, this->secondaryTileset); diff --git a/src/ui/tileseteditormetatileselector.cpp b/src/ui/tileseteditormetatileselector.cpp index a5e607f7..852ab0e9 100644 --- a/src/ui/tileseteditormetatileselector.cpp +++ b/src/ui/tileseteditormetatileselector.cpp @@ -32,6 +32,7 @@ void TilesetEditorMetatileSelector::draw() { } void TilesetEditorMetatileSelector::select(uint16_t metatileId) { + metatileId = this->getValidMetatileId(metatileId); QPoint coords = this->getMetatileIdCoords(metatileId); SelectablePixmapItem::select(coords.x(), coords.y(), 0, 0); this->selectedMetatile = metatileId; @@ -95,17 +96,19 @@ void TilesetEditorMetatileSelector::hoverLeaveEvent(QGraphicsSceneHoverEvent*) { } QPoint TilesetEditorMetatileSelector::getMetatileIdCoords(uint16_t metatileId) { - if (metatileId >= Project::getNumMetatilesTotal() - || (metatileId < Project::getNumMetatilesPrimary() && metatileId >= this->primaryTileset->metatiles->length()) - || (metatileId < Project::getNumMetatilesTotal() && metatileId >= Project::getNumMetatilesPrimary() + this->secondaryTileset->metatiles->length())) - { - // Invalid metatile id. - return QPoint(0, 0); - } - int index = metatileId < Project::getNumMetatilesPrimary() ? metatileId : metatileId - Project::getNumMetatilesPrimary() + this->primaryTileset->metatiles->length(); return QPoint(index % this->numMetatilesWide, index / this->numMetatilesWide); } +uint16_t TilesetEditorMetatileSelector::getValidMetatileId(uint16_t metatileId) { + if (metatileId >= Project::getNumMetatilesTotal() + || (metatileId < Project::getNumMetatilesPrimary() && metatileId >= this->primaryTileset->metatiles->length()) + || (metatileId < Project::getNumMetatilesTotal() && metatileId >= Project::getNumMetatilesPrimary() + this->secondaryTileset->metatiles->length())) + { + return 0; + } + return metatileId; +} + From a77b76988b25706ffbef7c1b4d2d9941ea5c5b61 Mon Sep 17 00:00:00 2001 From: Marcus Huderle Date: Tue, 2 Oct 2018 19:01:21 -0500 Subject: [PATCH 09/15] Fix small UI bugs in tileset editor --- forms/tileseteditor.ui | 18 ++++++++++++++++-- src/ui/imageproviders.cpp | 11 +++++++++-- src/ui/selectablepixmapitem.cpp | 4 ++++ src/ui/tileseteditor.cpp | 7 ++++++- 4 files changed, 35 insertions(+), 5 deletions(-) diff --git a/forms/tileseteditor.ui b/forms/tileseteditor.ui index 57b66a1d..db1dec68 100644 --- a/forms/tileseteditor.ui +++ b/forms/tileseteditor.ui @@ -70,7 +70,14 @@ - + + + Qt::ScrollBarAlwaysOff + + + Qt::ScrollBarAlwaysOff + + @@ -239,7 +246,14 @@ - + + + Qt::ScrollBarAlwaysOff + + + Qt::ScrollBarAlwaysOff + + diff --git a/src/ui/imageproviders.cpp b/src/ui/imageproviders.cpp index 2a1bc5ef..b9a6a6ad 100644 --- a/src/ui/imageproviders.cpp +++ b/src/ui/imageproviders.cpp @@ -83,8 +83,15 @@ QImage getTileImage(uint16_t tile, Tileset *primaryTileset, Tileset *secondaryTi QImage getColoredTileImage(uint16_t tile, Tileset *primaryTileset, Tileset *secondaryTileset, int paletteId) { QList palette = Tileset::getPalette(paletteId, primaryTileset, secondaryTileset); QImage tileImage = getTileImage(tile, primaryTileset, secondaryTileset); - for (int i = 0; i < 16; i++) { - tileImage.setColor(i, palette.at(i)); + if (tileImage.isNull()) { + tileImage = QImage(16, 16, QImage::Format_RGBA8888); + QPainter painter(&tileImage); + painter.fillRect(0, 0, 16, 16, palette.at(0)); + } else { + for (int i = 0; i < 16; i++) { + tileImage.setColor(i, palette.at(i)); + } } + return tileImage; } diff --git a/src/ui/selectablepixmapitem.cpp b/src/ui/selectablepixmapitem.cpp index 5dcd252f..dbfbaa34 100644 --- a/src/ui/selectablepixmapitem.cpp +++ b/src/ui/selectablepixmapitem.cpp @@ -80,6 +80,10 @@ void SelectablePixmapItem::updateSelection(int x, int y) QPoint SelectablePixmapItem::getCellPos(QPointF pos) { + if (pos.x() < 0) pos.setX(0); + if (pos.y() < 0) pos.setY(0); + if (pos.x() >= this->pixmap().width()) pos.setX(this->pixmap().width() - 1); + if (pos.y() >= this->pixmap().height()) pos.setY(this->pixmap().height() - 1); return QPoint(static_cast(pos.x()) / this->cellWidth, static_cast(pos.y()) / this->cellHeight); } diff --git a/src/ui/tileseteditor.cpp b/src/ui/tileseteditor.cpp index 871c869b..033d94c9 100644 --- a/src/ui/tileseteditor.cpp +++ b/src/ui/tileseteditor.cpp @@ -1,7 +1,6 @@ #include "tileseteditor.h" #include "ui_tileseteditor.h" #include "imageproviders.h" -#include TilesetEditor::TilesetEditor(Project *project, QString primaryTilesetLabel, QString secondaryTilesetLabel, QWidget *parent) : QMainWindow(parent), @@ -54,6 +53,11 @@ void TilesetEditor::setTilesets(QString primaryTilesetLabel, QString secondaryTi this->metatileLayersItem->setTilesets(this->primaryTileset, this->secondaryTileset); this->metatileSelector->select(this->metatileSelector->getSelectedMetatile()); this->drawSelectedTile(); + + this->ui->graphicsView_Tiles->setSceneRect(0, 0, this->tileSelector->pixmap().width() + 2, this->tileSelector->pixmap().height() + 2); + this->ui->graphicsView_Tiles->setFixedSize(this->tileSelector->pixmap().width() + 2, this->tileSelector->pixmap().height() + 2); + this->ui->graphicsView_Metatiles->setSceneRect(0, 0, this->metatileSelector->pixmap().width() + 2, this->metatileSelector->pixmap().height() + 2); + this->ui->graphicsView_Metatiles->setFixedSize(this->metatileSelector->pixmap().width() + 2, this->metatileSelector->pixmap().height() + 2); } void TilesetEditor::initMetatileSelector() @@ -203,4 +207,5 @@ void TilesetEditor::on_actionSave_Tileset_triggered() { this->project->saveTilesets(this->primaryTileset, this->secondaryTileset); emit this->tilesetsSaved(this->primaryTileset->name, this->secondaryTileset->name); + this->ui->statusbar->showMessage(QString("Saved primary and secondary Tilesets!"), 5000); } From 3ca284d5f3fd7005e9c8512477ba0dffde7486fa Mon Sep 17 00:00:00 2001 From: Marcus Huderle Date: Tue, 2 Oct 2018 19:01:24 -0500 Subject: [PATCH 10/15] Add ability to import new tiles --- forms/tileseteditor.ui | 13 ++++++ include/core/tileset.h | 2 + include/project.h | 3 ++ include/ui/tileseteditor.h | 6 +++ src/core/tileset.cpp | 2 + src/editor.cpp | 3 +- src/mainwindow.cpp | 2 +- src/project.cpp | 90 +++++++++++++++++++++----------------- src/ui/tileseteditor.cpp | 80 +++++++++++++++++++++++++++++++++ 9 files changed, 159 insertions(+), 42 deletions(-) diff --git a/forms/tileseteditor.ui b/forms/tileseteditor.ui index db1dec68..735606d2 100644 --- a/forms/tileseteditor.ui +++ b/forms/tileseteditor.ui @@ -383,6 +383,9 @@ File + + + @@ -395,6 +398,16 @@ Ctrl+S + + + Import Primary Tiles + + + + + Import Secondary Tiles + + diff --git a/include/core/tileset.h b/include/core/tileset.h index c3d55b1d..aea9f458 100644 --- a/include/core/tileset.h +++ b/include/core/tileset.h @@ -21,6 +21,8 @@ public: QString callback_label; QString metatile_attrs_label; QString metatile_attrs_path; + QString tilesImagePath; + QImage tilesImage; QList *tiles = nullptr; QList *metatiles = nullptr; diff --git a/include/project.h b/include/project.h index 4aa8d35e..21acd40a 100644 --- a/include/project.h +++ b/include/project.h @@ -74,6 +74,8 @@ public: void readMapsWithConnections(); void loadMapTilesets(Map*); void loadTilesetAssets(Tileset*); + void loadTilesetTiles(Tileset*, QImage); + void loadTilesetMetatiles(Tileset*); void saveBlockdata(Map*); void saveMapBorder(Map*); @@ -133,6 +135,7 @@ private: void saveMapConnections(Map*); void saveTilesetMetatileAttributes(Tileset*); void saveTilesetMetatiles(Tileset*); + void saveTilesetTilesImage(Tileset*); void updateMapsWithConnections(Map*); void saveMapsWithConnections(); void saveMapLayoutsTable(); diff --git a/include/ui/tileseteditor.h b/include/ui/tileseteditor.h index c179bfd0..9b6d6e67 100644 --- a/include/ui/tileseteditor.h +++ b/include/ui/tileseteditor.h @@ -41,12 +41,18 @@ private slots: void on_actionSave_Tileset_triggered(); + void on_actionImport_Primary_Tiles_triggered(); + + void on_actionImport_Secondary_Tiles_triggered(); + private: void initMetatileSelector(); void initTileSelector(); void initSelectedTileItem(); void initMetatileLayersItem(); void drawSelectedTile(); + void importTilesetTiles(Tileset*, bool); + void refresh(); Ui::TilesetEditor *ui; TilesetEditorMetatileSelector *metatileSelector = nullptr; TilesetEditorTileSelector *tileSelector = nullptr; diff --git a/src/core/tileset.cpp b/src/core/tileset.cpp index 5bb51e23..f62135ad 100644 --- a/src/core/tileset.cpp +++ b/src/core/tileset.cpp @@ -24,6 +24,8 @@ Tileset* Tileset::copy() { copy->callback_label = this->callback_label; copy->metatile_attrs_label = this->metatile_attrs_label; copy->metatile_attrs_path = this->metatile_attrs_path; + copy->tilesImage = this->tilesImage.copy(); + copy->tilesImagePath = this->tilesImagePath; copy->tiles = new QList; for (QImage tile : *this->tiles) { copy->tiles->append(tile.copy()); diff --git a/src/editor.cpp b/src/editor.cpp index 878e4a70..08f0c766 100644 --- a/src/editor.cpp +++ b/src/editor.cpp @@ -965,7 +965,6 @@ void Editor::updatePrimaryTileset(QString tilesetLabel, bool forceLoad) { if (map->layout->tileset_primary_label != tilesetLabel || forceLoad) { - qDebug() << "updatePrimaryTileset"; map->layout->tileset_primary_label = tilesetLabel; map->layout->tileset_primary = project->getTileset(tilesetLabel, forceLoad); emit tilesetChanged(map->name); @@ -974,7 +973,7 @@ void Editor::updatePrimaryTileset(QString tilesetLabel, bool forceLoad) void Editor::updateSecondaryTileset(QString tilesetLabel, bool forceLoad) { - if (map->layout->tileset_secondary_label != tilesetLabel) + if (map->layout->tileset_secondary_label != tilesetLabel || forceLoad) { map->layout->tileset_secondary_label = tilesetLabel; map->layout->tileset_secondary = project->getTileset(tilesetLabel, forceLoad); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 83e0dccb..7f64fdca 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -1244,7 +1244,7 @@ void MainWindow::on_checkBox_ToggleBorder_stateChanged(int selected) void MainWindow::on_actionTileset_Editor_triggered() { if (!this->tilesetEditor) { - this->tilesetEditor = new TilesetEditor(this->editor->project, this->editor->map->layout->tileset_primary_label, this->editor->map->layout->tileset_secondary_label); + this->tilesetEditor = new TilesetEditor(this->editor->project, this->editor->map->layout->tileset_primary_label, this->editor->map->layout->tileset_secondary_label, this); connect(this->tilesetEditor, SIGNAL(tilesetsSaved(QString, QString)), this, SLOT(onTilesetsSaved(QString, QString))); } diff --git a/src/project.cpp b/src/project.cpp index 2bc67c03..714868fa 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -581,6 +581,8 @@ void Project::saveTilesets(Tileset *primaryTileset, Tileset *secondaryTileset) { saveTilesetMetatileAttributes(secondaryTileset); saveTilesetMetatiles(primaryTileset); saveTilesetMetatiles(secondaryTileset); + saveTilesetTilesImage(primaryTileset); + saveTilesetTilesImage(secondaryTileset); } void Project::saveTilesetMetatileAttributes(Tileset *tileset) { @@ -619,6 +621,11 @@ void Project::saveTilesetMetatiles(Tileset *tileset) { } } +void Project::saveTilesetTilesImage(Tileset *tileset) { + qDebug() << QString("saving tiles png to '%1'").arg(tileset->tilesImagePath); + tileset->tilesImage.save(tileset->tilesImagePath); +} + void Project::loadMapTilesets(Map* map) { if (map->layout->has_unsaved_changes) { return; @@ -841,22 +848,59 @@ void Project::loadTilesetAssets(Tileset* tileset) { tileset->metatile_attrs_path = dir_path + "/metatile_attributes.bin"; } - // tiles tiles_path = fixGraphicPath(tiles_path); - QImage *image = new QImage(tiles_path); - //image->setColor(0, qRgb(0xff, 0, 0)); // debug + tileset->tilesImagePath = tiles_path; + QImage image = QImage(tileset->tilesImagePath); + this->loadTilesetTiles(tileset, image); + this->loadTilesetMetatiles(tileset); + // palettes + QList> *palettes = new QList>; + for (int i = 0; i < palette_paths->length(); i++) { + QString path = palette_paths->value(i); + // the palettes are not compressed. this should never happen. it's only a precaution. + path = path.replace(QRegExp("\\.lz$"), ""); + // TODO default to .pal (JASC-PAL) + // just use .gbapal for now + QFile file(path); + QList palette; + if (file.open(QIODevice::ReadOnly)) { + QByteArray data = file.readAll(); + for (int j = 0; j < 16; j++) { + uint16_t word = data[j*2] & 0xff; + word += (data[j*2 + 1] & 0xff) << 8; + int red = word & 0x1f; + int green = (word >> 5) & 0x1f; + int blue = (word >> 10) & 0x1f; + QRgb color = qRgb(red * 8, green * 8, blue * 8); + palette.append(color); + } + } else { + for (int j = 0; j < 16; j++) { + palette.append(qRgb(j * 16, j * 16, j * 16)); + } + qDebug() << QString("Could not open palette path '%1'").arg(path); + } + + palettes->append(palette); + } + tileset->palettes = palettes; +} + +void Project::loadTilesetTiles(Tileset *tileset, QImage image) { QList *tiles = new QList; int w = 8; int h = 8; - for (int y = 0; y < image->height(); y += h) - for (int x = 0; x < image->width(); x += w) { - QImage tile = image->copy(x, y, w, h); + for (int y = 0; y < image.height(); y += h) + for (int x = 0; x < image.width(); x += w) { + QImage tile = image.copy(x, y, w, h); tiles->append(tile); } + tileset->tilesImage = image; tileset->tiles = tiles; +} - // metatiles +void Project::loadTilesetMetatiles(Tileset* tileset) { QFile metatiles_file(tileset->metatiles_path); if (metatiles_file.open(QIODevice::ReadOnly)) { QByteArray data = metatiles_file.readAll(); @@ -902,38 +946,6 @@ void Project::loadTilesetAssets(Tileset* tileset) { } else { qDebug() << QString("Could not open tileset metatile attributes file '%1'").arg(tileset->metatile_attrs_path); } - - // palettes - QList> *palettes = new QList>; - for (int i = 0; i < palette_paths->length(); i++) { - QString path = palette_paths->value(i); - // the palettes are not compressed. this should never happen. it's only a precaution. - path = path.replace(QRegExp("\\.lz$"), ""); - // TODO default to .pal (JASC-PAL) - // just use .gbapal for now - QFile file(path); - QList palette; - if (file.open(QIODevice::ReadOnly)) { - QByteArray data = file.readAll(); - for (int j = 0; j < 16; j++) { - uint16_t word = data[j*2] & 0xff; - word += (data[j*2 + 1] & 0xff) << 8; - int red = word & 0x1f; - int green = (word >> 5) & 0x1f; - int blue = (word >> 10) & 0x1f; - QRgb color = qRgb(red * 8, green * 8, blue * 8); - palette.append(color); - } - } else { - for (int j = 0; j < 16; j++) { - palette.append(qRgb(j * 16, j * 16, j * 16)); - } - qDebug() << QString("Could not open palette path '%1'").arg(path); - } - - palettes->append(palette); - } - tileset->palettes = palettes; } Blockdata* Project::readBlockdata(QString path) { diff --git a/src/ui/tileseteditor.cpp b/src/ui/tileseteditor.cpp index 033d94c9..606fdc93 100644 --- a/src/ui/tileseteditor.cpp +++ b/src/ui/tileseteditor.cpp @@ -1,6 +1,9 @@ #include "tileseteditor.h" #include "ui_tileseteditor.h" #include "imageproviders.h" +#include +#include +#include TilesetEditor::TilesetEditor(Project *project, QString primaryTilesetLabel, QString secondaryTilesetLabel, QWidget *parent) : QMainWindow(parent), @@ -47,7 +50,10 @@ void TilesetEditor::setTilesets(QString primaryTilesetLabel, QString secondaryTi Tileset *secondaryTileset = project->getTileset(secondaryTilesetLabel); this->primaryTileset = primaryTileset->copy(); this->secondaryTileset = secondaryTileset->copy(); + this->refresh(); +} +void TilesetEditor::refresh() { this->metatileSelector->setTilesets(this->primaryTileset, this->secondaryTileset); this->tileSelector->setTilesets(this->primaryTileset, this->secondaryTileset); this->metatileLayersItem->setTilesets(this->primaryTileset, this->secondaryTileset); @@ -209,3 +215,77 @@ void TilesetEditor::on_actionSave_Tileset_triggered() emit this->tilesetsSaved(this->primaryTileset->name, this->secondaryTileset->name); this->ui->statusbar->showMessage(QString("Saved primary and secondary Tilesets!"), 5000); } + +void TilesetEditor::on_actionImport_Primary_Tiles_triggered() +{ + this->importTilesetTiles(this->primaryTileset, true); +} + +void TilesetEditor::on_actionImport_Secondary_Tiles_triggered() +{ + this->importTilesetTiles(this->secondaryTileset, false); +} + +void TilesetEditor::importTilesetTiles(Tileset *tileset, bool primary) { + QString descriptor = primary ? "primary" : "secondary"; + QString descriptorCaps = primary ? "Primary" : "Secondary"; + + QString filepath = QFileDialog::getOpenFileName( + this, + QString("Import %1 Tileset Tiles Image").arg(descriptorCaps), + this->project->root, + "Image Files (*.png)"); + if (filepath.isEmpty()) { + return; + } + + qDebug() << QString("Importing %1 tileset tiles '%2'").arg(descriptor).arg(filepath); + + // Validate image dimensions. + QImage image = QImage(filepath); + if (image.width() == 0 || image.height() == 0 || image.width() % 8 != 0 || image.height() % 8 != 0) { + QMessageBox msgBox(this); + msgBox.setText("Failed to import tiles."); + msgBox.setInformativeText(QString("The image dimensions (%1 x %2) are invalid. Width and height must be multiples of 8 pixels.") + .arg(image.width()) + .arg(image.height())); + msgBox.setDefaultButton(QMessageBox::Ok); + msgBox.setIcon(QMessageBox::Icon::Critical); + msgBox.exec(); + return; + } + + // Validate image is properly indexed to 16 colors. + if (image.colorCount() != 16) { + QMessageBox msgBox(this); + msgBox.setText("Failed to import tiles."); + msgBox.setInformativeText(QString("The image must be indexed and contain 16 total colors. The provided image has %1 indexed colors.") + .arg(image.colorCount())); + msgBox.setDefaultButton(QMessageBox::Ok); + msgBox.setIcon(QMessageBox::Icon::Critical); + msgBox.exec(); + return; + } + + // Validate total number of tiles in image. + int numTilesWide = image.width() / 16; + int numTilesHigh = image.height() / 16; + int totalTiles = numTilesHigh * numTilesWide; + int maxAllowedTiles = primary ? Project::getNumTilesPrimary() : Project::getNumTilesTotal() - Project::getNumTilesPrimary(); + if (totalTiles > maxAllowedTiles) { + QMessageBox msgBox(this); + msgBox.setText("Failed to import tiles."); + msgBox.setInformativeText(QString("The maximum number of tiles allowed in the %1 tileset is %2, but the provided image contains %3 total tiles.") + .arg(descriptor) + .arg(maxAllowedTiles) + .arg(totalTiles)); + msgBox.setDefaultButton(QMessageBox::Ok); + msgBox.setIcon(QMessageBox::Icon::Critical); + msgBox.exec(); + return; + } + + this->project->loadTilesetTiles(tileset, image); + this->project->loadTilesetMetatiles(tileset); + this->refresh(); +} From da13b8ea5e9735771f412cf7bc61760051355b03 Mon Sep 17 00:00:00 2001 From: Marcus Huderle Date: Tue, 2 Oct 2018 19:01:27 -0500 Subject: [PATCH 11/15] Enable multi-tile selections in tileset editor --- forms/tileseteditor.ui | 6 +-- include/ui/metatilelayersitem.h | 2 +- include/ui/tileseteditor.h | 6 +-- include/ui/tileseteditortileselector.h | 13 +++-- src/ui/metatilelayersitem.cpp | 3 +- src/ui/tileseteditor.cpp | 75 ++++++++++++++++++-------- src/ui/tileseteditortileselector.cpp | 41 +++++++++----- 7 files changed, 96 insertions(+), 50 deletions(-) diff --git a/forms/tileseteditor.ui b/forms/tileseteditor.ui index 735606d2..3a2a2efb 100644 --- a/forms/tileseteditor.ui +++ b/forms/tileseteditor.ui @@ -186,8 +186,8 @@ - 32 - 32 + 64 + 64 @@ -215,7 +215,7 @@ 0 0 309 - 415 + 409 diff --git a/include/ui/metatilelayersitem.h b/include/ui/metatilelayersitem.h index d2b7d243..b6599e58 100644 --- a/include/ui/metatilelayersitem.h +++ b/include/ui/metatilelayersitem.h @@ -21,7 +21,7 @@ private: Tileset *primaryTileset; Tileset *secondaryTileset; signals: - void tileChanged(int); + void tileChanged(int, int); protected: void mousePressEvent(QGraphicsSceneMouseEvent*); }; diff --git a/include/ui/tileseteditor.h b/include/ui/tileseteditor.h index 9b6d6e67..434e89ea 100644 --- a/include/ui/tileseteditor.h +++ b/include/ui/tileseteditor.h @@ -26,8 +26,8 @@ private slots: void onSelectedMetatileChanged(uint16_t); void onHoveredTileChanged(uint16_t); void onHoveredTileCleared(); - void onSelectedTileChanged(uint16_t); - void onMetatileLayerTileChanged(int); + void onSelectedTilesChanged(); + void onMetatileLayerTileChanged(int, int); void on_spinBox_paletteSelector_valueChanged(int arg1); @@ -50,7 +50,7 @@ private: void initTileSelector(); void initSelectedTileItem(); void initMetatileLayersItem(); - void drawSelectedTile(); + void drawSelectedTiles(); void importTilesetTiles(Tileset*, bool); void refresh(); Ui::TilesetEditor *ui; diff --git a/include/ui/tileseteditortileselector.h b/include/ui/tileseteditortileselector.h index 7369babb..62a14e2b 100644 --- a/include/ui/tileseteditortileselector.h +++ b/include/ui/tileseteditortileselector.h @@ -7,7 +7,7 @@ class TilesetEditorTileSelector: public SelectablePixmapItem { Q_OBJECT public: - TilesetEditorTileSelector(Tileset *primaryTileset, Tileset *secondaryTileset): SelectablePixmapItem(16, 16, 1, 1) { + TilesetEditorTileSelector(Tileset *primaryTileset, Tileset *secondaryTileset): SelectablePixmapItem(16, 16, 2, 2) { this->primaryTileset = primaryTileset; this->secondaryTileset = secondaryTileset; this->numTilesWide = 16; @@ -18,7 +18,8 @@ public: void select(uint16_t metatileId); void setTilesets(Tileset*, Tileset*); void setPaletteId(int); - uint16_t getSelectedTile(); + void setTileFlips(bool, bool); + QList getSelectedTiles(); protected: void mousePressEvent(QGraphicsSceneMouseEvent*); @@ -30,10 +31,12 @@ protected: private: Tileset *primaryTileset; Tileset *secondaryTileset; - uint16_t selectedTile; + QList selectedTiles; int numTilesWide; int paletteId; - void updateSelectedTile(); + bool xFlip; + bool yFlip; + void updateSelectedTiles(); uint16_t getTileId(int x, int y); QPoint getTileCoords(uint16_t); QList getCurPaletteTable(); @@ -41,7 +44,7 @@ private: signals: void hoveredTileChanged(uint16_t); void hoveredTileCleared(); - void selectedTileChanged(uint16_t); + void selectedTilesChanged(); }; #endif // TILESETEDITORTILESELECTOR_H diff --git a/src/ui/metatilelayersitem.cpp b/src/ui/metatilelayersitem.cpp index 50e6afaa..fe8b164f 100644 --- a/src/ui/metatilelayersitem.cpp +++ b/src/ui/metatilelayersitem.cpp @@ -41,6 +41,5 @@ void MetatileLayersItem::mousePressEvent(QGraphicsSceneMouseEvent *event) { QPointF pos = event->pos(); int x = static_cast(pos.x()) / 16; int y = static_cast(pos.y()) / 16; - int tileIndex = (x / 2 * 4) + (y * 2) + (x % 2); - emit this->tileChanged(tileIndex); + emit this->tileChanged(x, y); } diff --git a/src/ui/tileseteditor.cpp b/src/ui/tileseteditor.cpp index 606fdc93..c0403585 100644 --- a/src/ui/tileseteditor.cpp +++ b/src/ui/tileseteditor.cpp @@ -58,12 +58,13 @@ void TilesetEditor::refresh() { this->tileSelector->setTilesets(this->primaryTileset, this->secondaryTileset); this->metatileLayersItem->setTilesets(this->primaryTileset, this->secondaryTileset); this->metatileSelector->select(this->metatileSelector->getSelectedMetatile()); - this->drawSelectedTile(); + this->drawSelectedTiles(); this->ui->graphicsView_Tiles->setSceneRect(0, 0, this->tileSelector->pixmap().width() + 2, this->tileSelector->pixmap().height() + 2); this->ui->graphicsView_Tiles->setFixedSize(this->tileSelector->pixmap().width() + 2, this->tileSelector->pixmap().height() + 2); this->ui->graphicsView_Metatiles->setSceneRect(0, 0, this->metatileSelector->pixmap().width() + 2, this->metatileSelector->pixmap().height() + 2); this->ui->graphicsView_Metatiles->setFixedSize(this->metatileSelector->pixmap().width() + 2, this->metatileSelector->pixmap().height() + 2); + this->ui->graphicsView_selectedTile->setFixedSize(this->selectedTilePixmapItem->pixmap().width(), this->selectedTilePixmapItem->pixmap().height()); } void TilesetEditor::initMetatileSelector() @@ -91,8 +92,8 @@ void TilesetEditor::initTileSelector() this, SLOT(onHoveredTileChanged(uint16_t))); connect(this->tileSelector, SIGNAL(hoveredTileCleared()), this, SLOT(onHoveredTileCleared())); - connect(this->tileSelector, SIGNAL(selectedTileChanged(uint16_t)), - this, SLOT(onSelectedTileChanged(uint16_t))); + connect(this->tileSelector, SIGNAL(selectedTilesChanged()), + this, SLOT(onSelectedTilesChanged())); this->tilesScene = new QGraphicsScene; this->tilesScene->addItem(this->tileSelector); @@ -105,27 +106,42 @@ void TilesetEditor::initTileSelector() void TilesetEditor::initSelectedTileItem() { this->selectedTileScene = new QGraphicsScene; - this->drawSelectedTile(); + this->drawSelectedTiles(); this->ui->graphicsView_selectedTile->setScene(this->selectedTileScene); + this->ui->graphicsView_selectedTile->setFixedSize(this->selectedTilePixmapItem->pixmap().width(), this->selectedTilePixmapItem->pixmap().height()); } -void TilesetEditor::drawSelectedTile() { +void TilesetEditor::drawSelectedTiles() { if (!this->selectedTileScene) { return; } this->selectedTileScene->clear(); - QImage tileImage = getColoredTileImage(this->tileSelector->getSelectedTile(), this->primaryTileset, this->secondaryTileset, this->paletteId) - .mirrored(this->tileXFlip, this->tileYFlip); - this->selectedTilePixmapItem = new QGraphicsPixmapItem(QPixmap::fromImage(tileImage).scaled(32, 32)); + QList tiles = this->tileSelector->getSelectedTiles(); + QPoint dimensions = this->tileSelector->getSelectionDimensions(); + QImage selectionImage(32 * dimensions.x(), 32 * dimensions.y(), QImage::Format_RGBA8888); + QPainter painter(&selectionImage); + int tileIndex = 0; + for (int j = 0; j < dimensions.y(); j++) { + for (int i = 0; i < dimensions.x(); i++) { + QImage tileImage = getColoredTileImage(tiles.at(tileIndex), this->primaryTileset, this->secondaryTileset, this->paletteId) + .mirrored(this->tileXFlip, this->tileYFlip) + .scaled(32, 32); + tileIndex++; + painter.drawImage(i * 32, j * 32, tileImage); + } + } + + this->selectedTilePixmapItem = new QGraphicsPixmapItem(QPixmap::fromImage(selectionImage)); this->selectedTileScene->addItem(this->selectedTilePixmapItem); + this->ui->graphicsView_selectedTile->setFixedSize(this->selectedTilePixmapItem->pixmap().width(), this->selectedTilePixmapItem->pixmap().height()); } void TilesetEditor::initMetatileLayersItem() { Metatile *metatile = Tileset::getMetatile(this->metatileSelector->getSelectedMetatile(), this->primaryTileset, this->secondaryTileset); this->metatileLayersItem = new MetatileLayersItem(metatile, this->primaryTileset, this->secondaryTileset); - connect(this->metatileLayersItem, SIGNAL(tileChanged(int)), - this, SLOT(onMetatileLayerTileChanged(int))); + connect(this->metatileLayersItem, SIGNAL(tileChanged(int, int)), + this, SLOT(onMetatileLayerTileChanged(int, int))); this->metatileLayersScene = new QGraphicsScene; this->metatileLayersScene->addItem(this->metatileLayersItem); @@ -160,17 +176,30 @@ void TilesetEditor::onHoveredTileCleared() { this->ui->statusbar->clearMessage(); } -void TilesetEditor::onSelectedTileChanged(uint16_t) { - this->drawSelectedTile(); +void TilesetEditor::onSelectedTilesChanged() { + this->drawSelectedTiles(); } -void TilesetEditor::onMetatileLayerTileChanged(int tileIndex) { - Tile tile = this->metatile->tiles->at(tileIndex); - tile.tile = this->tileSelector->getSelectedTile(); - tile.xflip = this->tileXFlip; - tile.yflip = this->tileYFlip; - tile.palette = this->paletteId; - (*this->metatile->tiles)[tileIndex] = tile; +void TilesetEditor::onMetatileLayerTileChanged(int x, int y) { + int maxTileIndex = x < 2 ? 3 : 7; + QPoint dimensions = this->tileSelector->getSelectionDimensions(); + QList tiles = this->tileSelector->getSelectedTiles(); + int selectedTileIndex = 0; + for (int j = 0; j < dimensions.y(); j++) { + for (int i = 0; i < dimensions.x(); i++) { + int tileIndex = ((x + i) / 2 * 4) + ((y + j) * 2) + ((x + i) % 2); + if (tileIndex <= maxTileIndex) { + Tile tile = this->metatile->tiles->at(tileIndex); + tile.tile = tiles.at(selectedTileIndex); + tile.xflip = this->tileXFlip; + tile.yflip = this->tileYFlip; + tile.palette = this->paletteId; + (*this->metatile->tiles)[tileIndex] = tile; + } + selectedTileIndex++; + } + } + this->metatileSelector->draw(); this->metatileLayersItem->draw(); } @@ -179,19 +208,21 @@ void TilesetEditor::on_spinBox_paletteSelector_valueChanged(int paletteId) { this->paletteId = paletteId; this->tileSelector->setPaletteId(paletteId); - this->drawSelectedTile(); + this->drawSelectedTiles(); } void TilesetEditor::on_checkBox_xFlip_stateChanged(int checked) { this->tileXFlip = checked; - this->drawSelectedTile(); + this->tileSelector->setTileFlips(this->tileXFlip, this->tileYFlip); + this->drawSelectedTiles(); } void TilesetEditor::on_checkBox_yFlip_stateChanged(int checked) { this->tileYFlip = checked; - this->drawSelectedTile(); + this->tileSelector->setTileFlips(this->tileXFlip, this->tileYFlip); + this->drawSelectedTiles(); } void TilesetEditor::on_comboBox_metatileBehaviors_currentIndexChanged(const QString &metatileBehavior) diff --git a/src/ui/tileseteditortileselector.cpp b/src/ui/tileseteditortileselector.cpp index 09bc2d60..6d323f46 100644 --- a/src/ui/tileseteditortileselector.cpp +++ b/src/ui/tileseteditortileselector.cpp @@ -35,7 +35,7 @@ void TilesetEditorTileSelector::draw() { int y = tile / this->numTilesWide; int x = tile % this->numTilesWide; QPoint origin = QPoint(x * 16, y * 16); - painter.drawImage(origin, tileImage); + painter.drawImage(origin, tileImage.mirrored(this->xFlip, this->yFlip)); } painter.end(); @@ -46,8 +46,8 @@ void TilesetEditorTileSelector::draw() { void TilesetEditorTileSelector::select(uint16_t tile) { QPoint coords = this->getTileCoords(tile); SelectablePixmapItem::select(coords.x(), coords.y(), 0, 0); - this->selectedTile = tile; - emit selectedTileChanged(tile); + this->updateSelectedTiles(); + emit selectedTilesChanged(); } void TilesetEditorTileSelector::setTilesets(Tileset *primaryTileset, Tileset *secondaryTileset) { @@ -61,13 +61,26 @@ void TilesetEditorTileSelector::setPaletteId(int paletteId) { this->draw(); } -void TilesetEditorTileSelector::updateSelectedTile() { - QPoint origin = this->getSelectionStart(); - this->selectedTile = this->getTileId(origin.x(), origin.y()); +void TilesetEditorTileSelector::setTileFlips(bool xFlip, bool yFlip) { + this->xFlip = xFlip; + this->yFlip = yFlip; + this->draw(); } -uint16_t TilesetEditorTileSelector::getSelectedTile() { - return this->selectedTile; +void TilesetEditorTileSelector::updateSelectedTiles() { + this->selectedTiles.clear(); + QPoint origin = this->getSelectionStart(); + QPoint dimensions = this->getSelectionDimensions(); + for (int j = 0; j < dimensions.y(); j++) { + for (int i = 0; i < dimensions.x(); i++) { + uint16_t metatileId = this->getTileId(origin.x() + i, origin.y() + j); + this->selectedTiles.append(metatileId); + } + } +} + +QList TilesetEditorTileSelector::getSelectedTiles() { + return this->selectedTiles; } uint16_t TilesetEditorTileSelector::getTileId(int x, int y) { @@ -76,24 +89,24 @@ uint16_t TilesetEditorTileSelector::getTileId(int x, int y) { void TilesetEditorTileSelector::mousePressEvent(QGraphicsSceneMouseEvent *event) { SelectablePixmapItem::mousePressEvent(event); - this->updateSelectedTile(); - emit selectedTileChanged(this->selectedTile); + this->updateSelectedTiles(); + emit selectedTilesChanged(); } void TilesetEditorTileSelector::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { SelectablePixmapItem::mouseMoveEvent(event); - this->updateSelectedTile(); + this->updateSelectedTiles(); QPoint pos = this->getCellPos(event->pos()); uint16_t tile = this->getTileId(pos.x(), pos.y()); emit hoveredTileChanged(tile); - emit selectedTileChanged(tile); + emit selectedTilesChanged(); } void TilesetEditorTileSelector::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { SelectablePixmapItem::mouseReleaseEvent(event); - this->updateSelectedTile(); - emit selectedTileChanged(this->selectedTile); + this->updateSelectedTiles(); + emit selectedTilesChanged(); } void TilesetEditorTileSelector::hoverMoveEvent(QGraphicsSceneHoverEvent *event) { From cf150f3ce9f9742bf2f879b884d41f58f8284326 Mon Sep 17 00:00:00 2001 From: Marcus Huderle Date: Tue, 2 Oct 2018 19:01:31 -0500 Subject: [PATCH 12/15] Ask user about unsaved changes when closing tileset editor window --- include/mainwindow.h | 1 + include/ui/tileseteditor.h | 8 ++++++-- src/mainwindow.cpp | 10 ++++++++++ src/ui/tileseteditor.cpp | 39 +++++++++++++++++++++++++++++++++----- 4 files changed, 51 insertions(+), 7 deletions(-) diff --git a/include/mainwindow.h b/include/mainwindow.h index 9ba488b8..3ddc3c39 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -94,6 +94,7 @@ private slots: void onAddNewMapToGroupClick(QAction* triggeredAction); void onTilesetChanged(QString); void currentMetatilesSelectionChanged(); + void onTilesetEditorClosed(); void on_action_Export_Map_Image_triggered(); diff --git a/include/ui/tileseteditor.h b/include/ui/tileseteditor.h index 434e89ea..cb360d03 100644 --- a/include/ui/tileseteditor.h +++ b/include/ui/tileseteditor.h @@ -19,6 +19,7 @@ public: explicit TilesetEditor(Project*, QString, QString, QWidget *parent = nullptr); ~TilesetEditor(); void setTilesets(QString, QString); + void init(Project*, QString, QString); private slots: void onHoveredMetatileChanged(uint16_t); @@ -46,6 +47,7 @@ private slots: void on_actionImport_Secondary_Tiles_triggered(); private: + void closeEvent(QCloseEvent*); void initMetatileSelector(); void initTileSelector(); void initSelectedTileItem(); @@ -62,8 +64,9 @@ private: int paletteId; bool tileXFlip; bool tileYFlip; - Tileset *primaryTileset; - Tileset *secondaryTileset; + bool hasUnsavedChanges; + Tileset *primaryTileset = nullptr; + Tileset *secondaryTileset = nullptr; QGraphicsScene *metatilesScene = nullptr; QGraphicsScene *tilesScene = nullptr; QGraphicsScene *selectedTileScene = nullptr; @@ -72,6 +75,7 @@ private: signals: void tilesetsSaved(QString, QString); + void closed(); }; #endif // TILESETEDITOR_H diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 7f64fdca..4adf9562 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -1246,11 +1246,21 @@ void MainWindow::on_actionTileset_Editor_triggered() if (!this->tilesetEditor) { this->tilesetEditor = new TilesetEditor(this->editor->project, this->editor->map->layout->tileset_primary_label, this->editor->map->layout->tileset_secondary_label, this); connect(this->tilesetEditor, SIGNAL(tilesetsSaved(QString, QString)), this, SLOT(onTilesetsSaved(QString, QString))); + connect(this->tilesetEditor, SIGNAL(closed()), this, SLOT(onTilesetEditorClosed())); } if (!this->tilesetEditor->isVisible()) { this->tilesetEditor->show(); + } else if (this->tilesetEditor->isMinimized()) { + this->tilesetEditor->showNormal(); } else { this->tilesetEditor->activateWindow(); } } + +void MainWindow::onTilesetEditorClosed() { + if (this->tilesetEditor) { + delete this->tilesetEditor; + this->tilesetEditor = nullptr; + } +} diff --git a/src/ui/tileseteditor.cpp b/src/ui/tileseteditor.cpp index c0403585..c61116b4 100644 --- a/src/ui/tileseteditor.cpp +++ b/src/ui/tileseteditor.cpp @@ -9,15 +9,27 @@ TilesetEditor::TilesetEditor(Project *project, QString primaryTilesetLabel, QStr QMainWindow(parent), ui(new Ui::TilesetEditor) { + this->init(project, primaryTilesetLabel, secondaryTilesetLabel); +} + +TilesetEditor::~TilesetEditor() +{ + delete ui; +} + +void TilesetEditor::init(Project *project, QString primaryTilesetLabel, QString secondaryTilesetLabel) { ui->setupUi(this); this->project = project; + this->hasUnsavedChanges = false; this->tileXFlip = ui->checkBox_xFlip->isChecked(); this->tileYFlip = ui->checkBox_yFlip->isChecked(); this->paletteId = ui->spinBox_paletteSelector->value(); Tileset *primaryTileset = project->getTileset(primaryTilesetLabel); Tileset *secondaryTileset = project->getTileset(secondaryTilesetLabel); + if (this->primaryTileset) delete this->primaryTileset; + if (this->secondaryTileset) delete this->secondaryTileset; this->primaryTileset = primaryTileset->copy(); this->secondaryTileset = secondaryTileset->copy(); @@ -38,11 +50,6 @@ TilesetEditor::TilesetEditor(Project *project, QString primaryTilesetLabel, QStr this->metatileSelector->select(0); } -TilesetEditor::~TilesetEditor() -{ - delete ui; -} - void TilesetEditor::setTilesets(QString primaryTilesetLabel, QString secondaryTilesetLabel) { delete this->primaryTileset; delete this->secondaryTileset; @@ -202,6 +209,7 @@ void TilesetEditor::onMetatileLayerTileChanged(int x, int y) { this->metatileSelector->draw(); this->metatileLayersItem->draw(); + this->hasUnsavedChanges = true; } void TilesetEditor::on_spinBox_paletteSelector_valueChanged(int paletteId) @@ -245,6 +253,7 @@ void TilesetEditor::on_actionSave_Tileset_triggered() this->project->saveTilesets(this->primaryTileset, this->secondaryTileset); emit this->tilesetsSaved(this->primaryTileset->name, this->secondaryTileset->name); this->ui->statusbar->showMessage(QString("Saved primary and secondary Tilesets!"), 5000); + this->hasUnsavedChanges = false; } void TilesetEditor::on_actionImport_Primary_Tiles_triggered() @@ -319,4 +328,24 @@ void TilesetEditor::importTilesetTiles(Tileset *tileset, bool primary) { this->project->loadTilesetTiles(tileset, image); this->project->loadTilesetMetatiles(tileset); this->refresh(); + this->hasUnsavedChanges = true; +} + +void TilesetEditor::closeEvent(QCloseEvent *event) +{ + bool close = true; + if (this->hasUnsavedChanges) { + QMessageBox::StandardButton result = QMessageBox::question(this, "porymap", + "Discard unsaved Tileset changes?", + QMessageBox::No | QMessageBox::Yes, + QMessageBox::Yes); + close = result == QMessageBox::Yes; + } + + if (close) { + event->accept(); + emit closed(); + } else { + event->ignore(); + } } From 8db57f3e0c83b44f2286998d55dad561b73856fe Mon Sep 17 00:00:00 2001 From: Marcus Huderle Date: Tue, 2 Oct 2018 19:01:34 -0500 Subject: [PATCH 13/15] Cleanup tileset editor ui --- forms/tileseteditor.ui | 225 +++++++++++++++++++++------------------ src/ui/tileseteditor.cpp | 6 +- 2 files changed, 122 insertions(+), 109 deletions(-) diff --git a/forms/tileseteditor.ui b/forms/tileseteditor.ui index 3a2a2efb..54919db6 100644 --- a/forms/tileseteditor.ui +++ b/forms/tileseteditor.ui @@ -25,7 +25,7 @@ 0 0 - 308 + 386 539 @@ -99,37 +99,54 @@ - QFrame::StyledPanel + QFrame::NoFrame QFrame::Raised + + 0 + + + 0 + + + 0 + + + 0 + - QFrame::StyledPanel + QFrame::NoFrame QFrame::Raised + + 0 + + + 0 + + + 0 + + + 0 + - - - QFrame::StyledPanel + + + Tile Properties - - QFrame::Raised + + false - - - - - Y Flip - - - + @@ -147,6 +164,26 @@ + + + + Y Flip + + + + + + + + 0 + 0 + + + + Selection + + + @@ -164,30 +201,65 @@ + + + + + 16 + 16 + + + + + 32 + 32 + + + + QFrame::StyledPanel + + + Qt::ScrollBarAlwaysOff + + + Qt::ScrollBarAlwaysOff + + + - - - QFrame::StyledPanel + + + Metatile Properties - - QFrame::Raised + + false - + + false + + - + + + Bottom/Top + + + + + - 32 + 64 32 64 - 64 + 32 @@ -198,6 +270,26 @@ + + + + Metatile Behavior + + + + + + + + + + Layer Type + + + + + + @@ -214,8 +306,8 @@ 0 0 - 309 - 409 + 386 + 361 @@ -288,85 +380,6 @@ - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - - 0 - 0 - - - - QFrame::StyledPanel - - - QFrame::Raised - - - - - - Bottom/Top - - - - - - - - 64 - 32 - - - - - 64 - 32 - - - - Qt::ScrollBarAlwaysOff - - - Qt::ScrollBarAlwaysOff - - - - - - - Metatile Behavior - - - - - - - - - - Layer Type - - - - - - - - - - - - diff --git a/src/ui/tileseteditor.cpp b/src/ui/tileseteditor.cpp index c61116b4..540c5bf4 100644 --- a/src/ui/tileseteditor.cpp +++ b/src/ui/tileseteditor.cpp @@ -126,16 +126,16 @@ void TilesetEditor::drawSelectedTiles() { this->selectedTileScene->clear(); QList tiles = this->tileSelector->getSelectedTiles(); QPoint dimensions = this->tileSelector->getSelectionDimensions(); - QImage selectionImage(32 * dimensions.x(), 32 * dimensions.y(), QImage::Format_RGBA8888); + QImage selectionImage(16 * dimensions.x(), 16 * dimensions.y(), QImage::Format_RGBA8888); QPainter painter(&selectionImage); int tileIndex = 0; for (int j = 0; j < dimensions.y(); j++) { for (int i = 0; i < dimensions.x(); i++) { QImage tileImage = getColoredTileImage(tiles.at(tileIndex), this->primaryTileset, this->secondaryTileset, this->paletteId) .mirrored(this->tileXFlip, this->tileYFlip) - .scaled(32, 32); + .scaled(16, 16); tileIndex++; - painter.drawImage(i * 32, j * 32, tileImage); + painter.drawImage(i * 16, j * 16, tileImage); } } From 303f31f3d412553f917993dbb5dfa755afce7c89 Mon Sep 17 00:00:00 2001 From: Marcus Huderle Date: Tue, 2 Oct 2018 19:01:37 -0500 Subject: [PATCH 14/15] Add ability to change tileset metatile counts --- forms/tileseteditor.ui | 14 +++++- include/ui/tileseteditor.h | 2 + include/ui/tileseteditortileselector.h | 2 + src/ui/tileseteditor.cpp | 70 ++++++++++++++++++++++++++ 4 files changed, 87 insertions(+), 1 deletion(-) diff --git a/forms/tileseteditor.ui b/forms/tileseteditor.ui index 54919db6..bdbbae89 100644 --- a/forms/tileseteditor.ui +++ b/forms/tileseteditor.ui @@ -307,7 +307,7 @@ 0 0 386 - 361 + 359 @@ -397,10 +397,17 @@ + + + + Tools + + + @@ -421,6 +428,11 @@ Import Secondary Tiles + + + Change Number of Metatiles + + diff --git a/include/ui/tileseteditor.h b/include/ui/tileseteditor.h index cb360d03..53755153 100644 --- a/include/ui/tileseteditor.h +++ b/include/ui/tileseteditor.h @@ -46,6 +46,8 @@ private slots: void on_actionImport_Secondary_Tiles_triggered(); + void on_actionChange_Metatiles_Count_triggered(); + private: void closeEvent(QCloseEvent*); void initMetatileSelector(); diff --git a/include/ui/tileseteditortileselector.h b/include/ui/tileseteditortileselector.h index 62a14e2b..fe8d6bc2 100644 --- a/include/ui/tileseteditortileselector.h +++ b/include/ui/tileseteditortileselector.h @@ -12,6 +12,8 @@ public: this->secondaryTileset = secondaryTileset; this->numTilesWide = 16; this->paletteId = 0; + this->xFlip = false; + this->yFlip = false; setAcceptHoverEvents(true); } void draw(); diff --git a/src/ui/tileseteditor.cpp b/src/ui/tileseteditor.cpp index 540c5bf4..b1d388c7 100644 --- a/src/ui/tileseteditor.cpp +++ b/src/ui/tileseteditor.cpp @@ -4,6 +4,7 @@ #include #include #include +#include TilesetEditor::TilesetEditor(Project *project, QString primaryTilesetLabel, QString secondaryTilesetLabel, QWidget *parent) : QMainWindow(parent), @@ -349,3 +350,72 @@ void TilesetEditor::closeEvent(QCloseEvent *event) event->ignore(); } } + +void TilesetEditor::on_actionChange_Metatiles_Count_triggered() +{ + QDialog dialog(this, Qt::WindowTitleHint | Qt::WindowCloseButtonHint); + dialog.setWindowTitle("Change Number of Metatiles"); + dialog.setWindowModality(Qt::NonModal); + + QFormLayout form(&dialog); + + QSpinBox *primarySpinBox = new QSpinBox(); + QSpinBox *secondarySpinBox = new QSpinBox(); + primarySpinBox->setMinimum(1); + secondarySpinBox->setMinimum(1); + primarySpinBox->setMaximum(Project::getNumMetatilesPrimary()); + secondarySpinBox->setMaximum(Project::getNumMetatilesTotal() - Project::getNumMetatilesPrimary()); + primarySpinBox->setValue(this->primaryTileset->metatiles->length()); + secondarySpinBox->setValue(this->secondaryTileset->metatiles->length()); + form.addRow(new QLabel("Primary Tileset"), primarySpinBox); + form.addRow(new QLabel("Secondary Tileset"), secondarySpinBox); + + QDialogButtonBox buttonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, &dialog); + connect(&buttonBox, SIGNAL(accepted()), &dialog, SLOT(accept())); + connect(&buttonBox, SIGNAL(rejected()), &dialog, SLOT(reject())); + form.addRow(&buttonBox); + + if (dialog.exec() == QDialog::Accepted) { + int numPrimaryMetatiles = primarySpinBox->value(); + int numSecondaryMetatiles = secondarySpinBox->value(); + while (this->primaryTileset->metatiles->length() > numPrimaryMetatiles) { + Metatile *metatile = this->primaryTileset->metatiles->takeLast(); + delete metatile; + } + while (this->primaryTileset->metatiles->length() < numPrimaryMetatiles) { + Tile tile; + tile.palette = 0; + tile.tile = 0; + tile.xflip = 0; + tile.yflip = 0; + Metatile *metatile = new Metatile; + metatile->behavior = 0; + metatile->layerType = 0; + for (int i = 0; i < 8; i++) { + metatile->tiles->append(tile); + } + this->primaryTileset->metatiles->append(metatile); + } + while (this->secondaryTileset->metatiles->length() > numSecondaryMetatiles) { + Metatile *metatile = this->secondaryTileset->metatiles->takeLast(); + delete metatile; + } + while (this->secondaryTileset->metatiles->length() < numSecondaryMetatiles) { + Tile tile; + tile.palette = 0; + tile.tile = 0; + tile.xflip = 0; + tile.yflip = 0; + Metatile *metatile = new Metatile; + metatile->behavior = 0; + metatile->layerType = 0; + for (int i = 0; i < 8; i++) { + metatile->tiles->append(tile); + } + this->secondaryTileset->metatiles->append(metatile); + } + + this->refresh(); + this->hasUnsavedChanges = true; + } +} From 61ec1af0fb257571c2a2fff551336571b0181557 Mon Sep 17 00:00:00 2001 From: Marcus Huderle Date: Tue, 2 Oct 2018 19:01:41 -0500 Subject: [PATCH 15/15] Add tileset palette editor --- forms/paletteeditor.ui | 1536 ++++++++++++++++++++++++++++++++++++ forms/tileseteditor.ui | 6 + include/core/tileset.h | 1 + include/project.h | 2 + include/ui/paletteeditor.h | 43 + include/ui/tileseteditor.h | 7 + porymap.pro | 5 +- src/core/tileset.cpp | 3 + src/project.cpp | 74 +- src/ui/paletteeditor.cpp | 176 +++++ src/ui/tileseteditor.cpp | 41 +- 11 files changed, 1871 insertions(+), 23 deletions(-) create mode 100644 forms/paletteeditor.ui create mode 100644 include/ui/paletteeditor.h create mode 100644 src/ui/paletteeditor.cpp diff --git a/forms/paletteeditor.ui b/forms/paletteeditor.ui new file mode 100644 index 00000000..a8b18de4 --- /dev/null +++ b/forms/paletteeditor.ui @@ -0,0 +1,1536 @@ + + + PaletteEditor + + + + 0 + 0 + 817 + 739 + + + + MainWindow + + + + + + + + 0 + 0 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + Palette + + + + + + + + + + + + + + 0 + 0 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + Color 4 + + + + + + + 32 + 32 + + + + + 32 + 32 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + Red + + + + + + + 31 + + + Qt::Horizontal + + + false + + + false + + + QSlider::NoTicks + + + + + + + Green + + + + + + + Blue + + + + + + + 31 + + + Qt::Horizontal + + + + + + + 31 + + + Qt::Horizontal + + + + + + + + + + Color 5 + + + + + + + 32 + 32 + + + + + 32 + 32 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + Red + + + + + + + 31 + + + Qt::Horizontal + + + false + + + false + + + QSlider::NoTicks + + + + + + + Green + + + + + + + Blue + + + + + + + 31 + + + Qt::Horizontal + + + + + + + 31 + + + Qt::Horizontal + + + + + + + + + + Color 7 + + + + + + + 32 + 32 + + + + + 32 + 32 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + Red + + + + + + + 31 + + + Qt::Horizontal + + + false + + + false + + + QSlider::NoTicks + + + + + + + Green + + + + + + + Blue + + + + + + + 31 + + + Qt::Horizontal + + + + + + + 31 + + + Qt::Horizontal + + + + + + + + + + Color 6 + + + + + + + 32 + 32 + + + + + 32 + 32 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + Red + + + + + + + 31 + + + Qt::Horizontal + + + false + + + false + + + QSlider::NoTicks + + + + + + + Green + + + + + + + Blue + + + + + + + 31 + + + Qt::Horizontal + + + + + + + 31 + + + Qt::Horizontal + + + + + + + + + + Color 10 + + + + + + + 32 + 32 + + + + + 32 + 32 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + Red + + + + + + + 31 + + + Qt::Horizontal + + + false + + + false + + + QSlider::NoTicks + + + + + + + Green + + + + + + + Blue + + + + + + + 31 + + + Qt::Horizontal + + + + + + + 31 + + + Qt::Horizontal + + + + + + + + + + Color 8 + + + + + + + 32 + 32 + + + + + 32 + 32 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + Red + + + + + + + 31 + + + Qt::Horizontal + + + false + + + false + + + QSlider::NoTicks + + + + + + + Green + + + + + + + Blue + + + + + + + 31 + + + Qt::Horizontal + + + + + + + 31 + + + Qt::Horizontal + + + + + + + + + + Color 9 + + + + + + + 32 + 32 + + + + + 32 + 32 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + Red + + + + + + + 31 + + + Qt::Horizontal + + + false + + + false + + + QSlider::NoTicks + + + + + + + Green + + + + + + + Blue + + + + + + + 31 + + + Qt::Horizontal + + + + + + + 31 + + + Qt::Horizontal + + + + + + + + + + Color 11 + + + + + + + 32 + 32 + + + + + 32 + 32 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + Red + + + + + + + 31 + + + Qt::Horizontal + + + false + + + false + + + QSlider::NoTicks + + + + + + + Green + + + + + + + Blue + + + + + + + 31 + + + Qt::Horizontal + + + + + + + 31 + + + Qt::Horizontal + + + + + + + + + + Color 12 + + + + + + + 32 + 32 + + + + + 32 + 32 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + Red + + + + + + + 31 + + + Qt::Horizontal + + + false + + + false + + + QSlider::NoTicks + + + + + + + Green + + + + + + + Blue + + + + + + + 31 + + + Qt::Horizontal + + + + + + + 31 + + + Qt::Horizontal + + + + + + + + + + Color 14 + + + + + + + 32 + 32 + + + + + 32 + 32 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + Red + + + + + + + 31 + + + Qt::Horizontal + + + false + + + false + + + QSlider::NoTicks + + + + + + + Green + + + + + + + Blue + + + + + + + 31 + + + Qt::Horizontal + + + + + + + 31 + + + Qt::Horizontal + + + + + + + + + + Color 13 + + + + + + + 32 + 32 + + + + + 32 + 32 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + Red + + + + + + + 31 + + + Qt::Horizontal + + + false + + + false + + + QSlider::NoTicks + + + + + + + Green + + + + + + + Blue + + + + + + + 31 + + + Qt::Horizontal + + + + + + + 31 + + + Qt::Horizontal + + + + + + + + + + Color 15 + + + + + + + 32 + 32 + + + + + 32 + 32 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + Red + + + + + + + 31 + + + Qt::Horizontal + + + false + + + false + + + QSlider::NoTicks + + + + + + + Green + + + + + + + Blue + + + + + + + 31 + + + Qt::Horizontal + + + + + + + 31 + + + Qt::Horizontal + + + + + + + + + + Color 0 + + + + + + Red + + + + + + + 31 + + + Qt::Horizontal + + + false + + + false + + + QSlider::NoTicks + + + + + + + Green + + + + + + + 31 + + + Qt::Horizontal + + + + + + + Blue + + + + + + + 31 + + + Qt::Horizontal + + + + + + + + 32 + 32 + + + + + 32 + 32 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + + + Color 1 + + + + + + + 32 + 32 + + + + + 32 + 32 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + Red + + + + + + + 31 + + + Qt::Horizontal + + + false + + + false + + + QSlider::NoTicks + + + + + + + Green + + + + + + + 31 + + + Qt::Horizontal + + + + + + + Blue + + + + + + + 31 + + + Qt::Horizontal + + + + + + + + + + Color 2 + + + + + + + 32 + 32 + + + + + 32 + 32 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + Red + + + + + + + 31 + + + Qt::Horizontal + + + false + + + false + + + QSlider::NoTicks + + + + + + + Green + + + + + + + Blue + + + + + + + 31 + + + Qt::Horizontal + + + + + + + 31 + + + Qt::Horizontal + + + + + + + + + + Color 3 + + + + + + + 32 + 32 + + + + + 32 + 32 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + Red + + + + + + + 31 + + + Qt::Horizontal + + + false + + + false + + + QSlider::NoTicks + + + + + + + Green + + + + + + + Blue + + + + + + + 31 + + + Qt::Horizontal + + + + + + + 31 + + + Qt::Horizontal + + + + + + + + + + + + + + + 0 + 0 + 817 + 21 + + + + + + + + diff --git a/forms/tileseteditor.ui b/forms/tileseteditor.ui index bdbbae89..f8b6947f 100644 --- a/forms/tileseteditor.ui +++ b/forms/tileseteditor.ui @@ -405,6 +405,7 @@ + @@ -433,6 +434,11 @@ Change Number of Metatiles + + + Change Palettes + + diff --git a/include/core/tileset.h b/include/core/tileset.h index aea9f458..ce735e35 100644 --- a/include/core/tileset.h +++ b/include/core/tileset.h @@ -23,6 +23,7 @@ public: QString metatile_attrs_path; QString tilesImagePath; QImage tilesImage; + QList palettePaths; QList *tiles = nullptr; QList *metatiles = nullptr; diff --git a/include/project.h b/include/project.h index 21acd40a..fa4ee2ed 100644 --- a/include/project.h +++ b/include/project.h @@ -109,6 +109,7 @@ public: void loadEventPixmaps(QList objects); QMap getEventObjGfxConstants(); + QString fixPalettePath(QString path); QString fixGraphicPath(QString path); void readMapEvents(Map *map); @@ -136,6 +137,7 @@ private: void saveTilesetMetatileAttributes(Tileset*); void saveTilesetMetatiles(Tileset*); void saveTilesetTilesImage(Tileset*); + void saveTilesetPalettes(Tileset*, bool); void updateMapsWithConnections(Map*); void saveMapsWithConnections(); void saveMapLayoutsTable(); diff --git a/include/ui/paletteeditor.h b/include/ui/paletteeditor.h new file mode 100644 index 00000000..d8866f24 --- /dev/null +++ b/include/ui/paletteeditor.h @@ -0,0 +1,43 @@ +#ifndef PALETTEEDITOR_H +#define PALETTEEDITOR_H + +#include +#include +#include +#include "project.h" + +namespace Ui { +class PaletteEditor; +} + +class PaletteEditor : public QMainWindow { + Q_OBJECT +public: + explicit PaletteEditor(Project*, Tileset*, Tileset*, QWidget *parent = nullptr); + ~PaletteEditor(); + void setPaletteId(int); + +private: + Ui::PaletteEditor *ui; + Project *project = nullptr; + QList> sliders; + QList frames; + Tileset *primaryTileset; + Tileset *secondaryTileset; + void disableSliderSignals(); + void enableSliderSignals(); + void initColorSliders(); + void refreshColorSliders(); + void refreshColors(); + void refreshColor(int); + void setColor(int); + +signals: + void closed(); + void changedPaletteColor(); + void changedPalette(int); +private slots: + void on_spinBox_PaletteId_valueChanged(int arg1); +}; + +#endif // PALETTEEDITOR_H diff --git a/include/ui/tileseteditor.h b/include/ui/tileseteditor.h index 53755153..f2d1f54e 100644 --- a/include/ui/tileseteditor.h +++ b/include/ui/tileseteditor.h @@ -3,6 +3,7 @@ #include #include "project.h" +#include "paletteeditor.h" #include "tileseteditormetatileselector.h" #include "tileseteditortileselector.h" #include "metatilelayersitem.h" @@ -29,6 +30,9 @@ private slots: void onHoveredTileCleared(); void onSelectedTilesChanged(); void onMetatileLayerTileChanged(int, int); + void onPaletteEditorClosed(); + void onPaletteEditorChangedPaletteColor(); + void onPaletteEditorChangedPalette(int); void on_spinBox_paletteSelector_valueChanged(int arg1); @@ -48,6 +52,8 @@ private slots: void on_actionChange_Metatiles_Count_triggered(); + void on_actionChange_Palettes_triggered(); + private: void closeEvent(QCloseEvent*); void initMetatileSelector(); @@ -61,6 +67,7 @@ private: TilesetEditorMetatileSelector *metatileSelector = nullptr; TilesetEditorTileSelector *tileSelector = nullptr; MetatileLayersItem *metatileLayersItem = nullptr; + PaletteEditor *paletteEditor = nullptr; Project *project = nullptr; Metatile *metatile = nullptr; int paletteId; diff --git a/porymap.pro b/porymap.pro index b0ef9c13..70767deb 100644 --- a/porymap.pro +++ b/porymap.pro @@ -40,6 +40,7 @@ SOURCES += src/core/block.cpp \ src/ui/neweventtoolbutton.cpp \ src/ui/noscrollcombobox.cpp \ src/ui/noscrollspinbox.cpp \ + src/ui/paletteeditor.cpp \ src/ui/selectablepixmapitem.cpp \ src/ui/tileseteditor.cpp \ src/ui/tileseteditormetatileselector.cpp \ @@ -78,6 +79,7 @@ HEADERS += include/core/block.h \ include/ui/neweventtoolbutton.h \ include/ui/noscrollcombobox.h \ include/ui/noscrollspinbox.h \ + include/ui/paletteeditor.h \ include/ui/selectablepixmapitem.h \ include/ui/tileseteditor.h \ include/ui/tileseteditormetatileselector.h \ @@ -89,7 +91,8 @@ HEADERS += include/core/block.h \ FORMS += forms/mainwindow.ui \ forms/eventpropertiesframe.ui \ - forms/tileseteditor.ui + forms/tileseteditor.ui \ + forms/paletteeditor.ui RESOURCES += \ resources/images.qrc diff --git a/src/core/tileset.cpp b/src/core/tileset.cpp index f62135ad..d3acbf2b 100644 --- a/src/core/tileset.cpp +++ b/src/core/tileset.cpp @@ -26,6 +26,9 @@ Tileset* Tileset::copy() { copy->metatile_attrs_path = this->metatile_attrs_path; copy->tilesImage = this->tilesImage.copy(); copy->tilesImagePath = this->tilesImagePath; + for (int i = 0; i < this->palettePaths.length(); i++) { + copy->palettePaths.append(this->palettePaths.at(i)); + } copy->tiles = new QList; for (QImage tile : *this->tiles) { copy->tiles->append(tile.copy()); diff --git a/src/project.cpp b/src/project.cpp index 714868fa..f1168123 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -583,6 +583,8 @@ void Project::saveTilesets(Tileset *primaryTileset, Tileset *secondaryTileset) { saveTilesetMetatiles(secondaryTileset); saveTilesetTilesImage(primaryTileset); saveTilesetTilesImage(secondaryTileset); + saveTilesetPalettes(primaryTileset, true); + saveTilesetPalettes(secondaryTileset, false); } void Project::saveTilesetMetatileAttributes(Tileset *tileset) { @@ -622,10 +624,29 @@ void Project::saveTilesetMetatiles(Tileset *tileset) { } void Project::saveTilesetTilesImage(Tileset *tileset) { - qDebug() << QString("saving tiles png to '%1'").arg(tileset->tilesImagePath); tileset->tilesImage.save(tileset->tilesImagePath); } +void Project::saveTilesetPalettes(Tileset *tileset, bool primary) { + int startPaletteId = primary ? 0 : Project::getNumPalettesPrimary(); + int endPaletteId = primary ? Project::getNumPalettesPrimary() : Project::getNumPalettesTotal(); + for (int i = startPaletteId; i < endPaletteId; i++) { + QString filepath = tileset->palettePaths.at(i); + QString content = "JASC-PAL\r\n"; + content += "0100\r\n"; + content += "16\r\n"; + for (int j = 0; j < 16; j++) { + QRgb color = tileset->palettes->at(i).at(j); + content += QString("%1 %2 %3\r\n") + .arg(qRed(color)) + .arg(qGreen(color)) + .arg(qBlue(color)); + } + + saveTextFile(filepath, content); + } +} + void Project::loadMapTilesets(Map* map) { if (map->layout->has_unsaved_changes) { return; @@ -820,16 +841,15 @@ void Project::loadTilesetAssets(Tileset* tileset) { } } - QStringList *palette_paths = new QStringList; if (!palettes_values->isEmpty()) { for (int i = 0; i < palettes_values->length(); i++) { QString value = palettes_values->value(i); - palette_paths->append(root + "/" + value.section('"', 1, 1)); + tileset->palettePaths.append(this->fixPalettePath(root + "/" + value.section('"', 1, 1))); } } else { QString palettes_dir_path = dir_path + "/palettes"; for (int i = 0; i < 16; i++) { - palette_paths->append(palettes_dir_path + "/" + QString("%1").arg(i, 2, 10, QLatin1Char('0')) + ".gbapal"); + tileset->palettePaths.append(palettes_dir_path + "/" + QString("%1").arg(i, 2, 10, QLatin1Char('0')) + ".pal"); } } @@ -856,24 +876,31 @@ void Project::loadTilesetAssets(Tileset* tileset) { // palettes QList> *palettes = new QList>; - for (int i = 0; i < palette_paths->length(); i++) { - QString path = palette_paths->value(i); - // the palettes are not compressed. this should never happen. it's only a precaution. - path = path.replace(QRegExp("\\.lz$"), ""); - // TODO default to .pal (JASC-PAL) - // just use .gbapal for now - QFile file(path); + for (int i = 0; i < tileset->palettePaths.length(); i++) { QList palette; - if (file.open(QIODevice::ReadOnly)) { - QByteArray data = file.readAll(); - for (int j = 0; j < 16; j++) { - uint16_t word = data[j*2] & 0xff; - word += (data[j*2 + 1] & 0xff) << 8; - int red = word & 0x1f; - int green = (word >> 5) & 0x1f; - int blue = (word >> 10) & 0x1f; - QRgb color = qRgb(red * 8, green * 8, blue * 8); - palette.append(color); + QString path = tileset->palettePaths.value(i); + QString text = readTextFile(path); + if (!text.isNull()) { + QStringList lines = text.split(QRegExp("[\r\n]"),QString::SkipEmptyParts); + if (lines.length() == 19 && lines[0] == "JASC-PAL" && lines[1] == "0100" && lines[2] == "16") { + for (int j = 0; j < 16; j++) { + QStringList rgb = lines[j + 3].split(QRegExp(" "), QString::SkipEmptyParts); + if (rgb.length() != 3) { + qDebug() << QString("Invalid tileset palette RGB value: '%1'").arg(lines[j + 3]); + palette.append(qRgb((j - 3) * 16, (j - 3) * 16, (j - 3) * 16)); + } else { + int red = rgb[0].toInt(); + int green = rgb[1].toInt(); + int blue = rgb[2].toInt(); + QRgb color = qRgb(red, green, blue); + palette.append(color); + } + } + } else { + qDebug() << QString("Invalid JASC-PAL palette file for tileset."); + for (int j = 0; j < 16; j++) { + palette.append(qRgb(j * 16, j * 16, j * 16)); + } } } else { for (int j = 0; j < 16; j++) { @@ -1405,6 +1432,11 @@ QMap Project::getEventObjGfxConstants() { return constants; } +QString Project::fixPalettePath(QString path) { + path = path.replace(QRegExp("\\.gbapal$"), ".pal"); + return path; +} + QString Project::fixGraphicPath(QString path) { path = path.replace(QRegExp("\\.lz$"), ""); path = path.replace(QRegExp("\\.[1248]bpp$"), ".png"); diff --git a/src/ui/paletteeditor.cpp b/src/ui/paletteeditor.cpp new file mode 100644 index 00000000..bd67fa5f --- /dev/null +++ b/src/ui/paletteeditor.cpp @@ -0,0 +1,176 @@ +#include "paletteeditor.h" +#include "ui_paletteeditor.h" + +PaletteEditor::PaletteEditor(Project *project, Tileset *primaryTileset, Tileset *secondaryTileset, QWidget *parent) : + QMainWindow(parent), + ui(new Ui::PaletteEditor) +{ + this->project = project; + this->primaryTileset = primaryTileset; + this->secondaryTileset = secondaryTileset; + this->ui->setupUi(this); + this->ui->spinBox_PaletteId->setMinimum(0); + this->ui->spinBox_PaletteId->setMaximum(Project::getNumPalettesTotal() - 1); + this->sliders.clear(); + for (int i = 0; i < 16; i++) { + this->sliders.append(QList()); + } + this->sliders[0].append(this->ui->horizontalSlider); + this->sliders[0].append(this->ui->horizontalSlider_2); + this->sliders[0].append(this->ui->horizontalSlider_3); + this->sliders[1].append(this->ui->horizontalSlider_4); + this->sliders[1].append(this->ui->horizontalSlider_5); + this->sliders[1].append(this->ui->horizontalSlider_6); + this->sliders[2].append(this->ui->horizontalSlider_7); + this->sliders[2].append(this->ui->horizontalSlider_8); + this->sliders[2].append(this->ui->horizontalSlider_9); + this->sliders[3].append(this->ui->horizontalSlider_10); + this->sliders[3].append(this->ui->horizontalSlider_11); + this->sliders[3].append(this->ui->horizontalSlider_12); + this->sliders[4].append(this->ui->horizontalSlider_13); + this->sliders[4].append(this->ui->horizontalSlider_14); + this->sliders[4].append(this->ui->horizontalSlider_15); + this->sliders[5].append(this->ui->horizontalSlider_16); + this->sliders[5].append(this->ui->horizontalSlider_17); + this->sliders[5].append(this->ui->horizontalSlider_18); + this->sliders[6].append(this->ui->horizontalSlider_19); + this->sliders[6].append(this->ui->horizontalSlider_20); + this->sliders[6].append(this->ui->horizontalSlider_21); + this->sliders[7].append(this->ui->horizontalSlider_22); + this->sliders[7].append(this->ui->horizontalSlider_23); + this->sliders[7].append(this->ui->horizontalSlider_24); + this->sliders[8].append(this->ui->horizontalSlider_25); + this->sliders[8].append(this->ui->horizontalSlider_26); + this->sliders[8].append(this->ui->horizontalSlider_27); + this->sliders[9].append(this->ui->horizontalSlider_28); + this->sliders[9].append(this->ui->horizontalSlider_29); + this->sliders[9].append(this->ui->horizontalSlider_30); + this->sliders[10].append(this->ui->horizontalSlider_31); + this->sliders[10].append(this->ui->horizontalSlider_32); + this->sliders[10].append(this->ui->horizontalSlider_33); + this->sliders[11].append(this->ui->horizontalSlider_34); + this->sliders[11].append(this->ui->horizontalSlider_35); + this->sliders[11].append(this->ui->horizontalSlider_36); + this->sliders[12].append(this->ui->horizontalSlider_37); + this->sliders[12].append(this->ui->horizontalSlider_38); + this->sliders[12].append(this->ui->horizontalSlider_39); + this->sliders[13].append(this->ui->horizontalSlider_40); + this->sliders[13].append(this->ui->horizontalSlider_41); + this->sliders[13].append(this->ui->horizontalSlider_42); + this->sliders[14].append(this->ui->horizontalSlider_43); + this->sliders[14].append(this->ui->horizontalSlider_44); + this->sliders[14].append(this->ui->horizontalSlider_45); + this->sliders[15].append(this->ui->horizontalSlider_46); + this->sliders[15].append(this->ui->horizontalSlider_47); + this->sliders[15].append(this->ui->horizontalSlider_48); + + this->frames.clear(); + this->frames.append(this->ui->frame); + this->frames.append(this->ui->frame_2); + this->frames.append(this->ui->frame_3); + this->frames.append(this->ui->frame_4); + this->frames.append(this->ui->frame_5); + this->frames.append(this->ui->frame_6); + this->frames.append(this->ui->frame_7); + this->frames.append(this->ui->frame_8); + this->frames.append(this->ui->frame_9); + this->frames.append(this->ui->frame_10); + this->frames.append(this->ui->frame_11); + this->frames.append(this->ui->frame_12); + this->frames.append(this->ui->frame_13); + this->frames.append(this->ui->frame_14); + this->frames.append(this->ui->frame_15); + this->frames.append(this->ui->frame_16); + + this->initColorSliders(); + this->refreshColorSliders(); + this->refreshColors(); +} + +PaletteEditor::~PaletteEditor() +{ + delete ui; +} + +void PaletteEditor::disableSliderSignals() { + for (int i = 0; i < this->sliders.length(); i++) { + this->sliders.at(i).at(0)->blockSignals(true); + this->sliders.at(i).at(1)->blockSignals(true); + this->sliders.at(i).at(2)->blockSignals(true); + } +} + +void PaletteEditor::enableSliderSignals() { + for (int i = 0; i < this->sliders.length(); i++) { + this->sliders.at(i).at(0)->blockSignals(false); + this->sliders.at(i).at(1)->blockSignals(false); + this->sliders.at(i).at(2)->blockSignals(false); + } +} + +void PaletteEditor::initColorSliders() { + for (int i = 0; i < 16; i++) { + connect(this->sliders[i][0], &QSlider::valueChanged, [=](int) { this->setColor(i); }); + connect(this->sliders[i][1], &QSlider::valueChanged, [=](int) { this->setColor(i); }); + connect(this->sliders[i][2], &QSlider::valueChanged, [=](int) { this->setColor(i); }); + } +} + +void PaletteEditor::refreshColorSliders() { + disableSliderSignals(); + int paletteNum = this->ui->spinBox_PaletteId->value(); + for (int i = 0; i < 16; i++) { + QRgb color; + if (paletteNum < Project::getNumPalettesPrimary()) { + color = this->primaryTileset->palettes->at(paletteNum).at(i); + } else { + color = this->secondaryTileset->palettes->at(paletteNum).at(i); + } + + this->sliders[i][0]->setValue(qRed(color) / 8); + this->sliders[i][1]->setValue(qGreen(color) / 8); + this->sliders[i][2]->setValue(qBlue(color) / 8); + } + enableSliderSignals(); +} + +void PaletteEditor::refreshColors() { + for (int i = 0; i < 16; i++) { + this->refreshColor(i); + } +} + +void PaletteEditor::refreshColor(int colorIndex) { + QString stylesheet = QString("background-color: rgb(%1, %2, %3);") + .arg(this->sliders[colorIndex][0]->value() * 8) + .arg(this->sliders[colorIndex][1]->value() * 8) + .arg(this->sliders[colorIndex][2]->value() * 8); + this->frames[colorIndex]->setStyleSheet(stylesheet); +} + +void PaletteEditor::setPaletteId(int paletteId) { + this->ui->spinBox_PaletteId->blockSignals(true); + this->ui->spinBox_PaletteId->setValue(paletteId); + this->refreshColorSliders(); + this->refreshColors(); + this->ui->spinBox_PaletteId->blockSignals(false); +} + +void PaletteEditor::setColor(int colorIndex) { + int paletteNum = this->ui->spinBox_PaletteId->value(); + int red = this->sliders[colorIndex][0]->value() * 8; + int green = this->sliders[colorIndex][1]->value() * 8; + int blue = this->sliders[colorIndex][2]->value() * 8; + Tileset *tileset = paletteNum < Project::getNumPalettesPrimary() + ? this->primaryTileset + : this->secondaryTileset; + (*tileset->palettes)[paletteNum][colorIndex] = qRgb(red, green, blue); + this->refreshColor(colorIndex); + emit this->changedPaletteColor(); +} + +void PaletteEditor::on_spinBox_PaletteId_valueChanged(int paletteId) { + this->refreshColorSliders(); + this->refreshColors(); + emit this->changedPalette(paletteId); +} diff --git a/src/ui/tileseteditor.cpp b/src/ui/tileseteditor.cpp index b1d388c7..60fe30d4 100644 --- a/src/ui/tileseteditor.cpp +++ b/src/ui/tileseteditor.cpp @@ -215,9 +215,15 @@ void TilesetEditor::onMetatileLayerTileChanged(int x, int y) { void TilesetEditor::on_spinBox_paletteSelector_valueChanged(int paletteId) { + this->ui->spinBox_paletteSelector->blockSignals(true); + this->ui->spinBox_paletteSelector->setValue(paletteId); + this->ui->spinBox_paletteSelector->blockSignals(false); this->paletteId = paletteId; this->tileSelector->setPaletteId(paletteId); this->drawSelectedTiles(); + if (this->paletteEditor) { + this->paletteEditor->setPaletteId(paletteId); + } } void TilesetEditor::on_checkBox_xFlip_stateChanged(int checked) @@ -241,7 +247,6 @@ void TilesetEditor::on_comboBox_metatileBehaviors_currentIndexChanged(const QStr } } - void TilesetEditor::on_comboBox_layerType_currentIndexChanged(int layerType) { if (this->metatile) { @@ -419,3 +424,37 @@ void TilesetEditor::on_actionChange_Metatiles_Count_triggered() this->hasUnsavedChanges = true; } } + +void TilesetEditor::onPaletteEditorClosed() { + if (this->paletteEditor) { + delete this->paletteEditor; + this->paletteEditor = nullptr; + } +} + +void TilesetEditor::on_actionChange_Palettes_triggered() +{ + if (!this->paletteEditor) { + this->paletteEditor = new PaletteEditor(this->project, this->primaryTileset, this->secondaryTileset, this); + connect(this->paletteEditor, SIGNAL(closed()), this, SLOT(onPaletteEditorClosed())); + connect(this->paletteEditor, SIGNAL(changedPaletteColor()), this, SLOT(onPaletteEditorChangedPaletteColor())); + connect(this->paletteEditor, SIGNAL(changedPalette(int)), this, SLOT(onPaletteEditorChangedPalette(int))); + } + + if (!this->paletteEditor->isVisible()) { + this->paletteEditor->show(); + } else if (this->paletteEditor->isMinimized()) { + this->paletteEditor->showNormal(); + } else { + this->paletteEditor->activateWindow(); + } +} + +void TilesetEditor::onPaletteEditorChangedPaletteColor() { + this->refresh(); + this->hasUnsavedChanges = true; +} + +void TilesetEditor::onPaletteEditorChangedPalette(int paletteId) { + this->on_spinBox_paletteSelector_valueChanged(paletteId); +}