[nostalgia/core/studio] Make Pixel updates in TileSheetEditor use undo stack

This commit is contained in:
Gary Talent 2019-12-03 18:01:00 -06:00
parent e407ad7246
commit 01ad572499
3 changed files with 83 additions and 6 deletions

View File

@ -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,
};
} }

View File

@ -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() {

View File

@ -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;