[nostalgia/core/studio] Add Mod Greater/Equal To menu to TileSheetEditor
This commit is contained in:
parent
0b3b54b3fd
commit
faadcae7e9
@ -17,8 +17,9 @@ constexpr auto PaletteDir = "/Palettes/";
|
|||||||
// Command IDs to use with QUndoCommand::id()
|
// Command IDs to use with QUndoCommand::id()
|
||||||
enum class CommandId {
|
enum class CommandId {
|
||||||
UpdatePixel = 1,
|
UpdatePixel = 1,
|
||||||
UpdateDimension = 2,
|
ModPixel = 2,
|
||||||
InsertTile = 3,
|
UpdateDimension = 3,
|
||||||
|
InsertTile = 4,
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -9,10 +9,13 @@
|
|||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
#include <QBuffer>
|
#include <QBuffer>
|
||||||
|
#include <QDialog>
|
||||||
|
#include <QFormLayout>
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
#include <QHeaderView>
|
#include <QHeaderView>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include <QPointer>
|
#include <QPointer>
|
||||||
|
#include <QPushButton>
|
||||||
#include <QQmlContext>
|
#include <QQmlContext>
|
||||||
#include <QQuickItem>
|
#include <QQuickItem>
|
||||||
#include <QQuickWidget>
|
#include <QQuickWidget>
|
||||||
@ -28,6 +31,7 @@
|
|||||||
|
|
||||||
#include <nostalgia/core/consts.hpp>
|
#include <nostalgia/core/consts.hpp>
|
||||||
#include <nostalgia/common/point.hpp>
|
#include <nostalgia/common/point.hpp>
|
||||||
|
#include <qnamespace.h>
|
||||||
|
|
||||||
#include "consts.hpp"
|
#include "consts.hpp"
|
||||||
#include "util.hpp"
|
#include "util.hpp"
|
||||||
@ -35,6 +39,40 @@
|
|||||||
|
|
||||||
namespace nostalgia::core {
|
namespace nostalgia::core {
|
||||||
|
|
||||||
|
class ModAfterDialog: public QDialog {
|
||||||
|
|
||||||
|
private:
|
||||||
|
QComboBox *const m_afterColor = new QComboBox(this);
|
||||||
|
QSpinBox *const m_mod = new QSpinBox(this);
|
||||||
|
|
||||||
|
public:
|
||||||
|
ModAfterDialog(const QStringList &palette, QWidget *parent = nullptr): QDialog(parent) {
|
||||||
|
auto range = palette.size();
|
||||||
|
auto okBtn = new QPushButton(tr("&OK"), this);
|
||||||
|
setWindowTitle(tr("Mod Colors After"));
|
||||||
|
setWindowModality(Qt::WindowModality::ApplicationModal);
|
||||||
|
for (int i = 0; i < palette.size(); ++i) {
|
||||||
|
const auto c = palette[i];
|
||||||
|
m_afterColor->addItem(QString("%1: %2").arg(i + 1).arg(c));
|
||||||
|
}
|
||||||
|
m_mod->setMinimum(-range + 1);
|
||||||
|
m_mod->setMaximum(range - 1);
|
||||||
|
auto lyt = new QFormLayout(this); lyt->addRow(tr("&Greater/Equal To:"), m_afterColor);
|
||||||
|
lyt->addRow(tr("&Mod By:"), m_mod);
|
||||||
|
lyt->addWidget(okBtn);
|
||||||
|
connect(okBtn, &QPushButton::clicked, this, &ModAfterDialog::accept);
|
||||||
|
}
|
||||||
|
|
||||||
|
int color() {
|
||||||
|
return m_afterColor->currentIndex() - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int mod() {
|
||||||
|
return m_mod->value();
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
struct LabeledSpinner: public QWidget {
|
struct LabeledSpinner: public QWidget {
|
||||||
|
|
||||||
QSpinBox *const spinBox = new QSpinBox(this);
|
QSpinBox *const spinBox = new QSpinBox(this);
|
||||||
@ -107,6 +145,36 @@ class UpdateDimensionsCommand: public QUndoCommand {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class ModPixelsCommand: public QUndoCommand {
|
||||||
|
private:
|
||||||
|
SheetData *m_sheetData = nullptr;
|
||||||
|
QHash<int, int> m_pixelUpdates;
|
||||||
|
int m_mod = 0;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ModPixelsCommand(SheetData *sheetData, int mod): m_sheetData(sheetData), m_mod(mod) {
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~ModPixelsCommand() = default;
|
||||||
|
|
||||||
|
void addPixel(int index, int mod) {
|
||||||
|
m_pixelUpdates[index] = mod;
|
||||||
|
}
|
||||||
|
|
||||||
|
int id() const override {
|
||||||
|
return static_cast<int>(CommandId::ModPixel);
|
||||||
|
}
|
||||||
|
|
||||||
|
void redo() override {
|
||||||
|
m_sheetData->modPixels(m_pixelUpdates, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void undo() override {
|
||||||
|
m_sheetData->modPixels(m_pixelUpdates, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
class UpdatePixelsCommand: public QUndoCommand {
|
class UpdatePixelsCommand: public QUndoCommand {
|
||||||
private:
|
private:
|
||||||
struct PixelUpdate {
|
struct PixelUpdate {
|
||||||
@ -354,6 +422,27 @@ void SheetData::setSelectedColor(int index) {
|
|||||||
m_selectedColor = index;
|
m_selectedColor = index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SheetData::modGteCmd(int color, int mod) {
|
||||||
|
auto cmd = new ModPixelsCommand(this, mod);
|
||||||
|
for (int i = 0; i < m_pixels.size(); ++i) {
|
||||||
|
const auto p = m_pixels[i];
|
||||||
|
if (p >= color) {
|
||||||
|
const auto mx = (m_palette.size() - p) - 1;
|
||||||
|
cmd->addPixel(i, std::clamp(mod, -p, mx));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_cmdStack->push(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SheetData::modPixels(const QHash<int, int> &mods, int inversion) {
|
||||||
|
for (const auto index : mods.keys()) {
|
||||||
|
const auto mod = mods[index];
|
||||||
|
m_pixels[index] += mod * inversion;
|
||||||
|
}
|
||||||
|
emit pixelsChanged();
|
||||||
|
emit changeOccurred();
|
||||||
|
}
|
||||||
|
|
||||||
std::unique_ptr<NostalgiaGraphic> SheetData::toNostalgiaGraphic() const {
|
std::unique_ptr<NostalgiaGraphic> SheetData::toNostalgiaGraphic() const {
|
||||||
auto ng = std::make_unique<NostalgiaGraphic>();
|
auto ng = std::make_unique<NostalgiaGraphic>();
|
||||||
const auto highestColorIdx = static_cast<uint8_t>(*std::max_element(m_pixels.begin(), m_pixels.end()));
|
const auto highestColorIdx = static_cast<uint8_t>(*std::max_element(m_pixels.begin(), m_pixels.end()));
|
||||||
@ -433,8 +522,10 @@ TileSheetEditor::TileSheetEditor(QString path, const studio::Context *ctx, QWidg
|
|||||||
auto tb = new QToolBar(tr("Tile Sheet Options"));
|
auto tb = new QToolBar(tr("Tile Sheet Options"));
|
||||||
m_tilesX = new LabeledSpinner(tr("Tiles &X:"), 1, m_sheetData.columns());
|
m_tilesX = new LabeledSpinner(tr("Tiles &X:"), 1, m_sheetData.columns());
|
||||||
m_tilesY = new LabeledSpinner(tr("Tiles &Y:"), 1, m_sheetData.rows());
|
m_tilesY = new LabeledSpinner(tr("Tiles &Y:"), 1, m_sheetData.rows());
|
||||||
|
m_updateAfterBtn = new QPushButton(tr("&Mod After"), tb);
|
||||||
tb->addWidget(m_tilesX);
|
tb->addWidget(m_tilesX);
|
||||||
tb->addWidget(m_tilesY);
|
tb->addWidget(m_tilesY);
|
||||||
|
tb->addWidget(m_updateAfterBtn);
|
||||||
canvasLyt->setMenuBar(tb);
|
canvasLyt->setMenuBar(tb);
|
||||||
lyt->addWidget(m_splitter);
|
lyt->addWidget(m_splitter);
|
||||||
m_splitter->addWidget(canvasParent);
|
m_splitter->addWidget(canvasParent);
|
||||||
@ -453,6 +544,7 @@ TileSheetEditor::TileSheetEditor(QString path, const studio::Context *ctx, QWidg
|
|||||||
m_sheetData.load(m_ctx, m_itemPath);
|
m_sheetData.load(m_ctx, m_itemPath);
|
||||||
connect(m_tilesX->spinBox, QOverload<int>::of(&QSpinBox::valueChanged), &m_sheetData, &SheetData::updateColumns);
|
connect(m_tilesX->spinBox, QOverload<int>::of(&QSpinBox::valueChanged), &m_sheetData, &SheetData::updateColumns);
|
||||||
connect(m_tilesY->spinBox, QOverload<int>::of(&QSpinBox::valueChanged), &m_sheetData, &SheetData::updateRows);
|
connect(m_tilesY->spinBox, QOverload<int>::of(&QSpinBox::valueChanged), &m_sheetData, &SheetData::updateRows);
|
||||||
|
connect(m_updateAfterBtn, &QPushButton::clicked, this, &TileSheetEditor::updateAfterClicked);
|
||||||
m_canvas->rootContext()->setContextProperty("sheetData", &m_sheetData);
|
m_canvas->rootContext()->setContextProperty("sheetData", &m_sheetData);
|
||||||
m_canvas->setSource(QUrl::fromLocalFile(":/qml/TileSheetEditor.qml"));
|
m_canvas->setSource(QUrl::fromLocalFile(":/qml/TileSheetEditor.qml"));
|
||||||
m_canvas->setResizeMode(QQuickWidget::SizeRootObjectToView);
|
m_canvas->setResizeMode(QQuickWidget::SizeRootObjectToView);
|
||||||
@ -507,7 +599,6 @@ QWidget *TileSheetEditor::setupColorPicker(QWidget *parent) {
|
|||||||
m_colorPicker.colorTable->setSelectionMode(QAbstractItemView::SingleSelection);
|
m_colorPicker.colorTable->setSelectionMode(QAbstractItemView::SingleSelection);
|
||||||
m_colorPicker.colorTable->setHorizontalHeaderLabels(QStringList() << tr("Hex Code") << tr("Color"));
|
m_colorPicker.colorTable->setHorizontalHeaderLabels(QStringList() << tr("Hex Code") << tr("Color"));
|
||||||
m_colorPicker.colorTable->horizontalHeader()->setStretchLastSection(true);
|
m_colorPicker.colorTable->horizontalHeader()->setStretchLastSection(true);
|
||||||
m_colorPicker.colorTable->verticalHeader()->hide();
|
|
||||||
connect(m_colorPicker.colorTable, &QTableWidget::itemSelectionChanged, this, &TileSheetEditor::colorSelected);
|
connect(m_colorPicker.colorTable, &QTableWidget::itemSelectionChanged, this, &TileSheetEditor::colorSelected);
|
||||||
connect(m_colorPicker.palette, &QComboBox::currentTextChanged, this, [this](QString name) {
|
connect(m_colorPicker.palette, &QComboBox::currentTextChanged, this, [this](QString name) {
|
||||||
m_sheetData.setPalette(m_ctx, palettePath(name));
|
m_sheetData.setPalette(m_ctx, palettePath(name));
|
||||||
@ -636,4 +727,13 @@ void TileSheetEditor::setColorTable() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TileSheetEditor::updateAfterClicked() {
|
||||||
|
auto d = new ModAfterDialog(m_sheetData.palette(), this);
|
||||||
|
connect(d, &ModAfterDialog::accepted, [this, d] {
|
||||||
|
m_sheetData.modGteCmd(d->color(), d->mod());
|
||||||
|
});
|
||||||
|
connect(d, &ModAfterDialog::finished, d, &ModAfterDialog::deleteLater);
|
||||||
|
d->open();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -82,6 +82,10 @@ class SheetData: public QObject {
|
|||||||
|
|
||||||
void setSelectedColor(int index);
|
void setSelectedColor(int index);
|
||||||
|
|
||||||
|
void modGteCmd(int val, int mod);
|
||||||
|
|
||||||
|
void modPixels(const QHash<int, int> &pixels, int inversion);
|
||||||
|
|
||||||
[[nodiscard]] std::unique_ptr<NostalgiaGraphic> toNostalgiaGraphic() const;
|
[[nodiscard]] std::unique_ptr<NostalgiaGraphic> toNostalgiaGraphic() const;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
@ -128,6 +132,7 @@ class TileSheetEditor: public studio::Editor {
|
|||||||
class QSplitter *m_splitter = nullptr;
|
class QSplitter *m_splitter = nullptr;
|
||||||
struct LabeledSpinner *m_tilesX = nullptr;
|
struct LabeledSpinner *m_tilesX = nullptr;
|
||||||
struct LabeledSpinner *m_tilesY = nullptr;
|
struct LabeledSpinner *m_tilesY = nullptr;
|
||||||
|
class QPushButton *m_updateAfterBtn = nullptr;
|
||||||
class QQuickWidget* m_canvas = nullptr;
|
class QQuickWidget* m_canvas = nullptr;
|
||||||
struct {
|
struct {
|
||||||
QComboBox *palette = nullptr;
|
QComboBox *palette = nullptr;
|
||||||
@ -166,6 +171,9 @@ class TileSheetEditor: public studio::Editor {
|
|||||||
|
|
||||||
void setColorTable();
|
void setColorTable();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void updateAfterClicked();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user