Implemented first drawing capabilities in image editor

This commit is contained in:
2025-11-23 18:53:22 +01:00
parent c2fb13325b
commit b6a6084ba8
10 changed files with 282 additions and 29 deletions
+2
View File
@@ -38,6 +38,7 @@ HEADERS += \
src/editor/editorguiutils.h \
src/editor/roomscene.h \
src/editor/widgets/actiondragwidget.h \
src/editor/widgets/colorwidget.h \
src/editor/widgets/draggabletreeview.h \
src/editor/widgets/objectparentselectorwidget.h \
src/editor/widgets/objectselectorwidget.h \
@@ -108,6 +109,7 @@ SOURCES += \
src/editor/editorguiutils.cpp \
src/editor/roomscene.cpp \
src/editor/widgets/actiondragwidget.cpp \
src/editor/widgets/colorwidget.cpp \
src/editor/widgets/draggabletreeview.cpp \
src/editor/widgets/objectparentselectorwidget.cpp \
src/editor/widgets/objectselectorwidget.cpp \
+5 -2
View File
@@ -89,7 +89,7 @@ void EditSpriteDialog::newSprite()
if (dialog.exec() == QDialog::Accepted)
{
QPixmap pixmap{dialog.spriteSize()};
pixmap.fill(Qt::white);
pixmap.fill(Qt::transparent);
m_model->beginResetModel();
m_pixmaps = std::vector<QPixmap> { std::move(pixmap) };
@@ -110,8 +110,11 @@ 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->dataChanged(index, index, {Qt::DecorationRole});
emit m_model->endResetModel();
//emit m_model->dataChanged(index, index, {Qt::DecorationRole});
changed();
}
}
+59 -6
View File
@@ -4,6 +4,8 @@
#include <QMessageBox>
#include <QDebug>
#include <QButtonGroup>
#include <QFontDialog>
#include <QColorDialog>
ImageEditorDialog::ImageEditorDialog(const QPixmap &pixmap, const QString &title, QWidget *parent) :
QDialog{parent},
@@ -24,6 +26,21 @@ ImageEditorDialog::ImageEditorDialog(const QPixmap &pixmap, const QString &title
m_ui->scrollArea->setBackgroundRole(QPalette::Dark);
connect(m_ui->pushButtonSelectFont, &QAbstractButton::pressed,
this, &ImageEditorDialog::selectFont);
connect(m_ui->pushButtonLeftButtonColor, &QAbstractButton::pressed,
this, &ImageEditorDialog::selectLeftButtonColor);
connect(m_ui->pushButtonRightButtonColor, &QAbstractButton::pressed,
this, &ImageEditorDialog::selectRightButtonColor);
connect(m_ui->canvas, &DrawingCanvasWidget::changed,
this, &ImageEditorDialog::changed);
connect(m_ui->canvas, &DrawingCanvasWidget::leftButtonColorChanged,
this, &ImageEditorDialog::updateLeftButtonColor);
connect(m_ui->canvas, &DrawingCanvasWidget::rightButtonColorChanged,
this, &ImageEditorDialog::updateRightButtonColor);
{
auto group = new QButtonGroup{this};
group->setExclusive(true);
@@ -71,6 +88,9 @@ ImageEditorDialog::ImageEditorDialog(const QPixmap &pixmap, const QString &title
m_ui->toolButtonDraw->click();
updateLeftButtonColor(m_ui->canvas->leftButtonColor());
updateRightButtonColor(m_ui->canvas->rightButtonColor());
m_ui->canvas->setPixmap(m_pixmap);
}
@@ -78,12 +98,6 @@ ImageEditorDialog::~ImageEditorDialog() = default;
void ImageEditorDialog::accept()
{
if (!m_unsavedChanges)
{
QDialog::reject();
return;
}
// TODO
QDialog::accept();
@@ -128,6 +142,45 @@ void ImageEditorDialog::changed()
}
}
void ImageEditorDialog::selectFont()
{
QFontDialog dialog{m_ui->pushButtonSelectFont->font(), this};
if (dialog.exec() == QDialog::Accepted)
m_ui->pushButtonSelectFont->setFont(dialog.selectedFont());
}
void ImageEditorDialog::selectLeftButtonColor()
{
QColorDialog dialog{m_ui->canvas->leftButtonColor(), this};
if (dialog.exec() == QDialog::Accepted)
m_ui->canvas->setLeftButtonColor(dialog.selectedColor());
}
void ImageEditorDialog::selectRightButtonColor()
{
QColorDialog dialog{m_ui->canvas->rightButtonColor(), this};
if (dialog.exec() == QDialog::Accepted)
m_ui->canvas->setRightButtonColor(dialog.selectedColor());
}
void ImageEditorDialog::updateLeftButtonColor(const QColor &leftButtonColor)
{
auto frame = m_ui->pushButtonLeftButtonColor;
auto palette = frame->palette();
auto role = frame->backgroundRole();
palette.setBrush(role, leftButtonColor);
frame->setPalette(palette);
}
void ImageEditorDialog::updateRightButtonColor(const QColor &rightButtonColor)
{
auto frame = m_ui->pushButtonRightButtonColor;
auto palette = frame->palette();
auto role = frame->backgroundRole();
palette.setBrush(role, rightButtonColor);
frame->setPalette(palette);
}
void ImageEditorDialog::updateTitle()
{
setWindowTitle(tr("%0%1")
+5
View File
@@ -23,6 +23,11 @@ public:
private slots:
void changed();
void selectFont();
void selectLeftButtonColor();
void selectRightButtonColor();
void updateLeftButtonColor(const QColor &leftButtonColor);
void updateRightButtonColor(const QColor &rightButtonColor);
private:
void updateTitle();
+22 -19
View File
@@ -631,6 +631,12 @@
<layout class="QVBoxLayout" name="verticalLayout_11">
<item>
<widget class="QPushButton" name="pushButtonSelectFont">
<property name="minimumSize">
<size>
<width>0</width>
<height>64</height>
</size>
</property>
<property name="text">
<string>Aa</string>
</property>
@@ -704,7 +710,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>759</width>
<width>741</width>
<height>1042</height>
</rect>
</property>
@@ -731,19 +737,13 @@
</widget>
</item>
<item>
<widget class="QFrame" name="frameLeft">
<widget class="QPushButton" name="pushButtonLeftButtonColor">
<property name="minimumSize">
<size>
<width>0</width>
<height>40</height>
</size>
</property>
<property name="frameShape">
<enum>QFrame::Shape::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Shadow::Raised</enum>
</property>
</widget>
</item>
</layout>
@@ -758,19 +758,13 @@
</widget>
</item>
<item>
<widget class="QFrame" name="frameHeight">
<widget class="QPushButton" name="pushButtonRightButtonColor">
<property name="minimumSize">
<size>
<width>0</width>
<height>40</height>
</size>
</property>
<property name="frameShape">
<enum>QFrame::Shape::StyledPanel</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Shadow::Raised</enum>
</property>
</widget>
</item>
</layout>
@@ -778,10 +772,10 @@
</layout>
</item>
<item>
<widget class="QFrame" name="frame_4">
<widget class="ColorWidget" name="frameColorCoarse">
<property name="minimumSize">
<size>
<width>0</width>
<width>75</width>
<height>100</height>
</size>
</property>
@@ -794,10 +788,10 @@
</widget>
</item>
<item>
<widget class="QFrame" name="frame_5">
<widget class="ColorWidget" name="frameColorFine">
<property name="minimumSize">
<size>
<width>0</width>
<width>75</width>
<height>100</height>
</size>
</property>
@@ -878,6 +872,9 @@
</item>
<item>
<widget class="QGroupBox" name="groupBoxPreview">
<property name="visible">
<bool>false</bool>
</property>
<property name="title">
<string>Preview</string>
</property>
@@ -1114,6 +1111,12 @@
<extends>QWidget</extends>
<header>widgets/drawingcanvaswidget.h</header>
</customwidget>
<customwidget>
<class>ColorWidget</class>
<extends>QFrame</extends>
<header>widgets/colorwidget.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources>
<include location="../resources_editor.qrc"/>
+88
View File
@@ -0,0 +1,88 @@
#include "colorwidget.h"
#include <QPaintEvent>
#include <QResizeEvent>
#include <QPainter>
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)
QPainter p(this);
drawFrame(&p);
QRect r = contentsRect();
p.drawPixmap(r.topLeft(), m_pixmap);
}
void ColorWidget::resizeEvent(QResizeEvent *event)
{
Q_UNUSED(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++)
{
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;
}
}
m_pixmap = QPixmap::fromImage(img);
}
QPoint ColorWidget::colPt()
{
QRect r = contentsRect();
return QPoint((360 - m_hue) * (r.width() - 1) / 360, (255 - m_sat) * (r.height() - 1) / 255);
}
int ColorWidget::huePt(const QPoint &pt)
{
QRect r = contentsRect();
return 360 - pt.x() * 360 / (r.width() - 1);
}
int ColorWidget::satPt(const QPoint &pt)
{
QRect r = contentsRect();
return 255 - pt.y() * 255 / (r.height() - 1);
}
void ColorWidget::setCol(const QPoint &pt)
{
setCol(huePt(pt), satPt(pt));
}
+31
View File
@@ -0,0 +1,31 @@
#pragma once
#include <QFrame>
#include <QPixmap>
class ColorWidget : public QFrame
{
Q_OBJECT
public:
explicit ColorWidget(QWidget *parent = nullptr);
~ColorWidget() override;
public slots:
void setCol(int h, int s);
protected:
void paintEvent(QPaintEvent *event) override;
void resizeEvent(QResizeEvent *event) override;
private:
QPoint colPt();
int huePt(const QPoint &pt);
int satPt(const QPoint &pt);
void setCol(const QPoint &pt);
int m_hue{};
int m_sat{};
QPixmap m_pixmap;
};
+48 -2
View File
@@ -26,6 +26,20 @@ void DrawingCanvasWidget::setScale(float scale)
update();
}
void DrawingCanvasWidget::setLeftButtonColor(const QColor &leftButtonColor)
{
if (m_leftButtonColor == leftButtonColor)
return;
emit leftButtonColorChanged(m_leftButtonColor = leftButtonColor);
}
void DrawingCanvasWidget::setRightButtonColor(const QColor &rightButtonColor)
{
if (m_rightButtonColor == rightButtonColor)
return;
emit rightButtonColorChanged(m_rightButtonColor = rightButtonColor);
}
void DrawingCanvasWidget::paintEvent(QPaintEvent *ev)
{
if (!m_pixmap)
@@ -63,9 +77,20 @@ void DrawingCanvasWidget::mousePressEvent(QMouseEvent *event)
{
QWidget::mousePressEvent(event);
if (event->button() == Qt::LeftButton)
switch (event->button())
{
case Qt::LeftButton:
case Qt::RightButton:
{
m_currentlyDrawing = event->button() == Qt::LeftButton;
setMouseTracking(true);
setPixel(event->pos() / m_scale, event->button() == Qt::LeftButton);
break;
}
default:;
}
}
@@ -73,13 +98,34 @@ void DrawingCanvasWidget::mouseReleaseEvent(QMouseEvent *event)
{
QWidget::mouseReleaseEvent(event);
if (event->button() == Qt::LeftButton)
switch (event->button())
{
case Qt::LeftButton:
case Qt::RightButton:
{
m_currentlyDrawing = std::nullopt;
setMouseTracking(false);
break;
}
default:;
}
}
void DrawingCanvasWidget::mouseMoveEvent(QMouseEvent *event)
{
QWidget::mouseMoveEvent(event);
if (m_currentlyDrawing)
setPixel(event->pos() / m_scale, *m_currentlyDrawing);
}
void DrawingCanvasWidget::setPixel(QPoint pos, bool leftColor)
{
auto image = m_pixmap->toImage();
image.setPixelColor(pos.x(), pos.y(), leftColor ? m_leftButtonColor : m_rightButtonColor);
*m_pixmap = QPixmap::fromImage(image);
repaint();
emit changed();
}
+21
View File
@@ -8,6 +8,11 @@ class DrawingCanvasWidget : public QWidget
{
Q_OBJECT
Q_PROPERTY(float scale READ scale WRITE setScale NOTIFY scaleChanged FINAL)
Q_PROPERTY(QColor leftButtonColor READ leftButtonColor WRITE setLeftButtonColor NOTIFY leftButtonColorChanged FINAL)
Q_PROPERTY(QColor rightButtonColor READ rightButtonColor WRITE setRightButtonColor NOTIFY rightButtonColorChanged FINAL)
public:
explicit DrawingCanvasWidget(QWidget *parent = nullptr);
@@ -18,8 +23,17 @@ public:
float scale() const { return m_scale; }
void setScale(float scale);
QColor leftButtonColor() const { return m_leftButtonColor; }
void setLeftButtonColor(const QColor &LeftButtonColor);
QColor rightButtonColor() const { return m_rightButtonColor; }
void setRightButtonColor(const QColor &rightButtonColor);
signals:
void changed();
void scaleChanged(float scale);
void leftButtonColorChanged(const QColor &LeftButtonColor);
void rightButtonColorChanged(const QColor &rightButtonColor);
protected:
void paintEvent(QPaintEvent *ev) override;
@@ -28,7 +42,14 @@ protected:
void mouseMoveEvent(QMouseEvent *event) override;
private:
void setPixel(QPoint pos, bool leftColor);
QPixmap *m_pixmap{};
float m_scale{4.f};
QColor m_leftButtonColor{Qt::white};
QColor m_rightButtonColor{Qt::black};
std::optional<bool> m_currentlyDrawing;
};
+1
View File
@@ -148,6 +148,7 @@ QDataStream &operator>>(QDataStream &ds, std::variant<T...> &variant)
static constexpr func_t *funcs[] = {
detail::variantUnpacker<T, T...>...
};
assert(index >= 0 && size_t(index) < std::size(funcs));
variant = funcs[index](ds);
return ds;