diff --git a/source/mainwindow.cpp b/source/mainwindow.cpp index 30a25ea8..81620bac 100644 --- a/source/mainwindow.cpp +++ b/source/mainwindow.cpp @@ -625,7 +625,7 @@ void MainWindow::openFile(const OpenAsParam ¶ms) QObject::connect(this->trnUniqueWidget, &PaletteWidget::clearRootBorder, this->trnWidget, &PaletteWidget::clearBorder); if (isTileset) { - this->levelCelView = new LevelCelView(this->undoStack); + this->levelCelView = new LevelCelView(this->undoStack, this); this->levelCelView->initialize(this->gfx, this->min, this->til, this->sol, this->amp); // Refresh CEL view if a PAL or TRN is modified @@ -651,7 +651,7 @@ void MainWindow::openFile(const OpenAsParam ¶ms) } // Otherwise build a CelView else { - this->celView = new CelView(this->undoStack); + this->celView = new CelView(this->undoStack, this); this->celView->initialize(this->gfx); // Refresh CEL view if a PAL or TRN is modified @@ -778,6 +778,12 @@ void MainWindow::openPalFiles(QStringList filePaths, PaletteWidget *widget) this->ui->statusBar->clearMessage(); } +void MainWindow::updateStatusBar(const QString &status, const QString &styleSheet) +{ + this->ui->statusBar->setStyleSheet(styleSheet); + this->ui->statusBar->showMessage(status); +} + void MainWindow::saveFile(const QString &gfxPath) { this->ui->statusBar->showMessage("Saving..."); diff --git a/source/mainwindow.h b/source/mainwindow.h index 0711caf1..570358f0 100644 --- a/source/mainwindow.h +++ b/source/mainwindow.h @@ -63,6 +63,7 @@ class MainWindow : public QMainWindow { void nextPaletteCycle(D1PAL_CYCLE_TYPE type); void resetPaletteCycle(); + void updateStatusBar(const QString &status, const QString &styleSheet); QString getLastFilePath(); QString fileDialog(FILE_DIALOG_MODE mode, const char *title, const char *filter); diff --git a/source/views/celview.cpp b/source/views/celview.cpp index 92e4eba8..67b9a4a7 100644 --- a/source/views/celview.cpp +++ b/source/views/celview.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include "ui_celview.h" #include "undostack/framecmds.h" @@ -40,6 +41,25 @@ void CelScene::mousePressEvent(QGraphicsSceneMouseEvent *event) emit this->framePixelClicked(x, y); } +void CelScene::mouseMoveEvent(QGraphicsSceneMouseEvent *event) +{ + bool isInImage = false; + auto *levelcelview = dynamic_cast(view); + if (levelcelview != nullptr) { + if (levelcelview->checkImageType(event->scenePos().x(), event->scenePos().y()) != IMAGE_TYPE::NONE) + isInImage = true; + } else { + isInImage = dynamic_cast(view)->isInImage(event->scenePos().x(), event->scenePos().y()); + } + + if (isInImage) { + dynamic_cast(view->window())->updateStatusBar(QString::fromStdString(std::to_string(static_cast(event->scenePos().x())) + ", " + std::to_string(static_cast(event->scenePos().y()))), "color: rgb(0, 0, 0);"); + return; + } + + dynamic_cast(view->window())->updateStatusBar(QString::fromStdString(std::to_string(static_cast(event->scenePos().x())) + ", " + std::to_string(static_cast(event->scenePos().y()))), "color: rgb(160, 160, 160);"); +} + void CelScene::dragEnterEvent(QGraphicsSceneDragDropEvent *event) { this->dragMoveEvent(event); @@ -73,7 +93,7 @@ void CelScene::contextMenuEvent(QContextMenuEvent *event) CelView::CelView(std::shared_ptr us, QWidget *parent) : QWidget(parent) - , undoStack(us) + , undoStack(std::move(us)) , ui(new Ui::CelView()) , celScene(new CelScene(this)) { @@ -121,18 +141,23 @@ int CelView::getCurrentFrameIndex() return this->currentFrameIndex; } -void CelView::framePixelClicked(unsigned x, unsigned y) +bool CelView::isInImage(unsigned int x, unsigned int y) const { - int frameIndex = this->currentFrameIndex; + const int frameIndex = this->currentFrameIndex; + + const int tx = x - CEL_SCENE_SPACING; + const int ty = y - CEL_SCENE_SPACING; + + return ((ty > 0 && ty < this->gfx->getFrameHeight(frameIndex)) /* Coordinates are above/below image */ + && (tx > 0 && tx < this->gfx->getFrameWidth(frameIndex) /* Coordinates are to the left/right of the image */)); +} - int tx = x - CEL_SCENE_SPACING; - if (tx < 0 || tx >= this->gfx->getFrameWidth(frameIndex)) - return; // click is left or right from the frame -> ignore - int ty = y - CEL_SCENE_SPACING; - if (ty < 0 || ty >= this->gfx->getFrameHeight(frameIndex)) - return; // click is up or down from the frame -> ignore +void CelView::framePixelClicked(unsigned x, unsigned y) +{ + if (!isInImage(x, y)) + return; - int colorIndex = this->gfx->getFrame(frameIndex)->getPixel(tx, ty).getPaletteIndex(); + int colorIndex = this->gfx->getFrame(this->currentFrameIndex)->getPixel(x - CEL_SCENE_SPACING, y - CEL_SCENE_SPACING).getPaletteIndex(); emit this->colorIndexClicked(colorIndex); } diff --git a/source/views/celview.h b/source/views/celview.h index cec78e7b..9cd1b4c0 100644 --- a/source/views/celview.h +++ b/source/views/celview.h @@ -33,6 +33,7 @@ class CelScene : public QGraphicsScene { private slots: void mousePressEvent(QGraphicsSceneMouseEvent *event); + void mouseMoveEvent(QGraphicsSceneMouseEvent *event); void dragEnterEvent(QGraphicsSceneDragDropEvent *event); void dragMoveEvent(QGraphicsSceneDragDropEvent *event); void dropEvent(QGraphicsSceneDragDropEvent *event); @@ -66,6 +67,7 @@ class CelView : public QWidget { void updateGroupIndex(); void displayFrame(); + [[nodiscard]] bool isInImage(unsigned int x, unsigned int y) const; signals: void frameRefreshed(); diff --git a/source/views/levelcelview.cpp b/source/views/levelcelview.cpp index b3cdba61..802ae8d0 100644 --- a/source/views/levelcelview.cpp +++ b/source/views/levelcelview.cpp @@ -184,6 +184,45 @@ void LevelCelView::update() this->tabFrameWidget->initialize(this, this->gfx); } +/** + * @brief Checks in which image type the coordinates are currently in + * + * This function accepts coordinates and checks, based on them in which + * image type (frame, tile or megatile), the coordinates are currently in. + * This is currently useful for knowing where exactly user's cursor is. + */ +IMAGE_TYPE LevelCelView::checkImageType(unsigned x, unsigned y) +{ + unsigned celFrameWidth = MICRO_WIDTH; // this->gfx->getFrameWidth(this->currentFrameIndex); + unsigned subtileWidth = this->min->getSubtileWidth() * MICRO_WIDTH; + unsigned tileWidth = subtileWidth * TILE_WIDTH; + + unsigned celFrameHeight = MICRO_HEIGHT; // this->gfx->getFrameHeight(this->currentFrameIndex); + unsigned subtileHeight = this->min->getSubtileHeight() * MICRO_HEIGHT; + unsigned subtileShiftY = subtileWidth / 4; + unsigned tileHeight = subtileHeight + 2 * subtileShiftY; + + if (x >= CEL_SCENE_SPACING && x < (celFrameWidth + CEL_SCENE_SPACING) + && y >= CEL_SCENE_SPACING && y < (celFrameHeight + CEL_SCENE_SPACING) + && this->gfx->getFrameCount() != 0) { + return IMAGE_TYPE::FRAME; + } else if (x >= (celFrameWidth + CEL_SCENE_SPACING * 2) + && x < (celFrameWidth + subtileWidth + CEL_SCENE_SPACING * 2) + && y >= CEL_SCENE_SPACING + && y < (subtileHeight + CEL_SCENE_SPACING) + && this->min->getSubtileCount() != 0) { + return IMAGE_TYPE::SUBTILE; + } else if (x >= (celFrameWidth + subtileWidth + CEL_SCENE_SPACING * 3) + && x < (celFrameWidth + subtileWidth + tileWidth + CEL_SCENE_SPACING * 3) + && y >= CEL_SCENE_SPACING + && y < (tileHeight + CEL_SCENE_SPACING) + && this->til->getTileCount() != 0) { + return IMAGE_TYPE::TILE; + } + + return IMAGE_TYPE::NONE; +} + void LevelCelView::framePixelClicked(unsigned x, unsigned y) { quint8 index = 0; @@ -199,19 +238,16 @@ void LevelCelView::framePixelClicked(unsigned x, unsigned y) this->mode = TILESET_MODE::FREE; - if (x >= CEL_SCENE_SPACING && x < (celFrameWidth + CEL_SCENE_SPACING) - && y >= CEL_SCENE_SPACING && y < (celFrameHeight + CEL_SCENE_SPACING) - && this->gfx->getFrameCount() != 0) { + switch (this->checkImageType(x, y)) { + case IMAGE_TYPE::FRAME: { // If CEL frame color is clicked, select it in the palette widgets D1GfxFrame *frame = this->gfx->getFrame(this->currentFrameIndex); index = frame->getPixel(x - CEL_SCENE_SPACING, y - CEL_SCENE_SPACING).getPaletteIndex(); emit this->colorIndexClicked(index); - } else if (x >= (celFrameWidth + CEL_SCENE_SPACING * 2) - && x < (celFrameWidth + subtileWidth + CEL_SCENE_SPACING * 2) - && y >= CEL_SCENE_SPACING - && y < (subtileHeight + CEL_SCENE_SPACING) - && this->min->getSubtileCount() != 0) { + break; + } + case IMAGE_TYPE::SUBTILE: { this->mode = TILESET_MODE::SUBTILE; // When a CEL frame is clicked in the subtile, display the corresponding CEL frame @@ -230,11 +266,9 @@ void LevelCelView::framePixelClicked(unsigned x, unsigned y) this->currentFrameIndex = frameIndex - 1; this->displayFrame(); } - } else if (x >= (celFrameWidth + subtileWidth + CEL_SCENE_SPACING * 3) - && x < (celFrameWidth + subtileWidth + tileWidth + CEL_SCENE_SPACING * 3) - && y >= CEL_SCENE_SPACING - && y < (tileHeight + CEL_SCENE_SPACING) - && this->til->getTileCount() != 0) { + break; + } + case IMAGE_TYPE::TILE: { this->mode = TILESET_MODE::TILE; // When a subtile is clicked in the tile, display the corresponding subtile @@ -249,6 +283,10 @@ void LevelCelView::framePixelClicked(unsigned x, unsigned y) this->currentSubtileIndex = tilSubtiles.at(this->editIndex); this->displayFrame(); } + break; + } + default: + break; } this->update(); diff --git a/source/views/levelcelview.h b/source/views/levelcelview.h index 6f98e691..6a76af3a 100644 --- a/source/views/levelcelview.h +++ b/source/views/levelcelview.h @@ -39,6 +39,13 @@ enum class TILESET_MODE { TILE, // Edit tile }; +enum class IMAGE_TYPE { + NONE, + FRAME, + SUBTILE, + TILE +}; + class LevelCelView : public QWidget { Q_OBJECT @@ -94,6 +101,8 @@ class LevelCelView : public QWidget { void displayFrame(); + IMAGE_TYPE checkImageType(unsigned int x, unsigned int y); + private: void update(); void collectFrameUsers(int frameIndex, QList &users) const; diff --git a/source/views/view.cpp b/source/views/view.cpp index 54f38f7e..01de0d0c 100644 --- a/source/views/view.cpp +++ b/source/views/view.cpp @@ -1,8 +1,10 @@ #include "view.h" +#include "mainwindow.h" View::View(QWidget *parent) : QGraphicsView(parent) { + this->setMouseTracking(true); } void View::mousePressEvent(QMouseEvent *event) @@ -50,3 +52,8 @@ void View::mouseReleaseEvent(QMouseEvent *event) } } } + +void View::leaveEvent(QEvent *event) +{ + dynamic_cast(this->window())->updateStatusBar("", "color: rgb(0, 0, 0);"); +} diff --git a/source/views/view.h b/source/views/view.h index 62de97dd..235f93cd 100644 --- a/source/views/view.h +++ b/source/views/view.h @@ -13,4 +13,5 @@ class View : public QGraphicsView { private slots: void mouseReleaseEvent(QMouseEvent *event); void mousePressEvent(QMouseEvent *event); + void leaveEvent(QEvent *event) override; };