[nostalgia/core/studio] Make Pixel updates in TileSheetEditor use undo stack
This commit is contained in:
parent
e407ad7246
commit
01ad572499
@ -12,4 +12,9 @@ namespace nostalgia::core {
|
|||||||
|
|
||||||
constexpr auto PluginName = "NostalgiaCore";
|
constexpr auto PluginName = "NostalgiaCore";
|
||||||
|
|
||||||
|
// Command IDs to use with QUndoCommand::id()
|
||||||
|
enum class CommandId {
|
||||||
|
UpdatePixel = 1,
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -7,11 +7,13 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <QHeaderView>
|
#include <QHeaderView>
|
||||||
|
#include <QPointer>
|
||||||
#include <QQmlContext>
|
#include <QQmlContext>
|
||||||
#include <QQuickItem>
|
#include <QQuickItem>
|
||||||
#include <QQuickWidget>
|
#include <QQuickWidget>
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
#include <QSplitter>
|
#include <QSplitter>
|
||||||
|
#include <QUndoCommand>
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
|
|
||||||
#include "consts.hpp"
|
#include "consts.hpp"
|
||||||
@ -28,16 +30,83 @@ QColor toQColor(Color16 nc) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class UpdatePixelsCommand: public QUndoCommand {
|
||||||
|
private:
|
||||||
|
struct PixelUpdate {
|
||||||
|
QPointer<QQuickItem> item;
|
||||||
|
int oldColorId = 0;
|
||||||
|
|
||||||
|
bool operator==(const PixelUpdate &o) const {
|
||||||
|
return item == o.item;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator<(const PixelUpdate &o) const {
|
||||||
|
return item < o.item;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
uint64_t cmdIdx = 0;
|
||||||
|
int m_newColorId = 0;
|
||||||
|
const QStringList &m_palette;
|
||||||
|
QVector<uint8_t> &m_pixels;
|
||||||
|
QVector<PixelUpdate> m_pixelUpdates;
|
||||||
|
|
||||||
|
public:
|
||||||
|
UpdatePixelsCommand(QVector<uint8_t> &pixels, const QStringList &palette, const QVariantList &pixelItems, int newColorId, uint64_t cmdIdx): m_palette(palette), m_pixels(pixels) {
|
||||||
|
m_newColorId = newColorId;
|
||||||
|
cmdIdx = cmdIdx;
|
||||||
|
for (auto &pi : pixelItems) {
|
||||||
|
PixelUpdate pu;
|
||||||
|
auto p = qobject_cast<QQuickItem*>(pi.value<QObject*>());
|
||||||
|
pu.item = p;
|
||||||
|
pu.oldColorId = m_palette.indexOf(p->property("color").toString());
|
||||||
|
m_pixelUpdates.push_back(std::move(pu));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual ~UpdatePixelsCommand() = default;
|
||||||
|
|
||||||
|
int id() const override {
|
||||||
|
return static_cast<int>(CommandId::UpdatePixel);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool mergeWith(const QUndoCommand *cmd) override {
|
||||||
|
auto other = static_cast<const UpdatePixelsCommand*>(cmd);
|
||||||
|
if (cmdIdx == other->cmdIdx) {
|
||||||
|
m_pixelUpdates.append(other->m_pixelUpdates);
|
||||||
|
// inefficient, but probably not worth optimizing, but something to
|
||||||
|
// look at if this operation becomes a performace problem
|
||||||
|
std::sort(m_pixelUpdates.begin(), m_pixelUpdates.end());
|
||||||
|
m_pixelUpdates.erase(std::unique(m_pixelUpdates.begin(), m_pixelUpdates.end()), m_pixelUpdates.end());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void redo() override {
|
||||||
|
for (int i = 0; i < m_pixelUpdates.size(); i++) {
|
||||||
|
const auto &pu = m_pixelUpdates[i];
|
||||||
|
pu.item->setProperty("color", m_palette[m_newColorId]);
|
||||||
|
m_pixels[i] = m_newColorId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void undo() override {
|
||||||
|
for (int i = 0; i < m_pixelUpdates.size(); i++) {
|
||||||
|
const auto &pu = m_pixelUpdates[i];
|
||||||
|
pu.item->setProperty("color", pu.oldColorId);
|
||||||
|
m_pixels[i] = pu.oldColorId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
QString SheetData::pixel(int index) {
|
QString SheetData::pixel(int index) {
|
||||||
return m_palette[m_pixels[index]];
|
return m_palette[m_pixels[index]];
|
||||||
}
|
}
|
||||||
|
|
||||||
void SheetData::updatePixels(QVariantList pixels) {
|
void SheetData::updatePixels(QVariantList pixelItems) {
|
||||||
for (auto pi : pixels) {
|
m_cmdStack.push(new UpdatePixelsCommand(m_pixels, m_palette, pixelItems, m_selectedColor, m_cmdIdx++));
|
||||||
// TODO: replace with push to QUndoStack
|
|
||||||
auto p = qobject_cast<QQuickItem*>(pi.value<QObject*>());
|
|
||||||
p->setProperty("color", m_palette[m_selectedColor]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int SheetData::columns() {
|
int SheetData::columns() {
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include <QStringView>
|
#include <QStringView>
|
||||||
#include <QTableWidget>
|
#include <QTableWidget>
|
||||||
|
#include <QUndoStack>
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
|
||||||
@ -26,6 +27,8 @@ class SheetData: public QObject {
|
|||||||
Q_PROPERTY(int rows READ rows WRITE setRows NOTIFY rowsChanged)
|
Q_PROPERTY(int rows READ rows WRITE setRows NOTIFY rowsChanged)
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
uint64_t m_cmdIdx = 0;
|
||||||
|
QUndoStack m_cmdStack;
|
||||||
QStringList m_palette;
|
QStringList m_palette;
|
||||||
QVector<uint8_t> m_pixels;
|
QVector<uint8_t> m_pixels;
|
||||||
int m_columns = 2;
|
int m_columns = 2;
|
||||||
|
Loading…
Reference in New Issue
Block a user