#include "imageproviders.h" #include "metatileselector.h" #include "project.h" #include QPoint MetatileSelector::getSelectionDimensions() { if (this->prefabSelection || this->externalSelection) return selection.dimensions; return SelectablePixmapItem::getSelectionDimensions(); } void MetatileSelector::draw() { if (!this->primaryTileset || !this->secondaryTileset) { this->setPixmap(QPixmap()); } int primaryLength = this->primaryTileset->metatiles.length(); int length_ = primaryLength + this->secondaryTileset->metatiles.length(); int height_ = length_ / this->numMetatilesWide; if (length_ % this->numMetatilesWide != 0) { height_++; } QImage image(this->numMetatilesWide * 16, height_ * 16, QImage::Format_RGBA8888); image.fill(Qt::magenta); 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, map->metatileLayerOrder, map->metatileLayerOpacity); int map_y = i / this->numMetatilesWide; int map_x = i % this->numMetatilesWide; QPoint metatile_origin = QPoint(map_x * 16, map_y * 16); painter.drawImage(metatile_origin, metatile_image); } painter.end(); this->setPixmap(QPixmap::fromImage(image)); if (!this->prefabSelection && (!this->externalSelection || (this->externalSelectionWidth == 1 && this->externalSelectionHeight == 1))) { this->drawSelection(); } } bool MetatileSelector::select(uint16_t metatileId) { if (!Tileset::metatileIsValid(metatileId, this->primaryTileset, this->secondaryTileset)) return false; this->externalSelection = false; this->prefabSelection = false; this->selection = MetatileSelection{ QPoint(1, 1), false, QList({MetatileSelectionItem{true, metatileId}}), QList(), }; QPoint coords = this->getMetatileIdCoords(metatileId); SelectablePixmapItem::select(coords.x(), coords.y(), 0, 0); this->updateSelectedMetatiles(); return true; } bool MetatileSelector::selectFromMap(uint16_t metatileId, uint16_t collision, uint16_t elevation) { if (!Tileset::metatileIsValid(metatileId, this->primaryTileset, this->secondaryTileset)) return false; this->select(metatileId); this->selection.collisionItems.append(CollisionSelectionItem{true, collision, elevation}); this->selection.hasCollision = true; return true; } void MetatileSelector::setTilesets(Tileset *primaryTileset, Tileset *secondaryTileset) { this->primaryTileset = primaryTileset; this->secondaryTileset = secondaryTileset; if (this->externalSelection) this->updateExternalSelectedMetatiles(); else this->updateSelectedMetatiles(); this->draw(); } MetatileSelection MetatileSelector::getMetatileSelection() { return selection; } void MetatileSelector::setExternalSelection(int width, int height, QList metatiles, QList> collisions) { this->prefabSelection = false; this->externalSelection = true; this->externalSelectionWidth = width; this->externalSelectionHeight = height; this->externalSelectedMetatiles.clear(); this->selection.metatileItems.clear(); this->selection.collisionItems.clear(); this->selection.hasCollision = true; this->selection.dimensions = QPoint(width, height); for (int i = 0; i < metatiles.length(); i++) { auto collision = collisions.at(i); this->selection.collisionItems.append(CollisionSelectionItem{true, collision.first, collision.second}); uint16_t metatileId = metatiles.at(i); this->externalSelectedMetatiles.append(metatileId); if (!Tileset::metatileIsValid(metatileId, this->primaryTileset, this->secondaryTileset)) metatileId = 0; this->selection.metatileItems.append(MetatileSelectionItem{true, metatileId}); } this->draw(); emit selectedMetatilesChanged(); } void MetatileSelector::setPrefabSelection(MetatileSelection selection) { this->externalSelection = false; this->prefabSelection = true; this->externalSelectedMetatiles.clear(); this->selection = selection; this->draw(); emit selectedMetatilesChanged(); } bool MetatileSelector::shouldAcceptEvent(QGraphicsSceneMouseEvent *event) { QPoint pos = this->getCellPos(event->pos()); return Tileset::metatileIsValid(getMetatileId(pos.x(), pos.y()), this->primaryTileset, this->secondaryTileset); } void MetatileSelector::mousePressEvent(QGraphicsSceneMouseEvent *event) { if (!shouldAcceptEvent(event)) return; SelectablePixmapItem::mousePressEvent(event); this->updateSelectedMetatiles(); } void MetatileSelector::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { if (!shouldAcceptEvent(event)) return; SelectablePixmapItem::mouseMoveEvent(event); this->updateSelectedMetatiles(); QPoint pos = this->getCellPos(event->pos()); uint16_t metatileId = this->getMetatileId(pos.x(), pos.y()); emit this->hoveredMetatileSelectionChanged(metatileId); } void MetatileSelector::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { if (!shouldAcceptEvent(event)) return; SelectablePixmapItem::mouseReleaseEvent(event); this->updateSelectedMetatiles(); } void MetatileSelector::hoverMoveEvent(QGraphicsSceneHoverEvent *event) { QPoint pos = this->getCellPos(event->pos()); uint16_t metatileId = this->getMetatileId(pos.x(), pos.y()); emit this->hoveredMetatileSelectionChanged(metatileId); } void MetatileSelector::hoverLeaveEvent(QGraphicsSceneHoverEvent*) { emit this->hoveredMetatileSelectionCleared(); } void MetatileSelector::updateSelectedMetatiles() { this->externalSelection = false; this->prefabSelection = false; this->selection.metatileItems.clear(); this->selection.collisionItems.clear(); this->selection.hasCollision = false; this->selection.dimensions = this->getSelectionDimensions(); QPoint origin = this->getSelectionStart(); for (int j = 0; j < this->selection.dimensions.y(); j++) { for (int i = 0; i < this->selection.dimensions.x(); i++) { uint16_t metatileId = this->getMetatileId(origin.x() + i, origin.y() + j); if (!Tileset::metatileIsValid(metatileId, this->primaryTileset, this->secondaryTileset)) metatileId = 0; this->selection.metatileItems.append(MetatileSelectionItem{true, metatileId}); } } emit selectedMetatilesChanged(); } void MetatileSelector::updateExternalSelectedMetatiles() { this->selection.metatileItems.clear(); this->selection.dimensions = QPoint(this->externalSelectionWidth, this->externalSelectionHeight); for (int i = 0; i < this->externalSelectedMetatiles.count(); ++i) { uint16_t metatileId = this->externalSelectedMetatiles.at(i); if (!Tileset::metatileIsValid(metatileId, this->primaryTileset, this->secondaryTileset)) metatileId = 0; this->selection.metatileItems.append(MetatileSelectionItem{true, metatileId}); } emit selectedMetatilesChanged(); } uint16_t MetatileSelector::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()); } } QPoint MetatileSelector::getMetatileIdCoords(uint16_t metatileId) { if (!Tileset::metatileIsValid(metatileId, this->primaryTileset, this->secondaryTileset)) { // 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); } QPoint MetatileSelector::getMetatileIdCoordsOnWidget(uint16_t metatileId) { QPoint pos = getMetatileIdCoords(metatileId); pos.rx() = (pos.x() * this->cellWidth) + (this->cellWidth / 2); pos.ry() = (pos.y() * this->cellHeight) + (this->cellHeight / 2); return pos; } void MetatileSelector::setMap(Map *map) { this->map = map; }