porymap/src/ui/resizelayoutpopup.cpp
2024-11-12 12:30:56 -05:00

187 lines
8 KiB
C++

#include "resizelayoutpopup.h"
#include "editor.h"
#include "movablerect.h"
#include "config.h"
#include "ui_resizelayoutpopup.h"
// TODO: put this in a util file or something
extern int roundUp(int, int);
CheckeredBgScene::CheckeredBgScene(QObject *parent) : QGraphicsScene(parent) { }
void CheckeredBgScene::drawBackground(QPainter *painter, const QRectF &rect) {
QRect r = rect.toRect();
int xMin = r.left() - r.left() % this->gridSize - this->gridSize;
int yMin = r.top() - r.top() % this->gridSize - this->gridSize;
int xMax = r.right() - r.right() % this->gridSize + this->gridSize;
int yMax = r.bottom() - r.bottom() % this->gridSize + this->gridSize;
// draw grid 16x16 from top to bottom of scene
QColor paintColor(0x00ff00);
for (int x = xMin, xTile = 0; x <= xMax; x += this->gridSize, xTile++) {
for (int y = yMin, yTile = 0; y <= yMax; y += this->gridSize, yTile++) {
if (!((xTile ^ yTile) & 1)) { // tile numbers have same parity (evenness)
if (this->validRect.contains(x, y))
paintColor = QColor(132, 217, 165); // green light color
else
paintColor = 0xbcbcbc; // normal light color
}
else {
if (this->validRect.contains(x, y))
paintColor = QColor(76, 178, 121); // green dark color
else
paintColor = 0x969696; // normal dark color
}
painter->fillRect(QRect(x, y, this->gridSize, this->gridSize), paintColor);
}
}
}
/******************************************************************************
************************************************************************
******************************************************************************/
BoundedPixmapItem::BoundedPixmapItem(const QPixmap &pixmap, QGraphicsItem *parent) : QGraphicsPixmapItem(pixmap, parent) {
setFlags(this->flags() | QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemSendsGeometryChanges | QGraphicsItem::ItemIsSelectable);
}
void BoundedPixmapItem::paint(QPainter *painter, const QStyleOptionGraphicsItem * item, QWidget *widget) {
// Draw the pixmap darkened in the background
painter->fillRect(this->boundingRect().toAlignedRect(), QColor(0x444444));
painter->setCompositionMode(QPainter::CompositionMode_Multiply);
painter->drawPixmap(this->boundingRect().toAlignedRect(), this->pixmap());
// draw the normal pixmap on top, cropping to validRect as needed
painter->setCompositionMode(QPainter::CompositionMode_SourceOver);
QRect intersection = this->mapRectFromScene(this->boundary->rect()).toAlignedRect() & this->boundingRect().toAlignedRect();
QPixmap cropped = this->pixmap().copy(intersection);
painter->drawPixmap(intersection, cropped);
}
QVariant BoundedPixmapItem::itemChange(GraphicsItemChange change, const QVariant &value) {
if (change == ItemPositionChange && scene()) {
QPointF newPos = value.toPointF();
return QPointF(roundUp(newPos.x(), 16), roundUp(newPos.y(), 16));
}
else
return QGraphicsItem::itemChange(change, value);
}
/******************************************************************************
************************************************************************
******************************************************************************/
ResizeLayoutPopup::ResizeLayoutPopup(QWidget *parent, Editor *editor) :
QDialog(parent),
parent(parent),
editor(editor),
ui(new Ui::ResizeLayoutPopup)
{
ui->setupUi(this);
this->resetPosition();
this->setWindowFlags(this->windowFlags() | Qt::FramelessWindowHint);
this->setWindowModality(Qt::ApplicationModal);
this->scene = new CheckeredBgScene(this);
//this->ui->graphicsView->setAlignment(Qt::AlignTop|Qt::AlignLeft);
this->ui->graphicsView->setScene(this->scene);
this->ui->graphicsView->setRenderHints(QPainter::Antialiasing);
this->ui->graphicsView->setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
}
ResizeLayoutPopup::~ResizeLayoutPopup()
{
delete ui;
}
/// Reset position of the dialog to cover the MainWindow's layout metatile scene
void ResizeLayoutPopup::resetPosition() {
this->setGeometry(QRect(parent->mapToGlobal(QPoint(0, 0)), parent->size()));
}
/// Custom scene contains
/// (1) pixmap representing the current layout / not resizable / drag-movable
/// (1) layout outline / resizable / not movable
void ResizeLayoutPopup::setupLayoutView() {
if (!this->editor || !this->editor->layout) return;
// TODO: this should be a more robust check probably
// Border stuff
bool bordersEnabled = projectConfig.useCustomBorderSize;
if (bordersEnabled) {
this->ui->spinBox_borderWidth->setMinimum(1);
this->ui->spinBox_borderHeight->setMinimum(1);
this->ui->spinBox_borderWidth->setMaximum(MAX_BORDER_WIDTH);
this->ui->spinBox_borderHeight->setMaximum(MAX_BORDER_HEIGHT);
this->ui->spinBox_borderWidth->setLineEditEnabled(false);
this->ui->spinBox_borderHeight->setLineEditEnabled(false);
} else {
this->ui->frame_border->setVisible(false);
}
this->ui->spinBox_borderWidth->setValue(this->editor->layout->getBorderWidth());
this->ui->spinBox_borderHeight->setValue(this->editor->layout->getBorderHeight());
// Layout stuff
QPixmap pixmap = this->editor->layout->pixmap;
this->layoutPixmap = new BoundedPixmapItem(pixmap);
this->scene->addItem(layoutPixmap);
int maxWidth = this->editor->project->getMaxMapWidth();
int maxHeight = this->editor->project->getMaxMapHeight();
QGraphicsRectItem *cover = new QGraphicsRectItem(-maxWidth * 8, -maxHeight * 8, maxWidth * 16, maxHeight * 16);
this->scene->addItem(cover);
this->ui->spinBox_width->setMinimum(1);
this->ui->spinBox_width->setMaximum(maxWidth);
this->ui->spinBox_height->setMinimum(1);
this->ui->spinBox_height->setMaximum(maxHeight);
this->ui->spinBox_width->setLineEditEnabled(false);
this->ui->spinBox_height->setLineEditEnabled(false);
static bool layoutSizeRectVisible = true;
this->outline = new ResizableRect(this, &layoutSizeRectVisible, this->editor->layout->getWidth(), this->editor->layout->getHeight(), qRgb(255, 0, 255));
this->outline->setLimit(cover->rect().toAlignedRect());
connect(outline, &ResizableRect::rectUpdated, [=](QRect rect){
this->scene->setValidRect(rect);
this->ui->spinBox_width->setValue(rect.width() / 16);
this->ui->spinBox_height->setValue(rect.height() / 16);
});
scene->addItem(outline);
layoutPixmap->setBoundary(outline);
this->outline->rectUpdated(outline->rect().toAlignedRect());
this->ui->graphicsView->scale(0.5, 0.5);
this->ui->graphicsView->centerOn(layoutPixmap);
// this->ui->graphicsView->fitInView(cover->rect(), Qt::KeepAspectRatio);
}
void ResizeLayoutPopup::on_spinBox_width_valueChanged(int value) {
if (!this->outline) return;
QRectF rect = this->outline->rect();
this->outline->updatePosFromRect(QRect(rect.x(), rect.y(), value * 16, rect.height()));
}
void ResizeLayoutPopup::on_spinBox_height_valueChanged(int value) {
if (!this->outline) return;
QRectF rect = this->outline->rect();
this->outline->updatePosFromRect(QRect(rect.x(), rect.y(), rect.width(), value * 16));
}
/// Result is the number of metatiles to add (or subtract) to each side of the map after dimension changes
QMargins ResizeLayoutPopup::getResult() {
QMargins result = QMargins();
result.setLeft(this->layoutPixmap->x() - this->outline->rect().left());
result.setTop(this->layoutPixmap->y() - this->outline->rect().top());
result.setRight(this->outline->rect().right() - (this->layoutPixmap->x() + this->layoutPixmap->pixmap().width()));
result.setBottom(this->outline->rect().bottom() - (this->layoutPixmap->y() + this->layoutPixmap->pixmap().height()));
return result / 16;
}
QSize ResizeLayoutPopup::getBorderResult() {
return QSize(this->ui->spinBox_borderWidth->value(), this->ui->spinBox_borderHeight->value());
}