From 01ad572499aa39f52e8cd6e5afe706b22f773d3e Mon Sep 17 00:00:00 2001 From: Gary Talent Date: Tue, 3 Dec 2019 18:01:00 -0600 Subject: [PATCH] [nostalgia/core/studio] Make Pixel updates in TileSheetEditor use undo stack --- src/nostalgia/core/studio/consts.hpp | 5 ++ src/nostalgia/core/studio/tilesheeteditor.cpp | 81 +++++++++++++++++-- src/nostalgia/core/studio/tilesheeteditor.hpp | 3 + 3 files changed, 83 insertions(+), 6 deletions(-) diff --git a/src/nostalgia/core/studio/consts.hpp b/src/nostalgia/core/studio/consts.hpp index e6b22e50..1aa1b904 100644 --- a/src/nostalgia/core/studio/consts.hpp +++ b/src/nostalgia/core/studio/consts.hpp @@ -12,4 +12,9 @@ namespace nostalgia::core { constexpr auto PluginName = "NostalgiaCore"; +// Command IDs to use with QUndoCommand::id() +enum class CommandId { + UpdatePixel = 1, +}; + } diff --git a/src/nostalgia/core/studio/tilesheeteditor.cpp b/src/nostalgia/core/studio/tilesheeteditor.cpp index 8b2ed192..f07d7350 100644 --- a/src/nostalgia/core/studio/tilesheeteditor.cpp +++ b/src/nostalgia/core/studio/tilesheeteditor.cpp @@ -7,11 +7,13 @@ */ #include +#include #include #include #include #include #include +#include #include #include "consts.hpp" @@ -28,16 +30,83 @@ QColor toQColor(Color16 nc) { } +class UpdatePixelsCommand: public QUndoCommand { + private: + struct PixelUpdate { + QPointer 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 &m_pixels; + QVector m_pixelUpdates; + + public: + UpdatePixelsCommand(QVector &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(pi.value()); + 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(CommandId::UpdatePixel); + } + + bool mergeWith(const QUndoCommand *cmd) override { + auto other = static_cast(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) { return m_palette[m_pixels[index]]; } -void SheetData::updatePixels(QVariantList pixels) { - for (auto pi : pixels) { - // TODO: replace with push to QUndoStack - auto p = qobject_cast(pi.value()); - p->setProperty("color", m_palette[m_selectedColor]); - } +void SheetData::updatePixels(QVariantList pixelItems) { + m_cmdStack.push(new UpdatePixelsCommand(m_pixels, m_palette, pixelItems, m_selectedColor, m_cmdIdx++)); } int SheetData::columns() { diff --git a/src/nostalgia/core/studio/tilesheeteditor.hpp b/src/nostalgia/core/studio/tilesheeteditor.hpp index 1c8aa560..043c72d8 100644 --- a/src/nostalgia/core/studio/tilesheeteditor.hpp +++ b/src/nostalgia/core/studio/tilesheeteditor.hpp @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -26,6 +27,8 @@ class SheetData: public QObject { Q_PROPERTY(int rows READ rows WRITE setRows NOTIFY rowsChanged) private: + uint64_t m_cmdIdx = 0; + QUndoStack m_cmdStack; QStringList m_palette; QVector m_pixels; int m_columns = 2;