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