diff --git a/QtGameMaker.pro b/QtGameMaker.pro index dd36d89..1bdd6cf 100644 --- a/QtGameMaker.pro +++ b/QtGameMaker.pro @@ -38,8 +38,10 @@ HEADERS += \ src/editor/editorguiutils.h \ src/editor/roomscene.h \ src/editor/widgets/actiondragwidget.h \ + src/editor/widgets/coarsecolorwidget.h \ src/editor/widgets/colorwidget.h \ src/editor/widgets/draggabletreeview.h \ + src/editor/widgets/finecolorwidget.h \ src/editor/widgets/objectparentselectorwidget.h \ src/editor/widgets/objectselectorwidget.h \ src/editor/widgets/qlineeditwithmenu.h \ @@ -109,8 +111,10 @@ SOURCES += \ src/editor/editorguiutils.cpp \ src/editor/roomscene.cpp \ src/editor/widgets/actiondragwidget.cpp \ + src/editor/widgets/coarsecolorwidget.cpp \ src/editor/widgets/colorwidget.cpp \ src/editor/widgets/draggabletreeview.cpp \ + src/editor/widgets/finecolorwidget.cpp \ src/editor/widgets/objectparentselectorwidget.cpp \ src/editor/widgets/objectselectorwidget.cpp \ src/editor/widgets/qlineeditwithmenu.cpp \ diff --git a/src/editor/dialogs/editspritedialog.cpp b/src/editor/dialogs/editspritedialog.cpp index 7e7f633..dccfe42 100644 --- a/src/editor/dialogs/editspritedialog.cpp +++ b/src/editor/dialogs/editspritedialog.cpp @@ -94,7 +94,7 @@ void EditSpriteDialog::newSprite() m_model->beginResetModel(); m_pixmaps = std::vector { std::move(pixmap) }; m_model->endResetModel(); - qDebug() << m_model->rowCount({}); + changed(); } } @@ -110,11 +110,9 @@ void EditSpriteDialog::doubleClicked(const QModelIndex &index) ImageEditorDialog dialog{m_model->pixmap(index), tr("Image Editor: %0").arg(m_spriteName), this}; if (dialog.exec() == QDialog::Accepted) { - qDebug() << "apply pixmap?!"; - emit m_model->beginResetModel(); m_pixmaps[index.row()] = dialog.pixmap(); - emit m_model->endResetModel(); - //emit m_model->dataChanged(index, index, {Qt::DecorationRole}); + emit m_model->dataChanged(index, index, {Qt::DecorationRole}); + changed(); } } diff --git a/src/editor/dialogs/imageeditordialog.cpp b/src/editor/dialogs/imageeditordialog.cpp index f38cd2b..515e1fa 100644 --- a/src/editor/dialogs/imageeditordialog.cpp +++ b/src/editor/dialogs/imageeditordialog.cpp @@ -34,6 +34,16 @@ ImageEditorDialog::ImageEditorDialog(const QPixmap &pixmap, const QString &title connect(m_ui->pushButtonRightButtonColor, &QAbstractButton::pressed, this, &ImageEditorDialog::selectRightButtonColor); + connect(m_ui->frameColorCoarse, &ColorWidget::colorLeftClicked, + m_ui->canvas, &DrawingCanvasWidget::setLeftButtonColor); + connect(m_ui->frameColorCoarse, &ColorWidget::colorRightClicked, + m_ui->canvas, &DrawingCanvasWidget::setRightButtonColor); + + connect(m_ui->frameColorFine, &ColorWidget::colorLeftClicked, + m_ui->canvas, &DrawingCanvasWidget::setLeftButtonColor); + connect(m_ui->frameColorFine, &ColorWidget::colorRightClicked, + m_ui->canvas, &DrawingCanvasWidget::setRightButtonColor); + connect(m_ui->canvas, &DrawingCanvasWidget::changed, this, &ImageEditorDialog::changed); connect(m_ui->canvas, &DrawingCanvasWidget::leftButtonColorChanged, diff --git a/src/editor/dialogs/imageeditordialog.ui b/src/editor/dialogs/imageeditordialog.ui index 9519e39..8e0c99b 100644 --- a/src/editor/dialogs/imageeditordialog.ui +++ b/src/editor/dialogs/imageeditordialog.ui @@ -725,12 +725,20 @@ Colors + + 10 + + + + 8 + + Left @@ -752,6 +760,11 @@ + + + 8 + + Right @@ -772,34 +785,34 @@ - + - 75 - 100 + 0 + 125 - QFrame::Shape::StyledPanel + QFrame::Shape::Panel - QFrame::Shadow::Raised + QFrame::Shadow::Sunken - + - 75 - 100 + 0 + 125 - QFrame::Shape::StyledPanel + QFrame::Shape::Panel - QFrame::Shadow::Raised + QFrame::Shadow::Sunken @@ -1112,9 +1125,15 @@
widgets/drawingcanvaswidget.h
- ColorWidget + CoarseColorWidget QFrame -
widgets/colorwidget.h
+
widgets/coarsecolorwidget.h
+ 1 +
+ + FineColorWidget + QFrame +
widgets/finecolorwidget.h
1
diff --git a/src/editor/widgets/actiondragwidget.cpp b/src/editor/widgets/actiondragwidget.cpp index 9fbb904..d08bbbd 100644 --- a/src/editor/widgets/actiondragwidget.cpp +++ b/src/editor/widgets/actiondragwidget.cpp @@ -8,11 +8,6 @@ #include "projectserialization.h" #include "stdserialization.h" -ActionDragWidget::ActionDragWidget(QWidget *parent) : - QToolButton{parent} -{ -} - void ActionDragWidget::mousePressEvent(QMouseEvent *event) { QToolButton::mousePressEvent(event); diff --git a/src/editor/widgets/actiondragwidget.h b/src/editor/widgets/actiondragwidget.h index 67edebf..4c93311 100644 --- a/src/editor/widgets/actiondragwidget.h +++ b/src/editor/widgets/actiondragwidget.h @@ -10,7 +10,7 @@ class ActionDragWidget : public QToolButton Q_OBJECT public: - explicit ActionDragWidget(QWidget *parent = nullptr); + using QToolButton::QToolButton; const Action &action() const { return m_action; } void setAction(Action &&action) { m_action = std::move(action); } diff --git a/src/editor/widgets/coarsecolorwidget.cpp b/src/editor/widgets/coarsecolorwidget.cpp new file mode 100644 index 0000000..3e4b6f8 --- /dev/null +++ b/src/editor/widgets/coarsecolorwidget.cpp @@ -0,0 +1,102 @@ +#include "coarsecolorwidget.h" + +#include + +void CoarseColorWidget::resizeEvent(QResizeEvent *event) +{ + ColorWidget::resizeEvent(event); + + int w = width() - frameWidth() * 2; + int h = height() - frameWidth() * 2; + + // dynamic columns + constexpr int MIN_COL_WIDTH = 16; + constexpr int MAX_COL_WIDTH = 32; + + int minCols = std::max(1, w / MAX_COL_WIDTH); + int maxCols = std::max(1, w / MIN_COL_WIDTH); + int columns = std::clamp(maxCols, minCols, maxCols); + + // dynamic rows + constexpr int MIN_ROW_HEIGHT = 16; + constexpr int MAX_ROW_HEIGHT = 32; + + int minRows = std::max(1, h / MAX_ROW_HEIGHT); + int maxRows = std::max(1, h / MIN_ROW_HEIGHT); + int rows = std::clamp(maxRows, minRows, maxRows); + + m_image = QImage(w, h, QImage::Format_RGB32); + + { + QPainter p(&m_image); + p.setPen(Qt::NoPen); + + for (int r = 0; r < rows; ++r) + for (int c = 0; c < columns; ++c) + { + // fractional geometry (smooth scaling) + int x0 = (c * w) / columns; + int x1 = ((c+1) * w) / columns; + int y0 = (r * h) / rows; + int y1 = ((r+1) * h) / rows; + + int cw = x1 - x0; + int rh = y1 - y0; + + // color logic + QColor color; + float hue = float(c) * 360.f / float(columns); + + // bottom row = grayscale, but now rows are dynamic + if (r == rows - 1) + { + int v = int(c * 255.f / std::max(1, columns - 1)); + color = QColor(v, v, v); + } + else + { + // spread the "classic5 rows" over whatever number of rows we have + // We interpolate S and V vertically. + float t = float(r) / float(rows - 1); // 0..1, except grayscale row + + // Windows-like palette interpolation: + // r=0 (top): S=255 V=140 + // r=1: S=255 V=200 + // r=2: S=255 V=255 + // r=3: S=100 V=255 + // r=4: S= 40 V=255 + // r=5 bottom: grayscale row (handled above) + + // Predefined control points + constexpr struct { int s, v; } ctrl[] = { + {255, 140}, + {255, 200}, + {255, 255}, + {100, 255}, + { 40, 255} + }; + + int ctrlRows = 5; + + float pos = t * (ctrlRows - 1); + int i = int(pos); + float f = pos - i; + + if (i >= ctrlRows - 1) { + i = ctrlRows - 2; + f = 1.f; + } + + int S = int(ctrl[i].s * (1.f - f) + ctrl[i + 1].s * f); + int V = int(ctrl[i].v * (1.f - f) + ctrl[i + 1].v * f); + + color.setHsv(int(hue), S, V); + } + + p.setBrush(color); + p.drawRect(x0, y0, cw, rh); + } + } + + m_pixmap = QPixmap::fromImage(m_image); +} diff --git a/src/editor/widgets/coarsecolorwidget.h b/src/editor/widgets/coarsecolorwidget.h new file mode 100644 index 0000000..8b571e5 --- /dev/null +++ b/src/editor/widgets/coarsecolorwidget.h @@ -0,0 +1,14 @@ +#pragma once + +#include "colorwidget.h" + +class CoarseColorWidget : public ColorWidget +{ + Q_OBJECT + +public: + using ColorWidget::ColorWidget; + +protected: + void resizeEvent(QResizeEvent *event) override; +}; diff --git a/src/editor/widgets/colorwidget.cpp b/src/editor/widgets/colorwidget.cpp index cad627a..9be67b9 100644 --- a/src/editor/widgets/colorwidget.cpp +++ b/src/editor/widgets/colorwidget.cpp @@ -2,33 +2,17 @@ #include #include +#include #include -ColorWidget::ColorWidget(QWidget *parent) - : QFrame{parent} +ColorWidget::ColorWidget(QWidget *parent) : + QFrame{parent} { - setCol(150, 255); setAttribute(Qt::WA_NoSystemBackground); - setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed) ); } ColorWidget::~ColorWidget() = default; -void ColorWidget::setCol(int h, int s) -{ - int nhue = qMin(qMax(0,h), 359); - int nsat = qMin(qMax(0,s), 255); - if (nhue == m_hue && nsat == m_sat) - return; - QRect r(colPt(), QSize(20,20)); - m_hue = nhue; - m_sat = nsat; - r = r.united(QRect(colPt(), QSize(20,20))); - r.translate(contentsRect().x()-9, contentsRect().y()-9); -// update(r); - repaint(r); -} - void ColorWidget::paintEvent(QPaintEvent *event) { Q_UNUSED(event) @@ -39,50 +23,61 @@ void ColorWidget::paintEvent(QPaintEvent *event) p.drawPixmap(r.topLeft(), m_pixmap); } -void ColorWidget::resizeEvent(QResizeEvent *event) +void ColorWidget::mousePressEvent(QMouseEvent *event) { - Q_UNUSED(event) + QFrame::mousePressEvent(event); - int w = width() - frameWidth() * 2; - int h = height() - frameWidth() * 2; - QImage img(w, h, QImage::Format_RGB32); - int x, y; - uint *pixel = (uint *) img.scanLine(0); - for (y = 0; y < h; y++) + switch (event->button()) { - const uint *end = pixel + w; - x = 0; - while (pixel < end) { - QPoint p(x, y); - QColor c; - c.setHsv(huePt(p), satPt(p), 200); - *pixel = c.rgb(); - ++pixel; - ++x; - } + case Qt::LeftButton: + case Qt::RightButton: + { + m_currentlyPicking = event->button() == Qt::LeftButton; + + setMouseTracking(true); + + pickPixel(event->pos(), event->button() == Qt::LeftButton); + + break; + } + default:; } - m_pixmap = QPixmap::fromImage(img); } -QPoint ColorWidget::colPt() +void ColorWidget::mouseReleaseEvent(QMouseEvent *event) { - QRect r = contentsRect(); - return QPoint((360 - m_hue) * (r.width() - 1) / 360, (255 - m_sat) * (r.height() - 1) / 255); + QFrame::mouseReleaseEvent(event); + + switch (event->button()) + { + case Qt::LeftButton: + case Qt::RightButton: + { + m_currentlyPicking = std::nullopt; + + setMouseTracking(false); + + break; + } + default:; + } } -int ColorWidget::huePt(const QPoint &pt) +void ColorWidget::mouseMoveEvent(QMouseEvent *event) { - QRect r = contentsRect(); - return 360 - pt.x() * 360 / (r.width() - 1); + QFrame::mouseMoveEvent(event); + + if (m_currentlyPicking) + pickPixel(event->pos(), *m_currentlyPicking); } -int ColorWidget::satPt(const QPoint &pt) +void ColorWidget::pickPixel(const QPoint &pos, bool left) { - QRect r = contentsRect(); - return 255 - pt.y() * 255 / (r.height() - 1); -} + if (!m_image.rect().contains(pos)) + return; -void ColorWidget::setCol(const QPoint &pt) -{ - setCol(huePt(pt), satPt(pt)); + if (left) + emit colorLeftClicked(m_image.pixelColor(pos)); + else + emit colorRightClicked(m_image.pixelColor(pos)); } diff --git a/src/editor/widgets/colorwidget.h b/src/editor/widgets/colorwidget.h index 593842a..9a6357d 100644 --- a/src/editor/widgets/colorwidget.h +++ b/src/editor/widgets/colorwidget.h @@ -1,8 +1,11 @@ #pragma once #include +#include #include +#include + class ColorWidget : public QFrame { Q_OBJECT @@ -11,21 +14,22 @@ public: explicit ColorWidget(QWidget *parent = nullptr); ~ColorWidget() override; -public slots: - void setCol(int h, int s); +signals: + void colorLeftClicked(const QColor &color); + void colorRightClicked(const QColor &color); protected: void paintEvent(QPaintEvent *event) override; - void resizeEvent(QResizeEvent *event) override; + + void mousePressEvent(QMouseEvent *event) override; + void mouseReleaseEvent(QMouseEvent *event) override; + void mouseMoveEvent(QMouseEvent *event) override; + + QImage m_image; + QPixmap m_pixmap; private: - QPoint colPt(); - int huePt(const QPoint &pt); - int satPt(const QPoint &pt); - void setCol(const QPoint &pt); + void pickPixel(const QPoint &pos, bool left); - int m_hue{}; - int m_sat{}; - - QPixmap m_pixmap; + std::optional m_currentlyPicking; }; diff --git a/src/editor/widgets/draggabletreeview.cpp b/src/editor/widgets/draggabletreeview.cpp index 38148dd..2dcfe65 100644 --- a/src/editor/widgets/draggabletreeview.cpp +++ b/src/editor/widgets/draggabletreeview.cpp @@ -1,10 +1,5 @@ #include "draggabletreeview.h" -DraggableTreeView::DraggableTreeView(QWidget *parent) : - QTreeView{parent} -{ -} - void DraggableTreeView::dragMoveEvent(QDragMoveEvent *event) { setDropIndicatorShown(true); diff --git a/src/editor/widgets/draggabletreeview.h b/src/editor/widgets/draggabletreeview.h index fcb8f15..a09aeb2 100644 --- a/src/editor/widgets/draggabletreeview.h +++ b/src/editor/widgets/draggabletreeview.h @@ -7,7 +7,7 @@ class DraggableTreeView : public QTreeView Q_OBJECT public: - explicit DraggableTreeView(QWidget *parent = nullptr); + using QTreeView::QTreeView; void dragMoveEvent(QDragMoveEvent *event) override; void dropEvent(QDropEvent *event) override; diff --git a/src/editor/widgets/drawingcanvaswidget.cpp b/src/editor/widgets/drawingcanvaswidget.cpp index 149d53c..a46977a 100644 --- a/src/editor/widgets/drawingcanvaswidget.cpp +++ b/src/editor/widgets/drawingcanvaswidget.cpp @@ -4,11 +4,6 @@ #include #include -DrawingCanvasWidget::DrawingCanvasWidget(QWidget *parent) : - QWidget{parent} -{ -} - void DrawingCanvasWidget::setPixmap(QPixmap &pixmap) { m_pixmap = &pixmap; diff --git a/src/editor/widgets/drawingcanvaswidget.h b/src/editor/widgets/drawingcanvaswidget.h index d89e11a..1f8c810 100644 --- a/src/editor/widgets/drawingcanvaswidget.h +++ b/src/editor/widgets/drawingcanvaswidget.h @@ -14,7 +14,7 @@ class DrawingCanvasWidget : public QWidget Q_PROPERTY(QColor rightButtonColor READ rightButtonColor WRITE setRightButtonColor NOTIFY rightButtonColorChanged FINAL) public: - explicit DrawingCanvasWidget(QWidget *parent = nullptr); + using QWidget::QWidget; QPixmap *pixmap() { return m_pixmap; } const QPixmap *pixmap() const { return m_pixmap; } diff --git a/src/editor/widgets/finecolorwidget.cpp b/src/editor/widgets/finecolorwidget.cpp new file mode 100644 index 0000000..8bc3cdf --- /dev/null +++ b/src/editor/widgets/finecolorwidget.cpp @@ -0,0 +1,49 @@ +#include "finecolorwidget.h" + +void FineColorWidget::resizeEvent(QResizeEvent *event) +{ + ColorWidget::resizeEvent(event); + + int w = width() - frameWidth() * 2; + int h = height() - frameWidth() * 2; + + m_image = QImage{w, h, QImage::Format_RGB32}; + + for (int y = 0; y < h; y++) + { + uint *pixel = (uint *)m_image.scanLine(y); + float hue = float(360 - y * 360 / (h - 1)); + + QColor pure; + pure.setHsv(hue, 255, 255); + + for (int x = 0; x < w; x++, pixel++) + { + float t = float(x) / float(w - 1); // 0..1 across width + QColor c; + + if (t < 0.5f) + { + float k = t / 0.5f; // 0..1 across halve + c.setRgb( + pure.red() * k, + pure.green() * k, + pure.blue() * k + ); + } + else + { + float k = (t - 0.5f) / 0.5f; // 0..1 across halve + c.setRgb( + pure.red() + (255 - pure.red()) * k, + pure.green() + (255 - pure.green()) * k, + pure.blue() + (255 - pure.blue()) * k + ); + } + + *pixel = c.rgb(); + } + } + + m_pixmap = QPixmap::fromImage(m_image); +} diff --git a/src/editor/widgets/finecolorwidget.h b/src/editor/widgets/finecolorwidget.h new file mode 100644 index 0000000..f95ca1e --- /dev/null +++ b/src/editor/widgets/finecolorwidget.h @@ -0,0 +1,14 @@ +#pragma once + +#include "colorwidget.h" + +class FineColorWidget : public ColorWidget +{ + Q_OBJECT + +public: + using ColorWidget::ColorWidget; + +protected: + void resizeEvent(QResizeEvent *event) override; +};